**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é
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-dashboardne 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
listunspentdepuis Bitcoin - Met à jour
is_spent_onchain = 1pour 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ésdata/sync-utxos-cron.sh: Script wrapper pour cronfeatures/synchronisation-automatique-utxos-depenses.md: Cette documentation
Modalités de Déploiement
Déploiement Automatique
-
Redémarrer signet-dashboard :
sudo systemctl restart signet-dashboard.service -
Vérifier le cron :
crontab -l | grep sync-utxos -
Tester le script manuellement :
cd /home/ncantu/Bureau/code/bitcoin node data/sync-utxos-spent-status.mjs
Vérification
-
Vérifier les logs de synchronisation :
tail -f /home/ncantu/Bureau/code/bitcoin/data/sync-utxos.log -
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
-
Vérifier la synchronisation automatique :
- Les logs de
signet-dashboarddoivent 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
- Les logs de
-
Vérifier le cron :
- Le script doit s'exécuter toutes les heures
- Les logs doivent être écrits dans
data/sync-utxos.log
-
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
-
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
-
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
- Synchronisation complète : Tous les UTXOs sont mis à jour, pas seulement ceux en mémoire
- Réduction mémoire : Utilisation de tables temporaires SQL au lieu de structures en mémoire
- Fiabilité : L'API d'ancrage ne sélectionne plus d'UTXOs déjà dépensés
- Automatisation : Synchronisation automatique via cron toutes les heures