open-standards/smart-byte/smart-byte-rs/crates/smart-byte-conformance/tests/pack.rs
Transaction Science f9fbd5a3af
Some checks failed
smart-byte conformance gate / Validate conformance JSON files (pull_request) Successful in 4s
smart-byte conformance gate / Second implementation reproduces every vector (pull_request) Successful in 5s
smart-byte conformance gate / Spec changes require vector-pack updates (pull_request) Successful in 4s
smart-byte conformance gate / VERSIONS.md and README.md must exist (pull_request) Successful in 3s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 4s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m51s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m24s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m41s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m10s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m38s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 7m45s
standards workspaces build + test / aac-rs (pull_request) Successful in 4m3s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m51s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 2m3s
standards workspaces build + test / map-rs (pull_request) Successful in 5m27s
standards workspaces build + test / mesh-rs (pull_request) Successful in 2m19s
standards workspaces build + test / openpay (pull_request) Successful in 10m49s
standards workspaces build + test / arl-rs (pull_request) Successful in 47m4s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 46m44s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 42m33s
standards workspaces build + test / joulehook-rs (pull_request) Failing after 18m22s
standards workspaces build + test / sense-rs (pull_request) Successful in 10m25s
standards workspaces build + test / macOS energy backend (jcp-energy) (pull_request) Successful in 4m56s
smart-byte: governance, burns and transfers between clusters, with vectors
smart-byte-state implements cluster_state.md:
- governance: Change and Proposal, electorates, the quorum, the time lock;
- burns: Burn and the retired record;
- exports: ExportStatement and Certificate;
- the import checks.

smart-byte-core: Transition::sign_export and the destination member. The
envelope compares frames within a cluster only.

smart-byte-lockstep: the committing nodes sign each committed frame's export
certificates. The certificates are built from a committing node's report,
never from a node whose state diverged.

state_vectors.json grows to 23 vectors (state-013 to state-023 new,
state-011 extended) and is regenerated in place; v1 is DRAFT. Every new check
has a vector that fails an implementation leaving it out. The README
documents the 14 new error classes, and the regeneration log records the
change.

crosscheck/verify_v1.py implements governance, burns, exports and imports
from the spec text. It reproduces every vector, 117 of them, both plain and
under -O.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 11:48:44 -04:00

694 lines
24 KiB
Rust

