v0.1.0-pre.061
This commit is contained in:
387
olddocs/EXECUTION_MODEL.md
Normal file
387
olddocs/EXECUTION_MODEL.md
Normal file
@@ -0,0 +1,387 @@
|
||||
<!-- file: docs/EXECUTION_MODEL.md -->
|
||||
<!-- version: 29 -->
|
||||
|
||||
# Modèle d'exécution
|
||||
|
||||
Ce document décrit la couche d'exécution universelle du workspace.
|
||||
|
||||
## Séparation des responsabilités
|
||||
|
||||
Un décodeur lit une transaction existante. Un exécuteur prépare une opération future. Les deux couches peuvent partager une surface canonique, mais elles ne doivent pas dépendre l'une de l'autre.
|
||||
|
||||
```text
|
||||
kb_decoder_amm_pump_swap -> observation, décodage, audit
|
||||
kb_executor_amm_pump_swap -> construction future d'instructions d'achat/vente
|
||||
```
|
||||
|
||||
## Bibliothèques universelles
|
||||
|
||||
Le trading est le premier consommateur du workspace, pas la limite de ses crates. Les exécuteurs doivent pouvoir être réutilisés par une CLI, un worker, un outil d'administration, une application de jeu, une application Tauri ou un service autonome.
|
||||
|
||||
Cette universalité implique :
|
||||
|
||||
- un intent typé indépendant de l'interface utilisateur ;
|
||||
- un plan déterministe sans I/O ;
|
||||
- des builders couvrant les opérations officiellement appelables, y compris administratives ou dangereuses ;
|
||||
- des politiques de sécurité séparées du builder ;
|
||||
- une exposition UI volontairement plus étroite que la capacité de la bibliothèque ;
|
||||
- aucune dépendance vers les décodeurs pour construire ou signer une transaction.
|
||||
|
||||
Une opération dangereuse ne doit pas être supprimée de l'exécuteur. Elle doit être implémentée, testée, classifiée et soumise à une politique renforcée. `kb_app_demo` peut ne jamais l'exposer.
|
||||
|
||||
## Couches
|
||||
|
||||
- `kb_execution_api` définit les contrats communs des exécuteurs.
|
||||
- `kb_execution_safety` regroupe les validations avant simulation, signature ou envoi.
|
||||
- `kb-lib::executor::solana::transaction` assemble les plans en messages/transactions Solana et orchestre la signature sans RPC.
|
||||
- `kb_executor_solana_core` construit les instructions des programmes natifs.
|
||||
- `kb_wallet` isole les secrets et fournit des signataires.
|
||||
- `kb_onchain_transport` fournit simulation, envoi et confirmation.
|
||||
- `kb_pipeline` peut orchestrer la validation post-exécution par réingestion et replay.
|
||||
- `kb_app_demo` ne fait qu'orchestrer une sélection sûre de ces capacités.
|
||||
|
||||
## Pipeline obligatoire
|
||||
|
||||
```text
|
||||
intent
|
||||
-> execution plan
|
||||
-> policy checks
|
||||
-> transaction build
|
||||
-> simulation / dry-run
|
||||
-> signature
|
||||
-> send
|
||||
-> confirmation
|
||||
-> post-execution decode replay validation
|
||||
```
|
||||
|
||||
Construction, signature, envoi et validation ne doivent jamais être fusionnés dans une fonction opaque.
|
||||
|
||||
## Politique de couverture
|
||||
|
||||
`Supported` signifie que le builder et son contrat de comptes/signataires sont implémentés. `Unsupported(reason)` reste acceptable uniquement lorsqu'une surface n'est pas appelable par transaction, a été retirée du runtime, ne dispose pas encore d'une source officielle suffisante ou constitue une dette temporaire explicitement planifiée.
|
||||
|
||||
L'objectif de clôture de `kb_executor_solana_core` est de ne laisser aucune instruction native officiellement appelable oubliée. Les variantes historiques uniquement décodables ne doivent pas être artificiellement réémises.
|
||||
|
||||
## Adaptateurs RPC de simulation
|
||||
|
||||
`0.4.2-pre.004` ajoute dans `kb_onchain_transport` les premières lectures nécessaires avant signature :
|
||||
|
||||
```text
|
||||
getGenesisHash
|
||||
getLatestBlockhash
|
||||
getFeeForMessage
|
||||
simulateTransaction
|
||||
```
|
||||
|
||||
Le genesis hash sert à classifier les clusters publics connus. Le réseau de production est nommé Mainnet dans le contrat public du workspace ; le hash est inchangé et certains endpoints/CLI conservent encore l’alias historique `mainnet-beta`. Un hash inconnu reste explicite et n’est pas automatiquement assimilé à Devnet ou Mainnet. Le blockhash et sa dernière block height valide sont conservés séparément. L’estimation des frais accepte une valeur nulle lorsque le message référence un blockhash expiré.
|
||||
|
||||
La simulation accepte une transaction base64 non signée lorsque `sigVerify = false`; `replaceRecentBlockhash = true` permet au nœud de remplacer le blockhash avant simulation. Les erreurs runtime restent un résultat de simulation typé et ne sont pas confondues avec une erreur HTTP ou JSON-RPC.
|
||||
|
||||
`kb_onchain_transport` ne fabrique pas le contexte de sécurité : cluster attendu, âge du blockhash, nonce account et nonce authority sont fournis explicitement lors de la conversion vers `ExApiExecutionSimulationResult`. Depuis `pre.013`, `getAccountInfo` possède aussi un mode données complètes borné : le mode metadata-only conserve `dataSlice.length = 0`, tandis que `confirmed_with_data(max_data_bytes)` exige un tuple base64 complet dont la longueur décodée égale `space`.
|
||||
|
||||
## Assemblage et signature Solana
|
||||
|
||||
`0.4.2-pre.005` introduit `kb-lib::executor::solana::transaction`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `ExApiPlannedInstruction` en instructions SDK, compile le message avec son fee payer et sa source de blockhash, puis vérifie que les signataires réellement compilés correspondent exactement au contrat du plan.
|
||||
|
||||
La transaction non signée fournit deux sorties distinctes :
|
||||
|
||||
```text
|
||||
message base64 -> getFeeForMessage
|
||||
transaction non signée -> simulateTransaction(sigVerify=false, replaceRecentBlockhash=false)
|
||||
```
|
||||
|
||||
Le résultat de simulation est lié au hash exact du message et à la valeur de blockhash ou nonce compilée. Une simulation avec remplacement de blockhash reste utile au diagnostic, mais ne peut pas autoriser la signature du message original. La signature refuse un résultat provenant d’un autre message ou d’une autre valeur nonce, réévalue `kb_execution_safety`, exige la décision `Allow`, puis résout tous les signataires via l’interface Solana `Signer`. Les signataires manquants, supplémentaires ou dupliqués sont refusés. La transaction signée reste en mémoire/backend et n’est ni envoyée ni exposée automatiquement à Tauri.
|
||||
|
||||
La sérialisation transactionnelle utilise le schéma officiel `wincode` fourni par les types Solana et applique la limite réseau de 1 232 octets. Aucun appel direct à `bincode` n’est ajouté.
|
||||
|
||||
### Chemin durable nonce réel — `pre.013`
|
||||
|
||||
Le lifecycle d’un compte nonce et la consommation d’un durable nonce sont deux contrats distincts. Les opérations `initialize`, `advance`, `authorize`, `withdraw` et `upgrade` administrent le compte avec une politique `Latest`. Une transaction métier utilisant un nonce durable suit le chemin stateful suivant :
|
||||
|
||||
```text
|
||||
getAccountInfo complet et borné à la taille nonce officielle
|
||||
-> validation owner System Program / non-executable / space exact
|
||||
-> décodage wincode Versions::Current(State::Initialized)
|
||||
-> concordance compte et autorité avec ExecutionBlockhashPolicy
|
||||
-> Message::new_with_nonce
|
||||
-> AdvanceNonceAccount en instruction 0
|
||||
-> valeur nonce comme recent_blockhash du message
|
||||
-> simulation exacte sans remplacement
|
||||
-> signature du même hash de message et de la même valeur nonce
|
||||
```
|
||||
|
||||
`kb_executor_solana_core` ajoute l’autorité nonce aux signataires requis du plan métier. `kb-lib::executor::solana::transaction` refuse les états legacy ou non initialisés, conserve le plan source immuable, expose un plan effectif avec l’avance injectée et exige que le SDK reconnaisse la transaction comme durable nonce. La lecture RPC, l’assemblage, la simulation et la signature restent des étapes séparées.
|
||||
|
||||
|
||||
### Builders Address Lookup Table — `pre.015`
|
||||
|
||||
`kb_executor_solana_core` couvre les cinq opérations client de l’interface Address Lookup Table : création, extension, gel, désactivation et fermeture. Le builder stateless garantit le program ID, le payload, l’ordre des comptes et les signataires exacts, mais ne prétend pas connaître l’état courant du compte ni le coût de rent calculé par le runtime.
|
||||
|
||||
```text
|
||||
intent ALT typé
|
||||
-> builder officiel exact
|
||||
-> plan avec autorité/payer explicites
|
||||
-> lecture RPC stateful du compte et du slot
|
||||
-> contrôle owner / autorité / état / capacité / cooldown
|
||||
-> calcul du top-up rent-exempt et simulation exacte
|
||||
-> politique de dépense
|
||||
-> signature et envoi
|
||||
```
|
||||
|
||||
La création dérive la table depuis l’autorité et un slot récent. L’extension conserve l’ordre des adresses, exige une liste non vide et borne l’input à la capacité maximale officielle ; la capacité restante et le top-up effectif doivent être contrôlés sur le compte réel. Le gel est irréversible. La fermeture n’est autorisée qu’après désactivation et expiration du cooldown lié aux slots. `requested_spend_lamports` reste nul dans le plan ALT parce qu’aucun montant de rent n’est encodé directement dans l’instruction ; l’orchestrateur doit calculer le top-up à partir du compte réel et du minimum rent-exempt, le comparer au plafond de dépense, puis confirmer l’instruction par simulation.
|
||||
|
||||
|
||||
### Précompiles de signature — `pre.016`
|
||||
|
||||
Les précompiles Ed25519, secp256k1 et secp256r1 sont des vérifications natives, pas des signatures de transaction. Leur plan ne déclare aucun compte applicatif ni signataire propre ; le fee payer signe uniquement la transaction. Le programme métier qui consomme la preuve doit inspecter l’instruction correspondante et appliquer lui-même son contrat d’autorisation.
|
||||
|
||||
```text
|
||||
message + signature + clé/adresse
|
||||
-> builder inline ou table d’offsets officielle
|
||||
-> instruction précompile sans comptes
|
||||
-> positionnement transactionnel exact
|
||||
-> programme consommateur qui inspecte le sysvar d’instructions
|
||||
-> simulation exacte
|
||||
-> signature Solana du fee payer et des signataires métier distincts
|
||||
```
|
||||
|
||||
Les formes inline Ed25519 et secp256r1 utilisent `u16::MAX` comme référence à leurs propres données. secp256k1 encode des index d’instruction `u8` sans sentinelle ; la forme inline et les références locales du builder exigent donc que l’instruction secp256k1 soit à l’index transactionnel `0`. Un futur assembleur multi-plans doit refuser ou réécrire explicitement toute combinaison qui violerait cette position.
|
||||
|
||||
Les tables avancées acceptent des références externes et un buffer local ajouté après les offsets. Le builder borne le nombre d’entrées à 255, la taille totale à 65 535 octets et les plages locales connues. Il ne lit pas les données des autres instructions : leur cohérence cryptographique est vérifiée par le runtime et leur signification métier par le programme consommateur.
|
||||
|
||||
La signature secp256r1 est fournie au format compact `r || s`; le builder exige des composants non nuls et la forme low-S imposée par le runtime. Le builder secp256k1 reçoit la signature compacte, le recovery ID et l’adresse Ethereum déjà dérivée ; il ne manipule aucune clé privée et n’active aucun helper `bincode`. Le runtime secp256k1 ne garantit pas la canonicalité low-S : lorsqu’elle est requise, cette politique appartient au programme consommateur ou à une validation métier explicite.
|
||||
|
||||
|
||||
### Config, Feature, Slashing et ZK ElGamal — `pre.017`
|
||||
|
||||
Les opérations administratives natives restent des plans déterministes sans accès RPC implicite.
|
||||
|
||||
```text
|
||||
état/rent fourni par l’orchestrateur
|
||||
-> builder exact
|
||||
-> plan et signataires
|
||||
-> lecture stateful de confirmation
|
||||
-> simulation exacte
|
||||
```
|
||||
|
||||
Config encode manuellement le contrat `ConfigKeys + données sérialisées` afin de ne pas activer le helper `bincode` de l’interface. Feature reproduit les séquences officielles d’activation et de révocation. Les montants de rent sont des entrées explicites comptabilisées dans le plafond de dépense.
|
||||
|
||||
La preuve de bloc dupliqué Slashing est indivisible : transfert de préfinancement, instruction Ed25519 et instruction Slashing doivent conserver leurs positions. Le plan refuse donc durable nonce et exige un recent blockhash normal. Le compte de preuve, la fenêtre temporelle, le montant rent-exempt et la rétention avant fermeture relèvent de l’orchestrateur stateful.
|
||||
|
||||
ZK ElGamal accepte une preuve inline ou une preuve dans un compte, avec création optionnelle d’un contexte déjà préalloué. La fermeture exige l’autorité comme signataire. Le builder vérifie discriminant, taille et comptes, mais ne crée pas le contexte et ne recalcule pas la preuve cryptographique. L’ancien ZK Token Proof est historique et reste `decode-only`.
|
||||
|
||||
## Stake et Vote dans la bibliothèque
|
||||
|
||||
`pre.018` ajoute les vingt-quatre helpers clients actuels de `solana-stake-interface 4.3.1` sous forme de plans déterministes. Les formes composées conservent l’ordre officiel : création System puis initialisation Stake, délégation ajoutée en dernier, allocation/assignation avant split. Les rôles staker/withdrawer sont typés par `StakeAuthorizationKind`.
|
||||
|
||||
`pre.019` ajoute les vingt variantes wire Vote actuelles et quatre créations composées legacy/V2. Les autorités Ed25519/BLS, commissions, collecteurs, votes, switch proofs, compact updates et TowerSync sont encodés avec l’enum officielle `VoteInstruction` et `wincode`. Les créations, retraits et dépôts de récompenses déclarent leurs lamports dans le plafond de dépense.
|
||||
|
||||
La construction reste stateless. Avant simulation puis envoi, l’orchestrateur doit charger et valider l’état des comptes Stake/Vote, les autorités, le lockup, le rent, le minimum de délégation, les epochs d’activation/désactivation, la compatibilité merge/split/move, la version Vote, les collecteurs et l’admissibilité runtime de la tour. `Redelegate` reste historique `decode-only`, car l’interface officielle le déclare déprécié et non activable.
|
||||
|
||||
## Loaders dans la bibliothèque
|
||||
|
||||
`pre.020` ajoute onze plans Loader v3 et neuf plans Loader v4. Loader v3 utilise les helpers de `solana-loader-v3-interface 8.x` et leur schéma `wincode` pour créer des buffers, écrire, déployer, upgrader, modifier les autorités, fermer et étendre. Loader v4 conserve le contrat officiel des sept discriminants, mais son wire est construit localement et explicitement parce que les helpers publiés sont conditionnés par `bincode` et qu’aucun schéma `wincode` n’est exposé.
|
||||
|
||||
Les plans de création conservent l’ordre atomique System puis Loader. Les écritures sont bornées, les offsets contrôlés contre les dépassements, les comptes/signataires reproduisent l’interface officielle et les lamports explicitement transférés sont inclus dans `requested_spend_lamports`. Les loyers calculés dynamiquement par le runtime ne sont pas inventés par le builder.
|
||||
|
||||
Avant simulation, l’orchestrateur stateful doit vérifier owner, état courant, autorité, taille/capacité, rent, existence des comptes Program/ProgramData/buffer, relations dérivées et admissibilité de fermeture ou d’extension. Les opérations Loader restent hors de la démo opérateur. BPF Loader v1/v2 sont historiques `decode-only`; Native Loader correspond au déploiement du logiciel validator et n’expose pas d’instruction client autonome.
|
||||
|
||||
|
||||
## Préflight stateful natif — `pre.022`
|
||||
|
||||
Les builders restent déterministes et sans I/O. `kb_pipeline::inspect_solana_core_stateful_readiness` ajoute une étape séparée avant la simulation pour les opérations dont l’admissibilité dépend de comptes ou de l’époque courante.
|
||||
|
||||
```text
|
||||
SolanaCoreOperation
|
||||
-> plan stateless
|
||||
-> préflight stateful Localnet/Devnet
|
||||
-> rapport Ready / Blocked / NotRequired
|
||||
-> simulation exacte
|
||||
```
|
||||
|
||||
Le préflight vérifie le genesis hash attendu et utilise uniquement des RPC typés. Il couvre :
|
||||
|
||||
- ALT : PDA de création, slot récent, owner, autorité, capacité, rent top-up, état actif/désactivé et cooldown de fermeture ;
|
||||
- Config : absence/réutilisation contrôlée, allocation calculée, owner et espace disponible ;
|
||||
- Feature : compte absent ou System réutilisable, rent mesuré et état pending avant révocation ;
|
||||
- Slashing : compte de preuve complet et borné, deux shreds length-prefixed, fenêtre d’un epoch, rent du rapport, destination retenue et délai de fermeture ;
|
||||
- ZK ElGamal : plage de preuve, owner/space/rent du contexte préalloué, état zéro avant écriture, puis autorité et discriminant avant fermeture.
|
||||
|
||||
Le rapport contient des codes de contrôle stables, des faits mesurés et le plus haut slot de contexte observé. Il ne signe, ne simule et n’envoie aucune transaction. Testnet et Mainnet sont refusés dans cette couche tant que les parcours Localnet/Devnet ne sont pas validés.
|
||||
|
||||
## Préflight stateful SPL Token classique — `0.4.4-pre.005`
|
||||
|
||||
Le même découpage s’applique à SPL Token : `kb_executor_spl_token` construit un plan universel sans I/O, puis `kb_pipeline::inspect_spl_token_stateful_readiness` vérifie l’état Localnet ou Devnet avant simulation. Le décodeur ne réalise aucune lecture RPC.
|
||||
|
||||
Le préflight lit des données complètes bornées et reproduit les layouts classiques Mint, Account et Multisig. Il contrôle notamment owner programme, initialisation, mint/decimals, état frozen, solde et réserve native, delegate/allowance, autorités spécialisées, seuil multisig et rent des comptes préparés. Les montants restent des entiers bruts exacts. Une précondition métier invalide produit `Blocked`; une erreur de transport ou de forme reste une erreur `kb_core`.
|
||||
|
||||
La preuve réseau est séparée en deux niveaux. Le test opt-in de `pre.005` vérifie en lecture seule un `TransferChecked` sur des comptes Devnet fournis explicitement. Le scénario opérateur complet doit ensuite créer des comptes classiques sans ATA, simuler par défaut, et ne signer/envoyer qu’avec une autorisation distincte ; après confirmation, il doit réutiliser hydratation canonique, extraction core, replay, projections et second replay idempotent.
|
||||
|
||||
`pre.005-delta-fix-001` relie ce préflight au chemin d’exécution commun. La simulation constitue une API autonome sans store et conserve le plan, le rapport stateful, le blockhash, les frais et le résultat runtime. La soumission est une seconde API : elle refuse tout signataire absent du wallet de profil, puis applique confirmation, hydratation, extraction, decode replay, requête matérialisée bornée et preuve d’idempotence. Cette restriction de signataire appartient à l’orchestrateur actuel, pas à l’exécuteur universel ni au wire multisig.
|
||||
|
||||
Le 15 juillet 2026, ce parcours a réussi en simulation puis avec un envoi `TransferChecked` réel sur Devnet, entre deux comptes auxiliaires classiques créés sans dépendance ATA. `pre.005-delta-fix-002` durcit la preuve opt-in : résultat d’envoi présent, confirmation `confirmed` ou `finalized`, premier replay sans échec ni refus, matérialisation Token présente, second replay sans échec, refus ou nouvelle sortie, et signature imprimée pour l’audit.
|
||||
|
||||
`0.4.4-pre.006` compose ce contrat sans le contourner. La préparation interne génère trois keypairs éphémères, mesure le rent exact puis construit trois `SystemCreateAccount` officiels avec le propriétaire Token classique et les tailles 82/165/165. Chaque création est simulée, signée par le payeur et le nouveau compte, confirmée, puis relue pour vérifier owner, rent, taille, absence d'executable et données entièrement nulles. Les clés de création peuvent ensuite disparaître : les initialisations Token n'en ont pas besoin. Le lifecycle n'utilise pas ATA. Après autorisation destructive explicite, il exécute onze transactions séparées : initialisation du mint, initialisation des deux comptes, mint checked, transfer checked, approve checked, revoke, burn checked des deux soldes puis fermeture des deux comptes. Une étape incomplète arrête la séquence ; la suivante n'est construite qu'après confirmation, hydratation, extraction, décodage, matérialisation et second replay idempotent de la précédente.
|
||||
|
||||
Une confirmation RPC interrompue ne rend pas la séquence aveuglément rejouable : les initialisations Token ne sont pas idempotentes. La reprise exige donc l'index de la prochaine étape et la signature confirmée de son prédécesseur. Le pipeline hydrate cette signature, extrait le core, impose le decode Token commité, vérifie l'opération matérialisée attendue et un second replay sans sortie avant de construire l'étape suivante. Un délai borné entre étapes réduit les rafales vers le RPC public ; il ne transforme pas un statut inconnu en succès.
|
||||
|
||||
Cette reprise a été exercée sur Devnet le 15 juillet 2026 après un throttling `429` puis une confirmation momentanément incomplète. L'initialisation du compte destination déjà finalisée a été récupérée depuis sa signature canonique ; les étapes 3 à 10 ont ensuite achevé `MintToChecked`, `TransferChecked`, `ApproveChecked`, `Revoke`, deux `BurnChecked` et deux `CloseAccount`. Les neuf étapes récupérées ou envoyées ont chacune validé une matérialisation et un second replay idempotent.
|
||||
|
||||
`0.4.4-pre.007` n'ajoute aucune nouvelle couche d'exécution. La fenêtre Tauri existante construit un intent `TransferChecked` mince, puis appelle le même `execute_devnet_spl_token`. Le journal opérateur interroge au maximum 500 lignes via `MaterializedEventFilter`; les filtres exacts mint, compte et opération sont appliqués au payload typé en mémoire. La frontière UI conserve slots et montants bruts sous forme de chaînes et ne revendique aucun snapshot final ni agrégat OHLC.
|
||||
|
||||
`docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` constitue l’inventaire machine-readable de clôture. Un test Rust de `kb_executor_solana_core` charge cette matrice et impose dix-huit surfaces, 109 opérations appelables exactement égales à `SOLANA_CORE_OPERATION_CODES`, ainsi qu’une justification non vide pour chaque surface sans builder client. Le validateur Python provisoire a été supprimé.
|
||||
|
||||
## Préflight stateful ATA — `0.4.5-pre.004`
|
||||
|
||||
`kb_executor_spl_associated_token_account` construit exactement un builder officiel parmi
|
||||
`Create`, `CreateIdempotent` et `RecoverNested`. Le Token Program classique ou Token-2022 fait
|
||||
partie de l’intent et de la dérivation ; la bibliothèque ne lie toujours pas un plan à un endpoint
|
||||
ou à un wallet concret.
|
||||
|
||||
`kb_pipeline::inspect_spl_associated_token_account_stateful_readiness` est la frontière I/O
|
||||
Localnet/Devnet. Elle vérifie le genesis, le Program ID ATA, la simulation obligatoire, les mints,
|
||||
les PDA, l’absence stricte pour `Create`, la compatibilité absence/compte existant pour
|
||||
`CreateIdempotent`, les trois comptes Token de `RecoverNested`, tous les signataires et le solde du
|
||||
payer couvrant le plafond rent-plus-frais.
|
||||
|
||||
Les comptes Token-2022 peuvent dépasser 165 octets. Le préflight valide leur préfixe Token Account
|
||||
commun et laisse les extensions opaques ; il ne commence donc pas `0.4.6`. Le rent minimal du
|
||||
compte de base et le plafond sont contrôlés avant simulation. La taille et le rent exacts imposés
|
||||
par des extensions restent vérifiés par le runtime pendant la simulation obligatoire.
|
||||
|
||||
Le rapport `Ready`/`Blocked` ne signe, ne simule et n’envoie rien. L’orchestration de soumission,
|
||||
confirmation et replay reste une tranche séparée afin qu’un statut RPC inconnu ne provoque jamais
|
||||
une recréation ATA aveugle.
|
||||
|
||||
## Orchestration ATA Devnet — `0.4.5-pre.005`
|
||||
|
||||
`execute_devnet_spl_associated_token_account` réutilise les frontières communes validées : wallet
|
||||
persistant de profil, plan typé, préflight stateful, message exact, frais, simulation liée au hash,
|
||||
signature après autorisation, envoi et confirmation. Après confirmation, la signature déjà connue
|
||||
est hydratée par tentatives bornées ; chaque tentative RPC autorise deux reprises internes pour les
|
||||
réponses transitoires telles que `429`, sans reconstruire ni renvoyer l’instruction ATA.
|
||||
|
||||
Le replay sélectionne toujours le Program ID ATA. Pour une cible SPL Token classique, il sélectionne
|
||||
aussi le Program ID Token afin de décoder les CPI internes, tout en laissant chaque matérialiseur
|
||||
posséder uniquement ses faits. Pour Token-2022, il ne prétend pas décoder les instructions ou
|
||||
extensions CPI générales réservées à `0.4.6`. La seconde passe inclut l’état matérialisé et doit ne
|
||||
produire aucune nouvelle sortie.
|
||||
|
||||
La bibliothèque d’exécution ATA reste indépendante du cluster et du wallet. L’orchestrateur Devnet
|
||||
fourni ne peut signer qu’avec le wallet persistant du profil ; un `RecoverNested` exigeant une autre
|
||||
clé est donc refusé comme signataire indisponible. La fenêtre Tauri existante expose seulement les
|
||||
modes représentatifs `Create` et `CreateIdempotent`, la dérivation readonly et un journal ATA borné.
|
||||
|
||||
Le 16 juillet 2026, le parcours classique `CreateIdempotent` a été confirmé deux fois sur le même
|
||||
ATA Devnet. La première signature `2H9V…CPbP` et la seconde `3wWT…fv6q` ont chacune réussi
|
||||
simulation, confirmation, hydratation canonique, extraction, décodage, projection lifecycle unique
|
||||
et second replay sans nouvelle sortie. La seconde exécution prouve le chemin compte existant
|
||||
compatible ; elle reste un fait transactionnel distinct et non un doublon de replay.
|
||||
|
||||
Le garde-fou Token-2022 a également refusé correctement le Program ID `TokenzQd…` lorsqu’il était
|
||||
fourni à la place d’un compte mint : owner, layout Mint et état initialisé ne correspondaient pas.
|
||||
La preuve positive utilise ensuite le mint contrôlé `3DxK…KTE`, initialisé sur 82 octets et possédé
|
||||
par Token-2022. `CreateIdempotent` a créé puis réutilisé l’ATA `6WfC…C9Y`, compte de 170 octets
|
||||
initialisé pour `DwuA…g8B2` avec l’extension `ImmutableOwner`. Les signatures `bMMj…QAJ` au slot
|
||||
476702448 et `4RZK…VSG` au slot 476703343 ont chacune été simulées, confirmées, hydratées, décodées
|
||||
et matérialisées une fois, puis ignorées au second replay. L’état préalable observé établit la
|
||||
réutilisation de la seconde transaction, tandis que la projection parent conserve correctement
|
||||
`created_or_reused` car l’instruction seule ne distingue pas ces branches.
|
||||
|
||||
`RecoverNested` reste volontairement hors UI. Son parcours contrôlé opt-in reçoit deux mints et une
|
||||
fixture nested déjà préparée, puis réutilise le même orchestrateur afin de vérifier simulation,
|
||||
confirmation, fermeture du nested ATA, destination cohérente, deux projections ATA/risk et second
|
||||
replay idempotent sans introduire de décodeur Token-2022 général.
|
||||
|
||||
La preuve Devnet classique du 16 juillet 2026 utilise `3tdX…FbF5`, ATA wrapped SOL du wallet,
|
||||
comme owner du nested ATA `AAyv…gti5`. Celui-ci contenait exactement 1 token, soit
|
||||
1 000 000 000 unités brutes du mint `3fd5…hC9A`, et la destination `69TP…fyWp` était vide. La
|
||||
signature `37LG…HskM` a transféré le montant complet, fermé le nested ATA, conservé l’owner ATA et
|
||||
la destination initialisés, produit exactement les deux sorties parent `nested_ata_recovered` et
|
||||
`nested_ata_anti_pattern_recovered`, puis réussi le second replay sans doublon. Les mutations CPI
|
||||
Token de transfert et fermeture ne sont pas recopiées dans les projections parent ATA.
|
||||
|
||||
## Soumission et confirmation RPC
|
||||
|
||||
`0.4.2-pre.008` complète la frontière réseau sans fusionner les étapes :
|
||||
|
||||
```text
|
||||
SignedSolanaTransaction
|
||||
-> sendTransaction avec preflight obligatoire
|
||||
-> contrôle de la signature primaire retournée
|
||||
-> getSignatureStatuses borné
|
||||
-> getBlockHeight pour détecter l’expiration
|
||||
-> confirmed / finalized / failed / expired / timed_out
|
||||
```
|
||||
|
||||
`sendTransaction` signifie uniquement que le nœud a accepté la transaction signée pour relay. La confirmation reste une opération séparée. La politique borne le nombre de polls et leur intervalle, conserve le dernier slot et la dernière block height observée, puis termine explicitement sur succès, erreur runtime, expiration du recent blockhash ou timeout.
|
||||
|
||||
`requestAirdrop` et `getBalance` sont ajoutés comme primitives génériques de laboratoire. Le plafond d’airdrop Devnet appartient à la configuration et sera appliqué par l’orchestrateur du parcours réel ; la méthode RPC reste indépendante de Tauri et du wallet concret.
|
||||
|
||||
## Wallet temporaire persistant
|
||||
|
||||
`0.4.2-pre.003` introduit un signer de laboratoire dans `kb_wallet` :
|
||||
|
||||
```text
|
||||
wallets/temporary/<profile>/<alias>.json
|
||||
```
|
||||
|
||||
Il peut être généré en mémoire ou persisté afin de conserver la même adresse entre plusieurs démarrages, recevoir un airdrop devnet, créer des comptes et signer les transactions de validation. Le fichier utilise le format JSON Solana standard, reste exclu du dépôt et reçoit des permissions privées sur Unix.
|
||||
|
||||
Ce backend n'est pas un wallet de production : il n'est pas chiffré et les profils fournis l'interdisent sur mainnet. Les futurs backends chiffrés, coffre système et hardware wallet devront conserver la même frontière de signature afin que les exécuteurs ne changent pas.
|
||||
|
||||
## Garde-fous obligatoires
|
||||
|
||||
- dry-run activé par défaut ;
|
||||
- simulation RPC obligatoire avant envoi ;
|
||||
- cluster réel comparé au cluster attendu ;
|
||||
- contrôle du wallet source et des signataires requis ;
|
||||
- plafond de dépense, de frais et de compute-unit price ;
|
||||
- fraîcheur du blockhash ou état nonce durable complet, courant, initialisé et concordant ;
|
||||
- confirmation explicite pour tout envoi mainnet ;
|
||||
- journalisation séparée des plans et résultats ;
|
||||
- validation post-exécution par transaction canonique, extraction core, décodage et matérialisation.
|
||||
|
||||
## Exposition dans `kb_app_demo`
|
||||
|
||||
La démo exposera uniquement un sous-ensemble opérationnel sûr : transfert, création/allocate/assign contrôlés, Compute Budget et durable nonce après ajout d’un orchestrateur stateful validé sur cluster. Stake, Vote, loaders, changement d'autorité, Feature, Slashing et opérations ZK peuvent être disponibles dans les crates sans apparaître dans la fenêtre Tauri.
|
||||
|
||||
|
||||
## Orchestration Devnet et validation post-exécution
|
||||
|
||||
`0.4.2-pre.009` ajoute dans `kb_pipeline` une orchestration backend bornée pour le premier parcours System transfer sur Devnet. La fonction publique ne remplace aucune couche : elle appelle successivement les contrats existants et conserve leurs résultats séparés.
|
||||
|
||||
```text
|
||||
classification du genesis hash
|
||||
-> wallet temporaire persistant
|
||||
-> solde / airdrop plafonné
|
||||
-> PreparedExecutionPlan System transfer
|
||||
-> getLatestBlockhash
|
||||
-> getFeeForMessage
|
||||
-> simulateTransaction exact
|
||||
-> signature locale
|
||||
-> sendTransaction
|
||||
-> getSignatureStatuses + getBlockHeight
|
||||
-> getTransaction
|
||||
-> transaction canonique
|
||||
-> extraction core
|
||||
-> decode replay ciblé
|
||||
```
|
||||
|
||||
Le mode par défaut reste une simulation seule. Il ne signe pas, n’envoie pas et ne fabrique pas de signature vide. Le parcours soumis exige simultanément l’autorisation `submit`, la confirmation opérateur lorsque le profil l’impose, l’activation Devnet du wallet, un plafond de dépense et une simulation exacte réussie.
|
||||
|
||||
Le financement par faucet est une étape distincte, uniquement disponible sur Devnet et bornée par `devnet_airdrop_max_lamports`. Il est déclenché seulement lorsque le solde du wallet persistant ne couvre pas le transfert plus le plafond de frais. L’airdrop est lui-même confirmé avant de poursuivre.
|
||||
|
||||
`0.4.2-pre.010` ajoute une précondition liée au destinataire. Le mode metadata-only de `getAccountInfo` détermine si l’adresse existe déjà. Lorsqu’elle est absente, `getMinimumBalanceForRentExemption(0)` fournit le minimum nécessaire à la création implicite d’un compte System sans données ; un transfert inférieur est refusé avant simulation. Les échecs de simulation conservent désormais l’erreur runtime et un extrait borné des logs. La fenêtre `demo_execution_solana_core` ne réimplémente aucune de ces règles : elle sélectionne un profil Devnet, construit la requête et relaie les événements du pipeline.
|
||||
|
||||
Après une confirmation terminale, le pipeline hydrate exclusivement la signature envoyée. Une transaction on-chain échouée reste éligible à l’insertion canonique et au décodage comme intention échouée. Une expiration ou un timeout arrête la validation post-exécution sans prétendre que l’envoi a été confirmé.
|
||||
|
||||
Une erreur avant signature reste un `Err`. Dès qu’une signature locale existe, l’orchestrateur conserve cette signature et transforme les erreurs d’envoi, de confirmation ou de replay en diagnostics dans le résumé. Cette règle évite qu’un appelant perde la référence d’une transaction potentiellement diffusée.
|
||||
|
||||
L’orchestrateur est une API de bibliothèque et ne dépend pas de Tauri. La fenêtre `demo_execution_solana_core` expose uniquement une sélection Devnet réduite de ce backend ; les opérations administratives natives restent disponibles à terme dans les bibliothèques sans être nécessairement proposées dans l’interface.
|
||||
|
||||
## État de clôture `0.4.2`
|
||||
|
||||
Le parcours représentatif Devnet a validé la chaîne plan → simulation exacte → signature → envoi → confirmation → hydratation canonique → extraction core → decode replay. Les builders administratifs supplémentaires restent disponibles dans la bibliothèque, mais ne reçoivent aucune autorisation Mainnet implicite.
|
||||
|
||||
La règle de clôture est donc la suivante : complétude du wire et des plans offline, politique de sécurité et préflight stateful présents, puis preuve cluster obligatoire avant toute exposition mutable supplémentaire. Un statut `future` dans la matrice désigne cette preuve d’activation, pas une instruction manquante.
|
||||
Reference in New Issue
Block a user