Dies ist eine informative Übersetzung. Maßgeblich ist die englische Fassung; sie hat im Zweifel Vorrang. Zur englischen Fassung

Verifizierung

Die drei Verifizierer-Rollen von Label 309, die Verdikt-Zustände, die Bestätigungstiefe und der typisierte Fehlerkatalog, also wie jede prüfende Stelle allein aus öffentlicher Infrastruktur zur selben Antwort gelangt.

Label 309 wird verifiziert, nicht behauptet. Wer veröffentlicht, verankert einen Inhalts-Hash unter label 309 in der Cardano-Blockchain; von da an steht der Anspruch allein auf seinen eigenen Bytes, und jede Stelle, die über die Transaktionsreferenz verfügt, kann ihn überprüfen. Diese Seite beschreibt, wie diese Prüfung abläuft: die drei Verifizierer-Rollen, was jede einzelne anfasst und was nicht, die Verdikt-Zustände, die sie ausgeben, die Bestätigungstiefe, unterhalb derer ein Verdikt vorläufig bleibt, und den typisierten Fehlerkatalog, der dafür sorgt, dass zwei unabhängige Implementierungen bei derselben Eingabe denselben Fehler melden.

Die entscheidende Eigenschaft ist die Dienstunabhängigkeit. Ein konformer Verifizierer erreicht sein Verdikt allein über die öffentliche Chain, einen vom Verifizierer selbst gewählten Cardano-Explorer oder ein entsprechendes Gateway und, für Inhalts- und versiegelte Ansprüche, über inhaltsadressierte Speicher-Gateways, die der Verifizierer ebenfalls selbst auswählt. Er kontaktiert nie die veröffentlichende Stelle. Der Standard nennt keinen bestimmten Anbieter; das Gateway ist eine Eingabe, die der Betreiber bereitstellt.

Drei Rollen, jede eine strikte Erweiterung

Die Verifizierung ist in Schichten aufgebaut. Jede Rolle leistet alles, was die Rolle über ihr leistet, und fügt eine Fähigkeit hinzu. Eine niedrigere Rolle ist für sich genommen ein vollständiger, nützlicher Verifizierer, sie weist schlicht weniger nach.

RolleFügt hinzuFasst an
Struktureller ValidatorSchema- und Domänenkonformität über die Bytes des Datensatzesnichts, eine reine Funktion
Öffentlicher VerifiziererChain-Auflösung, On-Chain-Aufnahme, Signaturprüfungeneinen Cardano-Explorer und Inhalts-Gateways
Empfänger-VerifiziererProbeentschlüsselung versiegelter Nutzdaten, Neuberechnung des Klartext-Hashesden eigenen privaten Schlüssel des Verifizierers

Struktureller Validator: eine reine Funktion über die Bytes

Der strukturelle Validator ist eine einzige Funktion von einer Byte-Zeichenkette zu einem Ergebnis. Er führt keinerlei I/O, keine kryptografischen Signaturprüfungen und keine Entschlüsselung durch. Er sieht nie ein Netzwerk, eine Transaktion oder einen Schlüssel. Bei gleicher Eingabe liefert er jedes Mal, überall, dieselbe Ausgabe. Genau das erlaubt es, ihn vor der Übermittlung im Werkzeugkasten der veröffentlichenden Stelle, in einem Drittanbieter-Indexer oder in einem Archivierungswerkzeug laufen zu lassen, das die langfristige Wohlgeformtheit bestätigt, und das alles ohne Server.

Seine Verarbeitungskette ist festgelegt:

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.

Der Validator ist profilunabhängig: Er parst das vollständige v1-Schema, unabhängig davon, auf welcher Teilmenge ein nachgelagerter Verifizierer tätig werden will. Fehler lassen den Datensatz scheitern; Warnungen und Info-Einträge werden ausgewiesen, lassen ihn aber gültig. Entscheidend ist: Er bestätigt die Form eines COSE_Sign1, also ein Array aus vier Elementen, abgetrennte (null) Nutzdaten, einen wohlgeformten geschützten Header, verifiziert aber nie die Signatur, und er verwirft einen Datensatz nie allein deshalb, weil das Signaturverfahren eines ist, das er nicht kennt (das wird mit SIGNATURE_UNSUPPORTED gekennzeichnet, Schweregrad info, und der Datensatz bleibt gültig). Die Signatur zu verifizieren ist Aufgabe des öffentlichen Verifizierers. Welches Schema dieser Durchlauf durchsetzt, ist unter Der Datensatz beschrieben.

Öffentlicher Verifizierer: Chain, Aufnahme und Signaturen

