mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-10 16:11:29 +01:00
Add Grumpkin cycle implementation (#181)
* bn256+grumpkin from halo2curves * chore: Integrate halo2curves more extensively - Extend existing tests with additional test cases using the new curve types * fix: Assign correct orders to bn256 and grumpkin scalar fields - Swap scalar orders between grumpkin and bn256 in `impl_traits!` implementation * test: Finish improving test integration with halo2curves - Enhances test coverage for `pasta_curves` and `halo2curves` - Cleans up commented code in `test_ivc_nontrivial` and `test_ivc_nontrivial_with_compression` tests - Updates relevant test cases in `src/lib.rs` to include new curve tests * chore: Remove commented-out/uneeded code in bn254_grumpkin.rs * test: reproduce test_from_label for bn254_grumpkin - Implement the `from_label_serial` function in bn254_grumpkin provider - Add a test to compare parallel and serial implementations of `from_label` function * refactor: Clean up to_coordinate & summarize changes * refactor: rename bn254_grumpkin -> bn256_grumpkin * test: Expand testing for public params digest using bn256 and grumpkin * chore: Update halo2curves dependency in Cargo.toml - Updated the `halo2curves` dependency in `Cargo.toml` to the latest version `0.1.0` from a specific git branch. * refactor: Refactor multi-exponentiation methods across providers - Updated bn256_grumpkin.rs to use the cpu_best_multiexp function from pasta provider instead of its native function. - Modified visibility of cpu_best_multiexp function in pasta.rs from private to crate level. * chore: set up dependencies to import the correct getrandom feature on Wasm --------- Co-authored-by: Leo Alt <leo@ethereum.org>
This commit is contained in:
committed by
GitHub
parent
905ec2d5a1
commit
4b077bcab1
@@ -32,10 +32,15 @@ flate2 = "1.0"
|
||||
bitvec = "1.0"
|
||||
byteorder = "1.4.3"
|
||||
thiserror = "1.0"
|
||||
halo2curves = { version="0.1.0", features = [ "derive_serde" ] }
|
||||
|
||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
||||
pasta-msm = { version = "0.1.4" }
|
||||
|
||||
[target.wasm32-unknown-unknown.dependencies]
|
||||
# see https://github.com/rust-random/rand/pull/948
|
||||
getrandom = { version = "0.2.0", default-features = false, features = ["js"]}
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.4", features = ["html_reports"] }
|
||||
rand = "0.8.4"
|
||||
|
||||
@@ -62,7 +62,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_alloc_bit() {
|
||||
type G = pasta_curves::pallas::Point;
|
||||
test_alloc_bit_with::<G>();
|
||||
test_alloc_bit_with::<pasta_curves::pallas::Point>();
|
||||
test_alloc_bit_with::<crate::provider::bn256_grumpkin::bn256::Point>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +376,7 @@ mod tests {
|
||||
type PastaG2 = pasta_curves::vesta::Point;
|
||||
|
||||
use crate::constants::{BN_LIMB_WIDTH, BN_N_LIMBS};
|
||||
use crate::provider;
|
||||
use crate::{
|
||||
bellperson::r1cs::{NovaShape, NovaWitness},
|
||||
gadgets::utils::scalar_as_base,
|
||||
@@ -471,7 +472,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recursive_circuit() {
|
||||
fn test_recursive_circuit_pasta() {
|
||||
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: ROConstantsCircuit<PastaG2> = PoseidonConstantsCircuit::new();
|
||||
@@ -481,4 +482,19 @@ mod tests {
|
||||
params1, params2, ro_consts1, ro_consts2, 9815, 10347,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recursive_circuit_grumpkin() {
|
||||
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: ROConstantsCircuit<provider::bn256_grumpkin::grumpkin::Point> =
|
||||
PoseidonConstantsCircuit::new();
|
||||
let ro_consts2: ROConstantsCircuit<provider::bn256_grumpkin::bn256::Point> =
|
||||
PoseidonConstantsCircuit::new();
|
||||
|
||||
test_recursive_circuit_with::<
|
||||
provider::bn256_grumpkin::bn256::Point,
|
||||
provider::bn256_grumpkin::grumpkin::Point,
|
||||
>(params1, params2, ro_consts1, ro_consts2, 9983, 10536);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,6 +754,7 @@ mod tests {
|
||||
r1cs::{NovaShape, NovaWitness},
|
||||
{shape_cs::ShapeCS, solver::SatisfyingAssignment},
|
||||
};
|
||||
use crate::provider::bn256_grumpkin::{bn256, grumpkin};
|
||||
use ff::{Field, PrimeFieldBits};
|
||||
use pasta_curves::{arithmetic::CurveAffine, group::Curve, pallas, vesta};
|
||||
use rand::rngs::OsRng;
|
||||
@@ -768,7 +769,6 @@ mod tests {
|
||||
is_infinity: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<G> Point<G>
|
||||
where
|
||||
G: Group,
|
||||
@@ -896,6 +896,9 @@ mod tests {
|
||||
fn test_ecc_ops() {
|
||||
test_ecc_ops_with::<pallas::Affine, pallas::Point>();
|
||||
test_ecc_ops_with::<vesta::Affine, vesta::Point>();
|
||||
|
||||
test_ecc_ops_with::<bn256::Affine, bn256::Point>();
|
||||
test_ecc_ops_with::<grumpkin::Affine, grumpkin::Point>();
|
||||
}
|
||||
|
||||
fn test_ecc_ops_with<C, G>()
|
||||
@@ -977,6 +980,9 @@ mod tests {
|
||||
fn test_ecc_circuit_ops() {
|
||||
test_ecc_circuit_ops_with::<pallas::Point, vesta::Point>();
|
||||
test_ecc_circuit_ops_with::<vesta::Point, pallas::Point>();
|
||||
|
||||
test_ecc_circuit_ops_with::<bn256::Point, grumpkin::Point>();
|
||||
test_ecc_circuit_ops_with::<grumpkin::Point, bn256::Point>();
|
||||
}
|
||||
|
||||
fn test_ecc_circuit_ops_with<G1, G2>()
|
||||
@@ -1027,6 +1033,9 @@ mod tests {
|
||||
fn test_ecc_circuit_add_equal() {
|
||||
test_ecc_circuit_add_equal_with::<pallas::Point, vesta::Point>();
|
||||
test_ecc_circuit_add_equal_with::<vesta::Point, pallas::Point>();
|
||||
|
||||
test_ecc_circuit_add_equal_with::<bn256::Point, grumpkin::Point>();
|
||||
test_ecc_circuit_add_equal_with::<grumpkin::Point, bn256::Point>();
|
||||
}
|
||||
|
||||
fn test_ecc_circuit_add_equal_with<G1, G2>()
|
||||
@@ -1081,6 +1090,9 @@ mod tests {
|
||||
fn test_ecc_circuit_add_negation() {
|
||||
test_ecc_circuit_add_negation_with::<pallas::Point, vesta::Point>();
|
||||
test_ecc_circuit_add_negation_with::<vesta::Point, pallas::Point>();
|
||||
|
||||
test_ecc_circuit_add_negation_with::<bn256::Point, grumpkin::Point>();
|
||||
test_ecc_circuit_add_negation_with::<grumpkin::Point, bn256::Point>();
|
||||
}
|
||||
|
||||
fn test_ecc_circuit_add_negation_with<G1, G2>()
|
||||
|
||||
25
src/lib.rs
25
src/lib.rs
@@ -793,6 +793,7 @@ fn compute_digest<G: Group, T: Serialize>(o: &T) -> G::Scalar {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::provider::bn256_grumpkin::{bn256, grumpkin};
|
||||
use crate::provider::pedersen::CommitmentKeyExtTrait;
|
||||
|
||||
use super::*;
|
||||
@@ -895,6 +896,23 @@ mod tests {
|
||||
trivial_circuit2,
|
||||
"3f7b25f589f2da5ab26254beba98faa54f6442ebf5fa5860caf7b08b576cab00",
|
||||
);
|
||||
|
||||
let trivial_circuit1_grumpkin =
|
||||
TrivialTestCircuit::<<bn256::Point as Group>::Scalar>::default();
|
||||
let trivial_circuit2_grumpkin =
|
||||
TrivialTestCircuit::<<grumpkin::Point as Group>::Scalar>::default();
|
||||
let cubic_circuit1_grumpkin = CubicCircuit::<<bn256::Point as Group>::Scalar>::default();
|
||||
|
||||
test_pp_digest_with::<bn256::Point, grumpkin::Point, _, _>(
|
||||
trivial_circuit1_grumpkin,
|
||||
trivial_circuit2_grumpkin.clone(),
|
||||
"967acca1d6b4731cd65d4072c12bbaca9648f24d7bcc2877aee720e4265d4302",
|
||||
);
|
||||
test_pp_digest_with::<bn256::Point, grumpkin::Point, _, _>(
|
||||
cubic_circuit1_grumpkin,
|
||||
trivial_circuit2_grumpkin,
|
||||
"44629f26a78bf6c4e3077f940232050d1793d304fdba5e221d0cf66f76a37903",
|
||||
);
|
||||
}
|
||||
|
||||
fn test_ivc_trivial_with<G1, G2>()
|
||||
@@ -949,6 +967,8 @@ mod tests {
|
||||
type G1 = pasta_curves::pallas::Point;
|
||||
type G2 = pasta_curves::vesta::Point;
|
||||
test_ivc_trivial_with::<G1, G2>();
|
||||
|
||||
test_ivc_trivial_with::<bn256::Point, grumpkin::Point>();
|
||||
}
|
||||
|
||||
fn test_ivc_nontrivial_with<G1, G2>()
|
||||
@@ -1030,6 +1050,7 @@ mod tests {
|
||||
type G2 = pasta_curves::vesta::Point;
|
||||
|
||||
test_ivc_nontrivial_with::<G1, G2>();
|
||||
test_ivc_nontrivial_with::<bn256::Point, grumpkin::Point>();
|
||||
}
|
||||
|
||||
fn test_ivc_nontrivial_with_compression_with<G1, G2>()
|
||||
@@ -1124,6 +1145,7 @@ mod tests {
|
||||
type G2 = pasta_curves::vesta::Point;
|
||||
|
||||
test_ivc_nontrivial_with_compression_with::<G1, G2>();
|
||||
test_ivc_nontrivial_with_compression_with::<bn256::Point, grumpkin::Point>();
|
||||
}
|
||||
|
||||
fn test_ivc_nontrivial_with_spark_compression_with<G1, G2>()
|
||||
@@ -1221,6 +1243,7 @@ mod tests {
|
||||
type G2 = pasta_curves::vesta::Point;
|
||||
|
||||
test_ivc_nontrivial_with_spark_compression_with::<G1, G2>();
|
||||
test_ivc_nontrivial_with_spark_compression_with::<bn256::Point, grumpkin::Point>();
|
||||
}
|
||||
|
||||
fn test_ivc_nondet_with_compression_with<G1, G2>()
|
||||
@@ -1377,6 +1400,7 @@ mod tests {
|
||||
type G2 = pasta_curves::vesta::Point;
|
||||
|
||||
test_ivc_nondet_with_compression_with::<G1, G2>();
|
||||
test_ivc_nondet_with_compression_with::<bn256::Point, grumpkin::Point>();
|
||||
}
|
||||
|
||||
fn test_ivc_base_with<G1, G2>()
|
||||
@@ -1443,5 +1467,6 @@ mod tests {
|
||||
type G2 = pasta_curves::vesta::Point;
|
||||
|
||||
test_ivc_base_with::<G1, G2>();
|
||||
test_ivc_base_with::<bn256::Point, grumpkin::Point>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +210,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_tiny_r1cs_bellperson() {
|
||||
test_tiny_r1cs_bellperson_with::<G>();
|
||||
|
||||
test_tiny_r1cs_bellperson_with::<crate::provider::bn256_grumpkin::bn256::Point>();
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -384,5 +386,6 @@ mod tests {
|
||||
#[test]
|
||||
fn test_tiny_r1cs() {
|
||||
test_tiny_r1cs_with::<pasta_curves::pallas::Point>();
|
||||
test_tiny_r1cs_with::<crate::provider::bn256_grumpkin::bn256::Point>();
|
||||
}
|
||||
}
|
||||
|
||||
255
src/provider/bn256_grumpkin.rs
Normal file
255
src/provider/bn256_grumpkin.rs
Normal file
@@ -0,0 +1,255 @@
|
||||
//! This module implements the Nova traits for bn256::Point, bn256::Scalar, grumpkin::Point, grumpkin::Scalar.
|
||||
use crate::{
|
||||
provider::{
|
||||
keccak::Keccak256Transcript,
|
||||
pedersen::CommitmentEngine,
|
||||
poseidon::{PoseidonRO, PoseidonROCircuit},
|
||||
},
|
||||
traits::{CompressedGroup, Group, PrimeFieldExt, TranscriptReprTrait},
|
||||
};
|
||||
use digest::{ExtendableOutput, Input};
|
||||
use ff::{FromUniformBytes, PrimeField};
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::Num;
|
||||
use pasta_curves::{
|
||||
self,
|
||||
arithmetic::{CurveAffine, CurveExt},
|
||||
group::{cofactor::CofactorCurveAffine, Curve, Group as AnotherGroup, GroupEncoding},
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
use sha3::Shake256;
|
||||
use std::io::Read;
|
||||
|
||||
use halo2curves::bn256::{
|
||||
G1Affine as Bn256Affine, G1Compressed as Bn256Compressed, G1 as Bn256Point,
|
||||
};
|
||||
use halo2curves::grumpkin::{
|
||||
G1Affine as GrumpkinAffine, G1Compressed as GrumpkinCompressed, G1 as GrumpkinPoint,
|
||||
};
|
||||
|
||||
/// Re-exports that give access to the standard aliases used in the code base, for bn256
|
||||
pub mod bn256 {
|
||||
pub use halo2curves::bn256::{
|
||||
Fq as Base, Fr as Scalar, G1Affine as Affine, G1Compressed as Compressed, G1 as Point,
|
||||
};
|
||||
}
|
||||
|
||||
/// Re-exports that give access to the standard aliases used in the code base, for grumpkin
|
||||
pub mod grumpkin {
|
||||
pub use halo2curves::grumpkin::{
|
||||
Fq as Base, Fr as Scalar, G1Affine as Affine, G1Compressed as Compressed, G1 as Point,
|
||||
};
|
||||
}
|
||||
|
||||
// This implementation behaves in ways specific to the bn256/grumpkin curves in:
|
||||
// - to_coordinates,
|
||||
// - vartime_multiscalar_mul, where it does not call into accelerated implementations.
|
||||
macro_rules! impl_traits {
|
||||
(
|
||||
$name:ident,
|
||||
$name_compressed:ident,
|
||||
$name_curve:ident,
|
||||
$name_curve_affine:ident,
|
||||
$order_str:literal
|
||||
) => {
|
||||
impl Group for $name::Point {
|
||||
type Base = $name::Base;
|
||||
type Scalar = $name::Scalar;
|
||||
type CompressedGroupElement = $name_compressed;
|
||||
type PreprocessedGroupElement = $name::Affine;
|
||||
type RO = PoseidonRO<Self::Base, Self::Scalar>;
|
||||
type ROCircuit = PoseidonROCircuit<Self::Base>;
|
||||
type TE = Keccak256Transcript<Self>;
|
||||
type CE = CommitmentEngine<Self>;
|
||||
|
||||
fn vartime_multiscalar_mul(
|
||||
scalars: &[Self::Scalar],
|
||||
bases: &[Self::PreprocessedGroupElement],
|
||||
) -> Self {
|
||||
cpu_best_multiexp(scalars, bases)
|
||||
}
|
||||
|
||||
fn preprocessed(&self) -> Self::PreprocessedGroupElement {
|
||||
self.to_affine()
|
||||
}
|
||||
|
||||
fn compress(&self) -> Self::CompressedGroupElement {
|
||||
self.to_bytes()
|
||||
}
|
||||
|
||||
fn from_label(label: &'static [u8], n: usize) -> Vec<Self::PreprocessedGroupElement> {
|
||||
let mut shake = Shake256::default();
|
||||
shake.input(label);
|
||||
let mut reader = shake.xof_result();
|
||||
let mut uniform_bytes_vec = Vec::new();
|
||||
for _ in 0..n {
|
||||
let mut uniform_bytes = [0u8; 32];
|
||||
reader.read_exact(&mut uniform_bytes).unwrap();
|
||||
uniform_bytes_vec.push(uniform_bytes);
|
||||
}
|
||||
let gens_proj: Vec<$name_curve> = (0..n)
|
||||
.collect::<Vec<usize>>()
|
||||
.into_par_iter()
|
||||
.map(|i| {
|
||||
let hash = $name_curve::hash_to_curve("from_uniform_bytes");
|
||||
hash(&uniform_bytes_vec[i])
|
||||
})
|
||||
.collect();
|
||||
|
||||
let num_threads = rayon::current_num_threads();
|
||||
if gens_proj.len() > num_threads {
|
||||
let chunk = (gens_proj.len() as f64 / num_threads as f64).ceil() as usize;
|
||||
(0..num_threads)
|
||||
.collect::<Vec<usize>>()
|
||||
.into_par_iter()
|
||||
.map(|i| {
|
||||
let start = i * chunk;
|
||||
let end = if i == num_threads - 1 {
|
||||
gens_proj.len()
|
||||
} else {
|
||||
core::cmp::min((i + 1) * chunk, gens_proj.len())
|
||||
};
|
||||
if end > start {
|
||||
let mut gens = vec![$name_curve_affine::identity(); end - start];
|
||||
<Self as Curve>::batch_normalize(&gens_proj[start..end], &mut gens);
|
||||
gens
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
})
|
||||
.collect::<Vec<Vec<$name_curve_affine>>>()
|
||||
.into_par_iter()
|
||||
.flatten()
|
||||
.collect()
|
||||
} else {
|
||||
let mut gens = vec![$name_curve_affine::identity(); n];
|
||||
<Self as Curve>::batch_normalize(&gens_proj, &mut gens);
|
||||
gens
|
||||
}
|
||||
}
|
||||
|
||||
fn to_coordinates(&self) -> (Self::Base, Self::Base, bool) {
|
||||
let coordinates = self.to_affine().coordinates();
|
||||
if coordinates.is_some().unwrap_u8() == 1
|
||||
// The bn256/grumpkin convention is to define and return the identity point's affine encoding (not None)
|
||||
&& (Self::PreprocessedGroupElement::identity() != self.to_affine())
|
||||
{
|
||||
(*coordinates.unwrap().x(), *coordinates.unwrap().y(), false)
|
||||
} else {
|
||||
(Self::Base::zero(), Self::Base::zero(), true)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_curve_params() -> (Self::Base, Self::Base, BigInt) {
|
||||
let A = $name::Point::a();
|
||||
let B = $name::Point::b();
|
||||
let order = BigInt::from_str_radix($order_str, 16).unwrap();
|
||||
|
||||
(A, B, order)
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
$name::Point::identity()
|
||||
}
|
||||
|
||||
fn get_generator() -> Self {
|
||||
$name::Point::generator()
|
||||
}
|
||||
}
|
||||
|
||||
impl PrimeFieldExt for $name::Scalar {
|
||||
fn from_uniform(bytes: &[u8]) -> Self {
|
||||
let bytes_arr: [u8; 64] = bytes.try_into().unwrap();
|
||||
$name::Scalar::from_uniform_bytes(&bytes_arr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group> TranscriptReprTrait<G> for $name_compressed {
|
||||
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||
self.as_ref().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl CompressedGroup for $name_compressed {
|
||||
type GroupElement = $name::Point;
|
||||
|
||||
fn decompress(&self) -> Option<$name::Point> {
|
||||
Some($name_curve::from_bytes(&self).unwrap())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<G: Group> TranscriptReprTrait<G> for grumpkin::Base {
|
||||
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||
self.to_repr().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group> TranscriptReprTrait<G> for grumpkin::Scalar {
|
||||
fn to_transcript_bytes(&self) -> Vec<u8> {
|
||||
self.to_repr().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl_traits!(
|
||||
bn256,
|
||||
Bn256Compressed,
|
||||
Bn256Point,
|
||||
Bn256Affine,
|
||||
"30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"
|
||||
);
|
||||
|
||||
impl_traits!(
|
||||
grumpkin,
|
||||
GrumpkinCompressed,
|
||||
GrumpkinPoint,
|
||||
GrumpkinAffine,
|
||||
"30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
|
||||
);
|
||||
|
||||
/// Performs a multi-exponentiation operation without GPU acceleration.
|
||||
///
|
||||
/// This function will panic if coeffs and bases have a different length.
|
||||
///
|
||||
/// This will use multithreading if beneficial.
|
||||
/// Adapted from zcash/halo2
|
||||
// TODO: update once https://github.com/privacy-scaling-explorations/halo2curves/pull/29
|
||||
// (or a successor thereof) is merged
|
||||
fn cpu_best_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve {
|
||||
crate::provider::pasta::cpu_best_multiexp(coeffs, bases)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
type G = bn256::Point;
|
||||
|
||||
fn from_label_serial(label: &'static [u8], n: usize) -> Vec<Bn256Affine> {
|
||||
let mut shake = Shake256::default();
|
||||
shake.input(label);
|
||||
let mut reader = shake.xof_result();
|
||||
let mut ck = Vec::new();
|
||||
for _ in 0..n {
|
||||
let mut uniform_bytes = [0u8; 32];
|
||||
reader.read_exact(&mut uniform_bytes).unwrap();
|
||||
let hash = bn256::Point::hash_to_curve("from_uniform_bytes");
|
||||
ck.push(hash(&uniform_bytes).to_affine());
|
||||
}
|
||||
ck
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_label() {
|
||||
let label = b"test_from_label";
|
||||
for n in [
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1021,
|
||||
] {
|
||||
let ck_par = <G as Group>::from_label(label, n);
|
||||
let ck_ser = from_label_serial(label, n);
|
||||
assert_eq!(ck_par.len(), n);
|
||||
assert_eq!(ck_ser.len(), n);
|
||||
assert_eq!(ck_par, ck_ser);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,13 +95,14 @@ impl<G: Group> TranscriptEngineTrait<G> for Keccak256Transcript<G> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
provider::bn256_grumpkin::bn256,
|
||||
provider::keccak::Keccak256Transcript,
|
||||
traits::{Group, TranscriptEngineTrait},
|
||||
};
|
||||
use ff::PrimeField;
|
||||
use sha3::{Digest, Keccak256};
|
||||
|
||||
fn test_keccak_transcript_with<G: Group>() {
|
||||
fn test_keccak_transcript_with<G: Group>(expected_h1: &'static str, expected_h2: &'static str) {
|
||||
let mut transcript: Keccak256Transcript<G> = Keccak256Transcript::new(b"test");
|
||||
|
||||
// two scalars
|
||||
@@ -114,10 +115,7 @@ mod tests {
|
||||
|
||||
// make a challenge
|
||||
let c1: <G as Group>::Scalar = transcript.squeeze(b"c1").unwrap();
|
||||
assert_eq!(
|
||||
hex::encode(c1.to_repr().as_ref()),
|
||||
"432d5811c8be3d44d47f52108a8749ae18482efd1a37b830f966456b5d75340c"
|
||||
);
|
||||
assert_eq!(hex::encode(c1.to_repr().as_ref()), expected_h1);
|
||||
|
||||
// a scalar
|
||||
let s3 = <G as Group>::Scalar::from(128u64);
|
||||
@@ -127,16 +125,20 @@ mod tests {
|
||||
|
||||
// make a challenge
|
||||
let c2: <G as Group>::Scalar = transcript.squeeze(b"c2").unwrap();
|
||||
assert_eq!(
|
||||
hex::encode(c2.to_repr().as_ref()),
|
||||
"65f7908d53abcd18f3b1d767456ef9009b91c7566a635e9ca7be26e21d4d7a10"
|
||||
);
|
||||
assert_eq!(hex::encode(c2.to_repr().as_ref()), expected_h2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keccak_transcript() {
|
||||
type G = pasta_curves::pallas::Point;
|
||||
test_keccak_transcript_with::<G>()
|
||||
test_keccak_transcript_with::<pasta_curves::pallas::Point>(
|
||||
"432d5811c8be3d44d47f52108a8749ae18482efd1a37b830f966456b5d75340c",
|
||||
"65f7908d53abcd18f3b1d767456ef9009b91c7566a635e9ca7be26e21d4d7a10",
|
||||
);
|
||||
|
||||
test_keccak_transcript_with::<bn256::Point>(
|
||||
"93f9160d5501865b399ee4ff0ffe17b697a4023e33e931e2597d36e6cc4ac602",
|
||||
"bca8bdb96608a8277a7cb34bd493dfbc5baf2a080d1d6c9d32d7ab4f238eb803",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//! `RO` traits with Poseidon
|
||||
//! `EvaluationEngine` with an IPA-based polynomial evaluation argument
|
||||
|
||||
pub mod bn256_grumpkin;
|
||||
pub mod ipa_pc;
|
||||
pub mod keccak;
|
||||
pub mod pasta;
|
||||
|
||||
@@ -320,7 +320,7 @@ fn cpu_multiexp_serial<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C], acc: &
|
||||
///
|
||||
/// This will use multithreading if beneficial.
|
||||
/// Adapted from zcash/halo2
|
||||
fn cpu_best_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve {
|
||||
pub(crate) fn cpu_best_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve {
|
||||
assert_eq!(coeffs.len(), bases.len());
|
||||
|
||||
let num_threads = rayon::current_num_threads();
|
||||
|
||||
@@ -201,6 +201,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::provider::bn256_grumpkin::bn256;
|
||||
use crate::{
|
||||
bellperson::solver::SatisfyingAssignment, constants::NUM_CHALLENGE_BITS,
|
||||
gadgets::utils::le_bits_to_num, traits::Group,
|
||||
@@ -242,8 +243,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_ro() {
|
||||
type G = pasta_curves::pallas::Point;
|
||||
|
||||
test_poseidon_ro_with::<G>()
|
||||
test_poseidon_ro_with::<pasta_curves::pallas::Point>();
|
||||
test_poseidon_ro_with::<bn256::Point>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2185,6 +2185,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>, C: StepCircuit<G::Scala
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::provider::bn256_grumpkin::bn256;
|
||||
use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
|
||||
use core::marker::PhantomData;
|
||||
use ff::PrimeField;
|
||||
@@ -2244,6 +2245,7 @@ mod tests {
|
||||
type EE = crate::provider::ipa_pc::EvaluationEngine<G>;
|
||||
|
||||
test_spartan_snark_with::<G, EE>();
|
||||
test_spartan_snark_with::<_, crate::provider::ipa_pc::EvaluationEngine<bn256::Point>>();
|
||||
}
|
||||
|
||||
fn test_spartan_snark_with<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>>() {
|
||||
|
||||
Reference in New Issue
Block a user