Files
khadhroony-solana-project/docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md
2026-08-24 19:53:45 +02:00

438 lines
19 KiB
Markdown

<!-- file: docs/validation/012-V0_2_9_YELLOWSTONE_GRPC.md -->
<!-- version: 24 -->
# Validation `0.2.9` — Yellowstone gRPC standard + PublicNode
> **Statut courant : `pre.010-fix.001` est fermée sans warning. `pre.011` est candidate et doit prouver Config Transport V3, le mapping Config -> Yellowstone gRPC, la séparation protocol/provider et le profil PublicNode Mainnet. Ce document a été restructuré : les logs détaillés historiques vivent dans `deltas/0.2.9/`; cette matrice porte les exigences et le verdict courant.**
## 1. Autorités et baseline courante
Autorités :
```text
RULES.md + docs/rules/*
plan 016 courant
code réel Transport/Config
prompts/014-V0_2_9_START_PROMPT.md pour les contraintes non supersédées
deltas/0.2.9/* pour l'historique immuable et les décisions postérieures au prompt
upstream Yellowstone primaire
```
Baseline opérateur immédiatement avant `pre.011` (`0.2.9-pre.010-fix.001`) :
| Gate | Résultat |
|------------------------------------------|--------------------------|
| `cargo fmt --all` | PASS |
| audit Rust workspace | PASS, 0 candidate export |
| `cargo check --workspace` | PASS |
| `cargo clippy --workspace --all-targets` | PASS sans warning |
| Transport unit | 383/383 PASS |
| Transport public API | 49/49 PASS |
| Transport release completeness | 43/43 PASS |
| Transport doctests | 4/4 PASS |
| workspace dependency canary | 3/3 PASS |
| `cargo test --workspace` | PASS |
Cette baseline est le seuil de non-régression de `pre.011` pour Transport.
## 2. Gate dépendances et licence
| Exigence | Décision / preuve | État |
|--------------------------------|------------------------------------------|-------------------|
| proto officiel sans vendoring | `yellowstone-grpc-proto ^12.6` | **PASS** |
| pas de client upstream runtime | `yellowstone-grpc-client` absent | **PASS** |
| runtime Tonic KSP-owned | `tonic ^0.14` + `tonic-prost ^0.14` | **PASS** |
| proto subtree compatible | Apache-2.0 selon `LICENSING.md` upstream | **PASS** |
| source AGPL copiée | aucune | **PASS** |
| raw client Tonic public | aucun | **PASS** |
| graph final | réinspection `pre.012` | **PENDING FINAL** |
Le graphe n'est pas modifié par `pre.011`; aucune nouvelle dépendance Cargo n'est introduite dans cette tranche.
## 3. Matrice service `Geyser`
| RPC | Classification | Cible | Preuve | Verdict |
|-----------------------|--------------------------------|-------|---------------------------------|----------|
| `Subscribe` | standard | oui | stream bidi local + lifecycle | **PASS** |
| `SubscribeDeshred` | extension/pré-exécution Triton | non | exclusion documentée | **OUT** |
| `SubscribeReplayInfo` | standard unary | oui | fixture unary + reconnect tests | **PASS** |
| `Ping` | standard unary | oui | fixture exact echo | **PASS** |
| `GetLatestBlockhash` | standard unary | oui | fixture typed | **PASS** |
| `GetBlockHeight` | standard unary | oui | fixture typed | **PASS** |
| `GetSlot` | standard unary | oui | fixture typed | **PASS** |
| `IsBlockhashValid` | standard unary | oui | fixture typed + invalid input | **PASS** |
| `GetVersion` | standard unary | oui | fixture typed | **PASS** |
## 4. `SubscribeRequest` — coverage normative
### 4.1 Top-level
| Champ | Verdict | Preuve minimale |
|-----------------------|----------|----------------------------------|
| `accounts` | **PASS** | maps typed + wire exact |
| `slots` | **PASS** | maps typed + wire exact |
| `transactions` | **PASS** | maps typed + wire exact |
| `transactions_status` | **PASS** | same filter family, separate map |
| `blocks` | **PASS** | maps typed + wire exact |
| `blocks_meta` | **PASS** | named empty marker preserved |
| `entry` | **PASS** | named empty marker preserved |
| `commitment` | **PASS** | optional wire semantics |
| `accounts_data_slice` | **PASS** | order + bounds |
| `ping` | **PASS** | optional id |
| `from_slot` | **PASS** | optional + replay mutation |
### 4.2 Accounts
```text
account[]
owner[]
filters[]
nonempty_txn_signature?
cuckoo_accounts_filter?
memcmp bytes/base58/base64
datasize
token_account_state
lamports eq/ne/lt/gt
```
Verdict : **PASS** — wire complet retenu, bounds déterministes, payload Debug redacted, malformed fixed-width rejeté.
### 4.3 Slots
```text
filter_by_commitment?
interslot_updates?
processed
confirmed
finalized
first_shred_received
completed
created_bank
dead + dead_error?
```
Verdict : **PASS**.
### 4.4 Transactions et transaction_status
```text
vote?
failed?
signature?
account_include[]
account_exclude[]
account_required[]
cuckoo_account_include?
token_accounts? = ALL | BALANCE_CHANGED
```
Verdict : **PASS** — request wire, transaction storage/meta, status error et malformed signature couverts.
### 4.5 Blocks, block_meta, entry
```text
account_include[]
include_transactions?
include_accounts?
include_entries?
cuckoo_account_include?
blocks_meta marker
entry marker
```
Verdict : **PASS** — block complet, metadata, entries et champs optional/legacy couverts.
## 5. `SubscribeUpdate` — coverage normative
| Variante | Verdict |
|--------------------------------------|----------|
| account | **PASS** |
| slot | **PASS** |
| transaction | **PASS** |
| transaction_status | **PASS** |
| block | **PASS** |
| ping | **PASS** |
| pong | **PASS** |
| block_meta | **PASS** |
| entry | **PASS** |
| top-level `filters[]` / `created_at` | **PASS** |
Les raw protobufs ne sortent pas de la façade publique. Les décodeurs rejettent les formes structurellement invalides sans copier des payloads arbitraires dans les erreurs.
## 6. Settings, bounds et redaction
| Contrôle | État |
|-----------------------------------------------|--------------------|
| URL `http/https` seulement et longueur bornée | **PASS** |
| URL Debug redacted | **PASS** |
| metadata key/value/count bornés | **PASS** |
| metadata secret/public distincte | **PASS** Transport |
| timeouts non nuls et bornés | **PASS** |
| reconnect bounds cohérents | **PASS** |
| inbound/outbound message sizes | **PASS** |
| request/update queue capacities | **PASS** |
| filter group/name bounds | **PASS** |
| account/owner/memcmp/data slice bounds | **PASS** |
| transaction/block selectors bounds | **PASS** |
| remote `Status` message/details non recopiés | **PASS** |
| Transport -> env/config | absent ou **PASS** |
## 7. Lifecycle, backpressure et replay
| Exigence | Verdict | Preuve |
|------------------------------|-----------------|------------------------------------------------|
| stream bidi unique | **PASS** | round-trip fixture |
| mutation request | **PASS** | same request channel |
| server Ping / client reply | **PASS** | actor test |
| Pong decode | **PASS** | update decode |
| server half-close | **PASS** | state terminal observable |
| explicit client close | **PASS** | half-close avant deadline |
| hostile server shutdown | **PASS** | close timeout borné |
| slow receiver | **PASS** | overflow terminal observable |
| oversized inbound | **PASS** | Tonic decoder bound |
| oversized outbound | **PASS** | reject avant queue dispatch |
| reconnect backoff | **PASS** | budget borné |
| shutdown pendant backoff | **PASS** | interruption sans nouvelle connexion |
| resubscribe déterministe | **PASS** | last accepted full request |
| reprise `from_slot` | **PASS** | dernier slot observé + demande explicite |
| ReplayInfo `first_available` | **PASS** | clamp/gap seulement si prouvé |
| duplicate observability | **PASS** | compteur borné, pas de suppression silencieuse |
| exactly-once/lossless | **NON GARANTI** | contrat explicite |
Snapshot public requis et présent :
```text
reconnect_count
replay_attempt_count
continuity_gap_count
duplicate_update_count
last_requested_from_slot
last_observed_slot
state/error code safe
```
## 8. Gate Config V3 — `pre.011`
### 8.1 Schema et backward compatibility
Exigences candidate :
| Exigence | Preuve source actuelle | Verdict avant gate opérateur |
|------------------------------------------|------------------------------------------|------------------------------|
| schema `$id` V3 | `urn:ksp:schema:std.transport:v3` | **SOURCE OK** |
| branches V1/V2 conservées | `documentV1`, `documentV2`, `documentV3` | **SOURCE OK** |
| V1 HTTP-only | fixture historique | **PENDING TEST** |
| V2 HTTP+WS | fixture historique | **PENDING TEST** |
| V3 HTTP+WS+gRPC | fixture V3 + config committée | **PENDING TEST** |
| `grpc_endpoints` optionnel par profil V3 | profiles génériques sans gRPC | **PENDING TEST** |
| no `additionalProperties` relaxation | branches strictes | **SOURCE OK** |
### 8.2 Mapping runtime
V3 doit mapper :
```text
grpc_defaults -> YellowstoneGrpcSessionSettings
grpc_endpoints[].url -> YellowstoneGrpcEndpointUrl
provider -> YellowstoneGrpcProviderName
cluster -> YellowstoneGrpcClusterName
protocol = solana_yellowstone -> gate Config explicite
metadata -> YellowstoneGrpcMetadataEntry::public
secret_metadata -> YellowstoneGrpcMetadataEntry::secret
session overrides -> merge avec grpc_defaults
```
API :
| Surface | Exigence | Statut source |
|---------------------------------|-------------------------------------|---------------|
| `http_settings()` | inchangée | **OK** |
| `ws_settings()` | V1 None, V2/V3 selon profil | **OK** |
| `grpc_settings()` | V1/V2 None, V3 optionnel | **ADDED** |
| `into_transport_settings()` | tuple historique HTTP + WS inchangé | **PRESERVED** |
| `into_all_transport_settings()` | nouveau tuple HTTP + WS + gRPC | **ADDED** |
### 8.3 Provenance et secrets
Règles candidate :
```text
metadata publique + provenance KSP_SECRET_* -> reject
secret_metadata sans provenance secret -> reject
secret_metadata + variable KSP_PUBLIC_/KSP_* -> reject
secret_metadata + KSP_SECRET_/KSPB_SECRET_ -> accept
segments littéraux autour du secret -> accept
safe_value -> secret segment ********
Transport Debug -> URL/metadata secret absents
```
Le test V3 doit démontrer le cas valide et les deux croisements invalides sans exposer les canaris.
### 8.4 PublicNode Mainnet
Profil committé attendu :
```text
profile_id = publicnode_mainnet
provider = publicnode
cluster = mainnet-beta
protocol = solana_yellowstone
url = https://solana-yellowstone-grpc.publicnode.com:443 # provider affiche host:port ; KSP ajoute le scheme TLS requis
metadata = aucune
```
Le mapping doit produire un endpoint TLS Yellowstone standard et `Debug` ne doit pas exposer l'URL.
### 8.5 PublicNode Testnet
Verdict `pre.011` : **DEFERRED, NOT GUESSED**.
La page publique réauditée le 2026-08-24 expose une capacité Solana Testnet gRPC, mais l'hostname exact n'a pas été obtenu depuis une source suffisamment autoritative/indexable. Aucun profil Testnet n'est committé avant confirmation.
`pre.012` doit soit :
```text
confirmer hostname + réussir le smoke -> PASS
ou documenter l'impossibilité externe -> EXTERNAL BLOCK, sans endpoint inventé
```
## 9. Provider-neutrality
| Point | Verdict |
|-----------------------------------------------|----------------------|
| type public `PublicNodeGrpc*` sans divergence | absent, **PASS** |
| protocol standard encodé comme provider | non, **PASS** |
| provider descriptif séparé | oui, **PASS source** |
| auth PublicNode hardcodée dans Transport | non, **PASS** |
| Helius/OrbitFlare runtime gRPC dans `0.2.9` | non, **PASS** |
| provider extensions dans N2 | aucune, **PASS** |
## 10. Non-régressions obligatoires
Le gate final doit préserver :
```text
HTTP current typed 52/52
HTTP historical 14/14 Deprecated/Removed
KSP-TRANSPORT-007 vert
Standard WebSocket 9 familles / 18 opérations
Helius LaserStream WebSocket 7 familles standard + transaction + slotsUpdates, heartbeat provider-owned
Transport -> Config interdit
Transport -> std::env KSP_* interdit
tracing direct Transport interdit
```
`pre.011` ne modifie pas Transport runtime ; son seuil est donc au minimum la baseline `pre.010-fix.001`.
## 11. Historique des gates fermé
Les détails de commandes, warnings corrigés et fichiers exacts restent dans leurs deltas immuables.
| Tranche | Gate consolidé |
|-----------------------------------|--------------------------------------|
| `pre.001` + `fix.001` + `fix.002` | audit/sizing/providers/licence fermé |
| `pre.002` + `fix.001` + `fix.002` | moteur/settings/channel fermé |
| `pre.003` + `fix.001` | TLS/metadata/unary fermé |
| `pre.004` + `fix.001` | Subscribe common fermé |
| `pre.005` + `fix.001` | Accounts/Slots fermé |
| `pre.006` | namespace HTTP fermé |
| `pre.007` | Transactions fermé |
| `pre.008` + `fix.001` | Blocks fermé |
| `pre.009` + `fix.001` | bidi/backpressure fermé |
| `pre.010` + `fix.001` | reconnect/replay fermé sans warning |
Cette table remplace les anciens appendices numérotés successivement `19.x`, `20`, `21`, etc. qui rendaient le document ambigu.
## 12. Gate opérateur `pre.011`
Commandes requises :
```bash
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-config-lib
cargo test -p ksp-config-lib --test public_api
cargo test -p ksp-config-lib --test ownership
cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-core-lib --test workspace_dependencies
cargo test --workspace
```
Résultats attendus si aucun fix n'est requis :
```text
audit Rust clean / 0 export candidate
check/clippy PASS sans warning
Config unit baseline 110 + 3 nouveaux tests V3 = 113 attendus
Config public API 15 attendus, canari enrichi
Config ownership 5 attendus
Transport unit >= 383 sans régression
Transport public API >= 49 sans régression
Transport completeness >= 43 sans régression
Transport doctests 4 sans régression
workspace dependencies 3 sans régression
cargo test --workspace PASS
```
Ces nombres sont des attentes de candidate, pas un résultat déclaré avant exécution opérateur.
## 13. Gate `pre.012` et clôture stable
### 13.1 Live PublicNode
Mainnet minimal :
```text
opt-in seulement
settings Transport programmatic
aucun secret
connexion TLS
unary simple et/ou Subscribe borné selon smoke retenu
close borné
aucune dépendance Config ajoutée au test Transport pur
```
Testnet seulement après endpoint exact confirmé.
### 13.2 Compliance finale
```text
réaudit upstream release/proto
cargo tree Transport
cargo tree Transport --duplicates
cargo tree --duplicates
HTTP 52 + 14
Standard WS 18/18
Helius WS
public API crate-root
release completeness
Config V1/V2/V3
security/redaction
README/USAGE
prompt release suivante
workspace complet
```
### 13.3 Verdict stable
`0.2.9` peut devenir stable seulement si tous les éléments suivants sont vrais :
```text
standard vs extension explicitement classifié
SubscribeDeshred OUT documenté
7 unary verts
Subscribe + 9 updates verts
resource/backpressure/lifecycle verts
reconnect/replay sans promesse lossless
Config V3 backward V1/V2
provider/protocol distincts
PublicNode Mainnet validé ou incident externe précisément documenté
Testnet jamais inventé
HTTP/WS/Helius non régressés
dependency firewall vert
cargo graphs inspectés
workspace final vert
```