Der öffentliche Verifizierer legt die Chain über den strukturellen Validator. Bei einer gegebenen Cardano-Transaktionsreferenz tut er Folgendes:

  1. Er löst einen vom Verifizierer gewählten Explorer auf. Die Explorer-Kette ist eine Eingabe; der Verifizierer probiert sie der Reihe nach durch und ruft dabei das rohe On-Chain-Transaktions-CBOR ab – nie die Metadaten-JSON-Projektion des Explorers. Die JSON-Sicht fasst CBOR-Haupttypen zu einer JSON-Union zusammen und verwirft die Reihenfolge der Map-Schlüssel, die Rahmung mit definiter Länge sowie die Unterscheidung zwischen Bytes und Text, sodass ein Verifizierer, der daraus neu kodierte, die byte-exakte Signiereingabe nicht reproduzieren könnte und jede Signatur eines konformen Datensatzes scheitern würde. Die negative Antwort eines einzelnen Anbieters ist nicht chain-maßgeblich – die Transaktion kann on-chain und diesem Anbieter lediglich unbekannt sein –, sodass der Verifizierer jeden verbleibenden Anbieter konsultiert, bevor er TX_NOT_FOUND ausgibt; ist jeder Anbieter nicht erreichbar, gibt er PROVIDER_UNAVAILABLE aus.
  2. Er bindet die abgerufenen Bytes an die Transaktionsreferenz. Bevor der Verifizierer irgendetwas aus einer abgerufenen Transaktion liest, berechnet er blake2b-256 über die abgerufenen Transaktionskörper-Bytes neu – per Ledger-Definition die Transaktions-ID – und weist die Antwort bei jeder Abweichung vom angefragten Hash zurück. Danach berechnet er blake2b-256 über die abgerufenen Auxiliary-Data-Bytes neu und weist bei jeder Abweichung vom nun verifizierten auxiliary_data_hash des Körpers zurück. Beide Digests werden über die Bytes exakt so, wie sie abgerufen wurden berechnet, nie über eine Neukodierung. Eine Antwort, die eine der beiden Prüfungen nicht besteht, trägt nachweislich falsche Bytes und wird verworfen; liefert kein Anbieter eine Antwort, die die Bindung übersteht, trägt der Bericht TX_INTEGRITY_MISMATCH. Nach diesem Schritt ist jedes Byte des Datensatzes und der umgebenden Transaktion kryptografisch an den vom Aufrufer gelieferten Hash gebunden – kein Explorer kann den Datensatz austauschen, ändern oder abschneiden, ohne ein blake2b-256-Second-Preimage zu erzeugen.
  3. Er entpackt die Auxiliary Data. Das Ledger der Conway-Ära lässt drei Auxiliary-Data-Kodierungen zu, alle gültig: eine nackte ungetaggte Metadaten-Map, ein zweielementiges [ metadata, scripts ]-Array und eine Tag-259-Map mit den Metadaten unter Schlüssel 0. Der Verifizierer MUSS alle drei akzeptieren und ausschließlich anhand des CBOR-Haupttyps und -Tags auf oberster Ebene unterscheiden – ein Tag-259-Wert ist die Form mit Schlüssel-Map, ein ungetaggtes Array ist die zweielementige Form, und eine ungetaggte Map ist stets die Metadaten-Map selbst. Er DARF die Schlüssel einer Map NICHT prüfen, um die Form zu erraten; jede andere Form auf oberster Ebene oder jeder andere Tag als 259 ist MALFORMED_CBOR. Trägt die gebundene Transaktion keine label-309-Metadaten, gibt der Verifizierer METADATA_NOT_FOUND aus – ein dem Datensatz zurechenbares Ergebnis, denn die gebundene Transaktion selbst beweist die Abwesenheit: Kein Anbieter hätte die Metadaten entfernen können, ohne die Bindung zu verfehlen.
  4. Er setzt das Chunk-Array über den gesamten Körper wieder zusammen. Der Wert unter label 309 ist der kanonisch CBOR-kodierte Datensatzkörper, aufgeteilt in ein Array von Byte-Zeichenketten mit jeweils ≤ 64 Byte. Der Verifizierer verkettet die Elemente byteweise in ihrer Reihenfolge und gibt die rohen Bytes zurück, ohne sie neu zu kodieren, sodass die kanonische CBOR-Prüfung eine nichtkonforme On-Chain-Kodierung weiterhin erkennen kann.
  5. Er validiert strukturell den wieder zusammengesetzten Körper (die Rolle über ihm). Eine Ablehnung durch den Validator schließt den Bericht mit dem Verdikt failed kurz.
  6. Er prüft die Bestätigungstiefe (siehe unten). Eine Transaktion unterhalb des Schwellenwerts hält hier mit dem Verdikt pending an.
  7. Er verifiziert jede Signatur auf Datensatzebene unter striktem Ed25519. Er entschlüsselt nicht. Die Auflösung der Signatur, die domänengetrennten Nutzdaten und die strikten Verifizierungsregeln sind unter Signaturen festgelegt.
  8. Er ruft Inhalt ab und prüft Hashes, wobei er den Datensatz nur für Bytes zur Rechenschaft zieht, die er der eigenen Inhaltsadresse einer URI zurechnen kann (siehe unten). Er entschlüsselt nicht.

Warum rohes CBOR, nicht JSON

Eine Signatur wird über das byte-exakte kanonische CBOR des Datensatzkörpers berechnet. Eine JSON-Projektion von Metadaten ist konstruktionsbedingt verlustbehaftet und kann nicht verlustfrei zu diesen Bytes zurückführen. Ein erneutes Kodieren aus JSON bricht jede Signatur eines konformen Datensatzes. Das rohe Transaktions-CBOR ist die einzige maßgebliche Eingabe für jede kryptografische Prüfung; eine JSON-Sicht dient der Darstellung für Menschen, nachdem die Verifizierung bereits bestanden wurde.

Empfänger-Verifizierer: entschlüsseln und neu berechnen

