ark-r1cs-std/crypto-primitives/src/commitment/pedersen/mod.rs
crypto-primitives/src/commitment/pedersen/mod.rsRaw
1use crate::{Error, Vec};
2use algebra_core::{
3 bytes::ToBytes,
4 io::{Result as IoResult, Write},
5 BitIterator, Field, FpParameters, PrimeField, ProjectiveCurve, ToConstraintField, UniformRand,
6};
7
8use core::marker::PhantomData;
9use rand::Rng;
10
11use super::CommitmentScheme;
12
13pub use crate::crh::pedersen::Window;
14use crate::crh::{pedersen, FixedLengthCRH};
15
16#[cfg(feature = "r1cs")]
17pub mod constraints;
18
19#[derive(Clone)]
20pub struct Parameters<C: ProjectiveCurve> {
21 pub randomness_generator: Vec<C>,
22 pub generators: Vec<Vec<C>>,
23}
24
25pub struct Commitment<C: ProjectiveCurve, W: Window> {
26 group: PhantomData<C>,
27 window: PhantomData<W>,
28}
29
30#[derive(Derivative)]
31#[derivative(Clone, PartialEq, Debug, Eq, Default)]
32pub struct Randomness<C: ProjectiveCurve>(pub C::ScalarField);
33
34impl<C: ProjectiveCurve> UniformRand for Randomness<C> {
35 #[inline]
36 fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
37 Randomness(UniformRand::rand(rng))
38 }
39}
40
41impl<C: ProjectiveCurve> ToBytes for Randomness<C> {
42 fn write<W: Write>(&self, writer: W) -> IoResult<()> {
43 self.0.write(writer)
44 }
45}
46
47impl<C: ProjectiveCurve, W: Window> CommitmentScheme for Commitment<C, W> {
48 type Parameters = Parameters<C>;
49 type Randomness = Randomness<C>;
50 type Output = C::Affine;
51
52 fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
53 let time = start_timer!(|| format!(
54 "PedersenCOMM::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> C",
55 W::NUM_WINDOWS,
56 W::WINDOW_SIZE,
57 W::NUM_WINDOWS * W::WINDOW_SIZE
58 ));
59 let num_powers = <C::ScalarField as PrimeField>::Params::MODULUS_BITS as usize;
60 let randomness_generator = pedersen::CRH::<C, W>::generator_powers(num_powers, rng);
61 let generators = pedersen::CRH::<C, W>::create_generators(rng);
62 end_timer!(time);
63
64 Ok(Self::Parameters {
65 randomness_generator,
66 generators,
67 })
68 }
69
70 fn commit(
71 parameters: &Self::Parameters,
72 input: &[u8],
73 randomness: &Self::Randomness,
74 ) -> Result<Self::Output, Error> {
75 let commit_time = start_timer!(|| "PedersenCOMM::Commit");
76 // If the input is too long, return an error.
77 if input.len() > W::WINDOW_SIZE * W::NUM_WINDOWS {
78 panic!("incorrect input length: {:?}", input.len());
79 }
80 // Pad the input to the necessary length.
81 let mut padded_input = Vec::with_capacity(input.len());
82 let mut input = input;
83 if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS {
84 let current_length = input.len();
85 padded_input.extend_from_slice(input);
86 for _ in current_length..((W::WINDOW_SIZE * W::NUM_WINDOWS) / 8) {
87 padded_input.push(0u8);
88 }
89 input = padded_input.as_slice();
90 }
91 assert_eq!(parameters.generators.len(), W::NUM_WINDOWS);
92
93 // Invoke Pedersen CRH here, to prevent code duplication.
94
95 let crh_parameters = pedersen::Parameters {
96 generators: parameters.generators.clone(),
97 };
98 let mut result: C = pedersen::CRH::<C, W>::evaluate(&crh_parameters, &input)?.into();
99 let randomize_time = start_timer!(|| "Randomize");
100
101 // Compute h^r.
102 let mut scalar_bits = BitIterator::new(randomness.0.into_repr()).collect::<Vec<_>>();
103 scalar_bits.reverse();
104 for (bit, power) in scalar_bits
105 .into_iter()
106 .zip(¶meters.randomness_generator)
107 {
108 if bit {
109 result += power
110 }
111 }
112 end_timer!(randomize_time);
113 end_timer!(commit_time);
114
115 Ok(result.into())
116 }
117}
118
119impl<ConstraintF: Field, C: ProjectiveCurve + ToConstraintField<ConstraintF>>
120 ToConstraintField<ConstraintF> for Parameters<C>
121{
122 #[inline]
123 fn to_field_elements(&self) -> Result<Vec<ConstraintF>, Error> {
124 Ok(Vec::new())
125 }
126}