# Plan `0.2.4` — HTTP Blocks + Economics + compliance HTTP finale ## Statut Ce plan ouvre `0.2.4` par `0.2.4-pre.001` sur la base stable attendue `v0.2.3`. `0.2.1` a stabilisé la foundation HTTP et 4 wrappers typed, `0.2.2` les 22 wrappers Accounts/Tokens/Cluster et `0.2.3` les 11 wrappers Transactions. La surface acquise au démarrage est donc : ```text 52 méthodes HTTP courantes enregistrées 14 méthodes historiques Deprecated / runtime Removed 37 wrappers typed courants 15 wrappers typed restant sous HttpRpcCoverageRelease::V0_2_4 ``` La mission de `0.2.4` est strictement de compléter les **10 Blocks + 5 Economics** déjà affectées à `V0_2_4`, puis de fermer la compliance HTTP globale **52/52 current + 14/14 historical** sous la règle `KSP-TRANSPORT-007`. `0.2.4-rel.001` clôt ce plan sous statut **stable** : les 15/15 wrappers `V0_2_4` sont publiés, l'inventaire final reste 52 current + 14 Deprecated, les deux ensembles correspondent exactement au registre KSP et la matrice durable de clôture est `docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`. ## Gate de sizing `pre.001` Question obligatoire : ```text Les 15 wrappers Blocks/Economics, leurs DTOs/wires, les overloads/legacy, les tests, la compliance 52+14 et la documentation peuvent-ils être clôturés proprement dans cette release/session ? ``` Réponse : ```text OUI. ``` Aucun split de release n'est nécessaire avant implémentation. Le volume est supérieur à `0.2.3` en nombre de wrappers mais reste inférieur à `0.2.2`. La complexité est surtout concentrée dans `getBlock`, `getBlockProduction`, `getInflationReward` et la compliance finale ; ces fils sont donc isolés dans des prereleases dédiées. Si une tranche réelle dépasse le budget KSP d'environ 15–20 minutes, une prerelease supplémentaire sera créée **dans `0.2.4`** sans déplacer silencieusement une méthode vers `0.2.5`. ## Sources normatives réauditées le 2026-08-18 Documentation publique : ```text https://solana.com/docs/rpc/http https://solana.com/docs/rpc/json-structures ``` Pages Blocks : ```text https://solana.com/docs/rpc/http/getblock https://solana.com/docs/rpc/http/getblockcommitment https://solana.com/docs/rpc/http/getblockheight https://solana.com/docs/rpc/http/getblockproduction https://solana.com/docs/rpc/http/getblocks https://solana.com/docs/rpc/http/getblockswithlimit https://solana.com/docs/rpc/http/getblocktime https://solana.com/docs/rpc/http/getfirstavailableblock https://solana.com/docs/rpc/http/getrecentperformancesamples https://solana.com/docs/rpc/http/minimumledgerslot ``` Pages Economics : ```text https://solana.com/docs/rpc/http/getinflationgovernor https://solana.com/docs/rpc/http/getinflationrate https://solana.com/docs/rpc/http/getinflationreward https://solana.com/docs/rpc/http/getstakeminimumdelegation https://solana.com/docs/rpc/http/getsupply ``` La documentation Solana actuelle relie encore plusieurs définitions/source examples à **Agave `v3.1.8`**. Ce pointeur documentaire n'est donc pas utilisé comme preuve que `v3.1.8` représente le runtime stable actuel. Le cross-audit runtime a été effectué contre **Agave `v4.2.1`**, release patch publiée le 2026-08-13 dans la branche stable `4.2.x`. `v4.2.0` est explicitement publiée comme stable pour Mainnet Beta, Devnet et Testnet ; `v4.3.0-beta.0`, plus récente en date, reste une prerelease et n'est pas la baseline normative de cette release KSP. Sources primaires Agave ciblées : ```text https://github.com/anza-xyz/agave/releases/tag/v4.2.1 https://github.com/anza-xyz/agave/blob/v4.2.1/rpc/src/rpc.rs https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/config.rs https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/response.rs https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-api/src/custom_error.rs https://github.com/anza-xyz/agave/blob/v4.2.1/transaction-status-client-types/src/lib.rs https://github.com/anza-xyz/agave/blob/v4.2.1/transaction-status-client-types/src/option_serializer.rs https://github.com/anza-xyz/agave/blob/v4.2.1/transaction-status/src/lib.rs ``` SIMDs primaires ciblés par l'audit `KSP-TRANSPORT-007` : ```text https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0096-reward-collected-priority-fee-in-entirety.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0118-partitioned-epoch-reward-distribution.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0123-block-revenue-distribution.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0180-vote-account-leader-schedule.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0185-vote-account-v4.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0186-loaded-transaction-data-size-specification.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0291-commission-rate-in-basis-points.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0298-bank-hash-in-block-footer.md https://github.com/solana-foundation/solana-improvement-documents/pull/301 https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0307-add-block-footer.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0490-upgrade-stake-to-v5.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0550-double-disinflation.md https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0553-resource-fee-burn.md ``` ## Inventaire officiel réaudité L'index HTTP Solana actuel contient toujours exactement les catégories suivantes : ```text Accounts 6 Tokens 5 Transactions 11 Blocks 10 Cluster 15 Economics 5 -- Current 52 ``` La navigation Deprecated conserve les 14 noms historiques déjà enregistrés par KSP : ```text confirmTransaction getConfirmedBlock getConfirmedBlocks getConfirmedBlocksWithLimit getConfirmedSignaturesForAddress2 getConfirmedTransaction getFeeCalculatorForBlockhash getFeeRateGovernor getFees getRecentBlockhash getSignatureConfirmation getSignatureStatus getSnapshotSlot getStakeActivation ``` La partition KSP reste donc inchangée : ```text 0.2.1 = 4 0.2.2 = 22 0.2.3 = 11 0.2.4 = 15 -- current = 52 historical = 14 ``` Les 15 descriptors `V0_2_4` sont déjà classés `Read / RetrySafe`. `getBlock` reste le seul de ces descriptors marqué `StableWithDeprecatedLegacy` à cause de son second paramètre bare encoding encore accepté pour compatibilité. ## Règle de complétude `KSP-TRANSPORT-007` Un wrapper de cette release n'est complet que s'il expose sans perte toutes les possibilités RPC retenues par l'audit : paramètres ordonnés, objets de config, overloads, formes legacy encore supportées, contraintes déterministes utiles, variantes de réponse et distinctions `omitted`/`null` nécessaires. Pour `0.2.4`, cela impose notamment : - de ne pas réduire `getBlocks` à la seule forme `[start, end, config]` ; - de conserver le bare encoding legacy de `getBlock` sans le présenter comme forme recommandée ; - de préserver `transactionDetails = full ou signatures ou none ou accounts` et les conséquences sur la présence des champs de bloc ; - de préserver les champs wire riches des transactions/meta/rewards sans importer un client RPC Solana haut niveau ; - de conserver les `null` positionnels de `getInflationReward` et le champ runtime `commissionBps` lorsqu'il est présent ; - de ne pas inventer de limite d'adresses `getInflationReward` si aucune limite sémantique fixe n'est établie par la documentation/runtime courant ; la limite générale de taille de requête HTTP n'est pas transformée artificiellement en cardinalité métier KSP. ## Audit SIMD lié à `KSP-TRANSPORT-007` Le statut d'un SIMD n'est pas, à lui seul, le critère d'implémentation de Transport. La règle est la suivante : - si la baseline Solana/Agave stable expose déjà un paramètre, un champ ou une variante wire provenant d'une évolution SIMD, KSP doit le préserver même si le document SIMD n'a pas encore le statut `Activated` ; - si un SIMD modifie seulement la sémantique d'une valeur calculée par le runtime sans modifier son wire, KSP ne doit ni recalculer ni figer cette valeur localement ; - si un SIMD `Draft`/`Review` propose une extension RPC absente de la baseline stable retenue, KSP ne l'invente pas mais l'inscrit dans la watchlist et la réaudite avant le wrapper concerné puis à la compliance finale. ### SIMD applicables à la baseline `v4.2.1` **SIMD-0118 — Partitioned Epoch Rewards Distribution** est `Activated` et a un impact direct sur `getBlock`. Le wire stable `UiConfirmedBlock` expose `numRewardPartitions` sous forme optionnelle. La future structure de bloc KSP doit donc : - conserver `num_reward_partitions`/`numRewardPartitions` sans synthétiser `0` lorsqu'il est absent ; - utiliser `SolanaWireField` ou une représentation équivalente capable de préserver au minimum l'omission, et de ne pas écraser un éventuel `null` de compatibilité ; - couvrir par fixture un bloc avec `numRewardPartitions` présent et un bloc où le champ est omis ; - ne pas déduire localement le nombre de partitions à partir des rewards ou de l'epoch. **SIMD-0291 — Commission Rate in Basis Points** est encore en `Review`, mais Agave stable `v4.2.1` expose déjà les champs RPC de compatibilité correspondants. Il affecte trois surfaces KSP : - `getVoteAccounts.inflationRewardsCommissionBps` : déjà couvert et testé dans la surface `0.2.2`; aucune remédiation n'est requise ; - `getBlock.rewards[].commissionBps` : à couvrir dans `0.2.4` avec un reward wire de bloc dédié, distinct du reward d'inflation ; - `getInflationReward[].commissionBps` : à couvrir dans `0.2.4` dans le DTO `SolanaInflationReward` ou nom final équivalent. Pour les deux nouveaux wires de rewards, `commission` reste nullable et `commissionBps` doit préserver son caractère optionnel/omis. Les deux structures ne doivent pas être fusionnées artificiellement : le reward de bloc possède notamment `pubkey`, `lamports`, `postBalance` et `rewardType`, alors que le reward d'inflation possède `epoch`, `effectiveSlot`, `amount` et `postBalance`. La surface `getTransaction` de `0.2.3` ne nécessite pas de correction SIMD-0291 : `meta` est déjà conservé losslessly en `SolanaWireField`, ce qui préserve les rewards imbriqués et leurs extensions sans décodage métier. ### SIMDs déjà absorbés ou sans nouveau wire HTTP **SIMD-0185 — Vote Account v4** est `Accepted`. Les nouvelles données de vote account peuvent faire évoluer les sous-arbres retournés par les parsers `jsonParsed`, mais `SolanaParsedAccountData.parsed` reste un `serde_json::Value` lossless. Agave `v4.2.1` n'ajoute pas les collector fields de Vote Account v4 au DTO dédié `RpcVoteAccountInfo`; aucune extension spéculative de `SolanaVoteAccountInfo` n'est donc ajoutée maintenant. **SIMD-0186 — Loaded Transaction Data Size Specification** est `Accepted` et précise la sémantique consensus de la taille de données chargées. La surface `simulateTransaction` de `0.2.3` expose déjà `loadedAccountsDataSize` via `SolanaWireField` et couvre son omission : aucune nouvelle structure n'est requise. Transport ne doit pas recalculer cette valeur à partir des comptes de la transaction ; il restitue le résultat runtime. **SIMD-0385 — Transaction V1 Format** est encore en `Review`. Agave `v4.2.1` possède déjà du plumbing V1 dans ses types transaction-status, mais le contrat KSP acquis est volontairement générique : `SolanaTransactionVersion::Number(u8)` n'est pas limité à `0`, et les payloads JSON restent lossless. `0.2.4` doit conserver cette propriété dans `getBlock` et ajouter une canary déterministe avec une version numérique non nulle afin d'interdire une régression vers un modèle `legacy ou v0` seulement. **SIMD-0096 — Reward full priority fee to validator** est `Activated`, mais change la distribution économique des priority fees sans changer le wire HTTP que KSP doit décoder. Transport continue à restituer les valeurs runtime ; aucune structure spécifique n'est ajoutée. **SIMD-0550 — Double Disinflation Rate** est en `Review` et précise explicitement que `getInflationRate` et `getInflationGovernor` refléteront la nouvelle schedule sans changement d'API. KSP ne doit donc figer ni `initial`, ni `taper`, ni le taux courant : les DTOs restent des valeurs runtime `f64` et aucune formule d'inflation n'est réimplémentée dans Transport. Un réaudit avant la tranche Economics et à la clôture vérifie qu'aucun nouveau champ n'a été ajouté par la baseline stable. ### Watchlist obligatoire pendant `0.2.4` **SIMD-0180 — Vote Account Address Keyed Leader Schedule** est en `Review`. Son volet RPC demande explicitement que les endpoints historiques de leader schedule et slot leader continuent à retourner l'identité validator afin de préserver la compatibilité, tout en prévoyant de nouveaux endpoints vote-account-keyed. Le wrapper KSP `getLeaderSchedule` acquis en `0.2.2` ne doit donc pas être modifié spéculativement. En revanche, le réaudit d'inventaire de `pre.009` doit détecter si de nouveaux endpoints ont rejoint la surface HTTP officielle : ce serait alors une évolution de l'inventaire RPC, pas un changement silencieux du wire de `getLeaderSchedule`. **SIMD-0307 — Add Block Footer** est en `Review` et propose précisément une extension de `getBlock` : option de config `footer` et champs footer dans la réponse. Ces éléments sont absents de `RpcBlockConfig` et `UiConfirmedBlock` dans Agave stable `v4.2.1`; ils ne doivent donc pas être inventés. **SIMD-0298 — Add `bank_hash` to block footer** reste au statut documentaire `Idea` et prévoit d'étendre ce même footer avec `bank_hash`. Le réaudit `pre.006` du 18 août 2026 confirme que le wire RPC stable `v4.2.1` n'expose toujours aucun de ces champs. Le tracker Bankless Leader amont signale néanmoins l'implémentation Agave du mécanisme de block footer/bank hash pour la future migration Alpenglow : cela renforce la nécessité du réaudit final sans justifier une extension spéculative du wrapper actuel. **SIMD-0301 — Replace `bank_hash` with `parent_bank_hash`** est également surveillé comme évolution directement dépendante de ce footer. La proposition amont a été fermée sans merge le 28 janvier 2026; elle n'est donc pas un contrat SIMD adopté ni un champ RPC stable. `pre.009` doit réauditer ensemble `0298`, `0301` et `0307`. Si une baseline stable expose alors le footer, `KSP-TRANSPORT-007` impose de couvrir toutes ses options et tous ses champs effectivement livrés, sans supposer à l'avance si le hash final est `bankHash`, `parentBankHash` ou absent. **SIMD-0490 — Upgrade BPF Stake Program to v5.0.0** est en `Review` et prévoit notamment une hausse du minimum de délégation ainsi que son exposition par le RPC de minimum delegation. Pour `getStakeMinimumDelegation`, KSP doit donc traiter la valeur contextualisée comme une valeur runtime opaque en lamports : aucun minimum `1 lamport`, `1 SOL` ou autre ne doit être codé en dur ou validé côté Transport. Le SIMD sera réaudité avant `pre.007` et à `pre.009`. **SIMD-0553 — Base Inclusion and Resource-based Fee** est en `Draft`. Il change la sémantique du total de fees de `getFeeForMessage`, `simulateTransaction` et `getTransaction.meta.fee` sans imposer actuellement de changement de forme JSON. Les wrappers `0.2.3` doivent donc rester pass-through/lossless et ne pas recalculer le fee. La compliance finale `52/52` réauditera cette proposition afin de détecter une éventuelle extension stable de schéma apparue pendant la release. Les SIMDs `Review` liés au block-revenue sharing, notamment SIMD-0123, peuvent modifier à terme la provenance/sémantique des rewards, mais n'ajoutent pas de champ HTTP stable dans la baseline `v4.2.1`. Le reward wire de KSP doit donc rester fidèle aux champs effectivement retournés et ne pas encoder une taxonomie économique non présente sur le wire. ## Matrice Blocks — 10 wrappers | Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` | |-------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `getBlock` | `slot`; second paramètre absent, bare encoding legacy, ou config `{commitment, encoding, transactionDetails, maxSupportedTransactionVersion, rewards}` | `object ou null`; `previousBlockhash`, `blockhash`, `parentSlot`, transactions/signatures/rewards selon config, `numRewardPartitions`, `blockTime`, `blockHeight` | commitment runtime au moins `confirmed`; réutiliser les encodings/version/transaction wire de `0.2.3`; préserver omission vs null; `numRewardPartitions` suit SIMD-0118; les rewards préservent `commissionBps` de SIMD-0291; garder les erreurs runtime de bloc/version comme erreurs RPC, sans les masquer | | `getBlockCommitment` | `slot` uniquement | `{commitment: array ou null, totalStake: u64}` | aucune config à inventer; préserver commitment nullable | | `getBlockHeight` | config contextuelle optionnelle `{commitment, minContextSlot}` | `u64` | réutiliser `SolanaContextConfig`; `minContextSlot` est transmis tel quel au runtime | | `getBlockProduction` | config optionnelle `{commitment, identity, range:{firstSlot,lastSlot?}}` | `SolanaRpcResponse<{byIdentity, range}>` | `identity` typée Pubkey; validation locale déterministe `lastSlot >= firstSlot` lorsque les deux sont fournis; préserver les couples `[leaderSlots, blocksProduced]` | | `getBlocks` | `[start]`, `[start,end]`, `[start,config]`, `[start,end,config]`; config `{commitment,minContextSlot}` | `Vec` | commitment au moins `confirmed`; transmettre `minContextSlot`; conserver l'overload untagged du second paramètre; `end < start` donne `[]`; rejeter localement une différence `end-start > 500_000` | | `getBlocksWithLimit` | `start`, `limit`, config contextuelle optionnelle `{commitment,minContextSlot}` | `Vec` | commitment au moins `confirmed`; transmettre `minContextSlot`; `limit <= 500_000`; `limit = 0` est valide et donne `[]` | | `getBlockTime` | `slot` uniquement | `i64 ou null` | préserver l'absence de timestamp; les cas cleaned/skipped/not available restent des erreurs RPC runtime, pas des valeurs synthétiques | | `getFirstAvailableBlock` | aucun paramètre | `u64` | requête exacte `params: []`; aucune config | | `getRecentPerformanceSamples` | `limit?` | tableau de `{slot,numTransactions,numSlots,samplePeriodSecs,numNonVoteTransactions?}` | défaut runtime `720`; maximum `720`; rejeter avant I/O `limit > 720`; préserver `numNonVoteTransactions` nullable/ancien runtime | | `minimumLedgerSlot` | aucun paramètre | `u64` | requête exacte `params: []`; conserver les erreurs ledger/runtime | ### Clarification runtime `pre.004` — config des ranges Blocks Le réaudit d’implémentation de `pre.004` confirme dans Agave `v4.2.1` que `getBlocks` et `getBlocksWithLimit` consomment tous deux `RpcContextConfig`, et non un simple objet commitment. Le wrapper `RpcBlocksConfigWrapper` permet en plus à `getBlocks` de recevoir soit `end_slot`, soit cette config en deuxième position. KSP doit donc réutiliser `SolanaContextConfig` et préserver les deux champs stables : ```text commitment minContextSlot ``` La documentation publique n’affiche actuellement que `commitment` sur ces pages ; la source runtime stable prime ici conformément à `KSP-TRANSPORT-007`. ### `getBlock` — stratégie wire `getBlock` est le plus gros fil de la release et reçoit une prerelease dédiée. Les primitives déjà acquises de `rpc_transactions` doivent être réutilisées lorsque le wire est réellement commun : ```text SolanaTransactionEncoding SolanaEncodedTransaction SolanaTransactionVersion SolanaWireField ``` `SolanaConfirmedTransaction` ne doit **pas** être réutilisé tel quel pour un élément de bloc : ce DTO contient `slot` et `blockTime`, qui appartiennent au résultat top-level de `getTransaction` et non à chaque élément `transactions[]` d'un bloc. Un type wire de transaction de bloc dédié peut en revanche composer les primitives ci-dessus et préserver `transaction`, `meta` et `version` sans décodage Program. Les champs top-level dont la présence dépend de la config (`transactions`, `signatures`, `rewards`, `numRewardPartitions`) doivent utiliser une représentation capable de distinguer une omission d'un `null` lorsqu'une telle distinction existe sur le wire. `numRewardPartitions` est explicitement rattaché à SIMD-0118 et doit être couvert en présent/omis. Le reward wire de bloc doit conserver `commission` nullable et `commissionBps` optionnel/omis de SIMD-0291. Les transactions `accounts` ne doivent pas être forcées dans une structure `full` plus riche que le wire réellement retourné. Une version de transaction numérique différente de `0` doit rester représentable afin de ne pas régresser la compatibilité préparée pour SIMD-0385. ## Matrice Economics — 5 wrappers | Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` | |-----------------------------|-----------------------------------------------------------------------------------|--------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `getInflationGovernor` | config commitment optionnelle | `{initial,terminal,taper,foundation,foundationTerm}` en `f64` | réutiliser `SolanaCommitmentConfig`; aucun contexte de réponse | | `getInflationRate` | aucun paramètre | `{total,validator,foundation,epoch}` | requête exacte `params: []` | | `getInflationReward` | liste ordonnée d'adresses; config optionnelle `{epoch,commitment,minContextSlot}` | `Vec>` positionnel | commitment >= `confirmed`; ordre/cardinalité identiques aux entrées; préserver `commission: u8 ou null` et `commissionBps: u16` optionnel/omis de Agave `v4.2.1` conformément à SIMD-0291; aucune limite fixe d'adresses inventée | | `getStakeMinimumDelegation` | config contextuelle optionnelle `{commitment,minContextSlot}` | `SolanaRpcResponse` | réutiliser `SolanaContextConfig` / `SolanaRpcResponse`; restituer la valeur runtime en lamports sans minimum codé en dur; surveiller SIMD-0490 | | `getSupply` | config optionnelle `{commitment,excludeNonCirculatingAccountsList}` | `SolanaRpcResponse<{total,circulating,nonCirculating,nonCirculatingAccounts}>` | le booléen runtime par défaut est `false`; préserver la liste ordonnée retournée lorsqu'elle est demandée | ### Extension runtime `commissionBps` La documentation publique actuelle de `getInflationReward` énumère encore uniquement `commission`. Agave `v4.2.1` définit cependant aussi : ```text commission_bps: Option ``` sérialisé en `commissionBps` lorsqu'il est présent. Ce champ correspond à l'évolution SIMD-0291 et doit être conservé dans le DTO KSP pour ne pas perdre une capacité/extension du runtime stable courant. Le DTO doit préserver séparément `commission` nullable et `commissionBps` optionnel/omis; il ne doit pas convertir les basis points en pourcentage ni dériver l'un des deux champs depuis l'autre. ## Contraintes locales retenues Les validations déterministes suivantes doivent être réalisées avant I/O : ```text getBlock commitment >= confirmed getBlocks commitment >= confirmed getBlocks end-start <= 500_000 lorsqu'end >= start getBlocksWithLimit commitment >= confirmed getBlocksWithLimit limit <= 500_000 getRecentPerformanceSamples limit <= 720 getBlockProduction lastSlot >= firstSlot lorsqu'ils sont tous deux présents getInflationReward commitment >= confirmed ``` `getBlocks(end < start)` et `getBlocksWithLimit(limit = 0)` sont des cas valides qui doivent produire un tableau vide plutôt qu'une erreur locale. Ne pas reproduire localement les validations qui nécessiteraient un décodage disproportionné ou l'état du ledger : disponibilité réelle d'un bloc, slot cleaned/skipped, support effectif d'une version de transaction par le caller, présence historique des metadata, epoch disponible, minContextSlot atteint, etc. Ces cas restent des erreurs/réponses RPC validées par le flux central. ## Réutilisation des contrats existants ### À réutiliser directement ```text SolanaCommitment SolanaCommitmentConfig SolanaContextConfig SolanaRpcContext SolanaRpcResponse SolanaTransactionEncoding SolanaEncodedTransaction SolanaTransactionVersion SolanaWireField ``` ### À introduire dans `0.2.4` Noms définitifs ajustables pendant l'implémentation, responsabilités fixes : ```text config getBlock moderne + enum transactionDetails config/range/result getBlockProduction block commitment result confirmed block + transaction-in-block + reward wire, avec `numRewardPartitions` SIMD-0118 et `commissionBps` SIMD-0291 performance sample inflation governor/rate/reward, avec reward d'inflation distinct et `commissionBps` SIMD-0291 supply result/config ``` La déduplication ne doit pas fusionner des contrats ayant des sémantiques différentes uniquement parce que leurs champs se ressemblent. ## Architecture d'exécution Les 15 wrappers restent `Read / RetrySafe` et passent exclusivement par : ```text wrapper typed -> descriptor central -> execute_standard_rpc -> pool/admission -> executor HTTP -> validation JSON-RPC -> decode typed ``` Interdits : ```text client HTTP parallèle reqwest direct dans un wrapper retry/deadline/admission bypass Transport -> Config Transport -> Store/Program tracing direct solana-rpc-client / solana-client pour masquer les possibilités RPC ``` ## Dépendances Aucune nouvelle dépendance n'est nécessaire au vu de l'audit `pre.001`. En particulier : ```text solana-rpc-client NON solana-client NON crate SDK Block NON base64/bs58 NON pour cette release ``` Les primitives `serde`/`serde_json`, `ksp-core-lib::Pubkey` et les wires Transaction déjà présents suffisent à exprimer les contrats sans introduire un SDK RPC haut niveau. ## Tests déterministes attendus Chaque wrapper doit couvrir : - request JSON exacte ; - absence de config et objet vide lorsque ces deux formes sont significatives ; - tous les overloads/configs/encodings pertinents ; - réponse typed nominale ; - `null` et omission lorsque le wire les distingue ; - ordre et cardinalité ; - erreur JSON-RPC propagée ; - validation déterministe avant I/O lorsqu'elle est retenue par ce plan. Cas de régression obligatoires spécifiques : ```text getBlock bare encoding legacy getBlock transactionDetails full/signatures/none/accounts getBlock result null getBlock numRewardPartitions présent/omis (SIMD-0118) getBlock rewards commission nullable + commissionBps présent/omis (SIMD-0291) getBlock transaction version numérique non nulle conservée (canary SIMD-0385) getBlocks [start,config] vs [start,end,config] + minContextSlot transmis getBlocks range > 500_000 rejetée avant I/O getBlocksWithLimit 0 et > 500_000 + minContextSlot transmis getRecentPerformanceSamples défaut/720/>720 getBlockProduction lastSlot < firstSlot rejeté avant I/O getInflationReward ordre + null positionnels + commission/commissionBps présent/omis (SIMD-0291) getStakeMinimumDelegation valeur runtime arbitraire sans minimum codé en dur (watch SIMD-0490) getSupply excludeNonCirculatingAccountsList true/false/omitted ``` ## Compliance finale HTTP La dernière prerelease doit ajouter une preuve explicite que les **52 méthodes courantes enregistrées** possèdent désormais toutes un wrapper typed public réel. Un appel raw/générique ne compte pas. Canaries finales : ```text current registry == 52 historical registry == 14 V0_2_1 exact == 4 V0_2_2 exact == 22 V0_2_3 exact == 11 V0_2_4 exact == 15 typed wrappers current == 52/52 historical Deprecated/Removed == 14/14 KSP-TRANSPORT-007 audited current == 52/52 ``` La compliance `KSP-TRANSPORT-007` des 37 wrappers de `0.2.1`–`0.2.3` reste acquise par `docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`; la clôture `0.2.4` vérifie qu'aucune régression n'a été introduite et applique la même règle aux 15 nouveaux wrappers. Le réaudit final inclut explicitement les extensions wire déjà acquises SIMD-0118 et SIMD-0291, puis l'état des SIMD susceptibles de modifier la surface HTTP ou sa sémantique observable, au minimum SIMD-0180, SIMD-0298, SIMD-0301, SIMD-0307, SIMD-0385, SIMD-0490, SIMD-0550 et SIMD-0553, afin qu'une évolution devenue stable pendant la session ne soit pas oubliée. Il réaudite aussi l'inventaire officiel lui-même afin de détecter d'éventuels nouveaux endpoints issus de SIMD-0180 ou d'une autre évolution d'interface. ## Réaudit final `pre.009` Le réaudit du **18 août 2026** confirme l'index HTTP officiel actuel sans recalibrage : ```text Solana current HTTP exact names == KSP current registry exact names == 52 Solana Deprecated exact names == KSP historical exact names == 14 missing == 0 extra == 0 ``` La navigation officielle actuelle ne contient aucun nouvel endpoint HTTP issu de SIMD-0180. État final de la watchlist prospective : ```text SIMD-0180 Review SIMD-0298 Idea SIMD-0301 PR closed / unmerged SIMD-0307 Review SIMD-0385 Review SIMD-0490 Review SIMD-0550 Review SIMD-0553 Draft ``` Extensions SIMD déjà matérialisées dans le wire stable et réauditées à la clôture : ```text SIMD-0118 Activated -> numRewardPartitions préservé en omitted/null/value SIMD-0291 Review -> commission et commissionBps préservés indépendamment ``` Le statut `Review` de SIMD-0291 ne retire pas le champ déjà exposé par Agave `v4.2.1` : `KSP-TRANSPORT-007` impose de conserver ce wire réellement livré. SIMD-0118 est `Activated` et confirme définitivement que `numRewardPartitions` fait partie des extensions de bloc à ne pas aplatir ni synthétiser. Conséquences : - aucun changement anticipé de `getLeaderSchedule` pour SIMD-0180 ; - aucun `footer`, `bankHash` ou `parentBankHash` spéculatif dans `getBlock` ; - `SolanaTransactionVersion::Number(u8)` reste générique ; - minimum de délégation et inflation restent des valeurs runtime ; - SIMD-0553 ne crée aucun nouveau contrat HTTP stable dans la baseline auditée. La preuve typed finale est doublée : ```text public API canary -> référence les 52 wrappers current + 2 wrappers legacy séparés release canary -> fige noms exacts 52 + 14 et partition 4/22/11/15 ``` La matrice complète est conservée dans `docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`. ## Smokes live Les smokes restent opt-in et secondaires par rapport aux fixtures locales. `pre.009` étend le smoke Transport pur avec `getBlockHeight`, `getInflationRate` et `getStakeMinimumDelegation`. Ces reads restent robustes : aucun slot historique fixe, aucun compte reward spécifique et aucune valeur économique codée en dur. Éviter un `getBlock` dépendant d'un slot fixe ou tout scénario fragile lié à des récompenses d'un epoch précis. Le smoke historique Config -> Transport reste une exception transitoire de composition et ne devient pas la destination générale des futurs scénarios cross-crates. ## Prévision souple des prereleases ```text pre.001 audit officiel actuel + Agave stable + matrice + wires + contraintes + sizing pre.002 primitives/configs/results Blocks/Economics partagés + reward wires SIMD-0118/0291 + fixtures communes pre.003 Blocks simples : getBlockCommitment, getBlockHeight, getBlockTime, getFirstAvailableBlock, minimumLedgerSlot pre.004 ranges/performance : getBlocks, getBlocksWithLimit, getRecentPerformanceSamples pre.005 getBlockProduction + range/identity/result contextualisé pre.006 réaudit SIMD-0298/0307 + getBlock moderne + bare encoding legacy + transactionDetails + wire bloc riche + SIMD-0118/0291 + canary version numérique SIMD-0385 pre.007 réaudit SIMD-0490/0550 + Economics simples : getInflationGovernor, getInflationRate, getStakeMinimumDelegation, getSupply pre.008 réaudit commitment runtime + getInflationReward + null positionnels + commissionBps SIMD-0291 + invariants pre.009 réaudit SIMD HTTP (0118/0180/0291/0298/0301/0307/0385/0490/0550/0553 minimum) + réaudit inventaire officiel + compliance finale 52/52 + 14/14 + KSP-TRANSPORT-007 + docs + smokes + graphes + prompt 0.2.5 — Wallet foundation rel.001 publication strictement publicationnelle ``` Cette prévision peut être redécoupée si une tranche dépasse le budget réel. Elle ne doit pas être compressée artificiellement pour conserver un numéro de prerelease prévu. ## Hors périmètre ```text Wallet / .kspwallet WebSocket LaserStream Yellowstone gRPC Store/Program/Materializer modèle métier de transaction/bloc client RPC Solana haut niveau réécriture des deltas historiques ``` ## Critères de clôture `0.2.4` - 15/15 wrappers `V0_2_4` publics, typed et `KSP-TRANSPORT-007` conformes ; - 52/52 méthodes HTTP courantes avec wrapper typed ; - 14/14 historiques conservées en compliance ; - aucun bypass du flux central Transport ; - aucune nouvelle dépendance injustifiée ; - tests déterministes complets ; - smokes live pertinents validés par preuve opérateur ; - graphes Cargo Transport/Config réaudités ; - README/USAGE/matrices/validation synchronisés ; - prompt `0.2.5 — Wallet foundation` finalisé ; - dernière prerelease candidate complète ; - `0.2.4-rel.001` strictement publicationnelle. ## Publication stable `rel.001` La candidate `pre.009`, complétée par le fix documentaire `pre.009-fix.001`, a reçu les preuves opérateur de clôture suivantes le **18 août 2026** : ```text cargo test -p ksp-config-lib OK cargo test -p ksp-core-lib OK cargo test -p ksp-app-config-desk OK cargo test --workspace OK Transport dans le workspace : 240 unit passed 27 public API passed 22 release completeness passed smoke Devnet Transport pur 1 passed smoke Devnet Config -> Transport 1 passed ``` Les canaries workspace de dépendances et d’ownership Logging passent également dans `cargo test --workspace`. Les sorties manuelles `cargo tree` n’étant pas présentes dans le journal opérateur fourni à la publication, elles ne sont pas déclarées artificiellement comme exécutées ; les contrôles de graphe restent à rejouer avec la gate finale post-application de `rel.001` avant création du tag. `rel.001` ne modifie aucun wrapper, DTO, comportement réseau, dépendance ou feature Cargo : il passe uniquement le workspace à `0.2.4` stable et synchronise la documentation de publication. ## Questions ouvertes Aucune question fonctionnelle ou wire bloquante pour `0.2.4`. Les choix fonctionnels et wire de `0.2.4` sont figés. Toute nouvelle évolution officielle détectée après publication appartient à une release ultérieure, sauf défaut de conformité démontré nécessitant un correctif stable explicite.