open-standards/wai/wai-quantum-serve/src/lib.rs
Transaction Science 3f275c7cfd wai-quantum circuit2: the browser sink, the IDE and the serve component follow the gateset
QuantumSink reads WQC1 and WQC2 containers. It reports the capability the
magic names and the circuit hash. A refused container throws a message that
names its error class, the word reject.json lists.

QuantumIde builds in circuit2 by default. set_gateset(1) moves the current
circuit and every later build to circuit/1, and gateset() and capability()
report it. The debugger's prefix circuit keeps the IDE's gateset. add() stores
no parameter on a gate other than P, so an editor's leftover parameter no
longer makes a circuit2 circuit invalid. circuit_hash_hex() is empty for an
invalid circuit. A circuit/1 circuit with P(k>=8) gets the command-line
tool's note on the browser console, once per circuit state, never in a
returned value.

wai-quantum-serve takes gateset=v1 or v2 (default v2) on /run, /qasm and
/receipt. /run names the capability in its JSON, and /run and /receipt name
it in a wai-capability header. The /receipt body stays the receipt JSON
alone, so it is still the bytes a native seal gives. An unknown gateset or a
circuit with no circuit hash is a 400.

Native tests cover both corpora, the reject corpus, the IDE's gateset
switching, the add() parameter rule, the empty hash, and the serve
endpoints against the corpus GHZ3 hashes. The wai-web native test count in
CI moves from 24 to 31, and that workflow now triggers on changes to the
quantum corpora it reads.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 13:05:18 -04:00

578 lines
25 KiB
Rust

