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