QZR-1: QuantZK Verifiable Usage Receipt Specification
Status: Candidate (not frozen)
Spec id: QZR-1
Schema string: quantzk_billing_receipt_v1
Media type: application/vnd.quantzk.receipt+json
File extension: .qzk (JSON)
This specification separates QuantZK the company from the portable evidence object integrators and customers exchange. Normative language uses RFC 2119 MUST / SHOULD / MAY.
Freeze criterion. QZR-1 freezes only when an engineer with only this document (and listed public trust roots / golden vectors) can implement a verifier that agrees with
protocol/conformance/qzr-1/expected-results.jsonwithout reading@quantzk/*source.
1. Purpose
A QZR-1 receipt lets any party answer, offline:
- What usage identity produced a claimed charge?
- Which tariff / evaluator digests were declared?
- What public billing commitments were bound?
- Who signed the meter event (if present)?
- Which circuit / verification key / issuer produced the proof?
- Have the settlement-relevant bytes been modified?
- Does verification succeed without calling the issuer?
Fresh revocation / governance status requires a current revocation snapshot. Historical cryptographic validity of a frozen receipt remains checkable without issuer infrastructure.
2. Conformance levels (normative)
Levels answer different questions:
| Level | Meaning |
|---|---|
| Minimal | Cryptographic receipt: historically valid attestation for a declared profile, with a recomputable billing fingerprint. |
| Standard | Cryptographically bound billing receipt: Minimal + verification receipt + fingerprint integrity + mandatory Phase-2 in-circuit commitment binding under an authorized apiBillingV2 circuit/vkey. |
| Strict | Bound receipt + current operational trust: Standard + authenticated meter provenance (when required) + fresh revocation CLEAR + profile transparency policy. |
A level evaluation is a boolean PASS / FAIL. Individually reportable checks use the status enum in §6.1.
Downgrade resistance. An issuer MUST NOT omit Phase-2 fields and still claim Standard. For Standard evaluation, phase2_binding = NOT_CHECKED or missing proof ⇒ FAIL (not NOT_CHECKED). For Minimal, phase2_binding = NOT_APPLICABLE.
3. Top-level object
| Field | Type | Required | Description |
|---|---|---|---|
schema | string | yes | MUST be quantzk_billing_receipt_v1 |
qzr | string | yes | MUST be QZR-1 |
media_type | string | recommended | application/vnd.quantzk.receipt+json |
billing_version | string | yes | MUST be v2 for this revision |
profileId | string | yes | Declared verification profile id |
created_at | string (ISO-8601) | recommended | Envelope creation time |
issuer | string | optional | Display name (not an authorization root) |
attestation | object | yes | decision_attestation_v1 |
receipt | object | null | Standard+ | verification_receipt_v1 |
billing | object | yes | Charge + fingerprint + digests + commitments |
meter_envelope | object | null | Strict when required | Externally signed meter |
meter_event | object | null | recommended | Convenience copy |
tariff_snapshot | object | null | recommended | Convenience copy |
charge_authority | object | null | recommended | Signed grant that MUST predate the meter event (quantzk_charge_authority_v1) |
execution_intent | object | null | recommended when grant present | quantzk_execution_intent_v1 committed at preflight |
execution_intent_digest | string | null | recommended when grant present | 0x || SHA-256(JCS(execution_intent)); also MAY appear on billing_verify_fingerprint |
job_id | string | null | optional | Issuance correlation only |
temporary_receipt_hash | string | null | optional | Async accept hash |
issuance | object | null | optional | e.g. { "mode": "async", "status": "completed" } |
3.1 Integer wire representation
Integer fields that affect settlement (expected_charge_micros, usage_units, unit_price_micros, min/max charge micros) MUST be encoded as JSON numbers that are:
- Finite,
- Integers (no fractional part),
- In the inclusive range
0…9007199254740991(2^53 − 1).
Implementations MUST reject values outside this range or with a fractional part. (This keeps cross-language interoperability inside the IEEE–754 / JS safe-integer bound. Larger values require a future QZR revision with string-encoded decimals.)
4. billing object
| Field | Minimal | Standard | Strict | Description |
|---|---|---|---|---|
expected_charge_micros | MUST | MUST | MUST | Settled charge micros (§3.1) |
currency | SHOULD | SHOULD | SHOULD | ISO 4217 |
billing_verify_fingerprint | MUST | MUST | MUST | Canonical billed fields (§4.1) |
billing_verify_fingerprint_hash | SHOULD | MUST | MUST | §5 hash of fingerprint |
public_commitments | MUST | MUST | Object bound by Phase-2 | |
public_commitments_digest | MUST | MUST | Digest of public_commitments (§5.2) | |
transparency_inclusion_proof | profile | Log inclusion | ||
transparency_log_entry | profile | { entry_hash, … } |
4.1 billing_verify_fingerprint
MUST include at least:
event_id,tenant_id,billing_window_id,contract_versionusage_units,expected_charge_micros,currencyunit_price_microsmeter_event_digest,meter_signing_kidtariff_id,tariff_version,tariff_digestevaluator_version,evaluator_digest
Additional keys MAY be present; they MUST be included in canonicalization (§5).
4.2 Phase-2 claim boundary (normative, narrow)
Standard requires that the ordered billing field-images / public commitments are cryptographically bound by the approved Phase-2 circuit apiBillingV2 (binding_version = bn128-poseidon8-v1).
Standard does not claim that the Groth16 circuit recomputes the full deterministic tariff invoice algorithm. Tariff/charge consistency against tariff_snapshot remains a separate verifier invariant unless a future circuit version expands the relation.
4.3 Charge authority (Candidate)
The intended issuance order is authority → execution → charge → receipt.
Charge authority is a separate object from the QZR-1 receipt. The receipt MAY embed charge_authority (or reference digests) so verifiers can check continuity. Authorization answers “what was allowed?”; QZR-1 answers “what was charged?”
QZR-1 evaluate is always receipt-time. It MUST NOT be used as permission to execute a new paid action. Preflight MAY_EXECUTE and attest-time verification of prior consume_if_available are specified in Charge authority.
v1 grants MUST set usage_mode = single_use, a unique authority_id (qza: + SHA-256 hex of the signing message), and a unique nonce. Receipt-time authority: PASS means this receipt binds to this grant. It does not prove the grant was atomically consumed unless authority_consumption_check = PASS with authenticated consumption evidence, and it does not mean the grant may be spent now.
When charge_authority is present it MUST:
- Use schema
quantzk_charge_authority_v1with a valid Ed25519 signature over UTF-8QZK_CHARGE_AUTHORITY_V1|| LF || JCS(canonical_authority_payload).canonical_authority_payloadis the grant withauthority_id,authority_digest, andsignature.valueremoved. Digest algorithm is FIPS 180-4 SHA-256 of that signing message (full 32 bytes).authority_digest=0x|| lowercase hex;authority_id=qza:|| the same hex (64 chars). - Match tenant, contract, tariff id/version/digest,
unit_price_micros, and currency of the meter event / tariff snapshot. - Use integer Unix seconds only (
issued_at <= valid_from <= valid_until). With skews(default 60s):valid_from - s <= event_timestamp <= valid_until + s, and independentlyevent_timestamp >= issued_at - s. This is consistency of authenticated timestamps, not independent clock proof. Fractional grant timestamps are invalid. - Optional constraint keys (
subject_id,endpoint,vendor_id,model_id,tool_id,cost_center,policy_digest,max_charge_micros): key absent = unconstrained. JSONnulland empty string are not unconstrained and MUST FAIL. Present keys MUST match the meter/charge. - If
max_charge_microsis present:computed_charge_micros <= max_charge_micros, wherecomputed_charge_microsisbilling_verify_fingerprint.expected_charge_micros(the hashed charge). Convenience copies (billing.expected_charge_micros) MUST match that value (§4.4). Taxes/credits/discounts are outside the cap unless already folded into that integer. - Trust:
issuer/issuer_roleare signed claims only.authority_trust_modeisopen_signature(default) orpinned_roots(empty allow-list authorizes nobody). Do not infer trust from list emptiness. - Anti-downgrade (Standard). If
charge_authorityis present, thenbilling_verify_fingerprint.authority_idMUST be present and MUST equal the grant’s recomputedauthority_id(fromcanonical_authority_payloaddigest, not a mutable wire copy ofgrant.authority_id), andbilling_verify_fingerprint.execution_intent_digestMUST be present and MUST match the meter-event intent projection and all intent-digest mirrors. Digest comparison MUST use the same canonical form as §4.4 hex equality (optional0xstripped, lowercase). Missing identity/intent commitments yieldauthority_continuity/execution_intent_binding=NOT_CHECKEDand MUST FAIL Standard. They MUST NOT be upgraded toauthority: PASSby inference. Minimal MAY still PASS when those fields are absent (historical crypto). A present but mismatched digest orauthority_idisFAILat every profile (authority_continuity/execution_intent_binding≠ FAIL is required for Minimal as well as Standard).
Absence of the grant object is authority = NOT_CHECKED (receipts without Charge Authority). A present but invalid grant is FAIL and MUST fail Standard.
4.4 Authoritative-field consistency (normative)
Committed-value dominance. For every security-relevant semantic value represented in more than one location, the specification identifies exactly one authoritative cryptographically bound representation. All other representations are mirrors. A verifier MUST reject any receipt in which a present mirror does not canonicalize to the authoritative value.
No security decision MAY be made from an uncommitted mirror when a cryptographically committed representation of the same fact exists. Conflicting representations fail verification.
This registry is representation consistency. It does not replace artifact-specific authenticity or derivation checks (recompute authority_id from the signed grant; verify that vkey_hash corresponds to the verification key).
Path presence (leaf of the registry path):
| Wire state | Meaning |
|---|---|
key / path absent (undefined) | absent (ignore unless a profile requires the field) |
JSON null | present and invalid (FAIL) |
"" | present and invalid (FAIL) |
| present, valid encoding | canonicalize, then compare |
Authoritative values are validated even when every mirror is absent: a malformed authoritative representation is FAIL, not PASS.
Canonical equality (do not invent per-implementation “semantic” equality; do not coerce types):
| Kind | Rule |
|---|---|
| integer | JSON number only (typeof number); Number.isSafeInteger; range 0…2^53-1. Strings such as "120" are invalid, not integers. |
| hex digest | JSON string only; optional 0x prefix; lowercase [0-9a-f]; SHA-256 fields MUST be exactly 64 hex characters after prefix removal. Invalid encodings are not equal to each other. |
| string | JSON string only; exact equality (currency is the ISO-style code as emitted). Numbers are not strings. |
| structured object | JCS → SHA-256 → compare digests |
Authoritative-field registry:
| Semantic fact | Authoritative representation | Mirrors (if present) |
|---|---|---|
| Charge | fingerprint.expected_charge_micros | billing.expected_charge_micros, public commitments |
| Usage units | fingerprint.usage_units | meter_event.usage_units, public commitments |
| Event id | fingerprint.event_id | meter / envelope / public commitments |
| Tenant | fingerprint.tenant_id | meter / public commitments |
| Contract version | fingerprint.contract_version | meter |
| Billing window | fingerprint.billing_window_id | meter / public commitments |
| Currency | fingerprint.currency | billing / tariff / public commitments |
| Unit price | fingerprint.unit_price_micros | tariff snapshot |
| Tariff id/version/digest | fingerprint fields | tariff snapshot / billing / public commitments |
| Meter event digest | fingerprint.meter_event_digest | meter envelope / public commitments |
| Authority identity | signed grant authority_id and fingerprint.authority_id | envelope grant |
| Execution intent | fingerprint.execution_intent_digest | envelope / billing copies |
| Verification key | attestation.billing_proof.vkey_hash | billing.incircuit_binding.vkey_hash |
The fingerprint is not automatically authoritative for every fact. Authority identity is recomputed from the signed grant; the fingerprint commits which grant was used. Both MUST agree when the grant is present under Standard. Issuers MUST omit unconstrained convenience keys rather than emit null or "".
Language-neutral registry: protocol/conformance/qzr-1/authoritative-field-registry.json (version 1, SHA-256 1a2e01b8e2a89bf530da4ad87fc185b29f5915882a6fefa9e5dde41c4a762676). Cross-language attack vectors: protocol/conformance/qzr-1/committed-value-vectors.json (SHA-256 138b56b72f2874c869cd44b0ba46c70c6be99b09a48bb47c2f85a954b8973dbb). Artifact digests are SHA-256 over the exact raw UTF-8 file bytes (not JCS re-serialization). Independent implementations MUST agree on those vectors. Changing either file is a spec change, not a casual implementation update. §4.4 is not Standard-only: a conflicting mirror fails Minimal as well as Standard.
Document-level allowed_equality_types and allowed_entry_keys describe the registry schema; they do not extend it. A conforming implementation MUST validate entries against the QZR-1 version's normative constants (integer, hex, string and the entry key set). For registry v1, declared allowed_* arrays MUST exactly match those constants or the registry document is malformed.
Registry schema invariants (enforced at load time by all implementations):
| Invariant | Rule |
|---|---|
fact | unique across all entries |
authoritative | exactly one per fact; unique across all entries |
| mirror paths | unique within the fact; authoritative ≠ mirror |
equality | recognized enum only (integer, hex, string) |
| unknown entry keys | reject |
version | explicit integer ≥ 1 |
document allowed_* | MUST match normative constants for that version; MUST NOT be used as the authority for what is allowed |
5. Canonicalization and hashing (normative)
authority: PASS does not claim: permission to execute a new paid action, consumption uniqueness (that requires authority_consumption_check = PASS), budget reservation / concurrency-safe ledgering, path enforcement, QuantZK online at request time, source-clock correctness, current non-revocation without a snapshot, delegation_chain validity, that issuer_role confers trust, in-circuit intent binding, or correctness of an external policy engine beyond a declared policy_digest. See Charge authority.
Issuer: issuer, issuer_role, issuer_kid, signature. QuantZK verifies grants from authorized spend-authority keys; it need not be the issuer.
5. Canonicalization and hashing (normative)
All algorithms below are byte-exact. Implementations MUST NOT consult proprietary QuantZK packages to invent different rules.
5.1 QZR Canonical JSON
Input: a JSON value (after UTF-8 JSON parse).
Output: a Unicode string canonical, then encoded as UTF-8 bytes for hashing.
Rules (inspired by RFC 8785 / JCS, specialized here):
null→nulltrue/false→true/false- Numbers: MUST be finite. Encode with
JSON.stringifysemantics for IEEE-754 finite numbers. Negative zero MUST encode as0. Non-finite numbers MUST be rejected. BigInt MUST be rejected on the wire (use §3.1 integers). - Strings: Encode with
JSON.stringify(UTF-16 code units as in ECMA-404 / JSON; escapes for controls). Unicode is preserved as in standard JSON string encoding. - Arrays:
[+ elements joined by,+].undefined/ function / symbol array holes becomenull. - Objects: Enumerate own enumerable property names, sort by UTF-16 code unit order (
String<comparison), omit keys whose values canonicalize toundefined(i.e.undefined/ function / symbol values are omitted, not emitted asnull). Emit{+"key":valuepairs joined by,+}. Key names areJSON.stringify’d. - Top-level
undefinedis rejected.
Pseudocode:
serialize(v):
if v is null → "null"
if v is boolean → "true" | "false"
if v is number → reject if not finite; if -0 → "0"; else JSONNumber(v)
if v is string → JSONString(v)
if v is array → "[" + map(serialize-or-null) + "]"
if v is object →
keys = sort(Object.keys(v))
fields = []
for k in keys:
c = serialize(v[k]) # may be undefined → omit
if c defined: fields.append(JSONString(k) + ":" + c)
return "{" + join(fields, ",") + "}"5.2 SHA-256 hex encoding
sha256_hex(bytes) := lowercase hexadecimal encoding of SHA-256(bytes), length 64
wire_hash := "0x" || sha256_hex(bytes)5.3 Fingerprint hash
Let F = billing.billing_verify_fingerprint.
canonical_bytes = UTF-8( QZR_CanonicalJSON(F) )
billing_verify_fingerprint_hash = "0x" || sha256_hex(canonical_bytes)QZR-1 does not insert an ASCII domain-separator prefix. Separation is the fixed fingerprint schema (§4.1) hashed in isolation. Introducing "QZR-1:FINGERPRINT:" || … would be a breaking change reserved for a future QZR revision.
5.4 Public commitments digest
Let C = billing.public_commitments.
public_commitments_digest = "0x" || sha256_hex( UTF-8( QZR_CanonicalJSON(C) ) )5.5 Verification-key hash
For any verification key object V (Groth16 vkey JSON):
verification_key_hash = "0x" || sha256_hex( UTF-8( QZR_CanonicalJSON(V) ) )This is the hash used in allow-lists (not the raw file bytes of a .vkey.json unless those bytes equal the canonical form).
5.6 Phase-2 field images and commitment digest
binding_version MUST be bn128-poseidon8-v1.
This digest is circomlib Poseidon over the BN128 / BN254 scalar field (alt_bn128), the same family used by Circom Groth16 for apiBillingV2. It is not BLS12-381 Poseidon.
Normative primitive: Poseidon8_circomlib_bn128
| Parameter | Normative value |
|---|---|
| Curve / field | BN128 (a.k.a. BN254 / alt_bn128) scalar field |
Prime p | 21888242871839275222246405745257275088548364400416034343698204186575808495617 |
| Hash | Poseidon permutation as implemented by circomlib Poseidon.circom / circomlibjs buildPoseidon() default constants |
| Arity | 8 field elements (width t = 9 = 8 inputs + capacity) |
| Parameter set | Default circomlib / circomlibjs Poseidon constants for that width (do not substitute a BLS12-381 or custom S-box table) |
| Output | Single field element in [0, p), wire form = decimal string (snarkjs public-signal convention) |
Pseudocode (names are normative identifiers):
commitment_digest = Poseidon8_circomlib_bn128(fields)
// == circomlibjs: (await buildPoseidon())(fields) → F.toObject → decimal stringLet p be the bn128 scalar field prime above.
toFieldElement(value):
| Value | Mapping |
|---|---|
null / missing | 0 |
| finite number | trunc(value) mod p (normalized into [0, p)) |
string matching 0x + hex | integer from hex mod p |
string matching optional - + digits | decimal BigInt mod p |
| other string | SHA-256(UTF-8(string)) interpreted as big-endian integer mod p |
| object / array | SHA-256(UTF-8(QZR_CanonicalJSON(value))) mod p |
Ordered field-images (order is normative; do not reorder without a new binding_version):
fields[0] = toFieldElement(C.event_id)
fields[1] = toFieldElement(C.tenant_id)
fields[2] = toFieldElement(C.api_key_id ?? C.meter_signing_kid)
fields[3] = toFieldElement(C.endpoint ?? C.evaluator_digest)
fields[4] = toFieldElement(C.billing_window_id)
fields[5] = toFieldElement(C.tariff_id)
fields[6] = toFieldElement(C.usage_units)
fields[7] = toFieldElement(C.expected_charge_micros)commitment_digest = Poseidon8_circomlib_bn128(fields)Wire form of commitment_digest / Groth16 public signal: decimal string of the field element.
Known-answer test (Normative KAT)
Independent implementers MUST reproduce this digest before claiming §5.6 conformance.
fields = [1, 2, 3, 4, 5, 6, 7, 8] // already in F_p
Poseidon8_circomlib_bn128(fields) =
"18604317144381847857886385684060986177838410221561136253933256952257712543953"Canonical copy: protocol/conformance/qzr-1/poseidon8-kat.json.
The Phase-2 proof relation asserts knowledge of the eight private field-images such that Poseidon8_circomlib_bn128(fields) equals the single public signal. Verifiers MUST:
groth16.verify(authorized_vkey, [public_signal], proof) = truepublic_signal === Poseidon8_circomlib_bn128(deriveFieldImages(expected public_commitments))
6. Verification algorithm (normative)
6.1 Check status enum
Every atomic check reports exactly one of:
| Status | Meaning |
|---|---|
PASS | Checked and satisfied |
FAIL | Checked and not satisfied |
NOT_CHECKED | Applicable, but verifier lacked required external input (e.g. no revocation snapshot) |
NOT_APPLICABLE | Not required at the evaluated level / absent optional artifact |
Rules for NOT_CHECKED:
- Permitted for Minimal/Standard on revocation and transparency when no snapshot / log head is supplied.
- Forbidden as a substitute for missing Phase-2 artifacts under Standard (
missing ⇒ FAIL). - Permitted for charge authority when the envelope has no
charge_authority. A present but invalid grant isFAIL. A present grant withoutfingerprint.authority_idisauthority_continuity = NOT_CHECKEDand MUST FAIL Standard (anti-downgrade); it MUST NOT be reported asauthority: PASS. - Permitted for execution_intent_binding when there is no grant. A present grant without
fingerprint.execution_intent_digestisNOT_CHECKEDand MUST FAIL Standard. A present but mismatched digest isFAIL. - Permitted for authority_consumption / authority_consumption_check and authority_revocation when no consumption log / authority revocation snapshot is supplied.
- Strict MUST NOT return overall PASS while revocation is
NOT_CHECKED.
6.2 Authorization predicates (trust ≠ math)
Mathematical proof validity alone is insufficient.
proof_valid := Groth16 verifies under the key embedded in the attestation
circuit_authorized := attestation / billing_proof circuit_id (+ version) ∈ profile allow-list
verification_key_authorized := verification_key_hash(vkey) ∈ profile allow-list
issuer_authorized := attestation.signature.kid (or public key) ∈ profile allow-list
OR profile explicitly accepts the embedded key under an pinned issuer registry
profile_satisfied := all checks required by profileId succeedA malicious party can generate its own circuit, vkey, and valid proof. Without circuit_authorized ∧ verification_key_authorized ∧ issuer_authorized, a receipt MUST NOT be treated as authorized QZR billing evidence for that profile, even if proof_valid = true.
Profiles MUST publish:
authorized_issuer_kids/ issuer public keysauthorized_attestation_vkey_hashes(main VDI decision circuit)authorized_billing_vkey_hashes(Phase-2apiBillingV2, Standard+)authorized_circuit_ids/authorized_binding_versions- optional
authorized_policy_manifest_hashes - revocation freshness policy (
max_snapshot_age_seconds)
6.3 Envelope validity
envelope_valid :=
JSON parse succeeds
AND qzr == "QZR-1"
AND schema == "quantzk_billing_receipt_v1"
AND billing_version == "v2"
AND attestation is present
AND billing.billing_verify_fingerprint is present
AND integer fields satisfy §3.1On failure → levels FAIL; report QZR_VERSION_UNSUPPORTED or QZR_MALFORMED as appropriate.
6.4 Level predicates
attestation_valid :=
proof_valid
AND signature_valid
AND key_integrity_valid
AND schema/pipeline/policy checks required by profileId
AND issuer_authorized
AND verification_key_authorized // attestation circuit vkey
AND circuit_authorized // attestation circuit identity when profile lists itfingerprint_present := billing.billing_verify_fingerprint is an object with §4.1 required keys
fingerprint_hash_valid :=
billing.billing_verify_fingerprint_hash == FingerprintHash(§5.3)QZR1_MINIMAL_PASS :=
envelope_valid
AND attestation_valid
AND declared_profile_satisfied // profileId checks that Minimal requires
AND fingerprint_present
AND (fingerprint_hash_valid OR fingerprint_hash is absent)
AND committed_consistency ≠ FAIL // §4.4 applies at every level; not Standard-only
AND authority_continuity ≠ FAIL // present identity mismatch is not a Minimal bypass
AND execution_intent_binding ≠ FAIL // present intent mismatch is not a Minimal bypassWhen fingerprint hash is absent under Minimal → fingerprint_hash = NOT_CHECKED (permitted). When present and wrong → FAIL and Minimal FAIL.
receipt_valid := verification_receipt_v1 verifies against attestation (incl. expiry + binding)
public_commitments_present := billing.public_commitments is a non-empty object
public_commitments_digest_valid :=
billing.public_commitments_digest == CommitmentsDigest(§5.4)
billing_proof_present := attestation.billing_proof is present with binding_version bn128-poseidon8-v1
incircuit_binding_valid :=
verifyInCircuitBillingProof(attestation.billing_proof,
expectedPublicCommitments = billing.public_commitments,
allowedVkeyHashes = profile.authorized_billing_vkey_hashes)
AND billing_proof.circuit_id authorized
AND billing_proof.vkey_hash authorized
charge_authority_valid :=
if charge_authority absent: NOT_CHECKED
else receipt-context bind(grant, meter_event, tariff_snapshot)
(canonical_authority_payload + integer unix-second window)
→ PASS / FAIL
// QZR-1 is receipt-time; may_execute is always false here
execution_intent_binding :=
if no grant: NOT_CHECKED
else if execution_intent_digest (and optional execution_intent) absent: NOT_CHECKED
else if SHA-256(JCS(execution_intent)) matches digest
AND meter_event intent-field projection matches digest: PASS
else: FAIL
authority_consumption :=
if no grant or binding failed or no consumption log: NOT_CHECKED
else if log has no record for authority_id: AVAILABLE
else if log maps authority_id to this event_id
AND (when execution_intent_digest is expected: stored digest matches): CONSUMED_BY_THIS_EVENT
else: CONSUMED_BY_OTHER_EVENT
// Bare event_id strings are NOT CONSUMED_BY_THIS_EVENT when an intent digest is expected.
// v1 consumption logs are trusted-channel inputs, not portable self-authenticating proofs.
authority_consumption_check := // receipt-derived; do not collapse AVAILABLE with CONSUMED_BY_THIS_EVENT
if authority_consumption = NOT_CHECKED: NOT_CHECKED
else if authority_consumption = CONSUMED_BY_THIS_EVENT: PASS
else: FAIL // AVAILABLE or CONSUMED_BY_OTHER_EVENT
QZR1_STANDARD_PASS :=
QZR1_MINIMAL_PASS
AND receipt_valid
AND fingerprint_hash_valid // hash MUST be present
AND public_commitments_present
AND public_commitments_digest_valid
AND billing_proof_present // missing ⇒ FAIL (not NOT_CHECKED)
AND circuit_identity_authorized // apiBillingV2
AND verification_key_authorized // billing vkey allow-list
AND incircuit_binding_valid
AND committed_consistency ≠ FAIL
AND if charge_authority absent: charge_authority_valid = NOT_CHECKED
else charge_authority_valid = PASS
AND authority_continuity = PASS
AND execution_intent_binding = PASS
AND authority_consumption_check ∈ {PASS, NOT_CHECKED} // log-backed replay / unconsumed-on-receipt FAILmeter_trust_valid :=
if meter_envelope absent:
NOT_APPLICABLE if profile.allow_missing_meter else FAIL
else:
Ed25519 envelope verifies under trusted kid → PASS/FAIL
revocation_status :=
if no snapshot supplied: NOT_CHECKED
else if attestation_id or issuer kid revoked: FAIL
else: PASS // reported as CLEAR in summaries
revocation_snapshot_fresh :=
if no snapshot: NOT_CHECKED
else if now - snapshotTime > profile.max_snapshot_age_seconds: FAIL
else if attestation.issued_at > snapshotTime: FAIL // snapshot predates issuance
else: PASS
transparency_valid := per profile (NOT_APPLICABLE if not required and absent)
QZR1_STRICT_PASS :=
QZR1_STANDARD_PASS
AND meter_trust_valid ∈ {PASS, NOT_APPLICABLE}
AND revocation_status == PASS
AND revocation_snapshot_fresh == PASS
AND transparency_valid ∈ {PASS, NOT_APPLICABLE}6.5 Human summary label
Implementations MAY print QUANTZK VERIFIED when the requested level (default: Standard if Phase-2 present, else Minimal) evaluates to PASS. They MUST still emit the status enum for revocation / transparency so NOT_CHECKED is visible.
Offline Standard PASS with revocation = NOT_CHECKED means: cryptographically bound billing evidence; not “currently non-revoked.”
6.6 Reference implementations
- JS library:
@quantzk/sdk→verify() - CLI:
npx @quantzk/verify receipt.qzk - Conformance:
protocol/conformance/qzr-1/run-js.mjs - Committed-value registry + vectors:
protocol/conformance/qzr-1/authoritative-field-registry.json,committed-value-vectors.json(JS + Python) - Browser:
https://quantzk.com/protocol/verify.html
7. Logical uniqueness (portable protocol)
For a given logical billable event, the uniqueness key is:
(tenant_id, billing_window_id, event_id)as carried in the fingerprint / meter event.
Issuers MUST ensure that committed charges under the same uniqueness key are idempotent: a duplicate record MUST NOT create a second independent committed charge.
QZR-1 does not require a particular server job identifier. Returning the same job_id on duplicate accepts is a QuantZK API concern, not a QZR-1 wire requirement. Portable verifiers compare uniqueness keys and receipt / attestation identities, not job queues.
8. Versioning
| Spec | Notes |
|---|---|
| QZR-1 | This document |
| QZR-2 | Reserved for aggregates, multi-line invoices, cross-currency, and safe large integers |
Breaking changes require a new qzr / schema pair. Additive optional fields are allowed within QZR-1 only when they do not weaken §2 level predicates.
9. Security considerations
- Treat receipts as public evidence, not secrets.
proof_validwithout authorization predicates is not QZR authorization.- Offline Standard PASS ≠ current governance clearance.
- Do not put attest API secrets inside
.qzkfiles. - Independent implementations MUST treat this document + golden vectors as the contract.
10. Example (abbreviated Standard)
{
"schema": "quantzk_billing_receipt_v1",
"qzr": "QZR-1",
"billing_version": "v2",
"profileId": "VDI_VERIFY_STANDARD_V1",
"attestation": {
"type": "decision_attestation_v1",
"attestation_id": "vdi:att:0x…",
"billing_proof": {
"schema": "api-billing-v2-incircuit-proof-v1",
"binding_version": "bn128-poseidon8-v1",
"circuit_id": "apiBillingV2",
"vkey_hash": "0xa486fb…",
"public_signals": ["…"],
"proof": { "system": "groth16", "curve": "bn128" }
}
},
"receipt": { "type": "verification_receipt_v1", "receipt_id": "vdi:receipt:0x…" },
"billing": {
"expected_charge_micros": 221040,
"currency": "USD",
"billing_verify_fingerprint": { "usage_units": 1842, "event_id": "evt_123" },
"billing_verify_fingerprint_hash": "0x…",
"public_commitments": { "event_id": "evt_123", "usage_units": 1842 },
"public_commitments_digest": "0x…"
}
}11. Conformance vectors
Canonical fixtures: protocol/conformance/qzr-1/.
| Fixture | Expected (summary) |
|---|---|
valid-minimal.qzk | Minimal PASS; Standard FAIL (phase2 missing → FAIL) |
valid-standard.qzk | Minimal PASS; Standard PASS; revocation NOT_CHECKED offline |
valid-strict.qzk | Minimal/Standard/Strict PASS with fresh CLEAR snapshot |
invalid-standard-missing-binding.qzk | Minimal PASS; Standard FAIL |
invalid-standard-bad-binding.qzk | Standard FAIL |
invalid-standard-unknown-vkey.qzk | Standard FAIL (verification_key_authorized) |
valid-standard-revocation-not-checked.qzk | Standard PASS; revocation NOT_CHECKED |
invalid-strict-stale-revocation.qzk | Standard PASS; Strict FAIL |
invalid-tampered-*.qzk | Settlement / proof / signature / vkey failures |
invalid-revoked-attestation.qzk | Standard-class receipt whose attestation_id is revoked in revocation-snapshot.json. Offline: Minimal+Standard PASS, Strict FAIL, revocation=NOT_CHECKED. With snapshot: Minimal+Standard PASS, Strict FAIL, revocation=FAIL, current_status=REVOKED. |
invalid-version.qzk / invalid-malformed.qzk | envelope FAIL |
expected-results.json | Rich oracle (§11.1) |
trust-roots.json | Profile allow-lists for authorization checks |
11.1 Oracle shape
{
"fixture": "invalid-revoked-attestation.qzk",
"offline": {
"minimal": "PASS",
"standard": "PASS",
"strict": "FAIL",
"historical_crypto_valid": true,
"phase2_binding": "PASS",
"revocation": "NOT_CHECKED",
"current_status": "NOT_CHECKED"
},
"with_revocation_snapshot": {
"minimal": "PASS",
"standard": "PASS",
"strict": "FAIL",
"historical_crypto_valid": true,
"phase2_binding": "PASS",
"revocation": "FAIL",
"current_status": "REVOKED"
}
}Standard does not consume the revocation oracle. A revoked Standard receipt still reports standard: PASS when Phase-2 binding holds; only Strict (or an explicit revocation status field) fails. Implementations MUST NOT collapse revocation: FAIL and proof_valid: false into a single undifferentiated valid=false without reporting the separate statuses.
Run:
npm run test:qzr1
npm run test:qzr1:python
npm run test:committed-values12. Blind validation test
Give valid-standard.qzk, trust-roots.json, and this specification to an engineer who has never seen QuantZK. Do not explain further. Ask:
Can you independently determine whether this receipt meets QZR-1 Standard?
Success means they implement §§5–6 from the text, evaluate the predicates, and match expected-results.json, without opening @quantzk/vdi-billing or any other QuantZK source.
When a blind implementation agrees with the JS and Python runners across the golden vectors, QZR-1 may be considered for freeze as a protocol artifact rather than a vendor serialization format.
