wai-quantum 0.3.36

A deterministic quantum stack in pure Rust: byte-exact circuit simulation (statevector / stabilizer / tensor-network MPS / sparse-Pauli backends), sparse Pauli dynamics at utility scale (arbitrary angles, 1024 qubits), belief-propagation tensor networks on the hardware graph, error mitigation, qLDPC decoding, noise learning, circuit-equivalence proofs, a phasor interference-ML layer, information-theoretic limits, noisy channels and state tomography, and signed energy-accounted receipts. No QPU, no cloud, no system libraries — identical results native, in the browser, and as a WASI component at the edge.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
//! The acquisition class of a quantum receipt's joule figure — an optional,
//! signed label (`extensions/energy-measurement.md` §2 and §2.8 in the WAI
//! repository).
//!
//! Every receipt in this crate seals `joules_micro`, and none of them said how
//! the figure was acquired. The same number can be a counter reading, a model
//! or a constant, so without a class it cannot be compared with any other.
//! Receipts sealed before this module existed must keep verifying, so the
//! class is added as a **label** that leaves the unlabelled form untouched:
//!
//! - **Unlabelled** — the receipt types as they always were. Their signed
//!   bytes, receipt hashes and JSON are unchanged. The figure is *unlabelled*:
//!   a verifier accepts it as legacy and reads it as no class at all.
//! - **Labelled** — [`Labelled`] (and [`LabelledQbom`] for a bill of
//!   materials). The receipt is re-signed over its legacy payload with two
//!   changes: the signing domain's final version byte `0x01` becomes `0x02`,
//!   and the class's signed encoding follows the `joules_micro` field it
//!   labels. The class is inside the signature, so it cannot be added,
//!   stripped, restated or promoted in transit, and the `0x02` domain keeps
//!   every labelled payload distinct from every unlabelled one.
//!
//! The change is additive: no existing type, field or function changes. A
//! labelled receipt is a new type wrapping the old one, and the old type's own
//! `verify()` refuses it (its signature is over the labelled payload), so a
//! reader that does not know about labels fails closed rather than silently
//! dropping the class. A verifier that must accept both forms parses with
//! [`MaybeLabelled`], which reads the form from the JSON and verifies each by
//! its own rules; the `wai-quantum verify` CLI and the HTTP handler's
//! `POST /verify` in the `wai` repository both do.
//!
//! A label's declared uncertainty must reach at least the `0.5/√3` µJ that
//! every whole-microjoule figure carries from its rounding, so a label with
//! `joules_micro × relative_ppm` below [`RESOLUTION_FLOOR_UJ_PPM`] is refused.
//! That is a floor, not the whole of a figure's resolution: a figure read as
//! the difference of two register readings carries more, which the producer
//! must declare and no verifier can check.
//!
//! The class vocabulary and its signed encoding are byte-identical to the
//! `energy_class` module of the `wai` crate:
//!
//! ```text
//! tag 2 ModelBased           : —
//! tag 3 Estimator            : —
//! tag 4 OnChipCounter        : relative_ppm u32 BE · window_us u64 BE · filtering u8
//! tag 5 CalibratedInstrument : relative_ppm u32 BE · window_us u64 BE ·
//!                              ref_len u32 BE · calibration_ref (UTF-8)
//! ```
//!
//! Tag 1, the legacy `HwShunt` label, is never a valid label here: these
//! receipts never carried it, and a new label must say which hardware evidence
//! it has.

use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
use serde_json::{json, Map, Value};

/// A declared uncertainty: the standard relative uncertainty (k = 1) of the
/// figure, and the integration window it holds over. Both parts are required
/// and non-zero. For an on-chip counter it is the part the declarer could
/// evaluate, which excludes the counter's own systematic error; it is not a
/// statement of the figure's total error.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Uncertainty {
    /// Standard relative uncertainty in parts per million of the figure.
    pub relative_ppm: u32,
    /// Integration window in microseconds.
    pub window_us: u64,
}

/// Whether an on-chip counter was adding deliberate noise to its readings.
/// `Unknown` is the only honest value when the control state is out of reach,
/// and a verifier reads it as possibly filtered.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CounterFiltering {
    Unknown,
    Off,
    On,
}

impl CounterFiltering {
    pub fn label(self) -> &'static str {
        match self {
            CounterFiltering::Unknown => "Unknown",
            CounterFiltering::Off => "Off",
            CounterFiltering::On => "On",
        }
    }

    pub fn from_label(s: &str) -> Option<CounterFiltering> {
        match s {
            "Unknown" => Some(CounterFiltering::Unknown),
            "Off" => Some(CounterFiltering::Off),
            "On" => Some(CounterFiltering::On),
            _ => None,
        }
    }

    fn tag_byte(self) -> u8 {
        match self {
            CounterFiltering::Unknown => 0,
            CounterFiltering::Off => 1,
            CounterFiltering::On => 2,
        }
    }
}

