1use nub_program::ProgramBlob;
10
11pub const BENCH_GAS: u64 = i64::MAX as u64;
15
16pub const EXIT_HOST_CALL: u32 = 4;
20
21pub struct Program {
30 pub name: &'static str,
31 pub blob: &'static [u8],
32 pub expected_value: u64,
33 pub expected_gas: u64,
34}
35
36impl Program {
37 pub fn decode(&self) -> ProgramBlob {
39 ProgramBlob::from_bytes(self.blob)
40 .unwrap_or_else(|e| panic!("[{}] decode ProgramBlob: {e}", self.name))
41 }
42}
43
44pub const PROGRAMS: &[Program] = &[
46 Program {
47 name: "prime_sieve",
48 blob: include_bytes!(env!("PRIME_SIEVE_BLOB")),
49 expected_value: 0x2578,
50 expected_gas: 8_972_959,
51 },
52 Program {
53 name: "ed25519",
54 blob: include_bytes!(env!("ED25519_BLOB")),
55 expected_value: 0x1,
56 expected_gas: 2_360_953,
57 },
58 Program {
59 name: "keccak",
60 blob: include_bytes!(env!("KECCAK_BLOB")),
61 expected_value: 0x39e5_0259,
62 expected_gas: 100_934,
63 },
64 Program {
65 name: "blake2b",
66 blob: include_bytes!(env!("BLAKE2B_BLOB")),
67 expected_value: 0xee1f_55f1,
68 expected_gas: 62_396,
69 },
70 Program {
71 name: "ecrecover",
72 blob: include_bytes!(env!("ECRECOVER_BLOB")),
73 expected_value: 0x1,
74 expected_gas: 6_811_627,
75 },
76 Program {
77 name: "goldilocks_mul",
78 blob: include_bytes!(env!("GOLDILOCKS_MUL_BLOB")),
79 expected_value: 0x2cf7_3e57,
80 expected_gas: 2_400_166,
81 },
82 Program {
83 name: "poseidon2_perm",
84 blob: include_bytes!(env!("POSEIDON2_PERM_BLOB")),
85 expected_value: 0x3ce3_3156,
86 expected_gas: 14_561_457,
87 },
88 Program {
89 name: "mini_verifier",
90 blob: include_bytes!(env!("MINI_VERIFIER_BLOB")),
91 expected_value: 0xf98f_c4ab,
92 expected_gas: 5_879_175,
93 },
94 Program {
95 name: "poly_eval",
96 blob: include_bytes!(env!("POLY_EVAL_BLOB")),
97 expected_value: 0x01da_34e2,
98 expected_gas: 9_005_991,
99 },
100 Program {
101 name: "fri_fold_tree",
102 blob: include_bytes!(env!("FRI_FOLD_TREE_BLOB")),
103 expected_value: 0x37e6_76f4,
104 expected_gas: 6_194_439,
105 },
106];
107
108pub fn run_interpreter(name: &str, blob: &ProgramBlob) -> (u64, u64) {
114 let result = nub_arch_local::run_blob(blob, 0, [0; 4], BENCH_GAS)
115 .unwrap_or_else(|e| panic!("[{name}] prepare: {e}"));
116 assert_eq!(
117 result.exit_reason, EXIT_HOST_CALL,
118 "[{name}] did not halt cleanly: exit_reason={} exit_arg={}",
119 result.exit_reason, result.exit_arg,
120 );
121 assert_eq!(result.exit_arg, 0, "[{name}] unexpected host call");
122 (result.return_value, BENCH_GAS - result.gas_remaining)
123}
124
125#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
132pub const FLAT_GUEST_BLOB_PATH: &str = env!("NUB_FLAT_GUEST_BLOB");
133
134#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
140pub fn flat_sandbox() -> &'static nub::Nub<nub_flat::Flat> {
141 use std::sync::OnceLock;
142 static SANDBOX: OnceLock<nub::Nub<nub_flat::Flat>> = OnceLock::new();
143 SANDBOX.get_or_init(|| {
144 nub::Nub::create_hyperlight(FLAT_GUEST_BLOB_PATH, nub::NubOptions::default())
145 .expect("create the flat sandbox")
146 })
147}