Rand Protocol
Documentation
Développeurs

Développeurs

Les cinq dépôts, la pile technologique, la zkVM de Rand et ses jalons, les phases du pool blindé, les travaux de la v0.5 et les versions publiées depuis, jusqu'à la v0.6.8 sur la chain 20, l'organisation du code source du fullnode, ce qui est spécifié mais pas encore livré, ainsi que la manière de compiler, tester et contribuer.

Rand est open source. Le full node, l’explorateur, le bridge, la recherche sur les preuves et les clients wallet vivent chacun dans leur propre dépôt sur GitHub. Lisez le code, exécutez les tests, envoyez des correctifs. Cette page est la carte : où se trouve chaque composant, avec quoi il est construit, jusqu’où le système de preuve est arrivé, et où il s’arrête aujourd’hui.

Dépôts

dépôtcontenulangage
randprotocol/fullnodeFull node et wallet de référence : HotStuff BFT chaîné, réseau libp2p, le pool de notes RAND protégé, le vérificateur de preuves zkVM, JSON-RPC, la CLI wallet rand et le prouveur délégué rand-prover.Rust
randprotocol/randscan.orgExplorateur de blocs derrière randscan.org : un indexeur axum avec une API REST et WebSocket sur PostgreSQL, et un frontend Next.js.Rust · TypeScript
randprotocol/bridgeBridge à gardiens pour USDT et USDC depuis Ethereum, Binance Smart Chain, Tron et Solana : les contrats de garde, le format d’attestation partagé et ses vecteurs de test.Solidity · Rust
randprotocol/zkp-circuitsPrésentations pas à pas des systèmes de preuve (Groth16 contre STARK, pool protégé, signatures en anneau, mixer), research/, la zkVM de référence de Rand, recursion/, la VM de récursion, la chaîne d’outils invitée et les deux traducteurs, ainsi que les noyaux CUDA. La compilation du fullnode exige que ce dépôt soit cloné à côté, sous le nom circuits/.Rust
randprotocol/clientsLes clients wallet : bureau, web, iOS et Android.Rust · Swift · Java · JavaScript

La pile

Du Rust de bout en bout. Rand est sa propre chaîne : un nœud HotStuff BFT avec une couche de gossip libp2p, un pool de notes entièrement protégé comme registre, des signatures et un chiffrement de notes post-quantiques, et la zkVM de Rand pour le calcul confidentiel, le tout dans le dépôt fullnode. Le système de preuve lui-même est la partie en recherche active, plus bas.

couchece qui s’exécute
ConsensusHotStuff BFT chaîné, quorums pondérés par la mise, validation en trois chaînes
Réseaulibp2p : TCP, Noise, Yamux, gossipsub, Kademlia, mDNS sur les LAN
RegistrePool de notes protégé : arbre Poseidon2 de profondeur 32, ensemble de nullifiers, un bundle à actifs cachés 4 entrées-4 sorties par transaction (2 entrées-2 sorties jusqu’à la chaîne 13) ; depuis la chaîne 17, une seconde preuve d’authentification de palier 10 à côté de la preuve du bundle (autorisation scindée) ; depuis la chaîne 18, des enveloppes de note de 1 860 octets avec un mémo chiffré
JetonsRPL : un jeton est une entrée du registre du ledger avec un identifiant rpl1…, pas un contrat ; il circule sous forme de notes dans le même pool
StakingRegistre public des validateurs : mise issue d’un bundle, désengagement sur deux époques, époques de 1 000 blocs ; depuis la chaîne 20, un nouveau validateur est admis par un vote de l’ensemble
Calcul confidentielzkVM de Rand : RV32IM sous un STARK Plonky3 par lots, FRI à masquage ZK, ensemble de contraintes 8 ; depuis la chaîne 18, un appel déclare une limite de gas que le circuit applique et paie par gas et par KiB ; depuis la chaîne 20, un programme conserve son état dans des cellules et détient de la valeur dans un coffre (RPL-2)
CryptographieDilithium2 · ML-KEM-768 · Poseidon2 · BLAKE3 · ChaCha20-Poly1305
StockageUne RocksDB par nœud, commits avec fsync, contrôle d’intégrité au démarrage ; élagage facultatif de l’historique (--prune-history 24h), les nœuds d’archive conservant tout
BridgeVerrouillages attestés par des gardiens sur quatre chaînes, avec un quorum de cosignatures Dilithium2 sur chaque émission ; un actif bridgé est une note dans le même pool
LangageRust partout ; Solidity pour le bridge, TypeScript pour l’explorateur

Une seule relation pour tous les programmes

La relation d’exécution universelle R_exec du whitepaper existe sous forme de code : rand_zkvm, une machine RV32IM prouvée sous un unique STARK par lots sur Plonky3 au-dessus du corps Goldilocks. Elle prouve que quelque trace a exécuté le programme hc vers ces sorties publiques, sur des entrées engagées par un H_IN salé, et rien du programme n’est jamais un paramètre du vérificateur. Publier un programme confidentiel signifie enregistrer un hash, jamais générer un circuit sur mesure.

Le système de preuve est transparent, sans setup de confiance ni courbe à couplage, et son hypothèse est une fonction de hachage résistante aux collisions. Tout autre composant qui touche aux preuves est censé converger vers cette crate plutôt que de développer la sienne. La crate se trouve dans zkp-circuits/research et est intégrée au fullnode à l’ensemble de contraintes 8 (circuits aeacf31, fullnode v0.6.7 et v0.6.8). Les tableaux et mesures ci-dessous décrivent l’ensemble de contraintes 5 (jalon M4.2), sauf lorsqu’une ligne nomme un ensemble plus récent ; ils sont tirés des fichiers docs/zkvm.md, docs/zkvm-milestones.md et docs/confidential.md du fullnode à la date du 2026-09-13, et les mesures sont citées telles que relevées sur un portable Apple Silicon, non comme des objectifs.

