# WAI Extension: Quantum-Operations Attestation (`wai.quantum.calibration` · `wai.quantum.job` · `wai.quantum.mitigate` · `wai.quantum.decode` · `wai.quantum.compile` · `wai.quantum.rearrange`) Status: **Draft.** Engine: `wai-quantum/src/quantum_ops.rs` (feature `quantum_ops`, which `wai-rs` forwards under the same name and re-exports as `wai::quantum_ops`), with the energy forms of `wai-quantum/src/quantum_energy.rs`. The **verify-half** of WAI (`wai.asset.provenance`'s lineage, specialized) applied to the operations around a quantum processor. ## 0. What this extension adds A calibration run or a job on a quantum processor leaves a dataset, a state snapshot and a log; so does each classical step around it: the mitigation of its counts, the decoding of a syndrome, the compilation of a circuit, the rearrangement of a neutral-atom register. This extension adds a receipt over each operation with two properties: 1. **cryptographic signature + portability**: a record a *third party* verifies from the bytes alone, by the rules of §3, which are complete: a verifier written from them alone agrees with the reference on every vector of the corpus (§4); 2. **joules, or a statement that nobody measured them**: the energy of the operation with its acquisition class, or the unmetered form with its reason (§3.5), and never a figure of zero joules for a run nobody read. Version capture of the software that ran, bills of materials and hash-chained audit traces exist elsewhere; the receipt here is signed, content-addressed and grant-bounded. It is not a control system and **runs no hardware**: the operation is performed by the sink's control stack, exactly as WAI dispatches a decode to a sink's codec. WAI owns the **receipt**. ## 1. The records Six records, one per operation, each sealed the same way (§3): a payload of fixed binary framing, signed with Ed25519, whose content hashes are bound by a BLAKE3 Merkle root. Each carries a `grant` (§2), an optional `parent_receipt_hash` (the identity, §3.4, of the receipt this one follows: a signed lineage), its signer's key and label, and its energy (§3.5). ### 1.1 Calibration (`wai.quantum.calibration`) A signed record of one bring-up or tune-up run (`CalibrationReceipt`; the calibration engines of `quantum_cal`, `quantum_control` and `quantum_noise` produce what it binds): - `device_id`, `target` (`"q3"`, `"cz(q3,q4)"`, `"readout:q3"`); - `config_hash`: the content hash of the applied pulse or gate configuration; - `evidence[]`: each `{kind, blob_hash, summary}`, a benchmark outcome (randomized benchmarking, T1 and T2, Rabi, a readout fit) **content-addressed to its raw dataset bytes**, so a fidelity *claim* binds to the exact bytes that produced it (`evidence_matches()`). `summary` is a human sentence and is **not sealed** (§3.2): only `kind` and `blob_hash` are; - `merkle_root`, over `[config_hash] ++ evidence leaves` (§3.3); - `joules_micro`, the run's energy (§3.5); `grant`; `parent_receipt_hash`, the prior device state this one supersedes. ### 1.2 Jobs (`wai.quantum.job`) A signed record of one dispatched circuit (`JobReceipt`): - `backend_id`: what ran it (`"example:qpu-a"`, `"wai.quantum.circuit"`); - `circuit_hash`, `result_hash` (the counts histogram or the state), `shots` (requested); - **`calibration_ref`**: the identity (§3.4) of the calibration receipt of the device state the job ran under, or none for a simulator. A verifier given that calibration confirms the job names *that* calibration and both verify (§3.7): the property that the calibration claimed was the one in effect, signed; - `merkle_root`, over `[circuit_hash, result_hash]`, and `calibration_ref` after them when there is one; `joules_micro`, `grant`, `parent_receipt_hash`. ### 1.3 Mitigation (`wai.quantum.mitigate`) A signed record of one classical error-mitigation step (`MitigationReceipt`): the raw data and the optional noise model that went in, the estimate that came out. - `backend_id`; `method` (`"zne.richardson"`, `"readout.tensored"`, `"shadow.pauli"`); `observable`, a label of the estimated observable (sealed, but informational); - `input_hash` (the raw counts or expectation table), `noise_model_hash` (the model the method consumed, or none: the model's provenance pinned, not re-derived); - `raw_estimate_fx`, `mitigated_estimate_fx`, `error_bar_fx`: signed fixed point at scale 2^20 (`1.0` is `1048576`); `shots`; - `merkle_root`, over `[input_hash]`, `noise_model_hash` when there is one, and the result leaf (§3.3); `joules_micro`, `grant`, `parent_receipt_hash`. ### 1.4 Decoding (`wai.quantum.decode`) A signed record of one error-correction decode (`DecodeReceipt`): `code_id`, `decoder`, `check_matrix_hash`, `syndrome_hash`, `correction_hash`, `converged` (the correction reproduces the syndrome), `rounds` (a u32), `work_messages` (the messages passed), and `joules_micro`, `grant`, `parent_receipt_hash`. Whether a correction leaves a logical error is not a member: a decoder that sees only a syndrome cannot know it. ### 1.5 Compilation (`wai.quantum.compile`) A signed record that a compiled circuit is equivalent to its source (`CompileReceipt`): `source_hash`, `target_hash` (the routed circuit and its final map), `coupling_hash`, `method` (`"clifford-tableau"`), `equivalent`, `swaps` (a u32), `work`, and `joules_micro`, `grant`, `parent_receipt_hash`. ### 1.6 Register preparation (`wai.quantum.rearrange`) A signed record of a neutral-atom rearrangement plan (`RearrangeReceipt`): `initial_hash` (the loaded occupancy), `target_hash` (the target sites), `plan_hash` (the moves), `method` (`"hungarian-lsap"`), `success` (every target site filled), `atoms_moved` (a u32), `total_distance`, and `joules_micro`, `grant`, `parent_receipt_hash`. ## 2. The grant `GrantRef` = **capability ⊗ joule ceiling** (⊗ an optional funds ceiling, JCP §4.8 dual ceiling). The full grant lives in the JCP layer; the receipt binds its content hash (`grant_hash`), its `capability`, `joule_ceiling_micro` and `funds_ceiling`. **The joule ceiling is checked inside verification** (§3.6): a receipt whose `joules_micro` exceeds its grant's ceiling is not valid, so an operation that blew its energy grant cannot produce a passing receipt. A ceiling of 2^64 − 1 is no ceiling. An unmetered run (§3.5) has no figure to hold to the ceiling: the check passes, since its sealed figure is `0`, and a verifier states that the ceiling was not checked, because the run was not metered. ## 3. Encoding and verification This section is complete: it is what the reference does, and a verifier written from it alone gives every receipt of the corpus its verdict (§4). The reference's own words are `seal`, `to_json`, `from_json`, `verify` and `receipt_hash` of each type, and `quantum_energy::MaybeLabelled` for a receipt in any form. ### 3.1 Primitives - `H(x)` is BLAKE3 in its hash mode, 32 bytes. - `u8(n)`, `u32(n)`, `u64(n)` are unsigned integers and `i64(n)` a two's-complement integer, each **big-endian**, of 1, 4, 8 and 8 bytes. - `str(s)` is the UTF-8 bytes of `s` followed by one byte `0x00`. A string framed so must hold no U+0000 (§3.6). - `opt(h)` is `0x01 ‖ h` for a hash `h` (32 bytes), and `0x00` for none. - `grant(g)` is `grant_hash ‖ str(capability) ‖ u64(joule_ceiling_micro) ‖ f`, `f` being `0x01 ‖ u64(funds_ceiling)`, or `0x00` for no funds ceiling. - `tail(r)` is `grant(r.grant) ‖ opt(parent_receipt_hash) ‖ signer_pubkey ‖ signer_id`: the 32 key bytes, then the signer's label in UTF-8 with **no** terminator (it ends the payload). - A domain is ASCII followed by the version byte `0x01`. `D'` is `D` itself in the legacy form, and `D` with its last byte `0x01` replaced by `0x02` in the labelled and unmetered forms (§3.5). `E` is what follows the figure: nothing in the legacy form, the class's signed encoding in the labelled form, and the unmetered form's tag and reason (§3.5). - The signature is Ed25519 over the **payload bytes** themselves (not a digest of them), verified **strictly**, by [the provider protocol's rule](quantum-providers.md) §8.2 *The signature, strictly*: SPEC §7 *Signatures* with the key held to the prime-order subgroup, `S` < ℓ, `R` canonical and not of small order, and no cofactor. ### 3.2 Reading a receipt A receipt is JSON (RFC 8259), its text UTF-8, its value an object. The reference writes its members in the order of the table below, with no space, but the order and the spacing are not read. The receipt does **not read** when any of these holds; the reason is §3.6's: 1. the text is not UTF-8, not JSON, or its value is not an object; or a string in it has an escape that is no Unicode scalar value (a lone surrogate); or an object in it names a member twice, two names being the same when their escapes read as the same characters (`"a"` and `"a"`) (`unreadable`); 2. `kind` is absent, or is not the kind's string below (`kind`); 3. a member the kind requires is absent, or not of its form (`member`): - a **digest** is a string of exactly 64 lower-case hex digits (`0`–`9`, `a`–`f`); `sig` is one of 128, and `signer_pubkey` one of 64; - a **count** is a JSON number written as an integer: digits only, with no sign, fraction or exponent, of value 0 to 2^64 − 1 (`1.0`, `1e0`, `-0` and `+1` are not counts); a **u32 count** (`rounds`, `swaps`, `atoms_moved`) is a count of at most 2^32 − 1, and one past it does not read (it is never read as its low bits); - a **signed integer** (`raw_estimate_fx`, `mitigated_estimate_fx`, `error_bar_fx`) is a JSON number written as an integer, an optional `-` then digits, of value −2^63 to 2^63 − 1, and not `-0`; - a **string** is a JSON string; a **boolean** is `true` or `false`; - an **optional digest** (`parent_receipt_hash`, `calibration_ref`, `noise_model_hash`) is absent or `null` for none, or a digest; any other value does not read; - `grant` is an object with `grant_hash` (a digest), `capability` (a string), `joule_ceiling_micro` (a count) and `funds_ceiling`, absent or `null` for none or a count, any other value not reading; - `evidence` is an array, each entry an object with `kind` (a string), `blob_hash` (a digest) and `summary` (a string); 4. the energy members break §3.5's reading (`energy_form`). | `kind` | record | members it requires, beside `kind`, `grant`, `joules_micro`, `parent_receipt_hash`, `sig`, `signer_id`, `signer_pubkey` | |---|---|---| | `quantum-calibration` | §1.1 | `config_hash`, `device_id`, `evidence`, `merkle_root`, `target` | | `quantum-job` | §1.2 | `backend_id`, `calibration_ref` (optional), `circuit_hash`, `merkle_root`, `result_hash`, `shots` | | `quantum-mitigate` | §1.3 | `backend_id`, `error_bar_fx`, `input_hash`, `merkle_root`, `method`, `mitigated_estimate_fx`, `noise_model_hash` (optional), `observable`, `raw_estimate_fx`, `shots` | | `quantum-decode` | §1.4 | `check_matrix_hash`, `code_id`, `converged`, `correction_hash`, `decoder`, `rounds`, `syndrome_hash`, `work_messages` | | `quantum-compile` | §1.5 | `coupling_hash`, `equivalent`, `method`, `source_hash`, `swaps`, `target_hash`, `work` | | `quantum-rearrange` | §1.6 | `atoms_moved`, `initial_hash`, `method`, `plan_hash`, `success`, `target_hash`, `total_distance` | **What is read and decides nothing.** These are not sealed, and a verifier does not read them: - `receipt_hash`, which every form writes: the identity, for a reader's convenience. A verifier computes the identity itself (§3.4), and an application that keys receipts by identity MUST compute it, never take the written one; - `merkle_root` of a decode, compile or rearrange receipt: written for a reader, and computed by a verifier (§3.3) where the payload holds it; - each evidence entry's `summary`, a human sentence: change it and the receipt still verifies, so a reader MUST NOT present it as attested; - any member the table and §3.5 do not name. ### 3.3 The payloads Each kind's payload, in its form (§3.5). `M(l)` is the Merkle root of the list of hashes `l`: each hash `h` becomes the leaf `H("moq-jwp:merkle-leaf" ‖ 0x01 ‖ h)`; while a level holds more than one node, an odd level repeats its last node, and each pair `a, b` becomes `H("moq-jwp:merkle-node" ‖ 0x01 ‖ a ‖ b)`; one node is the root. (The lists here are never empty.) | kind | domain `D` | payload | |---|---|---| | calibration | `wai:quantum-calibration` | `D' ‖ str(device_id) ‖ str(target) ‖ config_hash ‖ merkle_root ‖ u64(number of evidence entries) ‖ u64(joules_micro) ‖ E ‖ tail` | | job | `wai:quantum-job` | `D' ‖ str(backend_id) ‖ circuit_hash ‖ result_hash ‖ opt(calibration_ref) ‖ u64(shots) ‖ merkle_root ‖ u64(joules_micro) ‖ E ‖ tail` | | mitigate | `wai:quantum-mitigate` | `D' ‖ str(backend_id) ‖ str(method) ‖ str(observable) ‖ input_hash ‖ opt(noise_model_hash) ‖ i64(raw_estimate_fx) ‖ i64(mitigated_estimate_fx) ‖ i64(error_bar_fx) ‖ u64(shots) ‖ merkle_root ‖ u64(joules_micro) ‖ E ‖ tail` | | decode | `wai:quantum-decode` | `D' ‖ str(code_id) ‖ str(decoder) ‖ check_matrix_hash ‖ syndrome_hash ‖ correction_hash ‖ u8(converged) ‖ u32(rounds) ‖ u64(work_messages) ‖ M([check_matrix_hash, syndrome_hash, correction_hash]) ‖ u64(joules_micro) ‖ E ‖ tail` | | compile | `wai:quantum-compile` | `D' ‖ source_hash ‖ target_hash ‖ coupling_hash ‖ str(method) ‖ u8(equivalent) ‖ u32(swaps) ‖ u64(work) ‖ M([source_hash, target_hash, coupling_hash]) ‖ u64(joules_micro) ‖ E ‖ tail` | | rearrange | `wai:quantum-rearrange` | `D' ‖ initial_hash ‖ target_hash ‖ plan_hash ‖ str(method) ‖ u8(success) ‖ u32(atoms_moved) ‖ u64(total_distance) ‖ M([initial_hash, target_hash, plan_hash]) ‖ u64(joules_micro) ‖ E ‖ tail` | A boolean is `u8` 1 for `true` and 0 for `false`. The `merkle_root` a calibration, job or mitigation receipt writes is the one its payload holds, and it must be the root of its leaves: - calibration: `[config_hash]` followed by, for each evidence entry in order, `H("wai:qcal-evidence" ‖ 0x01 ‖ str(kind) ‖ blob_hash)`; - job: `[circuit_hash, result_hash]`, followed by `calibration_ref` when there is one; - mitigation: `[input_hash]`, then `noise_model_hash` when there is one, then the result leaf `H("wai:quantum-mitigate-result" ‖ 0x01 ‖ str(method) ‖ i64(raw_estimate_fx) ‖ i64(mitigated_estimate_fx) ‖ i64(error_bar_fx))`. ### 3.4 The identity A receipt's identity, its `receipt_hash`, is `H(I ‖ payload ‖ sig)`, with `I` the kind's identity domain (`wai:quantum-calibration-id`, `wai:quantum-job-id`, `wai:quantum-mitigate-id`, `wai:quantum-decode-id`, `wai:quantum-compile-id`, `wai:quantum-rearrange-id`, each followed by `0x01` in every form) and `payload` the payload of the form it is in (§3.5). Another receipt names this one by its identity: a `parent_receipt_hash`, or a job's `calibration_ref`. ### 3.5 Energy: a figure, or unmetered, never zero for a run nobody read A receipt is in one of three forms, which its JSON decides: | form | its JSON | `E` (§3.1) and `D'` | |---|---|---| | **a figure, unlabelled** (the legacy form) | `joules_micro` a count; no `energy_` member | nothing; `D` | | **a figure, labelled** ([energy-measurement](energy-measurement.md) §2.8) | `joules_micro` a count of at least 1; `energy_provenance` and its evidence (energy-measurement §2.7) | the class's signed encoding (energy-measurement §2.7); `D` with `0x02` | | **unmetered** | `joules_micro` `null`; `energy_unmetered`, the reason, a string | `u8(0) ‖ u32(byte length of the reason) ‖ the reason in UTF-8`; `D` with `0x02` | The labelled form's class is `ModelBased` (tag 2), `Estimator` (3), `OnChipCounter` (4, then `u32(relative_ppm) ‖ u64(window_us) ‖ u8(filtering)`, filtering 0 `Unknown`, 1 `Off`, 2 `On`) or `CalibratedInstrument` (5, then `u32(relative_ppm) ‖ u64(window_us) ‖ u32(byte length of the reference) ‖ the reference in UTF-8`). The unmetered form seals its figure as `0` and its tag as energy-measurement §2.7's tag `0`, no class, followed by the reason. **Reading the energy members** (§3.2, `energy_form`). Of `energy_provenance`, `energy_uncertainty`, `energy_counter_filtering` and `energy_calibration_ref`, one whose value is `null` is read as absent. - With `energy_unmetered` present, whatever its value: it is a string; `joules_micro` is present and `null`; and none of the four class members is present. The figure is read as `0`. - Otherwise, with `energy_provenance`: it is one of the four names above (`HwShunt`, the legacy label, never labels these receipts, and any other name does not read); `energy_uncertainty`, when present, is an object whose `relative_ppm` is a u32 count and whose `window_us` is a count; `energy_counter_filtering`, when present, is `Unknown`, `Off` or `On`; `energy_calibration_ref`, when present, is a string. `ModelBased` and `Estimator` have none of the three; `OnChipCounter` has `energy_uncertainty`, may have `energy_counter_filtering` (`Unknown` when absent) and has no reference; `CalibratedInstrument` has `energy_uncertainty` and `energy_calibration_ref` and no filtering. A declared `relative_ppm` and `window_us` are each at least 1, and a reference is not empty once the characters of Unicode's `White_Space` property are taken from both its ends. - Otherwise, any of the three evidence members without `energy_provenance` does not read; with none, the receipt is in the legacy form. **What each form says, and how a `0` is read.** - A run nobody measured is sealed in the **unmetered form**, saying why. Its JSON holds no zero: `joules_micro` is `null`. A producer MUST NOT seal a new unmetered run as an unlabelled `0`. - An unlabelled receipt whose `joules_micro` is `0` is the **legacy form of the same statement**: unmetered, legacy, sealed before the unmetered form existed. It verifies as it always did, and a reader MUST present it as unmetered (legacy), never as a figure of zero joules, and MUST NOT total, average or compare it as 0 J (energy-measurement §2). - An unlabelled receipt with a figure of at least 1 is a figure with no class; a labelled one is a figure with its class. No form states a measured zero: a meter that read nothing produced no reading, and the receipt is unmetered. The reference reads either unmetered form through `MaybeLabelled::unmetered()` (the reason, or that the receipt is of the legacy form) and gives a figure only through `MaybeLabelled::joules_micro()`, which is never `Some(0)`. ### 3.6 What a verifier checks A verifier reads the receipt (§3.2, §3.5) and then checks, in its form: | reason | when | |---|---| | `unreadable`, `kind`, `member`, `energy_form` | the receipt does not read (§3.2). Reported alone: nothing else is checked | | `string_nul` | a string `str()` frames (§3.1) holds U+0000: `device_id`, `target`, an evidence entry's `kind`, `backend_id`, `method`, `observable`, `code_id`, `decoder`, or the grant's `capability`. Such a string could be read as two, so that two receipts would sign the same bytes | | `merkle_root` | a calibration, job or mitigation receipt's `merkle_root` is not the root of its leaves (§3.3) | | `ceiling` | `joules_micro` is more than the grant's `joule_ceiling_micro` (§2) | | `energy` | the labelled form's figure is `0` (a class beside no figure), or its declared uncertainty is below the resolution floor, `joules_micro × relative_ppm` < 288 676 (energy-measurement §2.3); or the unmetered form's reason is empty or more than 4096 bytes | | `bad_key` | `signer_pubkey` is refused by the strict rule's checks of the key (§3.1). The signature is then not checked | | `bad_signature` | the signature over the payload of the receipt's form does not hold, strictly | The receipt is **valid** exactly when there is no reason. The reference's `verify()` (of each type, of `Labelled`, of `Unmetered`, and of `MaybeLabelled`) is true exactly then, and its `from_json` gives `None` exactly when the receipt does not read. A receipt whose label or reason was added, stripped or restated after it was sealed fails `bad_signature`: the form is inside the signature through `D'` and `E`. ### 3.7 Links and content Beside a receipt's own validity, a verifier given more checks more: - **content**: given the bytes a hash binds (a configuration, a dataset, a circuit, a result, a plan), `H(bytes)` equals that hash (`evidence_matches`, `result_matches`, `input_matches`, `noise_model_matches`, `code_matches`, `correction_matches`, `source_matches`, `target_matches`, `plan_matches`); - **lineage**: given the receipt a `parent_receipt_hash` names, it is that receipt's identity (§3.4) in the form it was sealed in; - **the calibration a job ran under**: given a calibration receipt, the job's `calibration_ref` is its identity and both are valid (`verify_against_calibration`, which `MaybeLabelled` gives for every form of each). ## 4. Conformance - A **conforming producer** (a control stack, or an adapter over one, §6) MUST seal a receipt per operation it attests, with every hash the real content hash; `joules_micro` a figure it read, with its class where it has one, and never fabricated; and a run it did not read in the unmetered form, saying why (§3.5), never as `0`. - A **conforming verifier** MUST read a receipt by §3.2 and §3.5, MUST give it exactly §3.6's reasons, MUST read an unlabelled `0` as unmetered (legacy) and present no unmetered run as zero joules, and, for a job that claims a calibration state it is given, MUST check §3.7's link. - Receipts are **portable**: JSON, verifiable with the public key and the bytes they bind. - **The corpus**, [`../quantum-ops-conformance/`](../quantum-ops-conformance/): receipts of every kind and every energy form made by the reference (`vectors/`, pinned in `expected_hashes.json` with the artifacts each binds and its links), and receipts derived from them each one defect away, with the reason §3.6 gives it, or one change §3.2 says decides nothing (`crafted/`). The reference (`wai_quantum_ops_vectors verify`) gives every one its verdict; `ops_verify.py`, written from this section alone and sharing no code with the engine, gives every one its verdict and its exact reasons. ## 5. What this is NOT - **Not a control system, not a simulator, not a calibration learner.** It attests operations others perform. The control electronics and the tuning models are the dispatched **backend**: WAI's "don't reinvent, dispatch" (SPEC Appendix B), applied to quantum control. - **Not a reconstruction.** `joules_micro` and the results are *attested* (only the signer can vouch for its own silicon's draw); the hashes, the Merkle root, the grant ceiling and the links are *verifiable* by anyone. The receipt states plainly which half is which. ## 6. Integration (where it attaches) The natural attach point is the **control-system → cloud boundary**: the moment a calibration node or a job completes, the control system already holds everything a receipt needs (configuration, evidence datasets, result, backend identity), and its power rails are already instrumented, so adding a signature and a joule figure is *incremental*. In an open calibration framework, three points do it: the one place a node writes its dataset, which covers every node; the per-node boundary where the framework records the versions of the packages that ran; and, in a lab's task and database layer, the point where a production test records its pass or fail. ## 7. The metric This extension carries joules per verified calibration, per job, per mitigation, per decode, per compile and per rearrangement as signed, portable, content-addressed, grant-bounded records, and says so where nobody measured them. ## 8. What is not part of this extension Two more records the reference seals are **not part of the standard**: their labels are not registered, no text specifies their encoding, and no verifier other than the reference's is held to them. - `wai.quantum.qbom`, the reference's bill of materials (`quantum_qbom`): a manifest restating the stage receipts of one computation, each entry's figure with its optional class (energy-measurement §2.8). Its entries name the receipts of §1 by their identities (§3.4), and those receipts are what this extension attests. - `wai.quantum.fabric`, the reference's statement of where a result ran (`quantum_fabric`): the fabric member, its kernel, the parity its certificate earned against the CPU reference, and the joules. A later revision may register either with a text and vectors of its own.