v0.1.0-pre.064-065

This commit is contained in:
2026-07-30 17:50:29 +02:00
parent e0028b323e
commit 0befb170c7
440 changed files with 36186 additions and 39 deletions

View File

@@ -0,0 +1,151 @@
<!-- file: kb_execution_solana/README.md -->
<!-- version: 4 -->
# kb_execution_solana
`kb_execution_solana` transforme un `PreparedExecutionPlan` commun en message et transaction Solana, puis résout les signataires via linterface Solana `Signer` et signe uniquement après une simulation autorisée par `kb_execution_safety`.
La crate est indépendante des exécuteurs concrets et des transports RPC. Elle assemble aussi bien les plans à recent blockhash que les transactions consommant réellement un durable nonce.
## API publique
| Export | Usage |
|----------------------------------------|-------------------------------------------------------------------------------------------------------|
| `build_legacy_transaction(...)` | Compile un plan `Latest` avec un recent blockhash explicite. |
| `build_durable_nonce_transaction(...)` | Compile un plan `DurableNonce` avec un état nonce validé et injecte lavance en première instruction. |
| `durable_nonce_account_data_length()` | Fournit la longueur exacte à demander au RPC pour un compte nonce. |
| `parse_durable_nonce_account(...)` | Valide et décode un snapshot complet de compte nonce System. |
| `DurableNonceAccountState` | État validé exposant compte, autorité, nonce/blockhash et coût par signature. |
| `UnsignedSolanaTransaction` | Message compilé non signé, destiné aux frais, à la simulation exacte et à la signature contrôlée. |
| `SolanaSimulationEvidence` | Simulation liée au hash et au blockhash/nonce exacts du message. |
| `SignedSolanaTransaction` | Transaction signée, vérifiable localement et sérialisable pour `sendTransaction`. |
### Méthodes des types
| Type | Méthodes publiques |
|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `DurableNonceAccountState` | `account()`, `authority()`, `blockhash()`, `lamports_per_signature()`. |
| `UnsignedSolanaTransaction` | `plan()`, `message_hash()`, `blockhash()`, `required_signer_pubkeys()`, `message_base64()`, `transaction_base64()`, `bind_simulation(...)`, `sign_after_simulation(...)`. |
| `SolanaSimulationEvidence` | `message_hash()`, `blockhash()`, `simulation()`. |
| `SignedSolanaTransaction` | `message_hash()`, `primary_signature()`, `signer_pubkeys()`, `wire_length()`, `transaction_base64()`, `verify_signatures()`. |
## Exemple de flux
```rust
let unsigned = kb_execution_solana::build_legacy_transaction(&plan, recent_blockhash)?;
let simulation = rpc_simulation.to_execution_result(
unsigned.message_hash(),
unsigned.blockhash(),
observed_cluster,
)?;
let evidence = unsigned.bind_simulation(simulation)?;
let signed = unsigned.sign_after_simulation(&evidence, signers.as_slice())?;
signed.verify_signatures()?;
```
Le transport RPC reste extérieur : cette crate ne récupère pas le blockhash, ne charge pas le compte nonce et nenvoie pas le payload signé.
## Assemblage à recent blockhash
### `build_legacy_transaction(plan, recent_blockhash)`
Construit une transaction legacy non signée à partir dun blockhash base58 obtenu par `getLatestBlockhash`.
La fonction vérifie :
- la politique `ExecutionBlockhashKind::Latest` ;
- les public keys et le blockhash ;
- la présence dau moins une instruction ;
- légalité exacte entre signataires déclarés et signataires compilés ;
- la limite wire Solana de 1 232 octets.
Un plan `DurableNonce` est refusé et doit utiliser le chemin dédié.
## Lecture et validation dun compte nonce
### `durable_nonce_account_data_length()`
Retourne la taille wire officielle dun compte nonce, actuellement 80 octets. Cette valeur doit être utilisée comme limite exacte dun appel `getAccountInfo` avec données complètes.
### `parse_durable_nonce_account(account, owner, executable, space, data)`
Décode létat officiel `solana_nonce::versions::Versions` avec `wincode::deserialize_exact` et produit un `DurableNonceAccountState` uniquement lorsque toutes les conditions suivantes sont satisfaites :
- adresse du compte valide ;
- owner égal au System Program ;
- compte non exécutable ;
- `space` et longueur décodée égaux à la taille officielle ;
- version `Current` ;
- état `Initialized` ;
- autorité et valeur nonce extraites sans approximation.
Les états `Legacy`, `Uninitialized`, tronqués, suffixés ou possédés par un autre programme sont refusés. `DurableNonceAccountState` expose uniquement ladresse, lautorité, la valeur nonce utilisée comme blockhash et le coût par signature stocké dans létat.
Le chargement réseau reste extérieur à cette crate. Le contrat RPC prévu est :
```rust
let config = kb_rpc::GetAccountInfoConfig::confirmed_with_data(
kb_execution_solana::durable_nonce_account_data_length(),
)?;
```
## Assemblage durable nonce
### `build_durable_nonce_transaction(plan, nonce_state)`
Construit une transaction non signée qui consomme létat nonce validé.
La fonction exige :
- une politique `ExecutionBlockhashKind::DurableNonce` sans âge de blockhash récent ;
- le même compte nonce dans la politique et dans létat validé ;
- la même autorité dans la politique et dans létat validé ;
- lautorité nonce dans `required_signers` ;
- au moins une instruction métier à exécuter après lavance nonce.
Lassemblage utilise `Message::new_with_nonce`, place linstruction officielle `AdvanceNonceAccount` en position zéro, puis remplace le champ `recent_blockhash` par la valeur nonce extraite de létat. Le plan dorigine nest pas muté : `UnsignedSolanaTransaction::plan()` expose un plan effectif cloné contenant linstruction injectée.
Après compilation, la crate vérifie :
- la reconnaissance de la transaction par `solana_transaction::uses_durable_nonce` ;
- légalité exacte entre signataires déclarés et signataires compilés ;
- la taille wire ;
- le hash du message et la valeur nonce effectivement compilée.
Les opérations de gestion du compte nonce elles-mêmes, telles que `initialize`, `authorize`, `withdraw` ou `upgrade`, restent des transactions ordinaires à recent blockhash. Elles ne passent pas par ce chemin.
## Simulation et signature
### `UnsignedSolanaTransaction`
Expose :
- le plan effectif ;
- le hash exact du message ;
- le recent blockhash ou la valeur nonce compilée ;
- lordre exact des signataires ;
- le message base64 pour `getFeeForMessage` ;
- la transaction non signée base64 pour `simulateTransaction` avec `sigVerify = false` et `replaceRecentBlockhash = false`.
### `bind_simulation(result)`
Lie le résultat typé de simulation au hash du message **et** au blockhash/nonce compilé. Une simulation utilisant un autre message, une autre source de blockhash ou un blockhash de remplacement ne peut pas autoriser la signature.
### `sign_after_simulation(evidence, signers)`
Réévalue `kb_execution_safety`, exige une décision `Allow`, résout exactement tous les signataires via `&dyn solana_signer::Signer`, signe puis vérifie que la transaction est complète.
Les signataires manquants, supplémentaires ou dupliqués sont refusés. La fonction ne contacte aucun endpoint RPC et nenvoie rien.
### `SignedSolanaTransaction`
Expose uniquement des données non secrètes :
- hash du message ;
- signature primaire ;
- public keys des signataires ;
- taille wire ;
- payload base64 signé ;
- vérification locale des signatures.
Le payload signé reste côté backend. Il ne doit pas être transféré automatiquement à Tauri. `kb_rpc::HttpClient::send_transaction` et sa variante pool imposent le preflight et refusent une signature RPC différente de la signature primaire locale.