Der Empfänger-Verifizierer ist ein öffentlicher Verifizierer, der zusätzlich einen privaten Schlüssel besitzt. Bei einem versiegelten Eintrag, der an ihn adressiert ist, entschlüsselt er probeweise die On-Chain-Schlüsselslots mit seinem Schlüssel, gewinnt bei Erfolg den Inhaltsschlüssel zurück, entschlüsselt den Chiffretext und berechnet anschließend die Klartext-Hashes neu, um sie gegen die On-Chain-Verpflichtung zu prüfen. So schließt sich der Kreis zwischen den verschlüsselten Bytes und dem Anspruch auf die Existenz des Inhalts. Da jeder versiegelte Eintrag mindestens einen Inhalts-Hash-Eintrag trägt, hat diese Neuberechnung stets etwas Konkretes zum Vergleich. Der versiegelte Umschlag, die Schlüsselslots und die Konstruktion zum Entpacken sind unter Versiegelte PoE festgelegt.

Bevor der Empfänger ein KEM- oder AEAD-Primitive anfasst, wendet er erneut dieselben Form- und Ressourcenprüfungen des Umschlags an, die der strukturelle Validierer bereits ausgeführt hat, und weist zuerst einen strukturell ungültigen oder übergroßen Umschlag zurück. Zwei dieser vorgelagerten Schutzmaßnahmen sind deployment-festgelegte Ressourcengrenzen, keine Wire-Felder: Die Referenzgrenzen sind MAX_SLOTS = 1024 Slots und 65536 Bytes für den dekodierten enc-Umschlag, beide weit über der ~16-KiB-Metadatengrenze von Cardano, die jeden ehrlichen Datensatz deckelt, sodass ein Datensatz, der eine der beiden überschreitet, fehlgeformt ist und vor dem Lauf eines einzigen Primitives mit ENC_SLOTS_TOO_MANY oder ENC_ENVELOPE_TOO_LARGE zurückgewiesen wird. Deployments DÜRFEN sie verschärfen.

Eine Formprüfung ist sicherheitstragend: Das Kapselungsmaterial MUSS innerhalb eines slots[] eindeutig sein, also alle epk-Werte bei x25519 oder alle kem_ct-Werte bei mlkem768x25519. Eine Dublette innerhalb des Datensatzes wird mit ENC_SLOTS_DUPLICATE_KEM_MATERIAL zurückgewiesen, bevor irgendein KEM- oder AEAD-Primitive läuft, denn ein wiederholtes epk/kem_ct würde die Eindeutigkeit des Slot-Schlüssels brechen, auf die sich der Null-Nonce-wrap stützt. Schlüsselwiederverwendung über Datensätze oder Schlüssel hinweg ist eine Erzeugerpflicht und nicht verifizierer-erkennbar; nur die Dublette innerhalb des Datensatzes ist es. Alle drei Prüfungen sind strukturell: Der Validierer setzt sie bei jedem Datensatz durch (die Codes für doppeltes Material, Slot-Anzahl und dekodierten Umschlag sind Part-A-Codes); der Empfänger führt sie schlicht als Verteidigung in der Tiefe erneut aus.

Das Entpacken selbst sind zwei kryptografische Schritte, die der Empfänger aus dem Umschlag reproduziert, nie aus einer Nebeneingabe. Zuerst berechnet er den Transkript-Hash der Slots slots_hash einmal, vor der Schleife, und hält ihn über jeden Slot konstant: slots_hash = SHA-256("cardano-poe-slots-transcript-v1" || canonicalEncode(SLOTS_TRANSCRIPT)), wobei das Transkript die Header-Felder, die On-Wire-Slot-Menge (jedes Slot-Feld ein einzelner Byte-String – es gibt keine Stückelung pro Feld zu normalisieren) und den Hash-Anspruch des Elements über hashes_hash festschreibt. Die Bindung von hashes_hash ist es, die dem Empfänger erlaubt, allein aus On-Chain-Bytes zu bestätigen, dass der Umschlag für genau diesen Hash-Anspruch versiegelt wurde – noch vor jedem Chiffretext-Abruf; ein Umschlag, der auf ein Element mit einer anderen hashes-Map gespleißt wurde, scheitert am MAC. Er iteriert alle Slots ohne vorzeitigen Abbruch; ein Slot wird nur dann akzeptiert, wenn der Inhaltsschlüssel, den er ergibt, auch den On-Wire-slots_mac über diesen konstanten slots_hash reproduziert. Die Annahme bezieht zudem ein geheimnisunabhängiges Gültigkeitsbit ein: Auf dem klassischen Pfad setzt ein Slot, der das gemeinsame X25519-Geheimnis auf den Nullbyte-Wert treiben soll, dieses Bit auf falsch (ein Konstantzeitvergleich gegen 0^32), der KEK wird in konstanter Zeit auf einen aus 0^32 abgeleiteten Dummy ausgewählt, sodass die Schleife identische Arbeit leistet, und das Bit steuert die Annahme des Slots: Ein Slot mit ungültigem ECDH kann nie öffnen, unabhängig von seinem Wrap oder MAC. Sowohl das Öffnen des Wrap als auch das spätere Öffnen des Inhalts sind atomar: Bei einem Fehlschlag des AEAD-Tags geben sie keinen Klartext zurück, und der Kandidat, den sie zurückreichen (der umhüllte Schlüssel oder der Inhalts-Klartext), ist ein fester oder pseudozufälliger Dummy, der vom fehlgeschlagenen Chiffretext unabhängig ist; nie wird unverifizierter Klartext freigegeben.