/// How a joule figure was acquired.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum EnergyClass {
    /// Computed from a calibrated per-operation model (e.g. wall time × a
    /// power constant).
    ModelBased,
    /// A coarse constant or load estimator.
    Estimator,
    /// Read from an energy counter the measured silicon keeps about itself —
    /// RAPL, NVML, SMC, IOReport. A sensor reading, not an estimate, whose
    /// declared uncertainty is the declarer's own evaluation.
    OnChipCounter { uncertainty: Uncertainty, filtering: CounterFiltering },
    /// Read from an external instrument holding a current calibration, with a
    /// resolvable reference to its certificate.
    CalibratedInstrument { uncertainty: Uncertainty, calibration_ref: String },
}

/// Why a label was refused.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ClassError {
    /// A hardware class with no (or a zero) relative uncertainty.
    NoUncertainty,
    /// A declared uncertainty with no (or a zero) window.
    NoWindow,
    /// A calibrated instrument with no certificate reference.
    NoCalibrationRef,
    /// A label this implementation does not know.
    UnknownLabel,
    /// Evidence beside a class that carries none, or without any class.
    UnexpectedEvidence,
    /// The legacy `HwShunt` label, which no receipt here ever carried.
    LegacyLabel,
    /// A class beside a zero figure, which claims a measurement that did not
    /// occur.
    NoFigure,
    /// Labelling with a key other than the one that sealed the receipt.
    SignerMismatch,
    /// A labelled bill of materials whose class list does not match its
    /// entries, or labels none of them.
    EntryMismatch,
    /// A declared uncertainty below the resolution floor:
    /// `joules_micro × relative_ppm` below [`RESOLUTION_FLOOR_UJ_PPM`].
    BelowResolution,
}

impl core::fmt::Display for ClassError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.write_str(match self {
            ClassError::NoUncertainty => "a hardware energy class must declare a non-zero relative uncertainty",
            ClassError::NoWindow => "a declared uncertainty must state the integration window it holds over",
            ClassError::NoCalibrationRef => "a calibrated-instrument figure must reference its calibration certificate",
            ClassError::UnknownLabel => "unknown acquisition class",
            ClassError::UnexpectedEvidence => "evidence fields attached to a class that does not carry them",
            ClassError::LegacyLabel => "HwShunt is a legacy label and cannot label a receipt that never carried it",
            ClassError::NoFigure => "a class beside a zero figure claims a measurement that did not occur",
            ClassError::SignerMismatch => "only the key that signed a receipt may label it",
            ClassError::EntryMismatch => "a labelled bill must give one class slot per entry and label at least one",
            ClassError::BelowResolution => "the declared uncertainty is below the 0.5/√3 µJ (about 0.289 µJ) that rounding the figure to whole microjoules adds: joules_micro × relative_ppm must be at least 288 676",
        })
    }
}

impl std::error::Error for ClassError {}

