-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Small Gadgets refactor #353
Changes from all commits
f6439ae
e19854e
0389ea6
13c854a
442f3b7
fd3ae7a
8ef2a85
bec419d
75a5949
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,20 @@ | ||
//! This module implements various gadgets necessary for Nova and applications built with Nova. | ||
pub mod ecc; | ||
pub(crate) mod nonnative; | ||
pub(crate) mod r1cs; | ||
pub(crate) mod utils; | ||
mod ecc; | ||
pub(crate) use ecc::AllocatedPoint; | ||
|
||
mod nonnative; | ||
pub(crate) use nonnative::{bignat::nat_to_limbs, util::f_to_nat}; | ||
|
||
mod r1cs; | ||
pub(crate) use r1cs::{ | ||
conditionally_select_alloc_relaxed_r1cs, conditionally_select_vec_allocated_relaxed_r1cs_instance, | ||
}; | ||
pub(crate) use r1cs::{AllocatedR1CSInstance, AllocatedRelaxedR1CSInstance}; | ||
|
||
mod utils; | ||
#[cfg(test)] | ||
pub(crate) use utils::alloc_one; | ||
pub(crate) use utils::{ | ||
alloc_num_equals, alloc_scalar_as_base, alloc_zero, conditionally_select_vec, le_bits_to_num, | ||
scalar_as_base, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -158,9 +158,9 @@ impl<Scalar: PrimeField> Num<Scalar> { | |
/// Computes the natural number represented by an array of bits. | ||
/// Checks if the natural number equals `self` | ||
pub fn is_equal<CS: ConstraintSystem<Scalar>>(&self, mut cs: CS, other: &Bitvector<Scalar>) { | ||
let allocations = other.allocations.clone(); | ||
let mut f = Scalar::ONE; | ||
let sum = allocations | ||
let sum = other | ||
.allocations | ||
.iter() | ||
.fold(LinearCombination::zero(), |lc, bit| { | ||
let l = lc + (f, &bit.bit); | ||
|
@@ -202,8 +202,7 @@ impl<Scalar: PrimeField> Num<Scalar> { | |
let sum_lc = LinearCombination::zero() + &self.num - ∑ | ||
cs.enforce(|| "sum", |lc| lc + &sum_lc, |lc| lc + CS::one(), |lc| lc); | ||
let bits: Vec<LinearCombination<Scalar>> = allocations | ||
.clone() | ||
.into_iter() | ||
.iter() | ||
.map(|a| LinearCombination::zero() + &a.bit) | ||
.collect(); | ||
Ok(Bitvector { | ||
|
@@ -245,7 +244,7 @@ fn write_be<F: PrimeField, W: Write>(f: &F, mut writer: W) -> io::Result<()> { | |
/// Convert a field element to a natural number | ||
pub fn f_to_nat<Scalar: PrimeField>(f: &Scalar) -> BigInt { | ||
let mut s = Vec::new(); | ||
write_be(f, &mut s).unwrap(); // f.to_repr().write_be(&mut s).unwrap(); | ||
write_be(f, &mut s).unwrap(); | ||
BigInt::from_bytes_le(Sign::Plus, f.to_repr().as_ref()) | ||
} | ||
|
||
|
@@ -254,3 +253,41 @@ pub fn f_to_nat<Scalar: PrimeField>(f: &Scalar) -> BigInt { | |
pub fn nat_to_f<Scalar: PrimeField>(n: &BigInt) -> Option<Scalar> { | ||
Scalar::from_str_vartime(&format!("{n}")) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use bitvec::field::BitField as _; | ||
use ff::PrimeFieldBits; | ||
use rand::SeedableRng; | ||
use rand_chacha::ChaCha20Rng; | ||
|
||
// the write_be function above assumes Field::to_repr() outputs a representation that's an instance | ||
// of `AsRef<[u8]>` in lower endian. We test that here, as this is not what the I2OSP standard recommends | ||
// and may change in some implementations. | ||
Comment on lines
+264
to
+266
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good check! This is also implicitly assumed in my current CycleFold implementation as well |
||
fn test_repr_is_le_with<F: PrimeFieldBits>() { | ||
let mut rng = ChaCha20Rng::from_seed([0u8; 32]); | ||
for _i in 0..50 { | ||
let f = F::random(&mut rng); | ||
// This is guaranteed to be in LE | ||
let le_bits = f.to_le_bits(); | ||
let leftmost_u64 = le_bits[..64].load_le::<u64>(); | ||
|
||
// This is not | ||
let f_repr = f.to_repr(); | ||
let bytes: [u8; 8] = f_repr.as_ref()[..8].try_into().unwrap(); | ||
let u64_from_repr = u64::from_le_bytes(bytes); | ||
|
||
assert_eq!(leftmost_u64, u64_from_repr); | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_repr_is_le() { | ||
test_repr_is_le_with::<pasta_curves::pallas::Scalar>(); | ||
test_repr_is_le_with::<pasta_curves::pallas::Base>(); | ||
test_repr_is_le_with::<crate::provider::bn256_grumpkin::bn256::Scalar>(); | ||
test_repr_is_le_with::<crate::provider::bn256_grumpkin::bn256::Base>(); | ||
test_repr_is_le_with::<crate::provider::secp_secq::secp256k1::Scalar>(); | ||
test_repr_is_le_with::<crate::provider::secp_secq::secp256k1::Base>(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,15 +80,7 @@ where | |
CS: ConstraintSystem<<E as Engine>::Base>, | ||
{ | ||
AllocatedNum::alloc(cs.namespace(|| "allocate scalar as base"), || { | ||
let input_bits = input.unwrap_or(E::Scalar::ZERO).clone().to_le_bits(); | ||
let mut mult = E::Base::ONE; | ||
let mut val = E::Base::ZERO; | ||
for bit in input_bits { | ||
if bit { | ||
val += mult; | ||
} | ||
mult = mult + mult; | ||
} | ||
Comment on lines
-83
to
-91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this be a one-liner?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is morally a one-liner, you're commenting on the removed code. Unless you're talking specifically about inlining the val variable, which I'll take as a nit? |
||
let val = scalar_as_base::<E>(input.unwrap_or(E::Scalar::ZERO)); | ||
Ok(val) | ||
}) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,15 +14,9 @@ | |
use crate::{ | ||
constants::{NIO_NOVA_FOLD, NUM_HASH_BITS}, | ||
gadgets::{ | ||
ecc::AllocatedPoint, | ||
r1cs::{ | ||
conditionally_select_alloc_relaxed_r1cs, | ||
conditionally_select_vec_allocated_relaxed_r1cs_instance, AllocatedR1CSInstance, | ||
AllocatedRelaxedR1CSInstance, | ||
}, | ||
utils::{ | ||
alloc_num_equals, alloc_scalar_as_base, alloc_zero, conditionally_select_vec, le_bits_to_num, | ||
}, | ||
alloc_num_equals, alloc_scalar_as_base, alloc_zero, conditionally_select_alloc_relaxed_r1cs, | ||
conditionally_select_vec, conditionally_select_vec_allocated_relaxed_r1cs_instance, | ||
le_bits_to_num, AllocatedPoint, AllocatedR1CSInstance, AllocatedRelaxedR1CSInstance, | ||
}, | ||
r1cs::{R1CSInstance, RelaxedR1CSInstance}, | ||
traits::{commitment::CommitmentTrait, Engine, ROCircuitTrait, ROConstantsCircuit}, | ||
|
@@ -711,7 +705,7 @@ mod tests { | |
test_shape_cs::TestShapeCS, | ||
}, | ||
constants::{BN_LIMB_WIDTH, BN_N_LIMBS}, | ||
gadgets::utils::scalar_as_base, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More import cleanup possible here too |
||
gadgets::scalar_as_base, | ||
provider::{ | ||
poseidon::PoseidonConstantsCircuit, Bn256EngineIPA, GrumpkinEngine, PallasEngine, | ||
Secp256k1Engine, Secq256k1Engine, VestaEngine, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
use crate::gadgets::utils::alloc_zero; | ||
use crate::gadgets::alloc_zero; | ||
use crate::provider::poseidon::PoseidonConstantsCircuit; | ||
use crate::provider::Bn256EngineIPA; | ||
use crate::provider::PallasEngine; | ||
use crate::provider::Secp256k1Engine; | ||
use crate::provider::VestaEngine; | ||
use crate::supernova::circuit::{StepCircuit, TrivialSecondaryCircuit, TrivialTestCircuit}; | ||
use crate::traits::snark::default_ck_hint; | ||
use crate::{bellpepper::test_shape_cs::TestShapeCS, gadgets::utils::alloc_one}; | ||
Comment on lines
-1
to
-9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to clean up these imports with more |
||
use crate::{bellpepper::test_shape_cs::TestShapeCS, gadgets::alloc_one}; | ||
use abomonation::Abomonation; | ||
use bellpepper_core::num::AllocatedNum; | ||
use bellpepper_core::{ConstraintSystem, SynthesisError}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too