Usa questa pagina per scegliere la libreria giusta quando interagisci con la chain, per verificare un parametro rispetto a ciò che il nodo impone e per ricalcolare da te un id o un impegno (commitment). Ogni valore qui riportato è quello che il codice esegue sulla chain 20 (fullnode v0.6.8).
Primitive e dove sono usate
| primitiva | parametri | usata per |
|---|---|---|
| Dilithium2 | chiave pubblica di 1.312 byte, firma di 2.420 byte; coppie di chiavi derivate da un seed di 32 byte | voti dei validator e proposte di blocco; mint del faucet; Unbond, Withdraw e la Registration di un validator; i voti di un AdmitValidator (chain 20); le azioni dell’aggregator; l’autorità di mint Key di un token RPL (TokenMint, SetAuthority); le co-firme post-quantistiche dei guardiani del bridge, la sua chiave di pausa e, sulla chain 20, le prove di possesso delle nuove chiavi in una rotazione (sotto) |
| ML-KEM-768 | chiave di incapsulamento di 1.184 byte, testo cifrato di 1.088 byte | sigillare la chiave per-transazione di una busta della nota all’indirizzo del destinatario; sigillare una busta di input di chiamata per un auditor; sigillare un job di proving per un prover abbinato |
| ChaCha20-Poly1305 | chiave di 32 byte, nonce casuale di 12 byte anteposto, tag di 16 byte | ogni parte della busta: corpi delle note, chiavi di transazione incapsulate, trascrizioni degli input di chiamata; i job e le risposte di un prover abbinato |
| BLAKE3 | output di 32 byte, sempre con una stringa di dominio anteposta | indirizzi, id di transazione, il binding della transazione e il binding della chiamata, id dei programmi, id degli asset dei token, la state root e i suoi alberi di Merkle, l’identità p2p, i messaggi di firma, gli id degli asset del bridge, il blinding di un deposito sul bridge e i blinding delle note di commissione del bridge |
| Poseidon2 su Goldilocks | larghezza 8, rate 4, capacità 4, sponge a sovrascrittura senza padding; gli elementi del messaggio sono parole a 32 bit; le 86 costanti di round sono una tabella letterale nel sorgente del nodo (poseidon2_constants.rs) dal cut della chain 15, gli stessi valori che produceva prima l’estrazione con seed | tutto ciò che sta dentro una prova: chiavi, impegni delle note, nullifier, l’albero degli impegni, il digest del programma hc, gli impegni di input H_IN e H_PUB, il digest del bundle, l’impegno di autorizzazione |
| secp256k1 ECDSA + keccak256 | firme low-s, indirizzi dei guardiani di 20 byte in stile Ethereum, mu = keccak256(keccak256(body)) | attestazioni dei guardiani del bridge, così la stessa chiave funziona sui contratti EVM, sul programma Solana e su Rand; su Rand ogni attestazione richiede anche il quorum Dilithium2 qui sotto |
| bech32m (BIP-350) | parte leggibile rpl, payload di 32 byte, 52 caratteri di dati + 6 caratteri di checksum = 62 | la forma testuale rpl1… dell’id dell’asset di un token RPL |
| Plonky3 batch STARK | Goldilocks p = 2⁶⁴ − 2³² + 1, FRI hiding, blowup 8, arità di folding 8, 80 query, 20 bit di proof-of-work | ogni prova del bundle, prova di autenticazione e prova di chiamata; una prova del bundle e la sua prova di autenticazione portano le otto parole di binding della loro transazione come segmento di input pubblico |
I parametri obiettivo del whitepaper differiscono in alcuni punti da quelli che l’implementazione esegue (per esempio l’hash di trascrizione a 384 bit del paper rispetto alla trascrizione Poseidon2 della zkVM). Queste pagine descrivono il codice.
Co-firme post-quantistiche sul bridge
Le attestazioni dei guardiani del bridge sono secp256k1 ECDSA, che un avversario quantistico potrebbe falsificare. Dalla chain 14 ogni BridgeAttest — sia un deposito sia una rotazione del set dei guardiani — deve portare anche un quorum di firme Dilithium2 degli stessi guardiani sullo stesso digest:
M = "rand-bridge-pq-cosign-1" || rand_chain_id (u64 BE) || mu // 63 bytes, deterministic signing
dove mu = keccak256(keccak256(body)) è ciò che firma il quorum ECDSA. Il chain id di Rand in M impedisce che una co-firma di testnet venga verificata su un’altra chain Rand anche se le chiavi dei guardiani fossero riutilizzate. M vincola solo il chain id, anche sulla chain 20: è l’unico messaggio firmato che binding_domain non ha spostato dietro l’hash di genesi, perché i daemon dei guardiani che lo firmano vivono in un altro repository. Una copia di una chain con lo stesso chain id e lo stesso set di guardiani accetterebbe le co-firme dei suoi depositi; l’indice del set di guardiani non è in M, quindi una co-firma sopravvive a una rotazione del set ECDSA. Il campo pq_signatures dell’azione è una lista di PqSignature { index: u8, signature }, verificata prima il meno costoso: quorum(n) ≤ len ≤ n (PqNoQuorum), indici strettamente crescenti (PqIndexOrder), ogni indice inferiore a n (PqIndexOutOfRange), ogni firma esattamente di 2.420 byte (PqBadSignatureLength) e, per ultima, ogni firma verificata con pq_guardians[index] (PqBadSignature). I firmatari PQ non devono coincidere con i firmatari ECDSA; ciascun quorum è contato a sé. Il campo è dentro il binding della transazione, quindi non può essere rimosso né sostituito su una copia.
Il set PQ è il bridge.pq_guardians di genesi — otto chiavi da 1.312 byte sulla chain 20, come sulle chain da 15 a 19, allineate per indice al set ECDSA di genesi, set di guardiani 1 (la chain 14 ne aveva sei, allineate al set 0). Una rotazione del set di guardiani ECDSA non lo sposta mai. Sulla chain 14 era fisso per tutta la vita della chain; dalla chain 15 la genesi porta il gruppo rules_v2 del bridge, con cui un quorum PQ può sostituire l’intero set PQ (RotatePqGuardians) o la chiave di pausa (RotatePauseKey), ciascuno sotto il rotation_nonce del bridge. La genesi della chain 20 aggiunge bridge.rotation: una rotazione deve essere l’azione V2, con la firma Dilithium2 di ogni nuova chiave sullo stesso messaggio (prova di possesso), ed entra in vigore un giorno dopo il suo inserimento, a meno che la chiave di pausa corrente non la annulli (Bridge). rand_getBridgeState restituisce le chiavi e un bridge_attest decodificato elenca pq_signers, gli indici che hanno firmato. Lo stesso quorum PQ autorizza i messaggi di governance del bridge, ciascuno con un layout fisso big-endian che porta il chain id e un nonce. Sulla chain 20 (genesi binding_domain: 1) la cifra di versione di ogni dominio è 2 e l’hash di genesi di 32 byte sta tra il dominio e il chain id; le chain da 14 a 19 usano le forme -1:
| messaggio | dominio (chain 14–19 / chain 20) | firmato da |
|---|---|---|
M_pause | rand-bridge-pause-1 / -2 | l’unica chiave di pausa di genesi (Dilithium2), che può mettere in pausa e mai riattivare |
M_unpause | rand-bridge-pq-unpause-1 / -2 | un quorum di guardiani PQ |
M_list | rand-bridge-pq-list-1 / -2 | un quorum di guardiani PQ (ListBacking) |
M_register | rand-bridge-pq-register-1 / -2 | un quorum di guardiani PQ (RegisterBridgedToken) |
M_rotate_pq | rand-bridge-pq-rotate-pq-1 / -2 | un quorum del set PQ corrente (RotatePqGuardians, chain rules_v2); sulla chain 20 anche ogni nuova chiave, come prova di possesso |
M_rotate_pause | rand-bridge-pq-rotate-pause-1 / -2 | un quorum del set PQ corrente (RotatePauseKey, chain rules_v2); sulla chain 20 anche la nuova chiave |
M_cancel | rand-bridge-cancel-rotation-1 / -2, con un byte kind finale | la chiave di pausa corrente (CancelRotation, chain con bridge.rotation: chain 20) |
Lo STARK in produzione
La zkVM è al constraint set 8: nove tabelle obbligatorie (program, cpu, memory, alu, range, nibble, poseidon2, input, public) più una tabella keccak e una sha256 che una prova porta solo se il suo guest ha chiamato la syscall corrispondente, collegate da diciassette bus e provate come un unico batch STARK. Dal constraint set 7 ogni tabella dichiarata ha almeno 2⁷ righe e il terminale LogUp di ogni tabella è blindato attraverso il diciassettesimo bus, BLIND. L’interfaccia pubblica di una prova è di 35 elementi di campo (pv::NUM): il pc di ingresso, il tier, le otto parole di output, il digest del programma hc (8 parole), l’impegno di input privato con salt H_IN (8), il digest del segmento pubblico senza salt H_PUB (8) e, dal constraint set 8, il limite di gas dichiarato GAS_LIMIT.
| parametro | produzione | nota |
|---|---|---|
| query FRI | 80 | il retune a 27 query dei constraint set 3 e 4 è stato annullato dopo l’audit del 2026-09-12: lasciava ~42 bit provati |
| blowup | 8 (log_blowup = 3) | il grado massimo dei vincoli di ogni tabella è fissato sotto il tetto di 8 |
| arità di folding | 8 | |
| bit di proof-of-work | 20 | |
| soundness | 3·80 + 20 = 260 bit congetturati (ethSTARK); circa 86 bit provati sotto i proximity gaps | |
| zero knowledge | statistica: la LDE e il polinomio batch di FRI sono randomizzati, quindi due prove della stessa esecuzione differiscono | dal constraint set 7 ogni tabella dichiarata ha almeno 2⁷ righe, più degli 82 punti che una prova apre, e i terminali LogUp sono blindati |
| tier | 10, 12, 14, 16, 18, 20 | una prova rivela il tier, mai il numero di cicli; dal fullnode v0.5.6 una prova di chiamata sopra il tier 14 viene rifiutata (CallTierTooHigh), una prova del bundle è fissata al tier 14 e una prova di autenticazione al tier 10 |
| limite della prova | il max_proof_bytes di genesi: 4 MiB (4.194.304) sulle chain da 17 a 20; 8 MiB sulle chain da 13 a 16; 2 MiB (MAX_PROOF_BYTES) su una genesi che ne è priva, come la chain 12 | 2 MiB sta sopra ogni prova senza tabelle hash che i guest distribuiti possono produrre e sotto una che porta keccak; 4 MiB ammette entrambe |
| gas | 1 per riga cpu; 3 per riga di assorbimento Poseidon2; 64 per riga SHA256; 192 per riga KECCAK | accumulato nella colonna GAS della tabella cpu e provato al massimo GAS_LIMIT; il verifier rifiuta un limite superiore a gas_max(t, k, s) = (2ᵗ − 1) + 2ᵗ⁻² + 191·(2ᵏ/32) + 63·(2ˢ/64), che vale 1.279 per un header di tier 10 senza hash e 20.479 per uno di tier 14 |
Dimensioni misurate al constraint set 6 (Apple Silicon, build release): una prova di produzione senza keccak era di 1.298.729 byte al tier 10 e di 1.359.978 al tier 12; una prova al tier 10 con keccak era di 3.198.430 byte, oltre i 2 MiB predefiniti e sotto gli 8 MiB delle chain da 13 a 15. Una prova al tier 14 della guest bundle 2-in-2-out ritirata misurava 1.321.773 byte sulla chain 8, e da 1.418.406 a 1.420.423 byte sulla chain 13. La guest bundle 4-in-4-out ad asset nascosto della chain 14 resta al tier 14 senza alcuna tabella hash, e le sue prove misuravano 1.422.116 e 1.423.170 byte sulla chain 14 (2026-09-20); la chain 15 ha fissato la stessa guest (hc_bundle invariato). Lì una prova bundle dichiarava public_log_height 4, l’altezza delle otto parole di binding, e il nodo rifiutava qualsiasi altro valore prima di costruire una chiave del verificatore. La prova della chiamata ERC-20 approve con keccak, prodotta sulla chain 13 il 2026-09-19 (tier 16), è di 3.412.405 byte; ogni chain dalla fullnode v0.5.6 in poi rifiuta quella chiamata, al tier 16.
Le colonne di blinding e i floor delle tabelle del constraint set 7 aggiungono circa il 5% a una prova senza hash: misurato dalla fullnode il 2026-09-28, fib è di 1.367.688 byte al tier 10 e di 1.424.299 al tier 12, una prova al tier 10 con keccak di 3.283.898, e una prova bundle ad asset nascosto al tier 14 di 1.498.821 (guest v1) e 1.497.156 (guest v2). Da allora una prova bundle dichiara public_log_height 7. Il constraint set 8 aggiunge meno dell’1%. Misurato sulla chain 18 il 2026-09-30 (Apple Silicon): prove di autorizzazione da 1.364.940 a 1.375.371 byte (tier 10), prove bundle da 1.494.151 a 1.504.260 byte (tier 14, guest v3) e prove di chiamata di 1.498.589 byte al tier 14 senza tabella hash, 1.911.152 al tier 14 con la tabella SHA-256 e 3.346.865 al tier 12 con la tabella Keccak. Tutte rientrano nel limite di 4 MiB delle chain da 18 a 20.
La verifica richiede circa 16 ms con una chiave del verificatore già in cache e circa 230 ms la prima volta che si costruisce una chiave (tier, heights). Il profilo FRI test (16 query) esiste per la suite di test ed è insicuro; il genesis della chain 20 fissa production. La fullnode v0.6.8 non modifica alcun vincolo: la chain 20 fissa gli stessi hc_bundle e hc_auth delle chain da 17 a 19.
Costruzioni hash riproducibili
BLAKE3 con un dominio: blake3(domain || data), con la stringa di dominio senza separatore.
Il dominio di binding. Il genesis della chain 20 imposta binding_domain: 1 (fullnode v0.6.8, audit v6 BIND-1). Su una chain di questo tipo ogni binding di prova e ogni messaggio di azione firmato che legava il solo chain id lega ora anche l’hash del genesis: il numero di versione del dominio aumenta di uno e l’hash del genesis di 32 byte va per primo nella preimmagine, prima del chain id. Una prova o una firma prodotta per una chain non si verifica quindi su nessun’altra, nemmeno su una che riusi il chain id e le chiavi, come fa un re-cut. Le parole di binding sono un input pubblico delle prove, quindi nessuna guest né chiave del verificatore è cambiata. La tabella riporta entrambe le forme; le chain da 14 a 19 usano la prima, byte per byte. Già legati al genesis prima, e invariati: voti e proposte (da consensus_domain: 1), la Registration v2 e un voto AdmitValidator. Non spostata: la co-firma di mint del bridge (sopra). Un wallet richiede la v0.6.8 per inviare sulla chain 20 e decide la forma in base al chain id, non a ciò che un nodo dichiara; rand_getLimits.binding_domain la riporta.
| valore | costruzione |
|---|---|
| indirizzo trasparente | blake3("rand-address" || dilithium2_public_key), base58 |
| id della transazione | blake3("rand-txid-3" || bincode(view)), dove view è la transazione con i byte della prova del bundle sostituiti da blake3(proof) e la sua prova di autorizzazione da blake3(auth_proof); auth_commit entra così com’è. Il dominio era rand-txid-2, senza campi di autorizzazione, fino alla chain 16 |
| binding della transazione | blake3("rand-tx-bind-1" || bincode(chain_id, bundle', action')) sulle chain da 14 a 19; blake3("rand-tx-bind-2" || bincode(genesis_hash, chain_id, bundle', action')) sulla chain 20. Otto parole u32 little-endian, dove ' sostituisce bundle.proof, bundle.auth_proof e la proof di un Aggregate con il vettore vuoto; bincode con interi a larghezza fissa little-endian. Ogni prova del bundle e ogni prova di autorizzazione è prodotta su queste parole e verificata rispetto a esse |
| binding della chiamata | blake3("rand-call-bind-1" || …), oppure rand-call-bind-2 con l’hash del genesis per primo sulla chain 20: la costruzione del binding della transazione con anche la proof propria della Call (o dell’Invoke) svuotata. In un genesis hardening_v6, come la chain 20, il segmento pubblico di una prova di chiamata è formato dalle parole pubbliche del programma fissate al deploy seguite da queste otto parole, e quello di un Invoke aggiunge dopo di esse la propria transizione come parole di contesto |
| id del programma | blake3("rand-program" || base_pc as 4 LE bytes || words as 4 LE bytes each) |
| identità p2p | chiave ed25519 da blake3("rand-p2p-identity" || seed) |
| id dell’asset del bridge (per backing) | blake3("rand-bridge-asset" || token_chain as 2 BE bytes || token_address (32 bytes)) — rand_bridgeAssetId lo calcola e rand_getAssets lo stampa per ogni riga di backing; identifica una moneta di origine sulla rete, non il token |
| id dell’asset del token RPL, nativo | blake3("rand-rpl-asset" || bincode(name, symbol, decimals, authority, initial: Option<InitialMint>, salt)), con salt di 32 byte scelti dal creatore; mostrato in esadecimale e come rpl1… |
| id dell’asset del token RPL, bridged | blake3("rand-rpl-asset" || bincode(name, symbol, BRIDGE_DECIMALS, salt)) — non calcolato su una coppia (chain, token), poiché un token bridged copre più backing |
| blinding del deposito del bridge | r = blake3("rand-deposit-r-1" || mu), l’unico r che l’ammissione accetta per un BridgeAttest (altrimenti WrongDepositBlinding) |
| blinding delle note di commissione del bridge (chain 20) | la nota di commissione di un deposito: r = blake3("rand-bridge-fee-r-1" || mu); quella di un burn: r = blake3("rand-bridge-burn-fee-r-1" || txid); entrambi letti come otto parole little-endian. Le note non hanno busta: ogni campo è pubblico, essendo il proprietario il bridge.fees.recipient del genesis |
| destinatario del bridge | blake3("rand-shielded-recipient" || pk_bytes || kem_ek) sull’intero indirizzo schermato |
messaggio Mint del faucet | blake3("rand-mint-2" || bincode(chain_id, cm, pk, time, r, envelope, amount)); sulla chain 20 blake3("rand-mint-3" || bincode(genesis_hash, chain_id, cm, pk, time, r, envelope, amount)) |
messaggi TokenMint, SetAuthority | blake3("rand-rpl-mint-1" or "rand-rpl-authority-1", chain_id || asset_id || nonce || body); il body di un mint include blake3(bincode(envelope)). Sulla chain 20 rand-rpl-mint-2 e rand-rpl-authority-2, con l’hash del genesis per primo |
messaggio Registration | blake3("rand-register-2" || bincode(genesis_hash, chain_id, validator, payout)) in un genesis con staking.registration_v2 o binding_domain: 1, come la chain 20 (lì una registrazione v1 viene rifiutata); blake3("rand-register" || bincode(chain_id, payout)) altrove |
voto AdmitValidator (chain 20) | blake3("rand-admit-validator-1" || genesis_hash || candidate_address), firmato da ciascun validator votante |
messaggio Unbond | blake3("rand-unbond" || bincode(chain_id, validator, amount, nonce)); sulla chain 20 blake3("rand-unbond-2" || bincode(genesis_hash, chain_id, validator, amount, nonce)) |
messaggio Withdraw | blake3("rand-withdraw" || bincode(chain_id, validator, amount, nonce, time, r, envelope)); sulla chain 20 rand-withdraw-2, con l’hash del genesis per primo |
| nodo di Merkle (alberi di stato) | blake3("rand-merkle-node" || left || right) |
| foglia del registro dei token | blake3("rand-token-leaf-1" || bincode(TokenInfo)), in ordine di indice, sotto tokens_root |
| radice di stato | sulla chain 20, blake3("rand-state-admitted-1" || inner || admitted_root) attorno a inner = blake3("rand-state-8" || tree_root || nullifier_root || validators_root || programs_root || bridge_root || tokens_root || faucet_epoch || faucet_minted_in_epoch || bond_queue_root || gas_price || byte_price || program_state_root), dove program_state_root = blake3("rand-program-state-1" || cells_root || vaults_root) (RPL-2), i due contatori del faucet e i due prezzi correnti sono di 8 byte big-endian ciascuno, e il wrapper impegna l’insieme degli ammessi (staking.admission_by_vote). Quella della chain 19 era blake3("rand-state-7" || …) sugli stessi campi fino a byte_price (una sezione staking del genesis aggiunge i tre dopo tokens_root sotto rand-state-5, come sulle chain da 15 a 17; una sezione gas.dynamic del genesis aggiunge i due prezzi e sposta il dominio a rand-state-7); rand-state-4 sui primi sei sulla chain 14; rand-state-2 sui primi quattro su una chain senza sezione bridge, tokens o aggregation (Consenso) |
Poseidon2 con un tag di dominio: H(domain, msg) = sponge_hash([domain, msg...]), con il tag come prima parola assorbita, ogni parola un elemento di Goldilocks, il digest di 4 elementi suddiviso in otto parole u32 (metà bassa poi metà alta di ciascun elemento). Tag di dominio:
| tag | valore | costruzione |
|---|---|---|
NK | 1 | chiave di visualizzazione nk = H(1, sk) |
PK | 2 | valore pubblico della nota pk = H(2, nk) |
NF | 3 | nullifier H(3, nk || cm) |
CM | 4 | commitment della nota H(4, pk(8) || from(8) || amount_lo || amount_hi || asset || time || r(8)) — 28 parole |
OVK, KEM_SEED | 5, 6 | la chiave di visualizzazione in uscita e il seed ML-KEM, tramite un hash esteso in modalità contatore [domain, nk, counter] |
NODE | 7 | nodo dell’albero H(7, left || right); la foglia vuota è composta da soli zeri |
HC | 8 | il digest del programma; il tag, base_pc e len stanno nelle corsie di capacità della prima permutazione, poi le parole vengono assorbite quattro per blocco |
OUT | 9 | il digest di output del guest di trasferimento |
IN | 10 | H_IN: intestazione di capacità [10, n_in, 0], poi un salt di 4 parole, poi gli input |
BUNDLE | 11 | il digest del bundle 2-in-2-out ritirato, su 47 parole pubbliche; nessuna chain fissa più quel guest |
| hidden bundle | 64 | il digest del bundle con asset nascosto, su 81 parole nelle chain da 14 a 16: ancora, quattro nullifier, quattro commitment, fee, burn_a, burn_r (due parole ciascuno), burn_asset, time e, per ultima, la parola di taint. Nelle chain da 17 a 20 (guest del bundle v3) le parole sono 89: le otto parole del commitment di autorizzazione c si trovano immediatamente prima della parola di taint. L’asset privato A non ne fa parte. Il tag è locale al nodo e sta ben distante dai tag da 1 a 15 importati |
AUTH | 65 | il commitment di autorizzazione c = H(65, nk || salt), 16 parole, con un salt fresco di 256 bit per ogni bundle; pubblicato dalla prova del bundle all’interno del suo digest e dalla prova di autorizzazione come le sue otto parole di output, e trasportato dal bundle come auth_commit (chain da 17 a 20). Locale al nodo, come 64 |
PUB | 15 | H_PUB: intestazione [15, n_pub, 0], nessun salt; per un programma, sulla chain 20 le parole sono fissate al deploy (al massimo 32.768), il segmento di ogni chiamata è composto da quelle parole seguite dalle otto parole del binding della chiamata, e la chiamata viene verificata rispetto al digest di quel segmento; per una prova di bundle e una prova di autorizzazione il segmento è formato dalle otto parole di binding della transazione; un genesis senza max_program_public_words ammette soltanto il segmento vuoto |
hc, H_IN e H_PUB non sono semplici spugne con prefisso di messaggio: l’intestazione entra nella capacità, in modo che le righe del digest nella tabella cpu assorbano esattamente quattro parole per permutazione. Riproducili con il crate importato (randprotocol_zkvm::hash::{input_digest, public_digest}, isa::Program::digest) invece che a mano.
La spugna semplice non applica padding, quindi all’interno del primo blocco [a] e [a, 0] producono lo stesso hash. Ogni costruzione qui sopra calcola l’hash di un messaggio di lunghezza fissa sotto un proprio tag. Per i dati la cui lunghezza può variare, l’insieme di vincoli 7 ha aggiunto una spugna vincolata alla lunghezza (hash::sponge_hash_len, la syscall POSEIDON2_LEN): parte dallo stato [0, 0, 0, 0, n, 0, 0, 0], con n il numero di parole, e permuta almeno una volta. È un hash diverso delle stesse parole, e nessuna nota, nullifier, radice o digest della chain lo utilizza.
Due proprietà da ricordare: hc è vincolante ma non nascondente (nessun salt, quindi un programma ipotizzato può essere confermato e due deploy dello stesso programma sono collegabili), mentre H_IN è nascondente oltre che vincolante (un salt fresco di 128 bit per ogni prova), quindi pubblicare H_IN non rivela nulla sugli input finché chi detiene il salt non lo apre.
Derivazioni delle chiavi
| chiave | da |
|---|---|
| coppia di chiavi Dilithium2 (nodo) | deterministica a partire dal seed di 32 byte |
| libp2p ed25519 (nodo) | blake3("rand-p2p-identity" || seed) |
chiave di visualizzazione, pk, ovk, coppia di chiavi ML-KEM (wallet) | derivazioni Poseidon2 della chiave di spesa, come nella tabella sopra; la coppia ML-KEM è MlKem768::from_seed(kem_seed) |
I paper nella pagina dei paper contengono gli argomenti di sicurezza: le scelte post-quantistiche, il calcolo della solidità di FRI e il motivo per cui si mantengono 80 query, e il limite sulla lunghezza della traccia.