//! Literal consumer of the committed strict reader: no hash/encoder/traversal oracle.
use std::{fs, iter::FusedIterator, ops::Range, path::Path};

use cyber_bao::{
    BlockSize,
    proof::{ProofItem, ProofVerifier, VerifiedProof},
};

#[derive(Clone, Copy)]
enum Event {
    Parent,
    Leaf {
        proof: usize,
        file: u64,
        bytes: usize,
    },
}
struct Case {
    name: &'static str,
    directory: &'static str,
    proof_file: &'static str,
    root: &'static str,
    size: u64,
    log: u8,
    request: Range<u64>,
    actions: usize,
    wire_bytes: usize,
    events: &'static [Event],
}
fn root(hex: &str) -> [u8; 32] {
    assert_eq!(hex.len(), 64);
    std::array::from_fn(|i| u8::from_str_radix(&hex[2 * i..2 * i + 2], 16).unwrap())
}
fn finish<'a>(case: &Case, proof: &'a [u8]) -> (VerifiedProof<'a>, usize) {
    let mut job = ProofVerifier::new(
        proof,
        root(case.root),
        case.size,
        BlockSize(case.log),
        case.request.clone(),
    )
    .unwrap();
    let mut calls = 0;
    for _ in 1..case.actions {
        assert!(!job.is_finished(), "{} early terminal", case.name);
        calls += 1;
        assert!(job.step().unwrap().is_none(), "{} early view", case.name);
    }
    assert!(!job.is_finished());
    calls += 1;
    let view = job
        .step()
        .unwrap()
        .expect("literal EOF action returns view");
    assert!(job.is_finished());
    for _ in 0..10 {
        assert!(job.step().unwrap().is_none());
    }
    (view, calls) // the view survives the verifier and still borrows the proof
}
fn fused<T: FusedIterator>(_: &T) {}
fn run(base: &Path, case: &Case) {
    let dir = base.join(case.directory);
    let proof = fs::read(dir.join(case.proof_file)).unwrap();
    let body = fs::read(dir.join("body.bin")).unwrap();
    let selected = fs::read(dir.join("selected.bin")).unwrap();
    assert_eq!(proof.len(), case.wire_bytes);
    assert_eq!(u64::try_from(body.len()).unwrap(), case.size);
    assert_eq!(
        selected,
        body[usize::try_from(case.request.start).unwrap()
            ..usize::try_from(case.request.end).unwrap()]
    );
    let (view, calls) = finish(case, &proof);
    assert_eq!(calls, case.actions);
    assert_eq!(view.root(), root(case.root));
    assert_eq!(view.size(), case.size);
    assert_eq!(view.block_size(), BlockSize(case.log));
    assert_eq!(view.request(), case.request);
    let mut items = view.items();
    fused(&items);
    assert_eq!(items.is_complete(), case.events.is_empty());
    let mut copied = Vec::new();
    let mut emitted = 0;
    let mut leaves = 0;
    for (index, expected) in case.events.iter().enumerate() {
        assert!(!items.is_complete());
        emitted += 1;
        match (items.next().unwrap(), expected) {
            (ProofItem::Parent, Event::Parent) => {}
            (
                ProofItem::Leaf {
                    file_offset,
                    proof_offset,
                    bytes,
                },
                Event::Leaf {
                    proof: p,
                    file: f,
                    bytes: n,
                },
            ) => {
                leaves += 1;
                assert_eq!((proof_offset, file_offset, bytes.len()), (*p, *f, *n));
                assert_eq!(bytes.as_ptr(), proof[*p..].as_ptr());
                assert_eq!(bytes, &proof[*p..*p + *n]);
                let file = usize::try_from(*f).unwrap();
                assert_eq!(bytes, &body[file..file + *n]);
                let first = case.request.start.max(*f) - *f;
                let end = case.request.end.min(*f + u64::try_from(*n).unwrap()) - *f;
                copied.extend_from_slice(
                    &bytes[usize::try_from(first).unwrap()..usize::try_from(end).unwrap()],
                );
                println!(
                    "{{\"case\":\"{}\",\"leaf\":{},\"proof_offset\":{},\"file_offset\":{},\"bytes\":{}}}",
                    case.name,
                    leaves,
                    proof_offset,
                    file_offset,
                    bytes.len()
                );
            }
            _ => panic!(
                "{} event {} disagrees with literal carrier",
                case.name, index
            ),
        }
        assert_eq!(items.is_complete(), index + 1 == case.events.len());
    }
    assert_eq!(emitted, case.events.len());
    assert!(items.is_complete());
    for _ in 0..10 {
        assert!(items.next().is_none());
    }
    assert_eq!(copied, selected);
    println!(
        "{{\"case\":\"{}\",\"root\":\"{}\",\"verification_actions\":{},\"output_items\":{},\"leaves\":{},\"selected_bytes\":{},\"status\":\"pass\"}}",
        case.name,
        case.root,
        calls,
        emitted,
        leaves,
        copied.len()
    );
}
fn main() {
    use Event::{Leaf as L, Parent as P};
    let base = std::env::args_os()
        .nth(1)
        .expect("frozen literal directory");
    let four = "e621f66b42fb61b260200dfa649d3f16d35cde5af2e8c04cc2551c109f00c6f6";
    let short = "06001dbd4d71e5149839bed85cbe3fc979fcfc45ef711a6d9ad2fdc1499da3e3";
    let cases = [
        Case {
            name: "interleaved",
            directory: "interleaved",
            proof_file: "interleaved.bao",
            root: four,
            size: 16384,
            log: 0,
            request: 4095..8193,
            actions: 11,
            wire_bytes: 12488,
            events: &[
                P,
                P,
                L {
                    proof: 136,
                    file: 0,
                    bytes: 4096,
                },
                L {
                    proof: 4232,
                    file: 4096,
                    bytes: 4096,
                },
                P,
                L {
                    proof: 8392,
                    file: 8192,
                    bytes: 4096,
                },
            ],
        },
        Case {
            name: "left",
            directory: "left",
            proof_file: "proof.bao",
            root: four,
            size: 16384,
            log: 0,
            request: 1..3,
            actions: 6,
            wire_bytes: 4232,
            events: &[
                P,
                P,
                L {
                    proof: 136,
                    file: 0,
                    bytes: 4096,
                },
            ],
        },
        Case {
            name: "right",
            directory: "right",
            proof_file: "proof.bao",
            root: four,
            size: 16384,
            log: 0,
            request: 12289..12292,
            actions: 6,
            wire_bytes: 4232,
            events: &[
                P,
                P,
                L {
                    proof: 136,
                    file: 12288,
                    bytes: 4096,
                },
            ],
        },
        Case {
            name: "grouped",
            directory: "grouped",
            proof_file: "proof.bao",
            root: four,
            size: 16384,
            log: 1,
            request: 8191..8193,
            actions: 11,
            wire_bytes: 16456,
            events: &[
                P,
                L {
                    proof: 72,
                    file: 0,
                    bytes: 8192,
                },
                L {
                    proof: 8264,
                    file: 8192,
                    bytes: 8192,
                },
            ],
        },
        Case {
            name: "short",
            directory: "short",
            proof_file: "proof.bao",
            root: short,
            size: 4099,
            log: 0,
            request: 4095..4099,
            actions: 7,
            wire_bytes: 4171,
            events: &[
                P,
                L {
                    proof: 72,
                    file: 0,
                    bytes: 4096,
                },
                L {
                    proof: 4168,
                    file: 4096,
                    bytes: 3,
                },
            ],
        },
        Case {
            name: "short-grouped",
            directory: "short-grouped",
            proof_file: "proof.bao",
            root: short,
            size: 4099,
            log: 1,
            request: 4095..4099,
            actions: 6,
            wire_bytes: 4107,
            events: &[L {
                proof: 8,
                file: 0,
                bytes: 4099,
            }],
        },
        Case {
            name: "empty",
            directory: "empty",
            proof_file: "proof.bao",
            root: "ea57b2e6b1ec7d2de11b15cb6d7060dd61d247fe0fbf5f7d3fb97a7be9328552",
            size: 0,
            log: 0,
            request: 0..0,
            actions: 4,
            wire_bytes: 8,
            events: &[],
        },
        Case {
            name: "pcm",
            directory: "pcm",
            proof_file: "proof.bao",
            root: "da570b332b3f2eac27cdaa83f58bd498ab7fc7736732ab9c1b8d4838c9e307a3",
            size: 14,
            log: 0,
            request: 5..13,
            actions: 4,
            wire_bytes: 22,
            events: &[L {
                proof: 8,
                file: 0,
                bytes: 14,
            }],
        },
    ];
    for case in &cases {
        run(Path::new(&base), case);
    }
    println!(
        "Eight committed-reader cases PASS; no encoder, traversal or root recomputation oracle; no Kadek adapter executed"
    );
}

Homonyms

soft3/radio/audit/2026-10-13-audit-cargo-packaging/plan-input-v2/inputs/039.txt
soft3/radio/audit/2026-10-13-audit-cargo-packaging/plan-input/inputs/039.txt

Graph