warriors/trisha/rs/tests/plumb_v2.rs

#[path = "support/plumb_v2.rs"]
mod vectors;
use triton_vm::prelude::*;
use vectors::*;
fn run(program: &Program, c: &Case) -> Result<Vec<u64>, String> {
    VM::run(
        program.clone(),
        PublicInput::new(
            c.public
                .iter()
                .copied()
                .map(BFieldElement::new)
                .collect::<Vec<_>>(),
        ),
        NonDeterminism::new(
            c.secret
                .iter()
                .copied()
                .map(BFieldElement::new)
                .collect::<Vec<_>>(),
        ),
    )
    .map(|v| v.into_iter().map(|x| x.value()).collect())
    .map_err(|e| e.to_string())
}
#[test]
fn complete_coin_and_card_transitions_authenticate_claims() {
    for (name, cases) in [("coin", coin_cases()), ("card", card_cases())] {
        let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
            .join(format!("../examples/neptune/standards/{name}.tri"));
        for profile in ["hand", "debug", "release"] {
            let code = if profile == "hand" {
                std::fs::read_to_string(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join(
                    format!("../baselines/triton/os/neptune/standards/{name}.tasm"),
                ))
                .unwrap()
            } else {
                trisha_rs::build_tasm(&path, "neptune", profile).unwrap()
            };
            let p = Program::from_code(&code).unwrap();
            for c in &cases {
                assert_eq!(
                    run(&p, c).unwrap_or_else(|e| panic!("{} {profile}: {e}", c.name)),
                    c.output,
                    "{} {profile}",
                    c.name
                );
                for (label, index) in [("old root", 1), ("new root", 6)] {
                    let mut bad = c.clone();
                    bad.public[index] ^= 1;
                    assert!(run(&p, &bad).is_err(), "{} accepts {label}", c.name);
                }
                let mut bad = c.clone();
                bad.secret[0] ^= 1;
                assert!(
                    run(&p, &bad).is_err(),
                    "{} accepts changed authority config",
                    c.name
                );
                let mut bad = c.clone();
                bad.public[0] = 5;
                assert!(run(&p, &bad).is_err(), "unknown operation accepted");
            }
        }
    }
}

#[test]
fn tree_paths_and_full_authority_words_are_not_optional() {
    for (name, cases) in [("coin", coin_cases()), ("card", card_cases())] {
        let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
        let source = root.join(format!("examples/neptune/standards/{name}.tri"));
        let programs = [
            Program::from_code(
                &std::fs::read_to_string(
                    root.join(format!("baselines/triton/os/neptune/standards/{name}.tasm")),
                )
                .unwrap(),
            )
            .unwrap(),
            Program::from_code(&trisha_rs::build_tasm(&source, "neptune", "release").unwrap())
                .unwrap(),
        ];
        for c in cases {
            let config_only = c.name == "coin-2" || c.name == "card-config";
            let mut bad = c.clone();
            let auth_offset = if config_only || c.name.ends_with("-3") {
                30
            } else if name == "coin" {
                43
            } else {
                49
            };
            bad.secret[auth_offset + 4] ^= 1;
            for p in &programs {
                assert!(
                    run(p, &bad).is_err(),
                    "{} ignored final authority preimage word",
                    c.name
                );
            }
            if !config_only {
                let mut bad = c.clone();
                *bad.secret.last_mut().unwrap() ^= 1;
                for p in &programs {
                    assert!(run(p, &bad).is_err(), "{} ignored Merkle sibling", c.name);
                }
            }
            if c.name.ends_with("-3") || c.name.ends_with("-4") {
                let mut bad = c.clone();
                bad.public[12] += 1;
                for p in &programs {
                    assert!(
                        run(p, &bad).is_err(),
                        "{} ignored supply/count relation",
                        c.name
                    );
                }
            }
            if c.name == "coin-1" || c.name == "card-1" {
                let mut bad = c.clone();
                bad.public[if name == "coin" { 12 } else { 13 }] = 3;
                for p in &programs {
                    assert!(run(p, &bad).is_err(), "{} shortened lock", c.name);
                }
            }
        }
    }
}