Ein Empfängerschlüssel DARF rechtmäßig mehr als einen Slot treffen: Ein Erzeuger darf denselben Inhaltsschlüssel an denselben Empfänger in mehreren Slots versiegeln, jeweils mit frischem KEM-Material pro Slot, um die Empfängeranzahl aufzufüllen, eine gültige Datenschutztechnik und verschieden von der Ablehnung doppelten Kapselungsmaterials, die allein bei einem identischen epk/kem_ct greift. Der Verifizierer wählt den Schlüssel des ersten Treffers und DARF NICHT allein deshalb ablehnen, weil mehrere Slots getroffen haben. Die einzige Anomalie, die er ablehnen MUSS, sind zwei treffende Slots, die unterschiedliche Inhaltsschlüssel wiederherstellen (in konstanter Zeit verglichen): Die Schleife führt ein cek_conflict-Bit mit und fördert den einzelnen generischen Fehlschlag zutage, falls irgendein späterer Treffer einen Schlüssel ergibt, der vom ausgewählten abweicht. Das ist Verteidigung in der Tiefe: Unter dem Commitment auf die Slot-Menge ist ein Treffer mit abweichendem Schlüssel bereits unmöglich, sodass die Prüfung schlicht „fail closed“ fällt.

Dann leitet er auf dem zurückgewonnenen Inhaltsverschlüsselungsschlüssel den Inhaltsschlüssel ab (ein HKDF-Blatt dieses Schlüssels, gesalzen mit enc.nonce) und öffnet den Chiffretext des segmentierten STREAM Chunk für Chunk, wobei er den Tag jedes Chunks verifiziert, bevor er dessen Klartext freigibt. Die AAD pro Chunk ist leer: Aller Header-Kontext ist bereits transitiv über slots_mac an den Schlüssel gebunden, sodass das Umkippen eines Header-Felds ändert, was der Empfänger ableitet, und der Stream sich nicht öffnen lässt. Eine Abschneidung wird durch das Final-Flag erkannt – ein fehlender finaler Chunk, Daten danach, ein Final-Flag auf einem nicht-finalen Chunk oder ein zu kurzer nicht-finaler Chunk scheitern allesamt als TAMPERED_CIPHERTEXT. Das segmentierte Format erlegt keine kryptografische Nutzlast-Obergrenze auf (der 88-Bit-Chunk-Zähler lässt 2^88 Chunks zu); ein praktisches Maximum ist eine Denial-of-Service-Richtlinie des Deployments, inkrementell durchgesetzt, während der Stream gelesen wird. Auf dem Passphrase-Pfad liest der Empfänger zuerst den führenden 32-Byte-Commitment-Header und vergleicht ihn in konstanter Zeit, bevor er irgendeinen Chunk öffnet.

Beim Empfängerpfad zahlt sich die Präzision des Fehlerkatalogs aus: Er unterscheidet den Fall, in dem kein Slot diesen Schlüssel angenommen hat (falscher Empfänger), vom Fall, in dem ein Slot den Schlüssel angenommen hat, aber das Slot-Set oder der Chiffretext manipuliert wurde. Das sind unterschiedliche Sicherheitsaussagen, und sie tragen unterschiedliche Codes (siehe unten). Ein nicht vertrauenswürdiger Aufrufer erhält jedoch genau eine generische Fehlschlag-Form, unabhängig von der Ursache, also kein Slot geöffnet, das Slot-Set wurde manipuliert oder das Inhalts-Tag scheiterte, und die Antwort verrät nie, welcher Fall eingetreten ist, noch welcher Slot getroffen hat; die typisierten Codes sind eine interne Diagnose allein für einen vertrauenswürdigen lokalen Aufrufer.

Das Timing folgt einem expliziten Modell. Der Verifizierer DARF an der Kein-Treffer-Prüfung zurückkehren, bevor die Inhaltsentschlüsselung beginnt, sodass ein Nicht-Empfänger und ein Empfänger messbar unterschiedlich lange brauchen. Dieser Unterschied verrät allein Empfänger-versus-Nicht-Empfänger, nie welcher Slot getroffen hat, und kein Schlüsselmaterial. Ein einheitliches Timing zwischen einem Nicht-Empfänger und einem Empfänger, dessen Chiffretext nicht aufgeht, ist NICHT erforderlich, und ein Dummy-Inhaltsöffnen DARF NICHT vorgeschrieben werden, denn es würde jedem Passanten die Kosten der Inhaltsentschlüsselung auferlegen. Die Konstantzeit-Garantie, die gilt, ist die Über-alle-Slots-Garantie: Innerhalb des Durchlaufs eines einzelnen privaten Schlüssels läuft die Schleife mit Konstantzeitvergleichen über alle Slots, sodass nichts darüber durchsickert, welchen Slot dieser Schlüssel entpackt, falls überhaupt einen.

Finalität: die Bestätigungstiefe

Die Cardano-Abwicklung ist probabilistisch. Eine Transaktion, die einen Block tief liegt, kann durch eine kurze Reorganisation noch verwaisen; eine Transaktion, die viele Blöcke tief liegt, hat sich mit überwältigender Wahrscheinlichkeit gefestigt. Ein Verifizierer, der einen nur einen Block tiefen Datensatz als valid einstufen würde, ließe einem Angreifer die Möglichkeit, einen widersprüchlichen Datensatz auf einer konkurrierenden Fork neu zu verankern und für beide ein "valid"-Verdikt einzusammeln, womit die Annahme des reinen Anhängens, auf der der gesamte Nachweis beruht, stillschweigend zerbräche.

