tasm_lib/verifier/claim/
instantiate_fiat_shamir_with_claim.rs

1use triton_vm::prelude::*;
2
3use crate::hashing::absorb_multiple::AbsorbMultiple;
4use crate::prelude::*;
5use crate::verifier::claim::shared::claim_type;
6
7#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
8pub struct InstantiateFiatShamirWithClaim;
9
10impl BasicSnippet for InstantiateFiatShamirWithClaim {
11    fn inputs(&self) -> Vec<(DataType, String)> {
12        let claim_type = claim_type();
13        vec![(DataType::StructRef(claim_type), "*claim".to_owned())]
14    }
15
16    fn outputs(&self) -> Vec<(DataType, String)> {
17        vec![]
18    }
19
20    fn entrypoint(&self) -> String {
21        "tasmlib_verifier_claim_instantiate_fiat_shamir_with_claim".to_owned()
22    }
23
24    fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
25        let entrypoint = self.entrypoint();
26
27        // We call absorb multiple with the right length. The right length has to be read from
28        // the structure. Absorb multiple handles padding.
29        let calculate_claim_size = triton_asm!(
30            // _ *claim
31            // _ *output_size
32
33            read_mem 1
34            // _ output_size (*output - 1)
35
36            dup 1
37            addi 2
38            add
39            // _ output_size (*output + 1 + output_size)
40            // _ output_size *input_size
41
42            read_mem 1
43            pop 1
44            // _ output_size input_size
45
46            addi {Digest::LEN + 1 + 2} // fields `program_digest` & `version`, plus 2
47            add
48            // _ size
49
50
51        );
52
53        let absorb_multiple = library.import(Box::new(AbsorbMultiple));
54        triton_asm!(
55            {entrypoint}:
56                // _ *claim
57
58                dup 0
59                {&calculate_claim_size}
60                // _ *claim claim_size
61
62                call {absorb_multiple}
63                // _
64
65                return
66        )
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use twenty_first::math::other::random_elements;
73    use twenty_first::prelude::Sponge;
74
75    use super::*;
76    use crate::rust_shadowing_helper_functions::claim::load_claim_from_memory;
77    use crate::test_prelude::*;
78
79    impl Procedure for InstantiateFiatShamirWithClaim {
80        fn rust_shadow(
81            &self,
82            stack: &mut Vec<BFieldElement>,
83            memory: &mut HashMap<BFieldElement, BFieldElement>,
84            _nondeterminism: &NonDeterminism,
85            _public_input: &[BFieldElement],
86            sponge: &mut Option<Tip5>,
87        ) -> Vec<BFieldElement> {
88            let claim_pointer = stack.pop().unwrap();
89
90            let claim = load_claim_from_memory(claim_pointer, memory);
91
92            sponge.as_mut().unwrap().pad_and_absorb_all(&claim.encode());
93
94            vec![]
95        }
96
97        fn pseudorandom_initial_state(
98            &self,
99            seed: [u8; 32],
100            bench_case: Option<BenchmarkCase>,
101        ) -> ProcedureInitialState {
102            let mut rng = StdRng::from_seed(seed);
103
104            let (input_length, output_length) = match bench_case {
105                Some(BenchmarkCase::CommonCase) => (0, 0),
106                Some(BenchmarkCase::WorstCase) => (100, 100),
107                None => (rng.random_range(0..1000), rng.random_range(0..1000)),
108            };
109
110            let claim = Claim::new(rng.random())
111                .with_input(random_elements(input_length))
112                .with_output(random_elements(output_length));
113
114            let mut memory = HashMap::default();
115
116            let claim_pointer = rng.random();
117            encode_to_memory(&mut memory, claim_pointer, &claim);
118
119            let sponge: Tip5 = Tip5 {
120                state: rng.random(),
121            };
122            ProcedureInitialState {
123                stack: [self.init_stack_for_isolated_run(), vec![claim_pointer]].concat(),
124                nondeterminism: NonDeterminism::default().with_ram(memory),
125                public_input: vec![],
126                sponge: Some(sponge),
127            }
128        }
129
130        fn corner_case_initial_states(&self) -> Vec<ProcedureInitialState> {
131            let empty_everything = {
132                let minimal_claim = Claim::new(Digest::default());
133                let claim_pointer = rand::rng().random();
134                let mut memory = HashMap::default();
135                encode_to_memory(&mut memory, claim_pointer, &minimal_claim);
136                ProcedureInitialState {
137                    stack: [self.init_stack_for_isolated_run(), vec![claim_pointer]].concat(),
138                    nondeterminism: NonDeterminism::default().with_ram(memory),
139                    public_input: vec![],
140                    sponge: Some(Tip5::init()),
141                }
142            };
143            vec![empty_everything]
144        }
145    }
146
147    #[test]
148    fn test() {
149        ShadowedProcedure::new(InstantiateFiatShamirWithClaim).test();
150    }
151}
152
153#[cfg(test)]
154mod benches {
155    use super::*;
156    use crate::test_prelude::*;
157
158    #[test]
159    fn benchmark() {
160        ShadowedProcedure::new(InstantiateFiatShamirWithClaim).bench();
161    }
162}