tasm_lib/hashing/
squeeze_repeatedly_static_number.rs1use triton_vm::prelude::*;
2use twenty_first::tip5::RATE;
3
4use crate::prelude::*;
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
12pub struct SqueezeRepeatedlyStaticNumber {
13 pub num_squeezes: usize,
14}
15
16impl BasicSnippet for SqueezeRepeatedlyStaticNumber {
17 fn inputs(&self) -> Vec<(DataType, String)> {
18 vec![(DataType::VoidPointer, "address".to_string())]
19 }
20
21 fn outputs(&self) -> Vec<(DataType, String)> {
22 vec![]
23 }
24
25 fn entrypoint(&self) -> String {
26 format!(
27 "tasmlib_hashing_squeeze_repeatedly_static_number_{}",
28 self.num_squeezes
29 )
30 }
31
32 fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
33 assert_eq!(10, RATE, "Code assumes RATE is 10");
34
35 let entrypoint = self.entrypoint();
36 let one_squeeze = triton_asm!(
37 sponge_squeeze
40 dup 10
43 write_mem 5
46 write_mem 5
47 swap 1
50 pop 1
51 );
53
54 let all_squeezes = vec![one_squeeze; self.num_squeezes].concat();
55
56 triton_asm!(
57 {entrypoint}:
58 {&all_squeezes}
61 pop 1
64
65 return
66 )
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use crate::hashing::squeeze_repeatedly::SqueezeRepeatedly;
74 use crate::test_helpers::tasm_final_state;
75 use crate::test_helpers::verify_memory_equivalence;
76 use crate::test_helpers::verify_sponge_equivalence;
77 use crate::test_helpers::verify_stack_equivalence;
78 use crate::test_prelude::*;
79
80 impl Procedure for SqueezeRepeatedlyStaticNumber {
81 fn rust_shadow(
82 &self,
83 stack: &mut Vec<BFieldElement>,
84 memory: &mut HashMap<BFieldElement, BFieldElement>,
85 nondeterminism: &NonDeterminism,
86 public_input: &[BFieldElement],
87 sponge: &mut Option<Tip5>,
88 ) -> Vec<BFieldElement> {
89 stack.push(BFieldElement::new(self.num_squeezes as u64));
90 let ret =
91 SqueezeRepeatedly.rust_shadow(stack, memory, nondeterminism, public_input, sponge);
92 stack.pop();
93 stack.pop();
94
95 ret
96 }
97
98 fn pseudorandom_initial_state(
99 &self,
100 seed: [u8; 32],
101 bench_case: Option<BenchmarkCase>,
102 ) -> ProcedureInitialState {
103 let mut init_state = SqueezeRepeatedly.pseudorandom_initial_state(seed, bench_case);
104 init_state.stack.pop();
105 init_state
106 }
107 }
108
109 #[test]
110 fn squeeze_repeatedly_static_number_pbt() {
111 for num_squeezes in 0..25 {
112 ShadowedProcedure::new(SqueezeRepeatedlyStaticNumber { num_squeezes }).test();
113 }
114 }
115
116 #[test]
117 fn test_dyn_equivalence() {
118 fn dyn_output(seed: [u8; 32]) -> (VMState, usize) {
121 let dyn_snippet = ShadowedProcedure::new(SqueezeRepeatedly);
122 let ProcedureInitialState {
123 stack,
124 nondeterminism,
125 public_input: stdin,
126 sponge,
127 } = SqueezeRepeatedly.pseudorandom_initial_state(seed, None);
128 let num_squeeze_count = stack.last().unwrap().value();
129
130 (
131 tasm_final_state(&dyn_snippet, &stack, &stdin, nondeterminism, &sponge),
132 num_squeeze_count as usize,
133 )
134 }
135
136 fn stat_output(seed: [u8; 32], num_squeezes: usize) -> VMState {
137 let snippet = SqueezeRepeatedlyStaticNumber { num_squeezes };
138 let ProcedureInitialState {
139 stack,
140 nondeterminism,
141 public_input: stdin,
142 sponge,
143 } = snippet.pseudorandom_initial_state(seed, None);
144
145 tasm_final_state(
146 &ShadowedProcedure::new(snippet),
147 &stack,
148 &stdin,
149 nondeterminism,
150 &sponge,
151 )
152 }
153
154 let mut seed = [0u8; 32];
155 rand::rng().fill_bytes(&mut seed);
156 let (mut dyn_output, num_squeezes) = dyn_output(seed);
157 dyn_output.op_stack.stack.pop();
158 dyn_output.op_stack.stack.pop();
159
160 let stat_output = stat_output(seed, num_squeezes);
161
162 verify_memory_equivalence(
163 "Snippet with dynamic symbols",
164 &dyn_output.ram,
165 "Snippet with static symbols",
166 &stat_output.ram,
167 );
168 verify_sponge_equivalence(&dyn_output.sponge, &stat_output.sponge);
169 verify_stack_equivalence(
170 "Snippet with dynamic symbols",
171 &dyn_output.op_stack.stack,
172 "Snippet with static symbols",
173 &stat_output.op_stack.stack,
174 );
175 }
176}
177
178#[cfg(test)]
179mod benches {
180 use super::*;
181 use crate::test_prelude::*;
182
183 #[test]
184 fn bench_10() {
185 ShadowedProcedure::new(SqueezeRepeatedlyStaticNumber { num_squeezes: 10 }).bench();
186 }
187
188 #[test]
189 fn bench_200() {
190 ShadowedProcedure::new(SqueezeRepeatedlyStaticNumber { num_squeezes: 200 }).bench();
191 }
192}