Skip to main content

tasm_lib/verifier/
own_program_digest.rs

1use triton_vm::prelude::*;
2
3use crate::prelude::*;
4
5/// Return own program digest. Must be called with a clean stack.
6///
7/// Move own program digest to the top of the stack
8/// Must be called as the first function in the program, as
9/// it assumes that the bottom of the stack (stack[15..=11])
10/// contains the digest of the running program
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
12pub struct OwnProgramDigest;
13
14impl BasicSnippet for OwnProgramDigest {
15    fn parameters(&self) -> Vec<(DataType, String)> {
16        vec![]
17    }
18
19    fn return_values(&self) -> Vec<(DataType, String)> {
20        vec![(DataType::Digest, "own_program_digest".to_owned())]
21    }
22
23    fn entrypoint(&self) -> String {
24        "tasmlib_verifier_own_program_digest".to_owned()
25    }
26
27    fn code(&self, _library: &mut Library) -> Vec<LabelledInstruction> {
28        triton_asm!(
29            {self.entrypoint()}:
30                dup 15
31                dup 15
32                dup 15
33                dup 15
34                dup 15
35
36                return
37        )
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44    use crate::execute_with_terminal_state;
45    use crate::test_prelude::*;
46
47    #[derive(Debug, Clone, Eq, PartialEq)]
48    struct ProgramSetup {
49        program: Program,
50        program_digest: Digest,
51        init_stack: Vec<BFieldElement>,
52    }
53
54    fn test_program() -> ProgramSetup {
55        let snippet = OwnProgramDigest;
56        let program = Program::new(&snippet.link_for_isolated_run());
57        let program_digest = program.hash();
58        let init_stack = snippet.init_stack_for_isolated_run();
59
60        ProgramSetup {
61            program,
62            program_digest,
63            init_stack,
64        }
65    }
66
67    #[macro_rules_attr::apply(test)]
68    fn positive_test() {
69        let test_setup = test_program();
70
71        let vm_end_state = execute_with_terminal_state(
72            test_setup.program,
73            &[],
74            &test_setup.init_stack,
75            &NonDeterminism::default(),
76            None,
77        )
78        .unwrap();
79
80        let expected_stack = [
81            test_setup.init_stack.clone(),
82            test_setup.init_stack[..Digest::LEN].to_vec(),
83        ]
84        .concat();
85        assert_eq!(expected_stack, vm_end_state.op_stack.stack);
86        assert!(vm_end_state.jump_stack.is_empty());
87    }
88}