Rand Protocol
Documentazione
Guide

Eseguire un validator e un aggregator

L'hardware per ogni ruolo su Rand: che cosa fanno un validator, un observer, un prover e un aggregator, la RAM, la CPU e il disco necessari a ciascuno, le dimensioni DigitalOcean su cui gira la testnet, i limiti di memoria di proving misurati e i comandi di configurazione.

Usa questa pagina per dimensionare una macchina prima di avviarne una. Un validatore costa poco. Generare le prove no: la memoria di una prova cresce rapidamente con il suo livello (tier), ed è l’unico numero che decide se una macchina può svolgere il compito. Ogni cifra qui riportata è una misurazione dalla testnet o dai registri del fullnode. Le cifre non definitive sono contrassegnate.

Che cosa fa ciascun ruolo

ruoloche cosa faeseguegenera prove?
validatoreordina le transazioni, verifica ogni prova di ogni blocco, vota in HotStuffrand-node run --validatorno
osservatoresi sincronizza, riverifica ogni prova, serve JSON-RPC; non votarand-node runno
prover (un wallet)genera in locale le prove dei propri pacchetti e delle proprie chiamate, poi li inviarand send, rand call, rand program deploysì, per ogni transazione
prover delegatogenera la prova del pacchetto per un wallet abbinato a esso; sulla chain 20 riceve la viewing key di quel wallet, mai la chiave di spesarand-prover run, oppure rand-node run --proversì, solo prove di pacchetto
aggregatoregenera una prova ricorsiva su una finestra di prove di pacchetto, per un blocco di sigillaturarand-node aggregate --watchsì, le prove più grandi
host di buildcompila rand-node e rand e consegna i binari ai nodi piccolicargo build --releaseno

Validatori e osservatori non generano mai prove. Un trasferimento schermato o una chiamata viene provato dal wallet che lo invia oppure, per la sola prova del pacchetto, da un prover a cui quel wallet è abbinato (Esecuzione di un nodo). Oggi i validatori della flotta non generano alcuna prova.

L’aggregazione dei blocchi è implementata ma non attiva. Richiede una sezione aggregation nel genesis. La catena 20 non ne ha: l’aggregazione è disattivata, come sulle catene da 9 a 19, e la build si rifiuta di avviarsi su un genesis che contiene la sezione.

Dimensionamento in sintesi

ruoloRAMCPUdisco
validatore o osservatore2 GB (la flotta originale); un validatore richiede anche un orologio sincronizzato (orologio)1 vCPU (la maggior parte della flotta originale)con --prune-history 24h, circa un giorno di blocchi: tabelle dei blocchi da 3,3–4,4 GB misurate sulla catena 14; mantieni liberi più di 4 GB (disco)
archivio (storia completa)come un validatorecome un validatorecresce con la catena: circa 3,6 GB al giorno misurati per i QC a 18 firme della catena 14 con blocchi da 1,4 s, di più sulle catene da 18 a 20, i cui QC contengono fino a 26 firme, dato non rimisurato; i due archivi della testnet risiedono su volumi da 250 GiB
host di build8 GB (nodo E)4 vCPU (nodo E)l’albero dei sorgenti, target/, e almeno 20 GB liberi
prover, trasferimento schermato (tier 14)picco di 6,1 GB per un trasferimento sulla catena 18, da 6,1 a 6,6 GB per una chiamata con il pacchetto che la paga (2026-09-30)un core; sulla catena 18 due prove, la prova del pacchetto tier 14 in 102–134 s e la prova di autorizzazione tier 10 in 7–23 s (laptop Apple Silicon, 2026-09-30); circa 100 s per il solo pacchetto con asset nascosto 4-in-4-out sulla catena 14; 92,2–96,0 s misurati su un laptop per il pacchetto 2-in-2-out della catena 13 (produzione, 2026-09-19)piccolo
prover delegato5,74 GB per ogni prova eseguita contemporaneamente, più 1 GiB di margine; rifiuta di avviarsi con meno disponibileun core per provapiccolo
prover, chiamata tier 18 (l’ERC-20; rifiutata sulla catena dalla v0.5.6, vedi Memoria di proving)85,0 GB (transfer tradotto) / 85,5 GB (interpretato), misurati su m-16vcpu-128gbun corepiccolo
prover, chiamata tier 20 (SPL Token; rifiutata sulla catena dalla v0.5.6)non ancora provata; estrapolata a circa 330 GB, più del droplet con più memoria di DigitalOcean (m-32vcpu-256gb, 256 GB)un corepiccolo
aggregatore, N = 1almeno 64 GB era il limite prima delle esecuzioni del 2026-09-28/29; vedi Aggregatorioggi CPUcome un validatore
aggregatore, N = 2 / N = 3133 GB / 221 GB misurati con il constraint set 7 (2026-09-28/29)un nodo GPU per la produzione con N ≥ 2come un validatore

