Use esta página para dimensionar uma máquina de prova, para entender por que uma transferência leva mais de um minuto e por que o espaço em bloco, e não a computação, limita a vazão, e para saber o que quebra quando o sistema de provas muda. Tudo o que um validador aceita está respaldado por uma prova que ele próprio verificou.
O que uma prova afirma
Uma única relação, para todo programa que a cadeia executa:
Este programa RV32IM, iniciado em
base_pc, executado sobre um vetor de entrada privada comprometido porH_INe um segmento de entrada pública comprometido porH_PUB, parou em até2ᵗ − 1ciclos, gastou no máximoGAS_LIMITde gas e publicou estas oito palavras de saída.
O programa é identificado pelo seu digest em circuito hc; o verificador nunca vê uma palavra de instrução. Uma transferência blindada é essa relação aplicada ao programa convidado do pacote de ativos ocultos, um programa de 4 entradas e 4 saídas montado à mão, cujo hc está fixado no arquivo de gênese como hc_bundle. A chain 20 fixa o guest v3 (guests::bundle_hidden_v3, 60af094a…6e3fce, desde a chain 17). As chains 14 e 15 fixaram o v1 (83d3a370…cd0ef8) e a chain 16 o v2, sem ramificações (651043e2…839b). Desde a chain 17, todo pacote carrega também uma segunda prova, do programa convidado de autorização (guests::auth, hc_auth da gênese, 1e4e347f…5639c1): a prova do pacote recebe a chave de visualização, e a prova de autorização mostra que o remetente detém a chave de gasto correspondente. Essa é a autorização dividida, e é ela que permite que um provador pareado que detém apenas uma chave de visualização produza a prova do pacote. O guest de ativos ocultos substituiu o guest bundle de 2 entradas e 2 saídas das chains até a 13, que sobrevive no fullnode apenas para testes e que nenhuma chain fixa. Uma chamada confidencial é a mesma relação aplicada a um programa implantado (Programas).
Como a carteira prova um pacote
rand send <rand1…> <amount> faz o trabalho privado localmente, e apenas provas, compromissos, nullifiers e envelopes selados chegam à cadeia:
- Varrer a árvore com a chave de visualização e escolher as entradas: no máximo duas notas RAND que cubram o valor mais a taxa nos slots 2–3 e, para uma transferência ou queima de token, no máximo duas notas do token nos slots 0–1, com as notas RAND cobrindo apenas a taxa. Um slot de entrada não usado é um dummy: valor 0, pertencente à carteira, com a falha de pertencimento mascarada em circuito e o nullifier ainda assim publicado. Desde o guest v2, o guest não tem ramificações: o caminho de um dummy é calculado por hash ao longo dos 32 níveis, como o de uma nota real.
- Obter a âncora de topo (
rand_getAnchor) e a testemunha de Merkle de 32 níveis de cada entrada real (rand_getWitness(index)), conferindo a raiz retornada com a âncora. - Construir quatro saídas: a nota do destinatário e a nota de troco no grupo que move valor, presentes mesmo com valor zero, e dummies de valor zero nos demais, selados para uma chave descartável.
- Selar cada saída em um envelope (ML-KEM-768 para o destinatário, mais a chave da transação embrulhada sob a
ovkda carteira), montar a transação inteira com sua ação e calcular sua vinculação:blake3("rand-tx-bind-1" || …)sobre a transação com as provas em branco, oito palavras (Transações). Na chain 20, cuja gênese definebinding_domain: 1, éblake3("rand-tx-bind-2" || …)com o hash da gênese primeiro, depois o id da chain, de modo que uma prova feita para uma chain não é verificada em nenhuma outra, mesmo uma com o mesmo id de chain. Uma carteira anterior à v0.6.8 usa a vinculação antiga, e a chain 20 recusa suas provas. - Autorizar: sortear um salt novo de 256 bits e provar o guest de autorização sobre sua entrada privada de 16 palavras, a chave de gasto e o salt, com a vinculação como segmento de entrada pública, no nível 10. Ele deriva
nkda chave de gasto e publicac = H(AUTH, nk ‖ salt), que o pacote carrega comoauth_commit. - Provar o guest do pacote sobre sua entrada privada de 1.212 palavras (a chave de visualização
nk, quatro slots de entrada com seus caminhos, a âncora, quatro saídas,fee,burn_a,burn_r, o ativo privadoA,time, o salt) com a mesma vinculação como segmento de entrada pública, no nível 14. A prova mostra a propriedade, o pertencimento, que cada entrada real carrega o ativo do seu slot, os quatro nullifiers, o mesmoce os dois balançosin₀ + in₁ = out₀ + out₁ + burn_aein₂ + in₃ = out₂ + out₃ + fee + burn_r. Esta é a prova que um provador pareado pode produzir no lugar da carteira; a prova de autorização é feita na própria máquina da carteira. - Conferir o digest publicado pela prova com o calculado a partir do texto claro e enviar
Transaction { chain_id, bundle, action: None }.
A ordem importa desde a chain 14: os envelopes e a ação existem antes das provas, porque as provas se comprometem com eles. Para uma chamada, a prova da chamada é feita primeiro e também entra na vinculação. Em uma chain hardening_v6, a prova da chamada é ela própria feita sobre uma vinculação de chamada da transação com ambas as provas em branco (rand-call-bind-1 nas chains 16 a 19, rand-call-bind-2 com o hash da gênese na chain 20), que cobre os nullifiers do pacote de taxa, de modo que não pode ser copiada para outro pacote.
proving bundle (tier 14; about a minute on a laptop)…
proved in 98.3s: tier 14, 1423170 bytes
submitted transfer 4f2c… 1.5 RAND out, 98.499 RAND change, fee 0.001 RAND, anchored at height 192
A transcrição é o formato de saída da carteira conforme o guia do fullnode na chain 14; a contagem de bytes mostrada é a de uma prova de pacote em perfil de produção registrada na chain 14. A carteira desde a chain 17, incluindo a v0.6.8 na chain 20, imprime duas linhas antes destas, proving the spend authorisation on this machine (tier 10; seconds)… e authorisation proved in …: tier 10, … bytes, e reformula a linha do pacote como proving the bundle (tier 14; about a minute and a half on a laptop)….
A mesma maquinaria paga por toda ação, sempre com exatamente um pacote: uma implantação, uma chamada, um registro de token ou uma emissão de token viaja em uma autotransferência de valor zero de RAND; um bond, em um pacote que queima a participação por meio de burn_r; e uma queima de token ou uma queima de bridge, em um pacote que queima o ativo dos slots 0–1 (burn_a, burn_asset) e paga a taxa em RAND com os slots 2–3. O ativo que uma transferência move é uma palavra de testemunha e não consta de nenhum campo público.
O que custa
Medidos no laptop de desenvolvimento (Apple Silicon, build release), os números que os próprios documentos do fullnode registram:
| guest | palavras | ciclos | nível | prova | tamanho da prova (produção, 80 consultas) |
|---|---|---|---|---|---|
| guest do pacote v3 (chains 17 a 20) | — | 4.024 ciclos e 273 permutações Poseidon2 de folga no orçamento do nível 14 | 14 | ≈ 100 s, pico de 5,7 GB; 102,5 a 134,0 s medidos na chain 18 (2026-09-30) | ≈ 1,50 MB; 1.494.151 a 1.504.260 bytes medidos na chain 18 (2026-09-30) |
| guest de autorização (chains 17 a 20) | — | 250 | 10 | ≈ 7 s; 6,6 a 19,9 s medidos na chain 18 (2026-09-30) | ≈ 1,37 MB; 1.364.940 a 1.375.371 bytes medidos na chain 18 (2026-09-30) |
| pacote de ativos ocultos v1, 4 entradas e 4 saídas (chains 14 e 15) | — | abaixo do orçamento do nível 14, com cerca de 2.071 ciclos (13%) de folga | 14 | ≈ 98–100 s, pico de 5,7 GB | ≈ 1,43 MB; 1.422.116 e 1.423.170 bytes medidos na chain 14 |
bundle, 2 entradas e 2 saídas (aposentado; chains até a 13) | 3.811 | ≈ 9.160 | 14 | ≈ 100 s (94,6–97,9 s isolado; 114 s cada, para dois ao mesmo tempo) | 1.321.773 bytes medidos na chain 8 |
private_payment (uma chamada) | pequeno | < 1.000 | 10 | ≈ 7 s | ≈ 1,37 MB (fib no nível 10: 1.367.688 bytes sob o conjunto de restrições 7; 1.298.729 sob o conjunto 6) |
| uma chamada sem tabela de hash (ledger fora da cadeia, chain 18) | 773 | — | 14 | 114,8 s | 1.498.589 bytes |
| uma chamada com a tabela SHA-256 (prova de passivos, chain 18) | 994 | — | 14 | 122,9 s | 1.911.152 bytes |
| uma chamada com a tabela Keccak (voto anônimo, chain 18) | — | — | 12 | 29,2 s | 3.346.865 bytes |
A verificação é o custo de consenso, pago por todo nó: cerca de 16 ms com uma chave de verificação já aquecida, cerca de 230 ms na primeira vez que uma chave é construída para um dado formato. A chave de verificação não depende do conteúdo do programa — ela é indexada por (tier, program_log_height, input_log_height, keccak_log_height, sha256_log_height, public_log_height) — de modo que um nó constrói uma por formato e a reutiliza; para um programa implantado, a chave é calculada uma única vez em segundo plano no momento da implantação (cerca de 2 s em um laptop, 7 s em um servidor de 2 vCPUs). O pacote 2 entradas e 2 saídas da chain 13 e anteriores declarava o formato program 12, input 10, keccak 0, sha256 0, public 2, mem 16; uma prova de pacote da chain 14 declara public 4, a altura das oito palavras de vinculação, não carrega nenhuma das tabelas de hash e é recusada antes que qualquer chave de verificação seja construída se declarar outro nível, qualquer uma das tabelas ou outra altura pública. Desde o conjunto de restrições 7, toda tabela declarada tem pelo menos 2⁷ linhas, de modo que uma prova de pacote da chain 20 declara public 7.
Uma transferência na chain 20 carrega, portanto, cerca de 2,87 MB de prova, a prova do bundle e a prova de autenticação, e uma chamada uma terceira prova além dessas. Cada uma precisa caber no max_proof_bytes do genesis, 4.194.304 (4 MiB) na chain 20, como nas chains 17 a 19, abaixo dos 8 MiB das chains 13 a 16.
O guest de ativo oculto cabe no tier 14 apenas porque lê suas entradas privadas em um laço e funde as leituras de irmãos da verificação de Merkle; escrita no estilo anterior, desenrolado, a mesma relação cai no tier 16, com cerca de 400 s e 21–22 GB, o que excluiria carteiras de 16 GB.
A geração de provas é limitada pela CPU, e a carteira usa hoje o backend de CPU em todas as plataformas. Nas execuções de tier grande, o prover era single-threaded: um droplet de 16 vCPUs rodou a 99% de um único núcleo, e a memória, não os núcleos, decidiu se uma prova terminava (memória de prova). A flag --cuda em send, bond, call, deploy, bridge-mint e bridge-burn seleciona um backend NVIDIA que exige um build com --features cuda. Seus kernels rodaram pela primeira vez em hardware real, uma NVIDIA H100, em 2026-09-28 e coincidiram com a referência de CPU, mas nenhum PTX está versionado no checkout de circuits que a release incorpora, de modo que o build falha com no PTX for the GPU kernels até que os kernels sejam compilados. Nenhuma prova de produção foi medida em um nó de GPU da frota. Deliberadamente, não há fallback para a CPU. Uma chamada CUDA também não pode selar um envelope de entrada, porque o salt nunca sai do prover. O pico de memória de uma prova de bundle de ativo oculto no tier 14 é de cerca de 5,7 GB (Production FRI, CPU); as classes de memória maiores dizem respeito às provas do interpretador e de recursão abaixo (≥ 64 GB em diante).
Como um nó verifica
A admissão executa primeiro verificações baratas (Transações) e depois:
- recalcula o bundle digest a partir do texto claro publicado (âncora, quatro nullifiers, quatro commitments,
fee,burn_a,burn_r,burn_asset,time, oauth_commitdo bundle e uma palavra de taint fixada em zero) e exige que seja igual ao que a prova publicou — uma prova cuja witness quebrou a relação publica um digest contaminado que não corresponde a nenhum texto claro. Algumas verificações são estruturais (o guest fornece por conta própria o remetente, o ativo e o tempo de uma saída, de modo que um prover não pode escolhê-los), e o ativo privado não está no digest; - decodifica a prova e confere suas alturas declaradas com o tier (
check_declared_heights), de modo que o limite da chain sobre a forma de uma prova é o do verifier. Antes de qualquer assinatura ou prova ser verificada, uma triagem de prova canônica roda em toda transação submetida ou propagada por gossip (e, sobhardening_v6, na validação de blocos); desde o fullnode v0.6.8 (audit v6, ZKV-4), essa triagem primeiro limita todo grau declarado a 25 bits (MAX_HONEST_DEGREE_BITS, o teto da tabela de memória mais um), de modo que um cabeçalho com um grau enorme não prende mais um nó enquanto o cronograma de dobragem honesto é recalculado para ele, e um panic dentro da triagem recusa essa transação em vez de parar o nó; - calcula o binding da transação e executa
Machine::verify_public(hc_bundle, &binding, proof)— o verifier em lote mais a verificação de queH_PUBé o digest dessas oito palavras, de modo que uma prova copiada para uma transação com outra ação, outro envelope ou outro chain id, ou, na chain 20, para o genesis de outra chain, não verifica (até a chain 13 o segmento era vazio e nada vinculava uma prova à sua transação); - verifica a prova de autenticação contra
hc_authe o mesmo binding, e exige que ocque ela publica seja igual aauth_commit. Um bundle sem prova de autenticação é recusado (AuthMissing), assim como um cujocdifere (AuthMismatch); - exige que o
GAS_LIMITda prova do bundle seja igual aobundle_gas_limitdo genesis, 20.479, e o da prova de autenticação seja igual a 1.279, os tetos de cabeçalho dos dois guests (BundleGasLimit,AuthGasLimit); - para uma chamada, faz o mesmo contra o
code_hasharmazenado do programa, com as palavras públicas do programa seguidas do binding da chamada como segmento (umInvokede RPL-2 acrescenta sua transição como palavras de contexto, Programas), e então confere a taxa contra o limite de gas que a prova declara e seus bytes (Taxas).
Uma transação submetida por RPC ou gossip é verificada em um de quatro workers atrás de uma fila de 64 posições, fora do laço de consenso, e só é propagada adiante depois de verificada; um token bucket por peer (rajada de 16, reposição de 4 por segundo) mede o que um peer pode fazer um nó verificar, e um cache de 8.192 entradas responde sem custo a uma repetição de uma transação recusada em definitivo. A verificação das provas dentro de um bloco proposto ainda roda no laço de consenso quando o bloco é aplicado. Um nó que sincroniza reverifica todo certificado e toda prova de todo bloco antes de aceitá-lo; nada é confiável só porque um quórum assinou.
Tiers
| tier | orçamento de ciclos (2ᵗ − 1) | linhas da cpu | usado por |
|---|---|---|---|
| 10 | 1.023 | 2¹⁰ | o guest de autenticação; private_payment, fib |
| 12 | 4.095 | 2¹² | |
| 14 | 16.383 | 2¹⁴ | o guest de bundle de ativo oculto (e o guest bundle aposentado); a maior chamada |
| 16 | 65.535 | 2¹⁶ | a prova de chamada EVM na suíte de testes; o approve de ERC-20 traduzido (chamado na chain 13) |
| 18 | 262.143 | 2¹⁸ | transfer e transferFrom de ERC-20, traduzidos ou interpretados |
| 20 | 1.048.575 | 2²⁰ | SPL Token, traduzido ou no guest interpretador sBPF |
Desde o fullnode v0.5.6 (2026-09-25), uma prova de chamada acima do tier 14 é recusada (CallTierTooHigh) antes que uma verifier key seja construída, e um bloco que a carregue é inválido; uma chamada também pode carregar no máximo 128 permutações Keccak-f e 128 compressões SHA-256. Os tiers 16 a 20 ainda geram prova, mas apenas off-chain: nenhuma das linhas acima delas pode ser chamada na chain 20, e a chain 20 recusa o deploy de um programa grande demais para qualquer chamada de tier 14, com mais de 8.180 palavras sem entrada pública (ProgramUncallable) (o orçamento).
O prover escolhe o menor tier cujo orçamento cobre os ciclos mais as linhas do programa e do digest de entrada; uma execução que não cabe falha antes da geração da prova. Apenas o tier é público. Cada degrau multiplica aproximadamente por quatro o tempo de prova e acrescenta um pouco ao tamanho da prova. Na chain 20, a taxa de uma chamada segue o limite de gas que sua prova declara e seu tamanho em bytes, não o tier (Taxas).
Conjuntos de restrições e hard forks
Um conjunto de restrições é o conjunto exato de tabelas, colunas, buses, valores públicos e parâmetros FRI que o verifier confere. Uma prova feita sob um conjunto não verifica sob outro, em nenhuma das direções, e o replay de inicialização de um nó reverifica toda prova de sua chain — de modo que um nó construído a partir de um conjunto diferente falha na primeira prova e trunca. É por isso que toda mudança no conjunto é cortada como um novo chain id, com todos os nós em um único build, e por isso rand_status informa hc_bundle e hc_auth, e um nó cujo build discorda do genesis se recusa a iniciar.
| conjunto | data | o que mudou |
|---|---|---|
| 2 | 2026-09-10 | cinco correções de solidez após a primeira revisão |
| 3 | 2026-09-11 | chip Poseidon2, hc no circuito, a tabela de programa como witness, memória de sub-palavra, RV32M, FRI reajustado para 27 queries |
| 4 | 2026-09-11 | o compromisso de entrada com salt H_IN com sua própria tabela; o carregador de binário plano |
| 5 | 2026-09-12 | a tabela opcional keccak; altura de memória declarada pela prova; duas correções críticas da auditoria de zk; FRI de volta a 80 queries; MAX_PROOF_BYTES para 2 MiB |
| 6 | 2026-09-14 | a tabela obrigatória public e H_PUB; a tabela opcional sha256; os guests interpretadores de EVM e sBPF como bibliotecas; 34 valores públicos. O que as chains 12 a 15 executaram. |
| 7 | 2026-09-28 | todo terminal LogUp ofuscado por meio do bus BLIND; toda tabela declarada com piso de 2⁷ linhas; verificações de intervalo de 32 bits em palavras de entrada, públicas e de salt; a syscall POSEIDON2_LEN (7); JALR zera o bit 0 de seu destino e exige funct3 = 0; verifier keys com salt a partir de key_derivation_v2. O que as chains 16 e 17 executaram. |
| 8 | 2026-09-29 | o medidor de gas: a coluna GAS na tabela cpu e o valor público GAS_LIMIT; 35 valores públicos. O que as chains 18 a 20 executam. |
As chains 14 e 15 não mudaram nenhuma restrição. O nó da chain 15 mantém as 86 constantes de rodada do Poseidon2 como uma tabela literal, em vez de um sorteio a partir de uma seed (auditoria ZKV-2) — os mesmos valores, de modo que nenhum hash, digest ou prova se moveu. Chain 14: o bundle de ativo oculto é um novo guest (um novo hc_bundle) e o binding da transação usa o segmento público que o conjunto 6 já vincula no circuito. Ainda assim é um hard fork — o formato de wire do bundle, o guest fixado e todo id de transação mudaram, uma transação da chain 13 que carregue um bundle é recusada pelo novo build, e uma carteira construída antes do fork produz provas de segmento vazio que a chain recusa.
As três cadeias seguintes mudaram, cada uma, o que é uma prova. A chain 16 (fullnode v0.6.1, 2026-09-28) passou para o constraint set 7, fixou o guest de bundle v2, sem ramificações, e definiu hardening_v6, depois que a revisão de 2026-09-27 mostrou que tabelas curtas e terminais LogUp sem blinding vazavam dados privados (How the zkVM works). Todas as verifier keys mudaram. A chain 17 (v0.6.3, 2026-09-29) manteve o set 7 e acrescentou a autorização dividida: bundle guest v3, o auth guest, dois novos campos no formato de transmissão do bundle e o domínio de id de transação rand-txid-3. A chain 18 (v0.6.7-rc1, 2026-09-29) passou para o constraint set 8, por causa do medidor de gas. Seu custo medido em tamanho de prova é inferior a 1%. A chain 19 (2026-10-01) é um re-genesis da chain 18 na mesma build v0.6.7 e não alterou nada nas provas. A chain 20 (fullnode v0.6.8, 2026-10-01) mantém o constraint set 8 e os mesmos guests e verifier keys, e muda aquilo a que uma prova está vinculada: os bindings de transação e de chamada carregam o hash de genesis (binding_domain: 1), uma entrada pública que a carteira e o ledger calculam, de modo que nenhum circuito mudou. Ainda assim, é um hard fork, pois as provas de uma carteira v0.6.7 não são verificadas nela. Cada build recusa as cadeias anteriores pelo hash de genesis.
Duas notas de auditoria presentes no código e que vale conhecer: o valor público TIER é verificado pelo verifier contra o cabeçalho da prova e os degree bits do lote, mas não é restringido pelo próprio circuito (auditoria ZL1, sinalizada para o próximo set em vez de corrigida, porque removê-lo desloca o layout dos valores públicos); e H_IN é um compromisso visível ao guest que o verifier não compara com um valor fornecido pelo chamador, por projeto.
Upcoming: block aggregation
Com cerca de 1,43 MB por prova de bundle de ativo oculto nas chains 14 e 15, um bloco de 4 MiB (o padrão, e o da chain 12) comportava duas transferências shielded; comportava três com os ~1,3 MB do bundle 2-in-2-out. As chains 13, 14 e 15 elevaram o limite de bloco para 20 MiB (max_block_bytes), espaço para quatorze. A chain 20 mantém 20 MiB, e uma transferência nela carrega cerca de 2,87 MB de prova, de modo que um bloco comporta cerca de sete. A solução que o fullnode escolheu (2026-09-12), em vez de poda e em vez de um bloco maior, é a agregação em nível de bloco: uma prova recursiva por janela selada que verifica N provas de bundle, de modo que o histórico continua carregando provas de ponta a ponta enquanto as provas brutas podem ser descartadas. Ela está construída e integrada, mas não ativada, e desde a chain 14 precisa ser remedida antes de poder ser: o formato de bundle admitido foi medido com o segmento público vazio (public 2), e um bundle vinculado à transação declara public 4, de modo que nenhum bundle provado na chain 14 corresponde a ele. Os constraint sets 7 e 8 mudaram o formato de novo: uma prova de bundle agora declara public 7 e publica 35 valores, de modo que a interface do agregado é de 35 palavras por prova. Uma build de nó se recusa a iniciar em qualquer genesis que traga uma seção aggregation, e as chains 14 a 20 foram criadas sem ela. Um genesis com preços de gas dinâmicos, como o da chain 20, também é recusado junto a uma seção aggregation. Desde o fullnode v0.5.8, a prova agregada também vincula seu aggregator (auditoria AGG-2: o programa absorve aggregate_binding(chain_id, aggregator, nonce)), de modo que o digest do programa do formato admitido precisa ser medido em uma build que traga essa mudança. A ativação também ainda aguarda um exercício de ponta a ponta de agregado forjado contra o verificador de recursão corrigido, que não foi executado, e uma decisão sobre a prova de autorização: o programa de agregação verifica apenas provas de bundle, de modo que, em uma cadeia de autorização dividida, selar uma janela reduziria uma transferência de cerca de 2,87 MB para cerca de 1,37 MB, e não para nada.
O que está construído:
- uma segunda máquina, nativa de Goldilocks (a recursion VM,
randprotocol-rvm), cujo programa verifier confere uma prova RV32 em cerca de 1,97 milhão de linhas no tier 21 (2.044.506 sob o constraint set 7), e um programa de agregação genérico em N sobre uma janela de provas de bundle; - dois papéis: os validators continuam baratos em CPU e verificam um agregado por bloco selado; os aggregators (um registro sem permissão e com garantia, com um endereço de pagamento shielded) provam agregados em máquinas de classe GPU e recebem a parcela de prova dos bundles cobertos mais um subsídio de bloco em novos RAND, segundo um cronograma de halving;
- cinco ações (
RegisterAggregator,UnbondAggregator,WithdrawAggregator,SlashAggregator,Aggregate;SlashAggregatorpermanece no formato de transmissão e é recusada, porque um agregado repetido assina novamente o mesmo nonce e isso não é equivocação), uma admissão em nove etapas, selagem e poda dos bundles cobertos até cerca de 3 KB de campos públicos cada, uma sincronização em formato selado que custa a um nó novo uma verificação de recursão por janela, os métodos RPCrand_getAggregate,rand_getAggregators,rand_getUnsealed,rand_getRawTransactione o daemonrand-node aggregate --watch.
Medido no perfil FRI de teste: um agregado com N=1 provado em cerca de 26 minutos em um laptop sob carga (327.035 bytes); um nó novo aplicou um lote selado de sete blocos em menos de um segundo, com uma verificação de recursão. Classes de máquina conforme os primeiros limites: N=1 exige ≥ 64 GB de memória do host, N=2 ≥ 128 GB, N=3 ≥ 160 GB; o N ≥ 2 de produção pertence ao backend CUDA, que precisa de um nó com GPU que ainda não existe. Medido em uma máquina de 256 GB sob o constraint set 7 (2026-09-28 e 29), o agregado com N=2 consumiu 133 GB, o N=3 consumiu 221 GB, e a prova de saída de produção (o programa verifier sobre uma prova interna) excedeu 256 GB. Nada disso foi remedido sob o constraint set 8. Até que a agregação seja ativada, nenhum agregado substitui uma prova na chain 20: seus dois nós de arquivo guardam todas as provas brutas, e seus validators podam o histórico com mais de 24 horas.