Huit tables sur des bus nommés, une neuvième à la demande

Un seul engagement, une seule ouverture FRI. Les tables ne s’appellent jamais entre elles ; elles échangent des faits sur des bus LogUp nommés (PROGRAM, PROGRAM_WORD, MEMORY, ALU, POSEIDON2, INPUT_DIGEST, INPUT_READ, KECCAK et les consultations de plage et de quartet) et le vérificateur contrôle que chaque bus est équilibré globalement. Le degré maximal des contraintes de chaque table est fixé par un test sous le plafond de 8 que permet le blowup FRI.

tablenaturerôle
programtémoinMots d’instruction bruts décodés dans le circuit depuis M3.4, condensés par le cpu en hc
cputémoinUne ligne par cycle, plus des lignes de condensat qui absorbent le programme dans hc et les entrées salées dans H_IN
memorytémoinRegistres et RAM dans une seule table, triés par (space, addr, ts) ; accès inférieurs au mot depuis M2.5
alutémoinArithmétique par membres d’un octet, décalages, comparaisons ; multiplication et division RV32M depuis M2.6
rangeprétraitée · 256 lignesContrôles de plage et consultation des puissances de deux
nibbleprétraitée · 256 lignesAND, OR, XOR sur 4 bits ; une correspondance est en soi un contrôle de plage sur les deux opérandes
poseidon2témoinUne ligne par ronde de permutation, en blocs de 32 lignes ; alimente le bus POSEIDON2 et les deux condensats
inputtémoin · depuis M4.1Une ligne par mot d’entrée privé ; alimente INPUT_DIGEST et INPUT_READ, de sorte qu’une lecture ne peut échapper à l’engagement
keccaktémoin · facultativeKeccak-f[1600] en blocs de 32 lignes, présente seulement dans une preuve dont l’invité a appelé KECCAK (M4.2)

Trois ensembles de contraintes ont été livrés depuis. L’ensemble 6 a ajouté une table public obligatoire pour l’entrée publique d’un programme fixée au déploiement, liée au condensat non salé H_PUB, ainsi qu’une table sha256 facultative à côté de keccak. L’ensemble 7 (chaîne 16) masque chaque terminal LogUp sur un nouveau bus BLIND et impose à chaque table déclarée un plancher de 2⁷ lignes, et ajoute l’appel système POSEIDON2_LEN à longueur liée. L’ensemble 8 (chaîne 18) ajoute une colonne GAS à la table cpu et une valeur publique, le GAS_LIMIT déclaré.

Ce que révèle une preuve

Public : le hash de code hc (huit mots de condensat dans le circuit), l’engagement d’entrée salé H_IN (huit mots), le palier de gas et huit mots de sortie. Depuis l’ensemble de contraintes 6 également H_PUB, le condensat de l’entrée publique, et depuis l’ensemble de contraintes 8 la limite de gas déclarée. L’en-tête de la preuve déclare les hauteurs des tables Keccak et SHA-256, il montre donc si un appel a haché et, au-dessus du plancher de 2⁷, approximativement dans quelle mesure.

Caché : les entrées privées (H_IN est salé, il est donc masquant autant que liant) ; chaque mot d’instruction, car le vérificateur contrôle hc et jamais le programme ; chaque valeur de registre et de mémoire ; chaque branche prise ; le nombre exact de cycles et le gas exact utilisé ; et les appels système exécutés, hormis ce que montrent les hauteurs des deux tables de hachage.

Le palier est public pour chaque preuve parce que la taille d’un STARK révèle déjà la hauteur de sa trace ; cacher l’indice n’apporterait rien. hc est liant, pas masquant : voir où il s’arrête aujourd’hui.

Mesures, à l’ensemble de contraintes 5

FRI80 requêtes · 20 bits de PoW · blowup 8 · arité 8 · ZK activé ; 260 bits conjecturés, environ 86 prouvés. Le réglage à 27 requêtes de M2 a été annulé par l’audit du 2026-09-12
Appelprivate_payment au palier 10 : environ 7 s pour prouver, environ 1,2 MB de preuve à 80 requêtes (435 KB à 27), contre 21,6 s et 892 KB à M1
TransfertLe guest de bundle 2 entrées-2 sorties des chaînes jusqu’à la 13 : 3 811 mots, environ 9 160 cycles, palier 14 ; environ 100 s pour prouver, environ 1,3 MB de preuve. Le guest à actifs cachés 4 entrées-4 sorties de la chaîne 14 est fixé au même palier : environ 100 s, environ 1,42 MB
VérificationEnviron 16 ms avec une clé chaude ; la première vérification à une nouvelle clé (palier, hauteurs) prend environ 230 ms
BlocBudget de 4 MiB et plafond de preuves de 2 MiB : environ trois transferts protégés par bloc à 80 requêtes

Portable Apple Silicon, build release. C’est la séparation des tables d’octets de M2.3 qui a fait baisser le temps de preuve ; c’est le profil à 80 requêtes qui a fait remonter la taille des preuves. La clé du vérificateur est indépendante du contenu du programme, indexée par le palier et par les hauteurs de programme, d’entrée et de keccak déclarées par la preuve, de sorte qu’un nœud chauffe une clé et la réutilise.