Oggi il prover è a thread singolo. Un droplet da 16 vCPU ha funzionato al 99% di un solo core. Più core non rendono più veloce una singola prova; è la RAM in più a decidere se si conclude.

Validatori e osservatori

Memoria e CPU

I diciotto validatori originali girano su droplet da 2 GB. Verificare una prova costa poco:

operazionecosto
verificare una prova di pacchetto, con verifier key già in cachecirca 16 ms
la prima verifica con una nuova formacirca 230 ms
costruire la verifier key di un programma distribuito (una volta, in background)circa 7 s su un server da 2 vCPU
verificare una prova aggregata (quando l’aggregazione è attiva)circa 0,8 s a freddo, circa 16 ms a caldo (cifre di progetto)

La memoria che serve a un validatore per verificare una prova di chiamata tier 18 o tier 20 è ora in parte misurata, su un laptop Apple Silicon da 48 GB, indipendentemente dal droplet DigitalOcean che ha prodotto ciascuna prova: verificare la prova transfer tier 18 ha richiesto 50,2 s con un picco di RSS di 3,66 GB (tradotto) oppure 49,6 s (interprete, RSS non registrato separatamente); verificare la prova approve tier 16 ha richiesto 12,2 s (RSS non registrato separatamente). Il tier 20 non è stato misurato: non esiste ancora alcuna prova tier 20 da verificare. Dalla v0.5.6 un validatore non costruisce mai una chiave così grande: l’intestazione di una prova di chiamata viene controllata prima che si costruisca qualsiasi verifier key, e una chiamata oltre il tier 14 (o con una tabella keccak oltre 2^12, o una tabella sha256 oltre 2^13) viene rifiutata, in fase di ammissione e come regola di validità del blocco. La peggiore intestazione di chiamata ammissibile misurata ha richiesto 4,7 s e 312 MB per la verifica.

Un droplet da 1 vCPU e 2 GB non può compilare i binari. Compila su una macchina più grande e copiali (vedi setup).

Disco

cifravalorefonte
un blocco inattivo della catena 14, prima della v0.5.5circa 60 KB in blocks più circa 49 KB in qcs: il QC Dilithium2 a 18 firme memorizzato due volte, circa 6,6 GB al giorno con blocchi da 1,4 sl’incidente sul disco del 2026-09-24, AGENTS.md
lo stesso blocco dalla v0.5.5circa 60 KB: il QC di un blocco confermato è memorizzato una sola volta, nel justify del figlio; circa 3,6 GB al giorno con blocchi da 1,4 sdocs/deploy.md, nota di roll per la v0.5.5
write-ahead log di RocksDBlimitato a 256 MB dalla correzione del 2026-09-24; prima, 13 GB di log non eliminato per validatoreAGENTS.md
un validatore della catena 14 dopo lo svuotamento di --prune-history 24h (2026-09-25)tabelle dei blocchi 3,3–4,4 GB, da 19 GB; dischi utilizzati al 18–37%AGENTS.md, v0.5.7
la directory dei dati del nodo A, catena 12 all’altezza 62.276circa 10 GBdeploy/README.md, il rollout della v0.3
una catena che esegue blocchi pieni4 MiB ogni 2 s, circa 170 GB al giorno (il limite di blocco delle catene fino alla 12; quello della catena 20 è 20 MiB)docs/block-space.md
spazio libero che la flotta mantiene per le buildalmeno 20 GBdocs/block-space.md
un disco da 30 GB che ospita le directory dei dati di tre catenepieno; RocksDB No space left on device, crash loopmkc1 e mem1, deploy/README.md

