mmr_crypto_primitives/crh/pedersen/
mod.rs1use crate::{Error, Vec};
2use ark_std::rand::Rng;
3use ark_std::{
4 fmt::{Debug, Formatter, Result as FmtResult},
5 marker::PhantomData,
6};
7#[cfg(feature = "parallel")]
8use rayon::prelude::*;
9
10use crate::crh::{CRHScheme, TwoToOneCRHScheme};
11use ark_ec::ProjectiveCurve;
12use ark_ff::{Field, ToConstraintField};
13use ark_serialize::CanonicalSerialize;
14use ark_std::borrow::Borrow;
15use ark_std::cfg_chunks;
16
17use super::MMRTwoToOneCRHScheme;
18
19#[cfg(feature = "r1cs")]
20pub mod constraints;
21
22pub trait Window: Clone {
23 const WINDOW_SIZE: usize;
24 const NUM_WINDOWS: usize;
25}
26
27#[derive(Clone, Default)]
28pub struct Parameters<C: ProjectiveCurve> {
29 pub generators: Vec<Vec<C>>,
30}
31
32pub struct CRH<C: ProjectiveCurve, W: Window> {
33 group: PhantomData<C>,
34 window: PhantomData<W>,
35}
36
37impl<C: ProjectiveCurve, W: Window> CRH<C, W> {
38 pub(crate) const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS;
39 pub fn create_generators<R: Rng>(rng: &mut R) -> Vec<Vec<C>> {
40 let mut generators_powers = Vec::new();
41 for _ in 0..W::NUM_WINDOWS {
42 generators_powers.push(Self::generator_powers(W::WINDOW_SIZE, rng));
43 }
44 generators_powers
45 }
46
47 pub fn generator_powers<R: Rng>(num_powers: usize, rng: &mut R) -> Vec<C> {
48 let mut cur_gen_powers = Vec::with_capacity(num_powers);
49 let mut base = C::rand(rng);
50 for _ in 0..num_powers {
51 cur_gen_powers.push(base);
52 base.double_in_place();
53 }
54 cur_gen_powers
55 }
56}
57
58impl<C: ProjectiveCurve, W: Window> CRHScheme for CRH<C, W> {
59 type Input = [u8];
60 type Output = C::Affine;
61 type Parameters = Parameters<C>;
62
63 fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
64 let time = start_timer!(|| format!(
65 "PedersenCRH::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> C",
66 W::NUM_WINDOWS,
67 W::WINDOW_SIZE,
68 W::NUM_WINDOWS * W::WINDOW_SIZE
69 ));
70 let generators = Self::create_generators(rng);
71 end_timer!(time);
72 Ok(Self::Parameters { generators })
73 }
74
75 fn evaluate<T: Borrow<Self::Input>>(
76 parameters: &Self::Parameters,
77 input: T,
78 ) -> Result<Self::Output, Error> {
79 let eval_time = start_timer!(|| "PedersenCRH::Eval");
80 let input = input.borrow();
81 if (input.len() * 8) > W::WINDOW_SIZE * W::NUM_WINDOWS {
82 panic!(
83 "incorrect input length {:?} for window params {:?}✕{:?}",
84 input.len(),
85 W::WINDOW_SIZE,
86 W::NUM_WINDOWS
87 );
88 }
89
90 let mut padded_input = Vec::with_capacity(input.len());
91 let mut input = input;
92 if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS {
94 padded_input.extend_from_slice(input);
95 let padded_length = (W::WINDOW_SIZE * W::NUM_WINDOWS) / 8;
96 padded_input.resize(padded_length, 0u8);
97 input = padded_input.as_slice();
98 }
99
100 assert_eq!(
101 parameters.generators.len(),
102 W::NUM_WINDOWS,
103 "Incorrect pp of size {:?}✕{:?} for window params {:?}✕{:?}",
104 parameters.generators[0].len(),
105 parameters.generators.len(),
106 W::WINDOW_SIZE,
107 W::NUM_WINDOWS
108 );
109
110 let bits = bytes_to_bits(input);
112 let result = cfg_chunks!(bits, W::WINDOW_SIZE)
113 .zip(¶meters.generators)
114 .map(|(bits, generator_powers)| {
115 let mut encoded = C::zero();
116 for (bit, base) in bits.iter().zip(generator_powers.iter()) {
117 if *bit {
118 encoded += base;
119 }
120 }
121 encoded
122 })
123 .sum::<C>();
124
125 end_timer!(eval_time);
126
127 Ok(result.into())
128 }
129}
130
131pub struct TwoToOneCRH<C: ProjectiveCurve, W: Window> {
132 group: PhantomData<C>,
133 window: PhantomData<W>,
134}
135
136impl<C: ProjectiveCurve, W: Window> TwoToOneCRH<C, W> {
137 pub(crate) const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS;
138 const HALF_INPUT_SIZE_BITS: usize = Self::INPUT_SIZE_BITS / 2;
139 pub fn create_generators<R: Rng>(rng: &mut R) -> Vec<Vec<C>> {
140 CRH::<C, W>::create_generators(rng)
141 }
142
143 pub fn generator_powers<R: Rng>(num_powers: usize, rng: &mut R) -> Vec<C> {
144 CRH::<C, W>::generator_powers(num_powers, rng)
145 }
146}
147
148impl<C: ProjectiveCurve, W: Window> TwoToOneCRHScheme for TwoToOneCRH<C, W> {
149 type Input = [u8];
150 type Output = C::Affine;
151 type Parameters = Parameters<C>;
152
153 fn setup<R: Rng>(r: &mut R) -> Result<Self::Parameters, Error> {
154 CRH::<C, W>::setup(r)
155 }
156
157 fn evaluate<T: Borrow<Self::Input>>(
158 parameters: &Self::Parameters,
159 left_input: T,
160 right_input: T,
161 ) -> Result<Self::Output, Error> {
162 let left_input = left_input.borrow();
163 let right_input = right_input.borrow();
164 assert_eq!(
165 left_input.len(),
166 right_input.len(),
167 "left and right input should be of equal length"
168 );
169 debug_assert!(left_input.len() * 8 <= Self::HALF_INPUT_SIZE_BITS);
172
173 let mut buffer = vec![0u8; (Self::HALF_INPUT_SIZE_BITS + Self::HALF_INPUT_SIZE_BITS) / 8];
174
175 buffer
176 .iter_mut()
177 .zip(left_input.iter().chain(right_input.iter()))
178 .for_each(|(b, l_b)| *b = *l_b);
179
180 CRH::<C, W>::evaluate(parameters, buffer.as_slice())
181 }
182
183 fn compress<T: Borrow<Self::Output>>(
187 parameters: &Self::Parameters,
188 left_input: T,
189 right_input: T,
190 ) -> Result<Self::Output, Error> {
191 <Self as TwoToOneCRHScheme>::evaluate(
192 parameters,
193 crate::to_unchecked_bytes!(left_input)?,
194 crate::to_unchecked_bytes!(right_input)?,
195 )
196 }
197}
198
199pub fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
200 let mut bits = Vec::with_capacity(bytes.len() * 8);
201 for byte in bytes {
202 for i in 0..8 {
203 let bit = (*byte >> i) & 1;
204 bits.push(bit == 1)
205 }
206 }
207 bits
208}
209
210
211impl<C: ProjectiveCurve, W: Window> MMRTwoToOneCRHScheme for TwoToOneCRH<C, W> {
212 type Input = [u8];
213 type Output = C::Affine;
214 type Parameters = Parameters<C>;
215
216 fn setup<R: Rng>(r: &mut R) -> Result<Self::Parameters, Error> {
217 CRH::<C, W>::setup(r)
218 }
219
220 fn evaluate<T: Borrow<Self::Input>>(
221 parameters: &Self::Parameters,
222 left_input: T,
223 right_input: T,
224 ) -> Result<Self::Output, Error> {
225 let left_input = left_input.borrow();
226 let right_input = right_input.borrow();
227 assert_eq!(
228 left_input.len(),
229 right_input.len(),
230 "left and right input should be of equal length"
231 );
232 debug_assert!(left_input.len() * 8 <= Self::HALF_INPUT_SIZE_BITS);
235
236 let mut buffer = vec![0u8; (Self::HALF_INPUT_SIZE_BITS + Self::HALF_INPUT_SIZE_BITS) / 8];
237
238 buffer
239 .iter_mut()
240 .zip(left_input.iter().chain(right_input.iter()))
241 .for_each(|(b, l_b)| *b = *l_b);
242
243 CRH::<C, W>::evaluate(parameters, buffer.as_slice())
244 }
245
246 fn compress<T: Borrow<Self::Output>>(
250 parameters: &Self::Parameters,
251 left_input: T,
252 right_input: T,
253 ) -> Result<Self::Output, Error> {
254 <Self as MMRTwoToOneCRHScheme>::evaluate(
255 parameters,
256 crate::to_unchecked_bytes!(left_input)?,
257 crate::to_unchecked_bytes!(right_input)?,
258 )
259 }
260
261 fn left_compress(
262 parameters: &Self::Parameters,
263 left_input: &Self::Output,
264 right_input:&Self::Input,
265 ) -> Result<Self::Output, Error> {
266 <Self as MMRTwoToOneCRHScheme>::evaluate(
267 parameters,
268 crate::to_unchecked_bytes!(left_input)?,
269 right_input.to_vec(),
270 )
271 }
272
273 fn right_compress(
274 parameters: &Self::Parameters,
275 left_input: &Self::Input,
276 right_input: &Self::Output
277 ) -> Result<Self::Output, Error> {
278 <Self as MMRTwoToOneCRHScheme>::evaluate(
279 parameters,
280 left_input,
281 &crate::to_unchecked_bytes!(right_input)?,
282 )
283 }
284}
285
286
287impl<C: ProjectiveCurve> Debug for Parameters<C> {
288 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
289 writeln!(f, "Pedersen Hash Parameters {{")?;
290 for (i, g) in self.generators.iter().enumerate() {
291 writeln!(f, "\t Generator {}: {:?}", i, g)?;
292 }
293 writeln!(f, "}}")
294 }
295}
296
297impl<ConstraintF: Field, C: ProjectiveCurve + ToConstraintField<ConstraintF>>
298 ToConstraintField<ConstraintF> for Parameters<C>
299{
300 #[inline]
301 fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
302 Some(Vec::new())
303 }
304}