**Motivations:** - Permettre l'ancrage même si les fonds sont insuffisants pour le provisioning complet - Réduire automatiquement le provisioning si nécessaire au lieu d'échouer - Garantir qu'un ancrage minimal peut toujours être créé si les fonds sont suffisants **Root causes:** - Le système échouait si les fonds étaient insuffisants pour le provisioning complet (7 UTXOs) - Aucune logique de fallback pour réduire le provisioning ou permettre un ancrage minimal - Les utilisateurs devaient manuellement réduire le provisioning ou obtenir plus de fonds **Correctifs:** - Ajout d'une logique de réduction automatique du provisioning si les fonds sont insuffisants - Réduction progressive : 7 → 6 → 5 → 4 → 3 → 2 → 1 → 0 UTXOs de provisioning - En dernier recours, permet un ancrage sans provisioning (juste l'ancrage du hash) - Récursion avec provisioning réduit si l'essai initial échoue **Evolutions:** - Le système essaie maintenant automatiquement avec un provisioning réduit si nécessaire - L'ancrage est toujours créé si les fonds sont suffisants pour au moins l'ancrage minimal - Les logs indiquent quand le provisioning est réduit automatiquement **Pages affectées:** - api-anchorage/src/bitcoin-rpc.js - fixKnowledge/api-anchorage-utxo-robustness-improvements.md
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...",
"skipIfExists": false
}
Paramètres :
documentUid: string (optionnel, identifiant du document)hash: string (requis, hash SHA256 du document en hex, 64 caractères)skipIfExists: boolean (optionnel, par défautfalse, sitrue, ne réancrera pas un hash déjà ancré et retournera les informations existantes)
Note : La transaction est envoyée au mempool et retournée immédiatement. Aucun callback n'est supporté.
Réponse (nouvel ancrage) :
{
"ok": true,
"txid": "56504e002d95301ebcfb4b30eaedc5d3fd9a448e121ffdce4f356b8d34169e85",
"status": "confirmed",
"confirmations": 0,
"block_height": 152321,
"outputs": [...],
"fee": 0.00001,
"fee_sats": 1000,
"old": false
}
Réponse (hash déjà ancré avec skipIfExists: true) :
{
"ok": true,
"txid": "56504e002d95301ebcfb4b30eaedc5d3fd9a448e121ffdce4f356b8d34169e85",
"status": "confirmed",
"confirmations": 5,
"block_height": 152316,
"old": true
}
Champs de réponse :
ok: boolean, toujourstrueen cas de succèstxid: string, ID de la transaction Bitcoinstatus: string, statut de la transaction ("confirmed"ou"pending")confirmations: number, nombre de confirmationsblock_height: number|null, hauteur du bloc (null si pas encore dans un bloc)outputs: array, liste des outputs de la transaction (uniquement pour nouveaux ancrages)fee: number|null, frais de transaction en BTC (uniquement pour nouveaux ancrages)fee_sats: number|null, frais de transaction en sats (uniquement pour nouveaux ancrages)old: boolean,truesi le hash était déjà ancré,falsesi c'est un nouvel ancrage
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"
}'
# Ancrer un document sans réancrer si déjà ancré
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",
"skipIfExists": true
}'
# 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