Sulla catena 20, come sulla 19, 24 dei 26 validatori eseguono --prune-history 24h e conservano circa un giorno di blocchi; il ledger stesso (note, nullifier, ancore, il registro) non viene mai potato. Gli archivi, obs1 e rand-archive-2 (entrambi anche validatori), girano senza il flag. Un nodo mainnet non lo passa mai. Il nodo rifiuta di avviarsi con meno di --min-free-disk-mb (1.024 MB per impostazione predefinita) liberi sul filesystem della propria directory dei dati, e rand_getHealth risponde disk_low sotto il quadruplo di tale valore; un roll che attende ok si ferma su un nodo che si sta riempiendo. Vedi Potatura della storia per ciò a cui un nodo potato risponde ancora.

Elimina la directory dati di una catena dismessa dopo un cut-over. Le directory dati sono identificate dall’hash del genesis (data-<name>-<hash8>: -6210cf07 per la catena 20, -a3defc93 per la catena 19; i sei host guardian usano /var/lib/randnode/data-20), quindi quelle vecchie restano finché non le rimuovi. Al cut-over della catena 20 un validatore regionale (syd1) è partito in disk_low con 3,9 GB liberi e ha bloccato l’avvio a 25 su 26, perché sulla macchina c’erano ancora le directory delle catene da 14 a 17; eliminarle ha liberato 22 GB. Tieni la directory della catena precedente per un giorno come target di rollback, poi rimuovila. A blocchi pieni ogni prova raw di bundle pesa circa 1,42 MB dalla catena 14 (circa 1,3 MB fino alla catena 13). Dalla catena 17 ogni bundle porta anche una prova di autorizzazione, quindi un trasferimento pesa circa 2,85 MB di prove: circa 1,49 MB per la prova del bundle e 1,36 MB per la prova di autorizzazione (profilo di produzione, misurato il 2026-09-29). L’aggregazione, una volta attiva, riduce la prova di un bundle sigillato a circa 3 KB, a meno che il nodo non giri con --keep-raw-proofs. Non riguarda la prova di autorizzazione, che resta a dimensione piena.

Rete

Apri la porta TCP 30303 in ingresso su un nodo pubblico. I nodi dietro NAT si collegano in uscita con --bootstrap. Con blocchi pieni da 4 MiB un collegamento tra validatori trasporta circa 2 MB/s.

Orologio

Un validatore ha bisogno di NTP. La catena 14 è la prima in cui l’ora di sistema fa parte del consenso (bridge hardening B2):

regolalimitetipo
il timestamp di un blocco non può superare quello del suo genitore di più di questo valore60 s (MAX_TIMESTAMP_STEP_MS)regola di validità; il blocco non è valido (BlockError::TimestampLeap)
un validatore non vota per un blocco il cui timestamp supera il proprio orologio di più di questo valore15 s (MAX_CLOCK_DRIFT_MS)regola di voto

Un validatore con l’orologio in ritardo di 20 s smette di votare in silenzio: vede ogni blocco onesto come in anticipo rispetto al proprio orologio e trattiene il voto, senza che nulla dia errore. Sulla catena 20, diciotto validatori su ventisei devono votare per far committare qualsiasi cosa. Controlla ogni validatore e installa chrony dove l’orologio non è sincronizzato:

timedatectl                     # want "System clock synchronized: yes" and "NTP service: active"
chronyc tracking 2>/dev/null || timedatectl show-timesync --all 2>/dev/null
apt-get install -y chrony && systemctl enable --now chrony

Lo stesso limite di 15 s vale per un genesis. Imposta timestamp_ms vicino all’ora di lancio e mai oltre: un genesis più di 15 s nel futuro non committa alcun blocco 1 finché l’ora reale non lo raggiunge, e uno molto nel passato lascia il tempo dei blocchi indietro rispetto all’orologio, recuperando al massimo 60 s per blocco (docs/deploy.md). Un osservatore non vota, quindi la regola di voto non lo vincola.

Dimensioni DigitalOcean su cui gira la testnet

dimensioneRAM, vCPU, disconodinote
s-1vcpu-2gb2 GB, 1la maggior parte dei validatori regionali (tra cui ams3, nyc1, nyc2, sfo2)non può compilare; i binari vengono copiati
s-1vcpu-2gb-amd2 GB, 1atl1come sopra
s-2vcpu-2gb-intel2 GB, 2D (ric1)
s5-1vcpu-2gb-30gb2 GB, 1, 30 GBmkc1, mem1 (l’unica dimensione piccola disponibile lì)i dischi erano pieni (29 GB) al cut-over della catena 13; 7 GB liberi dopo l’eliminazione delle directory dati della catena 11 ormai morta; serve un ridimensionamento
4 vCPU, 8 GB8 GB, 4E (sgp1)validatore, host di build ed explorer