Les jeux de contraintes suivants ont fait évoluer les tailles. Avec le jeu de contraintes 7, une preuve de palier 10 pèse 1 367 688 octets au profil de production, et une preuve de palier 10 qui embarque Keccak 3 283 898 (mesuré le 2026-09-28). Depuis la chain 17, un transfert porte deux preuves : la preuve de bundle de palier 14, d’environ 1,49 MB, et la preuve d’authentification de palier 10, d’environ 1,37 MB et d’environ 7 s de preuve. Le genesis de la chain 20 fixe un bloc de 20 MiB et un plafond de preuve de 4 MiB, et un appel ne peut pas dépasser le palier 14.

Trois cibles, un seul circuit

Seul RISC-V s’exécute nativement. Les programmes Solidity et Solana s’exécutent soit sur un guest interpréteur au sein de la même relation, avec leur bytecode en entrée, soit sont traduits hors chaîne en programmes RISC-V dont les sorties sont identiques mot pour mot à celles de l’interpréteur. Les opcodes coûteux appellent des tables de coprocesseur dédiées plutôt qu’une simulation bit à bit.

ciblechemincoprocesseurs
RISC-VNatif. RV32IM, soit assemblé à la main via asm.rs, soit en Rust no_std compilé pour riscv32im-unknown-none-elf et chargé comme binaire plat depuis M4.1, soit construit à partir de Rust ou de C par rand-guest dans le conteneur d’image (Déployer un programme Rust)Poseidon2 (et POSEIDON2_LEN depuis le jeu 7) ; Keccak-f[1600] depuis M4.2 ; SHA-256 depuis le jeu 6
Soliditysolc --bin-runtime vers du bytecode EVM, puis soit le guest interpréteur evm.bin (bytecode en entrée), soit evm2rv, qui traduit le bytecode en C que rand-guest compile en une image RV32IM aux sorties identiques (Le transpileur Ethereum)Keccak-256 (table livrée), arithmétique modulaire sur 256 bits, ECRECOVER, appels système de témoins de Merkle pour le stockage
Solana / SVMun ELF sBPF, exécuté par le guest interpréteur sbpf.bin ou traduit par sbpf2rv en une image RV32IM aux sorties identiques (Le transpileur Solana)SHA-256, vérification Ed25519, multiplication 64 bits

Jalons

Le jalon 1 a prouvé la machine généraliste. Le jalon 3 en a fait un pool blindé : un transfert avec appartenance dans le circuit se prouve sous R_exec, et le vérifieur contrôle hc sans jamais voir un mot de programme. Le jalon 4 est la compatibilité : son chargeur, son engagement d’entrée et sa table Keccak ont été livrés avec les jeux de contraintes 4 et 5, et la table SHA-256 avec le jeu 6. Les guests interpréteurs EVM et sBPF, la chaîne d’outils rand-guest et les deux traducteurs sont construits. Le transfert ERC-20 a été prouvé, sur une machine de 128 GB ; la preuve SPL Token, au palier 20, ne l’a pas été. Le jalon 5 est la VM de récursion qui sous-tend l’agrégation de blocs, construite et désactivée sur toutes les chains. Les jeux de contraintes 7 et 8 ont suivi les revues de septembre et le modèle de gas.

