Files
khadhroony-solana-project/deltas/0.2.4/pre.008.md
2026-08-18 21:52:00 +02:00

475 lines
11 KiB
Markdown

<!-- file: deltas/0.2.4/pre.008.md -->
<!-- version: 1 -->
# Delta `0.2.4-pre.008` — `getInflationReward` complet + invariants positionnels
## Base requise
Livraison précédente :
```text
0.2.4-pre.007
workspace.package.version = "0.2.4-pre.7"
```
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 -> 231 unit tests OK
25 public API tests OK
20 release-completeness tests OK
1 smoke Devnet ignoré comme prévu
0 échec
```
## Objectif
Achever la surface Economics `0.2.4` avec le dernier wrapper prévu :
```text
getInflationReward
```
La tranche doit conserver sans perte :
```text
ordre exact des adresses d'entrée
cardinalité exacte de la réponse
null positionnels
config epoch / commitment / minContextSlot
commission nullable
commissionBps présent / omis / null de compatibilité
absence de limite métier d'adresses inventée par KSP
erreurs RPC runtime
```
À l'issue de cette tranche, les `10/10` wrappers Blocks et `5/5` wrappers Economics de `V0_2_4` sont matérialisés. La compliance globale `52/52 + 14/14` reste volontairement réservée à `pre.009`.
## Réaudit primaire du contrat Agave stable
Baseline stable conservée :
```text
Agave v4.2.1
```
Le serveur expose :
```text
getInflationReward(
address_strs: Vec<String>,
config: Option<RpcEpochConfig>,
) -> Vec<Option<RpcInflationReward>>
```
`RpcEpochConfig` contient :
```text
epoch: Option<u64>
commitment: Option<CommitmentConfig>
minContextSlot: Option<u64>
```
Le runtime reconstruit son résultat en itérant sur la liste d'adresses d'origine. Il restitue donc une position par entrée :
```text
reward trouvé -> Some(RpcInflationReward)
reward absent -> None / JSON null
```
Cette propriété justifie le contrôle KSP explicite de cardinalité : une réponse dont la longueur diffère du nombre d'adresses demandées est un wire invalide pour le wrapper typed.
## Correction de contrat découverte pendant `pre.008`
Le plan `011` n'explicitait pas encore la contrainte effective de commitment de `getInflationReward`.
Agave construit un `RpcContextConfig` depuis `RpcEpochConfig` puis appelle :
```text
getBlocksWithLimit(first_slot_in_epoch, 1, Some(context_config))
```
Cette voie applique la contrainte runtime :
```text
commitment >= confirmed
```
Conséquence KSP :
```text
commitment = processed -> rejet déterministe avant I/O
commitment = confirmed -> accepté
commitment = finalized -> accepté
commitment absent -> défaut runtime accepté
```
Le plan `011` passe donc de la version `4` à la version `5` avec :
- la nouvelle contrainte locale `getInflationReward commitment >= confirmed`;
- la matrice Economics corrigée;
- le libellé de `pre.008` complété par le réaudit de commitment.
Aucun autre changement de planning n'est effectué.
## SIMD-0291 — Commission Rate in Basis Points
Le document SIMD courant reste au statut :
```text
Review
```
La baseline Agave stable `v4.2.1` expose néanmoins déjà :
```text
RpcInflationReward {
epoch,
effective_slot,
amount,
post_balance,
commission: Option<u8>,
commission_bps: Option<u16>,
}
```
KSP conserve donc deux informations indépendantes :
```text
commission -> Option<u8>
commissionBps -> SolanaWireField<u16>
```
Aucune conversion `bps -> pourcentage` n'est réalisée. Aucun champ n'est dérivé depuis l'autre.
Le wire KSP accepte et distingue :
```text
commissionBps présent
commissionBps omis
commissionBps explicitement null pour compatibilité provider/wire
```
Même si Agave stable sérialise normalement l'absence via omission, conserver `null` séparément respecte la politique générale `SolanaWireField<T>` et évite une normalisation destructive.
## Version Cargo
Nouvelle prerelease technique :
```text
0.2.4-pre.7 -> 0.2.4-pre.8
```
Aucune dépendance ni feature Cargo n'est ajoutée ou modifiée.
## Surface publique `getInflationReward`
Nouvelle méthode :
```text
HttpTransportPool::get_inflation_reward(
role,
&[Pubkey],
Option<&SolanaInflationRewardConfig>,
) -> Result<Vec<Option<SolanaInflationReward>>>
```
Le premier paramètre JSON-RPC est toujours la liste d'adresses, y compris lorsqu'elle est vide :
```text
[] d'adresses -> params: [[]]
```
La config optionnelle est ajoutée uniquement lorsqu'elle contient au moins un champ :
```text
None / config vide -> [addresses]
config non vide -> [addresses, config]
```
Exemple complet :
```json
[
["address-1", "address-2"],
{
"epoch": 912,
"commitment": "finalized",
"minContextSlot": 431000000
}
]
```
## Ordre, doublons et cardinalité
Le wrapper ne trie ni ne déduplique les adresses.
Une requête conceptuelle :
```text
[A, B, A]
```
reste exactement :
```text
[A, B, A]
```
et la réponse reste positionnelle :
```text
[Some(reward A), None, Some(reward A)]
```
Après décodage du tableau JSON, KSP vérifie :
```text
result.len() == addresses.len()
```
Sinon :
```text
ERROR_CODE_INVALID_RESPONSE
expected_count = ...
actual_count = ...
```
## Absence de limite d'adresses inventée
Aucune constante métier n'est ajoutée pour `getInflationReward`.
En particulier, KSP ne réutilise pas artificiellement :
```text
256 # getSignatureStatuses
1000 # getSignaturesForAddress
```
ou toute autre limite d'un RPC voisin.
Une canary HTTP construit une requête de :
```text
300 adresses
```
et vérifie qu'elle atteint réellement le serveur fixture puis que les `300` `null` sont restitués.
La limite générale de taille d'une requête HTTP reste une contrainte de transport/provider, pas une cardinalité métier inventée par ce wrapper.
## Erreurs runtime préservées
Deux erreurs spécifiques sont couvertes par fixtures :
```text
-32016 MinContextSlotNotReached
-32017 EpochRewardsPeriodActive
```
Elles restent :
```text
ERROR_CODE_RPC_APPLICATION_ERROR
```
et ne sont pas converties en erreurs de décodage locales.
Les autres erreurs runtime possibles liées à l'historique/epoch restent également transportées par le flux JSON-RPC central, notamment les familles BlockCleanedUp, BlockNotAvailable, SlotNotEpochBoundary et long-term storage lorsqu'elles surviennent réellement.
## Discipline `#[cfg(test)]`
La politique introduite par `pre.002-fix.001` reste appliquée.
Deviennent runtime uniquement parce qu'ils ont maintenant un consommateur réel :
```text
SolanaInflationRewardConfig::is_empty
SolanaInflationRewardConfig::to_json_value
SolanaInflationReward::decode_wire
WireInflationReward
```
Ils rejoignent les helpers Economics activés en `pre.007`.
Aucun `#[allow(dead_code)]` n'est ajouté.
## Chemin d'exécution
Le wrapper suit la frontière existante :
```text
get_inflation_reward
-> economics_descriptor("getInflationReward")
-> HttpTransportPool::execute_standard_rpc
-> decode_inflation_rewards
```
Le descriptor central reste :
```text
V0_2_4 / Economics / Read / RetrySafe
```
Aucun chemin HTTP parallèle n'est créé.
## Fixtures
Nouvelles fixtures HTTP :
```text
get_inflation_reward.success.json
get_inflation_reward.duplicates.json
get_inflation_reward.single_null.json
get_inflation_reward.empty.json
get_inflation_reward.many_nulls.json
get_inflation_reward.error_min_context.json
get_inflation_reward.error_epoch_rewards_active.json
```
Elles couvrent :
- config complète;
- ordre positionnel;
- doublons d'adresses;
- `null` positionnels;
- `commission` nullable;
- `commissionBps` présent / omis / null;
- tableau d'adresses vide;
- 300 adresses sans limite métier KSP;
- erreurs RPC runtime.
## Tests
Neuf nouveaux tests unitaires couvrent :
```text
config complète + positions + états commission/commissionBps
ordre des doublons + null positionnel
config absente/vide tout en conservant le paramètre addresses
liste d'adresses vide
300 adresses sans limite locale 256
processed rejeté avant I/O
mismatch de cardinalité rejeté
MinContextSlotNotReached préservé
EpochRewardsPeriodActive préservé
```
Canary public API :
```text
public_v0_2_4_pre_008_inflation_reward_wrapper_is_available_from_crate_root
```
Canary release :
```text
release_v0_2_4_pre_008_completes_all_five_economics_wrappers_exactly_and_retry_safe
```
La canary globale :
```text
release_v0_2_4_descriptor_set_is_exact_and_remains_read_retry_safe_during_staged_wrappers
```
est renommée :
```text
release_v0_2_4_descriptor_set_is_exact_and_remains_read_retry_safe_through_wrapper_completion
```
car `pre.008` achève désormais les `15/15` wrappers `V0_2_4`.
Compteurs attendus après validation locale :
```text
240 unit tests
26 public API tests
21 release-completeness tests
1 smoke Devnet ignoré
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-onchain-transport-lib/src/rpc_economics.rs
crates/ksp-onchain-transport-lib/unit_tests/rpc_economics.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_inflation_reward.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_inflation_reward.duplicates.json
crates/ksp-onchain-transport-lib/fixtures/http/get_inflation_reward.single_null.json
crates/ksp-onchain-transport-lib/fixtures/http/get_inflation_reward.empty.json
crates/ksp-onchain-transport-lib/fixtures/http/get_inflation_reward.many_nulls.json
crates/ksp-onchain-transport-lib/fixtures/http/get_inflation_reward.error_min_context.json
crates/ksp-onchain-transport-lib/fixtures/http/get_inflation_reward.error_epoch_rewards_active.json
deltas/0.2.4/pre.008.md
```
## Non-objectifs
Cette tranche ne réalise pas encore :
- le réaudit SIMD final `0180/0298/0301/0307/0385/0490/0550/0553`;
- le réaudit final de l'inventaire officiel HTTP;
- la preuve globale `52/52 wrappers current`;
- la preuve globale `14/14 historical Deprecated/runtime Removed`;
- les smokes de clôture;
- les graphes finaux de dépendances;
- la documentation de clôture et le prompt `0.2.5`.
Ces points restent réservés à `pre.009`.
## Validation attendue
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
```
Résultat attendu :
```text
0 warning introduit
240 unit tests OK
26 public API tests OK
21 release-completeness tests OK
1 smoke Devnet ignoré
0 échec
```
## Commit attendu
```text
v0.2.4-pre.008
```
## Suite
`0.2.4-pre.009` reste la tranche de clôture technique/documentaire :
```text
réaudit SIMD HTTP final
réaudit inventaire officiel
compliance 52/52 + 14/14
KSP-TRANSPORT-007 final
smokes
graphes
documentation
prompt 0.2.5 — Wallet foundation
```