Questa tabella riguarda i diciotto validatori originali. Dal 2026-09-27 anche il validatore A gira su un droplet (sgp1), non su un laptop. Altri otto validatori sono stati vincolati con bond sulla catena 15 (2026-09-27): i due archivi, obs1 e rand-archive-2 (fra1), e i sei host guardian. Le dimensioni dei loro droplet non sono registrate qui, e neppure se mkc1 e mem1 siano stati ridimensionati. Tutti e 26 sono validatori genesis sulla catena 20, come sulla catena 19, con 1.000 RAND ciascuno, e al 2026-09-30 tutte e 26 le chiavi sono detenute da un unico operatore.

Memoria di proving

Il wallet produce la prova di ogni transazione che invia, quindi chi chiama un programma ha bisogno della memoria del tier di quel programma. Questi sono i limiti misurati. Le esecuzioni del tier 18 sono terminate, con prova generata e verificata su DigitalOcean; quelle del tier 20 no. Dalla v0.5.6 la catena rifiuta una prova di chiamata sopra il tier 14 (MAX_CALL_TIER), quindi le righe dei tier 16, 18 e 20 qui sotto sono misurazioni, non chiamate che la catena 20 ammette; ogni chiamata committata sulla catena 14 era di tier 10.

carico di lavorotiercicliche cosa è stato misuratorichiede
trasferimento shielded (il guest bundle)14circa 9.160 sulla catena 13 (il guest 2-in-2-out)92,2–96,0 s su un laptop Apple Silicon (produzione, catena 13, 2026-09-19); picco di memoria non registrato. Il guest 4-in-4-out con asset nascosto della catena 14 è fissato allo stesso tier: circa 100 s e una prova di circa 1,42 MB. Sulla catena 20 un trasferimento è composto da due prove (autorizzazione separata, dalla catena 17): la prova del bundle di tier 14, da 102 a 134 s e circa 1,49 MB, e una prova di autorizzazione di tier 10, da 7 a 23 s e circa 1,36 MB. Picco di memoria da 6,1 a 6,6 GB per una transazione intera (laptop Apple Silicon, catena 18, 2026-09-30)gira sul laptop di sviluppo
ERC-20 approve (produzione, sulla catena 13, 2026-09-19)1648.119prova della chiamata 388,7 s, 3.412.405 byte; l’intero rand call 622,8 s con 22,9 GB di RSS di picco su un laptop serie M da 48 GBun laptop da 48 GB
chiamate ERC-2018circa 66k–162kil transfer della prima fase (79.203 cicli, prima del code guard) è stato terminato con SIGKILL su un laptop da 48 GB a 24,7 GB dopo 1.016 s; un’esecuzione su un droplet da 64 GB ha superato i 47 GB a 25 minuti85,0 GB (tradotto) / 85,5 GB (interpretato) di RSS di picco, 3.230,5 s / 3.143,3 s di tempo di proving, prove da 811.600 / 805.108 byte. Misurato su m-16vcpu-128gb, 2026-09-19
vettori SPL Token20circa 700k–770kil Transfer tradotto (692.854 cicli, prima dell’ELF guard) è stato fermato su un laptop da 48 GB a 30,77 GB dopo 225 s, ancora in fase di proving; un’esecuzione di tier 20 è stata uccisa per OOM su un droplet da 64 GB a 65,1 GB dopo 10 min 41 snon ancora provato; estrapolato a circa 330 GB e circa 3,6 h (scaling misurato dei tier 16/18: memoria circa ×3,9, tempo circa ×4,1 ogni +2 tier) — più del droplet con più memoria di DigitalOcean (m-32vcpu-256gb, 256 GB)
uscita di produzione rVM al tier 21 (una prova di bundle verificata dentro la recursion VM)211.968.619 righerequisito derivato di 48,6 GB prima dell’esecuzione; con il constraint set 7 richiedeva più di quanto offrisse un droplet da 256 GB (2026-09-28/29)più di 256 GB; non rimisurato con il constraint set 8

Le chiamate ERC-20 arrivano ai tier 16 e 18 e SPL Token al tier 20 (Ethereum, Solana). Nessuna prova ai tier 18 o 20 è stata prodotta su una macchina da 48 GB.

