anchorage_layer_simple/features/synchronisation-automatique-utxos-depenses.md
ncantu 1d4b0d8f33 Pagination serveur, correction UTXO déjà dépensé et synchronisation automatique
**Motivations:**
- Réduire la consommation mémoire en paginant côté serveur au lieu de charger toutes les données
- Corriger les erreurs "Input not found or already spent" dans l'API d'ancrage
- Maintenir la synchronisation entre la base de données et l'état réel de Bitcoin
- Améliorer l'expérience utilisateur avec un suivi de progression pour la collecte de signatures

**Root causes:**
- Pagination effectuée côté client : le serveur retournait tous les UTXOs/hashes (68k+ UTXOs, 32k+ hashes) puis le frontend paginait en JavaScript
- Désynchronisation entre la DB et Bitcoin : UTXOs dépensés non mis à jour dans la base de données
- Détection d'erreur incomplète : ne couvrait pas tous les cas ("already spent", "input not found")
- Pas de vérification de disponibilité de l'UTXO juste avant utilisation dans une transaction

**Correctifs:**
- Implémentation de la pagination côté serveur pour `/api/utxo/list` et `/api/hash/list` avec paramètres `page` et `limit`
- Amélioration de la détection d'erreur pour inclure "already spent" et "input not found"
- Ajout d'une vérification de disponibilité de l'UTXO avant utilisation avec mécanisme de retry (max 3 tentatives)
- Mise à jour automatique de tous les UTXOs dépensés dans la base de données lors de chaque synchronisation
- Script de synchronisation périodique avec cron job toutes les heures
- Optimisation mémoire : utilisation de tables temporaires SQL au lieu de charger tous les UTXOs en mémoire

