1use alloc::{vec, vec::Vec};
6
7use core::marker::PhantomData;
8
9use crate::DomainParameter;
10use mina_curves::pasta::Fp;
11use mina_poseidon::{
12 constants::{PlonkSpongeConstantsKimchi, PlonkSpongeConstantsLegacy, SpongeConstants},
13 pasta,
14 poseidon::{ArithmeticSponge, ArithmeticSpongeParams, Sponge, SpongeState},
15};
16
17use super::{domain_prefix_to_field, Hashable, Hasher};
18
19pub struct Poseidon<SC: SpongeConstants, H: Hashable> {
26 sponge: ArithmeticSponge<Fp, SC>,
27 sponge_state: SpongeState,
28 pub state: Vec<Fp>,
30 phantom: PhantomData<H>,
31}
32
33impl<SC: SpongeConstants, H: Hashable> Poseidon<SC, H> {
34 fn new(domain_param: H::D, sponge_params: &'static ArithmeticSpongeParams<Fp>) -> Self {
35 let mut poseidon = Poseidon::<SC, H> {
36 sponge: ArithmeticSponge::<Fp, SC>::new(sponge_params),
37 sponge_state: SpongeState::Absorbed(0),
38 state: vec![],
39 phantom: PhantomData,
40 };
41
42 poseidon.init(domain_param);
43
44 poseidon
45 }
46}
47
48pub type PoseidonHasherLegacy<H> = Poseidon<PlonkSpongeConstantsLegacy, H>;
50
51pub(crate) fn new_legacy<H: Hashable>(domain_param: H::D) -> PoseidonHasherLegacy<H> {
53 Poseidon::<PlonkSpongeConstantsLegacy, H>::new(domain_param, pasta::fp_legacy::static_params())
54}
55
56pub type PoseidonHasherKimchi<H> = Poseidon<PlonkSpongeConstantsKimchi, H>;
58
59pub(crate) fn new_kimchi<H: Hashable>(domain_param: H::D) -> PoseidonHasherKimchi<H> {
61 Poseidon::<PlonkSpongeConstantsKimchi, H>::new(domain_param, pasta::fp_kimchi::static_params())
62}
63
64impl<SC: SpongeConstants, H: Hashable> Hasher<H> for Poseidon<SC, H>
65where
66 H::D: DomainParameter,
67{
68 fn reset(&mut self) -> &mut dyn Hasher<H> {
69 self.sponge.sponge_state = self.sponge_state.clone();
71 self.sponge.state.clone_from(&self.state);
72
73 self
74 }
75
76 fn init(&mut self, domain_param: H::D) -> &mut dyn Hasher<H> {
77 self.sponge.reset();
82
83 if let Some(domain_string) = H::domain_string(domain_param) {
84 self.sponge
85 .absorb(&[domain_prefix_to_field::<Fp>(domain_string)]);
86 self.sponge.squeeze();
87 }
88
89 self.sponge_state = self.sponge.sponge_state.clone();
91 self.state.clone_from(&self.sponge.state);
92
93 self
94 }
95
96 fn update(&mut self, input: &H) -> &mut dyn Hasher<H> {
97 self.sponge.absorb(&input.to_roinput().to_fields());
98
99 self
100 }
101
102 fn digest(&mut self) -> Fp {
103 let output = self.sponge.squeeze();
104 self.sponge.reset();
105 output
106 }
107}