open-standards/mesh/mesh-rs/crates/mesh-conformance/tests/pack.rs
Transaction Science e5a1b96e7a
Some checks failed
standards workspaces build + test / aac-rs (push) Successful in 1m47s
standards workspaces build + test / eoc-rs (push) Successful in 2m0s
standards workspaces build + test / jcp-rs (push) Successful in 1m25s
standards workspaces build + test / joule-code-rs (push) Successful in 2m11s
standards workspaces build + test / proof-rs (push) Successful in 1m13s
standards workspaces build + test / sandbox-rs (push) Successful in 2m21s
standards workspaces build + test / smart-byte-rs (push) Successful in 2m32s
standards workspaces build + test / jouleclaw-rs (push) Failing after 8m2s
standards workspaces build + test / joulecontract-rs (push) Successful in 1m14s
standards workspaces build + test / map-rs (push) Successful in 1m4s
standards workspaces build + test / mesh-rs (push) Successful in 45s
standards workspaces build + test / openpay (push) Successful in 3m45s
standards workspaces build + test / arl-rs (push) Successful in 2m29s
standards workspaces build + test / joule-ui-rs (push) Successful in 2m27s
standards workspaces build + test / jouledesk-rs (push) Successful in 2m23s
standards workspaces build + test / joulehook-rs (push) Successful in 2m7s
standards workspaces build + test / sense-rs (push) Successful in 2m3s
mesh: hold the reference implementation to its published conformance pack
conformance/v1 says a conforming implementation "MUST reproduce" its bytes, and
gen_vectors writes it, but nothing read it back. The existing tests re-run
reference_scenario() and compare it against the crate's own constants, so they
check the implementation against itself.

That gap is measured, not assumed. Changing the reference serve (SPAN_UJ
3_200_000 -> 3_200_001) leaves all four existing end_to_end tests green: both
sides of every comparison move together. A receipt-shape change would have
left this pack silently stale -- which is what happened to joulehook's.

tests/pack.rs answers two separate questions:

  - Drift: the reference implementation still emits exactly the published
    envelope.hex, signed_core.hex, receipt.json and meta.json, compared in the
    form gen_vectors writes them. Under the change above, this and the
    pinned-outcome test go red.

  - The README's cross-language check, done the way a third party would: from the
    pack files and RFC 9052 alone, with a hand-built CBOR encoder and no mesh COSE
    code, build Sig_structure ["Signature1", {1:-8, 4:steward}, h'', signed_core],
    verify the published signature under meta.json's key, and re-sign with the
    documented seed to rebuild the 663-byte envelope byte for byte. It does. So
    the claim holds from the RFC, not merely from the implementation agreeing
    with itself. These pack-only tests correctly stay green under the change
    above, since the pack remains self-consistent.

Plus negatives -- a single flipped payload byte and a stranger's key must both
fail verification -- and the pinned outcome read from the published receipt,
with the wedge metric recomputed from measured_uj / tokens_accepted rather than
trusted as a number.

The pack is current: a fresh regeneration into a scratch directory matched all
four files byte for byte, so nothing needed refreshing.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-17 07:45:47 -04:00

215 lines
8.5 KiB
Rust