Deshalb meldet ein Verifizierer den Datensatz als pending, nicht als failed, solange er unterhalb einer Schwelle für die Bestätigungstiefe liegt. Die EMPFOHLENE Schwelle für den allgemeinen Gebrauch beträgt ≥ 15 Blöcke (rund fünf Minuten). Die Schwelle ist eine Richtlinie des Verifizierers, keine Wire-Konstante: Einsätze, die hochwertige oder beweisrelevante Datensätze behandeln, SOLLTEN sie in Richtung harter Finalität anheben, und ein Verifizierer MUSS die von ihm verwendete Schwelle ausweisen, damit Verbraucher darüber eine strengere Richtlinie legen können. Ein pending-Datensatz ist wohlgeformt und on-chain; er hat sich lediglich noch nicht tief genug gefestigt und kann sich bei einem späteren erneuten Versuch zu valid auflösen.

Bestätigungstiefe, Blockhöhe und Blockzeit sind vom Explorer behauptete Tatsachen, die der Verifizierer nie fabriziert. Die Bindung an die Transaktionsreferenz macht den Inhalt der Transaktion vertrauenslos, aber die Chain-Tatsachen über sie sind nicht aus den Bytes ableitbar – das Transaktions-CBOR trägt weder Zeitstempel noch Höhe. Die Tiefe wird als (Tip-Höhe des auflösenden Explorers) − (Höhe des einschließenden Blocks) + 1 berechnet, sodass eine Transaktion im Tip-Block exakt die Tiefe 1 hat; die Blockzeit ist der POSIX-Zeitstempel (ganze Sekunden, UTC) des Slots des einschließenden Blocks, dem Zeitfeld des Explorers entnommen, nie vom Verifizierer neu berechnet. Weil diese Tatsachen auf dem Wort des Explorers beruhen, SOLLTE ein Verifizierer sie aus mindestens zwei unabhängigen Explorern auflösen und jede Abweichung sichtbar machen; Einsätze, für die die Blockzeit beweistragend ist – rechtliche Beurkundung, Fristenstreitigkeiten –, MÜSSEN sie gegenprüfen. Der Bericht trägt die aufgelöste Tiefe neben der Schwelle, gegen die sie verglichen wurde, sowie block_time (mit block_slot, sofern verfügbar).

Verdikt-Zustände

Ein Verifizierer schließt mit einem von vier maschinenlesbaren Verdikten ab, jedes eins-zu-eins mit einem Prozess-Exit-Code gepaart, sodass eine aufrufende Stelle, etwa ein CI-Gate, ein Monitor oder ein Skript, ein dem Datensatz zurechenbares Scheitern von einem vorübergehenden betrieblichen Scheitern unterscheiden kann, ohne den strukturierten Bericht parsen zu müssen. Der leitende Grundsatz ist die Zurechenbarkeit: Einen Datensatz zu verurteilen, erfordert Beweise, die die eigenen Bytes des Datensatzes – oder Bytes, die zurechenbar an seine Referenzen gebunden sind – tatsächlich liefern. Kein Fehlverhalten eines Anbieters kann ein failed fabrizieren.

VerdiktExitBedeutung
valid0jede vom Verifizierer ausgeführte Prüfung lieferte ok; kein Problem mit Schweregrad error liegt vor.
failed1ein dem Datensatz zurechenbares Scheitern: der strukturelle Validator hat die Bytes abgelehnt, eine Signatur ließ sich nicht verifizieren, ein zurechenbarer Hash stimmte nicht überein, die gebundene Transaktion trägt keine label-309-Metadaten (METADATA_NOT_FOUND) oder eine Deny-Host-Regel hat ausgelöst.
unverifiable2kein dem Datensatz zurechenbarer Fehler, aber eine erforderliche Prüfung ließ sich nicht ausführen oder nicht zurechnen – die Transaktion löste nicht auf, keine Anbieterantwort überstand die Bindung (TX_INTEGRITY_MISMATCH), oder festgelegter Inhalt/Chiffretext ließ sich nicht beschaffen oder zurechnen. Derselbe Datensatz kann bei einem erneuten Versuch oder unter einem anderen Gateway valid verifizieren.
pending3strukturell wohlgeformt und on-chain, aber unterhalb der Schwelle für die Bestätigungstiefe (INSUFFICIENT_CONFIRMATIONS); kann sich noch festigen. Kein Ergebnis eines ausstehenden Datensatzes darf als endgültig dargestellt werden.

Laufzeitfehler auf der Verifizierer-Host-Seite, die dem Datensatz nicht zurechenbar sind, verwenden Exit-Codes 4 und höher und entsprechen keinem Verdikt.

Ein valid-Verdikt DARF NICHT gemeldet werden, wenn ein Problem mit Schweregrad error vorliegt; ein Datensatz DARF valid sein mit einer nichtleeren Liste von warnings und/oder info. Keine Schicht darf einen Fehler zu einer Warnung "abmildern", um einen Datensatz durchzulassen. Jedes Verdikt ist seinem eigenen Fall vorbehalten: pending tritt nie an die Stelle von valid oder failed, und ein dem Anbieter zurechenbares Scheitern ist unverifiable, nie failed.

