Files
khadhroony-solana-project/docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md

33 KiB
Raw Blame History

Validation 0.2.9 — moteur Yellowstone + standard Solana + PublicNode

Statut : matrice ouverte par 0.2.9-pre.001, corrigée par pre.001-fix.002, avancée par pre.002, puis corrigée par pre.002-fix.001 et pre.002-fix.002. Le second gate opérateur confirme fmt/audit/check/Clippy et les 346 unit tests ; il a isolé le dernier écart dans le canari d'intégration public_api, encore synchrone alors que prepare() exige désormais un runtime Tokio actif. fix.002 corrige uniquement ce canari et attend la réexécution des tests Transport/workspace. Le scope distingue moteur Yellowstone, façade Solana standard et première intégration PublicNode. OrbitFlare et Helius sont les seules releases provider suivantes actuellement planifiées ; les autres providers restent en TODO/IDEAS sans numéro réservé.

1. Autorités du gate

Base interne :

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 :

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 :

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 :

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 :

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 :

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 / matérialisation pre.002 Preuve / état
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 et matérialisée source PASS / Cargo pending
yellowstone-grpc-proto ^12.6, default-features = false, aucune feature KSP Cargo tree pending
tonic ^0.14, default-features = false, feature channel locale Cargo tree pending
yellowstone-grpc-client absent manifest canary ajouté
prost/prost-types direct KSP absent manifest / Cargo tree pending
strategy C vendored proto fallback seulement aucun vendoring
system protoc aucun outil système KSP ajouté proto publié/build vendored
raw upstream types public interdit ; aucun reexport Tonic/Yellowstone public API canary ajouté
executable Yellowstone deps interdit dependency firewall à revalider

Versions observées :

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 pre.002
backend gRPC distinct HTTP/WS source/API canary IMPLEMENTED / Cargo pending
aucun WsProtocolKind gRPC source scan SOURCE PASS
Transport owns gRPC dependency graph IMPLEMENTED / tree pending
Config -> Transport seulement ownership test hérité / final TODO
Transport -X-> Config ownership test SOURCE PASS / Cargo pending
Transport -X-> std::env KSP_* ownership test SOURCE PASS
Logging façade KSP only logging ownership SOURCE PASS
no raw Tonic client escape hatch public API canary IMPLEMENTED / Cargo pending
moteur Yellowstone partagé sans duplication provider source/API canary N1 FOUNDATION IMPLEMENTED
façade Solana Yellowstone standard distincte du moteur public API canary TODO pre.003+
PublicNode représenté comme provider/capabilities, pas comme nouveau protocole public API/config canary TODO pre.010/011
provider peut réutiliser, restreindre ou étendre N2 sans dupliquer N1 capability/completeness review architecture conservée
aucune équivalence provider/standard présumée sans preuve provider matrix/tests architecture conservée
façade provider spécialisée seulement si delta réel completeness review TODO provider integration

10. Settings, bounds et redaction

État après pre.002 :

DONE/source+tests ajoutés  endpoint schemes http/https validés ; TLS réel reporté pre.003
DONE/source+tests ajoutés  endpoint URL, descripteurs et nombre dendpoints plafonnés
DONE/source+tests ajoutés  connect timeout > 0 et plafonné
DONE/source+tests ajoutés  unary timeout > 0 et plafonné
DONE/source+tests ajoutés  close timeout > 0 et plafonné
DONE/source+tests ajoutés  max inbound/outbound > 0 et plafonnés
DONE/source+tests ajoutés  request/update queue capacities > 0 et plafonnées
DONE/source+tests ajoutés  reconnect attempt/backoff bornés
TODO pre.004               filter-group count
TODO pre.004               filter-name length/uniqueness
TODO pre.003               metadata key/value count/size
TODO pre.005+              account/owner/include/exclude/required counts
TODO pre.004+              memcmp/data slice bounds
TODO pre.005+              Cuckoo dimensions/data bounds