//! The published pack, `smart-byte/conformance/v1`, held to the reference
//! implementation under `cargo test` — so CI fails whenever the two disagree.
use std::collections::BTreeSet;
use std::path::Path;
use serde_json::{Value, json};
use smart_byte_conformance::verify::{readme_error_classes, spec_cited_said_vectors};
use smart_byte_conformance::{pack, published_pack_dir, verify::verify_pack};
fn published(file: &str) -> String {
std::fs::read_to_string(published_pack_dir().join(file))
.unwrap_or_else(|e| panic!("read {file}: {e}"))
}
fn vectors(file: &str) -> Vec<Value> {
serde_json::from_str::<Value>(&published(file))
.unwrap()
.as_array()
.unwrap()
.clone()
}
fn by_name(file: &str, name: &str) -> Value {
vectors(file)
.into_iter()
.find(|v| v["name"] == name)
.unwrap_or_else(|| panic!("{file} has no vector {name}"))
}
#[test]
fn every_published_vector_agrees_with_the_reference() {
let report = verify_pack(&published_pack_dir());
let failures = report.failures();
assert!(failures.is_empty(), "{failures:#?}");
// One structure check per file, one check per vector, two completeness
// checks: none skipped.
let total: usize = pack::FILES.iter().map(|f| vectors(f).len()).sum();
assert_eq!(report.checks.len(), pack::FILES.len() + total + 2);
}
#[test]
fn the_published_pack_is_exactly_what_the_reference_generates() {
for (file, generated) in pack::generate() {
assert!(
published(file) == generated,
"{file} differs from the reference implementation's output; regenerate with \
`cargo run -p smart-byte-conformance --bin gen-conformance-vectors`"
);
}
}
/// Write the published pack to `dir` with `edit` applied to the files'
/// parsed contents, and return the names of the checks the verifier fails.
fn failures_with(dir: &Path, edit: impl Fn(&str, &mut Vec<Value>)) -> Vec<String> {
std::fs::create_dir_all(dir).unwrap();
for f in pack::FILES {
let mut items = vectors(f);
edit(f, &mut items);
std::fs::write(dir.join(f), serde_json::to_string_pretty(&items).unwrap()).unwrap();
}
verify_pack(dir)
.failures()
.into_iter()
.map(|c| c.vector.clone())
.collect()
}
fn scratch(name: &str) -> std::path::PathBuf {
Path::new(env!("CARGO_TARGET_TMPDIR")).join(name)
}
/// Falsification: the verifier is not vacuous. Each planted defect — a wrong
/// value, a wrong error class, a negative vector turned positive — must be
/// caught, and caught on the vector it was planted in.
#[test]
fn the_verifier_catches_a_planted_defect_in_every_file() {
let flip_last = |s: &str| {
let mut s = s.to_owned();
let last = s.pop().unwrap();
s.push(if last == '0' { '1' } else { '0' });
s
};
type Plant = (&'static str, &'static str, Box<dyn Fn(&mut Value)>);
let plants: Vec<Plant> = vec![
(
"canonicalisation_vectors.json",
"canon-001-sorted-map-keys",
Box::new(move |v| {
v["expected_cbor_hex"] = json!(flip_last(v["expected_cbor_hex"].as_str().unwrap()))
}),
),
(
"canonicalisation_vectors.json",
"canon-012-text-ordered-keys-refused",
Box::new(|v| v["error"] = json!("duplicate_map_key")),
),
(
"canonicalisation_vectors.json",
"canon-004-floats-forbidden",
Box::new(|v| v["input_cbor_hex"] = json!("a16a65786163745f68616c6601")),
),
(
"canonicalisation_vectors.json",
"canon-020-simple-value-refused",
Box::new(|v| v["input_cbor_hex"] = json!("f6")),
),
(
"said_vectors.json",
"said-008-spec-worked-example",
Box::new(move |v| {
v["expected_said"] = json!(flip_last(v["expected_said"].as_str().unwrap()))
}),
),
(
"said_vectors.json",
"said-009-non-canonical-copy-rejected",
Box::new(|v| v["error"] = json!("said_mismatch")),
),
(
"said_vectors.json",
"said-010-self-consistent-non-canonical-rejected",
Box::new(move |v| {
v["said_of_received_bytes"] =
json!(flip_last(v["said_of_received_bytes"].as_str().unwrap()))
}),
),
(
"said_vectors.json",
"said-003-transferred-envelope",
Box::new(|v| v["input"]["joule_cost"]["measured_microjoules"] = json!(1201)),
),
(
"signature_vectors.json",
"sig-001-issuer-attestation",
Box::new(move |v| v["signature"] = json!(flip_last(v["signature"].as_str().unwrap()))),
),
(
"signature_vectors.json",
"sig-003-message-swapped",
Box::new(|v| {
v["expected_verify"] = json!(true);
v["error"] = Value::Null;
}),
),
(
"signature_vectors.json",
"sig-006-non-canonical-s-rejected",
Box::new(|v| v["error"] = json!("malformed_signature")),
),
(
"signature_vectors.json",
"sig-007-non-canonical-key-rejected",
// The canonical spelling of the same point: now a well-formed key
// that merely fails to verify, so the published class is wrong.
Box::new(|v| {
v["verifying_key"] =
json!("0300000000000000000000000000000000000000000000000000000000000000")
}),
),
(
"kel_vectors.json",
"kel-004-no-next-keys",
Box::new(|v| v["expected"]["next_threshold"] = json!(1)),
),
(
"kel_vectors.json",
"kel-008-rotation-signed-by-current-keys",
Box::new(|v| v["error"] = json!("pre_rotation_mismatch")),
),
(
"kel_vectors.json",
"kel-017-rotation-after-no-next-keys",
Box::new(|v| v["error_at"] = json!(0)),
),
(
"kel_vectors.json",
"kel-022-key-written-as-integers",
// The issuer's inception in its own encoding, with its own
// signature: a log the vector says must be refused, accepted.
Box::new(|v| {
v["events"] =
by_name("kel_vectors.json", "kel-001-single-key-inception")["events"].clone()
}),
),
(
"kel_vectors.json",
"kel-013-duplicate-key",
// A seed that did not make the signature beside it.
Box::new(|v| v["events"][0]["signatures"][1]["seed"] = json!("00".repeat(32))),
),
(
"envelope_vectors.json",
"env-001-issued",
Box::new(move |v| {
v["expected"]["history_hash"] =
json!(flip_last(v["expected"]["history_hash"].as_str().unwrap()))
}),
),
(
"envelope_vectors.json",
"env-011-old-key-under-new-establishment",
Box::new(|v| v["error"] = json!("below_threshold")),
),
(
"envelope_vectors.json",
"env-018-cargo-bytes-written-as-integers",
// env-003 in its own encoding: accepted, though the vector says
// it must be refused.
Box::new(|v| {
let own = by_name("envelope_vectors.json", "env-003-empty-opaque-cargo");
v["envelope"] = own["envelope"].clone();
v["cbor_hex"] = own["cbor_hex"].clone();
}),
),
(
"envelope_vectors.json",
"env-002-transfers-across-a-rotation",
Box::new(|v| v["expected"]["owner"] = v["expected"]["issuer"].clone()),
),
(
"state_vectors.json",
"state-001-issue-transfer-rotate",
Box::new(move |v| {
let h = v["frames"][1]["expected_state_hash"]
.as_str()
.unwrap()
.to_owned();
v["frames"][1]["expected_state_hash"] = json!(flip_last(&h));
}),
),
(
"state_vectors.json",
"state-007-transfer-checks",
Box::new(|v| {
let results = v["frames"][1]["expected_results"].as_array_mut().unwrap();
let r = results
.iter_mut()
.find(|r| r["error"] == "broken_history_chain")
.unwrap();
r["error"] = json!("unknown_byte");
}),
),
(
"state_vectors.json",
"state-004-rotation-retires-old-keys",
// Application order is part of the result: the key event first.
Box::new(|v| {
v["frames"][1]["expected_results"]
.as_array_mut()
.unwrap()
.reverse()
}),
),
(
"state_vectors.json",
"state-011-malformed-inputs",
Box::new(|v| {
let results = v["frames"][0]["expected_results"].as_array_mut().unwrap();
let r = results
.iter_mut()
.find(|r| r["error"] == "non_shortest_integer")
.unwrap();
r["class"] = json!("transfer");
}),
),
(
"state_vectors.json",
"state-012-duplicate-submissions",
// A duplicate counted as a second input.
Box::new(|v| {
let results = v["frames"][0]["expected_results"].as_array_mut().unwrap();
let first = results[0].clone();
results.insert(1, first);
}),
),
(
"state_vectors.json",
"state-009-signers-need-their-log",
// Without Alice's inception her transfer cannot be checked.
Box::new(|v| {
let inputs = v["frames"][2]["inputs"].as_array_mut().unwrap();
inputs.retain(|i| i["input"].get("key_event").is_none());
}),
),
(
"state_vectors.json",
"state-013-issuer-added-after-the-delay",
Box::new(|v| v["frames"][2]["expected_results"][0]["error"] = json!("below_quorum")),
),
(
"state_vectors.json",
"state-015-removal-without-the-target",
Box::new(|v| v["frames"][1]["expected_results"][0]["error"] = json!("below_quorum")),
),
(
"state_vectors.json",
"state-018-redemption",
Box::new(|v| {
let results = v["frames"][3]["expected_results"].as_array_mut().unwrap();
let r = results
.iter_mut()
.find(|r| r["error"] == "duplicate_byte")
.unwrap();
r["error"] = json!("byte_retired");
}),
),
(
"state_vectors.json",
"state-019-export-and-return",
Box::new(move |v| {
let h = v["frames"][2]["expected_state_hash"]
.as_str()
.unwrap()
.to_owned();
v["frames"][2]["expected_state_hash"] = json!(flip_last(&h));
}),
),
(
"state_vectors.json",
"state-020-import-and-send-back",
Box::new(|v| {
let results = v["frames"][0]["expected_results"].as_array_mut().unwrap();
let r = results.iter_mut().find(|r| r["class"] == "import").unwrap();
r["outcome"] = json!("dropped");
r["error"] = json!("duplicate_import");
}),
),
(
"state_vectors.json",
"state-021-import-checks",
Box::new(|v| {
let results = v["frames"][1]["expected_results"].as_array_mut().unwrap();
let r = results
.iter_mut()
.find(|r| r["error"] == "below_threshold")
.unwrap();
r["error"] = json!("signature_invalid");
}),
),
(
"state_vectors.json",
"state-023-an-import-meets-the-byte",
// A burned byte's import reported as if the byte were still live.
Box::new(|v| v["frames"][2]["expected_results"][0]["error"] = json!("duplicate_byte")),
),
(
"lockstep_vectors.json",
"lockstep-002-supermajority-commit",
Box::new(|v| v["expected_dissent_logs"]["node_1"] = json!([])),
),
(
"lockstep_vectors.json",
"lockstep-004-three-nodes-one-diverged-split",
Box::new(|v| v["expected_commit"] = json!(true)),
),
(
"lockstep_vectors.json",
"lockstep-002-supermajority-commit",
Box::new(|v| v["expected_outcomes"]["node_4"] = json!("commit_with_dissent")),
),
(
"lockstep_vectors.json",
"lockstep-006-transport-liar-is-logged",
Box::new(|v| v["expected_outcomes"]["node_4"] = json!("minority_divergence")),
),
(
"gossip_vectors.json",
"gossip-002-said-conflict-rejected",
Box::new(|v| {
v["expected_results"][1] =
json!({"outcome": "duplicate", "said": v["expected_results"][0]["said"]})
}),
),
(
"gossip_vectors.json",
"gossip-005-non-canonical-copy-rejected",
Box::new(|v| {
let s = v["deliveries"][0]["claimed_said"].clone();
let b = v["deliveries"][0]["cbor_hex"].clone();
v["expected_results"][0] = json!({"outcome": "accepted", "said": s});
v["expected_held"] = json!([{"said": s, "cbor_hex": b}]);
}),
),
(
"gossip_vectors.json",
"gossip-001-cross-node-propagation",
Box::new(move |v| {
let h = v["expected_held"][0]["cbor_hex"]
.as_str()
.unwrap()
.to_owned();
v["expected_held"][0]["cbor_hex"] = json!(flip_last(&h));
}),
),
];
for (i, (file, name, mutate)) in plants.iter().enumerate() {
let failed = failures_with(&scratch(&format!("planted/{i}")), |f, items| {
if f == *file {
mutate(items.iter_mut().find(|v| v["name"] == *name).expect(name));
}
});
assert_eq!(
failed,
vec![name.to_string()],
"planted defect {i} in {file}/{name}"
);
}
}
/// A defect in a log the envelope vectors draw key states from fails that
/// log and every envelope vector, and nothing else.
#[test]
fn a_defect_in_a_log_fails_the_envelopes_that_rely_on_it() {
let failed = failures_with(&scratch("planted/log-dependency"), |f, items| {
if f == "kel_vectors.json" {
let v = items
.iter_mut()
.find(|v| v["name"] == "kel-003-two-of-three-rotation")
.unwrap();
// Drop the rotation's second signature: one of the two it needs.
v["events"][1]["signatures"].as_array_mut().unwrap().pop();
}
});
let mut expected = vec!["kel-003-two-of-three-rotation".to_string()];
expected.extend(
vectors("envelope_vectors.json")
.iter()
.map(|v| v["name"].as_str().unwrap().to_owned()),
);
assert_eq!(failed, expected);
}
/// Falsification: a pack cannot pass by losing vectors.
#[test]
fn an_incomplete_pack_fails() {
// Every file emptied.
let failed = failures_with(&scratch("incomplete/empty"), |_, items| items.clear());
for f in pack::FILES {
assert!(failed.contains(&"(file)".to_string()), "{f}");
}
assert!(failed.contains(&"spec-cited vectors present".to_string()));
assert!(failed.contains(&"README error classes exercised".to_string()));
// One vector the spec cites, deleted.
let failed = failures_with(&scratch("incomplete/said-010"), |f, items| {
if f == "said_vectors.json" {
items.retain(|v| !v["name"].as_str().unwrap().starts_with("said-010-"));
}
});
assert_eq!(failed, vec!["spec-cited vectors present".to_string()]);
// The only vector exercising a README error class, deleted.
let failed = failures_with(&scratch("incomplete/class"), |f, items| {
if f == "canonicalisation_vectors.json" {
items.retain(|v| v["name"] != "canon-020-simple-value-refused");
}
});
assert_eq!(failed, vec!["README error classes exercised".to_string()]);
}
/// Falsification: a vector that names an error class the README does not
/// list is caught, so the README stays the full list.
#[test]
fn an_undocumented_error_class_fails() {
let failed = failures_with(&scratch("undocumented"), |f, items| {
if f == "canonicalisation_vectors.json" {
let mut extra = items
.iter()
.find(|v| v["name"] == "canon-018-trailing-bytes-refused")
.unwrap()
.clone();
extra["name"] = json!("canon-099-made-up");
extra["error"] = json!("made_up_class");
items.push(extra);
}
});
assert!(failed.contains(&"README error classes exercised".to_string()));
assert!(failed.contains(&"canon-099-made-up".to_string()));
}
#[test]
fn a_pack_with_a_duplicated_json_member_fails() {
let dir = scratch("duplicate-member");
std::fs::create_dir_all(&dir).unwrap();
for f in pack::FILES {
let mut body = published(f);
if f == "lockstep_vectors.json" {
// Name a member twice; a plain JSON parser would keep the last.
body = body.replacen(
"\"node_count\": 4,",
"\"node_count\": 4,\n \"node_count\": 4,",
1,
);
}
std::fs::write(dir.join(f), body).unwrap();
}
let report = verify_pack(&dir);
let failed: Vec<&str> = report.failures().iter().map(|c| c.file.as_str()).collect();
assert_eq!(failed, vec!["lockstep_vectors.json"]);
}
#[test]
fn the_said_pack_holds_the_suite_the_spec_names() {
let cited = spec_cited_said_vectors().unwrap();
for n in 1..=11 {
assert!(
cited.contains(&format!("said-{n:03}")),
"the spec no longer cites said-{n:03}"
);
}
let keys = |name: &str| -> BTreeSet<String> {
by_name("said_vectors.json", name)["input"]
.as_object()
.unwrap()
.keys()
.cloned()
.collect()
};
let set = |ks: &[&str]| ks.iter().map(|k| k.to_string()).collect::<BTreeSet<_>>();
assert_eq!(keys("said-006-only-said-field"), set(&["d"]));
assert_eq!(keys("said-007-one-field-per-key"), set(&["d", "k"]));
assert_eq!(keys("said-008-spec-worked-example"), set(&["d", "n"]));
}
#[test]
fn every_canonical_rule_has_a_negative_vector() {
let classes: BTreeSet<String> = vectors("canonicalisation_vectors.json")
.into_iter()
.filter_map(|v| v["error"].as_str().map(str::to_owned))
.collect();
for rule in [
"non_shortest_integer",
"non_shortest_length",
"unsorted_map_keys",
"duplicate_map_key",
"float_forbidden",
"simple_value_forbidden",
"tag_forbidden",
"indefinite_length",
"invalid_utf8",
"trailing_bytes",
] {
assert!(
classes.contains(rule),
"no canonicalisation vector is refused with {rule}"
);
assert!(
readme_error_classes().unwrap().contains(rule),
"README omits {rule}"
);
}
}
#[test]
fn the_spec_prints_the_worked_example_the_pack_computes() {
let spec = std::fs::read_to_string(
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../spec/identity_and_key_rotation.md"),
)
.unwrap();
let example = by_name("said_vectors.json", "said-008-spec-worked-example");
for field in ["blake3_hex", "expected_said", "canonical_cbor_hex"] {
let value = example[field].as_str().unwrap();
assert!(
spec.contains(value),
"identity spec §2.4 does not print the pack's {field} {value}"
);
}
assert!(
spec.contains("total 61 bytes"),
"§2.4 must give the encoding's real length"
);
}
/// The files describe one world: the SAID vectors' objects are the envelope
/// and key-event-log vectors' objects, and the signature vectors sign their
/// messages.
#[test]
fn the_files_describe_one_world() {
let said = |name: &str| by_name("said_vectors.json", name)["expected_said"].clone();
let issued = by_name("envelope_vectors.json", "env-001-issued");
let transferred = by_name(
"envelope_vectors.json",
"env-002-transfers-across-a-rotation",
);
let alice = by_name("kel_vectors.json", "kel-002-rotation-then-interaction");
assert_eq!(
said("said-001-issued-envelope"),
issued["expected"]["snapshot"]
);
assert_eq!(
said("said-002-byte-identity"),
issued["expected"]["identity"]
);
assert_eq!(
said("said-003-transferred-envelope"),
transferred["expected"]["snapshot"]
);
assert_eq!(
said("said-004-rotation-event"),
alice["expected"]["event_saids"][1]
);
assert_eq!(
said("said-005-interaction-event"),
alice["expected"]["event_saids"][2]
);
// Alice's interaction anchors the byte she was issued.
assert_eq!(
alice["events"][2]["event"]["a"][0],
issued["expected"]["identity"]
);
let sig = |name: &str| by_name("signature_vectors.json", name);
let without_algorithm = |j: &Value| j.as_str().unwrap()[2..].to_owned();
let attestation = smart_byte_conformance::world::World::build()
.issued
.provenance
.signed_bytes();
assert_eq!(
sig("sig-001-issuer-attestation")["message_hex"],
json!(hex::encode(attestation))
);
assert_eq!(
sig("sig-001-issuer-attestation")["signature"],
json!(without_algorithm(
&issued["envelope"]["provenance"]["signature"]["signatures"][0]["signature"]["$bytes"]
))
);
assert_eq!(
sig("sig-002-key-event")["message_hex"],
alice["events"][0]["cbor_hex"]
);
assert_eq!(
sig("sig-002-key-event")["signature"],
json!(without_algorithm(
&alice["events"][0]["signatures"][0]["signature"]
))
);
// The cluster's founding frame: the three logs' inceptions and env-001's
// mint, as the other files give them.
let journey = by_name("state_vectors.json", "state-001-issue-transfer-rotate");
let founding: Vec<&Value> = journey["frames"][0]["inputs"]
.as_array()
.unwrap()
.iter()
.map(|i| &i["input"])
.collect();
for log in [
"kel-001-single-key-inception",
"kel-002-rotation-then-interaction",
"kel-003-two-of-three-rotation",
] {
let event = &by_name("kel_vectors.json", log)["events"][0]["event"];
assert!(
founding.iter().any(|i| &i["key_event"]["event"] == event),
"{log}'s inception"
);
}
assert!(
founding
.iter()
.any(|i| i["mint"] == issued["envelope"]["provenance"]),
"env-001's mint"
);
// A's export is what B imports, and B's export is what A takes back.
let a = by_name("state_vectors.json", "state-019-export-and-return");
let b = by_name("state_vectors.json", "state-020-import-and-send-back");
let id = issued["expected"]["identity"].as_str().unwrap();
let imported = |frame: &Value| {
frame["inputs"]
.as_array()
.unwrap()
.iter()
.find_map(|i| i["input"].get("import").cloned())
.unwrap()["certificate"]["statement"]["export"]
.clone()
};
assert_eq!(
imported(&b["frames"][0]),
a["frames"][2]["expected_state"]["exported"][id]
);
assert_eq!(
imported(&a["frames"][4]),
b["frames"][1]["expected_state"]["exported"][id]
);
// The byte the cluster holds is env-001's.
let state = &journey["frames"][0]["expected_state"];
assert!(
state["bytes"]
.get(issued["expected"]["identity"].as_str().unwrap())
.is_some()
);
}