Eine Commitment-Untergrenze regelt die Verfügbarkeit: Lief die Inhaltsprüfung, aber ließen Verfügbarkeitsfehler kein tatsächlich verifiziertes Inhalts-Commitment des Datensatzes übrig, ist das Verdikt unverifiable, nie valid – ein valid-Verdikt bedeutet, dass mindestens ein Inhalts-Commitment geprüft wurde. Integritätsergebnisse bleiben von der Untergrenze unberührt: Zurechenbare Bytes, die ein Commitment nicht erfüllen, ergeben failed, ungeachtet dessen, was sonst verfügbar war.

Inhaltsadressen-Bindung und Zurechenbarkeit

Schritt 8 (und, beim Empfänger-Verifizierer, die Entschlüsselung) ruft Bytes aus inhaltsadressierten Speicher-Gateways ab, die der Verifizierer gewählt hat – und Gateways sind nicht vertrauenswürdig. Die obige Verdikt-Linie dreht sich um eine einzige Frage, die der Verifizierer über jeden abgerufenen Byte-Strom beantworten können MUSS: Lassen sich diese Bytes der URI selbst zurechnen? Beide Schemata sind inhaltsadressiert, also können sie es:

  • ipfs:// – die CID über den abgerufenen Inhalt neu berechnen (den Multihash direkt bei einer CID mit Raw-Codec; Block-für-Block-Digests entlang des aufgelösten Pfades bei einer CID in DAG-Form).
  • ar:// – die signierte Arweave-Transaktion validieren und den Chunk-Merkle-Baum gegen ihren data_root neu berechnen; bei einem ANS-104-Data-Item den Deep-Hash neu berechnen, die Owner-Signatur verifizieren und prüfen, dass der SHA-256 der Signatur der ID in der URI gleicht.

Bytes, die die eigenen Digests des Datensatzes erfüllen, brauchen keine Bindungsprüfung – das Commitment des Datensatzes ist mindestens so stark wie das der Speicherschicht. Wo die Bindung angewendet wird, entscheidet die Zurechenbarkeit, was eine Abweichung bedeutet:

  • Zurechenbare Bytes – Bindung verifiziert oder vom Aufrufer außerhalb des Bandes geliefert – werden dem Datensatz angerechnet, wenn sie ein Commitment nicht erfüllen: URI_INTEGRITY_MISMATCH für Element-Inhalt (ein harter Integritätsfehler, ungeachtet dessen, was eine Geschwister-URI trägt), die MERKLE_*-Familie für eine Blattliste, TAMPERED_CIPHERTEXT für einen zurechenbaren Chiffretext-Blob. Verdikt failed.
  • Nicht zurechenbare Bytes – Bindung nicht verifiziert oder verifiziert und gescheitert – belasten den Anbieter, nie den Datensatz: URI_PROVIDER_INTEGRITY_MISMATCH (Warnung). Der Verifizierer fährt mit den verbleibenden URIs und Gateways fort; ein Anspruch, der ohne zurechenbare Bytes verbleibt, endet mit einem Verfügbarkeitsergebnis (CONTENT_UNAVAILABLE, MERKLE_LEAVES_UNAVAILABLE, CIPHERTEXT_UNAVAILABLE), Verdikt unverifiable – genau so, als wäre nichts abgerufen worden.

Dies ist das speicherseitige Gegenstück zur Bindung an die Transaktionsreferenz: Ein sich fehlverhaltendes Gateway kann nur die Verfügbarkeit verschlechtern, nie das Verdikt. URI_INTEGRITY_MISMATCH und URI_PROVIDER_INTEGRITY_MISMATCH sind daher verschiedene Codes – der erste verurteilt den Datensatz, der zweite einen Anbieter –, und ein Verifizierer, der sie vermengte, ließe ein feindseliges Gateway ein failed fälschen. Die nachträgliche Klartext-Hash-Prüfung nach der Entschlüsselung braucht keinen Zurechenbarkeits-Qualifizierer: Chiffretext, der unter dem authentifizierten Umschlag aufgeht, ist durch das AEAD selbst zugerechnet, sodass eine Klartext-Hash-Abweichung dort (URI_INTEGRITY_MISMATCH) stets dem Datensatz zurechenbar ist und failed erzwingt.

Der typisierte Fehlerkatalog

Jeder Fehlermodus löst sich zu einem Code aus einem einzigen geschlossenen Katalog auf. Codes sind in SCREAMING_SNAKE_CASE, und eine konforme Implementierung MUSS genau diese Zeichenketten ausgeben, nie den internen Kleinbuchstaben-Code eines Parsers, nie eine frei formulierte Meldung. Zwei Implementierungen in zwei Sprachen, die dieselbe Eingabe erhalten, geben denselben Code aus; die vollständige normative Liste wird byte-exakt durch die Konformitäts-Testsuite festgehalten, und der Katalog ist gesperrt (Codes werden nur per Änderung ergänzt).

Schweregrad-Modell

Jedes Problem trägt einen von drei Schweregraden, und die Unterscheidung trägt Gewicht:

  • error: entwertet das Verdikt. Ein valid-Ergebnis kann mit keinem error koexistieren.
  • warning: eine nicht fatale Laufzeitanomalie (ein einzelnes Gateway ist ausgefallen, eine Blattliste war nur teilweise verfügbar), die valid nicht blockiert.
  • info: ein bewusst ausgelassener Prüfschritt: ein Aspekt, den der Verifizierer gewählt hat, nicht zu bewerten (ein Feld außerhalb seines Profils, ein nicht erkanntes optionales Verfahren). Ein Info-Eintrag ist kein abgemilderter Fehler und wird nie als solcher verwendet.