idpérimètrecritère de sortiestatut
M1Cinq tables, ISA de base RV32I, HALT/WRITE_OUTPUT/READ_INPUT, ZK activé, remplissage par paliers, assembleur, émulateurfib, memcpy, bubble_sort, alu_mix et balance_check se prouvent et se vérifient ; chaque test de triche est rejetéterminé. 44 tests ; une revue ultérieure a comblé cinq failles de solidité en une seule vague
M1.5Clés de visualisation : un guest de transfert blindé à une entrée et une sortie, enveloppes de notes sous ML-KEM-768 et ChaCha20-Poly1305, divulgation à portée de partie et de transaction, un registre simuléUn transfert se prouve au palier 12 et le registre l’accepte ; chaque portée de divulgation ouvre exactement ses propres lignes ; une clé de visualisation ne peut pas dépenserterminé. Non intégré au nœud
M2Cache de clés de vérification, FRI réajusté à une cible conjecturée de 100 bits, table d’octets scindée en plage et quartet, chargements et stockages de sous-mots, extension RV32MLivré plus étroit que prévu : le chargeur de binaire plat et une liaison READ_INPUT plus ferme ont été reportés à M4.1terminé. fib au palier 10 : preuve de 892 KB à 268 KB, preuve de 21,6 s à 3,1 s, première vérification de 2,17 s à 16 ms. Jeu de contraintes 3, un hard fork
M3Puce et appel système Poseidon2 ; NOTE_COMMIT, NULLIFY et MERKLE_VERIFY comme routines du guest au-dessus ; l’engagement dépensé retiré de la sortie publique ; la table de programme comme témoin avec hc digéré dans le circuitLa relation de transfert se prouve sous R_exec avec appartenance dans le circuit, et verify(hc, proof) ne voit jamais un mot de programmeterminé. Guest de transfert : 4 554 instructions, 4 903 cycles, palier 14. Le parcours de Merkle est désormais une boucle comptée, si bien que la taille du programme ne dépend plus de la profondeur de l’arbre
CUDABackend de prouveur GPU : NTT et engagements Merkle Poseidon2 sous forme de noyaux CUDA derrière les traits Dft et Mmcs de Plonky3 ; rand send, call et deploy acceptent --cudaChaque guest se prouve et se vérifie via le jumeau de référence en Rust pur et le pilote factice ; le vérifieur CPU ne distingue pas les backendsterminé ; première exécution sur matériel le 2026-09-28. Sur un NVIDIA H100, les noyaux se compilent en PTX pour sm_80 et sm_90 et correspondent à la référence CPU et Plonky3. La re-mesure de production sur un nœud GPU de la flotte reste à faire. Un appel CUDA ne peut pas sceller une enveloppe d’entrée, car le sel ne quitte jamais le prouveur
M4.1Le chargeur de binaire plat et les premiers guests Rust no_std compilés pour riscv32im-unknown-none-elf ; l’engagement d’entrée salé H_IN avec sa propre table d’entrée, de sorte que READ_INPUT soit une recherche dans un vecteur engagéUn guest construit par la chaîne d’outils standard se charge, se prouve et se vérifie ; deux lectures d’un même indice d’entrée concordent et les entrées sont liées à H_INterminé. Livré le 2026-09-11 comme jeu de contraintes 4 : 26 valeurs publiques, huit tables, un hard fork
M4.2Une table de coprocesseur Keccak-f[1600] écrite à la main et un appel système KECCAK, présents dans une preuve seulement si le guest les a utilisés ; hauteur de mémoire déclarée par la preuve ; une clé de vérification indexée sur quatre composantes ; FRI de retour à 80 requêtes après l’audit du 2026-09-12keccak256 se prouve comme guest compilé, et une preuve sans la table a exactement la même forme qu’une preuve de M4.1terminé. Livré le 2026-09-12 comme jeu de contraintes 5, un hard fork. Une preuve avec Keccak est plus grande d’environ 1,9 MB, au-delà du plafond par défaut de 2 MiB. Une chain dont le genesis relève le plafond en admet une : la chain 13 (8 MiB) a accepté le 2026-09-19 un appel de 3,41 MB embarquant Keccak, et le plafond de la chain 20 est de 4 MiB
M4.3 · M4.4Guests interpréteurs EVM et sBPF compilés en RV32IM, avec le bytecode étranger en entrée ; une table de coprocesseur SHA-256 aux côtés de Keccak ; puis la chaîne d’outils rand-guest et les traducteurs evm2rv et sbpf2rv (2026-09-18)Un transfert ERC-20 et un Transfer SPL se prouvent chacun sous R_execconstruit ; une preuve de sortie réalisée. evm.bin (18 009 mots) et sbpf.bin (8 317) exécutent les vecteurs ERC-20 et SPL Token, et les images traduites leur correspondent mot pour mot. Le transfer ERC-20 a été prouvé au palier 18 sur un droplet de 128 GB le 2026-09-19 (pic de 85,0 GB, 53,8 min) ; la preuve SPL Token, au palier 20, est extrapolée à environ 330 GB et n’a pas été réalisée (mémoire de preuve). Aucun des deux n’est appelable sur la chain : un appel est plafonné au palier 14
M5La VM de récursion (rVM) : une machine native Goldilocks à 24 instructions dont les programmes vérifient les preuves zkVM de Rand, un programme d’agrégation générique en N par forme de preuve interne, une séparation des backends CPU et CUDA, et un auto-vérifieur (M5.1 à M5.4, 2026-09-13 au 2026-09-16)50 vraies preuves de bundle de production acceptées et 50 preuves altérées refusées à l’étape nommée ; une preuve rVM du programme vérifieur sur une vraie preuve de bundle se vérifie nativement (profil de test)construit ; les preuves de production exigent une grosse machine. Intégré comme crates/randprotocol-rvm. L’agrégation côté chain est fusionnée et désactivée sur toutes les chains (ci-dessous)
jeu 7Chaque terminal LogUp masqué ; chaque table déclarée plancher à 2⁷ lignes ; contrôles de plage sur 32 bits pour les mots d’entrée, publics et de sel ; l’appel système POSEIDON2_LEN ; un correctif JALR ; clés de vérification salées à partir de key_derivation_v2Les correctifs des revues zkVM des 2026-09-27 et 28 qui déplacent une clé de vérification, regroupés en une seule coupeterminé. Fullnode v0.6.1, chain 16 (2026-09-28), un hard fork
jeu 8Le compteur de gas : une colonne GAS dans la table cpu et un GAS_LIMIT public, avec GAS ≤ GAS_LIMIT prouvé dans le circuit ; le gas exact de l’exécution reste privéUn appel paie la limite qu’il déclare, et chaque preuve de bundle déclare la même limite figéeterminé. Fullnode v0.6.7-rc1, chain 18 (2026-09-29), un hard fork. bundle_gas_limit vaut 20 479

Phases du pool blindé

Le registre du fullnode a été livré en trois phases, chacune un hard fork (docs/shielded.md §7). S1 a remplacé le registre de comptes par un pool de notes ; S3 a réintroduit le pont sous forme de notes et a été livrée en premier ; S2 a ajouté le staking par-dessus. Les trois sont sur main et sur la chain actuelle.

Les lignes sous S2 correspondent au travail de la v0.5. Chacune est un hard fork. Elles ont été regroupées dans une chaîne neuve, la chaîne 14, créée le 2026-09-20 à partir du build b3c594c, puis étiquetée v0.5 le jour même après un aller-retour zUSD en conditions réelles via les points d’accès source déployés. La chaîne 15, en ligne depuis le 2026-09-26 sur v0.5.8 et les versions suivantes, a repris l’ensemble, avec les correctifs conditionnés au genesis des audits v4 et v5 activés : un faucet à liste d’autorisation avec un budget par epoch, une activation différée des bonds, un plafond de poids de stake, des enregistrements liés au genesis, consensus_domain 1, les règles de bridge v2 ainsi que le plafond du registre de tokens, des frais d’enregistrement brûlés et une borne de 2⁶³ sur les notes. La chaîne 20, en ligne depuis le 2026-10-01 à 06:17 UTC sur v0.6.8 (c9c9bd3c), un hard fork de la chaîne 19, conserve tout cela et y ajoute le travail des versions v0.6, listé ci-dessous.

