Use esta página para escolher a biblioteca certa ao interoperar com a chain, para conferir um parâmetro contra o que o nó impõe e para recalcular você mesmo um id ou um compromisso. Todos os valores aqui são os que o código executa na chain 20 (fullnode v0.6.8).
Primitivas e onde são usadas
| primitiva | parâmetros | usada para |
|---|---|---|
| Dilithium2 | chave pública de 1.312 bytes, assinatura de 2.420 bytes; pares de chaves derivados de uma semente de 32 bytes | votos e propostas de bloco dos validadores; mints do faucet; Unbond, Withdraw e o Registration de um validador; os votos de um AdmitValidator (chain 20); as ações do agregador; a autoridade de mint Key de um token RPL (TokenMint, SetAuthority); as co-assinaturas pós-quânticas dos guardiões da bridge, sua chave de pausa e, na chain 20, as provas de posse das novas chaves em uma rotação (abaixo) |
| ML-KEM-768 | chave de encapsulamento de 1.184 bytes, texto cifrado de 1.088 bytes | selar a chave por transação de um envelope de nota para o endereço do destinatário; selar um envelope de entrada de chamada para um auditor; selar um trabalho de prova para um provador pareado |
| ChaCha20-Poly1305 | chave de 32 bytes, nonce aleatório de 12 bytes anteposto, tag de 16 bytes | cada parte de um envelope: corpos de notas, chaves de transação encapsuladas, transcrições de entrada de chamada; os trabalhos e as respostas de um provador pareado |
| BLAKE3 | saída de 32 bytes, sempre com uma string de domínio como prefixo | endereços, ids de transação, o binding da transação e o binding da chamada, ids de programa, ids de ativo de token, a raiz de estado e suas árvores de Merkle, a identidade p2p, mensagens de assinatura, ids de ativo da bridge, o blinding de um depósito na bridge e os blindings das notas de taxa da bridge |
| Poseidon2 sobre Goldilocks | largura 8, taxa 4, capacidade 4, esponja de sobrescrita sem padding; os elementos da mensagem são palavras de 32 bits; as 86 constantes de rodada são uma tabela literal no código-fonte do nó (poseidon2_constants.rs) desde o corte da chain 15, os mesmos valores que o sorteio com semente produzia antes | tudo o que fica dentro de uma prova: chaves, compromissos de notas, nullifiers, a árvore de compromissos, o digest do programa hc, os compromissos de entrada H_IN e H_PUB, o digest do bundle, o compromisso de autorização |
| secp256k1 ECDSA + keccak256 | assinaturas low-s, endereços de guardião de 20 bytes no estilo Ethereum, mu = keccak256(keccak256(body)) | atestações dos guardiões da bridge, de modo que a mesma chave funcione nos contratos EVM, no programa Solana e na Rand; na Rand, toda atestação também exige o quórum Dilithium2 abaixo |
| bech32m (BIP-350) | parte legível rpl, payload de 32 bytes, 52 caracteres de dados + 6 caracteres de checksum = 62 | a forma textual rpl1… do id de ativo de um token RPL |
| Plonky3 batch STARK | Goldilocks p = 2⁶⁴ − 2³² + 1, FRI com hiding, blowup 8, aridade de dobra 8, 80 consultas, 20 bits de proof-of-work | toda prova de bundle, prova de autorização e prova de chamada; uma prova de bundle e sua prova de autorização carregam as oito palavras de binding de sua transação como segmento de entrada pública |
Os parâmetros-alvo do whitepaper diferem em alguns pontos do que a implementação executa (por exemplo, o hash de transcrição de 384 bits do artigo, contra a transcrição Poseidon2 da zkVM). Estas páginas descrevem o código.
Co-assinaturas pós-quânticas na bridge
As atestações dos guardiões da bridge são secp256k1 ECDSA, que um adversário quântico poderia forjar. Desde a chain 14, todo BridgeAttest — seja um depósito, seja uma rotação do conjunto de guardiões — deve carregar também um quórum de assinaturas Dilithium2 dos mesmos guardiões sobre o mesmo digest:
M = "rand-bridge-pq-cosign-1" || rand_chain_id (u64 BE) || mu // 63 bytes, deterministic signing
onde mu = keccak256(keccak256(body)) é o que o quórum ECDSA assina. O id da chain Rand em M impede que uma co-assinatura de testnet seja verificada em outra chain Rand, mesmo que as chaves dos guardiões tenham sido reutilizadas. M vincula apenas o id da chain, inclusive na chain 20: é a única mensagem assinada que o binding_domain não moveu para trás do hash de gênese, porque os daemons de guardiões que a assinam vivem em outro repositório. Uma cópia de uma chain sob o mesmo id de chain e com o mesmo conjunto de guardiões aceitaria as co-assinaturas dos depósitos dela; o índice do conjunto de guardiões não está em M, de modo que uma co-assinatura sobrevive a uma rotação do conjunto ECDSA. O campo pq_signatures da ação é uma lista de PqSignature { index: u8, signature }, verificada do barato para o caro: quorum(n) ≤ len ≤ n (PqNoQuorum), índices estritamente crescentes (PqIndexOrder), todo índice abaixo de n (PqIndexOutOfRange), toda assinatura com exatamente 2.420 bytes (PqBadSignatureLength) e, por último, cada assinatura verificada sob pq_guardians[index] (PqBadSignature). Os signatários PQ não precisam ser os signatários ECDSA; cada quórum é contado por conta própria. O campo está dentro do binding da transação, portanto não pode ser removido nem trocado em uma cópia.
O conjunto PQ é o bridge.pq_guardians da gênese — oito chaves de 1.312 bytes na chain 20, como nas chains 15 a 19, alinhadas por índice ao conjunto ECDSA da gênese, conjunto de guardiões 1 (a chain 14 tinha seis, alinhadas ao conjunto 0). Uma rotação do conjunto de guardiões ECDSA nunca o move. Na chain 14 ele ficou fixo durante toda a vida da chain; desde a chain 15 a gênese traz o grupo rules_v2 da bridge, sob o qual um quórum PQ pode substituir todo o conjunto PQ (RotatePqGuardians) ou a chave de pausa (RotatePauseKey), cada um sob o rotation_nonce da bridge. A gênese da chain 20 acrescenta bridge.rotation: uma rotação deve ser a ação V2, carregando a assinatura Dilithium2 de cada nova chave sobre a mesma mensagem (prova de posse), e entra em vigor um dia depois de registrada, a menos que a chave de pausa atual a cancele (Bridge). rand_getBridgeState serve as chaves e um bridge_attest decodificado lista pq_signers, os índices que assinaram. O mesmo quórum PQ autoriza as mensagens de governança da bridge, cada uma com um layout big-endian fixo que carrega o id da chain e um nonce. Na chain 20 (gênese binding_domain: 1), o dígito de versão de cada domínio é 2 e o hash de gênese de 32 bytes fica entre o domínio e o id da chain; as chains 14 a 19 usam as formas -1:
| mensagem | domínio (chains 14–19 / chain 20) | assinada por |
|---|---|---|
M_pause | rand-bridge-pause-1 / -2 | a única chave de pausa da gênese (Dilithium2), que pode pausar e nunca despausar |
M_unpause | rand-bridge-pq-unpause-1 / -2 | um quórum de guardiões PQ |
M_list | rand-bridge-pq-list-1 / -2 | um quórum de guardiões PQ (ListBacking) |
M_register | rand-bridge-pq-register-1 / -2 | um quórum de guardiões PQ (RegisterBridgedToken) |
M_rotate_pq | rand-bridge-pq-rotate-pq-1 / -2 | um quórum do conjunto PQ atual (RotatePqGuardians, chains rules_v2); na chain 20 também cada nova chave, como prova de posse |
M_rotate_pause | rand-bridge-pq-rotate-pause-1 / -2 | um quórum do conjunto PQ atual (RotatePauseKey, chains rules_v2); na chain 20 também a nova chave |
M_cancel | rand-bridge-cancel-rotation-1 / -2, com um byte kind ao final | a chave de pausa atual (CancelRotation, chains com bridge.rotation: chain 20) |
O STARK em produção
A zkVM está no constraint set 8: nove tabelas obrigatórias (program, cpu, memory, alu, range, nibble, poseidon2, input, public) mais uma tabela keccak e uma tabela sha256 que uma prova só carrega quando seu guest chamou o syscall correspondente, conectadas por dezessete buses e provadas como um único batch STARK. Desde o constraint set 7, toda tabela declarada tem pelo menos 2⁷ linhas e o terminal LogUp de cada tabela é cegado pelo décimo sétimo bus, BLIND. A interface pública de uma prova tem 35 elementos de corpo (pv::NUM): o pc de entrada, o tier, as oito palavras de saída, o digest do programa hc (8 palavras), o compromisso de entrada privada com sal H_IN (8), o digest do segmento público sem sal H_PUB (8) e, desde o constraint set 8, o limite de gas declarado GAS_LIMIT.
| parâmetro | produção | observação |
|---|---|---|
| consultas FRI | 80 | o reajuste para 27 consultas dos constraint sets 3 e 4 foi revertido após a auditoria de 2026-09-12: deixava ~42 bits provados |
| blowup | 8 (log_blowup = 3) | o grau máximo de restrição de cada tabela é fixado abaixo do teto de 8 |
| aridade de dobra | 8 | |
| bits de proof-of-work | 20 | |
| solidez | 3·80 + 20 = 260 bits conjecturados (ethSTARK); cerca de 86 bits provados sob proximity gaps | |
| conhecimento zero | estatístico: o LDE e o polinômio de lote do FRI são randomizados, de modo que duas provas de uma mesma execução diferem | desde o constraint set 7 toda tabela declarada tem pelo menos 2⁷ linhas, mais do que os 82 pontos que uma prova abre, e os terminais LogUp são cegados |
| tiers | 10, 12, 14, 16, 18, 20 | uma prova revela o tier, nunca a contagem de ciclos; desde o fullnode v0.5.6, uma prova de chamada acima do tier 14 é recusada (CallTierTooHigh), uma prova de bundle é fixada no tier 14 e uma prova de autorização no tier 10 |
| limite de prova | o max_proof_bytes da gênese: 4 MiB (4.194.304) nas chains 17 a 20; 8 MiB nas chains 13 a 16; 2 MiB (MAX_PROOF_BYTES) em uma gênese sem ele, como a chain 12 | 2 MiB está acima de toda prova sem tabelas de hash que os guests implantados podem produzir e abaixo de uma que carrega keccak; 4 MiB admite ambas |
| gas | 1 por linha de cpu; 3 por linha de absorção do Poseidon2; 64 por linha SHA256; 192 por linha KECCAK | acumulado na coluna GAS da tabela cpu e provado como no máximo GAS_LIMIT; o verificador recusa um limite acima de gas_max(t, k, s) = (2ᵗ − 1) + 2ᵗ⁻² + 191·(2ᵏ/32) + 63·(2ˢ/64), que é 1.279 para um cabeçalho de tier 10 sem hash e 20.479 para um de tier 14 |
Tamanhos medidos no conjunto de restrições 6 (Apple Silicon, build de release): uma prova de produção sem keccak tinha 1.298.729 bytes no tier 10 e 1.359.978 no tier 12; uma prova de tier 10 com keccak tinha 3.198.430, acima dos 2 MiB padrão e abaixo dos 8 MiB das chains 13 a 15. Uma prova de tier 14 do guest de bundle 2-in-2-out, já aposentado, mediu 1.321.773 bytes na chain 8 e de 1.418.406 a 1.420.423 bytes na chain 13. O guest de bundle de ativo oculto 4-in-4-out da chain 14 permanece no tier 14, sem nenhuma das duas tabelas de hash, e suas provas mediram 1.422.116 e 1.423.170 bytes na chain 14 (2026-09-20); a chain 15 fixou o mesmo guest (hc_bundle inalterado). Ali, uma prova de bundle declarava public_log_height 4, a altura das oito palavras de vinculação, e o nó recusava qualquer outro valor antes de construir uma verifier key. A prova da chamada approve de ERC-20 com keccak, feita na chain 13 em 2026-09-19 (tier 16), tem 3.412.405 bytes; toda chain desde o fullnode v0.5.6 recusa essa chamada, no tier 16.
As colunas de blinding e os pisos de tabela do conjunto de restrições 7 acrescentam cerca de 5% a uma prova sem hash: medido pelo fullnode em 2026-09-28, fib tem 1.367.688 bytes no tier 10 e 1.424.299 no tier 12, uma prova de tier 10 com keccak tem 3.283.898, e uma prova de bundle de ativo oculto de tier 14 tem 1.498.821 (guest v1) e 1.497.156 (guest v2). Desde então, uma prova de bundle declara public_log_height 7. O conjunto de restrições 8 acrescenta menos de 1%. Medido na chain 18 em 2026-09-30 (Apple Silicon): provas de autenticação de 1.364.940 a 1.375.371 bytes (tier 10), provas de bundle de 1.494.151 a 1.504.260 bytes (tier 14, guest v3) e provas de chamada de 1.498.589 bytes no tier 14 sem tabela de hash, 1.911.152 no tier 14 com a tabela SHA-256 e 3.346.865 no tier 12 com a tabela Keccak. Todas cabem no limite de 4 MiB das chains 18 a 20.
A verificação leva cerca de 16 ms com uma verifier key já aquecida e cerca de 230 ms na primeira vez que uma chave (tier, heights) é construída. O perfil FRI test (16 consultas) existe para a suíte de testes e é inseguro; o genesis da chain 20 fixa production. O fullnode v0.6.8 não altera nenhuma restrição: a chain 20 fixa os mesmos hc_bundle e hc_auth das chains 17 a 19.
Construções de hash que você pode reproduzir
BLAKE3 com um domínio: blake3(domain || data), a string de domínio sem separador.
O domínio de vinculação. O genesis da chain 20 define binding_domain: 1 (fullnode v0.6.8, audit v6 BIND-1). Em uma chain assim, toda vinculação de prova e toda mensagem de ação assinada que vinculava apenas o chain id passa a vincular também o hash do genesis: o número de versão do domínio sobe em uma unidade e o hash do genesis, de 32 bytes, vem primeiro na pré-imagem, antes do chain id. Uma prova ou uma assinatura feita para uma chain deixa então de ser verificada em qualquer outra, mesmo que reutilize o chain id e as chaves, como faz um re-cut. As palavras de vinculação são uma entrada pública das provas, de modo que nenhum guest nem verifier key mudou. A tabela traz as duas formas; as chains 14 a 19 usam a primeira, byte a byte. Já vinculados ao genesis antes, e inalterados: votos e propostas (desde consensus_domain: 1), o Registration v2 e um voto de AdmitValidator. Não alterada: a co-assinatura de mint da bridge (acima). Uma carteira precisa do v0.6.8 para enviar na chain 20 e decide a forma pelo chain id, não pelo que um nó afirma; rand_getLimits.binding_domain a informa.
| valor | construção |
|---|---|
| endereço transparente | blake3("rand-address" || dilithium2_public_key), base58 |
| id da transação | blake3("rand-txid-3" || bincode(view)), onde view é a transação com os bytes de prova do bundle substituídos por blake3(proof) e sua prova de autenticação por blake3(auth_proof); auth_commit entra como está. O domínio era rand-txid-2, sem campos de autenticação, até a chain 16 |
| vinculação da transação | blake3("rand-tx-bind-1" || bincode(chain_id, bundle', action')) nas chains 14 a 19; blake3("rand-tx-bind-2" || bincode(genesis_hash, chain_id, bundle', action')) na chain 20. Oito palavras u32 little-endian, onde ' substitui bundle.proof, bundle.auth_proof e o proof de um Aggregate pelo vetor vazio; bincode com inteiros little-endian de largura fixa. Toda prova de bundle e toda prova de autenticação é feita sobre estas palavras e verificada contra elas |
| vinculação da chamada | blake3("rand-call-bind-1" || …), ou rand-call-bind-2 com o hash do genesis primeiro na chain 20: a construção da vinculação da transação com o próprio proof do Call (ou do Invoke) também zerado. Em um genesis hardening_v6, como o da chain 20, o segmento público de uma prova de chamada são as palavras públicas do programa definidas no deploy seguidas por estas oito palavras, e o de um Invoke acrescenta sua transição como palavras de contexto depois delas |
| id do programa | blake3("rand-program" || base_pc as 4 LE bytes || words as 4 LE bytes each) |
| identidade p2p | chave ed25519 derivada de blake3("rand-p2p-identity" || seed) |
| id de ativo da bridge (por lastro) | blake3("rand-bridge-asset" || token_chain as 2 BE bytes || token_address (32 bytes)) — rand_bridgeAssetId o calcula e rand_getAssets o imprime por linha de lastro; ele identifica uma moeda de origem na rede, não o token |
| id de ativo de token RPL, nativo | blake3("rand-rpl-asset" || bincode(name, symbol, decimals, authority, initial: Option<InitialMint>, salt)), salt sendo 32 bytes escolhidos pelo criador; exibido em hexadecimal e como rpl1… |
| id de ativo de token RPL, com bridge | blake3("rand-rpl-asset" || bincode(name, symbol, BRIDGE_DECIMALS, salt)) — não sobre um par (chain, token), já que um token com bridge abrange vários lastros |
| blinding do depósito da bridge | r = blake3("rand-deposit-r-1" || mu), o único r que a admissão aceita para um BridgeAttest (WrongDepositBlinding caso contrário) |
| blindings das notas de taxa da bridge (chain 20) | a nota de taxa de um depósito: r = blake3("rand-bridge-fee-r-1" || mu); a de uma queima: r = blake3("rand-bridge-burn-fee-r-1" || txid); ambos lidos como oito palavras little-endian. As notas não têm envelope: todo campo é público, sendo o dono o bridge.fees.recipient do genesis |
| destinatário da bridge | blake3("rand-shielded-recipient" || pk_bytes || kem_ek) sobre o endereço protegido completo |
mensagem Mint do faucet | blake3("rand-mint-2" || bincode(chain_id, cm, pk, time, r, envelope, amount)); na chain 20, blake3("rand-mint-3" || bincode(genesis_hash, chain_id, cm, pk, time, r, envelope, amount)) |
mensagens TokenMint, SetAuthority | blake3("rand-rpl-mint-1" or "rand-rpl-authority-1", chain_id || asset_id || nonce || body); o corpo de um mint inclui blake3(bincode(envelope)). Na chain 20, rand-rpl-mint-2 e rand-rpl-authority-2, com o hash do genesis primeiro |
mensagem Registration | blake3("rand-register-2" || bincode(genesis_hash, chain_id, validator, payout)) em um genesis com staking.registration_v2 ou binding_domain: 1, como o da chain 20 (um registro v1 é recusado ali); blake3("rand-register" || bincode(chain_id, payout)) nos demais |
voto AdmitValidator (chain 20) | blake3("rand-admit-validator-1" || genesis_hash || candidate_address), assinado por cada validador votante |
mensagem Unbond | blake3("rand-unbond" || bincode(chain_id, validator, amount, nonce)); na chain 20, blake3("rand-unbond-2" || bincode(genesis_hash, chain_id, validator, amount, nonce)) |
mensagem Withdraw | blake3("rand-withdraw" || bincode(chain_id, validator, amount, nonce, time, r, envelope)); na chain 20, rand-withdraw-2, com o hash do genesis primeiro |
| nó de Merkle (árvores de estado) | blake3("rand-merkle-node" || left || right) |
| folha do registro de tokens | blake3("rand-token-leaf-1" || bincode(TokenInfo)), em ordem de índice, sob tokens_root |
| raiz de estado | na chain 20, blake3("rand-state-admitted-1" || inner || admitted_root) envolvendo 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), onde program_state_root = blake3("rand-program-state-1" || cells_root || vaults_root) (RPL-2), os dois contadores do faucet e os dois preços vigentes têm 8 bytes big-endian cada, e o invólucro compromete o conjunto admitido (staking.admission_by_vote). A da chain 19 era blake3("rand-state-7" || …) sobre os mesmos campos até byte_price (uma seção staking do genesis acrescenta os três após tokens_root sob rand-state-5, como nas chains 15 a 17; uma seção gas.dynamic do genesis acrescenta os dois preços e move o domínio para rand-state-7); rand-state-4 sobre os seis primeiros na chain 14; rand-state-2 sobre os quatro primeiros em uma chain sem seção bridge, tokens ou aggregation (Consenso) |
Poseidon2 com uma tag de domínio: H(domain, msg) = sponge_hash([domain, msg...]), a tag sendo a primeira palavra absorvida, cada palavra um elemento Goldilocks, o digest de 4 elementos dividido em oito palavras u32 (metade baixa e depois metade alta de cada elemento). Tags de domínio:
| tag | valor | construção |
|---|---|---|
NK | 1 | chave de visualização nk = H(1, sk) |
PK | 2 | valor público da nota pk = H(2, nk) |
NF | 3 | nullifier H(3, nk || cm) |
CM | 4 | compromisso da nota H(4, pk(8) || from(8) || amount_lo || amount_hi || asset || time || r(8)) — 28 palavras |
OVK, KEM_SEED | 5, 6 | a chave de visualização de saída e a semente do ML-KEM, por meio de um hash largo em modo contador [domain, nk, counter] |
NODE | 7 | nó da árvore H(7, left || right); a folha vazia é composta só de zeros |
HC | 8 | o digest do programa; a tag, base_pc e len ocupam as faixas de capacidade da primeira permutação, e então as palavras são absorvidas quatro por bloco |
OUT | 9 | o digest de saída do guest de transferência |
IN | 10 | H_IN: cabeçalho de capacidade [10, n_in, 0], depois um salt de 4 palavras, depois as entradas |
BUNDLE | 11 | o digest do bundle aposentado de 2 entradas e 2 saídas sobre 47 palavras públicas; nenhuma chain fixa mais esse guest |
| hidden bundle | 64 | o digest do bundle de ativo oculto sobre 81 palavras nas chains 14 a 16: âncora, quatro nullifiers, quatro compromissos, fee, burn_a, burn_r (duas palavras cada), burn_asset, time e, por último, a palavra de taint. Nas chains 17 a 20 (bundle guest v3) são 89 palavras: as oito palavras do compromisso de autorização c ficam imediatamente antes da palavra de taint. O ativo privado A não faz parte dele. A tag é local ao nó e fica longe das tags importadas 1 a 15 |
AUTH | 65 | o compromisso de autorização c = H(65, nk || salt), 16 palavras, com um salt novo de 256 bits por bundle; publicado pela prova do bundle dentro do seu digest e pela prova de autorização como suas oito palavras de saída, e transportado pelo bundle como auth_commit (chains 17 a 20). Local ao nó, como a 64 |
PUB | 15 | H_PUB: cabeçalho [15, n_pub, 0], sem salt; para um programa, na chain 20 as palavras são fixadas no deploy (no máximo 32.768), o segmento de cada chamada é essas palavras seguidas das oito palavras do binding da chamada, e a chamada é verificada contra o digest desse segmento; para uma prova de bundle e uma prova de autorização, o segmento são as oito palavras de binding da transação; um genesis sem max_program_public_words admite apenas o segmento vazio |
hc, H_IN e H_PUB não são sponges simples com prefixo de mensagem: o cabeçalho vai para a capacidade, de modo que as linhas de digest na tabela cpu absorvam exatamente quatro palavras por permutação. Reproduza-os com o crate importado (randprotocol_zkvm::hash::{input_digest, public_digest}, isa::Program::digest) em vez de fazê-lo à mão.
O sponge simples não faz padding, de modo que, dentro do primeiro bloco, [a] e [a, 0] produzem o mesmo hash. Toda construção acima aplica o hash a uma mensagem de comprimento fixo sob a sua própria tag. Para dados cujo comprimento pode variar, o conjunto de restrições 7 acrescentou um sponge com comprimento vinculado (hash::sponge_hash_len, o syscall POSEIDON2_LEN): ele parte do estado [0, 0, 0, 0, n, 0, 0, 0], sendo n o número de palavras, e permuta ao menos uma vez. É um hash diferente das mesmas palavras, e nenhuma nota, nullifier, raiz ou digest da chain o utiliza.
Duas propriedades a ter em mente: hc é vinculante, mas não ocultante (sem salt, de modo que um programa suposto pode ser confirmado e dois deploys do mesmo programa podem ser associados), e H_IN é ocultante além de vinculante (um salt novo de 128 bits por prova), de modo que publicar H_IN não revela nada sobre as entradas até que o detentor do salt o abra.
Derivações de chaves
| chave | a partir de |
|---|---|
| par de chaves Dilithium2 (nó) | determinístico a partir da semente de 32 bytes |
| libp2p ed25519 (nó) | blake3("rand-p2p-identity" || seed) |
chave de visualização, pk, ovk, par de chaves ML-KEM (carteira) | derivações Poseidon2 da chave de gasto, como na tabela acima; o par ML-KEM é MlKem768::from_seed(kem_seed) |
Os artigos na página de artigos trazem os argumentos de segurança: as escolhas pós-quânticas, a contabilidade de solidez do FRI e por que se mantêm 80 consultas, e o limite do comprimento do traço.