Ein Code steht für sich: INSUFFICIENT_CONFIRMATIONS wird auf das Verdikt pending abgebildet statt auf einen Schweregrad, weil der Datensatz wohlgeformt ist und nur noch auf die Abwicklung wartet.

Fehlerfamilien

Der Katalog gruppiert sich in Familien. Ein repräsentativer, nicht vollständiger Satz von Codes:

FamilieSchweregradRepräsentative Codes
Fehlerhaftes / nichtkanonisches CBORerrorMALFORMED_CBOR, CHUNK_TOO_LARGE
SchemaerrorSCHEMA_TYPE_MISMATCH, SCHEMA_MISSING_REQUIRED, SCHEMA_UNKNOWN_FIELD, SCHEMA_EMPTY_RECORD
Nicht unterstütztes VerfahrenerrorUNSUPPORTED_HASH_ALG, UNSUPPORTED_AEAD_ALG, UNSUPPORTED_KEM_ALG, UNSUPPORTED_MERKLE_COMMIT_ALG
Explorer / Metadatenerror / pendingTX_NOT_FOUND, PROVIDER_UNAVAILABLE, TX_INTEGRITY_MISMATCH (→ unverifiable), METADATA_NOT_FOUND (→ failed); INSUFFICIENT_CONFIRMATIONS (→ pending)
Signaturerror / infoMALFORMED_SIG_COSE_SIGN1, SIGNER_KEY_UNRESOLVED, SIGNATURE_INVALID, WALLET_ADDRESS_MISMATCH; SIGNATURE_UNSUPPORTED (info)
Verschlüsselung / KEM / WraperrorKEM_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
EntschlüsselungsergebniserrorWRONG_DECRYPTION_INPUT_SHAPE, WRONG_RECIPIENT_KEY, TAMPERED_HEADER, TAMPERED_CIPHERTEXT, KDF_DERIVATION_FAILED
URI / Inhalterror / warningINVALID_URI, URI_TARGET_FORBIDDEN, URI_INTEGRITY_MISMATCH, CONTENT_UNAVAILABLE (→ unverifiable), CIPHERTEXT_UNAVAILABLE (→ unverifiable); URI_PROVIDER_INTEGRITY_MISMATCH, URI_FETCH_FAILED (Warnungen)
Merkle-Listenverpflichtungerror / warning / infoMERKLE_ROOT_MISMATCH, SCHEMA_MERKLE_LEAF_COUNT_MISMATCH; MERKLE_LEAVES_UNAVAILABLE (dual); MERKLE_UNSUPPORTED (dual)
DienstunabhängigkeiterrorSERVICE_INDEPENDENCE_VIOLATION

Die Netzwerk-/Richtliniencodes (TX_NOT_FOUND, PROVIDER_UNAVAILABLE, CONTENT_UNAVAILABLE, CIPHERTEXT_UNAVAILABLE) – und TX_INTEGRITY_MISMATCH, dessen Abweichung gegen die Anbieter statt gegen den Datensatz beweisbar ist – haben in der Problemliste den Schweregrad error (sie blockieren ein valid-Verdikt), sind aber nicht dem Datensatz zurechenbar, sodass sie auf unverifiable abbilden, nie auf failed. URI_PROVIDER_INTEGRITY_MISMATCH ist die Pro-Abruf-Warnung nach demselben Grundsatz. Einige Codes tragen einen doppelten SchweregradENC_UNSUPPORTED, MERKLE_UNSUPPORTED, OUT_OF_PROFILE_SKIPPED und MERKLE_LEAVES_UNAVAILABLE –, die standardmäßig als info/warning gelesen werden und in einem strikten Kontext (der Empfängerrolle, der Merkle-only-Eskalation, dem strikten durchgängigen Modus oder der Commitment-Untergrenze) auf error heraufgestuft werden.

Der Empfängerpfad ist die diagnostisch präziseste Familie. Für einen vertrauenswürdigen lokalen Aufrufer löst sich eine gescheiterte Entschlüsselung zu einem von drei internen Codes auf: WRONG_RECIPIENT_KEY bedeutet, dass kein Slot den gelieferten Schlüssel angenommen hat (es wurde nie ein Inhaltsschlüssel zurückgewonnen); TAMPERED_HEADER bedeutet, dass ein Schlüssel zurückgewonnen wurde, aber der Kandidaten-Inhaltsschlüssel slots_mac über slots_hash nicht reproduzierte (ein Slot, ein Header-Feld oder slots_mac selbst wurde verändert); TAMPERED_CIPHERTEXT bedeutet, dass das Slot-Set intakt war, aber das Inhalts-AEAD-Tag scheiterte, nachdem der Schlüssel zurückgewonnen war. Die drei sind für diesen lokalen Aufrufer strukturell unterscheidbar, und die Grenze zwischen ihnen gibt kein Schlüsselmaterial preis. Für einen nicht vertrauenswürdigen externen Aufrufer fallen alle drei zu dem oben beschriebenen einen generischen Fehlschlag zusammen, nach der Form der Antwort nicht unterscheidbar. Unter dem Timing-Modell trennt eine zulässige frühe Kein-Treffer-Rückkehr WRONG_RECIPIENT_KEY (ein Nicht-Empfänger) von den beiden empfängerseitigen Manipulationsergebnissen, die untereinander keine weitere Unterscheidung tragen, sodass die diagnostische Präzision nie zu einem slot- oder schlüsselselektiven Orakel wird.

