Rand Protocol
Documentación
Guías

Criptografía

Las primitivas y dónde se usa cada una, los parámetros de STARK y FRI en producción, y las construcciones de hash que un desarrollador puede necesitar reproducir.

Use esta página para elegir la biblioteca adecuada cuando interactúe con la cadena, para comprobar un parámetro frente a lo que el nodo hace cumplir y para recalcular usted mismo un id o un compromiso. Cada valor aquí es el que el código ejecuta en la chain 20 (fullnode v0.6.8).

Primitivas y dónde se usan

primitivaparámetrosusos
Dilithium2clave pública de 1,312 bytes, firma de 2,420 bytes; pares de claves derivados de una semilla de 32 bytesvotos de validadores y propuestas de bloque; emisiones del faucet; Unbond, Withdraw y el Registration de un validador; los votos de un AdmitValidator (chain 20); las acciones del aggregator; la autoridad de emisión Key de un token RPL (TokenMint, SetAuthority); las cofirmas poscuánticas de los guardianes del puente, su clave de pausa y, en la chain 20, las pruebas de posesión de las nuevas claves en una rotación (más abajo)
ML-KEM-768clave de encapsulación de 1,184 bytes, texto cifrado de 1,088 bytessellar la clave por transacción de un sobre de nota para la dirección del receptor; sellar un sobre de entrada de llamada para un auditor; sellar un trabajo de prueba para un prover emparejado
ChaCha20-Poly1305clave de 32 bytes, nonce aleatorio de 12 bytes antepuesto, etiqueta de 16 bytescada parte de un sobre: cuerpos de notas, claves de transacción envueltas, transcripciones de entrada de llamada; los trabajos y respuestas de un prover emparejado
BLAKE3salida de 32 bytes, siempre con una cadena de dominio como prefijodirecciones, ids de transacción, el binding de la transacción y el binding de la llamada, ids de programa, ids de activo de los tokens, la raíz de estado y sus árboles de Merkle, la identidad p2p, mensajes de firma, ids de activo del puente, el cegado de un depósito del puente y los cegados de las notas de comisión del puente
Poseidon2 sobre Goldilocksancho 8, tasa 4, capacidad 4, esponja de sobrescritura sin relleno; los elementos del mensaje son palabras de 32 bits; las 86 constantes de ronda son una tabla literal en el código fuente del nodo (poseidon2_constants.rs) desde el corte de la chain 15, los mismos valores que producía antes el sorteo con semillatodo lo que ocurre dentro de una prueba: claves, compromisos de notas, nullifiers, el árbol de compromisos, el digest del programa hc, los compromisos de entrada H_IN y H_PUB, el digest del bundle, el compromiso de autorización
secp256k1 ECDSA + keccak256firmas low-s, direcciones de guardián de 20 bytes al estilo Ethereum, mu = keccak256(keccak256(body))atestaciones de los guardianes del puente, de modo que la misma clave funciona en los contratos EVM, el programa de Solana y Rand; en Rand toda atestación necesita además el quórum de Dilithium2 que se describe más abajo
bech32m (BIP-350)parte legible rpl, carga útil de 32 bytes, 52 caracteres de datos + 6 caracteres de suma de verificación = 62la forma textual rpl1… del id de activo de un token RPL
Plonky3 batch STARKGoldilocks p = 2⁶⁴ − 2³² + 1, FRI con ocultación, blowup 8, aridad de plegado 8, 80 consultas, 20 bits de prueba de trabajocada prueba de bundle, prueba de autorización y prueba de llamada; una prueba de bundle y su prueba de autorización llevan las ocho palabras de binding de su transacción como segmento de entrada pública

Los parámetros objetivo del whitepaper difieren en algunos puntos de lo que ejecuta la implementación (por ejemplo, el hash de transcripción de 384 bits del documento frente a la transcripción Poseidon2 de la zkVM). Estas páginas describen el código.

Cofirmas poscuánticas en el puente

Las atestaciones de los guardianes del puente son secp256k1 ECDSA, que un adversario cuántico podría falsificar. Desde la chain 14, todo BridgeAttest —tanto un depósito como una rotación del conjunto de guardianes— debe llevar también un quórum de firmas Dilithium2 de los mismos guardianes sobre el mismo digest:

M = "rand-bridge-pq-cosign-1" || rand_chain_id (u64 BE) || mu        // 63 bytes, deterministic signing

