Files
khadhroony-solana-project/docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md
2026-08-18 16:47:54 +02:00

37 KiB
Raw Blame History

Plan 0.2.3 — HTTP Transactions

Statut

Ce plan est ouvert par 0.2.3-pre.001 sur la base stable v0.2.2.

0.2.1 a stabilisé la foundation HTTP Solana et quatre wrappers typés canari. 0.2.2 a ajouté les 22 wrappers Accounts/Tokens/Cluster, les DTOs wire communs, le smoke Devnet Transport pur et les canaries exactes de complétude.

La release 0.2.3 complète uniquement les 11 méthodes Transactions déjà affectées à HttpRpcCoverageRelease::V0_2_3. Elle ne crée ni client HTTP parallèle, ni executor métier de transaction, ni dépendance Transport -> Config/Store/Program.

Sources normatives réauditées le 2026-08-18

Sources documentaires principales :

https://solana.com/docs/rpc/http
https://solana.com/docs/rpc/json-structures

Pages Transaction réauditées :

https://solana.com/docs/rpc/http/getfeeformessage
https://solana.com/docs/rpc/http/getlatestblockhash
https://solana.com/docs/rpc/http/getrecentprioritizationfees
https://solana.com/docs/rpc/http/getsignaturesforaddress
https://solana.com/docs/rpc/http/getsignaturestatuses
https://solana.com/docs/rpc/http/gettransaction
https://solana.com/docs/rpc/http/gettransactioncount
https://solana.com/docs/rpc/http/isblockhashvalid
https://solana.com/docs/rpc/http/requestairdrop
https://solana.com/docs/rpc/http/sendtransaction
https://solana.com/docs/rpc/http/simulatetransaction

Sources primaires Agave utilisées pour lever les ambiguïtés du wire et des limites runtime :

https://github.com/anza-xyz/agave/blob/v4.2.1/rpc/src/rpc.rs
https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/config.rs
https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/request.rs
https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/response.rs
https://github.com/anza-xyz/agave/blob/v4.2.1/transaction-status-client-types/src/lib.rs

Les liens Source du site RPC Solana consultés pointent encore vers Agave v3.1.8 et les exemples affichent encore apiVersion: 3.1.8. Comme pour la clôture 0.2.2, KSP recoupe donc la documentation publique avec Agave v4.2.1, dont le workspace déclare la version 4.2.1, sans prendre de dépendance sur ses crates RPC/client.

Audit global et périmètre confirmé

L'index HTTP Solana courant contient toujours 52 méthodes et sa catégorie Transactions contient exactement :

getFeeForMessage
getLatestBlockhash
getRecentPrioritizationFees
getSignaturesForAddress
getSignatureStatuses
getTransaction
getTransactionCount
isBlockhashValid
requestAirdrop
sendTransaction
simulateTransaction

La navigation Deprecated officielle conserve les 14 méthodes historiques déjà enregistrées dans KSP :

confirmTransaction
getConfirmedBlock
getConfirmedBlocks
getConfirmedBlocksWithLimit
getConfirmedSignaturesForAddress2
getConfirmedTransaction
getFeeCalculatorForBlockhash
getFeeRateGovernor
getFees
getRecentBlockhash
getSignatureConfirmation
getSignatureStatus
getSnapshotSlot
getStakeActivation

Aucune méthode Transaction n'est ajoutée, supprimée ou déplacée par rapport à la partition KSP stable 0.2.2 :

0.2.1 exact = 4
0.2.2 exact = 22
0.2.3 exact = 11
0.2.4 reste = 15

Les onze pages courantes ciblées restent des méthodes HTTP courantes. getTransaction conserve une forme de requête moderne par objet de configuration et une forme legacy de compatibilité où le second paramètre est directement la chaîne d'encoding ; la documentation actuelle marque explicitement cette forme bare comme dépréciée et recommande l'objet.

Gate de sizing obligatoire

Question :

Les 11 wrappers Transactions, leurs DTOs/wires, les règles write/simulation, les tests et la documentation peuvent-ils être clôturés proprement dans cette session ?

Réponse :

OUI.

Le périmètre est plus petit que 0.2.2, mais les méthodes sont plus hétérogènes. Le sizing reste acceptable en isolant les trois zones coûteuses :

  1. getTransaction et son wire encoding/version/meta ;
  2. requestAirdrop + sendTransaction et les preuves de no-resend après dispatch ambigu ;
  3. simulateTransaction et son résultat riche.

