open-standards/wai/wai-rs/tests/video_receipt.rs
Transaction Science 66daac8da5 video_receipt: each encode-receipt check held by a control signed over its defect
The error, the parameters and the source were each restated without signing
again, so the signature refused the control and dropping the check under test
went unnoticed. VideoEncodeReceipt::resign (hidden) seals a control over its
defect; with it, dropping the SSE recomputation, the parameters' match with the
header or the source frames' hashes each fails the test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 19:55:39 -04:00

473 lines
24 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! `wai.video.int_motion` receipt — the metered leg of the integer video class.
//!
//! The point of these tests is the split the profile rests on: everything except
//! the energy is independently checkable from the codestream, and the energy is
//! attested by the signature alone. Each half is tested for what it actually
//! promises, and the tamper cases confirm the checkable half cannot be bent.
#![cfg(feature = "video_receipt")]
// Most tests here seal over the tool's JSON form through the deprecated entry points:
// they are the legacy receipts, whose pinned bytes must keep verifying. The tests of
// the WIV1 payload, the identity a receipt has now, are at the end.
#![allow(deprecated)]
use std::path::PathBuf;
use ed25519_dalek::SigningKey;
use wai::energy_class::{CounterFiltering, Uncertainty};
use wai::video_receipt::{work_pixel_ops, Provenance, VideoReceipt};
fn dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/vectors/int_video")
}
fn raw(name: &str) -> Vec<u8> {
std::fs::read(dir().join(name)).expect("read vector")
}
fn key(seed: u8) -> SigningKey {
SigningKey::from_bytes(&[seed; 32])
}
/// An on-chip counter reading as the native meter emits it: a declared 3 %
/// standard uncertainty over a 2.8 s bracket, filtering state not determinable
/// by an unprivileged reader.
fn chip() -> Provenance {
Provenance::on_chip_counter(Uncertainty::new(30_000, 2_800_000).unwrap(), CounterFiltering::Unknown)
.unwrap()
}
fn seal_as(name: &str, uj: u64, prov: Option<Provenance>) -> (VideoReceipt, Vec<u8>, serde_json::Value) {
let bytes = raw(name);
let bs: serde_json::Value = serde_json::from_slice(&bytes).expect("parse");
let r = VideoReceipt::seal_decode(&key(7), "did:example:meter", &bytes, &bs, uj, prov, None)
.expect("seal");
(r, bytes, bs)
}
fn seal(name: &str, uj: u64) -> (VideoReceipt, Vec<u8>, serde_json::Value) {
seal_as(name, uj, (uj > 0).then(chip))
}
#[test]
fn seals_and_verifies_against_the_committed_clip() {
let (r, bytes, bs) = seal("int_video_bitstream.json", 4_200);
assert!(r.verify(), "signature + internal consistency");
assert!(r.verify_reconstruction(&bytes, &bs), "re-decode must reproduce every frame");
// The work figure follows from the geometry and is recomputable, so it
// cannot be inflated to flatter an energy number.
assert_eq!(r.h, 48);
assert_eq!(r.w, 48);
assert_eq!(r.frames.len(), 5);
assert_eq!(r.work_pixel_ops, work_pixel_ops(5, 48, 48));
assert_eq!(r.work_pixel_ops, 5 * 48 * 48 * 3);
let (rate, prov) = r.uj_per_kilopixel_op().expect("metered");
assert!((rate - 4_200.0 * 1000.0 / 34_560.0).abs() < 1e-9);
assert_eq!(prov, chip());
}
/// An unmetered receipt reports **no** rate. A `0` would read as "this decode
/// was free", which is a stronger and false claim than "nobody measured".
#[test]
fn unmetered_reports_no_rate_rather_than_zero() {
let (r, _, _) = seal("int_video_bitstream.json", 0);
assert!(r.verify());
assert_eq!(r.joules_micro, 0);
assert!(r.uj_per_kilopixel_op().is_none());
assert_eq!(r.energy_provenance, None);
assert!(r.to_json().contains("\"uj_per_kilopixel_op\":null"));
assert!(r.to_json().contains("\"energy_provenance\":null"));
}
/// Real footage, the half-pel path — the clip whose decode is most at risk of
/// differing between architectures, and therefore the one whose receipt is
/// worth the most.
#[test]
fn real_footage_receipt_round_trips() {
let (r, bytes, bs) = seal("video_real_bitstream.json", 91_000);
assert!(r.verify());
assert!(r.verify_reconstruction(&bytes, &bs));
assert_eq!((r.h, r.w, r.frames.len()), (96, 96, 8));
assert_eq!(r.work_pixel_ops, 8 * 96 * 96 * 3);
}
/// A receipt sealed over one clip must not verify against another.
#[test]
fn a_receipt_does_not_vouch_for_a_different_clip() {
let (r, _, _) = seal("int_video_bitstream.json", 10);
let other = raw("video_real_bitstream.json");
let other_bs: serde_json::Value = serde_json::from_slice(&other).unwrap();
assert!(!r.verify_reconstruction(&other, &other_bs));
}
/// Tampering with any checkable field must break the receipt.
#[test]
fn every_checkable_field_is_bound() {
let (base, bytes, bs) = seal("int_video_bitstream.json", 4_200);
// A flipped frame hash breaks the Merkle root.
let mut t = base.clone();
t.frames[2].hash[0] ^= 1;
assert!(!t.verify(), "flipped frame hash");
// Reordering frames breaks the index binding — inter-frame decode is
// order-dependent, so a permuted clip is a different clip.
let mut t = base.clone();
t.frames.swap(1, 3);
assert!(!t.verify(), "permuted frames");
// Inflating the work figure (the denominator of any efficiency claim)
// breaks recomputation.
let mut t = base.clone();
t.work_pixel_ops *= 10;
assert!(!t.verify(), "inflated work");
// Restating the geometry breaks the clip commitment.
let mut t = base.clone();
t.w += 1;
assert!(!t.verify(), "restated geometry");
// A different identity no longer describes this codestream.
let mut t = base.clone();
t.codestream_hash[0] ^= 1;
assert!(!t.verify_reconstruction(&bytes, &bs), "wrong codestream hash");
// And the energy is inside the signature even though it is not
// independently checkable — an intermediary cannot restate it.
let mut t = base.clone();
t.joules_micro = 1;
assert!(!t.verify(), "restated energy");
}
/// Receipts chain like every other class, and the chain link is covered by the
/// signature.
#[test]
fn receipts_chain_by_parent_hash() {
let (first, _, _) = seal("int_video_bitstream.json", 4_200);
let bytes = raw("video_real_bitstream.json");
let bs: serde_json::Value = serde_json::from_slice(&bytes).unwrap();
let second = VideoReceipt::seal_decode(
&key(7),
"did:example:meter",
&bytes,
&bs,
91_000,
Some(chip()),
Some(first.receipt_hash()),
)
.expect("seal");
assert!(second.verify());
assert_eq!(second.parent_receipt_hash, Some(first.receipt_hash()));
let mut t = second.clone();
t.parent_receipt_hash = None;
assert!(!t.verify(), "the chain link is signed");
}
/// A number and its acquisition class stand or fall together — the doctrine
/// this class exists to enforce, checked rather than merely documented.
#[test]
fn an_energy_figure_and_its_class_are_inseparable() {
let (metered, _, _) = seal("int_video_bitstream.json", 4_200);
let (unmetered, _, _) = seal("int_video_bitstream.json", 0);
assert!(metered.verify() && unmetered.verify());
// Stripping the class off a real figure leaves a number nobody can compare.
let mut t = metered.clone();
t.energy_provenance = None;
assert!(!t.verify(), "unlabelled non-zero figure");
// Labelling a measurement that never happened is the more dangerous half:
// it claims a sensor was in the loop when none was.
let mut t = unmetered.clone();
t.energy_provenance = Some(chip());
assert!(!t.verify(), "labelled zero");
// The class is inside the signature, so an intermediary cannot promote a
// modelled figure to a measured one.
let mut t = metered.clone();
t.energy_provenance = Some(Provenance::ModelBased);
assert!(!t.verify(), "restated class");
}
fn hex(b: &[u8]) -> String {
b.iter().map(|x| format!("{x:02x}")).collect()
}
/// A receipt sealed under the three-rung ladder keeps its signed bytes and its
/// JSON rendering. The digests were captured from the legacy encoding (tag
/// byte, no trailing evidence) and pin it: a verifier holding such a receipt
/// must reach the same verdict after the acquisition-class split as before.
#[test]
#[allow(deprecated)] // sealing a legacy HwShunt receipt is the point
fn legacy_labels_keep_their_signed_bytes() {
let (hw, _, _) = seal_as("int_video_bitstream.json", 4_200, Some(Provenance::HwShunt));
let (none, _, _) = seal("int_video_bitstream.json", 0);
assert!(hw.verify() && none.verify());
assert_eq!(
[
hex(&hw.receipt_hash()),
hex(blake3::hash(hw.to_json().as_bytes()).as_bytes()),
hex(&none.receipt_hash()),
],
[
"0dc851f603666496b1358ab427d8a84163c1841eade8970d537bcdc0567b1745",
"1cdcf1ebd778c39aca8614c4aa4d470dc9c5ad7ff680eaf3e1ee7302c39db15b",
"03a88242e999887d0ad9e515d9980755e6aad00989bed8e0ccba35b4bb2dd710",
]
);
}
/// The refined hardware class carries its declared uncertainty into the
/// signature and into the rendered receipt; the same class with no uncertainty
/// does not verify.
#[test]
fn a_refined_class_carries_its_uncertainty_and_cannot_omit_it() {
let (r, _, _) = seal("int_video_bitstream.json", 4_200);
assert!(r.verify());
let j = r.to_json();
assert!(j.contains("\"energy_provenance\":\"OnChipCounter\""), "{j}");
assert!(j.contains("\"energy_uncertainty\":{\"relative_ppm\":30000,\"window_us\":2800000}"), "{j}");
assert!(j.contains("\"energy_counter_filtering\":\"Unknown\""), "{j}");
serde_json::from_str::<serde_json::Value>(&j).expect("the receipt renders as valid JSON");
// Sealed without an uncertainty (by hand, bypassing the checked
// constructor): the signature is valid, the receipt is not.
let undeclared = Provenance::OnChipCounter {
uncertainty: Uncertainty { relative_ppm: 0, window_us: 2_800_000 },
filtering: CounterFiltering::Unknown,
};
let (bad, _, _) = seal_as("int_video_bitstream.json", 4_200, Some(undeclared));
assert!(!bad.verify(), "a hardware class with no declared uncertainty must not verify");
// And a declared uncertainty cannot be tightened after sealing.
let mut t = r.clone();
t.energy_provenance = Some(
Provenance::on_chip_counter(Uncertainty::new(1_000, 2_800_000).unwrap(), CounterFiltering::Unknown)
.unwrap(),
);
assert!(!t.verify(), "restated uncertainty");
}
/// The refined classes' signed bytes, pinned as they were when the hardware
/// class was split. `legacy_labels_keep_their_signed_bytes` holds the legacy
/// encodings; this holds the refined ones, so a byte that leaks into the
/// evidence encoding (`write_signed`) fails here. The digests were captured
/// from the code as the refined classes were introduced and must never be
/// edited to make a test pass.
#[test]
fn refined_labels_keep_their_signed_bytes() {
let (chip_r, _, _) = seal("int_video_bitstream.json", 4_200);
let cal = Provenance::calibrated_instrument(
Uncertainty::new(5_000, 60_000_000).unwrap(),
"https://calibration.example.org/certificates/0001",
)
.unwrap();
let (cal_r, _, _) = seal_as("int_video_bitstream.json", 4_200, Some(cal));
assert!(chip_r.verify() && cal_r.verify());
assert_eq!(
[
hex(&chip_r.receipt_hash()),
hex(blake3::hash(chip_r.to_json().as_bytes()).as_bytes()),
hex(&cal_r.receipt_hash()),
hex(blake3::hash(cal_r.to_json().as_bytes()).as_bytes()),
],
[
"23b6f548184a543fa324066427648152de6bb367f64aaddb9ff608d8af41543d",
"7ece767eb1428faff0d4dd035d1d85e285461bc4610c5af30223a5c0fc20dcc3",
"c6aad993760ff0b23c57a49e64a4a24c568db2af1c3f18b3c11e659c4ffb4151",
"2d5529def21fdbf30524a53c1638f06c6311bd3d0d50e125ba4d3a4b2fcf69bb",
]
);
}
/// A receipt sealed over the `WIV1` payload (`extensions/integer-payloads.md` §3):
/// its identity is BLAKE3 over the payload, it re-derives from the payload alone,
/// and every reconstruction field — frames, clip commitment, geometry, work — is the
/// one the JSON form's receipt carries, since both decode to the same frames.
#[test]
fn a_wiv1_receipt_identifies_the_payload_and_reconstructs_the_same_clip() {
for (bin, json) in [("int_video_bitstream.wiv1", "int_video_bitstream.json"), ("video_real_bitstream.wiv1", "video_real_bitstream.json")] {
let payload = raw(bin);
let r = VideoReceipt::seal_decode_wiv1(&key(7), "did:example:meter", &payload, 4_200, Some(chip()), None).expect("seal");
assert!(r.verify(), "{bin}");
assert!(r.verify_reconstruction_wiv1(&payload), "{bin}: re-decode must reproduce every frame");
assert_eq!(r.codestream_hash, *blake3::hash(&payload).as_bytes(), "{bin}: the identity is the payload's");
let (legacy, json_bytes, _) = seal(json, 4_200);
assert_eq!((&r.frames, r.clip_hash, r.h, r.w, r.work_pixel_ops), (&legacy.frames, legacy.clip_hash, legacy.h, legacy.w, legacy.work_pixel_ops),
"{bin}: the same reconstruction as the JSON form's receipt");
assert_ne!(r.codestream_hash, legacy.codestream_hash);
// Neither receipt vouches for the other's codestream.
assert!(!r.verify_reconstruction_wiv1(&json_bytes), "{bin}: a JSON form is not a WIV1 payload");
assert!(!legacy.verify_reconstruction_wiv1(&payload), "{bin}: the legacy receipt names the JSON bytes");
let mut other = payload.clone();
let at = other.len() - 5;
other[at] ^= 1;
assert!(!r.verify_reconstruction_wiv1(&other), "{bin}: one changed byte");
}
}
/// The signed bytes of receipts sealed over the `WIV1` payload, captured from the
/// code as this identity was introduced: a metered one with the on-chip class, an
/// unmetered one, and one chained to the first. Never edited to make a test pass.
#[test]
fn wiv1_receipts_keep_their_signed_bytes() {
let payload = raw("int_video_bitstream.wiv1");
let metered = VideoReceipt::seal_decode_wiv1(&key(7), "did:example:meter", &payload, 4_200, Some(chip()), None).unwrap();
let unmetered = VideoReceipt::seal_decode_wiv1(&key(7), "did:example:meter", &payload, 0, None, None).unwrap();
let chained = VideoReceipt::seal_decode_wiv1(&key(7), "did:example:meter", &payload, 0, None, Some(metered.receipt_hash())).unwrap();
assert!(metered.verify() && unmetered.verify() && chained.verify());
let got = [
hex(&metered.codestream_hash),
hex(&metered.receipt_hash()),
hex(blake3::hash(metered.to_json().as_bytes()).as_bytes()),
hex(&unmetered.receipt_hash()),
hex(&chained.receipt_hash()),
];
assert_eq!(
got,
[
"277865b574029f700f4fac023de3ab06ae598ee6f8ed726444e91442a6bd59e9",
"52c0ca1c9b383b9ad83226d423b36ecafbef92bf431432c7426a484c0406a742",
"97a7cb3b2598f609d205159e2ef1b2d7fb2d35e429ee161a6a8fbbd8ffdcae52",
"f19f86c9106981096bdbb5ea06926e3543112c26a5f737732938feb51c2b6119",
"58ca49ab785116aec8d2f3b990722e962967cbca6b4d6fe41087343872bd1628",
]
);
}
/// `video_receipt::decode_wiv1` reports a refusal by its code
/// (`extensions/integer-payloads.md` §8), the decode's as well as the parse's: the
/// refusal fixtures of a run-out stream and an unread word, and a JSON form.
#[test]
fn decode_wiv1_reports_refusal_codes() {
let fixture = |name: &str| std::fs::read(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../int-payload-conformance/refusals").join(name)).unwrap();
let code = |p: &[u8]| wai::video_receipt::decode_wiv1(p).map(|_| ()).unwrap_err();
assert_eq!(code(&fixture("wiv1_exhausted.bin")), "stream_exhausted");
assert_eq!(code(&fixture("wiv1_unread_word.bin")), "stream_noncanonical");
assert_eq!(code(&raw("int_video_bitstream.json")), "bad_magic");
}
/// `VideoReceipt::from_json` is the inverse of `to_json`: the JSON of a receipt of every
/// class (unmetered, the on-chip counter, a calibrated instrument, a model, the legacy
/// label), chained or not, reads back as the same receipt; and a holder of that JSON and
/// the payload, and nothing else, verifies it and re-derives it.
#[test]
#[allow(deprecated)] // the legacy HwShunt label is read back too
fn a_receipt_reads_back_from_its_json() {
use wai::video_receipt::ReadError;
let payload = raw("int_video_bitstream.wiv1");
let cal = Provenance::calibrated_instrument(Uncertainty::new(5_000, 2_800_000).unwrap(), "urn:example:cert \"7\"").unwrap();
let seal = |uj, p, parent| VideoReceipt::seal_decode_wiv1(&key(7), "did:example:meter", &payload, uj, p, parent).unwrap();
let first = seal(4_200, Some(chip()), None);
for r in [
first.clone(),
seal(0, None, None),
seal(4_200, Some(cal), None),
seal(4_200, Some(Provenance::ModelBased), Some(first.receipt_hash())),
seal(4_200, Some(Provenance::HwShunt), None),
VideoReceipt::seal_decode_wiv1(&key(9), "did:example:a \"quoted\" id\\", &payload, 0, None, None).unwrap(),
] {
let j = r.to_json();
let back = VideoReceipt::from_json(&j).unwrap_or_else(|e| panic!("{e}: {j}"));
assert_eq!(back, r);
assert!(back.verify() && back.verify_reconstruction_wiv1(&payload));
assert_eq!(back.to_json(), j, "to_json(from_json(j)) is j");
// Whitespace between the members is the reader's business, not the receipt's.
let spaced = serde_json::to_string_pretty(&serde_json::from_str::<serde_json::Value>(&j).unwrap()).unwrap();
assert!(spaced.contains("\"uj_per_kilopixel_op\": null") || r.joules_micro > 0);
if r.joules_micro == 0 {
assert_eq!(VideoReceipt::from_json(&spaced), Ok(r.clone()), "a re-indented unmetered receipt");
}
}
let j = first.to_json();
let refused = |t: String| VideoReceipt::from_json(&t).unwrap_err();
// Not what to_json writes.
assert_eq!(refused(j.replacen("\"h\":48", "\"h\":48,\"h\":49", 1)), ReadError::Malformed("not JSON read strictly"), "a member named twice");
assert_eq!(refused(j.replacen("{\"profile\"", "{\"extra\":1,\"profile\"", 1)), ReadError::Malformed("members"));
assert_eq!(refused(j.replacen(",\"energy_counter_filtering\":\"Unknown\"", "", 1)), ReadError::Malformed("members"), "the class's evidence dropped");
assert_eq!(refused(j.replacen("wai.video.int_motion/receipt", "wai.video.int_motion/other", 1)), ReadError::Malformed("profile"));
assert_eq!(refused(j.replacen("\"h\":48", "\"h\":48.0", 1)), ReadError::Malformed("h"), "a plain integer is read from its spelling");
assert_eq!(refused(j.replacen("\"w\":48", "\"w\":4294967296", 1)), ReadError::Malformed("w"));
let upper = format!("\"clip_hash\":\"{}\"", hex(&first.clip_hash).to_uppercase());
assert_eq!(refused(j.replacen(&format!("\"clip_hash\":\"{}\"", hex(&first.clip_hash)), &upper, 1)), ReadError::Malformed("clip_hash"));
assert!(matches!(refused(j.replacen("\"OnChipCounter\"", "\"OnChipCountr\"", 1)), ReadError::Class(_)));
// The derived members are held to the receipt.
let rate = format!("{:.6}", first.uj_per_kilopixel_op().unwrap().0);
assert_eq!(refused(j.replacen(&format!("\"uj_per_kilopixel_op\":{rate}"), "\"uj_per_kilopixel_op\":1.000000", 1)), ReadError::RateMismatch);
assert_eq!(refused(j.replacen(&format!("\"uj_per_kilopixel_op\":{rate}"), &format!("\"uj_per_kilopixel_op\":{rate}0"), 1)), ReadError::RateMismatch, "spelled as to_json spells it");
let rh = hex(&first.receipt_hash());
let mut other = rh.clone().into_bytes();
other[0] = if other[0] == b'0' { b'1' } else { b'0' };
assert_eq!(refused(j.replacen(&rh, std::str::from_utf8(&other).unwrap(), 1)), ReadError::ReceiptHashMismatch);
// A field restated reads, and then fails the receipt's own checks.
let restated = VideoReceipt::from_json(&j.replacen("\"joules_micro\":4200", "\"joules_micro\":4201", 1));
assert!(matches!(restated, Err(ReadError::RateMismatch) | Err(ReadError::ReceiptHashMismatch)));
}
/// Three frames of a gradient that moves a pixel a frame, 16 × 16.
fn moving_source() -> Vec<Vec<u8>> {
(0..3u32)
.map(|f| (0..16u32 * 16 * 3).map(|i| { let (p, c) = (i / 3, i % 3); ((p % 16 + f) * 9 + (p / 16) * 5 + c * 40) as u8 }).collect())
.collect()
}
fn enc_params() -> wai::int_video_enc::EncParams {
wai::int_video_enc::EncParams { block: 8, search: 2, mv_precision: 1, q: 4 }
}
/// The encode receipt (integer-payloads §15.3): sealed over the payload the reference
/// encoder writes, re-derived from that payload and the source alone (the source's hashes,
/// the header's parameters, the error recomputed), and refused when any of them is not the
/// receipt's; its JSON form reads back; its class is never the legacy label.
#[test]
#[allow(deprecated)] // the legacy label is refused here
fn an_encode_receipt_is_re_derived_from_its_payload_and_source() {
use wai::video_receipt::{ReadError, VideoEncodeReceipt};
let src = moving_source();
let model = Some(Provenance::ModelBased);
let (r, payload) = VideoEncodeReceipt::seal_encode(&key(7), "did:example:encoder", &src, 16, 16, enc_params(), 1_200, model.clone(), None).unwrap();
assert!(r.verify() && r.verify_encode(&payload, &src));
assert_eq!(r.work_pixel_ops, 3 * 16 * 16 * 3);
let enc = wai::int_video_enc::encode(&src, 16, 16, &enc_params()).unwrap();
assert_eq!((r.sse, payload.clone()), (enc.sse, enc.wiv1), "the error and the payload are the encoder's");
// The payload decodes to frames whose decode receipt is the payload's.
let dec = VideoReceipt::seal_decode_wiv1(&key(7), "did:example:meter", &payload, 0, None, None).unwrap();
assert_eq!(dec.codestream_hash, r.codestream_hash);
// Each part it rests on, changed, is refused.
let mut other = src.clone();
other[1][7] ^= 1;
assert!(!r.verify_encode(&payload, &other), "another source");
let mut p2 = payload.clone();
let at = p2.len() - 3;
p2[at] ^= 1;
assert!(!r.verify_encode(&p2, &src), "another payload");
let restated = |f: &dyn Fn(&mut VideoEncodeReceipt)| { let mut t = r.clone(); f(&mut t); t };
// Each control is signed again over its defect, so the defect alone is what is refused.
let signed = |f: &dyn Fn(&mut VideoEncodeReceipt)| { let mut t = restated(f); t.resign(&key(7)); assert!(t.verify(), "a consistent control"); t };
assert!(!signed(&|t| t.sse += 1).verify_encode(&payload, &src), "an error the decode does not have");
assert!(!signed(&|t| t.params.q = 5).verify_encode(&payload, &src), "a parameter the payload does not have");
let others: Vec<wai::video_receipt::FrameHash> = other.iter().enumerate().map(|(i, f)| wai::video_receipt::source_frame_hash(i as u64, f)).collect();
let claims_other = signed(&|t| { t.source_frames = others.clone(); t.source_hash = wai::video_receipt::source_hash(16, 16, &others); });
assert!(!claims_other.verify_encode(&payload, &src), "a source the receipt does not state, though the decode's error against it is the stated one");
assert!(!restated(&|t| t.params.search = 3).verify(), "search is attested: inside the signature");
assert!(!restated(&|t| t.joules_micro = 1_201).verify(), "the figure is signed");
assert!(!restated(&|t| t.source_frames.swap(0, 2)).verify(), "the frames in order");
// The class: the unmetered marker, a refined class, never the legacy label.
let (u, _) = VideoEncodeReceipt::seal_encode(&key(7), "did:example:encoder", &src, 16, 16, enc_params(), 0, None, None).unwrap();
assert!(u.verify());
let (legacy, _) = VideoEncodeReceipt::seal_encode(&key(7), "did:example:encoder", &src, 16, 16, enc_params(), 1_200, Some(Provenance::HwShunt), None).unwrap();
assert!(!legacy.verify(), "a new profile refuses HwShunt");
let (zero_classed, _) = VideoEncodeReceipt::seal_encode(&key(7), "did:example:encoder", &src, 16, 16, enc_params(), 0, model.clone(), None).unwrap();
assert!(!zero_classed.verify(), "a class beside the marker");
// The JSON form reads back as the receipt, and refuses what it does not write.
for x in [r.clone(), u.clone(), VideoEncodeReceipt::seal_encode(&key(9), "did:example:e", &src, 16, 16, enc_params(), 4_000_000, Some(chip()), Some(r.receipt_hash())).unwrap().0] {
let j = x.to_json();
assert_eq!(VideoEncodeReceipt::from_json(&j), Ok(x.clone()), "{j}");
}
let j = r.to_json();
assert_eq!(VideoEncodeReceipt::from_json(&j.replacen("\"sse\":", "\"sse\":1,\"sse\":", 1)), Err(ReadError::Malformed("not JSON read strictly")));
assert_eq!(VideoEncodeReceipt::from_json(&j.replacen("encode-receipt", "receipt", 1)), Err(ReadError::Malformed("profile")));
assert!(matches!(VideoEncodeReceipt::from_json(&j.replacen(&format!("\"sse\":{}", r.sse), &format!("\"sse\":{}", r.sse + 1), 1)), Err(ReadError::ReceiptHashMismatch)));
}