Aggregatori

Un aggregatore osserva la catena, prende le prove dei bundle di una finestra di blocchi finalizzati, produce una prova ricorsiva aggregata che li copre e la invia. Il blocco che la include è un blocco di sigillatura. L’aggregatore riceve la quota di proving dei bundle coperti più un sussidio di blocco in nuovi RAND, al suo indirizzo di pagamento registrato. L’aggregazione è senza permessi: può registrarsi qualsiasi operatore con un bond.

Esiste solo su una catena il cui genesis ha una sezione aggregation. La catena 20 non ce l’ha, e la sua build si rifiuta di avviarsi su un genesis che la contenga.

Hardware

aggregatoRAM dell’hostbackend
N = 1 bundlealmeno 64 GBCPU; il profilo di test ne ha provato uno in circa 26 minuti su un laptop carico (327.035 byte)
N = 2133 GB misurati; il limite precedente era di almeno 128 GBil backend GPU per la produzione
N = 3221 GB misurati; il limite precedente era di almeno 160 GBil backend GPU per la produzione
il nodo GPU della flottaalmeno 160 GB di host, un dispositivo da 80 GB (H100 o A100-80G)Linux, driver R580+, CUDA 13, LLVM 21, sm_80+; non ne esiste ancora nessuno

Le cifre per N = 2 e N = 3 sono state misurate su un droplet DigitalOcean da 256 GB il 2026-09-28/29, con il constraint set 7, e la prova di uscita di produzione richiedeva più dei 256 GB di quella macchina. Nessuna è stata rimisurata con il constraint set 8, che le catene da 18 a 20 eseguono, quindi considera la riga N = 1 come un limite inferiore. Il backend CUDA è girato per la prima volta su hardware reale il 2026-09-28, su una NVIDIA H100: i suoi kernel vengono compilati in PTX per sm_80 e sm_90 e coincidono con il riferimento CPU. La misurazione di produzione su un nodo GPU della flotta resta da fare. Ogni nodo paga inoltre una costruzione delle chiavi all’avvio, una tantum, per il programma di aggregazione: da 13,0 a 13,4 s al profilo di test (2¹⁹), e da 30 a 70 s attesi in produzione (2²¹).

Comandi

# print a signed registration; the bond burns out of a wallet bundle as the register bundle's burn
rand-node aggregator register --key agg.key.json --bond <RAND> --payout rand1… --rpc http://127.0.0.1:8545

# the daemon: poll rand_getUnsealed, fetch the raw bundles, prove, seal the payment note, submit
rand-node aggregate --key agg.key.json --rpc http://127.0.0.1:8545 --watch

# leave, then withdraw the released bond into a note at the payout address
rand-node aggregator unbond --key agg.key.json --rpc http://127.0.0.1:8545
rand-node aggregator withdraw --key agg.key.json --rpc http://127.0.0.1:8545
flag di aggregatepredefinitosignificato
--keyobbligatoriola chiave di aggregator che il registro conosce; firma ogni aggregato
--rpchttp://127.0.0.1:8545il nodo da interrogare e a cui inviare
--watchoffcontinua a interrogare invece di inviare una sola volta
--interval-secs15intervallo di polling con --watch
--no-waitofftermina non appena il nodo accetta l’aggregato

rand status mostra una sezione aggregation su una chain di questo tipo: aggregator registrati, blocchi non sigillati e indice del programma di sussidio. rand_getUnsealed è la lista di lavoro.

Setup

Questi passaggi seguono gli script che usa la testnet (deploy/vps-setup.sh, deploy/update-droplet.sh). Producono un validator o un observer Linux.

1. Compilare su un build host

La compilazione richiede build-essential clang cmake pkg-config libssl-dev, Rust 1.98.1 (fissato da rust-toolchain.toml) e un checkout di circuits accanto al checkout del fullnode. La prima compilazione richiede da 10 a 20 minuti.

git clone https://github.com/randprotocol/fullnode
git clone https://github.com/randprotocol/zkp-circuits circuits
cd fullnode
git checkout v0.6.8                       # c9c9bd3c, the build chain 20 runs
git -C ../circuits checkout "$(sed -n 's/^circuits: //p' crates/randprotocol-zkvm/guests-compiled/PROVENANCE.md)"   # aeacf31 for v0.6.8
git show origin/main:deploy/genesis-chain20.json > deploy/genesis-chain20.json   # committed after the tag
cargo build --release -p randprotocol-node -p randprotocol-client
sha256sum target/release/rand-node         # compare on every node you copy it to