//! The WAI quantum stack as a **WASI-HTTP component** — deterministic quantum
//! computation as a serverless function.
//!
//! This is the same Rust that runs natively and in the browser, exported through
//! `wasi:http/proxy` so any component-model host can serve it (`wasmtime serve`
//! and other WASI-HTTP runtimes). The results are not merely "equivalent": the
//! statevector hashes and the signed receipt bytes are **identical** to a native
//! run, because the computation is reproducible rather than negotiated.
//!
//! ```text
//! GET / service description
//! GET /health liveness
//! GET /algorithms the algorithm catalog
//! GET /run?algo=ghz&n=5&top=8 simulate; JSON with statevector hash + outcomes
//! POST /run body = OpenQASM 3.0
//! GET /qasm?algo=bell&n=2 emit OpenQASM 3.0
//! GET /receipt?algo=ghz&n=3 seal a signed, energy-accounted receipt
//! POST /verify body = receipt JSON → verdict
//! ```
//!
//! `/run` (both forms), `/qasm` and `/receipt` take `gateset=v2` (the default,
//! `wai.quantum.circuit2`) or `gateset=v1` (the frozen `wai.quantum.circuit`),
//! and build the circuit in it; any other value is a 400. The circuit hash, the
//! statevector and the receipt follow the gateset. `/run` names the capability
//! in its JSON as `"capability"`, and `/run` and `/receipt` name it in a
//! `wai-capability` response header. The `/receipt` body stays the receipt JSON
//! alone, so it is the same bytes a native run seals. A circuit whose hash
//! cannot be computed is a 400.
//!
//! `POST /verify` accepts a receipt in either form: as sealed, or with its
//! joule figure's acquisition class inside the signature
//! (`quantum_energy::Labelled`), and restates the class in its verdict. It
//! reports `signer_id` as the signer's own label, beside the level a
//! confirmation of the signer reached (`extensions/jwp-receipts.md` §7): this
//! handler holds no key log, so a valid receipt's signer is never more than
//! `unconfirmed`, with the reason it stopped at.
use ed25519_dalek::SigningKey;
use wai::quantum::{Circuit, Gateset, Measure};
use wai::quantum_energy::MaybeLabelled;
use wai::quantum_receipt::QuantumReceipt;
use wai::quantum_toolchain as qt;
use wasi::http::types::{
Fields, IncomingBody, IncomingRequest, Method, OutgoingBody, OutgoingResponse,
ResponseOutparam,
};
wasi::http::proxy::export!(Component);
struct Component;
/// The `POST /verify` verdict for a receipt JSON body: an HTTP status and a
/// JSON body — 200 valid, 409 invalid, 400 unparseable.
///
/// Either form verifies: a receipt as sealed, or one whose joule figure
/// carries its acquisition class inside the signature
/// (`quantum_energy::Labelled`, as the reference quantum meter emits). The
/// verdict restates the class and its evidence, or `"energy_provenance":null`
/// for a figure with no class.
///
/// A receipt's `joules_micro` of `0` is its unmetered marker, never a figure of
/// zero joules (energy-measurement §2), so the verdict renders it as
/// `"joules_micro":null` with `"metered":false`: a client totalling or comparing
/// the field cannot read an unmetered run as free work.
///
/// Beside `signer_id` the verdict reports `signer_level` and `signer_reason`
/// (jwp-receipts §7.1, §7.4): `unconfirmed` and `signer_id_not_origin_bound`
/// for a label or a `did:key`, `refused` and `signer_id_names_another_key`
/// for a `did:key` of another key, and `unconfirmed` and `origin_not_anchored`
/// for an origin-bound id, since the handler anchors no origin. Both are
/// `null` when the receipt is not valid.
fn verify_response(src: &str) -> (u16, String) {
let Some(any) = MaybeLabelled::<QuantumReceipt>::from_json(src) else {
return (400, "{\"valid\":false,\"reason\":\"unparseable receipt\"}".to_string());
};
let ok = any.verify();
let r = any.receipt();
let (joules, metered) = match r.joules_micro {
0 => ("null".to_string(), false),
j => (j.to_string(), true),
};
let signer = if ok {
let (level, reason) = wai::signer_id::level_without_anchors(&r.signer_id, &r.signer_pubkey);
format!("\"signer_level\":\"{}\",\"signer_reason\":\"{reason}\"", level.label())
} else {
"\"signer_level\":null,\"signer_reason\":null".to_string()
};
let class = match any.energy_class() {
None => "\"energy_provenance\":null".to_string(),
Some(c) => c.json_fields().iter().map(|(k, v)| format!("\"{k}\":{v}")).collect::<Vec<_>>().join(","),
};
(
if ok { 200 } else { 409 },
format!(
"{{\"valid\":{},\"circuit_hash\":\"{}\",\"statevector_hash\":\"{}\",\
\"n_qubits\":{},\"n_ops\":{},\"work_amp_updates\":{},\"joules_micro\":{joules},\"metered\":{metered},\"signer_id\":\"{}\",{signer},{class}}}",
ok,
hx(&r.circuit_hash),
hx(&r.statevector_hash),
r.n_qubits,
r.n_ops,
r.work_amp_updates,
esc(&r.signer_id)
),
)
}
fn hx(b: &[u8]) -> String {
b.iter().map(|x| format!("{x:02x}")).collect()
}
/// Minimal JSON string escaping for the values we emit (ids, names, prose).
fn esc(s: &str) -> String {
let mut o = String::with_capacity(s.len() + 8);
for c in s.chars() {
match c {
'"' => o.push_str("\\\""),
'\\' => o.push_str("\\\\"),
'\n' => o.push_str("\\n"),
'\r' => o.push_str("\\r"),
'\t' => o.push_str("\\t"),
c if (c as u32) < 0x20 => o.push_str(&format!("\\u{:04x}", c as u32)),
c => o.push(c),
}
}
o
}
/// The response header that names the capability a circuit was built in.
const CAPABILITY_HEADER: &str = "wai-capability";
fn send(out: ResponseOutparam, status: u16, ctype: &str, capability: Option<&str>, body: &[u8]) {
let hdrs = Fields::new();
let _ = hdrs.append("content-type", &ctype.as_bytes().to_vec());
if let Some(c) = capability {
let _ = hdrs.append(CAPABILITY_HEADER, &c.as_bytes().to_vec());
}
let resp = OutgoingResponse::new(hdrs);
let _ = resp.set_status_code(status);
let Ok(rbody) = resp.body() else { return };
ResponseOutparam::set(out, Ok(resp));
if let Ok(stream) = rbody.write() {
// chunk the write: blocking_write_and_flush caps at the stream's permit
for chunk in body.chunks(4000) {
if stream.blocking_write_and_flush(chunk).is_err() {
break;
}
}
drop(stream);
}
let _ = OutgoingBody::finish(rbody, None);
}
fn json(out: ResponseOutparam, status: u16, body: String) {
send(out, status, "application/json", None, body.as_bytes());
}
/// The JSON body of an error response.
fn err_body(msg: &str) -> String {
format!("{{\"error\":\"{}\"}}", esc(msg))
}
fn err(out: ResponseOutparam, status: u16, msg: &str) {
json(out, status, err_body(msg));
}
/// An answer computed apart from the WASI types, so the native tests can check
/// it: the status, the JSON body and, for a circuit that was built, the
/// capability it was built in.
struct Reply {
status: u16,
body: String,
capability: Option<&'static str>,
}
impl Reply {
fn error(status: u16, msg: &str) -> Reply {
Reply { status, body: err_body(msg), capability: None }
}
fn send(self, out: ResponseOutparam) {
send(out, self.status, "application/json", self.capability, self.body.as_bytes());
}
}
fn read_body(body: IncomingBody) -> Vec<u8> {
let mut buf = Vec::new();
if let Ok(stream) = body.stream() {
loop {
match stream.blocking_read(8192) {
Ok(chunk) if chunk.is_empty() => break,
Ok(chunk) => {
buf.extend_from_slice(&chunk);
if buf.len() > 4 << 20 {
break; // 4 MiB cap
}
}
Err(_) => break, // stream closed = EOF
}
}
}
buf
}
/// `name=value` pairs from a `path?query` string (percent-decoding `%XX` and `+`).
fn query(pq: &str, key: &str) -> Option<String> {
let q = pq.split_once('?')?.1;
for pair in q.split('&') {
let (k, v) = pair.split_once('=').unwrap_or((pair, ""));
if k == key {
return Some(pct(v));
}
}
None
}
fn pct(s: &str) -> String {
let b = s.as_bytes();
let mut o = Vec::with_capacity(b.len());
let mut i = 0;
while i < b.len() {
match b[i] {
b'%' if i + 2 < b.len() => {
let hi = (b[i + 1] as char).to_digit(16);
let lo = (b[i + 2] as char).to_digit(16);
match (hi, lo) {
(Some(h), Some(l)) => {
o.push((h * 16 + l) as u8);
i += 3;
}
_ => {
o.push(b[i]);
i += 1;
}
}
}
b'+' => {
o.push(b' ');
i += 1;
}
c => {
o.push(c);
i += 1;
}
}
}
String::from_utf8_lossy(&o).into_owned()
}
fn qnum<T: std::str::FromStr>(pq: &str, key: &str, dflt: T) -> T {
query(pq, key).and_then(|v| v.parse().ok()).unwrap_or(dflt)
}
/// The gateset `?gateset=` names: `v2` (`wai.quantum.circuit2`, the default)
/// or `v1` (the frozen `wai.quantum.circuit`). Any other value is an error.
fn gateset(pq: &str) -> Result<Gateset, String> {
match query(pq, "gateset").as_deref() {
None | Some("v2") => Ok(Gateset::V2),
Some("v1") => Ok(Gateset::V1),
Some(other) => Err(format!("unknown gateset '{other}' (v1, v2)")),
}
}
/// Move a built circuit into the gateset the request names. The builders make
/// circuit2 circuits with distinct controls and no parameter on a gate other
/// than `P`, which are valid circuit/1 circuits too.
fn in_gateset(mut c: Circuit, pq: &str) -> Result<Circuit, String> {
c.gateset = gateset(pq)?;
Ok(c)
}
fn build(pq: &str) -> Result<Circuit, String> {
let algo = query(pq, "algo").ok_or("missing ?algo= (see /algorithms)")?;
let n: u8 = qnum(pq, "n", 3);
let p: u32 = qnum(pq, "p", 0);
let c = qt::build_algorithm(&algo, n, p).ok_or(format!("unknown algorithm '{algo}'"))?;
in_gateset(c, pq)
}
/// The simulation result as JSON — the same fields the CLI prints.
fn run_json(c: &Circuit, top: usize) -> Result<String, String> {
c.validate().map_err(|e| format!("invalid circuit: {e:?}"))?;
let id = qt::circuit_id(c).map_err(|e| format!("circuit id: {e}"))?;
let sv = c.simulate().map_err(|e| format!("simulate: {e:?}"))?;
let (backend, why) = qt::recommend_backend(c);
let n = c.n_qubits as usize;
let items: Vec<String> = qt::top_outcomes(&sv, top)
.iter()
.map(|(k, p)| format!("{{\"state\":\"{k:0n$b}\",\"p\":{p}}}", n = n))
.collect();
Ok(format!(
"{{\"circuit_id\":\"{}\",\"capability\":\"{}\",\"n_qubits\":{},\"n_gates\":{},\"backend\":\"{backend:?}\",\
\"backend_reason\":\"{}\",\"work_amp_updates\":{},\"statevector_hash\":\"{}\",\"top\":[{}]}}",
hx(&id),
c.gateset.capability(),
c.n_qubits,
c.ops.len(),
esc(why),
qt::statevector_work(c),
hx(&sv.statevector_hash()),
items.join(",")
))
}
/// `/run`: 200 and the run JSON for the circuit the request built, or 400.
fn run_reply(built: Result<Circuit, String>, top: usize) -> Reply {
match built.and_then(|c| run_json(&c, top).map(|body| (c.gateset, body))) {
Ok((gs, body)) => Reply { status: 200, body, capability: Some(gs.capability()) },
Err(e) => Reply::error(400, &e),
}
}
/// `/receipt`: 200 and the sealed receipt JSON, or 400 for a request that
/// names no circuit or an unknown gateset, or a circuit the seal refuses.
fn receipt_reply(pq: &str) -> Reply {
let c = match build(pq) {
Ok(c) => c,
Err(e) => return Reply::error(400, &e),
};
let shots: u64 = qnum(pq, "shots", 0);
let seed: u64 = qnum(pq, "seed", 0);
seal_reply(&c, (shots > 0).then_some(Measure { seed, shots }))
}
/// Seal `c`: 200 and the receipt JSON, or 400 when the seal refuses the
/// circuit. Every refusal is the circuit's own: one its gateset does not allow,
/// so it has no circuit hash, or one too large to simulate.
fn seal_reply(c: &Circuit, measure: Option<Measure>) -> Reply {
// Deterministic demo key so the sealed bytes match a native run.
let key = SigningKey::from_bytes(&[42u8; 32]);
match QuantumReceipt::seal(&key, "did:key:wai-quantum-cli", c, measure, 0, None) {
Ok(r) => Reply { status: 200, body: r.to_json(), capability: Some(c.gateset.capability()) },
Err(e) => Reply::error(400, &format!("seal: {e}")),
}
}
impl wasi::exports::http::incoming_handler::Guest for Component {
fn handle(req: IncomingRequest, out: ResponseOutparam) {
let method = req.method();
let pq = req.path_with_query().unwrap_or_else(|| "/".into());
let path = pq.split('?').next().unwrap_or("/").to_string();
let is_post = matches!(method, Method::Post);
match (is_post, path.as_str()) {
(false, "/") => json(
out,
200,
"{\"service\":\"wai-quantum\",\"kind\":\"wasi:http/proxy component\",\
\"deterministic\":true,\"note\":\"statevector hashes and receipt bytes are identical to a native run\",\
\"gateset\":{\"default\":\"v2\",\"v2\":\"wai.quantum.circuit2\",\"v1\":\"wai.quantum.circuit\"},\
\"endpoints\":[\"/health\",\"/algorithms\",\"/run?algo=ghz&n=5\",\"/qasm?algo=bell\",\"/receipt?algo=ghz&n=3\",\"POST /run (OpenQASM)\",\"POST /verify (receipt JSON)\"]}"
.to_string(),
),
(false, "/health") => json(out, 200, "{\"ok\":true}".to_string()),
(false, "/algorithms") => {
let items: Vec<String> = qt::catalog()
.iter()
.map(|(id, name, desc)| {
format!(
"{{\"id\":\"{}\",\"name\":\"{}\",\"description\":\"{}\"}}",
esc(id),
esc(name),
esc(desc)
)
})
.collect();
json(out, 200, format!("{{\"algorithms\":[{}]}}", items.join(",")));
}
(false, "/run") => run_reply(build(&pq), qnum(&pq, "top", 8usize)).send(out),
(true, "/run") => {
let top = qnum(&pq, "top", 8usize);
let Ok(body) = req.consume() else {
return err(out, 400, "no body");
};
let src = String::from_utf8_lossy(&read_body(body)).into_owned();
let built = qt::from_qasm(&src).map_err(|e| format!("QASM parse: {e}"));
run_reply(built.and_then(|c| in_gateset(c, &pq)), top).send(out)
}
(false, "/qasm") => match build(&pq) {
Err(e) => err(out, 400, &e),
Ok(c) => send(out, 200, "text/plain; charset=utf-8", None, qt::to_qasm(&c).as_bytes()),
},
(false, "/receipt") => receipt_reply(&pq).send(out),
(true, "/verify") => {
let Ok(body) = req.consume() else {
return err(out, 400, "no body");
};
let src = String::from_utf8_lossy(&read_body(body)).into_owned();
let (status, verdict) = verify_response(&src);
json(out, status, verdict)
}
_ => err(out, 404, "not found — GET / for the endpoint list"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use wai::quantum::{circuit_hash, BaseGate, Gate};
use wai::quantum_energy::{CounterFiltering, EnergyClass, Labelled, Uncertainty};
fn ghz3() -> Circuit {
let mut c = Circuit::new(3);
c.h(0).cx(0, 1).cx(1, 2);
c
}
/// GHZ3's circuit and statevector hashes in each capability, as the
/// conformance corpora state them (`v2/expected_hashes.json` and
/// `expected_hashes.json`).
const GHZ3_V2: (&str, &str) = (
"c5911b898a899c999ce01730bb825c84678569493ac513760e15dcbccd84227f",
"51850f28817200e9e03980b60f34879c7bd0147a07b0c1746528b801cae2e2f8",
);
const GHZ3_V1: (&str, &str) = (
"34e44f7d68037cbb3aee677f56b894dc48df6d408aa068a16d3b18076e5e7c5c",
"08c5e6fb50b91a00d28795506cc5d99ce1e9a3a8b4c41e4bfd05f5d829af9542",
);
#[test]
fn the_gateset_parameter_defaults_to_circuit2_and_names_no_other() {
assert_eq!(gateset("/run?algo=bell"), Ok(Gateset::V2));
assert_eq!(gateset("/run?algo=bell&gateset=v2"), Ok(Gateset::V2));
assert_eq!(gateset("/run?gateset=v1&algo=bell"), Ok(Gateset::V1));
for bad in ["v3", "V1", "", "circuit2", "wai.quantum.circuit"] {
let e = gateset(&format!("/run?algo=bell&gateset={bad}")).unwrap_err();
assert!(e.contains("unknown gateset"), "{bad}: {e}");
}
// The OpenQASM body of `POST /run` takes the query's gateset too.
let c = qt::from_qasm("OPENQASM 3.0;\nqubit[3] q;\nh q[0];\ncx q[0], q[1];\ncx q[1], q[2];\n").unwrap();
assert_eq!(in_gateset(c.clone(), "/run?gateset=v1").unwrap().gateset, Gateset::V1);
assert_eq!(in_gateset(c.clone(), "/run").unwrap().gateset, Gateset::V2);
assert!(in_gateset(c, "/run?gateset=v0").is_err());
}
/// `/run` builds in the gateset the request names and says which, in its
/// JSON and its header; its hashes are the corpus's for that capability.
#[test]
fn run_names_its_capability_and_reproduces_the_corpus() {
for (q, capability, (circuit, statevector)) in [
("/run?algo=ghz&n=3", "wai.quantum.circuit2", GHZ3_V2),
("/run?algo=ghz&n=3&gateset=v2", "wai.quantum.circuit2", GHZ3_V2),
("/run?algo=ghz&n=3&gateset=v1", "wai.quantum.circuit", GHZ3_V1),
] {
let r = run_reply(build(q), 8);
assert_eq!((r.status, r.capability), (200, Some(capability)), "{q}: {}", r.body);
assert!(
r.body.starts_with(&format!("{{\"circuit_id\":\"{circuit}\",\"capability\":\"{capability}\",\"n_qubits\":3,")),
"{q}: {}",
r.body
);
assert!(r.body.contains(&format!("\"statevector_hash\":\"{statevector}\"")), "{q}: {}", r.body);
}
let r = run_reply(build("/run?algo=ghz&n=3&gateset=v9"), 8);
assert_eq!((r.status, r.capability), (400, None));
assert_eq!(r.body, "{\"error\":\"unknown gateset 'v9' (v1, v2)\"}");
}
/// A circuit with no circuit hash is a 400 from `/run` and from the seal,
/// never a 500 or a panic. A repeated control is such a circuit in
/// circuit2, and an ordinary one in circuit/1.
#[test]
fn a_circuit_with_no_hash_is_a_bad_request() {
let mut c = Circuit::new(3);
c.h(0);
c.ops.push(Gate { base: BaseGate::X, controls: vec![0, 0], target: 1, param: 0 });
assert!(circuit_hash(&c).is_err());
let r = run_reply(Ok(c.clone()), 8);
assert_eq!((r.status, r.capability), (400, None), "{}", r.body);
assert!(r.body.contains("invalid circuit"), "{}", r.body);
let r = seal_reply(&c, None);
assert_eq!((r.status, r.capability), (400, None), "{}", r.body);
assert!(r.body.starts_with("{\"error\":\"seal: invalid circuit: "), "{}", r.body);
c.gateset = Gateset::V1;
assert!(circuit_hash(&c).is_ok());
assert_eq!(run_reply(Ok(c.clone()), 8).status, 200);
assert_eq!(seal_reply(&c, None).status, 200);
}
/// `/receipt` seals in the gateset the request names. Its body is the
/// receipt JSON alone, the bytes a native seal of the same circuit gives;
/// the capability rides in the header.
#[test]
fn receipt_seals_in_the_requested_gateset() {
for (q, gs, circuit) in [
("/receipt?algo=ghz&n=3&shots=64&seed=7", Gateset::V2, GHZ3_V2.0),
("/receipt?algo=ghz&n=3&shots=64&seed=7&gateset=v1", Gateset::V1, GHZ3_V1.0),
] {
let r = receipt_reply(q);
assert_eq!((r.status, r.capability), (200, Some(gs.capability())), "{q}: {}", r.body);
let mut c = ghz3();
c.gateset = gs;
let key = SigningKey::from_bytes(&[42u8; 32]);
let native = QuantumReceipt::seal(&key, "did:key:wai-quantum-cli", &c, Some(Measure { seed: 7, shots: 64 }), 0, None).unwrap();
assert_eq!(r.body, native.to_json(), "{q}");
assert!(!r.body.contains("capability"), "{q}");
let parsed = QuantumReceipt::from_json(&r.body).unwrap();
assert!(parsed.verify());
assert_eq!(hx(&parsed.circuit_hash), circuit, "{q}");
assert!(parsed.verify_reconstruction(&c));
}
let r = receipt_reply("/receipt?algo=ghz&n=3&gateset=2");
assert_eq!((r.status, r.capability), (400, None));
assert!(r.body.contains("unknown gateset"), "{}", r.body);
assert_eq!(receipt_reply("/receipt?algo=nope").status, 400);
}
#[test]
fn verify_accepts_both_forms_and_restates_the_class() {
let key = SigningKey::from_bytes(&[0x71u8; 32]);
// As `/receipt` seals it: unmetered, unlabelled.
let r0 = QuantumReceipt::seal(&key, "did:key:wai-quantum-cli", &ghz3(), None, 0, None).unwrap();
let (status, body) = verify_response(&r0.to_json());
assert_eq!(status, 200, "{body}");
assert!(body.contains("\"valid\":true") && body.ends_with("\"energy_provenance\":null}"), "{body}");
// The signer's id is a label: a valid receipt, an unconfirmed signer.
assert!(
body.contains("\"signer_id\":\"did:key:wai-quantum-cli\",\"signer_level\":\"unconfirmed\",\"signer_reason\":\"signer_id_not_origin_bound\""),
"{body}"
);
// As the reference quantum meter emits it: a 1 µJ figure labelled
// OnChipCounter, declaring its own rounding.
let r1 = QuantumReceipt::seal(&key, "did:web:meter", &ghz3(), None, 1, None).unwrap();
let class = EnergyClass::OnChipCounter {
uncertainty: Uncertainty { relative_ppm: 288_830, window_us: 2_930_000 },
filtering: CounterFiltering::Unknown,
};
let l = Labelled::seal(r1, class, &key).unwrap();
let j = l.to_json();
let (status, body) = verify_response(&j);
assert_eq!(status, 200, "{body}");
assert!(body.contains("\"energy_provenance\":\"OnChipCounter\""), "{body}");
assert!(body.contains("\"relative_ppm\":288830") && body.contains("\"energy_counter_filtering\":\"Unknown\""));
// The unlabelled parse alone refuses it: what this handler did before.
assert!(!QuantumReceipt::from_json(&j).unwrap().verify());
// A restated label is refused, and the signer is then reported with no
// level; anything unparseable is refused.
let (status, body) = verify_response(&j.replace("288830", "288831"));
assert_eq!(status, 409);
assert!(body.contains("\"signer_level\":null,\"signer_reason\":null"), "{body}");
assert_eq!(verify_response("not a receipt").0, 400);
// An origin-bound id: valid, but no origin is anchored here.
let r2 = QuantumReceipt::seal(&key, "did:web:publisher.example#q1", &ghz3(), None, 0, None).unwrap();
let (status, body) = verify_response(&r2.to_json());
assert_eq!(status, 200, "{body}");
assert!(body.contains("\"signer_level\":\"unconfirmed\",\"signer_reason\":\"origin_not_anchored\""), "{body}");
// A did:key of another key contradicts the signer_pubkey beside it.
let other = wai::signer_id::did_key(&SigningKey::from_bytes(&[0x72u8; 32]).verifying_key().to_bytes());
let r3 = QuantumReceipt::seal(&key, &other, &ghz3(), None, 0, None).unwrap();
let (_, body) = verify_response(&r3.to_json());
assert!(body.contains("\"signer_level\":\"refused\",\"signer_reason\":\"signer_id_names_another_key\""), "{body}");
}
/// An unmetered receipt's `0` is the unmetered marker: the verdict never
/// presents it as a figure of zero joules.
#[test]
fn an_unmetered_receipt_is_never_reported_as_zero_joules() {
let key = SigningKey::from_bytes(&[0x71u8; 32]);
let r0 = QuantumReceipt::seal(&key, "did:key:wai-quantum-cli", &ghz3(), None, 0, None).unwrap();
let (_, body) = verify_response(&r0.to_json());
assert!(body.contains("\"joules_micro\":null,\"metered\":false"), "{body}");
assert!(!body.contains("\"joules_micro\":0"), "{body}");
let r1 = QuantumReceipt::seal(&key, "did:web:meter", &ghz3(), None, 7, None).unwrap();
let (_, body) = verify_response(&r1.to_json());
assert!(body.contains("\"joules_micro\":7,\"metered\":true"), "{body}");
}
}