11 KiB
Delta 0.2.4-pre.008 — getInflationReward complet + invariants positionnels
Base requise
Livraison précédente :
0.2.4-pre.007
workspace.package.version = "0.2.4-pre.7"
Les validations locales fournies pour cette base sont propres :
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 :
getInflationReward
La tranche doit conserver sans perte :
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 :
Agave v4.2.1
Le serveur expose :
getInflationReward(
address_strs: Vec<String>,
config: Option<RpcEpochConfig>,
) -> Vec<Option<RpcInflationReward>>
RpcEpochConfig contient :
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 :
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 :
getBlocksWithLimit(first_slot_in_epoch, 1, Some(context_config))
Cette voie applique la contrainte runtime :
commitment >= confirmed
Conséquence KSP :
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.008complé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 :
Review
La baseline Agave stable v4.2.1 expose néanmoins déjà :
RpcInflationReward {
epoch,
effective_slot,
amount,
post_balance,
commission: Option<u8>,
commission_bps: Option<u16>,
}
KSP conserve donc deux informations indépendantes :
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 :
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 :
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 :
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 :
[] d'adresses -> params: [[]]
La config optionnelle est ajoutée uniquement lorsqu'elle contient au moins un champ :
None / config vide -> [addresses]
config non vide -> [addresses, config]
Exemple complet :
[
["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 :
[A, B, A]
reste exactement :
[A, B, A]
et la réponse reste positionnelle :
[Some(reward A), None, Some(reward A)]
Après décodage du tableau JSON, KSP vérifie :
result.len() == addresses.len()
Sinon :
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 :
256 # getSignatureStatuses
1000 # getSignaturesForAddress
ou toute autre limite d'un RPC voisin.
Une canary HTTP construit une requête de :
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 :
-32016 MinContextSlotNotReached
-32017 EpochRewardsPeriodActive
Elles restent :
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 :
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 :
get_inflation_reward
-> economics_descriptor("getInflationReward")
-> HttpTransportPool::execute_standard_rpc
-> decode_inflation_rewards
Le descriptor central reste :
V0_2_4 / Economics / Read / RetrySafe
Aucun chemin HTTP parallèle n'est créé.
Fixtures
Nouvelles fixtures HTTP :
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;
nullpositionnels;commissionnullable;commissionBpsprésent / omis / null;- tableau d'adresses vide;
- 300 adresses sans limite métier KSP;
- erreurs RPC runtime.
Tests
Neuf nouveaux tests unitaires couvrent :
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 :
public_v0_2_4_pre_008_inflation_reward_wrapper_is_available_from_crate_root
Canary release :
release_v0_2_4_pre_008_completes_all_five_economics_wrappers_exactly_and_retry_safe
La canary globale :
release_v0_2_4_descriptor_set_is_exact_and_remains_read_retry_safe_during_staged_wrappers
est renommée :
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 :
240 unit tests
26 public API tests
21 release-completeness tests
1 smoke Devnet ignoré
Fichiers modifiés
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
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
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
Résultat attendu :
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
v0.2.4-pre.008
Suite
0.2.4-pre.009 reste la tranche de clôture technique/documentaire :
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