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::{
  3    bytes::ToBytes, groups::Group, BitIterator, Field, FpParameters, PrimeField, ToConstraintField,
  4    UniformRand,
  5};
  6
  7use rand::Rng;
  8use std::marker::PhantomData;
  9
 10use super::CommitmentScheme;
 11use std::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(&parameters.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}