This commit is contained in:
2026-07-23 16:37:12 +02:00
parent 99c345f2f2
commit 0da75c1311
2159 changed files with 230833 additions and 0 deletions

View File

@@ -0,0 +1,456 @@
<!-- file: docs/CORE_EXTRACTION_SELECTION_AND_REPLAY.md -->
<!-- version: 4 -->
# Sélection et replay de lextraction core
## Objet
Ce document décrit les modes disponibles dans `demo_core_extraction`, leur effet réel sur PostgreSQL et la différence entre :
- acquisition dune transaction depuis le réseau ;
- extraction du document canonique vers les tables core ;
- futur décodage protocolaire ;
- future matérialisation métier.
Dans `0.3.4`, le mot « replay » désigne uniquement le rejeu de létape suivante :
```text
kb_sol_raw_transactions.canonical_json
-> kb_model::CanonicalTransaction
-> CoreExtractionBundle
-> kb_sol_core_transactions
-> kb_sol_core_account_keys
-> kb_sol_core_instructions
-> kb_sol_core_inner_instructions
-> kb_sol_core_logs
-> kb_sol_core_balance_changes
-> kb_sol_ops_processing_ledger
```
Aucun appel RPC nest effectué par cette étape. Aucun décodeur Solana Core, SPL, DEX ou autre protocole nest exécuté. Aucune ligne métier nest matérialisée.
## Cycle complet dune transaction
Le cycle prévu est séparé en étapes rejouables :
```text
réseau RPC
-> acquisition HTTP ou WebSocket
-> transaction canonique raw
-> extraction structurelle core
-> observation et classification
-> décodage protocolaire
-> matérialisation métier
-> agrégations et stratégies
```
`0.3.4` couvre uniquement la transition `raw canonique -> core structurel`.
Les lignes de `kb_sol_core_instructions` sont créées avec `processing_state = pending`. Elles constituent lentrée des futurs décodeurs prévus à partir de `0.4.x`.
## Paramètres communs
### Transactions maximales
`limit` borne le nombre de transactions sélectionnées par PostgreSQL avant démarrage de la campagne.
La sélection est ordonnée par :
```text
slot ASC, signature ASC
```
Cette règle sapplique aussi au mode signatures explicites. Lordre des lignes collées dans la zone de texte nest donc pas lordre dexécution garanti.
### Concurrence
`max_concurrent_extractions` borne le nombre dextractions admises simultanément.
Chaque signature reste une unité transactionnelle indépendante. Une transaction Solana produit son graphe core dans une transaction PostgreSQL atomique.
### Force replay
Sans `force_replay`, une signature est ignorée lorsque le ledger contient déjà un succès ayant exactement :
```text
stage = core_extraction
processor_name = canonical_to_core
processor_version = version courante
input_key = signature
input_hash = canonical_json_hash courant
status = succeeded
```
Avec `force_replay`, ce skip est désactivé. Le graphe core existant de la signature est supprimé puis recréé dans la même transaction PostgreSQL. Les autres signatures ne sont pas touchées.
Le force replay ne relance pas `getTransaction` et ne remplace pas le document canonique raw. Il reconstruit uniquement le core depuis le raw déjà présent.
## Mode signatures explicites
### Entrée
La zone de texte accepte une signature par ligne.
Avant lappel au pipeline, linterface :
- supprime les espaces autour de chaque ligne ;
- ignore les lignes vides ;
- supprime les doublons en conservant la première occurrence ;
- valide chaque valeur comme signature Solana.
### Sélection PostgreSQL
Le mode sélectionne uniquement les signatures déjà présentes dans `kb_sol_raw_transactions`.
Une signature absente de la table raw nest pas téléchargée automatiquement. Elle napparaît simplement pas dans les candidats sélectionnés. Le compteur `selected` peut donc être inférieur au nombre de signatures saisies.
Aucun filtre de `processing_state` nest appliqué. Ce mode peut sélectionner une transaction raw :
- `received` ;
- `core_extracted` ;
- `failed`.
Le ledger décide ensuite entre skip, extraction ou retry.
### Usages principaux
- vérifier lidempotence sur un échantillon connu ;
- forcer la reconstruction de quelques signatures ;
- retenter explicitement des transactions raw en échec ;
- comparer deux versions de lextracteur ;
- préparer plus tard un corpus ciblé pour un décodeur.
### Point dattention
Si le nombre de signatures existantes dépasse `limit`, seules les premières selon `slot ASC, signature ASC` sont retenues.
## Mode transactions en attente
### Filtre réel
Le mode pending sélectionne :
```text
kb_sol_raw_transactions.processing_state = received
```
Il ne sélectionne ni les lignes déjà `core_extracted`, ni les lignes `failed`.
### Transition après succès
Après commit du graphe core :
```text
received -> core_extracted
```
La même ligne ne sera donc plus sélectionnée lors dune campagne pending suivante.
### Transition après échec
Après un échec dextraction persistable :
```text
received -> failed
```
La raison est stockée dans `lifecycle_reason` et le ledger reçoit un statut `failed`.
Une ligne `failed` doit être retentée par signature explicite ou par un futur mode dédié aux erreurs. Une nouvelle campagne pending ne la reprend pas.
### Usages principaux
- vider progressivement la file des transactions canoniques nouvellement acquises ;
- exécuter lextraction courante après un backfill HTTP ;
- traiter un lot borné sans sélectionner manuellement les signatures.
### Conséquence sur le corpus actuel
Après la campagne réelle de 70 transactions :
```text
selected = 70
extracted = 70
failed = 0
```
les 70 lignes raw sont normalement passées à `core_extracted`. Une nouvelle campagne pending doit donc sélectionner zéro transaction tant quaucune nouvelle transaction raw `received` na été acquise.
## Mode plage de slots
### Filtre réel
Le mode sélectionne toutes les transactions raw dont le slot se trouve dans lintervalle inclusif :
```text
min_slot <= slot <= max_slot
```
Aucun filtre de `processing_state` nest appliqué.
### Comportement normal
Les transactions déjà à jour sont sélectionnées puis comptées comme `skipped` par le ledger. Les transactions reçues, en échec, ou dont la version/hash a changé peuvent être extraites.
### Comportement avec force replay
Toutes les transactions sélectionnées sont reconstruites dans la limite configurée.
### Usages principaux
- rejouer un intervalle temporel connu ;
- vérifier une régression sur un bloc ou une période ;
- reconstruire un corpus après changement de version de lextracteur.
## Mode programme déjà indexé dans core
### Filtre réel actuel
Le mode sélectionne les signatures raw pour lesquelles il existe déjà une ligne correspondante dans :
```text
kb_sol_core_instructions
```
avec un `program_id` exactement égal à la valeur demandée.
La requête actuelle ne recherche pas dans :
- `kb_sol_core_inner_instructions` ;
- `kb_sol_core_logs` ;
- `kb_sol_core_account_keys` ;
- le document canonique raw.
### Conséquences
Ce mode ne peut pas découvrir un programme pour la première fois. Il fonctionne uniquement après une première extraction core ayant déjà résolu au moins une instruction top-level de ce programme.
Une transaction où le programme apparaît exclusivement en inner instruction nest pas sélectionnée par ce mode dans son état actuel.
### Usages principaux
- reconstruire les transactions dun programme déjà indexé après changement de version ;
- vérifier une correction de résolution des comptes ou instructions ;
- préparer un sous-corpus structurel avant le futur replay dun décodeur.
### Évolution recommandée
Le futur sélecteur de corpus devrait distinguer explicitement :
- programme top-level ;
- programme inner ;
- programme observé dans les logs ;
- union de toutes les occurrences core fiables.
Le mode dextraction actuel peut rester strictement basé sur les instructions top-level, à condition que cette limite demeure visible dans linterface.
## Interprétation des compteurs
| Compteur | Signification |
|-----------------------|-------------------------------------------------------------|
| `selected` | Candidats retournés par PostgreSQL après filtres et limite. |
| `started` | Candidats admis dans la file dexécution bornée. |
| `completed` | Candidats arrivés à un résultat terminal. |
| `skipped` | Ledger déjà à jour pour la même version et le même hash. |
| `extracted` | Graphe core écrit et commit réussi. |
| `failed` | Extraction ou persistance terminée en erreur. |
| `cancelledCandidates` | Candidats admis mais annulés avant résultat terminal. |
| `notStarted` | Candidats sélectionnés mais jamais admis après arrêt. |
| `cancelled` | Une demande darrêt coopératif a été observée. |
Pour une campagne terminée normalement :
```text
completed = skipped + extracted + failed
selected = completed + cancelledCandidates + notStarted
```
## Scénarios de validation recommandés
### Vérifier le skip
1. Extraire 5 à 10 signatures déjà présentes dans core depuis un outil de sélection.
2. Les coller dans le mode signatures explicites.
3. Laisser `force_replay` désactivé.
Résultat attendu :
```text
selected = N
skipped = N
extracted = 0
failed = 0
```
### Vérifier le force replay
1. Réutiliser exactement les mêmes signatures.
2. Activer `force_replay`.
Résultat attendu :
```text
selected = N
skipped = 0
extracted = N
failed = 0
```
Les cardinalités globales des tables core doivent rester stables pour ces signatures. Le `attempt_count` du ledger doit augmenter.
### Vérifier un changement de version ou de hash
Un changement réel de `processor_version` ou de `canonical_json_hash` doit provoquer une nouvelle extraction même sans `force_replay`.
Cette vérification doit être effectuée dans une base de test dédiée. Le hash canonique dune ligne de production ne doit pas être modifié manuellement.
### Vérifier le rollback
Le rollback atomique doit être validé par un test PostgreSQL avec injection dune erreur entre les insertions du graphe et le commit.
La méthode recommandée est un test dintégration sur `solana_test`, et non une corruption volontaire de la base principale.
## Sélecteur de corpus dans lapplication
La fenêtre read-only dédiée est :
```text
demo_sql_replay_candidates
```
Elle est accessible depuis le menu principal et depuis len-tête de `demo_core_extraction`. `demo_sql_diag` reste limité à la connexion, au profil actif, aux migrations et aux cardinalités.
Le sélecteur ne déclenche aucune acquisition RPC, extraction core, opération de décodage ou matérialisation. Il lit uniquement les tables PostgreSQL déjà alimentées.
## Tableau des transactions et signatures
Les filtres PostgreSQL disponibles sont :
- fragment de signature ;
- slot minimum et maximum inclusifs ;
- état raw `received`, `core_extracted`, `decoded`, `materialized` ou `failed` ;
- statut ledger `not_started`, `running`, `succeeded` ou `failed` ;
- program ID exact ;
- portée du programme : `any`, `outer`, `inner` ou `logs` ;
- entité exacte : `mint`, `owner` ou `account_key` ;
- limite ;
- ordre par slot croissant ou décroissant.
Chaque résultat affiche :
- signature et slot ;
- état raw et rétention ;
- présence de la transaction core et éventuel échec Solana ;
- dernier statut du ledger `core_extraction` ;
- version et nombre de tentatives ;
- nombres dinstructions et de programmes outer/inner ;
- date de dernière mise à jour raw.
Le filtre de programme inspecte les instructions outer, les inner instructions et les logs auxquels un `program_id` a pu être rattaché de manière prudente. Une occurrence dans les logs nest donc visible que lorsque le rattachement core a produit un `program_id` non nul.
## Tableau des programmes
Le tableau agrège :
```text
kb_sol_core_instructions.program_id
kb_sol_core_inner_instructions.program_id
kb_sol_core_logs.program_id
```
Pour chaque programme, il expose :
- le `program_id` ;
- le nombre de transactions distinctes ;
- le nombre dinstructions outer ;
- le nombre dinstructions inner ;
- le nombre de logs reliés ;
- le slot minimum et maximum.
La sélection dun programme peut alimenter le filtre programme du tableau des transactions, puis charger les signatures correspondantes.
## Tableau des entités
Le tableau agrège trois familles :
- `mint` depuis `kb_sol_core_balance_changes.mint` ;
- `owner` depuis `kb_sol_core_balance_changes.owner` ;
- `account_key` depuis `kb_sol_core_account_keys.account_key`.
Chaque ligne indique le nombre de transactions distinctes, le nombre doccurrences et la plage de slots. Une entité sélectionnée peut alimenter le filtre du tableau des transactions.
Les account keys ne sont pas présentées comme wallet, pool, mint ou token account sans classification supplémentaire.
## DataTables, copie et exports
La fenêtre utilise cinq tableaux DataTables avec intégration Bootstrap 5 et extension Select :
1. transactions et signatures ;
2. programmes ;
3. mints ;
4. owners ;
5. account keys.
Chaque tableau affiche 10 lignes par défaut. Une checkbox par ligne et une checkbox de header permettent de sélectionner le jeu filtré. Les filtres possèdent un bouton de reset qui restaure les valeurs par défaut, efface la recherche locale, désélectionne les lignes et recharge PostgreSQL.
Les signatures, program IDs, mints, owners et account keys sont tronqués visuellement sous la forme `préfixe…suffixe`. La valeur complète reste utilisée par le tri, la recherche, les tooltips, la copie et lexport. Un bouton de copie individuel évite les espaces parasites liés à une sélection manuelle.
La règle dexport est la suivante :
1. lorsquune ou plusieurs lignes sont sélectionnées, seules ces lignes sont exportées ;
2. sans sélection, toutes les lignes correspondant au filtre local DataTables sont exportées ;
3. la limite PostgreSQL reste la borne supérieure du corpus chargé.
Le frontend construit un CSV UTF-8 avec BOM, séparateur `;` et fins de ligne CRLF. Une commande Rust lécrit dans :
```text
data/exports_csv/
```
Le backend ajoute un suffixe numérique lorsque le nom existe déjà. Ce chemin a été validé sous Tauri/Linux et ne dépend pas du téléchargement HTML du WebView.
La copie multiligne des signatures est directement compatible avec la zone `Signatures explicites` de `demo_core_extraction`.
## Garanties et limites
- commandes Tauri read-only ;
- requêtes SQL statiques et paramétrées ;
- aucune zone permettant dexécuter du SQL libre ;
- limite obligatoire comprise entre `1` et `5 000` ;
- filtres exacts pour programme et entité afin déviter une sélection ambiguë ;
- recherche locale DataTables appliquée après le chargement serveur ;
- aucune découverte de transaction absente du raw ;
- aucun décodage de protocole ;
- aucun changement détat raw, core ou ledger.
Les futurs écrans de `0.4.x` pourront réutiliser le même principe pour les replays de décodeurs et de matérialiseurs.
## Utilisation du sélecteur SQL
`demo_sql_replay_candidates` aide à constituer des corpus sans requête manuelle dans pgAdmin ou DBeaver. Il reste séparé du worker : il lit les tables raw/core/ledger, puis produit des signatures ou des filtres réutilisables.
Dans longlet programmes, « Utiliser comme filtre transactions » prend exactement un programme coché. À défaut de sélection, une unique ligne restant après le filtre local est acceptée. Laction renseigne le program ID exact, choisit la portée `any`, ouvre longlet transactions et recharge la liste.
Le sélecteur des programmes connus est alimenté par `kb_program_ids`, mais la saisie libre reste disponible pour les programmes observés qui ne sont pas encore enregistrés.
Les exports CSV sont écrits dans `data/exports_csv/` par le backend Rust. Ils servent à laudit et à la conservation dun corpus ; pour rejouer immédiatement des signatures, la copie multiligne reste le chemin le plus direct.
Les notions de pool et de paire ne sont pas encore disponibles à ce stade structurel. Une account key core ne suffit pas à prouver quun compte représente un pool ou une paire. Cette navigation sera ajoutée après matérialisation de catalogues sémantiques par les décodeurs.
## Validation réelle de lidempotence
Un échantillon de 14 signatures a produit les résultats suivants :
```text
mode normal : extracted=0, skipped=14
force replay: extracted=14, skipped=0
mode normal : extracted=0, skipped=14
```
Le nombre de transactions core est resté à 70. Le ledger contient 70 lignes `succeeded` et 84 tentatives, soit les 70 tentatives initiales plus les 14 remplacements forcés. Les requêtes dintégrité nont détecté aucune anomalie.
## Politique future pour les transactions échouées
Les transactions on-chain échouées restent candidates au décodage. Elles conservent des informations sur les programmes appelés, les instructions exécutées avant lerreur, les logs, le compute consommé et la cause déchec.
Les décodeurs devront produire des observations marquées par le statut de la transaction. Les matérialiseurs ne devront pas convertir ces observations en mutations détat réussies, trades confirmés, changements de liquidité ou candles normales.