Aucun split de release n'est donc nécessaire à pre.001. Si une tranche réelle dépasse 1520 minutes, une prerelease supplémentaire est ajoutée dans 0.2.3 sans déplacer silencieusement une méthode vers 0.2.4.

Classification de sécurité confirmée

La metadata KSP existante reste correcte après réaudit :

8 Read            / RetrySafe
2 WriteSubmission / NeverAfterDispatch : requestAirdrop, sendTransaction
1 Simulation      / RetrySafe          : simulateTransaction

La règle centrale reste normative :

une WriteSubmission ne doit jamais être resoumise automatiquement lorsque KSP ne peut pas prouver que la tentative précédente n'a pas été dispatchée.

Un timeout après envoi, un HTTP temporaire reçu après dispatch, un rate-limit reçu après dispatch ou une rupture dont l'état de dispatch est ambigu arrêtent donc la boucle de retry Transport pour requestAirdrop et sendTransaction.

Une erreur explicitement classée NotDispatched peut encore suivre la policy centrale existante ; aucun wrapper write ne possède sa propre boucle.

Le champ RPC sendTransaction.maxRetries est distinct : il configure les retransmissions du noeud RPC après acceptation de la requête et ne constitue jamais une autorisation de retry HTTP côté KSP.

simulateTransaction n'émet pas la transaction sur le réseau et reste Simulation / RetrySafe dans la metadata Transport.

Flux architectural obligatoire

Tous les wrappers de cette release suivent le flux unique :

wrapper typed
    -> descriptor central
    -> execute_standard_rpc
    -> pool/admission
    -> executor HTTP
    -> validation JSON-RPC
    -> decode typed

Restent interdits :

wrapper -> reqwest direct
wrapper -> nouveau client HTTP
wrapper -> retry/deadline/admission bypass
Transport -> Config
Transport -> Store
Transport -> Program
Transport -> tracing direct

Les wrappers réutilisent SolanaCommitment, SolanaContextConfig, SolanaRpcContext, SolanaRpcResponse<T> et les erreurs KSP existantes lorsque leur contrat s'applique.

Décision dépendances et payloads sérialisés

Décision pre.001

Aucune nouvelle dépendance n'est ajoutée :

base64         NON
bs58           NON
wincode        NON
solana-client  NON
crate RPC SDK  NON

Motif : les trois entrées sérialisées de cette release peuvent être transportées comme chaînes encodées opaques accompagnées d'un encoding typé. KSP n'a pas besoin de désérialiser un message ou une transaction pour construire la requête, appliquer la policy de retry, préserver le wire ou décoder la réponse.

Agave réalise des contrôles de décodage, de désérialisation, de sanitization et de taille de transaction. Les reproduire complètement côté KSP impliquerait davantage que base64/bs58 : cela rapprocherait Transport d'un codec transactionnel et d'un SDK wire complet sans besoin fonctionnel établi. pre.001 ne crée donc pas cette responsabilité.

KSP applique en revanche avant I/O les invariants qui ne nécessitent aucun décodage du payload : cardinalités documentées/runtime, encodings acceptés par l'opération, formes de config, incompatibilités de flags et paramètres structuraux.

Cette décision peut être réouverte dans une future tranche si un besoin concret exige une validation locale des bytes sérialisés. L'ajout devra alors être borné, déclaré dans [workspace.dependencies] et justifié par un test qui démontre la valeur de la validation locale.

Encodings à distinguer

Pour les entrées sendTransaction et simulateTransaction, la source Agave actuelle accepte les encodings binaires base58 et base64 ; les encodings JSON ne sont pas des formats d'entrée valides pour ces deux opérations.

getFeeForMessage reçoit une chaîne base64. La page publique documente les messages legacy et v0. KSP ne parse pas la version du message et ne fige donc pas artificiellement le type public sur une liste de versions sérialisées que le runtime pourrait faire évoluer.

Pour la sortie getTransaction, le wire doit rester plus large : base58, base64, json, jsonParsed, ainsi que les formes legacy encore acceptées/auditées. Les formes encodées et JSON ne doivent pas être écrasées dans un seul String ambigu.

Règle de complétude des wrappers RPC

À partir de pre.005, la règle générale KSP-TRANSPORT-007 explicite un principe déjà recherché par les releases HTTP précédentes : un wrapper KSP n'est pas considéré complet s'il ne couvre qu'un sous-ensemble de convenance de la méthode RPC. Il doit exposer toute la surface sémantique auditée :

