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