# Validation `0.2.9` — Yellowstone gRPC standard/provider-neutral > **Statut : matrice ouverte par `0.2.9-pre.001`. Les colonnes `DONE` ne seront cochées qu'après preuves réellement exécutées. Le gate d'ouverture a audité le proto/service, les licences, les dépendances et les fournisseurs live gratuits ; il n'a pas ajouté de client gRPC de production.** ## 1. Autorités du gate Base interne : ```text v0.2.8 / archive Gitea stable fournie workspace.package.version initial = 0.2.8 deltas/0.2.8/rel.001.md prompts/014-V0_2_9_START_PROMPT.md ``` Sources upstream auditées le `2026-08-23` : ```text 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/LICENSING.md https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/solana-storage.proto https://docs.rs/crate/yellowstone-grpc-client/latest https://docs.rs/crate/yellowstone-grpc-proto/latest ``` Divergence enregistrée : ```text snapshot du prompt : GitHub release v14.2.2+solana.4.1.0 réaudit courant : GitHub release v15.1.2+solana.4.2.0 (2026-08-18) crate client : 13.3.0 crate proto : 12.6.0 ``` ## 2. Baseline stable | Gate | Preuve | État | | --- | --- | --- | | `cargo fmt --all` | log opérateur `v0.2.8` | DONE | | audit Rust workspace | clean | DONE | | `cargo check --workspace` | log opérateur | DONE | | `cargo clippy --workspace --all-targets` | log opérateur | DONE | | `cargo test --workspace` | log opérateur | DONE | | Transport unit | 335 passed | DONE | | Transport public API | 41 passed | DONE | | Transport release completeness | 34 passed | DONE | | Transport doctests | 4 passed | DONE | | `cargo tree -p ksp-onchain-transport-lib` | log opérateur | DONE | | `cargo tree --duplicates` | log opérateur | DONE | ## 3. Matrice service `Geyser` | RPC | Forme | Classification | Scope | Preuve cible | État | | --- | --- | --- | --- | --- | --- | | `Subscribe` | bidi | standard | IN | fixture locale + live | TODO | | `SubscribeDeshred` | bidi | Triton extension/pré-exécution malgré présence proto | OUT | canari d'absence/API | TODO | | `SubscribeReplayInfo` | unary | standard | IN | fixture unary | TODO | | `Ping` | unary | standard | IN | fixture unary | TODO | | `GetLatestBlockhash` | unary | standard | IN | fixture unary | TODO | | `GetBlockHeight` | unary | standard | IN | fixture unary | TODO | | `GetSlot` | unary | standard | IN | fixture unary | TODO | | `IsBlockhashValid` | unary | standard | IN | fixture unary | TODO | | `GetVersion` | unary | standard | IN | fixture unary | TODO | ## 4. `SubscribeRequest` — coverage normative ### 4.1 Top-level | Champ | Sémantique | Scope | Preuve | | --- | --- | --- | --- | | `accounts` | map filter-name -> account filter | IN | exact wire + bounds | | `slots` | map -> slot filter | IN | exact wire | | `transactions` | map -> transaction filter | IN | exact wire + bounds | | `transactions_status` | map -> transaction filter | IN | exact wire + bounds | | `blocks` | map -> block filter | IN | exact wire + bounds | | `blocks_meta` | map -> empty filter | IN | presence/empty semantics | | `entry` | map -> empty filter | IN | presence/empty semantics | | `commitment` | optional Processed/Confirmed/Finalized | IN | omitted/value exact | | `accounts_data_slice` | repeated offset/length | IN | order + bounds | | `ping` | optional id | IN | Ping/Pong lifecycle | | `from_slot` | optional u64 | IN | reconnect/replay tests | ### 4.2 Accounts | Capacité | Scope | Preuve | | --- | --- | --- | | `account[]` | IN | order/cardinality/address validation | | `owner[]` | IN | order/cardinality/address validation | | `filters[]` | IN | AND semantics preserved structurally | | `nonempty_txn_signature?` | IN | omitted/false/true | | `cuckoo_accounts_filter?` | IN | exact wire + dimension/data bounds | | memcmp bytes | IN | exact bytes + bounds | | memcmp base58 | IN | exact string + validation | | memcmp base64 | IN | exact string + validation | | `datasize` | IN | exact u64 | | `token_account_state` | IN | bool | | lamports `eq/ne/lt/gt` | IN | oneof exact | ### 4.3 Slots | Capacité | Scope | Preuve | | --- | --- | --- | | `filter_by_commitment?` | IN | optional semantics | | `interslot_updates?` | IN | optional semantics | | processed/confirmed/finalized | IN | enum decode | | first_shred_received/completed/created_bank/dead | IN | enum decode + dead_error | ### 4.4 Transactions / transaction_status | Capacité | Scope | Preuve | | --- | --- | --- | | `vote?` | IN | optional semantics | | `failed?` | IN | optional semantics | | `signature?` | IN | exact/validated | | `account_include[]` | IN | order/bounds | | `account_exclude[]` | IN | order/bounds | | `account_required[]` | IN | order/bounds | | `cuckoo_account_include?` | IN | exact wire + bounds | | `token_accounts? = ALL` | IN | optional enum | | `token_accounts? = BALANCE_CHANGED` | IN | optional enum | ### 4.5 Blocks | Capacité | Scope | Preuve | | --- | --- | --- | | `account_include[]` | IN | order/bounds | | `include_transactions?` | IN | optional semantics | | `include_accounts?` | IN | optional semantics | | `include_entries?` | IN | optional semantics | | `cuckoo_account_include?` | IN | exact wire + bounds | ## 5. `SubscribeUpdate` — coverage normative | Variante | Champs structurants | Scope | Preuve | | --- | --- | --- | --- | | `account` | account info, slot, is_startup | IN | exact decode | | `slot` | slot, parent?, status, dead_error? | IN | exact decode | | `transaction` | signature, vote, transaction, meta, index, slot | IN | exact decode | | `transaction_status` | slot, signature, vote, index, err | IN | exact decode | | `block` | hash/rewards/time/height/parents/counts + tx/accounts/entries | IN | exact decode + bounds | | `ping` | marker | IN | lifecycle | | `pong` | id | IN | lifecycle | | `block_meta` | metadata/counts | IN | exact decode | | `entry` | slot/index/hash/counts | IN | exact decode | Top-level à préserver : ```text filters[] created_at oneof absent/inconnu -> comportement explicitement testé ``` ## 6. `solana-storage.proto` — nested wire utile Le backend doit préserver les champs nécessaires des structures imbriquées actuelles, sans exposer les types upstream comme contrat public : ```text ConfirmedBlock ConfirmedTransaction Transaction Message MessageHeader MessageAddressTableLookup TransactionStatusMeta TransactionError InnerInstructions / InnerInstruction CompiledInstruction TokenBalance / UiTokenAmount ReturnData Reward / Rewards UnixTimestamp BlockHeight NumPartitions ``` États optionnels/legacy particulièrement sensibles : ```text compute_units_consumed? cost_units? inner_instructions_none log_messages_none return_data_none loaded writable/readonly addresses commission / commission_bps ``` Preuve cible : fixtures issues du wire Protobuf + cas old/current + malformed/oversized, sans conversion JSON arbitraire. ## 7. Unary RPC matrix | RPC | Request exact | Response exact | État | | --- | --- | --- | --- | | ReplayInfo | empty | `first_available?` | TODO | | Ping | `count` | `count` | TODO | | LatestBlockhash | `commitment?` | slot/hash/last_valid_height | TODO | | BlockHeight | `commitment?` | block_height | TODO | | Slot | `commitment?` | slot | TODO | | IsBlockhashValid | blockhash + `commitment?` | slot + bool | TODO | | Version | empty | version | TODO | ## 8. Dépendances / licence | Gate | Décision `pre.001` | Preuve suivante | | --- | --- | --- | | repository default | AGPL-3.0-only | `LICENSING.md` | | client subtree | Apache-2.0 | `LICENSING.md` | | proto subtree | Apache-2.0 | `LICENSING.md` | | strategy A client+proto | rejetée comme default | documenté | | strategy B proto+Tonic KSP | **retenue** | `pre.002` compile/tree | | strategy C vendored proto | fallback seulement | aucun vendoring pre.001 | | system protoc | non attendu avec crate publiée | vérifier build réel | | raw upstream types public | interdit par défaut | public API canary | | executable Yellowstone deps | interdit | dependency firewall | Versions observées : ```text yellowstone-grpc-client 13.3.0 yellowstone-grpc-proto 12.6.0 tonic 0.14.x (0.14.6 latest observé) prost/prost-types 0.14.x (0.14.4 latest observé) ``` ## 9. Architecture / ownership | Invariant | Preuve cible | État | | --- | --- | --- | | backend gRPC distinct HTTP/WS | source/API canary | TODO | | aucun `WsProtocolKind` gRPC | source scan | TODO | | Transport owns gRPC | dependency graph | TODO | | Config -> Transport seulement | ownership test | TODO | | Transport -X-> Config | ownership test | TODO | | Transport -X-> std::env KSP_* | ownership test | TODO | | Logging façade KSP only | logging ownership | TODO | | no raw Tonic client escape hatch | public API canary | TODO | | no provider-specific public types | public API/completeness | TODO | ## 10. Settings, bounds et redaction À fermer par tests : ```text endpoint schemes TLS/non-TLS explicitement validés connect timeout > 0 unary timeout > 0 close timeout > 0 max inbound/outbound > 0 et plafonnés request/update queue capacities > 0 et plafonnées reconnect attempt/backoff bornés filter-group count filter-name length/uniqueness metadata key/value count/size account/owner/include/exclude/required counts memcmp/data slice bounds Cuckoo dimensions/data bounds ``` Security canaries : ```text endpoint URL Debug redacted secret metadata Debug/Display absent Status message/details distants non recopiés aveuglément en context TLS/connect error sans credential/URI sensible request/update Debug sans payload arbitraire sensible snapshot sans endpoint secret ni remote internals inutiles ``` ## 11. Lifecycle / backpressure / replay | Cas | Attendu | État | | --- | --- | --- | | stream open | session bornée | TODO | | request mutation | ordre déterministe | TODO | | server Ping -> client request ping -> Pong | explicite | TODO | | server half-close | terminal/reconnect selon policy | TODO | | client close | cleanup borné | TODO | | receiver drop | cleanup capacité | TODO | | slow subscription | pas de queue infinie | TODO | | inbound oversized | rejet avant allocation excessive | TODO | | outbound oversized | rejet avant write | TODO | | reconnect budget | borné | TODO | | resubscribe order | déterministe | TODO | | `from_slot` | utilisé sans promesse lossless | TODO | | ReplayInfo | informatif | TODO | | duplicates | observables | TODO | | gaps | observables | TODO | | divergent node history | couverture documentée | TODO | | shutdown during reconnect | aucune nouvelle connexion après shutdown | TODO | Claims interdits sans nouvelle preuve : ```text exactly-once lossless historical replay complet ordre global sans gap ``` ## 12. Config V3 Décision de gate : ```text V1 HTTP reste lisible V2 HTTP+WS reste lisible V3 ajoute gRPC explicitement ``` Shape conceptuelle à matérialiser : ```text globals.grpc_defaults profiles[].grpc_endpoints[] endpoint.metadata[] # public/non-secret endpoint.secret_metadata[] # Config-owned secret provenance ``` Canaries : | Gate | État | | --- | --- | | V1 backward readable | TODO | | V2 backward readable | TODO | | V3 schema strict | TODO | | gRPC endpoint mapping | TODO | | secret provenance enforced | TODO | | safe projection redacted | TODO | | no Transport -> Config | TODO | | `.env.example` inventory if new env vars | TODO | ## 13. Fournisseurs live gratuits / durables | Provider | Cluster gRPC gratuit confirmé | Nature | Priorité `0.2.9` | Verdict | | --- | --- | --- | --- | --- | | **PublicNode / Allnodes-backed** | Mainnet + Testnet | endpoint public, pas de plan payant requis observé | 1 | **IN smoke** | | **OrbitFlare** | Devnet | Free $0, 10 RPS/1 TPS, unlimited credits | 2 | **IN smoke secondaire** | | Tatum | Mainnet | Free durable mais 100K lifetime credits, 5 subscriptions | 3 | opérateur optionnel | | Helius | aucun sur Free | Devnet Developer, Mainnet Business | — | OUT free | | Shyft | aucun sur Free | Free indique No gRPC Access | — | OUT free | | Alchemy | aucun sur Free | PAYG/Enterprise requis | — | OUT free | | QuickNode | aucun sur Free | Scale/Business ou add-on payant | — | OUT free | | Chainstack | aucun sur Free | add-on Yellowstone payant, Growth+ | — | OUT free | | ERPC | aucun durable | plan Geyser payant, trial 1 jour | — | OUT free | | NodeFlare | endpoint gRPC présent | plan Yellowstone mensuel payant | — | OUT free | | Bitquery | pas Yellowstone standard | CoreCast custom, stream gratuit non garanti | — | OUT 0.2.9 | | Solinfra | **non confirmé** | free tier + Yellowstone annoncés, entitlement gRPC free non explicite | recheck | CANDIDAT | Sources provider : ```text https://publicnode.com/ https://solana-yellowstone-grpc.publicnode.com/ https://orbitflare.com/pricing https://docs.tatum.io/reference/solana-grpc https://tatum.io/pricing https://www.helius.dev/pricing https://shyft.to/solana-rpc-grpc-pricing https://www.alchemy.com/docs/reference/yellowstone-grpc-quickstart https://www.quicknode.com/docs/solana/solana-grpc/overview https://chainstack.com/pricing/ https://erpc.global/en/grpc/ https://nodeflare.app/solana https://docs.bitquery.io/docs/grpc/solana/introduction/ https://solinfra.dev/ ``` ### Smoke PublicNode Cible principale officiellement affichée : ```text solana-yellowstone-grpc.publicnode.com:443 ``` Testnet GRPC est officiellement listé. L'endpoint exact doit être confirmé avant commit d'un profil durable. ### Smoke OrbitFlare Credential : jamais versionné. La clé/header gRPC exacte doit être confirmée depuis la documentation/live au moment du smoke ; le contrat Transport reste generic secret metadata. ## 14. Non-régressions obligatoires | Surface héritée | Attendu final | État | | --- | --- | --- | | HTTP current | 52 typed | TODO final | | HTTP historical | 14 Deprecated/Removed | TODO final | | Standard WS | 18 opérations / 9 familles | TODO final | | Helius WS | 7 standard + transaction | TODO final | | Helius heartbeat | Ping 60 s | TODO final | | Config V1/V2 | backward read | TODO final | | Wallet/Wallet Desk | aucune dépendance protocolaire Yellowstone directe | TODO final | ## 15. Forecast / preuve par tranche ```text pre.001 DONE audit + matrices + dependencies/license + providers + sizing pre.002 TODO deps/settings/errors/facade + cargo tree pre.003 TODO TLS/metadata + local fixture + 7 unary pre.004 TODO Subscribe common + Cuckoo/token/from_slot/bounds pre.005 TODO accounts + slots pre.006 TODO transactions + transaction_status pre.007 TODO blocks + block_meta + entry pre.008 TODO bidi lifecycle/backpressure/half-close/shutdown pre.009 TODO reconnect/replay/gap/duplicate/equivocation pre.010 TODO Config V3 pre.011 TODO live PublicNode/OrbitFlare + compliance + final cargo graphs pre.012 TODO docs/workspace final/prompt 0.2.10 rel.001 TODO stable ``` ## 16. Gate `pre.001` | Critère du prompt | Verdict | | --- | --- | | base stable `v0.2.8` confirmée | PASS | | baseline opérateur enregistrée | PASS | | upstream courant relu | PASS | | divergence snapshot/latest enregistrée | PASS | | service/proto exhaustif inventorié | PASS | | standard vs provider extension classifié | PASS | | `SubscribeDeshred` classifié | PASS / OUT | | unary RPCs classifiés | PASS / 7 IN | | replay/from_slot audités | PASS | | strategy dependency choisie | PASS / B | | licence auditée avant ajout | PASS | | features/MSRV/transitifs audit initial | PASS / materialisation pre.002 | | architecture distincte WS | PASS | | metadata/auth neutral | PASS | | Config shape décidée | PASS / V3 | | resource/backpressure policy décidée | PASS | | smoke ownership décidé | PASS | | providers gratuits audités | PASS | | release dimensionnée | PASS | | forecast recalibré | PASS | | split criteria écrits | PASS | | aucune implémentation lourde prématurée | PASS | **Verdict `pre.001` : gate positif ; `pre.002` peut matérialiser la stratégie B sous validation Cargo.**