Esta é uma tradução informativa. A versão em inglês é a oficial e prevalece. Ler a versão em inglês

Verificação

Os três papéis de verificador do Label 309, os estados de veredito, a profundidade de finalidade e o catálogo tipado de erros — como qualquer pessoa chega à mesma resposta usando apenas infraestrutura pública.

O Label 309 é verificado, nunca apenas afirmado. Quem publica ancora o hash de um conteúdo na Cardano sob o rótulo de metadados 309; a partir daí, a afirmação se sustenta pelos próprios bytes, e qualquer pessoa de posse da referência de transação pode conferi-la. Esta página define como essa conferência funciona: os três papéis de verificador, o que cada um faz e não toca, os estados de veredito que emitem, a profundidade de confirmação abaixo da qual um veredito permanece provisório e o catálogo tipado de erros que faz duas implementações independentes concordarem na mesma falha para a mesma entrada.

A propriedade que define o padrão é a independência de serviço. Um verificador em conformidade chega ao seu veredito usando apenas a blockchain pública, um explorador ou gateway Cardano escolhido pelo próprio verificador e — para afirmações sobre conteúdo e para registros selados — gateways de armazenamento endereçado por conteúdo que o verificador também escolhe. Ele nunca contata quem publicou. O padrão não nomeia nenhum provedor específico; o gateway é uma entrada fornecida pelo operador.

Três papéis, cada um uma extensão estrita

A verificação é organizada em camadas. Cada papel faz tudo o que o papel acima dele faz e então acrescenta uma capacidade. Um papel inferior já é, por si só, um verificador completo e útil — ele apenas prova menos.

PapelAcrescentaToca
Validador estruturalconformidade de esquema + de domínio sobre os bytes do registronada — uma função pura
Verificador públicoresolução de cadeia, inclusão on-chain, verificação de assinaturasum explorador Cardano + gateways de conteúdo
Verificador do destinatáriotentativa de decifragem de uma carga útil selada, recálculo do hash do texto claroa chave privada do próprio verificador

Validador estrutural — uma função pura sobre os bytes

O validador estrutural é uma única função que vai de uma cadeia de bytes a um resultado. Ele não realiza nenhuma E/S, nenhuma verificação de assinatura criptográfica e nenhuma decifragem. Nunca vê uma rede, uma transação ou uma chave. Dada a mesma entrada, ele retorna a mesma saída, sempre, em qualquer lugar — e é isso que permite executá-lo antes da submissão, dentro das ferramentas de quem publica, dentro de um indexador de terceiros ou dentro de uma ferramenta de arquivamento que confirma a boa formação a longo prazo, tudo isso sem servidor.

Seu fluxo é fixo:

1. resource bounds   — a local, non-normative guard on input size; never a
                       Label 309 conformance error.
2. canonical decode  — decode with a canonical-CBOR decoder (RFC 8949 §4.2.1):
                       definite lengths, sorted map keys, no duplicate keys,
                       valid UTF-8. Any malformed or non-canonical input →
                       a single MALFORMED_CBOR.
3. schema parse      — type, length, and the chunk/length bounds; a strict
                       object mode that rejects unknown fields.
4. domain rules      — cross-field constraints the schema cannot express:
                       registry membership, the items-or-merkle rule, COSE
                       structural shape, URI reconstruction, envelope shape.
5. result            — { valid, record } with optional warnings/info, or a
                       sorted list of typed issues.

O validador é independente de perfil: ele analisa o esquema v1 completo, independentemente do subconjunto sobre o qual um verificador posterior pretenda agir. Erros reprovam o registro; entradas de aviso e de informação são expostas, mas o deixam válido. De forma crucial, ele confirma a forma de um COSE_Sign1 — array de quatro elementos, carga útil destacada (null), um cabeçalho protegido bem formado — mas nunca verifica a assinatura, e nunca rejeita um registro apenas porque o algoritmo de assinatura é um que ele não reconhece (isso é marcado como SIGNATURE_UNSUPPORTED, severidade info, e o registro permanece válido). Verificar a assinatura é tarefa do verificador público. Veja O registro para o esquema que este passo impõe.

Verificador público — cadeia, inclusão e assinaturas

