**Motivations:** - Ajouter dates manquantes dans hash_list.txt et compléter historique - Compléter blockTime manquants dans utxo_list.txt et compléter historique - Récupérer frais depuis transactions d'ancrage (OP_RETURN) et les stocker - Bouton UI pour déclencher récupération frais - Diagnostic Bloc Rewards (pourquoi ~4700 BTC au lieu de 50 BTC) **Root causes:** - hash_list.txt sans date (format ancien) - utxo_list.txt blockTime souvent vide - Frais absents du fichier (métadonnées OP_RETURN non stockées) - Pas de moyen de récupérer/compléter frais depuis UI **Correctifs:** - hash_list.txt : format étendu avec date (rétrocompatible) - utxo_list.txt : blockTime complété automatiquement lors écritures - fees_list.txt : nouveau fichier pour stocker frais - updateFeesFromAnchors() : récupère frais depuis OP_RETURN ancrages - Endpoint /api/utxo/fees/update pour déclencher récupération - Bouton "Récupérer les frais depuis les ancrages" dans section Frais (spinner) - Scripts batch : complete-hash-list-dates.js, complete-utxo-list-blocktime.js - Script diagnostic : diagnose-bloc-rewards.js (subsidy, coinbase, listunspent) **Evolutions:** - Frais chargés depuis fees_list.txt dans getUtxoList - Complétion automatique dates/blockTime lors écritures futures **Pages affectées:** - signet-dashboard/src/bitcoin-rpc.js - signet-dashboard/src/server.js - signet-dashboard/public/utxo-list.html - scripts/complete-hash-list-dates.js - scripts/complete-utxo-list-blocktime.js - scripts/diagnose-bloc-rewards.js - features/utxo-list-fees-update-and-historical-completion.md
13 KiB
Correction : Erreur lors de la génération du hash pour un document
Auteur : Équipe 4NK Date : 2026-01-24 Version : 1.0
Problème Identifié
Erreur lors de la génération d'un hash pour un document dans le dashboard signet.
Symptômes
- Erreur lors de la génération du hash pour les fichiers binaires (PDF, images, etc.)
- Le hash généré était incorrect pour les fichiers binaires
- Pas de message d'erreur clair lorsque la lecture du fichier échouait
- Les fichiers texte fonctionnaient correctement
Cause Racine
Root cause : La fonction generateHashFromFile() utilisait FileReader.readAsText() qui convertit le fichier en texte UTF-8. Cette méthode échoue pour les fichiers binaires car :
- Fichiers binaires non valides en UTF-8 : Les fichiers binaires (PDF, images, etc.) contiennent des bytes qui ne sont pas valides en UTF-8, ce qui cause des erreurs lors de la conversion
- Hash incorrect : Même si la conversion réussissait partiellement, le hash calculé était basé sur la représentation texte corrompue du fichier, pas sur les bytes bruts, ce qui produisait un hash incorrect
- Backend traite comme UTF-8 : Le backend utilisait
crypto.createHash('sha256').update(content, 'utf8')qui suppose que le contenu est en UTF-8, ce qui est incorrect pour les fichiers binaires - Pas de gestion d'erreur : Il n'y avait pas de gestion d'erreur pour
reader.onerror, donc les erreurs de lecture n'étaient pas capturées et affichées à l'utilisateur
Problème technique : Le code ne distinguait pas les fichiers texte des fichiers binaires et utilisait une méthode de lecture inadaptée pour les fichiers binaires.
Correctifs Appliqués
1. Modification de generateHashFromFile() pour utiliser readAsArrayBuffer()
Fichier : signet-dashboard/public/app.js
Avant :
const reader = new FileReader();
reader.onload = async (e) => {
const fileContent = e.target.result;
// ...
body: JSON.stringify({ fileContent }),
};
reader.readAsText(selectedFile);
Après :
const reader = new FileReader();
await new Promise((resolve, reject) => {
reader.onload = async (e) => {
try {
const arrayBuffer = e.target.result;
// Convertir l'ArrayBuffer en base64 pour l'envoi au backend
// Utiliser une boucle pour éviter les limites de taille des arguments de fonction
const uint8Array = new Uint8Array(arrayBuffer);
let binaryString = '';
for (let i = 0; i < uint8Array.length; i++) {
binaryString += String.fromCharCode(uint8Array[i]);
}
const base64 = btoa(binaryString);
// ...
body: JSON.stringify({ fileContent: base64, isBase64: true }),
} catch (error) {
showResult('anchor-result', 'error', `Erreur : ${error.message}`);
reject(error);
}
};
reader.onerror = (error) => {
showResult('anchor-result', 'error', `Erreur lors de la lecture du fichier : ${error.message || 'Erreur inconnue'}`);
reject(error);
};
reader.readAsArrayBuffer(selectedFile);
});
Impact :
- Les fichiers binaires sont maintenant lus correctement comme ArrayBuffer
- Le contenu est converti en base64 pour l'envoi au backend
- Gestion d'erreur complète avec
reader.onerror - Utilisation d'une boucle pour la conversion base64 pour éviter les limites de taille des arguments de fonction pour les gros fichiers
- Meilleure gestion des erreurs HTTP avec affichage des messages d'erreur du backend
2. Modification du backend pour accepter les fichiers binaires en base64
Fichier : signet-dashboard/src/server.js
Avant :
app.post('/api/hash/generate', (req, res) => {
try {
const { text, fileContent } = req.body;
if (!text && !fileContent) {
return res.status(400).json({ error: 'text or fileContent is required' });
}
const content = text || fileContent;
const hash = crypto.createHash('sha256').update(content, 'utf8').digest('hex');
res.json({ hash });
} catch (error) {
logger.error('Error generating hash', { error: error.message });
res.status(500).json({ error: error.message });
}
});
Après :
app.post('/api/hash/generate', (req, res) => {
try {
const { text, fileContent, isBase64 } = req.body;
if (!text && !fileContent) {
return res.status(400).json({ error: 'text or fileContent is required' });
}
let hash;
if (text) {
// Pour le texte, utiliser UTF-8
hash = crypto.createHash('sha256').update(text, 'utf8').digest('hex');
} else if (fileContent) {
if (isBase64) {
// Pour les fichiers binaires, décoder le base64 et calculer le hash sur les bytes bruts
const buffer = Buffer.from(fileContent, 'base64');
hash = crypto.createHash('sha256').update(buffer).digest('hex');
} else {
// Fallback pour compatibilité : traiter comme UTF-8 (pour fichiers texte)
hash = crypto.createHash('sha256').update(fileContent, 'utf8').digest('hex');
}
} else {
return res.status(400).json({ error: 'text or fileContent is required' });
}
res.json({ hash });
} catch (error) {
logger.error('Error generating hash', { error: error.message, stack: error.stack });
res.status(500).json({ error: error.message });
}
});
Impact :
- Le backend distingue maintenant les fichiers texte (UTF-8) des fichiers binaires (base64)
- Le hash est calculé sur les bytes bruts pour les fichiers binaires, garantissant un hash correct
- Compatibilité maintenue avec l'ancien format (fichiers texte sans
isBase64) - Meilleure journalisation des erreurs avec la stack trace
- Gestion d'erreur robuste pour le décodage base64 avec messages d'erreur clairs
- Validation des paramètres pour éviter les erreurs silencieuses
3. Augmentation de la limite de taille du body JSON
Fichier : signet-dashboard/src/server.js
Avant :
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
Après :
// Augmenter la limite de taille pour le body JSON (100MB) pour supporter les gros fichiers en base64
app.use(express.json({ limit: '100mb' }));
app.use(express.urlencoded({ extended: true, limit: '100mb' }));
Impact :
- Support des gros fichiers (jusqu'à ~75MB en binaire, ~100MB en base64)
- Évite les erreurs "payload too large" pour les fichiers volumineux
4. Ajout d'un middleware pour gérer les erreurs de parsing JSON
Fichier : signet-dashboard/src/server.js
Ajout :
// Middleware pour gérer les erreurs de parsing JSON
app.use((err, req, res, next) => {
if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
logger.error('JSON parsing error', {
error: err.message,
path: req.path,
method: req.method
});
return res.status(400).json({
error: 'Invalid JSON',
message: err.message
});
}
next(err);
});
Impact :
- Capture les erreurs de parsing JSON avant qu'elles n'atteignent les routes
- Retourne des messages d'erreur clairs pour les requêtes JSON mal formées
- Améliore la journalisation des erreurs de parsing
Modifications
Fichiers Modifiés
-
signet-dashboard/public/app.js:- Modification de
generateHashFromFile()pour utiliserreadAsArrayBuffer()au lieu dereadAsText() - Ajout de la gestion d'erreur
reader.onerror - Conversion en base64 avec une boucle pour supporter les gros fichiers
- Amélioration de la gestion des erreurs HTTP avec affichage des messages d'erreur du backend
- Modification de
-
signet-dashboard/src/server.js:- Modification de la route
/api/hash/generatepour accepterisBase64(lignes 472-530) - Calcul du hash sur les bytes bruts pour les fichiers binaires
- Distinction entre fichiers texte (UTF-8) et fichiers binaires (base64)
- Amélioration de la journalisation des erreurs
- Gestion d'erreur robuste pour le décodage base64
- Validation des paramètres d'entrée
- Augmentation de la limite de taille du body JSON à 100MB (lignes 132-134)
- Ajout d'un middleware pour gérer les erreurs de parsing JSON (lignes 144-156)
- Modification de la route
Fichiers Créés
fixKnowledge/dashboard-hash-generation-error.md: Cette documentation
Modalités de Déploiement
Déploiement des Modifications
-
Vérifier que le dashboard est en cours d'exécution :
curl http://localhost:3020/api/blockchain/info -
Redémarrer le dashboard :
# Si démarré avec npm start # Arrêter avec Ctrl+C puis redémarrer cd /home/ncantu/Bureau/code/bitcoin/signet-dashboard npm start # Si démarré avec systemd sudo systemctl restart signet-dashboard -
Vérifier que le dashboard fonctionne :
curl http://localhost:3020/
Tests de Validation
-
Test avec un fichier texte :
- Créer un fichier texte simple
- Générer le hash via l'interface
- Vérifier que le hash est généré correctement
-
Test avec un fichier binaire (PDF) :
- Sélectionner un fichier PDF
- Générer le hash via l'interface
- Vérifier que le hash est généré correctement (pas d'erreur)
-
Test avec un fichier binaire (image) :
- Sélectionner une image (PNG, JPG, etc.)
- Générer le hash via l'interface
- Vérifier que le hash est généré correctement
-
Test avec un gros fichier :
- Sélectionner un fichier de plusieurs Mo
- Générer le hash via l'interface
- Vérifier que le hash est généré correctement (pas d'erreur de mémoire)
Modalités d'Analyse
Vérification que la génération de hash fonctionne
-
Test de l'API directement :
# Test avec du texte curl -X POST http://localhost:3020/api/hash/generate \ -H "Content-Type: application/json" \ -d '{"text": "Hello World"}' # Test avec un fichier binaire (base64) # Générer le base64 d'un fichier base64 -i test.pdf > test.pdf.base64 # Envoyer au backend curl -X POST http://localhost:3020/api/hash/generate \ -H "Content-Type: application/json" \ -d "{\"fileContent\": \"$(cat test.pdf.base64)\", \"isBase64\": true}" -
Vérifier les logs :
# Si démarré avec npm start tail -f /tmp/dashboard.log # Si démarré avec systemd sudo journalctl -u signet-dashboard -f -
Test dans le navigateur :
- Ouvrir
https://dashboard.certificator.4nkweb.com/ - Aller dans l'onglet "Ancrage"
- Sélectionner un fichier PDF
- Cliquer sur "Générer le Hash"
- Vérifier que le hash est généré sans erreur
- Ouvrir
Diagnostic des Erreurs
-
Erreur "Erreur lors de la lecture du fichier" :
- Vérifier que le fichier est valide
- Vérifier les logs du navigateur (Console JavaScript)
- Vérifier les logs du backend
-
Erreur "Erreur lors de la génération du hash" :
- Vérifier les logs du backend pour voir l'erreur exacte
- Vérifier que le backend reçoit bien
isBase64: truepour les fichiers binaires - Vérifier que le base64 est valide
-
Hash incorrect :
- Vérifier que le hash est calculé sur les bytes bruts (pas sur UTF-8)
- Comparer avec un hash calculé localement :
sha256sum fichier.pdf
Résultat
✅ Problème résolu
- Les fichiers binaires (PDF, images, etc.) peuvent maintenant être hashés correctement
- Le hash est calculé sur les bytes bruts, garantissant un hash correct et reproductible
- Les erreurs sont maintenant capturées et affichées clairement à l'utilisateur
- Les gros fichiers sont supportés grâce à la conversion base64 par boucle et l'augmentation de la limite de taille du body
- Compatibilité maintenue avec les fichiers texte
- L'erreur 500 (Internal Server Error) est maintenant corrigée avec une gestion d'erreur robuste
- Les erreurs de parsing JSON sont maintenant gérées correctement avec des messages d'erreur clairs
- Validation des paramètres pour éviter les erreurs silencieuses
Prévention
Pour éviter ce problème à l'avenir :
- Toujours utiliser
readAsArrayBuffer()pour les fichiers binaires : Ne jamais utiliserreadAsText()pour les fichiers binaires - Distinguer les fichiers texte des fichiers binaires : Utiliser un flag (
isBase64) pour indiquer le type de contenu - Calculer le hash sur les bytes bruts : Ne jamais calculer le hash sur une représentation texte d'un fichier binaire
- Gérer les erreurs de FileReader : Toujours implémenter
reader.onerrorpour capturer les erreurs de lecture - Utiliser des boucles pour les conversions base64 : Éviter
String.fromCharCode(...array)qui peut échouer pour les gros fichiers
Pages Affectées
signet-dashboard/public/app.js: Modification degenerateHashFromFile()(lignes 534-590)signet-dashboard/src/server.js: Modification de la route/api/hash/generate(lignes 472-502)fixKnowledge/dashboard-hash-generation-error.md: Documentation (nouveau)