mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-11 16:41:28 +01:00
Simplifications in Nova's RO (#98)
* rename methods for better clarity * rename * Bump version
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
use super::{
|
||||
commitments::Commitment,
|
||||
constants::NUM_HASH_BITS,
|
||||
gadgets::{
|
||||
ecc::AllocatedPoint,
|
||||
r1cs::{AllocatedR1CSInstance, AllocatedRelaxedR1CSInstance},
|
||||
@@ -16,7 +17,7 @@ use super::{
|
||||
},
|
||||
},
|
||||
r1cs::{R1CSInstance, RelaxedR1CSInstance},
|
||||
traits::{circuit::StepCircuit, Group, HashFuncCircuitTrait, HashFuncConstantsCircuit},
|
||||
traits::{circuit::StepCircuit, Group, ROCircuitTrait, ROConstantsCircuit},
|
||||
};
|
||||
use bellperson::{
|
||||
gadgets::{
|
||||
@@ -91,7 +92,7 @@ where
|
||||
SC: StepCircuit<G::Base>,
|
||||
{
|
||||
params: NovaAugmentedCircuitParams,
|
||||
ro_consts: HashFuncConstantsCircuit<G>,
|
||||
ro_consts: ROConstantsCircuit<G>,
|
||||
inputs: Option<NovaAugmentedCircuitInputs<G>>,
|
||||
step_circuit: SC, // The function that is applied for each step
|
||||
}
|
||||
@@ -106,7 +107,7 @@ where
|
||||
params: NovaAugmentedCircuitParams,
|
||||
inputs: Option<NovaAugmentedCircuitInputs<G>>,
|
||||
step_circuit: SC,
|
||||
ro_consts: HashFuncConstantsCircuit<G>,
|
||||
ro_consts: ROConstantsCircuit<G>,
|
||||
) -> Self {
|
||||
Self {
|
||||
params,
|
||||
@@ -221,14 +222,14 @@ where
|
||||
T: AllocatedPoint<G::Base>,
|
||||
) -> Result<(AllocatedRelaxedR1CSInstance<G>, AllocatedBit), SynthesisError> {
|
||||
// Check that u.x[0] = Hash(params, U, i, z0, zi)
|
||||
let mut ro = G::HashFuncCircuit::new(self.ro_consts.clone());
|
||||
let mut ro = G::ROCircuit::new(self.ro_consts.clone());
|
||||
ro.absorb(params.clone());
|
||||
ro.absorb(i);
|
||||
ro.absorb(z_0);
|
||||
ro.absorb(z_i);
|
||||
U.absorb_in_ro(cs.namespace(|| "absorb U"), &mut ro)?;
|
||||
|
||||
let hash_bits = ro.get_hash(cs.namespace(|| "Input hash"))?;
|
||||
let hash_bits = ro.squeeze(cs.namespace(|| "Input hash"), NUM_HASH_BITS)?;
|
||||
let hash = le_bits_to_num(cs.namespace(|| "bits to hash"), hash_bits)?;
|
||||
let check_pass = alloc_num_equals(
|
||||
cs.namespace(|| "check consistency of u.X[0] with H(params, U, i, z0, zi)"),
|
||||
@@ -328,13 +329,13 @@ where
|
||||
.synthesize(&mut cs.namespace(|| "F"), z_input)?;
|
||||
|
||||
// Compute the new hash H(params, Unew, i+1, z0, z_{i+1})
|
||||
let mut ro = G::HashFuncCircuit::new(self.ro_consts);
|
||||
let mut ro = G::ROCircuit::new(self.ro_consts);
|
||||
ro.absorb(params);
|
||||
ro.absorb(i_new.clone());
|
||||
ro.absorb(z_0);
|
||||
ro.absorb(z_next);
|
||||
Unew.absorb_in_ro(cs.namespace(|| "absorb U_new"), &mut ro)?;
|
||||
let hash_bits = ro.get_hash(cs.namespace(|| "output hash bits"))?;
|
||||
let hash_bits = ro.squeeze(cs.namespace(|| "output hash bits"), NUM_HASH_BITS)?;
|
||||
let hash = le_bits_to_num(cs.namespace(|| "convert hash to num"), hash_bits)?;
|
||||
|
||||
// Outputs the computed hash and u.X[1] that corresponds to the hash of the other circuit
|
||||
@@ -356,7 +357,7 @@ mod tests {
|
||||
use crate::{
|
||||
bellperson::r1cs::{NovaShape, NovaWitness},
|
||||
poseidon::PoseidonConstantsCircuit,
|
||||
traits::{circuit::TrivialTestCircuit, HashFuncConstantsTrait},
|
||||
traits::{circuit::TrivialTestCircuit, ROConstantsTrait},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -364,8 +365,8 @@ mod tests {
|
||||
// In the following we use 1 to refer to the primary, and 2 to refer to the secondary circuit
|
||||
let params1 = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, true);
|
||||
let params2 = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, false);
|
||||
let ro_consts1: HashFuncConstantsCircuit<G2> = PoseidonConstantsCircuit::new();
|
||||
let ro_consts2: HashFuncConstantsCircuit<G1> = PoseidonConstantsCircuit::new();
|
||||
let ro_consts1: ROConstantsCircuit<G2> = PoseidonConstantsCircuit::new();
|
||||
let ro_consts2: ROConstantsCircuit<G1> = PoseidonConstantsCircuit::new();
|
||||
|
||||
// Initialize the shape and gens for the primary
|
||||
let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> =
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
errors::NovaError,
|
||||
traits::{AbsorbInROTrait, AppendToTranscriptTrait, CompressedGroup, Group, HashFuncTrait},
|
||||
traits::{AbsorbInROTrait, AppendToTranscriptTrait, CompressedGroup, Group, ROTrait},
|
||||
};
|
||||
use core::{
|
||||
fmt::Debug,
|
||||
@@ -166,7 +166,7 @@ impl<G: Group> AppendToTranscriptTrait for Commitment<G> {
|
||||
}
|
||||
|
||||
impl<G: Group> AbsorbInROTrait<G> for Commitment<G> {
|
||||
fn absorb_in_ro(&self, ro: &mut G::HashFunc) {
|
||||
fn absorb_in_ro(&self, ro: &mut G::RO) {
|
||||
let (x, y, is_infinity) = self.comm.to_coordinates();
|
||||
ro.absorb(x);
|
||||
ro.absorb(y);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! This module implements various gadgets necessary for folding R1CS types.
|
||||
use crate::{
|
||||
constants::NUM_CHALLENGE_BITS,
|
||||
gadgets::{
|
||||
ecc::AllocatedPoint,
|
||||
utils::{
|
||||
@@ -8,7 +9,7 @@ use crate::{
|
||||
},
|
||||
},
|
||||
r1cs::{R1CSInstance, RelaxedR1CSInstance},
|
||||
traits::{Group, HashFuncCircuitTrait, HashFuncConstantsCircuit},
|
||||
traits::{Group, ROCircuitTrait, ROConstantsCircuit},
|
||||
};
|
||||
use bellperson::{
|
||||
gadgets::{boolean::Boolean, num::AllocatedNum, Assignment},
|
||||
@@ -60,7 +61,7 @@ where
|
||||
}
|
||||
|
||||
/// Absorb the provided instance in the RO
|
||||
pub fn absorb_in_ro(&self, ro: &mut G::HashFuncCircuit) {
|
||||
pub fn absorb_in_ro(&self, ro: &mut G::ROCircuit) {
|
||||
ro.absorb(self.W.x.clone());
|
||||
ro.absorb(self.W.y.clone());
|
||||
ro.absorb(self.W.is_infinity.clone());
|
||||
@@ -207,7 +208,7 @@ where
|
||||
pub fn absorb_in_ro<CS: ConstraintSystem<<G as Group>::Base>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
ro: &mut G::HashFuncCircuit,
|
||||
ro: &mut G::ROCircuit,
|
||||
) -> Result<(), SynthesisError> {
|
||||
ro.absorb(self.W.x.clone());
|
||||
ro.absorb(self.W.y.clone());
|
||||
@@ -262,19 +263,19 @@ where
|
||||
params: AllocatedNum<G::Base>, // hash of R1CSShape of F'
|
||||
u: AllocatedR1CSInstance<G>,
|
||||
T: AllocatedPoint<G::Base>,
|
||||
ro_consts: HashFuncConstantsCircuit<G>,
|
||||
ro_consts: ROConstantsCircuit<G>,
|
||||
limb_width: usize,
|
||||
n_limbs: usize,
|
||||
) -> Result<AllocatedRelaxedR1CSInstance<G>, SynthesisError> {
|
||||
// Compute r:
|
||||
let mut ro = G::HashFuncCircuit::new(ro_consts);
|
||||
let mut ro = G::ROCircuit::new(ro_consts);
|
||||
ro.absorb(params);
|
||||
self.absorb_in_ro(cs.namespace(|| "absorb running instance"), &mut ro)?;
|
||||
u.absorb_in_ro(&mut ro);
|
||||
ro.absorb(T.x.clone());
|
||||
ro.absorb(T.y.clone());
|
||||
ro.absorb(T.is_infinity.clone());
|
||||
let r_bits = ro.get_challenge(cs.namespace(|| "r bits"))?;
|
||||
let r_bits = ro.squeeze(cs.namespace(|| "r bits"), NUM_CHALLENGE_BITS)?;
|
||||
let r = le_bits_to_num(cs.namespace(|| "r"), r_bits.clone())?;
|
||||
|
||||
// W_fold = self.W + r * u.W
|
||||
|
||||
57
src/lib.rs
57
src/lib.rs
@@ -26,6 +26,7 @@ use crate::bellperson::{
|
||||
};
|
||||
use ::bellperson::{Circuit, ConstraintSystem};
|
||||
use circuit::{NovaAugmentedCircuit, NovaAugmentedCircuitInputs, NovaAugmentedCircuitParams};
|
||||
use constants::NUM_HASH_BITS;
|
||||
use constants::{BN_LIMB_WIDTH, BN_N_LIMBS};
|
||||
use core::marker::PhantomData;
|
||||
use errors::NovaError;
|
||||
@@ -36,8 +37,8 @@ use r1cs::{
|
||||
R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
|
||||
};
|
||||
use traits::{
|
||||
circuit::StepCircuit, snark::RelaxedR1CSSNARKTrait, AbsorbInROTrait, Group, HashFuncConstants,
|
||||
HashFuncConstantsCircuit, HashFuncConstantsTrait, HashFuncTrait,
|
||||
circuit::StepCircuit, snark::RelaxedR1CSSNARKTrait, AbsorbInROTrait, Group, ROConstants,
|
||||
ROConstantsCircuit, ROConstantsTrait, ROTrait,
|
||||
};
|
||||
|
||||
/// A type that holds public parameters of Nova
|
||||
@@ -48,13 +49,13 @@ where
|
||||
C1: StepCircuit<G1::Scalar>,
|
||||
C2: StepCircuit<G2::Scalar>,
|
||||
{
|
||||
ro_consts_primary: HashFuncConstants<G1>,
|
||||
ro_consts_circuit_primary: HashFuncConstantsCircuit<G2>,
|
||||
ro_consts_primary: ROConstants<G1>,
|
||||
ro_consts_circuit_primary: ROConstantsCircuit<G2>,
|
||||
r1cs_gens_primary: R1CSGens<G1>,
|
||||
r1cs_shape_primary: R1CSShape<G1>,
|
||||
r1cs_shape_padded_primary: R1CSShape<G1>,
|
||||
ro_consts_secondary: HashFuncConstants<G2>,
|
||||
ro_consts_circuit_secondary: HashFuncConstantsCircuit<G1>,
|
||||
ro_consts_secondary: ROConstants<G2>,
|
||||
ro_consts_circuit_secondary: ROConstantsCircuit<G1>,
|
||||
r1cs_gens_secondary: R1CSGens<G2>,
|
||||
r1cs_shape_secondary: R1CSShape<G2>,
|
||||
r1cs_shape_padded_secondary: R1CSShape<G2>,
|
||||
@@ -78,14 +79,12 @@ where
|
||||
let augmented_circuit_params_secondary =
|
||||
NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, false);
|
||||
|
||||
let ro_consts_primary: HashFuncConstants<G1> = HashFuncConstants::<G1>::new();
|
||||
let ro_consts_secondary: HashFuncConstants<G2> = HashFuncConstants::<G2>::new();
|
||||
let ro_consts_primary: ROConstants<G1> = ROConstants::<G1>::new();
|
||||
let ro_consts_secondary: ROConstants<G2> = ROConstants::<G2>::new();
|
||||
|
||||
// ro_consts_circuit_primart are parameterized by G2 because the type alias uses G2::Base = G1::Scalar
|
||||
let ro_consts_circuit_primary: HashFuncConstantsCircuit<G2> =
|
||||
HashFuncConstantsCircuit::<G2>::new();
|
||||
let ro_consts_circuit_secondary: HashFuncConstantsCircuit<G1> =
|
||||
HashFuncConstantsCircuit::<G1>::new();
|
||||
let ro_consts_circuit_primary: ROConstantsCircuit<G2> = ROConstantsCircuit::<G2>::new();
|
||||
let ro_consts_circuit_secondary: ROConstantsCircuit<G1> = ROConstantsCircuit::<G1>::new();
|
||||
|
||||
// Initialize gens for the primary
|
||||
let circuit_primary: NovaAugmentedCircuit<G2, C1> = NovaAugmentedCircuit::new(
|
||||
@@ -245,8 +244,8 @@ where
|
||||
RelaxedR1CSInstance::<G2>::default(&pp.r1cs_gens_secondary, &pp.r1cs_shape_secondary);
|
||||
|
||||
// Outputs of the two circuits thus far
|
||||
let zi_primary = c_primary.compute(&z0_primary);
|
||||
let zi_secondary = c_secondary.compute(&z0_secondary);
|
||||
let zi_primary = c_primary.output(&z0_primary);
|
||||
let zi_secondary = c_secondary.output(&z0_secondary);
|
||||
|
||||
Ok(Self {
|
||||
r_W_primary,
|
||||
@@ -334,8 +333,8 @@ where
|
||||
.map_err(|_e| NovaError::UnSat)?;
|
||||
|
||||
// update the running instances and witnesses
|
||||
let zi_primary = c_primary.compute(&r_snark.zi_primary);
|
||||
let zi_secondary = c_secondary.compute(&r_snark.zi_secondary);
|
||||
let zi_primary = c_primary.output(&r_snark.zi_primary);
|
||||
let zi_secondary = c_secondary.output(&r_snark.zi_secondary);
|
||||
|
||||
Ok(Self {
|
||||
r_W_primary,
|
||||
@@ -385,21 +384,24 @@ where
|
||||
|
||||
// check if the output hashes in R1CS instances point to the right running instances
|
||||
let (hash_primary, hash_secondary) = {
|
||||
let mut hasher = <G2 as Group>::HashFunc::new(pp.ro_consts_secondary.clone());
|
||||
let mut hasher = <G2 as Group>::RO::new(pp.ro_consts_secondary.clone());
|
||||
hasher.absorb(scalar_as_base::<G2>(pp.r1cs_shape_secondary.get_digest()));
|
||||
hasher.absorb(G1::Scalar::from(num_steps as u64));
|
||||
hasher.absorb(z0_primary);
|
||||
hasher.absorb(self.zi_primary);
|
||||
self.r_U_secondary.absorb_in_ro(&mut hasher);
|
||||
|
||||
let mut hasher2 = <G1 as Group>::HashFunc::new(pp.ro_consts_primary.clone());
|
||||
let mut hasher2 = <G1 as Group>::RO::new(pp.ro_consts_primary.clone());
|
||||
hasher2.absorb(scalar_as_base::<G1>(pp.r1cs_shape_primary.get_digest()));
|
||||
hasher2.absorb(G2::Scalar::from(num_steps as u64));
|
||||
hasher2.absorb(z0_secondary);
|
||||
hasher2.absorb(self.zi_secondary);
|
||||
self.r_U_primary.absorb_in_ro(&mut hasher2);
|
||||
|
||||
(hasher.get_hash(), hasher2.get_hash())
|
||||
(
|
||||
hasher.squeeze(NUM_HASH_BITS),
|
||||
hasher2.squeeze(NUM_HASH_BITS),
|
||||
)
|
||||
};
|
||||
|
||||
if hash_primary != scalar_as_base::<G1>(self.l_u_primary.X[1])
|
||||
@@ -597,21 +599,24 @@ where
|
||||
|
||||
// check if the output hashes in R1CS instances point to the right running instances
|
||||
let (hash_primary, hash_secondary) = {
|
||||
let mut hasher = <G2 as Group>::HashFunc::new(pp.ro_consts_secondary.clone());
|
||||
let mut hasher = <G2 as Group>::RO::new(pp.ro_consts_secondary.clone());
|
||||
hasher.absorb(scalar_as_base::<G2>(pp.r1cs_shape_secondary.get_digest()));
|
||||
hasher.absorb(G1::Scalar::from(num_steps as u64));
|
||||
hasher.absorb(z0_primary);
|
||||
hasher.absorb(self.zn_primary);
|
||||
self.r_U_secondary.absorb_in_ro(&mut hasher);
|
||||
|
||||
let mut hasher2 = <G1 as Group>::HashFunc::new(pp.ro_consts_primary.clone());
|
||||
let mut hasher2 = <G1 as Group>::RO::new(pp.ro_consts_primary.clone());
|
||||
hasher2.absorb(scalar_as_base::<G1>(pp.r1cs_shape_primary.get_digest()));
|
||||
hasher2.absorb(G2::Scalar::from(num_steps as u64));
|
||||
hasher2.absorb(z0_secondary);
|
||||
hasher2.absorb(self.zn_secondary);
|
||||
self.r_U_primary.absorb_in_ro(&mut hasher2);
|
||||
|
||||
(hasher.get_hash(), hasher2.get_hash())
|
||||
(
|
||||
hasher.squeeze(NUM_HASH_BITS),
|
||||
hasher2.squeeze(NUM_HASH_BITS),
|
||||
)
|
||||
};
|
||||
|
||||
if hash_primary != scalar_as_base::<G1>(self.l_u_primary.X[1])
|
||||
@@ -709,7 +714,7 @@ mod tests {
|
||||
Ok(y)
|
||||
}
|
||||
|
||||
fn compute(&self, z: &F) -> F {
|
||||
fn output(&self, z: &F) -> F {
|
||||
*z * *z * *z + z + F::from(5u64)
|
||||
}
|
||||
}
|
||||
@@ -816,7 +821,7 @@ mod tests {
|
||||
assert_eq!(zn_primary, <G1 as Group>::Scalar::one());
|
||||
let mut zn_secondary_direct = <G2 as Group>::Scalar::zero();
|
||||
for _i in 0..num_steps {
|
||||
zn_secondary_direct = CubicCircuit::default().compute(&zn_secondary_direct);
|
||||
zn_secondary_direct = CubicCircuit::default().output(&zn_secondary_direct);
|
||||
}
|
||||
assert_eq!(zn_secondary, zn_secondary_direct);
|
||||
assert_eq!(zn_secondary, <G2 as Group>::Scalar::from(2460515u64));
|
||||
@@ -878,7 +883,7 @@ mod tests {
|
||||
assert_eq!(zn_primary, <G1 as Group>::Scalar::one());
|
||||
let mut zn_secondary_direct = <G2 as Group>::Scalar::zero();
|
||||
for _i in 0..num_steps {
|
||||
zn_secondary_direct = CubicCircuit::default().compute(&zn_secondary_direct);
|
||||
zn_secondary_direct = CubicCircuit::default().output(&zn_secondary_direct);
|
||||
}
|
||||
assert_eq!(zn_secondary, zn_secondary_direct);
|
||||
assert_eq!(zn_secondary, <G2 as Group>::Scalar::from(2460515u64));
|
||||
@@ -960,7 +965,7 @@ mod tests {
|
||||
Ok(y)
|
||||
}
|
||||
|
||||
fn compute(&self, z: &F) -> F {
|
||||
fn output(&self, z: &F) -> F {
|
||||
// sanity check
|
||||
let x = *z;
|
||||
let y_pow_5 = {
|
||||
|
||||
46
src/nifs.rs
46
src/nifs.rs
@@ -2,12 +2,13 @@
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use super::commitments::CompressedCommitment;
|
||||
use super::errors::NovaError;
|
||||
use super::r1cs::{
|
||||
R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
|
||||
use super::{
|
||||
commitments::CompressedCommitment,
|
||||
constants::NUM_CHALLENGE_BITS,
|
||||
errors::NovaError,
|
||||
r1cs::{R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness},
|
||||
traits::{AbsorbInROTrait, Group, ROTrait},
|
||||
};
|
||||
use super::traits::{AbsorbInROTrait, Group, HashFuncTrait};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// A SNARK that holds the proof of a step of an incremental computation
|
||||
@@ -18,8 +19,8 @@ pub struct NIFS<G: Group> {
|
||||
_p: PhantomData<G>,
|
||||
}
|
||||
|
||||
type HashFuncConstants<G> =
|
||||
<<G as Group>::HashFunc as HashFuncTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants;
|
||||
type ROConstants<G> =
|
||||
<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants;
|
||||
|
||||
impl<G: Group> NIFS<G> {
|
||||
/// Takes as input a Relaxed R1CS instance-witness tuple `(U1, W1)` and
|
||||
@@ -30,7 +31,7 @@ impl<G: Group> NIFS<G> {
|
||||
/// if and only if `W1` satisfies `U1` and `W2` satisfies `U2`.
|
||||
pub fn prove(
|
||||
gens: &R1CSGens<G>,
|
||||
ro_consts: &HashFuncConstants<G>,
|
||||
ro_consts: &ROConstants<G>,
|
||||
S: &R1CSShape<G>,
|
||||
U1: &RelaxedR1CSInstance<G>,
|
||||
W1: &RelaxedR1CSWitness<G>,
|
||||
@@ -38,7 +39,7 @@ impl<G: Group> NIFS<G> {
|
||||
W2: &R1CSWitness<G>,
|
||||
) -> Result<(NIFS<G>, (RelaxedR1CSInstance<G>, RelaxedR1CSWitness<G>)), NovaError> {
|
||||
// initialize a new RO
|
||||
let mut ro = G::HashFunc::new(ro_consts.clone());
|
||||
let mut ro = G::RO::new(ro_consts.clone());
|
||||
|
||||
// append S to the transcript
|
||||
S.absorb_in_ro(&mut ro);
|
||||
@@ -54,7 +55,7 @@ impl<G: Group> NIFS<G> {
|
||||
comm_T.absorb_in_ro(&mut ro);
|
||||
|
||||
// compute a challenge from the RO
|
||||
let r = ro.get_challenge();
|
||||
let r = ro.squeeze(NUM_CHALLENGE_BITS);
|
||||
|
||||
// fold the instance using `r` and `comm_T`
|
||||
let U = U1.fold(U2, &comm_T, &r)?;
|
||||
@@ -79,13 +80,13 @@ impl<G: Group> NIFS<G> {
|
||||
/// if and only if `U1` and `U2` are satisfiable.
|
||||
pub fn verify(
|
||||
&self,
|
||||
ro_consts: &HashFuncConstants<G>,
|
||||
ro_consts: &ROConstants<G>,
|
||||
S: &R1CSShape<G>,
|
||||
U1: &RelaxedR1CSInstance<G>,
|
||||
U2: &R1CSInstance<G>,
|
||||
) -> Result<RelaxedR1CSInstance<G>, NovaError> {
|
||||
// initialize a new RO
|
||||
let mut ro = G::HashFunc::new(ro_consts.clone());
|
||||
let mut ro = G::RO::new(ro_consts.clone());
|
||||
|
||||
// append S to the transcript
|
||||
S.absorb_in_ro(&mut ro);
|
||||
@@ -99,7 +100,7 @@ impl<G: Group> NIFS<G> {
|
||||
comm_T.absorb_in_ro(&mut ro);
|
||||
|
||||
// compute a challenge from the RO
|
||||
let r = ro.get_challenge();
|
||||
let r = ro.squeeze(NUM_CHALLENGE_BITS);
|
||||
|
||||
// fold the instance using `r` and `comm_T`
|
||||
let U = U1.fold(U2, &comm_T, &r)?;
|
||||
@@ -112,7 +113,7 @@ impl<G: Group> NIFS<G> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::traits::{Group, HashFuncConstantsTrait};
|
||||
use crate::traits::{Group, ROConstantsTrait};
|
||||
use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
|
||||
use ff::{Field, PrimeField};
|
||||
use rand::rngs::OsRng;
|
||||
@@ -166,10 +167,8 @@ mod tests {
|
||||
let _ = synthesize_tiny_r1cs_bellperson(&mut cs, None);
|
||||
let shape = cs.r1cs_shape();
|
||||
let gens = cs.r1cs_gens();
|
||||
let ro_consts = <<G as Group>::HashFunc as HashFuncTrait<
|
||||
<G as Group>::Base,
|
||||
<G as Group>::Scalar,
|
||||
>>::Constants::new();
|
||||
let ro_consts =
|
||||
<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::new();
|
||||
|
||||
// Now get the instance and assignment for one instance
|
||||
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
|
||||
@@ -193,10 +192,7 @@ mod tests {
|
||||
|
||||
fn execute_sequence(
|
||||
gens: &R1CSGens<G>,
|
||||
ro_consts: &<<G as Group>::HashFunc as HashFuncTrait<
|
||||
<G as Group>::Base,
|
||||
<G as Group>::Scalar,
|
||||
>>::Constants,
|
||||
ro_consts: &<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants,
|
||||
shape: &R1CSShape<G>,
|
||||
U1: &R1CSInstance<G>,
|
||||
W1: &R1CSWitness<G>,
|
||||
@@ -304,10 +300,8 @@ mod tests {
|
||||
|
||||
// generate generators and ro constants
|
||||
let gens = R1CSGens::new(num_cons, num_vars);
|
||||
let ro_consts = <<G as Group>::HashFunc as HashFuncTrait<
|
||||
<G as Group>::Base,
|
||||
<G as Group>::Scalar,
|
||||
>>::Constants::new();
|
||||
let ro_consts =
|
||||
<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::new();
|
||||
|
||||
let rand_inst_witness_generator =
|
||||
|gens: &R1CSGens<G>, I: &S| -> (S, R1CSInstance<G>, R1CSWitness<G>) {
|
||||
|
||||
10
src/pasta.rs
10
src/pasta.rs
@@ -1,6 +1,6 @@
|
||||
//! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar.
|
||||
use crate::{
|
||||
poseidon::{PoseidonHashFunc, PoseidonHashFuncCircuit},
|
||||
poseidon::{PoseidonRO, PoseidonROCircuit},
|
||||
traits::{ChallengeTrait, CompressedGroup, Group},
|
||||
};
|
||||
use digest::{ExtendableOutput, Input};
|
||||
@@ -40,8 +40,8 @@ impl Group for pallas::Point {
|
||||
type Scalar = pallas::Scalar;
|
||||
type CompressedGroupElement = PallasCompressedElementWrapper;
|
||||
type PreprocessedGroupElement = pallas::Affine;
|
||||
type HashFunc = PoseidonHashFunc<Self::Base, Self::Scalar>;
|
||||
type HashFuncCircuit = PoseidonHashFuncCircuit<Self::Base>;
|
||||
type RO = PoseidonRO<Self::Base, Self::Scalar>;
|
||||
type ROCircuit = PoseidonROCircuit<Self::Base>;
|
||||
|
||||
fn vartime_multiscalar_mul(
|
||||
scalars: &[Self::Scalar],
|
||||
@@ -138,8 +138,8 @@ impl Group for vesta::Point {
|
||||
type Scalar = vesta::Scalar;
|
||||
type CompressedGroupElement = VestaCompressedElementWrapper;
|
||||
type PreprocessedGroupElement = vesta::Affine;
|
||||
type HashFunc = PoseidonHashFunc<Self::Base, Self::Scalar>;
|
||||
type HashFuncCircuit = PoseidonHashFuncCircuit<Self::Base>;
|
||||
type RO = PoseidonRO<Self::Base, Self::Scalar>;
|
||||
type ROCircuit = PoseidonROCircuit<Self::Base>;
|
||||
|
||||
fn vartime_multiscalar_mul(
|
||||
scalars: &[Self::Scalar],
|
||||
|
||||
170
src/poseidon.rs
170
src/poseidon.rs
@@ -1,8 +1,5 @@
|
||||
//! Poseidon Constants and Poseidon-based RO used in Nova
|
||||
use super::{
|
||||
constants::{NUM_CHALLENGE_BITS, NUM_HASH_BITS},
|
||||
traits::{HashFuncCircuitTrait, HashFuncConstantsTrait, HashFuncTrait},
|
||||
};
|
||||
use super::traits::{ROCircuitTrait, ROConstantsTrait, ROTrait};
|
||||
use bellperson::{
|
||||
gadgets::{
|
||||
boolean::{AllocatedBit, Boolean},
|
||||
@@ -29,7 +26,7 @@ where
|
||||
constants32: PoseidonConstants<Scalar, U32>,
|
||||
}
|
||||
|
||||
impl<Scalar> HashFuncConstantsTrait<Scalar> for PoseidonConstantsCircuit<Scalar>
|
||||
impl<Scalar> ROConstantsTrait<Scalar> for PoseidonConstantsCircuit<Scalar>
|
||||
where
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
{
|
||||
@@ -46,7 +43,7 @@ where
|
||||
}
|
||||
|
||||
/// A Poseidon-based RO to use outside circuits
|
||||
pub struct PoseidonHashFunc<Base, Scalar>
|
||||
pub struct PoseidonRO<Base, Scalar>
|
||||
where
|
||||
Base: PrimeField + PrimeFieldBits,
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
@@ -58,30 +55,7 @@ where
|
||||
_p: PhantomData<Scalar>,
|
||||
}
|
||||
|
||||
impl<Base, Scalar> PoseidonHashFunc<Base, Scalar>
|
||||
where
|
||||
Base: PrimeField + PrimeFieldBits,
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
{
|
||||
fn hash_inner(&self) -> Base {
|
||||
match self.state.len() {
|
||||
27 => {
|
||||
Poseidon::<Base, U27>::new_with_preimage(&self.state, &self.constants.constants27).hash()
|
||||
}
|
||||
32 => {
|
||||
Poseidon::<Base, U32>::new_with_preimage(&self.state, &self.constants.constants32).hash()
|
||||
}
|
||||
_ => {
|
||||
panic!(
|
||||
"Number of elements in the RO state does not match any of the arities used in Nova: {:?}",
|
||||
self.state.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Base, Scalar> HashFuncTrait<Base, Scalar> for PoseidonHashFunc<Base, Scalar>
|
||||
impl<Base, Scalar> ROTrait<Base, Scalar> for PoseidonRO<Base, Scalar>
|
||||
where
|
||||
Base: PrimeField + PrimeFieldBits,
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
@@ -102,28 +76,27 @@ where
|
||||
}
|
||||
|
||||
/// Compute a challenge by hashing the current state
|
||||
fn get_challenge(&self) -> Scalar {
|
||||
let hash = self.hash_inner();
|
||||
// Only keep NUM_CHALLENGE_BITS bits
|
||||
let bits = hash.to_le_bits();
|
||||
let mut res = Scalar::zero();
|
||||
let mut coeff = Scalar::one();
|
||||
for bit in bits[0..NUM_CHALLENGE_BITS].into_iter() {
|
||||
if *bit {
|
||||
res += coeff;
|
||||
fn squeeze(&self, num_bits: usize) -> Scalar {
|
||||
let hash = match self.state.len() {
|
||||
27 => {
|
||||
Poseidon::<Base, U27>::new_with_preimage(&self.state, &self.constants.constants27).hash()
|
||||
}
|
||||
coeff += coeff;
|
||||
}
|
||||
res
|
||||
}
|
||||
32 => {
|
||||
Poseidon::<Base, U32>::new_with_preimage(&self.state, &self.constants.constants32).hash()
|
||||
}
|
||||
_ => {
|
||||
panic!(
|
||||
"Number of elements in the RO state does not match any of the arities used in Nova: {:?}",
|
||||
self.state.len()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
fn get_hash(&self) -> Scalar {
|
||||
let hash = self.hash_inner();
|
||||
// Only keep NUM_HASH_BITS bits
|
||||
// Only return `num_bits`
|
||||
let bits = hash.to_le_bits();
|
||||
let mut res = Scalar::zero();
|
||||
let mut coeff = Scalar::one();
|
||||
for bit in bits[0..NUM_HASH_BITS].into_iter() {
|
||||
for bit in bits[0..num_bits].into_iter() {
|
||||
if *bit {
|
||||
res += coeff;
|
||||
}
|
||||
@@ -134,7 +107,7 @@ where
|
||||
}
|
||||
|
||||
/// A Poseidon-based RO gadget to use inside the verifier circuit.
|
||||
pub struct PoseidonHashFuncCircuit<Scalar>
|
||||
pub struct PoseidonROCircuit<Scalar>
|
||||
where
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
{
|
||||
@@ -143,48 +116,7 @@ where
|
||||
constants: PoseidonConstantsCircuit<Scalar>,
|
||||
}
|
||||
|
||||
impl<Scalar> PoseidonHashFuncCircuit<Scalar>
|
||||
where
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
{
|
||||
fn hash_inner<CS>(&mut self, mut cs: CS) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<Scalar>,
|
||||
{
|
||||
let out = match self.state.len() {
|
||||
27 => poseidon_hash(
|
||||
cs.namespace(|| "Poseidon hash"),
|
||||
self.state.clone(),
|
||||
&self.constants.constants27,
|
||||
)?,
|
||||
32 => poseidon_hash(
|
||||
cs.namespace(|| "Posideon hash"),
|
||||
self.state.clone(),
|
||||
&self.constants.constants32,
|
||||
)?,
|
||||
_ => {
|
||||
panic!(
|
||||
"Number of elements in the RO state does not match any of the arities used in Nova: {}",
|
||||
self.state.len()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
// return the hash as a vector of bits
|
||||
Ok(
|
||||
out
|
||||
.to_bits_le_strict(cs.namespace(|| "poseidon hash to boolean"))?
|
||||
.iter()
|
||||
.map(|boolean| match boolean {
|
||||
Boolean::Is(ref x) => x.clone(),
|
||||
_ => panic!("Wrong type of input. We should have never reached there"),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Scalar> HashFuncCircuitTrait<Scalar> for PoseidonHashFuncCircuit<Scalar>
|
||||
impl<Scalar> ROCircuitTrait<Scalar> for PoseidonROCircuit<Scalar>
|
||||
where
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
{
|
||||
@@ -204,20 +136,45 @@ where
|
||||
}
|
||||
|
||||
/// Compute a challenge by hashing the current state
|
||||
fn get_challenge<CS>(&mut self, mut cs: CS) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
fn squeeze<CS>(
|
||||
&mut self,
|
||||
mut cs: CS,
|
||||
num_bits: usize,
|
||||
) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<Scalar>,
|
||||
{
|
||||
let bits = self.hash_inner(cs.namespace(|| "hash"))?;
|
||||
Ok(bits[..NUM_CHALLENGE_BITS].into())
|
||||
}
|
||||
let hash = match self.state.len() {
|
||||
27 => poseidon_hash(
|
||||
cs.namespace(|| "Poseidon hash"),
|
||||
self.state.clone(),
|
||||
&self.constants.constants27,
|
||||
)?,
|
||||
32 => poseidon_hash(
|
||||
cs.namespace(|| "Posideon hash"),
|
||||
self.state.clone(),
|
||||
&self.constants.constants32,
|
||||
)?,
|
||||
_ => {
|
||||
panic!(
|
||||
"Number of elements in the RO state does not match any of the arities used in Nova: {}",
|
||||
self.state.len()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
fn get_hash<CS>(&mut self, mut cs: CS) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<Scalar>,
|
||||
{
|
||||
let bits = self.hash_inner(cs.namespace(|| "hash"))?;
|
||||
Ok(bits[..NUM_HASH_BITS].into())
|
||||
// return the hash as a vector of bits, truncated
|
||||
Ok(
|
||||
hash
|
||||
.to_bits_le_strict(cs.namespace(|| "poseidon hash to boolean"))?
|
||||
.iter()
|
||||
.map(|boolean| match boolean {
|
||||
Boolean::Is(ref x) => x.clone(),
|
||||
_ => panic!("Wrong type of input. We should have never reached there"),
|
||||
})
|
||||
.collect::<Vec<AllocatedBit>>()[..num_bits]
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +184,10 @@ mod tests {
|
||||
type S = pasta_curves::pallas::Scalar;
|
||||
type B = pasta_curves::vesta::Scalar;
|
||||
type G = pasta_curves::pallas::Point;
|
||||
use crate::{bellperson::solver::SatisfyingAssignment, gadgets::utils::le_bits_to_num};
|
||||
use crate::{
|
||||
bellperson::solver::SatisfyingAssignment, constants::NUM_CHALLENGE_BITS,
|
||||
gadgets::utils::le_bits_to_num,
|
||||
};
|
||||
use ff::Field;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
@@ -236,8 +196,8 @@ mod tests {
|
||||
// Check that the number computed inside the circuit is equal to the number computed outside the circuit
|
||||
let mut csprng: OsRng = OsRng;
|
||||
let constants = PoseidonConstantsCircuit::new();
|
||||
let mut ro: PoseidonHashFunc<S, B> = PoseidonHashFunc::new(constants.clone());
|
||||
let mut ro_gadget: PoseidonHashFuncCircuit<S> = PoseidonHashFuncCircuit::new(constants);
|
||||
let mut ro: PoseidonRO<S, B> = PoseidonRO::new(constants.clone());
|
||||
let mut ro_gadget: PoseidonROCircuit<S> = PoseidonROCircuit::new(constants);
|
||||
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
|
||||
for i in 0..27 {
|
||||
let num = S::random(&mut csprng);
|
||||
@@ -249,8 +209,8 @@ mod tests {
|
||||
.unwrap();
|
||||
ro_gadget.absorb(num_gadget);
|
||||
}
|
||||
let num = ro.get_challenge();
|
||||
let num2_bits = ro_gadget.get_challenge(&mut cs).unwrap();
|
||||
let num = ro.squeeze(NUM_CHALLENGE_BITS);
|
||||
let num2_bits = ro_gadget.squeeze(&mut cs, NUM_CHALLENGE_BITS).unwrap();
|
||||
let num2 = le_bits_to_num(&mut cs, num2_bits).unwrap();
|
||||
assert_eq!(num.to_repr(), num2.get_value().unwrap().to_repr());
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::{
|
||||
constants::{BN_LIMB_WIDTH, BN_N_LIMBS, NUM_HASH_BITS},
|
||||
errors::NovaError,
|
||||
gadgets::utils::scalar_as_base,
|
||||
traits::{AbsorbInROTrait, AppendToTranscriptTrait, Group, HashFuncTrait},
|
||||
traits::{AbsorbInROTrait, AppendToTranscriptTrait, Group, ROTrait},
|
||||
};
|
||||
use bellperson_nonnative::{mp::bignat::nat_to_limbs, util::convert::f_to_nat};
|
||||
use core::cmp::max;
|
||||
@@ -453,7 +453,7 @@ impl<G: Group> AppendToTranscriptTrait for R1CSShape<G> {
|
||||
}
|
||||
|
||||
impl<G: Group> AbsorbInROTrait<G> for R1CSShape<G> {
|
||||
fn absorb_in_ro(&self, ro: &mut G::HashFunc) {
|
||||
fn absorb_in_ro(&self, ro: &mut G::RO) {
|
||||
ro.absorb(scalar_as_base::<G>(self.get_digest()));
|
||||
}
|
||||
}
|
||||
@@ -500,7 +500,7 @@ impl<G: Group> AppendToTranscriptTrait for R1CSInstance<G> {
|
||||
}
|
||||
|
||||
impl<G: Group> AbsorbInROTrait<G> for R1CSInstance<G> {
|
||||
fn absorb_in_ro(&self, ro: &mut G::HashFunc) {
|
||||
fn absorb_in_ro(&self, ro: &mut G::RO) {
|
||||
self.comm_W.absorb_in_ro(ro);
|
||||
for x in &self.X {
|
||||
ro.absorb(scalar_as_base::<G>(*x));
|
||||
@@ -640,7 +640,7 @@ impl<G: Group> AppendToTranscriptTrait for RelaxedR1CSInstance<G> {
|
||||
}
|
||||
|
||||
impl<G: Group> AbsorbInROTrait<G> for RelaxedR1CSInstance<G> {
|
||||
fn absorb_in_ro(&self, ro: &mut G::HashFunc) {
|
||||
fn absorb_in_ro(&self, ro: &mut G::RO) {
|
||||
self.comm_W.absorb_in_ro(ro);
|
||||
self.comm_E.absorb_in_ro(ro);
|
||||
ro.absorb(scalar_as_base::<G>(self.u));
|
||||
|
||||
@@ -13,8 +13,8 @@ pub trait StepCircuit<F: PrimeField>: Send + Sync + Clone {
|
||||
z: AllocatedNum<F>,
|
||||
) -> Result<AllocatedNum<F>, SynthesisError>;
|
||||
|
||||
/// Execute the circuit for a computation step and return output
|
||||
fn compute(&self, z: &F) -> F;
|
||||
/// return the output of the step when provided with with the step's input
|
||||
fn output(&self, z: &F) -> F;
|
||||
}
|
||||
|
||||
/// A trivial step circuit that simply returns the input
|
||||
@@ -35,7 +35,7 @@ where
|
||||
Ok(z)
|
||||
}
|
||||
|
||||
fn compute(&self, z: &F) -> F {
|
||||
fn output(&self, z: &F) -> F {
|
||||
*z
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ pub trait Group:
|
||||
|
||||
/// A type that represents a hash function that consumes elements
|
||||
/// from the base field and squeezes out elements of the scalar field
|
||||
type HashFunc: HashFuncTrait<Self::Base, Self::Scalar>;
|
||||
type RO: ROTrait<Self::Base, Self::Scalar>;
|
||||
|
||||
/// An alternate implementation of Self::HashFunc in the circuit model
|
||||
type HashFuncCircuit: HashFuncCircuitTrait<Self::Base>;
|
||||
/// An alternate implementation of Self::RO in the circuit model
|
||||
type ROCircuit: ROCircuitTrait<Self::Base>;
|
||||
|
||||
/// A method to compute a multiexponentation
|
||||
fn vartime_multiscalar_mul(
|
||||
@@ -87,7 +87,7 @@ pub trait AppendToTranscriptTrait {
|
||||
/// A helper trait to absorb different objects in RO
|
||||
pub trait AbsorbInROTrait<G: Group> {
|
||||
/// Absorbs the value in the provided RO
|
||||
fn absorb_in_ro(&self, ro: &mut G::HashFunc);
|
||||
fn absorb_in_ro(&self, ro: &mut G::RO);
|
||||
}
|
||||
|
||||
/// A helper trait to generate challenges using a transcript object
|
||||
@@ -97,9 +97,9 @@ pub trait ChallengeTrait {
|
||||
}
|
||||
|
||||
/// A helper trait that defines the behavior of a hash function that we use as an RO
|
||||
pub trait HashFuncTrait<Base, Scalar> {
|
||||
pub trait ROTrait<Base, Scalar> {
|
||||
/// A type representing constants/parameters associated with the hash function
|
||||
type Constants: HashFuncConstantsTrait<Base> + Clone + Send + Sync;
|
||||
type Constants: ROConstantsTrait<Base> + Clone + Send + Sync;
|
||||
|
||||
/// Initializes the hash function
|
||||
fn new(constants: Self::Constants) -> Self;
|
||||
@@ -107,17 +107,14 @@ pub trait HashFuncTrait<Base, Scalar> {
|
||||
/// Adds a scalar to the internal state
|
||||
fn absorb(&mut self, e: Base);
|
||||
|
||||
/// Returns a random challenge by hashing the internal state
|
||||
fn get_challenge(&self) -> Scalar;
|
||||
|
||||
/// Returns a hash of the internal state
|
||||
fn get_hash(&self) -> Scalar;
|
||||
/// Returns a challenge of `num_bits` by hashing the internal state
|
||||
fn squeeze(&self, num_bits: usize) -> Scalar;
|
||||
}
|
||||
|
||||
/// A helper trait that defines the behavior of a hash function that we use as an RO in the circuit model
|
||||
pub trait HashFuncCircuitTrait<Base: PrimeField> {
|
||||
pub trait ROCircuitTrait<Base: PrimeField> {
|
||||
/// A type representing constants/parameters associated with the hash function
|
||||
type Constants: HashFuncConstantsTrait<Base> + Clone + Send + Sync;
|
||||
type Constants: ROConstantsTrait<Base> + Clone + Send + Sync;
|
||||
|
||||
/// Initializes the hash function
|
||||
fn new(constants: Self::Constants) -> Self;
|
||||
@@ -125,30 +122,25 @@ pub trait HashFuncCircuitTrait<Base: PrimeField> {
|
||||
/// Adds a scalar to the internal state
|
||||
fn absorb(&mut self, e: AllocatedNum<Base>);
|
||||
|
||||
/// Returns a random challenge by hashing the internal state
|
||||
fn get_challenge<CS>(&mut self, cs: CS) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<Base>;
|
||||
|
||||
/// Returns a hash of the internal state
|
||||
fn get_hash<CS>(&mut self, cs: CS) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
/// Returns a challenge of `num_bits` by hashing the internal state
|
||||
fn squeeze<CS>(&mut self, cs: CS, num_bits: usize) -> Result<Vec<AllocatedBit>, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<Base>;
|
||||
}
|
||||
|
||||
/// A helper trait that defines the constants associated with a hash function
|
||||
pub trait HashFuncConstantsTrait<Base> {
|
||||
pub trait ROConstantsTrait<Base> {
|
||||
/// produces constants/parameters associated with the hash function
|
||||
fn new() -> Self;
|
||||
}
|
||||
|
||||
/// An alias for constants associated with G::HashFunc
|
||||
pub type HashFuncConstants<G> =
|
||||
<<G as Group>::HashFunc as HashFuncTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants;
|
||||
/// An alias for constants associated with G::RO
|
||||
pub type ROConstants<G> =
|
||||
<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants;
|
||||
|
||||
/// An alias for constants associated with G::HashFuncCircuit
|
||||
pub type HashFuncConstantsCircuit<G> =
|
||||
<<G as Group>::HashFuncCircuit as HashFuncCircuitTrait<<G as Group>::Base>>::Constants;
|
||||
/// An alias for constants associated with G::ROCircuit
|
||||
pub type ROConstantsCircuit<G> =
|
||||
<<G as Group>::ROCircuit as ROCircuitTrait<<G as Group>::Base>>::Constants;
|
||||
|
||||
/// A helper trait for types with a group operation.
|
||||
pub trait GroupOps<Rhs = Self, Output = Self>:
|
||||
|
||||
Reference in New Issue
Block a user