paramètres obligatoires et optionnels
champs de configuration
variantes/overloads courants
formes legacy encore supportées
contraintes déterministes connues
variantes/null/omissions significatives des réponses

Cette exigence ne signifie pas recopier solana-rpc-client ou tout solana-transaction-status-client-types. Une structure riche peut rester un serde_json::Value à une frontière explicitement lossless lorsque KSP n'a pas encore besoin de son modèle métier, à condition qu'aucune possibilité RPC ni information wire ne soit supprimée. Les syntaxes strictement équivalentes peuvent être canonicalisées.

Pour getTransaction, pre.005 couvre donc les deux formes de requête auditée : objet moderne et bare encoding legacy déprécié. La documentation publique courante expose base58, base64, json et jsonParsed pour l'objet moderne ; Agave v4.2.1 accepte aussi l'alias rétrocompatible binary via le même enum wire, que KSP conserve donc sans le présenter comme choix moderne recommandé. La config complète commitment/encoding/maxSupportedTransactionVersion est exposée, avec rejet local de processed car la méthode documente confirmed|finalized. Le résultat null, les transactions chaîne/tuple/objet, les versions legacy/numériques, meta lossless et transactionIndex optionnel courant sont préservés.

Matrice exacte des 11 méthodes

Méthode Paramètres ordonnés / config Résultat à préserver Validation / particularités
getFeeForMessage messageBase64, SolanaContextConfig? SolanaRpcResponse<Option<u64>> message base64 opaque ; null préservé
getLatestBlockhash SolanaContextConfig? contexte + { blockhash, lastValidBlockHeight } blockhash wire non vide ; contexte conservé
getRecentPrioritizationFees Vec<Pubkey>? Vec<{ slot, prioritizationFee }> maximum 128 adresses ; ordre serveur conservé
getSignaturesForAddress Pubkey, config pagination Vec<SignatureInfo> limit 1..=1000; newest -> oldest; nulls préservés
getSignatureStatuses Vec<signature>, config history? contexte + Vec<Option<SignatureStatus>> maximum 256; positions/nulls conservés; tableau vide accepté par Agave courant
getTransaction signature, config moderne ou encoding bare legacy Option<ConfirmedTransaction> transaction absente = null; encoding/version/meta lossless
getTransactionCount SolanaContextConfig? u64 forme simple, config contextuelle
isBlockhashValid blockhash, SolanaContextConfig? SolanaRpcResponse<bool> blockhash passé tel quel au runtime sauf invariant KSP non ambigu
requestAirdrop Pubkey, lamports, config? signature WriteSubmission; aucun resend après dispatch ambigu
sendTransaction transaction encodée, config? première signature base58/base64; maxRetries est node-side; no-resend KSP
simulateTransaction transaction encodée, config? contexte + résultat simulation base58/base64; sigVerify incompatible avec replaceRecentBlockhash

DTOs et wires communs prévus

Les noms Rust exacts restent ajustables à pre.002, mais les responsabilités suivantes sont figées.

Blockhash et latest blockhash

Le résultat de getLatestBlockhash conserve :

blockhash            String/newtype wire KSP
lastValidBlockHeight u64

Le même petit objet { blockhash, lastValidBlockHeight } peut être réutilisé lorsque simulateTransaction retourne un replacementBlockhash.

Aucune primitive cryptographique supplémentaire n'est nécessaire pour le transporter.

Signature information

getSignaturesForAddress conserve au minimum :

signature          String/newtype KSP
slot               u64
err                JSON transaction error nullable
memo               Option<String>
blockTime          Option<i64>
confirmationStatus Option<Processed|Confirmed|Finalized>
transactionIndex   Option<u32>

La page HTTP actuelle ne liste pas transactionIndex, mais Agave v4.2.1 l'expose comme champ optionnel avec serde(default) et omission lorsque absent. KSP doit donc l'accepter sans le rendre obligatoire, afin de ne pas perdre une donnée runtime actuelle ni casser les providers qui ne l'émettent pas encore.

err reste un contrat transaction-error wire et ne devient pas un modèle Program. Une représentation serde_json::Value bornée à cette frontière est acceptable tant que KSP ne possède pas encore le codec générique des erreurs de transaction.

Signature status

getSignatureStatuses préserve l'ordre exact du tableau d'entrée. Chaque position de sortie est :