donde mu = keccak256(keccak256(body)) es lo que firma el quórum ECDSA. El id de la cadena Rand en M impide que una cofirma de testnet se verifique en otra cadena Rand, incluso si se reutilizaran las claves de los guardianes. M enlaza únicamente el id de la cadena, también en la chain 20: es el único mensaje firmado que binding_domain no desplazó detrás del hash de génesis, porque los daemons de los guardianes que lo firman viven en otro repositorio. Una copia de una cadena con el mismo id de cadena y el mismo conjunto de guardianes aceptaría las cofirmas de sus depósitos; el índice del conjunto de guardianes no está en M, de modo que una cofirma sobrevive a una rotación del conjunto ECDSA. El campo pq_signatures de la acción es una lista de PqSignature { index: u8, signature }, que se comprueba primero lo barato y después lo costoso: quorum(n) ≤ len ≤ n (PqNoQuorum), índices estrictamente crecientes (PqIndexOrder), todos los índices por debajo de n (PqIndexOutOfRange), cada firma de exactamente 2,420 bytes (PqBadSignatureLength) y, por último, cada firma verificada con pq_guardians[index] (PqBadSignature). Los firmantes PQ no tienen que ser los firmantes ECDSA; cada quórum se cuenta por separado. El campo está dentro del binding de la transacción, por lo que no se puede quitar ni sustituir en una copia.

El conjunto PQ es el bridge.pq_guardians del génesis: ocho claves de 1,312 bytes en la chain 20, igual que en las chains 15 a 19, alineadas por índice con el conjunto ECDSA del génesis, conjunto de guardianes 1 (la chain 14 tenía seis, alineadas con el conjunto 0). Una rotación del conjunto de guardianes ECDSA nunca lo mueve. En la chain 14 quedó fijo durante toda la vida de la cadena; desde la chain 15 el génesis incluye el grupo rules_v2 del puente, bajo el cual un quórum PQ puede sustituir todo el conjunto PQ (RotatePqGuardians) o la clave de pausa (RotatePauseKey), cada uno bajo el rotation_nonce del puente. El génesis de la chain 20 añade bridge.rotation: una rotación debe ser la acción V2, con la firma Dilithium2 propia de cada nueva clave sobre el mismo mensaje (prueba de posesión), y surte efecto un día después de registrarse, salvo que la clave de pausa vigente la cancele (Puente). rand_getBridgeState sirve las claves y un bridge_attest decodificado lista pq_signers, los índices que firmaron. El mismo quórum PQ autoriza los mensajes de gobernanza del puente, cada uno con un formato fijo big-endian que incluye el id de la cadena y un nonce. En la chain 20 (génesis binding_domain: 1) el dígito de versión de cada dominio es 2 y el hash de génesis de 32 bytes va entre el dominio y el id de la cadena; las chains 14 a 19 usan las formas -1:

mensajedominio (chains 14–19 / chain 20)firmado por
M_pauserand-bridge-pause-1 / -2la única clave de pausa del génesis (Dilithium2), que puede pausar y nunca reanudar
M_unpauserand-bridge-pq-unpause-1 / -2un quórum de guardianes PQ
M_listrand-bridge-pq-list-1 / -2un quórum de guardianes PQ (ListBacking)
M_registerrand-bridge-pq-register-1 / -2un quórum de guardianes PQ (RegisterBridgedToken)
M_rotate_pqrand-bridge-pq-rotate-pq-1 / -2un quórum del conjunto PQ vigente (RotatePqGuardians, cadenas rules_v2); en la chain 20 también cada nueva clave, como su prueba de posesión
M_rotate_pauserand-bridge-pq-rotate-pause-1 / -2un quórum del conjunto PQ vigente (RotatePauseKey, cadenas rules_v2); en la chain 20 también la nueva clave
M_cancelrand-bridge-cancel-rotation-1 / -2, con un byte kind finalla clave de pausa vigente (CancelRotation, cadenas con bridge.rotation: chain 20)

El STARK en producción