O verificador público sobrepõe a cadeia ao validador estrutural. Dada uma referência de transação Cardano, ele:

  1. Resolve um explorador escolhido pelo verificador. A cadeia de exploradores é uma entrada; o verificador os tenta na ordem indicada, buscando o CBOR bruto da transação on-chain — nunca a projeção de metadados em JSON do explorador. A visão JSON colapsa os tipos principais do CBOR em uma união JSON e descarta a ordem das chaves do mapa, a moldura de comprimento definido e a distinção entre bytes e texto, de modo que um verificador que recodificasse a partir dela não conseguiria reproduzir a entrada de assinatura byte a byte e toda assinatura de um registro em conformidade falharia. A resposta negativa de um único provedor não é autoritativa quanto à cadeia — a transação pode estar on-chain e apenas ser desconhecida daquele provedor —, então o verificador consulta todos os provedores restantes antes de emitir TX_NOT_FOUND; se todos os provedores estiverem inacessíveis, ele emite PROVIDER_UNAVAILABLE.
  2. Vincula os bytes buscados à referência da transação. Antes de ler qualquer coisa de uma transação buscada, o verificador recalcula o blake2b-256 sobre os bytes do corpo da transação buscada — por definição do ledger, o id da transação — e rejeita a resposta diante de qualquer divergência com o hash solicitado. Em seguida, recalcula o blake2b-256 sobre os bytes de dados auxiliares buscados e rejeita diante de qualquer divergência com o auxiliary_data_hash do corpo já verificado. Ambos os digests são calculados sobre os bytes exatamente como buscados, nunca uma recodificação. Uma resposta que falhe em qualquer das verificações carrega bytes comprovadamente errados e é descartada; se nenhum provedor produzir uma resposta que sobreviva ao vínculo, o relatório carrega TX_INTEGRITY_MISMATCH. Depois desse passo, cada byte do registro e da transação ao redor está criptograficamente comprometido com o hash fornecido por quem chama — nenhum explorador pode substituir, emendar ou truncar o registro sem produzir uma segunda pré-imagem de blake2b-256.
  3. Desembrulha os dados auxiliares. O ledger da era Conway admite três codificações de dados auxiliares, todas válidas: um mapa de metadados simples e sem tag, um array de dois elementos [ metadata, scripts ] e um mapa com tag 259, com os metadados sob a chave 0. O verificador DEVE aceitar as três e despachar puramente pelo tipo e pela tag de CBOR no nível superior — um valor com tag 259 é a forma de mapa por chave, um array sem tag é a forma de dois elementos e um mapa sem tag é sempre o próprio mapa de metadados. Ele NÃO DEVE inspecionar as chaves de um mapa para adivinhar a forma; qualquer outra forma de nível superior, ou qualquer tag que não seja a 259, é MALFORMED_CBOR. Se a transação vinculada não carregar metadados sob o rótulo 309, o verificador emite METADATA_NOT_FOUND — um resultado atribuível ao registro, porque a própria transação vinculada prova a ausência: nenhum provedor poderia ter removido os metadados sem falhar no vínculo.
  4. Remonta o array de fragmentos do corpo inteiro. O valor do rótulo 309 é o corpo do registro em CBOR canônico dividido em um array de cadeias de bytes de ≤ 64 bytes. O verificador concatena os elementos em ordem, byte a byte — devolvendo os bytes brutos, sem passo de recodificação — para que a verificação de CBOR canônico ainda possa detectar uma codificação on-chain fora de conformidade.
  5. Valida estruturalmente o corpo remontado (o papel acima). Uma rejeição do validador interrompe o relatório com o veredito failed.
  6. Verifica a profundidade de confirmação (mais abaixo). Uma transação abaixo do limiar para aqui com o veredito pending.
  7. Verifica cada assinatura no nível do registro sob Ed25519 estrito. Ele não decifra. A resolução de assinaturas, a carga útil com separação de domínio e as regras estritas de verificação estão especificadas em Assinaturas.
  8. Busca e confere por hash o conteúdo, responsabilizando o registro apenas pelos bytes que ele consegue atribuir ao próprio endereço de conteúdo de uma URI (mais abaixo). Ele não decifra.

Por que CBOR bruto, e não JSON

Uma assinatura é calculada sobre o CBOR canônico, byte a byte, do corpo do registro. Uma projeção JSON dos metadados é, por construção, uma projeção com perdas — ela não consegue retornar exatamente a esses bytes. Recodificar a partir do JSON quebra toda assinatura de um registro em conformidade. O CBOR bruto da transação é a única entrada autoritativa para qualquer verificação criptográfica; uma visão em JSON serve para exibição a pessoas, depois que a verificação já passou.