Option<SignatureStatus>

Un statut présent conserve :

slot               u64
confirmations      Option<usize/u64>
err                transaction error nullable
status             forme legacy de résultat, encore présente sur le wire
confirmationStatus Option<Processed|Confirmed|Finalized>

La forme status historique à l'intérieur de l'objet courant n'est pas confondue avec les anciennes méthodes RPC Deprecated du registre. KSP peut la préserver de manière lossless sans la recommander comme nouvelle API métier.

Transaction encoding/config

Le contrat moderne getTransaction doit disposer d'un objet de config contenant :

commitment                     Option<SolanaCommitment>
encoding                       Option<TransactionEncoding>
maxSupportedTransactionVersion Option<u8>

La compatibilité auditée garde en plus une forme legacy explicite :

getTransaction(signature, "<encoding>")

Cette API legacy doit être nommée/annotée de manière à ne pas sembler être la voie recommandée. Le descriptor existant StableWithDeprecatedLegacy reste correct.

Le résultat confirmé garde un top-level typé :

slot             u64
blockTime        Option<i64>
transaction      EncodedTransaction
meta             absent | null | transaction-meta wire
version          absent | null | legacy | number
transactionIndex absent | null | u32

Le recoupement d'implémentation pre.002 avec transaction-status-client-types Agave v4.2.1 a confirmé que EncodedConfirmedTransactionWithStatusMeta expose également transactionIndex: Option<u32> au top-level de getTransaction. Cette extension optionnelle est donc préservée comme celle de getSignaturesForAddress, sans être rendue obligatoire pour les providers plus anciens.

EncodedTransaction doit préserver les différentes formes réellement sérialisées :

objet JSON/jsonParsed
chaîne legacy binaire
[string, "base58" | "base64"]

KSP ne doit pas dupliquer tout solana-transaction-status-client-types pour obtenir cette union. Les sous-structures transaction/message/meta qui sont riches, évolutives ou dépendantes de jsonParsed peuvent rester lossless via des DTOs étroits + serde_json::Value aux frontières prévues.

Le meta doit au minimum respecter la distinction absent/null/présent imposée par le wire et ne jamais inventer des listes ou zéros lorsque le provider omet une donnée optionnelle.

pre.002 matérialise cette distinction avec une primitive générique SolanaWireField<T> limitée au wire Transport : Omitted, Null, Value(T). Elle est utilisée pour les champs Transaction/Simulation où l'omission et null doivent rester distinguables ; elle ne transforme pas ce mécanisme en modèle métier et ne remplace pas Option<T> lorsque les deux états ont le même sens contractuel.

getRecentPrioritizationFees

Le paramètre optionnel est un tableau d'adresses. La documentation actuelle fixe un maximum de 128 et précise que, lorsqu'il est fourni, les samples correspondent aux transactions ayant verrouillé toutes ces adresses en writable. La cache d'un noeud conserve actuellement jusqu'à 150 blocs de données de prioritization fees ; ce nombre décrit le runtime/cache et n'est pas une cardinalité de réponse à imposer côté client.

Le résultat conserve simplement :

slot              u64
prioritizationFee u64

Pagination getSignaturesForAddress

La config prévue conserve :

commitment     Option<SolanaCommitment>
minContextSlot Option<u64>
limit          Option<usize>
before         Option<String/newtype signature>
until          Option<String/newtype signature>

Agave v4.2.1 applique 1000 par défaut et refuse limit == 0 ou limit > 1000. KSP peut donc rejeter cette cardinalité avant I/O sans dépendance supplémentaire.

getSignatureStatuses

La requête conserve :

signatures               Vec<String/newtype signature>
searchTransactionHistory Option<bool>

La documentation et Agave bornent le tableau à 256 signatures. La source actuelle refuse uniquement > 256; un tableau vide reste donc une forme valide à ne pas interdire arbitrairement.

Quand searchTransactionHistory est absent/faux, le noeud recherche seulement son cache récent. KSP transporte l'option sans transformer silencieusement l'appel en recherche historique coûteuse.

Write submissions

requestAirdrop

La config courante conserve :

commitment      Option<SolanaCommitment>
recentBlockhash Option<String>

Le résultat est une signature de transaction. L'appel déclenche la création/soumission d'une transaction de faucet : il reste donc WriteSubmission / NeverAfterDispatch même si la réponse n'est qu'une signature.

