1use math::{fields::f62::BaseElement, FieldElement, StarkField};
7
8use super::{exp_acc, Digest, ElementHasher, Hasher};
9
10mod digest;
11pub use digest::ElementDigest;
12
13#[cfg(test)]
14mod tests;
15
16const STATE_WIDTH: usize = 12;
22const RATE_WIDTH: usize = 8;
23
24const DIGEST_SIZE: usize = 4;
26
27const NUM_ROUNDS: usize = 7;
30
31#[cfg(test)]
37const ALPHA: u32 = 3;
38#[cfg(test)]
39const INV_ALPHA: u64 = 3074416663688030891;
40
41pub struct Rp62_248();
91
92impl Hasher for Rp62_248 {
93 type Digest = ElementDigest;
94
95 const COLLISION_RESISTANCE: u32 = 124;
96
97 fn hash(bytes: &[u8]) -> Self::Digest {
98 let num_elements = if bytes.len() % 7 == 0 {
102 bytes.len() / 7
103 } else {
104 bytes.len() / 7 + 1
105 };
106
107 let mut state = [BaseElement::ZERO; STATE_WIDTH];
111 state[STATE_WIDTH - 1] = BaseElement::new(num_elements as u64);
112
113 let mut i = 0;
117 let mut buf = [0_u8; 8];
118 for chunk in bytes.chunks(7) {
119 if i < num_elements - 1 {
120 buf[..7].copy_from_slice(chunk);
121 } else {
122 let chunk_len = chunk.len();
127 buf = [0_u8; 8];
128 buf[..chunk_len].copy_from_slice(chunk);
129 buf[chunk_len] = 1;
130 }
131
132 state[i] += BaseElement::new(u64::from_le_bytes(buf));
136 i += 1;
137 if i % RATE_WIDTH == 0 {
138 apply_permutation(&mut state);
139 i = 0;
140 }
141 }
142
143 if i > 0 {
148 apply_permutation(&mut state);
149 }
150
151 ElementDigest::new(state[..DIGEST_SIZE].try_into().unwrap())
153 }
154
155 fn merge(values: &[Self::Digest; 2]) -> Self::Digest {
156 let mut state = [BaseElement::ZERO; STATE_WIDTH];
160 state[..RATE_WIDTH].copy_from_slice(Self::Digest::digests_as_elements(values));
161 state[STATE_WIDTH - 1] = BaseElement::new(RATE_WIDTH as u64);
162
163 apply_permutation(&mut state);
165 ElementDigest::new(state[..DIGEST_SIZE].try_into().unwrap())
166 }
167
168 fn merge_many(values: &[Self::Digest]) -> Self::Digest {
169 Self::hash_elements(ElementDigest::digests_as_elements(values))
170 }
171
172 fn merge_with_int(seed: Self::Digest, value: u64) -> Self::Digest {
173 let mut state = [BaseElement::ZERO; STATE_WIDTH];
180 state[..DIGEST_SIZE].copy_from_slice(seed.as_elements());
181 state[DIGEST_SIZE] = BaseElement::new(value);
182 if value < BaseElement::MODULUS {
183 state[STATE_WIDTH - 1] = BaseElement::new(DIGEST_SIZE as u64 + 1);
184 } else {
185 state[DIGEST_SIZE + 1] = BaseElement::new(value / BaseElement::MODULUS);
186 state[STATE_WIDTH - 1] = BaseElement::new(DIGEST_SIZE as u64 + 2);
187 }
188
189 apply_permutation(&mut state);
191 ElementDigest::new(state[..DIGEST_SIZE].try_into().unwrap())
192 }
193}
194
195impl ElementHasher for Rp62_248 {
196 type BaseField = BaseElement;
197
198 fn hash_elements<E: FieldElement<BaseField = Self::BaseField>>(elements: &[E]) -> Self::Digest {
199 let elements = E::slice_as_base_elements(elements);
201
202 let mut state = [BaseElement::ZERO; STATE_WIDTH];
206 state[STATE_WIDTH - 1] = BaseElement::new(elements.len() as u64);
207
208 let mut i = 0;
212 for &element in elements.iter() {
213 state[i] += element;
214 i += 1;
215 if i % RATE_WIDTH == 0 {
216 apply_permutation(&mut state);
217 i = 0;
218 }
219 }
220
221 if i > 0 {
226 apply_permutation(&mut state);
227 }
228
229 ElementDigest::new(state[..DIGEST_SIZE].try_into().unwrap())
231 }
232}
233
234fn apply_permutation(state: &mut [BaseElement; STATE_WIDTH]) {
241 for i in 0..NUM_ROUNDS {
243 apply_round(state, i);
244 }
245}
246
247#[inline(always)]
249fn apply_round(state: &mut [BaseElement; STATE_WIDTH], round: usize) {
250 apply_sbox(state);
252 apply_mds(state);
253 add_constants(state, &ARK1[round]);
254
255 apply_inv_sbox(state);
257 apply_mds(state);
258 add_constants(state, &ARK2[round]);
259}
260
261#[inline(always)]
265fn apply_mds(state: &mut [BaseElement; STATE_WIDTH]) {
266 let mut result = [BaseElement::ZERO; STATE_WIDTH];
267 result.iter_mut().zip(MDS).for_each(|(r, mds_row)| {
268 state.iter().zip(mds_row).for_each(|(&s, m)| {
269 *r += m * s;
270 });
271 });
272 *state = result
273}
274
275#[inline(always)]
276fn add_constants(state: &mut [BaseElement; STATE_WIDTH], ark: &[BaseElement; STATE_WIDTH]) {
277 state.iter_mut().zip(ark).for_each(|(s, &k)| *s += k);
278}
279
280#[inline(always)]
281fn apply_sbox(state: &mut [BaseElement; STATE_WIDTH]) {
282 state.iter_mut().for_each(|v| *v = v.cube())
283}
284
285#[inline(always)]
286fn apply_inv_sbox(state: &mut [BaseElement; STATE_WIDTH]) {
287 let mut t1 = *state;
292 t1.iter_mut().for_each(|t1| *t1 = t1.square());
293
294 let t2 = exp_acc::<BaseElement, STATE_WIDTH, 2>(t1, t1);
296
297 let t4 = exp_acc::<BaseElement, STATE_WIDTH, 4>(t2, t2);
299
300 let t8 = exp_acc::<BaseElement, STATE_WIDTH, 8>(t4, t4);
302
303 let acc = exp_acc::<BaseElement, STATE_WIDTH, 7>(t8, t2);
305
306 let acc = exp_acc::<BaseElement, STATE_WIDTH, 15>(acc, t8);
308
309 let acc = exp_acc::<BaseElement, STATE_WIDTH, 16>(acc, t8);
311
312 let acc = exp_acc::<BaseElement, STATE_WIDTH, 8>(acc, t4);
314
315 state.iter_mut().zip(acc).for_each(|(s, a)| *s *= a);
317}
318
319const MDS: [[BaseElement; STATE_WIDTH]; STATE_WIDTH] = [
324 [
325 BaseElement::new(3950144678237376122),
326 BaseElement::new(2690153189131774333),
327 BaseElement::new(936645784682382348),
328 BaseElement::new(3107191214132265415),
329 BaseElement::new(2603209838230440664),
330 BaseElement::new(1199396433148647196),
331 BaseElement::new(1282983482067326228),
332 BaseElement::new(461437407589395643),
333 BaseElement::new(2214977176974126410),
334 BaseElement::new(360795585898440),
335 BaseElement::new(4611624977880333167),
336 BaseElement::new(265720),
337 ],
338 [
339 BaseElement::new(3536793164176604955),
340 BaseElement::new(1911503332938627860),
341 BaseElement::new(3418675122760523340),
342 BaseElement::new(1504989930332511353),
343 BaseElement::new(2722575982003138843),
344 BaseElement::new(1431609872573058051),
345 BaseElement::new(1192456656548488631),
346 BaseElement::new(545546930229576032),
347 BaseElement::new(945223199513254881),
348 BaseElement::new(1241455355734630133),
349 BaseElement::new(4607295377894412377),
350 BaseElement::new(52955405230),
351 ],
352 [
353 BaseElement::new(4170851182034451356),
354 BaseElement::new(4049722115827050441),
355 BaseElement::new(2592958603203603955),
356 BaseElement::new(1591126261909367400),
357 BaseElement::new(1258275846807863107),
358 BaseElement::new(1998950167196902314),
359 BaseElement::new(3042201191319512244),
360 BaseElement::new(543039388605157758),
361 BaseElement::new(1398996793391337371),
362 BaseElement::new(4366181202594792993),
363 BaseElement::new(2647705527662157444),
364 BaseElement::new(9741692640081640),
365 ],
366 [
367 BaseElement::new(2734904247639408359),
368 BaseElement::new(4279587509601476247),
369 BaseElement::new(4485482368008952587),
370 BaseElement::new(3891839128198288856),
371 BaseElement::new(3605615068318190226),
372 BaseElement::new(4481033712623965820),
373 BaseElement::new(4511906145686918697),
374 BaseElement::new(3379942354449020806),
375 BaseElement::new(3990599459674901680),
376 BaseElement::new(3930378924631282611),
377 BaseElement::new(2736309679810514295),
378 BaseElement::new(4088651356677543187),
379 ],
380 [
381 BaseElement::new(842258110397353220),
382 BaseElement::new(3379876823114508085),
383 BaseElement::new(1075495666387844288),
384 BaseElement::new(2308322198399190449),
385 BaseElement::new(535073101119307124),
386 BaseElement::new(2549013922555968548),
387 BaseElement::new(2089967165864721761),
388 BaseElement::new(1833259538539094178),
389 BaseElement::new(1286299364399671252),
390 BaseElement::new(3116429868056012525),
391 BaseElement::new(3765145590440791140),
392 BaseElement::new(276983628385769116),
393 ],
394 [
395 BaseElement::new(1299560456850023050),
396 BaseElement::new(4414989737001639740),
397 BaseElement::new(627780834867342283),
398 BaseElement::new(1711770898052004155),
399 BaseElement::new(1979604523493335895),
400 BaseElement::new(33488920757262988),
401 BaseElement::new(3296083413419576217),
402 BaseElement::new(716111559512999319),
403 BaseElement::new(1748727787185165915),
404 BaseElement::new(2725007460252215875),
405 BaseElement::new(2185047820717910109),
406 BaseElement::new(2319951565550756140),
407 ],
408 [
409 BaseElement::new(4184625686841861769),
410 BaseElement::new(1784981074793151883),
411 BaseElement::new(502457291852703062),
412 BaseElement::new(345570060311611630),
413 BaseElement::new(2471821400707240604),
414 BaseElement::new(2133038110899525730),
415 BaseElement::new(939120245208093777),
416 BaseElement::new(4151312447988641414),
417 BaseElement::new(210626922136569504),
418 BaseElement::new(2121768124528492214),
419 BaseElement::new(3469035391047007665),
420 BaseElement::new(743768221345332434),
421 ],
422 [
423 BaseElement::new(2145694559473526100),
424 BaseElement::new(1632268183143575659),
425 BaseElement::new(440280249850363795),
426 BaseElement::new(1074260737240252344),
427 BaseElement::new(434235372443698697),
428 BaseElement::new(4579079558834190297),
429 BaseElement::new(507988595809300562),
430 BaseElement::new(746255436130103157),
431 BaseElement::new(1959107915115263608),
432 BaseElement::new(4030330146733953284),
433 BaseElement::new(3748621471482452510),
434 BaseElement::new(1760002751403551673),
435 ],
436 [
437 BaseElement::new(2299194066166806303),
438 BaseElement::new(2406031288159683129),
439 BaseElement::new(3724303300393675060),
440 BaseElement::new(3136303930848425791),
441 BaseElement::new(842217609243732235),
442 BaseElement::new(2433222065782096659),
443 BaseElement::new(1853915347332186193),
444 BaseElement::new(3565339054535487990),
445 BaseElement::new(3159752035320462032),
446 BaseElement::new(1001592926358592140),
447 BaseElement::new(1070575826169209928),
448 BaseElement::new(2177302522881920563),
449 ],
450 [
451 BaseElement::new(2207526749486243134),
452 BaseElement::new(4032720262691072240),
453 BaseElement::new(1260214313840482146),
454 BaseElement::new(3621152551536391331),
455 BaseElement::new(1609693674346558276),
456 BaseElement::new(1076797379868177960),
457 BaseElement::new(1050224695423079188),
458 BaseElement::new(1679887683779537233),
459 BaseElement::new(1053394941293588429),
460 BaseElement::new(2176319632402176708),
461 BaseElement::new(807051555764923088),
462 BaseElement::new(2483141537228001953),
463 ],
464 [
465 BaseElement::new(873986056056007361),
466 BaseElement::new(2985158312969304104),
467 BaseElement::new(2082576071668149043),
468 BaseElement::new(1607709264834493266),
469 BaseElement::new(1027130385873843589),
470 BaseElement::new(3876861839368848637),
471 BaseElement::new(2999813843878199730),
472 BaseElement::new(3252530728916107838),
473 BaseElement::new(4464640832314938694),
474 BaseElement::new(1978539358398864357),
475 BaseElement::new(3425590232595452442),
476 BaseElement::new(3706838041850115299),
477 ],
478 [
479 BaseElement::new(3407508207732360664),
480 BaseElement::new(2899952415584588394),
481 BaseElement::new(282047285293952955),
482 BaseElement::new(4147714396995528527),
483 BaseElement::new(1141786266584343815),
484 BaseElement::new(3523991864183271024),
485 BaseElement::new(1659008334442446407),
486 BaseElement::new(2857663046861472404),
487 BaseElement::new(1954265424153359502),
488 BaseElement::new(4018750979872307732),
489 BaseElement::new(494911809436924696),
490 BaseElement::new(1282149942051721903),
491 ],
492];
493
494pub const ARK1: [[BaseElement; STATE_WIDTH]; NUM_ROUNDS] = [
503 [
504 BaseElement::new(2066114551762569441),
505 BaseElement::new(3806895469920197238),
506 BaseElement::new(4101271467144175579),
507 BaseElement::new(597783788093439290),
508 BaseElement::new(3459529549731874958),
509 BaseElement::new(3361732357449281221),
510 BaseElement::new(4510044102131299796),
511 BaseElement::new(2674251637583411151),
512 BaseElement::new(4589456981709905074),
513 BaseElement::new(97204927704726530),
514 BaseElement::new(3366467278170867590),
515 BaseElement::new(1661995649761352250),
516 ],
517 [
518 BaseElement::new(2552080730515318124),
519 BaseElement::new(4551129269607279176),
520 BaseElement::new(3896238353185798118),
521 BaseElement::new(4378451547412130464),
522 BaseElement::new(1120678946404787820),
523 BaseElement::new(3392815550656692052),
524 BaseElement::new(3397267446269039551),
525 BaseElement::new(2148161493216445570),
526 BaseElement::new(449851947043698998),
527 BaseElement::new(2745778316253333994),
528 BaseElement::new(3247100729373266485),
529 BaseElement::new(1474512661374883327),
530 ],
531 [
532 BaseElement::new(3875405236566248698),
533 BaseElement::new(3509172052827303011),
534 BaseElement::new(232674088014396347),
535 BaseElement::new(4189609763147780999),
536 BaseElement::new(3106901133683704323),
537 BaseElement::new(592695797873090171),
538 BaseElement::new(266738566669046215),
539 BaseElement::new(2668509039085882180),
540 BaseElement::new(950720373611234910),
541 BaseElement::new(1192091586747406812),
542 BaseElement::new(2245360993531047612),
543 BaseElement::new(2031514636218081872),
544 ],
545 [
546 BaseElement::new(2291456653144584105),
547 BaseElement::new(869259464485808552),
548 BaseElement::new(1154055231930493301),
549 BaseElement::new(1843073679205946182),
550 BaseElement::new(1748748883129851856),
551 BaseElement::new(4085632850766581010),
552 BaseElement::new(2907511654177734852),
553 BaseElement::new(1563252740420931271),
554 BaseElement::new(57166044462862224),
555 BaseElement::new(3237323403752048612),
556 BaseElement::new(4563484427236835576),
557 BaseElement::new(2956709587309713553),
558 ],
559 [
560 BaseElement::new(2157779262561212790),
561 BaseElement::new(2452020513593893218),
562 BaseElement::new(3051597722203497560),
563 BaseElement::new(3131962147511514023),
564 BaseElement::new(194930663253195526),
565 BaseElement::new(930794074695110797),
566 BaseElement::new(3616451697350340387),
567 BaseElement::new(1493869649774878568),
568 BaseElement::new(2790579710588613698),
569 BaseElement::new(4552593272704308029),
570 BaseElement::new(931863165972727433),
571 BaseElement::new(2628222466499909093),
572 ],
573 [
574 BaseElement::new(628982718083809865),
575 BaseElement::new(3809487906119235546),
576 BaseElement::new(1412055838972795717),
577 BaseElement::new(2702758340764464061),
578 BaseElement::new(643165380746471120),
579 BaseElement::new(1755475976486779630),
580 BaseElement::new(4322584783908582556),
581 BaseElement::new(2377752666356883186),
582 BaseElement::new(3806838324704149861),
583 BaseElement::new(3978620600887524391),
584 BaseElement::new(2546609133879704944),
585 BaseElement::new(3704323050566652251),
586 ],
587 [
588 BaseElement::new(364418616620607840),
589 BaseElement::new(557500673241722848),
590 BaseElement::new(2838167312179774894),
591 BaseElement::new(919171238566781484),
592 BaseElement::new(1810286722734245651),
593 BaseElement::new(2647811277753845608),
594 BaseElement::new(1083073358474695843),
595 BaseElement::new(2087740333294235353),
596 BaseElement::new(3237593972479805167),
597 BaseElement::new(2979012086287276314),
598 BaseElement::new(4247318354894968843),
599 BaseElement::new(4339035876293932168),
600 ],
601];
602
603pub const ARK2: [[BaseElement; STATE_WIDTH]; NUM_ROUNDS] = [
604 [
605 BaseElement::new(3819036781602939606),
606 BaseElement::new(887046499825451011),
607 BaseElement::new(2129644207518417092),
608 BaseElement::new(2927054444958183703),
609 BaseElement::new(3938394192009721127),
610 BaseElement::new(4350492790583122386),
611 BaseElement::new(3932489874389553135),
612 BaseElement::new(2187735113981662094),
613 BaseElement::new(2707268329521558754),
614 BaseElement::new(1672475830798880457),
615 BaseElement::new(577661991381759440),
616 BaseElement::new(4202413457369478629),
617 ],
618 [
619 BaseElement::new(2386138289504492057),
620 BaseElement::new(3614836749985123032),
621 BaseElement::new(1959364639655691456),
622 BaseElement::new(3952161783467742979),
623 BaseElement::new(2113797503569123694),
624 BaseElement::new(2706761515468719677),
625 BaseElement::new(1408899580454624727),
626 BaseElement::new(1752562999883762712),
627 BaseElement::new(2699036399761024947),
628 BaseElement::new(2111974313315470120),
629 BaseElement::new(1945634303007041433),
630 BaseElement::new(603680138767490486),
631 ],
632 [
633 BaseElement::new(216541366065294490),
634 BaseElement::new(1663917238463860974),
635 BaseElement::new(3681161841551456227),
636 BaseElement::new(1463044976083347872),
637 BaseElement::new(4293067359825676566),
638 BaseElement::new(3701547299239100959),
639 BaseElement::new(2198012560927400476),
640 BaseElement::new(924090339017537873),
641 BaseElement::new(4592565695695653575),
642 BaseElement::new(2568652539159558382),
643 BaseElement::new(2556673802560280889),
644 BaseElement::new(2055200673419696274),
645 ],
646 [
647 BaseElement::new(675825972975288687),
648 BaseElement::new(157304917963529210),
649 BaseElement::new(2874195676109427150),
650 BaseElement::new(400733584567227315),
651 BaseElement::new(982698402204661622),
652 BaseElement::new(820183842893732317),
653 BaseElement::new(301881572013037058),
654 BaseElement::new(1963857632534980766),
655 BaseElement::new(4091993061963419897),
656 BaseElement::new(4102179200035343013),
657 BaseElement::new(886874507443125118),
658 BaseElement::new(1900379595653484868),
659 ],
660 [
661 BaseElement::new(663951223276314056),
662 BaseElement::new(3247862347650141921),
663 BaseElement::new(2405853211128575753),
664 BaseElement::new(2313821214725089833),
665 BaseElement::new(892865509580640652),
666 BaseElement::new(3786801988137677226),
667 BaseElement::new(1708051655041482785),
668 BaseElement::new(413367975786665969),
669 BaseElement::new(4184177931828745920),
670 BaseElement::new(1902978742415691889),
671 BaseElement::new(3457684352259258126),
672 BaseElement::new(2092600929857819767),
673 ],
674 [
675 BaseElement::new(3616150808336931771),
676 BaseElement::new(3206846600545625539),
677 BaseElement::new(3830153390371624940),
678 BaseElement::new(2654199900015314333),
679 BaseElement::new(783490214003335242),
680 BaseElement::new(3730076606034436027),
681 BaseElement::new(3784919641869206369),
682 BaseElement::new(2204748845493012644),
683 BaseElement::new(448185939031874189),
684 BaseElement::new(435945873799083567),
685 BaseElement::new(695310862494154666),
686 BaseElement::new(2112586212508747422),
687 ],
688 [
689 BaseElement::new(1802926915815728451),
690 BaseElement::new(2057340163436909216),
691 BaseElement::new(982232855844273391),
692 BaseElement::new(1559347186127685318),
693 BaseElement::new(1420221884912541505),
694 BaseElement::new(4213862187371016442),
695 BaseElement::new(476828620219460093),
696 BaseElement::new(4518037022029400598),
697 BaseElement::new(186346377116487094),
698 BaseElement::new(4479404873270208061),
699 BaseElement::new(3269764362972891817),
700 BaseElement::new(2929967273325723272),
701 ],
702];