anchorage_layer_simple/fixKnowledge/api-anchorage-insufficient-utxo.md
ncantu e34b6ee43a Fix UTXO selection and race condition in anchorage API
**Motivations:**
- Resolve insufficient UTXO amount errors when wallet has many small UTXOs
- Prevent race conditions when multiple anchor requests arrive simultaneously
- Improve signet dashboard functionality and documentation

**Root causes:**
- API tried to find a single UTXO large enough instead of combining multiple UTXOs
- No mutex mechanism to prevent concurrent transactions from using the same UTXOs
- UTXOs in mempool still appear as available in listunspent before block confirmation

**Correctifs:**
- Implement coin selection algorithm to combine multiple UTXOs when needed
- Add mutex-based locking mechanism to serialize UTXO access
- Filter locked UTXOs during selection to prevent double spending
- Properly handle change output when combining multiple UTXOs
- Lock UTXOs during transaction creation and unlock after mempool broadcast

**Evolutions:**
- Enhance signet dashboard with improved Bitcoin RPC integration
- Update mempool documentation
- Add comprehensive fix documentation in fixKnowledge/

**Pages affectées:**
- api-anchorage/src/bitcoin-rpc.js
- signet-dashboard/src/bitcoin-rpc.js
- signet-dashboard/src/server.js
- signet-dashboard/public/app.js
- signet-dashboard/public/index.html
- signet-dashboard/public/styles.css
- signet-dashboard/start.sh
- docs/MEMPOOL.md
- fixKnowledge/api-anchorage-insufficient-utxo.md (new)
- fixKnowledge/api-anchorage-utxo-race-condition.md (new)
- anchor_count.txt (new)
- mempool (submodule update)
2026-01-25 01:21:18 +01:00

213 lines
7.0 KiB
Markdown