idpérimètrecritère de sortiestatut
S1Le pool lui-même : notes, lots prouvés à 2 entrées et 2 sorties, arbre d’engagements Poseidon2 de profondeur 32 et ensemble de nullifiers, le portefeuille rand avec prouveur local, le RPC expurgéUn transfert protégé entre portefeuilles, une course de double dépense entre deux validateurs et un déploiement suivi d’un appel payés par des lots passent tous dans la suite de tests du clusterterminé. En ligne sur la flotte publique depuis la chaîne 6 (2026-09-12)
S3Le bridge sous forme de notes : un avoir ponté porte l’indice d’actif du registre, une attestation dépose une note unique que la chaîne calcule elle-même, BridgeBurn est l’unique transaction à deux lots ; enveloppes scellées pour les entrées d’appel, ouvrables par l’appelant, par une clé propre à l’appel ou par un auditeur désignéUn actif ponté est émis, dépensé et brûlé sous forme de note ; un appelant peut divulguer ce sur quoi un programme a tourné sans le publier, et rand open-call vérifie l’ouverture par rapport à H_INterminé. Livré en premier. Les chaînes 9 à 13 ont laissé la section bridge hors de leur genesis ; toutes les chaînes depuis la 14 l’incluent. Depuis la chaîne 14, une burn tient en un seul lot, et non deux
S2Le staking sur la chaîne protégée : un registre public des validateurs, Bond à partir de la burn d’un lot, Unbond sur deux epochs, Withdraw vers une note à une adresse de versement, des epochs de 1 000 blocs qui recalculent l’ensemble, et un audit de l’offre portant sur le registre et le poolUn cinquième validateur s’enregistre, place un bond et propose à partir de l’epoch suivante ; un autre se retire de l’ensemble par unbond et retire ses fonds vers une note que son portefeuille de versement dépense ; les deux passent dans la suite de tests du clusterterminé. L’arbre d’engagements local du portefeuille a suivi le 2026-09-21 : un portefeuille calcule ses propres témoins et n’indique plus à son nœud quelle feuille il dépense
RPLLe standard de token (docs/tokens.md) : un token est une entrée de registre dans le grand livre avec un identifiant bech32m rpl1… de 62 caractères ; la création est sans permission moyennant des frais d’enregistrement en RAND ; l’autorité de mint est fixée à l’enregistrement : aucune, une clé ou le bridge ; les symboles ne sont pas uniques ; rand token create, mint, set-authority, burn, info, list, ainsi que rand_getTokens, rand_getToken, rand_getTokenSupplyUn token est enregistré, émis, envoyé avec rand send --asset et brûlé sous forme de notes dans le même poolen service depuis la chaîne 14 (v0.5). Sur la chaîne 20, les frais d’enregistrement sont de 1 RAND, brûlés, le registre contient au plus 4 096 tokens, et le genesis inscrit zUSD à l’indice 1
RPL-2L’état des programmes (docs/program-state.md) : des cellules par programme (une clé de 8 mots vers une valeur de 8 mots, dans la racine d’état), un coffre public par actif, un token émis uniquement par son programme, et l’action Invoke (Action 33), un appel qui déclare les cellules qu’il lit et écrit ainsi que les notes qu’il verse ; rand program invoke, state, vault, ainsi que rand_getProgramCell, rand_getProgramCells, rand_getProgramVaultLe grand livre n’applique une transition que si chaque lecture déclarée est toujours valide et que le coffre couvre chaque versement ; une lecture périmée est refusée et à nouveau prouvéeen service depuis la chaîne 20 (v0.6.8). cell_fee de 0,01 RAND par cellule créée ; au plus 8 lectures, 8 écritures et 4 versements par invoke. Voir Programmes
lot à actif cachéChaque transaction porte exactement un lot de 4 entrées et 4 sorties à la place de celui de 2 entrées et 2 sorties : les emplacements 0–1 contiennent l’actif privé (des leurres sur un transfert en RAND seul), les emplacements 2–3 sont toujours en RAND et paient les frais. Le transfert de token à deux lots et la burn de bridge à deux lots disparaissentUn transfert de RAND et un transfert de n’importe quel token RPL publient exactement la même forme, de sorte que l’actif déplacé est cachéen service depuis la chaîne 14 (v0.5). Niveau 14, environ 100 s de preuve, environ 1,42 MB de preuve sur les chaînes 14 et 15 ; hc_bundle 83d3a370… à ce moment-là. Les chaînes 18 à 20 imposent le guest de lot v3, hc_bundle 60af094a…, environ 1,49 MB
liaison de transactionChaque preuve de lot est produite sur, et vérifiée par rapport à, H("rand-tx-bind-1", chain_id ‖ tx with proofs blanked), porté dans le segment des entrées publiquesUne preuve copiée, non modifiée, soumise à nouveau avec une destination, un validateur ou un mémo modifié est refuséeen service depuis la chaîne 14 (v0.5). Depuis la chaîne 20 (binding_domain 1), la préimage est H("rand-tx-bind-2", genesis hash ‖ chain_id ‖ …), et chaque message d’action signé porte lui aussi le hash du genesis, de sorte que rien de ce qui a été prouvé ou signé pour une chaîne ne se vérifie sur une autre
B1–B4Renforcement du bridge (docs/bridge.md §§14–20). B1 : un plafond de mint quotidien par backing, et une clé de pause qui ne peut que mettre en pause (la reprise exige le quorum PQ). B2 : un horodatage de bloc de plus de 60 s après celui de son parent est invalide, et un validateur ne vote pas pour un bloc en avance de plus de 15 s sur son horloge, si bien que les validateurs ont besoin de NTP. B3 : un quorum de cosignatures Dilithium2 sur chaque mint. B4 : l’inscription d’un token ponté ou d’un backing après le genesis sous le quorum de gardiens PQ, sans coupure de chaînezUSD, un token à sept backings (USDT et USDC sur Ethereum, Binance Smart Chain, Tron et Solana), est enregistré par transaction, et total_supply == Σ backings.locked tient par construction. Le test local en neuf phases (zusd_e2e.rs : quatre validateurs, vraies preuves, faucet, enregistrement, dépôt, transfert, burn, audit) a réussi 9 phases sur 9en service depuis la chaîne 14 (v0.5). Sur la chaîne 20 : plafond de mint de 100 000 zUSD par jour et par backing, plus un plafond global de 4 000 zUSD par période glissante de 24 heures (règles de bridge v2), ensemble de gardiens 1 avec huit gardiens PQ, des frais de 10 bps en zUSD sur chaque mint et chaque burn (bridge.fees), et des rotations de gardiens qui exigent la possession et attendent 86 400 s (bridge.rotation). zUSD est inscrit dans le genesis de la chaîne 20 avec ses sept backings et les 99 zUSD verrouillés au moment de la coupure
audit v3Les correctifs du troisième cycle d’audit interne, dirigé par un cofondateur (2026-09-19 ; aucun audit indépendant n’a été réalisé). POOL-1 : un Mint de faucet porte l’ouverture de sa note (pk, time, r), l’admission recalcule l’engagement, et le minter signe rand-mint-2 ; les notes d’allocation du genesis portent aussi une ouverture. RPC-1 : rand_getWitness(es) exécute au plus deux reconstructions d’arbre à la fois et répond -32000 busy après 10 s. OPS-1 : les dix-huit clés de validateur ont été renouvelées, générées hors du dépôt, et aucune clé n’est suivie dans le dépôtUn mint dont l’engagement s’ouvre sur plus que son montant est refusé ; aucune clé de la chaîne 14 n’a jamais figuré dans le dépôten service depuis la chaîne 14 (v0.5). PRIV-1, la requête de témoin qui désigne la feuille, a été close le 2026-09-21 par l’arbre propre du portefeuille

