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