La chain 20 richiede v0.6.8 su ogni nodo prima di init. Il suo genesis contiene campi che nessuna build precedente legge (testnet, binding_domain, proof_window_blocks, program_state, i gruppi rotation e fees del bridge, i massimali di gas, l’ammissione allo staking tramite voto), e v0.6.8 include le modifiche di consenso CON-4 e CH-1 dell’audit v6. Le proof sono ancora prodotte con il constraint set 8, come sulle chain 18 e 19, con una proof di autorizzazione accanto a ogni proof di bundle (hc_auth). Una build v0.6.8 rifiuta il genesis delle chain da 14 a 17 con run e verify. Eseguite l’unica build che esegue la flotta. Il file di genesis si trova nel main del fullnode (commit 74cfaca0), non nel tag v0.6.8, da cui la terza riga git. Il checkout di circuits deve essere al commit da cui la release è stata vendorizzata, che la seconda riga git qui sopra legge dall’albero del fullnode. Aggiungete -p randprotocol-prover per compilare anche rand-prover.

2. Installare i binari sul nodo

scp target/release/rand-node target/release/rand deploy/genesis-chain20.json root@<node>:/root/
ssh root@<node> 'install -m 755 /root/rand-node /root/rand /usr/local/bin/'

3. Chiave, genesis, firewall

Sul nodo:

install -d -m 700 /root/keys
test -e /root/keys/node.key.json || rand-node keygen --out /root/keys/node.key.json   # prints the address; keep the seed secret
rand-node init --datadir /root/data-6210cf07 --genesis /root/genesis-chain20.json
timedatectl                                        # "System clock synchronized: yes" (see Clock)
ufw allow 22/tcp && ufw allow 30303/tcp && ufw enable

Generate la chiave sul nodo, come sopra, e tenetela fuori da qualsiasi checkout. Nessuna chiave è più tracciata nel repository del fullnode (audit v3, OPS-1). I file deploy/node-*.key.json committati per le chain da 8 a 13 sono seed pubblicati; le chiavi dei validator della chain 20 (le diciotto generate per la chain 14 e le otto vincolate sulla chain 15) sono state generate fuori dal repository, e la flotta conserva la chiave di ogni droplet in /root/keys/node-<name>.key.json, fuori dall’albero dei sorgenti. La posizione conta su un nodo predisposto dagli script della flotta: deploy/rebuild-vps.sh e deploy/push-to-vps.sh sincronizzano /root/fullnode con rsync e --delete, quindi una chiave tenuta dentro quell’albero viene cancellata dalla ricostruzione successiva e l’unit non riesce più a riavviarsi. Da v0.6.8 keygen rifiuta di sovrascrivere un file esistente (v0.6.7 lo sovrascriveva senza chiedere); il test -e rende la riga sicura da rieseguire in entrambi i casi. Fate un backup della chiave fuori dall’host prima di vincolarla.

init stampa l’hash del genesis. Deve risultare 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135 (chain 20). Il file di genesis è genesis-chain20.json in deploy/ del repository del fullnode, su main. Date alla directory dei dati il nome dei primi otto caratteri dell’hash, come fa la flotta (data-<name>-6210cf07), così da non collidere mai con quella della chain 19 (-a3defc93) né con quella di una chain successiva. Il genesis imposta questi limiti. Il tetto delle proof era 8 MiB sulle chain da 13 a 16 ed è 4 MiB dalla chain 17, dove una transazione ha cominciato a portare fino a tre proof:

limitechain 20
max_program_words65.535
max_proof_bytes4.194.304 (4 MiB)
max_block_bytes20.971.520 (20 MiB)
max_call_envelope_bytes65.536
max_program_public_words32.768
envelope_bytes1.860 (ogni envelope di note, con il suo campo memo cifrato)
proof_window_blocks1.024 (256 sulla chain 19)
program_statecommissione per cella 0,1 RAND (10.000.000 unità); al massimo 8 letture, 8 scritture e 4 payout per invoke
sezione aggregationnessuna (aggregazione disattivata)

