# Delta `0.2.4-pre.003` — cinq wrappers Blocks simples ## Base requise Livraison précédente : ```text 0.2.4-pre.002-fix.001 workspace.package.version = "0.2.4-pre.2.fix.1" ``` Les validations locales fournies pour cette base sont propres : ```text cargo fmt --all -> terminé cargo check --workspace -> terminé sans warning cargo clippy --workspace --all-targets -> terminé sans warning cargo test -p ksp-onchain-transport-lib -> 196 unit tests OK 20 public API tests OK 15 release-completeness tests OK 1 smoke Devnet ignoré comme prévu 0 échec ``` Le plan canonique reste `docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md` version 2. ## Objectif Implémenter exactement la première tranche de wrappers Blocks prévue par le plan : ```text getBlockCommitment getBlockHeight getBlockTime getFirstAvailableBlock minimumLedgerSlot ``` Les cinq méthodes sont déjà présentes dans le registre audité `V0_2_4`, toutes classées `Read / RetrySafe`. Cette prerelease ne modifie donc pas le registre ; elle matérialise leurs wrappers typed au-dessus du chemin Transport commun existant. Les méthodes Blocks restantes restent hors de cette tranche : ```text getBlock getBlockProduction getBlocks getBlocksWithLimit getRecentPerformanceSamples ``` Les cinq méthodes Economics restent également sans wrapper runtime à ce stade. ## Réaudit RPC de la tranche Le contrat HTTP courant a été revérifié avant implémentation : - `getBlockCommitment` prend un `slot: u64` et retourne un objet avec `commitment: array ou null` et `totalStake: u64` ; - `getBlockHeight` accepte un objet optionnel `commitment` / `minContextSlot` et retourne `u64` ; - `getBlockTime` prend un `slot: u64` et retourne un timestamp Unix `i64` lorsqu'il est disponible ; KSP conserve également le résultat JSON `null` sous `Option` conformément au wire déjà audité ; - `getFirstAvailableBlock` ne prend aucun paramètre et retourne un `u64` ; - `minimumLedgerSlot` ne prend aucun paramètre et retourne un `u64`. Aucun nouveau champ, overload ou invariant déterministe n'a été identifié pour ces cinq méthodes par rapport au plan `pre.001`. ## Version Cargo Nouvelle prerelease technique : ```text 0.2.4-pre.2.fix.1 -> 0.2.4-pre.3 ``` Aucune dépendance ni feature Cargo n'est ajoutée ou modifiée. ## Implémentation ### Chemin Blocks commun `rpc_blocks.rs` ajoute un `impl HttpTransportPool` dédié aux wrappers Blocks. Tous les appels passent par : ```text wrapper typed Blocks -> blocks_descriptor(...) -> execute_standard_rpc(...) -> pool/admission -> executor HTTP -> validation JSON-RPC -> decode typed ``` `blocks_descriptor` exige simultanément : ```text category == HttpRpcCategory::Blocks coverage_release == HttpRpcCoverageRelease::V0_2_4 ``` Un descripteur absent ou incohérent échoue donc avant l'I/O normale au lieu de contourner le registre audité. Aucune boucle de retry locale n'est ajoutée. Les cinq méthodes héritent de la politique centrale `RetrySafe` déjà attachée à leurs descripteurs. ### `getBlockCommitment` Signature publique : ```text HttpTransportPool::get_block_commitment(role, slot) -> Result ``` Paramètres wire : ```json [430000123] ``` Le DTO `SolanaBlockCommitment` introduit en `pre.002` est désormais réellement consommé par un wrapper runtime. Son helper `decode_wire` et la struct privée `WireBlockCommitment` sortent donc de `#[cfg(test)]`. Le champ nullable `commitment` reste représenté par `Option>`; `totalStake` reste `u64`. Conformément au fix précédent, **aucun autre** décodeur Blocks/Economics préparé en `pre.002` n'est activé prématurément. ### `getBlockHeight` Signature publique : ```text HttpTransportPool::get_block_height(role, Option<&SolanaContextConfig>) -> Result ``` La configuration réutilise le contrat partagé existant : ```text commitment minContextSlot ``` Un `None` ou un `SolanaContextConfig::default()` produit une liste de paramètres vide : ```json [] ``` Une configuration non vide conserve exactement les champs fournis, par exemple : ```json [ { "commitment": "finalized", "minContextSlot": 429000000 } ] ``` Aucune valeur de commitment n'est inventée localement lorsque la configuration est absente. ### `getBlockTime` Signature publique : ```text HttpTransportPool::get_block_time(role, slot) -> Result> ``` Le wrapper conserve sans perte les deux états de résultat : ```text JSON i64 -> Some(timestamp) JSON null -> None ``` Transport ne convertit pas le timestamp en date/heure applicative et ne synthétise aucune valeur pour `null`. ### `getFirstAvailableBlock` Signature publique : ```text HttpTransportPool::get_first_available_block(role) -> Result ``` Le wrapper envoie exactement : ```json [] ``` et retourne le slot `u64` fourni par le runtime. ### `minimumLedgerSlot` Signature publique : ```text HttpTransportPool::minimum_ledger_slot(role) -> Result ``` Le wrapper envoie exactement : ```json [] ``` et retourne le slot minimum `u64` fourni par le nœud, sans lui appliquer de sémantique de rétention locale. ## Discipline `#[cfg(test)]` héritée de `pre.002-fix.001` La correction précédente est prolongée explicitement : ```text runtime en pre.003 SolanaBlockCommitment::decode_wire WireBlockCommitment reste test-only SolanaGetBlockConfig::{is_empty,to_json_value} SolanaBlockProductionRange::to_json_value SolanaBlockProductionConfig::{is_empty,to_json_value} SolanaBlockProduction::decode_wire SolanaBlockReward::decode_wire SolanaBlockTransaction::decode_wire SolanaConfirmedBlock::decode_wire SolanaPerformanceSample::decode_wire helpers privés transaction/reward de bloc autres WireBlock* helpers/wires Economics ``` Aucun `#[allow(dead_code)]` n'est introduit. ## Fixtures HTTP ajoutées ```text crates/ksp-onchain-transport-lib/fixtures/http/get_block_commitment.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_block_height.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_block_time.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_block_time.null.json crates/ksp-onchain-transport-lib/fixtures/http/get_first_available_block.success.json crates/ksp-onchain-transport-lib/fixtures/http/minimum_ledger_slot.success.json ``` Les fixtures sont des enveloppes JSON-RPC complètes et déterministes utilisées par les tests HTTP locaux. ## Tests `unit_tests/rpc_blocks.rs` ajoute six tests async de wrapper : ```text typed_get_block_commitment_serializes_slot_and_preserves_distribution typed_get_block_height_serializes_context_config typed_get_block_height_omits_explicitly_empty_config typed_get_block_time_preserves_timestamp_and_null typed_get_first_available_block_has_no_params typed_minimum_ledger_slot_has_no_params ``` Ils vérifient les requêtes HTTP réellement émises vers le serveur fixture local, et pas seulement des helpers de sérialisation isolés. `tests/public_api.rs` ajoute une canarie qui référence les cinq méthodes directement depuis `HttpTransportPool` afin de verrouiller leur disponibilité publique. `tests/release_completeness.rs` : - renomme la canarie globale `V0_2_4` qui parlait encore de l'état « before wrappers » ; - ajoute une canarie `pre.003` qui verrouille exactement les cinq méthodes de cette tranche et leur classification `Read / RetrySafe`. Après application, les compteurs attendus pour la crate Transport sont donc au minimum : ```text unit tests 196 -> 202 public API tests 20 -> 21 release-completeness 15 -> 16 smoke Devnet 1 ignoré comme prévu ``` Ces nombres sont des attentes dérivées des tests ajoutés ; les validations Cargo doivent être exécutées sur le checkout de développement. ## Documentation de crate La rustdoc racine de `ksp-onchain-transport-lib` est mise à jour pour refléter l'état réel de `0.2.4-pre.003` : les primitives Blocks/Economics sont acquises et cinq wrappers Blocks sont désormais actifs. Le plan `011`, le ROADMAP et le CHANGELOG restent inchangés : aucun redécoupage de release ni jalon documentaire final n'est nécessaire dans cette tranche. ## Fichiers modifiés ```text Cargo.toml crates/ksp-onchain-transport-lib/src/lib.rs crates/ksp-onchain-transport-lib/src/rpc_blocks.rs crates/ksp-onchain-transport-lib/unit_tests/rpc_blocks.rs crates/ksp-onchain-transport-lib/tests/public_api.rs crates/ksp-onchain-transport-lib/tests/release_completeness.rs ``` ## Fichiers ajoutés ```text crates/ksp-onchain-transport-lib/fixtures/http/get_block_commitment.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_block_height.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_block_time.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_block_time.null.json crates/ksp-onchain-transport-lib/fixtures/http/get_first_available_block.success.json crates/ksp-onchain-transport-lib/fixtures/http/minimum_ledger_slot.success.json deltas/0.2.4/pre.003.md ``` ## Fichiers supprimés Aucun. ## Fichiers volontairement inchangés ```text crates/ksp-onchain-transport-lib/src/rpc_method.rs crates/ksp-onchain-transport-lib/src/rpc_economics.rs crates/ksp-onchain-transport-lib/unit_tests/rpc_economics.rs docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md ROADMAP.md CHANGELOG.md deltas/0.2.4/pre.001.md deltas/0.2.4/pre.001-fix.001.md deltas/0.2.4/pre.002.md deltas/0.2.4/pre.002-fix.001.md ``` Aucun delta historique n'est réécrit. ## Validations exécutées dans le sandbox Le sandbox ne fournit pas le toolchain Rust. Les contrôles effectués sont donc statiques : - parsing des six nouvelles fixtures JSON ; - contrôle du signal Cargo `0.2.4-pre.3` ; - contrôle de présence exacte des cinq nouvelles méthodes publiques ; - contrôle que seul le wire `getBlockCommitment` nécessaire à cette tranche sort de `#[cfg(test)]` ; - contrôle qu'aucun `#[allow(dead_code)]` n'est introduit ; - scan du nouveau code de production pour `unwrap`, `expect`, `panic!` et `unsafe` ; - contrôle différentiel contre `0.2.4-pre.002-fix.001` ; - contrôle des versions d'en-tête des fichiers modifiés. ## Validations Cargo à exécuter ```bash cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-onchain-transport-lib ``` Le critère attendu est : aucune régression, aucun warning introduit par `pre.003`, et les nouveaux compteurs `202 / 21 / 16` si aucune autre modification locale n'ajoute de test. Le commit attendu après validation est : ```text v0.2.4-pre.003 ``` ## Questions ouvertes Aucune pour cette tranche. ## Suite `0.2.4-pre.004` reste dédiée aux ranges/performance : ```text getBlocks getBlocksWithLimit getRecentPerformanceSamples ``` avec les validations déterministes déjà cadrées dans le plan : plage maximale de 500 000 slots, `limit <= 500000`, `limit <= 720` pour les performance samples, et conservation des formes de réponse sans perte.