v0.2.3-pre.001
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/000-README.md -->
|
||||
<!-- version: 34 -->
|
||||
<!-- version: 35 -->
|
||||
|
||||
# Plans KSP
|
||||
|
||||
@@ -18,6 +18,7 @@ Un plan décrit le périmètre, les décisions déjà acquises, les questions ou
|
||||
- [`007-V0_2_0_SERIES_PLANNING.md`](007-V0_2_0_SERIES_PLANNING.md) — plan historique clôturé de la release stable `0.2.0`, ouvert par `pre.001`, consolidé par `pre.002`, audité par `pre.003` puis publié par `rel.001`; il fixe l'ordre `0.2.1+`, la stratégie RAW/CORE/DECODE/SPECIALIZED, les vertical slices Program et le prompt `0.2.1`.
|
||||
- [`008-V0_2_1_ONCHAIN_HTTP_PLAN.md`](008-V0_2_1_ONCHAIN_HTTP_PLAN.md) — plan de `0.2.1`, établi par `0.2.1-pre.001`, recalibré par `pre.001-fix.001` et amené en clôture candidate par `pre.007`; il conserve l'inventaire 52 méthodes HTTP courantes + 14 Deprecated historiques, le design Transport/Config et le split de couverture typée sur `0.2.1`–`0.2.4`.
|
||||
- [`009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md`](009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md) — plan clôturé de la release stable `0.2.2`, établi par `pre.001`, corrigé après réaudit Agave v4.2.1 puis exécuté jusqu'à `pre.007-fix.002`; il couvre les 22 wrappers Accounts/Tokens/Cluster, le smoke Transport opt-in et la préparation de `0.2.3`.
|
||||
- [`010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`](010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md) — plan actif de `0.2.3 — HTTP Transactions`, ouvert par `pre.001`; il confirme les 11 méthodes, la classification `8 Read / 2 WriteSubmission / 1 Simulation`, les wires transactionnels et le no-resend après dispatch ambigu.
|
||||
|
||||
Le `pre.001` de chaque release fonctionnelle peut introduire son propre plan détaillé lorsque la release s'ouvre.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/002-FUNCTIONAL_RELEASE_SEQUENCE.md -->
|
||||
<!-- version: 36 -->
|
||||
<!-- version: 37 -->
|
||||
|
||||
# Séquence des releases fonctionnelles KSP
|
||||
|
||||
@@ -392,6 +392,8 @@ Chaque `pre.001` réaudite la documentation officielle actuelle. Les méthodes D
|
||||
|
||||
`0.2.2-pre.001` a confirmé la partition de 22 méthodes et son fix documentaire a recoupé les formes wire avec Agave v4.2.1. Les tranches `pre.002`–`pre.006` ont livré les DTOs puis les 5 Accounts, 5 Tokens et 12 Cluster. `pre.007`, puis `pre.007-fix.001` et `pre.007-fix.002`, ont fermé les canaries exactes 22/22, le smoke Devnet Transport pur, README/USAGE, la matrice de validation `004` et le prompt `0.2.3`. `0.2.2-rel.001` publie cette surface stable après validation du workspace et des deux smokes Devnet. Le smoke cross-crates Config -> Transport de `0.2.1` reste séparé et transitoire.
|
||||
|
||||
`0.2.3-pre.001` réaudite le 2026-08-18 la catégorie Transactions contre la documentation Solana actuelle et Agave v4.2.1 : les 11 méthodes prévues restent exactes, la classification `8 Read / RetrySafe`, `2 WriteSubmission / NeverAfterDispatch` et `1 Simulation / RetrySafe` reste correcte, et le gate de sizing est positif. Aucun `base64`, `bs58`, `wincode` ni client RPC Solana supplémentaire n’est ajouté à l’ouverture : les payloads sérialisés restent opaques dans Transport tant qu’un besoin de décodage local n’est pas démontré. Le plan détaillé actif est `docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md`.
|
||||
|
||||
## `0.2.5` — Wallet foundation
|
||||
|
||||
Mission : créer `ksp-wallet-lib` et le format `.kspwallet`.
|
||||
|
||||
636
docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md
Normal file
636
docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md
Normal file
@@ -0,0 +1,636 @@
|
||||
<!-- file: docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# 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 :
|
||||
|
||||
```text
|
||||
https://solana.com/docs/rpc/http
|
||||
https://solana.com/docs/rpc/json-structures
|
||||
```
|
||||
|
||||
Pages Transaction réauditées :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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` :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 15–20 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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
wrapper typed
|
||||
-> descriptor central
|
||||
-> execute_standard_rpc
|
||||
-> pool/admission
|
||||
-> executor HTTP
|
||||
-> validation JSON-RPC
|
||||
-> decode typed
|
||||
```
|
||||
|
||||
Restent interdits :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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.
|
||||
|
||||
## 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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
Option<SignatureStatus>
|
||||
```
|
||||
|
||||
Un statut présent conserve :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
commitment Option<SolanaCommitment>
|
||||
encoding Option<TransactionEncoding>
|
||||
maxSupportedTransactionVersion Option<u8>
|
||||
```
|
||||
|
||||
La compatibilité auditée garde en plus une forme legacy explicite :
|
||||
|
||||
```text
|
||||
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é :
|
||||
|
||||
```text
|
||||
slot u64
|
||||
blockTime Option<i64>
|
||||
transaction EncodedTransaction
|
||||
meta Option<transaction-meta wire>
|
||||
version legacy | number
|
||||
```
|
||||
|
||||
`EncodedTransaction` doit préserver les différentes formes réellement sérialisées :
|
||||
|
||||
```text
|
||||
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.
|
||||
|
||||
### `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 :
|
||||
|
||||
```text
|
||||
slot u64
|
||||
prioritizationFee u64
|
||||
```
|
||||
|
||||
### Pagination `getSignaturesForAddress`
|
||||
|
||||
La config prévue conserve :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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 :
|
||||
|
||||
```text
|
||||
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.
|
||||
|
||||
## Prévision souple des prereleases
|
||||
|
||||
```text
|
||||
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 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. La dernière prerelease reste une tranche de
|
||||
clôture documentaire/validation et ne doit pas devenir une implémentation massive tardive.
|
||||
|
||||
## 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` ;
|
||||
- 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
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
cargo test -p ksp-onchain-transport-lib
|
||||
```
|
||||
|
||||
## Validations prévues à la clôture
|
||||
|
||||
```bash
|
||||
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.002`–`pre.008` défini.
|
||||
|
||||
La tranche suivante peut commencer par les primitives wire communes sans réouvrir le scope de release.
|
||||
Reference in New Issue
Block a user