arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
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(&parameters.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}