//! Consume the published `mesh/1` conformance pack.
//!
//! `gen_vectors` writes `conformance/v1/` and nothing read it back: the other tests in
//! this crate re-run `reference_scenario()`, so they check the implementation against
//! itself. A pack that says a conforming implementation "MUST reproduce" its bytes
//! needs a test that holds the reference implementation to those bytes too.
//!
//! Two different questions, answered separately:
//!
//! 1. **Drift** — does the reference implementation still emit exactly the published
//! files? This is the failure a pack silently develops when the receipt shape
//! changes and nobody regenerates.
//! 2. **Cross-language check** — the README's own claim, checked the way a third
//! party would: from the pack files and RFC 9052 alone, with a hand-built CBOR
//! encoder and no mesh COSE code, reproduce `envelope.hex` byte for byte.
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
use mesh_conformance::{MAX_TOKENS, SPAN_UJ, STEWARD_SEED, reference_scenario};
use serde_json::Value;
use std::path::PathBuf;
fn pack_dir() -> PathBuf {
let d = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../../conformance/v1");
d.canonicalize().expect("the conformance pack must exist next to the spec")
}
fn text(rel: &str) -> String {
std::fs::read_to_string(pack_dir().join(rel)).unwrap_or_else(|e| panic!("read {rel}: {e}"))
}
fn hexfile(rel: &str) -> Vec<u8> {
hex::decode(text(rel).trim()).unwrap_or_else(|e| panic!("{rel} is not hex: {e}"))
}
fn json(rel: &str) -> Value {
serde_json::from_str(&text(rel)).unwrap_or_else(|e| panic!("{rel} must parse: {e}"))
}
// --- A deliberately minimal CBOR encoder (RFC 8949), independent of mesh ---------
fn head(major: u8, len: u64) -> Vec<u8> {
let m = major << 5;
match len {
0..=23 => vec![m | len as u8],
24..=0xff => vec![m | 24, len as u8],
0x100..=0xffff => {
let mut v = vec![m | 25];
v.extend_from_slice(&(len as u16).to_be_bytes());
v
}
_ => {
let mut v = vec![m | 26];
v.extend_from_slice(&(len as u32).to_be_bytes());
v
}
}
}
fn bstr(b: &[u8]) -> Vec<u8> {
let mut v = head(2, b.len() as u64);
v.extend_from_slice(b);
v
}
fn tstr(s: &str) -> Vec<u8> {
let mut v = head(3, s.len() as u64);
v.extend_from_slice(s.as_bytes());
v
}
/// The protected header the README specifies: `{1: -8, 4: <steward bytes>}`, keys in
/// deterministic (bytewise) order.
fn protected_header(kid: &str) -> Vec<u8> {
let mut v = head(5, 2); // map(2)
v.push(0x01); // 1 (alg)
v.push(0x27); // -8 (EdDSA): major 1, value 7
v.push(0x04); // 4 (kid)
v.extend(bstr(kid.as_bytes()));
v
}
/// RFC 9052 §4.4: `Sig_structure = ["Signature1", protected, external_aad, payload]`.
fn sig_structure(protected: &[u8], payload: &[u8]) -> Vec<u8> {
let mut v = head(4, 4);
v.extend(tstr("Signature1"));
v.extend(bstr(protected));
v.extend(bstr(&[])); // empty external AAD
v.extend(bstr(payload));
v
}
/// RFC 9052 §4.2: tag 18 over `[protected, unprotected, payload, signature]`.
fn cose_sign1(protected: &[u8], payload: &[u8], sig: &[u8]) -> Vec<u8> {
let mut v = vec![0xd2]; // tag 18
v.extend(head(4, 4));
v.extend(bstr(protected));
v.extend(head(5, 0)); // empty unprotected map
v.extend(bstr(payload));
v.extend(bstr(sig));
v
}
// --- 1. Drift ---------------------------------------------------------------------
/// The reference implementation still emits exactly the published files. Compared in
/// the form `gen_vectors` writes them, so any change to the receipt — a new field, a
/// renamed one, a different route — shows up here instead of in a third party's
/// failed verification.
#[test]
fn the_reference_implementation_still_emits_the_published_pack() {
let s = reference_scenario();
let core = s.receipt.signed_core(&s.steward).expect("reference receipt signs");
assert_eq!(
format!("{}\n", hex::encode(&s.envelope)),
text("reference/envelope.hex"),
"envelope.hex is stale against the reference implementation"
);
assert_eq!(
format!("{}\n", hex::encode(&core)),
text("reference/signed_core.hex"),
"signed_core.hex is stale against the reference implementation"
);
assert_eq!(
format!("{}\n", serde_json::to_string_pretty(&s.receipt.to_jcr1_wire(&s.steward)).unwrap()),
text("reference/receipt.json"),
"receipt.json is stale against the reference implementation"
);
let meta = json("meta.json");
assert_eq!(meta["steward"], s.steward.as_str());
assert_eq!(meta["pubkey_hex"], hex::encode(s.verifying_key).as_str());
}
// --- 2. Cross-language check ------------------------------------------------------
/// The README's claim, verified from the pack and the RFC alone: the published
/// envelope is exactly `signed_core` wrapped per RFC 9052 and signed by the key
/// `meta.json` publishes.
#[test]
fn envelope_is_reproduced_from_signed_core_and_rfc_9052_alone() {
let meta = json("meta.json");
let kid = meta["steward"].as_str().expect("meta names the steward");
let pubkey: [u8; 32] = hex::decode(meta["pubkey_hex"].as_str().unwrap())
.unwrap()
.try_into()
.expect("a 32-byte Ed25519 key");
let core = hexfile("reference/signed_core.hex");
let envelope = hexfile("reference/envelope.hex");
let protected = protected_header(kid);
let to_sign = sig_structure(&protected, &core);
// Verifier direction — needs only what is published, not the seed.
let sig_bytes = &envelope[envelope.len() - 64..];
let sig = Signature::from_slice(sig_bytes).expect("64-byte signature");
VerifyingKey::from_bytes(&pubkey)
.unwrap()
.verify(&to_sign, &sig)
.expect("the published envelope must verify under the published key");
// Signer direction — Ed25519 is deterministic, so re-signing with the documented
// steward seed must rebuild the envelope exactly.
let sk = SigningKey::from_bytes(&STEWARD_SEED);
assert_eq!(sk.verifying_key().to_bytes(), pubkey, "meta.json pubkey is not the seed's");
let rebuilt = cose_sign1(&protected, &core, &sk.sign(&to_sign).to_bytes());
assert_eq!(rebuilt, envelope, "hand-built COSE_Sign1 does not match envelope.hex");
assert_eq!(envelope.len(), 663);
}
/// The verifier direction is not vacuous: a single changed payload byte, or the right
/// bytes under the wrong key, must both fail.
#[test]
fn a_tampered_core_or_a_wrong_key_does_not_verify() {
let meta = json("meta.json");
let kid = meta["steward"].as_str().unwrap();
let pubkey: [u8; 32] =
hex::decode(meta["pubkey_hex"].as_str().unwrap()).unwrap().try_into().unwrap();
let envelope = hexfile("reference/envelope.hex");
let sig = Signature::from_slice(&envelope[envelope.len() - 64..]).unwrap();
let protected = protected_header(kid);
let mut core = hexfile("reference/signed_core.hex");
let mid = core.len() / 2;
core[mid] ^= 0x01;
assert!(
VerifyingKey::from_bytes(&pubkey).unwrap().verify(&sig_structure(&protected, &core), &sig).is_err(),
"a tampered signed core verified"
);
let core = hexfile("reference/signed_core.hex");
let stranger = SigningKey::from_bytes(&[0x42; 32]).verifying_key();
assert!(
stranger.verify(&sig_structure(&protected, &core), &sig).is_err(),
"the envelope verified under a key that did not sign it"
);
}
/// The outcome the README pins, read from the published receipt. The wedge metric is
/// recomputed from the receipt's own fields rather than trusted as a number.
#[test]
fn published_receipt_carries_the_pinned_outcome() {
let r = json("reference/receipt.json");
assert_eq!(r["mesh_receipt"], "mesh/1");
assert_eq!(r["backend"], "tiny", "cache is below the F1 floor; merge/frontier exceed 8 J");
assert_eq!(r["energy_provenance"], "HwShunt");
assert_eq!(r["measured_uj"], SPAN_UJ);
assert_eq!(r["tokens_accepted"], MAX_TOKENS);
assert_eq!(r["sequence"], 0, "the reference receipt is the chain's genesis");
assert!(r["fidelity_met"].as_u64() >= r["fidelity_floor"].as_u64(), "fidelity floor not met");
let per_token = r["measured_uj"].as_u64().unwrap() / r["tokens_accepted"].as_u64().unwrap();
assert_eq!(per_token, 50_000);
assert_eq!(r["uj_per_accepted_token"], per_token, "wedge metric disagrees with its inputs");
assert_eq!(r["steward"], json("meta.json")["steward"]);
}