impl EnergyClass {
    /// The wire label.
    pub fn label(&self) -> &'static str {
        match self {
            EnergyClass::ModelBased => "ModelBased",
            EnergyClass::Estimator => "Estimator",
            EnergyClass::OnChipCounter { .. } => "OnChipCounter",
            EnergyClass::CalibratedInstrument { .. } => "CalibratedInstrument",
        }
    }

    /// The tag byte of the signed encoding.
    pub fn tag_byte(&self) -> u8 {
        match self {
            EnergyClass::ModelBased => 2,
            EnergyClass::Estimator => 3,
            EnergyClass::OnChipCounter { .. } => 4,
            EnergyClass::CalibratedInstrument { .. } => 5,
        }
    }

    /// The declared uncertainty, where the class carries one.
    pub fn uncertainty(&self) -> Option<Uncertainty> {
        match self {
            EnergyClass::OnChipCounter { uncertainty, .. }
            | EnergyClass::CalibratedInstrument { uncertainty, .. } => Some(*uncertainty),
            _ => None,
        }
    }

    /// The evidence rules: a hardware class carries a non-zero uncertainty and
    /// window; a calibrated instrument a non-empty certificate reference.
    pub fn validate(&self) -> Result<(), ClassError> {
        let check = |u: &Uncertainty| {
            if u.relative_ppm == 0 {
                Err(ClassError::NoUncertainty)
            } else if u.window_us == 0 {
                Err(ClassError::NoWindow)
            } else {
                Ok(())
            }
        };
        match self {
            EnergyClass::OnChipCounter { uncertainty, .. } => check(uncertainty),
            EnergyClass::CalibratedInstrument { uncertainty, calibration_ref } => {
                check(uncertainty)?;
                if calibration_ref.trim().is_empty() {
                    return Err(ClassError::NoCalibrationRef);
                }
                Ok(())
            }
            _ => Ok(()),
        }
    }

    /// Append the signed encoding: the tag byte, then the evidence.
    pub fn write_signed(&self, o: &mut Vec<u8>) {
        o.push(self.tag_byte());
        match self {
            EnergyClass::OnChipCounter { uncertainty, filtering } => {
                o.extend_from_slice(&uncertainty.relative_ppm.to_be_bytes());
                o.extend_from_slice(&uncertainty.window_us.to_be_bytes());
                o.push(filtering.tag_byte());
            }
            EnergyClass::CalibratedInstrument { uncertainty, calibration_ref } => {
                o.extend_from_slice(&uncertainty.relative_ppm.to_be_bytes());
                o.extend_from_slice(&uncertainty.window_us.to_be_bytes());
                o.extend_from_slice(&(calibration_ref.len() as u32).to_be_bytes());
                o.extend_from_slice(calibration_ref.as_bytes());
            }
            _ => {}
        }
    }

    /// Rebuild a class from its wire parts, applying every evidence rule.
    /// `filtering` absent on an `OnChipCounter` reads as `Unknown`.
    pub fn from_parts(
        label: &str,
        uncertainty: Option<Uncertainty>,
        filtering: Option<CounterFiltering>,
        calibration_ref: Option<&str>,
    ) -> Result<EnergyClass, ClassError> {
        let unrefined = |c: EnergyClass| {
            if uncertainty.is_some() || filtering.is_some() || calibration_ref.is_some() {
                Err(ClassError::UnexpectedEvidence)
            } else {
                Ok(c)
            }
        };
        let c = match label {
            "HwShunt" => return Err(ClassError::LegacyLabel),
            "ModelBased" => unrefined(EnergyClass::ModelBased)?,
            "Estimator" => unrefined(EnergyClass::Estimator)?,
            "OnChipCounter" => {
                if calibration_ref.is_some() {
                    return Err(ClassError::UnexpectedEvidence);
                }
                EnergyClass::OnChipCounter {
                    uncertainty: uncertainty.ok_or(ClassError::NoUncertainty)?,
                    filtering: filtering.unwrap_or(CounterFiltering::Unknown),
                }
            }
            "CalibratedInstrument" => {
                if filtering.is_some() {
                    return Err(ClassError::UnexpectedEvidence);
                }
                EnergyClass::CalibratedInstrument {
                    uncertainty: uncertainty.ok_or(ClassError::NoUncertainty)?,
                    calibration_ref: calibration_ref.ok_or(ClassError::NoCalibrationRef)?.to_owned(),
                }
            }
            _ => return Err(ClassError::UnknownLabel),
        };
        c.validate()?;
        Ok(c)
    }

    /// The JSON fields the class renders as, under the same names as the WAI
    /// receipts: `energy_provenance`, and for a hardware class
    /// `energy_uncertainty` `{relative_ppm, window_us}` with
    /// `energy_counter_filtering` or `energy_calibration_ref`. The prefix keeps
    /// them clear of fields the receipts already render — a job receipt's
    /// `calibration_ref` names a calibration receipt, not a certificate.
    pub fn json_fields(&self) -> Vec<(&'static str, Value)> {
        let mut f = vec![("energy_provenance", Value::from(self.label()))];
        match self {
            EnergyClass::OnChipCounter { uncertainty, filtering } => {
                f.push(("energy_uncertainty", json!({"relative_ppm": uncertainty.relative_ppm, "window_us": uncertainty.window_us})));
                f.push(("energy_counter_filtering", Value::from(filtering.label())));
            }
            EnergyClass::CalibratedInstrument { uncertainty, calibration_ref } => {
                f.push(("energy_uncertainty", json!({"relative_ppm": uncertainty.relative_ppm, "window_us": uncertainty.window_us})));
                f.push(("energy_calibration_ref", Value::from(calibration_ref.as_str())));
            }
            _ => {}
        }
        f
    }

    /// Read an optional class from a JSON object. No class and no evidence is
    /// `Ok(None)`; evidence without a class is refused.
    pub fn from_json_object(o: &Map<String, Value>) -> Result<Option<EnergyClass>, ClassError> {
        let present = |k: &str| !matches!(o.get(k), None | Some(Value::Null));
        let label = match o.get("energy_provenance") {
            None | Some(Value::Null) => {
                if present("energy_uncertainty") || present("energy_counter_filtering") || present("energy_calibration_ref") {
                    return Err(ClassError::UnexpectedEvidence);
                }
                return Ok(None);
            }
            Some(Value::String(s)) => s.as_str(),
            Some(_) => return Err(ClassError::UnknownLabel),
        };
        let uncertainty = match o.get("energy_uncertainty") {
            None | Some(Value::Null) => None,
            Some(Value::Object(u)) => {
                let ppm = u.get("relative_ppm").and_then(Value::as_u64).ok_or(ClassError::NoUncertainty)?;
                let window_us = u.get("window_us").and_then(Value::as_u64).ok_or(ClassError::NoWindow)?;
                Some(Uncertainty { relative_ppm: u32::try_from(ppm).map_err(|_| ClassError::NoUncertainty)?, window_us })
            }
            Some(_) => return Err(ClassError::NoUncertainty),
        };
        let filtering = match o.get("energy_counter_filtering") {
            None | Some(Value::Null) => None,
            Some(Value::String(s)) => Some(CounterFiltering::from_label(s).ok_or(ClassError::UnknownLabel)?),
            Some(_) => return Err(ClassError::UnknownLabel),
        };
        let calibration_ref = match o.get("energy_calibration_ref") {
            None | Some(Value::Null) => None,
            Some(Value::String(s)) => Some(s.as_str()),
            Some(_) => return Err(ClassError::NoCalibrationRef),
        };
        EnergyClass::from_parts(label, uncertainty, filtering, calibration_ref).map(Some)
    }
}