Verificador do destinatário — decifrar e recalcular

O verificador do destinatário é um verificador público que, além disso, possui uma chave privada. Para um item selado endereçado a ele, ele tenta decifrar os slots de chave on-chain com sua chave, recupera a chave de conteúdo em caso de sucesso, decifra o texto cifrado e então recalcula os hashes do texto claro contra o compromisso registrado on-chain — fechando o ciclo entre os bytes cifrados e a afirmação de existência do conteúdo. Como todo item selado carrega pelo menos uma entrada de hash de conteúdo, esse recálculo sempre tem algo concreto com que se comparar. O envelope selado, os slots de chave e a construção de desembrulho estão especificados em PoE selada.

Antes de o destinatário tocar qualquer primitiva KEM ou AEAD, ele reaplica as mesmas verificações de forma e de recursos do envelope que o validador estrutural já executou, rejeitando primeiro um envelope estruturalmente inválido ou superdimensionado. Duas dessas barreiras pré-primitiva são limites de recursos fixados pela implantação, não campos de transmissão: os limites de referência são MAX_SLOTS = 1024 slots e 65536 bytes para o envelope enc decodificado, ambos muito acima do teto de ~16 KiB de metadados de transação da Cardano que limita qualquer registro honesto, de modo que um registro que exceda qualquer um deles é malformado e é rejeitado com ENC_SLOTS_TOO_MANY ou ENC_ENVELOPE_TOO_LARGE antes de uma única primitiva ser executada. As implantações PODEM restringi-los.

Uma verificação de forma tem peso de segurança: o material de encapsulamento DEVE ser distinto dentro de um mesmo slots[] — todos os valores de epk no caso de x25519, ou todos os valores de kem_ct no caso de mlkem768x25519. Uma duplicata dentro do registro é rejeitada com ENC_SLOTS_DUPLICATE_KEM_MATERIAL antes que qualquer primitiva KEM ou AEAD seja executada, porque um epk/kem_ct repetido quebraria a unicidade da chave por slot da qual o envoltório de nonce zero depende. O reúso de chave entre registros ou entre chaves é uma obrigação do produtor e não é detectável pelo verificador; só a duplicata dentro do registro o é. As três verificações são estruturais — o validador as impõe em todo registro (os códigos de material duplicado, de contagem de slots e de envelope decodificado são códigos da Parte A); o destinatário simplesmente as roda de novo como defesa em profundidade.

O próprio desembrulho são duas etapas criptográficas que o destinatário reproduz a partir do envelope, nunca de qualquer entrada lateral. Primeiro, ele recalcula o hash da transcrição de slots slots_hash uma vez, antes do laço, e o mantém constante ao longo de cada slot: slots_hash = SHA-256("cardano-poe-slots-transcript-v1" || canonicalEncode(SLOTS_TRANSCRIPT)), em que a transcrição fixa os campos de cabeçalho, o conjunto de slots em trânsito (cada campo de slot é uma única cadeia de bytes — não há fracionamento por campo a normalizar) e a alegação de hash do item por meio de hashes_hash. Vincular o hashes_hash é o que permite ao destinatário confirmar que o envelope foi selado para esta exata alegação de hash apenas a partir dos bytes on-chain, antes de qualquer busca de texto cifrado — um envelope colado em um item com um mapa hashes diferente falha no MAC. Ele itera todos os slots sem interrupção antecipada; um slot só é aceito quando a chave de conteúdo que ele produz também reproduz o slots_mac presente em trânsito sobre aquele slots_hash constante. A aceitação também incorpora um bit de validade independente do segredo: no caminho clássico, um slot forjado para levar o segredo compartilhado X25519 ao valor todo-zero zera esse bit (uma comparação em tempo constante contra 0^32), a KEK é selecionada em tempo constante para uma KEK fictícia derivada de 0^32 de modo que o laço realize trabalho idêntico, e o bit governa a aceitação do slot — um slot com ECDH inválido nunca pode abrir, independentemente de seu envoltório ou MAC. Tanto a abertura do envoltório quanto a abertura posterior do conteúdo são atômicas: em uma falha de tag AEAD, elas não retornam texto em claro, e o candidato que devolvem (a chave envolvida ou o texto em claro do conteúdo) é um valor fictício, fixo ou pseudoaleatório, independente do texto cifrado que falhou — nenhum texto em claro não verificado é jamais liberado.

