Utilisez cette page pour dimensionner une machine avant d’en exploiter une. Un validateur coûte peu. La preuve, non : la mémoire d’une preuve croît fortement avec son niveau, et c’est le seul chiffre qui décide si une machine peut faire le travail. Chaque chiffre ci-dessous est une mesure issue du testnet ou des relevés du fullnode. Les chiffres qui ne sont pas définitifs sont signalés.
Ce que fait chaque rôle
| rôle | fonction | exécute | prouve ? |
|---|---|---|---|
| validateur | ordonne les transactions, vérifie chaque preuve de chaque bloc, vote dans HotStuff | rand-node run --validator | non |
| observateur | se synchronise, revérifie chaque preuve, sert le JSON-RPC ; ne vote pas | rand-node run | non |
| prouveur (un wallet) | prouve localement ses propres lots et ses appels, puis les soumet | rand send, rand call, rand program deploy | oui, chaque transaction |
| prouveur délégué | produit la preuve de lot d’un wallet qui lui est associé ; sur la chaîne 20, il reçoit la clé de visualisation de ce wallet, jamais la clé de dépense | rand-prover run, ou rand-node run --prover | oui, preuves de lot uniquement |
| agrégateur | produit une preuve récursive unique sur une fenêtre de preuves de lot, pour un bloc de scellement | rand-node aggregate --watch | oui, les plus grosses preuves |
| hôte de compilation | compile rand-node et rand et remet les binaires aux petits nœuds | cargo build --release | non |
Les validateurs et les observateurs ne prouvent jamais. Un transfert blindé ou un appel est prouvé par le wallet qui l’envoie ou, pour la seule preuve de lot, par un prouveur auquel ce wallet est associé (Exploiter un nœud). Les validateurs de la flotte ne prouvent rien aujourd’hui.
L’agrégation de blocs est construite mais non active. Elle exige une section aggregation dans la genèse. La chaîne 20 n’en a pas : l’agrégation est désactivée, comme sur les chaînes 9 à 19, et la compilation refuse de démarrer sur une genèse qui contient cette section.
Dimensionnement en un coup d’œil
| rôle | RAM | CPU | disque |
|---|---|---|---|
| validateur ou observateur | 2 GB (la flotte d’origine) ; un validateur a aussi besoin d’une horloge synchronisée (horloge) | 1 vCPU (la plupart de la flotte d’origine) | avec --prune-history 24h, environ un jour de blocs : tables de blocs de 3,3–4,4 GB mesurées sur la chaîne 14 ; gardez plus de 4 GB libres (disque) |
| archive (historique complet) | comme un validateur | comme un validateur | croît avec la chaîne : environ 3,6 GB par jour mesurés pour les QC à 18 signatures de la chaîne 14 avec des blocs de 1,4 s, davantage sur les chaînes 18 à 20, dont les QC portent jusqu’à 26 signatures, ce qui n’a pas été remesuré ; les deux archives du testnet reposent sur des volumes de 250 GiB |
| hôte de compilation | 8 GB (nœud E) | 4 vCPU (nœud E) | l’arborescence des sources, target/, et au moins 20 GB libres |
| prouveur, transfert blindé (niveau 14) | pic de 6,1 GB pour un transfert sur la chaîne 18, 6,1 à 6,6 GB pour un appel avec son lot de paiement (2026-09-30) | un cœur ; sur la chaîne 18, deux preuves : la preuve de lot de niveau 14 en 102 à 134 s et la preuve d’autorisation de niveau 10 en 7 à 23 s (portable Apple Silicon, 2026-09-30) ; environ 100 s pour le seul lot d’actif caché à 4 entrées et 4 sorties sur la chaîne 14 ; 92,2–96,0 s mesurées sur un portable pour le lot à 2 entrées et 2 sorties de la chaîne 13 (production, 2026-09-19) | faible |
| prouveur délégué | 5,74 GB pour chaque preuve exécutée simultanément, plus 1 GiB de marge ; il refuse de démarrer avec moins de mémoire disponible | un cœur par preuve | faible |
| prouveur, appel de niveau 18 (l’ERC-20 ; refusé on-chain depuis la v0.5.6, voir Mémoire de preuve) | 85,0 GB (transfer traduit) / 85,5 GB (interprété), mesurés sur m-16vcpu-128gb | un cœur | faible |
| prouveur, appel de niveau 20 (SPL Token ; refusé on-chain depuis la v0.5.6) | pas encore prouvé ; extrapolé à environ 330 GB, soit plus que le plus gros droplet à mémoire de DigitalOcean (m-32vcpu-256gb, 256 GB) | un cœur | faible |
| agrégateur, N = 1 | au moins 64 GB était la borne avant les exécutions des 2026-09-28/29 ; voir Agrégateurs | CPU aujourd’hui | comme un validateur |
| agrégateur, N = 2 / N = 3 | 133 GB / 221 GB mesurés sous l’ensemble de contraintes 7 (2026-09-28/29) | un nœud GPU pour la production avec N ≥ 2 | comme un validateur |
Le prouveur est aujourd’hui monothread. Un droplet de 16 vCPU a tourné à 99 % d’un seul cœur. Davantage de cœurs n’accélèrent pas une preuve ; c’est davantage de RAM qui détermine si elle aboutit.
Validateurs et observateurs
Mémoire et CPU
Les dix-huit validateurs d’origine tournent sur des droplets de 2 GB. Vérifier une preuve coûte peu :
| opération | coût |
|---|---|
| vérifier une preuve de lot, clé de vérification en cache | environ 16 ms |
| la première vérification pour une nouvelle forme | environ 230 ms |
| construire la clé de vérification d’un programme déployé (une fois, en arrière-plan) | environ 7 s sur un serveur à 2 vCPU |
| vérifier une preuve agrégée (lorsque l’agrégation est active) | environ 0,8 s à froid, environ 16 ms en cache (chiffres de conception) |
La mémoire dont un validateur a besoin pour vérifier une preuve d’appel de niveau 18 ou 20 est désormais en partie mesurée, sur un portable Apple Silicon de 48 GB, indépendamment du droplet DigitalOcean qui a produit chaque preuve : la vérification de la preuve transfer de niveau 18 a pris 50,2 s pour un pic de 3,66 GB de RSS (traduit) ou 49,6 s (interpréteur, RSS non enregistré séparément) ; la vérification de la preuve approve de niveau 16 a pris 12,2 s (RSS non enregistré séparément). Le niveau 20 n’est pas mesuré : aucune preuve de niveau 20 n’existe encore à vérifier. Depuis la v0.5.6, un validateur ne construit jamais une clé aussi grande : l’en-tête d’une preuve d’appel est contrôlé avant la construction de toute clé de vérification, et un appel au-dessus du niveau 14 (ou avec une table keccak au-dessus de 2^12, ou une table sha256 au-dessus de 2^13) est refusé, à l’admission et comme règle de validité de bloc. L’en-tête d’appel admissible le plus lourd mesuré a demandé 4,7 s et 312 MB pour être vérifié.
Un droplet de 1 vCPU et 2 GB ne peut pas compiler les binaires. Compilez sur une machine plus grande et copiez-les (voir installation).
Disque
| chiffre | valeur | source |
|---|---|---|
| un bloc inactif de la chaîne 14, avant la v0.5.5 | environ 60 KB dans blocks plus environ 49 KB dans qcs : le QC Dilithium2 à 18 signatures stocké deux fois, environ 6,6 GB par jour avec des blocs de 1,4 s | l’incident disque du 2026-09-24, AGENTS.md |
| le même bloc depuis la v0.5.5 | environ 60 KB : le QC d’un bloc validé est stocké une seule fois, dans le justify de son enfant ; environ 3,6 GB par jour avec des blocs de 1,4 s | docs/deploy.md, note de déploiement de la v0.5.5 |
| journal d’écriture anticipée de RocksDB | plafonné à 256 MB depuis le correctif du 2026-09-24 ; auparavant, 13 GB de journal non purgé par validateur | AGENTS.md |
un validateur de la chaîne 14 après vidange de --prune-history 24h (2026-09-25) | tables de blocs de 3,3–4,4 GB, contre 19 GB ; disques utilisés à 18–37 % | AGENTS.md, v0.5.7 |
| répertoire de données du nœud A, chaîne 12 à la hauteur 62 276 | environ 10 GB | deploy/README.md, le déploiement de la v0.3 |
| une chaîne qui exécute des blocs pleins | 4 MiB toutes les 2 s, environ 170 GB par jour (le plafond de bloc des chaînes jusqu’à 12 ; celui de la chaîne 20 est de 20 MiB) | docs/block-space.md |
| espace libre que la flotte conserve pour les compilations | au moins 20 GB | docs/block-space.md |
| un disque de 30 GB contenant les répertoires de données de trois chaînes | plein ; RocksDB No space left on device, boucle de plantage | mkc1 et mem1, deploy/README.md |
Sur la chaîne 20, comme sur la chaîne 19, 24 des 26 validateurs exécutent --prune-history 24h et conservent environ un jour de blocs ; le registre lui-même (notes, nullifiers, ancres, le registre) n’est jamais élagué. Les archives, obs1 et rand-archive-2 (toutes deux aussi validateurs), tournent sans cette option. Un nœud mainnet ne la passe jamais. Le nœud refuse de démarrer avec moins de --min-free-disk-mb (1 024 MB par défaut) libres sur le système de fichiers de son répertoire de données, et rand_getHealth répond disk_low en dessous de quatre fois cette valeur ; un déploiement qui attend ok s’arrête sur un nœud en train de se remplir. Voir Élagage de l’historique pour ce qu’un nœud élagué sait encore répondre.
Supprimez le répertoire de données d’une chaîne retirée après une bascule. Les répertoires de données sont indexés par le hash du genesis (data-<name>-<hash8> : -6210cf07 pour la chaîne 20, -a3defc93 pour la chaîne 19 ; les six hôtes guardian utilisent /var/lib/randnode/data-20) ; les anciens restent donc tant que vous ne les supprimez pas. Lors de la bascule vers la chaîne 20, un validateur régional (syd1) est reparti en disk_low avec 3,9 GB libres et a retenu le démarrage à 25 sur 26, car les répertoires des chaînes 14 à 17 s’y trouvaient encore ; leur suppression a libéré 22 GB. Conservez le répertoire de la chaîne précédente pendant un jour comme cible de retour arrière, puis supprimez-le. À pleine charge de blocs, chaque preuve de bundle brute pèse environ 1,42 MB depuis la chaîne 14 (environ 1,3 MB jusqu’à la chaîne 13). Depuis la chaîne 17, chaque bundle porte aussi une preuve d’autorisation, de sorte qu’un transfert représente environ 2,85 MB de preuves : environ 1,49 MB pour la preuve de bundle et 1,36 MB pour la preuve d’autorisation (profil de production, mesuré le 2026-09-29). Une fois active, l’agrégation réduit la preuve d’un bundle scellé à environ 3 KB, sauf si le nœud tourne avec --keep-raw-proofs. Elle ne couvre pas la preuve d’autorisation, qui garde sa taille complète.
Réseau
Ouvrez le port TCP 30303 en entrée sur un nœud public. Les nœuds derrière un NAT se connectent vers l’extérieur avec --bootstrap. À pleine charge de blocs de 4 MiB, une liaison de validateur transporte environ 2 MB/s.
Horloge
Un validateur a besoin de NTP. La chaîne 14 est la première où l’heure murale fait partie du consensus (renforcement du bridge B2) :
| règle | borne | nature |
|---|---|---|
| l’horodatage d’un bloc ne peut pas dépasser celui de son parent de plus que cette valeur | 60 s (MAX_TIMESTAMP_STEP_MS) | règle de validité ; le bloc est invalide (BlockError::TimestampLeap) |
| un validateur ne vote pas pour un bloc dont l’horodatage devance sa propre horloge de plus que cette valeur | 15 s (MAX_CLOCK_DRIFT_MS) | règle de vote |
Un validateur dont l’horloge retarde de 20 s cesse de voter sans rien signaler : il voit chaque bloc honnête comme en avance sur son horloge et retient son vote, sans qu’aucune erreur ne survienne. Sur la chaîne 20, dix-huit validateurs sur vingt-six doivent voter pour que quoi que ce soit soit validé. Vérifiez chaque validateur et installez chrony là où l’horloge n’est pas synchronisée :
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
La même borne de 15 s s’applique à un genesis. Fixez timestamp_ms près de l’heure de lancement et jamais au-delà : un genesis situé à plus de 15 s dans le futur ne valide aucun bloc 1 tant que l’heure murale ne l’a pas atteint, et un genesis très ancien laisse l’heure des blocs en retard sur l’horloge murale, qu’elle rattrape au rythme de 60 s par bloc au plus (docs/deploy.md). Un observateur ne vote pas ; la règle de vote ne s’applique donc pas à lui.
Tailles DigitalOcean utilisées par le testnet
| taille | RAM, vCPU, disque | nœuds | remarques |
|---|---|---|---|
s-1vcpu-2gb | 2 GB, 1 | la plupart des validateurs régionaux (dont ams3, nyc1, nyc2, sfo2) | ne peut pas compiler ; les binaires y sont copiés |
s-1vcpu-2gb-amd | 2 GB, 1 | atl1 | idem |
s-2vcpu-2gb-intel | 2 GB, 2 | D (ric1) | |
s5-1vcpu-2gb-30gb | 2 GB, 1, 30 GB | mkc1, mem1 (la seule petite taille disponible là-bas) | les disques étaient pleins (29 GB) lors de la bascule vers la chaîne 13 ; 7 GB libres après la suppression des répertoires de données de la chaîne 11, morte ; un redimensionnement est nécessaire |
| 4 vCPU, 8 GB | 8 GB, 4 | E (sgp1) | validateur, hôte de compilation et explorateur |
Ce tableau couvre les dix-huit validateurs d’origine. Depuis le 2026-09-27, le validateur A tourne lui aussi sur un droplet (sgp1) et non sur un ordinateur portable. Huit validateurs supplémentaires ont déposé leur garantie sur la chaîne 15 (2026-09-27) : les deux archives, obs1 et rand-archive-2 (fra1), et les six hôtes guardian. Les tailles de leurs droplets ne sont pas consignées ici, pas plus que le fait de savoir si mkc1 et mem1 ont été redimensionnés. Les 26 sont des validateurs du genesis sur la chaîne 20, comme sur la chaîne 19, à 1 000 RAND chacun, et au 2026-09-30 les 26 clés sont détenues par un seul opérateur.
Mémoire de preuve
Le wallet prouve chaque transaction qu’il envoie ; l’appelant d’un programme a donc besoin de la mémoire correspondant au tier de ce programme. Ce sont les bornes mesurées. Les exécutions du tier 18 ont abouti, avec preuve générée et vérifiée sur DigitalOcean ; celle du tier 20, non. Depuis la v0.5.6, la chaîne refuse toute preuve d’appel au-dessus du tier 14 (MAX_CALL_TIER) ; les lignes des tiers 16, 18 et 20 ci-dessous sont donc des mesures et non des appels que la chaîne 20 admet ; tous les appels validés sur la chaîne 14 étaient du tier 10.
| charge de travail | tier | cycles | ce qui a été mesuré | nécessite |
|---|---|---|---|---|
transfert shielded (le guest bundle) | 14 | environ 9 160 sur la chaîne 13 (le guest 2 entrées, 2 sorties) | 92,2–96,0 s sur un ordinateur portable Apple Silicon (production, chaîne 13, 2026-09-19) ; pic de mémoire non consigné. Le guest à actif masqué 4 entrées, 4 sorties de la chaîne 14 est fixé au même tier : environ 100 s et une preuve d’environ 1,42 MB. Sur la chaîne 20, un transfert comprend deux preuves (autorisation scindée, depuis la chaîne 17) : la preuve de bundle du tier 14, de 102 à 134 s et d’environ 1,49 MB, et une preuve d’autorisation du tier 10, de 7 à 23 s et d’environ 1,36 MB. Pic de mémoire de 6,1 à 6,6 GB pour une transaction complète (ordinateur portable Apple Silicon, chaîne 18, 2026-09-30) | fonctionne sur l’ordinateur portable de développement |
ERC-20 approve (production, sur la chaîne 13, 2026-09-19) | 16 | 48 119 | preuve d’appel 388,7 s, 3 412 405 octets ; le rand call complet 622,8 s avec un pic de 22,9 GB de RSS sur un ordinateur portable série M de 48 GB | un ordinateur portable de 48 GB |
| appels ERC-20 | 18 | environ 66k à 162k | le transfer de la première étape (79 203 cycles, avant le garde-fou de code) a été tué par SIGKILL sur un ordinateur portable de 48 GB à 24,7 GB après 1 016 s ; une exécution sur un droplet de 64 GB dépassait 47 GB à 25 minutes | 85,0 GB (traduit) / 85,5 GB (interprété) de RSS en pic, 3 230,5 s / 3 143,3 s de temps de preuve, preuves de 811 600 / 805 108 octets. Mesuré sur m-16vcpu-128gb, 2026-09-19 |
| vecteurs SPL Token | 20 | environ 700k à 770k | le Transfer traduit (692 854 cycles, avant le garde-fou d’ELF) a été arrêté sur un ordinateur portable de 48 GB à 30,77 GB après 225 s, la preuve étant toujours en cours ; une exécution du tier 20 a été tuée par manque de mémoire sur un droplet de 64 GB à 65,1 GB après 10 m 41 s | pas encore prouvé ; extrapolé à environ 330 GB et environ 3,6 h (mise à l’échelle mesurée des tiers 16/18 : mémoire environ ×3,9, temps environ ×4,1 par tranche de +2 tiers) — davantage que le plus grand droplet à mémoire élevée de DigitalOcean (m-32vcpu-256gb, 256 GB) |
| sortie de production rVM au tier 21 (une preuve de bundle vérifiée dans la VM de récursion) | 21 | 1 968 619 lignes | besoin dérivé de 48,6 GB avant l’exécution ; sous le jeu de contraintes 7, il a nécessité plus que ce qu’offrait un droplet de 256 GB (2026-09-28/29) | plus de 256 GB ; non re-mesuré sous le jeu de contraintes 8 |
Les appels ERC-20 se situent aux tiers 16 et 18 et SPL Token au tier 20 (Ethereum, Solana). Aucune preuve des tiers 18 ou 20 n’a été produite sur une machine de 48 GB.
Agrégateurs
Un agrégateur surveille la chaîne, prend les preuves de bundle d’une fenêtre de blocs finalisés, prouve un agrégat récursif unique qui les couvre, puis le soumet. Le bloc qui l’inclut est un bloc de scellement. L’agrégateur reçoit la part de preuve des bundles couverts, plus une subvention de bloc en nouveaux RAND, à son adresse de paiement enregistrée. L’agrégation est sans permission : tout opérateur disposant d’un dépôt de garantie peut s’enregistrer.
Elle n’existe que sur une chaîne dont le genesis comporte une section aggregation. La chaîne 20 n’en a pas, et son build refuse de démarrer sur un genesis qui en contient une.
Matériel
| agrégat | RAM de l’hôte | backend |
|---|---|---|
| N = 1 bundle | au moins 64 GB | CPU ; le profil de test en a prouvé un en environ 26 minutes sur un ordinateur portable chargé (327 035 octets) |
| N = 2 | 133 GB mesurés ; la borne précédente était d’au moins 128 GB | le backend GPU pour la production |
| N = 3 | 221 GB mesurés ; la borne précédente était d’au moins 160 GB | le backend GPU pour la production |
| le nœud GPU de la flotte | au moins 160 GB côté hôte, un périphérique de 80 GB (H100 ou A100-80G) | Linux, pilote R580+, CUDA 13, LLVM 21, sm_80+ ; aucun n’existe encore |
Les chiffres de N = 2 et N = 3 ont été mesurés sur un droplet DigitalOcean de 256 GB le 2026-09-28/29, sous le jeu de contraintes 7, et la preuve de sortie de production a nécessité plus que les 256 GB de cette machine. Aucun n’a été re-mesuré sous le jeu de contraintes 8, que font tourner les chaînes 18 à 20 ; considérez donc la ligne N = 1 comme une borne inférieure. Le backend CUDA a tourné pour la première fois sur du matériel réel le 2026-09-28, sur un NVIDIA H100 : ses kernels se compilent en PTX pour sm_80 et sm_90 et correspondent à la référence CPU. La mesure de production sur un nœud GPU de la flotte reste à faire. Chaque nœud paie en outre une construction de clés unique au démarrage pour le programme d’agrégat : 13,0 à 13,4 s au profil de test (2¹⁹), et 30 à 70 s attendues en production (2²¹).
Commandes
# 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
Indicateur aggregate | défaut | signification |
|---|---|---|
--key | obligatoire | la clé d’aggregator que connaît le registre ; signe chaque agrégat |
--rpc | http://127.0.0.1:8545 | le nœud à interroger et auquel soumettre |
--watch | désactivé | continuer d’interroger au lieu de soumettre une seule fois |
--interval-secs | 15 | intervalle d’interrogation avec --watch |
--no-wait | désactivé | rendre la main dès que le nœud accepte l’agrégat |
rand status affiche une section aggregation sur une telle chaîne : les aggregators enregistrés, les blocs non scellés et l’indice du barème de subvention. rand_getUnsealed est la liste de travail.
Installation
Ces étapes suivent les scripts qu’utilise le testnet (deploy/vps-setup.sh, deploy/update-droplet.sh). Elles produisent un validator Linux ou un nœud observateur.
1. Compiler sur une machine de build
La compilation exige build-essential clang cmake pkg-config libssl-dev, Rust 1.98.1 (fixé par rust-toolchain.toml) et une copie de travail de circuits à côté de celle du fullnode. La première compilation prend de 10 à 20 minutes.
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 chaîne 20 exige v0.6.8 sur chaque nœud avant init. Son genesis comporte des champs qu’aucune version antérieure ne lit (testnet, binding_domain, proof_window_blocks, program_state, les groupes rotation et fees du bridge, les plafonds de gas, l’admission au staking par vote), et v0.6.8 intègre les changements de consensus CON-4 et CH-1 de l’audit v6. Les preuves sont toujours produites sous le jeu de contraintes 8, comme sur les chaînes 18 et 19, avec une preuve d’autorisation à côté de chaque preuve de bundle (hc_auth). Une version v0.6.8 refuse le genesis des chaînes 14 à 17 à run et verify. Exécutez la compilation unique que fait tourner la flotte. Le fichier genesis se trouve sur la branche main du fullnode (commit 74cfaca0), et non dans le tag v0.6.8, d’où la troisième ligne git. La copie de circuits doit être au commit à partir duquel la version a été vendorisée, ce que lit la deuxième ligne git ci-dessus dans l’arborescence du fullnode. Ajoutez -p randprotocol-prover pour compiler aussi rand-prover.
2. Installer les binaires sur le nœud
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. Clé, genesis, pare-feu
Sur le nœud :
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
Générez la clé sur le nœud, comme ci-dessus, et gardez-la hors de toute copie de travail. Plus aucune clé n’est versionnée dans le dépôt du fullnode (audit v3, OPS-1). Les fichiers deploy/node-*.key.json committés pour les chaînes 8 à 13 sont des graines publiées ; les clés de validator de la chaîne 20 (les dix-huit générées pour la chaîne 14 et les huit liées par bond sur la chaîne 15) ont été générées hors dépôt, et la flotte conserve la clé de chaque droplet dans /root/keys/node-<name>.key.json, en dehors de l’arborescence source. L’emplacement compte sur un nœud provisionné par les scripts de la flotte : deploy/rebuild-vps.sh et deploy/push-to-vps.sh synchronisent /root/fullnode par rsync avec --delete, de sorte qu’une clé conservée dans cette arborescence est supprimée par la reconstruction suivante et que l’unité ne redémarre plus. Depuis v0.6.8, keygen refuse d’écraser un fichier existant (v0.6.7 l’écrasait sans demander) ; le test -e rend la ligne sûre à relancer dans les deux cas. Sauvegardez la clé hors de l’hôte avant de la lier par bond.
init affiche le hash du genesis. Il doit valoir 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135 (chaîne 20). Le fichier genesis est genesis-chain20.json, dans deploy/ du dépôt du fullnode, sur main. Nommez le répertoire de données d’après les huit premiers caractères du hash, comme le fait la flotte (data-<name>-6210cf07), afin qu’il n’entre jamais en collision avec celui de la chaîne 19 (-a3defc93) ni avec celui d’une chaîne ultérieure. Le genesis fixe ces limites. Le plafond de preuve était de 8 MiB sur les chaînes 13 à 16 et il est de 4 MiB depuis la chaîne 17, où une transaction a commencé à porter jusqu’à trois preuves :
| limite | chaîne 20 |
|---|---|
max_program_words | 65,535 |
max_proof_bytes | 4,194,304 (4 MiB) |
max_block_bytes | 20,971,520 (20 MiB) |
max_call_envelope_bytes | 65,536 |
max_program_public_words | 32,768 |
envelope_bytes | 1,860 (chaque enveloppe de note, avec son champ de mémo chiffré) |
proof_window_blocks | 1,024 (256 sur la chaîne 19) |
program_state | frais de cellule de 0.1 RAND (10,000,000 unités) ; au plus 8 lectures, 8 écritures et 4 paiements par invoke |
section aggregation | aucune (agrégation désactivée) |
Le genesis de la chaîne 20 comporte aussi consensus_domain: 1, binding_domain: 1, testnet: true, une section staking avec admission par vote, une section gas avec des plafonds de prix, les groupes rotation et fees du bridge, hardening_v6 et les deux empreintes de guest hc_bundle et hc_auth ; Exécuter un nœud liste ce qu’ils définissent.
4. Une unité systemd
Voici l’unité qu’écrit deploy/vps-setup.sh, avec les chemins ci-dessus :
[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
Retirez --validator pour un nœud observateur. --prune-history 24h est ce qu’exécutent les validators du testnet, à l’exception des archives ; retirez-le pour un nœud qui conserve l’historique complet, et ne le passez jamais sur mainnet. Les multiaddrs d’amorçage de la chaîne 20 sont les nœuds C (fra1), D (ric1) et E (sgp1), inchangés depuis la chaîne 19. La chaîne 20 fonctionne avec les clés de validator générées pour la chaîne 14, et une identité p2p est dérivée de la clé de validator ; ces identifiants de pair sont donc ceux qu’utilisait la chaîne 14. Un nouveau nœud qui se synchronise depuis le genesis a aussi besoin d’un pair à historique complet ; ajoutez donc l’une des deux archives (obs1, puis 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
Gardez le RPC sur 127.0.0.1 sauf si un pare-feu le protège. Un nœud qui doit servir le public ouvre à côté l’écouteur public de v0.6.8 (--public-rpc <ADDR>) et place un proxy devant celui-ci, jamais devant --rpc (JSON-RPC). Une unité reprise de v0.6.7 ne doit pas passer --prover-accept-spend-key, que v0.6.8 refuse au démarrage.
systemctl daemon-reload && systemctl enable --now rand-node
journalctl -u rand-node -f
rand status # height climbing, peer_count rising
5. Rejoindre l’ensemble des validators
Une nouvelle clé ne figure dans l’ensemble d’aucune epoch. Sur la chaîne 20, elle doit d’abord être admise par vote : son genesis définit staking.admission_by_vote, de sorte que les validators détenant plus des deux tiers du poids de vote la signent chacun avec rand-node admit sign --candidate <key or registration> --key <validator key> --genesis-hash <chain 20's hash>, et que l’un d’eux soumet les votes avec rand-node admit submit ; rand_getAdmitted la liste alors. Liez ensuite par bond au moins 1,000 RAND à cette clé : affichez une inscription avec rand-node register --key /root/keys/node.key.json --payout rand1… --v2 (la chaîne 20 refuse une inscription v1), puis liez par bond depuis un wallet avec rand bond <address> 1000 --registration <hex>. Le bond attend son epoch d’activation, au plus tôt trois frontières de 1,000 blocs après son commit, et au plus 2,500 bps du poids actif deviennent du nouveau poids par frontière (la chaîne 19 le plafonnait à 10,000 RAND fixes). Staking l’explique pas à pas.
6. Mise à jour
Cela vaut pour une version qui exécute la même chaîne. Passer d’une chaîne antérieure à la chaîne 20 n’est pas une mise à jour : il faut le nouveau binaire, le nouveau genesis et un répertoire de données neuf, et le répertoire de données de l’ancienne chaîne peut être supprimé ensuite (deploy/retire-chain-dirs.sh ; la flotte le conserve un jour pour un retour arrière). Pour déployer une nouvelle version sans coupure de chaîne, compilez une fois, comparez le sha256 de rand-node et de rand, arrêtez le service, installez, puis redémarrez, un nœud à la fois. Certaines versions sont déployées en arrêt total puis redémarrage total ; les notes de chaque version précisent lesquelles (la règle de palier d’appel de v0.5.6, le changement de format Status de v0.5.7, la vérification de preuve plus stricte de v0.6). v0.6.7 a été déployée sur la chaîne 18 un nœud à la fois ; v0.6.8 est venue avec la chaîne 20, en arrêt total puis redémarrage total, car ses changements de consensus CON-4 et CH-1 ne doivent jamais être déployés nœud par nœud. Attendez que chaque nœud ait rejoint le réseau avant le suivant, afin que le quorum ne manque jamais de plus d’un nœud. deploy/update-droplet.sh <ip> [build-host] fait exactement cela via SSH.
Les versions jusqu’à v0.6.8 ont été compilées à la main sur une seule machine et ne sont pas signées. La release GitHub v0.6.8 comporte rand-node, rand, rand-prover et SHA256SUMS, compilés sur le nœud E ; cette somme de contrôle détecte un téléchargement corrompu et ne garantit pas la machine de build. v0.6.8 fournit un workflow de release qui compile les binaires à partir du tag, et deploy/update-droplet.sh refuse une installation sans SHA256SUMS signé sauf si ALLOW_UNSIGNED=1 est défini. deploy/release-signers ne liste encore aucune clé, de sorte que le chemin signé n’a pas été utilisé.
Les chaînes 15, 16, 17 et 18 sont entrées en service en 2,7 jours (du 2026-09-26 au 2026-09-29), chacune par un arrêt total de la flotte. La chaîne 19 a suivi le 2026-10-01 à 03:43 UTC, un re-genesis de la chaîne 18 sur la même version, puis la chaîne 20 le même jour à 06:17 UTC, issue d’un snapshot de la chaîne 19 au hard fork v0.6.8 ; chaque nœud s’est arrêté à la hauteur 7,700 de la chaîne 19. Une politique de coupure écrite (2026-09-30) s’applique à partir de la chaîne 20 ; le compte rendu de coupure de la chaîne 20 a dispensé de la reconstruction par un second opérateur, car un seul opérateur détient toutes les clés. Une coupure exige une raison qu’une mise à jour progressive ne peut satisfaire, une liste publiée de ce qu’elle apporte et de ce qu’elle abandonne, une checklist de reconstruction des clients faite au préalable, un second opérateur qui reconstruit le genesis jusqu’au même hash, un plan de retour arrière et un identifiant de chaîne jamais utilisé.