anchorage_layer_simple/scripts/diagnose-bloc-rewards.mjs
ncantu 0db7a76044 Fix: double déclaration const now, scripts .mjs, /api/utxo/count accepte ancrages
**Motivations:**
- Corriger erreur syntaxe double déclaration const now dans bitcoin-rpc.js
- Scripts batch en .mjs (ES modules) sans dépendance dotenv
- /api/utxo/count doit accepter catégorie ancrages (pluriel) du fichier

**Root causes:**
- const now déclaré deux fois dans même portée (lignes 294 et 299)
- Scripts utilisent dotenv non installé globalement
- /api/utxo/count cherchait seulement 'anchor' mais fichier utilise 'ancrages'

**Correctifs:**
- Supprimer deuxième déclaration const now (ligne 299)
- Scripts .mjs : parser .env manuellement sans dotenv
- /api/utxo/count : accepter 'anchor' OU 'ancrages'

**Evolutions:**
- Aucune

**Pages affectées:**
- signet-dashboard/src/bitcoin-rpc.js
- signet-dashboard/src/server.js
- scripts/complete-utxo-list-blocktime.mjs
- scripts/diagnose-bloc-rewards.mjs
2026-01-26 02:06:10 +01:00

171 lines
6.1 KiB
JavaScript
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Script de diagnostic pour comprendre pourquoi les Bloc Rewards affichent ~4700 BTC au lieu de 50 BTC
* Vérifie : listunspent, getrawtransaction, blockheight, subsidy
*/
import { readFileSync, existsSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Charger les variables d'environnement depuis .env si disponible
let envVars = {};
try {
const envPath = join(__dirname, '../signet-dashboard/.env');
if (existsSync(envPath)) {
const envContent = readFileSync(envPath, 'utf8');
for (const line of envContent.split('\n')) {
const match = line.match(/^([^#=]+)=(.*)$/);
if (match) {
envVars[match[1].trim()] = match[2].trim();
}
}
}
} catch (error) {
console.warn('Could not load .env file, using defaults');
}
const BITCOIN_RPC_URL = envVars.BITCOIN_RPC_URL || process.env.BITCOIN_RPC_URL || 'http://127.0.0.1:38332';
const BITCOIN_RPC_USER = envVars.BITCOIN_RPC_USER || process.env.BITCOIN_RPC_USER || 'bitcoin';
const BITCOIN_RPC_PASSWORD = envVars.BITCOIN_RPC_PASSWORD || process.env.BITCOIN_RPC_PASSWORD || 'bitcoin';
const BITCOIN_RPC_WALLET = envVars.BITCOIN_RPC_WALLET || process.env.BITCOIN_RPC_WALLET || 'custom_signet';
const auth = Buffer.from(`${BITCOIN_RPC_USER}:${BITCOIN_RPC_PASSWORD}`).toString('base64');
const rpcUrl = `${BITCOIN_RPC_URL}/wallet/${BITCOIN_RPC_WALLET}`;
async function rpcCall(method, params = []) {
try {
const response = await fetch(rpcUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${auth}`,
},
body: JSON.stringify({
jsonrpc: '1.0',
id: method,
method,
params,
}),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
if (result.error) {
throw new Error(`RPC error: ${result.error.message}`);
}
return result.result;
} catch (error) {
console.error(`Error calling ${method}:`, error.message);
return null;
}
}
async function diagnoseBlocRewards() {
console.log('🔍 Diagnostic Bloc Rewards - Pourquoi ~4700 BTC au lieu de 50 BTC?\n');
// 1. Lire les Bloc Rewards depuis utxo_list.txt
const utxoListPath = join(__dirname, '../utxo_list.txt');
if (!existsSync(utxoListPath)) {
console.error('❌ utxo_list.txt not found');
return;
}
const content = readFileSync(utxoListPath, 'utf8').trim();
const lines = content.split('\n');
const blocRewards = lines
.filter(line => line.trim().startsWith('bloc_rewards;'))
.slice(0, 5); // Prendre les 5 premiers
if (blocRewards.length === 0) {
console.log('⚠️ Aucun Bloc Reward trouvé dans utxo_list.txt');
return;
}
console.log(`📋 Analyse de ${blocRewards.length} Bloc Rewards depuis utxo_list.txt:\n`);
// 2. Vérifier blockchain info (hauteur actuelle)
console.log('1⃣ Informations blockchain:');
const blockchainInfo = await rpcCall('getblockchaininfo');
if (blockchainInfo) {
console.log(` Hauteur actuelle: ${blockchainInfo.blocks}`);
console.log(` Chain: ${blockchainInfo.chain}`);
console.log(` Subsidy attendu (blocs 0-209999): 50 BTC\n`);
}
// 3. Analyser chaque Bloc Reward
for (let i = 0; i < blocRewards.length; i++) {
const line = blocRewards[i];
const parts = line.split(';');
if (parts.length < 4) continue;
const txid = parts[1];
const amount = parseFloat(parts[3]);
const confirmations = parseInt(parts[4], 10) || 0;
console.log(`\n${i + 1}. Transaction: ${txid}`);
console.log(` Montant dans fichier: ${amount} BTC`);
// 4. Vérifier listunspent
const unspent = await rpcCall('listunspent', [1]);
if (unspent) {
const utxo = unspent.find(u => u.txid === txid && u.vout === 0);
if (utxo) {
console.log(` Montant listunspent: ${utxo.amount} BTC`);
console.log(` Confirmations listunspent: ${utxo.confirmations}`);
} else {
console.log(` ⚠️ UTXO non trouvé dans listunspent (peut être dépensé)`);
}
}
// 5. Vérifier getrawtransaction
const rawTx = await rpcCall('getrawtransaction', [txid, true]);
if (rawTx) {
console.log(` Blockheight: ${rawTx.blockheight || 'non confirmé'}`);
console.log(` Blocktime: ${rawTx.blocktime ? new Date(rawTx.blocktime * 1000).toISOString() : 'N/A'}`);
if (rawTx.vout && rawTx.vout.length > 0) {
const vout0 = rawTx.vout[0];
console.log(` Vout[0].value: ${vout0.value} BTC`);
console.log(` Vout[0].scriptPubKey.type: ${vout0.scriptPubKey?.type || 'N/A'}`);
// Vérifier si coinbase
if (rawTx.vin && rawTx.vin.length === 1 && rawTx.vin[0].coinbase) {
console.log(` ✅ Transaction coinbase détectée`);
console.log(` Coinbase: ${rawTx.vin[0].coinbase}`);
}
}
// 6. Calculer subsidy attendu
if (rawTx.blockheight !== null && rawTx.blockheight !== undefined) {
const height = rawTx.blockheight;
if (height < 210000) {
const expectedSubsidy = 50;
const fees = amount - expectedSubsidy;
console.log(` Subsidy attendu (hauteur ${height}): ${expectedSubsidy} BTC`);
console.log(` Frais calculés (montant - subsidy): ${fees.toFixed(8)} BTC`);
if (Math.abs(fees) > 1) {
console.log(` ⚠️ ÉCART IMPORTANT: ${fees.toFixed(2)} BTC de frais (anormal pour un bloc)`);
}
} else {
console.log(` ⚠️ Bloc après 210000, subsidy devrait être réduit`);
}
}
}
}
console.log('\n\n📝 Conclusion:');
console.log(' - Si montants listunspent/getrawtransaction = montants fichier → source correcte');
console.log(' - Si montants >> 50 BTC → signet custom avec subsidy différent ou bug nœud');
console.log(' - Vérifier chain params du signet (subsidy, halving)');
}
diagnoseBlocRewards().catch(console.error);