Wie Codes auf die vier Verdikte abbilden

Ein vom strukturellen Validator ausgegebener Code bedeutet, dass die Bytes des Datensatzes nicht konform sind. Der öffentliche Verifizierer kürzt den Bericht mit dem Verdikt failed ab – Exit 1 – samt der Problemliste des Validators, ohne weitere Chain- oder Krypto-Arbeit auszuführen. Ein Code, der erst ausgegeben wird, nachdem die strukturelle Validierung bestanden wurde – eine Signatur, die sich nicht verifizieren ließ, ein zurechenbarer Hash, der nicht übereinstimmte, METADATA_NOT_FOUND auf der gebundenen Transaktion – ist ebenso failed: Jeder ist dem Datensatz zurechenbar, ein Beweis, den die eigenen Bytes des Datensatzes liefern.

Ein vorübergehendes oder dem Anbieter zurechenbares Scheitern ist ein anderes Verdikt: Inhalt, der sich nicht abrufen oder zurechnen ließ, ein nicht erreichbarer Explorer oder ein Anbieter, der Bytes lieferte, die die Bindung an die Transaktionsreferenz verfehlen, bilden allesamt auf unverifiable ab – Exit 2 –, denn keines ist die Schuld des Datensatzes, und derselbe Datensatz kann bei einem erneuten Versuch valid verifizieren. Die Unterscheidung, die der Exit-Code bewahrt, ist daher dreiteilig unter den scheiternden Zuständen: dem Datensatz zurechenbares failed (1), betrieblich oder dem Anbieter zurechenbares unverifiable (2) und unterschwelliges pending (3).

Einige wenige Codes tragen einen kontextabhängigen Schweregrad. Ein Verifizierer, der einen reichhaltigeren Datensatz liest, als sein deklariertes Profil vorgibt (etwa ein reiner Hash-Verifizierer, der auf einen versiegelten Eintrag trifft), meldet das zusätzliche Feld in einem Anzeigekontext als info und validiert den Hash-Anspruch dennoch, oder in einem strikten durchgängigen Audit-Kontext als error. Ebenso ist ein nicht erkanntes optionales Signaturverfahren info, denn der Anspruch auf die Existenz des Inhalts hängt nicht davon ab, sodass ein öffentlicher reiner Hash-Nachweis auch dann valid bleibt, wenn eine ergänzende Signatur nicht verifizierbar ist.

Dienstunabhängigkeit ist nicht optional

Die Verifizierung greift nie auf die veröffentlichende Stelle zurück. Jeder ausgehende Aufruf, den ein konformer Verifizierer macht, richtet sich an Infrastruktur, die der Betreiber gewählt hat: einen Cardano-Explorer für die Transaktion und inhaltsadressierte Speicher-Gateways für etwaige ar://- oder ipfs://-Bytes. Das ist strukturell durchgesetzt, kein Versprechen in einem Code-Kommentar:

  • Jeder Netzwerkaufruf läuft durch eine einzige Egress-Hülle, die url, method, status, die Byte-Anzahl und den Zweck für jeden Aufruf, ob Erfolg, Fehler oder erneuter Versuch, in einen verpflichtenden Prüfpfad des Berichts schreibt. Ein Verifizierer, der diesen Pfad nicht vorlegen kann, kann seine Unabhängigkeit nicht nachweisen.
  • Diese Hülle nimmt eine vom Einsatz gelieferte Deny-Host-Liste entgegen und lässt jeden Aufruf an einen passenden Host hart mit SERVICE_INDEPENDENCE_VIOLATION scheitern. Die Liste ist eine Betreibereingabe, eine Konformitätssuite füllt sie mit den eigenen Domains der Implementierenden, keine Wire-Konstante von Label 309.
  • Ein Konformitäts-Harness lässt den Verifizierer gegen eingefrorene Fixture-Transaktionen in einem Netzwerk laufen, in dem die eigenen Domains des Betreibers ins Leere auflösen, und stellt sicher, dass der Verifizierer dennoch valid zurückgibt. Die Zusicherung erfolgt auf der Netzwerkebene des Betriebssystems, nicht durch ein Durchsuchen des Quellcodes: Ein Verifizierer, der einen verbotenen Host über eine fest verdrahtete IP erreicht, würde einen Quellcode-Scan bestehen, aber an diesem Test scheitern.

Der Verifizierer braucht einen erreichbaren Cardano-Explorer und nichts Implementierungsspezifisches. Inhalts-Gateways, ein privater Empfängerschlüssel und eine Off-Chain-Blattliste sind optionale Eingaben, die jeweils die Inhalts-, die Empfänger- und die Merkle-Prüfung freischalten. Keine davon ist ein Dienst, den der Standard benennt, und keine davon ist die veröffentlichende Stelle.

Verwandte Seiten

  • Der Datensatz: das Wire-Format, gegen das der strukturelle Validator prüft: label 309, die Form der Map, die Wiederzusammensetzung der Stücke und das CDDL-Schema.
  • Signaturen: die Konstruktion des COSE_Sign1 auf Datensatzebene, die domänengetrennten Nutzdaten und die strikten Ed25519-Verifizierungsregeln.
  • Versiegelte PoE: der Verschlüsselungsumschlag, die Empfänger-Schlüsselslots und das Entpacken, das der Empfänger-Verifizierer durchführt.