La zkVM está en el conjunto de restricciones 8: nueve tablas obligatorias (program, cpu, memory, alu, range, nibble, poseidon2, input, public) más una tabla keccak y una tabla sha256 que una prueba lleva solo cuando su guest invocó la syscall correspondiente, conectadas por diecisiete buses y probadas como un único batch STARK. Desde el conjunto de restricciones 7, toda tabla declarada tiene al menos 2⁷ filas y el terminal LogUp de cada tabla se cega a través del decimoséptimo bus, BLIND. La interfaz pública de una prueba son 35 elementos de campo (pv::NUM): el pc de entrada, el tier, las ocho palabras de salida, el digest del programa hc (8 palabras), el compromiso de entrada privada con sal H_IN (8), el digest del segmento público sin sal H_PUB (8) y, desde el conjunto de restricciones 8, el límite de gas declarado GAS_LIMIT.

parámetroproducciónobservación
consultas FRI80el reajuste a 27 consultas de los conjuntos de restricciones 3 y 4 se revirtió tras la auditoría del 2026-09-12: dejaba ~42 bits demostrados
blowup8 (log_blowup = 3)el grado máximo de restricción de cada tabla está fijado por debajo del tope de 8
aridad de plegado8
bits de prueba de trabajo20
solidez3·80 + 20 = 260 bits conjeturados (ethSTARK); unos 86 bits demostrados bajo brechas de proximidad
conocimiento ceroestadístico: la LDE y el polinomio batch de FRI se aleatorizan, de modo que dos pruebas de una misma ejecución difierendesde el conjunto de restricciones 7 toda tabla declarada tiene al menos 2⁷ filas, más que los 82 puntos que abre una prueba, y los terminales LogUp están cegados
tiers10, 12, 14, 16, 18, 20una prueba revela el tier, nunca el número de ciclos; desde fullnode v0.5.6 se rechaza una prueba de llamada por encima del tier 14 (CallTierTooHigh), una prueba de bundle queda fijada al tier 14 y una prueba de autorización al tier 10
tope de pruebael max_proof_bytes del génesis: 4 MiB (4,194,304) en las chains 17 a 20; 8 MiB en las chains 13 a 16; 2 MiB (MAX_PROOF_BYTES) en un génesis que no lo tenga, como la chain 122 MiB está por encima de toda prueba sin tablas hash que puedan producir los guests desplegados y por debajo de una que lleve keccak; 4 MiB admite ambas
gas1 por fila de cpu; 3 por fila de absorción de Poseidon2; 64 por fila SHA256; 192 por fila KECCAKacumulado en la columna GAS de la tabla cpu y demostrado como máximo GAS_LIMIT; el verifier rechaza un límite superior a gas_max(t, k, s) = (2ᵗ − 1) + 2ᵗ⁻² + 191·(2ᵏ/32) + 63·(2ˢ/64), que es 1,279 para una cabecera de tier 10 sin hashes y 20,479 para una de tier 14

Tamaños medidos en el conjunto de restricciones 6 (Apple Silicon, compilación release): una prueba de producción sin keccak pesó 1 298 729 bytes en el nivel 10 y 1 359 978 en el nivel 12; una prueba de nivel 10 con keccak pesó 3 198 430, por encima de los 2 MiB predeterminados y por debajo de los 8 MiB de las cadenas 13 a 15. Una prueba de nivel 14 del guest de bundle retirado de 2 entradas y 2 salidas pesó 1 321 773 bytes en la cadena 8, y entre 1 418 406 y 1 420 423 bytes en la cadena 13. El guest de bundle de activos ocultos de 4 entradas y 4 salidas de la cadena 14 permanece en el nivel 14 sin ninguna de las dos tablas de hash, y sus pruebas pesaron 1 422 116 y 1 423 170 bytes en la cadena 14 (2026-09-20); la cadena 15 fijó el mismo guest (hc_bundle sin cambios); allí, una prueba de bundle declaraba public_log_height 4, la altura de las ocho palabras de vinculación, y el nodo rechazaba cualquier otro valor antes de construir una clave de verificación. La prueba de la llamada approve de ERC-20 con keccak, realizada en la cadena 13 el 2026-09-19 (nivel 16), pesa 3 412 405 bytes; todas las cadenas desde fullnode v0.5.6 rechazan esa llamada, en el nivel 16.

