v0.2.4-pre.004

This commit is contained in:
2026-08-18 20:54:16 +02:00
parent e500024c3a
commit 561b6678ed
12 changed files with 764 additions and 13 deletions

423
deltas/0.2.4/pre.004.md Normal file
View File

@@ -0,0 +1,423 @@
<!-- file: deltas/0.2.4/pre.004.md -->
<!-- version: 1 -->
# 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<end_slot>,
Option<&SolanaContextConfig>,
) -> Result<Vec<u64>>
```
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<u64>` 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<Vec<u64>>
```
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<limit>,
) -> Result<Vec<SolanaPerformanceSample>>
```
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
```