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    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(&parameters.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}