**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é
API d'Ancrage Bitcoin Signet
Auteur : Équipe 4NK Date : 2026-01-23 Version : 1.0
Description
API REST pour ancrer des documents sur la blockchain Bitcoin Signet. Cette API permet de créer des transactions Bitcoin qui incluent les hash de documents dans des outputs OP_RETURN, permettant ainsi de prouver l'existence d'un document à un moment donné.
Caractéristiques
- Port :
3010 - Domaine :
certificator.4nkweb.com(via nginx sur proxy 192.168.1.100) - Authentification : API Key via header
x-api-key - Format : JSON REST API
- Bitcoin : Connexion RPC au nœud Bitcoin Signet (port 38332)
- Mempool : Les transactions sont envoyées au mempool et retournées immédiatement (pas de callbacks)
Installation
Prérequis
- Node.js >= 18.0.0
- Accès au nœud Bitcoin Signet (RPC sur port 38332)
- Wallet Bitcoin avec des fonds pour créer des transactions
Installation des Dépendances
cd api-anchorage
npm install
Configuration
- Copier le fichier d'exemple :
cp .env.example .env
- Éditer
.env:
# Bitcoin RPC Configuration
BITCOIN_RPC_HOST=localhost
BITCOIN_RPC_PORT=38332
BITCOIN_RPC_USER=bitcoin
BITCOIN_RPC_PASSWORD=bitcoin
# API Configuration
API_PORT=3010
API_HOST=0.0.0.0
# API Keys (séparées par des virgules)
API_KEYS=your-api-key-here,another-api-key
# Logging
LOG_LEVEL=info
# Mining Configuration
MINING_ENABLED=true
MINING_FEE_RATE=0.00001
Important :
BITCOIN_RPC_HOST: Si l'API est dans un conteneur Docker, utiliser l'IP du conteneur Bitcoin ouhost.docker.internalAPI_KEYS: Définir au moins une clé API valide
Démarrage
Mode Développement
npm run dev
Mode Production
npm start
Avec PM2 (recommandé pour production)
pm2 start src/server.js --name anchor-api
pm2 save
pm2 startup
Endpoints
GET /health
Vérifie l'état de l'API et de la connexion Bitcoin.
Authentification : Non requise
Réponse :
{
"ok": true,
"service": "anchor-api",
"bitcoin": {
"connected": true,
"blocks": 152321,
"chain": "signet",
"networkactive": true,
"connections": 1
},
"timestamp": "2026-01-23T16:35:27.821Z"
}
POST /api/anchor/document
Ancre un document sur Bitcoin Signet. La transaction est créée et envoyée au mempool, puis retournée immédiatement.
Authentification : Requise (header x-api-key)
Body :
{
"documentUid": "doc-123456",
"hash": "a1b2c3d4e5f6..."
}
Note : La transaction est envoyée au mempool et retournée immédiatement. Aucun callback n'est supporté.
Réponse :
{
"txid": "56504e002d95301ebcfb4b30eaedc5d3fd9a448e121ffdce4f356b8d34169e85",
"status": "confirmed",
"confirmations": 0,
"block_height": 152321
}
Erreurs :
400 Bad Request: Hash invalide401 Unauthorized: Clé API invalide ou manquante402 Payment Required: Solde insuffisant500 Internal Server Error: Erreur serveur
POST /api/anchor/verify
Vérifie si un hash est ancré sur Bitcoin Signet.
Authentification : Requise (header x-api-key)
Body :
{
"hash": "a1b2c3d4e5f6...",
"txid": "56504e002d95301ebcfb4b30eaedc5d3fd9a448e121ffdce4f356b8d34169e85" // optionnel
}
Réponse (hash trouvé) :
{
"verified": true,
"anchor_info": {
"transaction_id": "56504e002d95301ebcfb4b30eaedc5d3fd9a448e121ffdce4f356b8d34169e85",
"block_height": 152321,
"confirmations": 0,
"current_block_height": 152321
}
}
Réponse (hash non trouvé) :
{
"verified": false,
"message": "Hash not found in recent blocks"
}
Utilisation
Exemple avec curl
# Health check
curl http://localhost:3010/health
# Ancrer un document
curl -X POST http://localhost:3010/api/anchor/document \
-H "Content-Type: application/json" \
-H "x-api-key: your-api-key-here" \
-d '{
"documentUid": "doc-123",
"hash": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890"
}'
# Vérifier un ancrage
curl -X POST http://localhost:3010/api/anchor/verify \
-H "Content-Type: application/json" \
-H "x-api-key: your-api-key-here" \
-d '{
"hash": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890"
}'
Exemple avec le client de test
# Configurer la clé API
export API_KEY=your-api-key-here
export API_URL=http://localhost:3010
# Exécuter le test
npm test
Configuration Nginx (sur proxy 192.168.1.100)
Ajouter dans la configuration nginx du proxy :
# API Anchor sur certificator.4nkweb.com
server {
listen 443 ssl http2;
server_name certificator.4nkweb.com;
ssl_certificate /etc/letsencrypt/live/certificator.4nkweb.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/certificator.4nkweb.com/privkey.pem;
location / {
proxy_pass http://192.168.1.103:3010;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
Note : Remplacer 192.168.1.103 par l'IP du serveur où l'API est déployée.
Architecture
Client
↓ HTTPS
Nginx (proxy 192.168.1.100:443)
↓ HTTP
API Anchor (port 3010)
↓ RPC
Bitcoin Signet Node (port 38332)
Sécurité
Clés API
- Les clés API sont définies dans
.env(variableAPI_KEYS) - Plusieurs clés peuvent être définies (séparées par des virgules)
- La clé doit être envoyée dans le header
x-api-key - Le endpoint
/healthne nécessite pas d'authentification
Recommandations
- Ne jamais commiter
.env: Le fichier.envcontient des secrets - Utiliser HTTPS : Via nginx avec certificats Let's Encrypt
- Restreindre RPCALLOWIP : Dans la configuration Bitcoin, limiter l'accès RPC
- Rotater les clés API : Changer régulièrement les clés API
- Monitoring : Surveiller les logs pour détecter les abus
Dépannage
L'API ne peut pas se connecter à Bitcoin
Vérifier :
# Vérifier que le nœud Bitcoin est accessible
curl -u bitcoin:bitcoin http://localhost:38332
# Vérifier les variables d'environnement
grep BITCOIN_RPC .env
Erreur "Insufficient balance"
Le wallet Bitcoin n'a pas assez de fonds pour créer des transactions.
Solution :
- Miner des blocs pour obtenir des récompenses
- Recevoir des fonds depuis un autre wallet
- Vérifier le solde :
bitcoin-cli getbalance
Erreur "Unauthorized"
La clé API est invalide ou manquante.
Solution :
- Vérifier que le header
x-api-keyest présent - Vérifier que la clé est dans
API_KEYSdu.env
Logs
Les logs sont affichés sur la console avec le format :
[2026-01-23T16:35:27.821Z] [INFO] API d'ancrage Bitcoin Signet démarrée {"host":"0.0.0.0","port":3010}
Niveaux de log :
error: Erreurs critiqueswarn: Avertissementsinfo: Informations généralesdebug: Détails de débogage
Contrôlé par la variable LOG_LEVEL dans .env.
Structure du Projet
api-anchorage/
├── src/
│ ├── server.js # Serveur Express principal
│ ├── bitcoin-rpc.js # Client Bitcoin RPC
│ ├── logger.js # Système de logging
│ └── routes/
│ ├── health.js # Route health check
│ └── anchor.js # Routes d'ancrage
├── package.json
├── .env.example
├── .env # Configuration (ne pas commiter)
├── README.md
└── src/test-client.js # Client de test
Développement
Tests Locaux
# Démarrer l'API
npm run dev
# Dans un autre terminal, tester
npm test
Format de Transaction
Les transactions d'ancrage utilisent un output OP_RETURN avec le format :
- Préfixe :
"ANCHOR:"(7 bytes) - Hash : Hash SHA256 du document (32 bytes)
Total : 39 bytes dans l'output OP_RETURN.
Dernière mise à jour : 2026-01-23