# Delta `0.2.4-pre.002` — primitives Blocks/Economics et fixtures wire partagées ## Base requise Livraison précédente : ```text 0.2.4-pre.001-fix.001 workspace.package.version = "0.2.4-pre.1" ``` Le plan canonique est `docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md` version 2. Le fix `pre.001-fix.001` est appliqué avant cette tranche ; les deltas historiques `pre.001.md` et `pre.001-fix.001.md` restent inchangés. ## Objectif Installer les primitives, configurations et résultats partagés nécessaires aux 10 wrappers Blocks et 5 wrappers Economics de `0.2.4`, ainsi que leurs fixtures wire locales déterministes, sans encore implémenter les wrappers prévus à partir de `pre.003` et sans déclarer la couverture typed `V0_2_4` complète. Cette tranche matérialise dès maintenant les exigences `KSP-TRANSPORT-007` qui appartiennent au wire partagé : omissions/null explicites, versions de transaction numériques génériques, reward partitions SIMD-0118, commissions basis-points SIMD-0291, adresses RPC typées en `Pubkey` et sous-arbres Transaction riches conservés losslessly. ## Version Cargo Conformément à `VER-ID-009`, la nouvelle prerelease synchronise le signal technique : ```text 0.2.4-pre.1 -> 0.2.4-pre.2 ``` Aucune dépendance ni feature Cargo n'est ajoutée ou modifiée. ## Implémentation ### Module Blocks partagé Le nouveau module privé `rpc_blocks` ajoute les types publics suivants, réexportés explicitement depuis la racine de crate : ```text SolanaTransactionDetails SolanaGetBlockConfig SolanaBlockProductionRange SolanaBlockProductionConfig SolanaBlockCommitment SolanaBlockProductionResultRange SolanaBlockProduction SolanaBlockReward SolanaBlockTransaction SolanaConfirmedBlock SolanaPerformanceSample ``` `SolanaTransactionDetails` couvre exactement les quatre valeurs wire modernes : ```text full signatures none accounts ``` `SolanaGetBlockConfig` conserve indépendamment les cinq options du contrat moderne : ```text commitment encoding transactionDetails maxSupportedTransactionVersion rewards ``` Aucune validation de commitment ni aucun choix de forme legacy n'est encore exécuté ici : ces responsabilités appartiennent au wrapper `getBlock` de `pre.006`. `SolanaBlockProductionConfig` conserve `commitment`, une `identity` typée `Pubkey` et une range `firstSlot/lastSlot?`. La validation `lastSlot >= firstSlot` reste volontairement réservée au wrapper `getBlockProduction` de `pre.005`. `SolanaBlockProduction` décode les clés dynamiques de `byIdentity` en `Pubkey` et conserve les couples `(leader slots, blocks produced)` ainsi que la range effective retournée par le runtime. Le futur wrapper appliquera le `SolanaRpcResponse` partagé autour de ce résultat. ### Wire `getBlock` `SolanaConfirmedBlock` est un DTO bloc dédié et ne réutilise pas `SolanaConfirmedTransaction`, dont `slot` et `blockTime` sont propres au top-level de `getTransaction`. Le bloc conserve : ```text previousBlockhash blockhash parentSlot transactions signatures rewards numRewardPartitions blockTime blockHeight ``` Les champs conditionnels `transactions`, `signatures`, `rewards` et `numRewardPartitions` utilisent `SolanaWireField` afin de préserver les trois états : ```text Omitted Null Value(T) ``` `numRewardPartitions` couvre explicitement le wire associé à SIMD-0118 sans synthétiser une valeur `0` en cas d'omission ou de `null`. `SolanaBlockTransaction` compose les primitives Transaction déjà acquises : ```text SolanaEncodedTransaction SolanaWireField pour meta SolanaWireField pour version ``` Le décodeur interne `SolanaTransactionVersion::decode_wire` passe donc de privé à `pub(crate)` pour être réutilisé sans dupliquer la logique `legacy | u8`. Son comportement public reste inchangé. Une fixture `getBlock` porte volontairement la version numérique `1` afin d'empêcher une future régression qui bornerait artificiellement cette primitive à V0, conformément au watchpoint SIMD-0385. `SolanaBlockReward` conserve : ```text pubkey: Pubkey lamports: i64 postBalance: u64 rewardType: String ou null commission: u8 ou null commissionBps: SolanaWireField ``` `commissionBps` couvre l'extension stable déjà exposée par le runtime pour SIMD-0291. `commission` et `commissionBps` restent indépendants ; Transport ne dérive jamais l'un depuis l'autre. `rewardType` reste volontairement une chaîne nullable au niveau Transport. Cette tranche n'introduit pas une taxonomie économique KSP spéculative alors que les évolutions de reward semantics restent dans la watchlist, notamment SIMD-0123. ### Module Economics partagé Le nouveau module privé `rpc_economics` ajoute et réexporte : ```text SolanaInflationGovernor SolanaInflationRate SolanaInflationRewardConfig SolanaInflationReward SolanaSupplyConfig SolanaSupply ``` `SolanaInflationGovernor` et `SolanaInflationRate` conservent directement les valeurs runtime `f64`/epoch sans reproduire localement les formules d'inflation. `SolanaInflationRewardConfig` sérialise uniquement les options fournies : ```text epoch commitment minContextSlot ``` `SolanaInflationReward` conserve `commission: Option` et `commissionBps: SolanaWireField` pour couvrir SIMD-0291 sans perdre la différence omission/null/présent du champ basis-points. La cardinalité et les `null` positionnels de la liste `getInflationReward` seront pris en charge par le wrapper de `pre.008`; le DTO de cette tranche représente uniquement une entrée non-null. `SolanaSupplyConfig` utilise `Option` pour `excludeNonCirculatingAccountsList`. Cela distingue un champ omis d'un `false` explicitement envoyé, tout en laissant le runtime appliquer son défaut lorsque l'option est absente. `SolanaSupply` convertit la liste ordonnée `nonCirculatingAccounts` en `Vec` et échoue proprement si une clé retournée n'est pas une public key valide. Le futur wrapper réutilisera `SolanaRpcResponse`. ### Frontières conservées Cette prerelease n'ajoute aucun `impl HttpTransportPool` pour les 15 méthodes `V0_2_4`. Les nouveaux types sont donc uniquement des contrats wire/config/result partagés. Le flux d'exécution reste inchangé : ```text wrapper typed futur -> descriptor central -> execute_standard_rpc -> pool/admission -> executor HTTP -> validation JSON-RPC -> decode typed ``` Aucun client HTTP parallèle, aucune boucle de retry locale et aucune dépendance Solana RPC haut niveau ne sont introduits. ## Fixtures déterministes ajoutées ```text crates/ksp-onchain-transport-lib/fixtures/http/block_commitment.variants.json crates/ksp-onchain-transport-lib/fixtures/http/block_production.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/confirmed_block.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/confirmed_block.omissions.json crates/ksp-onchain-transport-lib/fixtures/http/performance_sample.variants.json crates/ksp-onchain-transport-lib/fixtures/http/inflation_governor.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/inflation_rate.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/inflation_reward.variants.json crates/ksp-onchain-transport-lib/fixtures/http/supply.v4_2_1.json ``` Elles couvrent notamment : - block commitment présent et `null` ; - `getBlockProduction.byIdentity` et la range effective ; - bloc riche avec transaction version numérique `1` ; - `meta` explicite `null` et version omise ; - reward `commissionBps` présent puis omis ; - `numRewardPartitions` présent, omis et explicitement `null` ; - performance sample courant puis ancien sans `numNonVoteTransactions` ; - inflation governor/rate ; - liste inflation reward avec un `null` positionnel et les variantes `commissionBps` ; - supply avec liste ordonnée de public keys. ## Tests ajoutés `unit_tests/rpc_blocks.rs` ajoute **8 tests déterministes** couvrant configs, résultats, omissions/null, version transaction non nulle, extensions SIMD et validation des public keys. `unit_tests/rpc_economics.rs` ajoute **6 tests déterministes** couvrant configs, inflation values, reward basis-points, `null` positionnel de fixture, supply ordonnée et invalid pubkey. Les tests d'intégration ajoutent aussi : - une canarie de surface publique qui vérifie que les 17 nouveaux types sont disponibles depuis la racine de crate ; - une canarie de registre qui confirme que `V0_2_4` reste exactement composé des **10 Blocks + 5 Economics**, tous `Read / RetrySafe`, et que `getBlock` conserve son marqueur de forme legacy dépréciée sans prétendre que les wrappers existent déjà. La canarie typed-complete `V0_2_4 == 15` reste volontairement fermée jusqu'aux tranches d'implémentation des wrappers. ## Fichiers ajoutés ```text crates/ksp-onchain-transport-lib/src/rpc_blocks.rs crates/ksp-onchain-transport-lib/src/rpc_economics.rs crates/ksp-onchain-transport-lib/unit_tests/rpc_blocks.rs crates/ksp-onchain-transport-lib/unit_tests/rpc_economics.rs crates/ksp-onchain-transport-lib/fixtures/http/block_commitment.variants.json crates/ksp-onchain-transport-lib/fixtures/http/block_production.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/confirmed_block.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/confirmed_block.omissions.json crates/ksp-onchain-transport-lib/fixtures/http/performance_sample.variants.json crates/ksp-onchain-transport-lib/fixtures/http/inflation_governor.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/inflation_rate.v4_2_1.json crates/ksp-onchain-transport-lib/fixtures/http/inflation_reward.variants.json crates/ksp-onchain-transport-lib/fixtures/http/supply.v4_2_1.json deltas/0.2.4/pre.002.md ``` ## Fichiers modifiés ```text Cargo.toml crates/ksp-onchain-transport-lib/src/lib.rs crates/ksp-onchain-transport-lib/src/rpc_transactions.rs crates/ksp-onchain-transport-lib/tests/public_api.rs crates/ksp-onchain-transport-lib/tests/release_completeness.rs ``` ## Fichiers supprimés Aucun. ## Fichiers volontairement inchangés ```text CHANGELOG.md ROADMAP.md docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md crates/ksp-onchain-transport-lib/Cargo.toml crates/ksp-onchain-transport-lib/README.md crates/ksp-onchain-transport-lib/USAGE.md crates/ksp-onchain-transport-lib/src/executor.rs crates/ksp-onchain-transport-lib/src/rpc_method.rs crates/ksp-config-lib/** config/** deltas/0.2.4/pre.001.md deltas/0.2.4/pre.001-fix.001.md ``` Aucun ancien delta n'est réécrit. Aucun wrapper Blocks/Economics n'est avancé prématurément. ## Validations exécutées dans le sandbox - reconstruction exacte de la base `v0.2.3` puis application des overlays `0.2.4-pre.001` et `0.2.4-pre.001-fix.001` ; - contrôle différentiel de la tranche `pre.002` contre cette base ; - recoupement ciblé des configs/résultats avec la baseline Agave `v4.2.1` retenue par le plan ; - parse JSON local des neuf nouvelles fixtures ; - contrôle statique des 17 réexports crate-root ; - contrôle statique que chaque nouveau item `pub`/`pub(crate)` de production possède sa documentation ; - contrôle statique de l'absence de `impl HttpTransportPool` dans les nouveaux modules ; - contrôle statique de l'absence de `use`, `unwrap`, `expect`, `panic!` et opérateur `?` dans les deux nouvelles sources de production ; - contrôle statique des lignes Rust modifiées à `<= 160` colonnes ; - contrôle différentiel de `Cargo.toml` : seul `workspace.package.version` change ; - contrôle différentiel de `rpc_transactions.rs` : seule la version de fichier et la visibilité interne documentée de `SolanaTransactionVersion::decode_wire` changent ; - contrôle que `CHANGELOG.md`, `ROADMAP.md`, le plan `011` version 2 et les deltas historiques restent inchangés. ## Validations Cargo non exécutées Le sandbox courant ne fournit pas `cargo`, `rustc` ni `rustfmt`. Les commandes suivantes ne sont donc pas déclarées comme réussies et doivent être exécutées sur le checkout de développement avant commit : ```bash cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-onchain-transport-lib ``` Aucun `cargo tree` supplémentaire n'est requis par cette tranche puisqu'aucune dépendance ni feature n'a changé. Les graphes complets restent obligatoires à la clôture `pre.009`. Le commit attendu après application et validations suit `VER-GIT-001` : ```text v0.2.4-pre.002 ``` ## Décisions prises - séparer physiquement les primitives Blocks et Economics dans deux modules Transport dédiés ; - ne pas avancer de wrapper avant sa tranche propriétaire ; - réutiliser `SolanaWireField`, `SolanaEncodedTransaction` et `SolanaTransactionVersion` plutôt que dupliquer le wire Transaction ; - ouvrir uniquement la visibilité interne de `SolanaTransactionVersion::decode_wire` sans modifier son API publique ; - typer les identités/adresses RPC en `Pubkey` lorsqu'elles sont structurelles ; - garder les sous-arbres Transaction/meta riches lossless via `serde_json::Value` ; - garder `rewardType` ouvert au niveau Transport au lieu d'introduire une taxonomie économique prématurée ; - distinguer `excludeNonCirculatingAccountsList` omis d'un `false` explicite ; - intégrer dès les fixtures partagées SIMD-0118, SIMD-0291 et la canarie future-compatible SIMD-0385 ; - ne pas modifier le plan `011`, aucune capacité stable additive n'ayant été découverte pendant cette tranche. ## Questions ouvertes Aucune question bloquante pour `pre.003`. ## Suite `0.2.4-pre.003` : implémenter les cinq wrappers Blocks simples avec requêtes JSON exactes et réponses typed : ```text getBlockCommitment getBlockHeight getBlockTime getFirstAvailableBlock minimumLedgerSlot ```