mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-12 00:41:32 +01:00
Initial commit to extract crypto-primitives to new crate
This commit is contained in:
25
crypto-primitives/src/crh/constraints.rs
Normal file
25
crypto-primitives/src/crh/constraints.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use algebra::Field;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::crh::FixedLengthCRH;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
use r1cs_std::prelude::*;
|
||||
|
||||
pub trait FixedLengthCRHGadget<H: FixedLengthCRH, ConstraintF: Field>: Sized {
|
||||
type OutputGadget: ConditionalEqGadget<ConstraintF>
|
||||
+ EqGadget<ConstraintF>
|
||||
+ ToBytesGadget<ConstraintF>
|
||||
+ CondSelectGadget<ConstraintF>
|
||||
+ AllocGadget<H::Output, ConstraintF>
|
||||
+ Debug
|
||||
+ Clone
|
||||
+ Sized;
|
||||
type ParametersGadget: AllocGadget<H::Parameters, ConstraintF> + Clone;
|
||||
|
||||
fn check_evaluation_gadget<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
parameters: &Self::ParametersGadget,
|
||||
input: &[UInt8],
|
||||
) -> Result<Self::OutputGadget, SynthesisError>;
|
||||
}
|
||||
115
crypto-primitives/src/crh/injective_map/constraints.rs
Normal file
115
crypto-primitives/src/crh/injective_map/constraints.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
use std::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
use crate::crh::{
|
||||
FixedLengthCRHGadget,
|
||||
injective_map::{InjectiveMap, PedersenCRHCompressor, TECompressor},
|
||||
pedersen::{
|
||||
PedersenWindow,
|
||||
constraints::{PedersenCRHGadget, PedersenCRHGadgetParameters},
|
||||
}
|
||||
};
|
||||
|
||||
use algebra::{
|
||||
curves::{
|
||||
models::{ModelParameters, TEModelParameters},
|
||||
twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective},
|
||||
},
|
||||
fields::{Field, PrimeField, SquareRootField},
|
||||
groups::Group,
|
||||
};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use r1cs_std::{
|
||||
fields::fp::FpGadget,
|
||||
groups::{curves::twisted_edwards::AffineGadget as TwistedEdwardsGadget, GroupGadget},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
pub trait InjectiveMapGadget<G: Group, I: InjectiveMap<G>, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>>
|
||||
{
|
||||
type OutputGadget: EqGadget<ConstraintF>
|
||||
+ ToBytesGadget<ConstraintF>
|
||||
+ CondSelectGadget<ConstraintF>
|
||||
+ AllocGadget<I::Output, ConstraintF>
|
||||
+ Debug
|
||||
+ Clone
|
||||
+ Sized;
|
||||
|
||||
fn evaluate_map<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
ge: &GG,
|
||||
) -> Result<Self::OutputGadget, SynthesisError>;
|
||||
}
|
||||
|
||||
pub struct TECompressorGadget;
|
||||
|
||||
impl<ConstraintF, P> InjectiveMapGadget<TEAffine<P>, TECompressor, ConstraintF, TwistedEdwardsGadget<P, ConstraintF, FpGadget<ConstraintF>>>
|
||||
for TECompressorGadget
|
||||
where
|
||||
ConstraintF: PrimeField + SquareRootField,
|
||||
P: TEModelParameters + ModelParameters<BaseField = ConstraintF>,
|
||||
{
|
||||
type OutputGadget = FpGadget<ConstraintF>;
|
||||
|
||||
fn evaluate_map<CS: ConstraintSystem<ConstraintF>>(
|
||||
_cs: CS,
|
||||
ge: &TwistedEdwardsGadget<P, ConstraintF, FpGadget<ConstraintF>>,
|
||||
) -> Result<Self::OutputGadget, SynthesisError> {
|
||||
Ok(ge.x.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<ConstraintF, P>
|
||||
InjectiveMapGadget<TEProjective<P>, TECompressor, ConstraintF, TwistedEdwardsGadget<P, ConstraintF, FpGadget<ConstraintF>>>
|
||||
for TECompressorGadget
|
||||
where
|
||||
ConstraintF: PrimeField + SquareRootField,
|
||||
P: TEModelParameters + ModelParameters<BaseField = ConstraintF>,
|
||||
{
|
||||
type OutputGadget = FpGadget<ConstraintF>;
|
||||
|
||||
fn evaluate_map<CS: ConstraintSystem<ConstraintF>>(
|
||||
_cs: CS,
|
||||
ge: &TwistedEdwardsGadget<P, ConstraintF, FpGadget<ConstraintF>>,
|
||||
) -> Result<Self::OutputGadget, SynthesisError> {
|
||||
Ok(ge.x.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PedersenCRHCompressorGadget<
|
||||
G: Group,
|
||||
I: InjectiveMap<G>,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
IG: InjectiveMapGadget<G, I, ConstraintF, GG>,
|
||||
> {
|
||||
_compressor: PhantomData<I>,
|
||||
_compressor_gadget: PhantomData<IG>,
|
||||
_crh: PedersenCRHGadget<G, ConstraintF, GG>,
|
||||
}
|
||||
|
||||
impl<G, I, ConstraintF, GG, IG, W> FixedLengthCRHGadget<PedersenCRHCompressor<G, I, W>, ConstraintF>
|
||||
for PedersenCRHCompressorGadget<G, I, ConstraintF, GG, IG>
|
||||
where
|
||||
G: Group,
|
||||
I: InjectiveMap<G>,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
IG: InjectiveMapGadget<G, I, ConstraintF, GG>,
|
||||
W: PedersenWindow,
|
||||
{
|
||||
type OutputGadget = IG::OutputGadget;
|
||||
type ParametersGadget = PedersenCRHGadgetParameters<G, W, ConstraintF, GG>;
|
||||
|
||||
fn check_evaluation_gadget<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
parameters: &Self::ParametersGadget,
|
||||
input: &[UInt8],
|
||||
) -> Result<Self::OutputGadget, SynthesisError> {
|
||||
let result = PedersenCRHGadget::<G, ConstraintF, GG>::check_evaluation_gadget(
|
||||
cs.ns(|| "PedCRH"),
|
||||
parameters,
|
||||
input,
|
||||
)?;
|
||||
IG::evaluate_map(cs.ns(|| "InjectiveMap"), &result)
|
||||
}
|
||||
}
|
||||
76
crypto-primitives/src/crh/injective_map/mod.rs
Normal file
76
crypto-primitives/src/crh/injective_map/mod.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use crate::CryptoError;
|
||||
use algebra::bytes::ToBytes;
|
||||
use crate::Error;
|
||||
use rand::Rng;
|
||||
use std::{fmt::Debug, hash::Hash, marker::PhantomData};
|
||||
|
||||
use super::{
|
||||
pedersen::{PedersenCRH, PedersenParameters, PedersenWindow},
|
||||
FixedLengthCRH,
|
||||
};
|
||||
use algebra::{
|
||||
curves::{
|
||||
models::{ModelParameters, TEModelParameters},
|
||||
twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective},
|
||||
ProjectiveCurve,
|
||||
},
|
||||
groups::Group,
|
||||
};
|
||||
|
||||
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub mod constraints;
|
||||
|
||||
pub trait InjectiveMap<G: Group> {
|
||||
type Output: ToBytes + Clone + Eq + Hash + Default + Debug;
|
||||
fn injective_map(ge: &G) -> Result<Self::Output, CryptoError>;
|
||||
}
|
||||
|
||||
pub struct TECompressor;
|
||||
|
||||
impl<P: TEModelParameters> InjectiveMap<TEAffine<P>> for TECompressor {
|
||||
type Output = <P as ModelParameters>::BaseField;
|
||||
|
||||
fn injective_map(ge: &TEAffine<P>) -> Result<Self::Output, CryptoError> {
|
||||
debug_assert!(ge.is_in_correct_subgroup_assuming_on_curve());
|
||||
Ok(ge.x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: TEModelParameters> InjectiveMap<TEProjective<P>> for TECompressor {
|
||||
type Output = <P as ModelParameters>::BaseField;
|
||||
|
||||
fn injective_map(ge: &TEProjective<P>) -> Result<Self::Output, CryptoError> {
|
||||
let ge = ge.into_affine();
|
||||
debug_assert!(ge.is_in_correct_subgroup_assuming_on_curve());
|
||||
Ok(ge.x)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PedersenCRHCompressor<G: Group, I: InjectiveMap<G>, W: PedersenWindow> {
|
||||
_group: PhantomData<G>,
|
||||
_compressor: PhantomData<I>,
|
||||
_crh: PedersenCRH<G, W>,
|
||||
}
|
||||
|
||||
impl<G: Group, I: InjectiveMap<G>, W: PedersenWindow> FixedLengthCRH
|
||||
for PedersenCRHCompressor<G, I, W>
|
||||
{
|
||||
const INPUT_SIZE_BITS: usize = PedersenCRH::<G, W>::INPUT_SIZE_BITS;
|
||||
type Output = I::Output;
|
||||
type Parameters = PedersenParameters<G>;
|
||||
|
||||
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
|
||||
let time = start_timer!(|| format!("PedersenCRHCompressor::Setup"));
|
||||
let params = PedersenCRH::<G, W>::setup(rng);
|
||||
end_timer!(time);
|
||||
params
|
||||
}
|
||||
|
||||
fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result<Self::Output, Error> {
|
||||
let eval_time = start_timer!(|| "PedersenCRHCompressor::Eval");
|
||||
let result = I::injective_map(&PedersenCRH::<G, W>::evaluate(parameters, input)?)?;
|
||||
end_timer!(eval_time);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
24
crypto-primitives/src/crh/mod.rs
Normal file
24
crypto-primitives/src/crh/mod.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use algebra::bytes::ToBytes;
|
||||
use rand::Rng;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub mod injective_map;
|
||||
pub mod pedersen;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub mod constraints;
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub use constraints::*;
|
||||
|
||||
|
||||
pub trait FixedLengthCRH {
|
||||
const INPUT_SIZE_BITS: usize;
|
||||
type Output: ToBytes + Clone + Eq + Hash + Default;
|
||||
type Parameters: Clone + Default;
|
||||
|
||||
fn setup<R: Rng>(r: &mut R) -> Result<Self::Parameters, Error>;
|
||||
fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result<Self::Output, Error>;
|
||||
}
|
||||
193
crypto-primitives/src/crh/pedersen/constraints.rs
Normal file
193
crypto-primitives/src/crh/pedersen/constraints.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
use algebra::Field;
|
||||
|
||||
use crate::crh::{
|
||||
FixedLengthCRHGadget,
|
||||
pedersen::{PedersenCRH, PedersenParameters, PedersenWindow},
|
||||
};
|
||||
use algebra::groups::Group;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use r1cs_std::prelude::*;
|
||||
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(
|
||||
bound = "G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"
|
||||
))]
|
||||
pub struct PedersenCRHGadgetParameters<
|
||||
G: Group,
|
||||
W: PedersenWindow,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
> {
|
||||
params: PedersenParameters<G>,
|
||||
_group_g: PhantomData<GG>,
|
||||
_engine: PhantomData<ConstraintF>,
|
||||
_window: PhantomData<W>,
|
||||
}
|
||||
|
||||
pub struct PedersenCRHGadget<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
|
||||
#[doc(hideen)]
|
||||
_group: PhantomData<*const G>,
|
||||
#[doc(hideen)]
|
||||
_group_gadget: PhantomData<*const GG>,
|
||||
#[doc(hideen)]
|
||||
_engine: PhantomData<ConstraintF>,
|
||||
}
|
||||
|
||||
impl<ConstraintF, G, GG, W> FixedLengthCRHGadget<PedersenCRH<G, W>, ConstraintF> for PedersenCRHGadget<G, ConstraintF, GG>
|
||||
where
|
||||
ConstraintF: Field,
|
||||
G: Group,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
W: PedersenWindow,
|
||||
{
|
||||
type OutputGadget = GG;
|
||||
type ParametersGadget = PedersenCRHGadgetParameters<G, W, ConstraintF, GG>;
|
||||
|
||||
fn check_evaluation_gadget<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
parameters: &Self::ParametersGadget,
|
||||
input: &[UInt8],
|
||||
) -> Result<Self::OutputGadget, SynthesisError> {
|
||||
let mut padded_input = input.to_vec();
|
||||
// Pad the input if it is not the current length.
|
||||
if input.len() * 8 < W::WINDOW_SIZE * W::NUM_WINDOWS {
|
||||
let current_length = input.len();
|
||||
for _ in current_length..(W::WINDOW_SIZE * W::NUM_WINDOWS / 8) {
|
||||
padded_input.push(UInt8::constant(0u8));
|
||||
}
|
||||
}
|
||||
assert_eq!(padded_input.len() * 8, W::WINDOW_SIZE * W::NUM_WINDOWS);
|
||||
assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS);
|
||||
|
||||
// Allocate new variable for the result.
|
||||
let input_in_bits: Vec<_> = padded_input
|
||||
.iter()
|
||||
.flat_map(|byte| byte.into_bits_le())
|
||||
.collect();
|
||||
let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE);
|
||||
let result =
|
||||
GG::precomputed_base_multiscalar_mul(cs, ¶meters.params.generators, input_in_bits)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>>
|
||||
AllocGadget<PedersenParameters<G>, ConstraintF> for PedersenCRHGadgetParameters<G, W, ConstraintF, GG>
|
||||
{
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(_cs: CS, value_gen: F) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<PedersenParameters<G>>,
|
||||
{
|
||||
let params = value_gen()?.borrow().clone();
|
||||
Ok(PedersenCRHGadgetParameters {
|
||||
params,
|
||||
_group_g: PhantomData,
|
||||
_engine: PhantomData,
|
||||
_window: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
_cs: CS,
|
||||
value_gen: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<PedersenParameters<G>>,
|
||||
{
|
||||
let params = value_gen()?.borrow().clone();
|
||||
Ok(PedersenCRHGadgetParameters {
|
||||
params,
|
||||
_group_g: PhantomData,
|
||||
_engine: PhantomData,
|
||||
_window: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use algebra::fields::bls12_381::fr::Fr;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::crh::{
|
||||
pedersen::{PedersenCRH, PedersenWindow},
|
||||
pedersen::constraints::PedersenCRHGadget,
|
||||
FixedLengthCRH,
|
||||
FixedLengthCRHGadget
|
||||
};
|
||||
use algebra::curves::{jubjub::JubJubProjective as JubJub, ProjectiveCurve};
|
||||
use r1cs_core::ConstraintSystem;
|
||||
use r1cs_std::{
|
||||
groups::curves::twisted_edwards::jubjub::JubJubGadget,
|
||||
test_constraint_system::TestConstraintSystem, prelude::*,
|
||||
};
|
||||
|
||||
type TestCRH = PedersenCRH<JubJub, Window>;
|
||||
type TestCRHGadget = PedersenCRHGadget<JubJub, Fr, JubJubGadget>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub(super) struct Window;
|
||||
|
||||
impl PedersenWindow for Window {
|
||||
const WINDOW_SIZE: usize = 128;
|
||||
const NUM_WINDOWS: usize = 8;
|
||||
}
|
||||
|
||||
fn generate_input<CS: ConstraintSystem<Fr>, R: Rng>(
|
||||
mut cs: CS,
|
||||
rng: &mut R,
|
||||
) -> ([u8; 128], Vec<UInt8>) {
|
||||
let mut input = [1u8; 128];
|
||||
rng.fill_bytes(&mut input);
|
||||
|
||||
let mut input_bytes = vec![];
|
||||
for (byte_i, input_byte) in input.into_iter().enumerate() {
|
||||
let cs = cs.ns(|| format!("input_byte_gadget_{}", byte_i));
|
||||
input_bytes.push(UInt8::alloc(cs, || Ok(*input_byte)).unwrap());
|
||||
}
|
||||
(input, input_bytes)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crh_primitive_gadget_test() {
|
||||
let rng = &mut thread_rng();
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
|
||||
let (input, input_bytes) = generate_input(&mut cs, rng);
|
||||
println!("number of constraints for input: {}", cs.num_constraints());
|
||||
|
||||
let parameters = TestCRH::setup(rng).unwrap();
|
||||
let primitive_result = TestCRH::evaluate(¶meters, &input).unwrap();
|
||||
|
||||
let gadget_parameters =
|
||||
<TestCRHGadget as FixedLengthCRHGadget<TestCRH, Fr>>::ParametersGadget::alloc(
|
||||
&mut cs.ns(|| "gadget_parameters"),
|
||||
|| Ok(¶meters),
|
||||
)
|
||||
.unwrap();
|
||||
println!(
|
||||
"number of constraints for input + params: {}",
|
||||
cs.num_constraints()
|
||||
);
|
||||
|
||||
let gadget_result =
|
||||
<TestCRHGadget as FixedLengthCRHGadget<TestCRH, Fr>>::check_evaluation_gadget(
|
||||
&mut cs.ns(|| "gadget_evaluation"),
|
||||
&gadget_parameters,
|
||||
&input_bytes,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("number of constraints total: {}", cs.num_constraints());
|
||||
|
||||
let primitive_result = primitive_result.into_affine();
|
||||
assert_eq!(primitive_result.x, gadget_result.x.value.unwrap());
|
||||
assert_eq!(primitive_result.y, gadget_result.y.value.unwrap());
|
||||
assert!(cs.is_satisfied());
|
||||
}
|
||||
}
|
||||
141
crypto-primitives/src/crh/pedersen/mod.rs
Normal file
141
crypto-primitives/src/crh/pedersen/mod.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
use crate::Error;
|
||||
use rand::Rng;
|
||||
use rayon::prelude::*;
|
||||
use std::{
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use crate::crh::FixedLengthCRH;
|
||||
use algebra::groups::Group;
|
||||
|
||||
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub mod constraints;
|
||||
|
||||
pub trait PedersenWindow: Clone {
|
||||
const WINDOW_SIZE: usize;
|
||||
const NUM_WINDOWS: usize;
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct PedersenParameters<G: Group> {
|
||||
pub generators: Vec<Vec<G>>,
|
||||
}
|
||||
|
||||
pub struct PedersenCRH<G: Group, W: PedersenWindow> {
|
||||
group: PhantomData<G>,
|
||||
window: PhantomData<W>,
|
||||
}
|
||||
|
||||
impl<G: Group, W: PedersenWindow> PedersenCRH<G, W> {
|
||||
pub fn create_generators<R: Rng>(rng: &mut R) -> Vec<Vec<G>> {
|
||||
let mut generators_powers = Vec::new();
|
||||
for _ in 0..W::NUM_WINDOWS {
|
||||
generators_powers.push(Self::generator_powers(W::WINDOW_SIZE, rng));
|
||||
}
|
||||
generators_powers
|
||||
}
|
||||
|
||||
pub fn generator_powers<R: Rng>(num_powers: usize, rng: &mut R) -> Vec<G> {
|
||||
let mut cur_gen_powers = Vec::with_capacity(num_powers);
|
||||
let mut base = G::rand(rng);
|
||||
for _ in 0..num_powers {
|
||||
cur_gen_powers.push(base);
|
||||
base.double_in_place();
|
||||
}
|
||||
cur_gen_powers
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group, W: PedersenWindow> FixedLengthCRH for PedersenCRH<G, W> {
|
||||
const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS;
|
||||
type Output = G;
|
||||
type Parameters = PedersenParameters<G>;
|
||||
|
||||
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
|
||||
let time = start_timer!(|| format!(
|
||||
"PedersenCRH::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> G",
|
||||
W::NUM_WINDOWS,
|
||||
W::WINDOW_SIZE,
|
||||
W::NUM_WINDOWS * W::WINDOW_SIZE
|
||||
));
|
||||
let generators = Self::create_generators(rng);
|
||||
end_timer!(time);
|
||||
Ok(Self::Parameters { generators })
|
||||
}
|
||||
|
||||
fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result<Self::Output, Error> {
|
||||
let eval_time = start_timer!(|| "PedersenCRH::Eval");
|
||||
|
||||
if (input.len() * 8) > W::WINDOW_SIZE * W::NUM_WINDOWS {
|
||||
panic!(
|
||||
"incorrect input length {:?} for window params {:?}x{:?}",
|
||||
input.len(),
|
||||
W::WINDOW_SIZE,
|
||||
W::NUM_WINDOWS
|
||||
);
|
||||
}
|
||||
|
||||
let mut padded_input = Vec::with_capacity(input.len());
|
||||
let mut input = input;
|
||||
// Pad the input if it is not the current length.
|
||||
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,
|
||||
"Incorrect pp of size {:?}x{:?} for window params {:?}x{:?}",
|
||||
parameters.generators[0].len(),
|
||||
parameters.generators.len(),
|
||||
W::WINDOW_SIZE,
|
||||
W::NUM_WINDOWS
|
||||
);
|
||||
|
||||
// Compute sum of h_i^{m_i} for all i.
|
||||
let result = bytes_to_bits(input)
|
||||
.par_chunks(W::WINDOW_SIZE)
|
||||
.zip(¶meters.generators)
|
||||
.map(|(bits, generator_powers)| {
|
||||
let mut encoded = G::zero();
|
||||
for (bit, base) in bits.iter().zip(generator_powers.iter()) {
|
||||
if *bit {
|
||||
encoded = encoded + base;
|
||||
}
|
||||
}
|
||||
encoded
|
||||
})
|
||||
.reduce(|| G::zero(), |a, b| a + &b);
|
||||
end_timer!(eval_time);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
|
||||
let mut bits = Vec::with_capacity(bytes.len() * 8);
|
||||
for byte in bytes {
|
||||
for i in 0..8 {
|
||||
let bit = (*byte >> i) & 1;
|
||||
bits.push(bit == 1)
|
||||
}
|
||||
}
|
||||
bits
|
||||
}
|
||||
|
||||
impl<G: Group> Debug for PedersenParameters<G> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "Pedersen Hash Parameters {{\n")?;
|
||||
for (i, g) in self.generators.iter().enumerate() {
|
||||
write!(f, "\t Generator {}: {:?}\n", i, g)?;
|
||||
}
|
||||
write!(f, "}}\n")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user