0.1.0
This commit is contained in:
112
docs/INSTRUCTION_REPLAY_CONTRACTS.md
Normal file
112
docs/INSTRUCTION_REPLAY_CONTRACTS.md
Normal file
@@ -0,0 +1,112 @@
|
||||
<!-- 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`.
|
||||
Reference in New Issue
Block a user