/// The least `joules_micro × relative_ppm` a declared uncertainty may have
/// (`extensions/energy-measurement.md` §2.3). `joules_micro` is a whole number
/// of microjoules, so a figure is uncertain by at least the rounding to it,
/// ±0.5 µJ taken as rectangular: `0.5/√3` µJ. A declaration of `ppm` on a
/// figure of `F` µJ covers that only when `F · ppm / 10⁶ ≥ 0.5/√3`, which for
/// the integer `F · ppm` is `≥ 288 676`. The same constant as the `wai`
/// crate's `energy_class::RESOLUTION_FLOOR_UJ_PPM`.
pub const RESOLUTION_FLOOR_UJ_PPM: u64 = 288_676;

/// The rule a label must meet: a valid class beside a non-zero figure, whose
/// declared uncertainty, if it has one, reaches the resolution floor
/// ([`RESOLUTION_FLOOR_UJ_PPM`]).
pub fn check_label(joules_micro: u64, class: &EnergyClass) -> Result<(), ClassError> {
    if joules_micro == 0 {
        return Err(ClassError::NoFigure);
    }
    class.validate()?;
    match class.uncertainty() {
        Some(u) if (joules_micro as u128) * (u.relative_ppm as u128) < RESOLUTION_FLOOR_UJ_PPM as u128 => {
            Err(ClassError::BelowResolution)
        }
        _ => Ok(()),
    }
}

/// The labelled form of a legacy signing domain: its final version byte `0x01`
/// replaced by `0x02`.
pub(crate) fn labelled_domain(domain: &[u8], label: Option<&EnergyClass>) -> Vec<u8> {
    let mut d = domain.to_vec();
    if label.is_some() {
        match d.last_mut() {
            Some(v) if *v == 0x01 => *v = 0x02,
            _ => panic!("a labelled signing domain must end in the legacy version byte 0x01"),
        }
    }
    d
}

/// Append an optional label after the figure it labels: nothing when absent.
pub(crate) fn write_label(label: Option<&EnergyClass>, o: &mut Vec<u8>) {
    if let Some(c) = label {
        c.write_signed(o);
    }
}

/// Insert `fields` into a JSON object at their sorted-key positions, leaving
/// every existing key in place; a leading `"kind"` key stays first.
pub(crate) fn insert_sorted(obj: Map<String, Value>, mut fields: Vec<(&'static str, Value)>) -> Map<String, Value> {
    fields.sort_by(|a, b| a.0.cmp(b.0));
    let mut pending = fields.into_iter().peekable();
    let mut out = Map::new();
    for (i, (k, v)) in obj.into_iter().enumerate() {
        if !(i == 0 && k == "kind") {
            while let Some((nk, _)) = pending.peek() {
                if *nk < k.as_str() {
                    let (nk, nv) = pending.next().unwrap();
                    out.insert(nk.to_string(), nv);
                } else {
                    break;
                }
            }
        }
        out.insert(k, v);
    }
    for (nk, nv) in pending {
        out.insert(nk.to_string(), nv);
    }
    out
}

fn hx(b: &[u8]) -> String {
    b.iter().map(|x| format!("{x:02x}")).collect()
}

pub(crate) mod sealed {
    pub trait Sealed {}
}

/// A receipt type of this crate that can carry a label. Implemented for every
/// receipt that seals `joules_micro` except the bill of materials, which
/// labels per entry ([`LabelledQbom`]). Sealed: the methods are the plumbing
/// [`Labelled`] needs and are not a public API.
pub trait Labellable: sealed::Sealed + Clone + core::fmt::Debug + PartialEq + Sized {
    #[doc(hidden)]
    fn labelled_payload(&self, label: Option<&EnergyClass>) -> Vec<u8>;
    #[doc(hidden)]
    fn id_domain(&self) -> &'static [u8];
    #[doc(hidden)]
    fn figure(&self) -> u64;
    #[doc(hidden)]
    fn body_ok(&self) -> bool;
    #[doc(hidden)]
    fn signer_key(&self) -> [u8; 32];
    #[doc(hidden)]
    fn signature(&self) -> [u8; 64];
    #[doc(hidden)]
    fn set_signature(&mut self, sig: [u8; 64]);
    #[doc(hidden)]
    fn unlabelled_json(&self) -> String;
    #[doc(hidden)]
    fn parse_unlabelled_json(s: &str) -> Option<Self>;
    #[doc(hidden)]
    fn unlabelled_verify(&self) -> bool;
    #[doc(hidden)]
    fn unlabelled_receipt_hash(&self) -> [u8; 32];
}

macro_rules! labellable {
    ($t:ty, $id:expr) => {
        impl $crate::quantum_energy::sealed::Sealed for $t {}
        impl $crate::quantum_energy::Labellable for $t {
            fn labelled_payload(&self, label: Option<&$crate::quantum_energy::EnergyClass>) -> Vec<u8> {
                self.payload_with(label)
            }
            fn id_domain(&self) -> &'static [u8] {
                $id
            }
            fn figure(&self) -> u64 {
                self.joules_micro
            }
            fn body_ok(&self) -> bool {
                self.body_verifies()
            }
            fn signer_key(&self) -> [u8; 32] {
                self.signer_pubkey
            }
            fn signature(&self) -> [u8; 64] {
                self.sig
            }
            fn set_signature(&mut self, sig: [u8; 64]) {
                self.sig = sig;
            }
            fn unlabelled_json(&self) -> String {
                self.to_json()
            }
            fn parse_unlabelled_json(s: &str) -> Option<Self> {
                Self::from_json(s)
            }
            fn unlabelled_verify(&self) -> bool {
                self.verify()
            }
            fn unlabelled_receipt_hash(&self) -> [u8; 32] {
                self.receipt_hash()
            }
        }
    };
}
pub(crate) use labellable;