Il genesis della chain 20 contiene anche consensus_domain: 1, binding_domain: 1, testnet: true, una sezione staking con ammissione tramite voto, una sezione gas con massimali di prezzo, i gruppi rotation e fees del bridge, hardening_v6 e i due pin di guest hc_bundle e hc_auth; Running a node elenca ciò che impostano.

4. Un’unit systemd

Questa è l’unit che scrive deploy/vps-setup.sh, con i percorsi indicati sopra:

[Unit]
Description=RAND full node
After=network-online.target
[Service]
Environment=RUST_LOG=info,libp2p=warn,libp2p_mdns=off
ExecStart=/usr/local/bin/rand-node run --datadir /root/data-6210cf07 --key /root/keys/node.key.json --validator --listen /ip4/0.0.0.0/tcp/30303 --rpc 127.0.0.1:8545 --no-mdns --prune-history 24h --bootstrap <multiaddr> --bootstrap <multiaddr>
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target

Eliminate --validator per un observer. --prune-history 24h è ciò che eseguono i validator della testnet, tranne gli archivi; eliminatelo per un nodo che conserva la storia completa, e non passatelo mai su mainnet. I multiaddr di bootstrap per la chain 20 sono i nodi C (fra1), D (ric1) ed E (sgp1), invariati rispetto alla chain 19. La chain 20 gira sulle chiavi dei validator generate per la chain 14, e un’identità p2p deriva dalla chiave del validator, quindi questi peer id sono quelli usati dalla chain 14. Un nuovo nodo che si sincronizza dal genesis ha inoltre bisogno di un peer con storia completa, perciò aggiungete uno dei due archivi (obs1, poi rand-archive-2):

/ip4/164.90.239.200/tcp/30303/p2p/12D3KooWEQEbUwZRgqhDPXhW7vNBmcRcnhUDGUADe81VFdv3ALYe
/ip4/165.245.173.74/tcp/30303/p2p/12D3KooWJyc5oDHggAr89e9QrRFBy9Tg8TxXh18yzrb1SM6KKLYw
/ip4/188.166.235.187/tcp/30303/p2p/12D3KooWSyX84P1DAbWByLHpRBMLRWD53r3Jj4aqVt6tHoF8B2ZQ
/ip4/168.144.46.203/tcp/30303/p2p/12D3KooWS5usdMPvsbaWSaT2xtKndHvDYurwmueoNvaRRarb2wRf
/ip4/206.81.29.236/tcp/30303/p2p/12D3KooWPocyZGcNB9Vp68VSfgVvNXhSzBBoJa4h9R1yMkp71XHh

Tenete l’RPC su 127.0.0.1 a meno che un firewall non lo protegga. Un nodo che deve servire il pubblico apre accanto ad esso il listener pubblico di v0.6.8 (--public-rpc <ADDR>) e vi pone davanti un proxy, mai davanti a --rpc (JSON-RPC). Un’unit ereditata da v0.6.7 non deve passare --prover-accept-spend-key, che v0.6.8 rifiuta all’avvio.

systemctl daemon-reload && systemctl enable --now rand-node
journalctl -u rand-node -f
rand status                       # height climbing, peer_count rising

5. Entrare nel set dei validator

Una nuova chiave non fa parte del set di nessuna epoch. Sulla chain 20 deve prima essere votata: il suo genesis imposta staking.admission_by_vote, quindi i validator che detengono più di due terzi del peso di voto la firmano ciascuno con rand-node admit sign --candidate <key or registration> --key <validator key> --genesis-hash <chain 20's hash>, e uno di essi invia i voti con rand-node admit submit; rand_getAdmitted la elenca poi. Quindi vincolate ad essa almeno 1.000 RAND: stampate una registrazione con rand-node register --key /root/keys/node.key.json --payout rand1… --v2 (la chain 20 rifiuta una registrazione v1), poi eseguite il bond da un wallet con rand bond <address> 1000 --registration <hex>. Il bond attende la sua epoch di attivazione, al più presto tre confini di 1.000 blocchi dopo il suo commit, e al massimo 2.500 bps del peso attivo diventano nuovo peso per confine (la chain 19 lo limitava a un valore fisso di 10.000 RAND). Staking lo illustra passo per passo.

6. Aggiornamento

