Files
khadhroony-solana-project/docs/plans/016-V0_2_9_YELLOWSTONE_GRPC_PLAN.md
2026-08-24 08:37:36 +02:00

33 KiB
Raw Blame History

Plan 0.2.9 — Yellowstone gRPC standard/provider-neutral

Statut : 0.2.9-pre.001 — gate audit/sizing positif. Aucune implémentation gRPC lourde ni dépendance Yellowstone/Tonic n'est introduite dans cette tranche. La stratégie cible est yellowstone-grpc-proto publié + client/lifecycle KSP autour de Tonic, avec PublicNode comme premier smoke live Mainnet/Testnet et OrbitFlare comme second smoke Devnet authentifié.

1. Objet, base et état d'ouverture

0.2.9 introduit dans ksp-onchain-transport-lib une première fondation Yellowstone gRPC standard et provider-neutral, distincte de HTTP et de WebSocket.

Base autoritaire auditée à l'ouverture :

archive opérateur = khadhroony-solana-project-v0.2.8-full-from-gitea.zip
workspace.package.version initial = 0.2.8
deltas/0.2.8/rel.001.md présent
prompts/014-V0_2_9_START_PROMPT.md présent
prompt fourni = byte-identique au prompt embarqué
metadata .git = absente de l'archive opérateur

Le signal d'ouverture est :

workspace.package.version = 0.2.9-pre.1
commit attendu            = v0.2.9-pre.001
aucun tag prerelease

État hérité à ne pas régresser :

HTTP Solana                52/52 current typed + 14 historiques Deprecated/Removed
KSP-TRANSPORT-007          appliqué
WebSocket standard         9 familles / 18 subscribe-unsubscribe
Helius LaserStream WS      7 familles standard + transactionSubscribe/unsubscribe
Helius heartbeat           Ping control frame 60 s, actor-owned
Config Transport           V1 HTTP + V2 HTTP/WS backward-readable
Config -> Transport        autorisé
Transport -> Config        interdit

2. Résultat du gate pre.001

Le gate est positif avec scope borné.

0.2.9 peut raisonnablement porter :

backend Yellowstone gRPC séparé
settings/runtime bounds gRPC
TLS + metadata générique et redacted
7 RPC unary du service Geyser courant hors SubscribeDeshred
Subscribe bidirectionnel standard
7 familles de filtres top-level
9 variantes SubscribeUpdate
DTOs KSP provider-neutral
backpressure/half-close/shutdown bornés
reconnect/resubscribe KSP-owned
from_slot + SubscribeReplayInfo avec observabilité gap/duplicate/equivocation
Config V3 dédiée gRPC, tout en lisant V1/V2
smokes live opt-in PublicNode puis OrbitFlare
compliance HTTP/WS/Helius non régressée

Sont explicitement exclus :

SubscribeDeshred et pré-exécution/deshred
adapters publics PublicNode/Allnodes/OrbitFlare/Tatum/Helius/Triton/etc.
client autoreconnect upstream comme contrat public KSP
pool/scheduler automatique complexe de sessions gRPC
exactly-once / lossless / ordre global garanti
serveur Geyser/plugin validator
Store/workers/backfill historique

La présence de PublicNode et OrbitFlare ne nécessite donc pas une couche provider-specific publique. Ils entrent dans la release comme environnements d'interopérabilité et profils Config derrière le même backend Yellowstone standard.

3. Sources internes relues

Le gate a relu les règles et documents imposés par le prompt depuis la base stable :

RULES.md
docs/000-README.md

docs/rules/RULES_GENERAL.md
docs/rules/RULES_KSP.md
docs/rules/RULES_RUST.md
docs/rules/RULES_DEPENDENCIES.md
docs/rules/RULES_DOCUMENTATION.md
docs/rules/FILE_CONTRACTS.md
docs/rules/VERSION_WORKFLOW.md
docs/rules/PROMPT_STRUCTURE.md

docs/architecture/000-README.md
docs/architecture/002-LAYERS_AND_DEPENDENCIES.md
docs/architecture/003-COMPONENT_CONTRACTS.md
docs/architecture/004-COMPONENT_INVENTORY.md
docs/architecture/005-DEPENDENCY_GRAPH.md
docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md
docs/architecture/010-APPS_SERVICES_SCENARIOS_AND_CONTROL.md

docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md
docs/plans/007-V0_2_0_SERIES_PLANNING.md
docs/plans/008-V0_2_1_ONCHAIN_HTTP_PLAN.md
docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md
docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md

docs/validation/003-V0_2_1_ONCHAIN_HTTP.md
docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md
docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md
docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md

deltas/0.2.8/rel.001.md

Le code réel audité confirme notamment :

  • Transport possède déjà HTTP et WebSocket dans une seule crate ;
  • Config dépend de Transport, l'inverse est interdit ;
  • le schéma Transport V2 est fermé par additionalProperties: false et distingue endpoints / ws_endpoints ;
  • aucun contrat gRPC n'existe encore ;
  • les abstractions WebSocket ne doivent pas être réutilisées pour gRPC.

4. Baseline stable enregistrée

La preuve opérateur fournie juste avant l'ouverture enregistre sur v0.2.8 :

cargo fmt --all                               OK
python3 scripts/audit_rust_workspace_rules.py OK / clean
cargo check --workspace                       OK
cargo clippy --workspace --all-targets        OK
cargo test --workspace                        OK
cargo tree -p ksp-onchain-transport-lib        fourni
cargo tree --duplicates                        fourni

Sous-ensembles Transport observés pendant cargo test --workspace :

unit tests              335 passed
public_api               41 passed
release_completeness     34 passed
doc-tests                 4 passed
live smokes               opt-in / ignored par défaut

Dépendances directes Transport observées avant gRPC :

futures-util      0.3.34
reqwest           0.13.4
serde             1.0.229
serde_json        1.0.151
tokio             1.53.1
tokio-tungstenite 0.30.0
ksp-core-lib      0.2.8
ksp-logging-lib   0.2.8

Le graphe existant contient déjà les familles modernes suivantes via HTTP/WS :

bytes 1.x
http 1.x
hyper 1.x
hyper-util 0.1.x
tower 0.5.x
rustls 0.23.x
tokio-rustls 0.26.x

Le coût réel de tonic/prost/yellowstone-grpc-proto devra néanmoins être mesuré après matérialisation en pre.002; aucun doublon n'est préjugé acceptable avant cargo tree.

5. Audit upstream Yellowstone au 2026-08-23

5.1 Divergence du snapshot du prompt

Le snapshot préparatoire du prompt mentionnait v14.2.2+solana.4.1.0 comme release GitHub observée. Le réaudit courant trouve désormais :

release GitHub latest = v15.1.2+solana.4.2.0
publication release   = 2026-08-18
Rust annoncé          = 1.96.1

Le changelog master indique en outre :

2026-08-17 yellowstone-grpc-geyser 15.1.2
2026-08-10 yellowstone-grpc-proto 12.6.0
2026-07-31 yellowstone-grpc-client 13.3.0

Cela confirme que version du plugin GitHub, version du client crate et version du proto crate évoluent indépendamment.

Sources primaires :

https://github.com/rpcpool/yellowstone-grpc/releases
https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md
https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto
https://docs.rs/crate/yellowstone-grpc-proto/latest
https://docs.rs/crate/yellowstone-grpc-client/latest

5.2 Crates publiées retenues pour le gate

État publié observé :

yellowstone-grpc-client = 13.3.0, publié 2026-07-31
yellowstone-grpc-proto  = 12.6.0, publié 2026-08-13 sur docs.rs
prost/prost-types       = 0.14.x
tonic                   = 0.14.x

yellowstone-grpc-client 13.3.0 dépend notamment de :

bytes ^1.10.1
futures ^0.3.24
hyper ^1.4.1
hyper-util ^0.1.7
tokio ^1.47.1
tonic ^0.14.0
tonic-health ^0.14.0
tower ^0.5.0
yellowstone-grpc-proto ^12.5.0

Il expose désormais un AutoReconnect, une politique de reconnexion et de la déduplication/replay. Ces capacités sont utiles comme référence, mais ne doivent pas posséder la sémantique publique KSP.

