liminal_ark_pnbr_sponge/
lib.rs1#![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)]
16#![forbid(unsafe_code)]
17
18use ark_ff::{FpParameters, PrimeField};
19use ark_std::vec;
20use ark_std::vec::Vec;
21
22#[cfg(feature = "r1cs")]
24pub mod constraints;
25
26mod absorb;
27pub use absorb::*;
28
29pub mod poseidon;
36
37#[derive(Clone, Copy, Eq, PartialEq)]
39pub enum FieldElementSize {
40 Full,
42
43 Truncated(usize),
45}
46
47impl FieldElementSize {
48 pub(crate) fn num_bits<F: PrimeField>(&self) -> usize {
49 if let FieldElementSize::Truncated(num_bits) = self {
50 if *num_bits > (F::Params::MODULUS_BITS as usize) {
51 panic!("num_bits is greater than the capacity of the field.")
52 }
53 };
54 F::Params::CAPACITY as usize
55 }
56
57 pub fn sum<F: PrimeField>(elements: &[Self]) -> usize {
59 elements.iter().map(|item| item.num_bits::<F>()).sum()
60 }
61}
62
63pub(crate) fn squeeze_field_elements_with_sizes_default_impl<F: PrimeField>(
65 sponge: &mut impl CryptographicSponge,
66 sizes: &[FieldElementSize],
67) -> Vec<F> {
68 if sizes.len() == 0 {
69 return Vec::new();
70 }
71
72 let mut total_bits = 0usize;
73 for size in sizes {
74 total_bits += size.num_bits::<F>();
75 }
76
77 let bits = sponge.squeeze_bits(total_bits);
78 let mut bits_window = bits.as_slice();
79
80 let mut output = Vec::with_capacity(sizes.len());
81 for size in sizes {
82 let num_bits = size.num_bits::<F>();
83 let nonnative_bits_le: Vec<bool> = bits_window[..num_bits].to_vec();
84 bits_window = &bits_window[num_bits..];
85
86 let nonnative_bytes = nonnative_bits_le
87 .chunks(8)
88 .map(|bits| {
89 let mut byte = 0u8;
90 for (i, &bit) in bits.into_iter().enumerate() {
91 if bit {
92 byte += 1 << i;
93 }
94 }
95 byte
96 })
97 .collect::<Vec<_>>();
98
99 output.push(F::from_le_bytes_mod_order(nonnative_bytes.as_slice()));
100 }
101
102 output
103}
104
105pub trait CryptographicSponge: Clone {
109 type Parameters;
111
112 fn new(params: &Self::Parameters) -> Self;
114
115 fn absorb(&mut self, input: &impl Absorb);
117
118 fn squeeze_bytes(&mut self, num_bytes: usize) -> Vec<u8>;
120
121 fn squeeze_bits(&mut self, num_bits: usize) -> Vec<bool>;
123
124 fn squeeze_field_elements_with_sizes<F: PrimeField>(
135 &mut self,
136 sizes: &[FieldElementSize],
137 ) -> Vec<F> {
138 squeeze_field_elements_with_sizes_default_impl(self, sizes)
139 }
140
141 fn squeeze_field_elements<F: PrimeField>(&mut self, num_elements: usize) -> Vec<F> {
146 self.squeeze_field_elements_with_sizes::<F>(
147 vec![FieldElementSize::Full; num_elements].as_slice(),
148 )
149 }
150
151 fn fork(&self, domain: &[u8]) -> Self {
153 let mut new_sponge = self.clone();
154
155 let mut input = Absorb::to_sponge_bytes_as_vec(&domain.len());
156 input.extend_from_slice(domain);
157 new_sponge.absorb(&input);
158
159 new_sponge
160 }
161}
162
163pub trait FieldBasedCryptographicSponge<CF: PrimeField>: CryptographicSponge {
166 fn squeeze_native_field_elements(&mut self, num_elements: usize) -> Vec<CF>;
168
169 fn squeeze_native_field_elements_with_sizes(&mut self, sizes: &[FieldElementSize]) -> Vec<CF> {
172 let mut all_full_sizes = true;
173 for size in sizes {
174 if *size != FieldElementSize::Full {
175 all_full_sizes = false;
176 break;
177 }
178 }
179
180 if all_full_sizes {
181 self.squeeze_native_field_elements(sizes.len())
182 } else {
183 squeeze_field_elements_with_sizes_default_impl(self, sizes)
184 }
185 }
186}
187
188pub trait SpongeExt: CryptographicSponge {
192 type State: Clone;
194 fn from_state(state: Self::State, params: &Self::Parameters) -> Self;
196 fn into_state(self) -> Self::State;
198}
199
200#[derive(Clone, Debug)]
202pub enum DuplexSpongeMode {
203 Absorbing {
205 next_absorb_index: usize,
207 },
208 Squeezing {
210 next_squeeze_index: usize,
212 },
213}