Aucun retry ad hoc n'est autorisé dans le wrapper. Un résultat ambigu après dispatch remonte au caller.

sendTransaction

Transport reçoit une transaction déjà construite et signée. Il ne devient ni builder, ni signer, ni executor métier.

La config courante conserve :

encoding            Option<Base58|Base64>
skipPreflight       Option/default false
preflightCommitment Option<SolanaCommitment>
maxRetries          Option<usize>
minContextSlot      Option<u64>

Le runtime RPC vérifie normalement les signatures et simule la transaction avant relay lorsque skipPreflight est faux. Une réponse réussie ne constitue pas une confirmation on-chain ; le résultat est la première signature embarquée dans la transaction.

La distinction de retry doit rester explicite :

sendTransaction.maxRetries  = retry/retransmission du noeud RPC
KSP HttpRetrySettings       = retry de la requête HTTP

La première peut être configurée par l'appel. La seconde reste bloquée après tout dispatch ambigu grâce au descriptor central.

simulateTransaction

La simulation conserve les options Agave actuelles :

commitment             Option<SolanaCommitment>
encoding               Option<Base58|Base64>
replaceRecentBlockhash bool/default false
sigVerify              bool/default false
minContextSlot         Option<u64>
innerInstructions      bool/default false
accounts               Option<SimulationAccountsConfig>

L'invariant runtime courant :

sigVerify == true && replaceRecentBlockhash == true -> invalid params

KSP doit le rejeter avant I/O, car il est déterministe et ne nécessite aucun décodage de la transaction.

La sous-config accounts conserve l'encoding Account compatible et un tableau d'adresses. Agave rejette actuellement les encodings Account binary/base58 pour ce retour et borne dynamiquement le nombre demandé au nombre de comptes de la transaction. Comme KSP ne décode pas la transaction en 0.2.3, cette limite dynamique reste une validation runtime/provider et n'est pas réimplémentée avec une dépendance transactionnelle.

Le résultat de simulation Agave v4.2.1 contient notamment, sous forme optionnelle lorsque pertinente :

err
logs
accounts
unitsConsumed
loadedAccountsDataSize
returnData
innerInstructions
replacementBlockhash
fee
preBalances
postBalances
preTokenBalances
postTokenBalances
loadedAddresses

Transport doit préserver ces champs et leurs null/absences sans décoder les instructions ou retours Program en modèles métier.

Erreurs et validations avant I/O

Les wrappers réutilisent le domaine d'erreur KSP. Les contrôles locaux ciblés comprennent au minimum :

getRecentPrioritizationFees : <= 128 adresses
getSignaturesForAddress     : limit 1..=1000 quand fourni
getSignatureStatuses        : <= 256 signatures
sendTransaction             : encoding d'entrée binaire supporté
simulateTransaction         : encoding d'entrée binaire supporté
simulateTransaction         : sigVerify XOR replaceRecentBlockhash pour le couple interdit

Les validations nécessitant de décoder/sanitizer les bytes de message/transaction restent côté RPC pour cette release.

Les erreurs JSON-RPC significatives — invalid params, min-context non atteint, transaction non trouvée sous forme null, preflight failure, transaction history indisponible, unsupported transaction version — doivent être couvertes par fixtures lorsque la méthode correspondante peut les produire. KSP ne convertit pas une erreur RPC applicative en retry de transport.

Stratégie de tests

Chaque wrapper possède des fixtures HTTP locales déterministes qui vérifient selon son contrat :

  • méthode et tableau params exacts, dans l'ordre exact ;
  • omission correcte du paramètre config lorsqu'il est absent ;
  • success typed ;
  • null / champ optionnel / champ omis ;
  • erreur JSON-RPC ;
  • cardinalité rejetée avant I/O lorsque KSP la connaît sans décodage ;
  • forme legacy getTransaction séparée de la forme moderne ;
  • maxSupportedTransactionVersion ;
  • encodings transaction ;
  • positions null de getSignatureStatuses ;
  • ordre newest-first de getSignaturesForAddress ;
  • champs de simulation riches et optionnels.

Tests write/no-resend

Les tests requestAirdrop et sendTransaction ne doivent pas se contenter de tester la fonction pure evaluate_transport_retry déjà existante. Ils doivent exercer le chemin wrapper -> executor avec un serveur fixture capable de compter les requêtes et démontrer au minimum :

