Guias · Parte 6 de 6
Certificados de inclusão
Você publicou uma raiz Merkle sob a label 309, junto com a lista de folhas fora da cadeia que a sustenta. Essa raiz é um compromisso perfeitamente válido — mas não é algo que você possa entregar a um colega, anexar a um contrato ou juntar a um processo judicial. Um certificado de inclusão é justamente essa entrega: um pequeno arquivo autocontido que prende uma ou mais folhas à raiz publicada, incorpora cada irmão necessário para reconstruir essa raiz e nomeia a transação de Cardano cuja hora de bloco dá fé do conjunto inteiro. Qualquer pessoa pode verificá-lo offline, contra qualquer explorador, sem conta e sem confiar em quem quer que o tenha produzido.
Se você conhece o OpenTimestamps, a ideia é a mesma —um recibo portátil de prova
de existência— com duas diferenças propositais. A autoridade de carimbo de tempo
é a hora de bloco da blockchain de Cardano, não um servidor de calendário. E
a prova é gerada e verificada inteiramente no lado do cliente: sem gateway,
sem servidor emissor, sem confiança em nós em nenhum passo. É o equivalente, em
chave de prova de existência, de um arquivo .ots, ancorado em Cardano e
verificável de forma autônoma.
O que um certificado prova — e o que não prova
Um certificado faz exatamente duas afirmações criptográficas, cada uma verificável de forma independente por qualquer pessoa:
- Inclusão. Uma dada
leafocupa a posiçãoindexde uma árvore Merkle SHA-256 conforme a RFC 9162 de tamanhotree_sizecuja raiz éroot. Isso se prova recalculando a raiz a partir da folha, do seu índice, do tamanho da árvore e do caminho de irmãos incorporado. É autocontido: o próprio arquivo do certificado basta. - Ancoragem. Essa
rootaparece literalmente no campomerkle[].rootdo registro da label 309 transportado pela transaçãotx_hash. Isso se prova lendo essa transação em qualquer explorador público de Cardano e comparando os bytes. Precisa do arquivo do certificado mais um explorador, nada além disso.
Juntas, elas provam que o conteúdo da folha existia na hora de bloco de
tx_hash, ou antes dela.
O que um certificado NÃO prova
A hora é afirmada pela blockchain pública, não fica ligada criptograficamente à prova —exatamente como no OpenTimestamps e no Chainpoint, você está confiando na hora de bloco da cadeia, nunca em quem produziu o certificado. Um certificado não é um carimbo de tempo eletrônico «qualificado» eIDAS (RFC 3161 / uma TSA qualificada); é um carimbo de tempo ancorado em blockchain: uma evidência corroborante forte de uma afirmação temporal, na mesma categoria de outros carimbos de tempo baseados em blockchain, e a redação no arquivo diz exatamente isso. Ele nada diz sobre quem é o autor do conteúdo (isso é uma assinatura de registro opcional; veja Assinaturas), nem prova que o conteúdo não era conhecido antes. Ele prova a existência até um prazo, não a autoria e não a novidade.
Por que a prova vai sem assinatura
Um Receipt COSE estrito do IETF é um COSE_Sign1 cujo payload é a raiz Merkle,
assinado por alguma autoridade. Aqui a autoridade é a blockchain, não uma
chave em nosso poder — então assinar a raiz com a nossa chave reintroduziria a
confiança no servidor e quebraria a propriedade de verificabilidade autônoma sobre
a qual todo o padrão se assenta. Em vez disso, o certificado emite a estrutura
CBOR de prova de inclusão do IETF exatamente como especificada, e leva a
ancoragem na blockchain no lugar da assinatura. A matemática da prova é
idêntica byte a byte à codificação do IETF; ela vai sem assinatura de propósito e
está ancorada na blockchain.
O certificado JSON
O artefato principal é o label-309-inclusion-certificate-v1: um arquivo JSON
legível tanto por pessoas quanto por máquinas. Um único arquivo cobre uma ou
muitas folhas, e cada item incorpora seu caminho completo de irmãos, de modo que o
arquivo se reverifica para sempre — sem busca no Arweave, sem gateway, sem precisar
do publicador original.
{
"format": "label-309-inclusion-certificate-v1",
"generated_at": "2026-06-16T12:00:00.000Z", // informational only, never trusted
"anchor": {
"chain": "cardano",
"network": "mainnet",
"tx_hash": "…64hex…",
"metadata_label": 309,
"block_time": 1781611200, // POSIX seconds — explorer-asserted
"block_time_iso": "2026-06-16T12:00:00.000Z",
"block_height": 12345678, // optional; explorer-asserted
"explorer_urls": [
"https://cardanoscan.io/transaction/…",
"https://adastat.net/transactions/…"
]
},
"merkle": {
"tree_alg": "rfc9162-sha256",
"root": "…64hex…",
"tree_size": 1024, // === the on-chain leaf_count
"leaves_list_uri": "ar://<txid>" // optional source reference
},
"items": [
{
"leaf": "…64hex…", // the content hash committed as a leaf
"leaf_alg": "sha2-256", // how to hash a file to reproduce `leaf`
"index": 42,
"proof": ["…64hex…", "…64hex…"], // siblings, leaf→root; [] for a single-leaf tree
"verified": true, // proof recomputes to merkle.root at build time
"label": "contract.pdf" // optional note/filename
}
],
"claim": "Each listed hash was included in a Merkle tree whose root was published on the Cardano blockchain in the referenced transaction under metadata label 309; therefore each hash provably existed on or before the stated block time.",
"verification": {
"method": "RFC 9162 (Certificate Transparency) SHA-256 inclusion proof. For each item, recompute the Merkle root from leaf+index+tree_size+proof and compare to merkle.root; then confirm merkle.root equals the merkle[].root in the label 309 record of anchor.tx_hash on any public Cardano explorer.",
"requires_trust_in_cardanowall": false,
"time_asserted_by": "Cardano blockchain (block time), via public explorers"
}
}Alguns detalhes que vale a pena conhecer:
root,leafe cada entrada deproof[]são valores brutos de 32 bytes representados em hex. Os produtores os emitem em minúsculas; um verificador aceita qualquer um dos dois casos e rejeita qualquer caractere não hexadecimal ou cadeia de comprimento ímpar.- O
"verified": truearmazenado é o resultado do produtor no momento da construção. Um verificador nunca confia nele: recalcula a prova por conta própria e relata o seu próprio veredito. Uma folha que não foi encontrada na árvore é registrada com"verified": falsee um campo"error", nunca descartada em silêncio, de forma que o arquivo seja honesto quanto às falhas. block_timeé o carimbo de tempo POSIX —afirmado pelo explorador— do bloco que a inclui.block_time_isoé a sua representação em UTC, apenas por conveniência.
A prova de inclusão em CBOR (alinhada a COSE / RFC 9162)
Ao lado do JSON, cada item pode ser exportado como um artefato .cbor compacto
cuja estrutura de prova é idêntica byte a byte ao
draft-ietf-cose-merkle-tree-proofs.
Isso significa que qualquer verificador de estruturas de dados verificáveis
RFC 9162 / COSE pode ler a matemática da prova diretamente: o núcleo de
interoperabilidade é padrão, não sob medida. Ele não carrega nenhuma hora de bloco
absoluta nem prosa jurídica (isso vive no JSON); é apenas o núcleo portátil da
prova, e está ancorado na blockchain e sem assinatura pela razão exposta acima.
A prova de inclusão crua do IETF —bstr .cbor [tree_size, leaf_index, inclusion_path], com o valor vds (verifiable-data-structure) 1 para
RFC 9162 SHA-256— pode ser extraída por si só para um verificador COSE puro; a
ancoragem em Cardano é transportada ao lado dela como um pequeno mapa no lugar da
assinatura Sign1.
Construir e verificar com as ferramentas
O formato de certificado faz parte das ferramentas públicas e independentes do
gateway: o SDK @cardanowall/sdk-ts (com gêmeos idênticos byte a byte em Python e
Rust), a CLI cardanowall e as superfícies de verificação nas aplicações. A
matemática de construção e verificação é pura e offline — só a resolução de dados
frescos da cadeia toca a rede.
Com a CLI
certificate build recebe a lista de folhas, os alvos (hex bruto de uma folha, ou
arquivos cujo hash será calculado) e a transação cujos dados de ancoragem ela
resolve. certificate verify reexecuta a prova de inclusão por item e imprime a
ancoragem que ainda cabe a você confirmar na cadeia:
# Build a certificate for two files against a published root.
cardanowall certificate build \
--leaves-list leaves.cbor \
--tx <tx-hash> \
--file contract.pdf --file exhibit-a.png \
--out contract.cert.json
# Re-verify the proofs offline — no network, no trust in the producer.
cardanowall certificate verify contract.cert.jsonO código de saída 0 significa que a prova de cada item se recalcula até a raiz;
um código diferente de zero sinaliza uma falha de inclusão, uma entrada inválida
ou um erro de E/S — pronto para integrar diretamente ao CI. Cada item isolado
também pode ser extraído no formato canônico
{ tree_alg, tree_size, index, leaf, proof[] } e conferido com
cardanowall merkle verify.
Com o SDK TypeScript
A API certificate é pura: você busca os bytes da lista de folhas com o fetch
próprio da plataforma e os entrega; o caminho criptográfico nunca chega à rede:
import { certificate, merkle } from '@cardanowall/sdk-ts';
// `leaves` comes from decodeLeavesList(...) over the fetched leaves-list bytes.
const cert = certificate.buildInclusionCertificate({
anchor, // chain facts resolved from the tx
merkle: { treeAlg: 'rfc9162-sha256', root, treeSize: leaves.length },
leaves,
targets: [{ leaf, leafAlg: 'sha2-256', label: 'contract.pdf' }],
});
// Pure re-verification from the certificate alone — no Arweave, no chain.
const result = certificate.verifyInclusionCertificate(cert);
console.log(result.ok); // true when every item's proof recomputes to root
console.log(result.anchorClaim); // the anchor you confirm on a public explorer
// Each item also re-verifies through the plain Merkle predicate.
const item = cert.items[0];
const ok = merkle.merkleSha2256VerifyInclusion(
leafBytes, item.index, cert.merkle.tree_size, proofBytes, rootBytes,
);O verifyInclusionCertificate relata o veredito da prova e devolve em eco a
ancoragem afirmada; confirmar essa ancoragem na cadeia é o seu passo à parte e
explícito — o objeto de resultado deixa isso claro. O mesmo módulo é espelhado byte
a byte nos SDKs Python (certificate) e Rust (certificate).
No navegador, em uma página de transação
Um registro da label 309 que carrega um compromisso merkle[] exibe um painel de
inclusão em sua página de transação. Cole um ou mais hashes em hex, ou solte os
arquivos originais para calcular o hash deles no lado do cliente; a página busca a
lista de folhas direto do armazenamento endereçado por conteúdo no seu navegador,
recalcula cada prova, mostra um veredito verde/vermelho por item e oferece o JSON,
o CBOR e um PDF imprimível para download. O PDF incorpora o JSON completo como
arquivo anexado, então ele próprio é o artefato verificável por máquina — não
apenas uma imagem de um. Nada disso toca um servidor privado.
O algoritmo de verificação, de ponta a ponta
Para verificar um certificado de forma independente —no seu próprio código, sem nenhuma ferramenta nossa— faça exatamente isto:
- Rejeite os campos malformados. Cada entrada de
root/leaf/proof[]deve ser hex de comprimento par que decodifique para 32 bytes;tree_sizee cadaindexdevem ser inteiros seguros, comindex < tree_sizee1 ≤ tree_size ≤ 2³² − 1. - Recalcule a raiz de cada item. Usando a RFC 9162 §2.1.3.2, combine a folha
(
leaf = SHA-256(0x00 ‖ leaf_digest)) com o seu caminho de irmãos (node = SHA-256(0x01 ‖ L ‖ R)), dividindo na maior potência de dois estritamente abaixo do tamanho da subárvore corrente, e compare o resultado commerkle.rootbyte a byte. Uma árvore de folha única tem prova vazia. - Confirme a ancoragem na cadeia. Busque
anchor.tx_hashem qualquer explorador público de Cardano, leia seus metadados da label 309 e confirme quemerkle.rooté igual aomerkle[].rootdo registro. A hora de bloco que você lê ali é o carimbo de tempo que o certificado afirma.
Os passos 1 e 2 são a parte autocontida: eles nunca saem da sua máquina. O passo 3 é a única leitura de rede, e ela vai para um explorador escolhido por você, nunca para quem produziu o certificado.
Um arquivo, verificável para sempre
Como cada irmão do caminho está incorporado, um certificado continua se verificando muito depois de a lista de folhas, o gateway original ou o produtor terem desaparecido. As duas conferências —recalcular a raiz a partir do arquivo, confirmar a raiz na cadeia— são tudo de que qualquer pessoa algum dia precisará. Consulte Agrupar em lote com Merkle para ver como a raiz e a lista de folhas são construídas, antes de mais nada, e Verificação para o modelo completo de verificador no qual a conferência do lado da cadeia se encaixa.