**Evolutions:**
- Pagination serveur avec métadonnées (total, totalPages, page, limit) pour les endpoints `/api/utxo/list` et `/api/hash/list`
- Adaptation du frontend pour utiliser la pagination serveur (compatibilité maintenue avec chargement jusqu'à 1000 éléments)
- Ajout de `onProgress` callback dans `runCollectLoop` pour notifier la progression de la collecte de signatures
- Nouvelle fonction `collectProgress` pour calculer la progression (satisfied vs required) pour les notifications/UI
- Refactoring de `hasEnoughSignatures` avec extraction de `pairsPerMemberFromSigs` pour réutilisabilité

**Pages affectées:**
- `api-anchorage/src/bitcoin-rpc.js` : Vérification disponibilité UTXO, amélioration détection erreur, paramètre retryCount
- `api-anchorage/src/routes/anchor.js` : Passage des nouveaux paramètres à createAnchorTransaction
- `signet-dashboard/src/server.js` : Pagination pour `/api/hash/list` et `/api/utxo/list`
- `signet-dashboard/src/bitcoin-rpc.js` : Mise à jour automatique de tous les UTXOs dépensés avec optimisation mémoire
- `signet-dashboard/public/hash-list.html` : Adaptation pour charger avec pagination serveur
- `signet-dashboard/public/utxo-list.html` : Adaptation pour utiliser la pagination serveur par catégorie
- `userwallet/src/utils/collectSignatures.ts` : Ajout interface CollectLoopOpts avec onProgress callback
- `userwallet/src/utils/loginValidation.ts` : Ajout fonction collectProgress, refactoring avec pairsPerMemberFromSigs
- `data/sync-utxos-spent-status.mjs` : Script de synchronisation périodique des UTXOs dépensés
- `data/sync-utxos-cron.sh` : Script wrapper pour cron job
- `features/pagination-serveur-base-donnees.md` : Documentation de la pagination serveur
- `features/synchronisation-automatique-utxos-depenses.md` : Documentation de la synchronisation automatique
- `fixKnowledge/api-anchorage-utxo-already-spent-error.md` : Documentation de la correction de l'erreur UTXO déjà dépensé
2026-01-27 22:21:38 +01:00

6.1 KiB

Synchronisation automatique des UTXOs dépensés

Auteur : Équipe 4NK Date : 2026-01-27 Version : 1.0

Objectif

Mettre à jour automatiquement tous les UTXOs dépensés dans la base de données pour maintenir la synchronisation avec l'état réel de Bitcoin, tout en réduisant l'usage mémoire.

Problème Identifié

Avant

  • signet-dashboard ne mettait à jour que les UTXOs chargés en mémoire lors d'une mise à jour
  • Les UTXOs dépensés n'étaient pas mis à jour dans la base de données s'ils n'étaient pas en mémoire
  • Désynchronisation entre la DB et l'état réel de Bitcoin
  • 442 UTXOs dépensés détectés lors de la première synchronisation

Impact

  • L'API d'ancrage sélectionnait des UTXOs déjà dépensés
  • Erreurs "Input not found or already spent" lors de la création de transactions
  • Dégradation de la fiabilité de l'API d'ancrage

Solutions Implémentées

1. Mise à jour automatique dans signet-dashboard

Fichier : signet-dashboard/src/bitcoin-rpc.js

Modification : Mise à jour de TOUS les UTXOs de la base de données lors de chaque synchronisation, pas seulement ceux en mémoire.

Optimisations mémoire :

  • Utilisation d'une table temporaire SQL au lieu de charger tous les UTXOs en mémoire
  • Traitement par batch de 1000 UTXOs pour réduire la consommation mémoire
  • Une seule requête SQL pour mettre à jour tous les UTXOs dépensés

Code :

// Créer une table temporaire pour stocker les UTXOs disponibles
db.exec(`
  CREATE TEMP TABLE IF NOT EXISTS temp_available_utxos (
    txid TEXT,
    vout INTEGER,
    PRIMARY KEY (txid, vout)
  )
`);

// Insérer les UTXOs disponibles par batch
const SYNC_BATCH_SIZE = 1000;
for (let i = 0; i < unspent.length; i += SYNC_BATCH_SIZE) {
  const batch = unspent.slice(i, i + SYNC_BATCH_SIZE);
  insertBatch(batch);
}

// Mettre à jour les UTXOs dépensés en une seule requête SQL
const updateSpentStmt = db.prepare(`
  UPDATE utxos
  SET is_spent_onchain = 1, updated_at = CURRENT_TIMESTAMP
  WHERE is_spent_onchain = 0
    AND (txid || ':' || vout) NOT IN (
      SELECT txid || ':' || vout FROM temp_available_utxos
    )
`);

2. Script de synchronisation périodique

Fichier : data/sync-utxos-spent-status.mjs

Fonctionnalités :

  • Vérifie tous les UTXOs marqués comme non dépensés dans la DB
  • Compare avec listunspent depuis Bitcoin
  • Met à jour is_spent_onchain = 1 pour ceux qui ne sont plus disponibles
  • Optimisé pour la mémoire : utilise une table temporaire SQL au lieu de charger tous les UTXOs en mémoire

Optimisations mémoire :

  • Ne charge pas tous les UTXOs de la DB en mémoire (compte seulement)
  • Utilise une table temporaire SQL pour les UTXOs disponibles
  • Traitement par batch de 1000 UTXOs

3. Cron job pour synchronisation automatique

Fichier : data/sync-utxos-cron.sh

Configuration : Exécution toutes les heures via cron

0 * * * * /home/ncantu/Bureau/code/bitcoin/data/sync-utxos-cron.sh

Fonctionnalités :

  • Exécute le script de synchronisation
  • Log les résultats dans data/sync-utxos.log
  • Garde seulement les 100 dernières lignes du log

Modifications

Fichiers Modifiés

  • signet-dashboard/src/bitcoin-rpc.js :
    • Ligne 1033-1101 : Mise à jour automatique de tous les UTXOs dépensés lors de chaque synchronisation
    • Utilisation d'une table temporaire SQL pour réduire la mémoire
    • Traitement par batch de 1000 UTXOs

Fichiers Créés

  • data/sync-utxos-spent-status.mjs : Script de synchronisation des UTXOs dépensés
  • data/sync-utxos-cron.sh : Script wrapper pour cron
  • features/synchronisation-automatique-utxos-depenses.md : Cette documentation

Modalités de Déploiement

Déploiement Automatique

  1. Redémarrer signet-dashboard :

    sudo systemctl restart signet-dashboard.service
    
  2. Vérifier le cron :

    crontab -l | grep sync-utxos
    
  3. Tester le script manuellement :

    cd /home/ncantu/Bureau/code/bitcoin
    node data/sync-utxos-spent-status.mjs
    

Vérification

  1. Vérifier les logs de synchronisation :

    tail -f /home/ncantu/Bureau/code/bitcoin/data/sync-utxos.log
    
  2. Vérifier les statistiques :

    cd /home/ncantu/Bureau/code/bitcoin/signet-dashboard
    node -e "const Database = require('better-sqlite3'); const db = new Database('../data/signet.db'); const stats = { total: db.prepare('SELECT COUNT(*) as count FROM utxos').get().count, spent: db.prepare('SELECT COUNT(*) as count FROM utxos WHERE is_spent_onchain = 1').get().count, notSpent: db.prepare('SELECT COUNT(*) as count FROM utxos WHERE is_spent_onchain = 0').get().count }; console.log('Total:', stats.total, 'Dépensés:', stats.spent, 'Non dépensés:', stats.notSpent); db.close();"
    

Modalités d'Analyse

Vérification que la correction fonctionne

  1. Vérifier la synchronisation automatique :

    • Les logs de signet-dashboard doivent afficher "UTXOs dépensés mis à jour dans la base de données" lors de chaque synchronisation
    • Le nombre d'UTXOs dépensés doit augmenter progressivement
  2. Vérifier le cron :

    • Le script doit s'exécuter toutes les heures
    • Les logs doivent être écrits dans data/sync-utxos.log
  3. Vérifier l'API d'ancrage :

    • Plus d'erreurs "Input not found or already spent"
    • Les UTXOs sélectionnés sont toujours disponibles

Optimisations Mémoire

  1. Avant :

    • Chargement de tous les UTXOs en mémoire (68k+ UTXOs)
    • Création d'un Set avec tous les UTXOs disponibles
    • Consommation mémoire élevée
  2. Après :

    • Utilisation d'une table temporaire SQL
    • Traitement par batch de 1000 UTXOs
    • Réduction significative de la consommation mémoire

Bénéfices

  1. Synchronisation complète : Tous les UTXOs sont mis à jour, pas seulement ceux en mémoire
  2. Réduction mémoire : Utilisation de tables temporaires SQL au lieu de structures en mémoire
  3. Fiabilité : L'API d'ancrage ne sélectionne plus d'UTXOs déjà dépensés
  4. Automatisation : Synchronisation automatique via cron toutes les heures