**Motivations:** - Réduction drastique de la consommation mémoire lors des ancrages - Élimination du chargement de 173k+ UTXOs à chaque requête - Stabilisation de la mémoire système sous charge élevée (50+ ancrages/minute) **Root causes:** - api-anchorage chargeait tous les UTXOs (173k+) via listunspent RPC à chaque ancrage - Filtrage et tri de 173k+ objets en mémoire pour sélectionner un seul UTXO - Croissance mémoire de ~16 MB toutes les 12 secondes avec 50 ancrages/minute - Saturation mémoire système en quelques minutes **Correctifs:** - Création du module database.js pour gérer la base de données SQLite partagée - Remplacement de listunspent RPC par requête SQL directe avec LIMIT 1 - Sélection directe d'un UTXO depuis la DB au lieu de charger/filtrer 173k+ objets - Marquage des UTXOs comme dépensés dans la DB après utilisation - Fermeture propre de la base de données lors de l'arrêt **Evolutions:** - Utilisation de la base de données SQLite partagée avec signet-dashboard - Réduction mémoire de 99.999% (173k+ objets → 1 objet par requête) - Amélioration des performances (requête SQL indexée vs filtrage en mémoire) - Optimisation mémoire de signet-dashboard (chargement UTXOs seulement si nécessaire) - Monitoring de lockedUtxos dans api-anchorage pour détecter les fuites - Nettoyage des intervalles frontend pour éviter les fuites mémoire **Pages affectées:** - api-anchorage/src/database.js (nouveau) - api-anchorage/src/bitcoin-rpc.js - api-anchorage/src/server.js - api-anchorage/package.json - signet-dashboard/src/bitcoin-rpc.js - signet-dashboard/public/app.js - features/optimisation-memoire-applications.md (nouveau) - features/api-anchorage-optimisation-base-donnees.md (nouveau)
5.2 KiB
5.2 KiB
UserWallet – DH systématique et flux scan → fetch par hash → déchiffrer
Author: Équipe 4NK
Date: 2026-01-26
Question
Le DH est-il systématiquement mis en place pour les types de messages envoyés (sauf DH) afin que l’utilisateur scanne → aille chercher le hash avec le message → qu’il sache alors déchiffrer ?
Réponse courte (avant implémentation)
Non. Aujourd’hui le DH n’est pas systématique pour tous les types de messages. Seul le pairing utilise ECDH + MsgCle lorsque la clé publique du pair distant est connue ; le login et le sync générique ne suivent pas ce schéma.
État après implémentation (DH systématique + flux scan → fetch → déchiffrer)
1. Pairing (membre finaliser)
- Envoi : DH obligatoire.
recipientPublicKey(clé du pair distant) etsenderIdentityrequis. Chiffrement ECDH, POSTMsgChiffre+ POSTMsgCle(df_ecdh_scannable= clé publique de l’émetteur). Plus de base64. - Réception :
fetchPairingMessage→ fetch messages → fetch keys par hash → déchiffrement ECDH uniquement (plus de base64). Si pas desenderPublicKey/ identité → message ignoré. - UX : formulaire pairing avec saisie « Clé publique (hex, 66 car.) » du pair distant ; affichage de la clé publique locale pour copie sur l’autre appareil.
2. Login (challenge)
- Envoi : ECDH vers l’identité (destinataire = nous). POST
MsgChiffre+ POSTMsgCle(df_ecdh_scannable= clé publique émetteur) + POST signatures. Plus deencryptForAllni clé symétrique. - Réception : preuve envoyée au parent (iframe). Message login sur le relais déchiffrable via sync (scan keys → fetch par hash → ECDH).
3. Sync générique
- Flux : scan des MsgCle (
GET /keys?start=&end=) → regroupement parhash_message→ fetch message par hash (GET /messages/:hash) → déchiffrement ECDH (tryDecryptWithKeysavecdf_ecdh_scannable+ identité). Plus de base64. - Identité :
SyncServicereçoitLocalIdentity | null; sans identité, messages traités comme indéchiffrables.
Ce que prévoient les specs
- Message individuel de déchiffrement : hash + clé de chiffrement + df = « diffie-hellman à scanner » pour obtenir la clé de déchiffrement (secret partagé).
- Flux : « Récupérer et scanner tous les messages de clés » (depuis date anniversaire / checkpoint) ; les messages déchiffrables sont identifiés via les DH ; puis on va chercher le message par hash et on déchiffre.
- Publish to all : tout est chiffré ; seuls les pairs qui peuvent dériver la clé (via ECDH) peuvent lire. Le « matériel DH » est publiable car inexploitable par les tiers.
Donc, pour les types de messages hors DH : chiffrement + MsgCle avec df_ecdh_scannable systématique, et flux scan des clés → fetch message par hash → déchiffrer.
Écarts principaux (avant implémentation)
| Aspect | Specs | Actuel (avant) |
|---|---|---|
| DH pour tous les messages (hors DH) | Oui, via MsgCle + df | Non : login sans MsgCle ; pairing optionnel ; sync en base64 |
| Flux | Scan MsgCle → hashes déchiffrables → fetch message par hash | Fetch messages → fetch keys par hash ; pas de scan MsgCle centré ECDH |
| Utilisation des clés en sync | Déchiffrement ECDH avec df | Base64 si keys.length > 0 ; clés non utilisées |
| Login | Sous-entendu publish to all + MsgCle/DH | encryptForAll seul, pas de MsgCle |
Implémentation réalisée
- api-relay :
GET /keys?start=&end=(fenêtrereceived_at),StorageService.getKeysInWindow. - userwallet relay :
getKeysInWindow,getMessageByHash. - Login :
LoginBuilderutiliseencryptWithECDH(identité comme destinataire),challengeToMsgCle,loginPublishPOSTMsgCleen plus deMsgChiffreet signatures. - Pairing : DH obligatoire ;
publishPairingMessageexigerecipientPublicKeyetsenderIdentity; plus de base64.fetchPairingMessageECDH uniquement. UX : saisie clé publique (hex 66 car.) + affichage clé locale. - Sync : flux scan-first.
SyncService(relays, graphResolver, identity). Pour chaque relais :getKeysInWindow→ regroupement par hash →getMessageByHash→tryDecryptWithKeys(ECDH) → validation → mise à jour graphe.syncDecrypt.tryDecryptWithKeysutilisedecryptWithECDHavecdf_ecdh_scannable.
Références
userwallet/docs/specs.md: Message individuel de déchiffrement, df DH à scanner, « récupérer et scanner tous les messages de clés », fenêtre de scan, fetch par hash.userwallet/features/userwallet-pairing-connecte.md: chiffrement pairing ECDH vs base64, MsgCle.userwallet/src/utils/encryption.ts:encryptWithECDH/decryptWithECDH.userwallet/src/services/pairingConfirm.ts: publication pairing + MsgCle (DH obligatoire),fetchPairingMessage(ECDH seul).userwallet/src/services/syncService.ts: flux scan-first,getKeysInWindow→getMessageByHash→tryDecryptWithKeys.userwallet/src/services/syncDecrypt.ts:tryDecryptWithKeys(ECDH).userwallet/src/services/loginBuilder.ts: ECDH +challengeToMsgCle.