Usa questa pagina per dimensionare una macchina di proving, per capire perché un trasferimento richiede oltre un minuto e perché a limitare il throughput è lo spazio nei blocchi e non il calcolo, e per sapere che cosa si rompe quando cambia il sistema di prova. Tutto ciò che un validator accetta è sostenuto da una prova che ha verificato in prima persona.
Che cosa afferma una prova
Una sola relazione, per ogni programma eseguito dalla chain:
Questo programma RV32IM, avviato a
base_pc, eseguito su un vettore di input privato impegnato daH_INe su un segmento di input pubblico impegnato daH_PUB, si è arrestato entro2ᵗ − 1cicli, ha speso al massimoGAS_LIMITdi gas e ha pubblicato queste otto parole di output.
Il programma è identificato dal suo digest in-circuit hc; il verificatore non vede mai una parola di istruzione. Un trasferimento shielded è questa relazione applicata alla hidden-asset bundle guest, un programma 4-in-4-out assemblato a mano il cui hc è fissato nel file di genesi come hc_bundle. La chain 20 fissa la guest v3 (guests::bundle_hidden_v3, 60af094a…6e3fce, dalla chain 17). Le chain 14 e 15 fissavano la v1 (83d3a370…cd0ef8) e la chain 16 la v2 senza rami (651043e2…839b). Dalla chain 17 ogni bundle porta anche una seconda prova, quella della auth guest (guests::auth, genesi hc_auth, 1e4e347f…5639c1): la prova del bundle prende la viewing key, e la prova auth dimostra che il mittente detiene la spend key che le corrisponde. È l’autorizzazione divisa, ed è ciò che permette a un prover associato che detiene solo una viewing key di produrre la prova del bundle. La hidden-asset guest ha sostituito la guest bundle 2-in-2-out delle chain fino alla 13, che sopravvive nel fullnode solo per i test e che nessuna chain fissa. Una chiamata confidenziale è la stessa relazione applicata a un programma distribuito (Programs).
Come il wallet produce la prova di un bundle
rand send <rand1…> <amount> svolge il lavoro privato in locale, e sulla chain arrivano solo prove, impegni, nullifier e envelope sigillati:
- Scansione dell’albero con la viewing key e scelta degli input: al massimo due note RAND che coprono l’importo più la commissione negli slot 2–3, e per un trasferimento o un burn di token al massimo due note del token negli slot 0–1, con le note RAND che coprono la sola commissione. Uno slot di input non usato è un dummy: importo 0, di proprietà del wallet, con il fallimento di appartenenza mascherato nel circuito e il nullifier comunque pubblicato. Dalla guest v2 la guest è senza rami: il percorso di un dummy viene sottoposto a hash su tutti i 32 livelli come quello di una nota reale.
- Recupero dell’anchor di testa (
rand_getAnchor) e del witness di Merkle a 32 livelli di ogni input reale (rand_getWitness(index)), verificando la radice restituita rispetto all’anchor. - Costruzione di quattro output: la nota del destinatario e la nota di resto nel gruppo che sposta valore, presenti anche a zero, e dummy a importo zero altrove, sigillati a una chiave usa e getta.
- Sigillatura di ogni output in un envelope (ML-KEM-768 verso il destinatario, più la chiave della transazione incapsulata sotto l’
ovkdel wallet), assemblaggio dell’intera transazione con la sua azione e calcolo del suo binding:blake3("rand-tx-bind-1" || …)sulla transazione con le prove azzerate, otto parole (Transactions). Sulla chain 20, la cui genesi impostabinding_domain: 1, èblake3("rand-tx-bind-2" || …)con prima l’hash di genesi, poi l’id della chain, così una prova prodotta per una chain non si verifica su nessun’altra, nemmeno su una con lo stesso id di chain. Un wallet precedente alla v0.6.8 usa il vecchio binding, e la chain 20 rifiuta le sue prove. - Autorizzazione: estrazione di un nuovo salt a 256 bit e prova della auth guest sul suo input privato di 16 parole, la spend key e il salt, con il binding come segmento di input pubblico, al tier 10. Deriva
nkdalla spend key e pubblicac = H(AUTH, nk ‖ salt), che il bundle porta comeauth_commit. - Prova della bundle guest sul suo input privato di 1.212 parole (la viewing key
nk, quattro slot di input con i loro percorsi, l’anchor, quattro output,fee,burn_a,burn_r, l’asset privatoA,time, il salt) con lo stesso binding come segmento di input pubblico, al tier 14. La prova dimostra la proprietà, l’appartenenza, che ogni input reale porti l’asset del proprio slot, i quattro nullifier, lo stessoc, e i due bilanciin₀ + in₁ = out₀ + out₁ + burn_aein₂ + in₃ = out₂ + out₃ + fee + burn_r. È la prova che un prover associato può produrre al posto del wallet; la prova auth viene prodotta sulla macchina del wallet stesso. - Verifica del digest pubblicato dalla prova rispetto a quello calcolato dal testo in chiaro, e invio di
Transaction { chain_id, bundle, action: None }.
L’ordine conta dalla chain 14: gli envelope e l’azione esistono prima delle prove, perché le prove si impegnano su di essi. Per una chiamata, la prova della chiamata viene prodotta per prima e rientra anch’essa nel binding. Su una chain hardening_v6 la prova della chiamata è a sua volta prodotta su un binding della chiamata della transazione con entrambe le prove azzerate (rand-call-bind-1 sulle chain da 16 a 19, rand-call-bind-2 con l’hash di genesi sulla chain 20), che copre i nullifier del bundle delle commissioni, così non può essere copiata sotto un altro bundle.
proving bundle (tier 14; about a minute on a laptop)…
proved in 98.3s: tier 14, 1423170 bytes
submitted transfer 4f2c… 1.5 RAND out, 98.499 RAND change, fee 0.001 RAND, anchored at height 192
Il transcript è il formato di output del wallet tratto dalla guida del fullnode alla chain 14; la dimensione in byte mostrata è quella di una prova di bundle con profilo di produzione registrata sulla chain 14. Il wallet dalla chain 17, v0.6.8 sulla chain 20 inclusa, stampa due righe prima di queste, proving the spend authorisation on this machine (tier 10; seconds)… e authorisation proved in …: tier 10, … bytes, e formula la riga del bundle come proving the bundle (tier 14; about a minute and a half on a laptop)….
Lo stesso meccanismo paga ogni azione, sempre con esattamente un bundle: un deploy, una chiamata, una registrazione di token o un mint di token viaggiano su un auto-trasferimento di RAND a valore zero, un bond su un bundle che brucia la stake tramite burn_r, e un burn di token o un burn di bridge su un bundle che brucia l’asset dagli slot 0–1 (burn_a, burn_asset) e paga la commissione in RAND dagli slot 2–3. L’asset che un trasferimento sposta è una parola del witness e non compare in nessun campo pubblico.
Quanto costa
Misurati sul laptop di sviluppo (Apple Silicon, build release), i numeri registrati nei documenti del fullnode:
| guest | parole | cicli | tier | proving | dimensione della prova (produzione, 80 query) |
|---|---|---|---|---|---|
| bundle guest v3 (chain da 17 a 20) | — | 4.024 cicli e 273 permutazioni Poseidon2 di margine nel budget del tier 14 | 14 | ≈ 100 s, 5,7 GB di picco; da 102,5 a 134,0 s misurati sulla chain 18 (2026-09-30) | ≈ 1,50 MB; da 1.494.151 a 1.504.260 byte misurati sulla chain 18 (2026-09-30) |
| auth guest (chain da 17 a 20) | — | 250 | 10 | ≈ 7 s; da 6,6 a 19,9 s misurati sulla chain 18 (2026-09-30) | ≈ 1,37 MB; da 1.364.940 a 1.375.371 byte misurati sulla chain 18 (2026-09-30) |
| hidden-asset bundle v1, 4-in-4-out (chain 14 e 15) | — | sotto il budget del tier 14 con circa 2.071 cicli (13%) di margine | 14 | ≈ 98–100 s, 5,7 GB di picco | ≈ 1,43 MB; 1.422.116 e 1.423.170 byte misurati sulla chain 14 |
bundle, 2-in-2-out (ritirata; chain fino alla 13) | 3.811 | ≈ 9.160 | 14 | ≈ 100 s (94,6–97,9 s da sola; 114 s ciascuna per due insieme) | 1.321.773 byte misurati sulla chain 8 |
private_payment (una chiamata) | poche | < 1.000 | 10 | ≈ 7 s | ≈ 1,37 MB (fib al tier 10: 1.367.688 byte con il constraint set 7; 1.298.729 con il set 6) |
| una chiamata senza tabella hash (off-chain ledger, chain 18) | 773 | — | 14 | 114,8 s | 1.498.589 byte |
| una chiamata con la tabella SHA-256 (proof of liabilities, chain 18) | 994 | — | 14 | 122,9 s | 1.911.152 byte |
| una chiamata con la tabella Keccak (anonymous vote, chain 18) | — | — | 12 | 29,2 s | 3.346.865 byte |
La verifica è il costo di consenso, pagato da ogni nodo: circa 16 ms con una verifier key calda, circa 230 ms la prima volta che si costruisce una chiave per una data forma. La verifier key non dipende dal contenuto del programma — è indicizzata da (tier, program_log_height, input_log_height, keccak_log_height, sha256_log_height, public_log_height) — quindi un nodo ne costruisce una per forma e la riutilizza; per un programma distribuito la chiave viene calcolata una sola volta in background al momento del deploy (circa 2 s su un laptop, 7 s su un server con 2 vCPU). Il bundle 2-in-2-out della chain 13 e precedenti dichiarava la forma program 12, input 10, keccak 0, sha256 0, public 2, mem 16; una prova di bundle della chain 14 dichiara public 4, l’altezza delle otto parole di binding, non porta alcuna tabella hash, e viene rifiutata prima che venga costruita qualsiasi verifier key se dichiara un altro tier, una delle due tabelle o un’altra altezza pubblica. Dal constraint set 7 ogni tabella dichiarata ha almeno 2⁷ righe, quindi una prova di bundle della chain 20 dichiara public 7.
Una trasferimento sulla chain 20 porta quindi circa 2,87 MB di prova, la prova del bundle e la prova di autorizzazione, e una chiamata una terza prova in più. Ciascuna deve rientrare nel max_proof_bytes del genesis, 4.194.304 (4 MiB) sulla chain 20, come sulle chain da 17 a 19, in calo rispetto agli 8 MiB delle chain da 13 a 16.
Il guest a asset nascosto rientra nel livello 14 solo perché legge i propri input privati in un ciclo e fonde le letture dei nodi fratelli del controllo di Merkle; scritta nel vecchio stile srotolato, la stessa relazione finisce al livello 16, con circa 400 s e 21–22 GB, il che escluderebbe i wallet da 16 GB.
La generazione delle prove è limitata dalla CPU, e oggi il wallet usa il backend CPU su ogni piattaforma. Nelle esecuzioni sui livelli grandi il prover era a thread singolo: un droplet da 16 vCPU girava al 99% di un solo core, e a decidere se una prova arrivasse a termine era la memoria, non i core (memoria di proving). Il flag --cuda su send, bond, call, deploy, bridge-mint e bridge-burn seleziona un backend NVIDIA che richiede una build con --features cuda. I suoi kernel sono girati per la prima volta su hardware reale, una NVIDIA H100, il 2026-09-28, e hanno coinciso con il riferimento CPU, ma nel checkout dei circuits che la release include non è committato alcun PTX, quindi la build fallisce con no PTX for the GPU kernels finché i kernel non vengono compilati. Nessuna prova di produzione è stata misurata su un nodo GPU della flotta. Non c’è di proposito alcun ripiego sulla CPU. Una chiamata CUDA non può nemmeno sigillare una busta di input, perché il salt non lascia mai il prover. Il picco di memoria per una prova di bundle a asset nascosto di livello 14 è di circa 5,7 GB (Production FRI, CPU); le classi di memoria più grandi riguardano le prove dell’interprete e della ricorsione più sotto (≥ 64 GB e oltre).
Come verifica un nodo
L’ammissione esegue prima i controlli economici (Transazioni), poi:
- ricalcola il digest del bundle dal testo in chiaro pubblicato (ancora, quattro nullifier, quattro impegni,
fee,burn_a,burn_r,burn_asset,time, l’auth_commitdel bundle e una parola di taint fissata a zero) e richiede che sia uguale a quello pubblicato dalla prova — una prova il cui witness ha violato la relazione pubblica un digest contaminato che non corrisponde ad alcun testo in chiaro. Alcuni controlli sono invece strutturali (il guest fornisce da sé mittente, asset e tempo di un output, quindi un prover non può sceglierli), e l’asset privato non è nel digest; - decodifica la prova e ne verifica le altezze dichiarate rispetto al livello (
check_declared_heights), così il limite della chain sulla forma di una prova è quello del verificatore. Prima che venga controllata qualsiasi firma o prova, su ogni transazione inviata o diffusa via gossip (e, conhardening_v6, nella validazione dei blocchi) gira un filtro di prova canonica; dal fullnode v0.6.8 (audit v6, ZKV-4) quel filtro limita prima ogni grado dichiarato a 25 bit (MAX_HONEST_DEGREE_BITS, il massimo della tabella della memoria più uno), così un’intestazione con un grado enorme non trattiene più un nodo mentre il programma di folding onesto viene ricalcolato per essa, e un panic dentro il filtro rifiuta quella transazione invece di fermare il nodo; - calcola il binding della transazione ed esegue
Machine::verify_public(hc_bundle, &binding, proof)— il verificatore batch più il controllo cheH_PUBsia il digest di quelle otto parole, così una prova copiata su una transazione con un’altra azione, un’altra busta o un altro chain id, o sulla chain 20 sul genesis di un’altra chain, non si verifica (fino alla chain 13 il segmento era vuoto e nulla legava una prova alla sua transazione); - verifica la prova di autorizzazione rispetto a
hc_authe allo stesso binding, e richiede che lacche pubblica sia uguale adauth_commit. Un bundle senza prova di autorizzazione è rifiutato (AuthMissing), e lo è anche uno la cuicdifferisce (AuthMismatch); - richiede che il
GAS_LIMITdella prova del bundle sia uguale albundle_gas_limitdel genesis, 20.479, e quello della prova di autorizzazione a 1.279, i tetti di intestazione dei due guest (BundleGasLimit,AuthGasLimit); - per una chiamata, esegue lo stesso controllo rispetto al
code_hashmemorizzato del programma, con le parole pubbliche del programma seguite dal binding della chiamata come segmento (unInvokeRPL-2 aggiunge la propria transizione come parole di contesto, Programmi), poi verifica la commissione rispetto al limite di gas che la prova dichiara e ai suoi byte (Commissioni).
Una transazione inviata via RPC o gossip viene verificata su uno di quattro worker dietro una coda profonda 64, fuori dal ciclo di consenso, e rilanciata via gossip solo dopo che è stata verificata; un token bucket per peer (burst 16, ricarica 4 al secondo) regola quanto un peer può far verificare a un nodo, e una cache da 8.192 voci risponde gratis alla ripetizione di una transazione rifiutata in modo permanente. La verifica delle prove dentro un blocco proposto gira ancora sul ciclo di consenso quando il blocco viene applicato. Un nodo che si sincronizza riverifica ogni certificato e ogni prova di ogni blocco prima di accettarlo; nulla è considerato attendibile solo perché un quorum lo ha firmato.
Livelli
| livello | budget di cicli (2ᵗ − 1) | righe cpu | usato da |
|---|---|---|---|
| 10 | 1.023 | 2¹⁰ | il guest di autorizzazione; private_payment, fib |
| 12 | 4.095 | 2¹² | |
| 14 | 16.383 | 2¹⁴ | il guest di bundle a asset nascosto (e il guest bundle ritirato); la chiamata più grande |
| 16 | 65.535 | 2¹⁶ | la prova di chiamata EVM nella suite di test; l’approve ERC-20 tradotto (chiamato sulla chain 13) |
| 18 | 262.143 | 2¹⁸ | transfer e transferFrom ERC-20, tradotti o interpretati |
| 20 | 1.048.575 | 2²⁰ | SPL Token, tradotto o sul guest interprete sBPF |
Dal fullnode v0.5.6 (2026-09-25) una prova di chiamata oltre il livello 14 è rifiutata (CallTierTooHigh) prima che venga costruita una chiave del verificatore, e un blocco che ne contiene una non è valido; una chiamata può inoltre portare al massimo 128 permutazioni Keccak-f e 128 compressioni SHA-256. I livelli da 16 a 20 si dimostrano ancora, ma solo off chain: nessuna delle righe sopra il livello 14 può essere chiamata sulla chain 20, e la chain 20 rifiuta il deploy di un programma troppo grande per qualsiasi chiamata di livello 14, cioè con più di 8.180 parole senza un input pubblico (ProgramUncallable) (il budget).
Il prover sceglie il livello più piccolo il cui budget copre i cicli più le righe del programma e del digest degli input; un’esecuzione che non rientra fallisce prima della dimostrazione. Solo il livello è pubblico. Ogni passo quadruplica più o meno il tempo di proving e aggiunge poco alla dimensione della prova. Sulla chain 20 la commissione di una chiamata segue il limite di gas che la sua prova dichiara e la sua dimensione in byte, non il livello (Commissioni).
Insiemi di vincoli e hard fork
Un insieme di vincoli è l’insieme esatto di tabelle, colonne, bus, valori pubblici e parametri FRI che il verificatore controlla. Una prova prodotta con un insieme non si verifica con un altro, in nessuna delle due direzioni, e il replay di avvio di un nodo riverifica ogni prova della sua chain — quindi un nodo costruito da un insieme diverso fallisce alla prima prova e tronca. Per questo ogni modifica dell’insieme viene rilasciata come nuovo chain id con tutti i nodi su una sola build, e per questo rand_status riporta hc_bundle e hc_auth e un nodo la cui build non concorda con il genesis rifiuta di avviarsi.
| insieme | data | cosa è cambiato |
|---|---|---|
| 2 | 2026-09-10 | cinque correzioni di soundness dopo la prima revisione |
| 3 | 2026-09-11 | chip Poseidon2, hc in-circuit, la tabella del programma come witness, memoria sub-word, RV32M, FRI riaccordato a 27 query |
| 4 | 2026-09-11 | l’impegno di input con salt H_IN con la propria tabella; il loader di binari flat |
| 5 | 2026-09-12 | la tabella keccak facoltativa; altezza di memoria dichiarata dalla prova; due correzioni critiche dall’audit zk; FRI di nuovo a 80 query; MAX_PROOF_BYTES a 2 MiB |
| 6 | 2026-09-14 | la tabella public obbligatoria e H_PUB; la tabella sha256 facoltativa; i guest interpreti EVM e sBPF come librerie; 34 valori pubblici. Ciò che hanno eseguito le chain da 12 a 15. |
| 7 | 2026-09-28 | ogni terminale LogUp oscurato tramite il bus BLIND; ogni tabella dichiarata con un minimo di 2⁷ righe; range check a 32 bit su parole di input, pubbliche e di salt; la syscall POSEIDON2_LEN (7); JALR azzera il bit 0 del proprio target e richiede funct3 = 0; chiavi del verificatore con salt da key_derivation_v2. Ciò che hanno eseguito le chain 16 e 17. |
| 8 | 2026-09-29 | il contatore del gas: la colonna GAS nella tabella cpu e il valore pubblico GAS_LIMIT; 35 valori pubblici. Ciò che eseguono le chain da 18 a 20. |
Le chain 14 e 15 non hanno cambiato alcun vincolo. Il nodo della chain 15 tiene le 86 costanti di round di Poseidon2 come tabella letterale invece che come estrazione da seed (audit ZKV-2) — gli stessi valori, quindi nessun hash, digest o prova si è mosso. Chain 14: il bundle a asset nascosto è un nuovo guest (un nuovo hc_bundle) e il binding della transazione usa il segmento pubblico che l’insieme 6 già lega in circuito. È comunque un hard fork — il formato di rete del bundle, il guest fissato e ogni id di transazione sono cambiati, una transazione della chain 13 che porta un bundle è rifiutata dalla nuova build, e un wallet costruito prima del fork produce prove a segmento vuoto che la chain rifiuta.
Le tre chain successive hanno ciascuna cambiato che cosa sia una prova. La chain 16 (fullnode v0.6.1, 2026-09-28) è passata al constraint set 7, ha fissato il bundle guest v2 privo di ramificazioni e ha impostato hardening_v6, dopo che la revisione del 2026-09-27 aveva mostrato che tabelle corte e terminali LogUp non mascherati facevano trapelare dati privati (How the zkVM works). Ogni chiave del verifier è cambiata. La chain 17 (v0.6.3, 2026-09-29) ha mantenuto il set 7 e ha aggiunto l’autorizzazione separata: bundle guest v3, l’auth guest, due nuovi campi nel formato di trasmissione del bundle e il dominio dell’id di transazione rand-txid-3. La chain 18 (v0.6.7-rc1, 2026-09-29) è passata al constraint set 8 per il gas meter. Il suo costo misurato in dimensione della prova è inferiore all’1%. La chain 19 (2026-10-01) è una re-genesi della chain 18 sulla stessa build v0.6.7 e non ha cambiato nulla nelle prove. La chain 20 (fullnode v0.6.8, 2026-10-01) mantiene il constraint set 8 e gli stessi guest e le stesse chiavi del verifier, e cambia ciò a cui una prova è vincolata: i binding della transazione e della chiamata portano l’hash di genesi (binding_domain: 1), un input pubblico che il wallet e il ledger calcolano, quindi nessun circuito si è spostato. È comunque un hard fork, perché le prove di un wallet v0.6.7 non vengono verificate su di essa. Ogni build rifiuta le chain precedenti in base all’hash di genesi.
Due note di audit riportate nel codice e che vale la pena conoscere: il valore pubblico TIER viene controllato dal verifier rispetto all’intestazione della prova e ai degree bits del batch, ma non è vincolato dal circuito stesso (audit ZL1, segnalato per il set successivo anziché corretto, perché rimuoverlo sposta il layout dei valori pubblici); e H_IN è un impegno visibile al guest che il verifier non confronta con un valore fornito dal chiamante, per scelta progettuale.
Upcoming: block aggregation
A circa 1,43 MB per prova di bundle con asset nascosto sulle chain 14 e 15, un blocco da 4 MiB (il valore predefinito, e quello della chain 12) conteneva due trasferimenti shielded; ne conteneva tre con il bundle 2-in-2-out da ~1,3 MB. Le chain 13, 14 e 15 hanno portato il limite del blocco a 20 MiB (max_block_bytes), spazio per quattordici. La chain 20 mantiene 20 MiB, e un trasferimento vi porta circa 2,87 MB di prova, quindi un blocco ne contiene circa sette. Il rimedio scelto dal fullnode (2026-09-12) al posto del pruning e di un blocco più grande è la block-level aggregation: una prova ricorsiva per finestra sigillata che verifica N prove di bundle, così la cronologia resta dotata di prove da un capo all’altro mentre le prove grezze possono essere scartate. È costruita e integrata ma non attivata, e dalla chain 14 deve essere rimisurata prima di poterlo essere: la forma di bundle ammessa era stata misurata con il segmento pubblico vuoto (public 2), mentre un bundle vincolato alla transazione dichiara public 4, quindi nessun bundle provato sulla chain 14 vi corrisponde. I constraint set 7 e 8 hanno spostato di nuovo la forma: una prova di bundle ora dichiara public 7 e pubblica 35 valori, quindi l’interfaccia dell’aggregato è di 35 parole per prova. Una build del nodo rifiuta di avviarsi su qualsiasi genesi che contenga una sezione aggregation, e le chain da 14 a 20 sono state create senza. Anche una genesi con prezzi del gas dinamici, come quella della chain 20, viene rifiutata se affiancata a una sezione aggregation. Dal fullnode v0.5.8 la prova aggregata vincola inoltre il proprio aggregator (audit AGG-2: il programma assorbe aggregate_binding(chain_id, aggregator, nonce)), quindi il digest del programma della forma ammessa deve essere misurato su una build che includa questa modifica. L’attivazione attende anche un esercizio end-to-end di aggregato falsificato contro il recursion verifier corretto, che non è stato eseguito, e una decisione sull’auth proof: il programma di aggregazione verifica solo prove di bundle, quindi su una chain con autorizzazione separata sigillare una finestra ridurrebbe un trasferimento da circa 2,87 MB a circa 1,37 MB, non a zero.
Che cosa è stato costruito:
- una seconda macchina nativa Goldilocks (la recursion VM,
randprotocol-rvm) il cui programma verifier controlla una prova RV32 in circa 1,97 milioni di righe al tier 21 (2.044.506 con il constraint set 7), e un programma di aggregazione generico in N su una finestra di prove di bundle; - due ruoli: i validator restano leggeri per la CPU e verificano un aggregato per ogni blocco sigillato; gli aggregator (un registro permissionless con vincolo di deposito e un indirizzo di pagamento shielded) producono gli aggregati su macchine di classe GPU e ricevono la quota di proving dei bundle coperti più un sussidio di blocco in nuovi RAND secondo un calendario di dimezzamento;
- cinque azioni (
RegisterAggregator,UnbondAggregator,WithdrawAggregator,SlashAggregator,Aggregate;SlashAggregatorresta nel formato di trasmissione ma viene rifiutata, perché un aggregato ritentato firma di nuovo lo stesso nonce e non è equivocazione), un’ammissione in nove passi, il sigillo e il pruning dei bundle coperti fino a circa 3 KB di campi pubblici ciascuno, una sincronizzazione in forma sigillata che costa a un nodo nuovo una verifica ricorsiva per finestra, i metodi RPCrand_getAggregate,rand_getAggregators,rand_getUnsealed,rand_getRawTransactione il daemonrand-node aggregate --watch.
Misurato sul profilo FRI di test: un aggregato con N=1 provato in circa 26 minuti su un laptop sotto carico (327.035 byte); un nodo nuovo ha applicato un batch sigillato di sette blocchi in meno di un secondo con una sola verifica ricorsiva. Classi di macchina come inizialmente stabilite: N=1 richiede ≥ 64 GB di memoria dell’host, N=2 ≥ 128 GB, N=3 ≥ 160 GB; la produzione con N ≥ 2 spetta al backend CUDA, che richiede un nodo GPU che non esiste ancora. Misurato su una macchina da 256 GB con il constraint set 7 (2026-09-28 e 29), l’aggregato con N=2 ha richiesto 133 GB, quello con N=3 221 GB, e la exit proof di produzione (il programma verifier su una prova interna) ha superato i 256 GB. Nulla di ciò è stato rimisurato con il constraint set 8. Finché l’aggregazione non si attiva, nessun aggregato sostituisce una prova sulla chain 20: i suoi due nodi archivio conservano ogni prova grezza, e i suoi validator eliminano la cronologia più vecchia di 24 ore.