ark-r1cs-std/crypto-primitives/src/crh/pedersen/mod.rs
crypto-primitives/src/crh/pedersen/mod.rsRaw
1use crate::{Error, Vec};
2use core::{
3 fmt::{Debug, Formatter, Result as FmtResult},
4 marker::PhantomData,
5};
6use rand::Rng;
7#[cfg(feature = "parallel")]
8use rayon::prelude::*;
9
10use crate::crh::FixedLengthCRH;
11use algebra_core::{Field, ProjectiveCurve, ToConstraintField};
12use ff_fft::cfg_chunks;
13
14#[cfg(feature = "r1cs")]
15pub mod constraints;
16
17pub trait Window: Clone {
18 const WINDOW_SIZE: usize;
19 const NUM_WINDOWS: usize;
20}
21
22#[derive(Clone, Default)]
23pub struct Parameters<C: ProjectiveCurve> {
24 pub generators: Vec<Vec<C>>,
25}
26
27pub struct CRH<C: ProjectiveCurve, W: Window> {
28 group: PhantomData<C>,
29 window: PhantomData<W>,
30}
31
32impl<C: ProjectiveCurve, W: Window> CRH<C, W> {
33 pub fn create_generators<R: Rng>(rng: &mut R) -> Vec<Vec<C>> {
34 let mut generators_powers = Vec::new();
35 for _ in 0..W::NUM_WINDOWS {
36 generators_powers.push(Self::generator_powers(W::WINDOW_SIZE, rng));
37 }
38 generators_powers
39 }
40
41 pub fn generator_powers<R: Rng>(num_powers: usize, rng: &mut R) -> Vec<C> {
42 let mut cur_gen_powers = Vec::with_capacity(num_powers);
43 let mut base = C::rand(rng);
44 for _ in 0..num_powers {
45 cur_gen_powers.push(base);
46 base.double_in_place();
47 }
48 cur_gen_powers
49 }
50}
51
52impl<C: ProjectiveCurve, W: Window> FixedLengthCRH for CRH<C, W> {
53 const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS;
54 type Output = C::Affine;
55 type Parameters = Parameters<C>;
56
57 fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
58 let time = start_timer!(|| format!(
59 "PedersenCRH::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> C",
60 W::NUM_WINDOWS,
61 W::WINDOW_SIZE,
62 W::NUM_WINDOWS * W::WINDOW_SIZE
63 ));
64 let generators = Self::create_generators(rng);
65 end_timer!(time);
66 Ok(Self::Parameters { generators })
67 }
68
69 fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result<Self::Output, Error> {
70 let eval_time = start_timer!(|| "PedersenCRH::Eval");
71
72 if (input.len() * 8) > W::WINDOW_SIZE * W::NUM_WINDOWS {
73 panic!(
74 "incorrect input length {:?} for window params {:?}✕{:?}",
75 input.len(),
76 W::WINDOW_SIZE,
77 W::NUM_WINDOWS
78 );
79 }
80
81 let mut padded_input = Vec::with_capacity(input.len());
82 let mut input = input;
83 // Pad the input if it is not the current length.
84 if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS {
85 let current_length = input.len();
86 padded_input.extend_from_slice(input);
87 for _ in current_length..((W::WINDOW_SIZE * W::NUM_WINDOWS) / 8) {
88 padded_input.push(0u8);
89 }
90 input = padded_input.as_slice();
91 }
92
93 assert_eq!(
94 parameters.generators.len(),
95 W::NUM_WINDOWS,
96 "Incorrect pp of size {:?}✕{:?} for window params {:?}✕{:?}",
97 parameters.generators[0].len(),
98 parameters.generators.len(),
99 W::WINDOW_SIZE,
100 W::NUM_WINDOWS
101 );
102
103 // Compute sum of h_i^{m_i} for all i.
104 let bits = bytes_to_bits(input);
105 let result = cfg_chunks!(bits, W::WINDOW_SIZE)
106 .zip(¶meters.generators)
107 .map(|(bits, generator_powers)| {
108 let mut encoded = C::zero();
109 for (bit, base) in bits.iter().zip(generator_powers.iter()) {
110 if *bit {
111 encoded += base;
112 }
113 }
114 encoded
115 })
116 .sum::<C>();
117
118 end_timer!(eval_time);
119
120 Ok(result.into())
121 }
122}
123
124pub fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
125 let mut bits = Vec::with_capacity(bytes.len() * 8);
126 for byte in bytes {
127 for i in 0..8 {
128 let bit = (*byte >> i) & 1;
129 bits.push(bit == 1)
130 }
131 }
132 bits
133}
134
135impl<C: ProjectiveCurve> Debug for Parameters<C> {
136 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
137 write!(f, "Pedersen Hash Parameters {{\n")?;
138 for (i, g) in self.generators.iter().enumerate() {
139 write!(f, "\t Generator {}: {:?}\n", i, g)?;
140 }
141 write!(f, "}}\n")
142 }
143}
144
145impl<ConstraintF: Field, C: ProjectiveCurve + ToConstraintField<ConstraintF>>
146 ToConstraintField<ConstraintF> for Parameters<C>
147{
148 #[inline]
149 fn to_field_elements(&self) -> Result<Vec<ConstraintF>, Error> {
150 Ok(Vec::new())
151 }
152}