#[test]
fn disabled_authority_is_checked_as_all_five_words() {
    let dir = tempfile::tempdir().unwrap();
    let path = dir.path().join("auth.tri");
    std::fs::write(&path,"program authority\nuse os.neptune.standards.plumb\nfn main(){let a:Digest=pub_read5()\nif plumb.is_zero(a){pub_write(0)}else{plumb.verify_auth(a)\npub_write(1)}}").unwrap();
    let p =
        Program::from_code(&trisha_rs::build_tasm(&path, "neptune", "release").unwrap()).unwrap();
    assert_eq!(
        run(
            &p,
            &Case {
                name: "disabled".into(),
                public: vec![0; 5],
                secret: vec![],
                output: vec![]
            }
        )
        .unwrap(),
        vec![0]
    );
    assert_eq!(
        run(
            &p,
            &Case {
                name: "valid".into(),
                public: auth(KEY).to_vec(),
                secret: KEY.to_vec(),
                output: vec![]
            }
        )
        .unwrap(),
        vec![1]
    );
    let bad = Case {
        name: "nonzero with field-sum zero".into(),
        public: vec![1, 18446744069414584320, 0, 0, 0],
        secret: KEY.to_vec(),
        output: vec![],
    };
    assert!(run(&p, &bad).is_err());
}

#[test]
fn fixtures_record_independent_complete_transition_claims() {
    if std::env::var_os("TRISHA_WRITE_PLUMB_FIXTURES").is_none() {
        return;
    }
    let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
    let words = |v: &[u64]| {
        format!(
            "[{}]",
            v.iter()
                .map(|x| format!("\"{x}\""))
                .collect::<Vec<_>>()
                .join(", ")
        )
    };
    for (name, cases) in [("coin", coin_cases()), ("card", card_cases())] {
        for c in cases {
            let dir = root.join(format!("baselines/triton/fixtures/plumb-v2-{}", c.name));
            std::fs::create_dir_all(&dir).unwrap();
            let text=format!("source = \"../../../../examples/neptune/standards/{name}.tri\"\nhand = \"../../os/neptune/standards/{name}.tasm\"\ntarget = \"neptune\"\ninput = {}\nsecret = {}\noutput = {}\nmax_cycles = 2000000\nreference = \"PLUMB v2 complete {} transition; independent upstream Tip5 sparse-tree host oracle, full Digest authorities, same-sibling roots, declared event words.\"\n",words(&c.public),words(&c.secret),words(&c.output),c.name);
            std::fs::write(dir.join("vector.bench.toml"), text).unwrap();
        }
    }
}

