270 lines
9.0 KiB
Markdown
270 lines
9.0 KiB
Markdown
<!-- file: deltas/0.2.2/pre.005.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.2.2-pre.005` — sept wrappers HTTP Cluster simples typés
|
|
|
|
## Base requise
|
|
|
|
Livraison précédente validée localement par l'opérateur :
|
|
|
|
```text
|
|
0.2.2-pre.004
|
|
workspace.package.version = "0.2.2-pre.4"
|
|
```
|
|
|
|
La validation opérateur du 2026-08-18 a confirmé :
|
|
|
|
```text
|
|
cargo fmt --all OK
|
|
cargo check --workspace OK
|
|
cargo clippy --workspace --all-targets OK
|
|
cargo test -p ksp-onchain-transport-lib OK
|
|
```
|
|
|
|
Résultats Transport de cette base :
|
|
|
|
```text
|
|
106 unit tests
|
|
11 public API tests
|
|
4 release completeness tests
|
|
0 warning signalé par check/clippy
|
|
```
|
|
|
|
Le plan canonique reste `docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md` version 3.
|
|
|
|
## Contrôle documentaire avant nouvelle tranche
|
|
|
|
Le contrôle de cohérence demandé entre prereleases confirme :
|
|
|
|
- `ROADMAP.md` conserve correctement `0.2.2` en cours `[/]` ;
|
|
- le plan `009` attribue exactement à `pre.005` les sept méthodes Cluster simples implémentées ici ;
|
|
- `pre.006` conserve exactement cinq méthodes différées : `getLeaderSchedule`, `getSlot`, `getSlotLeader`, `getSlotLeaders`, `getVoteAccounts` ;
|
|
- les index `docs/000-README.md`, `docs/plans/000-README.md` et `docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md` restent cohérents et ne nécessitent aucune modification.
|
|
|
|
## Objectif
|
|
|
|
Implémenter les sept wrappers publics typés Cluster simples prévus par le plan :
|
|
|
|
```text
|
|
getClusterNodes
|
|
getEpochInfo
|
|
getEpochSchedule
|
|
getHighestSnapshotSlot
|
|
getIdentity
|
|
getMaxRetransmitSlot
|
|
getMaxShredInsertSlot
|
|
```
|
|
|
|
Tous passent par la foundation HTTP commune :
|
|
|
|
```text
|
|
wrapper typé
|
|
-> descriptor audité
|
|
-> execute_standard_rpc
|
|
-> pool/admission/retry/deadline
|
|
-> reqwest HTTP
|
|
-> JSON-RPC validation
|
|
-> décodage DTO KSP
|
|
```
|
|
|
|
Aucun wrapper Cluster ne contacte `reqwest` directement.
|
|
|
|
## Version Cargo
|
|
|
|
Conformément au cycle prerelease KSP :
|
|
|
|
```text
|
|
0.2.2-pre.4 -> 0.2.2-pre.5
|
|
```
|
|
|
|
Aucune dépendance ni feature Cargo n'est ajoutée ou retirée.
|
|
|
|
## Réaudit ciblé du contrat courant
|
|
|
|
Les pages RPC Solana courantes ont été revérifiées le 2026-08-18 :
|
|
|
|
```text
|
|
https://solana.com/docs/rpc/http/getclusternodes
|
|
https://solana.com/docs/rpc/http/getepochinfo
|
|
https://solana.com/docs/rpc/http/getepochschedule
|
|
https://solana.com/docs/rpc/http/gethighestsnapshotslot
|
|
https://solana.com/docs/rpc/http/getidentity
|
|
https://solana.com/docs/rpc/http/getmaxretransmitslot
|
|
https://solana.com/docs/rpc/http/getmaxshredinsertslot
|
|
```
|
|
|
|
Le contrat reste cohérent avec le plan `009` :
|
|
|
|
- `getClusterNodes` ne prend aucun paramètre et renvoie une liste de contacts de noeuds ;
|
|
- `getEpochInfo` accepte uniquement la config commune `commitment/minContextSlot` et conserve `transactionCount` nullable ;
|
|
- `getEpochSchedule` ne prend aucun paramètre et renvoie la structure fixe d'epoch schedule ;
|
|
- `getHighestSnapshotSlot` ne prend aucun paramètre, conserve `incremental` nullable et laisse l'absence de snapshot comme erreur JSON-RPC distante ;
|
|
- `getIdentity` ne prend aucun paramètre et renvoie l'objet `{ identity }`, converti en `Pubkey` KSP ;
|
|
- `getMaxRetransmitSlot` et `getMaxShredInsertSlot` ne prennent aucun paramètre et renvoient chacun un `u64`.
|
|
|
|
Le champ Agave `v4.2.1` `clientId: Option<String>` identifié par `pre.001-fix.001` reste conservé par `SolanaClusterNode`, sans devenir obligatoire.
|
|
|
|
## Surface typée Cluster simple
|
|
|
|
### `getClusterNodes`
|
|
|
|
```text
|
|
role -> Vec<SolanaClusterNode>
|
|
```
|
|
|
|
Chaque `pubkey` est validée et convertie en `ksp_core_lib::Pubkey`. Les endpoints réseau restent des chaînes optionnelles. Les champs optionnels absents, y compris `clientId`, restent `None`.
|
|
|
|
### `getEpochInfo`
|
|
|
|
```text
|
|
role + Option<SolanaContextConfig> -> SolanaEpochInfo
|
|
```
|
|
|
|
Un config explicitement vide est omis de `params`. `transactionCount: null` reste `None`.
|
|
|
|
### `getEpochSchedule`
|
|
|
|
```text
|
|
role -> SolanaEpochSchedule
|
|
```
|
|
|
|
Aucune transformation métier n'est introduite.
|
|
|
|
### `getHighestSnapshotSlot`
|
|
|
|
```text
|
|
role -> SolanaSnapshotSlotInfo
|
|
```
|
|
|
|
`incremental` reste optionnel. Une erreur RPC « no snapshot » n'est pas convertie en valeur sentinelle.
|
|
|
|
### `getIdentity`
|
|
|
|
```text
|
|
role -> Pubkey
|
|
```
|
|
|
|
Le wrapper valide la chaîne `identity` avant de l'exposer comme `Pubkey`, sans recopier une valeur wire invalide dans le diagnostic.
|
|
|
|
### `getMaxRetransmitSlot` / `getMaxShredInsertSlot`
|
|
|
|
```text
|
|
role -> u64
|
|
```
|
|
|
|
Les deux wrappers partagent un chemin privé simple de décodage `u64` et ne créent aucun DTO artificiel.
|
|
|
|
## Activation ciblée des helpers préparés en `pre.002`
|
|
|
|
Les helpers Cluster nécessaires à cette tranche deviennent production-live uniquement maintenant qu'ils ont des consommateurs runtime :
|
|
|
|
- `SolanaClusterNode::decode_wire` + `WireClusterNode` ;
|
|
- `SolanaEpochInfo::decode_wire` + `WireEpochInfo` ;
|
|
- `SolanaEpochSchedule::decode_wire` + `WireEpochSchedule` ;
|
|
- `SolanaSnapshotSlotInfo::decode_wire` + `WireSnapshotSlotInfo`.
|
|
|
|
Les helpers spécifiques à `getLeaderSchedule` et `getVoteAccounts` restent sous `#[cfg(test)]` jusqu'à `pre.006`. Aucun `#[allow(dead_code)]` n'est ajouté.
|
|
|
|
## Fixtures HTTP déterministes ajoutées
|
|
|
|
```text
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.invalid_pubkey.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_info.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_schedule.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.error.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_identity.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_identity.invalid_pubkey.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_max_retransmit_slot.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_max_shred_insert_slot.success.json
|
|
```
|
|
|
|
Les tests utilisent uniquement un serveur HTTP loopback local.
|
|
|
|
## Couverture de tests ajoutée
|
|
|
|
Les tests couvrent notamment :
|
|
|
|
- requête sans paramètres pour les six méthodes sans config ;
|
|
- sérialisation exacte `commitment + minContextSlot` pour `getEpochInfo` ;
|
|
- omission d'un `SolanaContextConfig` explicitement vide ;
|
|
- `transactionCount: null` ;
|
|
- champs ClusterNode optionnels présents et absents ;
|
|
- conservation de `clientId` Agave `v4.2.1` ;
|
|
- rejet d'une `pubkey` de noeud invalide ;
|
|
- `incremental: null` ;
|
|
- propagation d'une erreur RPC « no snapshot » ;
|
|
- validation de l'identity `Pubkey` ;
|
|
- décodage des deux slots max comme `u64`.
|
|
|
|
Le test public compile explicitement les sept nouvelles méthodes depuis `HttpTransportPool`.
|
|
|
|
Un canari release fige le sous-ensemble `pre.005` exact et vérifie `Read + RetrySafe` pour les sept descriptors, tout en laissant les cinq méthodes Cluster de `pre.006` enregistrées mais différées.
|
|
|
|
Après application, la cible Transport attendue devient :
|
|
|
|
```text
|
|
116 unit tests
|
|
12 public API tests
|
|
5 release completeness tests
|
|
```
|
|
|
|
## Fichiers ajoutés
|
|
|
|
```text
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_cluster_nodes.invalid_pubkey.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_info.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_epoch_schedule.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_highest_snapshot_slot.error.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_identity.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_identity.invalid_pubkey.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_max_retransmit_slot.success.json
|
|
crates/ksp-onchain-transport-lib/fixtures/http/get_max_shred_insert_slot.success.json
|
|
deltas/0.2.2/pre.005.md
|
|
```
|
|
|
|
## Fichiers modifiés
|
|
|
|
```text
|
|
Cargo.toml
|
|
crates/ksp-onchain-transport-lib/src/rpc_cluster.rs
|
|
crates/ksp-onchain-transport-lib/unit_tests/rpc_cluster.rs
|
|
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
|
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
|
```
|
|
|
|
## Fichiers supprimés
|
|
|
|
Aucun.
|
|
|
|
## Documentation durable
|
|
|
|
Aucune modification de ROADMAP/plan/index n'est requise par cette tranche après le contrôle documentaire : les documents existants décrivent déjà exactement ce découpage.
|
|
|
|
`CHANGELOG.md` reste réservé à la clôture stable.
|
|
|
|
## Validation à exécuter sur le checkout opérateur
|
|
|
|
```bash
|
|
cargo fmt --all
|
|
cargo check --workspace
|
|
cargo clippy --workspace --all-targets
|
|
cargo test -p ksp-onchain-transport-lib
|
|
```
|
|
|
|
La livraison n'affirme pas que ces commandes ont été exécutées dans l'environnement de génération.
|
|
|
|
## Critères de validation de `pre.005`
|
|
|
|
`pre.005` est validable lorsque :
|
|
|
|
- les quatre commandes ci-dessus passent sans warning nouveau ;
|
|
- les 116 unit tests passent ;
|
|
- les 12 tests public API passent ;
|
|
- les 5 tests release completeness passent ;
|
|
- aucun helper Cluster simple production-live n'est `dead_code` ;
|
|
- les cinq wrappers complexes de `pre.006` restent hors de cette tranche.
|