yellowstone-grpc-proto 12.6.0 dépend notamment de :

prost ^0.14.0
prost-types ^0.14.0
solana-pubkey ^4.0.0
thiserror ^2.0.16
siphasher ^1
tonic ^0.14.0 optionnel
tonic-prost ^0.14.0 optionnel
bytes ^1.10.1 optionnel

Le solana-pubkey ^4.0 du proto est compatible en gamme avec le ^4.3 déjà utilisé par KSP ; l'unification exacte sera vérifiée par Cargo en pre.002.

5.3 Licences

Le dépôt upstream déclare :

licence par défaut du repository = AGPL-3.0-only

mais LICENSING.md affecte explicitement Apache-2.0 aux sous-arbres :

examples/
yellowstone-grpc-client/
yellowstone-grpc-client-nodejs/
yellowstone-grpc-proto/

Conséquence du gate :

  • dépendre de la crate publiée yellowstone-grpc-proto est compatible avec la distribution MIT de KSP sous réserve des obligations Apache usuelles ;
  • aucun fichier provenant des zones AGPL du repository ne sera copié dans KSP ;
  • KSP ne vendore pas les .proto dans la stratégie retenue ;
  • si un fichier upstream devait être copié ultérieurement, sa provenance et sa licence seraient réauditées fichier par fichier avant incorporation.

Sources :

https://github.com/rpcpool/yellowstone-grpc/blob/master/LICENSING.md
https://docs.rs/crate/yellowstone-grpc-proto/latest

5.4 MSRV / build

Observations pertinentes :

plugin release 15.1.2      Rust 1.96.1
tonic 0.14.6               rust-version 1.88
prost 0.14.x                MSRV publié actuellement 1.85
proto crate 12.6.0          génération incluse dans la crate publiée

Le build de yellowstone-grpc-proto utilise une chaîne de génération avec protoc vendored côté crate publiée ; KSP n'a donc pas à ajouter son propre build.rs ni à exiger un protoc système pour la stratégie B.

Le MSRV du plugin Geyser n'est pas le MSRV automatique du client KSP. Le gate technique final reste la toolchain réellement utilisée par le workspace et la compilation des dépendances choisies en pre.002.

6. Matrice du service Geyser courant

Le proto publié yellowstone-grpc-proto 12.6.0 et le proto master exposent le même inventaire de service observé pendant le gate :

RPC Forme Statut Cible 0.2.9 Décision
Subscribe bidi stream standard Yellowstone oui fondation principale
SubscribeDeshred bidi stream présent dans proto, trajectoire Triton extension/pré-exécution non report explicite
SubscribeReplayInfo unary standard oui information de replay, pas garantie lossless
Ping unary standard oui canari/liveness unary
GetLatestBlockhash unary standard oui canari typed
GetBlockHeight unary standard oui canari typed
GetSlot unary standard oui canari typed
IsBlockhashValid unary standard oui canari typed
GetVersion unary standard oui canari typed

SubscribeDeshred est techniquement publié dans le proto, mais le changelog upstream le rattache explicitement aux Triton Extension Patches et décrit la réception de transactions avant exécution. Il reste donc hors fondation provider-neutral 0.2.9.

7. Matrice SubscribeRequest

Surface standard retenue intégralement :

Champ Type / sémantique 0.2.9
accounts map nom -> SubscribeRequestFilterAccounts oui
slots map nom -> SubscribeRequestFilterSlots oui
transactions map nom -> SubscribeRequestFilterTransactions oui
transactions_status même famille de filtre transaction oui
blocks map nom -> SubscribeRequestFilterBlocks oui
blocks_meta map nom -> filtre vide oui
entry map nom -> filtre vide oui
commitment optional Processed/Confirmed/Finalized oui
accounts_data_slice repeated offset/length oui
ping optional request ping/id oui
from_slot optional u64 oui, sémantique prudente

7.1 Accounts

account[]
owner[]
filters[]
nonempty_txn_signature?
cuckoo_accounts_filter?

Filtres account :

memcmp { offset, oneof bytes | base58 | base64 }
datasize
token_account_state
lamports { oneof eq | ne | lt | gt }

