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