tasm_lib/hashing/algebraic_hasher/
hash_static_size.rs1use triton_vm::prelude::*;
2
3use crate::hashing::absorb_multiple_static_size::AbsorbMultipleStaticSize;
4use crate::prelude::*;
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
7pub struct HashStaticSize {
8 pub size: usize,
9}
10
11impl BasicSnippet for HashStaticSize {
12 fn parameters(&self) -> Vec<(DataType, String)> {
13 vec![(DataType::VoidPointer, "*addr".to_owned())]
14 }
15
16 fn return_values(&self) -> Vec<(DataType, String)> {
17 vec![
18 (DataType::Digest, "digest".to_owned()),
19 (DataType::VoidPointer, "*addr + size".to_owned()),
20 ]
21 }
22
23 fn entrypoint(&self) -> String {
24 format!(
25 "tasmlib_hashing_algebraic_hasher_hash_static_size_{}",
26 self.size
27 )
28 }
29
30 fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
31 let entrypoint = self.entrypoint();
32 let absorb_subroutine =
33 library.import(Box::new(AbsorbMultipleStaticSize { size: self.size }));
34
35 triton_asm!(
36 {entrypoint}:
39 sponge_init
40 call {absorb_subroutine}
41 sponge_squeeze swap 6 pop 1
43 swap 6 pop 1
44 swap 6 pop 1
45 swap 6 pop 1
46 swap 6
47 swap 1 pop 1
48 return
50 )
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use twenty_first::prelude::*;
57
58 use super::*;
59 use crate::test_prelude::*;
60
61 #[macro_rules_attr::apply(test)]
62 fn hash_static_size_small_pbt() {
63 for size in 0..20 {
64 println!("Testing size {size}");
65 ShadowedProcedure::new(HashStaticSize { size }).test();
66 }
67 }
68
69 #[macro_rules_attr::apply(proptest(cases = 50))]
70 fn hash_static_size_pbt_pbt(#[strategy(arb())] size: u8) {
71 ShadowedProcedure::new(HashStaticSize {
72 size: size as usize,
73 })
74 .test();
75 }
76
77 impl Procedure for HashStaticSize {
78 fn rust_shadow(
79 &self,
80 stack: &mut Vec<BFieldElement>,
81 memory: &mut HashMap<BFieldElement, BFieldElement>,
82 nondeterminism: &NonDeterminism,
83 public_input: &[BFieldElement],
84 sponge: &mut Option<Tip5>,
85 ) -> Result<Vec<BFieldElement>, RustShadowError> {
86 *sponge = Some(Tip5::init());
87
88 let absorb_snippet = AbsorbMultipleStaticSize { size: self.size };
89 absorb_snippet.rust_shadow(stack, memory, nondeterminism, public_input, sponge)?;
90
91 let Some(sponge) = sponge.as_mut() else {
93 return Err(RustShadowError::SpongeUninitialized);
94 };
95 let mut squeezed = sponge.squeeze();
96 squeezed.reverse();
97 stack.extend(squeezed);
98
99 let digest = pop_encodable::<Digest>(stack)?;
101
102 for _ in 0..Digest::LEN {
104 stack.pop().ok_or(RustShadowError::StackUnderflow)?;
105 }
106
107 let input_pointer_plus_size = stack.pop().ok_or(RustShadowError::StackUnderflow)?;
109
110 stack.extend(digest.reversed().values().to_vec());
112
113 stack.push(input_pointer_plus_size);
114
115 Ok(Vec::new())
118 }
119
120 fn pseudorandom_initial_state(
121 &self,
122 seed: [u8; 32],
123 _bench_case: Option<BenchmarkCase>,
124 ) -> ProcedureInitialState {
125 let mut rng = StdRng::from_seed(seed);
126 let memory_start: BFieldElement = rng.random();
127 let memory: HashMap<BFieldElement, BFieldElement> = (0..self.size)
128 .map(|i| (memory_start + BFieldElement::new(i as u64), rng.random()))
129 .collect();
130
131 let nondeterminism = NonDeterminism::default().with_ram(memory);
132 ProcedureInitialState {
133 stack: [self.init_stack_for_isolated_run(), vec![memory_start]].concat(),
134 nondeterminism,
135 public_input: vec![],
136 sponge: None,
137 }
138 }
139 }
140}
141
142#[cfg(test)]
143mod benches {
144 use super::*;
145 use crate::test_prelude::*;
146
147 #[macro_rules_attr::apply(test)]
149 fn hash_var_lenstatic_size_benchmark_356() {
150 ShadowedProcedure::new(HashStaticSize { size: 356 }).bench();
151 }
152
153 #[macro_rules_attr::apply(test)]
155 fn hash_var_lenstatic_size_benchmark_249() {
156 ShadowedProcedure::new(HashStaticSize { size: 249 }).bench();
157 }
158
159 #[macro_rules_attr::apply(test)]
161 fn hash_var_lenstatic_size_benchmark_12() {
162 ShadowedProcedure::new(HashStaticSize { size: 12 }).bench();
163 }
164
165 #[macro_rules_attr::apply(test)]
167 fn hash_var_lenstatic_size_benchmark_1000() {
168 ShadowedProcedure::new(HashStaticSize { size: 1000 }).bench();
169 }
170}