# Correction : Erreur "Insufficient UTXO amount" sur l'API d'ancrage
**Auteur** : Équipe 4NK
**Date** : 2026-01-24
**Version** : 1.0
## Problème Identifié
L'API d'ancrage retournait une erreur "Insufficient UTXO amount. Required: 0.00006 BTC, Largest available: 0.00001 BTC" même lorsque le wallet avait suffisamment de fonds totaux.
### Symptômes
- Erreur : "Insufficient UTXO amount. Required: 0.00006 BTC, Largest available: 0.00001 BTC"
- Le wallet contient de nombreux UTXOs de 0.00001 BTC chacun
- Le solde total du wallet est suffisant, mais aucun UTXO individuel n'est assez grand
- L'API ne peut pas créer de transaction d'ancrage
## Cause Racine
L'API essayait de trouver un seul UTXO avec suffisamment de fonds pour couvrir le montant requis (0.00006 BTC = montant de sortie + frais estimés). Cependant, tous les UTXOs disponibles étaient de 0.00001 BTC chacun, ce qui est insuffisant individuellement.
**Problème technique** : L'algorithme de sélection d'UTXO ne combinait pas plusieurs UTXOs pour atteindre le montant requis. Il cherchait uniquement un UTXO unique assez grand.
## Correctifs Appliqués
### Modification de la sélection d'UTXOs dans `bitcoin-rpc.js`
**Fichier** : `api-anchorage/src/bitcoin-rpc.js`
**Avant** :
```javascript
// Sélectionner un UTXO avec suffisamment de fonds
const sortedUnspent = [...unspent].sort((a, b) => b.amount - a.amount);
const amount = 0.00001;
const estimatedFee = 0.00005;
const totalNeeded = amount + estimatedFee;
// Trouver un UTXO avec suffisamment de fonds
let utxo = sortedUnspent.find(u => u.amount >= totalNeeded);
if (!utxo) {
utxo = sortedUnspent[0];
if (utxo.amount < totalNeeded) {
throw new Error(`Insufficient UTXO amount...`);
}
}
const inputs = [{
txid: utxo.txid,
vout: utxo.vout,
}];
```
**Après** :
```javascript
// Sélectionner plusieurs UTXOs si nécessaire (coin selection)
const sortedUnspent = [...unspent].sort((a, b) => b.amount - a.amount);
const amount = 0.00001;
const estimatedFeePerInput = 0.000001;
const estimatedFeeBase = 0.00001;
// Sélectionner les UTXOs nécessaires pour couvrir le montant + frais
const selectedUtxos = [];
let totalSelected = 0;
let estimatedInputs = 1;
let totalNeeded = amount + estimatedFeeBase;
// Itérer jusqu'à trouver une combinaison qui fonctionne
for (let iteration = 0; iteration < 10; iteration++) {
totalNeeded = amount + estimatedFeeBase + (estimatedInputs * estimatedFeePerInput);
selectedUtxos.length = 0;
totalSelected = 0;
for (const utxo of sortedUnspent) {
if (totalSelected >= totalNeeded) break;
selectedUtxos.push(utxo);
totalSelected += utxo.amount;
}
if (totalSelected >= totalNeeded) break;
estimatedInputs = selectedUtxos.length + 1;
}
const inputs = selectedUtxos.map(utxo => ({
txid: utxo.txid,
vout: utxo.vout,
}));
```
**Impact** : L'API peut maintenant combiner plusieurs UTXOs pour créer une transaction, même si aucun UTXO individuel n'est assez grand.
### Gestion du change (monnaie restante)
**Ajout** : Calcul et gestion du change lorsque plusieurs UTXOs sont utilisés :
```javascript
// Calculer le change (monnaie restante après avoir payé le montant)
const estimatedFee = estimatedFeeBase + (selectedUtxos.length * estimatedFeePerInput);
const change = totalSelected - amount - estimatedFee;
const outputs = {
data: anchorData.toString('hex'), // OP_RETURN output
[address]: amount, // Montant minimal pour la transaction
};
// Si le change est significatif (> 0.000001 BTC), l'envoyer à une adresse de change
if (change > 0.000001) {
const changeAddress = await this.getNewAddress();
outputs[changeAddress] = change;
}
```
**Impact** : Le change est correctement géré et renvoyé au wallet au lieu d'être perdu.
## Modifications
### Fichiers Modifiés
- `api-anchorage/src/bitcoin-rpc.js` : Implémentation de la sélection multiple d'UTXOs (coin selection) et gestion du change
### Fichiers Créés
- `fixKnowledge/api-anchorage-insufficient-utxo.md` : Cette documentation
## Modalités de Déploiement
### Redémarrage de l'API
1. **Arrêter l'API** :
```bash
ps aux | grep "node.*api-anchorage" | grep -v grep | awk '{print $2}' | xargs kill
```
2. **Redémarrer l'API** :
```bash
cd /home/ncantu/Bureau/code/bitcoin/api-anchorage
npm start
```
### Vérification
1. **Tester l'ancrage** :
```bash
curl -X POST http://localhost:3010/api/anchor/document \
-H 'Content-Type: application/json' \
-H 'x-api-key: 770b9b33-8a15-4a6d-8f95-1cd2b36e7376' \
--data-raw '{"hash":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}'
```
2. **Vérifier les logs** :
```bash
tail -f /tmp/anchorage-api.log | grep -E "(Selected UTXOs|change)"
```
## Modalités d'Analyse
### Vérification que la correction fonctionne
1. **Vérifier que la transaction est créée** :
- La réponse doit contenir un `txid` valide
- Pas d'erreur "Insufficient UTXO amount"
2. **Vérifier les logs** :
- Les logs doivent afficher "Selected UTXOs for transaction" avec le nombre d'UTXOs sélectionnés
- Les logs doivent afficher le montant total sélectionné et le change calculé
3. **Vérifier la transaction sur la blockchain** :
```bash
bitcoin-cli getrawtransaction <txid> true
```
- La transaction doit avoir plusieurs inputs (un par UTXO sélectionné)
- La transaction doit avoir un output de change si le change est significatif
### Cas limites
1. **Pas assez de fonds totaux** :
- L'erreur doit indiquer le montant total disponible
- L'erreur doit indiquer le nombre d'UTXOs disponibles
2. **Beaucoup de petits UTXOs** :
- L'API doit combiner plusieurs UTXOs jusqu'à avoir suffisamment de fonds
- Les frais doivent être correctement estimés en fonction du nombre d'inputs
3. **Change très petit** :
- Si le change est < 0.000001 BTC, il sera inclus dans les frais (dust)
- Si le change est >= 0.000001 BTC, il sera renvoyé au wallet
## Résultat
✅ **Problème résolu**
- L'API peut maintenant combiner plusieurs UTXOs pour créer une transaction
- Les transactions d'ancrage fonctionnent même avec de nombreux petits UTXOs
- Le change est correctement géré et renvoyé au wallet
- Les frais sont correctement estimés en fonction du nombre d'inputs
**Exemple de transaction réussie** :
- Transaction ID : `edacb5000f2f0520072f277e06406b1287f1d38531e7810d33939e5d9cbd598b`
- Plusieurs UTXOs de 0.00001 BTC combinés pour atteindre le montant requis
## Prévention
Pour éviter ce problème à l'avenir :
1. **Utiliser un algorithme de coin selection** : Toujours combiner plusieurs UTXOs si nécessaire
2. **Estimer correctement les frais** : Prendre en compte le nombre d'inputs dans l'estimation des frais
3. **Gérer le change** : Toujours renvoyer le change au wallet au lieu de le perdre
4. **Tester avec différents scénarios** : Tester avec des wallets contenant de nombreux petits UTXOs
## Pages Affectées
- `api-anchorage/src/bitcoin-rpc.js` : Implémentation de la sélection multiple d'UTXOs et gestion du change
- `fixKnowledge/api-anchorage-insufficient-utxo.md` : Documentation (nouveau)