Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (push) Successful in 3s
standards workspaces build + test / aac-rs (push) Successful in 37s
standards workspaces build + test / joule-code-rs (push) Successful in 42s
standards workspaces build + test / eoc-rs (push) Successful in 1m47s
standards workspaces build + test / jcp-rs (push) Successful in 1m14s
standards workspaces build + test / proof-rs (push) Successful in 1m9s
standards workspaces build + test / jouleclaw-rs (push) Successful in 4m6s
standards workspaces build + test / joulecontract-rs (push) Successful in 38s
standards workspaces build + test / sandbox-rs (push) Successful in 2m1s
standards workspaces build + test / map-rs (push) Successful in 36s
standards workspaces build + test / mesh-rs (push) Successful in 34s
standards workspaces build + test / openpay (push) Successful in 1m23s
standards workspaces build + test / smart-byte-rs (push) Successful in 2m28s
WAI conformance / cargo-class corpora · linux-arm64 (push) Successful in 33s
WAI conformance / cargo-class corpora · linux (push) Successful in 28s
WAI conformance / cross-arch byte-equality · linux-arm64 (push) Successful in 17s
WAI conformance / cross-arch byte-equality · linux (push) Successful in 14s
standards workspaces build + test / arl-rs (push) Successful in 8m41s
standards workspaces build + test / joule-ui-rs (push) Successful in 7m56s
standards workspaces build + test / jouledesk-rs (push) Successful in 8m24s
standards workspaces build + test / joulehook-rs (push) Successful in 8m34s
standards workspaces build + test / sense-rs (push) Successful in 7m58s
WAI conformance / cargo-class corpora · macos (push) Successful in 1m4s
WAI conformance / cross-arch byte-equality · macos (push) Successful in 23s
WAI conformance / cargo-class corpora · windows (push) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (push) Has been cancelled
crates.io publish was blocked: the name `wai` is taken (an unrelated 2017 crate), and `default = ["codecs"]` would make `cargo add` pull libjxl/libavif/opus/FLAC/ rav1e/dav1d system libraries — so most builds would fail for someone who only wants quantum. Extracting the quantum stack solves both. `wai-quantum` is dependency-light and pure Rust (blake3 + serde_json, with ed25519-dalek only for the sealing features). No system libraries, so it builds everywhere the stack already runs: native, browser wasm, and wasm32-wasip2. The split follows the seam that was already there — 12,975 lines moved with only four coupling points: - `world:🧾:merkle_root` (used by 3 modules) is reproduced verbatim in `wai-quantum::merkle`, domain separators included, so every previously issued receipt and published conformance vector still verifies; - `wrap_envelope` is a WAI-envelope concern, not a quantum one, so it stays in `wai` as `quantum_envelope` (it had no external callers). `wai` keeps every quantum feature name and re-exports the modules unchanged, so wai-web, wai-quantum-serve and the deployed site build without edits. Also re-exports `ed25519_dalek` from wai-quantum: the sealing API takes a `SigningKey`, and a consumer picking their own version could get an incompatible one. Verified the extraction is observably a no-op — identical to the values recorded before it: ghz -n 5 circuit-id 355d1166… state-hash 0b5f4201… grover -n 4 -p 9 state-hash 25a7d930… receipt JSON sha256 117ff588… 208 tests pass (173 wai-quantum + 35 wai); wai-web and the WASI-HTTP component build unchanged, and the edge endpoint still returns the identical hash. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
42 lines
1.4 KiB
Rust
42 lines
1.4 KiB
Rust
//! The JWP Merkle floor, verbatim.
|
|
//!
|
|
//! Receipts in this crate bind their leaves with the same Merkle construction the
|
|
//! WAI worlds/provenance receipts use. The domain separators and tree shape are
|
|
//! reproduced **exactly** — every previously issued receipt and every published
|
|
//! conformance vector must still verify against this code.
|
|
|
|
const MERKLE_LEAF: &[u8] = b"moq-jwp:merkle-leaf\x01";
|
|
const MERKLE_NODE: &[u8] = b"moq-jwp:merkle-node\x01";
|
|
|
|
fn merkle_leaf(content_hash: &[u8; 32]) -> [u8; 32] {
|
|
let mut h = blake3::Hasher::new();
|
|
h.update(MERKLE_LEAF);
|
|
h.update(content_hash);
|
|
*h.finalize().as_bytes()
|
|
}
|
|
|
|
fn merkle_node(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
|
|
let mut h = blake3::Hasher::new();
|
|
h.update(MERKLE_NODE);
|
|
h.update(left);
|
|
h.update(right);
|
|
*h.finalize().as_bytes()
|
|
}
|
|
|
|
/// Merkle root over `object_hashes` (odd levels duplicate the last node).
|
|
pub fn merkle_root(object_hashes: &[[u8; 32]]) -> [u8; 32] {
|
|
if object_hashes.is_empty() {
|
|
return [0u8; 32];
|
|
}
|
|
let mut level: Vec<[u8; 32]> = object_hashes.iter().map(merkle_leaf).collect();
|
|
while level.len() > 1 {
|
|
if level.len() % 2 == 1 {
|
|
level.push(*level.last().unwrap());
|
|
}
|
|
level = level
|
|
.chunks_exact(2)
|
|
.map(|pair| merkle_node(&pair[0], &pair[1]))
|
|
.collect();
|
|
}
|
|
level[0]
|
|
}
|