Les formes Cuckoo actuelles sont conservées parce qu'elles appartiennent au proto publié standard observé, pas parce qu'un provider particulier les demande.

7.2 Slots

filter_by_commitment?
interslot_updates?

SlotStatus courant :

processed
confirmed
finalized
first_shred_received
completed
created_bank
dead

7.3 Transactions / transaction_status

vote?
failed?
signature?
account_include[]
account_exclude[]
account_required[]
cuckoo_account_include?
token_accounts? = ALL | BALANCE_CHANGED

L'optional token_accounts contrôle l'expansion vers les owners de token accounts dans les balances pre/post ; son absence est distincte de ses deux valeurs connues.

7.4 Blocks

account_include[]
include_transactions?
include_accounts?
include_entries?
cuckoo_account_include?

7.5 BlocksMeta / Entry

Les deux filtres sont actuellement des messages vides : leur présence nommée active la famille ; KSP doit donc conserver la distinction absence / map vide / entrée nommée vide au niveau de son contrat logique.

7.6 Common

commitment?          Processed | Confirmed | Finalized
accounts_data_slice  offset + length
ping?                id
from_slot?           u64

KSP appliquera des bornes déterministes avant I/O sur les noms, cardinalités, listes de comptes/owners, memcmp, data slices et tailles de payload. Les valeurs exactes sont un contrat KSP et non une copie aveugle des quotas d'un provider ; elles seront matérialisées avec tests en pre.004.

8. Matrice SubscribeUpdate

Le oneof update_oneof standard contient exactement neuf variantes observées :

Variante Champs structurants à préserver
account account info + slot + is_startup
slot slot + optional parent + status + optional dead_error
transaction signature/is_vote/transaction/meta/index + slot
transaction_status slot/signature/is_vote/index/error
block slot/hash/rewards/time/height/parent/counts + transactions/accounts/entries
ping marker server ping
pong id
block_meta block metadata/counts sans tableaux complets
entry slot/index/num_hashes/hash/transaction counts/index

Le top-level contient aussi :

filters[]   noms de filtres correspondants
created_at  google.protobuf.Timestamp

Les types imbriqués solana-storage.proto nécessaires aux transactions/blocs seront projetés dans des types KSP sans perte arbitraire de champs utiles. Les types Prost/Yellowstone générés restent internes au backend et ne sont pas réexportés dans l'API publique.

9. RPCs unary retenus

RPC Request Response Notes
SubscribeReplayInfo vide first_available? information de disponibilité seulement
Ping count count exact echo attendu
GetLatestBlockhash commitment? slot, blockhash, last_valid_block_height typed
GetBlockHeight commitment? block_height typed
GetSlot commitment? slot typed
IsBlockhashValid blockhash + commitment? slot + valid typed
GetVersion vide version opaque string bornée

Les unary ne remplacent pas les méthodes HTTP équivalentes : ce sont des capacités du backend Yellowstone et restent séparées des wrappers JSON-RPC HTTP existants.

10. Replay, reconnexion et continuité

Le changelog upstream contient deux signaux qui interdisent une promesse simpliste :

2026-07-22 : correction d'un replay blocks from_slot accepté mais reprenant live avec state gap
2026-06-15 : auto-reconnect upstream modifié pour mettre le replay en quarantaine et comparer les blockhashes afin de traiter l'equivocation entre nodes

Décision KSP :

reconnect automatique           oui, borné et KSP-owned
resubscribe déterministe        oui
from_slot                       oui, sans promesse lossless
SubscribeReplayInfo             oui, informatif
exactly-once                    non garanti
lossless                        non garanti
ordre global sans gap           non garanti
duplicate possible              oui, observable/traité selon scope
gap possible                    oui, observable
equivocation node/fork          observable quand preuve disponible

Observabilité cible :

reconnect_count
continuity_gap_count
duplicate_update_count
replay_attempt_count
last_requested_from_slot
last_observed_slot
terminal error code safe

Une détection d'equivocation peut nécessiter une preuve de blockhash ; si elle ne peut pas être généralisée proprement à toutes les familles, le plan exige de documenter sa couverture exacte au lieu de l'annoncer globalement.

