38 KiB
Blueprint — Wallet desktop per criptovaluta UTXO/SPV
Specifica autonoma e indipendente dal linguaggio per costruire da zero un wallet solo desktop (Windows e Linux), orientato al power-user come Sparrow Wallet.
Il documento è pensato per essere letto e implementato passo per passo: contiene tutto il necessario — algoritmi, strutture dati, parametri, protocollo di rete e sequenza di costruzione — senza presupporre un framework, un linguaggio o un codice sorgente preesistente. Ogni funzionalità elencata va considerata parte del prodotto completo; quelle marcate (opzionale) possono essere rimandate a release successive ma sono comunque documentate.
0. Glossario rapido
| Termine | Significato |
|---|---|
| SPV | Simplified Payment Verification: il wallet non scarica la catena, verifica le transazioni tramite prove di Merkle sugli header dei blocchi. |
| UTXO | Unspent Transaction Output: una "moneta" non spesa; il saldo è la somma degli UTXO controllati dal wallet. |
| HD | Hierarchical Deterministic: tutte le chiavi derivano da un seed unico (BIP32). |
| PSBT | Partially Signed Bitcoin Transaction: formato standard per transazioni firmate parzialmente (offline, multisig, hardware). |
| Watch-only | Wallet che conosce solo le chiavi pubbliche: vede saldo e storico ma non può firmare. |
| Server di indicizzazione | Server che indicizza la catena e risponde alle query del client (protocollo §10). |
| Scripthash | SHA-256 dello scriptPubKey con byte invertiti: chiave con cui il server indicizza gli indirizzi. |
1. Visione del prodotto
Un wallet desktop nativo con queste qualità target (modello Sparrow):
- Solo desktop: nessuna UI mobile. UX densa, orientata a trasparenza e controllo.
- Single-sig e multisig di prima classe, con supporto hardware wallet.
- Controllo totale su monete e fee: coin control (UTXO), selezione manuale, etichette, controllo fee, RBF/CPFP.
- PSBT-centrico: ogni flusso di firma passa per PSBT, abilitando firma offline, air-gapped e collaborativa.
- Leggero (SPV): avvio immediato, nessun full node richiesto (ma con possibilità di collegare un server proprio).
- Privacy-aware: coin selection che preserva la privacy, supporto proxy/Tor, possibilità di server privato.
- Eseguibile distribuibile: binario per Windows e Linux, firma del codice, build riproducibili.
L'applicazione è strutturata in due grandi blocchi: un core (logica pura, senza UI) e una GUI desktop sopra di esso. Tutta la logica di seguito appartiene al core, tranne dove indicato.
2. Architettura a livelli (target)
┌─────────────────────────────────────────────────────────────────────┐
│ GUI desktop — viste, wizard, coin control, dialog di firma │
├─────────────────────────────────────────────────────────────────────┤
│ Application API — casi d'uso: crea/apri wallet, invia, ricevi, │
│ firma, storico, gestione canali, ecc. │
│ Esposta anche come CLI + RPC locale (§13). │
├─────────────────────────────────────────────────────────────────────┤
│ Dominio wallet — wallet, keystore, indirizzi, UTXO, contatti, │
│ fatture, richieste, costruzione/firma tx, │
│ coin selection, fee policy │
├─────────────────────────────────────────────────────────────────────┤
│ SPV / Sincronizz. — synchronizer, verifier (Merkle), gestione │
│ header/checkpoint, saldo e storico │
├─────────────────────────────────────────────────────────────────────┤
│ Rete — pool di connessioni, selezione server, TLS │
│ con pinning, proxy, protocollo di query (§10) │
├─────────────────────────────────────────────────────────────────────┤
│ Crittografia — secp256k1, hash, BIP32/39/SLIP39, base58, │
│ bech32, cifratura file wallet, ECIES │
├─────────────────────────────────────────────────────────────────────┤
│ Persistenza — file wallet JSON cifrato, config, percorsi │
│ Lightning (⏳ poi) — sottosistema separato, fase successiva (§11) │
└─────────────────────────────────────────────────────────────────────┘
Regola di dipendenza: ogni livello dipende solo verso il basso. La GUI parla solo con l'Application API, mai direttamente con rete o crittografia. Questo permette di avere CLI, test automatici e GUI sullo stesso core.
Requisiti di componenti (astratti, non legati al linguaggio)
Indipendentemente dallo stack scelto, servono librerie/moduli che forniscano:
- Curva ellittica secp256k1 (firma/verifica ECDSA + Schnorr, tweak chiavi). Non reimplementare a mano la matematica della curva: usare una libreria auditata.
- Funzioni hash: SHA-256, doppio SHA-256, RIPEMD-160, HASH160 (SHA256→RIPEMD160), SHA-512, HMAC-SHA512, PBKDF2-HMAC-SHA512.
- Encoding: Base58Check, Bech32 e Bech32m.
- Cifratura simmetrica (AES-256) e ECIES per messaggi.
- TLS con accesso al certificato per il pinning.
- JSON per file wallet e protocollo.
- Generatore di numeri casuali crittografico per seed e nonce.
3. Profilo di rete / catena (parametri da definire PRIMA di tutto)
Un wallet è legato a una catena specifica tramite un insieme di costanti. Vanno fissate all'inizio: un valore sbagliato produce indirizzi non validi o fa rifiutare la catena. Definire un oggetto/struct di configurazione con i seguenti campi.
I valori del profilo di riferimento qui sotto sono stati verificati contro il sorgente del nodo (
chainparams.cpp/pow.cpp): sono i parametri di consenso autoritativi.
| Campo | Descrizione | Esempio (profilo di riferimento mainnet) |
|---|---|---|
net_name |
nome rete / sottocartella dati | mainnet |
coin_unit |
simbolo unità | PLM |
wif_prefix |
prefisso chiavi private WIF | 0x80 |
addr_p2pkh |
byte versione indirizzi legacy | 55 → indirizzi che iniziano con P |
addr_p2sh |
byte versione indirizzi P2SH | 5 → iniziano con 3 |
segwit_hrp |
prefisso human-readable bech32 | plm → indirizzi plm1... |
bolt11_hrp |
prefisso fatture Lightning | plm |
genesis_hash |
hash del blocco genesi (mainnet riusa la genesi di Bitcoin) | 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f |
default_ports |
porte del server di indicizzazione usato dal wallet | {tcp: 50001, ssl: 50002} |
bip44_coin_type |
coin type SLIP-0044 nel derivation path (convenzione wallet, non parametro di consenso del nodo) | 746 |
uri_scheme |
schema URI pagamenti (BIP21) | palladium: |
explorer_url |
block explorer di default | https://explorer.palladium-coin.com/ |
skip_pow_validation |
salta la verifica difficoltà — obbligatorio: la catena usa LWMA (vedi nota sotto) | true |
Nota sulle porte. Le
default_portssopra sono quelle del server di indicizzazione (es. ElectrumX-like) a cui si connette il wallet, non la porta P2P del nodo (che nel sorgente è2333mainnet /12333testnet /28444regtest). Sono due cose distinte: il wallet SPV parla solo col server di indicizzazione.Nota sulla difficoltà (LWMA). Il nodo calcola la difficoltà con LWMA (Linearly Weighted Moving Average) e un tempo di blocco di 2 minuti (
nPowTargetSpacingV2 = 120s; il vecchionPowTargetTimespandi 14 giorni è mantenuto solo per la validazione storica). Un client SPV non è in grado di ricalcolare LWMA, quindiskip_pow_validationdeve esseretruee la fiducia sulla catena va ancorata ai checkpoint (§7.3).
Header chiavi estese BIP32 (mainnet di riferimento) — servono per serializzare/parsare xprv/xpub per ciascun tipo di indirizzo:
| Tipo indirizzo | prefisso priv | header priv | prefisso pub | header pub |
|---|---|---|---|---|
| standard (P2PKH) | xprv | 0x0488ade4 |
xpub | 0x0488b21e |
| segwit wrapped (P2WPKH-P2SH) | yprv | 0x049d7878 |
ypub | 0x049d7cb2 |
| multisig wrapped (P2WSH-P2SH) | Yprv | 0x0295b005 |
Ypub | 0x0295b43f |
| native segwit (P2WPKH) | zprv | 0x04b2430c |
zpub | 0x04b24746 |
| native segwit multisig (P2WSH) | Zprv | 0x02aa7a99 |
Zpub | 0x02aa7ed3 |
Testnet (profilo di riferimento): wif_prefix=0xff, addr_p2pkh=127, addr_p2sh=115,
segwit_hrp=tplm, bip44_coin_type=1, header tprv/tpub 0x04358394/0x043587cf, ecc.
Regtest: segwit_hrp=rplm.
Server iniziali (bootstrap, profilo di riferimento): forniti come lista
host:porta_tcp:porta_ssl; il pool li usa per il primo contatto e poi scopre altri peer
via protocollo (server.peers.subscribe).
Tutte le costanti devono essere centralizzate in un solo punto e selezionabili per rete (mainnet/testnet/regtest), così da non disperdere magic number nel codice.
4. Crittografia, seed e gestione chiavi
4.1 Seed e mnemoniche — tutti gli schemi supportati
Il wallet deve supportare più schemi di seed e saperli riconoscere automaticamente:
- Seed nativo versionato: mnemonica con un prefisso di versione codificato via HMAC
(distingue i sottotipi
standard,segwit,2fa,2fa-segwit). In creazione si garantisce che la mnemonica generata non sia contemporaneamente un valido BIP39. - BIP39: import/restore di seed standard a 12 o 24 parole, con verifica del checksum.
- SLIP39 (Shamir Secret Sharing) (opzionale): seed suddiviso in più share; servono K share su N per ricostruirlo.
- Formato seed legacy (opzionale, retrocompatibilità): vecchio schema pre-BIP32.
Wordlist multilingua: inglese, spagnolo, giapponese, portoghese, cinese. Le parole vanno normalizzate (NFKD) prima della derivazione.
Passphrase / extension word (opzionale ma obbligatoria da implementare): parola/e
aggiuntive combinate col seed tramite PBKDF2-HMAC-SHA512, 2048 round, con salt
"<schema>" + passphrase (per il seed nativo il prefisso del salt è una costante dello
schema; per BIP39 è "mnemonic" + passphrase). Cambia completamente il wallet derivato.
Avvisi UI obbligatori: se persa, i fondi sono irrecuperabili; va annotata separatamente
dal seed; è case-sensitive e gli spazi contano.
4.2 Derivazione gerarchica (BIP32/BIP44/49/84)
- Da seed → root key (BIP32). Da root → chiavi estese per account.
- Path standard con il
coin_typedel profilo:- Legacy P2PKH:
m/44'/<coin>'/account'/change/index - Segwit wrapped P2SH-P2WPKH:
m/49'/<coin>'/account'/change/index - Native segwit P2WPKH:
m/84'/<coin>'/account'/change/index - Multisig:
m/48'/<coin>'/account'/script_type'/...
- Legacy P2PKH:
- Supportare derivation path personalizzati (Sparrow-like): l'utente può specificare il path manualmente in import.
- Catena
change=0(receiving) echange=1(change). Derivazione per indice on-demand.
4.3 Tipi di indirizzo (tutti)
| Tipo | script | prefisso (profilo rif.) | uso |
|---|---|---|---|
| Native SegWit | P2WPKH | plm1... |
default consigliato: fee minime |
| Legacy | P2PKH | P... |
massima compatibilità |
| SegWit wrapped | P2SH-P2WPKH | 3... |
compatibilità intermedia |
| Multisig native | P2WSH | plm1... |
M-di-N moderno |
| Multisig wrapped | P2SH / P2SH-P2WSH | 3... |
M-di-N legacy |
4.4 Tipi di keystore (sorgenti di chiavi)
- HD da seed (caso principale): seed → root → xprv/xpub.
- HD da master key importata: import di xprv/xpub (o y/z varianti). Solo xpub = watch-only.
- Chiavi private importate: lista di chiavi WIF singole.
- Hardware wallet: la chiave privata non lascia mai il dispositivo (vedi §4.6).
- Keystore "split/2FA" (opzionale): parte della firma delegata a un servizio remoto.
- Keystore legacy (opzionale).
4.5 Tipi di wallet
- Standard (single-sig HD) — caso d'uso principale.
- Multisig M-di-N — combinazione di più keystore (seed/xpub/hardware misti).
- Importato — indirizzi o chiavi private importate; può essere watch-only o spendibile.
- Watch-only — solo chiavi pubbliche; costruisce ma non firma (esporta PSBT).
Una factory legge il tipo dal file wallet e istanzia la classe corretta.
4.6 Hardware wallet (tutti i modelli supportati)
Integrazione con dispositivi hardware via il loro protocollo USB/HID/seriale. Modelli da supportare: Trezor, Ledger, KeepKey, Coldcard, BitBox02, Digital BitBox, Safe-T, Jade. Funzioni: import dell'xpub dal dispositivo, conferma indirizzo sullo schermo del device, firma PSBT sul device (la chiave privata non viene mai esposta), gestione PIN/passphrase. Per i dispositivi air-gapped (es. Coldcard): scambio PSBT via file/QR/microSD.
4.7 Backup e sicurezza delle chiavi
- Cifratura del file wallet con password (vedi §8); cambio password.
- Cifratura/decifratura messaggi e firma/verifica messaggi con una chiave.
- Export: seed, master private key, master public key, chiavi private (per indirizzo o per path), in modo protetto (richiesta password).
- Backup su carta con visual one-time-pad (opzionale, "revealer"): genera un foglio cifrato che, sovrapposto a una griglia segreta stampata, rivela il seed.
- Recupero a timelock (opzionale): predisposizione di transazioni di recupero che diventano spendibili dopo un timelock, per ereditarietà/dead-man-switch.
5. Ricezione fondi
- Generazione indirizzi: prossimo indirizzo non usato; lista indirizzi receiving e change; rispetto del gap limit (numero massimo di indirizzi vuoti consecutivi scansionati; configurabile, con comando per aumentarlo).
- Richieste di pagamento: creare una richiesta con importo, scadenza, descrizione; elencarle, eliminarle, segnarne lo stato (in attesa/pagata/scaduta).
- URI BIP21: generare e parsare
«scheme»:«indirizzo»?amount=...&label=...&message=.... - QR code: generazione per indirizzi/URI/richieste; scansione da webcam o immagine.
- Risoluzione nomi: OpenAlias/DNS, LNURL, e richieste firmate BIP70 (opzionale).
- Etichette sugli indirizzi e sulle richieste.
6. Invio fondi e costruzione transazioni
6.1 Composizione
- Pay-to singolo e pay-to-many (più output in una sola transazione).
- Input destinatario: indirizzo, URI, nome OpenAlias/LNURL, o richiesta scansionata.
- Importo in unità coin o in fiat (con conversione al tasso corrente).
- Opzione "invia tutto" (max), con sottrazione fee dall'importo.
- Locktime e sequence impostabili (per RBF/timelock).
- Etichetta della transazione.
6.2 Coin control (cuore di un wallet desktop)
- Vista UTXO completa con importi, indirizzo, conferme, etichetta.
- Selezione manuale degli UTXO da spendere (coin control).
- Freeze/unfreeze di indirizzi e di singoli UTXO (esclusi dalla spesa automatica).
- Visualizzazione del change previsto e dell'indirizzo di change.
6.3 Strategie di selezione monete (coin selection)
Implementare almeno due strategie selezionabili:
- Privacy-preserving: raggruppa gli UTXO per indirizzo (evita di unire monete di indirizzi diversi), riduce la perdita di privacy futura e il bloat di UTXO.
- Random: selezione casuale con arrotondamento del change per offuscare gli importi. Obiettivi comuni: minimizzare fee, evitare output dust, gestire il change correttamente.
6.4 Politiche di fee (tutte)
Modalità di calcolo fee, selezionabili:
- Fissa (importo assoluto).
- Fee rate fisso (sat/vByte).
- Dinamica ETA-based: stima dal server per un target di conferma (es. 1, 2, 5, 10, 25, 144, 1008 blocchi).
- Dinamica mempool-based: in base allo stato della mempool. Mostrare sempre fee totale, fee rate effettivo e dimensione virtuale stimata. Avviso se la fee è anomala (troppo alta/bassa).
6.5 Firma e modello PSBT
Ogni transazione non banale passa per PSBT:
- Crea PSBT (non firmata) dal wallet.
- Firma con: keystore software, hardware wallet, o firma offline su altra macchina.
- Combina PSBT parzialmente firmate (multisig: ogni cosigner firma e si uniscono).
- Finalizza ed estrai la transazione grezza.
- Import/export PSBT via: file, QR code (anche animato per PSBT grandi), scambio su rete decentralizzata per cosigning (opzionale), trasmissione audio (opzionale, "audio modem").
- Flusso watch-only / air-gapped: la macchina online crea la PSBT, quella offline firma, la online trasmette.
6.6 Gestione post-invio
- Broadcast della transazione (e broadcast di un pacchetto di transazioni correlate).
- RBF (Replace-By-Fee): bump della fee di una tx non confermata; cancellazione (invio a sé stessi con fee più alta).
- CPFP (Child-Pays-For-Parent): accelerare una tx in entrata spendendola con fee alta.
- Rimozione di tx locali non confermate.
- Sweep: spazzare tutti i fondi di una chiave privata esterna verso il wallet.
- Aggiunta manuale di una tx (incolla raw/hex) e firma con chiave fornita.
6.7 Reportistica
- Plusvalenze/minusvalenze on-chain (capital gains) per anno fiscale.
- Esportazione storico (CSV/JSON) con etichette.
- Timestamp di inizio/fine anno per i report.
7. Blockchain, sincronizzazione e validazione (SPV)
7.1 Modello SPV
Il wallet non scarica la catena completa. Mantiene solo gli header dei blocchi e verifica le transazioni che lo riguardano con prove di Merkle contro tali header.
7.2 Validazione header
- Header a lunghezza fissa (campi: versione, prev_hash, merkle_root, timestamp, bits, nonce).
- Verifica del collegamento (prev_hash) e dell'hash atteso di ogni header.
- Proof-of-Work: confronto
hash <= targete coerenza deibits. - Difficoltà: la catena di riferimento usa LWMA (retargeting per-blocco, tempo di
blocco 2 minuti — confermato dal nodo). Un client SPV non ricalcola LWMA, quindi il flag
skip_pow_validationdel profilo (§3) disattiva il controllo bits/target; in tal caso la fiducia è ancorata ai checkpoint (sotto). Implementare entrambe le modalità (PoW classico stile Bitcoin e modalità "skip" per catene LWMA). - Header organizzati in chunk (es. 2016) salvati su file locale; gestione di fork (più rami concorrenti) con scelta del ramo a maggior lavoro.
7.3 Checkpoint
Lista hardcoded di [hash, target] a intervalli regolari, usata per:
- accelerare la validazione iniziale (non riverificare dall'origine),
- ancorare la validità della catena quando la verifica PoW è disattivata. Fornire un meccanismo per aggiornare/spedire i checkpoint con le release.
7.4 Sincronizzazione wallet
- Per ogni indirizzo: calcola lo scripthash, sottoscrivi al server.
- Alla notifica di cambiamento: richiedi lo storico (lista txid + altezza).
- Scarica le transazioni mancanti.
- Verifica ciascuna con prova di Merkle contro l'header all'altezza indicata.
- Aggiorna saldo (confermato/non confermato), UTXO e storico.
- Estendi la scansione finché si raggiunge il gap limit di indirizzi vuoti.
8. Persistenza e configurazione
- File wallet: un file (JSON) contenente keystore, indirizzi, storico, etichette, contatti, richieste, fatture, (e stato canali Lightning se attivo). Cifrato con AES quando è impostata una password (la password protegge il file su disco; non sblocca il seed). Schema versionato con migrazioni automatiche all'apertura.
- Configurazione globale separata dal wallet: rete selezionata, server, proxy, unità, lingua, politiche fee di default, block explorer.
- Percorsi dati per piattaforma + modalità portable (dati accanto all'eseguibile, utile per chiavette USB).
- Multi-wallet: aprire/chiudere più wallet, elencarli, passare dall'uno all'altro.
9. Rete e connettività
- Pool di connessioni: più server contemporaneamente per ridondanza; un server "primario" per gli header; fan-out delle query.
- Selezione server: automatica o manuale; scoperta di nuovi peer dal protocollo.
- TLS con pinning (TOFU): al primo contatto il certificato del server viene salvato; ai successivi viene confrontato. Se cambia → connessione rifiutata. Fornire un comando "reset certificati SSL" per i server self-signed (caso tipico: il server rinnova il certificato e il client va sbloccato manualmente).
- Proxy / Tor: supporto SOCKS5 per instradare tutto il traffico.
- Stima fee dal server; relay fee minima.
- Stato connessione visibile in UI; riconnessione automatica.
10. Protocollo client ↔ server (query di indicizzazione)
Il client comunica via JSON-RPC (su TCP, opzionalmente TLS). Implementare richieste e parsing per i seguenti metodi (gli indirizzi sono indicizzati per scripthash):
# Negoziazione / server
server.version server.banner server.features
server.ping server.peers.subscribe server.donation_address
# Header / catena
blockchain.headers.subscribe blockchain.block.header blockchain.block.headers
blockchain.estimatefee blockchain.relayfee
# Indirizzi (per scripthash)
blockchain.scripthash.subscribe blockchain.scripthash.get_balance
blockchain.scripthash.get_history blockchain.scripthash.listunspent
# Transazioni
blockchain.transaction.get blockchain.transaction.get_merkle
blockchain.transaction.broadcast blockchain.transaction.broadcast_package
blockchain.transaction.id_from_pos
11. Lightning Network — ⏳ DA FARE IN SEGUITO (fase successiva, fuori dal primo rilascio)
Non incluso nel primo rilascio. Coerentemente con il modello Sparrow (on-chain only), il wallet parte senza Lightning. Questo capitolo resta documentato come specifica per una fase successiva: va affrontato solo dopo che tutte le funzioni on-chain (§4–§10) sono complete e stabili. Va progettato come sottosistema separato e disattivabile, in modo da non bloccare né complicare il primo rilascio.
Quando verrà affrontato, è un grande sottosistema a sé. Funzionalità da implementare:
- Canali: apertura, chiusura cooperativa e forzata, lista canali e peer.
- Pagamenti: invio/ricezione su BOLT11, MPP (multi-part payments), trampoline routing, onion routing, gossip/routing della rete.
- Fatture: creazione/decodifica BOLT11; hold invoice (trattenute fino a conferma).
- Backup canali: export/import dei backup di stato (critici per non perdere fondi).
- Watchtower: locale e remoto, per punire chiusure fraudolente quando offline.
- Submarine swap: scambio on-chain ↔ Lightning, con provider/server di swap; rebalance dei canali.
- LNURL e indirizzi Lightning (lightning-address).
- Nostr Wallet Connect (NWC) (opzionale): controllo remoto del wallet Lightning.
- Payserver (opzionale): endpoint per ricevere pagamenti.
Promemoria: per il primo rilascio Lightning è escluso. Le funzioni base (§4–§10) non dipendono in alcun modo da questo capitolo; affrontarlo solo come iterazione successiva.
12. Contatti, etichette e dati ausiliari
- Rubrica contatti: nome ↔ indirizzo, con ricerca.
- Etichette su indirizzi, transazioni, UTXO, richieste.
- Sincronizzazione etichette (opzionale): cifrate, condivise tra istanze del wallet via un servizio.
- Lista fatture (uscite) e lista richieste (entrate) con stato.
13. Interfacce non grafiche
- CLI: ogni caso d'uso del core esposto come comando da riga di comando (utile per scripting e per i test automatici).
- RPC locale / daemon (opzionale): un processo in background che espone l'API su socket locale autenticato, così la GUI e strumenti esterni parlano con lo stesso core.
Famiglie di comandi da prevedere (elenco rappresentativo della superficie API completa): creazione/restore/apertura/chiusura wallet, generazione indirizzi, saldo e storico, pay-to / pay-to-many, firma/broadcast, gestione PSBT (deserialize/combine/finalize), freeze/unfreeze UTXO, bumpfee/cancel, sweep, import/export chiavi e xkey, conversione xkey, firma/verifica messaggi, gestione richieste e fatture, contatti, conversione fiat, stato sincronizzazione, gestione server/config. (Comandi Lightning — apertura/chiusura canali, pagamenti, swap, backup canali — solo nella fase successiva, vedi §11.)
14. Funzioni di supporto e infrastruttura
- Tassi di cambio / fiat: integrazione con più provider di prezzo; conversione importi in valuta locale; prezzi storici per la reportistica; aggiornamento periodico.
- Internazionalizzazione (i18n): UI multilingua, con rilevamento lingua di sistema.
- Crash reporter: raccolta e invio (con consenso) dei crash.
- Sistema di plugin (opzionale): caricamento di estensioni (hardware wallet, swap server, watchtower, label sync, ecc.) come moduli separati.
- Hardening memoria (opzionale): blocco in RAM (no swap su disco) dei segreti dove il SO lo consente; azzeramento dei buffer sensibili dopo l'uso.
- Block explorer: apertura di tx/indirizzi nell'explorer configurato.
15. Wizard di creazione/restore (flusso UI)
- Avvio: crea nuovo wallet / apri esistente / importa.
- Tipo wallet: Standard / Multisig (M-di-N) / Importa indirizzi o chiavi / Hardware.
- Per Standard: nuovo seed / ho già un seed / usa master key / usa device hardware.
- Nuovo seed → mostra le parole → conferma reinserendole.
- Passphrase opzionale (extension word) con avvisi (§4.1).
- Scelta tipo di indirizzo (default: native segwit).
- Password di cifratura del file wallet.
- Sincronizzazione e comparsa di saldo/storico.
Per multisig: raccolta di N cosigner (seed/xpub/hardware), scelta soglia M, derivation path e tipo di script; generazione del descrittore del wallet e verifica incrociata degli xpub tra i partecipanti.
16. Sequenza di costruzione consigliata (passo per passo)
Costruire e testare in quest'ordine; ad ogni passo verificare con vettori noti.
- Profilo di rete (§3): centralizzare tutte le costanti; selettore mainnet/testnet/regtest.
- Crittografia e chiavi (§4): hash, secp256k1, base58/bech32, BIP32/39, generazione indirizzi. Test: dato un seed → produrre gli indirizzi attesi (golden vectors).
- Persistenza (§8): definire e versionare lo schema del file wallet (JSON) + cifratura.
- Rete + protocollo (§9–10): connessione, TLS+pinning, query base.
- SPV + sincronizzazione (§7): header, checkpoint, Merkle, saldo/storico su un wallet watch-only. Test: stesso xpub → stesso saldo di un wallet di riferimento.
- Transazioni (§6): costruzione, coin selection, fee, PSBT, firma, broadcast su testnet.
- GUI desktop (§15 + viste): wizard, dashboard saldo/storico, invia (con coin control), ricevi, UTXO, contatti, impostazioni.
- Hardware wallet (§4.6) e multisig (§4.5): firma collaborativa via PSBT.
- Estensioni: fiat/exchange rate, label sync, reportistica.
- ⏳ Fase successiva (post-rilascio): Lightning (§11) come sottosistema separato, da iniziare solo quando i passi 1–9 sono completi e stabili.
Test cross-implementazione (obbligatorio per un wallet): ad ogni passo confrontare gli output (indirizzi, txid, PSBT) con un wallet di riferimento usando gli stessi input. Un indirizzo o un txid diverso è un bug bloccante.
17. Requisiti di sicurezza (non negoziabili)
- Seed e chiavi private mai in chiaro su disco non cifrato, mai nei log, mai inviati in rete.
- Cifratura del file wallet con derivazione robusta della chiave dalla password.
- Validare ogni dato proveniente dalla rete: le risposte dei server non sono fidate; verificare sempre con prove di Merkle + checkpoint.
- Watch-only realmente read-only: nessuna chiave privata derivabile dalle sole pubbliche.
- TLS con pinning del certificato e reset esplicito controllato dall'utente.
- Azzeramento dei segreti in memoria dopo l'uso; ove possibile blocco anti-swap.
- Firma del codice dei binari Windows/Linux e build riproducibili per consentire la verifica indipendente.
18. Packaging e distribuzione desktop
- Windows: eseguibile installabile e versione portable (dati accanto all'exe). Firma Authenticode.
- Linux: formato portabile autoconsistente (es. immagine eseguibile singola) e/o pacchetto nativo; firma GPG dei rilasci.
- Build riproducibili (ambiente di build isolato/containerizzato) e pubblicazione degli hash + firme dei binari.
- File di associazione per lo schema URI dei pagamenti (
uri_schemedel profilo) così che i link di pagamento aprano il wallet.
19. Stack tecnologico raccomandato (.NET 8 + Avalonia + NBitcoin)
I capitoli §1–§18 sono indipendenti dal linguaggio e restano il riferimento. Questa sezione propone una realizzazione concreta scelta per tre vincoli: sviluppo assistito da IA, semplicità, e un solo sorgente che produca sia
.exe(Windows) sia AppImage (Linux). Lo stack non è obbligatorio: è la via più liscia per questo prodotto.
19.1 Perché questo stack
NBitcoin(C#) modella reti altcoin custom viaNetworkBuilder(prefissi P2PKH/P2SH, WIF, header BIP32 xpub/xprv, HRP bech32, genesi): mappatura diretta della §3. Fornisce già HD/BIP32/39, indirizzi (legacy/segwit/wrapped), costruzione e serializzazione transazioni, PSBT, firma, base58/bech32, hashing → è la libreria che fa scrivere meno crittografia a mano per un altcoin.- Avalonia UI è cross-platform nativo: un solo sorgente per Windows e Linux.
- C#/.NET ha tooling maturo e un enorme corpus → l'IA produce codice idiomatico con poche frizioni; alto livello e GC = sviluppo rapido.
- Posizione di sicurezza accettabile sulle chiavi senza la curva di apprendimento di Rust e senza i rischi di Electron (chiavi in JS, footprint, supply-chain npm).
Alternative scartate: Rust + BDK + Tauri (binari minimi e memory-safe, ma curva
ripida e customizzazione altcoin più laboriosa → contro "semplicità"); Electron + TS
(packaging e UI rapidissimi, ma gestione chiavi più fragile → sconsigliato per un wallet);
Java/JavaFX (è lo stack di Sparrow e produce già .exe+AppImage, ma nessun vantaggio
netto su .NET per questo caso).
19.2 Cosa è coperto dalla libreria e cosa va scritto a mano
Coperto da NBitcoin (non reimplementare): rete custom, BIP32/39, indirizzi, transazioni, PSBT, firma, base58/bech32, hashing.
Da implementare a mano (NBitcoin non lo include — è il grosso del lavoro originale):
- Client del protocollo del server di indicizzazione (§10): JSON-RPC su TCP/TLS, pool di connessioni, TLS pinning/TOFU, reset certificati, proxy/Tor.
- Sincronizzazione SPV (§7.4): scripthash, storico, verifica prove di Merkle.
- Validazione header + checkpoint con modalità "skip PoW" per LWMA (§3/§7): NBitcoin assume il retargeting di Bitcoin, quindi questo strato è custom.
- Coin selection privacy-preserving e fee policy (fissa/rate/ETA/mempool), RBF/CPFP (§6): logica di dominio sopra le primitive NBitcoin.
- File wallet cifrato (schema JSON versionato + AES) e config (§8).
19.3 Mappatura strato del blueprint → componente concreto
| Strato (§2) | Realizzazione |
|---|---|
| Crittografia (§4) | NBitcoin (Network custom, ExtKey, Mnemonic, BitcoinAddress, PSBT) |
| Profilo rete (§3) | NetworkBuilder con i valori §3, centralizzato in Core/Chain |
| SPV/Sync (§7) | codice custom in Core/Spv |
| Rete/protocollo (§9–10) | client custom in Core/Net |
| Dominio wallet (§4–§6) | Core/Wallet sopra NBitcoin |
| Persistenza (§8) | System.Text.Json + AES in Core/Storage |
| Application API (§13) | progetti Cli e API condivisa |
| GUI desktop (§15) | Avalonia in App |
19.4 Struttura del progetto (una sola solution .NET)
PalladiumWallet.sln
├─ src/Core/ (libreria, nessuna dipendenza UI)
│ ├─ Chain/ profilo rete (NetworkBuilder), costanti §3, checkpoint
│ ├─ Crypto/ wrapper NBitcoin: seed, BIP32/39, indirizzi, keystore
│ ├─ Wallet/ wallet, UTXO, coin selection, fee policy, PSBT, firma
│ ├─ Spv/ header store, verifier (Merkle), sync
│ ├─ Net/ client protocollo, pool, TLS pinning, proxy
│ └─ Storage/ file wallet JSON cifrato, config
├─ src/App/ (Avalonia UI: wizard, dashboard, invia/ricevi, coin control)
├─ src/Cli/ (riga di comando sullo stesso Core — utile ai test)
└─ tests/ (xUnit: golden vectors indirizzi/txid, test SPV)
Regola di dipendenza (§2): App e Cli dipendono da Core; Core non conosce la UI.
19.5 Ambiente di sviluppo e build — tutto su Ubuntu, senza Wine
- Dev:
.NET 8 SDK(repo Microsoft /apt), VS Code + estensione C# o Rider. Avalonia gira ed è eseguibile nativamente su Ubuntu. - Architetture host: si sviluppa sia su x86_64 sia su arm64 (il .NET SDK è
nativo su
linux-x64elinux-arm64; NBitcoin è C# puro gestito, nessuna dipendenza nativa legata all'arch). - Build cross dei binari da Linux, senza Wine (.NET cross-targeta nativamente):
- Windows:
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained→.exe. - Linux:
dotnet publish -r linux-x64 --self-contained.
- Windows:
- Docker consigliato: un solo
Dockerfilesumcr.microsoft.com/dotnet/sdk:8.0produce i target in modo riproducibile. - Wine non serve per compilare. Servirebbe solo per costruire un installer Windows
con Inno Setup su Linux (evitabile distribuendo l'
.exesingle-file portable) o per testare l'.exesu Linux (test, non build). Firma Authenticode fattibile da Linux conosslsigncode.
19.6 Packaging "un sorgente → .exe + AppImage" (multi-architettura)
Da una macchina Ubuntu x86_64 si producono tutti e quattro i target:
| Target | RID | Output | Da x86_64 |
|---|---|---|---|
| Windows x64 | win-x64 |
.exe |
✅ diretto (no Wine) |
| Windows arm64 | win-arm64 |
.exe |
✅ diretto (no Wine) |
| Linux x64 | linux-x64 |
AppImage | ✅ nativo |
| Linux arm64 | linux-arm64 |
AppImage | ✅ via docker buildx + QEMU |
- Binari:
dotnet publish -r <rid> -p:PublishSingleFile=true --self-containedper ciascun RID. Il.exeWindows (x64 e arm64) esce direttamente; niente Wine. - AppImage Linux x64:
dotnet publish -r linux-x64+ PupNet Deploy su Ubuntu. - AppImage Linux arm64: il
dotnet publish -r linux-arm64cross-compila i binari da x86_64, ma l'assemblaggio dell'AppImage (appimagetool/runtime) è arch-specifico → si fa condocker buildxmulti-arch + emulazione QEMU (--platform linux/arm64) nella stessa pipeline, così l'AppImage arm64 viene impacchettato in ambiente arm64 emulato. - Associazione dello schema URI
palladium:; build riproducibili in Docker; firma codice.
19.7 Flusso di test (non serve compilare e lanciare l'app per testare)
Tre livelli, tutti su Ubuntu, il grosso headless:
dotnet test— logica delCoresenza GUI né rete reale: golden vector seed→indirizzi del profilo (confronto 1:1 col wallet di riferimento), costruzione/firma tx, PSBT, coin selection, parsing protocollo e verifica Merkle con server mockato.- CLI (
dotnet run --project src/Cli -- ...) contro regtest/testnet: sync, saldo su xpub watch-only, costruzione tx — flussi reali senza aprire la UI. - GUI solo per rifinire l'interfaccia:
dotnet runcompila+lancia in un comando, con Hot Reload Avalonia e previewer XAML (niente ciclo build-lancia manuale).
Dev-loop (equivalente di npm run dev) — nativo anche su Debian arm64:
dotnet watch --project src/App≈npm run dev: ricompila e applica Hot Reload a ogni salvataggio, con la finestra Avalonia aggiornata dal vivo;dotnet runper il lancio singolo; previewer XAML nell'IDE per le viste.- Su arm64 si sviluppa e si vede la grafica nativamente (.NET SDK
linux-arm64, Avalonia rende con Skia, fallback software se manca l'accelerazione GPU). QEMU non serve per sviluppare/testare — l'emulazione riguarda solo l'impacchettamento di AppImage di un'altra architettura (§19.6). - Prerequisiti runtime su Debian/Ubuntu: ambiente grafico (X11/Wayland) e librerie native di
Avalonia, es.
apt install libx11-6 libice6 libsm6 libfontconfig1 libglib2.0-0 libgl1(più mesa). Per logica/crypto non serve GUI:dotnet teste la CLI girano headless.
Questo blueprint è una specifica completa e indipendente dal linguaggio. I parametri del profilo di rete (§3) e la logica di validazione header/checkpoint (§7) sono gli elementi critici e specifici della catena; tutto il resto è l'ingegneria standard di un wallet SPV desktop. Implementando i capitoli nell'ordine del §16 si ottiene un wallet desktop completo in stile Sparrow.