/// A receipt whose joule figure carries its acquisition class, inside the
/// signature.
///
/// Built with [`Labelled::seal`] from a receipt sealed the usual way, by the
/// same key. `receipt.verify()` on the inner receipt is `false` for a labelled
/// receipt — its signature covers the labelled payload — so always verify
/// through [`Labelled::verify`], and identify it by [`Labelled::receipt_hash`]
/// (e.g. as another receipt's `parent_receipt_hash`).
#[derive(Clone, Debug, PartialEq)]
pub struct Labelled<R> {
    pub receipt: R,
    pub energy_class: EnergyClass,
}

impl<R: Labellable> Labelled<R> {
    /// Label a sealed receipt's figure and re-sign it. `signer` must be the key
    /// that sealed it. Refuses a class beside a zero figure and a class
    /// without its evidence.
    pub fn seal(mut receipt: R, energy_class: EnergyClass, signer: &SigningKey) -> Result<Labelled<R>, ClassError> {
        if signer.verifying_key().to_bytes() != receipt.signer_key() {
            return Err(ClassError::SignerMismatch);
        }
        check_label(receipt.figure(), &energy_class)?;
        let sig = signer.sign(&receipt.labelled_payload(Some(&energy_class))).to_bytes();
        receipt.set_signature(sig);
        Ok(Labelled { receipt, energy_class })
    }

    /// The label rule, the receipt's own consistency checks (Merkle root,
    /// recomputed work, grant ceiling — whatever its `verify()` checks), and
    /// the signature over the labelled payload.
    pub fn verify(&self) -> bool {
        if check_label(self.receipt.figure(), &self.energy_class).is_err() || !self.receipt.body_ok() {
            return false;
        }
        let Ok(k) = VerifyingKey::from_bytes(&self.receipt.signer_key()) else {
            return false;
        };
        k.verify(
            &self.receipt.labelled_payload(Some(&self.energy_class)),
            &Signature::from_bytes(&self.receipt.signature()),
        )
        .is_ok()
    }

    /// Stable identity: `BLAKE3(id_domain ‖ labelled payload ‖ sig)`, the
    /// receipt type's own identity construction over the labelled payload.
    pub fn receipt_hash(&self) -> [u8; 32] {
        let mut h = blake3::Hasher::new();
        h.update(self.receipt.id_domain());
        h.update(&self.receipt.labelled_payload(Some(&self.energy_class)));
        h.update(&self.receipt.signature());
        *h.finalize().as_bytes()
    }

    /// The receipt's canonical JSON with the class and its evidence inserted
    /// at their sorted-key positions and `receipt_hash` giving the labelled
    /// identity.
    pub fn to_json(&self) -> String {
        let v: Value = serde_json::from_str(&self.receipt.unlabelled_json()).expect("a receipt renders valid JSON");
        let Value::Object(mut obj) = v else { panic!("a receipt renders a JSON object") };
        if obj.contains_key("receipt_hash") {
            obj.insert("receipt_hash".into(), Value::from(hx(&self.receipt_hash())));
        }
        Value::Object(insert_sorted(obj, self.energy_class.json_fields())).to_string()
    }