Versions depuis la v0.5

Chaque version est un tag git accompagné d’une entrée dans le CHANGELOG.md du fullnode. Une version qui modifie le consensus, le format de transmission ou une clé de vérification est livrée avec une nouvelle chaîne ; les autres sont déployées sur la chaîne en ligne un nœud à la fois.

versionce qu’elle apportechaîne
v0.5 à v0.5.8Jetons RPL, zUSD et le pont durci (ci-dessus) ; les correctifs d’audit ; l’élagage de l’historique ; le durcissement du consensus et de la synchronisation14, 15
v0.5.9Correctifs de rescan : le faucet ne frappe qu’à partir des validateurs de genesis, repli exponentiel de la synchronisation, contrôles préalables du gossip15
v0.5.10Partage d’adresses : empreintes, liens randpay: et codes QR ; le mémo chiffré, activé pour la première fois par la chaîne 1815
v0.5.11Acquisition (vesting) à verrouillage temporel dans le genesis pour les allocations de l’équipe, des investisseurs et des partenaires. Conditionnée au genesis et active sur aucune chaîneaucune
v0.6Le zkVM, la rVM et les correctifs d’agrégation issus des revues de septembre15
v0.6.1Jeu de contraintes 7 : masquage LogUp, plancher de table de 2⁷, contrôles de plage sur 32 bits, POSEIDON2_LEN, le correctif JALR. La chaîne 16 a été créée avec hardening_v6 et le guest de bundle v216
v0.6.2Preuve déléguée, phase 1 : le binaire rand-prover et l’option --prover du portefeuille. Un prouveur de phase 1 reçoit la clé de dépense16
v0.6.3, v0.6.4Preuve déléguée, phase 2 : autorisation scindée. La preuve de bundle ne prend plus la clé de dépense, une preuve d’autorisation de palier 10 la prend, et le domaine de l’identifiant de transaction devient rand-txid-317
v0.6.6, v0.6.7-rc1Gas : jeu de contraintes 8, une limite de gas déclarée par preuve, des prix dynamiques du gas et des octets ; le mémo activé. v0.6.6 n’a jamais été publiée sous forme de tag18
v0.6.7Correctifs sur la chaîne 18 qui ne changent aucune règle de consensus : élagage des preuves scellées (dormant), verrouillage du format d’enveloppe, hygiène des clés de visualisation, l’allocateur de la rVM, aliasing des noyaux GPU, couverture de test de l’ALU. Taguée avant la fin de sa suite de tests complète sur tout le workspace18, 19
v0.6.8RPL-2 : cellules de programme, coffres de programme et l’action Invoke. Frais de pont zUSD, dans les deux sens. Les derniers correctifs de l’audit v6 : aucune libération automatique de verrou (CON-4) et un pacemaker à certificat de timeout (CH-1) ; un écouteur --public-rpc, des limites de lecture, des pairs validateurs réservés, des budgets de synchronisation et de gossip, le plafond d’octets du pool, une borne sur le degré déclaré dans l’en-tête d’une preuve (ZKV-4) ; et les règles conditionnées au genesis que la chaîne 20 active : la liaison au hash du genesis, testnet, une fenêtre de preuve de 1 024 blocs, des plafonds de prix du gas et la charge en octets payante, l’admission par vote, le plafond d’entrée de stake exprimé en fraction, la possession et un délai pour les rotations du pont. Les portefeuilles ont besoin de cette version pour envoyer sur la chaîne 2020

Où cela s’arrête aujourd’hui