A chave de um destinatário PODE legitimamente corresponder a mais de um slot: um produtor pode selar a mesma chave de conteúdo para o mesmo destinatário em vários slots, cada um com material KEM por slot fresco, para preencher a contagem de destinatários — uma técnica de privacidade válida e distinta da rejeição de material de encapsulamento duplicado, que dispara apenas em um epk/kem_ct idêntico. O verificador seleciona a chave do primeiro slot correspondente e NÃO DEVE rejeitar apenas porque vários slots corresponderam. A única anomalia que ele DEVE rejeitar são dois slots correspondentes que recuperam chaves de conteúdo diferentes (comparadas em tempo constante): o laço carrega um bit cek_conflict e expõe a única falha genérica se qualquer correspondência posterior produzir uma chave que difira da selecionada. Isso é defesa em profundidade — sob o comprometimento do conjunto de slots, uma correspondência com chave distinta já é inviável, de modo que a verificação simplesmente falha de forma fechada.

Depois, sobre a chave de criptografia de conteúdo recuperada, ele deriva a chave de conteúdo (uma folha de HKDF dessa chave, com salt enc.nonce) e abre o texto cifrado em STREAM segmentado bloco a bloco, verificando a tag de cada bloco antes de liberar o texto claro daquele bloco. O AAD por bloco é vazio: todo o contexto de cabeçalho já está vinculado à chave de forma transitiva por meio do slots_mac, de modo que inverter qualquer campo de cabeçalho muda o que o destinatário deriva e o fluxo não abre. O truncamento é detectado pelo sinalizador final — um bloco final ausente, dados após ele, um sinalizador final em um bloco não final, ou um bloco não final curto falham todos como TAMPERED_CIPHERTEXT. O formato segmentado não impõe nenhum teto criptográfico de carga útil (o contador de blocos de 88 bits admite 2^88 blocos); um máximo prático é uma política de negação de serviço da implantação, imposta de forma incremental à medida que o fluxo é lido. No caminho da frase secreta, o destinatário primeiro lê o cabeçalho de compromisso inicial de 32 bytes e o compara em tempo constante antes de abrir qualquer bloco.

O caminho do destinatário é onde o catálogo de erros mostra toda a sua precisão: ele distingue o caso em que nenhum slot aceitou esta chave (destinatário errado) do caso em que um slot aceitou a chave, mas o conjunto de slots ou o texto cifrado foi adulterado. Essas são afirmações de segurança diferentes e carregam códigos diferentes (mais abaixo). Um chamador não confiável, porém, recebe exatamente uma forma de falha genérica, qualquer que seja a causa — nenhum slot abriu, o conjunto de slots foi adulterado ou a tag de conteúdo falhou — e a resposta nunca revela qual caso ocorreu, nem qual slot correspondeu; os códigos tipados são um diagnóstico interno apenas para um chamador local confiável.

A temporização segue um modelo explícito. O verificador PODE retornar na verificação de não correspondência — antes da decifragem do conteúdo — de modo que um não destinatário e um destinatário levem tempos mensuravelmente diferentes. Essa diferença revela apenas destinatário versus não destinatário, nunca qual slot correspondeu nem qualquer material de chave. Uma temporização uniforme entre um não destinatário e um destinatário cujo texto cifrado falha ao abrir NÃO é exigida, e uma abertura de conteúdo fictícia NÃO DEVE ser obrigatória — isso imporia o custo da decifragem de conteúdo a todo transeunte. A garantia de tempo constante que de fato vale é a entre slots: dentro da passada de uma única chave privada, o laço percorre todos os slots com comparações em tempo constante, de modo que nada revele qual slot, se algum, aquela chave desembrulha.

Finalidade: profundidade de confirmação

A liquidação na Cardano é probabilística. Uma transação com um bloco de profundidade ainda pode ser orfanizada por um reorg curto; uma transação com muitos blocos de profundidade já liquidou com probabilidade esmagadora. Um verificador que classificasse como valid um registro com um único bloco de profundidade permitiria que um atacante reancorasse um registro contraditório em uma bifurcação concorrente e obtivesse um veredito de "valid" em ambos — quebrando silenciosamente a premissa de apenas-acréscimo sobre a qual repousa toda a prova.

