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 state: Vec<Fp>,
29 phantom: PhantomData<H>,
30}
31
32impl<SC: SpongeConstants, H: Hashable> Poseidon<SC, H> {
33 fn new(domain_param: H::D, sponge_params: &'static ArithmeticSpongeParams<Fp>) -> Self {
34 let mut poseidon = Poseidon::<SC, H> {
35 sponge: ArithmeticSponge::<Fp, SC>::new(sponge_params),
36 sponge_state: SpongeState::Absorbed(0),
37 state: vec![],
38 phantom: PhantomData,
39 };
40
41 poseidon.init(domain_param);
42
43 poseidon
44 }
45}
46
47pub type PoseidonHasherLegacy<H> = Poseidon<PlonkSpongeConstantsLegacy, H>;
49
50pub(crate) fn new_legacy<H: Hashable>(domain_param: H::D) -> PoseidonHasherLegacy<H> {
52 Poseidon::<PlonkSpongeConstantsLegacy, H>::new(domain_param, pasta::fp_legacy::static_params())
53}
54
55pub type PoseidonHasherKimchi<H> = Poseidon<PlonkSpongeConstantsKimchi, H>;
57
58pub(crate) fn new_kimchi<H: Hashable>(domain_param: H::D) -> PoseidonHasherKimchi<H> {
60 Poseidon::<PlonkSpongeConstantsKimchi, H>::new(domain_param, pasta::fp_kimchi::static_params())
61}
62
63impl<SC: SpongeConstants, H: Hashable> Hasher<H> for Poseidon<SC, H>
64where
65 H::D: DomainParameter,
66{
67 fn reset(&mut self) -> &mut dyn Hasher<H> {
68 self.sponge.sponge_state = self.sponge_state.clone();
70 self.sponge.state.clone_from(&self.state);
71
72 self
73 }
74
75 fn init(&mut self, domain_param: H::D) -> &mut dyn Hasher<H> {
76 self.sponge.reset();
79
80 if let Some(domain_string) = H::domain_string(domain_param) {
81 self.sponge
82 .absorb(&[domain_prefix_to_field::<Fp>(domain_string)]);
83 self.sponge.squeeze();
84 }
85
86 self.sponge_state = self.sponge.sponge_state.clone();
88 self.state.clone_from(&self.sponge.state);
89
90 self
91 }
92
93 fn update(&mut self, input: &H) -> &mut dyn Hasher<H> {
94 self.sponge.absorb(&input.to_roinput().to_fields());
95
96 self
97 }
98
99 fn digest(&mut self) -> Fp {
100 let output = self.sponge.squeeze();
101 self.sponge.reset();
102 output
103 }
104}