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