Files
khadhroony-bot3/migration/khadhroony-bot2-reference/docs/INSTRUCTION_REPLAY_CONTRACTS.md
2026-07-23 16:37:12 +02:00

113 lines
4.9 KiB
Markdown

<!-- file: docs/INSTRUCTION_REPLAY_CONTRACTS.md -->
<!-- version: 4 -->
# Contrats de replay par instruction
Ce document complète le cadrage `0.2.1`. Il ne crée pas encore le schéma SQL complet, mais il verrouille l'idée suivante : le scheduling de replay doit cibler les instructions normalisées, tandis que le décodage doit recevoir une instruction avec son contexte Solana extrait.
## Motivation
Une transaction Solana peut contenir plusieurs instructions top-level et plusieurs inner instructions. Certaines instructions peuvent être déjà décodées, d'autres non. Rejouer toute la transaction à chaque correction de décodeur serait plus coûteux et moins précis.
Le pipeline doit donc pouvoir faire :
```text
raw transaction
→ extraction core transaction
→ extraction account keys, instructions, inner instructions, logs, balances
→ sélection des instructions non traitées
→ reconstruction d'un replay input contextualisé
→ decode/materialize uniquement sur ces inputs
```
## Scheduling instruction-level
L'état `CoreInstructionProcessingState` prépare cette granularité.
| État | Sens |
|-------------------|---------------------------------------------------------------|
| `Pending` | Instruction disponible pour premier traitement. |
| `Decoded` | Instruction décodée par au moins un décodeur. |
| `Materialized` | Instruction ayant produit une projection métier. |
| `Ignored` | Instruction ignorée volontairement par la politique courante. |
| `Failed` | Instruction en échec, à diagnostiquer. |
| `ReplayRequested` | Instruction à rejouer même si un traitement précédent existe. |
Les états ne remplacent pas le ledger par module/version. Ils servent de vue rapide et de filtre de scheduling.
## Décodage contextualisé
Le décodeur ne doit pas être limité à `CoreInstructionRow.payload_json`.
Certains protocoles Solana exigent de lire :
- les inner instructions ;
- les logs Anchor ou non Anchor ;
- les balances avant/après ;
- les comptes résolus ;
- les loaded addresses ;
- les erreurs de transaction ;
- des séquences de logs liées à un CPI ;
- des instructions voisines de la même transaction.
`CoreInstructionReplayInput` représente ce contrat de lecture : une instruction ciblée plus un contexte extrait depuis les tables `core`. Depuis le contrat `2`, ce contexte inclut également toutes les instructions outer de la signature, ordonnées numériquement et munies de leur payload retenu et de son hash.
## Sélection de replay
`CoreInstructionReplayFilter` permet de sélectionner les instructions par :
- état de traitement ;
- `program_id` ;
- plage de slots.
L'usage standard pour un worker de decode sera :
```text
processing_state = Pending ou ReplayRequested
program_id = programme ciblé par le décodeur
plage de slots = optionnelle
```
Le repository charge les logs, balances, account keys et instructions outer nécessaires pour retourner `CoreInstructionReplayInput`. La liste outer inclut la cible et utilise les champs stables `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Cette extension lit les tables existantes et ne demande aucune migration.
## Marquage de cycle de vie
`CoreInstructionLifecycleMark` permet à un module de changer l'état d'une instruction après traitement.
Exemples :
- un décodeur reconnu marque l'instruction `Decoded` ;
- un materializer complet marque l'instruction `Materialized` ;
- un décodeur non concerné peut marquer `Ignored` dans un contexte contrôlé ;
- une erreur de parsing marque `Failed` ;
- une correction de décodeur peut remettre `ReplayRequested`.
## Relation avec `kb_sol_ops_processing_ledger`
Le processing ledger garde le détail par module, version et input. L'état sur l'instruction reste le dernier état opérationnel visible.
Pour éviter les doublons, l'input key du ledger devra être stable, par exemple :
```text
signature:instruction_path:program_id:processor_name:processor_version
```
La forme exacte n'est pas figée en `0.2.1`, mais elle doit rester déterministe.
## Rétention du payload d'instruction et des logs
Le payload JSON d'une instruction et le texte des logs sont utiles au début. Plus tard, après décodage et matérialisation fiables, ils pourront être compactés ou purgés avec conservation d'un hash.
Les entities `CoreInstructionRow` et `CoreLogRow` préparent ce cas en autorisant :
- payload ou texte présent ;
- payload ou texte absent ;
- hash conservé ;
- état de traitement consultable pour replay.
La purge effective ne doit pas être implémentée avant que les diagnostics de replay soient fiables.
## Décision pour `0.2.1`
`0.2.1` ajoute les contrats Rust nécessaires, mais ne crée pas encore les tables SQL. Les migrations réelles restent prévues pour `0.2.3` et `0.2.4`.