Por isso, enquanto o registro permanece abaixo de um limiar de profundidade de confirmação, o verificador o reporta como pending, não failed. O limiar de uso geral RECOMENDADO é de ≥ 15 blocos (cerca de cinco minutos). O limiar é uma política do verificador, não uma constante do formato de fios: implantações que lidam com registros de alto valor ou de natureza probatória DEVEM elevá-lo em direção à finalidade rígida, e um verificador DEVE expor o limiar que utilizou para que os consumidores possam sobrepor uma política mais estrita. Um registro pending está bem formado e on-chain; ele apenas ainda não liquidou com profundidade suficiente, e pode resolver para valid em uma nova tentativa posterior.

A profundidade de confirmação, a altura do bloco e o horário do bloco são fatos afirmados pelo explorador que o verificador nunca fabrica. O vínculo com a referência da transação torna o conteúdo da transação livre de confiança, mas os fatos da cadeia a respeito dela não são deriváveis dos bytes — o CBOR da transação não carrega carimbo de tempo nem altura. A profundidade é calculada como (altura do tip do explorador que resolve) − (altura do bloco que inclui a transação) + 1, de modo que uma transação no bloco do tip tem profundidade exatamente 1; o horário do bloco é o carimbo de tempo POSIX (segundos inteiros, UTC) do slot do bloco que inclui a transação, retirado do campo de tempo do explorador, nunca recalculado pelo verificador. Como esses fatos repousam sobre a palavra do explorador, um verificador DEVERIA resolvê-los a partir de pelo menos dois exploradores independentes e expor qualquer divergência; implantações para as quais o horário do bloco tem peso decisivo — notarização legal, disputas de prazo — DEVEM conferi-lo de forma cruzada. O relatório carrega a profundidade resolvida ao lado do limiar contra o qual ela foi comparada, e o block_time (com block_slot quando disponível).

Estados de veredito

Um verificador conclui em um de quatro vereditos legíveis por máquina, cada um emparelhado um a um com um código de saída de processo, para que um chamador — um portão de CI, um monitor, um script — consiga distinguir uma falha atribuível ao registro de uma falha operacional transitória sem precisar analisar o relatório estruturado. O princípio que governa é a atribuição: condenar um registro exige evidência que os próprios bytes do registro — ou bytes atribuivelmente vinculados às suas referências — de fato forneçam. Nenhuma má conduta de provedor pode fabricar um failed.

VereditoSaídaSignificado
valid0toda verificação executada pelo verificador retornou ok; nenhuma questão de severidade error está presente.
failed1uma falha atribuível ao registro: o validador estrutural rejeitou os bytes, uma assinatura não verificou, um hash atribuível divergiu, a transação vinculada não carrega metadados sob o rótulo 309 (METADATA_NOT_FOUND), ou uma regra de deny-host disparou.
unverifiable2nenhum erro atribuível ao registro, mas uma verificação obrigatória não pôde rodar ou não pôde ser atribuída — a transação não resolveu, nenhuma resposta de provedor sobreviveu ao vínculo (TX_INTEGRITY_MISMATCH), ou conteúdo/texto cifrado comprometido não pôde ser obtido ou atribuído. O mesmo registro pode verificar como valid em uma nova tentativa ou sob um gateway diferente.
pending3estruturalmente bem formado e on-chain, mas abaixo do limiar de profundidade de confirmação (INSUFFICIENT_CONFIRMATIONS); pode liquidar. Nenhum resultado de um registro pendente pode ser apresentado como definitivo.

Falhas de runtime do host do verificador que não são atribuíveis ao registro usam códigos de saída 4 ou superiores e não correspondem a veredito algum.

Um veredito valid NÃO DEVE ser reportado quando qualquer questão de severidade error estiver presente; um registro PODE ser valid com uma lista warnings e/ou info não vazia. Nenhuma camada pode "suavizar" um erro, transformando-o em aviso para fazer um registro passar. Cada veredito é reservado para o seu próprio caso: o estado pending nunca é usado em substituição a valid ou failed, e uma falha atribuível ao provedor é unverifiable, nunca failed.

Um piso de comprometimento governa a disponibilidade: quando a conferência de conteúdo rodou, mas falhas de disponibilidade não deixaram nenhum comprometimento de conteúdo do registro de fato verificado, o veredito é unverifiable, nunca valid — um veredito valid significa que ao menos um comprometimento de conteúdo foi conferido. Os resultados de integridade não são afetados pelo piso: bytes atribuíveis que falham em um comprometimento produzem failed independentemente do que mais estivesse disponível.

Vínculo com o endereço de conteúdo e atribuição

