# Delta `0.2.4-pre.004` — ranges Blocks et performance samples ## Base requise Livraison précédente : ```text 0.2.4-pre.003 workspace.package.version = "0.2.4-pre.3" ``` 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 -> 202 unit tests OK 21 public API tests OK 16 release-completeness tests OK 1 smoke Devnet ignoré comme prévu 0 échec ``` Le plan canonique `docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md` passe de la version 2 à la version 3 dans cette livraison afin de corriger explicitement la config runtime stable de `getBlocks` / `getBlocksWithLimit` : Agave `v4.2.1` utilise `RpcContextConfig` avec `commitment` et `minContextSlot`. ## Objectif Implémenter exactement la tranche `pre.004` prévue : ```text getBlocks getBlocksWithLimit getRecentPerformanceSamples ``` Les trois méthodes sont déjà enregistrées dans la partition `V0_2_4 / Blocks` et classées `Read / RetrySafe`. Cette prerelease ne modifie donc pas le registre central. Après cette tranche, huit des dix wrappers Blocks de `0.2.4` sont matérialisés : ```text pre.003 getBlockCommitment getBlockHeight getBlockTime getFirstAvailableBlock minimumLedgerSlot pre.004 getBlocks getBlocksWithLimit getRecentPerformanceSamples ``` Restent volontairement différés : ```text pre.005 getBlockProduction pre.006 getBlock ``` Les cinq méthodes Economics restent également hors scope. ## Réaudit RPC de la tranche Le contrat HTTP courant a été revérifié avant implémentation et reste conforme au plan `pre.001` : - `getBlocks` accepte `start_slot`, un second paramètre qui peut être soit `end_slot`, soit un `RpcContextConfig`, puis éventuellement ce même type de config en troisième position ; la config stable contient `commitment` et `minContextSlot`, et la plage maximale est de `500_000` slots ; - `getBlocksWithLimit` accepte `start_slot`, `limit` puis un `RpcContextConfig` optionnel `{commitment,minContextSlot}` ; `limit` ne doit pas dépasser `500_000` ; - `getRecentPerformanceSamples` accepte un `limit` optionnel avec maximum `720`; l'absence du paramètre laisse le runtime appliquer son défaut ; - les résultats `getBlocks` / `getBlocksWithLimit` restent des listes ordonnées de slots `u64` ; - `getRecentPerformanceSamples` reste une liste dans l'ordre fourni par le serveur et expose `slot`, `numTransactions`, `numSlots`, `samplePeriodSecs`, avec `numNonVoteTransactions` conservé comme champ optionnel pour compatibilité avec les anciens wires. Aucun nouvel overload ni nouvelle limite n'a été identifié. En revanche, le cross-audit source Agave a clarifié un champ stable que la page publique n'affiche pas : `minContextSlot` fait partie du `RpcContextConfig` accepté par `getBlocks` et `getBlocksWithLimit`. Le plan vivant est corrigé en conséquence sous sa version 3. ## Version Cargo Nouvelle prerelease technique : ```text 0.2.4-pre.3 -> 0.2.4-pre.4 ``` Aucune dépendance ni feature Cargo n'est ajoutée ou modifiée. ## `getBlocks` Signature publique : ```text HttpTransportPool::get_blocks( role, start_slot, Option, Option<&SolanaContextConfig>, ) -> Result> ``` Le wrapper préserve les quatre formes retenues par `KSP-TRANSPORT-007` : ```json [430000100] [430000100, 430000109] [430000100, {"commitment":"confirmed", "minContextSlot":429999999}] [430000100, 430000109, {"commitment":"confirmed", "minContextSlot":429999999}] ``` Un `Some(SolanaContextConfig::default())` reste un overload config explicite : ```json [430000100, {}] ``` Il n'est pas réécrit silencieusement en `[430000100]`. Validation déterministe avant I/O : ```text commitment = processed -> rejet end >= start et end - start > 500_000 -> rejet ``` La borne est inclusive : ```text end - start = 500_000 -> valide ``` Le cas : ```text end < start ``` reste valide et est envoyé au runtime ; KSP accepte alors le tableau vide retourné sans fabriquer une erreur locale ni synthétiser une autre réponse. Le résultat `Vec` est conservé dans l'ordre exact retourné par le serveur ; aucun tri ni remplissage des slots absents n'est effectué. ## `getBlocksWithLimit` Signature publique : ```text HttpTransportPool::get_blocks_with_limit( role, start_slot, limit, Option<&SolanaContextConfig>, ) -> Result> ``` Validation déterministe avant I/O : ```text commitment = processed -> rejet limit > 500_000 -> rejet ``` Les deux bornes importantes sont couvertes explicitement : ```text limit = 0 -> valide limit = 500_000 -> valide limit = 500_001 -> rejet avant I/O ``` Aucune borne minimale artificielle `1` n'est ajoutée. Comme pour `getBlocks`, l'ordre et les éventuels trous de slots de la réponse sont laissés au runtime et préservés par Transport. ## `getRecentPerformanceSamples` Signature publique : ```text HttpTransportPool::get_recent_performance_samples( role, Option, ) -> Result> ``` Wire sans limite explicite : ```json [] ``` Wire avec maximum explicite : ```json [720] ``` Validation déterministe : ```text limit <= 720 -> valide limit > 720 -> rejet avant I/O ``` Le wrapper n'introduit aucune borne minimale locale et ne remplace pas l'absence de limite par une valeur synthétique `720` dans la requête. `SolanaPerformanceSample`, introduit en `pre.002`, est désormais consommé par un wrapper runtime. Son décodeur interne et `WirePerformanceSample` sortent donc de `#[cfg(test)]`. Le décodage conserve : ```text slot numTransactions numNonVoteTransactions présent ou omis numSlots samplePeriodSecs ``` L'ordre retourné par le serveur est conservé sans tri local. ## Discipline `#[cfg(test)]` La règle introduite par `pre.002-fix.001` reste appliquée strictement. Nouveaux éléments devenus runtime en `pre.004` : ```text SolanaPerformanceSample::decode_wire WirePerformanceSample ``` Éléments déjà runtime en `pre.003` : ```text SolanaBlockCommitment::decode_wire WireBlockCommitment ``` Restent test-only jusqu'à leur tranche : ```text 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 helpers privés transaction/reward de bloc WireBlockProduction* WireBlockReward WireBlockTransaction WireConfirmedBlock helpers/wires Economics ``` Aucun `#[allow(dead_code)]` n'est introduit. ## Fixtures HTTP ajoutées ```text crates/ksp-onchain-transport-lib/fixtures/http/get_blocks.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_blocks.empty.json crates/ksp-onchain-transport-lib/fixtures/http/get_blocks_with_limit.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_blocks_with_limit.empty.json crates/ksp-onchain-transport-lib/fixtures/http/get_recent_performance_samples.success.json ``` Les réponses de blocs utilisent volontairement des slots non continus afin de prouver que Transport ne synthétise pas les slots absents. La fixture performance contient un échantillon courant avec `numNonVoteTransactions` et un échantillon compatible ancien wire sans ce champ. ## Tests unitaires ajoutés `unit_tests/rpc_blocks.rs` ajoute six tests async : ```text typed_get_blocks_covers_all_four_overloads_and_preserves_server_order typed_get_blocks_allows_reversed_and_boundary_ranges_but_rejects_oversized_before_io typed_block_range_wrappers_reject_processed_commitment_before_io typed_get_blocks_with_limit_accepts_zero_and_maximum_and_rejects_above_maximum typed_get_recent_performance_samples_preserves_default_explicit_limit_order_and_older_shape typed_get_recent_performance_samples_rejects_above_720_before_io ``` Ils couvrent notamment : ```text getBlocks [start] getBlocks [start,end] getBlocks [start,config] getBlocks [start,end,config] getBlocks [start,{}] getBlocks end < start getBlocks différence = 500_000 autorejet getBlocks différence = 500_001 commitment processed rejeté avant I/O getBlocksWithLimit 0 getBlocksWithLimit 500_000 getBlocksWithLimit 500_001 rejeté avant I/O getRecentPerformanceSamples sans limite getRecentPerformanceSamples 720 getRecentPerformanceSamples 721 rejeté avant I/O ordre des résultats conservé ancien sample sans numNonVoteTransactions accepté ``` ## Canaries d'intégration `tests/public_api.rs` ajoute : ```text public_v0_2_4_pre_004_range_and_performance_wrappers_are_available_from_crate_root ``` La canarie référence directement : ```text HttpTransportPool::get_blocks HttpTransportPool::get_blocks_with_limit HttpTransportPool::get_recent_performance_samples ``` `tests/release_completeness.rs` ajoute : ```text release_v0_2_4_pre_004_range_performance_subset_is_exact_and_retry_safe ``` Elle verrouille le sous-ensemble exact : ```text getBlocks getBlocksWithLimit getRecentPerformanceSamples ``` et leur classification commune : ```text HttpRpcCoverageRelease::V0_2_4 HttpRpcCategory::Blocks RpcOperationKind::Read TransportRetryClass::RetrySafe ``` ## Frontières architecturales Cette tranche ne modifie pas les frontières établies : ```text Transport -X-> Config Transport -X-> Store Transport -X-> Program Transport -X-> tracing direct ``` Les wrappers passent exclusivement par `execute_standard_rpc` et la politique centrale de retry. Aucun client RPC Solana haut niveau, aucun retry local, aucune lecture d'environnement/configuration et aucune dépendance externe nouvelle ne sont introduits. ## Fichiers modifiés ```text Cargo.toml 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 docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md ``` ## Fichiers ajoutés ```text crates/ksp-onchain-transport-lib/fixtures/http/get_blocks.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_blocks.empty.json crates/ksp-onchain-transport-lib/fixtures/http/get_blocks_with_limit.success.json crates/ksp-onchain-transport-lib/fixtures/http/get_blocks_with_limit.empty.json crates/ksp-onchain-transport-lib/fixtures/http/get_recent_performance_samples.success.json deltas/0.2.4/pre.004.md ``` Aucun fichier n'est supprimé. ## Validation à exécuter après application ```bash cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-onchain-transport-lib ``` Compteurs attendus si aucun test existant n'est ajouté/supprimé localement entre-temps : ```text 208 unit tests 22 public API tests 17 release-completeness tests 1 smoke Devnet ignoré comme prévu 0 échec ``` Le sandbox de génération ne possède pas le toolchain Rust ; aucune compilation locale n'est revendiquée dans ce delta. ## Suite La tranche suivante reste celle prévue par le plan : ```text 0.2.4-pre.005 getBlockProduction ``` Elle devra activer uniquement les helpers runtime nécessaires à `SolanaBlockProductionConfig`, `SolanaBlockProductionRange` et `SolanaBlockProduction`, puis couvrir `identity`, `range`, le résultat contextualisé et la validation `lastSlot >= firstSlot`. ## Commit attendu Après validation locale réussie : ```text v0.2.4-pre.004 ```