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