O passo 8 (e, para o verificador do destinatário, a decifragem) busca bytes de gateways de armazenamento endereçados por conteúdo escolhidos pelo verificador — e os gateways não são confiáveis. A regra de veredito acima gira em torno de uma única pergunta que o verificador DEVE conseguir responder sobre cada fluxo de bytes buscado: esses bytes podem ser atribuídos à própria URI? Ambos os esquemas são endereçados por conteúdo, então podem:

  • ipfs:// — recalcular o CID sobre o conteúdo buscado (o multihash diretamente, no caso de um CID de codec bruto; digests bloco a bloco ao longo do caminho resolvido, no caso de um CID em forma de DAG).
  • ar:// — validar a transação Arweave assinada e recalcular a árvore de Merkle dos blocos contra seu data_root; no caso de um data item ANS-104, recalcular o deep-hash, verificar a assinatura do proprietário e conferir que o SHA-256 da assinatura é igual ao id da URI.

Bytes que satisfazem os próprios digests do registro não precisam de verificação de vínculo — o comprometimento do registro é pelo menos tão forte quanto o da camada de armazenamento. Onde o vínculo é aplicado, a atribuição decide o que uma divergência significa:

  • Bytes atribuíveis — vínculo verificado, ou fornecidos fora de banda por quem chama — são imputados ao registro quando falham em um comprometimento: URI_INTEGRITY_MISMATCH para o conteúdo do item (uma falha de integridade rígida, independentemente do que qualquer URI irmã contenha), a família MERKLE_* para uma lista de folhas, TAMPERED_CIPHERTEXT para um blob de texto cifrado atribuível. Veredito failed.
  • Bytes não atribuíveis — vínculo não verificado, ou verificado e falho — incriminam o provedor que serve, nunca o registro: URI_PROVIDER_INTEGRITY_MISMATCH (aviso). O verificador prossegue com as URIs e os gateways restantes; uma alegação que fique sem bytes atribuíveis termina em um resultado de disponibilidade (CONTENT_UNAVAILABLE, MERKLE_LEAVES_UNAVAILABLE, CIPHERTEXT_UNAVAILABLE), veredito unverifiable — exatamente como se nada tivesse sido buscado.

Esta é a contraparte, do lado do armazenamento, do vínculo com a referência da transação: um gateway mal-intencionado só pode degradar a disponibilidade, nunca o veredito. URI_INTEGRITY_MISMATCH e URI_PROVIDER_INTEGRITY_MISMATCH são, portanto, códigos distintos — o primeiro condena o registro, o segundo condena um provedor — e um verificador que os confundisse permitiria que um gateway hostil forjasse um failed. O recálculo do hash do texto claro pós-decifragem não precisa de qualificador de atribuição: o texto cifrado que abre sob o envelope autenticado é atribuído pelo próprio AEAD, de modo que uma divergência de hash do texto claro ali (URI_INTEGRITY_MISMATCH) é sempre atribuível ao registro e força failed.

O catálogo tipado de erros

Todo modo de falha resolve para um código de um único catálogo fechado. Os códigos seguem o estilo SCREAMING_SNAKE_CASE, e uma implementação em conformidade DEVE emitir exatamente essas cadeias — nunca o código interno em minúsculas de um parser, nunca uma mensagem em texto livre. Duas implementações em duas linguagens, alcançando a mesma entrada, emitem o mesmo código; a lista normativa completa é fixada byte a byte pela suíte de testes de conformidade, e o catálogo é imutável (códigos só são acrescentados por emenda).

Modelo de severidade

Toda questão carrega uma de três severidades, e a distinção é determinante:

  • error — invalida o veredito. Um resultado valid não pode coexistir com nenhum error.
  • warning — uma anomalia de execução não fatal (um único gateway falhou, uma lista de folhas estava apenas parcialmente disponível) que não impede o valid.
  • info — uma não verificação deliberada: um aspecto que o verificador escolheu não avaliar (um campo fora de seu perfil, um algoritmo opcional não reconhecido). Uma entrada de info não é um erro suavizado e nunca é usada como tal.

Um código fica à parte: INSUFFICIENT_CONFIRMATIONS mapeia para o veredito pending, e não para uma severidade, porque o registro está bem formado e apenas aguarda a liquidação.

Famílias de erros

O catálogo se agrupa em famílias. Um conjunto representativo — não exaustivo — de códigos:

