Skip to main content

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 parameters(&self) -> Vec<(DataType, String)> {
12        let claim_type = claim_type();
13        vec![(DataType::StructRef(claim_type), "*claim".to_owned())]
14    }
15
16    fn return_values(&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        ) -> Result<Vec<BFieldElement>, RustShadowError> {
88            let claim_pointer = stack.pop().ok_or(RustShadowError::StackUnderflow)?;
89
90            let claim = load_claim_from_memory(claim_pointer, memory);
91
92            let Some(sponge) = sponge.as_mut() else {
93                return Err(RustShadowError::SpongeUninitialized);
94            };
95            sponge.pad_and_absorb_all(&claim.encode());
96
97            Ok(Vec::new())
98        }
99
100        fn pseudorandom_initial_state(
101            &self,
102            seed: [u8; 32],
103            bench_case: Option<BenchmarkCase>,
104        ) -> ProcedureInitialState {
105            let mut rng = StdRng::from_seed(seed);
106
107            let (input_length, output_length) = match bench_case {
108                Some(BenchmarkCase::CommonCase) => (0, 0),
109                Some(BenchmarkCase::WorstCase) => (100, 100),
110                None => (rng.random_range(0..1000), rng.random_range(0..1000)),
111            };
112
113            let claim = Claim::new(rng.random())
114                .with_input(random_elements(input_length))
115                .with_output(random_elements(output_length));
116
117            let mut memory = HashMap::default();
118
119            let claim_pointer = rng.random();
120            encode_to_memory(&mut memory, claim_pointer, &claim);
121
122            let sponge: Tip5 = Tip5 {
123                state: rng.random(),
124            };
125            ProcedureInitialState {
126                stack: [self.init_stack_for_isolated_run(), vec![claim_pointer]].concat(),
127                nondeterminism: NonDeterminism::default().with_ram(memory),
128                public_input: vec![],
129                sponge: Some(sponge),
130            }
131        }
132
133        fn corner_case_initial_states(&self) -> Vec<ProcedureInitialState> {
134            let empty_everything = {
135                let minimal_claim = Claim::new(Digest::default());
136                let claim_pointer = rand::rng().random();
137                let mut memory = HashMap::default();
138                encode_to_memory(&mut memory, claim_pointer, &minimal_claim);
139                ProcedureInitialState {
140                    stack: [self.init_stack_for_isolated_run(), vec![claim_pointer]].concat(),
141                    nondeterminism: NonDeterminism::default().with_ram(memory),
142                    public_input: vec![],
143                    sponge: Some(Tip5::init()),
144                }
145            };
146            vec![empty_everything]
147        }
148    }
149
150    #[macro_rules_attr::apply(test)]
151    fn test() {
152        ShadowedProcedure::new(InstantiateFiatShamirWithClaim).test();
153    }
154}
155
156#[cfg(test)]
157mod benches {
158    use super::*;
159    use crate::test_prelude::*;
160
161    #[macro_rules_attr::apply(test)]
162    fn benchmark() {
163        ShadowedProcedure::new(InstantiateFiatShamirWithClaim).bench();
164    }
165}