Utilisez cette page pour choisir la bonne bibliothèque lorsque vous interopérez avec la chaîne, pour vérifier un paramètre par rapport à ce que le nœud applique, et pour recalculer vous-même un identifiant ou un engagement. Chaque valeur indiquée ici est celle qu’exécute le code sur la chain 20 (fullnode v0.6.8).
Primitives et leurs usages
| primitive | paramètres | usage |
|---|---|---|
| Dilithium2 | clé publique de 1 312 octets, signature de 2 420 octets ; paires de clés dérivées d’une graine de 32 octets | votes et propositions de blocs des validateurs ; mints du faucet ; Unbond, Withdraw et la Registration d’un validateur ; les votes d’un AdmitValidator (chain 20) ; les actions de l’agrégateur ; l’autorité de mint Key d’un jeton RPL (TokenMint, SetAuthority) ; les cosignatures post-quantiques des gardiens du bridge, sa clé de pause et, sur la chain 20, les preuves de possession des nouvelles clés lors d’une rotation (ci-dessous) |
| ML-KEM-768 | clé d’encapsulation de 1 184 octets, chiffré de 1 088 octets | scellement de la clé propre à chaque transaction d’une enveloppe de note à l’adresse du destinataire ; scellement d’une enveloppe d’entrée d’appel à un auditeur ; scellement d’une tâche de preuve à un prouveur apparié |
| ChaCha20-Poly1305 | clé de 32 octets, nonce aléatoire de 12 octets placé en préfixe, tag de 16 octets | chaque partie d’une enveloppe : corps de note, clés de transaction enveloppées, transcriptions d’entrée d’appel ; les tâches et les réponses d’un prouveur apparié |
| BLAKE3 | sortie de 32 octets, toujours avec une chaîne de domaine en préfixe | adresses, identifiants de transaction, liaison de transaction et liaison d’appel, identifiants de programme, identifiants d’actif des jetons, racine d’état et ses arbres de Merkle, identité p2p, messages de signature, identifiants d’actif du bridge, facteur d’aveuglement d’un dépôt du bridge et facteurs d’aveuglement des notes de frais du bridge |
| Poseidon2 sur Goldilocks | largeur 8, taux 4, capacité 4, éponge à écrasement sans bourrage ; les éléments du message sont des mots de 32 bits ; les 86 constantes de ronde forment une table littérale dans le code source du nœud (poseidon2_constants.rs) depuis la coupe de la chain 15, avec les mêmes valeurs que celles produites auparavant par le tirage à graine | tout ce qui se trouve dans une preuve : clés, engagements de notes, nullifiers, arbre d’engagements, condensat de programme hc, engagements d’entrée H_IN et H_PUB, condensat du bundle, engagement d’autorisation |
| secp256k1 ECDSA + keccak256 | signatures low-s, adresses de gardiens de 20 octets au style Ethereum, mu = keccak256(keccak256(body)) | attestations des gardiens du bridge, de sorte que la même clé fonctionne sur les contrats EVM, le programme Solana et Rand ; sur Rand, chaque attestation exige aussi le quorum Dilithium2 ci-dessous |
| bech32m (BIP-350) | partie lisible rpl, charge utile de 32 octets, 52 caractères de données + 6 caractères de somme de contrôle = 62 | la forme textuelle rpl1… de l’identifiant d’actif d’un jeton RPL |
| Plonky3 batch STARK | Goldilocks p = 2⁶⁴ − 2³² + 1, FRI avec masquage, blowup 8, arité de repliement 8, 80 requêtes, 20 bits de preuve de travail | chaque preuve de bundle, preuve d’auth et preuve d’appel ; une preuve de bundle et sa preuve d’auth portent les huit mots de liaison de leur transaction comme segment d’entrée publique |
Les paramètres cibles du livre blanc diffèrent par endroits de ce qu’exécute l’implémentation (par exemple le condensat de transcription de 384 bits du document, face à la transcription Poseidon2 du zkVM). Ces pages décrivent le code.
Cosignatures post-quantiques sur le bridge
Les attestations des gardiens du bridge sont des signatures secp256k1 ECDSA, qu’un adversaire quantique pourrait falsifier. Depuis la chain 14, chaque BridgeAttest — un dépôt comme une rotation de l’ensemble des gardiens — doit aussi porter un quorum de signatures Dilithium2 des mêmes gardiens sur le même condensat :
M = "rand-bridge-pq-cosign-1" || rand_chain_id (u64 BE) || mu // 63 bytes, deterministic signing
où mu = keccak256(keccak256(body)) est ce que signe le quorum ECDSA. L’identifiant de chaîne Rand dans M empêche une cosignature de testnet d’être valide sur une autre chaîne Rand, même si les clés des gardiens étaient réutilisées. M ne lie que l’identifiant de chaîne, y compris sur la chain 20 : c’est le seul message signé que binding_domain n’a pas déplacé derrière le condensat de genèse, parce que les démons de gardiens qui le signent vivent dans un autre dépôt. Une copie d’une chaîne sous le même identifiant de chaîne, avec le même ensemble de gardiens, accepterait les cosignatures de ses dépôts ; l’indice de l’ensemble de gardiens ne figure pas dans M, si bien qu’une cosignature survit à une rotation de l’ensemble ECDSA. Le champ pq_signatures de l’action est une liste de PqSignature { index: u8, signature }, vérifiée du moins coûteux au plus coûteux : quorum(n) ≤ len ≤ n (PqNoQuorum), indices strictement croissants (PqIndexOrder), chaque indice inférieur à n (PqIndexOutOfRange), chaque signature d’exactement 2 420 octets (PqBadSignatureLength), et enfin chaque signature vérifiée sous pq_guardians[index] (PqBadSignature). Les signataires PQ ne sont pas nécessairement les signataires ECDSA ; chaque quorum est compté séparément. Le champ est inclus dans la liaison de transaction : il ne peut donc être retiré ni remplacé sur une copie.
L’ensemble PQ est le bridge.pq_guardians de la genèse — huit clés de 1 312 octets sur la chain 20, comme sur les chains 15 à 19, alignées par indice sur l’ensemble ECDSA de la genèse, ensemble de gardiens 1 (la chain 14 en avait six, alignées sur l’ensemble 0). Une rotation de l’ensemble de gardiens ECDSA ne le modifie jamais. Sur la chain 14, il était fixé pour toute la vie de la chaîne ; depuis la chain 15, la genèse porte le groupe rules_v2 du bridge, sous lequel un quorum PQ peut remplacer l’ensemble PQ entier (RotatePqGuardians) ou la clé de pause (RotatePauseKey), chacun sous le rotation_nonce du bridge. La genèse de la chain 20 ajoute bridge.rotation : une rotation doit être l’action V2, portant sur le même message la signature Dilithium2 propre à chaque nouvelle clé (preuve de possession), et elle prend effet un jour après son inscription, sauf si la clé de pause actuelle l’annule (Bridge). rand_getBridgeState sert les clés, et un bridge_attest décodé liste pq_signers, les indices qui ont signé. Le même quorum PQ autorise les messages de gouvernance du bridge, chacun étant une disposition big-endian fixe qui porte l’identifiant de chaîne et un nonce. Sur la chain 20 (genèse binding_domain: 1), le chiffre de version de chaque domaine est 2 et le condensat de genèse de 32 octets se place entre le domaine et l’identifiant de chaîne ; les chains 14 à 19 utilisent les formes en -1 :
| message | domaine (chains 14–19 / chain 20) | signé par |
|---|---|---|
M_pause | rand-bridge-pause-1 / -2 | l’unique clé de pause de la genèse (Dilithium2), qui peut mettre en pause et jamais lever la pause |
M_unpause | rand-bridge-pq-unpause-1 / -2 | un quorum de gardiens PQ |
M_list | rand-bridge-pq-list-1 / -2 | un quorum de gardiens PQ (ListBacking) |
M_register | rand-bridge-pq-register-1 / -2 | un quorum de gardiens PQ (RegisterBridgedToken) |
M_rotate_pq | rand-bridge-pq-rotate-pq-1 / -2 | un quorum de l’ensemble PQ actuel (RotatePqGuardians, chaînes rules_v2) ; sur la chain 20, aussi chaque nouvelle clé, comme preuve de possession |
M_rotate_pause | rand-bridge-pq-rotate-pause-1 / -2 | un quorum de l’ensemble PQ actuel (RotatePauseKey, chaînes rules_v2) ; sur la chain 20, aussi la nouvelle clé |
M_cancel | rand-bridge-cancel-rotation-1 / -2, avec un octet kind final | la clé de pause actuelle (CancelRotation, chaînes avec bridge.rotation : chain 20) |
Le STARK en production
Le zkVM en est à l’ensemble de contraintes 8 : neuf tables obligatoires (program, cpu, memory, alu, range, nibble, poseidon2, input, public), plus une table keccak et une table sha256 qu’une preuve ne porte que si son invité a appelé l’appel système correspondant, reliées par dix-sept bus et prouvées comme un seul STARK par lot. Depuis l’ensemble de contraintes 7, chaque table déclarée compte au moins 2⁷ lignes et le terminal LogUp de chaque table est aveuglé via le dix-septième bus, BLIND. L’interface publique d’une preuve compte 35 éléments de corps (pv::NUM) : le pc d’entrée, le palier, les huit mots de sortie, le condensat de programme hc (8 mots), l’engagement salé des entrées privées H_IN (8), le condensat non salé du segment public H_PUB (8) et, depuis l’ensemble de contraintes 8, la limite de gas déclarée GAS_LIMIT.
| paramètre | production | note |
|---|---|---|
| requêtes FRI | 80 | le réglage à 27 requêtes des ensembles de contraintes 3 et 4 a été annulé après l’audit du 2026-09-12 : il laissait ~42 bits prouvés |
| blowup | 8 (log_blowup = 3) | le degré maximal de contrainte de chaque table est fixé sous le plafond de 8 |
| arité de repliement | 8 | |
| bits de preuve de travail | 20 | |
| solidité | 3·80 + 20 = 260 bits conjecturés (ethSTARK) ; environ 86 bits prouvés sous les écarts de proximité | |
| connaissance nulle | statistique : le LDE et le polynôme de lot FRI sont randomisés, de sorte que deux preuves d’une même exécution diffèrent | depuis l’ensemble de contraintes 7, chaque table déclarée compte au moins 2⁷ lignes, soit plus que les 82 points qu’ouvre une preuve, et les terminaux LogUp sont aveuglés |
| paliers | 10, 12, 14, 16, 18, 20 | une preuve révèle le palier, jamais le nombre de cycles ; depuis fullnode v0.5.6, une preuve d’appel au-delà du palier 14 est refusée (CallTierTooHigh), une preuve de bundle est fixée au palier 14 et une preuve d’auth au palier 10 |
| plafond de preuve | le max_proof_bytes de la genèse : 4 MiB (4 194 304) sur les chains 17 à 20 ; 8 MiB sur les chains 13 à 16 ; 2 MiB (MAX_PROOF_BYTES) sur une genèse qui n’en a pas, comme la chain 12 | 2 MiB dépasse toute preuve sans table de hachage que les invités déployés peuvent produire, et reste inférieur à une preuve portant keccak ; 4 MiB admet les deux |
| gas | 1 par ligne cpu ; 3 par ligne d’absorption Poseidon2 ; 64 par ligne SHA256 ; 192 par ligne KECCAK | cumulé dans la colonne GAS de la table cpu et prouvé au plus égal à GAS_LIMIT ; le vérificateur refuse une limite supérieure à gas_max(t, k, s) = (2ᵗ − 1) + 2ᵗ⁻² + 191·(2ᵏ/32) + 63·(2ˢ/64), soit 1 279 pour un en-tête de palier 10 sans hachage et 20 479 pour un en-tête de palier 14 |
Tailles mesurées avec le jeu de contraintes 6 (Apple Silicon, build release) : une preuve de production sans keccak pesait 1 298 729 octets au palier 10 et 1 359 978 au palier 12 ; une preuve de palier 10 avec keccak pesait 3 198 430 octets, au-dessus des 2 MiB par défaut et sous les 8 MiB des chaînes 13 à 15. Une preuve de palier 14 du guest de bundle 2-entrées-2-sorties, désormais retiré, a mesuré 1 321 773 octets sur la chaîne 8, et de 1 418 406 à 1 420 423 octets sur la chaîne 13. Le guest de bundle à actif caché 4-entrées-4-sorties de la chaîne 14 reste au palier 14 sans aucune des deux tables de hachage ; ses preuves ont mesuré 1 422 116 et 1 423 170 octets sur la chaîne 14 (2026-09-20), et la chaîne 15 a épinglé le même guest (hc_bundle inchangé) ; une preuve de bundle y déclarait public_log_height 4, la hauteur des huit mots de liaison, et le nœud refusait toute autre valeur avant de construire une clé de vérification. La preuve de l’appel ERC-20 approve avec keccak, produite sur la chaîne 13 le 2026-09-19 (palier 16), pèse 3 412 405 octets ; depuis fullnode v0.5.6, toutes les chaînes refusent cet appel, au palier 16.
Les colonnes d’aveuglement et les planchers de tables du jeu de contraintes 7 ajoutent environ 5 % à une preuve sans hachage : mesuré par le fullnode le 2026-09-28, fib pèse 1 367 688 octets au palier 10 et 1 424 299 au palier 12, une preuve de palier 10 avec keccak 3 283 898, et une preuve de bundle à actif caché de palier 14 1 498 821 (guest v1) et 1 497 156 (guest v2). Depuis, une preuve de bundle déclare public_log_height 7. Le jeu de contraintes 8 ajoute moins de 1 %. Mesuré sur la chaîne 18 le 2026-09-30 (Apple Silicon) : des preuves d’authentification de 1 364 940 à 1 375 371 octets (palier 10), des preuves de bundle de 1 494 151 à 1 504 260 octets (palier 14, guest v3), et des preuves d’appel de 1 498 589 octets au palier 14 sans table de hachage, 1 911 152 au palier 14 avec la table SHA-256 et 3 346 865 au palier 12 avec la table Keccak. Toutes tiennent dans le plafond de 4 MiB des chaînes 18 à 20.
La vérification prend environ 16 ms avec une clé de vérification déjà chaude et environ 230 ms la première fois qu’une clé (tier, heights) est construite. Le profil FRI test (16 requêtes) existe pour la suite de tests et n’est pas sûr ; le genesis de la chaîne 20 épingle production. Fullnode v0.6.8 ne modifie aucune contrainte : la chaîne 20 épingle les mêmes hc_bundle et hc_auth que les chaînes 17 à 19.
Constructions de hachage que vous pouvez reproduire
BLAKE3 avec un domaine : blake3(domain || data), la chaîne de domaine sans séparateur.
Le domaine de liaison. Le genesis de la chaîne 20 définit binding_domain: 1 (fullnode v0.6.8, audit v6 BIND-1). Sur une telle chaîne, chaque liaison de preuve et chaque message d’action signé qui ne liait que l’identifiant de chaîne lie désormais aussi le hash du genesis : le numéro de version du domaine augmente de un et le hash du genesis de 32 octets passe en tête de la préimage, avant l’identifiant de chaîne. Une preuve ou une signature produite pour une chaîne ne se vérifie alors sur aucune autre, même une qui réutilise l’identifiant de chaîne et les clés, comme le fait une refonte. Les mots de liaison sont une entrée publique des preuves : aucun guest ni aucune clé de vérification n’a changé. Le tableau donne les deux formes ; les chaînes 14 à 19 utilisent la première, octet pour octet. Déjà liés au genesis auparavant, et inchangés : les votes et les propositions (depuis consensus_domain: 1), la Registration v2 et un vote AdmitValidator. Non déplacée : la co-signature de mint du pont (ci-dessus). Un wallet a besoin de v0.6.8 pour envoyer sur la chaîne 20, et détermine la forme d’après l’identifiant de chaîne, non d’après ce qu’un nœud affirme ; rand_getLimits.binding_domain la rapporte.
| valeur | construction |
|---|---|
| adresse transparente | blake3("rand-address" || dilithium2_public_key), base58 |
| identifiant de transaction | blake3("rand-txid-3" || bincode(view)), où view est la transaction dont les octets de preuve du bundle sont remplacés par blake3(proof) et sa preuve d’authentification par blake3(auth_proof) ; auth_commit entre tel quel. Le domaine était rand-txid-2, sans champs d’authentification, jusqu’à la chaîne 16 |
| liaison de transaction | blake3("rand-tx-bind-1" || bincode(chain_id, bundle', action')) sur les chaînes 14 à 19 ; blake3("rand-tx-bind-2" || bincode(genesis_hash, chain_id, bundle', action')) sur la chaîne 20. Huit mots u32 petit-boutiens, où ' remplace bundle.proof, bundle.auth_proof et le proof d’un Aggregate par le vecteur vide ; bincode avec des entiers petit-boutiens de largeur fixe. Chaque preuve de bundle et chaque preuve d’authentification est produite sur ces mots et vérifiée par rapport à eux |
| liaison d’appel | blake3("rand-call-bind-1" || …), ou rand-call-bind-2 avec le hash du genesis en tête sur la chaîne 20 : la construction de la liaison de transaction avec le proof propre au Call (ou à l’Invoke) également vidé. Sur un genesis hardening_v6, tel que la chaîne 20, le segment public d’une preuve d’appel est constitué des mots publics du programme fixés au déploiement, suivis de ces huit mots, et celui d’un Invoke ajoute sa transition comme mots de contexte après eux |
| identifiant de programme | blake3("rand-program" || base_pc as 4 LE bytes || words as 4 LE bytes each) |
| identité p2p | clé ed25519 dérivée de blake3("rand-p2p-identity" || seed) |
| identifiant d’actif du pont (par adossement) | blake3("rand-bridge-asset" || token_chain as 2 BE bytes || token_address (32 bytes)) — rand_bridgeAssetId le calcule et rand_getAssets l’affiche pour chaque ligne d’adossement ; il identifie une pièce source sur le réseau, et non le token |
| identifiant d’actif de token RPL, natif | blake3("rand-rpl-asset" || bincode(name, symbol, decimals, authority, initial: Option<InitialMint>, salt)), salt étant 32 octets choisis par le créateur ; affiché en hexadécimal et sous la forme rpl1… |
| identifiant d’actif de token RPL, ponté | blake3("rand-rpl-asset" || bincode(name, symbol, BRIDGE_DECIMALS, salt)) — non calculé sur une paire (chain, token), puisqu’un même token ponté couvre plusieurs adossements |
| aveuglement de dépôt du pont | r = blake3("rand-deposit-r-1" || mu), le seul r que l’admission accepte pour un BridgeAttest (WrongDepositBlinding sinon) |
| aveuglements des notes de frais du pont (chaîne 20) | la note de frais d’un dépôt : r = blake3("rand-bridge-fee-r-1" || mu) ; celle d’une destruction : r = blake3("rand-bridge-burn-fee-r-1" || txid) ; les deux lus comme huit mots petit-boutiens. Les notes n’ont pas d’enveloppe : tous les champs sont publics, le propriétaire étant le bridge.fees.recipient du genesis |
| destinataire du pont | blake3("rand-shielded-recipient" || pk_bytes || kem_ek) sur l’adresse protégée complète |
message Mint du faucet | blake3("rand-mint-2" || bincode(chain_id, cm, pk, time, r, envelope, amount)) ; sur la chaîne 20 blake3("rand-mint-3" || bincode(genesis_hash, chain_id, cm, pk, time, r, envelope, amount)) |
messages TokenMint, SetAuthority | blake3("rand-rpl-mint-1" or "rand-rpl-authority-1", chain_id || asset_id || nonce || body) ; le corps d’un mint inclut blake3(bincode(envelope)). Sur la chaîne 20 rand-rpl-mint-2 et rand-rpl-authority-2, avec le hash du genesis en tête |
message Registration | blake3("rand-register-2" || bincode(genesis_hash, chain_id, validator, payout)) sur un genesis avec staking.registration_v2 ou binding_domain: 1, tel que la chaîne 20 (une inscription v1 y est refusée) ; blake3("rand-register" || bincode(chain_id, payout)) ailleurs |
vote AdmitValidator (chaîne 20) | blake3("rand-admit-validator-1" || genesis_hash || candidate_address), signé par chaque validateur votant |
message Unbond | blake3("rand-unbond" || bincode(chain_id, validator, amount, nonce)) ; sur la chaîne 20 blake3("rand-unbond-2" || bincode(genesis_hash, chain_id, validator, amount, nonce)) |
message Withdraw | blake3("rand-withdraw" || bincode(chain_id, validator, amount, nonce, time, r, envelope)) ; sur la chaîne 20 rand-withdraw-2, avec le hash du genesis en tête |
| nœud de Merkle (arbres d’état) | blake3("rand-merkle-node" || left || right) |
| feuille du registre de tokens | blake3("rand-token-leaf-1" || bincode(TokenInfo)), dans l’ordre des index, sous tokens_root |
| racine d’état | sur la chaîne 20, blake3("rand-state-admitted-1" || inner || admitted_root) autour de inner = blake3("rand-state-8" || tree_root || nullifier_root || validators_root || programs_root || bridge_root || tokens_root || faucet_epoch || faucet_minted_in_epoch || bond_queue_root || gas_price || byte_price || program_state_root), où program_state_root = blake3("rand-program-state-1" || cells_root || vaults_root) (RPL-2), les deux compteurs du faucet et les deux prix en vigueur font chacun 8 octets gros-boutiens, et l’enveloppe externe engage l’ensemble des validateurs admis (staking.admission_by_vote). Celle de la chaîne 19 était blake3("rand-state-7" || …) sur les mêmes champs jusqu’à byte_price (une section staking du genesis ajoute les trois après tokens_root sous rand-state-5, comme sur les chaînes 15 à 17 ; une section gas.dynamic du genesis ajoute les deux prix et fait passer le domaine à rand-state-7) ; rand-state-4 sur les six premiers sur la chaîne 14 ; rand-state-2 sur les quatre premiers sur une chaîne sans section bridge, tokens ni aggregation (Consensus) |
Poseidon2 avec une balise de domaine : H(domain, msg) = sponge_hash([domain, msg...]), la balise étant le premier mot absorbé, chaque mot un élément de Goldilocks, le condensat de 4 éléments découpé en huit mots u32 (moitié basse puis moitié haute de chaque élément). Balises de domaine :
| balise | valeur | construction |
|---|---|---|
NK | 1 | clé de visualisation nk = H(1, sk) |
PK | 2 | valeur publique de la note pk = H(2, nk) |
NF | 3 | nullifier H(3, nk || cm) |
CM | 4 | engagement de la note H(4, pk(8) || from(8) || amount_lo || amount_hi || asset || time || r(8)) — 28 mots |
OVK, KEM_SEED | 5, 6 | la clé de visualisation sortante et la graine ML-KEM, par un hachage large en mode compteur [domain, nk, counter] |
NODE | 7 | nœud de l’arbre H(7, left || right) ; la feuille vide est constituée uniquement de zéros |
HC | 8 | le condensat du programme ; la balise, base_pc et len occupent les voies de capacité de la première permutation, puis les mots sont absorbés par blocs de quatre |
OUT | 9 | le condensat de sortie du guest de transfert |
IN | 10 | H_IN : en-tête de capacité [10, n_in, 0], puis un sel de 4 mots, puis les entrées |
BUNDLE | 11 | le condensat du bundle 2-entrées-2-sorties retiré, sur 47 mots publics ; plus aucune chaîne n’impose ce guest |
| hidden bundle | 64 | le condensat du bundle à actif caché, sur 81 mots sur les chaînes 14 à 16 : ancre, quatre nullifiers, quatre engagements, fee, burn_a, burn_r (deux mots chacun), burn_asset, time, et le mot de souillure en dernier. Sur les chaînes 17 à 20 (bundle guest v3), il compte 89 mots : les huit mots de l’engagement d’autorisation c se placent immédiatement avant le mot de souillure. L’actif privé A n’y figure pas. La balise est locale au nœud et se situe à l’écart des balises reprises 1 à 15 |
AUTH | 65 | l’engagement d’autorisation c = H(65, nk || salt), 16 mots, avec un sel de 256 bits renouvelé pour chaque bundle ; publié par la preuve du bundle dans son condensat et par la preuve d’autorisation comme ses huit mots de sortie, et porté par le bundle sous le nom auth_commit (chaînes 17 à 20). Local au nœud, comme 64 |
PUB | 15 | H_PUB : en-tête [15, n_pub, 0], sans sel ; pour un programme, sur la chaîne 20, les mots sont fixés au déploiement (32 768 au plus), le segment de chaque appel est constitué de ces mots suivis des huit mots de la liaison d’appel, et l’appel est vérifié par rapport au condensat de ce segment ; pour une preuve de bundle et une preuve d’autorisation, le segment est constitué des huit mots de liaison de la transaction ; un genesis sans max_program_public_words n’admet que le segment vide |
hc, H_IN et H_PUB ne sont pas de simples éponges préfixées par le message : l’en-tête est placé dans la capacité afin que les lignes de condensat de la table cpu absorbent exactement quatre mots par permutation. Reproduisez-les avec la crate reprise (randprotocol_zkvm::hash::{input_digest, public_digest}, isa::Program::digest) plutôt qu’à la main.
L’éponge simple n’applique pas de remplissage : dans le premier bloc, [a] et [a, 0] ont donc le même condensat. Toutes les constructions ci-dessus hachent un message de longueur fixe sous leur propre balise. Pour les données de longueur variable, le jeu de contraintes 7 a ajouté une éponge liée à la longueur (hash::sponge_hash_len, l’appel système POSEIDON2_LEN) : elle part de l’état [0, 0, 0, 0, n, 0, 0, 0], n étant le nombre de mots, et effectue au moins une permutation. C’est un autre hachage des mêmes mots, et aucune note, aucun nullifier, aucune racine ni aucun condensat de la chaîne ne l’utilise.
Deux propriétés à retenir : hc est contraignant (binding) mais non occultant (hiding) (sans sel, un programme deviné peut être confirmé et deux déploiements d’un même programme sont liables), et H_IN est à la fois occultant et contraignant (un sel de 128 bits renouvelé pour chaque preuve) ; publier H_IN ne révèle donc rien des entrées tant que le détenteur du sel ne les ouvre pas.
Dérivations de clés
| clé | à partir de |
|---|---|
| paire de clés Dilithium2 (nœud) | déterministe à partir de la graine de 32 octets |
| libp2p ed25519 (nœud) | blake3("rand-p2p-identity" || seed) |
clé de visualisation, pk, ovk, paire de clés ML-KEM (portefeuille) | dérivations Poseidon2 de la clé de dépense, comme indiqué dans le tableau ci-dessus ; la paire ML-KEM est MlKem768::from_seed(kem_seed) |
Les articles de la page des articles présentent les arguments de sécurité : les choix post-quantiques, le décompte de solidité de FRI et la raison pour laquelle 80 requêtes sont conservées, ainsi que la borne sur la longueur de la trace.