Security canaries :

DONE/source+tests ajoutés  endpoint URL Debug redacted
TODO pre.003               secret metadata Debug/Display absent
TODO pre.003               Status message/details distants non recopiés aveuglément en context
PARTIAL pre.002             URI Tonic invalide mappée sans recopier l'erreur ; TLS/connect réel pre.003
TODO pre.004+              request/update Debug sans payload arbitraire sensible
PARTIAL pre.002             channel Debug ne contient ni URL ni raw Tonic ; snapshot lifecycle ultérieur

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 :

exactly-once
lossless
historical replay complet
ordre global sans gap

12. Config V3

Décision de gate :

V1 HTTP reste lisible
V2 HTTP+WS reste lisible
V3 ajoute gRPC explicitement

Shape conceptuelle à matérialiser :

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. Providers — validation et séquence

Provider Accès gratuit/durable observé Rôle architectural Release cible Verdict
PublicNode / Allnodes-backed Mainnet + Testnet Yellowstone gRPC première intégration concrète 0.2.9 IN provider
OrbitFlare Devnet Free provider dédié ; compat/restrictions/extensions à auditer 0.2.10 PLANNED
Helius LaserStream gRPC accès dépendant du plan provider dédié ; compat/replay/auth/extensions à auditer 0.2.11 PLANNED
eRPC à réauditer waitlist provider non réservé TODO
Triton à réauditer upstream + extensions provider possibles non réservé TODO
Alchemy à réauditer waitlist provider non réservé TODO
QuickNode à réauditer waitlist provider non réservé TODO
Chainstack à réauditer waitlist provider non réservé TODO
Tatum / Shyft / Solinfra / NodeFlare / autres selon accès/capabilities attente exploratoire non réservé IDEAS

PublicNode 0.2.9

Cible principale officiellement affichée :

solana-yellowstone-grpc.publicnode.com:443

Gates :

utilise le moteur Yellowstone partagé
utilise la façade standard Solana
provider/capabilities/profile explicitement identifiables
aucune duplication actor/channel/stream
wire N2 réutilisé seulement pour les capacités réellement compatibles ; divergence N3 explicite
Mainnet smoke opt-in
Testnet smoke opt-in si endpoint exact confirmé

Providers suivants

OrbitFlare (0.2.10) et Helius LaserStream gRPC (0.2.11) sont les seules intégrations provider actuellement planifiées après PublicNode. Pour chacune, le gate doit comparer le provider au Yellowstone upstream courant : capacités supportées, restrictions, extensions wire, auth/metadata, compression, keepalive, replay/from_slot, limites et lifecycle.

Les autres providers restent en TODO/IDEAS sans release dédiée. Aucune façade, dépendance, Config profile ou smoke n'est préparé pour eux tant qu'une décision explicite ne les fait pas entrer dans la séquence active.

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 — 1520 min max ; release <= une session

pre.001 DONE  audit/sizing/architecture                                      1520 min nominal
pre.002 FIX.001 CANDIDATE  moteur: deps/settings/errors/channel           1520 min
pre.003 TODO  moteur: TLS/metadata + fixture + 7 unary                        1520 min
pre.004 TODO  standard: Subscribe common/from_slot/bounds                     1520 min
pre.005 TODO  standard: accounts + slots                                      1520 min
pre.006 TODO  standard: transactions + transaction_status                     1520 min
pre.007 TODO  standard: blocks + block_meta + entry                           1520 min
pre.008 TODO  moteur: bidi/backpressure/half-close/shutdown                   1520 min
pre.009 TODO  moteur: reconnect/replay/gap/duplicate                          1520 min
pre.010 TODO  Config V3 + protocol/provider + profils PublicNode              1520 min
pre.011 TODO  PublicNode live + compliance + docs/prompt 0.2.10               1520 min
rel.001 TODO stable