#[test]
fn shared_config_utility_fixture_uses_v2_full_digest_schema() {
    let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
    let cfg = Config::new();
    let library =
        std::fs::read_to_string(root.join("baselines/triton/os/neptune/standards/plumb.tasm"))
            .unwrap();
    let prefix = format!(
        "{} {} call __verify_config push 1 write_io 1 halt\n",
        vec!["divine 1"; 30].join(" "),
        vec!["read_io 1"; 5].join(" ")
    );
    let p = Program::from_code(&(prefix.clone() + &library)).unwrap();
    let source="program baseline_plumb_config\nuse os.neptune.standards.plumb\nfn main(){let expected:Digest=pub_read5()\nlet a:Digest=divine5() let b:Digest=divine5() let c:Digest=divine5() let d:Digest=divine5() let e:Digest=divine5()\nlet h0=divine() let h1=divine() let h2=divine() let h3=divine() let h4=divine()\nplumb.verify_config(a,b,c,d,e,h0,h1,h2,h3,h4,expected)\npub_write(1)}\n";
    let tmp = tempfile::tempdir().unwrap();
    let path = tmp.path().join("main.tri");
    std::fs::write(&path, source).unwrap();
    let compiled =
        Program::from_code(&trisha_rs::build_tasm(&path, "neptune", "release").unwrap()).unwrap();
    for bad in [false, true] {
        let mut secret = cfg.words();
        if bad {
            *secret.last_mut().unwrap() += 1;
        }
        let c = Case {
            name: "config".into(),
            public: cfg.hash().to_vec(),
            secret,
            output: vec![1],
        };
        for program in [&p, &compiled] {
            if bad {
                assert!(run(program, &c).is_err());
            } else {
                assert_eq!(run(program, &c).unwrap(), vec![1]);
            }
        }
    }
    if std::env::var_os("TRISHA_WRITE_PLUMB_FIXTURES").is_some() {
        let words = |v: &[u64]| {
            format!(
                "[{}]",
                v.iter()
                    .map(|x| format!("\"{x}\""))
                    .collect::<Vec<_>>()
                    .join(",")
            )
        };
        for bad in [false, true] {
            let dir = root.join(if bad {
                "baselines/triton/fixtures/plumb-config-bad"
            } else {
                "baselines/triton/fixtures/plumb-config"
            });
            let mut secret = cfg.words();
            if bad {
                *secret.last_mut().unwrap() += 1;
            }
            std::fs::write(dir.join("main.tri"), source).unwrap();
            std::fs::write(dir.join("vector.bench.toml"),format!("source=\"main.tri\"\nhand=\"../../os/neptune/standards/plumb.tasm\"\ntarget=\"neptune\"\ninput={}\nsecret={}\noutput=[1]\nexpect_failure={bad}\nreference=\"PLUMBv2 full30-field config, independent upstream Tip5 pair tree; last-hook mutation rejects.\"\nhand_prefix=\"{}\"\n",words(&cfg.hash()),words(&secret),prefix.trim())).unwrap();
        }
    }
}

#[test]
fn card_flags_creator_and_metadata_cap_are_bound_to_authenticated_state() {
    use std::collections::BTreeMap;
    let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
    let source = root.join("examples/neptune/standards/card.tri");
    let programs = [
        Program::from_code(
            &std::fs::read_to_string(root.join("baselines/triton/os/neptune/standards/card.tasm"))
                .unwrap(),
        )
        .unwrap(),
        Program::from_code(&trisha_rs::build_tasm(&source, "neptune", "release").unwrap()).unwrap(),
    ];
    let cases = card_cases();
    for (op, bit) in [(0, 1), (1, 8), (2, 4), (4, 2)] {
        let mut case = cases
            .iter()
            .find(|c| c.name == format!("card-{op}"))
            .unwrap()
            .clone();
        let mut old = Card::new();
        old.flags &= !bit;
        case.secret[47] = old.flags;
        case.public[1..6].copy_from_slice(&tree(&BTreeMap::from([(old.id, old.hash())]), 0).0);
        if op != 4 {
            let mut new = old.clone();
            new.nonce += 1;
            match op {
                0 => {
                    new.owner = 202;
                    new.auth = auth([1, 2, 3, 4, 5]);
                }
                1 => new.lock = 15,
                2 => new.metadata = 402,
                _ => unreachable!(),
            }
            case.public[6..11].copy_from_slice(&tree(&BTreeMap::from([(new.id, new.hash())]), 0).0);
        }
        for p in &programs {
            assert!(
                run(p, &case).is_err(),
                "operation{op} ignored authenticated capability flag"
            );
        }
    }
    let mint = cases.iter().find(|c| c.name == "card-3").unwrap();
    let mut bad = mint.clone();
    bad.secret[51] ^= 1;
    let mut new = Card::new();
    new.nonce = 0;
    new.lock = 0;
    new.creator[0] ^= 1;
    bad.public[6..11].copy_from_slice(&tree(&BTreeMap::from([(new.id, new.hash())]), 0).0);
    for p in &programs {
        assert!(
            run(p, &bad).is_err(),
            "creator substituted while recomputing valid destination root"
        );
    }
    let mut bad = mint.clone();
    bad.public[13] = 0;
    for p in &programs {
        assert!(
            run(p, &bad).is_err(),
            "metadata cap replaced by unlimited public cap"
        );
    }
}

Homonyms

warriors/trisha/rs/tests/support/plumb_v2.rs

Graph