FamíliaSeveridadeCódigos representativos
CBOR malformado / não canônicoerrorMALFORMED_CBOR, CHUNK_TOO_LARGE
EsquemaerrorSCHEMA_TYPE_MISMATCH, SCHEMA_MISSING_REQUIRED, SCHEMA_UNKNOWN_FIELD, SCHEMA_EMPTY_RECORD
Algoritmo não suportadoerrorUNSUPPORTED_HASH_ALG, UNSUPPORTED_AEAD_ALG, UNSUPPORTED_KEM_ALG, UNSUPPORTED_MERKLE_COMMIT_ALG
Explorador / metadadoserror / pendingTX_NOT_FOUND, PROVIDER_UNAVAILABLE, TX_INTEGRITY_MISMATCH (→ unverifiable), METADATA_NOT_FOUND (→ failed); INSUFFICIENT_CONFIRMATIONS (→ pending)
Assinaturaerror / infoMALFORMED_SIG_COSE_SIGN1, SIGNER_KEY_UNRESOLVED, SIGNATURE_INVALID, WALLET_ADDRESS_MISMATCH; SIGNATURE_UNSUPPORTED (info)
Cifragem / KEM / embrulhoerrorKEM_EPK_LENGTH_MISMATCH, KEM_CT_LENGTH_MISMATCH, WRAP_LENGTH_MISMATCH, ENC_SLOTS_DUPLICATE_KEM_MATERIAL, ENC_SLOTS_TOO_MANY, ENC_ENVELOPE_TOO_LARGE, ENC_REQUIRES_CONTENT_HASH
Resultado da decifragemerrorWRONG_DECRYPTION_INPUT_SHAPE, WRONG_RECIPIENT_KEY, TAMPERED_HEADER, TAMPERED_CIPHERTEXT, KDF_DERIVATION_FAILED
URI / conteúdoerror / warningINVALID_URI, URI_TARGET_FORBIDDEN, URI_INTEGRITY_MISMATCH, CONTENT_UNAVAILABLE (→ unverifiable), CIPHERTEXT_UNAVAILABLE (→ unverifiable); URI_PROVIDER_INTEGRITY_MISMATCH, URI_FETCH_FAILED (avisos)
Compromisso de lista Merkleerror / warning / infoMERKLE_ROOT_MISMATCH, SCHEMA_MERKLE_LEAF_COUNT_MISMATCH; MERKLE_LEAVES_UNAVAILABLE (dupla); MERKLE_UNSUPPORTED (dupla)
Independência de serviçoerrorSERVICE_INDEPENDENCE_VIOLATION

Os códigos de rede/política (TX_NOT_FOUND, PROVIDER_UNAVAILABLE, CONTENT_UNAVAILABLE, CIPHERTEXT_UNAVAILABLE) — e o TX_INTEGRITY_MISMATCH, cuja divergência é comprovável contra os provedores, e não contra o registro — têm severidade error na lista de questões (eles bloqueiam um veredito valid), mas não são atribuíveis ao registro, de modo que mapeiam para unverifiable, nunca failed. O URI_PROVIDER_INTEGRITY_MISMATCH é o aviso por busca sob o mesmo princípio. Alguns poucos códigos carregam severidade duplaENC_UNSUPPORTED, MERKLE_UNSUPPORTED, OUT_OF_PROFILE_SKIPPED e MERKLE_LEAVES_UNAVAILABLE —, lidos como info/warning por padrão e promovidos a error em um contexto estrito (o papel de destinatário, a escalada de apenas-merkle, o modo estrito de ponta a ponta ou o piso de comprometimento).

O caminho do destinatário é a família mais precisa em termos de diagnóstico. Para um chamador local confiável, uma decifragem malsucedida resolve para um de três códigos internos: WRONG_RECIPIENT_KEY significa que nenhum slot aceitou a chave fornecida (nenhuma chave de conteúdo chegou a ser recuperada); TAMPERED_HEADER significa que uma chave foi recuperada, mas a chave de conteúdo candidata não reproduziu slots_mac sobre slots_hash (um slot, um campo de cabeçalho ou o próprio slots_mac foi alterado); TAMPERED_CIPHERTEXT significa que o conjunto de slots estava íntegro, mas a tag AEAD do conteúdo falhou depois que a chave foi recuperada. Os três são estruturalmente distinguíveis para esse chamador local, e a fronteira entre eles não vaza nenhum material de chave. Para um chamador externo não confiável, os três se reduzem à única falha genérica descrita acima, indistinguível pela forma da resposta. Sob o modelo de temporização, um retorno antecipado e permitido na não correspondência separa WRONG_RECIPIENT_KEY (um não destinatário) dos dois resultados de adulteração do lado do destinatário, que não carregam nenhuma distinção adicional entre si — de modo que a precisão diagnóstica nunca se torna um oráculo seletivo de slot ou de chave.

