anchorage_layer_simple/features/userwallet-collecte-distante-2-devices.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

4.3 KiB
Raw Permalink Blame History

UserWallet Collecte distante (2 devices)

Author: Équipe 4NK
Date: 2026-01-26

Objectif

Supporter cardinalite_minimale > 1 avec deux appareils : signature locale sur le 1ᵉʳ, signature sur le 2ᵉ, récupération des sigs via les relais, puis publication de la preuve lorsque toutes les sigs requises sont réunies.

Flux

  1. Device 1 : construire le challenge, signer localement (pairs locaux du membre), publier message + sigs locales sur les relais.
  2. Device 1 : boucle de collecte — fetch des sigs par hash sur les relais, merge avec les sigs locales, dédup par pair. Dès que hasEnoughSignatures (assez de pairs distincts par membre par rapport à cardinalite_minimale), on arrête.
  3. Device 2 : obtenir hash et nonce (lien ou QR émis par Device 1 pendant la collecte). Ouvrir /login-sign?hash=...&nonce=..., signer hash-nonce avec la clé du pair local, poster la signature sur les relais.
  4. Device 1 : une fois assez de sigs (dont celle du 2ᵉ), si au moins une signature provient du 2ᵉ appareil (pair non local) → confirmation manuelle : « Les mots ont pu être visibles à lécran et interceptés. Confirmer que cest bien vous qui avez validé sur lautre appareil ? » [Accepter] / [Refuser]. Accepter → vérification (dépendances, clés autorisées, strict), marquage du nonce, envoi de la preuve au parent. Refuser → pas denvoi, transition vers S_LOGIN_FAILURE.
  5. Device 1 : si aucune sig distante (cardinalité 1, sig locale seule), pas de confirmation ; vérification et envoi directement.

Modifications

  • loginBuilder.signChallenge : signature de hash-nonce uniquement (plus pairUuid), pour alignement vérif + relais.
  • loginValidation : requiredSigsPerMember, hasEnoughSignatures, hasRemoteSignatures (au moins une sig dun pair non local). Suppression du refus systématique cardinalite > 1.
  • collectSignatures : fetchSignaturesForHash, buildPairToMembers, buildPubkeyToPair, mapMsgSignaturesToProofFormat, runCollectLoop (poll + timeout).
  • loginPublish : publishMessageAndSigs (message + sigs locales vers relais).
  • LoginScreen : signature pour les pairs locaux du membre uniquement ; après publication, boucle de collecte si loginPath ; si hasRemoteSignatures → écran de confirmation [Accepter] / [Refuser], puis vérification et envoi uniquement sur Accepter ; sinon vérification et envoi directs. Affichage « En attente des signatures des autres appareils… » + LoginCollectShare (lien + QR vers /login-sign). Retour désactivé pendant la confirmation.
  • Machine à états : E_LOCAL_VERDICT_REJECT depuis S_LOGIN_PUBLISH_PROOFS_LOGIN_FAILURE (refus des sigs distantes sans envoi).
  • LoginSignScreen : route /login-sign?hash=...&nonce=... ; signature et publication de la sig sur les relais.
  • LoginCollectShare : lien et QR vers /login-sign?hash=...&nonce=... pendant la collecte.

Modalités de déploiement

Déploiement classique du front userwallet. Aucune évolution côte relais.

Confirmation manuelle (signatures 2ᵉ appareil)

Les mots (lien/QR) sont affichés à lécran et peuvent être interceptés (épaule, tiers). Quand au moins une signature reçue provient dun pair non local (2ᵉ device), Device 1 nenvoie pas la preuve tant que lutilisateur na pas manuellement accepté (« cest bien moi qui ai validé sur lautre appareil »). [Refuser] → pas denvoi, S_LOGIN_FAILURE.

Modalités danalyse

  • Device 1 : construction du chemin, challenge, publication → collecte → affichage du lien/QR. Ouvrir le lien sur le 2ᵉ appareil, signer → retour sur le 1ᵉʳ, la collecte doit finir. Si sigs distantes : affichage de la confirmation Accepter/Refuser ; Accepter → envoi preuve, Refuser → échec.
  • Device 2 : aller sur /login-sign?hash=...&nonce=... (ou scanner le QR), vérifier « Signature publiée ».
  • Vérifier timeout de collecte (5 min) si le 2ᵉ ne signe pas.
  • Vérifier que [Refuser] nenvoie pas la preuve et mène à létat déchec.

Références

  • features/userwallet-validation-conformite.md (§ Cardinalite_minimale)
  • userwallet/docs/specs.md (collecte signatures mFA, S_LOGIN_COLLECT_SIGNATURES)