anchorage_layer_simple/userwallet/features/userwallet-dh-systematique-scan-fetch.md
ncantu 0960e43a45 Optimisation mémoire api-anchorage avec base de données SQLite
**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)
2026-01-27 21:12:22 +01:00

70 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 lutilisateur **scanne****aille chercher le hash** avec le message → quil **sache alors déchiffrer** ?
## Réponse courte (avant implémentation)
**Non.** Aujourdhui le DH nest 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) et `senderIdentity` requis. Chiffrement ECDH, POST `MsgChiffre` + POST `MsgCle` (`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 de `senderPublicKey` / 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 lautre appareil.
### 2. Login (challenge)
- **Envoi** : ECDH vers lidentité (destinataire = nous). POST `MsgChiffre` + POST `MsgCle` (`df_ecdh_scannable` = clé publique émetteur) + POST signatures. Plus de `encryptForAll` ni 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 par `hash_message`**fetch message par hash** (`GET /messages/:hash`) → **déchiffrement ECDH** (`tryDecryptWithKeys` avec `df_ecdh_scannable` + identité). Plus de base64.
- **Identité** : `SyncService` reçoit `LocalIdentity | 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
1. **api-relay** : `GET /keys?start=&end=` (fenêtre `received_at`), `StorageService.getKeysInWindow`.
2. **userwallet relay** : `getKeysInWindow`, `getMessageByHash`.
3. **Login** : `LoginBuilder` utilise `encryptWithECDH` (identité comme destinataire), `challengeToMsgCle`, `loginPublish` POST `MsgCle` en plus de `MsgChiffre` et signatures.
4. **Pairing** : DH obligatoire ; `publishPairingMessage` exige `recipientPublicKey` et `senderIdentity` ; plus de base64. `fetchPairingMessage` ECDH uniquement. UX : saisie clé publique (hex 66 car.) + affichage clé locale.
5. **Sync** : flux scan-first. `SyncService(relays, graphResolver, identity)`. Pour chaque relais : `getKeysInWindow` → regroupement par hash → `getMessageByHash``tryDecryptWithKeys` (ECDH) → validation → mise à jour graphe. `syncDecrypt.tryDecryptWithKeys` utilise `decryptWithECDH` avec `df_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`.