Files
2026-08-18 21:52:00 +02:00

11 KiB

Delta 0.2.4-pre.008getInflationReward 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.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 :

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;
  • 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 :

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