    /// Parse a labelled receipt. `None` when the JSON carries no class — parse
    /// that with the receipt type's own `from_json` — or a malformed one.
    pub fn from_json(s: &str) -> Option<Labelled<R>> {
        let v: Value = serde_json::from_str(s).ok()?;
        let energy_class = EnergyClass::from_json_object(v.as_object()?).ok()??;
        let receipt = R::parse_unlabelled_json(s)?;
        Some(Labelled { receipt, energy_class })
    }
}

/// A receipt in whichever form it arrived: unlabelled — every receipt issued
/// before labels existed, and every unmetered one — or [`Labelled`].
///
/// A verify path that parses only the receipt type's own JSON refuses every
/// labelled receipt (its signature covers the labelled payload), and one that
/// parses only [`Labelled`] refuses every legacy receipt. This type is the one
/// entry point that accepts both and loses neither: [`MaybeLabelled::from_json`]
/// picks the form from the JSON itself, and each form verifies by its own rules.
#[derive(Clone, Debug, PartialEq)]
pub enum MaybeLabelled<R> {
    Unlabelled(R),
    Labelled(Labelled<R>),
}

impl<R: Labellable> MaybeLabelled<R> {
    /// Parse either form. JSON carrying `energy_provenance` parses only as
    /// [`Labelled`]; JSON carrying `energy_` evidence without a class, or a
    /// malformed class, is refused — never read as an unlabelled receipt with
    /// its label dropped.
    pub fn from_json(s: &str) -> Option<MaybeLabelled<R>> {
        let v: Value = serde_json::from_str(s).ok()?;
        match EnergyClass::from_json_object(v.as_object()?) {
            Ok(None) => R::parse_unlabelled_json(s).map(MaybeLabelled::Unlabelled),
            Ok(Some(_)) => Labelled::from_json(s).map(MaybeLabelled::Labelled),
            Err(_) => None,
        }
    }

    /// The receipt's own `verify()` when unlabelled; [`Labelled::verify`] —
    /// the label rules, the receipt's consistency checks and the signature
    /// over the labelled payload — when labelled.
    pub fn verify(&self) -> bool {
        match self {
            MaybeLabelled::Unlabelled(r) => r.unlabelled_verify(),
            MaybeLabelled::Labelled(l) => l.verify(),
        }
    }

    /// The receipt, whichever form carries it.
    pub fn receipt(&self) -> &R {
        match self {
            MaybeLabelled::Unlabelled(r) => r,
            MaybeLabelled::Labelled(l) => &l.receipt,
        }
    }

    /// The figure's class, or `None` for an unlabelled figure — which is read
    /// as no class at all, not as any particular one.
    pub fn energy_class(&self) -> Option<&EnergyClass> {
        match self {
            MaybeLabelled::Unlabelled(_) => None,
            MaybeLabelled::Labelled(l) => Some(&l.energy_class),
        }
    }

    /// The identity another receipt names this one by: the receipt type's own
    /// hash when unlabelled, [`Labelled::receipt_hash`] when labelled.
    pub fn receipt_hash(&self) -> [u8; 32] {
        match self {
            MaybeLabelled::Unlabelled(r) => r.unlabelled_receipt_hash(),
            MaybeLabelled::Labelled(l) => l.receipt_hash(),
        }
    }

    /// The canonical JSON of whichever form this is.
    pub fn to_json(&self) -> String {
        match self {
            MaybeLabelled::Unlabelled(r) => r.unlabelled_json(),
            MaybeLabelled::Labelled(l) => l.to_json(),
        }
    }
}

impl<R> From<Labelled<R>> for MaybeLabelled<R> {
    fn from(l: Labelled<R>) -> MaybeLabelled<R> {
        MaybeLabelled::Labelled(l)
    }
}

#[cfg(feature = "quantum_ops")]
impl MaybeLabelled<crate::quantum_ops::JobReceipt> {
    /// The cross-link check for either form of job and calibration: the job's
    /// `calibration_ref` names the calibration's identity — its labelled
    /// identity when it is labelled — and both verify by their own rules.
    /// `JobReceipt::verify_against_calibration` is this check for two
    /// unlabelled receipts.
    pub fn verify_against_calibration(&self, cal: &MaybeLabelled<crate::quantum_ops::CalibrationReceipt>) -> bool {
        self.receipt().calibration_ref == Some(cal.receipt_hash()) && cal.verify() && self.verify()
    }
}

#[cfg(feature = "quantum_receipt")]
impl MaybeLabelled<crate::quantum_receipt::QuantumReceipt> {
    /// [`QuantumReceipt::verify_reconstruction`](crate::quantum_receipt::QuantumReceipt::verify_reconstruction)
    /// or [`Labelled::verify_reconstruction`], whichever form this is.
    pub fn verify_reconstruction(&self, circuit: &crate::quantum::Circuit) -> bool {
        match self {
            MaybeLabelled::Unlabelled(r) => r.verify_reconstruction(circuit),
            MaybeLabelled::Labelled(l) => l.verify_reconstruction(circuit),
        }
    }
}