11. Stratégie dépendances — A/B/C

A. yellowstone-grpc-client + yellowstone-grpc-proto

Avantages : client prêt, TLS/connect/reconnect déjà implémentés.

Inconvénients :

  • sémantique autoreconnect/replay/dedup upstream importée implicitement ;
  • davantage de dépendances et types upstream ;
  • risque de fuite de types/client brut dans l'API KSP ;
  • contrôle moindre sur redaction, backpressure et lifecycle.

Décision : non retenue comme stratégie principale. Le client reste une référence et peut servir ponctuellement à vérifier le wire dans les tests/outils si nécessaire, sans devenir contrat public.

B. yellowstone-grpc-proto + client KSP autour de tonic

Avantages :

  • proto publié Apache-2.0, pas de copie vendored ;
  • wire officiel généré disponible ;
  • Tonic 0.14 aligné avec l'écosystème HTTP/2 moderne déjà présent ;
  • KSP garde reconnect/backpressure/errors/redaction ;
  • types upstream cachés derrière les DTOs KSP ;
  • solana-pubkey reste dans la même major actuelle.

Décision : stratégie cible retenue.

Matérialisation attendue en pre.002 :

yellowstone-grpc-proto ^12.6   workspace dependency, features minimales
tonic ^0.14                    workspace dependency, features client/TLS minimales
prost/prost-types              pas de direct dependency KSP sauf besoin démontré
tokio-stream/futures           seulement si nécessaire et sans doublon gratuit

L'exacte feature set sera déterminée par compilation et cargo tree, pas par anticipation documentaire.

C. proto/génération KSP minimale bornée

Avantage : contrôle maximum du code généré.

Inconvénients : copie/licence/synchronisation du proto, build.rs, protoc et dette de suivi plus forte.

Décision : reportée/fallback uniquement si B bloque une exigence KSP démontrée.

12. Architecture publique cible

12.1 Séparation des backends

HTTP                TransportSettings / EndpointClient / pool HTTP existants
WebSocket           Ws* existants
Yellowstone gRPC    nouveaux Grpc*/Yellowstone* dédiés

Interdictions :

pas de WsProtocolKind pour gRPC
pas de WsEndpointSettings réutilisé
pas de WsSession déguisée
pas de client Tonic brut réexporté

12.2 Noms et ownership

Noms cibles, affinables sans casser le principe :

YellowstoneGrpcEndpointUrl
YellowstoneGrpcEndpointSettings
YellowstoneGrpcSessionSettings
YellowstoneGrpcTransportSettings
YellowstoneGrpcSession
YellowstoneSubscriptionHandle<T>
YellowstoneSubscribeRequest / filters KSP
YellowstoneUpdate / typed update projections

Le backend wire Tonic/Prost reste privé. Tous les types publics nécessaires sont réexportés au crate root conformément aux règles KSP.

12.3 Metadata/auth provider-neutral

Transport reçoit :

metadata publique bornée
metadata sensible via wrapper opaque/redacted

Il ne connaît :

aucun nom KSP_SECRET_*
aucun std::env
aucun header PublicNode/OrbitFlare/Tatum hardcodé comme contrat standard

Les clés metadata sont validées avant I/O ; les valeurs sensibles ne sont jamais dans Debug, Display, KspError, logs ou snapshots.

13. Config V3 cible

Le schéma V2 actuel est fermé et possède :

profiles[].endpoints
profiles[].ws_endpoints

Ajouter gRPC dans V2 ferait évoluer silencieusement une shape fermée. Le gate retient donc une V3 explicite, tout en conservant V1/V2 backward-readable.

Shape conceptuelle cible :

format_version = 3
globals.grpc_defaults
profiles[].grpc_endpoints[]

Chaque endpoint gRPC doit pouvoir porter au minimum :

name
enabled
provider descriptif
cluster descriptif
url
metadata publique optionnelle
secret_metadata optionnelle
session/runtime overrides bornés optionnels

Règle de sensibilité :

  • metadata ne contient que des valeurs non secrètes ;
  • secret_metadata est une classe séparée ;
  • Config résout les placeholders et exige une provenance/sensibilité secret appropriée avant mapping ;
  • Transport reçoit une valeur opaque/redacted et ne sait pas quel env l'a produite.

