**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
84 lines
4.8 KiB
Markdown
84 lines
4.8 KiB
Markdown
# 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 `MessageBase` dans SyncService et utiliser les types partagés.
|
||
- Supprimer les fallbacks (retour de `[]` ou `false` en 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()` puis `if (!storage.hasSeenHash())` pour relayer. Or `storeMessage` marque le hash comme vu, donc la condition était toujours fausse et le relais jamais exécuté.
|
||
- **MessageBase** : SyncService définissait une interface locale `MessageBase` avec `hash?: string`, alors que le code utilisait `msg.hash.hash_value` (type `Hash`). Incohérence de typage et duplication.
|
||
- **relay.ts** : Les GET renvoyaient `[]` et les POST `false` en cas d’erreur, ce qui masquait les échecs (fallback interdit).
|
||
- **importIdentity** : On générait une nouvelle paire, puis on écrasait `privateKey` par la seed fournie tout en gardant la `publicKey` de 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)` **avant** `storage.storeMessage(stored)`.
|
||
- Appeler `storage.storeMessage(stored)`.
|
||
- Relayer seulement si `!alreadySeen` : `await relay.relayMessage(msg)` et `stored.relayed = true`.
|
||
|
||
### 2. userwallet – SyncService MessageBase
|
||
|
||
**Fichier:** `userwallet/src/services/syncService.ts`
|
||
|
||
- Importer `MessageBase` depuis `../types/message`.
|
||
- Supprimer l’interface locale `MessageBase` en fin de fichier.
|
||
- Utiliser le type partagé pour `validateMessage` et `updateGraph`.
|
||
|
||
### 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.ok` ou d’échec fetch, avec message incluant statut et URL du relais.
|
||
- **POST** (`postMessageChiffre`, `postSignature`, `postKey`) : ne plus retourner `false` ; `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 postSignature` sans vérifier de booléen ; en cas de throw, le `catch` existant 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): string` qui 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 `raw` comme `privateKey` et la clé dérivée comme `publicKey`.
|
||
- 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.
|
||
|
||
## Évolutions
|
||
|
||
- Aucune évolution fonctionnelle au-delà des correctifs ci‑dessus.
|
||
|
||
## Pages affectées
|
||
|
||
- `api-relay/src/routes/messages.ts`
|
||
- `userwallet/src/services/syncService.ts`
|
||
- `userwallet/src/utils/relay.ts`
|
||
- `userwallet/src/utils/crypto.ts`
|
||
- `userwallet/src/utils/identity.ts`
|
||
- `userwallet/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 `null` et le message en console.
|