Como os códigos se mapeiam nos quatro vereditos

Um código emitido pelo validador estrutural significa que os bytes do registro não estão em conformidade. O verificador público interrompe imediatamente o relatório com o veredito failed — saída 1 — e a lista de questões do validador, sem executar nenhum trabalho adicional de cadeia ou criptografia. Um código emitido somente depois que a validação estrutural passou — uma assinatura que não verificou, um hash atribuível que não conferiu, METADATA_NOT_FOUND na transação vinculada — é igualmente failed: cada um é atribuível ao registro, evidência que os próprios bytes do registro fornecem.

Uma falha transitória ou atribuível ao provedor é um veredito diferente: conteúdo que não pôde ser buscado ou atribuído, um explorador que estava inacessível, ou um provedor que serviu bytes que falham no vínculo com a referência da transação mapeiam todos para unverifiable — saída 2 —, porque nenhum é culpa do registro e o mesmo registro pode verificar como valid em uma nova tentativa. A distinção que o código de saída preserva é, portanto, tripla entre os estados de falha: failed atribuível ao registro (1), unverifiable operacional ou atribuível ao provedor (2) e pending abaixo do limiar (3).

Alguns poucos códigos carregam uma severidade que depende do contexto. Um verificador que lê um registro mais rico do que seu perfil declarado (por exemplo, um verificador de apenas hash que encontra um item selado) reporta o campo extra como info em um contexto de exibição e ainda assim valida a afirmação de hash, ou como error em um contexto de auditoria estrita de ponta a ponta. Da mesma forma, um algoritmo de assinatura opcional não reconhecido é info — a afirmação de existência do conteúdo não depende dele — de modo que uma prova pública de apenas hash permanece valid mesmo quando uma assinatura informativa não pode ser verificada.

A independência de serviço não é opcional

A verificação nunca volta a contatar quem publicou. Toda chamada de saída que um verificador em conformidade faz é dirigida a infraestrutura escolhida pelo operador — um explorador Cardano para a transação e gateways de armazenamento endereçado por conteúdo para quaisquer bytes ar:// ou ipfs://. Isso é imposto estruturalmente, não é uma promessa em comentário de código:

  • Toda chamada de rede passa por um único invólucro de saída que registra url, method, status, contagem de bytes e finalidade de cada chamada — sucesso, falha e nova tentativa por igual — em uma trilha de auditoria obrigatória no relatório. Um verificador que não consegue produzir essa trilha não consegue provar sua independência.
  • Esse invólucro aceita uma lista de hosts proibidos (deny-host) fornecida pela implantação e faz falhar de imediato qualquer chamada a um host correspondente, com SERVICE_INDEPENDENCE_VIOLATION. A lista é uma entrada do operador — uma suíte de conformidade a preenche com os próprios domínios de quem implementa — não uma constante do formato de fios do Label 309.
  • Um arcabouço de conformidade executa o verificador contra transações de fixture congeladas em uma rede onde os próprios domínios do operador não resolvem para lugar algum, e verifica que o verificador ainda retorna valid. A verificação é feita na camada de rede do sistema operacional, não vasculhando o código-fonte — um verificador que alcançasse um host proibido por um IP fixo no código passaria em uma varredura de fonte, mas falharia neste teste.

O verificador precisa de um explorador Cardano acessível e de nada específico da implementação. Gateways de conteúdo, uma chave privada de destinatário e uma lista de folhas off-chain são entradas opcionais que habilitam, respectivamente, as verificações de conteúdo, de destinatário e de Merkle. Nenhuma delas é um serviço que o padrão nomeie, e nenhuma delas é quem publicou.

Páginas relacionadas

  • O registro — o formato de fios contra o qual o validador estrutural confere: o rótulo 309, a forma do mapa, a remontagem dos fragmentos e o esquema CDDL.
  • Assinaturas — a construção COSE_Sign1 no nível do registro, a carga útil com separação de domínio e as regras estritas de verificação Ed25519.
  • PoE selada — o envelope de cifragem, os slots de chave do destinatário e o desembrulho que o verificador do destinatário realiza.