**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
4.8 KiB
4.8 KiB
Correctifs UserWallet et API Relay
Auteur: Équipe 4NK
Date: 2026-01-26
Motivations
- Corriger la condition de relais dans POST /messages (api-relay) : les messages n’étaient jamais relayés.
- Supprimer la duplication du type
MessageBasedans SyncService et utiliser les types partagés. - Supprimer les fallbacks (retour de
[]oufalseen erreur) dans relay.ts et remonter les erreurs. - Implémenter une vraie dérivation clé publique depuis la clé privée à l’import d’identité, et documenter la limite (pas de mnemonic/seed).
Root causes
- Relais : On appelait
storage.storeMessage()puisif (!storage.hasSeenHash())pour relayer. OrstoreMessagemarque le hash comme vu, donc la condition était toujours fausse et le relais jamais exécuté. - MessageBase : SyncService définissait une interface locale
MessageBaseavechash?: string, alors que le code utilisaitmsg.hash.hash_value(typeHash). Incohérence de typage et duplication. - relay.ts : Les GET renvoyaient
[]et les POSTfalseen cas d’erreur, ce qui masquait les échecs (fallback interdit). - importIdentity : On générait une nouvelle paire, puis on écrasait
privateKeypar la seed fournie tout en gardant lapublicKeyde la paire générée. Aucune dérivation depuis la clé importée.
Correctifs
1. api-relay – POST /messages (relay condition)
Fichier: api-relay/src/routes/messages.ts
- Calculer
alreadySeen = storage.hasSeenHash(msg.hash)avantstorage.storeMessage(stored). - Appeler
storage.storeMessage(stored). - Relayer seulement si
!alreadySeen:await relay.relayMessage(msg)etstored.relayed = true.
2. userwallet – SyncService MessageBase
Fichier: userwallet/src/services/syncService.ts
- Importer
MessageBasedepuis../types/message. - Supprimer l’interface locale
MessageBaseen fin de fichier. - Utiliser le type partagé pour
validateMessageetupdateGraph.
3. userwallet – relay.ts (remonter les erreurs)
Fichier: userwallet/src/utils/relay.ts
- GET (
getMessagesChiffres,getSignatures,getKeys) : ne plus retourner[]en erreur ;throw new Error(...)en cas de!response.okou d’échec fetch, avec message incluant statut et URL du relais. - POST (
postMessageChiffre,postSignature,postKey) : ne plus retournerfalse;throw new Error(...)en cas d’échec. Types de retour passés àPromise<void>.
Fichier: userwallet/src/components/LoginScreen.tsx
- Adapter la boucle de publication :
await postMessageChiffre/await postSignaturesans vérifier de booléen ; en cas de throw, lecatchexistant pousse{ relay, success: false }et on continue.
4. userwallet – importIdentity (dérivation + limite)
Fichiers: userwallet/src/utils/crypto.ts, userwallet/src/utils/identity.ts
- crypto.ts : Ajouter
publicKeyFromPrivateKey(privateKeyHex: string): stringqui dérive la clé publique secp256k1 (compressée, hex) depuis la clé privée hex. - identity.ts :
- Valider que l’entrée est 64 caractères hexadécimaux (32 octets), après trim et suppression d’un préfixe
0xéventuel. - Utiliser
publicKeyFromPrivateKey(raw)pour la clé publique. - Stocker
rawcommeprivateKeyet la clé dérivée commepublicKey. - Documenter en JSDoc : seul l’import d’une clé privée hex brute est supporté ; mnemonic (BIP39) et dérivation depuis seed ne sont pas implémentés.
- Valider que l’entrée est 64 caractères hexadécimaux (32 octets), après trim et suppression d’un préfixe
Évolutions
- Aucune évolution fonctionnelle au-delà des correctifs ci‑dessus.
Pages affectées
api-relay/src/routes/messages.tsuserwallet/src/services/syncService.tsuserwallet/src/utils/relay.tsuserwallet/src/utils/crypto.tsuserwallet/src/utils/identity.tsuserwallet/src/components/LoginScreen.tsx
Modalités de déploiement
- api-relay : Redémarrer le serveur après déploiement.
- userwallet : Rebuild du frontend et déploiement des assets. Les appelants de
relay.ts(SyncService, LoginScreen) gèrent déjà les erreurs (try/catch) ; les throws sont remontés jusqu’à eux.
Modalités d’analyse
- Relais : Poster un message sur un relais avec pairs configurés ; vérifier qu’il est bien relayé vers les pairs (logs, GET sur un pair).
- SyncService : Vérifier que le type-check et le lint passent ; lancer une sync et s’assurer qu’aucune régression sur la résolution du graphe.
- relay.ts : En cas de relais injoignable ou réponse non ok, vérifier que l’erreur est bien levée (et non masquée par
[]/false). - importIdentity : Importer une clé privée hex valide (64 caractères), vérifier que la clé publique stockée correspond à la dérivation secp256k1. Tester un format invalide (ex. mnemonic) et vérifier le retour
nullet le message en console.