Questo vale per una build che esegue la stessa chain. Passare da una chain precedente alla chain 20 non è un aggiornamento: servono il nuovo binario, il nuovo genesis e una directory dei dati nuova, e la directory dei dati della vecchia chain può essere eliminata in seguito (deploy/retire-chain-dirs.sh; la flotta la conserva per un giorno in vista di un rollback). Per distribuire una nuova build senza un cambio di chain, compilate una volta, confrontate lo sha256 di rand-node e di rand, fermate il servizio, installate e riavviate, un nodo alla volta. Alcune release vengono distribuite con arresto totale e riavvio totale (la regola dei call-tier di v0.5.6, la modifica del wire Status di v0.5.7, la verifica delle proof più rigorosa di v0.6); le note di ogni release indicano quale. v0.6.7 è stata distribuita sulla chain 18 un nodo alla volta; v0.6.8 è arrivata con la chain 20, con arresto totale e riavvio totale, perché le sue modifiche di consenso CON-4 e CH-1 non devono mai essere distribuite nodo per nodo. Attendete che ogni nodo si riunisca prima del successivo, così il quorum non risulta mai carente di più di uno. deploy/update-droplet.sh <ip> [build-host] fa esattamente questo via SSH.

Le release fino a v0.6.8 sono state compilate a mano su un solo host e non sono firmate. La release v0.6.8 su GitHub contiene rand-node, rand, rand-prover e SHA256SUMS, compilati sul nodo E; quel checksum intercetta un download corrotto e non garantisce per il build host. v0.6.8 include un workflow di release che compila i binari dal tag, e deploy/update-droplet.sh rifiuta un’installazione senza un SHA256SUMS firmato, a meno che non sia impostato ALLOW_UNSIGNED=1. deploy/release-signers non elenca ancora alcuna chiave, quindi il percorso firmato non è mai stato usato.

Le chain 15, 16, 17 e 18 sono entrate in funzione nell’arco di 2,7 giorni (dal 2026-09-26 al 2026-09-29), ciascuna con un arresto totale della flotta. La chain 19 è seguita il 2026-10-01 alle 03:43 UTC, un re-genesis della chain 18 sulla stessa build, e la chain 20 lo stesso giorno alle 06:17 UTC, ricavata da uno snapshot della chain 19 all’hard fork v0.6.8; ogni nodo si è fermato all’altezza 7.700 della chain 19. Una politica scritta di cambio chain (2026-09-30) si applica dalla chain 20 in poi; il registro del cambio della chain 20 ha derogato alla ricostruzione da parte di un secondo operatore, perché un solo operatore detiene tutte le chiavi. Un cambio richiede un motivo che un aggiornamento progressivo non può soddisfare, un elenco pubblicato di ciò che porta e di ciò che elimina, una checklist di ricostruzione dei client completata in anticipo, un secondo operatore che ricostruisce il genesis fino allo stesso hash, un piano di rollback e un id di chain mai usato prima.

Ultima verifica rispetto al commit c0878c3f del fullnode (chain 21) il 2026-10-12 e fullnode v0.8.0 `c0878c3f` (`docs/deploy.md`, `docs/cli.md`, `docs/staking.md`, `docs/node-hardware.md`, `deploy/cutover-fleet-chain21.sh`, `CHANGELOG.md`) and `main` `246cb5f9` (`deploy/genesis-chain21.json`, `deploy/cut-records/chain21.record`); the live chain-21 RPC, 2026-10-12, fullnode `90e7716` (v0.6.7 `86941a1` and `main` after it, 2026-09-30: `deploy/nodes.env`, `deploy/genesis-chain18.json`, `deploy/README.md`, `deploy/vps-setup.sh`, `docs/deploy.md`, `docs/node-hardware.md`, `docs/prover.md`, `docs/cli.md`, `docs/staking.md`, `README.md`, `CHANGELOG.md`, `AGENTS.md`), fullnode `8abf85e` (v0.5.9: `docs/rpc.md`), fullnode `ed88241` (`deploy/README.md`, `deploy/nodes.env`, `deploy/genesis-chain14.json`, `deploy/run-a.sh`, `deploy/vps-setup.sh`, `deploy/update-droplet.sh`, `docs/deploy.md`, `docs/superpowers/handoffs/2026-09-20-chain14-cut-runbook.md`, `docs/aggregation.md`, `docs/block-space.md`, `docs/zkvm-m4-m5-progress.md`, `docs/cli.md`). Dove il codice e questa pagina non concordano, ha ragione il codice; segnalacelo.