grpc_defaults porte les defaults génériques utiles :

connect timeout
unary timeout
close timeout
max inbound/outbound message size
request/update channel capacities
max logical filter groups/names
reconnect attempts/backoff

La forme JSON exacte et les bornes sont matérialisées en pre.010, mais la décision V3 + grpc_endpoints séparés + metadata publique/secrète séparée est fermée par pre.001.

14. Audit fournisseurs gRPC gratuits et durables

L'objectif n'est pas de sélectionner un SDK provider mais de disposer de smokes accessibles sans abonnement payant éphémère.

14.1 PublicNode / Allnodes — priorité 1

PublicNode annonce explicitement des endpoints « free-est » et liste pour Solana :

Mainnet: Yellowstone GRPC
Testnet: GRPC

Endpoint Mainnet affiché officiellement au gate :

solana-yellowstone-grpc.publicnode.com:443

PublicNode est un service soutenu/opéré par Allnodes dans l'écosystème actuel ; il ne faut pas modéliser « PublicNode » et « Allnodes » comme deux protocoles Yellowstone distincts.

Décision 0.2.9 :

pas de PublicNodeGrpcSession publique
pas de AllnodesGrpcSession publique
PublicNode Mainnet = premier smoke live opt-in sans secret
PublicNode Testnet = second cluster du même smoke/provider si endpoint exact confirmé live

La page officielle confirme l'existence de Testnet GRPC, mais le hostname exact n'est pas figé dans ce gate tant qu'il n'a pas été confirmé depuis la surface officielle/live. Il sera vérifié avant ajout d'un profil committé.

Sources :

https://publicnode.com/
https://solana-yellowstone-grpc.publicnode.com/

14.2 OrbitFlare — priorité 2

Le pricing officiel courant annonce pour le plan Free :

$0/mo
10 RPS
1 TPS
gRPC Access = Devnet only
Credit Limits = Unlimited

Cela répond au besoin « gratuit durable » mieux qu'un trial de quelques jours, mais nécessite un compte/credential.

Décision 0.2.9 :

OrbitFlare Devnet = smoke live opt-in secondaire
auth = via generic secret metadata Config -> Transport
aucun OrbitFlareGrpc* public
aucun header provider hardcodé avant vérification exacte de la doc/live

Source :

https://orbitflare.com/pricing

14.3 Tatum — candidat tertiaire, non gate

Tatum documente un endpoint Yellowstone Solana Mainnet et un plan Free utilisable sans abonnement payant, mais le plan courant impose :

3 RPS
100K lifetime credits
5 subscriptions

Le caractère « forever » du plan n'en fait donc pas une ressource illimitée dans le temps : le quota de crédits est lifetime.

Décision : candidat manuel tertiaire, utile pour interop Mainnet authentifiée, mais pas dépendance du gate 0.2.9.

Sources :

https://docs.tatum.io/reference/solana-grpc
https://tatum.io/pricing

14.4 Fournisseurs vérifiés mais non retenus comme gratuits gRPC

État courant vérifié :

Helius      Free: pas de LaserStream gRPC ; Devnet à partir de Developer, Mainnet Business
Shyft       Free: No gRPC Access
Alchemy     Yellowstone gRPC: PAYG ou Enterprise requis
QuickNode   Yellowstone gRPC: Scale/Business ou add-on payant
Chainstack  Yellowstone gRPC: add-on payant à partir de 49 USD/mois, Growth+
ERPC        Geyser gRPC payant ; seulement trial 1 jour sur le plan Standard
NodeFlare   endpoint Yellowstone publié, mais plan Yellowstone à forfait mensuel
Bitquery    CoreCast gRPC n'est pas Yellowstone ; accès stream gratuit non garanti et offre publique payante/trial

Candidat non validé comme gratuit durable :

Solinfra    site public = free tier + Yellowstone annoncés, mais entitlement gRPC du free tier non explicite