Las columnas de cegado y los mínimos de tabla del conjunto de restricciones 7 añaden cerca de un 5 % a una prueba sin hash: según la medición del fullnode del 2026-09-28, fib pesa 1 367 688 bytes en el nivel 10 y 1 424 299 en el nivel 12, una prueba de nivel 10 con keccak 3 283 898, y una prueba de bundle de activos ocultos de nivel 14 1 498 821 (guest v1) y 1 497 156 (guest v2). Desde entonces, una prueba de bundle declara public_log_height 7. El conjunto de restricciones 8 añade menos del 1 %. Medido en la cadena 18 el 2026-09-30 (Apple Silicon): pruebas de autorización de 1 364 940 a 1 375 371 bytes (nivel 10), pruebas de bundle de 1 494 151 a 1 504 260 bytes (nivel 14, guest v3) y pruebas de llamada de 1 498 589 bytes en el nivel 14 sin tabla de hash, 1 911 152 en el nivel 14 con la tabla SHA-256 y 3 346 865 en el nivel 12 con la tabla Keccak. Todas caben en el límite de 4 MiB de las cadenas 18 a 20.

La verificación toma unos 16 ms con una clave de verificación ya en caché y unos 230 ms la primera vez que se construye una clave (tier, heights). El perfil FRI test (16 consultas) existe para la suite de pruebas y no es seguro; el génesis de la cadena 20 fija production. Fullnode v0.6.8 no cambia ninguna restricción: la cadena 20 fija los mismos hc_bundle y hc_auth que las cadenas 17 a 19.

Construcciones de hash que puede reproducir

BLAKE3 con un dominio: blake3(domain || data), con la cadena de dominio sin separador.

El dominio de vinculación. El génesis de la cadena 20 establece binding_domain: 1 (fullnode v0.6.8, auditoría v6 BIND-1). En una cadena así, toda vinculación de pruebas y todo mensaje de acción firmado que antes vinculaba solo el id de la cadena vincula ahora también el hash del génesis: el número de versión del dominio sube en uno y el hash del génesis de 32 bytes va primero en la preimagen, antes del id de la cadena. Una prueba o una firma hecha para una cadena no se verifica entonces en ninguna otra, ni siquiera en una que reutilice el id de la cadena y las claves, como ocurre con un nuevo corte. Las palabras de vinculación son una entrada pública de las pruebas, de modo que no cambió ningún guest ni clave de verificación. La tabla da ambas formas; las cadenas 14 a 19 usan la primera, byte a byte. Ya vinculados al génesis antes, y sin cambios: los votos y las propuestas (desde consensus_domain: 1), el Registration v2 y un voto AdmitValidator. No se modificó: la cofirma de acuñación del puente (arriba). Una billetera necesita v0.6.8 para enviar en la cadena 20, y decide la forma por el id de la cadena, no por lo que afirme un nodo; rand_getLimits.binding_domain la informa.