connection failure prouvée NotDispatched -> policy centrale applicable
HTTP 429 après dispatch                    -> une seule soumission write
HTTP 5xx temporaire après dispatch         -> une seule soumission write
timeout/issue ambiguë après dispatch       -> aucune seconde soumission automatique

L'objectif n'est pas de créer une policy parallèle dans les wrappers, mais de prouver que les descriptors write utilisent réellement la policy centrale dans l'exécution standard.

Simulation

simulateTransaction reste retry-safe. Les fixtures doivent donc vérifier la config, l'incompatibilité sigVerify/replaceRecentBlockhash, les résultats partiels/nullables et au moins un scénario de retry transport sûr déjà supporté par l'executor commun.

Canaries de complétude à conserver

À toute la release :

current == 52
historical == 14
0.2.1 exact == 4
0.2.2 exact == 22
0.2.3 exact == 11
0.2.4 exact == 15

Aucun wrapper 0.2.4 n'est déclaré typed-complete avant sa release.

La canarie 0.2.3 exact == 11 ne devient réellement verte qu'une fois les onze wrappers publics et leurs tests de surface en place. Le registry peut déjà contenir leurs descriptors sans que cela ne compte comme couverture typée.

Smokes live

Les fixtures locales restent normatives pour la correctness des wrappers. Les smokes live sont opt-in et ne les remplacent pas.

La décision finale de smoke est réservée à la prerelease de clôture. Toute extension doit respecter l'ownership déjà stabilisée :

  • un smoke Transport pur qui construit ses settings programmatiquement peut rester sous ksp-onchain-transport-lib ;
  • un nouveau smoke cross-crates Config + Transport + ... ne doit pas être ajouté sous Config comme destination générale ;
  • requestAirdrop et sendTransaction ne seront pas exercés live sans justification forte, car un smoke de lecture/simulation suffit à valider la route Transaction sans introduire d'effet de bord ou de dépendance faucet/provider.

Un candidat raisonnable pour la clôture est un smoke Transport pur combinant getLatestBlockhash et une lecture Transaction déterministe ; une simulation live n'est retenue que si une fixture transactionnelle stable peut être fournie sans déplacer la construction/signature métier dans Transport.

Audit rétroactif KSP-TRANSPORT-007 planifié

La règle KSP-TRANSPORT-007 formalise en pre.005 un principe déjà appliqué dans les audits de 0.2.1 et 0.2.2, mais elle n'était pas encore un critère de clôture nommé lors de ces releases. Un contrôle rétroactif dédié est donc ajouté avant la clôture documentaire.

L'audit pre.008 couvrira au minimum :

4 wrappers foundation de 0.2.1
22 wrappers Accounts/Tokens/Cluster de 0.2.2
11 wrappers Transactions de 0.2.3

Il comparera la surface publique KSP aux paramètres/configs/overloads et formes de réponse des sources normatives courantes retenues. Les syntaxes strictement équivalentes peuvent rester canonicalisées conformément à la règle. Toute possibilité supportée manquante sera corrigée dans cette tranche ; si aucun manque n'est trouvé, la tranche fournira la preuve/canarie d'audit sans modification fonctionnelle artificielle.

Un contrôle ciblé effectué pendant pre.006 confirme déjà que les configs structurantes de 0.2.2 (RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcLargestAccountsConfig, RpcLeaderScheduleConfig, RpcGetVoteAccountsConfig) correspondent aux champs Agave v4.2.1 exposés par les DTOs KSP. Ce contrôle ne remplace pas l'audit exhaustif pre.008.

Prévision souple des prereleases

pre.001  audit officiel/Agave + matrice + sécurité + wire/deps + sizing
pre.002  primitives/configs/results Transactions partagés + fixtures communes
pre.003  getFeeForMessage + getLatestBlockhash + getTransactionCount + isBlockhashValid
pre.004  getRecentPrioritizationFees + getSignaturesForAddress + getSignatureStatuses
pre.005  getTransaction moderne + compatibilité legacy + transaction/meta/version wire
pre.006  requestAirdrop + sendTransaction + preuves end-to-end no-resend
pre.007  simulateTransaction + résultat riche + invariants de config
pre.008  audit rétroactif KSP-TRANSPORT-007 sur 0.2.1 -> 0.2.3 + remédiations éventuelles
pre.009  réaudit final + canaries + smoke opt-in si pertinent + README/USAGE + validation + prompt 0.2.4