Les écarts par rapport au livre blanc, énoncés plutôt qu’atténués. Chacun est suivi dans la documentation propre à la crate, avec le jalon qui le referme.

  • hc est liant mais pas masquant : il ne porte aucun sel, de sorte qu’un programme deviné peut être confirmé et que deux déploiements du même programme sont liables. Ce que M3.4 a supprimé, c’est que le vérificateur détienne tout le programme en clair.
  • Un portefeuille construit avant le 2026-09-21 demande des témoins à son nœud, et une demande de témoin désigne la feuille sur le point d’être dépensée. Un rand actuel conserve sa propre copie de l’arbre et ne demande jamais rien ; le nœud sert toujours rand_getWitness pour les anciens portefeuilles.
  • Les dépôts sont publics à la frontière : une frappe du faucet, une note de genesis et un dépôt via le pont portent tous leur montant en clair (depuis la chaîne 14, une frappe et une note de genesis portent aussi leur ouverture, de sorte que la clé du propriétaire est également publique), la même visibilité à un saut que celle d’un dépôt de transparent vers protégé, où que ce soit.
  • La connaissance nulle est statistique, non parfaite. C’est la propriété que le FRI masquant de Plonky3 0.7 fournit réellement, et la crate le dit.
  • Le hash du transcript est Poseidon2 avec des constantes de ronde de développement, et non le SHA3-384 / BLAKE3-384 des articles. Un changement de configuration, pas une réécriture.
  • Avec 80 requêtes FRI, une preuve de bundle pesait environ 1,42 MB sur les chaînes 14 et 15 (environ 1,3 MB jusqu’à la chaîne 13). Depuis la chaîne 17, un transfert porte environ 2,85 MB de preuve : la preuve de bundle, environ 1,49 MB, et la preuve d’autorisation, environ 1,37 MB. Sur une chaîne par défaut, avec des blocs de 4 MiB et un plafond de preuve de 2 MiB, une preuve contenant du Keccak dépasse d’emblée le plafond de preuve ; le genesis de la chaîne 20 fixe des blocs de 20 MiB et un plafond de preuve de 4 MiB (les chaînes 13 à 16 fixent 8 MiB).
  • L’en-tête d’une preuve d’appel n’est pas masqué. Il déclare le palier et les hauteurs des tables Keccak et SHA-256, et indique donc si un appel a effectué un hachage. Les appels validés sur la chaîne 15 avant le plancher du prouveur v0.6 exposaient davantage : une table privée de moins de 2⁷ lignes pouvait être lue dans la preuve. Le plancher du prouveur v0.6 a fermé cette faille pour les nouveaux appels, et le jeu de contraintes 7 avec hardening_v6 en a fait une règle de la chaîne à partir de la chaîne 16.
  • Un appel est plafonné au palier 14, avec au plus 2¹² lignes Keccak (128 permutations) et 2¹³ lignes SHA-256 (128 compressions), et sous hardening_v6, un programme de plus de 8 180 mots ne peut pas être déployé. Les guests interpréteurs EVM et sBPF ainsi que les images ERC-20 et SPL Token traduites dépassent tous cette taille.
  • Quiconque détient le témoin voit tout. Le ZK protège la vue du vérificateur, pas celle du prouveur. Depuis la chaîne 17, un portefeuille peut confier la preuve de bundle à un rand-prover appairé sans lui remettre la clé de dépense, mais ce prouveur détient toujours la clé de visualisation et voit les notes. Le backend CUDA a tourné pour la première fois sur du matériel le 2026-09-28 et n’a pas encore de mesure en production.

Organisation du dépôt

Le workspace Cargo du fullnode, tel qu’il est décrit dans son README et son répertoire crates/.

chemince qu’il contient
crates/randprotocol-core/Logique pure, sans E/S : cryptographie, notes et arbre d’engagements, règles du registre, gas, genesis, la machine à états HotStuff
crates/randprotocol-zkvm/Le zkVM de Rand, importé depuis zkp-circuits/research au jeu de contraintes 8 (circuits aeacf31 ; resynchronisé avec deploy/sync-zkvm.sh), ainsi que le vérificateur de preuves côté chaîne et son cache de clés de vérification
crates/randprotocol-rvm/La VM de récursion, importée depuis zkp-circuits/recursion : une machine native au corps fini dont les programmes vérifient les preuves du zkVM de Rand
crates/bridge-codec/Le format de transmission et la règle de quorum du pont à gardiens, partagés octet pour octet avec les contrats Solidity et le programme Solana
crates/randprotocol-node/Stockage RocksDB, réseau libp2p, mempool, synchronisation des blocs, le serveur JSON-RPC et le binaire rand-node
crates/randprotocol-client/Le binaire de portefeuille rand et la bibliothèque RpcClient, sans dépendance à RocksDB ni à libp2p
crates/randprotocol-prover/Le binaire rand-prover : un prouveur délégué qui prouve des bundles pour les portefeuilles appairés
deploy/Fichiers de genesis du testnet, nodes.env, scripts d’exécution, provisionnement cloud, scripts de bascule et de reconstruction. Aucune clé n’y est suivie depuis la préparation de la chaîne 14
docs/Documentation de référence et spécification de conception
scripts/Testnet local à deux validateurs

Spécifié, pas encore livré

Ces composants sont décrits dans les articles ou dans la documentation du fullnode, mais ne tournent pas : soit ils sont absents des dépôts, soit ils sont construits et activés sur aucune chaîne. Ils sont listés pour que l’écart entre la spécification et le code soit lisible plutôt que déduit.

