continuity-receipt (Rust)
Second, independent implementation of the Continuity Receipt verifier for
continuity-receipt/0.1-0.2 bundles. The Python implementation in
../continuity_receipt/ remains the reference; this crate exists for the
two-independent-implementations bar, native embedding, and single-binary
deployment.
It re-implements the pinned JCS subset (canon.rs), did:key Ed25519
verification (didkey.rs), and the full verification algorithm with the same
error codes, verdict precedence, and JSON output shape as
continuity_receipt.verify (verify.rs).
Install
The crate tracks continuity-receipt/0.1-0.2 bundles; the Python
implementation in this repository remains the reference. Publication
runbook: PUBLISH.md.
Run
The binary prints the same JSON shape as the Python CLI (verdict, errors,
provisional_reasons, insufficient_reasons, summary) and exits 0 iff the
verdict is TRUSTED, else 1.
Selective disclosure
continuity-receipt-disclose mirrors continuity_receipt/disclose.py
(redact / verify / reveal / check):
The gate-key file is the raw 32-byte Ed25519 seed. Redaction re-signs the
modified receipt and every receipt after it, so the signer must be the
chain's issuer; redacting a cross-checked field (for example spend_cap)
fails closed to UNTRUSTED because a commitment cannot prove the claim.
Tests
The vector runner reads ../vectors/manifest.json and checks all 20 vectors
against their expected verdict and error code. Malformed-bundle smoke cases
(empty object, non-object, missing receipts) are included so the verifier
returns structured errors instead of panicking. tests/disclose.rs covers
redaction, tail re-signing, refusal cases, and commitment recomputation
against the frozen vectors. tests/fuzz_corpus.rs mutates every vector
(deterministic seed) plus synthetic malformed shapes and byte truncations:
every case must yield a structured verdict with coded errors and never
panic. Set CR_FUZZ_CORPUS_DIR=<dir> to write the generated corpus to disk.
The Python↔Rust differentials run in CI after cargo build:
Intentional, documented differences from Python
- Floats and canonicalization failures produce a structured
malformed(or the relevant check's) error instead of a Python exception/traceback. - Invalid JSON input to the CLI prints a structured
malformedresult and exits1instead of raising. - Non-list
anchors/revocationsvalues and other deeply malformed shapes are failed closed with the corresponding structured error where Python would raise. disclose redactadditionally accepts repeatable--salt <path>=<hex>for reproducible commitments; the Python CLI always randomizes salts.disclose verifydoes not accept--revocationsuntil the Rust revocation-list loader lands; external lists remain Python-only.