Une prerelease intermédiaire peut être ajoutée si le volume réel d'une tranche dépasse le budget. Après formalisation de KSP-TRANSPORT-007 en pre.005, pre.008 est désormais réservée à un audit rétroactif explicite des wrappers HTTP déjà livrés depuis 0.2.1, afin de ne pas transformer la tranche de clôture en remédiation fonctionnelle tardive. La dernière prerelease reste une tranche de clôture documentaire/validation et ne doit pas devenir une implémentation massive tardive.

Résultat de pre.008 — réaudit rétroactif KSP-TRANSPORT-007

Le réaudit rétroactif a été exécuté sur les 37 wrappers HTTP typés courants livrés par 0.2.1, 0.2.2 et 0.2.3-pre.007 : 4 foundation, 22 Accounts/Tokens/Cluster et 11 Transactions. La matrice durable est conservée dans docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md.

Le contrôle croise la documentation HTTP Solana courante avec Agave v4.2.1, génération recommandée pour adoption générale Mainnet-beta le 10 août 2026 et dont les activations Mainnet-beta ont commencé le 17 août 2026. master est déjà en 4.3.0-alpha, mais n'est pas retenu comme contrat stable de cette release.

Verdict : aucune possibilité RPC supportée n'est manquante dans les 37 wrappers audités. Les extensions runtime déjà prises en charge par KSP (binary, sortResults, tokenAccountState, clientId, inflationRewardsCommissionBps, recentBlockhash, champs riches de simulation, transactionIndex, etc.) sont conservées même lorsqu'elles ne sont pas toutes détaillées dans la page publique Solana. Les syntaxes strictement équivalentes peuvent rester canonicalisées conformément à KSP-TRANSPORT-007.

Aucune remédiation fonctionnelle artificielle n'est donc introduite en pre.008. La tranche ajoute une preuve durable et une canarie nommée couvrant exactement les 37 descriptors courants de 0.2.1 à 0.2.3, tout en préservant la forme legacy dépréciée de getTransaction. La clôture reste déplacée à pre.009.

Critères de clôture de 0.2.3

La release ne peut être candidate stable que si :

  • les 11 wrappers sont publics et passent tous par execute_standard_rpc ;
  • chaque wrapper couvre tous les paramètres/options/overloads normatifs ou runtime supportés retenus par l'audit, selon KSP-TRANSPORT-007 ;
  • les trois classes de sécurité restent exactes 8 Read / 2 WriteSubmission / 1 Simulation ;
  • requestAirdrop et sendTransaction prouvent l'absence de resend automatique après dispatch ambigu ;
  • getTransaction préserve la forme moderne et la compatibilité legacy explicitement dépréciée ;
  • maxSupportedTransactionVersion est préservé ;
  • les cardinalités 128 / 1000 / 256 sont testées selon leur contrat exact ;
  • les tableaux et null positionnels sont préservés ;
  • simulateTransaction préserve son config/result sans décodage Program ;
  • les canaries 52/14/4/22/11/15 passent ;
  • aucune dépendance Transport -> Config/Store/Program/tracing direct n'est introduite ;
  • README/USAGE, plan, matrice de validation et prompt 0.2.4 sont synchronisés ;
  • les validations Cargo de clôture et graphes de dépendances ont une preuve opérateur ou une exécution réelle ;
  • CHANGELOG.md reste réservé à 0.2.3-rel.001 ;
  • la release stable finale reste strictement publicationnelle.

Validations prévues pendant le développement

cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib

Validations prévues à la clôture

cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-config-lib
cargo test -p ksp-core-lib
cargo test -p ksp-app-config-desk
cargo test --workspace

cargo tree -p ksp-onchain-transport-lib
cargo tree -p ksp-onchain-transport-lib -d
cargo tree -p ksp-onchain-transport-lib -e features
cargo tree -p ksp-onchain-transport-lib -e normal

Aucune commande n'est déclarée réussie sans exécution réelle ou preuve opérateur.

Résultat de pre.001

pre.001 s'arrête volontairement avant toute source Rust fonctionnelle :

  • périmètre 11/11 confirmé ;
  • classification sécurité confirmée ;
  • architecture commune confirmée ;
  • wire/config/result audités ;
  • limites locales/runtime distinguées ;
  • aucune nouvelle dépendance justifiée ;
  • gate de sizing positif ;
  • découpage pre.002pre.008 défini.

La tranche suivante peut commencer par les primitives wire communes sans réouvrir le scope de release.