Solinfra pourra être revalidé en pre.011 si une grille publique ou le dashboard confirme un droit Yellowstone durable à 0 USD. Triton et d'autres providers peuvent également être réaudités si leur offre change, mais aucun autre accès Yellowstone gratuit durable n'a été confirmé avec une preuve publique suffisante pendant ce gate.

15. Smoke ownership

Le smoke live reste opt-in et n'autorise aucune violation architecturale.

Hiérarchie cible :

1. Transport pur programmatic -> PublicNode Mainnet, sans secret
2. Transport pur programmatic -> PublicNode Testnet, si endpoint exact confirmé
3. composition Config V3 -> Transport -> OrbitFlare Devnet, secret résolu par Config
4. Tatum Mainnet authentifié, opérateur-only si utile

Le smoke 1/2 peut vivre dans ksp-onchain-transport-lib/tests car il construit ses settings programmatiquement et ne teste que Transport.

Le smoke 3 ne doit pas être ajouté à ksp-config-lib par facilité. Si aucune surface d'intégration dédiée n'existe encore, il peut rester une procédure opérateur/documentée ou être placé sur une surface de composition déjà légitime ; le plan doit revalider l'owner au moment de pre.010/pre.011.

Aucun secret provider n'est versionné.

16. Threat model et bornes

16.1 Secrets / diagnostics

Menaces :

URI avec credential
metadata gRPC sensible
Status/message/details provider arbitraires
Debug dérivé de requests/filtres
TLS/connect errors réémettant URI/metadata

Réponse : projections sûres, error codes KSP, contexts allowlistés et redaction testée.

16.2 Ressources

À borner avant I/O :

URL/metadata key/value lengths
connect/unary/close timeouts
max inbound/outbound message sizes
request/update channel capacities
nombre de filter groups
longueur et unicité des filter names
account/owner/include/exclude/required counts
memcmp filters + payload size
data slices
Cuckoo filter dimensions/data size
block/account/transaction update payload
reconnect attempts/backoff

16.3 Backpressure

Politique :

aucune queue non bornée
aucun drop silencieux présenté lossless
overflow observable
slow logical subscription isolée si possible
shutdown déterministe

16.4 Lifecycle adversarial

Tester au minimum :

server half-close
client close
remote Status
malformed/unknown enum
oneof absent/inattendu
oversized inbound/outbound
stream flood
mutation de filtres pendant updates
late update après mutation/unsubscribe
reconnect loop
shutdown during reconnect
reconnect sur node divergent
duplicate/gap après from_slot/replay
TLS/certificate failure
unary timeout

17. Forecast souple recalibré

Prévision courante :

pre.001  DONE — audit upstream/service/proto + providers gratuits + licences/deps + architecture + threat model + sizing
         preuve : plan + matrice + stratégie B + Config V3 décidée + forecast recalibré

pre.002  proto/dependencies matérialisés + settings/errors/façade gRPC minimale provider-neutral
         preuve : features justifiées + compile/tests + redaction + cargo tree direct/duplicates

pre.003  channel/TLS/metadata générique + fixture serveur local + 7 unary RPCs
         preuve : connect/TLS/timeouts/Status safe + wire unary exact

pre.004  Subscribe foundation : maps, commitment, ping, from_slot, data slices, Cuckoo/token controls, validations/bounds
         preuve : omitted/empty/oneof exact + rejects avant I/O

pre.005  Accounts + Slots : filters + typed updates
         preuve : fixtures exactes + enum/optional/malformed/adversarial

pre.006  Transactions + transaction_status + solana-storage wire utile
         preuve : include/exclude/required/Cuckoo/token expansion + tx/meta sans perte arbitraire

pre.007  Blocks + block_meta + entry + rewards/storage nested types
         preuve : counts/arrays/optional/oneof/payload bounds exacts

pre.008  stream bidirectionnel : mutations, Ping/Pong, half-close, backpressure, shutdown
         preuve : actor/session local + bounded queues + cleanup déterministe

pre.009  reconnect/resubscribe + from_slot/ReplayInfo + gaps/duplicates/equivocation observability
         preuve : reconnect local déterministe + aucune promesse lossless implicite

pre.010  Config Transport V3 : grpc_defaults/grpc_endpoints + public/secret metadata + backward V1/V2
         preuve : schema/fixtures/mapping/redaction + Config -> Transport uniquement

