open-standards/wai/wai-rs/src/quantum_envelope.rs
Transaction Science 252a9fdeba wai-quantum circuit2: wai-rs registers circuit2 and carries the corpus in both capabilities
The codec registry registers wai.quantum.circuit2 beside wai.quantum.circuit, with
the same media class, tier, licence and replicate class. The registry export, the
vocabulary and the generated REGISTRY.md table are regenerated from it, and SPEC.md
section 5 gains its row and qualifies the circuit/1 row's QFT sentence.

wrap_envelope returns a Result and tags the envelope with the circuit's own
capability. open_envelope decodes the payload and refuses an envelope whose
capability is not the one the container's magic names.

wai_quantum_vectors gen writes the circuit/1 corpus with three table-sensitive
vectors after the four frozen ones, the seven vectors again in circuit2 under v2/,
and 26 reject files with reject.json naming the class each is refused as. verify
checks all three trees: each vector decodes to the capability its entry names and
reproduces its hashes, and each reject file fails with its listed class. The four
original files and their manifest entries are unchanged.

The wai-quantum CLI takes --gateset v1|v2 (default v2) on every command that builds
a circuit and on fabric, reports the capability in its run and fabric JSON, and
prints the circuit/1 table note on standard error only. wai_quantum_meter names the
capability of the circuit it meters.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 12:38:07 -04:00

115 lines
5.6 KiB
Rust

//! Wrapping a quantum circuit in a WAI envelope, and opening one.
//!
//! The computation itself lives in the dependency-light [`wai_quantum`] crate;
//! this is the container half — the part that belongs to WAI, not to quantum.
//!
//! The envelope's capability is the circuit's: `wai.quantum.circuit2` for a
//! [`Gateset::V2`] circuit, whose payload is a `WQC2` container, and
//! `wai.quantum.circuit` for a [`Gateset::V1`] one, whose payload is `WQC1`.
use wai_quantum::quantum::{from_wqc, to_wqc, Circuit, Gateset, Measure, QuantumError};
/// Wrap a circuit in a v1.0 WAI envelope under its gateset's capability
/// ([`Gateset::capability`]). The payload is the circuit's `WQC` container;
/// `intent=replicate` is sound because the reconstruction is byte-exact
/// (statevector-equivalence).
///
/// Fails as [`to_wqc`] does, for a circuit its gateset does not allow, and with
/// [`QuantumError::TooManyQubits`] for a circuit of 64 qubits or more, whose
/// dimension the manifest's `target.dim` cannot hold.
pub fn wrap_envelope(c: &Circuit, measure: Option<Measure>) -> Result<crate::container::Wai, QuantumError> {
use crate::container::{Conditioning, Manifest, ModelRequirement};
let payload = to_wqc(c, measure)?;
let dim = 1u64.checked_shl(u32::from(c.n_qubits)).ok_or(QuantumError::TooManyQubits(c.n_qubits))?;
let manifest = Manifest::new("quantum", "replicate", ModelRequirement::new(c.gateset.capability()), Conditioning::new("wqc"))
.with_target(serde_json::json!({ "n_qubits": c.n_qubits, "dim": dim }));
Ok(crate::container::Wai::new(manifest, payload))
}
/// Open a quantum envelope: decode its `WQC` payload, then require the
/// envelope's capability to be the one the container's magic names.
///
/// A payload that does not decode fails as [`from_wqc`] does. A decoded circuit
/// whose gateset is not the one the capability names — a `WQC2` payload under
/// `wai.quantum.circuit`, a `WQC1` payload under `wai.quantum.circuit2`, or any
/// payload under another capability — is [`QuantumError::Contract`].
pub fn open_envelope(w: &crate::container::Wai) -> Result<(Circuit, Option<Measure>), QuantumError> {
let (c, m) = from_wqc(&w.payload)?;
let cap = w.capability();
if Gateset::from_capability(cap) != Some(c.gateset) {
// The capability is the file's; quote at most 64 characters of it.
let quoted: String = cap.chars().take(64).collect();
return Err(QuantumError::Contract(format!(
"the envelope's capability {quoted:?} does not name the payload's container, {} ({})",
String::from_utf8_lossy(&c.gateset.magic()),
c.gateset.capability()
)));
}
Ok((c, m))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::container::Wai;
fn bell(gs: Gateset) -> Circuit {
let mut c = Circuit::with_gateset(2, gs);
c.h(0).cx(0, 1);
c
}
/// The envelope's bytes, read back.
fn reread(w: &Wai) -> Wai {
Wai::from_bytes(&w.to_bytes().unwrap()).unwrap()
}
/// The capability follows the circuit's gateset, and the circuit — gateset
/// included — and its measurement survive the envelope.
#[test]
fn envelope_wraps_under_the_gatesets_capability() {
for (gs, cap, magic) in [
(Gateset::V2, crate::codecs::CAP_QUANTUM_CIRCUIT2, b"WQC2"),
(Gateset::V1, crate::codecs::CAP_QUANTUM_CIRCUIT, b"WQC1"),
] {
// The registry's strings are copies of the crate's.
assert_eq!(gs.capability(), cap);
let c = bell(gs);
let m = Some(Measure { seed: 7, shots: 1024 });
let wai = wrap_envelope(&c, m).unwrap();
assert_eq!(wai.capability(), cap);
assert_eq!(&wai.payload[0..4], magic);
assert_eq!(wai.manifest.target, serde_json::json!({ "n_qubits": 2, "dim": 4 }));
let back = reread(&wai);
assert_eq!(open_envelope(&back).unwrap(), (c.clone(), m));
let (c2, _) = from_wqc(&back.payload).unwrap();
assert_eq!(c2, c);
}
assert_eq!(wrap_envelope(&Circuit::new(1), None).unwrap().capability(), "wai.quantum.circuit2");
}
/// An envelope whose capability is not the one its payload's magic names is
/// refused, whichever way round, and so is a quantum payload under any
/// other capability. A payload that is not a container fails as the
/// container reader does, and a circuit its gateset forbids is never wrapped.
#[test]
fn a_capability_that_does_not_name_the_payload_is_refused() {
for (gs, other) in [(Gateset::V2, "wai.quantum.circuit"), (Gateset::V1, "wai.quantum.circuit2"), (Gateset::V2, "wai.image.png")] {
let mut wai = wrap_envelope(&bell(gs), None).unwrap();
wai.manifest.model_requirement.capability = other.to_string();
let e = open_envelope(&reread(&wai)).unwrap_err();
assert_eq!(e.kind(), "contract", "{gs:?} under {other}: {e}");
}
let mut wai = wrap_envelope(&bell(Gateset::V2), None).unwrap();
wai.payload = b"not a circuit".to_vec();
assert_eq!(open_envelope(&wai).unwrap_err().kind(), "malformed");
// A repeated control: allowed in circuit/1, refused by circuit2.
let mut c = Circuit::with_gateset(3, Gateset::V2);
c.ccx(0, 0, 2);
assert_eq!(wrap_envelope(&c, None).err().expect("refused").kind(), "invalid");
c.gateset = Gateset::V1;
assert_eq!(open_envelope(&wrap_envelope(&c, None).unwrap()).unwrap().0, c);
// A circuit whose dimension the manifest cannot hold.
assert_eq!(wrap_envelope(&Circuit::new(64), None).err(), Some(QuantumError::TooManyQubits(64)));
}
}