composantétat
bridge · guardianLes démons guardian et relayer qui exécutent le format d’attestation de bout en bout ; les contrats, le codec et la moitié réceptrice du fullnode sont livrés, les démons ne le sont pas
fullnode · aggregationAgrégation de blocs avec la VM de récursion : scellement, élagage et synchronisation en forme scellée. Construite et désactivée sur toutes les chaînes ; rand-node refuse un genesis comportant une section aggregation. Elle requiert encore l’exercice de bout en bout avec un agrégat forgé, et elle ne supprime que la preuve de bundle, pas la preuve d’autorisation. Les preuves rVM de production exigent une grande machine : sous le jeu de contraintes 7, un agrégat de deux a demandé 133 GB, de trois 221 GB, et la preuve de sortie plus de 256 GB (mesuré les 2026-09-28 et 29 ; non re-mesuré sous le jeu de contraintes 8)
fullnode · vestingAllocations de genesis à verrouillage temporel pour l’équipe, les investisseurs et les partenaires (v0.5.11, docs/vesting.md). Conditionnées au genesis : sans section vesting, les quatre actions de vesting sont refusées, et aucune chaîne n’en a. L’audit de l’offre de la chaîne 20 indique zéro pour tous les compteurs de vesting. Depuis v0.6.8, une entrée révocable est révoquée par un seuil de ses révocateurs, et uniquement vers la trésorerie que nomme son entrée de genesis
fullnode · slashingLe slashing et l’emprisonnement (jailing) pour équivocation du leader sont construits dans v0.6.8 derrière staking.slashing et désactivés sur la chaîne 20 (son genesis n’en comporte pas, alors que les 26 clés de validateur appartiennent à un seul opérateur). Les récompenses de bloc, la balise de leader par tirage au sort par hash, un accumulateur de nullifiers et les appels entre programmes ne sont pas construits. L’état persistant par programme a été livré avec RPL-2 (ci-dessus)
prover/Démon de preuve GPU : réclame des lots dans la file, entre en concurrence à la soumission. Les noyaux CUDA se trouvent dans zkp-circuits et ont tourné pour la première fois sur un NVIDIA H100 le 2026-09-28 ; le démon de marché n’existe pas. rand-prover, qui est livré, prouve pour les portefeuilles qui lui sont appairés et n’est pas un marché
zkp-circuits · M4.4 exit proofUne preuve d’un transfert SPL Token (palier 20), extrapolée à environ 330 GB. Le transfert ERC-20 (palier 18) a été prouvé sur un droplet de 128 GB le 2026-09-19. Ni l’un ni l’autre ne peut être appelé sur la chaîne 20, qui plafonne un appel au palier 14

Compilation et tests

Workflow Rust standard dans chaque dépôt. Le fullnode est un unique workspace Cargo avec une chaîne d’outils figée et une suite de tests de cluster qui démarre de vrais nœuds via TCP. Sa compilation exige que le dépôt circuits soit extrait à côté, dans un répertoire nommé circuits, au commit à partir duquel les crates vendorisées ont été synchronisées (aeacf31 pour v0.6.7 et v0.6.8). La zkVM est un crate autonome de zkp-circuits, avec sa propre chaîne d’outils figée et une démo qui explique ce qu’un appel confidentiel révèle et ce qu’il ne révèle pas.

Le fullnode :

git clone https://github.com/randprotocol/fullnode.git
git clone https://github.com/randprotocol/zkp-circuits.git circuits   # the sibling directory must be named circuits
git -C circuits checkout "$(sed -n 's/^circuits: //p' fullnode/crates/randprotocol-zkvm/guests-compiled/PROVENANCE.md)"
cd fullnode

# Rust 1.98.1 is pinned by rust-toolchain.toml; first build pulls RocksDB and Plonky3, 10 to 20 minutes
cargo build --release        # target/release/rand-node, target/release/rand, target/release/rand-prover

# All crates; release because STARK proving is slow in debug. One to two hours, mostly proving
cargo test --release

# One machine, two validators
scripts/local-testnet.sh
target/release/rand --rpc http://127.0.0.1:8545 status

La zkVM de recherche, dans zkp-circuits/research :

# Toolchain is pinned by rust-toolchain.toml; the first build pulls Plonky3
cargo build --release

# Narrated demo: thirteen proofs, one at production FRI parameters (~6-7 min)
cargo run --release

# Emulator, per-table constraints, cheating provers, ZK, end-to-end, viewing keys, compiled guests (395 tests, ~17 min)
cargo test

La suite du fullnode, telle que mesurée à v0.6.1 sur une machine de 16 vCPU : core 521 tests, node 373, client 117, la suite du prover tricheur 116, les tricheries de bundle caché 21 (75 min), le flux du wallet 6 (53 min), le cluster 26 (44 min) et la porte de bout en bout zUSD 2 (51 min). Les preuves de production de la VM de récursion n’en font pas partie et nécessitent la mémoire indiquée ci-dessus.

Running a node explique comment rejoindre le testnet public avec cette compilation ; le genesis du testnet, les pairs d’amorçage et les scripts d’exécution sont fournis dans le répertoire deploy/ du fullnode, et la page de téléchargement en donne la version courte.

Contribuer

Le fullnode est publié sous licence GNU General Public License v3.0 (GPL-3.0-only) ; il était auparavant sous Apache-2.0. Ouvrez des issues pour les bugs et les propositions de conception sur le dépôt concerné par la modification. Les pull requests sont les bienvenues : exécutez cargo fmt && cargo clippy avant de soumettre et gardez des changements circonscrits. Les issues du fullnode sont le point de départ.

L’architecture, le circuit de confidentialité, la preuve du jeton de frais et le compromis post-quantique sont tous documentés dans le livre blanc de la page des articles. Le répertoire docs/ du dépôt du fullnode est la source à laquelle chaque page de cette documentation est comparée.

Dernière vérification par rapport au commit c0878c3f de fullnode (chaîne 21) le 2026-10-12. Lorsque le code et cette page divergent, c'est le code qui a raison ; signalez-le-nous.