anemoi/ed_on_bls12_377/anemoi_2_1/
hasher.rs1#[cfg(not(feature = "std"))]
4use alloc::vec::Vec;
5
6use super::digest::AnemoiDigest;
7use super::{AnemoiEdOnBls12_377_2_1, Jive, Sponge};
8use super::{DIGEST_SIZE, STATE_WIDTH};
9use crate::traits::Anemoi;
10use ark_ff::PrimeField;
11
12use super::Felt;
13use super::{One, Zero};
14
15impl Sponge<Felt> for AnemoiEdOnBls12_377_2_1 {
16 type Digest = AnemoiDigest;
17
18 fn hash(bytes: &[u8]) -> Self::Digest {
19 let num_elements = if bytes.len() % 31 == 0 {
22 bytes.len() / 31
23 } else {
24 bytes.len() / 31 + 1
25 };
26
27 let mut state = [Felt::zero(); STATE_WIDTH];
29
30 let mut buf = [0u8; 32];
37 for (i, chunk) in bytes.chunks(31).enumerate() {
38 if i < num_elements - 1 {
39 buf[0..31].copy_from_slice(chunk);
40 } else {
41 let chunk_len = chunk.len();
45 buf = [0u8; 32];
46 buf[..chunk_len].copy_from_slice(chunk);
47 if chunk_len < 31 {
49 buf[chunk_len] = 1;
50 }
51 }
52
53 state[0] += Felt::from_le_bytes_mod_order(&buf[..]);
57 AnemoiEdOnBls12_377_2_1::permutation(&mut state);
58 }
59 state[STATE_WIDTH - 1] += Felt::one();
60
61 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
65 }
66
67 fn hash_field(elems: &[Felt]) -> Self::Digest {
68 let mut state = [Felt::zero(); STATE_WIDTH];
70
71 for &element in elems.iter() {
74 state[0] += element;
75 AnemoiEdOnBls12_377_2_1::permutation(&mut state);
76 }
77
78 state[STATE_WIDTH - 1] += Felt::one();
79
80 Self::Digest::new(state[..DIGEST_SIZE].try_into().unwrap())
84 }
85
86 fn merge(digests: &[Self::Digest; 2]) -> Self::Digest {
87 let result = Self::compress(&Self::Digest::digests_to_elements(digests));
90 Self::Digest::new(result.try_into().unwrap())
91 }
92}
93
94impl Jive<Felt> for AnemoiEdOnBls12_377_2_1 {
95 fn compress(elems: &[Felt]) -> Vec<Felt> {
96 assert!(elems.len() == STATE_WIDTH);
97
98 let mut state = elems.to_vec();
99 AnemoiEdOnBls12_377_2_1::permutation(&mut state);
100
101 vec![state[0] + state[1] + elems[0] + elems[1]]
102 }
103
104 fn compress_k(elems: &[Felt], k: usize) -> Vec<Felt> {
105 assert!(k == 2);
107
108 Self::compress(elems)
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 #[cfg(not(feature = "std"))]
115 use alloc::vec;
116
117 use super::super::MontFp;
118 use super::*;
119 use ark_ff::BigInteger;
120
121 #[test]
122 fn test_anemoi_hash() {
123 let input_data = [
125 vec![Felt::zero(), Felt::zero()],
126 vec![Felt::one(), Felt::one()],
127 vec![Felt::zero(), Felt::one()],
128 vec![Felt::one(), Felt::zero()],
129 vec![MontFp!(
130 "2701794724129673170044881656924003678119508097167887646056013505081505153941"
131 )],
132 vec![
133 MontFp!(
134 "6136112418425776110987395661408630531947256723654514515474099325642827368195"
135 ),
136 MontFp!(
137 "1750665747509629654143681886817319364490061620706939457796280733677342840536"
138 ),
139 ],
140 vec![
141 MontFp!(
142 "7419302752507955507727625165019065254163119937378581731857420479322421089499"
143 ),
144 MontFp!(
145 "4559650952616111375934279109757813936885978902236988815039265000756509380033"
146 ),
147 MontFp!(
148 "1135233996092168754628300471243482957747287551785928066349278596976141683924"
149 ),
150 ],
151 vec![
152 MontFp!(
153 "1043102290181650327389949602749036862032433278523840306868639917710387374771"
154 ),
155 MontFp!(
156 "4307491562116361618597497082323305958665690819685789478378073202108247466174"
157 ),
158 MontFp!(
159 "8276002717822051727248370396378451046543961863530952458242898618930392259498"
160 ),
161 MontFp!(
162 "697823225422979508435425451318633448160314726681841164485634653488707337155"
163 ),
164 ],
165 vec![
166 MontFp!(
167 "3511613069045600668201060103623350362861378594064425563036950657064452808148"
168 ),
169 MontFp!(
170 "164826560488580658427980384618027169790561646104634207479832305366799917896"
171 ),
172 MontFp!(
173 "7725367446600896112606560721239505513493098704961497582884899050064367743267"
174 ),
175 MontFp!(
176 "1304519449128211841092493704609228683609347511981155101682539749031135624359"
177 ),
178 MontFp!(
179 "2253160602893615828475245752494423392208457478787057653939826714992705372503"
180 ),
181 ],
182 vec![
183 MontFp!(
184 "6778459080375078354240530484738211312590141386355539256680627032395387751580"
185 ),
186 MontFp!(
187 "93624049550182582977412113403479422800060943063169915046698223121519200466"
188 ),
189 MontFp!(
190 "7722399227155929647209203618018966141115046905466472477162114078434889925803"
191 ),
192 MontFp!(
193 "4362457042764236508126106021709659576958225187859016903781545398127098366287"
194 ),
195 MontFp!(
196 "1635598988571107961875869710676973678440790488903729803300931707418622110543"
197 ),
198 MontFp!(
199 "4340733038522388446865752953560902505670573737797919431024824522904869142592"
200 ),
201 ],
202 ];
203
204 let output_data = [
205 [MontFp!(
206 "6038547479163037986409334235918516245718888275963429958045868475748310870262"
207 )],
208 [MontFp!(
209 "5290322214010334967587282982485974931105631029110653070735751242693563614504"
210 )],
211 [MontFp!(
212 "3724359895368550768973893174946038660878167910590705539560114603470279328816"
213 )],
214 [MontFp!(
215 "5395258772068762925789170702532573198276721923542161779150941414089330072040"
216 )],
217 [MontFp!(
218 "6437389331144526233027251753132997194151245817848750712560989451783332250690"
219 )],
220 [MontFp!(
221 "6387014775150552799372860356098991172191065503357197351459808793371394774834"
222 )],
223 [MontFp!(
224 "779756219490472826418676381497465819568380834103446740858202937881929583962"
225 )],
226 [MontFp!(
227 "5281691314668098790968241205590675464346678528867299504089015084730289888849"
228 )],
229 [MontFp!(
230 "620311156215507825863696040333743484531686107885002700624515445245202549984"
231 )],
232 [MontFp!(
233 "6791364295911321742758975425730448919938309444628380874854471393642988927668"
234 )],
235 ];
236
237 for (input, expected) in input_data.iter().zip(output_data) {
238 assert_eq!(
239 expected,
240 AnemoiEdOnBls12_377_2_1::hash_field(input).to_elements()
241 );
242 }
243 }
244
245 #[test]
246 fn test_anemoi_hash_bytes() {
247 let input_data = [
249 vec![Felt::zero(), Felt::zero()],
250 vec![Felt::one(), Felt::one()],
251 vec![Felt::zero(), Felt::one()],
252 vec![Felt::one(), Felt::zero()],
253 ];
254
255 let output_data = [
256 [MontFp!(
257 "6038547479163037986409334235918516245718888275963429958045868475748310870262"
258 )],
259 [MontFp!(
260 "5290322214010334967587282982485974931105631029110653070735751242693563614504"
261 )],
262 [MontFp!(
263 "3724359895368550768973893174946038660878167910590705539560114603470279328816"
264 )],
265 [MontFp!(
266 "5395258772068762925789170702532573198276721923542161779150941414089330072040"
267 )],
268 ];
269
270 for (input, expected) in input_data.iter().zip(output_data) {
274 let mut bytes = [0u8; 62];
275 bytes[0..31].copy_from_slice(&input[0].into_bigint().to_bytes_le()[0..31]);
276 bytes[31..62].copy_from_slice(&input[1].into_bigint().to_bytes_le()[0..31]);
277
278 assert_eq!(
279 expected,
280 AnemoiEdOnBls12_377_2_1::hash(&bytes).to_elements()
281 );
282 }
283 }
284
285 #[test]
286 fn test_anemoi_jive() {
287 let input_data = [
289 vec![Felt::zero(), Felt::zero()],
290 vec![Felt::one(), Felt::one()],
291 vec![Felt::zero(), Felt::one()],
292 vec![Felt::one(), Felt::zero()],
293 ];
294
295 let output_data = [
296 [MontFp!(
297 "676553123262956770831412211816454043839638653372636331333841739259626467495"
298 )],
299 [MontFp!(
300 "961399696453657341825013342908082065226592910566258118404273138500594033718"
301 )],
302 [MontFp!(
303 "7483032027386392696108818818965861527781219423978929688858862524367943483025"
304 )],
305 [MontFp!(
306 "1507470731653473592080957199708477983334364641992160367637834033297977648401"
307 )],
308 ];
309 for (input, expected) in input_data.iter().zip(output_data) {
310 assert_eq!(expected.to_vec(), AnemoiEdOnBls12_377_2_1::compress(input));
311 }
312
313 for (input, expected) in input_data.iter().zip(output_data) {
314 assert_eq!(
315 expected.to_vec(),
316 AnemoiEdOnBls12_377_2_1::compress_k(input, 2)
317 );
318 }
319
320 for (input, expected) in input_data.iter().zip(output_data) {
321 assert_eq!(
322 expected,
323 AnemoiEdOnBls12_377_2_1::merge(&[
324 AnemoiDigest::new([input[0]]),
325 AnemoiDigest::new([input[1]])
326 ])
327 .to_elements()
328 );
329 }
330 }
331}