pre.011  interop live + compliance : PublicNode Mainnet puis Testnet, OrbitFlare Devnet secondaire, Tatum optionnel
         preuve : smokes opt-in architecture-safe + HTTP 52/14 + WS 18/18 + Helius + API/firewall + cargo graph final

pre.012  README/USAGE + matrice finale + workspace final + indexes + prompt 0.2.10
         preuve : workspace final vert + documentation version-neutral + prompt autonome

rel.001  publication stable stricte

Chaque tranche vise nominalement 1520 minutes de travail effectif. Le forecast n'est pas une deadline.

Critères de split

Scinder avant dette silencieuse si l'un de ces cas apparaît :

  1. yellowstone-grpc-proto + tonic impose un conflit MSRV ou un doublon majeur de stack réseau impossible à justifier ;
  2. les DTOs transactions/blocs exigent une réexposition massive des types upstream ou une réimplémentation disproportionnée ;
  3. l'upstream modifie encore matériellement le proto pendant la release ;
  4. le replay/reconnect devient un sous-système plus grand que la foundation ;
  5. les smokes provider nécessitent des comportements non standard qui contamineraient l'API publique.

En cas de split, le noyau prioritaire à conserver dans 0.2.9 est :

connexion/TLS/metadata + unary + Subscribe standard canonique + lifecycle borné

et le reste est replanifié explicitement dans la séquence ; aucune capacité n'est abandonnée silencieusement.

18. Fichiers attendus par tranche

Cibles probables, sans imposer artificiellement le découpage source :

crates/ksp-onchain-transport-lib/src/grpc_settings.rs
crates/ksp-onchain-transport-lib/src/grpc_session.rs
crates/ksp-onchain-transport-lib/src/grpc_protocol.rs
crates/ksp-onchain-transport-lib/src/grpc_subscribe.rs
crates/ksp-onchain-transport-lib/src/grpc_updates.rs
crates/ksp-onchain-transport-lib/src/grpc_unary.rs
unit_tests/ correspondants
tests/public_api.rs
tests/release_completeness.rs
tests/yellowstone_grpc_*_smoke.rs
crates/ksp-config-lib/src/transport.rs
config/std.transport.json
config/schemas/std.transport.schema.json
.env.example si des variables provider committées sont introduites

Les noms exacts restent soumis aux règles de structure du code réel ; ce plan ne force pas un fichier par concept si une composition plus claire apparaît.

19. Gates de validation

Après chaque changement Rust :

cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo clippy --workspace --all-targets

Tests ciblés :

cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-config-lib  # seulement si Config modifiée

À la fermeture technique d'une prerelease :

cargo test --workspace

Après ajout/modification de la stack gRPC :

cargo tree -p ksp-onchain-transport-lib
cargo tree -p ksp-onchain-transport-lib --duplicates
cargo tree --duplicates

Inspecter en particulier :

yellowstone-grpc-proto
tonic / tonic-prost
prost / prost-types
bytes / http / hyper / hyper-util
tower
rustls / tokio-rustls
solana-* transitifs

20. Conditions de clôture

0.2.9 ne devient stable que si :

inventaire service/proto courant réconcilié
SubscribeDeshred explicitement exclu/classifié
7 unary RPCs retenus validés
Subscribe standard retenu sans perte arbitraire
9 update variants traitées
provider-neutral API sans raw client escape hatch
metadata/secrets redacted
resource bounds et backpressure testés
reconnect/from_slot/replay documentés sans promesse lossless
Config V3 backward V1/V2 si Config intégrée
PublicNode interop Mainnet validée opt-in ou impossibilité externe documentée
OrbitFlare Devnet validé si credential opérateur disponible, sinon procédure documentée
HTTP 52+14 non régressé
standard WS 18/18 non régressé
Helius WS non régressé
cargo graphs inspectés
README/USAGE synchronisés
matrice `012` fermée
prompt 0.2.10 prêt
workspace final vert

21. Release suivante

0.2.10 reste dédiée à ksp-offchain-transport-lib et aux prix, sans être anticipée dans la stack Yellowstone.