1#![cfg_attr(not(feature = "std"), no_std)]
2#![deny(
4 const_err,
5 future_incompatible,
6 missing_docs,
7 non_shorthand_field_patterns,
8 renamed_and_removed_lints,
9 rust_2018_idioms,
10 stable_features,
11 trivial_casts,
12 trivial_numeric_casts,
13 unused,
14 variant_size_differences,
15 warnings
16)]
17#![forbid(unsafe_code)]
18
19use ark_ff::{FpParameters, PrimeField};
20use ark_std::vec;
21use ark_std::vec::Vec;
22
23#[cfg(feature = "r1cs")]
25pub mod constraints;
26
27mod absorb;
28pub use absorb::*;
29
30pub mod poseidon;
37
38#[derive(Clone, Copy, Eq, PartialEq)]
40pub enum FieldElementSize {
41 Full,
43
44 Truncated(usize),
46}
47
48impl FieldElementSize {
49 pub(crate) fn num_bits<F: PrimeField>(&self) -> usize {
50 if let FieldElementSize::Truncated(num_bits) = self {
51 if *num_bits > (F::Params::MODULUS_BITS as usize) {
52 panic!("num_bits is greater than the capacity of the field.")
53 }
54 };
55 F::Params::CAPACITY as usize
56 }
57
58 pub fn sum<F: PrimeField>(elements: &[Self]) -> usize {
60 elements.iter().map(|item| item.num_bits::<F>()).sum()
61 }
62}
63
64pub(crate) fn squeeze_field_elements_with_sizes_default_impl<F: PrimeField>(
66 sponge: &mut impl CryptographicSponge,
67 sizes: &[FieldElementSize],
68) -> Vec<F> {
69 if sizes.len() == 0 {
70 return Vec::new();
71 }
72
73 let mut total_bits = 0usize;
74 for size in sizes {
75 total_bits += size.num_bits::<F>();
76 }
77
78 let bits = sponge.squeeze_bits(total_bits);
79 let mut bits_window = bits.as_slice();
80
81 let mut output = Vec::with_capacity(sizes.len());
82 for size in sizes {
83 let num_bits = size.num_bits::<F>();
84 let nonnative_bits_le: Vec<bool> = bits_window[..num_bits].to_vec();
85 bits_window = &bits_window[num_bits..];
86
87 let nonnative_bytes = nonnative_bits_le
88 .chunks(8)
89 .map(|bits| {
90 let mut byte = 0u8;
91 for (i, &bit) in bits.into_iter().enumerate() {
92 if bit {
93 byte += 1 << i;
94 }
95 }
96 byte
97 })
98 .collect::<Vec<_>>();
99
100 output.push(F::from_le_bytes_mod_order(nonnative_bytes.as_slice()));
101 }
102
103 output
104}
105
106pub trait CryptographicSponge: Clone {
110 type Parameters;
112
113 fn new(params: &Self::Parameters) -> Self;
115
116 fn absorb(&mut self, input: &impl Absorb);
118
119 fn squeeze_bytes(&mut self, num_bytes: usize) -> Vec<u8>;
121
122 fn squeeze_bits(&mut self, num_bits: usize) -> Vec<bool>;
124
125 fn squeeze_field_elements_with_sizes<F: PrimeField>(
136 &mut self,
137 sizes: &[FieldElementSize],
138 ) -> Vec<F> {
139 squeeze_field_elements_with_sizes_default_impl(self, sizes)
140 }
141
142 fn squeeze_field_elements<F: PrimeField>(&mut self, num_elements: usize) -> Vec<F> {
147 self.squeeze_field_elements_with_sizes::<F>(
148 vec![FieldElementSize::Full; num_elements].as_slice(),
149 )
150 }
151
152 fn fork(&self, domain: &[u8]) -> Self {
154 let mut new_sponge = self.clone();
155
156 let mut input = Absorb::to_sponge_bytes_as_vec(&domain.len());
157 input.extend_from_slice(domain);
158 new_sponge.absorb(&input);
159
160 new_sponge
161 }
162}
163
164pub trait FieldBasedCryptographicSponge<CF: PrimeField>: CryptographicSponge {
167 fn squeeze_native_field_elements(&mut self, num_elements: usize) -> Vec<CF>;
169
170 fn squeeze_native_field_elements_with_sizes(&mut self, sizes: &[FieldElementSize]) -> Vec<CF> {
173 let mut all_full_sizes = true;
174 for size in sizes {
175 if *size != FieldElementSize::Full {
176 all_full_sizes = false;
177 break;
178 }
179 }
180
181 if all_full_sizes {
182 self.squeeze_native_field_elements(sizes.len())
183 } else {
184 squeeze_field_elements_with_sizes_default_impl(self, sizes)
185 }
186 }
187}
188
189pub trait SpongeExt: CryptographicSponge {
193 type State: Clone;
195 fn from_state(state: Self::State, params: &Self::Parameters) -> Self;
197 fn into_state(self) -> Self::State;
199}