Gate de sizing : une prerelease estimée à plus de 20 minutes est scindée ; si 0.2.9 ne paraît plus clôturable dans la session courante, la release est scindée avant implémentation supplémentaire.

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/build/transitifs audit initial PASS / matérialisation 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.

17. Gate pre.002 / pre.002-fix.001

Premier passage opérateur sur pre.002 :

Gate / observation Résultat avant fix État après fix.001
workspace version 0.2.9-pre.2 0.2.9-pre.2.fix.1
cargo fmt --all PASS à réexécuter
audit Rust workspace PASS / clean PASS local / clean
cargo check --workspace PASS, avec warning channel jamais lu warning supprimé par état privé _channel
cargo clippy --workspace --all-targets FAIL : implicit_return dans unit_tests/grpc_settings.rs corrigé ; à réexécuter
cargo test -p ksp-onchain-transport-lib FAIL : connect_lazy() appelé hors reactor Tokio, 344/345 avant fix test/runtime corrigés ; à réexécuter
dependency canary Core PASS / 3 passed inchangé
cargo tree -p ksp-onchain-transport-lib obtenu et inspecté PASS graphe
cargo tree -p ... --duplicates / workspace duplicates obtenu et inspecté PASS avec doublons build/runtime documentés

Correction fix.001 :

le champ Tonic reste présent en production ; il n'est pas placé sous cfg(test)
le champ privé devient `_channel` tant qu'aucune opération pre.003 ne le consomme
prepare() vérifie tokio::runtime::Handle::try_current() avant connect_lazy()
absence de runtime -> KspError grpc_channel_failed sûr, jamais panic Tonic
le test positif s'exécute sous #[tokio::test]
un test sync couvre explicitement l'absence de runtime et la redaction
la closure de cardinalité settings utilise un return explicite conforme à Clippy

Le choix de ne pas mettre le channel sous #[cfg(test)] est intentionnel : pre.002 matérialise une ressource N1 réelle de production qui sera consommée par pre.003; une compilation normale sans ce champ rendrait le contrat de tranche artificiellement différent entre production et tests.

Inspection du graphe opérateur :

tonic                 0.14.6
yellowstone-grpc-proto 12.6.0
prost/prost-types      0.14.4
solana-pubkey          4.3.0 unifié
http/hyper/hyper-util  1.5.0 / 1.11.0 / 0.1.20
tower                  0.5.3
bytes                  1.12.1

Aucune version concurrente Tonic/Prost/Solana n'a été introduite dans le graphe Transport. Les répétitions Prost de même version proviennent des unités build/runtime de la crate proto publiée.

Verdict pre.002-fix.001 : correctif source prêt ; pre.002 reste ouverte jusqu'à réexécution verte de fmt/audit/check/clippy/tests/workspace et confirmation finale du graphe.

Second passage opérateur après fix.001

Gate / observation Résultat fix.001 État fix.002
workspace version 0.2.9-pre.2.fix.1 0.2.9-pre.2.fix.2
cargo fmt --all PASS à réexécuter
audit Rust workspace PASS / clean PASS local / clean
cargo check --workspace PASS inchangé
cargo clippy --workspace --all-targets PASS inchangé
Transport unit PASS / 346 passed inchangé
Transport public_api FAIL / 41 passed, 1 failed : prepare() appelé hors runtime Tokio canari placé sous #[tokio::test]
dependency canary Core PASS / 3 passed inchangé
graphes Cargo déjà fournis et inspectés inchangés

Le second échec ne révèle aucune nouvelle faiblesse du moteur N1 : il confirme au contraire le contrat introduit par fix.001. Le canari public API doit être exécuté dans le même contexte Tokio que le test unitaire positif ; aucune modification supplémentaire de YellowstoneGrpcChannel n'est nécessaire.

Verdict pre.002-fix.002 : correctif de test d'intégration prêt ; pre.002 reste ouverte jusqu'à réexécution verte de cargo test -p ksp-onchain-transport-lib, cargo test --workspace et des gates habituels.