valorconstrucción
dirección transparenteblake3("rand-address" || dilithium2_public_key), base58
id de transacciónblake3("rand-txid-3" || bincode(view)), donde view es la transacción con los bytes de la prueba del bundle reemplazados por blake3(proof) y su prueba de autorización por blake3(auth_proof); auth_commit entra tal cual. El dominio era rand-txid-2, sin campos de autorización, hasta la cadena 16
vinculación de la transacciónblake3("rand-tx-bind-1" || bincode(chain_id, bundle', action')) en las cadenas 14 a 19; blake3("rand-tx-bind-2" || bincode(genesis_hash, chain_id, bundle', action')) en la cadena 20. Ocho palabras u32 little-endian, donde ' reemplaza bundle.proof, bundle.auth_proof y el proof de un Aggregate por el vector vacío; bincode con enteros little-endian de ancho fijo. Toda prueba de bundle y de autorización se genera sobre estas palabras y se verifica contra ellas
vinculación de la llamadablake3("rand-call-bind-1" || …), o rand-call-bind-2 con el hash del génesis primero en la cadena 20: la construcción de la vinculación de la transacción con el proof propio del Call (o del Invoke) también vaciado. En un génesis hardening_v6, como el de la cadena 20, el segmento público de la prueba de una llamada son las palabras públicas del programa fijadas en el despliegue seguidas de estas ocho palabras, y el de un Invoke añade su transición como palabras de contexto a continuación
id de programablake3("rand-program" || base_pc as 4 LE bytes || words as 4 LE bytes each)
identidad p2pclave ed25519 derivada de blake3("rand-p2p-identity" || seed)
id de activo del puente (por respaldo)blake3("rand-bridge-asset" || token_chain as 2 BE bytes || token_address (32 bytes)) — rand_bridgeAssetId lo calcula y rand_getAssets lo imprime por fila de respaldo; identifica una moneda de origen en la red, no el token
id de activo de token RPL, nativoblake3("rand-rpl-asset" || bincode(name, symbol, decimals, authority, initial: Option<InitialMint>, salt)), con salt de 32 bytes elegidos por el creador; se muestra en hexadecimal y como rpl1…
id de activo de token RPL, puenteadoblake3("rand-rpl-asset" || bincode(name, symbol, BRIDGE_DECIMALS, salt)) — no sobre un par (chain, token), ya que un token puenteado abarca varios respaldos
cegado del depósito del puenter = blake3("rand-deposit-r-1" || mu), el único r que la admisión acepta para un BridgeAttest (WrongDepositBlinding en caso contrario)
cegados de las notas de comisión del puente (cadena 20)la nota de comisión de un depósito: r = blake3("rand-bridge-fee-r-1" || mu); la de una quema: r = blake3("rand-bridge-burn-fee-r-1" || txid); ambos se leen como ocho palabras little-endian. Las notas no tienen sobre: todos los campos son públicos, y el propietario es el bridge.fees.recipient del génesis
destinatario del puenteblake3("rand-shielded-recipient" || pk_bytes || kem_ek) sobre la dirección shielded completa
mensaje Mint del faucetblake3("rand-mint-2" || bincode(chain_id, cm, pk, time, r, envelope, amount)); en la cadena 20 blake3("rand-mint-3" || bincode(genesis_hash, chain_id, cm, pk, time, r, envelope, amount))
mensajes TokenMint, SetAuthorityblake3("rand-rpl-mint-1" or "rand-rpl-authority-1", chain_id || asset_id || nonce || body); el cuerpo de una acuñación incluye blake3(bincode(envelope)). En la cadena 20, rand-rpl-mint-2 y rand-rpl-authority-2, con el hash del génesis primero
mensaje Registrationblake3("rand-register-2" || bincode(genesis_hash, chain_id, validator, payout)) en un génesis con staking.registration_v2 o binding_domain: 1, como el de la cadena 20 (allí se rechaza un registro v1); blake3("rand-register" || bincode(chain_id, payout)) en los demás
voto AdmitValidator (cadena 20)blake3("rand-admit-validator-1" || genesis_hash || candidate_address), firmado por cada validador votante
mensaje Unbondblake3("rand-unbond" || bincode(chain_id, validator, amount, nonce)); en la cadena 20 blake3("rand-unbond-2" || bincode(genesis_hash, chain_id, validator, amount, nonce))
mensaje Withdrawblake3("rand-withdraw" || bincode(chain_id, validator, amount, nonce, time, r, envelope)); en la cadena 20 rand-withdraw-2, con el hash del génesis primero
nodo de Merkle (árboles de estado)blake3("rand-merkle-node" || left || right)
hoja del registro de tokensblake3("rand-token-leaf-1" || bincode(TokenInfo)), en orden de índice, bajo tokens_root
raíz de estadoen la cadena 20, blake3("rand-state-admitted-1" || inner || admitted_root) alrededor 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), donde program_state_root = blake3("rand-program-state-1" || cells_root || vaults_root) (RPL-2), los dos contadores del faucet y los dos precios vigentes son de 8 bytes big-endian cada uno, y el envoltorio compromete el conjunto admitido (staking.admission_by_vote). La de la cadena 19 era blake3("rand-state-7" || …) sobre los mismos campos hasta byte_price (una sección staking del génesis añade los tres después de tokens_root bajo rand-state-5, como en las cadenas 15 a 17; una sección gas.dynamic del génesis añade los dos precios y pasa el dominio a rand-state-7); rand-state-4 sobre los primeros seis en la cadena 14; rand-state-2 sobre los primeros cuatro en una cadena sin sección bridge, tokens ni aggregation (Consenso)

Poseidon2 con una etiqueta de dominio: H(domain, msg) = sponge_hash([domain, msg...]), con la etiqueta como la primera palabra absorbida, cada palabra un elemento de Goldilocks, y el resumen de 4 elementos dividido en ocho palabras u32 (mitad baja y luego mitad alta de cada elemento). Etiquetas de dominio:

etiquetavalorconstrucción
NK1clave de visualización nk = H(1, sk)
PK2valor público de la nota pk = H(2, nk)
NF3anulador H(3, nk || cm)
CM4compromiso de la nota H(4, pk(8) || from(8) || amount_lo || amount_hi || asset || time || r(8)) — 28 palabras
OVK, KEM_SEED5, 6la clave de visualización saliente y la semilla de ML-KEM, mediante un hash ancho en modo contador [domain, nk, counter]
NODE7nodo del árbol H(7, left || right); la hoja vacía es todo ceros
HC8el resumen del programa; la etiqueta, base_pc y len ocupan los carriles de capacidad de la primera permutación, y después las palabras se absorben de cuatro en cuatro por bloque
OUT9el resumen de salida del guest de transferencia
IN10H_IN: encabezado de capacidad [10, n_in, 0], luego una sal de 4 palabras y después las entradas
BUNDLE11el resumen del bundle retirado de 2 entradas y 2 salidas sobre 47 palabras públicas; ninguna cadena fija ya ese guest
bundle oculto64el resumen del bundle de activo oculto sobre 81 palabras en las cadenas 14 a 16: ancla, cuatro anuladores, cuatro compromisos, fee, burn_a, burn_r (dos palabras cada uno), burn_asset, time y, al final, la palabra de contaminación. En las cadenas 17 a 20 (guest de bundle v3) son 89 palabras: las ocho palabras del compromiso de autorización c van inmediatamente antes de la palabra de contaminación. El activo privado A no figura en él. La etiqueta es local al nodo y queda separada de las etiquetas incorporadas del 1 al 15
AUTH65el compromiso de autorización c = H(65, nk || salt), de 16 palabras, con una sal nueva de 256 bits por bundle; lo publica la prueba del bundle dentro de su resumen y la prueba de autorización como sus ocho palabras de salida, y el bundle lo lleva como auth_commit (cadenas 17 a 20). Local al nodo, como 64
PUB15H_PUB: encabezado [15, n_pub, 0], sin sal; para un programa, en la cadena 20 las palabras se fijan en el despliegue (como máximo 32.768), el segmento de cada llamada es esas palabras seguidas de las ocho palabras del vínculo de la llamada, y la llamada se comprueba contra el resumen de ese segmento; para una prueba de bundle y una prueba de autorización el segmento son las ocho palabras de vinculación de la transacción; un génesis sin max_program_public_words admite solo el segmento vacío

hc, H_IN y H_PUB no son esponjas simples con prefijo de mensaje: el encabezado va en la capacidad para que las filas de resumen de la tabla cpu absorban exactamente cuatro palabras por permutación. Reprodúzcalos con el crate incorporado (randprotocol_zkvm::hash::{input_digest, public_digest}, isa::Program::digest) en lugar de hacerlo a mano.

La esponja simple no aplica relleno, de modo que dentro del primer bloque [a] y [a, 0] producen el mismo hash. Cada construcción anterior hace el hash de un mensaje de longitud fija bajo su propia etiqueta. Para datos cuya longitud puede variar, el conjunto de restricciones 7 añadió una esponja con la longitud incorporada (hash::sponge_hash_len, la llamada al sistema POSEIDON2_LEN): parte del estado [0, 0, 0, 0, n, 0, 0, 0], con n el número de palabras, y permuta al menos una vez. Es un hash distinto de las mismas palabras, y ninguna nota, anulador, raíz ni resumen de la cadena lo usa.

Dos propiedades que conviene recordar: hc es vinculante pero no ocultante (sin sal, de modo que un programa supuesto puede confirmarse y dos despliegues de un mismo programa son enlazables), y H_IN es ocultante además de vinculante (una sal nueva de 128 bits por prueba), de modo que publicar H_IN no revela nada sobre las entradas hasta que quien posee la sal lo abre.

Derivaciones de claves

clavea partir de
par de claves Dilithium2 (nodo)determinista a partir de la semilla de 32 bytes
libp2p ed25519 (nodo)blake3("rand-p2p-identity" || seed)
clave de visualización, pk, ovk, par de claves ML-KEM (wallet)derivaciones Poseidon2 de la clave de gasto, como se indica en la tabla anterior; el par ML-KEM es MlKem768::from_seed(kem_seed)

Los artículos de la página de artículos contienen los argumentos de seguridad: las elecciones poscuánticas, el cómputo de solidez de FRI y por qué se mantienen 80 consultas, y la cota de longitud de la traza.

Verificado por última vez con el commit c0878c3f del fullnode (cadena 21) el 2026-10-12. Cuando el código y esta página no coinciden, el código tiene razón; avísenos.