Résultat de pre.002

pre.002 installe les primitives/configurations/résultats partagés sans déclarer un wrapper Transaction comme terminé :

  • encodings Transaction séparés entre entrées binaires base58/base64 et surface getTransaction incluant les formes JSON/legacy ;
  • configs modernes de getTransaction, pagination signatures, statuses, airdrop, send et simulation ;
  • DTOs latestBlockhash, prioritization fee, signature info/status, transaction encodée/versionnée et résultat de simulation ;
  • primitive SolanaWireField<T> pour préserver explicitement omitted/null/value ;
  • transactionIndex préservé sur getSignaturesForAddress et sur le top-level getTransaction courant ;
  • transaction/meta/return data/inner instructions/token balances riches conservés losslessly aux frontières prévues sans décodage Program ;
  • fixtures communes déterministes pour les variantes legacy/binary/JSON, version/meta/index et simulation riche ;
  • aucune nouvelle dépendance Cargo et aucun wrapper 0.2.3 activé prématurément.

La tranche suivante reste pre.003 : getFeeForMessage, getLatestBlockhash, getTransactionCount et isBlockhashValid.

Résultat de pre.006

pre.006 active les deux écritures Transaction sans introduire de chemin de soumission parallèle :

  • requestAirdrop expose Pubkey, lamports, commitment et le recentBlockhash encore supporté par Agave v4.2.1 ;
  • sendTransaction transporte une transaction déjà signée/encodée et expose base58/base64, skipPreflight, preflightCommitment, maxRetries et minContextSlot ;
  • sendTransaction.maxRetries reste explicitement node-side et ne modifie jamais HttpRetrySettings ;
  • les deux wrappers passent par leur descriptor central WriteSubmission / NeverAfterDispatch puis execute_standard_rpc ;
  • les fixtures end-to-end comptent les requêtes et prouvent une seule soumission après HTTP 429, HTTP 503 et timeout après dispatch ;
  • une connexion refusée classée NotDispatched peut encore utiliser la policy centrale de retry/fallback, démontrée pour les deux wrappers ;
  • les erreurs RPC applicatives, dont un échec de preflight sendTransaction, restent des erreurs applicatives sans retry transport ;
  • aucune dépendance transactionnelle/codec supplémentaire n'est ajoutée ;
  • simulateTransaction reste la seule méthode 0.2.3 non encore activée.

La prévision est ajustée : pre.008 devient l'audit rétroactif KSP-TRANSPORT-007 et la clôture finale est déplacée à pre.009.

Résultat de pre.007

pre.007 active la dernière méthode Transaction, simulateTransaction, et porte donc la couverture typée 0.2.3 à 11/11 :

  • transaction d'entrée conservée comme chaîne opaque, sans dépendance codec/SDK ;
  • encodings d'entrée base58 et base64 couverts ;
  • config complète conservée : commitment, encoding, replaceRecentBlockhash, sigVerify, minContextSlot, innerInstructions, accounts ;
  • sous-config accounts capable d'émettre base64, base64+zstd et jsonParsed, avec rejet local de binary/base58 conformément à Agave v4.2.1 ;
  • incompatibilité déterministe sigVerify=true + replaceRecentBlockhash=true rejetée avant I/O ;
  • limite dynamique du nombre d'adresses accounts laissée au runtime puisque KSP ne décode pas la transaction ;
  • résultat riche préservé losslessly, y compris les champs Agave v4.2.1 au-delà du résumé documentaire public : fee, balances, token balances et loaded addresses ;
  • omitted/null/value conservés pour les champs optionnels avec SolanaWireField<T> ;
  • accounts de simulation décodés via le wire Account KSP existant, avec null positionnels conservés ;
  • erreur RPC applicative conservée sans transformation en erreur transport ;
  • descriptor central Simulation / RetrySafe exercé end-to-end par un scénario HTTP 503 puis succès, démontrant que la simulation peut être retentée ;
  • canarie release exacte 8 Read / 2 WriteSubmission / 1 Simulation, soit les 11 méthodes V0_2_3.

Aucune dépendance n'est ajoutée. Le travail fonctionnel initialement planifié pour les 11 Transactions est désormais implémenté ; pre.008 reste volontairement réservée au réaudit rétroactif KSP-TRANSPORT-007 des wrappers HTTP 0.2.1 -> 0.2.3, puis pre.009 à la clôture.