438 lines
19 KiB
Markdown
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
|
|
```
|