open-standards/wai/wai-rs/tests/fleet.rs
Transaction Science be42dd3b1f wai.delivery.fleet: an organisation's nodes enrolled by their keys, their records verified, and a report signed for a period
extensions/fleet.md: the enrolment (WFE1), the records a node contributes as it
signs them (a relay's session summaries, per-hop records with their ledgers, the
room descriptors that place them), placement in time and one thing once, the
fleet report (WFR1) with node and room lines, energy per scope and class with
unmetered figures counted as unmetered, citations, the bundle and its
verification, and the reasons.

wai-rs: the fleet module (feature fleet), its corpus generator
(wai_fleet_vectors), tests/fleet.rs; live-conformance/fleet/ (63 vectors) and
fleet_verify.py, the second implementation.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 15:22:20 -04:00

168 lines
9.2 KiB
Rust

//! `wai.delivery.fleet` (extensions/fleet.md): the committed corpus
//! `live-conformance/fleet/vectors.json` regenerates byte for byte from its seeds and the metering
//! corpus, and is the only file there besides its README; every vector gets the outcome it states;
//! every reason the extension adds and every code it reuses refuses a vector; the accepted vectors
//! are the cases §11 names, with measured, unmetered and partial energy stated as §5.4 states
//! them; a fleet's records held as a service holds them sign the report the corpus holds; and §10
//! lists exactly the reasons the reference reports.
#![cfg(feature = "fleet")]
use std::collections::BTreeSet;
use std::path::PathBuf;
use serde_json::{json, Value};
use wai::fleet::{self, corpus, Held, Reason};
fn wai_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
fn read(p: &str) -> String {
std::fs::read_to_string(wai_dir().join(p)).unwrap_or_else(|e| panic!("{p}: {e}"))
}
fn committed() -> String {
read("live-conformance/fleet/vectors.json")
}
fn doc() -> Value {
serde_json::from_str(&committed()).unwrap()
}
fn vector(d: &Value, name: &str) -> Value {
d["vectors"].as_array().unwrap().iter().find(|v| v["name"] == name).unwrap_or_else(|| panic!("no vector {name}")).clone()
}
#[test]
fn the_committed_corpus_regenerates_from_its_seeds_and_the_metering_corpus() {
let generated = corpus::generate(&wai_dir()).expect("the corpus generates");
assert!(committed() == generated, "live-conformance/fleet/vectors.json differs from `wai_fleet_vectors gen`");
let mut files: Vec<String> = std::fs::read_dir(wai_dir().join("live-conformance/fleet")).unwrap().flatten().map(|e| e.file_name().to_string_lossy().into_owned()).collect();
files.sort();
assert_eq!(files, ["README.md", "vectors.json"]);
}
#[test]
fn every_vector_gets_its_stated_outcome() {
let fails = corpus::verify(&committed());
assert!(fails.is_empty(), "{}", fails.join("\n"));
}
/// Every reason this extension adds and every code it reuses refuses a vector.
#[test]
fn the_corpus_refuses_every_reason() {
let d = doc();
let seen: BTreeSet<&str> = d["vectors"].as_array().unwrap().iter().filter_map(|v| v["outcome"]["reason"].as_str()).collect();
for r in Reason::ALL.iter().chain(Reason::REUSED.iter()) {
assert!(seen.contains(r.code()), "nothing in the corpus is refused {r}");
}
}
fn coverage(e: &Value, scope: &str) -> String {
e[scope]["coverage"].as_str().unwrap().to_string()
}
fn classes(e: &Value, scope: &str) -> Vec<String> {
e[scope]["rows"].as_array().unwrap().iter().map(|r| r["class"].as_str().unwrap().to_string()).collect()
}
/// The accepted vectors are §11's, and state energy as §5.4 states it: measured with its class,
/// unmetered as unmetered, a mix as partial, and a silent node as silent.
#[test]
fn the_accepted_vectors_state_measured_unmetered_and_partial_energy() {
let d = doc();
let week = vector(&d, "a_week")["outcome"].clone();
assert_eq!(week["outcome"], "accept");
let lesson = &week["rooms"][0];
assert_eq!(classes(&lesson["energy"], "hops"), ["ModelBased", "Estimator", "OnChipCounter"], "one row per class, never one across them");
assert_eq!(coverage(&lesson["energy"], "hops"), "whole");
assert_eq!(coverage(&week["rooms"][1]["energy"], "hops"), "unmetered", "the reference relay's recorded hop");
assert_eq!(coverage(&week["totals"]["energy"], "hops"), "partial", "measured and unmetered hops together");
assert_eq!(coverage(&week["totals"]["energy"], "sessions"), "unmetered", "every session's figure is the marker");
assert_eq!(week["totals"]["energy"]["sessions"]["unmetered"], 7);
assert_eq!(week["totals"]["energy"]["hops"]["unmetered"], 1);
let silent: Vec<&str> = week["enrolments"].as_array().unwrap().iter().filter(|e| e["silent"] == true).map(|e| e["label"].as_str().unwrap()).collect();
assert_eq!(silent, ["room service"], "enrolled and silent: listed, with no line");
assert!(week["nodes"].as_array().unwrap().iter().all(|n| n["label"] != "room service"));
let edge = week["nodes"].as_array().unwrap().iter().find(|n| n["label"] == "edge").unwrap();
let home = week["nodes"].as_array().unwrap().iter().find(|n| n["label"] == "home").unwrap();
assert_eq!((edge["links"].as_u64(), home["links"].as_u64()), (Some(1), Some(1)), "the edge's upstream link, one session at each end");
assert_eq!(edge["link_bytes_in"], home["link_bytes_out"], "what home sent over the link, the edge received");
assert!(week["nodes"].as_array().unwrap().iter().chain(week["rooms"].as_array().unwrap()).all(|l| !l["cites"].as_array().unwrap().is_empty()), "every line cites its records");
let measured = vector(&d, "measured_only")["outcome"].clone();
assert_eq!(coverage(&measured["totals"]["energy"], "hops"), "whole");
assert_eq!(coverage(&measured["totals"]["energy"], "sessions"), "none");
let row = &measured["totals"]["energy"]["hops"]["rows"][0];
assert_eq!((row["class"].as_str(), row["figures"].as_u64()), (Some("OnChipCounter"), Some(2)));
assert!(row["max_ppm"].as_u64().unwrap() > 0, "the largest declared uncertainty of the two");
let unmetered = vector(&d, "unmetered_only")["outcome"].clone();
assert_eq!(coverage(&unmetered["totals"]["energy"], "sessions"), "unmetered");
assert_eq!(coverage(&unmetered["totals"]["energy"], "hops"), "none");
assert!(unmetered["totals"]["energy"]["sessions"]["rows"].as_array().unwrap().is_empty(), "no row, never a figure of zero joules");
let silent = vector(&d, "enrolled_and_silent")["outcome"].clone();
assert_eq!((silent["nodes"].as_array().unwrap().len(), silent["rooms"].as_array().unwrap().len()), (0, 0));
assert!(silent["enrolments"].as_array().unwrap().iter().all(|e| e["silent"] == true));
assert_eq!(coverage(&silent["totals"]["energy"], "hops"), "none");
}
/// A fleet held as the service holds it (§9): the week's enrolments and records admitted one by
/// one, in the corpus's order, sign the corpus's report byte for byte; each record is admitted
/// once; and the per-hop records of a room come back in the ledger's source form (§8).
#[test]
fn a_held_fleet_signs_the_corpus_report() {
let d = doc();
let week = vector(&d, "a_week");
let b = &week["bundle"];
let org_seed: [u8; 32] = {
use sha2::{Digest, Sha256};
Sha256::new().chain_update(b"wai:fleet/corpus/key\x00").chain_update(b"organisation").finalize().into()
};
let org = ed25519_dalek::SigningKey::from_bytes(&org_seed);
let mut held = Held::new(org.verifying_key().to_bytes());
for e in b["enrolments"].as_array().unwrap() {
held.enrol(&fleet::unhex(e.as_str().unwrap()).unwrap()).unwrap();
}
assert_eq!(held.enrol(&fleet::unhex(b["enrolments"][0].as_str().unwrap()).unwrap()).unwrap_err(), Reason::EnrolmentDuplicate);
for r in b["records"].as_array().unwrap() {
held.admit(r).unwrap_or_else(|e| panic!("{r}: {e}"));
}
for r in b["records"].as_array().unwrap().iter().take(3) {
assert_eq!(held.admit(r).unwrap_err(), Reason::RecordDuplicate, "a record is held once");
}
let start = week["outcome"]["start"].as_u64().unwrap();
let end = week["outcome"]["end"].as_u64().unwrap();
let (report, bundle) = held.report(&org, start, end).unwrap();
assert_eq!(Value::String(fleet::hex(&report.to_bytes())), b["report"], "the corpus's report, byte for byte");
assert_eq!(fleet::outcome_json(&fleet::verify(&bundle)), week["outcome"]);
let lesson = week["outcome"]["rooms"][0]["room"].as_str().unwrap();
let hops = held.hops_of(&fleet::unhex(lesson).unwrap().try_into().unwrap());
assert_eq!(hops.len(), 3);
assert!(hops.iter().all(|h| h.as_object().unwrap().keys().cloned().collect::<Vec<_>>() == ["record", "ledger"]));
// A day of the week holds the lesson's records and none of the relay room's.
let (_, day) = held.of_period(1_792_108_800_000_000, 1_792_195_200_000_000);
assert!(day.iter().all(|(r, _)| !matches!(r, fleet::Record::Hop(h) if fleet::hex(&h.record.room) != lesson)));
// A record of an unenrolled node, or before its descriptor, is refused.
let mut empty = Held::new(org.verifying_key().to_bytes());
let hop = b["records"].as_array().unwrap().iter().find(|r| r["kind"] == "hop").unwrap();
assert_eq!(empty.admit(hop).unwrap_err(), Reason::SignerNotEnrolled);
empty.enrol(&fleet::unhex(b["enrolments"][0].as_str().unwrap()).unwrap()).unwrap();
let e = empty.admit(&json!({"kind": "descriptor", "descriptor": "00"}));
assert_eq!(e.unwrap_err(), Reason::Truncated);
}
/// §10 of the extension lists exactly the codes `Reason::ALL` has, each once, in order, and
/// names every code `Reason::REUSED` has.
#[test]
fn the_extension_lists_the_reasons() {
let text = read("extensions/fleet.md");
let section = text.split("\n## 10. Reasons").nth(1).unwrap().split("\n## 11.").next().unwrap();
let listed: Vec<&str> = section.lines().filter_map(|l| l.strip_prefix("| `")).filter_map(|l| l.split('`').next()).collect();
let ours: Vec<&str> = Reason::ALL.iter().map(|r| r.code()).collect();
assert_eq!(listed, ours);
for r in Reason::REUSED {
assert!(section.contains(&format!("`{}`", r.code())), "§10 does not name the reused code {r}");
}
}