You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

136 lines
4.1 KiB

use crate::{Error, Vec};
use algebra_core::{
bytes::ToBytes,
groups::Group,
io::{Result as IoResult, Write},
BitIterator, Field, FpParameters, PrimeField, ToConstraintField, UniformRand,
};
use core::marker::PhantomData;
use rand::Rng;
use super::CommitmentScheme;
pub use crate::crh::pedersen::PedersenWindow;
use crate::crh::{
pedersen::{PedersenCRH, PedersenParameters as PedersenCRHParameters},
FixedLengthCRH,
};
#[cfg(feature = "r1cs")]
pub mod constraints;
#[derive(Clone)]
pub struct PedersenParameters<G: Group> {
pub randomness_generator: Vec<G>,
pub generators: Vec<Vec<G>>,
}
pub struct PedersenCommitment<G: Group, W: PedersenWindow> {
group: PhantomData<G>,
window: PhantomData<W>,
}
#[derive(Derivative)]
#[derivative(
Clone(bound = "G: Group"),
PartialEq(bound = "G: Group"),
Debug(bound = "G: Group"),
Eq(bound = "G: Group"),
Default(bound = "G: Group")
)]
pub struct PedersenRandomness<G: Group>(pub G::ScalarField);
impl<G: Group> UniformRand for PedersenRandomness<G> {
#[inline]
fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
PedersenRandomness(UniformRand::rand(rng))
}
}
impl<G: Group> ToBytes for PedersenRandomness<G> {
fn write<W: Write>(&self, writer: W) -> IoResult<()> {
self.0.write(writer)
}
}
impl<G: Group, W: PedersenWindow> CommitmentScheme for PedersenCommitment<G, W> {
type Parameters = PedersenParameters<G>;
type Randomness = PedersenRandomness<G>;
type Output = G;
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
let time = start_timer!(|| format!(
"PedersenCOMM::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> G",
W::NUM_WINDOWS,
W::WINDOW_SIZE,
W::NUM_WINDOWS * W::WINDOW_SIZE
));
let num_powers = <G::ScalarField as PrimeField>::Params::MODULUS_BITS as usize;
let randomness_generator = PedersenCRH::<_, W>::generator_powers(num_powers, rng);
let generators = PedersenCRH::<_, W>::create_generators(rng);
end_timer!(time);
Ok(Self::Parameters {
randomness_generator,
generators,
})
}
fn commit(
parameters: &Self::Parameters,
input: &[u8],
randomness: &Self::Randomness,
) -> Result<Self::Output, Error> {
let commit_time = start_timer!(|| "PedersenCOMM::Commit");
// If the input is too long, return an error.
if input.len() > W::WINDOW_SIZE * W::NUM_WINDOWS {
panic!("incorrect input length: {:?}", input.len());
}
// Pad the input to the necessary length.
let mut padded_input = Vec::with_capacity(input.len());
let mut input = input;
if (input.len() * 8) < W::WINDOW_SIZE * W::NUM_WINDOWS {
let current_length = input.len();
padded_input.extend_from_slice(input);
for _ in current_length..((W::WINDOW_SIZE * W::NUM_WINDOWS) / 8) {
padded_input.push(0u8);
}
input = padded_input.as_slice();
}
assert_eq!(parameters.generators.len(), W::NUM_WINDOWS);
// Invoke Pedersen CRH here, to prevent code duplication.
let crh_parameters = PedersenCRHParameters {
generators: parameters.generators.clone(),
};
let mut result = PedersenCRH::<_, W>::evaluate(&crh_parameters, &input)?;
let randomize_time = start_timer!(|| "Randomize");
// Compute h^r.
let mut scalar_bits = BitIterator::new(randomness.0.into_repr()).collect::<Vec<_>>();
scalar_bits.reverse();
for (bit, power) in scalar_bits
.into_iter()
.zip(&parameters.randomness_generator)
{
if bit {
result += power
}
}
end_timer!(randomize_time);
end_timer!(commit_time);
Ok(result)
}
}
impl<ConstraintF: Field, G: Group + ToConstraintField<ConstraintF>> ToConstraintField<ConstraintF>
for PedersenParameters<G>
{
#[inline]
fn to_field_elements(&self) -> Result<Vec<ConstraintF>, Error> {
Ok(Vec::new())
}
}