use std::path::Path;
use trident::runtime::ProgramInput;
use trisha_rs::recursive;
use triton_vm::prelude::*;
fn fields(values: &[u64]) -> String {
format!(
"[{}]",
values
.iter()
.map(|v| format!("\"{v}\""))
.collect::<Vec<_>>()
.join(", ")
)
}
fn fixture(
root: &Path,
name: &str,
source: &str,
hand: &str,
prefix: &str,
input: &ProgramInput,
output: &[u64],
failure: bool,
library: bool,
) {
let directory = root.join("baselines/triton/fixtures").join(name);
std::fs::create_dir_all(&directory).unwrap();
let libraries = if library {
"[\"../../os/neptune/proof.tasm\"]"
} else {
"[]"
};
let witness_files = if name.starts_with("recursive-aggregate") {
"[\"../recursive-witnesses/first.toml\", \"../recursive-witnesses/second.toml\"]"
} else {
"[\"../recursive-witnesses/first.toml\"]"
};
let text = format!(
r#"source = "../../../../examples/triton/{source}.tri"
hand = "../../os/neptune/{hand}.tasm"
target = "triton"
input = {public}
output = {output}
witness_files = {witness_files}
hand_prefix = "{prefix}"
hand_libraries = {libraries}
expect_failure = {failure}
max_cycles = 3000000
reference = "Official default-security Triton7 proof for read_io1 +3 write_io1, inputs2/9 outputs5/12. Expected full-claim commitments computed by native Tip5(BFieldCodec Claim); published Triton7 verifier hand linkage is independent of Trident compilation. Version1 full-proof ABI replaces invalid configurable-FRI prototype."
"#,
public = fields(&input.public),
output = fields(output)
);
std::fs::write(directory.join("vector.bench.toml"), text).unwrap();
}
fn main() {
let root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
let program = Program::from_code("read_io 1 push 3 add write_io 1 halt").unwrap();
let mut witnesses = Vec::new();
for value in [2, 9] {
let (trace, output) = VM::trace_execution(
program.clone(),
vec![BFieldElement::new(value)].into(),
NonDeterminism::default(),
)
.unwrap();
assert_eq!(output, vec![BFieldElement::new(value + 3)]);
let claim = Claim::about_program(&program)
.with_input(vec![BFieldElement::new(value)])
.with_output(output);
let proof = Stark::default().prove(&claim, &trace).unwrap();
witnesses.push(recursive::encode(&claim, &proof).unwrap());
}
let witness_dir = root.join("baselines/triton/fixtures/recursive-witnesses");
std::fs::create_dir_all(&witness_dir).unwrap();
for (name, witness) in ["first", "second"].into_iter().zip(&witnesses) {
let digests = witness
.digests
.iter()
.flatten()
.copied()
.collect::<Vec<_>>();
std::fs::write(
witness_dir.join(format!("{name}.toml")),
format!(
"secret = {}\ndigests = {}\n",
fields(&witness.secret),
fields(&digests)
),
)
.unwrap();
}
let hand_root = root.join("baselines/triton/os/neptune");
std::fs::write(hand_root.join("proof.tasm"), format!("// Version1 real default-security verifier. Generated by recursive_baselines.\n// Historical filename retained in the43-entry benchmark inventory; VM ownership is Trisha.\n{}", recursive::assembly())).unwrap();
std::fs::write(hand_root.join("programs/recursive_verifier.tasm"), "// Version1: public full-claim commitment; output1 after verification.\n__main: read_io 5 call trisha_recursive_verify_v1 push 1 write_io 1 halt\n").unwrap();
let relay = "read_io 5 dup 4 dup 4 dup 4 dup 4 dup 4 call trisha_recursive_verify_v1 swap 4 swap 1 swap 3 swap 1 write_io 5";
std::fs::write(
hand_root.join("programs/proof_relay.tasm"),
format!("// Version1: output the verified full-claim commitment.\n__main: {relay} halt\n"),
)
.unwrap();
std::fs::write(hand_root.join("programs/proof_aggregator.tasm"), format!("// Version1: bounded1..16 independent full proofs.\n__main: read_io 1 dup 0 push 0 eq push 0 eq assert push 17 dup 1 lt assert call __aggregate_loop pop 1 halt\n__aggregate_loop: dup 0 push 0 eq skiz return\n{relay}\npush -1 add recurse\n")).unwrap();
for (name, source, hand, prefix, output, library) in [
(
"recursive-proof",
"recursive_verifier",
"proof",
"read_io 5 call trisha_recursive_verify_v1 push 1 write_io 1 halt\\n",
vec![1],
false,
),
(
"recursive-verifier",
"recursive_verifier",
"programs/recursive_verifier",
"call __main halt\\n",
vec![1],
true,
),
(
"recursive-relay",
"proof_relay",
"programs/proof_relay",
"call __main halt\\n",
witnesses[0].public.clone(),
true,
),
] {
fixture(
root,
name,
source,
hand,
prefix,
&witnesses[0],
&output,
false,
library,
);
let mut wrong = witnesses[0].clone();
wrong.public[0] = (wrong.public[0] + 1) % BFieldElement::P;
fixture(
root,
&format!("{name}-bad-claim"),
source,
hand,
prefix,
&wrong,
&[],
true,
library,
);
}
let mut aggregate = ProgramInput {
public: vec![2],
secret: vec![],
digests: vec![],
};
let mut output = Vec::new();
for witness in witnesses {
output.extend(&witness.public);
aggregate.public.extend(witness.public);
aggregate.secret.extend(witness.secret);
aggregate.digests.extend(witness.digests);
}
fixture(
root,
"recursive-aggregate-two",
"proof_aggregator",
"programs/proof_aggregator",
"call __main halt\\n",
&aggregate,
&output,
false,
true,
);
for invalid_count in [0, 17, 1u64 << 32] {
let mut invalid = aggregate.clone();
invalid.public[0] = invalid_count;
fixture(
root,
&format!("recursive-aggregate-count-{invalid_count}"),
"proof_aggregator",
"programs/proof_aggregator",
"call __main halt\\n",
&invalid,
&[],
true,
true,
);
}
aggregate.public[6] = (aggregate.public[6] + 1) % BFieldElement::P;
fixture(
root,
"recursive-aggregate-bad-second",
"proof_aggregator",
"programs/proof_aggregator",
"call __main halt\\n",
&aggregate,
&[],
true,
true,
);
println!("Generated eleven positive/negative fixtures covering four actual recursive baselines; transaction validation remains a separate protocol.");
}