#[cfg(feature = "quantum_receipt")]
impl Labelled<crate::quantum_receipt::QuantumReceipt> {
    /// The strong, portable check for a labelled circuit receipt: re-simulate
    /// `circuit`, confirm it reproduces the receipt's identity, reconstruction
    /// and histogram, then [`Labelled::verify`].
    pub fn verify_reconstruction(&self, circuit: &crate::quantum::Circuit) -> bool {
        self.receipt.reconstruction_matches(circuit) && self.verify()
    }
}

/// A bill of materials whose entries carry their stages' acquisition classes.
///
/// A QBOM restates each stage's figure, so each entry is labelled separately:
/// `classes[i]` labels `entries[i]`, and `None` leaves an entry unlabelled. The
/// labelled body is the legacy body under the `0x02` domain with every entry's
/// optional class (`0` when unlabelled) after that entry's figure. The total
/// carries no class of its own; a sum over stages of different classes is only
/// as strong as its weakest stage.
#[cfg(feature = "quantum_qbom")]
#[derive(Clone, Debug, PartialEq)]
pub struct LabelledQbom {
    pub qbom: crate::quantum_qbom::Qbom,
    pub classes: Vec<Option<EnergyClass>>,
}

#[cfg(feature = "quantum_qbom")]
impl LabelledQbom {
    fn check(&self) -> Result<(), ClassError> {
        if self.classes.len() != self.qbom.entries.len() || self.classes.iter().all(Option::is_none) {
            return Err(ClassError::EntryMismatch);
        }
        for (e, c) in self.qbom.entries.iter().zip(&self.classes) {
            if let Some(c) = c {
                check_label(e.joules_micro, c)?;
            }
        }
        Ok(())
    }

    /// Label a sealed bill's entries and re-sign it with the key that sealed
    /// it. `classes` gives one slot per entry and labels at least one.
    pub fn seal(
        mut qbom: crate::quantum_qbom::Qbom,
        classes: Vec<Option<EnergyClass>>,
        signer: &SigningKey,
    ) -> Result<LabelledQbom, ClassError> {
        if signer.verifying_key().to_bytes() != qbom.signer_pubkey {
            return Err(ClassError::SignerMismatch);
        }
        let probe = LabelledQbom { qbom: qbom.clone(), classes };
        probe.check()?;
        qbom.sig = signer.sign(&qbom.labelled_signing_payload(&probe.classes)).to_bytes();
        Ok(LabelledQbom { qbom, classes: probe.classes })
    }

    /// The label rules and the signature over the labelled payload.
    pub fn verify(&self) -> bool {
        if self.check().is_err() {
            return false;
        }
        let Ok(k) = VerifyingKey::from_bytes(&self.qbom.signer_pubkey) else {
            return false;
        };
        k.verify(&self.qbom.labelled_signing_payload(&self.classes), &Signature::from_bytes(&self.qbom.sig))
            .is_ok()
    }

    /// The provenance root over the labelled body.
    pub fn provenance_root(&self) -> [u8; 32] {
        *blake3::hash(&self.qbom.labelled_body(&self.classes)).as_bytes()
    }

    /// Stable identity over the labelled payload.
    pub fn receipt_hash(&self) -> [u8; 32] {
        let mut h = blake3::Hasher::new();
        h.update(crate::quantum_qbom::DOMAIN_QBOM_ID);
        h.update(&self.qbom.labelled_signing_payload(&self.classes));
        h.update(&self.qbom.sig);
        *h.finalize().as_bytes()
    }

    /// Given the actual stage receipts as `(receipt_hash, verifies, class)`,
    /// does the bill bind exactly them — including each entry's class
    /// matching its stage receipt's class?
    pub fn binds(&self, receipts: &[([u8; 32], bool, Option<&EnergyClass>)]) -> bool {
        if !self.verify() || receipts.len() != self.qbom.entries.len() {
            return false;
        }
        self.qbom.entries.iter().zip(&self.classes).all(|(e, c)| {
            receipts.iter().any(|(h, ok, rc)| *h == e.receipt_hash && *ok && *rc == c.as_ref())
        })
    }

    /// The bill's canonical JSON with each entry's class inserted into that
    /// entry, and the labelled root and identity.
    pub fn to_json(&self) -> String {
        let v: Value = serde_json::from_str(&self.qbom.to_json()).expect("a qbom renders valid JSON");
        let Value::Object(mut obj) = v else { panic!("a qbom renders a JSON object") };
        if let Some(Value::Array(entries)) = obj.get_mut("entries") {
            for (e, c) in entries.iter_mut().zip(&self.classes) {
                if let (Value::Object(eo), Some(c)) = (e, c) {
                    let taken = std::mem::take(eo);
                    *eo = insert_sorted(taken, c.json_fields());
                }
            }
        }
        obj.insert("provenance_root".into(), Value::from(hx(&self.provenance_root())));
        obj.insert("receipt_hash".into(), Value::from(hx(&self.receipt_hash())));
        Value::Object(obj).to_string()
    }

    /// Parse a labelled bill. `None` when no entry carries a class, or a class
    /// is malformed.
    pub fn from_json(s: &str) -> Option<LabelledQbom> {
        let v: Value = serde_json::from_str(s).ok()?;
        let mut classes = Vec::new();
        for e in v.as_object()?.get("entries")?.as_array()? {
            classes.push(EnergyClass::from_json_object(e.as_object()?).ok()?);
        }
        if classes.iter().all(Option::is_none) {
            return None;
        }
        let qbom = crate::quantum_qbom::Qbom::from_json(s)?;
        Some(LabelledQbom { qbom, classes })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn chip(ppm: u32) -> EnergyClass {
        EnergyClass::OnChipCounter { uncertainty: Uncertainty { relative_ppm: ppm, window_us: 2_977_104 }, filtering: CounterFiltering::Unknown }
    }

    #[test]
    fn encoding_matches_the_wai_vocabulary() {
        let mut o = Vec::new();
        chip(20_000).write_signed(&mut o);
        let mut want = vec![4u8];
        want.extend_from_slice(&20_000u32.to_be_bytes());
        want.extend_from_slice(&2_977_104u64.to_be_bytes());
        want.push(0);
        assert_eq!(o, want);
        let mut o = Vec::new();
        EnergyClass::ModelBased.write_signed(&mut o);
        EnergyClass::Estimator.write_signed(&mut o);
        assert_eq!(o, vec![2, 3]);
        let c = EnergyClass::CalibratedInstrument { uncertainty: Uncertainty { relative_ppm: 5_000, window_us: 60_000_000 }, calibration_ref: "cert-1".into() };
        let mut o = Vec::new();
        c.write_signed(&mut o);
        assert_eq!(o[0], 5);
        assert_eq!(&o[13..17], &6u32.to_be_bytes());
        assert_eq!(&o[17..], b"cert-1");
    }

    #[test]
    fn labels_are_refused_where_they_would_mislead() {
        assert_eq!(check_label(0, &chip(1)), Err(ClassError::NoFigure));
        assert_eq!(check_label(5, &chip(0)), Err(ClassError::NoUncertainty));
        // The resolution floor, at its boundary, from both sides of the product.
        assert_eq!(check_label(1, &chip(288_675)), Err(ClassError::BelowResolution));
        assert_eq!(check_label(1, &chip(288_676)), Ok(()));
        assert_eq!(check_label(288_675, &chip(1)), Err(ClassError::BelowResolution));
        assert_eq!(check_label(288_676, &chip(1)), Ok(()));
        assert_eq!(check_label(u64::MAX, &chip(u32::MAX)), Ok(()), "no overflow");
        assert_eq!(check_label(1, &EnergyClass::ModelBased), Ok(()), "no declaration, nothing to cover");
        assert_eq!(EnergyClass::from_parts("HwShunt", None, None, None), Err(ClassError::LegacyLabel));
        assert_eq!(EnergyClass::from_parts("OnChipCounter", None, None, None), Err(ClassError::NoUncertainty));
        assert_eq!(
            EnergyClass::from_parts("ModelBased", Some(Uncertainty { relative_ppm: 1, window_us: 1 }), None, None),
            Err(ClassError::UnexpectedEvidence)
        );
        let parse = |s: &str| {
            let v: Value = serde_json::from_str(s).unwrap();
            EnergyClass::from_json_object(v.as_object().unwrap())
        };
        assert_eq!(parse(r#"{"joules_micro":5}"#), Ok(None));
        assert_eq!(parse(r#"{"energy_counter_filtering":"Off"}"#), Err(ClassError::UnexpectedEvidence));
        // A receipt's own `calibration_ref` field is not class evidence.
        assert_eq!(parse(r#"{"calibration_ref":"d2d8"}"#), Ok(None));
        assert_eq!(
            parse(r#"{"energy_provenance":"OnChipCounter","energy_uncertainty":{"relative_ppm":7,"window_us":9}}"#),
            Ok(Some(EnergyClass::OnChipCounter { uncertainty: Uncertainty { relative_ppm: 7, window_us: 9 }, filtering: CounterFiltering::Unknown }))
        );
    }

    #[test]
    fn a_labelled_domain_changes_only_the_version_byte() {
        let d = b"wai:quantum-receipt\x01";
        assert_eq!(labelled_domain(d, None), d.to_vec());
        let l = labelled_domain(d, Some(&EnergyClass::Estimator));
        assert_eq!(&l[..l.len() - 1], &d[..d.len() - 1]);
        assert_eq!(l.last(), Some(&0x02));
    }
}