From c0aa61ff3a207d76af58a16365da3f1f8ebcceae Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 19:10:43 +0200 Subject: [PATCH 01/63] Integration with ginger-algebra-ocl: MSM --- Cargo.toml | 1 + algebra-utils/Cargo.toml | 49 +++++++++ {algebra => algebra-utils}/benches/fft/mod.rs | 0 .../src/fft/domain/basic_radix_2_domain.rs | 2 +- .../src/fft/domain/domain_selector.rs | 4 +- .../src/fft/domain/mixed_radix_2_domain.rs | 2 +- .../src/fft/domain/mod.rs | 8 +- .../src/fft/domain/test.rs | 4 +- .../src/fft/evaluations.rs | 2 +- {algebra => algebra-utils}/src/fft/mod.rs | 0 .../src/fft/multicore.rs | 0 .../src/fft/polynomial/dense.rs | 8 +- .../src/fft/polynomial/mod.rs | 2 +- .../src/fft/polynomial/sparse.rs | 6 +- algebra-utils/src/lib.rs | 21 ++++ .../src/msm/fixed_base.rs | 2 +- {algebra => algebra-utils}/src/msm/mod.rs | 0 .../src/msm/variable_base.rs | 102 +++++++++++++++++- algebra/Cargo.toml | 3 +- algebra/src/lib.rs | 10 -- proof-systems/Cargo.toml | 3 +- proof-systems/src/gm17/generator.rs | 5 +- proof-systems/src/gm17/prover.rs | 3 +- proof-systems/src/gm17/r1cs_to_sap.rs | 2 +- proof-systems/src/groth16/generator.rs | 5 +- proof-systems/src/groth16/prover.rs | 3 +- proof-systems/src/groth16/r1cs_to_qap.rs | 2 +- 27 files changed, 203 insertions(+), 46 deletions(-) create mode 100644 algebra-utils/Cargo.toml rename {algebra => algebra-utils}/benches/fft/mod.rs (100%) rename {algebra => algebra-utils}/src/fft/domain/basic_radix_2_domain.rs (99%) rename {algebra => algebra-utils}/src/fft/domain/domain_selector.rs (98%) rename {algebra => algebra-utils}/src/fft/domain/mixed_radix_2_domain.rs (99%) rename {algebra => algebra-utils}/src/fft/domain/mod.rs (98%) rename {algebra => algebra-utils}/src/fft/domain/test.rs (95%) rename {algebra => algebra-utils}/src/fft/evaluations.rs (99%) rename {algebra => algebra-utils}/src/fft/mod.rs (100%) rename {algebra => algebra-utils}/src/fft/multicore.rs (100%) rename {algebra => algebra-utils}/src/fft/polynomial/dense.rs (99%) rename {algebra => algebra-utils}/src/fft/polynomial/mod.rs (99%) rename {algebra => algebra-utils}/src/fft/polynomial/sparse.rs (98%) create mode 100644 algebra-utils/src/lib.rs rename {algebra => algebra-utils}/src/msm/fixed_base.rs (97%) rename {algebra => algebra-utils}/src/msm/mod.rs (100%) rename {algebra => algebra-utils}/src/msm/variable_base.rs (72%) diff --git a/Cargo.toml b/Cargo.toml index 3f4feab5b..cffc64d5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "algebra", + "algebra-utils", "bench-utils", "primitives", "proof-systems", diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml new file mode 100644 index 000000000..13cb9a1f3 --- /dev/null +++ b/algebra-utils/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "algebra-utils" +version = "0.1.0" +authors = [ + "Sean Bowe", + "Alessandro Chiesa", + "Matthew Green", + "Ian Miers", + "Pratyush Mishra", + "Howard Wu", + "Daniele Di Benedetto ", + "Marcelo Kaihara ", + "Ulrich Haboeck " +] +description = "A library for finite fields, elliptic curves and FFTs evaluation over prime finite fields" +include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] +license = "MIT/Apache-2.0" +edition = "2018" + +################################# Dependencies ################################ + +[dependencies] +algebra = { path = "../algebra", features = [ "parallel" ] } + +rand = { version = "0.7" } + +rayon = { version = "1", optional = true } + +# gpu feature +algebra-kernels = { path = "../../ginger-algebra-ocl/algebra-kernels", optional = true } +bellperson = { path = "../../ginger-algebra-ocl/bellperson", optional = true } +crossbeam = { version = "0.7", optional = true } + +[dev-dependencies] +blake2 = "0.7" +criterion = "0.2" +rand_xorshift = { version = "0.2" } +paste = "1.0" +algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } +algebra-kernels = { path = "../../ginger-algebra-ocl/algebra-kernels", features = ["bls12_381", "jubjub"] } + +[features] +parallel = [ "rayon" ] +fft = [] +gpu = [ "algebra-kernels", "bellperson", "crossbeam" ] + +[build-dependencies] +rustc_version = "0.2" \ No newline at end of file diff --git a/algebra/benches/fft/mod.rs b/algebra-utils/benches/fft/mod.rs similarity index 100% rename from algebra/benches/fft/mod.rs rename to algebra-utils/benches/fft/mod.rs diff --git a/algebra/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs similarity index 99% rename from algebra/src/fft/domain/basic_radix_2_domain.rs rename to algebra-utils/src/fft/domain/basic_radix_2_domain.rs index 20850ba8e..955178644 100644 --- a/algebra/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -1,4 +1,4 @@ -use crate::{FpParameters, PrimeField}; +use algebra::{FpParameters, PrimeField}; use crate::{multicore::Worker, EvaluationDomain}; use std::fmt; use rayon::prelude::*; diff --git a/algebra/src/fft/domain/domain_selector.rs b/algebra-utils/src/fft/domain/domain_selector.rs similarity index 98% rename from algebra/src/fft/domain/domain_selector.rs rename to algebra-utils/src/fft/domain/domain_selector.rs index 5df018503..abdea5af5 100644 --- a/algebra/src/fft/domain/domain_selector.rs +++ b/algebra-utils/src/fft/domain/domain_selector.rs @@ -1,5 +1,5 @@ use crate::{BasicRadix2Domain, EvaluationDomain, MixedRadix2Domain}; -use crate::{ +use algebra::{ PrimeField, FpParameters, }; @@ -46,7 +46,7 @@ pub fn get_best_evaluation_domain(num_coeffs: usize) -> Option: Debug } u } else { - use crate::fields::batch_inversion; + use algebra::fields::batch_inversion; let mut l = (t_size - &one) * &self.size_inv(); let mut r = one; @@ -221,8 +221,8 @@ impl Iterator for Elements { #[cfg(test)] mod tests { use crate::get_best_evaluation_domain; - use crate::Field; - use crate::fields::mnt6753::fr::Fr; + use algebra::Field; + use algebra::fields::mnt6753::fr::Fr; use rand::{Rng, thread_rng}; #[test] diff --git a/algebra/src/fft/domain/test.rs b/algebra-utils/src/fft/domain/test.rs similarity index 95% rename from algebra/src/fft/domain/test.rs rename to algebra-utils/src/fft/domain/test.rs index cf6c1b7ab..b79e46d5e 100644 --- a/algebra/src/fft/domain/test.rs +++ b/algebra-utils/src/fft/domain/test.rs @@ -1,5 +1,5 @@ -use crate::{UniformRand, Field, PrimeField, FpParameters}; -use crate::curves::{mnt6753::MNT6, PairingEngine}; +use algebra::{UniformRand, Field, PrimeField, FpParameters}; +use algebra::curves::{mnt6753::MNT6, PairingEngine}; use crate::{domain::*, multicore::*}; use rand; use std::cmp::min; diff --git a/algebra/src/fft/evaluations.rs b/algebra-utils/src/fft/evaluations.rs similarity index 99% rename from algebra/src/fft/evaluations.rs rename to algebra-utils/src/fft/evaluations.rs index f4f4b7994..af43b6460 100644 --- a/algebra/src/fft/evaluations.rs +++ b/algebra-utils/src/fft/evaluations.rs @@ -1,7 +1,7 @@ //! A polynomial represented in evaluations form. use std::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; -use crate::PrimeField; +use algebra::PrimeField; use crate::{DensePolynomial, EvaluationDomain}; /// Stores a polynomial in evaluation form. diff --git a/algebra/src/fft/mod.rs b/algebra-utils/src/fft/mod.rs similarity index 100% rename from algebra/src/fft/mod.rs rename to algebra-utils/src/fft/mod.rs diff --git a/algebra/src/fft/multicore.rs b/algebra-utils/src/fft/multicore.rs similarity index 100% rename from algebra/src/fft/multicore.rs rename to algebra-utils/src/fft/multicore.rs diff --git a/algebra/src/fft/polynomial/dense.rs b/algebra-utils/src/fft/polynomial/dense.rs similarity index 99% rename from algebra/src/fft/polynomial/dense.rs rename to algebra-utils/src/fft/polynomial/dense.rs index b9fd96ec8..d8ae9efdf 100644 --- a/algebra/src/fft/polynomial/dense.rs +++ b/algebra-utils/src/fft/polynomial/dense.rs @@ -3,8 +3,8 @@ use std::fmt; use std::ops::{Add, AddAssign, Deref, DerefMut, Div, Mul, Neg, Sub, SubAssign}; -use crate::{Field, PrimeField, get_best_evaluation_domain}; -use crate::{Evaluations, EvaluationDomain, DenseOrSparsePolynomial}; +use algebra::{Field, PrimeField}; +use crate::{Evaluations, EvaluationDomain, DenseOrSparsePolynomial, get_best_evaluation_domain}; use rand::Rng; use rayon::prelude::*; @@ -361,8 +361,8 @@ impl<'a, 'b, F: PrimeField> Mul<&'a DensePolynomial> for &'b DensePolynomial< mod tests { use crate::domain::get_best_evaluation_domain; use crate::polynomial::*; - use crate::fields::{mnt6753::fr::Fr, Field}; - use crate::UniformRand; + use algebra::fields::{mnt6753::fr::Fr, Field}; + use algebra::UniformRand; use rand::thread_rng; #[test] diff --git a/algebra/src/fft/polynomial/mod.rs b/algebra-utils/src/fft/polynomial/mod.rs similarity index 99% rename from algebra/src/fft/polynomial/mod.rs rename to algebra-utils/src/fft/polynomial/mod.rs index 226d51686..be077ddf7 100644 --- a/algebra/src/fft/polynomial/mod.rs +++ b/algebra-utils/src/fft/polynomial/mod.rs @@ -1,6 +1,6 @@ //! Work with sparse and dense polynomials. -use crate::{Field, PrimeField}; +use algebra::{Field, PrimeField}; use std::borrow::Cow; use std::convert::TryInto; use DenseOrSparsePolynomial::*; diff --git a/algebra/src/fft/polynomial/sparse.rs b/algebra-utils/src/fft/polynomial/sparse.rs similarity index 98% rename from algebra/src/fft/polynomial/sparse.rs rename to algebra-utils/src/fft/polynomial/sparse.rs index b324bc550..6a49e27de 100644 --- a/algebra/src/fft/polynomial/sparse.rs +++ b/algebra-utils/src/fft/polynomial/sparse.rs @@ -2,7 +2,7 @@ use std::fmt; -use crate::{Field, PrimeField}; +use algebra::{Field, PrimeField}; use crate::DensePolynomial; use crate::{DenseOrSparsePolynomial, EvaluationDomain, Evaluations}; @@ -128,8 +128,8 @@ impl Into> for SparsePolynomial { #[cfg(test)] mod tests { use crate::{get_best_evaluation_domain, DensePolynomial, SparsePolynomial}; - use crate::fields::mnt6753::fr::Fr; - use crate::Field; + use algebra::fields::mnt6753::fr::Fr; + use algebra::Field; #[test] fn evaluate_over_domain() { diff --git a/algebra-utils/src/lib.rs b/algebra-utils/src/lib.rs new file mode 100644 index 000000000..99f06d45d --- /dev/null +++ b/algebra-utils/src/lib.rs @@ -0,0 +1,21 @@ +#![deny(unused_import_braces, unused_qualifications, trivial_casts)] +#![deny(trivial_numeric_casts, variant_size_differences)] +#![deny(non_shorthand_field_patterns, unused_attributes, unused_imports)] +#![deny(unused_extern_crates, renamed_and_removed_lints, unused_allocation)] +#![deny(unused_comparisons, bare_trait_objects, const_err, unused_must_use)] +#![deny(unused_mut, unused_unsafe, private_in_public)] +#![cfg_attr(use_asm, feature(llvm_asm))] +#![cfg_attr(not(use_asm), forbid(unsafe_code))] +#![cfg_attr(use_asm, deny(unsafe_code))] + +#[cfg(feature = "parallel")] +pub mod msm; +#[cfg(feature = "parallel")] +pub use self::msm::*; + +#[cfg(feature = "fft")] +pub mod fft; +#[cfg(feature = "fft")] +pub use self::fft::*; + +pub type Error = Box; \ No newline at end of file diff --git a/algebra/src/msm/fixed_base.rs b/algebra-utils/src/msm/fixed_base.rs similarity index 97% rename from algebra/src/msm/fixed_base.rs rename to algebra-utils/src/msm/fixed_base.rs index 610b4ff70..c5af79505 100644 --- a/algebra/src/msm/fixed_base.rs +++ b/algebra-utils/src/msm/fixed_base.rs @@ -1,4 +1,4 @@ -use crate::{BigInteger, FpParameters, PrimeField, ProjectiveCurve}; +use algebra::{BigInteger, FpParameters, PrimeField, ProjectiveCurve}; use rayon::prelude::*; pub struct FixedBaseMSM; diff --git a/algebra/src/msm/mod.rs b/algebra-utils/src/msm/mod.rs similarity index 100% rename from algebra/src/msm/mod.rs rename to algebra-utils/src/msm/mod.rs diff --git a/algebra/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs similarity index 72% rename from algebra/src/msm/variable_base.rs rename to algebra-utils/src/msm/variable_base.rs index e6aa67e89..974b0fc70 100644 --- a/algebra/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -1,6 +1,15 @@ -use crate::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, ProjectiveCurve}; +use algebra::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, ProjectiveCurve}; use rayon::prelude::*; +#[cfg(feature = "gpu")] +use algebra_kernels::msm::{ + get_cpu_utilization, get_kernels, get_gpu_min_length +}; +#[cfg(feature = "gpu")] +use bellperson::gpu::GPUError; +#[cfg(feature = "gpu")] +use crossbeam::thread; + pub struct VariableBaseMSM; impl VariableBaseMSM { @@ -160,22 +169,105 @@ impl VariableBaseMSM { }) + lowest } + #[cfg(feature = "gpu")] + fn msm_inner_gpu( + bases: &[G], + scalars: &[::BigInt] + ) -> G::Projective + where + G: AffineCurve, + G::Projective: ProjectiveCurve + { + let zero = G::Projective::zero(); + + let mut n = bases.len(); + let cpu_n; + + let kernels = get_kernels().unwrap(); + let num_devices = kernels.len(); + let gpu_min_length = get_gpu_min_length(); + + if gpu_min_length > n { + cpu_n = n; + n = 0; + } else { + cpu_n = ((n as f64) * get_cpu_utilization()) as usize; + n = n - cpu_n; + } + + let (cpu_bases, bases) = bases.split_at(cpu_n); + let (cpu_scalars, scalars) = scalars.split_at(cpu_n); + + let chunk_size = ((n as f64) / (num_devices as f64)).ceil() as usize; + + match thread::scope(|s| -> Result { + let mut acc = G::Projective::zero(); + let mut threads = Vec::new(); + + if n > 0 { + for ((bases, scalars), kern) in bases + .chunks(chunk_size) + .zip(scalars.chunks(chunk_size)) + .zip(kernels.iter()) + { + threads.push(s.spawn( + move |_| -> Result { + let mut acc = G::Projective::zero(); + for (bases, scalars) in bases.chunks(kern.n).zip(scalars.chunks(kern.n)) { + let result = kern.msm(bases, scalars, bases.len())?; + acc.add_assign_mixed(&result.into_affine()); + } + Ok(acc) + }, + )); + } + } + + if cpu_n > 0 { + threads.push(s.spawn( + move |_| -> Result { + let acc = Self::msm_inner(cpu_bases, cpu_scalars); + Ok(acc) + } + )) + } + + let mut results = vec![]; + for t in threads { + results.push(t.join()); + } + for r in results { + acc.add_assign_mixed(&r??.into_affine()); + } + + Ok(acc) + }) { + Ok(res) => res.unwrap(), + Err(_) => zero + } + } + pub fn multi_scalar_mul( bases: &[G], scalars: &[::BigInt], ) -> G::Projective { - Self::msm_inner(bases, scalars) + + #[cfg(not(feature = "gpu"))] + return Self::msm_inner(bases, scalars); + + #[cfg(feature = "gpu")] + return Self::msm_inner_gpu(bases, scalars); } } #[cfg(test)] mod test { use super::*; - use crate::curves::bls12_381::G1Projective; - use crate::fields::bls12_381::Fr; + use algebra::curves::bls12_381::G1Projective; + use algebra::fields::bls12_381::Fr; use rand::SeedableRng; use rand_xorshift::XorShiftRng; - use crate::UniformRand; + use algebra::UniformRand; fn naive_var_base_msm( bases: &[G], diff --git a/algebra/Cargo.toml b/algebra/Cargo.toml index 4d50ca4c8..9cf62878b 100644 --- a/algebra/Cargo.toml +++ b/algebra/Cargo.toml @@ -43,12 +43,11 @@ algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", [features] parallel = [ "rayon" ] -fft = ["rayon"] n_fold = [] llvm_asm = [] bls12_377 = [] -bls12_381 = [] +bls12_381 = [ "jubjub" ] edwards_bls12 = [] edwards_sw6 = [] jubjub = [] diff --git a/algebra/src/lib.rs b/algebra/src/lib.rs index 267fe993c..a9f381c3f 100644 --- a/algebra/src/lib.rs +++ b/algebra/src/lib.rs @@ -40,14 +40,4 @@ pub use self::rand::*; mod to_field_vec; pub use to_field_vec::ToConstraintField; -#[cfg(feature = "parallel")] -pub mod msm; -#[cfg(feature = "parallel")] -pub use self::msm::*; - -#[cfg(feature = "fft")] -pub mod fft; -#[cfg(feature = "fft")] -pub use self::fft::*; - pub type Error = Box; \ No newline at end of file diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index aa6deb58a..a2f6c65cc 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -20,7 +20,8 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = [ "parallel", "fft" ] } +algebra = { path = "../algebra", features = [ "parallel" ] } +algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } r1cs-core = { path = "../r1cs/core" } bench-utils = { path = "../bench-utils" } diff --git a/proof-systems/src/gm17/generator.rs b/proof-systems/src/gm17/generator.rs index 70fe87588..60c1d0cac 100644 --- a/proof-systems/src/gm17/generator.rs +++ b/proof-systems/src/gm17/generator.rs @@ -1,6 +1,7 @@ -use algebra::fft::domain::get_best_evaluation_domain; +use algebra_utils::fft::domain::get_best_evaluation_domain; +use algebra_utils::msm::FixedBaseMSM; use algebra::{ - msm::FixedBaseMSM, UniformRand, + UniformRand, AffineCurve, Field, PairingEngine, PrimeField, ProjectiveCurve, }; diff --git a/proof-systems/src/gm17/prover.rs b/proof-systems/src/gm17/prover.rs index 0d2967b6b..f2d886dd9 100644 --- a/proof-systems/src/gm17/prover.rs +++ b/proof-systems/src/gm17/prover.rs @@ -2,8 +2,9 @@ use rand::Rng; use rayon::prelude::*; use algebra::{ - UniformRand, msm::VariableBaseMSM, AffineCurve, Field, PairingEngine, PrimeField, ProjectiveCurve, + UniformRand, AffineCurve, Field, PairingEngine, PrimeField, ProjectiveCurve, }; +use algebra_utils::msm::VariableBaseMSM; use crate::gm17::{Parameters, Proof}; use crate::gm17::r1cs_to_sap::R1CStoSAP; diff --git a/proof-systems/src/gm17/r1cs_to_sap.rs b/proof-systems/src/gm17/r1cs_to_sap.rs index 3d642be0f..f05680db3 100644 --- a/proof-systems/src/gm17/r1cs_to_sap.rs +++ b/proof-systems/src/gm17/r1cs_to_sap.rs @@ -1,4 +1,4 @@ -use algebra::fft::domain::get_best_evaluation_domain; +use algebra_utils::fft::domain::get_best_evaluation_domain; use algebra::{Field, PairingEngine}; use crate::gm17::{generator::KeypairAssembly, prover::ProvingAssignment}; diff --git a/proof-systems/src/groth16/generator.rs b/proof-systems/src/groth16/generator.rs index 0c08908de..ef640f151 100644 --- a/proof-systems/src/groth16/generator.rs +++ b/proof-systems/src/groth16/generator.rs @@ -1,5 +1,6 @@ -use algebra::{groups::Group, msm::FixedBaseMSM, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand}; -use algebra::fft::domain::get_best_evaluation_domain; +use algebra::{groups::Group, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand}; +use algebra_utils::msm::FixedBaseMSM; +use algebra_utils::fft::domain::get_best_evaluation_domain; use r1cs_core::{ ConstraintSynthesizer, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable, diff --git a/proof-systems/src/groth16/prover.rs b/proof-systems/src/groth16/prover.rs index 6d9f48a75..0654f770a 100644 --- a/proof-systems/src/groth16/prover.rs +++ b/proof-systems/src/groth16/prover.rs @@ -2,9 +2,10 @@ use rand::Rng; use rayon::prelude::*; use algebra::{ - groups::Group, msm::VariableBaseMSM, AffineCurve, Field, PairingEngine, PrimeField, + groups::Group, AffineCurve, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand, }; +use algebra_utils::msm::VariableBaseMSM; use crate::groth16::{push_constraints, r1cs_to_qap::R1CStoQAP, Parameters, Proof}; diff --git a/proof-systems/src/groth16/r1cs_to_qap.rs b/proof-systems/src/groth16/r1cs_to_qap.rs index 0bb981de9..2dc547ae8 100644 --- a/proof-systems/src/groth16/r1cs_to_qap.rs +++ b/proof-systems/src/groth16/r1cs_to_qap.rs @@ -1,5 +1,5 @@ use algebra::{Field, PairingEngine}; -use algebra::fft::domain::get_best_evaluation_domain; +use algebra_utils::fft::domain::get_best_evaluation_domain; use crate::groth16::{generator::KeypairAssembly, prover::ProvingAssignment}; use r1cs_core::{ConstraintSystem, Index, SynthesisError}; From ac3368e6b695d0c71d3eae288250688a4f566790 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 20:04:38 +0200 Subject: [PATCH 02/63] FFT GPU integration --- .../src/fft/domain/basic_radix_2_domain.rs | 29 ++++++++++++++++++- .../src/fft/domain/mixed_radix_2_domain.rs | 27 +++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs index 955178644..96f22e423 100644 --- a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -5,6 +5,9 @@ use rayon::prelude::*; use rand::Rng; use std::any::Any; +#[cfg(feature = "gpu")] +use algebra_kernels::fft::get_kernels; + /// Defines a domain over which finite field (I)FFTs can be performed. Works /// only for fields that have a large multiplicative subgroup of size that is /// a power-of-2. The roots of the target polynomial will be the powers of a @@ -125,13 +128,21 @@ impl BasicRadix2Domain { } fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { + #[cfg(not(feature = "gpu"))] + Self::best_cpu_fft(a, worker, omega, log_n); + + #[cfg(feature = "gpu")] + Self::gpu_fft(a, worker, omega, log_n); + } + + fn best_cpu_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { let log_cpus = worker.log_num_cpus(); if log_n <= log_cpus { Self::serial_fft(a, omega, log_n); } else { Self::parallel_fft(a, worker, omega, log_n, log_cpus); - } + } } pub(crate) fn serial_fft(a: &mut [F], omega: F, log_n: u32) { @@ -234,6 +245,22 @@ impl BasicRadix2Domain { } }); } + + #[cfg(feature = "gpu")] + pub(crate) fn gpu_fft(a: &mut [F], cpu_worker: &Worker, omega: F, log_n: u32) { + + match get_kernels() { + Ok(kernels) => { + match kernels[0].radix_fft(a, &omega, log_n) { + Ok(_) => {}, + Err(error) => { panic!(error); } + } + }, + Err(error) => { + panic!(error); + } + } + } } impl EvaluationDomain for BasicRadix2Domain { diff --git a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs index b19c17bd0..bfc434227 100644 --- a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs @@ -5,6 +5,9 @@ use std::fmt; use rand::Rng; use std::any::Any; +#[cfg(feature = "gpu")] +use algebra_kernels::fft::get_kernels; + /// Defines a domain over which finite field (I)FFTs can be performed. Works /// only for fields that have a large multiplicative subgroup of size that is /// a power-of-2 and a small multiplicative subgroup of size that is a power of @@ -361,7 +364,31 @@ impl MixedRadix2Domain { }); } + #[cfg(feature = "gpu")] + pub(crate) fn gpu_fft(a: &mut [F], cpu_worker: &Worker, omega: F, log_n: u32) { + + match get_kernels() { + Ok(kernels) => { + match kernels[0].radix_fft(a, &omega, log_n) { + Ok(_) => {}, + Err(error) => { panic!(error); } + } + }, + Err(error) => { + panic!(error); + } + } + } + fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { + #[cfg(not(feature = "gpu"))] + Self::best_cpu_fft(a, worker, omega, log_n); + + #[cfg(feature = "gpu")] + Self::gpu_fft(a, worker, omega, log_n); + } + + fn best_cpu_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { let log_cpus = worker.log_num_cpus(); if log_n <= log_cpus { From 338827dbd9e5c7754b8d8c5b5fc4211b5efbabbc Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 20:12:53 +0200 Subject: [PATCH 03/63] GPU FFT bugfix --- .../src/fft/domain/basic_radix_2_domain.rs | 50 ++++++++----------- .../src/fft/domain/mixed_radix_2_domain.rs | 48 ++++++++---------- 2 files changed, 43 insertions(+), 55 deletions(-) diff --git a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs index 96f22e423..61ca3dada 100644 --- a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -129,20 +129,30 @@ impl BasicRadix2Domain { fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { #[cfg(not(feature = "gpu"))] - Self::best_cpu_fft(a, worker, omega, log_n); + { + let log_cpus = worker.log_num_cpus(); + + if log_n <= log_cpus { + Self::serial_fft(a, omega, log_n); + } else { + Self::parallel_fft(a, worker, omega, log_n, log_cpus); + } + } #[cfg(feature = "gpu")] - Self::gpu_fft(a, worker, omega, log_n); - } - - fn best_cpu_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { - let log_cpus = worker.log_num_cpus(); - - if log_n <= log_cpus { - Self::serial_fft(a, omega, log_n); - } else { - Self::parallel_fft(a, worker, omega, log_n, log_cpus); - } + { + match get_kernels() { + Ok(kernels) => { + match kernels[0].radix_fft(a, &omega, log_n) { + Ok(_) => {}, + Err(error) => { panic!(error); } + } + }, + Err(error) => { + panic!(error); + } + } + } } pub(crate) fn serial_fft(a: &mut [F], omega: F, log_n: u32) { @@ -245,22 +255,6 @@ impl BasicRadix2Domain { } }); } - - #[cfg(feature = "gpu")] - pub(crate) fn gpu_fft(a: &mut [F], cpu_worker: &Worker, omega: F, log_n: u32) { - - match get_kernels() { - Ok(kernels) => { - match kernels[0].radix_fft(a, &omega, log_n) { - Ok(_) => {}, - Err(error) => { panic!(error); } - } - }, - Err(error) => { - panic!(error); - } - } - } } impl EvaluationDomain for BasicRadix2Domain { diff --git a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs index bfc434227..a15481398 100644 --- a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs @@ -364,37 +364,31 @@ impl MixedRadix2Domain { }); } - #[cfg(feature = "gpu")] - pub(crate) fn gpu_fft(a: &mut [F], cpu_worker: &Worker, omega: F, log_n: u32) { - - match get_kernels() { - Ok(kernels) => { - match kernels[0].radix_fft(a, &omega, log_n) { - Ok(_) => {}, - Err(error) => { panic!(error); } - } - }, - Err(error) => { - panic!(error); - } - } - } - fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { #[cfg(not(feature = "gpu"))] - Self::best_cpu_fft(a, worker, omega, log_n); - - #[cfg(feature = "gpu")] - Self::gpu_fft(a, worker, omega, log_n); - } + { + let log_cpus = worker.log_num_cpus(); - fn best_cpu_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { - let log_cpus = worker.log_num_cpus(); + if log_n <= log_cpus { + Self::mixed_serial_fft(a, omega, log_n); + } else { + Self::mixed_parallel_fft(a, worker, omega, log_n, log_cpus); + } + } - if log_n <= log_cpus { - Self::mixed_serial_fft(a, omega, log_n); - } else { - Self::mixed_parallel_fft(a, worker, omega, log_n, log_cpus); + #[cfg(feature = "gpu")] + { + match get_kernels() { + Ok(kernels) => { + match kernels[0].radix_fft(a, &omega, log_n) { + Ok(_) => {}, + Err(error) => { panic!(error); } + } + }, + Err(error) => { + panic!(error); + } + } } } } From 83ae8f7ead11942b48894ef5dce6b8dbe0281c1a Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 20:34:32 +0200 Subject: [PATCH 04/63] Change FFT test to BLS --- algebra-utils/src/fft/domain/test.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algebra-utils/src/fft/domain/test.rs b/algebra-utils/src/fft/domain/test.rs index b79e46d5e..e0c1407f6 100644 --- a/algebra-utils/src/fft/domain/test.rs +++ b/algebra-utils/src/fft/domain/test.rs @@ -1,5 +1,5 @@ use algebra::{UniformRand, Field, PrimeField, FpParameters}; -use algebra::curves::{mnt6753::MNT6, PairingEngine}; +use algebra::curves::{bls12_381::Bls12_381, PairingEngine}; use crate::{domain::*, multicore::*}; use rand; use std::cmp::min; @@ -42,7 +42,7 @@ fn fft_composition() { let rng = &mut rand::thread_rng(); - test_fft_composition::(rng); + test_fft_composition::(rng); } #[test] @@ -75,5 +75,5 @@ fn parallel_fft_consistency() { let rng = &mut rand::thread_rng(); - test_consistency::(rng); + test_consistency::(rng); } \ No newline at end of file From 3f6facc21cb18b5ef0a5774399ad269fe5679385 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 20:40:54 +0200 Subject: [PATCH 05/63] GPU unit-tests adjusted --- algebra-utils/src/fft/domain/mod.rs | 3 +++ algebra-utils/src/fft/domain/test.rs | 11 +++++++++++ algebra-utils/src/fft/polynomial/dense.rs | 6 +++++- algebra-utils/src/fft/polynomial/sparse.rs | 3 +++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/algebra-utils/src/fft/domain/mod.rs b/algebra-utils/src/fft/domain/mod.rs index 8538c1b04..5dfd84ffa 100644 --- a/algebra-utils/src/fft/domain/mod.rs +++ b/algebra-utils/src/fft/domain/mod.rs @@ -222,7 +222,10 @@ impl Iterator for Elements { mod tests { use crate::get_best_evaluation_domain; use algebra::Field; + #[cfg(not(feature = "gpu"))] use algebra::fields::mnt6753::fr::Fr; + #[cfg(feature = "gpu")] + use algebra::fields::bls12_381::fr::Fr; use rand::{Rng, thread_rng}; #[test] diff --git a/algebra-utils/src/fft/domain/test.rs b/algebra-utils/src/fft/domain/test.rs index e0c1407f6..a13515990 100644 --- a/algebra-utils/src/fft/domain/test.rs +++ b/algebra-utils/src/fft/domain/test.rs @@ -1,4 +1,7 @@ use algebra::{UniformRand, Field, PrimeField, FpParameters}; +#[cfg(not(feature = "gpu"))] +use algebra::curves::{mnt6753::MNT6, PairingEngine}; +#[cfg(feature = "gpu")] use algebra::curves::{bls12_381::Bls12_381, PairingEngine}; use crate::{domain::*, multicore::*}; use rand; @@ -42,6 +45,10 @@ fn fft_composition() { let rng = &mut rand::thread_rng(); + #[cfg(not(feature = "gpu"))] + test_fft_composition::(rng); + + #[cfg(feature = "gpu")] test_fft_composition::(rng); } @@ -75,5 +82,9 @@ fn parallel_fft_consistency() { let rng = &mut rand::thread_rng(); + #[cfg(not(feature = "gpu"))] + test_consistency::(rng); + + #[cfg(feature = "gpu")] test_consistency::(rng); } \ No newline at end of file diff --git a/algebra-utils/src/fft/polynomial/dense.rs b/algebra-utils/src/fft/polynomial/dense.rs index d8ae9efdf..dcc98cfaa 100644 --- a/algebra-utils/src/fft/polynomial/dense.rs +++ b/algebra-utils/src/fft/polynomial/dense.rs @@ -361,7 +361,11 @@ impl<'a, 'b, F: PrimeField> Mul<&'a DensePolynomial> for &'b DensePolynomial< mod tests { use crate::domain::get_best_evaluation_domain; use crate::polynomial::*; - use algebra::fields::{mnt6753::fr::Fr, Field}; + #[cfg(not(feature = "gpu"))] + use algebra::fields::mnt6753::fr::Fr; + #[cfg(feature = "gpu")] + use algebra::fields::bls12_381::fr::Fr; + use algebra::fields::Field; use algebra::UniformRand; use rand::thread_rng; diff --git a/algebra-utils/src/fft/polynomial/sparse.rs b/algebra-utils/src/fft/polynomial/sparse.rs index 6a49e27de..92ec7f9a5 100644 --- a/algebra-utils/src/fft/polynomial/sparse.rs +++ b/algebra-utils/src/fft/polynomial/sparse.rs @@ -128,7 +128,10 @@ impl Into> for SparsePolynomial { #[cfg(test)] mod tests { use crate::{get_best_evaluation_domain, DensePolynomial, SparsePolynomial}; + #[cfg(not(feature = "gpu"))] use algebra::fields::mnt6753::fr::Fr; + #[cfg(feature = "gpu")] + use algebra::fields::bls12_381::fr::Fr; use algebra::Field; #[test] From ab4e5fe6f1992fc946cb18e081b5f36e3d747440 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 20:56:53 +0200 Subject: [PATCH 06/63] Bellperson renamed to algenra-cl-gen --- algebra-utils/Cargo.toml | 2 +- algebra-utils/src/msm/variable_base.rs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 13cb9a1f3..994737fb4 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -28,7 +28,7 @@ rayon = { version = "1", optional = true } # gpu feature algebra-kernels = { path = "../../ginger-algebra-ocl/algebra-kernels", optional = true } -bellperson = { path = "../../ginger-algebra-ocl/bellperson", optional = true } +algebra-cl-gen = { path = "../../ginger-algebra-ocl/algebra-cl-gen", optional = true } crossbeam = { version = "0.7", optional = true } [dev-dependencies] diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 974b0fc70..843628512 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -2,11 +2,9 @@ use algebra::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, Projecti use rayon::prelude::*; #[cfg(feature = "gpu")] -use algebra_kernels::msm::{ - get_cpu_utilization, get_kernels, get_gpu_min_length -}; +use algebra_kernels::msm::{get_cpu_utilization, get_kernels, get_gpu_min_length}; #[cfg(feature = "gpu")] -use bellperson::gpu::GPUError; +use algebra_cl_gen::gpu::GPUError; #[cfg(feature = "gpu")] use crossbeam::thread; From 4899a3f88a63280175b84ce54f9561b8b472c25b Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 20 Dec 2020 20:58:39 +0200 Subject: [PATCH 07/63] Bellperson renamed to algenra-cl-gen --- algebra-utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 994737fb4..dd79944f3 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -43,7 +43,7 @@ algebra-kernels = { path = "../../ginger-algebra-ocl/algebra-kernels", features [features] parallel = [ "rayon" ] fft = [] -gpu = [ "algebra-kernels", "bellperson", "crossbeam" ] +gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] [build-dependencies] rustc_version = "0.2" \ No newline at end of file From 9073e3f11be1e431ec3624c2b9b6e9fcb8c780ab Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 21 Dec 2020 00:07:41 +0200 Subject: [PATCH 08/63] Polycommit module implemented --- algebra-utils/src/lib.rs | 5 + algebra-utils/src/polycommit/mod.rs | 137 ++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 algebra-utils/src/polycommit/mod.rs diff --git a/algebra-utils/src/lib.rs b/algebra-utils/src/lib.rs index 99f06d45d..ef135500a 100644 --- a/algebra-utils/src/lib.rs +++ b/algebra-utils/src/lib.rs @@ -18,4 +18,9 @@ pub mod fft; #[cfg(feature = "fft")] pub use self::fft::*; +#[cfg(feature = "parallel")] +pub mod polycommit; +#[cfg(feature = "parallel")] +pub use self::polycommit::*; + pub type Error = Box; \ No newline at end of file diff --git a/algebra-utils/src/polycommit/mod.rs b/algebra-utils/src/polycommit/mod.rs new file mode 100644 index 000000000..5eeac8b53 --- /dev/null +++ b/algebra-utils/src/polycommit/mod.rs @@ -0,0 +1,137 @@ +use algebra::{AffineCurve, PrimeField, SquareRootField}; + +#[cfg(not(feature = "gpu"))] +use rayon::prelude::*; +#[cfg(feature = "gpu")] +use algebra_kernels::polycommit::get_kernels; + +pub fn polycommit_round_reduce< + F: PrimeField + SquareRootField + Into<::BigInt>, + G: AffineCurve +>( + round_challenge: F, + round_challenge_inv: F, + c_l: &mut [F], + c_r: &[F], + z_l: &mut [F], + z_r: &[F], + k_l: &mut [G::Projective], + k_r: &[G], +) { + #[cfg(not(feature = "gpu"))] + { + c_l.par_iter_mut() + .zip(c_r) + .for_each(|(c_l, c_r)| *c_l += &(round_challenge_inv * &c_r)); + + z_l.par_iter_mut() + .zip(z_r) + .for_each(|(z_l, z_r)| *z_l += &(round_challenge * &z_r)); + + k_l.par_iter_mut() + .zip(k_r) + .for_each(|(k_l, k_r)| *k_l += &(k_r.mul(round_challenge))); + } + + #[cfg(feature = "gpu")] + match get_kernels() { + Ok(kernels) => { + match kernels[0].polycommit_round_reduce( + round_challenge, + round_challenge_inv, + c_l, + c_r, + z_l, + z_r, + k_l, + k_r + ) { + Ok(_) => {}, + Err(error) => { panic!(error); } + } + }, + Err(error) => { + panic!(error); + } + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use algebra::curves::bls12_381::G1Projective; + use algebra::fields::bls12_381::Fr; + use algebra::{Field, UniformRand, ProjectiveCurve}; + + #[test] + fn test_polycommit_round_reduce() { + + use rayon::prelude::*; + + let mut rng = &mut rand::thread_rng(); + + let round_challenge = Fr::rand(&mut rng); + let round_challenge_inv = round_challenge.inverse().unwrap(); + + let samples = 1 << 10; + + let mut coeffs_l = (0..samples) + .map(|_| Fr::rand(&mut rng)) + .collect::>(); + + let coeffs_r = (0..samples) + .map(|_| Fr::rand(&mut rng)) + .collect::>(); + + let mut z_l = (0..samples) + .map(|_| Fr::rand(&mut rng)) + .collect::>(); + + let z_r= (0..samples) + .map(|_| Fr::rand(&mut rng)) + .collect::>(); + + let mut key_proj_l= (0..samples) + .map(|_| G1Projective::rand(&mut rng)) + .collect::>(); + + let key_r= (0..samples) + .map(|_| G1Projective::rand(&mut rng).into_affine()) + .collect::>(); + + let mut gpu_coeffs_l = coeffs_l.clone(); + let gpu_coeffs_r = coeffs_r.clone(); + let mut gpu_z_l = z_l.clone(); + let gpu_z_r = z_r.clone(); + let mut gpu_key_proj_l = key_proj_l.clone(); + let gpu_key_r = key_r.clone(); + + coeffs_l.par_iter_mut() + .zip(coeffs_r) + .for_each(|(c_l, c_r)| *c_l += &(round_challenge_inv * &c_r)); + + z_l.par_iter_mut() + .zip(z_r) + .for_each(|(z_l, z_r)| *z_l += &(round_challenge * &z_r)); + + key_proj_l.par_iter_mut() + .zip(key_r) + .for_each(|(k_l, k_r)| *k_l += &(k_r.mul(round_challenge))); + + polycommit_round_reduce( + round_challenge, + round_challenge_inv, + &mut gpu_coeffs_l, + &gpu_coeffs_r, + &mut gpu_z_l, + &gpu_z_r, + &mut gpu_key_proj_l, + &gpu_key_r + ); + + assert_eq!(coeffs_l, gpu_coeffs_l); + assert_eq!(z_l, gpu_z_l); + assert_eq!(key_proj_l, gpu_key_proj_l); + } +} \ No newline at end of file From e6bb468767bdf91e557f3f722afc9e473110052d Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 21 Dec 2020 00:18:09 +0200 Subject: [PATCH 09/63] Panic messaging fixed --- algebra-utils/src/fft/domain/basic_radix_2_domain.rs | 4 ++-- algebra-utils/src/fft/domain/mixed_radix_2_domain.rs | 4 ++-- algebra-utils/src/polycommit/mod.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs index 61ca3dada..bfad55b77 100644 --- a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -145,11 +145,11 @@ impl BasicRadix2Domain { Ok(kernels) => { match kernels[0].radix_fft(a, &omega, log_n) { Ok(_) => {}, - Err(error) => { panic!(error); } + Err(error) => { panic!("{}", error); } } }, Err(error) => { - panic!(error); + panic!("{}", error); } } } diff --git a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs index a15481398..d2eeb5aba 100644 --- a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs @@ -382,11 +382,11 @@ impl MixedRadix2Domain { Ok(kernels) => { match kernels[0].radix_fft(a, &omega, log_n) { Ok(_) => {}, - Err(error) => { panic!(error); } + Err(error) => { panic!("{}", error); } } }, Err(error) => { - panic!(error); + panic!("{}", error); } } } diff --git a/algebra-utils/src/polycommit/mod.rs b/algebra-utils/src/polycommit/mod.rs index 5eeac8b53..0af5d9c45 100644 --- a/algebra-utils/src/polycommit/mod.rs +++ b/algebra-utils/src/polycommit/mod.rs @@ -47,11 +47,11 @@ pub fn polycommit_round_reduce< k_r ) { Ok(_) => {}, - Err(error) => { panic!(error); } + Err(error) => { panic!("{}", error); } } }, Err(error) => { - panic!(error); + panic!("{}", error); } } } From 4b86eff9961a0be78156a88aeefafad1f70507f8 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 21 Dec 2020 00:29:53 +0200 Subject: [PATCH 10/63] Templating approach changed for polycommit reduce --- algebra-utils/src/polycommit/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/algebra-utils/src/polycommit/mod.rs b/algebra-utils/src/polycommit/mod.rs index 0af5d9c45..558a7b664 100644 --- a/algebra-utils/src/polycommit/mod.rs +++ b/algebra-utils/src/polycommit/mod.rs @@ -1,4 +1,4 @@ -use algebra::{AffineCurve, PrimeField, SquareRootField}; +use algebra::AffineCurve; #[cfg(not(feature = "gpu"))] use rayon::prelude::*; @@ -6,15 +6,14 @@ use rayon::prelude::*; use algebra_kernels::polycommit::get_kernels; pub fn polycommit_round_reduce< - F: PrimeField + SquareRootField + Into<::BigInt>, - G: AffineCurve + G: AffineCurve >( - round_challenge: F, - round_challenge_inv: F, - c_l: &mut [F], - c_r: &[F], - z_l: &mut [F], - z_r: &[F], + round_challenge: G::ScalarField, + round_challenge_inv: G::ScalarField, + c_l: &mut [G::ScalarField], + c_r: &[G::ScalarField], + z_l: &mut [G::ScalarField], + z_r: &[G::ScalarField], k_l: &mut [G::Projective], k_r: &[G], ) { From e98e2ffa080ffcba609b50498ee25f781608beb5 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 21 Dec 2020 00:50:22 +0200 Subject: [PATCH 11/63] Set min limit to invoke GPU --- .../src/fft/domain/basic_radix_2_domain.rs | 26 ++++--- .../src/fft/domain/mixed_radix_2_domain.rs | 26 ++++--- algebra-utils/src/polycommit/mod.rs | 70 +++++++++---------- 3 files changed, 59 insertions(+), 63 deletions(-) diff --git a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs index bfad55b77..684aaf0c9 100644 --- a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -6,7 +6,7 @@ use rand::Rng; use std::any::Any; #[cfg(feature = "gpu")] -use algebra_kernels::fft::get_kernels; +use algebra_kernels::fft::{get_kernels, get_gpu_min_length}; /// Defines a domain over which finite field (I)FFTs can be performed. Works /// only for fields that have a large multiplicative subgroup of size that is @@ -128,19 +128,8 @@ impl BasicRadix2Domain { } fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { - #[cfg(not(feature = "gpu"))] - { - let log_cpus = worker.log_num_cpus(); - - if log_n <= log_cpus { - Self::serial_fft(a, omega, log_n); - } else { - Self::parallel_fft(a, worker, omega, log_n, log_cpus); - } - } - #[cfg(feature = "gpu")] - { + if get_gpu_min_length() <= 1 << log_n { match get_kernels() { Ok(kernels) => { match kernels[0].radix_fft(a, &omega, log_n) { @@ -151,8 +140,17 @@ impl BasicRadix2Domain { Err(error) => { panic!("{}", error); } - } + } + return; } + + let log_cpus = worker.log_num_cpus(); + + if log_n <= log_cpus { + Self::serial_fft(a, omega, log_n); + } else { + Self::parallel_fft(a, worker, omega, log_n, log_cpus); + } } pub(crate) fn serial_fft(a: &mut [F], omega: F, log_n: u32) { diff --git a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs index d2eeb5aba..97cb2d50d 100644 --- a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs @@ -6,7 +6,7 @@ use rand::Rng; use std::any::Any; #[cfg(feature = "gpu")] -use algebra_kernels::fft::get_kernels; +use algebra_kernels::fft::{get_kernels, get_gpu_min_length}; /// Defines a domain over which finite field (I)FFTs can be performed. Works /// only for fields that have a large multiplicative subgroup of size that is @@ -364,20 +364,9 @@ impl MixedRadix2Domain { }); } - fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { - #[cfg(not(feature = "gpu"))] - { - let log_cpus = worker.log_num_cpus(); - - if log_n <= log_cpus { - Self::mixed_serial_fft(a, omega, log_n); - } else { - Self::mixed_parallel_fft(a, worker, omega, log_n, log_cpus); - } - } - + fn best_fft(a: &mut [F], _worker: &Worker, omega: F, log_n: u32) { #[cfg(feature = "gpu")] - { + if get_gpu_min_length() <= 1 << log_n { match get_kernels() { Ok(kernels) => { match kernels[0].radix_fft(a, &omega, log_n) { @@ -389,7 +378,16 @@ impl MixedRadix2Domain { panic!("{}", error); } } + return; } + + let log_cpus = _worker.log_num_cpus(); + + if log_n <= log_cpus { + Self::mixed_serial_fft(a, omega, log_n); + } else { + Self::mixed_parallel_fft(a, _worker, omega, log_n, log_cpus); + } } } diff --git a/algebra-utils/src/polycommit/mod.rs b/algebra-utils/src/polycommit/mod.rs index 558a7b664..9c4fd57d6 100644 --- a/algebra-utils/src/polycommit/mod.rs +++ b/algebra-utils/src/polycommit/mod.rs @@ -1,9 +1,9 @@ use algebra::AffineCurve; -#[cfg(not(feature = "gpu"))] use rayon::prelude::*; + #[cfg(feature = "gpu")] -use algebra_kernels::polycommit::get_kernels; +use algebra_kernels::polycommit::{get_kernels, get_gpu_min_length}; pub fn polycommit_round_reduce< G: AffineCurve @@ -17,42 +17,42 @@ pub fn polycommit_round_reduce< k_l: &mut [G::Projective], k_r: &[G], ) { - #[cfg(not(feature = "gpu"))] - { - c_l.par_iter_mut() - .zip(c_r) - .for_each(|(c_l, c_r)| *c_l += &(round_challenge_inv * &c_r)); + #[cfg(feature = "gpu")] + if get_gpu_min_length() <= k_l.len() { + match get_kernels() { + Ok(kernels) => { + match kernels[0].polycommit_round_reduce( + round_challenge, + round_challenge_inv, + c_l, + c_r, + z_l, + z_r, + k_l, + k_r + ) { + Ok(_) => {}, + Err(error) => { panic!("{}", error); } + } + }, + Err(error) => { + panic!("{}", error); + } + } + return; + } - z_l.par_iter_mut() - .zip(z_r) - .for_each(|(z_l, z_r)| *z_l += &(round_challenge * &z_r)); + c_l.par_iter_mut() + .zip(c_r) + .for_each(|(c_l, c_r)| *c_l += &(round_challenge_inv * &c_r)); - k_l.par_iter_mut() - .zip(k_r) - .for_each(|(k_l, k_r)| *k_l += &(k_r.mul(round_challenge))); - } + z_l.par_iter_mut() + .zip(z_r) + .for_each(|(z_l, z_r)| *z_l += &(round_challenge * &z_r)); - #[cfg(feature = "gpu")] - match get_kernels() { - Ok(kernels) => { - match kernels[0].polycommit_round_reduce( - round_challenge, - round_challenge_inv, - c_l, - c_r, - z_l, - z_r, - k_l, - k_r - ) { - Ok(_) => {}, - Err(error) => { panic!("{}", error); } - } - }, - Err(error) => { - panic!("{}", error); - } - } + k_l.par_iter_mut() + .zip(k_r) + .for_each(|(k_l, k_r)| *k_l += &(k_r.mul(round_challenge))); } #[cfg(test)] From 99738078a8c24885fa7ecd759b5c8b22c6a8558e Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 21 Dec 2020 01:05:52 +0200 Subject: [PATCH 12/63] Linking packages to GIT --- algebra-utils/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index dd79944f3..7f2a37448 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -27,8 +27,8 @@ rand = { version = "0.7" } rayon = { version = "1", optional = true } # gpu feature -algebra-kernels = { path = "../../ginger-algebra-ocl/algebra-kernels", optional = true } -algebra-cl-gen = { path = "../../ginger-algebra-ocl/algebra-cl-gen", optional = true } +algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", optional = true } +algebra-cl-gen = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", optional = true } crossbeam = { version = "0.7", optional = true } [dev-dependencies] @@ -38,7 +38,7 @@ rand_xorshift = { version = "0.2" } paste = "1.0" algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } -algebra-kernels = { path = "../../ginger-algebra-ocl/algebra-kernels", features = ["bls12_381", "jubjub"] } +algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", features = ["bls12_381", "jubjub"] } [features] parallel = [ "rayon" ] From 612aa96cb793191455f380a7fb6bf57d69e7b598 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 21 Dec 2020 01:14:43 +0200 Subject: [PATCH 13/63] Dependency import bugfix --- algebra-utils/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 7f2a37448..407cbde28 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = [ "parallel" ] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } rand = { version = "0.7" } @@ -36,7 +36,7 @@ blake2 = "0.7" criterion = "0.2" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", features = ["bls12_381", "jubjub"] } From 82a54c19afdb5ef3d7ff604bbee70c2a6ae72411 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 27 Dec 2020 16:36:26 +0200 Subject: [PATCH 14/63] Tweedle curve added --- algebra/Cargo.toml | 7 +-- algebra/src/curves/mod.rs | 3 ++ algebra/src/curves/tweedle/dee.rs | 83 +++++++++++++++++++++++++++++++ algebra/src/curves/tweedle/dum.rs | 83 +++++++++++++++++++++++++++++++ algebra/src/curves/tweedle/mod.rs | 2 + algebra/src/fields/mod.rs | 3 ++ algebra/src/fields/tweedle/fq.rs | 77 ++++++++++++++++++++++++++++ algebra/src/fields/tweedle/fr.rs | 77 ++++++++++++++++++++++++++++ algebra/src/fields/tweedle/mod.rs | 6 +++ 9 files changed, 338 insertions(+), 3 deletions(-) create mode 100644 algebra/src/curves/tweedle/dee.rs create mode 100644 algebra/src/curves/tweedle/dum.rs create mode 100644 algebra/src/curves/tweedle/mod.rs create mode 100644 algebra/src/fields/tweedle/fq.rs create mode 100644 algebra/src/fields/tweedle/fr.rs create mode 100644 algebra/src/fields/tweedle/mod.rs diff --git a/algebra/Cargo.toml b/algebra/Cargo.toml index 9cf62878b..eff4d021d 100644 --- a/algebra/Cargo.toml +++ b/algebra/Cargo.toml @@ -39,7 +39,7 @@ blake2 = "0.7" criterion = "0.2" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753", "bn_382", "tweedle"] } [features] parallel = [ "rayon" ] @@ -56,9 +56,10 @@ mnt4_753 = [] mnt6_298 = [] mnt6_753 = [] bn_382 = [] +tweedle = [] -full = [ "bls12_377", "bls12_381", "sw6", "mnt4_753", "mnt6_298", "mnt6_753", "edwards_bls12", "edwards_sw6", "jubjub", "bn_382" ] +full = [ "bls12_377", "bls12_381", "sw6", "mnt4_753", "mnt6_298", "mnt6_753", "edwards_bls12", "edwards_sw6", "jubjub", "bn_382", "tweedle" ] [build-dependencies] field-assembly = { path = "./field-assembly" } -rustc_version = "0.2" \ No newline at end of file +rustc_version = "0.2" diff --git a/algebra/src/curves/mod.rs b/algebra/src/curves/mod.rs index 8183bd78b..0703b51a4 100644 --- a/algebra/src/curves/mod.rs +++ b/algebra/src/curves/mod.rs @@ -39,6 +39,9 @@ pub mod mnt6; #[cfg(feature = "sw6")] pub mod sw6; +#[cfg(feature = "tweedle")] +pub mod tweedle; + #[cfg(test)] pub mod tests; diff --git a/algebra/src/curves/tweedle/dee.rs b/algebra/src/curves/tweedle/dee.rs new file mode 100644 index 000000000..291182d03 --- /dev/null +++ b/algebra/src/curves/tweedle/dee.rs @@ -0,0 +1,83 @@ +use crate::field_new; +use crate::{ + biginteger::BigInteger256, + curves::{ + models::short_weierstrass_jacobian::{GroupAffine, GroupProjective}, + ModelParameters, SWModelParameters}, + Zero, + fields::tweedle::{Fq, Fp} +}; + +#[derive(Copy, Clone, Default, PartialEq, Eq)] +pub struct TweedledeeParameters; + +impl ModelParameters for TweedledeeParameters { + type BaseField = Fq; + type ScalarField = Fp; +} + +pub type Affine = GroupAffine; +pub type Projective = GroupProjective; + +impl SWModelParameters for TweedledeeParameters { + /// COEFF_A = 0 + const COEFF_A: Fq = field_new!(Fq, BigInteger256([0x0, 0x0, 0x0, 0x0])); + + /// COEFF_B = 5 + const COEFF_B: Fq = field_new!( + Fq, + BigInteger256([ + 0x30aef343ffffffed, + 0xbcb60a132dafff0b, + 0xffffffffffffffff, + 0x3fffffffffffffff + ]) + ); + + /// COFACTOR = 1 + const COFACTOR: &'static [u64] = &[0x1]; + + /// COFACTOR_INV = 1 + const COFACTOR_INV: Fp = field_new!( + Fp, + BigInteger256([ + 0x1c3ed159fffffffd, + 0xf5601c89bb41f2d3, + 0xffffffffffffffff, + 0x3fffffffffffffff + ]) + ); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (G_GENERATOR_X, G_GENERATOR_Y); + + #[inline(always)] + fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { + Self::BaseField::zero() + } +} + +/// G_GENERATOR_X = +/// 1 +pub const G_GENERATOR_X: Fq = field_new!( + Fq, + BigInteger256([ + 0x7379f083fffffffd, + 0xf5601c89c3d86ba3, + 0xffffffffffffffff, + 0x3fffffffffffffff + ]) +); + +/// G1_GENERATOR_Y = +/// 14240188643175251183985684255458419213835105645119662786317263805424119994471 +pub const G_GENERATOR_Y: Fq = field_new!( + Fq, + BigInteger256([ + 0x1e28b41c4fc25056, + 0x544abc778a8b7ce5, + 0xe133d9afa567f32b, + 0x37705e17172ff461 + ]) +); diff --git a/algebra/src/curves/tweedle/dum.rs b/algebra/src/curves/tweedle/dum.rs new file mode 100644 index 000000000..c48904156 --- /dev/null +++ b/algebra/src/curves/tweedle/dum.rs @@ -0,0 +1,83 @@ +use crate::field_new; +use crate::{ + biginteger::BigInteger256, + curves::{ + models::short_weierstrass_jacobian::{GroupAffine, GroupProjective}, + ModelParameters, SWModelParameters}, + Zero, + fields::tweedle::{Fq, Fp} +}; + +#[derive(Copy, Clone, Default, PartialEq, Eq)] +pub struct TweedledumParameters; + +impl ModelParameters for TweedledumParameters { + type BaseField = Fp; + type ScalarField = Fq; +} + +pub type Affine = GroupAffine; +pub type Projective = GroupProjective; + +impl SWModelParameters for TweedledumParameters { + /// COEFF_A = 0 + const COEFF_A: Fp = field_new!(Fp, BigInteger256([0x0, 0x0, 0x0, 0x0])); + + /// COEFF_B = 5 + const COEFF_B: Fp = field_new!( + Fp, + BigInteger256([ + 0x8388339ffffffed, + 0xbcb60a12f74c5739, + 0xffffffffffffffff, + 0x3fffffffffffffff + ]) + ); + + /// COFACTOR = 1 + const COFACTOR: &'static [u64] = &[0x1]; + + /// COFACTOR_INV = 1 + const COFACTOR_INV: Fq = field_new!( + Fq, + BigInteger256([ + 0x7379f083fffffffd, + 0xf5601c89c3d86ba3, + 0xffffffffffffffff, + 0x3fffffffffffffff + ]) + ); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (G_GENERATOR_X, G_GENERATOR_Y); + + #[inline(always)] + fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { + Self::BaseField::zero() + } +} + +/// G_GENERATOR_X = +/// 1 +pub const G_GENERATOR_X: Fp = field_new!( + Fp, + BigInteger256([ + 0x1c3ed159fffffffd, + 0xf5601c89bb41f2d3, + 0xffffffffffffffff, + 0x3fffffffffffffff + ]) +); + +/// G1_GENERATOR_Y = +/// 385654983219305453067387443941241858913435815837190103938162313975739315615 +pub const G_GENERATOR_Y: Fp = field_new!( + Fp, + BigInteger256([ + 0x7414a31870fe2315, + 0x5771cccafdb1a2b5, + 0x747fd502e877c849, + 0x3175a51e493b99fc + ]) +); diff --git a/algebra/src/curves/tweedle/mod.rs b/algebra/src/curves/tweedle/mod.rs new file mode 100644 index 000000000..8021b1bf5 --- /dev/null +++ b/algebra/src/curves/tweedle/mod.rs @@ -0,0 +1,2 @@ +pub mod dee; +pub mod dum; diff --git a/algebra/src/fields/mod.rs b/algebra/src/fields/mod.rs index 564b3fec7..41d41914c 100644 --- a/algebra/src/fields/mod.rs +++ b/algebra/src/fields/mod.rs @@ -40,6 +40,9 @@ pub mod mnt6; #[cfg(feature = "sw6")] pub mod sw6; +#[cfg(feature = "tweedle")] +pub mod tweedle; + #[cfg(test)] pub mod tests; diff --git a/algebra/src/fields/tweedle/fq.rs b/algebra/src/fields/tweedle/fq.rs new file mode 100644 index 000000000..6284b95ee --- /dev/null +++ b/algebra/src/fields/tweedle/fq.rs @@ -0,0 +1,77 @@ +use crate::{ + biginteger::BigInteger256 as BigInteger, + fields::{FftParameters, Fp256, Fp256Parameters, FpParameters}, +}; + +pub struct FqParameters; + +pub type Fq = Fp256; + +impl Fp256Parameters for FqParameters {} +impl FftParameters for FqParameters { + type BigInt = BigInteger; + + const TWO_ADICITY: u32 = 34; + + #[rustfmt::skip] + const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([ + 0xb5373d390b45cde8, + 0x1437982d8ca321e6, + 0x5f6fd892c6494e7e, + 0x19f5297fb35e2ae1, + ]); +} +impl FpParameters for FqParameters { + // 28948022309329048855892746252171976963322203655954433126947083963168578338817 + const MODULUS: BigInteger = BigInteger([ + 0x842cafd400000001, + 0x38aa127696286c9, + 0x0, + 0x4000000000000000, + ]); + + const R: BigInteger = BigInteger([ + 0x7379f083fffffffd, + 0xf5601c89c3d86ba3, + 0xffffffffffffffff, + 0x3fffffffffffffff, + ]); + + const R2: BigInteger = BigInteger([ + 0x8595fa8000000010, + 0x7e16a565c6895230, + 0xf4c0e6fcb03aa0a2, + 0xc8ad9106886013, + ]); + + const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([ + 0xc21657ea00000000, + 0x1c55093b4b14364, + 0x0, + 0x2000000000000000, + ]); + + // T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T + + const T: BigInteger = BigInteger([0xda58a1b2610b2bf5, 0xe2a849, 0x0, 0x10000000]); + + const T_MINUS_ONE_DIV_TWO: BigInteger = + BigInteger([0xed2c50d9308595fa, 0x715424, 0x0, 0x8000000]); + + // GENERATOR = 5 + const GENERATOR: BigInteger = BigInteger([ + 0x30aef343ffffffed, + 0xbcb60a132dafff0b, + 0xffffffffffffffff, + 0x3fffffffffffffff, + ]); + + const MODULUS_BITS: u32 = 255; + + const CAPACITY: u32 = Self::MODULUS_BITS - 1; + + // Check this + const REPR_SHAVE_BITS: u32 = 1; + + const INV: u64 = 9524180637049683967; +} diff --git a/algebra/src/fields/tweedle/fr.rs b/algebra/src/fields/tweedle/fr.rs new file mode 100644 index 000000000..8434b599b --- /dev/null +++ b/algebra/src/fields/tweedle/fr.rs @@ -0,0 +1,77 @@ +use crate::{ + biginteger::BigInteger256 as BigInteger, + fields::{FftParameters, Fp256, Fp256Parameters}, +}; + +pub type Fr = Fp256; + +pub struct FpParameters; + +impl Fp256Parameters for FpParameters {} +impl FftParameters for FpParameters { + type BigInt = BigInteger; + + const TWO_ADICITY: u32 = 33; + + #[rustfmt::skip] + const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([ + 0xa189b4c6deb5f0b4, + 0x84b1839059d394b6, + 0x62394c58292596e9, + 0x3017cc8a62e742c4, + ]); + +} + +impl algebra_core::fields::FpParameters for FpParameters { + // 28948022309329048855892746252171976963322203655955319056773317069363642105857 + const MODULUS: BigInteger = BigInteger([ + 11619397960441266177, + 255193519591741881, + 0, + 4611686018427387904, + ]); + + const R: BigInteger = BigInteger([ + 2035294266095304701, + 17681163514934325971, + 18446744073709551615, + 4611686018427387903, + ]); + + const R2: BigInteger = BigInteger([ + 2885853259929485328, + 10494584067553537908, + 15959394653775906393, + 56485833754855950, + ]); + + const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([ + 0xd0a0327100000000, + 0x1c55093b61facdc, + 0x0, + 0x2000000000000000, + ]); + + // T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T + const T: BigInteger = BigInteger([0xb61facdcd0a03271, 0x1c55093, 0x0, 0x20000000]); + + const T_MINUS_ONE_DIV_TWO: BigInteger = + BigInteger([0xdb0fd66e68501938, 0xe2a849, 0x0, 0x10000000]); + + // GENERATOR = 5 + const GENERATOR: BigInteger = BigInteger([ + 592367636130562029, + 13598067201466455865, + 18446744073709551615, + 4611686018427387903, + ]); + + const MODULUS_BITS: u32 = 255; + + const CAPACITY: u32 = Self::MODULUS_BITS - 1; + + const REPR_SHAVE_BITS: u32 = 1; + + const INV: u64 = 11619397960441266175; +} diff --git a/algebra/src/fields/tweedle/mod.rs b/algebra/src/fields/tweedle/mod.rs new file mode 100644 index 000000000..1c2f05b49 --- /dev/null +++ b/algebra/src/fields/tweedle/mod.rs @@ -0,0 +1,6 @@ +pub mod fr; +pub use self::fr::*; + +pub mod fq; +pub use self::fq::*; + From e7f7e9123eba93716d35541306996d2aff4a29c1 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 27 Dec 2020 16:57:31 +0200 Subject: [PATCH 15/63] Tweedle implementation bugfixes --- algebra/src/curves/tweedle/dee.rs | 14 +++++++------- algebra/src/curves/tweedle/dum.rs | 24 +++++++++++------------ algebra/src/fields/tweedle/fq.rs | 28 ++++++++++++++------------- algebra/src/fields/tweedle/fr.rs | 32 ++++++++++++++----------------- 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/algebra/src/curves/tweedle/dee.rs b/algebra/src/curves/tweedle/dee.rs index 291182d03..7c5afc0d9 100644 --- a/algebra/src/curves/tweedle/dee.rs +++ b/algebra/src/curves/tweedle/dee.rs @@ -1,11 +1,11 @@ -use crate::field_new; use crate::{ biginteger::BigInteger256, curves::{ models::short_weierstrass_jacobian::{GroupAffine, GroupProjective}, - ModelParameters, SWModelParameters}, - Zero, - fields::tweedle::{Fq, Fp} + ModelParameters, SWModelParameters + }, + Field, field_new, + fields::tweedle::* }; #[derive(Copy, Clone, Default, PartialEq, Eq)] @@ -13,7 +13,7 @@ pub struct TweedledeeParameters; impl ModelParameters for TweedledeeParameters { type BaseField = Fq; - type ScalarField = Fp; + type ScalarField = Fr; } pub type Affine = GroupAffine; @@ -38,8 +38,8 @@ impl SWModelParameters for TweedledeeParameters { const COFACTOR: &'static [u64] = &[0x1]; /// COFACTOR_INV = 1 - const COFACTOR_INV: Fp = field_new!( - Fp, + const COFACTOR_INV: Fr = field_new!( + Fr, BigInteger256([ 0x1c3ed159fffffffd, 0xf5601c89bb41f2d3, diff --git a/algebra/src/curves/tweedle/dum.rs b/algebra/src/curves/tweedle/dum.rs index c48904156..2173afcf8 100644 --- a/algebra/src/curves/tweedle/dum.rs +++ b/algebra/src/curves/tweedle/dum.rs @@ -1,18 +1,18 @@ -use crate::field_new; use crate::{ biginteger::BigInteger256, curves::{ models::short_weierstrass_jacobian::{GroupAffine, GroupProjective}, - ModelParameters, SWModelParameters}, - Zero, - fields::tweedle::{Fq, Fp} + ModelParameters, SWModelParameters + }, + Field, field_new, + fields::tweedle::* }; #[derive(Copy, Clone, Default, PartialEq, Eq)] pub struct TweedledumParameters; impl ModelParameters for TweedledumParameters { - type BaseField = Fp; + type BaseField = Fr; type ScalarField = Fq; } @@ -21,11 +21,11 @@ pub type Projective = GroupProjective; impl SWModelParameters for TweedledumParameters { /// COEFF_A = 0 - const COEFF_A: Fp = field_new!(Fp, BigInteger256([0x0, 0x0, 0x0, 0x0])); + const COEFF_A: Fr = field_new!(Fr, BigInteger256([0x0, 0x0, 0x0, 0x0])); /// COEFF_B = 5 - const COEFF_B: Fp = field_new!( - Fp, + const COEFF_B: Fr = field_new!( + Fr, BigInteger256([ 0x8388339ffffffed, 0xbcb60a12f74c5739, @@ -60,8 +60,8 @@ impl SWModelParameters for TweedledumParameters { /// G_GENERATOR_X = /// 1 -pub const G_GENERATOR_X: Fp = field_new!( - Fp, +pub const G_GENERATOR_X: Fr = field_new!( + Fr, BigInteger256([ 0x1c3ed159fffffffd, 0xf5601c89bb41f2d3, @@ -72,8 +72,8 @@ pub const G_GENERATOR_X: Fp = field_new!( /// G1_GENERATOR_Y = /// 385654983219305453067387443941241858913435815837190103938162313975739315615 -pub const G_GENERATOR_Y: Fp = field_new!( - Fp, +pub const G_GENERATOR_Y: Fr = field_new!( + Fr, BigInteger256([ 0x7414a31870fe2315, 0x5771cccafdb1a2b5, diff --git a/algebra/src/fields/tweedle/fq.rs b/algebra/src/fields/tweedle/fq.rs index 6284b95ee..3094d82fc 100644 --- a/algebra/src/fields/tweedle/fq.rs +++ b/algebra/src/fields/tweedle/fq.rs @@ -1,6 +1,7 @@ use crate::{ biginteger::BigInteger256 as BigInteger, - fields::{FftParameters, Fp256, Fp256Parameters, FpParameters}, + fields::{Fp256, Fp256Parameters, FpParameters}, + field_new }; pub struct FqParameters; @@ -8,20 +9,9 @@ pub struct FqParameters; pub type Fq = Fp256; impl Fp256Parameters for FqParameters {} -impl FftParameters for FqParameters { +impl FpParameters for FqParameters { type BigInt = BigInteger; - const TWO_ADICITY: u32 = 34; - - #[rustfmt::skip] - const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([ - 0xb5373d390b45cde8, - 0x1437982d8ca321e6, - 0x5f6fd892c6494e7e, - 0x19f5297fb35e2ae1, - ]); -} -impl FpParameters for FqParameters { // 28948022309329048855892746252171976963322203655954433126947083963168578338817 const MODULUS: BigInteger = BigInteger([ 0x842cafd400000001, @@ -70,8 +60,20 @@ impl FpParameters for FqParameters { const CAPACITY: u32 = Self::MODULUS_BITS - 1; + const TWO_ADICITY: u32 = 34; + + const ROOT_OF_UNITY: BigInteger = BigInteger([ + 0xb5373d390b45cde8, + 0x1437982d8ca321e6, + 0x5f6fd892c6494e7e, + 0x19f5297fb35e2ae1, + ]); + // Check this const REPR_SHAVE_BITS: u32 = 1; const INV: u64 = 9524180637049683967; } + +pub const FQ_ONE: Fq = field_new!(Fq, FqParameters::R); +pub const FQ_ZERO: Fq = field_new!(Fq, BigInteger([0, 0, 0, 0])); diff --git a/algebra/src/fields/tweedle/fr.rs b/algebra/src/fields/tweedle/fr.rs index 8434b599b..a1f7dfa84 100644 --- a/algebra/src/fields/tweedle/fr.rs +++ b/algebra/src/fields/tweedle/fr.rs @@ -1,29 +1,16 @@ use crate::{ biginteger::BigInteger256 as BigInteger, - fields::{FftParameters, Fp256, Fp256Parameters}, + fields::{FpParameters, Fp256, Fp256Parameters}, }; -pub type Fr = Fp256; +pub type Fr = Fp256; -pub struct FpParameters; +pub struct FrParameters; -impl Fp256Parameters for FpParameters {} -impl FftParameters for FpParameters { +impl Fp256Parameters for FrParameters {} +impl FpParameters for FrParameters { type BigInt = BigInteger; - const TWO_ADICITY: u32 = 33; - - #[rustfmt::skip] - const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([ - 0xa189b4c6deb5f0b4, - 0x84b1839059d394b6, - 0x62394c58292596e9, - 0x3017cc8a62e742c4, - ]); - -} - -impl algebra_core::fields::FpParameters for FpParameters { // 28948022309329048855892746252171976963322203655955319056773317069363642105857 const MODULUS: BigInteger = BigInteger([ 11619397960441266177, @@ -71,6 +58,15 @@ impl algebra_core::fields::FpParameters for FpParameters { const CAPACITY: u32 = Self::MODULUS_BITS - 1; + const TWO_ADICITY: u32 = 33; + + const ROOT_OF_UNITY: BigInteger = BigInteger([ + 0xa189b4c6deb5f0b4, + 0x84b1839059d394b6, + 0x62394c58292596e9, + 0x3017cc8a62e742c4, + ]); + const REPR_SHAVE_BITS: u32 = 1; const INV: u64 = 11619397960441266175; From 2edeafce90c847f5fc11a367e8837bc92c3589b3 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 00:04:38 +0200 Subject: [PATCH 16/63] Benches migrated from Zexe --- .gitignore | 5 + algebra-utils/Cargo.toml | 29 +- algebra-utils/benches/fft/fft_bn382.rs | 386 ++++++++++++++++++ algebra-utils/benches/fft/fft_tweedle.rs | 384 +++++++++++++++++ algebra-utils/benches/fft/mod.rs | 121 ------ .../benches/msm/variable_msm_bn382.rs | 125 ++++++ .../benches/msm/variable_msm_tweedle.rs | 239 +++++++++++ primitives/Cargo.toml | 4 +- proof-systems/Cargo.toml | 11 +- .../benches/bn382_gro16_test_circuits.rs | 247 +++++++++++ r1cs/core/Cargo.toml | 2 +- r1cs/gadgets/crypto/Cargo.toml | 4 +- r1cs/gadgets/std/Cargo.toml | 4 +- 13 files changed, 1427 insertions(+), 134 deletions(-) create mode 100644 algebra-utils/benches/fft/fft_bn382.rs create mode 100644 algebra-utils/benches/fft/fft_tweedle.rs delete mode 100644 algebra-utils/benches/fft/mod.rs create mode 100644 algebra-utils/benches/msm/variable_msm_bn382.rs create mode 100644 algebra-utils/benches/msm/variable_msm_tweedle.rs create mode 100644 proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs diff --git a/.gitignore b/.gitignore index 050d7bfea..6db3fb476 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ +/.vscode + target Cargo.lock *.idea *.iml *.orig primitives/src/merkle_tree/field_based_mht/smt/rocksdb_storage/* + +coeffs_* +msm_bases_* diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 407cbde28..d44842007 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -33,12 +33,13 @@ crossbeam = { version = "0.7", optional = true } [dev-dependencies] blake2 = "0.7" -criterion = "0.2" +criterion = "0.3.3" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } -algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", features = ["bls12_381", "jubjub"] } +algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } +bench-utils = { path = "../bench-utils" } [features] parallel = [ "rayon" ] @@ -46,4 +47,24 @@ fft = [] gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] [build-dependencies] -rustc_version = "0.2" \ No newline at end of file +rustc_version = "0.2" + +[[bench]] +name = "fft_bn382" +path = "benches/fft/fft_bn382.rs" +harness = false + +[[bench]] +name = "fft_tweedle" +path = "benches/fft/fft_tweedle.rs" +harness = false + +[[bench]] +name = "variable_msm_bn382" +path = "benches/msm/variable_msm_bn382.rs" +harness = false + +[[bench]] +name = "variable_msm_tweedle" +path = "benches/msm/variable_msm_tweedle.rs" +harness = false diff --git a/algebra-utils/benches/fft/fft_bn382.rs b/algebra-utils/benches/fft/fft_bn382.rs new file mode 100644 index 000000000..6e49b0f34 --- /dev/null +++ b/algebra-utils/benches/fft/fft_bn382.rs @@ -0,0 +1,386 @@ +#[macro_use] +extern crate criterion; + +#[macro_use] +extern crate bench_utils; + +use algebra::{ + fields::bn_382::Fr, + PrimeField, UniformRand, +}; +use algebra_utils::fft::{DensePolynomial, EvaluationDomain, BasicRadix2Domain, get_best_evaluation_domain}; +use rand; + +use std::{ + fs::File, + path::Path, + time::{SystemTime, UNIX_EPOCH}, +}; + +use criterion::{BatchSize, BenchmarkId, Criterion}; + +const DATA_PATH: &'static str = "./coeffs_bn382"; + +fn save_data(num_coeffs: usize) { + + let mut fs = File::create(DATA_PATH).unwrap(); + let rng = &mut rand::thread_rng(); + + for _ in 0..num_coeffs { + let elem:F = UniformRand::rand(rng); + match elem.write(&mut fs) { + Ok(_) => {}, + Err(msg) => { panic!("Cannot save coeffs to file: {}", msg)} + } + } +} + +fn load_data(samples: usize) -> Vec { + + if !Path::new(DATA_PATH).exists() { + save_data::(1 << 23); + } + + let mut fs = File::open(DATA_PATH).unwrap(); + let mut a: Vec = Vec::with_capacity(samples); + + for _i in 0..samples { + let elem1 = F::read(&mut fs).unwrap(); + a.push(elem1); + } + a +} + +fn bench_ffts>( + c: &mut Criterion, + num_coeffs: usize, + name: &'static str, +) { + let mut group = c.benchmark_group(name); + + // We expect the num_coeffs input to be a compatible size for the domain. + let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); + let domain_size = domain.size(); + assert_eq!(num_coeffs, domain_size); + + group.bench_with_input( + BenchmarkId::from_parameter(num_coeffs), + &num_coeffs, + |b, _samples| { + b.iter_batched( + || { + let a: Vec = load_data(num_coeffs); + a + }, + |a| { + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + domain.fft( + &mut a.as_slice(), + ); + + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }, + BatchSize::PerIteration, + ); + }, + ); +} + +fn bench_fft_bn382(c: &mut Criterion) { + bench_ffts::>(c, 1 << 14, "radix-2 FFT - 2^14 - bn382"); + bench_ffts::>(c, 1 << 15, "radix-2 FFT - 2^15 - bn382"); + bench_ffts::>(c, 1 << 16, "radix-2 FFT - 2^16 - bn382"); + bench_ffts::>(c, 1 << 17, "radix-2 FFT - 2^17 - bn382"); + bench_ffts::>(c, 1 << 18, "radix-2 FFT - 2^18 - bn382"); + bench_ffts::>(c, 1 << 19, "radix-2 FFT - 2^19 - bn382"); + bench_ffts::>(c, 1 << 20, "radix-2 FFT - 2^20 - bn382"); + bench_ffts::>(c, 1 << 21, "radix-2 FFT - 2^21 - bn382"); + bench_ffts::>(c, 1 << 22, "radix-2 FFT - 2^22 - bn382"); + bench_ffts::>(c, 1 << 23, "radix-2 FFT - 2^23 - bn382"); +} + +fn bench_iffts>( + c: &mut Criterion, + num_coeffs: usize, + name: &'static str, +) { + let mut group = c.benchmark_group(name); + + // We expect the num_coeffs input to be a compatible size for the domain. + let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); + let domain_size = domain.size(); + assert_eq!(num_coeffs, domain_size); + + group.bench_with_input( + BenchmarkId::from_parameter(num_coeffs), + &num_coeffs, + |b, _samples| { + b.iter_batched( + || { + let a: Vec = load_data(num_coeffs); + a + }, + |mut a| { + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + domain.ifft( + &mut a, + ); + + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }, + BatchSize::PerIteration, + ); + }, + ); +} + +fn bench_ifft_bn382(c: &mut Criterion) { + bench_iffts::>(c, 1 << 14, "radix-2 iFFT - 2^14 - bn382"); + bench_iffts::>(c, 1 << 15, "radix-2 iFFT - 2^15 - bn382"); + bench_iffts::>(c, 1 << 16, "radix-2 iFFT - 2^16 - bn382"); + bench_iffts::>(c, 1 << 17, "radix-2 iFFT - 2^17 - bn382"); + bench_iffts::>(c, 1 << 18, "radix-2 iFFT - 2^18 - bn382"); + bench_iffts::>(c, 1 << 19, "radix-2 iFFT - 2^19 - bn382"); + bench_iffts::>(c, 1 << 20, "radix-2 iFFT - 2^20 - bn382"); + bench_iffts::>(c, 1 << 21, "radix-2 iFFT - 2^21 - bn382"); + bench_iffts::>(c, 1 << 22, "radix-2 iFFT - 2^22 - bn382"); + bench_iffts::>(c, 1 << 23, "radix-2 iFFT - 2^23 - bn382"); +} + +fn bench_dense_poly_muls>( + c: &mut Criterion, + num_degree: usize, + name: &'static str, +) { + // Per benchmark setup + let rng = &mut rand::thread_rng(); + + c.bench_function(name, move |bencher| { + let p1 = DensePolynomial::::rand(num_degree, rng); + let p2 = DensePolynomial::::rand(num_degree, rng); + + bencher.iter(|| { + add_to_trace!( + || format!("****************{}*******************", num_degree), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + let _ab = (&p1) * (&p2); + + add_to_trace!( + || format!("****************{}*******************", num_degree), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }) + }); +} + +fn bench_dense_poly_mul_bn382(c: &mut Criterion) { + bench_dense_poly_muls::>( + c, + 1 << 14, + "radix-2 DensePolynomial::mul - 2^14 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 15, + "radix-2 DensePolynomial::mul - 2^15 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 16, + "radix-2 DensePolynomial::mul - 2^16 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 17, + "radix-2 DensePolynomial::mul - 2^17 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 18, + "radix-2 DensePolynomial::mul - 2^18 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 19, + "radix-2 DensePolynomial::mul - 2^19 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 20, + "radix-2 DensePolynomial::mul - 2^20 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 21, + "radix-2 DensePolynomial::mul - 2^21 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 22, + "radix-2 DensePolynomial::mul - 2^22 - bn382", + ); + bench_dense_poly_muls::>( + c, + 1 << 23, + "radix-2 DensePolynomial::mul - 2^23 - bn382", + ); +} + +fn bench_dense_poly_div_by_vanishing_poly>( + c: &mut Criterion, + num_coeffs: usize, + name: &'static str, +) { + // Per benchmark setup + let rng = &mut rand::thread_rng(); + + // We expect the num_coeffs input to be a compatible size for the domain. + let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); + let domain_size = domain.size(); + assert_eq!(num_coeffs, domain_size); + + c.bench_function(name, move |bencher| { + let p = DensePolynomial::::rand(4 * num_coeffs, rng); + + bencher.iter(|| { + add_to_trace!( + || format!("****************{}*******************", num_coeffs), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + let _ans1 = p.divide_by_vanishing_poly( + domain.clone(), + ); + + add_to_trace!( + || format!("****************{}*******************", num_coeffs), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }) + }); +} + +fn bench_dense_poly_divide_by_vanishing_poly_bn382(c: &mut Criterion) { + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 14, + "radix-2 DensePolynomial::div by vanishing poly - 2^14 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 15, + "radix-2 DensePolynomial::div by vanishing poly - 2^15 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 16, + "radix-2 DensePolynomial::div by vanishing poly - 2^16 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 17, + "radix-2 DensePolynomial::div by vanishing poly - 2^17 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 18, + "radix-2 DensePolynomial::div by vanishing poly - 2^18 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 19, + "radix-2 DensePolynomial::div by vanishing poly - 2^19 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 20, + "radix-2 DensePolynomial::div by vanishing poly - 2^20 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 21, + "radix-2 DensePolynomial::div by vanishing poly - 2^21 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 22, + "radix-2 DensePolynomial::div by vanishing poly - 2^22 - bn382", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 23, + "radix-2 DensePolynomial::div by vanishing poly - 2^23 - bn382", + ); +} + +criterion_group! { + name = radix_2_fft; + config = Criterion::default().sample_size(10); + targets = bench_fft_bn382, bench_ifft_bn382, bench_dense_poly_mul_bn382, bench_dense_poly_divide_by_vanishing_poly_bn382 +} + +criterion_main!(radix_2_fft); diff --git a/algebra-utils/benches/fft/fft_tweedle.rs b/algebra-utils/benches/fft/fft_tweedle.rs new file mode 100644 index 000000000..2a5556a55 --- /dev/null +++ b/algebra-utils/benches/fft/fft_tweedle.rs @@ -0,0 +1,384 @@ +#[macro_use] +extern crate criterion; + +#[macro_use] +extern crate bench_utils; + +use algebra::{ + fields::tweedle::Fr, + PrimeField, UniformRand, +}; +use algebra_utils::fft::{DensePolynomial, EvaluationDomain, BasicRadix2Domain, get_best_evaluation_domain}; +use rand; + +use std::{ + fs::File, + time::{SystemTime, UNIX_EPOCH}, +}; + +use criterion::{BatchSize, BenchmarkId, Criterion}; +const DATA_PATH: &'static str = "./coeffs_tweedle"; + +fn save_data(num_coeffs: usize) { + + let mut fs = File::create(DATA_PATH).unwrap(); + let rng = &mut rand::thread_rng(); + + for _ in 0..num_coeffs { + let elem:F = UniformRand::rand(rng); + match elem.write(&mut fs) { + Ok(_) => {}, + Err(msg) => { panic!("Cannot save coeffs to file: {}", msg)} + } + } +} + +fn load_data(samples: usize) -> Vec { + + if !Path::new(DATA_PATH).exists() { + save_data::(1 << 23); + } + + let mut fs = File::open(DATA_PATH).unwrap(); + let mut a: Vec = Vec::with_capacity(samples); + + for _i in 0..samples { + let elem1 = F::read(&mut fs).unwrap(); + a.push(elem1); + } + a +} + +fn bench_ffts>( + c: &mut Criterion, + num_coeffs: usize, + name: &'static str, +) { + let mut group = c.benchmark_group(name); + + // We expect the num_coeffs input to be a compatible size for the domain. + let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); + let domain_size = domain.size(); + assert_eq!(num_coeffs, domain_size); + + group.bench_with_input( + BenchmarkId::from_parameter(num_coeffs), + &num_coeffs, + |b, _samples| { + b.iter_batched( + || { + let a: Vec = load_data(num_coeffs); + a + }, + |a| { + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + domain.fft( + &mut a.as_slice(), + ); + + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }, + BatchSize::PerIteration, + ); + }, + ); +} + +fn bench_fft_tweedle(c: &mut Criterion) { + bench_ffts::>(c, 1 << 14, "radix-2 FFT - 2^14 - tweedle"); + bench_ffts::>(c, 1 << 15, "radix-2 FFT - 2^15 - tweedle"); + bench_ffts::>(c, 1 << 16, "radix-2 FFT - 2^16 - tweedle"); + bench_ffts::>(c, 1 << 17, "radix-2 FFT - 2^17 - tweedle"); + bench_ffts::>(c, 1 << 18, "radix-2 FFT - 2^18 - tweedle"); + bench_ffts::>(c, 1 << 19, "radix-2 FFT - 2^19 - tweedle"); + bench_ffts::>(c, 1 << 20, "radix-2 FFT - 2^20 - tweedle"); + bench_ffts::>(c, 1 << 21, "radix-2 FFT - 2^21 - tweedle"); + bench_ffts::>(c, 1 << 22, "radix-2 FFT - 2^22 - tweedle"); + bench_ffts::>(c, 1 << 23, "radix-2 FFT - 2^23 - tweedle"); +} + +fn bench_iffts>( + c: &mut Criterion, + num_coeffs: usize, + name: &'static str, +) { + let mut group = c.benchmark_group(name); + + // We expect the num_coeffs input to be a compatible size for the domain. + let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); + let domain_size = domain.size(); + assert_eq!(num_coeffs, domain_size); + + group.bench_with_input( + BenchmarkId::from_parameter(num_coeffs), + &num_coeffs, + |b, _samples| { + b.iter_batched( + || { + let a: Vec = load_data(num_coeffs); + a + }, + |mut a| { + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + domain.ifft( + &mut a, + ); + + add_to_trace!( + || format!("****************{}*******************", domain_size), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }, + BatchSize::PerIteration, + ); + }, + ); +} + +fn bench_ifft_tweedle(c: &mut Criterion) { + bench_iffts::>(c, 1 << 14, "radix-2 iFFT - 2^14 - tweedle"); + bench_iffts::>(c, 1 << 15, "radix-2 iFFT - 2^15 - tweedle"); + bench_iffts::>(c, 1 << 16, "radix-2 iFFT - 2^16 - tweedle"); + bench_iffts::>(c, 1 << 17, "radix-2 iFFT - 2^17 - tweedle"); + bench_iffts::>(c, 1 << 18, "radix-2 iFFT - 2^18 - tweedle"); + bench_iffts::>(c, 1 << 19, "radix-2 iFFT - 2^19 - tweedle"); + bench_iffts::>(c, 1 << 20, "radix-2 iFFT - 2^20 - tweedle"); + bench_iffts::>(c, 1 << 21, "radix-2 iFFT - 2^21 - tweedle"); + bench_iffts::>(c, 1 << 22, "radix-2 iFFT - 2^22 - tweedle"); + bench_iffts::>(c, 1 << 23, "radix-2 iFFT - 2^23 - tweedle"); +} + +fn bench_dense_poly_muls>( + c: &mut Criterion, + num_degree: usize, + name: &'static str, +) { + // Per benchmark setup + let rng = &mut rand::thread_rng(); + + c.bench_function(name, move |bencher| { + let p1 = DensePolynomial::::rand(num_degree, rng); + let p2 = DensePolynomial::::rand(num_degree, rng); + + bencher.iter(|| { + add_to_trace!( + || format!("****************{}*******************", num_degree), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + let _ab = (&p1) * (&p2); + + add_to_trace!( + || format!("****************{}*******************", num_degree), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }) + }); +} + +fn bench_dense_poly_mul_tweedle(c: &mut Criterion) { + bench_dense_poly_muls::>( + c, + 1 << 14, + "radix-2 DensePolynomial::mul - 2^14 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 15, + "radix-2 DensePolynomial::mul - 2^15 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 16, + "radix-2 DensePolynomial::mul - 2^16 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 17, + "radix-2 DensePolynomial::mul - 2^17 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 18, + "radix-2 DensePolynomial::mul - 2^18 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 19, + "radix-2 DensePolynomial::mul - 2^19 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 20, + "radix-2 DensePolynomial::mul - 2^20 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 21, + "radix-2 DensePolynomial::mul - 2^21 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 22, + "radix-2 DensePolynomial::mul - 2^22 - tweedle", + ); + bench_dense_poly_muls::>( + c, + 1 << 23, + "radix-2 DensePolynomial::mul - 2^23 - tweedle", + ); +} + +fn bench_dense_poly_div_by_vanishing_poly>( + c: &mut Criterion, + num_coeffs: usize, + name: &'static str, +) { + // Per benchmark setup + let rng = &mut rand::thread_rng(); + + // We expect the num_coeffs input to be a compatible size for the domain. + let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); + let domain_size = domain.size(); + assert_eq!(num_coeffs, domain_size); + + c.bench_function(name, move |bencher| { + let p = DensePolynomial::::rand(4 * num_coeffs, rng); + + bencher.iter(|| { + add_to_trace!( + || format!("****************{}*******************", num_coeffs), + || format!( + "--->START TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + + let _ans1 = p.divide_by_vanishing_poly( + domain.clone(), + ); + + add_to_trace!( + || format!("****************{}*******************", num_coeffs), + || format!( + "--->END TIMESTAMP: {:?}", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + ) + ); + }) + }); +} + +fn bench_dense_poly_divide_by_vanishing_poly_tweedle(c: &mut Criterion) { + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 14, + "radix-2 DensePolynomial::div by vanishing poly - 2^14 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 15, + "radix-2 DensePolynomial::div by vanishing poly - 2^15 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 16, + "radix-2 DensePolynomial::div by vanishing poly - 2^16 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 17, + "radix-2 DensePolynomial::div by vanishing poly - 2^17 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 18, + "radix-2 DensePolynomial::div by vanishing poly - 2^18 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 19, + "radix-2 DensePolynomial::div by vanishing poly - 2^19 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 20, + "radix-2 DensePolynomial::div by vanishing poly - 2^20 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 21, + "radix-2 DensePolynomial::div by vanishing poly - 2^21 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 22, + "radix-2 DensePolynomial::div by vanishing poly - 2^22 - tweedle", + ); + bench_dense_poly_div_by_vanishing_poly::>( + c, + 1 << 23, + "radix-2 DensePolynomial::div by vanishing poly - 2^23 - tweedle", + ); +} + +criterion_group! { + name = radix_2_fft; + config = Criterion::default().sample_size(10); + targets = bench_fft_tweedle, bench_ifft_tweedle, bench_dense_poly_mul_tweedle, bench_dense_poly_divide_by_vanishing_poly_tweedle +} + +criterion_main!(radix_2_fft); diff --git a/algebra-utils/benches/fft/mod.rs b/algebra-utils/benches/fft/mod.rs deleted file mode 100644 index 56e00063b..000000000 --- a/algebra-utils/benches/fft/mod.rs +++ /dev/null @@ -1,121 +0,0 @@ -use algebra::{ - fields::mnt6753::Fr, - fft::get_best_evaluation_domain, - UniformRand, -}; -use rand::SeedableRng; -use rand_xorshift::XorShiftRng; - -#[bench] -fn bench_basic_domain_fft(b: &mut ::test::Bencher) { - const SAMPLES: usize = 1000; - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - - let num_coeffs = 1 << 14; - let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); - let domain_size = domain.size(); - assert_eq!(num_coeffs, domain_size); - - let v_a: Vec> = (0..SAMPLES) - .map(|_| { - let mut v = vec![]; - for _ in 0..domain_size { - v.push(Fr::rand(&mut rng)); - } - v - }).collect(); - - let v_b: Vec> = (0..SAMPLES) - .map(|_| { - let mut v = vec![]; - for _ in 0..domain_size { - v.push(Fr::rand(&mut rng)); - } - v - }).collect(); - - let v_c: Vec> = (0..SAMPLES) - .map(|_| { - let mut v = vec![]; - for _ in 0..domain_size { - v.push(Fr::rand(&mut rng)); - } - v - }).collect(); - - let mut count = 0; - b.iter(|| { - count = (count + 1) % SAMPLES; - let mut a = v_a[count].clone(); - let mut b = v_b[count].clone(); - domain.ifft_in_place(&mut a); - domain.ifft_in_place(&mut b); - domain.coset_fft_in_place(&mut a); - domain.coset_fft_in_place(&mut b); - let mut ab = domain.mul_polynomials_in_evaluation_domain(&a, &b); - drop(a); - drop(b); - let mut c = v_c[count].clone(); - domain.ifft_in_place(&mut c); - domain.coset_fft_in_place(&mut c); - domain.divide_by_vanishing_poly_on_coset_in_place(&mut ab); - domain.coset_ifft_in_place(&mut ab); - }); -} - -#[bench] -fn bench_mixed_domain_fft(b: &mut ::test::Bencher) { - const SAMPLES: usize = 1000; - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - - let num_coeffs = 10240; - let domain = get_best_evaluation_domain::(num_coeffs).unwrap(); - let domain_size = domain.size(); - assert_eq!(num_coeffs, domain_size); - - let v_a: Vec> = (0..SAMPLES) - .map(|_| { - let mut v = vec![]; - for _ in 0..domain_size { - v.push(Fr::rand(&mut rng)); - } - v - }).collect(); - - let v_b: Vec> = (0..SAMPLES) - .map(|_| { - let mut v = vec![]; - for _ in 0..domain_size { - v.push(Fr::rand(&mut rng)); - } - v - }).collect(); - - let v_c: Vec> = (0..SAMPLES) - .map(|_| { - let mut v = vec![]; - for _ in 0..domain_size { - v.push(Fr::rand(&mut rng)); - } - v - }).collect(); - - let mut count = 0; - b.iter(|| { - count = (count + 1) % SAMPLES; - let mut a = v_a[count].clone(); - let mut b = v_b[count].clone(); - domain.ifft_in_place(&mut a); - domain.ifft_in_place(&mut b); - domain.coset_fft_in_place(&mut a); - domain.coset_fft_in_place(&mut b); - let mut ab = domain.mul_polynomials_in_evaluation_domain(&a, &b); - drop(a); - drop(b); - let mut c = v_c[count].clone(); - domain.ifft_in_place(&mut c); - domain.coset_fft_in_place(&mut c); - domain.divide_by_vanishing_poly_on_coset_in_place(&mut ab); - domain.coset_ifft_in_place(&mut ab); - }); -} \ No newline at end of file diff --git a/algebra-utils/benches/msm/variable_msm_bn382.rs b/algebra-utils/benches/msm/variable_msm_bn382.rs new file mode 100644 index 000000000..a724b8b90 --- /dev/null +++ b/algebra-utils/benches/msm/variable_msm_bn382.rs @@ -0,0 +1,125 @@ +#[macro_use] +extern crate criterion; + +#[macro_use] +extern crate bench_utils; + +use criterion::{BenchmarkId, Criterion, BatchSize}; + +use algebra::{ + curves::bn_382::{G1Projective, G1Affine}, + BigInteger384, UniformRand, ProjectiveCurve, FromBytes, ToBytes +}; +use algebra_utils::msm::VariableBaseMSM; + +use std::time::{SystemTime, UNIX_EPOCH}; +use std::fs::File; +use std::path::Path; + +const DATA_PATH: &'static str = "./msm_bases_bn382"; + +fn save_data(samples: usize) { + let rng = &mut rand::thread_rng(); + + let mut fs = File::create(DATA_PATH).unwrap(); + + for _ in 0..samples { + let elem1:BigInteger384 = BigInteger384::rand(rng); + let elem2:G1Affine = G1Projective::rand(rng).into_affine(); + match elem1.write(&mut fs) { + Ok(_) => {}, + Err(msg) => { panic!("Cannot save coeffs to file: {}", msg)} + } + match elem2.write(&mut fs) { + Ok(_) => {}, + Err(msg) => { panic!("Cannot save coeffs to file: {}", msg)} + } + } +} + +fn load_data(samples: usize) -> (Vec,Vec) { + + if !Path::new(DATA_PATH).exists() { + save_data(1 << 23); + } + + let mut fs = File::open(DATA_PATH).unwrap(); + let mut v = Vec::with_capacity(samples); + let mut g = Vec::with_capacity(samples); + + for _i in 0..samples { + let elem1 = BigInteger384::read(&mut fs).unwrap(); + let elem2 = G1Affine::read(&mut fs).unwrap(); + v.push(elem1); + g.push(elem2); + } + + (v, g) +} + +fn variable_msm_affine(c: &mut Criterion) { + + let mut group = c.benchmark_group("variable_base_msm_affine-bn382-variable number of bases = number of scalars"); + let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + //VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), PARAM_C); + VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn variable_msm_fast(c: &mut Criterion) { + let mut group = c.benchmark_group("variable_base_msm_fast-bn382-variable number of bases = number of scalars"); + let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + + VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +criterion_group! { + name = variable_msm_eval_bn382; + config = Criterion::default().sample_size(10); + targets = variable_msm_fast, variable_msm_affine, +} + +criterion_main! ( + variable_msm_eval_bn382 +); + diff --git a/algebra-utils/benches/msm/variable_msm_tweedle.rs b/algebra-utils/benches/msm/variable_msm_tweedle.rs new file mode 100644 index 000000000..5d27c517a --- /dev/null +++ b/algebra-utils/benches/msm/variable_msm_tweedle.rs @@ -0,0 +1,239 @@ +#[macro_use] +extern crate criterion; + +#[macro_use] +extern crate bench_utils; + +use criterion::{BenchmarkId, Criterion, BatchSize}; + +use algebra::tweedle::{ + Fp, dee::Projective as G1Projective, + dee::Affine as G1Affine +}; + +use algebra::{UniformRand, PrimeField, ProjectiveCurve}; +use rand::rngs::OsRng; +use std::time::{SystemTime, UNIX_EPOCH}; + + +use algebra_core::msm::VariableBaseMSM; +use rand_xorshift::XorShiftRng; +use std::fs::File; +use rand::SeedableRng; +use algebra_core::{ToBytes, BigInteger256, FromBytes}; + +const PARAM_C: usize = 16; + +fn variable_msm_affine_sd(c: &mut Criterion) { + + let mut group = c.benchmark_group("variable_base_msm_affine_sd-tweedle_dee-variable number of bases = number of scalars"); + let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), PARAM_C); + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn variable_msm_affine(c: &mut Criterion) { + let mut group = c.benchmark_group("variable_base_msm_affine-tweedle_dee-variable number of bases = number of scalars"); + let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), PARAM_C); + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn variable_msm_fast(c: &mut Criterion) { + + let mut group = c.benchmark_group("variable_base_msm_fast-tweedle_dee-variable number of bases = number of scalars"); + let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + VariableBaseMSM::multi_scalar_mul_c(g.as_slice(), v.as_slice(), PARAM_C); + add_to_trace!( + || format!("****************{}*******************", samples), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn variable_msm_affine_sd_4(c: &mut Criterion) { + + let mut group = c.benchmark_group("variable_base_msm_affine_sd-tweedle_dee-variable number of bases = number of scalars"); + let samples = (17..=23).map(|i| 2usize.pow(i)).collect::>(); + + let c = 4; + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples.to_string()+"_"+ &*c.to_string()), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}-{}*******************", samples, c), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), c); + add_to_trace!( + || format!("****************{}-{}*******************", samples, c), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn variable_msm_affine_4(c: &mut Criterion) { + + let mut group = c.benchmark_group("variable_base_msm_affine-tweedle_dee-variable number of bases = number of scalars"); + let samples = (17..=23).map(|i| 2usize.pow(i)).collect::>(); + + let c = 4; + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples.to_string()+"_"+ &*c.to_string()), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}-{}*******************", samples, c), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), c); + add_to_trace!( + || format!("****************{}-{}*******************", samples, c), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn variable_msm_fast_4(c: &mut Criterion) { + + let mut group = c.benchmark_group("variable_base_msm_fast-tweedle_dee-variable number of bases = number of scalars"); + let samples = (17..=23).map(|i| 2usize.pow(i)).collect::>(); + + let c = 4; + + for &samples in samples.iter() { + group.bench_with_input(BenchmarkId::from_parameter(samples.to_string()+"_"+ &*c.to_string()), &samples, |b, _samples| { + //group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { + b.iter_batched(|| { + let (v, g) = load_data(samples); + (v, g) + }, + |(v, g)| { + add_to_trace!( + || format!("****************{}-{}*******************", samples, c), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + VariableBaseMSM::multi_scalar_mul_c(g.as_slice(), v.as_slice(), c); + add_to_trace!( + || format!("****************{}-{}*******************", samples, c), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + }, + BatchSize::PerIteration); + }); + } +} + +fn load_data(samples: usize) -> (Vec,Vec) { + + let mut fs = File::open("./scalars_bases_tweedle").unwrap(); + let mut v = Vec::with_capacity(samples); + let mut g = Vec::with_capacity(samples); + + for _i in 0..samples { + let elem1 = BigInteger256::read(&mut fs).unwrap(); + let elem2 = G1Affine::read(&mut fs).unwrap(); + v.push(elem1); + g.push(elem2); + } + (v, g) +} + + +#[allow(dead_code)] +fn generate_data() { + + const SAMPLES: usize = 1<<23; + + let mut rng = XorShiftRng::seed_from_u64(234872845u64); + + let mut fs = File::create("./scalars_bases_tweedle").unwrap(); + + for _i in 0..SAMPLES { + let elem = Fp::rand(&mut rng).into_repr(); + elem.write(&mut fs).unwrap(); + let elem = G1Projective::rand(&mut rng).into_affine(); + elem.write(&mut fs).unwrap(); + } +} + + +criterion_group! { + name = variable_msm_eval_tweedle; + config = Criterion::default().sample_size(10); + targets = variable_msm_fast, variable_msm_affine, variable_msm_affine_sd + // targets = variable_msm_fast_4, variable_msm_affine_4, variable_msm_affine_sd_4 +} + +criterion_main! ( + variable_msm_eval_tweedle +); + diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 9af27bc8f..4e560f852 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = ["parallel"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["parallel"] } bench-utils = { path = "../bench-utils" } digest = { version = "0.7", optional = true } @@ -51,7 +51,7 @@ mnt6_753 = ["algebra/mnt6_753"] bn_382 = ["algebra/bn_382"] [dev-dependencies] -algebra = { path = "../algebra", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } primitives = { path = "../primitives", features = ["mnt4_753", "mnt6_753", "bn_382"] } criterion = "0.3" diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index a2f6c65cc..314ededb8 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = [ "parallel" ] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } r1cs-core = { path = "../r1cs/core" } bench-utils = { path = "../bench-utils" } @@ -37,7 +37,7 @@ csv = { version = "1" } criterion = "0.3" rand_xorshift = { version = "0.2" } -algebra = { path = "../algebra", features = [ "bls12_377", "mnt4_753", "mnt6_753", "sw6", "bn_382" ] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } r1cs-crypto = { path = "../r1cs/gadgets/crypto", features = ["nizk"] } r1cs-std = { path = "../r1cs/gadgets/std" } @@ -46,6 +46,7 @@ print-trace = [ "bench-utils/print-trace" ] groth16 = [] gm17 = [] llvm_asm = ["algebra/llvm_asm"] +gpu = ["algebra-utils/gpu"] [[example]] name = "groth16" @@ -71,4 +72,10 @@ required-features = ["gm17", "r1cs-crypto/mnt4_753", "r1cs-crypto/mnt6_753", "r1 name = "gro16_bench" path = "src/groth16/benches/gro16_bench.rs" harness = false +required-features = ["groth16", "algebra/bn_382"] + +[[bench]] +name = "bn382_gro16_test_circuits" +path = "src/groth16/benches/bn382_gro16_test_circuits.rs" +harness = false required-features = ["groth16", "algebra/bn_382"] \ No newline at end of file diff --git a/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs b/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs new file mode 100644 index 000000000..1676d7a05 --- /dev/null +++ b/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs @@ -0,0 +1,247 @@ +use algebra::{ + fields::bn_382::Fr, + curves::bn_382::Bn382, + UniformRand, PrimeField, +}; +use r1cs_core::{SynthesisError, ConstraintSynthesizer, ConstraintSystem}; +use proof_systems::groth16::{generate_random_parameters, create_random_proof}; + +use criterion::{BenchmarkId, BatchSize}; +use criterion::Criterion; +use r1cs_std::Assignment; +use r1cs_std::fields::fp::FpGadget; +use r1cs_std::fields::FieldGadget; +use r1cs_std::alloc::AllocGadget; + +use rand::{ + rngs::OsRng, thread_rng +}; + +use std::time::{SystemTime, UNIX_EPOCH}; + +#[macro_use] +extern crate criterion; + +#[macro_use] +extern crate bench_utils; + +pub struct TestCircuit1 { + num_constraints: usize, + a: Option, + b: Option, +} + +pub struct TestCircuit2 { + num_constraints: usize, + a: Option, + b: Option, +} + +impl ConstraintSynthesizer for TestCircuit1 { + fn generate_constraints>( + self, + cs: &mut CS, + ) -> Result<(), SynthesisError> { + + let mut a_k_minus_1 = FpGadget::::alloc_input( + cs.ns(|| "alloc a"), + || self.a.ok_or(SynthesisError::AssignmentMissing) + )?; + + let mut b_k_minus_1 = FpGadget::::alloc_input( + cs.ns(|| "alloc b"), + || self.b.ok_or(SynthesisError::AssignmentMissing) + )?; + + // let zero = FpGadget::::zero(cs.ns(|| "alloc zero"))?; + + // a_k_minus_1.enforce_not_equal(cs.ns(|| "a_0 != 0"), &zero)?; + // b_k_minus_1.enforce_not_equal(cs.ns(|| "b_0 != 0"), &zero)?; + + for k in 0..(self.num_constraints - 5)/2 { + + let a_k = FpGadget::::alloc( + cs.ns(|| format!("alloc a_{}", k)), + || Ok(a_k_minus_1.value.get()? * &b_k_minus_1.value.get()?) + )?; + + let b_k = FpGadget::::alloc( + cs.ns(|| format!("alloc b_{}", k)), + || Ok(b_k_minus_1.value.get()? * &a_k_minus_1.value.get()?) + )?; + + a_k_minus_1.mul_equals( + cs.ns(|| format!("a_{} * b_{} = a_{}", k - 1, k - 1, k)), + &b_k_minus_1, + &a_k + )?; + + b_k_minus_1.mul_equals( + cs.ns(|| format!("b_{} * a_{} = b_{}", k - 1, k - 1, k)), + &a_k_minus_1, + &b_k + )?; + + a_k_minus_1 = a_k; + b_k_minus_1 = b_k; + } + + Ok(()) + } +} + +impl ConstraintSynthesizer for TestCircuit2 { + fn generate_constraints>( + self, + cs: &mut CS, + ) -> Result<(), SynthesisError> { + + let mut a_k_minus_1 = FpGadget::::alloc_input( + cs.ns(|| "alloc a"), + || self.a.ok_or(SynthesisError::AssignmentMissing) + )?; + + let mut b_k_minus_1 = FpGadget::::alloc_input( + cs.ns(|| "alloc b"), + || self.b.ok_or(SynthesisError::AssignmentMissing) + )?; + + // let zero = FpGadget::::zero(cs.ns(|| "alloc zero"))?; + + // a_k_minus_1.enforce_not_equal(cs.ns(|| "a_0 != 0"), &zero)?; + // b_k_minus_1.enforce_not_equal(cs.ns(|| "b_0 != 0"), &zero)?; + + for k in 0..(self.num_constraints - 5)/2 { + + let a_k = FpGadget::::alloc( + cs.ns(|| format!("alloc a_{}", k)), + || Ok(a_k_minus_1.value.get()? * &b_k_minus_1.value.get()?.inverse().get()?) + )?; + + let b_k = FpGadget::::alloc( + cs.ns(|| format!("alloc b_{}", k)), + || Ok(b_k_minus_1.value.get()? * &a_k_minus_1.value.get()?) + )?; + + a_k.mul_equals( + cs.ns(|| format!("a_{} * b_{} = a_{}", k, k - 1, k - 1)), + &b_k_minus_1, + &a_k_minus_1 + )?; + + b_k_minus_1.mul_equals( + cs.ns(|| format!("b_{} * a_{} = b_{}", k - 1, k - 1, k)), + &a_k_minus_1, + &b_k + )?; + + a_k_minus_1 = a_k; + b_k_minus_1 = b_k; + } + + Ok(()) + } +} + +fn bench_prover_circuit1(c: &mut Criterion){ + + let mut rng = thread_rng(); + + let mut group = c.benchmark_group("gro16-bn382-test circuit 1-variable constraints"); + + let num_constraints = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + for &num_constraints in num_constraints.iter() + { + let params = { + let c = TestCircuit1::{ num_constraints, a: None, b: None }; + generate_random_parameters::(c, &mut rng).unwrap() + }; + + add_to_trace!( + || format!("****************{}*******************", num_constraints), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + + group.bench_with_input(BenchmarkId::from_parameter(num_constraints), &num_constraints, |bn, _constraints| { + bn.iter_batched( + || { + let mut rng = OsRng::default(); + let a = Fr::rand(&mut rng); + let b = Fr::rand(&mut rng); + (a, b) + }, + |(a, b)| { + let c = TestCircuit1{ num_constraints, a: Some(a), b: Some(b) }; + + create_random_proof( + c, + ¶ms, + &mut rng, + ) + .unwrap(); + + }, + BatchSize::PerIteration + ); + }); + add_to_trace!( + || format!("****************{}*******************", num_constraints), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); } + group.finish(); +} + +fn bench_prover_circuit2(c: &mut Criterion){ + let mut rng = thread_rng(); + + let mut group = c.benchmark_group("gro16-bn382-test circuit 2-variable constraints"); + + let num_constraints = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + + for &num_constraints in num_constraints.iter() + { + let params = { + let c = TestCircuit2::{ num_constraints, a: None, b: None }; + generate_random_parameters::(c, &mut rng).unwrap() + }; + + add_to_trace!( + || format!("****************{}*******************", num_constraints), + || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + group.bench_with_input(BenchmarkId::from_parameter(num_constraints), &num_constraints, |bn, _constraints| { + bn.iter_batched( + || { + let mut rng = OsRng::default(); + let a = Fr::rand(&mut rng); + let b = Fr::rand(&mut rng); + (a, b) + }, + |(a, b)| { + let c = TestCircuit2{ num_constraints, a: Some(a), b: Some(b) }; + + create_random_proof( + c, + ¶ms, + &mut rng, + ).unwrap(); + }, + BatchSize::PerIteration + ); + }); + add_to_trace!( + || format!("****************{}*******************", num_constraints), + || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) + ); + } + group.finish(); +} + +criterion_group!( +name = bn382_gro16_test_circuits; +config = Criterion::default().sample_size(10); +targets = bench_prover_circuit1, bench_prover_circuit2 +); + +criterion_main!(bn382_gro16_test_circuits); \ No newline at end of file diff --git a/r1cs/core/Cargo.toml b/r1cs/core/Cargo.toml index 947a85de0..24cb11215 100644 --- a/r1cs/core/Cargo.toml +++ b/r1cs/core/Cargo.toml @@ -18,5 +18,5 @@ include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" [dependencies] -algebra = { path = "../../algebra" } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl" } smallvec = { version = "0.6" } diff --git a/r1cs/gadgets/crypto/Cargo.toml b/r1cs/gadgets/crypto/Cargo.toml index f30f8d99f..20465a096 100644 --- a/r1cs/gadgets/crypto/Cargo.toml +++ b/r1cs/gadgets/crypto/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../../../algebra", features = ["parallel"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } primitives = {path = "../../../primitives"} r1cs-core = { path = "../../core"} r1cs-std = { path = "../std"} @@ -51,6 +51,6 @@ llvm_asm = ["algebra/llvm_asm"] [dev-dependencies] rand_xorshift = { version = "0.2" } -algebra = { path = "../../../algebra", features = ["bls12_381", "sw6"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "sw6"] } r1cs-std = { path = "../std", features = ["jubjub", "edwards_sw6", "bls12_377", "mnt4_753", "mnt6_753", "bn_382"] } r1cs-crypto = { path = "../crypto", features = ["mnt4_753", "mnt6_753", "bn_382"] } \ No newline at end of file diff --git a/r1cs/gadgets/std/Cargo.toml b/r1cs/gadgets/std/Cargo.toml index 3f5e6913d..6eb0b6e5b 100644 --- a/r1cs/gadgets/std/Cargo.toml +++ b/r1cs/gadgets/std/Cargo.toml @@ -20,7 +20,7 @@ license = "MIT/Apache-2.0" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../../../algebra" } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl" } r1cs-core = { path = "../../core"} derivative = "1" radix_trie = "0.1" @@ -41,4 +41,4 @@ mnt6_753 = [ "algebra/mnt6_753" ] [dev-dependencies] rand = { version = "0.7" } rand_xorshift = { version = "0.2" } -algebra = { path = "../../../algebra", features = ["bls12_381", "jubjub"] } +algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "jubjub"] } From 6e5b3e2a1c91474c03921be84dc7950e8a045997 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 00:11:02 +0200 Subject: [PATCH 17/63] ASM feature added to algebra-utils --- algebra-utils/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index d44842007..859196ec4 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -45,6 +45,7 @@ bench-utils = { path = "../bench-utils" } parallel = [ "rayon" ] fft = [] gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] +llvm_asm = [ "algebra/llvm_asm" ] [build-dependencies] rustc_version = "0.2" From 59c804e27e7286ba62804b803baf4bcba4509f10 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 00:54:55 +0200 Subject: [PATCH 18/63] Benches bugfix --- algebra-utils/benches/fft/fft_tweedle.rs | 1 + .../benches/msm/variable_msm_tweedle.rs | 214 ++++-------------- 2 files changed, 51 insertions(+), 164 deletions(-) diff --git a/algebra-utils/benches/fft/fft_tweedle.rs b/algebra-utils/benches/fft/fft_tweedle.rs index 2a5556a55..3039e9176 100644 --- a/algebra-utils/benches/fft/fft_tweedle.rs +++ b/algebra-utils/benches/fft/fft_tweedle.rs @@ -13,6 +13,7 @@ use rand; use std::{ fs::File, + path::Path, time::{SystemTime, UNIX_EPOCH}, }; diff --git a/algebra-utils/benches/msm/variable_msm_tweedle.rs b/algebra-utils/benches/msm/variable_msm_tweedle.rs index 5d27c517a..ce84b4c17 100644 --- a/algebra-utils/benches/msm/variable_msm_tweedle.rs +++ b/algebra-utils/benches/msm/variable_msm_tweedle.rs @@ -6,53 +6,60 @@ extern crate bench_utils; use criterion::{BenchmarkId, Criterion, BatchSize}; -use algebra::tweedle::{ - Fp, dee::Projective as G1Projective, - dee::Affine as G1Affine +use algebra::{ + curves::tweedle::dee::{Projective as G1Projective, Affine as G1Affine}, + BigInteger256, UniformRand, ProjectiveCurve, FromBytes, ToBytes }; +use algebra_utils::msm::VariableBaseMSM; -use algebra::{UniformRand, PrimeField, ProjectiveCurve}; -use rand::rngs::OsRng; use std::time::{SystemTime, UNIX_EPOCH}; - - -use algebra_core::msm::VariableBaseMSM; -use rand_xorshift::XorShiftRng; use std::fs::File; -use rand::SeedableRng; -use algebra_core::{ToBytes, BigInteger256, FromBytes}; +use std::path::Path; + +const DATA_PATH: &'static str = "./msm_bases_tweedle"; + +fn save_data(samples: usize) { + let rng = &mut rand::thread_rng(); + + let mut fs = File::create(DATA_PATH).unwrap(); + + for _ in 0..samples { + let elem1:BigInteger256 = BigInteger256::rand(rng); + let elem2:G1Affine = G1Projective::rand(rng).into_affine(); + match elem1.write(&mut fs) { + Ok(_) => {}, + Err(msg) => { panic!("Cannot save coeffs to file: {}", msg)} + } + match elem2.write(&mut fs) { + Ok(_) => {}, + Err(msg) => { panic!("Cannot save coeffs to file: {}", msg)} + } + } +} -const PARAM_C: usize = 16; +fn load_data(samples: usize) -> (Vec,Vec) { -fn variable_msm_affine_sd(c: &mut Criterion) { + if !Path::new(DATA_PATH).exists() { + save_data(1 << 23); + } - let mut group = c.benchmark_group("variable_base_msm_affine_sd-tweedle_dee-variable number of bases = number of scalars"); - let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + let mut fs = File::open(DATA_PATH).unwrap(); + let mut v = Vec::with_capacity(samples); + let mut g = Vec::with_capacity(samples); - for &samples in samples.iter() { - group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { - b.iter_batched(|| { - let (v, g) = load_data(samples); - (v, g) - }, - |(v, g)| { - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), PARAM_C); - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - }, - BatchSize::PerIteration); - }); + for _i in 0..samples { + let elem1 = BigInteger256::read(&mut fs).unwrap(); + let elem2 = G1Affine::read(&mut fs).unwrap(); + v.push(elem1); + g.push(elem2); } + + (v, g) } fn variable_msm_affine(c: &mut Criterion) { - let mut group = c.benchmark_group("variable_base_msm_affine-tweedle_dee-variable number of bases = number of scalars"); + + let mut group = c.benchmark_group("variable_base_msm_affine-tweedle-variable number of bases = number of scalars"); let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); for &samples in samples.iter() { @@ -66,11 +73,12 @@ fn variable_msm_affine(c: &mut Criterion) { || format!("****************{}*******************", samples), || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); - VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), PARAM_C); + //VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), PARAM_C); + VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); add_to_trace!( || format!("****************{}*******************", samples), || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); + ); }, BatchSize::PerIteration); }); @@ -78,10 +86,10 @@ fn variable_msm_affine(c: &mut Criterion) { } fn variable_msm_fast(c: &mut Criterion) { - - let mut group = c.benchmark_group("variable_base_msm_fast-tweedle_dee-variable number of bases = number of scalars"); + let mut group = c.benchmark_group("variable_base_msm_fast-tweedle-variable number of bases = number of scalars"); let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + for &samples in samples.iter() { group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { b.iter_batched(|| { @@ -93,97 +101,10 @@ fn variable_msm_fast(c: &mut Criterion) { || format!("****************{}*******************", samples), || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); - VariableBaseMSM::multi_scalar_mul_c(g.as_slice(), v.as_slice(), PARAM_C); - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - }, - BatchSize::PerIteration); - }); - } -} - -fn variable_msm_affine_sd_4(c: &mut Criterion) { - let mut group = c.benchmark_group("variable_base_msm_affine_sd-tweedle_dee-variable number of bases = number of scalars"); - let samples = (17..=23).map(|i| 2usize.pow(i)).collect::>(); - - let c = 4; - - for &samples in samples.iter() { - group.bench_with_input(BenchmarkId::from_parameter(samples.to_string()+"_"+ &*c.to_string()), &samples, |b, _samples| { - b.iter_batched(|| { - let (v, g) = load_data(samples); - (v, g) - }, - |(v, g)| { + VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); add_to_trace!( - || format!("****************{}-{}*******************", samples, c), - || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), c); - add_to_trace!( - || format!("****************{}-{}*******************", samples, c), - || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - }, - BatchSize::PerIteration); - }); - } -} - -fn variable_msm_affine_4(c: &mut Criterion) { - - let mut group = c.benchmark_group("variable_base_msm_affine-tweedle_dee-variable number of bases = number of scalars"); - let samples = (17..=23).map(|i| 2usize.pow(i)).collect::>(); - - let c = 4; - - for &samples in samples.iter() { - group.bench_with_input(BenchmarkId::from_parameter(samples.to_string()+"_"+ &*c.to_string()), &samples, |b, _samples| { - b.iter_batched(|| { - let (v, g) = load_data(samples); - (v, g) - }, - |(v, g)| { - add_to_trace!( - || format!("****************{}-{}*******************", samples, c), - || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), c); - add_to_trace!( - || format!("****************{}-{}*******************", samples, c), - || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - }, - BatchSize::PerIteration); - }); - } -} - -fn variable_msm_fast_4(c: &mut Criterion) { - - let mut group = c.benchmark_group("variable_base_msm_fast-tweedle_dee-variable number of bases = number of scalars"); - let samples = (17..=23).map(|i| 2usize.pow(i)).collect::>(); - - let c = 4; - - for &samples in samples.iter() { - group.bench_with_input(BenchmarkId::from_parameter(samples.to_string()+"_"+ &*c.to_string()), &samples, |b, _samples| { - //group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { - b.iter_batched(|| { - let (v, g) = load_data(samples); - (v, g) - }, - |(v, g)| { - add_to_trace!( - || format!("****************{}-{}*******************", samples, c), - || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - VariableBaseMSM::multi_scalar_mul_c(g.as_slice(), v.as_slice(), c); - add_to_trace!( - || format!("****************{}-{}*******************", samples, c), + || format!("****************{}*******************", samples), || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); }, @@ -192,45 +113,10 @@ fn variable_msm_fast_4(c: &mut Criterion) { } } -fn load_data(samples: usize) -> (Vec,Vec) { - - let mut fs = File::open("./scalars_bases_tweedle").unwrap(); - let mut v = Vec::with_capacity(samples); - let mut g = Vec::with_capacity(samples); - - for _i in 0..samples { - let elem1 = BigInteger256::read(&mut fs).unwrap(); - let elem2 = G1Affine::read(&mut fs).unwrap(); - v.push(elem1); - g.push(elem2); - } - (v, g) -} - - -#[allow(dead_code)] -fn generate_data() { - - const SAMPLES: usize = 1<<23; - - let mut rng = XorShiftRng::seed_from_u64(234872845u64); - - let mut fs = File::create("./scalars_bases_tweedle").unwrap(); - - for _i in 0..SAMPLES { - let elem = Fp::rand(&mut rng).into_repr(); - elem.write(&mut fs).unwrap(); - let elem = G1Projective::rand(&mut rng).into_affine(); - elem.write(&mut fs).unwrap(); - } -} - - criterion_group! { name = variable_msm_eval_tweedle; config = Criterion::default().sample_size(10); - targets = variable_msm_fast, variable_msm_affine, variable_msm_affine_sd - // targets = variable_msm_fast_4, variable_msm_affine_4, variable_msm_affine_sd_4 + targets = variable_msm_fast, variable_msm_affine, } criterion_main! ( From d64045e164560ac7f73843cf456aa1aa51a01f4e Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 22:39:26 +0200 Subject: [PATCH 19/63] Add tweedle to r1cs-std --- r1cs/gadgets/std/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/r1cs/gadgets/std/Cargo.toml b/r1cs/gadgets/std/Cargo.toml index 6eb0b6e5b..561859ca5 100644 --- a/r1cs/gadgets/std/Cargo.toml +++ b/r1cs/gadgets/std/Cargo.toml @@ -28,7 +28,7 @@ radix_trie = "0.1" [features] llvm_asm = ["algebra/llvm_asm"] -full = [ "bls12_377", "bn_382", "edwards_bls12", "edwards_sw6", "jubjub", "mnt4_753", "mnt6_753" ] +full = [ "bls12_377", "bn_382", "edwards_bls12", "edwards_sw6", "jubjub", "mnt4_753", "mnt6_753", "tweedle" ] bls12_377 = [ "algebra/bls12_377" ] bn_382 = [ "algebra/bn_382" ] @@ -37,6 +37,7 @@ edwards_sw6 = [ "algebra/edwards_sw6"] jubjub = [ "algebra/jubjub" ] mnt4_753 = [ "algebra/mnt4_753" ] mnt6_753 = [ "algebra/mnt6_753" ] +tweedle = [ "algebra/tweedle" ] [dev-dependencies] rand = { version = "0.7" } From 0a1937c1aefe90e223e89458dd78a11f1d78a53d Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 23:14:43 +0200 Subject: [PATCH 20/63] log2 function added --- algebra/src/lib.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/algebra/src/lib.rs b/algebra/src/lib.rs index a9f381c3f..160d4f685 100644 --- a/algebra/src/lib.rs +++ b/algebra/src/lib.rs @@ -40,4 +40,14 @@ pub use self::rand::*; mod to_field_vec; pub use to_field_vec::ToConstraintField; -pub type Error = Box; \ No newline at end of file +pub type Error = Box; + +/// Returns log2 +pub fn log2(x: usize) -> u32 { + if x <= 1 { + return 0; + } + + let n = x.leading_zeros(); + core::mem::size_of::() as u32 * 8 - n +} From 5069ae16d014a09c015e04fe332941dd895d9e9b Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 23:34:55 +0200 Subject: [PATCH 21/63] Merge with 'all' --- .../src/fft/domain/basic_radix_2_domain.rs | 36 ----- .../src/fft/domain/mixed_radix_2_domain.rs | 9 -- algebra-utils/src/fft/domain/mod.rs | 46 +++++- algebra-utils/src/fft/multicore.rs | 28 +--- algebra-utils/src/fft/polynomial/dense.rs | 2 +- algebra/src/curves/mod.rs | 31 +++- .../models/short_weierstrass_jacobian.rs | 68 ++++++++- .../models/twisted_edwards_extended/mod.rs | 45 +++++- algebra/src/fields/arithmetic.rs | 85 ++++++----- algebra/src/fields/macros.rs | 1 + algebra/src/fields/mod.rs | 16 +- algebra/src/fields/models/cubic_extension.rs | 3 + .../src/fields/models/quadratic_extension.rs | 3 + algebra/src/lib.rs | 45 +++++- primitives/src/merkle_tree/mod.rs | 9 +- proof-systems/src/gm17/generator.rs | 11 +- proof-systems/src/groth16/generator.rs | 11 +- proof-systems/src/lib.rs | 2 +- .../src/merkle_tree/field_based_mht/mod.rs | 87 +++++++++++ r1cs/gadgets/crypto/src/merkle_tree/mod.rs | 2 +- r1cs/gadgets/crypto/src/signature/mod.rs | 15 +- .../signature/schnorr/field_based_schnorr.rs | 140 +++++++++++++++++- r1cs/gadgets/std/src/lib.rs | 2 +- .../gadgets/std/src/test_constraint_system.rs | 4 +- 24 files changed, 543 insertions(+), 158 deletions(-) diff --git a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs index 684aaf0c9..8b3e0d721 100644 --- a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -2,7 +2,6 @@ use algebra::{FpParameters, PrimeField}; use crate::{multicore::Worker, EvaluationDomain}; use std::fmt; use rayon::prelude::*; -use rand::Rng; use std::any::Any; #[cfg(feature = "gpu")] @@ -92,41 +91,6 @@ impl BasicRadix2Domain { }); } - /// Sample an element that is *not* in the domain. - pub fn sample_element_outside_domain(&self, rng: &mut R) -> F { - let mut t = F::rand(rng); - while self.evaluate_vanishing_polynomial(t).is_zero() { - t = F::rand(rng); - } - t - } - - /// Given an index which assumes the first elements of this domain are the elements of - /// another (sub)domain with size size_s, - /// this returns the actual index into this domain. - pub fn reindex_by_subdomain(&self, other: Self, index: usize) -> usize { - assert!(self.size() >= other.size()); - // Let this subgroup be G, and the subgroup we're re-indexing by be S. - // Since its a subgroup, the 0th element of S is at index 0 in G, the first element of S is at - // index |G|/|S|, the second at 2*|G|/|S|, etc. - // Thus for an index i that corresponds to S, the index in G is i*|G|/|S| - let period = self.size() / other.size(); - if index < other.size() { - index * period - } else { - // Let i now be the index of this element in G \ S - // Let x be the number of elements in G \ S, for every element in S. Then x = (|G|/|S| - 1). - // At index i in G \ S, the number of elements in S that appear before the index in G to which - // i corresponds to, is floor(i / x) + 1. - // The +1 is because index 0 of G is S_0, so the position is offset by at least one. - // The floor(i / x) term is because after x elements in G \ S, there is one more element from S - // that will have appeared in G. - let i = index - other.size(); - let x = period - 1; - i + (i / x) + 1 - } - } - fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { #[cfg(feature = "gpu")] if get_gpu_min_length() <= 1 << log_n { diff --git a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs index 97cb2d50d..63972b1d4 100644 --- a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs @@ -2,7 +2,6 @@ use algebra::{FpParameters, PrimeField}; use crate::{multicore::Worker, EvaluationDomain}; use rayon::prelude::*; use std::fmt; -use rand::Rng; use std::any::Any; #[cfg(feature = "gpu")] @@ -102,14 +101,6 @@ impl MixedRadix2Domain { return Some(best as usize); } - pub fn sample_element_outside_domain(&self, rng: &mut R) -> F { - let mut t = F::rand(rng); - while self.evaluate_vanishing_polynomial(t).is_zero() { - t = F::rand(rng); - } - t - } - fn k_adicity(k: u64, n: u64) -> u64{ let mut r = 0; let mut ctr = n.clone(); diff --git a/algebra-utils/src/fft/domain/mod.rs b/algebra-utils/src/fft/domain/mod.rs index 5dfd84ffa..b2b8d9d00 100644 --- a/algebra-utils/src/fft/domain/mod.rs +++ b/algebra-utils/src/fft/domain/mod.rs @@ -31,13 +31,18 @@ use rayon::prelude::*; //use std::hash::Hash; use std::fmt::Debug; use std::any::Any; +use rand::Rng; /// Defines a domain over which finite field (I)FFTs can be performed. -pub trait EvaluationDomain: Debug +pub trait EvaluationDomain: Debug + Send + Sync { /// Returns the size of the domain fn size(&self) -> usize; + fn size_as_field_element(&self) -> F { + F::from_repr(F::BigInt::from(self.size() as u64)) + } + /// Interprets size as a field element F and returns its inverse in the field fn size_inv(&self) -> F; @@ -158,12 +163,38 @@ pub trait EvaluationDomain: Debug batch_inversion(u.as_mut_slice()); u.par_iter_mut().zip(ls).for_each(|(tau_minus_r, l)| { - *tau_minus_r = l * tau_minus_r; + *tau_minus_r *= l; }); u } } + /// Given an index which assumes the first elements of this domain are the elements of + /// another (sub)domain with size size_s, + /// this returns the actual index into this domain. + fn reindex_by_subdomain(&self, other_size: usize, index: usize) -> usize { + assert!(self.size() >= other_size); + // Let this subgroup be G, and the subgroup we're re-indexing by be S. + // Since its a subgroup, the 0th element of S is at index 0 in G, the first element of S is at + // index |G|/|S|, the second at 2*|G|/|S|, etc. + // Thus for an index i that corresponds to S, the index in G is i*|G|/|S| + let period = self.size() / other_size; + if index < other_size { + index * period + } else { + // Let i now be the index of this element in G \ S + // Let x be the number of elements in G \ S, for every element in S. Then x = (|G|/|S| - 1). + // At index i in G \ S, the number of elements in S that appear before the index in G to which + // i corresponds to, is floor(i / x) + 1. + // The +1 is because index 0 of G is S_0, so the position is offset by at least one. + // The floor(i / x) term is because after x elements in G \ S, there is one more element from S + // that will have appeared in G. + let i = index - other_size; + let x = period - 1; + i + (i / x) + 1 + } + } + /// Return an iterator over the elements of the domain. fn elements(&self) -> Elements { Elements { @@ -218,6 +249,17 @@ impl Iterator for Elements { } } +pub fn sample_element_outside_domain< + F: PrimeField, + R: Rng +>(domain: &Box>, rng: &mut R) -> F { + let mut t = F::rand(rng); + while domain.evaluate_vanishing_polynomial(t).is_zero() { + t = F::rand(rng); + } + t +} + #[cfg(test)] mod tests { use crate::get_best_evaluation_domain; diff --git a/algebra-utils/src/fft/multicore.rs b/algebra-utils/src/fft/multicore.rs index 54dbbe0e0..b1493825b 100644 --- a/algebra-utils/src/fft/multicore.rs +++ b/algebra-utils/src/fft/multicore.rs @@ -15,7 +15,7 @@ impl Worker { } pub(crate) fn log_num_cpus(&self) -> u32 { - log2_floor(self.cpus) + crate::log2_floor(self.cpus) } pub(crate) fn scope<'a, F, R>(&self, elements: usize, f: F) -> R @@ -31,28 +31,4 @@ impl Worker { rayon::scope(move |scope| f(scope, chunk_size)) } -} - -pub(crate) fn log2_floor(num: usize) -> u32 { - assert!(num > 0); - - let mut pow = 0; - - while (1 << (pow + 1)) <= num { - pow += 1; - } - - pow -} - -#[test] -fn test_log2_floor() { - assert_eq!(log2_floor(1), 0); - assert_eq!(log2_floor(2), 1); - assert_eq!(log2_floor(3), 1); - assert_eq!(log2_floor(4), 2); - assert_eq!(log2_floor(5), 2); - assert_eq!(log2_floor(6), 2); - assert_eq!(log2_floor(7), 2); - assert_eq!(log2_floor(8), 3); -} +} \ No newline at end of file diff --git a/algebra-utils/src/fft/polynomial/dense.rs b/algebra-utils/src/fft/polynomial/dense.rs index dcc98cfaa..7a1c48219 100644 --- a/algebra-utils/src/fft/polynomial/dense.rs +++ b/algebra-utils/src/fft/polynomial/dense.rs @@ -140,7 +140,7 @@ impl DensePolynomial { /// Divide `self` by the vanishing polynomial for the domain `domain`. /// Returns the quotient and remainder of the division. - pub fn divide_by_vanishing_poly(&self, domain: Box>) -> Option<(DensePolynomial, DensePolynomial)> { + pub fn divide_by_vanishing_poly(&self, domain: &Box>) -> Option<(DensePolynomial, DensePolynomial)> { let self_poly: DenseOrSparsePolynomial = self.into(); let vanishing_poly: DenseOrSparsePolynomial = domain.vanishing_polynomial().into(); self_poly.divide_with_q_and_r(&vanishing_poly) diff --git a/algebra/src/curves/mod.rs b/algebra/src/curves/mod.rs index 0703b51a4..b244c3cc3 100644 --- a/algebra/src/curves/mod.rs +++ b/algebra/src/curves/mod.rs @@ -1,4 +1,4 @@ -use crate::{bytes::{FromBytes, ToBytes}, fields::{Field, PrimeField, SquareRootField}, groups::Group, SemanticallyValid, FromBytesChecked}; +use crate::{bytes::{FromBytes, ToBytes}, fields::{Field, PrimeField, SquareRootField}, groups::Group, SemanticallyValid, FromBytesChecked, bits::{ToBits, FromCompressedBits}, ToCompressedBits}; use crate::UniformRand; use std::{ fmt::{Debug, Display}, @@ -174,6 +174,11 @@ pub trait ProjectiveCurve: /// conversion to affine is cheap. fn batch_normalization(v: &mut [Self]); + fn batch_normalization_into_affine(mut v: Vec) -> Vec { + Self::batch_normalization(v.as_mut_slice()); + v.into_iter().map(|p| p.into_affine()).collect() + } + /// Checks if the point is already "normalized" so that /// cheap affine conversion is possible. #[must_use] @@ -222,6 +227,8 @@ pub trait AffineCurve: + for <'a> Deserialize<'a> + SemanticallyValid + FromBytesChecked + + ToCompressedBits + + FromCompressedBits + Copy + Clone + Default @@ -250,6 +257,28 @@ pub trait AffineCurve: #[must_use] fn is_zero(&self) -> bool; + /// Returns a group element if the set of bytes forms a valid group element, + /// otherwise returns None. This function is primarily intended for sampling + /// random group elements from a hash-function or RNG output. + fn from_random_bytes(bytes: &[u8]) -> Option { + + let fe = match ::BasePrimeField::from_random_bytes(bytes) { + Some(fe) => fe, + None => return None + }; + + //Get point from chunks + let mut fe_bits = fe.write_bits(); + fe_bits.push(false); //We don't want an infinity point + fe_bits.push(false); //We decide to choose the even y coordinate + match Self::decompress(fe_bits) { + Ok(point) => { + Some(point) + }, + Err(_) => None + } + } + /// Checks that the current point is on curve and is in the /// prime order subgroup #[must_use] diff --git a/algebra/src/curves/models/short_weierstrass_jacobian.rs b/algebra/src/curves/models/short_weierstrass_jacobian.rs index 51090c11c..f54dee779 100644 --- a/algebra/src/curves/models/short_weierstrass_jacobian.rs +++ b/algebra/src/curves/models/short_weierstrass_jacobian.rs @@ -1,6 +1,6 @@ use rand::{Rng, distributions::{Standard, Distribution}}; use crate::curves::models::SWModelParameters as Parameters; -use crate::{UniformRand, SemanticallyValid, FromBytesChecked}; +use crate::{UniformRand, SemanticallyValid, Error, FromBytesChecked, BitSerializationError, FromCompressedBits, ToCompressedBits}; use std::{ fmt::{Display, Formatter, Result as FmtResult}, io::{Read, Result as IoResult, Write, Error as IoError, ErrorKind}, @@ -320,6 +320,72 @@ impl FromBytesChecked for GroupAffine

{ } } +use crate::{ToBits, FromBits}; +impl ToCompressedBits for GroupAffine

+{ + #[inline] + fn compress(&self) -> Vec { + // Strictly speaking, self.x is zero already when self.infinity is true, but + // to guard against implementation mistakes we do not assume this. + let p = if self.infinity {P::BaseField::zero()} else {self.x}; + let mut res = p.write_bits(); + + // Is this the point at infinity? If so, set the most significant bit. + res.push(self.infinity); + + // Is the y-coordinate the odd one of the two associated with the + // x-coordinate? If so, set the third-most significant bit so long as this is not + // the point at infinity. + + res.push(!self.infinity && self.y.is_odd()); + + res + } +} + +impl FromCompressedBits for GroupAffine

+{ + #[inline] + fn decompress(compressed: Vec) -> Result { + let len = compressed.len() - 1; + let parity_flag_set = compressed[len]; + let infinity_flag_set = compressed[len - 1]; + + //Mask away the flag bits and try to get the x coordinate + let x = P::BaseField::read_bits(compressed[0..(len - 1)].to_vec())?; + match (infinity_flag_set, parity_flag_set, x.is_zero()) { + + //If the infinity flag is set, return the value assuming + //the x-coordinate is zero and the parity bit is not set. + (true, false, true) => Ok(Self::zero()), + + //If infinity flag is not set, then we attempt to construct + //a point from the x coordinate and the parity. + (false, _, _) => { + + //Attempt to get the y coordinate from its parity and x + match Self::get_point_from_x_and_parity(x, parity_flag_set) { + + //Check p belongs to the subgroup we expect + Some(p) => { + if p.is_in_correct_subgroup_assuming_on_curve() { + Ok(p) + } + else { + let e = BitSerializationError::NotPrimeOrder; + Err(Box::new(e)) + } + } + _ => Err(Box::new(BitSerializationError::NotOnCurve)), + } + }, + + //Other combinations are illegal + _ => Err(Box::new(BitSerializationError::InvalidFlags)), + } + } +} + impl Default for GroupAffine

{ #[inline] fn default() -> Self { diff --git a/algebra/src/curves/models/twisted_edwards_extended/mod.rs b/algebra/src/curves/models/twisted_edwards_extended/mod.rs index 9111f97a3..60f310f8d 100644 --- a/algebra/src/curves/models/twisted_edwards_extended/mod.rs +++ b/algebra/src/curves/models/twisted_edwards_extended/mod.rs @@ -1,5 +1,5 @@ use rand::{Rng, distributions::{Standard, Distribution}}; -use crate::{UniformRand, SemanticallyValid, FromBytesChecked}; +use crate::{UniformRand, SemanticallyValid, Error, FromBytesChecked, ToCompressedBits, FromCompressedBits, BitSerializationError}; use std::{ fmt::{Display, Formatter, Result as FmtResult}, io::{Read, Result as IoResult, Error as IoError, Write}, @@ -286,6 +286,49 @@ impl FromBytesChecked for GroupAffine

{ } } +use crate::{ToBits, FromBits}; +impl ToCompressedBits for GroupAffine

+{ + #[inline] + fn compress(&self) -> Vec { + + let mut res = self.x.write_bits(); + + // Is the y-coordinate the odd one of the two associated with the + // x-coordinate? + res.push(self.y.is_odd()); + + res + } +} + +impl FromCompressedBits for GroupAffine

+{ + #[inline] + fn decompress(compressed: Vec) -> Result { + let len = compressed.len() - 1; + let parity_flag_set = compressed[len]; + + //Mask away the flag bits and try to get the x coordinate + let x = P::BaseField::read_bits(compressed[0..(len - 1)].to_vec())?; + + //Attempt to get the y coordinate from its parity and x + match Self::get_point_from_x_and_parity(x, parity_flag_set) { + + //Check p belongs to the subgroup we expect + Some(p) => { + if p.is_in_correct_subgroup_assuming_on_curve() { + Ok(p) + } + else { + let e = BitSerializationError::NotPrimeOrder; + Err(Box::new(e)) + } + } + _ => Err(Box::new(BitSerializationError::NotOnCurve)), + } + } +} impl Default for GroupAffine

{ #[inline] diff --git a/algebra/src/fields/arithmetic.rs b/algebra/src/fields/arithmetic.rs index e4355f62a..6bba903f4 100644 --- a/algebra/src/fields/arithmetic.rs +++ b/algebra/src/fields/arithmetic.rs @@ -327,7 +327,6 @@ macro_rules! sqrt_impl { }}; } -// Implements AddAssign on Self by deferring to an implementation on &Self #[macro_export] macro_rules! impl_additive_ops_from_ref { ($type: ident, $params: ident) => { @@ -423,7 +422,6 @@ macro_rules! impl_additive_ops_from_ref { }; } -// Implements AddAssign on Self by deferring to an implementation on &Self #[macro_export] macro_rules! impl_multiplicative_ops_from_ref { ($type: ident, $params: ident) => { @@ -439,18 +437,6 @@ macro_rules! impl_multiplicative_ops_from_ref { } } - #[allow(unused_qualifications)] - impl MulShort for $type

{ - type Output = Self; - - #[inline] - fn mul_short(self, other: Self) -> Self { - let mut result = self; - result.mul_short_assign(&other); - result - } - } - #[allow(unused_qualifications)] impl std::ops::Div for $type

{ type Output = Self; @@ -475,18 +461,6 @@ macro_rules! impl_multiplicative_ops_from_ref { } } - #[allow(unused_qualifications)] - impl<'a, P: $params> MulShort<&'a mut Self> for $type

{ - type Output = Self; - - #[inline] - fn mul_short(self, other: &'a mut Self) -> Self { - let mut result = self; - result.mul_short_assign(&*other); - result - } - } - #[allow(unused_qualifications)] impl<'a, P: $params> std::ops::Div<&'a mut Self> for $type

{ type Output = Self; @@ -520,13 +494,6 @@ macro_rules! impl_multiplicative_ops_from_ref { } } - #[allow(unused_qualifications)] - impl MulShortAssign for $type

{ - fn mul_short_assign(&mut self, other: Self) { - self.mul_short_assign(&other) - } - } - #[allow(unused_qualifications)] impl<'a, P: $params> std::ops::DivAssign<&'a mut Self> for $type

{ fn div_assign(&mut self, other: &'a mut Self) { @@ -542,16 +509,56 @@ macro_rules! impl_multiplicative_ops_from_ref { } #[allow(unused_qualifications)] - impl<'a, P: $params> MulShortAssign<&'a mut Self> for $type

{ - fn mul_short_assign(&mut self, other: &'a mut Self) { - self.mul_short_assign(&*other) + impl std::ops::DivAssign for $type

{ + fn div_assign(&mut self, other: Self) { + self.div_assign(&other) + } + } + }; +} + +#[macro_export] +macro_rules! impl_mul_short { + ($type: ident, $params: ident) => { + #[allow(unused_qualifications)] + impl MulShort for $type

{ + type Output = Self; + + #[inline] + fn mul_short(self, other: Self) -> Self { + let mut result = self; + result.mul_short_assign(&other); + result } } #[allow(unused_qualifications)] - impl std::ops::DivAssign for $type

{ - fn div_assign(&mut self, other: Self) { - self.div_assign(&other) + impl<'a, P: $params> MulShort<&'a mut Self> for $type

{ + type Output = Self; + + #[inline] + fn mul_short(self, other: &'a mut Self) -> Self { + let mut result = self; + result.mul_short_assign(&*other); + result + } + } + + #[allow(unused_qualifications)] + impl MulShortAssign for $type

{ + + #[inline] + fn mul_short_assign(&mut self, other: Self) { + self.mul_short_assign(&other) + } + } + + #[allow(unused_qualifications)] + impl<'a, P: $params> MulShortAssign<&'a mut Self> for $type

{ + + #[inline] + fn mul_short_assign(&mut self, other: &'a mut Self) { + self.mul_short_assign(&*other) } } }; diff --git a/algebra/src/fields/macros.rs b/algebra/src/fields/macros.rs index 809740ae8..3422b6452 100644 --- a/algebra/src/fields/macros.rs +++ b/algebra/src/fields/macros.rs @@ -453,6 +453,7 @@ macro_rules! impl_Fp { impl_additive_ops_from_ref!($Fp, $FpParameters); impl_multiplicative_ops_from_ref!($Fp, $FpParameters); + impl_mul_short!($Fp, $FpParameters); impl<'a, P: $FpParameters> AddAssign<&'a Self> for $Fp

{ #[inline] diff --git a/algebra/src/fields/mod.rs b/algebra/src/fields/mod.rs index 41d41914c..5a30f780c 100644 --- a/algebra/src/fields/mod.rs +++ b/algebra/src/fields/mod.rs @@ -118,6 +118,14 @@ pub trait Field: + From + From + From + + Add + + Sub + + Mul + + Div + + AddAssign + + SubAssign + + MulAssign + + DivAssign + for<'a> Add<&'a Self, Output = Self> + for<'a> Sub<&'a Self, Output = Self> + for<'a> Mul<&'a Self, Output = Self> @@ -126,6 +134,10 @@ pub trait Field: + for<'a> SubAssign<&'a Self> + for<'a> MulAssign<&'a Self> + for<'a> DivAssign<&'a Self> + + std::iter::Sum + + for<'a> std::iter::Sum<&'a Self> + + std::iter::Product + + for<'a> std::iter::Product<&'a Self> { type BasePrimeField: PrimeField; @@ -474,7 +486,7 @@ pub fn batch_inversion(v: &mut [F]) { let mut prod = Vec::with_capacity(v.len()); let mut tmp = F::one(); for f in v.iter().filter(|f| !f.is_zero()) { - tmp.mul_assign(&f); + tmp.mul_assign(f); prod.push(tmp); } @@ -491,7 +503,7 @@ pub fn batch_inversion(v: &mut [F]) { .zip(prod.into_iter().rev().skip(1).chain(Some(F::one()))) { // tmp := tmp * g.z; g.z := tmp * s = 1/z - let newtmp = tmp * &f; + let newtmp = tmp * *f; *f = tmp * &s; tmp = newtmp; } diff --git a/algebra/src/fields/models/cubic_extension.rs b/algebra/src/fields/models/cubic_extension.rs index f828dfacc..04f269b3d 100644 --- a/algebra/src/fields/models/cubic_extension.rs +++ b/algebra/src/fields/models/cubic_extension.rs @@ -464,6 +464,9 @@ impl<'a, P: CubicExtParameters> SubAssign<&'a Self> for CubicExtField

{ } } +impl_additive_ops_from_ref!(CubicExtField, CubicExtParameters); +impl_multiplicative_ops_from_ref!(CubicExtField, CubicExtParameters); + impl<'a, P: CubicExtParameters> MulAssign<&'a Self> for CubicExtField

{ #[inline] fn mul_assign(&mut self, other: &Self) { diff --git a/algebra/src/fields/models/quadratic_extension.rs b/algebra/src/fields/models/quadratic_extension.rs index 84efa45fc..4b2ac8460 100644 --- a/algebra/src/fields/models/quadratic_extension.rs +++ b/algebra/src/fields/models/quadratic_extension.rs @@ -470,6 +470,9 @@ impl<'a, P: QuadExtParameters> SubAssign<&'a Self> for QuadExtField

{ } } +impl_additive_ops_from_ref!(QuadExtField, QuadExtParameters); +impl_multiplicative_ops_from_ref!(QuadExtField, QuadExtParameters); + impl<'a, P: QuadExtParameters> MulAssign<&'a Self> for QuadExtField

{ #[inline] fn mul_assign(&mut self, other: &Self) { diff --git a/algebra/src/lib.rs b/algebra/src/lib.rs index 160d4f685..ec047b8d0 100644 --- a/algebra/src/lib.rs +++ b/algebra/src/lib.rs @@ -42,12 +42,47 @@ pub use to_field_vec::ToConstraintField; pub type Error = Box; -/// Returns log2 +/// Returns the base-2 logarithm of `x`. +/// ``` +/// use algebra::log2; +/// +/// assert_eq!(log2(16), 4); +/// assert_eq!(log2(17), 5); +/// assert_eq!(log2(1), 0); +/// assert_eq!(log2(0), 0); +/// assert_eq!(log2(usize::MAX), (std::mem::size_of::() * 8) as u32); +/// assert_eq!(log2(1 << 15), 15); +/// assert_eq!(log2(2usize.pow(18)), 18); +/// ``` +#[inline] pub fn log2(x: usize) -> u32 { - if x <= 1 { - return 0; + if x == 0 { + 0 + } else if x.is_power_of_two() { + 1usize.leading_zeros() - x.leading_zeros() + } else { + 0usize.leading_zeros() - x.leading_zeros() } +} - let n = x.leading_zeros(); - core::mem::size_of::() as u32 * 8 - n +/// Returns the floor of the base-2 logarithm of `x`. +/// ``` +/// use algebra::log2_floor; +/// assert_eq!(log2_floor(0), 0); +/// assert_eq!(log2_floor(1), 0); +/// assert_eq!(log2_floor(2), 1); +/// assert_eq!(log2_floor(3), 1); +/// assert_eq!(log2_floor(4), 2); +/// assert_eq!(log2_floor(5), 2); +/// assert_eq!(log2_floor(6), 2); +/// assert_eq!(log2_floor(7), 2); +/// assert_eq!(log2_floor(8), 3); +/// ``` +#[inline] +pub fn log2_floor(x: usize) -> u32 { + if x == 0 { + 0 + } else { + (x as f64).log2() as u32 + } } diff --git a/primitives/src/merkle_tree/mod.rs b/primitives/src/merkle_tree/mod.rs index cd2a3f467..5e517136e 100644 --- a/primitives/src/merkle_tree/mod.rs +++ b/primitives/src/merkle_tree/mod.rs @@ -1,5 +1,6 @@ use crate::{crh::FixedLengthCRH, Error}; use algebra::bytes::ToBytes; + use std::{fmt, rc::Rc}; use serde::{Serialize, Deserialize}; @@ -259,12 +260,6 @@ impl std::error::Error for MerkleTreeError { } } -/// Returns the log2 value of the given number. -#[inline] -fn log2(number: usize) -> usize { - (number as f64).log2() as usize -} - /// Returns the height of the tree, given the size of the tree. #[inline] fn tree_height(tree_size: usize) -> usize { @@ -272,7 +267,7 @@ fn tree_height(tree_size: usize) -> usize { return 1; } - log2(tree_size) + algebra::log2_floor(tree_size) as usize } /// Returns true iff the index represents the root. diff --git a/proof-systems/src/gm17/generator.rs b/proof-systems/src/gm17/generator.rs index 60c1d0cac..690bcaff0 100644 --- a/proof-systems/src/gm17/generator.rs +++ b/proof-systems/src/gm17/generator.rs @@ -1,5 +1,7 @@ -use algebra_utils::fft::domain::get_best_evaluation_domain; use algebra_utils::msm::FixedBaseMSM; +use algebra_utils::fft::domain::{ + get_best_evaluation_domain, sample_element_outside_domain, +}; use algebra::{ UniformRand, AffineCurve, Field, PairingEngine, PrimeField, ProjectiveCurve, @@ -183,12 +185,7 @@ where .ok_or(SynthesisError::PolynomialDegreeTooLarge)?; //Sample element outside domain - let t = loop { - let random_t = E::Fr::rand(rng); - if !domain.evaluate_vanishing_polynomial(random_t).is_zero() { - break (random_t) - } - }; + let t = sample_element_outside_domain(&domain, rng); end_timer!(domain_time); /////////////////////////////////////////////////////////////////////////// diff --git a/proof-systems/src/groth16/generator.rs b/proof-systems/src/groth16/generator.rs index ef640f151..507049796 100644 --- a/proof-systems/src/groth16/generator.rs +++ b/proof-systems/src/groth16/generator.rs @@ -1,6 +1,8 @@ use algebra::{groups::Group, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand}; use algebra_utils::msm::FixedBaseMSM; -use algebra_utils::fft::domain::get_best_evaluation_domain; +use algebra_utils::fft::domain::{ + get_best_evaluation_domain, sample_element_outside_domain +}; use r1cs_core::{ ConstraintSynthesizer, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable, @@ -167,12 +169,7 @@ pub fn generate_parameters( .ok_or(SynthesisError::PolynomialDegreeTooLarge)?; //Sample element outside domain - let t = loop { - let random_t = E::Fr::rand(rng); - if !domain.evaluate_vanishing_polynomial(random_t).is_zero() { - break (random_t) - } - }; + let t = sample_element_outside_domain(&domain, rng); end_timer!(domain_time); /////////////////////////////////////////////////////////////////////////// diff --git a/proof-systems/src/lib.rs b/proof-systems/src/lib.rs index 6b9823e54..3fe46abe2 100644 --- a/proof-systems/src/lib.rs +++ b/proof-systems/src/lib.rs @@ -14,4 +14,4 @@ extern crate bench_utils; pub mod groth16; #[cfg(feature = "gm17")] -pub mod gm17; +pub mod gm17; \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/merkle_tree/field_based_mht/mod.rs b/r1cs/gadgets/crypto/src/merkle_tree/field_based_mht/mod.rs index 9426b3107..e3fb9d3ae 100644 --- a/r1cs/gadgets/crypto/src/merkle_tree/field_based_mht/mod.rs +++ b/r1cs/gadgets/crypto/src/merkle_tree/field_based_mht/mod.rs @@ -15,6 +15,11 @@ use crate::FieldBasedMerkleTreePathGadget; use std::borrow::Borrow; use std::marker::PhantomData; +#[derive(Derivative)] +#[derivative( + PartialEq(bound = "P: FieldBasedMerkleTreeParameters"), + Eq(bound = "P: FieldBasedMerkleTreeParameters") +)] pub struct FieldBasedBinaryMerkleTreePathGadget where P: FieldBasedMerkleTreeParameters, @@ -275,6 +280,88 @@ for FieldBasedBinaryMerkleTreePathGadget } } +impl ConstantGadget, ConstraintF> +for FieldBasedBinaryMerkleTreePathGadget + where + P: FieldBasedMerkleTreeParameters, + HGadget: FieldBasedHashGadget, + ConstraintF: Field, +{ + fn from_value>(mut cs: CS, value: &FieldBasedBinaryMHTPath

) -> Self { + let mut path = Vec::new(); + for (i, (sibling, d)) in value.get_raw_path().iter().enumerate() { + let sibling_hash = HGadget::DataGadget::from_value( + cs.ns(|| format!("hardcode sibling {}", i)), + sibling + ); + let direction = Boolean::Constant(*d); + path.push((sibling_hash, direction)); + } + Self { path } + } + + fn get_constant(&self) -> FieldBasedBinaryMHTPath

{ + let mut path = Vec::new(); + for (sibling_g, d_g) in self.path.iter() { + let sibling = sibling_g.get_constant(); + let d = d_g.get_value().unwrap(); + path.push((sibling, d)) + } + FieldBasedBinaryMHTPath::

::new(path) + } +} + +impl EqGadget +for FieldBasedBinaryMerkleTreePathGadget + where + P: FieldBasedMerkleTreeParameters, + HGadget: FieldBasedHashGadget, + ConstraintF: Field, +{ + fn is_eq>(&self, mut cs: CS, other: &Self) -> Result { + let mut v = Vec::new(); + let len = self.path.len(); + assert_eq!(self.path.len(), other.path.len()); + for i in 0..len { + let b1_i = &self.path[i].0.is_eq(cs.ns(|| format!("b1_{}", i)), &other.path[i].0)?; + let b2_i = &self.path[i].1.is_eq(cs.ns(|| format!("b2_{}", i)), &other.path[i].1)?; + let b_i = Boolean::and(cs.ns(|| format!("b1_{} && b2_{}", i, i)), &b1_i, &b2_i)?; + v.push(b_i); + } + Boolean::kary_and(cs.ns(|| "is eq final"), v.as_slice()) + } + + fn conditional_enforce_equal>( + &self, + mut cs: CS, + other: &Self, + should_enforce: &Boolean + ) -> Result<(), SynthesisError> { + let len = self.path.len(); + assert_eq!(self.path.len(), other.path.len()); + for i in 0..len { + &self.path[i].0.conditional_enforce_equal(cs.ns(|| format!("conditional_eq_1_{}", i)), &other.path[i].0, should_enforce)?; + &self.path[i].1.conditional_enforce_equal(cs.ns(|| format!("conditional_eq_2_{}", i)), &other.path[i].1, should_enforce)?; + } + Ok(()) + } + + fn conditional_enforce_not_equal>( + &self, + mut cs: CS, + other: &Self, + should_enforce: &Boolean + ) -> Result<(), SynthesisError> { + let len = self.path.len(); + assert_eq!(self.path.len(), other.path.len()); + for i in 0..len { + &self.path[i].0.conditional_enforce_not_equal(cs.ns(|| format!("conditional_neq_1_{}", i)), &other.path[i].0, should_enforce)?; + &self.path[i].1.conditional_enforce_not_equal(cs.ns(|| format!("conditional_neq_2_{}", i)), &other.path[i].1, should_enforce)?; + } + Ok(()) + } +} + #[cfg(test)] mod test { use primitives::{ diff --git a/r1cs/gadgets/crypto/src/merkle_tree/mod.rs b/r1cs/gadgets/crypto/src/merkle_tree/mod.rs index 81e007e51..a2d182173 100644 --- a/r1cs/gadgets/crypto/src/merkle_tree/mod.rs +++ b/r1cs/gadgets/crypto/src/merkle_tree/mod.rs @@ -15,7 +15,7 @@ pub trait FieldBasedMerkleTreePathGadget< H: FieldBasedHash, HGadget: FieldBasedHashGadget, ConstraintF: PrimeField, ->: AllocGadget +>: AllocGadget + ConstantGadget + EqGadget where { /// Return the length of the path diff --git a/r1cs/gadgets/crypto/src/signature/mod.rs b/r1cs/gadgets/crypto/src/signature/mod.rs index 9e1eec36f..cbf6321a0 100644 --- a/r1cs/gadgets/crypto/src/signature/mod.rs +++ b/r1cs/gadgets/crypto/src/signature/mod.rs @@ -1,9 +1,10 @@ -use algebra::Field; +use algebra::{Field, PrimeField}; use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_std::prelude::*; use primitives::signature::{ SignatureScheme, FieldBasedSignatureScheme, }; +use r1cs_std::to_field_gadget_vec::ToConstraintFieldGadget; pub mod schnorr; @@ -24,11 +25,17 @@ pub trait SigRandomizePkGadget { } -pub trait FieldBasedSigGadget { +pub trait FieldBasedSigGadget { type DataGadget: FieldGadget; - type SignatureGadget: AllocGadget; - type PublicKeyGadget: AllocGadget; + type SignatureGadget: AllocGadget + + ConstantGadget + + EqGadget + + ToConstraintFieldGadget; + type PublicKeyGadget: AllocGadget + + ConstantGadget + + EqGadget + + ToConstraintFieldGadget; /// Enforce `signature` verification with `public_key` on `message`, returning a Boolean /// enforced to be `true` if signature verification is successful, and `false` otherwise. diff --git a/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs b/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs index 483cfa59b..deb7487aa 100644 --- a/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs +++ b/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs @@ -29,10 +29,10 @@ use r1cs_std::alloc::ConstantGadget; #[derive(Derivative)] #[derivative( -Debug(bound = "ConstraintF: PrimeField, G: Group"), -Clone(bound = "ConstraintF: PrimeField, G: Group"), -PartialEq(bound = "ConstraintF: PrimeField, G: Group"), -Eq(bound = "ConstraintF: PrimeField, G: Group") + Debug(bound = "ConstraintF: PrimeField, G: Group"), + Clone(bound = "ConstraintF: PrimeField, G: Group"), + PartialEq(bound = "ConstraintF: PrimeField, G: Group"), + Eq(bound = "ConstraintF: PrimeField, G: Group") )] pub struct FieldBasedSchnorrSigGadget< ConstraintF: PrimeField, @@ -94,7 +94,80 @@ for FieldBasedSchnorrSigGadget } } -#[derive(Clone)] +impl ConstantGadget, ConstraintF> +for FieldBasedSchnorrSigGadget + where + ConstraintF: PrimeField, + G: Group, +{ + fn from_value>( + mut cs: CS, + value: &FieldBasedSchnorrSignature + ) -> Self { + let e = FpGadget::::from_value(cs.ns(|| "hardcode e"), &value.e); + let s = FpGadget::::from_value(cs.ns(|| "hardcode s"), &value.s); + Self{ e, s, _field: PhantomData, _group: PhantomData } + } + + fn get_constant(&self) -> FieldBasedSchnorrSignature + { + let e = self.e.value.unwrap(); + let s = self.s.value.unwrap(); + FieldBasedSchnorrSignature::::new(e, s) + } +} + +impl EqGadget for FieldBasedSchnorrSigGadget + where + ConstraintF: PrimeField, + G: Group, +{ + fn is_eq>(&self, mut cs: CS, other: &Self) -> Result { + let b1 = self.e.is_eq(cs.ns(|| "b1"), &other.e)?; + let b2 = self.s.is_eq(cs.ns(|| "b2"), &other.s)?; + Boolean::and(cs.ns(|| "b1 && b2"), &b1, &b2) + } + + fn conditional_enforce_equal>( + &self, + mut cs: CS, + other: &Self, + should_enforce: &Boolean + ) -> Result<(), SynthesisError> { + self.e.conditional_enforce_equal(cs.ns(|| "self.e =? other.e"), &other.e, should_enforce)?; + self.s.conditional_enforce_equal(cs.ns(|| "self.s =? other.s"), &other.s, should_enforce)?; + Ok(()) + } + + fn conditional_enforce_not_equal>( + &self, + mut cs: CS, + other: &Self, + should_enforce: &Boolean + ) -> Result<(), SynthesisError> { + self.e.conditional_enforce_not_equal(cs.ns(|| "self.e !=? other.e"), &other.e, should_enforce)?; + self.s.conditional_enforce_not_equal(cs.ns(|| "self.s !=? other.s"), &other.s, should_enforce)?; + Ok(()) + } +} + +impl ToConstraintFieldGadget for FieldBasedSchnorrSigGadget + where + ConstraintF: PrimeField, + G: Group, +{ + type FieldGadget = FpGadget; + + fn to_field_gadget_elements>( + &self, + _cs: CS + ) -> Result, SynthesisError> + { + Ok(vec![self.e.clone(), self.s.clone()]) + } +} + +#[derive(Clone, Eq, PartialEq)] pub struct FieldBasedSchnorrPkGadget< ConstraintF: PrimeField, G: Group, @@ -181,6 +254,63 @@ for FieldBasedSchnorrPkGadget } } +impl EqGadget for FieldBasedSchnorrPkGadget + where + ConstraintF: PrimeField, + G: Group, + GG: GroupGadget, +{ + fn is_eq>( + &self, + cs: CS, + other: &Self + ) -> Result { + self.pk.is_eq(cs, &other.pk) + } + + fn conditional_enforce_equal>( + &self, + cs: CS, + other: &Self, + should_enforce: &Boolean, + ) -> Result<(), SynthesisError> { + self.pk.conditional_enforce_equal( + cs, + &other.pk, + should_enforce + ) + } + + fn conditional_enforce_not_equal>( + &self, + cs: CS, + other: &Self, + should_enforce: &Boolean, + ) -> Result<(), SynthesisError> { + self.pk.conditional_enforce_not_equal( + cs, + &other.pk, + should_enforce + ) + } +} + +impl ToConstraintFieldGadget for FieldBasedSchnorrPkGadget + where + ConstraintF: PrimeField, + G: Group, + GG: GroupGadget + ToConstraintFieldGadget>, +{ + type FieldGadget = FpGadget; + + fn to_field_gadget_elements>( + &self, + cs: CS + ) -> Result, SynthesisError> { + self.pk.to_field_gadget_elements(cs) + } +} + pub struct FieldBasedSchnorrSigVerificationGadget< ConstraintF: PrimeField, G: Group, diff --git a/r1cs/gadgets/std/src/lib.rs b/r1cs/gadgets/std/src/lib.rs index acfb2efc9..5a5b8a464 100644 --- a/r1cs/gadgets/std/src/lib.rs +++ b/r1cs/gadgets/std/src/lib.rs @@ -88,5 +88,5 @@ impl Assignment for Option { } pub trait FromGadget: Sized { - fn from>(other: T) -> Result; + fn from>(other: T, cs: CS) -> Result; } diff --git a/r1cs/gadgets/std/src/test_constraint_system.rs b/r1cs/gadgets/std/src/test_constraint_system.rs index 8096c4b1b..3d61be76f 100644 --- a/r1cs/gadgets/std/src/test_constraint_system.rs +++ b/r1cs/gadgets/std/src/test_constraint_system.rs @@ -38,8 +38,8 @@ impl TestConstraintSystem { Index::Aux(index) => aux[index].0, }; - tmp.mul_assign(&coeff); - acc.add_assign(&tmp); + tmp.mul_assign(coeff); + acc.add_assign(tmp); } acc From 30bc43705588b38e39ea5f46c64e483a30533cb3 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 28 Dec 2020 23:38:57 +0200 Subject: [PATCH 22/63] log2_floor call bugfix --- algebra-utils/src/fft/multicore.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algebra-utils/src/fft/multicore.rs b/algebra-utils/src/fft/multicore.rs index b1493825b..a51164e85 100644 --- a/algebra-utils/src/fft/multicore.rs +++ b/algebra-utils/src/fft/multicore.rs @@ -15,7 +15,7 @@ impl Worker { } pub(crate) fn log_num_cpus(&self) -> u32 { - crate::log2_floor(self.cpus) + algebra::log2_floor(self.cpus) } pub(crate) fn scope<'a, F, R>(&self, elements: usize, f: F) -> R From 8c58de7f45dbe99ab9723331d0dde18236846df9 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 00:03:19 +0200 Subject: [PATCH 23/63] Dependency usage bugfix --- algebra/src/fields/mod.rs | 1 - .../groth16/benches/bn382_gro16_test_circuits.rs | 13 +++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/algebra/src/fields/mod.rs b/algebra/src/fields/mod.rs index 5a30f780c..56bae7340 100644 --- a/algebra/src/fields/mod.rs +++ b/algebra/src/fields/mod.rs @@ -356,7 +356,6 @@ impl FromBits for F { #[inline] fn read_bits(bits: Vec) -> Result { let modulus_bits = ::Params::MODULUS_BITS as usize; - println!("Bits len: {}", bits.len()); //NOTE: We allow bits having enough leading bits to zero s.t. the length will be <= F::MODULUS_BITS let leading_zeros = leading_zeros(bits.as_slice()) as usize; diff --git a/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs b/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs index 1676d7a05..d5c19c555 100644 --- a/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs +++ b/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs @@ -10,6 +10,7 @@ use criterion::{BenchmarkId, BatchSize}; use criterion::Criterion; use r1cs_std::Assignment; use r1cs_std::fields::fp::FpGadget; +use r1cs_std::eq::EqGadget; use r1cs_std::fields::FieldGadget; use r1cs_std::alloc::AllocGadget; @@ -53,10 +54,10 @@ impl ConstraintSynthesizer for TestCircuit1 { || self.b.ok_or(SynthesisError::AssignmentMissing) )?; - // let zero = FpGadget::::zero(cs.ns(|| "alloc zero"))?; + let zero = FpGadget::::zero(cs.ns(|| "alloc zero"))?; - // a_k_minus_1.enforce_not_equal(cs.ns(|| "a_0 != 0"), &zero)?; - // b_k_minus_1.enforce_not_equal(cs.ns(|| "b_0 != 0"), &zero)?; + a_k_minus_1.enforce_not_equal(cs.ns(|| "a_0 != 0"), &zero)?; + b_k_minus_1.enforce_not_equal(cs.ns(|| "b_0 != 0"), &zero)?; for k in 0..(self.num_constraints - 5)/2 { @@ -106,10 +107,10 @@ impl ConstraintSynthesizer for TestCircuit2 { || self.b.ok_or(SynthesisError::AssignmentMissing) )?; - // let zero = FpGadget::::zero(cs.ns(|| "alloc zero"))?; + let zero = FpGadget::::zero(cs.ns(|| "alloc zero"))?; - // a_k_minus_1.enforce_not_equal(cs.ns(|| "a_0 != 0"), &zero)?; - // b_k_minus_1.enforce_not_equal(cs.ns(|| "b_0 != 0"), &zero)?; + a_k_minus_1.enforce_not_equal(cs.ns(|| "a_0 != 0"), &zero)?; + b_k_minus_1.enforce_not_equal(cs.ns(|| "b_0 != 0"), &zero)?; for k in 0..(self.num_constraints - 5)/2 { From d04c4242f7507c271403ce304eec1a72ab60013e Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 00:34:57 +0200 Subject: [PATCH 24/63] Polycommit removed from ginger-lib --- algebra-utils/src/lib.rs | 5 - algebra-utils/src/polycommit/mod.rs | 136 ---------------------------- 2 files changed, 141 deletions(-) delete mode 100644 algebra-utils/src/polycommit/mod.rs diff --git a/algebra-utils/src/lib.rs b/algebra-utils/src/lib.rs index ef135500a..99f06d45d 100644 --- a/algebra-utils/src/lib.rs +++ b/algebra-utils/src/lib.rs @@ -18,9 +18,4 @@ pub mod fft; #[cfg(feature = "fft")] pub use self::fft::*; -#[cfg(feature = "parallel")] -pub mod polycommit; -#[cfg(feature = "parallel")] -pub use self::polycommit::*; - pub type Error = Box; \ No newline at end of file diff --git a/algebra-utils/src/polycommit/mod.rs b/algebra-utils/src/polycommit/mod.rs deleted file mode 100644 index 9c4fd57d6..000000000 --- a/algebra-utils/src/polycommit/mod.rs +++ /dev/null @@ -1,136 +0,0 @@ -use algebra::AffineCurve; - -use rayon::prelude::*; - -#[cfg(feature = "gpu")] -use algebra_kernels::polycommit::{get_kernels, get_gpu_min_length}; - -pub fn polycommit_round_reduce< - G: AffineCurve ->( - round_challenge: G::ScalarField, - round_challenge_inv: G::ScalarField, - c_l: &mut [G::ScalarField], - c_r: &[G::ScalarField], - z_l: &mut [G::ScalarField], - z_r: &[G::ScalarField], - k_l: &mut [G::Projective], - k_r: &[G], -) { - #[cfg(feature = "gpu")] - if get_gpu_min_length() <= k_l.len() { - match get_kernels() { - Ok(kernels) => { - match kernels[0].polycommit_round_reduce( - round_challenge, - round_challenge_inv, - c_l, - c_r, - z_l, - z_r, - k_l, - k_r - ) { - Ok(_) => {}, - Err(error) => { panic!("{}", error); } - } - }, - Err(error) => { - panic!("{}", error); - } - } - return; - } - - c_l.par_iter_mut() - .zip(c_r) - .for_each(|(c_l, c_r)| *c_l += &(round_challenge_inv * &c_r)); - - z_l.par_iter_mut() - .zip(z_r) - .for_each(|(z_l, z_r)| *z_l += &(round_challenge * &z_r)); - - k_l.par_iter_mut() - .zip(k_r) - .for_each(|(k_l, k_r)| *k_l += &(k_r.mul(round_challenge))); -} - -#[cfg(test)] -mod tests { - - use super::*; - use algebra::curves::bls12_381::G1Projective; - use algebra::fields::bls12_381::Fr; - use algebra::{Field, UniformRand, ProjectiveCurve}; - - #[test] - fn test_polycommit_round_reduce() { - - use rayon::prelude::*; - - let mut rng = &mut rand::thread_rng(); - - let round_challenge = Fr::rand(&mut rng); - let round_challenge_inv = round_challenge.inverse().unwrap(); - - let samples = 1 << 10; - - let mut coeffs_l = (0..samples) - .map(|_| Fr::rand(&mut rng)) - .collect::>(); - - let coeffs_r = (0..samples) - .map(|_| Fr::rand(&mut rng)) - .collect::>(); - - let mut z_l = (0..samples) - .map(|_| Fr::rand(&mut rng)) - .collect::>(); - - let z_r= (0..samples) - .map(|_| Fr::rand(&mut rng)) - .collect::>(); - - let mut key_proj_l= (0..samples) - .map(|_| G1Projective::rand(&mut rng)) - .collect::>(); - - let key_r= (0..samples) - .map(|_| G1Projective::rand(&mut rng).into_affine()) - .collect::>(); - - let mut gpu_coeffs_l = coeffs_l.clone(); - let gpu_coeffs_r = coeffs_r.clone(); - let mut gpu_z_l = z_l.clone(); - let gpu_z_r = z_r.clone(); - let mut gpu_key_proj_l = key_proj_l.clone(); - let gpu_key_r = key_r.clone(); - - coeffs_l.par_iter_mut() - .zip(coeffs_r) - .for_each(|(c_l, c_r)| *c_l += &(round_challenge_inv * &c_r)); - - z_l.par_iter_mut() - .zip(z_r) - .for_each(|(z_l, z_r)| *z_l += &(round_challenge * &z_r)); - - key_proj_l.par_iter_mut() - .zip(key_r) - .for_each(|(k_l, k_r)| *k_l += &(k_r.mul(round_challenge))); - - polycommit_round_reduce( - round_challenge, - round_challenge_inv, - &mut gpu_coeffs_l, - &gpu_coeffs_r, - &mut gpu_z_l, - &gpu_z_r, - &mut gpu_key_proj_l, - &gpu_key_r - ); - - assert_eq!(coeffs_l, gpu_coeffs_l); - assert_eq!(z_l, gpu_z_l); - assert_eq!(key_proj_l, gpu_key_proj_l); - } -} \ No newline at end of file From dc5dd2a58f37848d0232271d2b3fca3571a86c28 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 00:45:57 +0200 Subject: [PATCH 25/63] Reduce groth16 bench to 2^22 max --- .../src/groth16/benches/bn382_gro16_test_circuits.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs b/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs index d5c19c555..b7bec4d04 100644 --- a/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs +++ b/proof-systems/src/groth16/benches/bn382_gro16_test_circuits.rs @@ -150,7 +150,7 @@ fn bench_prover_circuit1(c: &mut Criterion){ let mut group = c.benchmark_group("gro16-bn382-test circuit 1-variable constraints"); - let num_constraints = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + let num_constraints = (14..=22).map(|i| 2usize.pow(i)).collect::>(); for &num_constraints in num_constraints.iter() { @@ -198,7 +198,7 @@ fn bench_prover_circuit2(c: &mut Criterion){ let mut group = c.benchmark_group("gro16-bn382-test circuit 2-variable constraints"); - let num_constraints = (14..=23).map(|i| 2usize.pow(i)).collect::>(); + let num_constraints = (14..=22).map(|i| 2usize.pow(i)).collect::>(); for &num_constraints in num_constraints.iter() { From 44826d50624d63be804aa829385c395bf8e301ee Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 00:58:36 +0200 Subject: [PATCH 26/63] MSM switched to affine --- algebra-utils/src/msm/variable_base.rs | 4 ++-- proof-systems/src/groth16/prover.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 843628512..04806c3fb 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -224,7 +224,7 @@ impl VariableBaseMSM { if cpu_n > 0 { threads.push(s.spawn( move |_| -> Result { - let acc = Self::msm_inner(cpu_bases, cpu_scalars); + let acc = Self::multi_scalar_mul_affine(cpu_bases, cpu_scalars); Ok(acc) } )) @@ -251,7 +251,7 @@ impl VariableBaseMSM { ) -> G::Projective { #[cfg(not(feature = "gpu"))] - return Self::msm_inner(bases, scalars); + return Self::multi_scalar_mul_affine(bases, scalars); #[cfg(feature = "gpu")] return Self::msm_inner_gpu(bases, scalars); diff --git a/proof-systems/src/groth16/prover.rs b/proof-systems/src/groth16/prover.rs index 0654f770a..61f25409a 100644 --- a/proof-systems/src/groth16/prover.rs +++ b/proof-systems/src/groth16/prover.rs @@ -212,10 +212,10 @@ where let c_acc_time = start_timer!(|| "Compute C"); let h_query = params.get_h_query_full()?; - let h_acc = VariableBaseMSM::multi_scalar_mul_affine(&h_query, &h_assignment); + let h_acc = VariableBaseMSM::multi_scalar_mul(&h_query, &h_assignment); let l_aux_source = params.get_l_query_full()?; - let l_aux_acc = VariableBaseMSM::multi_scalar_mul_affine(l_aux_source, &aux_assignment); + let l_aux_acc = VariableBaseMSM::multi_scalar_mul(l_aux_source, &aux_assignment); let s_g_a = g_a.mul(&s); let r_g1_b = g1_b.mul(&r); @@ -245,7 +245,7 @@ fn calculate_coeff( assignment: &[::BigInt], ) -> G::Projective { let el = query[0]; - let acc = VariableBaseMSM::multi_scalar_mul_affine(&query[1..], assignment); + let acc = VariableBaseMSM::multi_scalar_mul(&query[1..], assignment); let mut res = initial; res.add_assign_mixed(&el); From 8d33e682f81a4be09119e06443667778b3aeb647 Mon Sep 17 00:00:00 2001 From: Maksym Vereschak Date: Mon, 28 Dec 2020 23:11:59 +0000 Subject: [PATCH 27/63] Call parameter bugfix --- algebra-utils/benches/fft/fft_bn382.rs | 2 +- algebra-utils/benches/fft/fft_tweedle.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/algebra-utils/benches/fft/fft_bn382.rs b/algebra-utils/benches/fft/fft_bn382.rs index 6e49b0f34..c11f11aed 100644 --- a/algebra-utils/benches/fft/fft_bn382.rs +++ b/algebra-utils/benches/fft/fft_bn382.rs @@ -307,7 +307,7 @@ fn bench_dense_poly_div_by_vanishing_poly> ); let _ans1 = p.divide_by_vanishing_poly( - domain.clone(), + &domain.clone(), ); add_to_trace!( diff --git a/algebra-utils/benches/fft/fft_tweedle.rs b/algebra-utils/benches/fft/fft_tweedle.rs index 3039e9176..78eb7a044 100644 --- a/algebra-utils/benches/fft/fft_tweedle.rs +++ b/algebra-utils/benches/fft/fft_tweedle.rs @@ -306,7 +306,7 @@ fn bench_dense_poly_div_by_vanishing_poly> ); let _ans1 = p.divide_by_vanishing_poly( - domain.clone(), + &domain.clone(), ); add_to_trace!( From 2b31a1ffbf3c0cd81736b9619d9b43b6a521daef Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 01:31:04 +0200 Subject: [PATCH 28/63] Curves features updated --- algebra-utils/Cargo.toml | 12 ++++++++++++ proof-systems/Cargo.toml | 1 + 2 files changed, 13 insertions(+) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 859196ec4..662d2a231 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -47,6 +47,18 @@ fft = [] gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] llvm_asm = [ "algebra/llvm_asm" ] +bls12_377 = [ "algebra-kernels/bls12_377", "algebra/bls12_377" ] +bls12_381 = [ "algebra-kernels/bls12_381", "algebra/bls12_381" ] +edwards_bls12 = [ "algebra-kernels/edwards_bls12", "algebra/edwards_bls12" ] +edwards_sw6 = [ "algebra-kernels/edwards_sw6", "algebra/edwards_sw6" ] +jubjub = [ "algebra-kernels/jubjub", "algebra/jubjub" ] +sw6 = [ "algebra-kernels/sw6", "algebra/sw6" ] +mnt4_753 = [ "algebra-kernels/mnt4_753", "algebra/mnt4_753" ] +mnt6_298 = [ "algebra-kernels/mnt6_298", "algebra/mnt6_298" ] +mnt6_753 = [ "algebra-kernels/mnt6_753", "algebra/mnt6_753" ] +bn_382 = [ "algebra-kernels/bn_382", "algebra/bls12_377" ] +tweedle = [ "algebra-kernels/tweedle", "algebra/tweedle" ] + [build-dependencies] rustc_version = "0.2" diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index 314ededb8..0cfd4777d 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -38,6 +38,7 @@ criterion = "0.3" rand_xorshift = { version = "0.2" } algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra-utils = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } r1cs-crypto = { path = "../r1cs/gadgets/crypto", features = ["nizk"] } r1cs-std = { path = "../r1cs/gadgets/std" } From f87de26c5c54e828aef1a6b551e50acfc4ebfc08 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 01:33:03 +0200 Subject: [PATCH 29/63] algebra utils path bugfix --- proof-systems/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index 0cfd4777d..828641286 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -38,7 +38,7 @@ criterion = "0.3" rand_xorshift = { version = "0.2" } algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } -algebra-utils = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra-utils = { git = "../algebra-utils", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } r1cs-crypto = { path = "../r1cs/gadgets/crypto", features = ["nizk"] } r1cs-std = { path = "../r1cs/gadgets/std" } From 04e59f08a7f8a7ac768ca196f09ea04abb1a8f1e Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 29 Dec 2020 01:33:32 +0200 Subject: [PATCH 30/63] algebra utils path bugfix --- proof-systems/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index 828641286..bb44ff3c9 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -38,7 +38,7 @@ criterion = "0.3" rand_xorshift = { version = "0.2" } algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } -algebra-utils = { git = "../algebra-utils", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } r1cs-crypto = { path = "../r1cs/gadgets/crypto", features = ["nizk"] } r1cs-std = { path = "../r1cs/gadgets/std" } From df06696ea497180306d3e4259f0457320f65562c Mon Sep 17 00:00:00 2001 From: Marcelo Kaihara Date: Wed, 30 Dec 2020 16:57:31 +0100 Subject: [PATCH 31/63] Implementation of Poseidon Hash for Tweedle --- primitives/Cargo.toml | 5 +- .../benches/crypto_primitives/poseidon_crh.rs | 36 +- primitives/src/crh/poseidon/mod.rs | 32 ++ .../src/crh/poseidon/parameters/bn382.rs | 4 +- primitives/src/crh/poseidon/parameters/mod.rs | 7 +- .../src/crh/poseidon/parameters/tweedle.rs | 487 ++++++++++++++++++ 6 files changed, 565 insertions(+), 6 deletions(-) create mode 100644 primitives/src/crh/poseidon/parameters/tweedle.rs diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 4e560f852..04f373425 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -49,10 +49,11 @@ vrf = [] mnt4_753 = ["algebra/mnt4_753"] mnt6_753 = ["algebra/mnt6_753"] bn_382 = ["algebra/bn_382"] +tweedle = ["algebra/tweedle"] [dev-dependencies] algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } -primitives = { path = "../primitives", features = ["mnt4_753", "mnt6_753", "bn_382"] } +primitives = { path = "../primitives", features = ["mnt4_753", "mnt6_753", "bn_382", "tweedle"] } criterion = "0.3" rand_xorshift = { version = "0.2" } @@ -93,7 +94,7 @@ required-features = ["vrf", "mnt4_753", "mnt6_753"] name = "poseidon_crh" path = "benches/crypto_primitives/poseidon_crh.rs" harness = false -required-features = ["bn_382", "mnt4_753", "mnt6_753"] +required-features = ["bn_382", "mnt4_753", "mnt6_753", "tweedle"] [[bench]] name = "poseidon_mht" diff --git a/primitives/benches/crypto_primitives/poseidon_crh.rs b/primitives/benches/crypto_primitives/poseidon_crh.rs index 62bb54b1c..c28909782 100644 --- a/primitives/benches/crypto_primitives/poseidon_crh.rs +++ b/primitives/benches/crypto_primitives/poseidon_crh.rs @@ -5,6 +5,8 @@ use algebra::{ mnt6753::Fr as MNT6753Fr, bn_382::Fr as BN382Fr, bn_382::Fq as BN382Fq, + tweedle::Fr as tweedleFr, + tweedle::Fq as tweedleFq } }; @@ -76,13 +78,45 @@ fn poseidon_crh_eval_bn382fq(c: &mut Criterion) { }); } +fn poseidon_crh_eval_tweedlefr(c: &mut Criterion) { + + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + let mut h = TweedleFrPoseidonHash::init(None); + + c.bench_function("Poseidon CRH Eval for tweedleFr", move |b| { + b.iter(|| { + for _ in 0..2000 { + h.update(tweedleFr::rand(&mut rng)); + } + h.finalize(); + }) + }); +} + +fn poseidon_crh_eval_tweedlefq(c: &mut Criterion) { + + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + let mut h = TweedleFqPoseidonHash::init(None); + + c.bench_function("Poseidon CRH Eval for tweedleFq", move |b| { + b.iter(|| { + for _ in 0..2000 { + h.update(tweedleFq::rand(&mut rng)); + } + h.finalize(); + }) + }); +} + + criterion_group! { name = crh_poseidon_eval; config = Criterion::default().sample_size(20); targets = poseidon_crh_eval_mnt4, poseidon_crh_eval_mnt6, poseidon_crh_eval_bn382fq, poseidon_crh_eval_bn382fr, + poseidon_crh_eval_tweedlefq, poseidon_crh_eval_tweedlefr, } criterion_main! ( crh_poseidon_eval -); \ No newline at end of file +); diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 0834b1986..f3e4c0f0b 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -347,4 +347,36 @@ mod test { assert_eq!(output, expected_output, "Outputs do not match for BN382Fq"); } + use algebra::{ + fields::tweedle::{ + fr::Fr as tweedleFr, fq::Fq as tweedleFq, + }, + biginteger::BigInteger256, + }; + use crate::crh::parameters::tweedle::*; + + #[test] + fn test_poseidon_hash_tweedle_fr() { + let expected_output = tweedleFr::new(BigInteger256([10853721058648678319, 16685221779982166148, 7657542961996224896, 317411048550701368])); + + let mut digest = TweedleFrPoseidonHash::init(None); + digest.update(tweedleFr::from_str("1").unwrap()); + digest.update(tweedleFr::from_str("2").unwrap()); + let output = digest.finalize(); + + assert_eq!(output, expected_output, "Outputs do not match for tweedleFr"); + } + + #[test] + fn test_poseidon_hash_tweedle_fq() { + let expected_output = tweedleFq::new(BigInteger256([9400878458790897114, 15068972336691613232, 13673927707991766433, 1032370839092625161])); + + let mut digest = TweedleFqPoseidonHash::init(None); + digest.update(tweedleFq::from_str("1").unwrap()); + digest.update(tweedleFq::from_str("2").unwrap()); + let output = digest.finalize(); + + assert_eq!(output, expected_output, "Outputs do not match for tweedleFq"); + } + } \ No newline at end of file diff --git a/primitives/src/crh/poseidon/parameters/bn382.rs b/primitives/src/crh/poseidon/parameters/bn382.rs index e1936e39d..11391c18d 100644 --- a/primitives/src/crh/poseidon/parameters/bn382.rs +++ b/primitives/src/crh/poseidon/parameters/bn382.rs @@ -37,7 +37,7 @@ impl PoseidonParameters for BN382FqPoseidonParameters { // Array of round constants const ROUND_CST: &'static[BN382Fq] = &[ - // Constants converted to Montgomery representation. Montgomery constant = 2^768 + // Constants converted to Montgomery representation. Montgomery constant = 2^384 // For rounds 4 + 53 + 4 = 61 field_new!(BN382Fq,BigInteger384([1142645960830323570, 13103856874656979564, 2413523699113461786, 6879845599697826609, 5058580133776391234, 1554316228962593243])), @@ -276,7 +276,7 @@ impl PoseidonParameters for BN382FrPoseidonParameters { // Array of round constants const ROUND_CST: &'static [BN382Fr] = &[ - // Constants converted to Montgomery representation. Montgomery constant = 2^768 + // Constants converted to Montgomery representation. Montgomery constant = 2^384 // For rounds 4 + 53 + 4 = 61 field_new!(BN382Fr,BigInteger384([8194766694145669507, 7188863510214511890, 13912473340830233741, 8410018237892050446, 755366085174236854, 2391227650143111718])), diff --git a/primitives/src/crh/poseidon/parameters/mod.rs b/primitives/src/crh/poseidon/parameters/mod.rs index 790d33346..e530329e7 100644 --- a/primitives/src/crh/poseidon/parameters/mod.rs +++ b/primitives/src/crh/poseidon/parameters/mod.rs @@ -11,4 +11,9 @@ pub use self::mnt6753::*; #[cfg(feature = "bn_382")] pub mod bn382; #[cfg(feature = "bn_382")] -pub use self::bn382::*; \ No newline at end of file +pub use self::bn382::*; + +#[cfg(feature = "tweedle")] +pub mod tweedle; +#[cfg(feature = "tweedle")] +pub use self::tweedle::*; diff --git a/primitives/src/crh/poseidon/parameters/tweedle.rs b/primitives/src/crh/poseidon/parameters/tweedle.rs new file mode 100644 index 000000000..25ae81901 --- /dev/null +++ b/primitives/src/crh/poseidon/parameters/tweedle.rs @@ -0,0 +1,487 @@ +use crate::crh::{ + PoseidonParameters, + FieldBasedHashParameters, PoseidonHash, batched_crh::PoseidonBatchHash, + PoseidonQuinticSBox, +}; +use algebra::fields::tweedle::Fq as tweedleFq; +use algebra::fields::tweedle::Fr as tweedleFr; + +use algebra::biginteger::BigInteger256; +use algebra::field_new; + +#[derive(Clone)] +pub struct TweedleFqPoseidonParameters; + +impl FieldBasedHashParameters for TweedleFqPoseidonParameters { + type Fr = tweedleFq; + const R:usize = 2; // The rate of the hash function +} + +impl PoseidonParameters for TweedleFqPoseidonParameters { + + const T:usize = 3; // Number of S-Boxes + const R_F:i32 = 4; // Number of full rounds (for each of the two full rounds) + const R_P:i32 = 53; // Number of partial rounds + + // The zero element of the field + const ZERO:tweedleFq = field_new!(tweedleFq, BigInteger256([0, 0, 0, 0])); + // The constant 3 to add to the position corresponding to the capacity + const C2:tweedleFq = field_new!(tweedleFq, BigInteger256([1313830951112933365, 15639615358200390918, 18446744073709551615, 4611686018427387903])); + + + // State vector after permutation of zero state vector + // CORRECT!!!! + const AFTER_ZERO_PERM: &'static [tweedleFq] = &[ + field_new!(tweedleFq,BigInteger256([13441481771078552986, 12972335911030719087, 15437699503042710849, 160361526711774217])), + field_new!(tweedleFq,BigInteger256([15405486376089262217, 14312420080355796560, 15664467984797307766, 3141491969611633139])), + field_new!(tweedleFq,BigInteger256([17787109336398570921, 13715585997734925278, 4320211150096131134, 3378087138098461311])) + ]; + + // Array of round constants + const ROUND_CST: &'static[tweedleFq] = &[ + // Constants converted to Montgomery representation. Montgomery constant = 2^256 + // For rounds 4 + 53 + 4 = 61 + + field_new!(tweedleFq,BigInteger256([18375047913323486431, 5923822429093641730, 14792793232622296002, 460740392914680724])), + field_new!(tweedleFq,BigInteger256([14931792468847234636, 17728159657503714589, 13500175472161438304, 3615544277822058541])), + field_new!(tweedleFq,BigInteger256([1548594241411011801, 13126481624920840825, 17129171112426146970, 501536674856715822])), + field_new!(tweedleFq,BigInteger256([7195819876525230546, 16622942093039222960, 7453886381688349568, 494917437502518487])), + field_new!(tweedleFq,BigInteger256([3332423456486599023, 10000656673613732061, 15392103053619900362, 1748683560535990472])), + field_new!(tweedleFq,BigInteger256([13673407196190650592, 17396216761848944067, 12029578185838428217, 1047231933623357604])), + field_new!(tweedleFq,BigInteger256([10462700099232365033, 3621982514915236984, 10323073177777975244, 3576625367978319447])), + field_new!(tweedleFq,BigInteger256([5280302247684058121, 12413488222341749077, 5699574202463024572, 3109762661198616])), + field_new!(tweedleFq,BigInteger256([1671657072263102741, 18135209815774604514, 9805448327929679421, 3285084869023497664])), + field_new!(tweedleFq,BigInteger256([2295443428727658934, 15317606372664453501, 18155385285422593461, 398675696883414209])), + field_new!(tweedleFq,BigInteger256([4080171794620839645, 9515163533055863902, 14650348374092624119, 742911999247368959])), + field_new!(tweedleFq,BigInteger256([13969101692049584803, 8809090391057346469, 5316034866033635299, 1730139658204335913])), + field_new!(tweedleFq,BigInteger256([12981011791482681208, 3651399279239878977, 3845372373811895280, 3456914477373222524])), + field_new!(tweedleFq,BigInteger256([7792767116139164570, 8189439715943562412, 1220914334499711071, 3532988254507327904])), + field_new!(tweedleFq,BigInteger256([5688400659388919487, 3069613770356962217, 17461729530031842264, 1211351398860104589])), + field_new!(tweedleFq,BigInteger256([10339382492376072447, 1855672965244714015, 18372883031082610481, 794763713140921390])), + field_new!(tweedleFq,BigInteger256([16066176482239480823, 12087574669422884278, 2147149564929349361, 824125054157151876])), + field_new!(tweedleFq,BigInteger256([13272033263567215414, 7652200798821202319, 15802330312590375322, 4225027044245037193])), + field_new!(tweedleFq,BigInteger256([14072395220600341227, 18378672619168457884, 685746925372261792, 4143233687605584996])), + field_new!(tweedleFq,BigInteger256([5485733526628028410, 3446813435059618664, 9415333817081109095, 3795758168960557230])), + field_new!(tweedleFq,BigInteger256([8448067327768997497, 2423108563974828257, 12058220891872660346, 2195359407257569183])), + field_new!(tweedleFq,BigInteger256([17915978863458429395, 7809395148418243254, 11364327594943247932, 4100464924797289007])), + field_new!(tweedleFq,BigInteger256([15380925499745655701, 795668084015472000, 14837187764044891191, 2936270471602724797])), + field_new!(tweedleFq,BigInteger256([17230341573216200665, 12212811360729372464, 13321874991762913791, 287314185177051346])), + field_new!(tweedleFq,BigInteger256([18132380827519387723, 12277871322994361614, 13545701124167640889, 3410677268980241469])), + field_new!(tweedleFq,BigInteger256([10095550376384431808, 1155702318370222469, 2962937094568611198, 3481681969816085506])), + field_new!(tweedleFq,BigInteger256([11042999902210831792, 11786709817887160790, 13884428412322050202, 58925602301305543])), + field_new!(tweedleFq,BigInteger256([13560999651882317367, 17286988406541828788, 14022663546836068326, 1531164007046538915])), + field_new!(tweedleFq,BigInteger256([13794570563525428928, 3232952470564703652, 4389393763280885579, 1699158985057767495])), + field_new!(tweedleFq,BigInteger256([6790091840122275826, 8488729028109470967, 2401799582539993119, 1877301237507560649])), + field_new!(tweedleFq,BigInteger256([8845077712080523633, 3513671401752966901, 16430163308541471083, 3142837136696838825])), + field_new!(tweedleFq,BigInteger256([11407176159840391828, 9768735417749375483, 13526395196167438931, 2511478158082789950])), + field_new!(tweedleFq,BigInteger256([14533477465056590277, 12785365280466606528, 8516245743782326058, 806355231289037267])), + field_new!(tweedleFq,BigInteger256([15066071013209203736, 13582258282852237397, 17685700828154582525, 2579296184315460019])), + field_new!(tweedleFq,BigInteger256([8496863837435409909, 4279268300914766712, 2101673805157847797, 3541136890715403231])), + field_new!(tweedleFq,BigInteger256([12303520794761374574, 16763428716075095627, 1434895753410914019, 192054853882706347])), + field_new!(tweedleFq,BigInteger256([10691943766528535560, 12431933425523333921, 8749390924533060252, 586842827185966794])), + field_new!(tweedleFq,BigInteger256([6187704998650504979, 5098295898874973014, 11151054004367124065, 3187732152644427131])), + field_new!(tweedleFq,BigInteger256([2202792942727180475, 11643078321384456302, 16208242621507159878, 2909812319500571646])), + field_new!(tweedleFq,BigInteger256([5328412348087515797, 9566038929408628318, 15700803421326755116, 3240226181740791303])), + field_new!(tweedleFq,BigInteger256([5446442679535403944, 9604397354458414345, 14327448411440334618, 3773249171861420809])), + field_new!(tweedleFq,BigInteger256([16646958062619510989, 5877631070296195132, 5641262816049541464, 1004166659345749598])), + field_new!(tweedleFq,BigInteger256([16307128872015819934, 2220511814858905768, 9470231673086883893, 895580991924951673])), + field_new!(tweedleFq,BigInteger256([5508432456386297606, 13369025331072968067, 4101230575453798353, 191401932037439206])), + field_new!(tweedleFq,BigInteger256([6706431679124947996, 4859190773720147889, 1850319662178598395, 4389084024692075903])), + field_new!(tweedleFq,BigInteger256([14532230888281505347, 7477718091019015818, 17072484038738189801, 3290987331697301344])), + field_new!(tweedleFq,BigInteger256([18438163623934087373, 3750537772258066503, 17037347195834883306, 2708482619963199162])), + field_new!(tweedleFq,BigInteger256([1288732744453262849, 15349537036568248057, 7422579766432093839, 3774608235619850160])), + field_new!(tweedleFq,BigInteger256([9749513427878522946, 11528056065387422410, 2986420750858100571, 1940252586933017733])), + field_new!(tweedleFq,BigInteger256([6019515620055322905, 18068995189255597161, 5967550666384145171, 1753678114490763843])), + field_new!(tweedleFq,BigInteger256([12378993308099518097, 12412086191781885485, 12110680658620042658, 1971011405094755247])), + field_new!(tweedleFq,BigInteger256([3447659090748273349, 11179278672800598927, 15923935877179044468, 4035962497258800535])), + field_new!(tweedleFq,BigInteger256([10590880688727997198, 11572281123368030267, 3375742792530212883, 4561223334451420615])), + field_new!(tweedleFq,BigInteger256([1608621516889427167, 7398035687461997638, 7947879613517703380, 417095221931638468])), + field_new!(tweedleFq,BigInteger256([15421577456380670355, 2178887690198725001, 9394430976845639565, 4496909276349461574])), + field_new!(tweedleFq,BigInteger256([14133624478248611322, 7162592009211147591, 13963453286349088948, 1771899910166319253])), + field_new!(tweedleFq,BigInteger256([1425797751085022599, 1571354496488027626, 2677498806918454794, 2186903939450246827])), + field_new!(tweedleFq,BigInteger256([1616250069752351027, 555228004513451537, 11917736063779090304, 1843888760350849975])), + field_new!(tweedleFq,BigInteger256([10965291335676092921, 2231655424201057272, 13584147532879238419, 711076366728319120])), + field_new!(tweedleFq,BigInteger256([861326620860790090, 1398884691234386105, 10911193452462483392, 3123948214009039034])), + field_new!(tweedleFq,BigInteger256([3632000310403980599, 9711561633943025723, 8577268569336422469, 3239787271572597987])), + field_new!(tweedleFq,BigInteger256([1961125604217862884, 3139021884708101015, 10816992759795420734, 3919423078312847747])), + field_new!(tweedleFq,BigInteger256([8507790987428380663, 4128507429575564483, 4353461697582145862, 712145479977325302])), + field_new!(tweedleFq,BigInteger256([7618875353969279329, 3293349099976580020, 15506365211448425855, 1202150480792923403])), + field_new!(tweedleFq,BigInteger256([5457021276445480210, 2134541362521554606, 17374711837372391947, 3648038117621890219])), + field_new!(tweedleFq,BigInteger256([10765176413679378487, 171656286831033162, 7229859583479519350, 4469920960582455303])), + field_new!(tweedleFq,BigInteger256([13461587134377567476, 3147159660624392958, 16568381400221006456, 3211248697297961674])), + field_new!(tweedleFq,BigInteger256([14323795793311900149, 9031408720196330816, 15968216383147023489, 4444255654862708795])), + field_new!(tweedleFq,BigInteger256([7638359329899673095, 17547653236178575299, 17371749119945918414, 3103611848668250330])), + field_new!(tweedleFq,BigInteger256([12612607088186345699, 15293801876911522362, 10135659896266731028, 196584574193443451])), + field_new!(tweedleFq,BigInteger256([11171891532508840935, 8395581612953364133, 6520553280169652935, 262329976239826024])), + field_new!(tweedleFq,BigInteger256([6809170786379763468, 5320300937314500202, 13373772426386006646, 1467949990171769875])), + field_new!(tweedleFq,BigInteger256([17694631132921847960, 17076891302643176841, 11904988927675510383, 4121446305249773268])), + field_new!(tweedleFq,BigInteger256([12762343788712681458, 5786418181383646070, 17970118911399364273, 1430833675397379079])), + field_new!(tweedleFq,BigInteger256([694223596649206640, 13735620519058789129, 5810651642143488007, 2112528937989260659])), + field_new!(tweedleFq,BigInteger256([16554262590008830889, 1995796346197697473, 16297048578084224190, 4169987431246743377])), + field_new!(tweedleFq,BigInteger256([8248353518585398804, 12195142604935233652, 10199117909127699818, 888087992710690441])), + field_new!(tweedleFq,BigInteger256([15386131267990963373, 7874870509972495334, 18112520653935199703, 2297034442762080104])), + field_new!(tweedleFq,BigInteger256([11205371889551140107, 14831716791383964443, 10644185602325047494, 1101558538249669687])), + field_new!(tweedleFq,BigInteger256([12621238164615387356, 17036681656408816315, 17139700703123112026, 3650390407119741560])), + field_new!(tweedleFq,BigInteger256([10049081787436278179, 5231900962482113820, 2122661949530634555, 3369902720157480311])), + field_new!(tweedleFq,BigInteger256([2569834939264899178, 8640063413210681183, 7723717385188385753, 2161397311541801787])), + field_new!(tweedleFq,BigInteger256([14186604312646444905, 16127071399536272112, 5582941028285134378, 4598365613026593250])), + field_new!(tweedleFq,BigInteger256([13288896464621325393, 1156070886820945225, 1334386369091282281, 1445414558148509390])), + field_new!(tweedleFq,BigInteger256([10943224149816515865, 11524288100171107300, 7992779615064184817, 3924418880546396018])), + field_new!(tweedleFq,BigInteger256([4877970112957537318, 9554633740117540754, 4057747530113270215, 232022978084158527])), + field_new!(tweedleFq,BigInteger256([9563911209062997159, 9521277605605953226, 5178948471314818928, 1319013290421570828])), + field_new!(tweedleFq,BigInteger256([12117772128941506071, 11124570075382599419, 1172327983952825983, 888617469852216585])), + field_new!(tweedleFq,BigInteger256([5374783348069869041, 10307612446585477387, 13124963550030808031, 1364972046735428189])), + field_new!(tweedleFq,BigInteger256([9651192469056292662, 17196100795514854214, 10942101116695223076, 863532964686381813])), + field_new!(tweedleFq,BigInteger256([7137455362819122436, 6517646534276183620, 16850528084465737793, 3995876150794252351])), + field_new!(tweedleFq,BigInteger256([5879041798684645896, 13924513831775341526, 1936535396258975099, 2191995551270818306])), + field_new!(tweedleFq,BigInteger256([14819185247007650160, 8841078600018668624, 15497143130127444587, 1909982931659989929])), + field_new!(tweedleFq,BigInteger256([7154700080631124909, 14653391704152082848, 14322282497378513820, 1758140308864978420])), + field_new!(tweedleFq,BigInteger256([18297143393072298385, 1870045362157282242, 143736994066908950, 286415654226138654])), + field_new!(tweedleFq,BigInteger256([13770610977466565066, 897097399629661202, 1507418880333689553, 4099837867205938777])), + field_new!(tweedleFq,BigInteger256([8206481251877972431, 1059885375904908159, 494492934812622063, 3579084368149877972])), + field_new!(tweedleFq,BigInteger256([4950313918674430561, 13426577911015775788, 4342611229158556955, 401201126699186706])), + field_new!(tweedleFq,BigInteger256([3699286877665172979, 4176809051639050681, 11450765141197870686, 2461491629359294833])), + field_new!(tweedleFq,BigInteger256([5218856687062940762, 2827535237090766352, 5963527838589382444, 3751445627405083235])), + field_new!(tweedleFq,BigInteger256([11881563275765687033, 18171870502101144438, 5843909009118641177, 3686291813785521260])), + field_new!(tweedleFq,BigInteger256([5054944658628014907, 6077308549014680338, 10697072581208417735, 3680168991382163729])), + field_new!(tweedleFq,BigInteger256([10801155309073585954, 11777359113704962594, 15546098999245555674, 2658334572247723370])), + field_new!(tweedleFq,BigInteger256([11326396499983108915, 167090552583701423, 9250457927459399201, 2694399637654904364])), + field_new!(tweedleFq,BigInteger256([15840336121949097076, 10959308968092221723, 17782512938216788774, 3830286662062746131])), + field_new!(tweedleFq,BigInteger256([2613743751478940430, 11071541872995151394, 12385212852097507290, 1215382145596571146])), + field_new!(tweedleFq,BigInteger256([3560622648158146837, 16999894113354352452, 358189321050161410, 2915086624092521000])), + field_new!(tweedleFq,BigInteger256([18305428042677051046, 5797433216271982653, 13038594247059141951, 2640908183575167690])), + field_new!(tweedleFq,BigInteger256([13466288514113415237, 17870229245356704420, 416721081388595686, 2400842670115274062])), + field_new!(tweedleFq,BigInteger256([18308393055792988878, 264424842075942877, 17607190396524970422, 2710299021400166157])), + field_new!(tweedleFq,BigInteger256([5042676379434646459, 10302786640029471076, 3457025167548572920, 575903063531713056])), + field_new!(tweedleFq,BigInteger256([14467261911700558519, 5473705053687362752, 16751696060807990750, 3511761672623514514])), + field_new!(tweedleFq,BigInteger256([9715151656667039135, 9410670589621450880, 4734306451087135361, 4256697671211814844])), + field_new!(tweedleFq,BigInteger256([16021347353210130358, 2776555037708099774, 6583078997241909805, 1103249144591551026])), + field_new!(tweedleFq,BigInteger256([3518504920202512536, 15112423015245588816, 5471961387996069101, 4548255882436268691])), + field_new!(tweedleFq,BigInteger256([14187758243643018817, 11656720507727125592, 4290773348570153699, 3366433174492927003])), + field_new!(tweedleFq,BigInteger256([2662803858271313524, 8503240156046651960, 2350716960135304653, 4412085524028135091])), + field_new!(tweedleFq,BigInteger256([8484408613859982271, 10426101479054831169, 17437233526638213860, 3163057627042341970])), + field_new!(tweedleFq,BigInteger256([7268397093809212951, 17976072475859891887, 4970918853623810058, 1840709333255917234])), + field_new!(tweedleFq,BigInteger256([10556868181934839038, 11088624017625777481, 14750020033748575325, 318156816359699586])), + field_new!(tweedleFq,BigInteger256([5990552971674900524, 5512515502897504280, 17803703232147812798, 833909428977295170])), + field_new!(tweedleFq,BigInteger256([6161976780791080483, 10448742693640525996, 1150810876133687510, 850359841986341794])), + field_new!(tweedleFq,BigInteger256([4242187551986314414, 14333283797384598116, 1084328495240451538, 2301829035044026612])), + field_new!(tweedleFq,BigInteger256([16464933953927214969, 13269682871778555088, 8641492326955097330, 4395699539743430679])), + field_new!(tweedleFq,BigInteger256([14840300324055428396, 8667792823810349182, 15442379853115846028, 814104381660095518])), + field_new!(tweedleFq,BigInteger256([6908454172075020710, 9763590299837251026, 6460970487630013676, 4145669497236935933])), + field_new!(tweedleFq,BigInteger256([15382743504358933060, 16771573392995500378, 1364759062308557399, 2794545437540427083])), + field_new!(tweedleFq,BigInteger256([17430659333882631469, 10059852764805356342, 1696412937827258673, 409396711532671932])), + field_new!(tweedleFq,BigInteger256([1182516670450950389, 4260671198809734028, 17661727476729487311, 1795653040313110528])), + field_new!(tweedleFq,BigInteger256([4143583825601959516, 6480913905699613877, 9384928534646208393, 2993977093170921808])), + field_new!(tweedleFq,BigInteger256([15042422928575313971, 8509921617884984577, 1869446074369576093, 3685510660691508054])), + field_new!(tweedleFq,BigInteger256([9430141932476827006, 5525439769280813113, 5551670547884865200, 2841182790574938993])), + field_new!(tweedleFq,BigInteger256([15990876638397641970, 3462285571963952642, 8580365697899971519, 1861576315365057553])), + field_new!(tweedleFq,BigInteger256([3270921466185456757, 12414611243736764233, 7214227383177852747, 1244282561965229132])), + field_new!(tweedleFq,BigInteger256([5126468273324266592, 10126055408576359138, 18187577788170507249, 1676667860177201718])), + field_new!(tweedleFq,BigInteger256([16605930358753242935, 5531995910875396774, 7872194118495068485, 2116149803372961301])), + field_new!(tweedleFq,BigInteger256([7848518661371975580, 6163262817800232173, 6454008458642853025, 1100355458093515375])), + field_new!(tweedleFq,BigInteger256([8958544393098059958, 18101280833298102121, 7680754758287349945, 2934004533993838012])), + field_new!(tweedleFq,BigInteger256([11940837110954720084, 7809491392276245224, 6416852667130422427, 4341725519096749918])), + field_new!(tweedleFq,BigInteger256([5607455893062401636, 17563682011987915105, 16044551536691979357, 2112365129569928783])), + field_new!(tweedleFq,BigInteger256([16875222170693831420, 8899870421434435141, 4802802909060923480, 1294212825691281984])), + field_new!(tweedleFq,BigInteger256([14058046083342203652, 14888687498487489213, 11289263600854136761, 1413066012941216836])), + field_new!(tweedleFq,BigInteger256([13722432265523739654, 3586261583135642460, 10032882584911013759, 1031535389409798278])), + field_new!(tweedleFq,BigInteger256([16254382577394487454, 12211212379838164725, 15412437247916747694, 4477869597150638667])), + field_new!(tweedleFq,BigInteger256([14741310595762569073, 7798824244276396895, 6917044619020638047, 4223028382340023413])), + field_new!(tweedleFq,BigInteger256([15283716514174572795, 10991517511697396796, 15082615501967190362, 2076460226418018150])), + field_new!(tweedleFq,BigInteger256([4555172096130461325, 9450031505516032647, 9092330649873199972, 1735947115478430734])), + field_new!(tweedleFq,BigInteger256([515408819060950847, 17246700587027924790, 7185476514700787826, 2533626805091282148])), + field_new!(tweedleFq,BigInteger256([3469618765605112500, 3592962814296172952, 6078063358853629864, 684447813421736160])), + field_new!(tweedleFq,BigInteger256([1544161166776483665, 13542137990422074256, 17620908716644175555, 2853867931669513944])), + field_new!(tweedleFq,BigInteger256([7583873768388772762, 2812682654654652549, 1168533076541168323, 3956848789102897904])), + field_new!(tweedleFq,BigInteger256([5894312208987958932, 9072140115657922423, 3719214012665517911, 3280846627480631750])), + field_new!(tweedleFq,BigInteger256([13094363293018642621, 8916842278972893939, 15174701240774270743, 3975545984877733023])), + field_new!(tweedleFq,BigInteger256([17376709897845888823, 15293848543075451948, 16695214180387073107, 3811492016583028999])), + field_new!(tweedleFq,BigInteger256([15747516313440152674, 14846452211311669236, 11418170030614742509, 2770245811181112092])), + field_new!(tweedleFq,BigInteger256([9125220409312103584, 14693344586663248684, 3018760772051432764, 2140837742130257970])), + field_new!(tweedleFq,BigInteger256([196519920804176752, 7789718629572584464, 6511679129791119671, 2504336086705919675])), + field_new!(tweedleFq,BigInteger256([651813505401392427, 10402893360691015528, 12430022390316920884, 2454688422176626672])), + field_new!(tweedleFq,BigInteger256([15560774832762169682, 17818796614771857426, 13499604651635479990, 1721814517135130956])), + field_new!(tweedleFq,BigInteger256([1959525967607443738, 13937338278653829757, 4015648709192138000, 2105914096156330180])), + field_new!(tweedleFq,BigInteger256([14671411391100381191, 10518143546569483929, 107912222411555645, 2697937519135570198])), + field_new!(tweedleFq,BigInteger256([11528600923259981245, 18406233414170085622, 150603739596798420, 1002773186845409448])), + field_new!(tweedleFq,BigInteger256([4906720806095789256, 8494577289003454158, 6005029233421231659, 721161169362695420])), + field_new!(tweedleFq,BigInteger256([17162446454809251849, 149568523458343550, 6072009353756795788, 2682003578291509111])), + field_new!(tweedleFq,BigInteger256([4664480087225854026, 3191482647603138804, 18283230111466046101, 49261718585730566])), + field_new!(tweedleFq,BigInteger256([2633981178676475839, 6393203064816058036, 14801351307598523023, 290544077455262947])), + field_new!(tweedleFq,BigInteger256([16370745222821771566, 2091954367065507008, 8597474180032191817, 1093592665993584681])), + field_new!(tweedleFq,BigInteger256([3042421511740653507, 9629235393916222260, 6170151894956371487, 3663601922878832129])), + field_new!(tweedleFq,BigInteger256([14951557014812481687, 9486162855179516586, 13861192940345607592, 538182989034581364])), + field_new!(tweedleFq,BigInteger256([12795218764723668212, 9459485011978579911, 16284751703333222422, 611710002273926197])), + field_new!(tweedleFq,BigInteger256([148160453940177357, 10342912063261689484, 12020180593850992767, 496261877935436013])), + field_new!(tweedleFq,BigInteger256([1528601007128230293, 8362154615954927558, 15870596824461794501, 1319664920705456211])), + field_new!(tweedleFq,BigInteger256([14688320614761073435, 16445001864112931345, 14170952461624906973, 2952048231090936137])), + field_new!(tweedleFq,BigInteger256([13053072401082173904, 13124711687008399299, 3090718706246754517, 3001187486929335029])), + field_new!(tweedleFq,BigInteger256([4742586276038333006, 8289744211465421058, 12590676152875801782, 2762371651600237679])), + field_new!(tweedleFq,BigInteger256([1661311756608187627, 6026202867365126168, 8716426438974019973, 796150335524171672])), + field_new!(tweedleFq,BigInteger256([3904163380933259176, 6207536143651268557, 14716301740815945400, 2069526340202021928])), + field_new!(tweedleFq,BigInteger256([18158391892037122785, 10833602786621593204, 13621106806211451404, 1832906363649136106])), + field_new!(tweedleFq,BigInteger256([17052597029373873024, 5340492711582249654, 1578488667298794344, 4561085328936681990])), + field_new!(tweedleFq,BigInteger256([10935563906253472527, 9283554493131717120, 16415933150172416267, 3102321933878801004])), + field_new!(tweedleFq,BigInteger256([2889826238426736722, 11250527879516772786, 4804677738651221588, 2700994595388134011])), + field_new!(tweedleFq,BigInteger256([1181934124953713276, 16309592490821468756, 3268483268528674486, 2589165494052908611])), + field_new!(tweedleFq,BigInteger256([11973879302548863363, 3577470108885223051, 881130995026323322, 2907471080787690526])) + + ]; + + // The MDS matrix constants + const MDS_CST: &'static [tweedleFq] = &[ + // Constants in Montgomery representation with R = 2^256 + field_new!(tweedleFq,BigInteger256([17845126873319735294, 17936357034622120556, 18446744073709551615, 816178221477274908])), + field_new!(tweedleFq,BigInteger256([8922563436659867647, 18191550554165836086, 18446744073709551615, 398483477240155648])), + field_new!(tweedleFq,BigInteger256([8922563436659867647, 18191550554165836086, 18446744073709551615, 2285763712979539187])), + field_new!(tweedleFq,BigInteger256([8922563436659867647, 18191550554165836086, 18446744073709551615, 398483477240155648])), + field_new!(tweedleFq,BigInteger256([17845126873319735294, 17936357034622120556, 18446744073709551615, 816178221477274908])), + field_new!(tweedleFq,BigInteger256([0, 0, 0, 1132209747590703800])), + field_new!(tweedleFq,BigInteger256([8922563436659867647, 18191550554165836086, 18446744073709551615, 2285763712979539187])), + field_new!(tweedleFq,BigInteger256([0, 0, 0, 1132209747590703800])), + field_new!(tweedleFq,BigInteger256([17845126873319735294, 17936357034622120556, 18446744073709551615, 816178221477274908])), + ]; +} + +pub type TweedleFqQuinticSbox = PoseidonQuinticSBox; +pub type TweedleFqPoseidonHash = PoseidonHash; +pub type TweedleFqBatchPoseidonHash = PoseidonBatchHash; + +#[derive(Clone)] +pub struct TweedleFrPoseidonParameters; + +impl FieldBasedHashParameters for TweedleFrPoseidonParameters { + type Fr = tweedleFr; + // Number of partial rounds + const R: usize = 2; // The rate of the hash function +} + +impl PoseidonParameters for TweedleFrPoseidonParameters { + + const T: usize = 3; + // Number of S-Boxes + const R_F: i32 = 4; + // Number of full rounds (for each of the two full rounds) + const R_P: i32 = 53; + + // The zero element of the field + const ZERO: tweedleFr = field_new!(tweedleFr, BigInteger256([0, 0, 0, 0])); + // The constant 3 to add to the position corresponding to the capacity + const C2: tweedleFr = field_new!(tweedleFr, BigInteger256([5914477434710786037, 15639615358728680791, 18446744073709551615, 4611686018427387903])); + + // State vector after permutation of zero state vector + const AFTER_ZERO_PERM: &'static [tweedleFr] = &[ + field_new!(tweedleFr,BigInteger256([14882572424636798050, 11702526969277291115, 10816378453686605010, 3889898181123487985])), + field_new!(tweedleFr,BigInteger256([18096539402025508228, 10825022229503489043, 7820976511104237879, 3073430066177187921])), + field_new!(tweedleFr,BigInteger256([8633173038692367603, 17063824873430395553, 6489769180483112062, 4431146996138157376])) + ]; + + // Array of round constants + const ROUND_CST: &'static [tweedleFr] = &[ + // Constants converted to Montgomery representation. Montgomery constant = 2^256 + // For rounds 4 + 53 + 4 = 61 + + field_new!(tweedleFr,BigInteger256([8619684056976873607, 7644075163257984763, 12792900609200393724, 3613864077061109332])), + field_new!(tweedleFr,BigInteger256([3110562762534959747, 12876557538611445920, 26655201273877071, 2463977134324310617])), + field_new!(tweedleFr,BigInteger256([10728471279120797255, 11177527914083796570, 11036642661462384674, 3456191112591050733])), + field_new!(tweedleFr,BigInteger256([16167086681459234304, 11998749637582881025, 4131718235849221436, 4077022249447580893])), + field_new!(tweedleFr,BigInteger256([6365906429842807618, 16842857868691586463, 16477220441529521688, 958938781546708761])), + field_new!(tweedleFr,BigInteger256([17023099621324675510, 12562576475317728089, 13392734636044037723, 2296720017939740197])), + field_new!(tweedleFr,BigInteger256([9465417883093788001, 990310299705415476, 9099486570956068414, 889739391304189597])), + field_new!(tweedleFr,BigInteger256([15714384846116973051, 2551063405185229655, 15779970676815414122, 2229630462035587367])), + field_new!(tweedleFr,BigInteger256([7277726030224199983, 6802580208430940285, 129144927234020214, 3998118669133530210])), + field_new!(tweedleFr,BigInteger256([1155714257457453208, 4103594676901354295, 14871650934391542701, 917369871177292957])), + field_new!(tweedleFr,BigInteger256([7482772196214053743, 9088159930467036028, 2831645828895516839, 1753999541291964072])), + field_new!(tweedleFr,BigInteger256([5463654378660348172, 3869343441213247234, 1194194517278674598, 291980067372748614])), + field_new!(tweedleFr,BigInteger256([15708887609362524071, 17034193586159465397, 5726311567571869567, 4351829251063859480])), + field_new!(tweedleFr,BigInteger256([369620898032456828, 12595190899537535710, 4605621911134707792, 1622209102448326549])), + field_new!(tweedleFr,BigInteger256([10716954271374658649, 5273045079835508661, 236429984916260727, 3103578511117355559])), + field_new!(tweedleFr,BigInteger256([13491052997173308741, 2867279563823041931, 3337578719013390011, 2459401588032398222])), + field_new!(tweedleFr,BigInteger256([5228130277703071242, 196679918534811130, 16584545054686476732, 246743403318484429])), + field_new!(tweedleFr,BigInteger256([2214288757198189190, 9131272582309826070, 9880902250519987931, 4147309303131922043])), + field_new!(tweedleFr,BigInteger256([16151572960616794071, 7182346711986238679, 13847805352759494303, 2689932828734207345])), + field_new!(tweedleFr,BigInteger256([1549091956498136732, 5307842996977176629, 8534657396061619174, 2368807241320998357])), + field_new!(tweedleFr,BigInteger256([12635826816434332392, 9809534712124822704, 5030778034294881244, 612041445440958941])), + field_new!(tweedleFr,BigInteger256([1307582599787366924, 176152596393861892, 15427621521292319261, 1796740376201321482])), + field_new!(tweedleFr,BigInteger256([9954941022920998106, 18217688101744210841, 12403118084038074083, 1436272938973511806])), + field_new!(tweedleFr,BigInteger256([2197677570222797569, 4234588688130983368, 11383730159676121036, 4381107941520348007])), + field_new!(tweedleFr,BigInteger256([17489684293826531735, 16497145478850797959, 5961835511222744736, 2507899844127304427])), + field_new!(tweedleFr,BigInteger256([8567960125428632953, 5293217856396607322, 7821192585621439923, 4369600692211500388])), + field_new!(tweedleFr,BigInteger256([5209097354746252161, 2494044799754600500, 14545025973239510550, 424459448480509804])), + field_new!(tweedleFr,BigInteger256([6950829389326950348, 2094927083592691435, 3600357402965386240, 1614578071799319964])), + field_new!(tweedleFr,BigInteger256([2046227209793666284, 4634245880615842284, 743546379944816397, 2136072227665206432])), + field_new!(tweedleFr,BigInteger256([14732681589869050430, 17993499457332133090, 11580173955635458823, 153730473075768381])), + field_new!(tweedleFr,BigInteger256([15466265511828374153, 3174929021304724463, 9123131275263138208, 1731637734908483240])), + field_new!(tweedleFr,BigInteger256([12880709185578614961, 4417220689207436134, 13562035144259105847, 786653871909509615])), + field_new!(tweedleFr,BigInteger256([2537683178039302277, 6547821439211948118, 17622186806064298524, 824767091368624424])), + field_new!(tweedleFr,BigInteger256([10859641752770761211, 8709366739392491966, 5146143291311830526, 3819165079851669967])), + field_new!(tweedleFr,BigInteger256([11550692793274137781, 5284618019050657880, 17176767873878640542, 1218101636948747787])), + field_new!(tweedleFr,BigInteger256([7944041481576372283, 16073289961299100024, 4084130351431417912, 2985481430250697120])), + field_new!(tweedleFr,BigInteger256([7487455482614466243, 9816905780614302043, 11481220452995414760, 2055506029906428682])), + field_new!(tweedleFr,BigInteger256([15998605761221278746, 10754846787164779576, 13053894778131520115, 1380298825863612270])), + field_new!(tweedleFr,BigInteger256([10138148064763536687, 15404956438535414500, 9046785084910482434, 889499260581482252])), + field_new!(tweedleFr,BigInteger256([7582311957522059408, 10824686509857520247, 4818404383302879690, 337731057974085779])), + field_new!(tweedleFr,BigInteger256([16471525983337114412, 17777473099732092681, 8687822595316022622, 183465165871938532])), + field_new!(tweedleFr,BigInteger256([19476793737751487, 498361977231477546, 11052452028410739405, 2575175629449283075])), + field_new!(tweedleFr,BigInteger256([287320741612452654, 3098975741623906034, 2148443769740777106, 41290915449445427])), + field_new!(tweedleFr,BigInteger256([1983939227058516026, 453031019190577090, 8088045153627598498, 746490247057036775])), + field_new!(tweedleFr,BigInteger256([10155354356409594494, 14923532719978279418, 7388690313092839905, 656321338886272926])), + field_new!(tweedleFr,BigInteger256([7933034718686986976, 9040235728927793064, 8541058408932585670, 3052286992668871127])), + field_new!(tweedleFr,BigInteger256([15993037423405923152, 14208390909519033958, 5828766947894580393, 1427801137265778195])), + field_new!(tweedleFr,BigInteger256([3990220005508634068, 11763446998519727183, 3430874013128293138, 4344596967958367639])), + field_new!(tweedleFr,BigInteger256([15339895830544936637, 7080279573083568206, 16546428094463945869, 963418279429023476])), + field_new!(tweedleFr,BigInteger256([12191766618066012112, 11725300945014640099, 11720048136373854012, 1656463910909279236])), + field_new!(tweedleFr,BigInteger256([10878245510533083718, 15344912440588967293, 7276212516689523021, 1847286572844959913])), + field_new!(tweedleFr,BigInteger256([3969883923986814948, 5847490166400087604, 10207839272961202388, 247200277595501769])), + field_new!(tweedleFr,BigInteger256([13631303205671414104, 16048292350827941444, 12024979098956812155, 3511124023127515833])), + field_new!(tweedleFr,BigInteger256([10307518233327120199, 17450164955598995711, 14400838388364410719, 4576520419843873000])), + field_new!(tweedleFr,BigInteger256([2865892317575847574, 9383603231602276131, 1721815409084447596, 662414132519977294])), + field_new!(tweedleFr,BigInteger256([11905358681649949946, 17856497998327415916, 6210219199721796156, 487004751057700914])), + field_new!(tweedleFr,BigInteger256([5251560383510002050, 4895930693504518605, 8248666219309858908, 1900943335822685701])), + field_new!(tweedleFr,BigInteger256([16851906679524904877, 11424193380323294222, 17854697842149418067, 4097018978326536745])), + field_new!(tweedleFr,BigInteger256([4862962277923605236, 2073649245314871534, 1167427641289601554, 3879696912601875490])), + field_new!(tweedleFr,BigInteger256([6319191188346085399, 9481929377934895398, 1132457788698682353, 2121176911649084939])), + field_new!(tweedleFr,BigInteger256([12610938074939144046, 7551837873386858854, 4255955444475416166, 3930126495094270385])), + field_new!(tweedleFr,BigInteger256([1891189390123520440, 5364534799308714347, 17697380720683472092, 2440897738488609818])), + field_new!(tweedleFr,BigInteger256([3911484453761695238, 16662088899173415302, 2338170416264180130, 1197658019934926321])), + field_new!(tweedleFr,BigInteger256([9357079458098186694, 16806283576217310246, 16645675940814857102, 3363329537462438389])), + field_new!(tweedleFr,BigInteger256([8004563494686959117, 5791100024276955871, 4101603827862973257, 3951613272291825217])), + field_new!(tweedleFr,BigInteger256([4303489510499465294, 16455645950843713938, 14943218406349308883, 1513087689562659790])), + field_new!(tweedleFr,BigInteger256([16725036004670267491, 12643871746495789827, 15444360638693052880, 1030804773377328240])), + field_new!(tweedleFr,BigInteger256([4626891838964708991, 2257837493555818757, 3443455811485344720, 2645630541782097763])), + field_new!(tweedleFr,BigInteger256([10747828561388998321, 15738422188844170687, 12015697011215959287, 3645234969689165679])), + field_new!(tweedleFr,BigInteger256([5920436951364626391, 15812628513006086302, 15155085065850653083, 4182280790554320157])), + field_new!(tweedleFr,BigInteger256([17817980414594726477, 7800231092122193438, 4237284811038835135, 1502207726734883643])), + field_new!(tweedleFr,BigInteger256([6501429392126438773, 15341006371208402757, 8261300667865850927, 4197340538109337899])), + field_new!(tweedleFr,BigInteger256([1460349842615098663, 8641099211872815390, 6307752253681609162, 4126141939256604940])), + field_new!(tweedleFr,BigInteger256([12597101760967004301, 9923603378206328104, 4846831508582884671, 1249733648720032467])), + field_new!(tweedleFr,BigInteger256([1991068974866343810, 14741787453870369292, 16049999040696632138, 1723973958495838887])), + field_new!(tweedleFr,BigInteger256([1794179341422777081, 17859067037566096147, 8529801701385683140, 1510710746841040089])), + field_new!(tweedleFr,BigInteger256([4118333466030263116, 11079623028539466327, 2397528824422176776, 885205040733033050])), + field_new!(tweedleFr,BigInteger256([3168547875896682340, 17936675188072961625, 12805514050772767444, 3764121968866528944])), + field_new!(tweedleFr,BigInteger256([2961129148463271720, 14894620627460376941, 7314997486138753531, 415737319780308758])), + field_new!(tweedleFr,BigInteger256([14095667241130693552, 16181301976234177889, 11323313193664658902, 3316774482250747904])), + field_new!(tweedleFr,BigInteger256([12595069537302797190, 12277503567293702898, 13008746954519879403, 3102182896494120844])), + field_new!(tweedleFr,BigInteger256([10907682852170094005, 12139282532735522080, 3882656295158240851, 1976731331117712049])), + field_new!(tweedleFr,BigInteger256([5729034989112740528, 1659495446913835, 4710932510737852006, 2564618636493887])), + field_new!(tweedleFr,BigInteger256([15111817639658622965, 14270204731887234173, 17799367585461762676, 895262047078647083])), + field_new!(tweedleFr,BigInteger256([3951429925281727994, 349638497011183124, 10143588424818583165, 1532842669510173903])), + field_new!(tweedleFr,BigInteger256([2380855197995029544, 7661859067324559040, 2014409457720533061, 2274662433636851054])), + field_new!(tweedleFr,BigInteger256([796357199575013091, 5829320828431964505, 822752053697386775, 1466337527784035592])), + field_new!(tweedleFr,BigInteger256([14120033709675895571, 14191030238014416001, 12084704207033103880, 4463293250387886473])), + field_new!(tweedleFr,BigInteger256([16170688698462646983, 2558675867628516698, 1722317884345097796, 4336810859184623677])), + field_new!(tweedleFr,BigInteger256([15180870943997729860, 6831871930202643135, 10112797799012037332, 1547248128656974475])), + field_new!(tweedleFr,BigInteger256([3670287011655784009, 15197688426404648451, 728640708758854503, 1188147678926969488])), + field_new!(tweedleFr,BigInteger256([15487569673553291962, 10692610486282931288, 13861496515814201198, 3952704376825089924])), + field_new!(tweedleFr,BigInteger256([9289246336206703455, 2281725152316678058, 17928296278437090449, 2964290366172857854])), + field_new!(tweedleFr,BigInteger256([16626910299620616792, 9600071536831318920, 10049723765299551951, 3024785812811896486])), + field_new!(tweedleFr,BigInteger256([5719858591847710161, 9203759175061825093, 3497220997744084044, 1166830486149893015])), + field_new!(tweedleFr,BigInteger256([6138823576067067429, 229753612574203103, 1747251366496489092, 4248056118868727634])), + field_new!(tweedleFr,BigInteger256([1820473450648263593, 15220145589280352088, 1010160302224498127, 2778372256980984072])), + field_new!(tweedleFr,BigInteger256([18383345165008727010, 8923573095448658402, 425268939316185044, 1499853874596683137])), + field_new!(tweedleFr,BigInteger256([14225172617948243085, 680074032079137978, 8912647757312080538, 2913718117468509637])), + field_new!(tweedleFr,BigInteger256([3722626145362937661, 17896698157567342476, 14569116951882527069, 193174577286397044])), + field_new!(tweedleFr,BigInteger256([10105813369156190124, 10526832195385299293, 10116518039474479200, 1924819146348502789])), + field_new!(tweedleFr,BigInteger256([5104177631732483068, 7466530660604108808, 9422405290170433269, 2439171695178098227])), + field_new!(tweedleFr,BigInteger256([14976877337911800605, 2398177378323494012, 5141619249386622159, 4459556514128113707])), + field_new!(tweedleFr,BigInteger256([4528181997373674540, 10455366701118170752, 15782976311237417598, 3383512605537768372])), + field_new!(tweedleFr,BigInteger256([3799983087525751540, 10504325285182855036, 3670418708539385720, 2572046701792047346])), + field_new!(tweedleFr,BigInteger256([8313934919498954453, 9665574611455932350, 16992759677107964552, 1822738573528548487])), + field_new!(tweedleFr,BigInteger256([9657513133693457625, 15531150659603567727, 8672500467754077938, 3361799656901461265])), + field_new!(tweedleFr,BigInteger256([6084133581765505367, 10275388997576989803, 10041522430858413279, 2992663356298655152])), + field_new!(tweedleFr,BigInteger256([9478782736852293381, 10377416685934549231, 14457422486510356017, 252980782358753475])), + field_new!(tweedleFr,BigInteger256([17810439246110811478, 12679641703229829965, 16720035918072500873, 22763597403534489])), + field_new!(tweedleFr,BigInteger256([5041530814423822484, 4820066070840658614, 9269274563850346599, 3980042650208141941])), + field_new!(tweedleFr,BigInteger256([13654590720783081581, 14557472969049748158, 3627016829118107018, 4334487326303612869])), + field_new!(tweedleFr,BigInteger256([3304909079859414569, 4064114328490236138, 6357701336106994039, 3347430249868409160])), + field_new!(tweedleFr,BigInteger256([15811871736094312780, 11402768999672471648, 14298505420387624058, 1380948307890967904])), + field_new!(tweedleFr,BigInteger256([6114363917451576378, 1725746458250677009, 12526412261588393455, 2997547672969973177])), + field_new!(tweedleFr,BigInteger256([18143351882216241420, 9956443463778182145, 5818021443287238240, 2966752734934660455])), + field_new!(tweedleFr,BigInteger256([10673271085444088704, 4084034267690931716, 17546499688490171999, 3048583468352253569])), + field_new!(tweedleFr,BigInteger256([16867930661895014623, 16938273740081335013, 5920422602974366675, 1200123797919497144])), + field_new!(tweedleFr,BigInteger256([9212734102674160476, 12408429963695107429, 17356210321010993167, 3612712717113949659])), + field_new!(tweedleFr,BigInteger256([13687170873924167795, 12096182216294160366, 14165864175083721211, 2155618482392594715])), + field_new!(tweedleFr,BigInteger256([3551010168711196960, 2423276309801385732, 879303811574084874, 4260659501105851640])), + field_new!(tweedleFr,BigInteger256([17752521501327154633, 12371921495934184214, 16841706573947016814, 3711564261308516650])), + field_new!(tweedleFr,BigInteger256([4651625969385323320, 7340617511818604844, 1966338781557896858, 2700530130850162269])), + field_new!(tweedleFr,BigInteger256([14997726626482012518, 17375368787970491019, 15603137624224200750, 3738093568741389473])), + field_new!(tweedleFr,BigInteger256([10148881995301695979, 6974012753909722307, 11677797053379710521, 1571337749252551002])), + field_new!(tweedleFr,BigInteger256([16300795291174790413, 8484530364837971091, 11126454886334612437, 3816376087268079999])), + field_new!(tweedleFr,BigInteger256([2780282574874972648, 13035440078354207623, 14347717190008404597, 2136019178885036525])), + field_new!(tweedleFr,BigInteger256([10373156258604654432, 4194474272768572268, 11700100306761491461, 1625689487199659977])), + field_new!(tweedleFr,BigInteger256([2447443381884623207, 13175404511538312668, 10644683036005838146, 1354795464402850852])), + field_new!(tweedleFr,BigInteger256([1316061417459515271, 2009396777454326723, 18214351582065898738, 4456759973943570733])), + field_new!(tweedleFr,BigInteger256([10862441343574312257, 3538239187907418313, 12579297258093661233, 3200731937504851959])), + field_new!(tweedleFr,BigInteger256([18109530562391187571, 544778997753047298, 10838929406295760942, 3812294688855870081])), + field_new!(tweedleFr,BigInteger256([5930451431034041214, 9780516091691198752, 7297885146569036822, 929041374174267110])), + field_new!(tweedleFr,BigInteger256([4229609487853310473, 13479220354479049854, 6550350342329530200, 1605105394576382921])), + field_new!(tweedleFr,BigInteger256([4574356597967732823, 16593505579083526343, 6922962309308072240, 3934100996266348943])), + field_new!(tweedleFr,BigInteger256([12376107470234029882, 9654472396966947643, 17479266319534080668, 4146777673578390386])), + field_new!(tweedleFr,BigInteger256([17962567822157042417, 2843718487006879628, 4855410825064109087, 3246246564283304450])), + field_new!(tweedleFr,BigInteger256([9996187751215761508, 4980686377956843020, 16074348799401366719, 2880668237826615294])), + field_new!(tweedleFr,BigInteger256([2168000893620879027, 10491411681907685289, 5364265970443569469, 4605886465994552712])), + field_new!(tweedleFr,BigInteger256([3627775336744832994, 8918665283059127536, 9789164560145806441, 1309773762005102048])), + field_new!(tweedleFr,BigInteger256([4120100953687678702, 9458042973439267583, 13038571715950616558, 644251636815219351])), + field_new!(tweedleFr,BigInteger256([1105850745885324253, 7616084836354459183, 8319594133309884641, 237327984422090130])), + field_new!(tweedleFr,BigInteger256([18159131629162449263, 18345158329905807776, 6384983823589710929, 1214593526573032690])), + field_new!(tweedleFr,BigInteger256([6921382437764020243, 1594198101511322009, 9957572733241783743, 4100674727739310156])), + field_new!(tweedleFr,BigInteger256([2809831857988903643, 18059285874006113457, 4533414101715086512, 1380245542121993415])), + field_new!(tweedleFr,BigInteger256([16689322906940808154, 1134229132315165666, 16176598065009951108, 2799708059807984053])), + field_new!(tweedleFr,BigInteger256([8288730377241274056, 6895817741895343323, 18118075342652422658, 4517245171719852591])), + field_new!(tweedleFr,BigInteger256([11435311806896676314, 1047684991333202069, 2165280429439619719, 2377919619389714335])), + field_new!(tweedleFr,BigInteger256([5959582850094324091, 9798417952933379157, 14770765428358670871, 1931733895422656762])), + field_new!(tweedleFr,BigInteger256([15595029562917879208, 9220687116738973785, 14061947273883327258, 2495742204549602296])), + field_new!(tweedleFr,BigInteger256([12923985125224889267, 15523140810420913624, 12813028566271571169, 3692924904160482916])), + field_new!(tweedleFr,BigInteger256([7973888663376556525, 1566713740771999933, 17065015632147362607, 110616200699915302])), + field_new!(tweedleFr,BigInteger256([4974158986588270585, 16055900568880338485, 4068522770921979506, 3144247174048393432])), + field_new!(tweedleFr,BigInteger256([12521529080696892052, 2208426747619386025, 15498050159670141751, 312762471807967459])), + field_new!(tweedleFr,BigInteger256([2639472435529636023, 4412448719213980745, 10697866907866711992, 3462675396478939569])), + field_new!(tweedleFr,BigInteger256([1900122985148135851, 15508633960690337329, 12424509687045318239, 2328284454314565851])), + field_new!(tweedleFr,BigInteger256([6328173618346113556, 3944831839293133405, 9979074218387539355, 883141626752252130])), + field_new!(tweedleFr,BigInteger256([7127319216116447655, 879690474840045336, 14387422959549610530, 1022656191187668760])), + field_new!(tweedleFr,BigInteger256([8682249354777516146, 6943596205302335716, 4532206849418793535, 4334655900362677123])), + field_new!(tweedleFr,BigInteger256([201499112412530735, 16266496712731712867, 4714622486949045736, 4292712095655299994])), + field_new!(tweedleFr,BigInteger256([12501282516181189568, 1920220835460843314, 1631182849529664579, 4292571031109302572])), + field_new!(tweedleFr,BigInteger256([6799814532618150781, 2586710601752356639, 3445685565357856712, 2321934796936220623])), + field_new!(tweedleFr,BigInteger256([12085163624348468115, 8393388684842295111, 368298011708885887, 2020894204261297119])), + field_new!(tweedleFr,BigInteger256([3211140538522754056, 16937518834342613839, 4202796777892304808, 3993859191648788346])), + field_new!(tweedleFr,BigInteger256([2518848783741383597, 8128288374790438480, 6793335114664413262, 1656622859212592492])), + field_new!(tweedleFr,BigInteger256([2725799845309359446, 6577199666086924533, 13927716703405648512, 814936969732855025])), + field_new!(tweedleFr,BigInteger256([16305300951036739636, 16951619740809192954, 1382666680382242999, 2755226671911304104])), + field_new!(tweedleFr,BigInteger256([3768290149135599128, 2220656628618162418, 14867038587490419115, 717940462662022544])), + field_new!(tweedleFr,BigInteger256([9201575371566904862, 14510888835856990575, 10324947356260484913, 2549355830334453291])), + field_new!(tweedleFr,BigInteger256([14459552438969429613, 4511787048828134435, 5544954829489252540, 2567308358615778412])), + field_new!(tweedleFr,BigInteger256([117480208696663825, 11312698943452464688, 3988208170058839097, 2501417516139316426])), + field_new!(tweedleFr,BigInteger256([12545535200523038870, 3454232282773205892, 17621263929461207208, 2391620709543529930])), + field_new!(tweedleFr,BigInteger256([833608254901454418, 13763672928908263944, 11496674018143895790, 2430878303448433821])), + field_new!(tweedleFr,BigInteger256([12490956859497827580, 18156496590239595487, 4536001274804505052, 2881457510944738404])), + field_new!(tweedleFr,BigInteger256([3812793722996664923, 13979546967980192259, 10374334293112550394, 748222621845535679])), + field_new!(tweedleFr,BigInteger256([347625991907446651, 4063157933390978088, 13035705520690440896, 2979147225297302457])), + field_new!(tweedleFr,BigInteger256([5580643752681027299, 16045867182055651747, 17914713274721061270, 980621120342512280])), + field_new!(tweedleFr,BigInteger256([9063537673394104239, 956517737944494408, 18353807666326944426, 1284778836698510557])), + field_new!(tweedleFr,BigInteger256([14326410443738100272, 13850376698216628938, 9884801658110631283, 3433426127066073401])), + field_new!(tweedleFr,BigInteger256([18387450350210803098, 12896501285461160487, 7836851072043570308, 540999244608355236])), + field_new!(tweedleFr,BigInteger256([17788313578174558309, 4146346451204821249, 12085955298953844688, 961011359245879450])), + field_new!(tweedleFr,BigInteger256([16352672786868196452, 13878156201944952139, 9369679985520409923, 2763370764816683980])), + field_new!(tweedleFr,BigInteger256([11675307358578594657, 1024728673635976735, 2996568915846448242, 4235010740076978242])) + + ]; + + // The MDS matrix constants + const MDS_CST: &'static [tweedleFr] = &[ + // Constants in Montgomery representation with R = 2^256 + field_new!(tweedleFr,BigInteger256([2035294266095304701, 17681163514934325971, 18446744073709551615, 738809890580381016])), + field_new!(tweedleFr,BigInteger256([6827346113268285439, 18191550554117809734, 18446744073709551615, 3864121177739205297])), + field_new!(tweedleFr,BigInteger256([6827346113268285439, 18191550554117809734, 18446744073709551615, 1692999340309304955])), + field_new!(tweedleFr,BigInteger256([6827346113268285439, 18191550554117809734, 18446744073709551615, 3864121177739205297])), + field_new!(tweedleFr,BigInteger256([2035294266095304701, 17681163514934325971, 18446744073709551615, 738809890580381016])), + field_new!(tweedleFr,BigInteger256([6827346113268285439, 18191550554117809734, 18446744073709551615, 4430788883075327881])), + field_new!(tweedleFr,BigInteger256([6827346113268285439, 18191550554117809734, 18446744073709551615, 1692999340309304955])), + field_new!(tweedleFr,BigInteger256([6827346113268285439, 18191550554117809734, 18446744073709551615, 4430788883075327881])), + field_new!(tweedleFr,BigInteger256([2035294266095304701, 17681163514934325971, 18446744073709551615, 738809890580381016])), + ]; +} + +pub type TweedleFrQuinticSbox = PoseidonQuinticSBox; +pub type TweedleFrPoseidonHash = PoseidonHash; +pub type TweedleFrBatchPoseidonHash = PoseidonBatchHash; From 08b63b301893c6470637a94a87ea867135793369 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Sun, 3 Jan 2021 17:04:05 +0200 Subject: [PATCH 32/63] ginger-algebra-ocl branch switched --- algebra-utils/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 662d2a231..41af2db23 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -27,8 +27,8 @@ rand = { version = "0.7" } rayon = { version = "1", optional = true } # gpu feature -algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", optional = true } -algebra-cl-gen = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", optional = true } +algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } +algebra-cl-gen = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } crossbeam = { version = "0.7", optional = true } [dev-dependencies] @@ -38,7 +38,7 @@ rand_xorshift = { version = "0.2" } paste = "1.0" algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } -algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "master", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } +algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } bench-utils = { path = "../bench-utils" } [features] From 2344d88a2d4b7513444fecc7d541ca90d193287c Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Tue, 5 Jan 2021 14:11:02 +0100 Subject: [PATCH 33/63] Updated dependencies --- algebra-utils/Cargo.toml | 10 +++++----- algebra/src/fields/bn_382/tests.rs | 6 ++++++ algebra/src/fields/models/fp12_2over3over2.rs | 2 +- primitives/Cargo.toml | 4 ++-- proof-systems/Cargo.toml | 4 ++-- r1cs/core/Cargo.toml | 2 +- r1cs/gadgets/crypto/Cargo.toml | 4 ++-- r1cs/gadgets/std/Cargo.toml | 4 ++-- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 41af2db23..d77dd9d3d 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -20,15 +20,15 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } +algebra = { path = "../algebra", features = [ "parallel" ] } rand = { version = "0.7" } rayon = { version = "1", optional = true } # gpu feature -algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } -algebra-cl-gen = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } +algebra-kernels = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } +algebra-cl-gen = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } crossbeam = { version = "0.7", optional = true } [dev-dependencies] @@ -36,9 +36,9 @@ blake2 = "0.7" criterion = "0.3.3" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { path = "../algebra", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } -algebra-kernels = { git = "ssh://git@github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } +algebra-kernels = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } bench-utils = { path = "../bench-utils" } [features] diff --git a/algebra/src/fields/bn_382/tests.rs b/algebra/src/fields/bn_382/tests.rs index f52ceb880..bdef3ca3e 100644 --- a/algebra/src/fields/bn_382/tests.rs +++ b/algebra/src/fields/bn_382/tests.rs @@ -19,6 +19,12 @@ use rand_xorshift::XorShiftRng; pub(crate) const ITERATIONS: usize = 5; +#[test] +fn test_size_fr() { + println!("{}", ::Params::MODULUS_BITS); + println!("{}", std::mem::size_of::<::BigInt>() * 8) +} + #[test] fn test_bn_382_fr() { let mut rng = XorShiftRng::seed_from_u64(1231275789u64); diff --git a/algebra/src/fields/models/fp12_2over3over2.rs b/algebra/src/fields/models/fp12_2over3over2.rs index 2b16e35fc..079b8f633 100644 --- a/algebra/src/fields/models/fp12_2over3over2.rs +++ b/algebra/src/fields/models/fp12_2over3over2.rs @@ -217,6 +217,6 @@ mod test { assert!(characteristic_square_mod_6_is_one(&[39, 41])); assert!(!characteristic_square_mod_6_is_one(&[40, 41])); assert!(characteristic_square_mod_6_is_one(&[41, 41])); - assert!(characteristic_square_mod_6_is_one(&[1, u64::MAX])); + assert!(characteristic_square_mod_6_is_one(&[1, std::u64::MAX])); } } \ No newline at end of file diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 4e560f852..9af27bc8f 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["parallel"] } +algebra = { path = "../algebra", features = ["parallel"] } bench-utils = { path = "../bench-utils" } digest = { version = "0.7", optional = true } @@ -51,7 +51,7 @@ mnt6_753 = ["algebra/mnt6_753"] bn_382 = ["algebra/bn_382"] [dev-dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } +algebra = { path = "../algebra", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } primitives = { path = "../primitives", features = ["mnt4_753", "mnt6_753", "bn_382"] } criterion = "0.3" diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index bb44ff3c9..88ee08e8f 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } +algebra = { path = "../algebra", features = [ "parallel" ] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } r1cs-core = { path = "../r1cs/core" } bench-utils = { path = "../bench-utils" } @@ -37,7 +37,7 @@ csv = { version = "1" } criterion = "0.3" rand_xorshift = { version = "0.2" } -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { path = "../algebra", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } r1cs-crypto = { path = "../r1cs/gadgets/crypto", features = ["nizk"] } r1cs-std = { path = "../r1cs/gadgets/std" } diff --git a/r1cs/core/Cargo.toml b/r1cs/core/Cargo.toml index 24cb11215..947a85de0 100644 --- a/r1cs/core/Cargo.toml +++ b/r1cs/core/Cargo.toml @@ -18,5 +18,5 @@ include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" [dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl" } +algebra = { path = "../../algebra" } smallvec = { version = "0.6" } diff --git a/r1cs/gadgets/crypto/Cargo.toml b/r1cs/gadgets/crypto/Cargo.toml index 20465a096..dd982e4ff 100644 --- a/r1cs/gadgets/crypto/Cargo.toml +++ b/r1cs/gadgets/crypto/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } +algebra = { path = "../../../algebra", features = [ "parallel" ] } primitives = {path = "../../../primitives"} r1cs-core = { path = "../../core"} r1cs-std = { path = "../std"} @@ -51,6 +51,6 @@ llvm_asm = ["algebra/llvm_asm"] [dev-dependencies] rand_xorshift = { version = "0.2" } -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "sw6"] } +algebra = { path = "../../../algebra", features = ["bls12_381", "sw6"] } r1cs-std = { path = "../std", features = ["jubjub", "edwards_sw6", "bls12_377", "mnt4_753", "mnt6_753", "bn_382"] } r1cs-crypto = { path = "../crypto", features = ["mnt4_753", "mnt6_753", "bn_382"] } \ No newline at end of file diff --git a/r1cs/gadgets/std/Cargo.toml b/r1cs/gadgets/std/Cargo.toml index 561859ca5..5cb968df2 100644 --- a/r1cs/gadgets/std/Cargo.toml +++ b/r1cs/gadgets/std/Cargo.toml @@ -20,7 +20,7 @@ license = "MIT/Apache-2.0" ################################# Dependencies ################################ [dependencies] -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl" } +algebra = { path = "../../../algebra" } r1cs-core = { path = "../../core"} derivative = "1" radix_trie = "0.1" @@ -42,4 +42,4 @@ tweedle = [ "algebra/tweedle" ] [dev-dependencies] rand = { version = "0.7" } rand_xorshift = { version = "0.2" } -algebra = { git = "ssh://git@github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "jubjub"] } +algebra = { path = "../../../algebra", features = ["bls12_381", "jubjub"] } From 9849e49cd2e353ea1e8646386675bd58b1864c6d Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Tue, 5 Jan 2021 09:27:51 -0500 Subject: [PATCH 34/63] Reverted algebra dependencies to be specified in git form --- algebra-utils/Cargo.toml | 4 ++-- algebra/Cargo.toml | 2 +- primitives/Cargo.toml | 4 ++-- proof-systems/Cargo.toml | 4 ++-- r1cs/core/Cargo.toml | 2 +- r1cs/gadgets/crypto/Cargo.toml | 4 ++-- r1cs/gadgets/std/Cargo.toml | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index d77dd9d3d..9b48b6d6f 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = [ "parallel" ] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } rand = { version = "0.7" } @@ -36,7 +36,7 @@ blake2 = "0.7" criterion = "0.3.3" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { path = "../algebra", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } algebra-kernels = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } bench-utils = { path = "../bench-utils" } diff --git a/algebra/Cargo.toml b/algebra/Cargo.toml index eff4d021d..2a8774209 100644 --- a/algebra/Cargo.toml +++ b/algebra/Cargo.toml @@ -39,7 +39,7 @@ blake2 = "0.7" criterion = "0.2" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { path = "../algebra", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753", "bn_382", "tweedle"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "jubjub", "mnt4_753", "mnt6_753", "bn_382", "tweedle"] } [features] parallel = [ "rayon" ] diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 9af27bc8f..dc298abf4 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = ["parallel"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["parallel"] } bench-utils = { path = "../bench-utils" } digest = { version = "0.7", optional = true } @@ -51,7 +51,7 @@ mnt6_753 = ["algebra/mnt6_753"] bn_382 = ["algebra/bn_382"] [dev-dependencies] -algebra = { path = "../algebra", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["edwards_sw6", "jubjub", "sw6", "bls12_377"] } primitives = { path = "../primitives", features = ["mnt4_753", "mnt6_753", "bn_382"] } criterion = "0.3" diff --git a/proof-systems/Cargo.toml b/proof-systems/Cargo.toml index 88ee08e8f..3bd05413a 100644 --- a/proof-systems/Cargo.toml +++ b/proof-systems/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../algebra", features = [ "parallel" ] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } r1cs-core = { path = "../r1cs/core" } bench-utils = { path = "../bench-utils" } @@ -37,7 +37,7 @@ csv = { version = "1" } criterion = "0.3" rand_xorshift = { version = "0.2" } -algebra = { path = "../algebra", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft", "bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } r1cs-crypto = { path = "../r1cs/gadgets/crypto", features = ["nizk"] } r1cs-std = { path = "../r1cs/gadgets/std" } diff --git a/r1cs/core/Cargo.toml b/r1cs/core/Cargo.toml index 947a85de0..1500830a4 100644 --- a/r1cs/core/Cargo.toml +++ b/r1cs/core/Cargo.toml @@ -18,5 +18,5 @@ include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" [dependencies] -algebra = { path = "../../algebra" } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl" } smallvec = { version = "0.6" } diff --git a/r1cs/gadgets/crypto/Cargo.toml b/r1cs/gadgets/crypto/Cargo.toml index dd982e4ff..2c02a484d 100644 --- a/r1cs/gadgets/crypto/Cargo.toml +++ b/r1cs/gadgets/crypto/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../../../algebra", features = [ "parallel" ] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = [ "parallel" ] } primitives = {path = "../../../primitives"} r1cs-core = { path = "../../core"} r1cs-std = { path = "../std"} @@ -51,6 +51,6 @@ llvm_asm = ["algebra/llvm_asm"] [dev-dependencies] rand_xorshift = { version = "0.2" } -algebra = { path = "../../../algebra", features = ["bls12_381", "sw6"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "sw6"] } r1cs-std = { path = "../std", features = ["jubjub", "edwards_sw6", "bls12_377", "mnt4_753", "mnt6_753", "bn_382"] } r1cs-crypto = { path = "../crypto", features = ["mnt4_753", "mnt6_753", "bn_382"] } \ No newline at end of file diff --git a/r1cs/gadgets/std/Cargo.toml b/r1cs/gadgets/std/Cargo.toml index 5cb968df2..18135c126 100644 --- a/r1cs/gadgets/std/Cargo.toml +++ b/r1cs/gadgets/std/Cargo.toml @@ -20,7 +20,7 @@ license = "MIT/Apache-2.0" ################################# Dependencies ################################ [dependencies] -algebra = { path = "../../../algebra" } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl" } r1cs-core = { path = "../../core"} derivative = "1" radix_trie = "0.1" @@ -42,4 +42,4 @@ tweedle = [ "algebra/tweedle" ] [dev-dependencies] rand = { version = "0.7" } rand_xorshift = { version = "0.2" } -algebra = { path = "../../../algebra", features = ["bls12_381", "jubjub"] } +algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "jubjub"] } From fa67f2a40ef3b2011deb557fd24868f73f0ed83f Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Mon, 11 Jan 2021 15:55:06 +0100 Subject: [PATCH 35/63] AlgebraicSponge primitive and gadgets for Poseidon + tests refactoring --- primitives/src/crh/mod.rs | 64 ++++- primitives/src/crh/poseidon/mod.rs | 267 +++++++++++--------- primitives/src/lib.rs | 7 - r1cs/gadgets/crypto/src/crh/mod.rs | 106 +++++++- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 259 ++++++++----------- 5 files changed, 418 insertions(+), 285 deletions(-) diff --git a/primitives/src/crh/mod.rs b/primitives/src/crh/mod.rs index 0eada8a89..1d216a186 100644 --- a/primitives/src/crh/mod.rs +++ b/primitives/src/crh/mod.rs @@ -1,5 +1,5 @@ use algebra::{ - Field, bytes::ToBytes + Field, PrimeField, bytes::ToBytes }; use rand::Rng; use std::hash::Hash; @@ -110,11 +110,24 @@ pub trait BatchFieldBasedHash { } } +/// the trait for algebraic sponge +pub trait AlgebraicSponge: Clone { + /// Initialize the sponge + fn new() -> Self; + /// Update the sponge with `elems` + fn absorb(&mut self, elems: Vec); + /// Output `num` field elements from the sponge. This function + /// is idempotent and calling it multiple times will result + /// in the same outputs, unless more absorbing are performed + /// in between the calls. + fn squeeze(&self, num: usize) -> Vec; +} + #[cfg(test)] mod test { use algebra::{ - fields::mnt4753::Fr as MNT4753Fr, Field, UniformRand + fields::mnt4753::Fr as MNT4753Fr, Field, PrimeField, UniformRand }; use super::BatchFieldBasedHash; @@ -124,6 +137,9 @@ mod test { use rand_xorshift::XorShiftRng; use rand::SeedableRng; + use crate::{ + FieldBasedHash, AlgebraicSponge + }; struct DummyMNT4BatchPoseidonHash; @@ -132,6 +148,50 @@ mod test { type BaseHash = MNT4PoseidonHash; } + pub(crate) fn field_based_hash_test( + personalization: Option<&[H::Data]>, + inputs: Vec, + expected_output: H::Data + ) + { + // Test H(inputs) == expected_output + let mut digest = H::init(personalization); + inputs.iter().for_each(|fe| { digest.update(fe.clone()); }); + let output = digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match"); + + let inputs_len = inputs.len(); + if inputs_len > 1 { + let final_elem = inputs[inputs_len - 1].clone(); + // Test finalize() holding the state and allowing updates in between different calls to it + digest.reset(None); + inputs.into_iter().take(inputs_len - 1).for_each(|fe| { digest.update(fe); }); + + digest.finalize(); + digest.update(final_elem); + assert_eq!(output, digest.finalize()); + + //Test finalize() being idempotent + assert_eq!(output, digest.finalize()); + } + } + + pub(crate) fn algebraic_sponge_test, F: PrimeField>( + to_absorb: Vec, + expected_squeezes: Vec + ) + { + let mut sponge = H::new(); + + // Absorb all field elements + sponge.absorb(to_absorb); + + // Squeeze and check the outputs + for i in 0..expected_squeezes.len() { + assert_eq!(&expected_squeezes[..i + 1], &sponge.squeeze(i + 1)[..]); + } + } + #[ignore] #[test] fn test_default_batch_hash_implementation() { diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 0834b1986..37135deae 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -17,6 +17,7 @@ pub use self::parameters::*; pub mod sbox; pub use self::sbox::*; +use crate::AlgebraicSponge; pub trait PoseidonParameters: 'static + FieldBasedHashParameters + Clone { const T: usize; // Number of S-Boxes @@ -29,7 +30,11 @@ pub trait PoseidonParameters: 'static + FieldBasedHashParameters + Clone { const MDS_CST: &'static[Self::Fr]; // The MDS matrix } -#[derive(Debug)] +#[derive(Derivative)] +#[derivative( + Clone(bound = ""), + Debug(bound = "") +)] pub struct PoseidonHash, SB: PoseidonSBox

>{ state: Vec, pending: Vec, @@ -44,22 +49,21 @@ impl PoseidonHash SB: PoseidonSBox

, { #[inline] - fn apply_permutation(&mut self) { + fn apply_permutation(&mut self, add_c2: bool) { for (input, state) in self.pending.iter().zip(self.state.iter_mut()) { *state += input; } - self.state[P::R] += &P::C2; + if add_c2 { self.state[P::R] += &P::C2 }; Self::poseidon_perm(&mut self.state); } #[inline] - fn _finalize(&self) -> F { - let mut state = self.state.clone(); + fn _finalize(&self, state: &mut Vec, add_c2: bool) -> F { for (input, s) in self.pending.iter().zip(state.iter_mut()) { *s += input; } - state[P::R] += &P::C2; - Self::poseidon_perm(&mut state); + if add_c2 { state[P::R] += &P::C2; } + Self::poseidon_perm(state); state[0] } @@ -134,6 +138,8 @@ impl FieldBasedHash for PoseidonHash type Parameters = P; fn init(personalization: Option<&[Self::Data]>) -> Self { + assert_eq!(P::T - P::R, 1, "The assumption that the capacity is one field element is not satisfied."); + let mut state = Vec::with_capacity(P::T); for i in 0..P::T { state.push(P::AFTER_ZERO_PERM[i]); @@ -180,7 +186,7 @@ impl FieldBasedHash for PoseidonHash fn update(&mut self, input: Self::Data) -> &mut Self { self.pending.push(input); if self.pending.len() == P::R { - self.apply_permutation(); + self.apply_permutation(true); self.pending.clear(); } self @@ -188,7 +194,7 @@ impl FieldBasedHash for PoseidonHash fn finalize(&self) -> Self::Data { if !self.pending.is_empty() { - self._finalize() + self._finalize(&mut self.state.clone(), true) } else { self.state[0] } @@ -201,118 +207,130 @@ impl FieldBasedHash for PoseidonHash } } +impl AlgebraicSponge for PoseidonHash + where + F: PrimeField, + P: PoseidonParameters, + SB: PoseidonSBox

, +{ + fn new() -> Self { + Self::init(None) + } + + fn absorb(&mut self, elems: Vec) { + elems.into_iter().for_each(|f| { + self.pending.push(f); + if self.pending.len() == P::R { + self.apply_permutation(false); + self.pending.clear(); + } + }) + } + + fn squeeze(&self, num: usize) -> Vec { + let mut state = self.state.clone(); + for (input, s) in self.pending.iter().zip(state.iter_mut()) { + *s += input; + } + let mut output = Vec::with_capacity(num); + for _ in 0..num { + Self::poseidon_perm(&mut state); + output.push(state[0].clone()); + } + output + } +} + #[cfg(test)] mod test { - use algebra::{ - fields::{ - mnt4753::Fr as MNT4753Fr, - mnt6753::Fr as MNT6753Fr, - }, - }; - use std::str::FromStr; + use algebra::{fields::{ + mnt4753::Fr as MNT4753Fr, + mnt6753::Fr as MNT6753Fr, + }, PrimeField}; use algebra::biginteger::BigInteger768; use crate::crh::{ poseidon::parameters::{ mnt4753::MNT4PoseidonHash, mnt6753::MNT6PoseidonHash, }, - FieldBasedHash, + test::{field_based_hash_test, algebraic_sponge_test} }; - #[test] - fn test_poseidon_hash_mnt4() { - - // Regression test - let expected_output = MNT4753Fr::new(BigInteger768([120759599714708995, 15132412086599307425, 1270378153255747692, 3280164418217209635, 5680179791594071572, 2475152338055275001, 9455820118751334058, 6363436228419696186, 3538976751580678769, 14987158621073838958, 10703097083485496843, 48481977539350])); - let mut poseidon_digest = MNT4PoseidonHash::init(None); - let input = [MNT4753Fr::from_str("1").unwrap(), MNT4753Fr::from_str("2").unwrap()]; - - let output = poseidon_digest - .update(input[0]) - .update(input[1]) - .finalize(); - assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); - - // Test finalize() holding the state and allowing updates in between different calls to it - poseidon_digest - .reset(None) - .update(input[0].clone()); - poseidon_digest.finalize(); - poseidon_digest.update(input[1].clone()); - assert_eq!(output, poseidon_digest.finalize()); - - //Test finalize() being idempotent - assert_eq!(output, poseidon_digest.finalize()); - } - - #[test] - fn test_poseidon_hash_mnt4_single_element() { - let expected_output = MNT4753Fr::new(BigInteger768([10133114337753187244, 13011129467758174047, 14520750556687040981, 911508844858788085, 1859877757310385382, 9602832310351473622, 8300303689130833769, 981323167857397563, 5760566649679562093, 8644351468476031499, 10679665778836668809, 404482168782668])); - let mut poseidon_digest = MNT4PoseidonHash::init(None); - poseidon_digest.update(MNT4753Fr::from_str("1").unwrap()); - let output = poseidon_digest.finalize(); - assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); - } - - #[test] - fn test_poseidon_hash_mnt4_three_element() { - let expected_output = MNT4753Fr::new(BigInteger768([5991160601160569512, 9804741598782512164, 8257389273544061943, 15170134696519047397, 9908596892162673198, 7815454566429677811, 9000639780203615183, 8443915450757188195, 1987926952117715938, 17724141978374492147, 13890449093436164383, 191068391234529])); - let mut poseidon_digest = MNT4PoseidonHash::init(None); - - for i in 1..=3{ - poseidon_digest.update(MNT4753Fr::from(i as u64)); + fn generate_inputs(num: usize) -> Vec{ + let mut inputs = Vec::with_capacity(num); + for i in 1..=num { + let input = F::from(i as u32); + inputs.push(input); } - - let output = poseidon_digest.finalize(); - assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); + inputs } #[test] - fn test_poseidon_hash_mnt6() { - let expected_output = MNT6753Fr::new(BigInteger768([8195238283171732026, 13694263410588344527, 1885103367289967816, 17142467091011072910, 13844754763865913168, 14332001103319040991, 8911700442280604823, 6452872831806760781, 17467681867740706391, 5384727593134901588, 2343350281633109128, 244405261698305])); - let mut poseidon_digest = MNT6PoseidonHash::init(None); - let input = [MNT6753Fr::from_str("1").unwrap(), MNT6753Fr::from_str("2").unwrap()]; - - let output = poseidon_digest - .update(input[0]) - .update(input[1]) - .finalize(); - assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); - - // Test finalize() holding the state and allowing updates in between different calls to it - poseidon_digest - .reset(None) - .update(input[0].clone()); - poseidon_digest.finalize(); - poseidon_digest.update(input[1].clone()); - assert_eq!(output, poseidon_digest.finalize()); - - //Test finalize() being idempotent - assert_eq!(output, poseidon_digest.finalize()); + fn test_poseidon_hash_mnt4() { + field_based_hash_test::( + None, + generate_inputs(1), + MNT4753Fr::new(BigInteger768([10133114337753187244, 13011129467758174047, 14520750556687040981, 911508844858788085, 1859877757310385382, 9602832310351473622, 8300303689130833769, 981323167857397563, 5760566649679562093, 8644351468476031499, 10679665778836668809, 404482168782668])) + ); + + field_based_hash_test::( + None, + generate_inputs(2), + MNT4753Fr::new(BigInteger768([120759599714708995, 15132412086599307425, 1270378153255747692, 3280164418217209635, 5680179791594071572, 2475152338055275001, 9455820118751334058, 6363436228419696186, 3538976751580678769, 14987158621073838958, 10703097083485496843, 48481977539350])) + ); + + field_based_hash_test::( + None, + generate_inputs(3), + MNT4753Fr::new(BigInteger768([5991160601160569512, 9804741598782512164, 8257389273544061943, 15170134696519047397, 9908596892162673198, 7815454566429677811, 9000639780203615183, 8443915450757188195, 1987926952117715938, 17724141978374492147, 13890449093436164383, 191068391234529])) + + ); + + algebraic_sponge_test::( + generate_inputs(5), + vec![ + MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), + MNT4753Fr::new(BigInteger768([16127953875295592987, 11894863219027726126, 17701631661641187911, 14870672795897948467, 12477792521878046393, 7933118744616181152, 16504185330957910903, 4440754255912752398, 2147815826017548215, 15556058995384616380, 7316328326052908756, 488587201854075])), + MNT4753Fr::new(BigInteger768([17093615125500557324, 5853740299004434536, 14185517698974334849, 15081129818867394374, 4393775450585412195, 15317350057972385858, 602096567370343479, 171645566249469757, 213587553721144028, 16770187529782220214, 10656253922486106039, 183907258171817])), + MNT4753Fr::new(BigInteger768([12712297803466521417, 5718281485803573501, 13963200307320285636, 13279387328772122744, 11400771971860800684, 18129978631072081884, 16152730030736233432, 4443584430842639200, 10168547976596639262, 8852760702638429316, 6245616001490582246, 290914933918621])), + MNT4753Fr::new(BigInteger768([10000480287694253354, 5873338108557543580, 14250396374254092226, 15940814885061001617, 7624733801679967429, 10913153568558026344, 10086885331318146225, 5264350148957133820, 9338271530149930761, 15261863060094932371, 15830626088040155644, 456905335294658])) + ] + ); } #[test] - fn test_poseidon_hash_mnt6_single_element() { + fn test_poseidon_hash_mnt6() { let expected_output = MNT6753Fr::new(BigInteger768([9820480440897423048, 13953114361017832007, 6124683910518350026, 12198883805142820977, 16542063359667049427, 16554395404701520536, 6092728884107650560, 1511127385771028618, 14755502041894115317, 9806346309586473535, 5880260960930089738, 191119811429922])); - let mut poseidon_digest = MNT6PoseidonHash::init(None); - let input = MNT6753Fr::from_str("1").unwrap(); - poseidon_digest.update(input); - let output = poseidon_digest.finalize(); - assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); - } - - #[test] - fn test_poseidon_hash_mnt6_three_element() { - let expected_output = MNT6753Fr::new(BigInteger768([13800884891843937189, 3814452749758584714, 14612220153016028606, 15886322817426727111, 12444362646204085653, 5214641378156871899, 4248022398370599899, 5982332416470364372, 3842784910369906888, 11445718704595887413, 5723531295320926061, 101830932453997])); - let mut poseidon_digest = MNT6PoseidonHash::init(None); + field_based_hash_test::( + None, + generate_inputs(1), + expected_output + ); - for i in 1..=3{ - let input = MNT6753Fr::from(i as u64); - poseidon_digest.update(input); - } + let expected_output = MNT6753Fr::new(BigInteger768([8195238283171732026, 13694263410588344527, 1885103367289967816, 17142467091011072910, 13844754763865913168, 14332001103319040991, 8911700442280604823, 6452872831806760781, 17467681867740706391, 5384727593134901588, 2343350281633109128, 244405261698305])); + field_based_hash_test::( + None, + generate_inputs(2), + expected_output + ); - let output = poseidon_digest.finalize(); - assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); + let expected_output = MNT6753Fr::new(BigInteger768([13800884891843937189, 3814452749758584714, 14612220153016028606, 15886322817426727111, 12444362646204085653, 5214641378156871899, 4248022398370599899, 5982332416470364372, 3842784910369906888, 11445718704595887413, 5723531295320926061, 101830932453997])); + field_based_hash_test::( + None, + generate_inputs(3), + expected_output + ); + + algebraic_sponge_test::( + generate_inputs(5), + vec![ + MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), + MNT6753Fr::new(BigInteger768([893755365716394547, 9594068362757650017, 10451094618402356015, 6337497625726267689, 4160278191670220893, 6010491150125800070, 828252792235881440, 2673899143833542881, 13863607618619424503, 10731000306034932792, 12767597931406600360, 152088456622435])), + MNT6753Fr::new(BigInteger768([2814201016530476081, 8511720540093155210, 4852589771558571678, 13110129496171929816, 4735221329350745796, 12663409230803838109, 11568212364226125976, 1693070022169342918, 2888127900540921339, 4204338349274483900, 15311382501005232626, 438220753471979])), + MNT6753Fr::new(BigInteger768([1775158153332815483, 2026417705400082199, 11123169942942274855, 14330277722886619530, 7836191979464539572, 4865965751577341882, 16998150036867812011, 2739207342391276882, 4247579097230352822, 6464967486406868296, 10032824663714337053, 463362661909267])), + MNT6753Fr::new(BigInteger768([17595647052173133652, 5444801609492079542, 17111761943624358533, 9849391399095026693, 263233265735065436, 1281866738651078101, 2333944581006551597, 13500573177506341637, 10203063908384511927, 15054379420590094900, 13913006388276371623, 451783078041284])) + ] + ); } use algebra::{ @@ -326,25 +344,42 @@ mod test { #[test] fn test_poseidon_hash_bn382_fr() { let expected_output = BN382Fr::new(BigInteger384([5374955110091081208, 9708994766202121080, 14988884941712225891, 5210165913215347951, 13114182334648522197, 392522167697949297])); - - let mut digest = BN382FrPoseidonHash::init(None); - digest.update(BN382Fr::from_str("1").unwrap()); - digest.update(BN382Fr::from_str("2").unwrap()); - let output = digest.finalize(); - - assert_eq!(output, expected_output, "Outputs do not match for BN382Fr"); + field_based_hash_test::( + None, + generate_inputs(2), + expected_output + ); + + algebraic_sponge_test::( + generate_inputs(5), + vec![ + BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), + BN382Fr::new(BigInteger384([696581192457039113, 7735026456746748023, 2858087404435942973, 8551026292503659964, 10649071471792522052, 1622107112684056397])), + BN382Fr::new(BigInteger384([13847543644949650964, 4311663852800204305, 4992676739644232980, 4027896082677996619, 12253082643656956806, 534636992911167858])), + BN382Fr::new(BigInteger384([13260537455622274637, 17371511872105869645, 1623345855391475943, 1872797973978834237, 7609952746869694608, 847112821092614604])), + BN382Fr::new(BigInteger384([2836595273011902376, 5748666575747773318, 13745164138914401597, 11231420449817912461, 3298276789500282573, 1513701281573365844])) + ] + ); } #[test] fn test_poseidon_hash_bn382_fq() { let expected_output = BN382Fq::new(BigInteger384([10704305393280846886, 13510271104066299406, 8759721062701909552, 14597420682011858322, 7770486455870140465, 1389855295932765543])); - - let mut digest = BN382FqPoseidonHash::init(None); - digest.update(BN382Fq::from_str("1").unwrap()); - digest.update(BN382Fq::from_str("2").unwrap()); - let output = digest.finalize(); - - assert_eq!(output, expected_output, "Outputs do not match for BN382Fq"); + field_based_hash_test::( + None, + generate_inputs(2), + expected_output + ); + + algebraic_sponge_test::( + generate_inputs(5), + vec![ + BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), + BN382Fq::new(BigInteger384([4268335443493036543, 5752606093574636763, 7217511812669325408, 5182020843125294140, 5400661559267345372, 2261580635543305540])), + BN382Fq::new(BigInteger384([1487056021032845247, 4971413697289841114, 829985713515651434, 17668516547215117574, 6183480290866190120, 2494711740844925696])), + BN382Fq::new(BigInteger384([12440731074295045789, 13776548474636848476, 9611723257742392848, 14113646477500207966, 2479383220929757679, 2462018425115041259])), + BN382Fq::new(BigInteger384([13447602317280700149, 7333172335365879673, 3401105980077026956, 7168529825556409731, 18013175927097546368, 369466729188096152])), + ] + ); } - } \ No newline at end of file diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index f8ca20945..8475d57e3 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,13 +1,6 @@ #[macro_use] extern crate bench_utils; -#[cfg(any( - feature = "commitment", - feature = "merkle_tree", - feature = "prf", - feature = "signature", - feature = "vrf" -))] #[macro_use] extern crate derivative; diff --git a/r1cs/gadgets/crypto/src/crh/mod.rs b/r1cs/gadgets/crypto/src/crh/mod.rs index 6546d24bc..1f38ab7ca 100644 --- a/r1cs/gadgets/crypto/src/crh/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/mod.rs @@ -1,4 +1,6 @@ -use algebra::Field; +use algebra::{ + Field, PrimeField +}; use std::fmt::Debug; use primitives::crh::{ @@ -17,6 +19,7 @@ pub use self::sbox::*; pub mod poseidon; pub use self::poseidon::*; +use primitives::AlgebraicSponge; pub trait FixedLengthCRHGadget: Sized { type OutputGadget: EqGadget @@ -55,4 +58,105 @@ pub trait FieldHasherGadget< cs: CS, personalization: Option<&[HG::DataGadget]> ) -> Result; +} + +pub trait AlgebraicSpongeGadget, ConstraintF: PrimeField>: Sized { + type DataGadget: FieldGadget; + + fn new>(cs: CS) -> Result; + + fn enforce_absorb>( + &mut self, + cs: CS, + input: &[Self::DataGadget], + ) -> Result<(), SynthesisError>; + + fn enforce_squeeze>( + &self, + cs: CS, + num: usize, + ) -> Result, SynthesisError>; +} + +#[cfg(test)] +mod test { + use algebra::PrimeField; + use primitives::{ + FieldBasedHash, AlgebraicSponge + }; + use crate::{ + FieldBasedHashGadget, AlgebraicSpongeGadget, + }; + use r1cs_std::{ + fields::fp::FpGadget, + test_constraint_system::TestConstraintSystem, + alloc::AllocGadget, + }; + use r1cs_core::ConstraintSystem; + + pub(crate) fn field_based_hash_gadget_native_test< + F: PrimeField, + H: FieldBasedHash, + HG: FieldBasedHashGadget> + >(inputs: Vec) + { + let mut cs = TestConstraintSystem::::new(); + + let primitive_result = { + let mut digest = H::init(None); + inputs.iter().for_each(|elem| { digest.update(*elem);}); + digest.finalize() + }; + + let mut input_gadgets = Vec::with_capacity(inputs.len()); + inputs.into_iter().enumerate().for_each(|(i, elem)|{ + let elem_gadget = HG::DataGadget::alloc( + cs.ns(|| format!("alloc input {}", i)), + || Ok(elem) + ).unwrap(); + input_gadgets.push(elem_gadget); + }); + + let gadget_result = HG::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + input_gadgets.as_slice() + ).unwrap(); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); + } + + pub(crate) fn algebraic_sponge_gadget_native_test< + F: PrimeField, + H: AlgebraicSponge, + HG: AlgebraicSpongeGadget> + >(inputs: Vec) + { + let mut cs = TestConstraintSystem::::new(); + + let mut primitive_sponge = H::new(); + primitive_sponge.absorb(inputs.clone()); + + let mut input_gadgets = Vec::with_capacity(inputs.len()); + inputs.iter().enumerate().for_each(|(i, elem)|{ + let elem_gadget = HG::DataGadget::alloc( + cs.ns(|| format!("alloc input {}", i)), + || Ok(elem.clone()) + ).unwrap(); + input_gadgets.push(elem_gadget); + }); + + let mut sponge_gadget = HG::new(cs.ns(|| "new poseidon sponge")).unwrap(); + sponge_gadget.enforce_absorb(cs.ns(|| "absorb inputs"), input_gadgets.as_slice()).unwrap(); + + for i in 0..inputs.len() { + let output_gadgets = sponge_gadget.enforce_squeeze( + cs.ns(|| format!("squeeze {} field elements", i + 1)), + i + 1 + ).unwrap().iter().map(|fe_gadget| fe_gadget.value.unwrap()).collect::>(); + assert_eq!(output_gadgets, primitive_sponge.squeeze(i + 1)); + } + + assert!(cs.is_satisfied()); + } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index c5269cf39..12e3ecaaa 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -29,6 +29,7 @@ pub mod bn382; #[cfg(feature = "bn_382")] pub use self::bn382::*; use primitives::PoseidonSBox; +use crate::AlgebraicSpongeGadget; pub struct PoseidonHashGadget < @@ -38,7 +39,9 @@ pub struct PoseidonHashGadget SBG: SBoxGadget, > { - _field: PhantomData, + state: Vec>, + pending: Vec>, + _parameters: PhantomData

, _sbox: PhantomData, _sbox_gadget: PhantomData, @@ -108,7 +111,6 @@ impl< (*d).add_constant_in_place(cs.ns(|| format!("add_constant_2_{}", round_cst_idx)), &rc)?; round_cst_idx += 1; } - } // Second full rounds @@ -260,180 +262,119 @@ impl FieldBasedHashGadget AlgebraicSpongeGadget, ConstraintF> +for PoseidonHashGadget + where + ConstraintF: PrimeField, + P: PoseidonParameters, + SB: PoseidonSBox

, + SBG: SBoxGadget, +{ + type DataGadget = FpGadget; - let mut rng = &mut thread_rng(); - let mut cs = TestConstraintSystem::::new(); + fn new>(mut cs: CS) -> Result { + assert_eq!(P::T - P::R, 1, "The assumption that the capacity is one field element is not satisfied."); - let mut vec_elem_4753 = Vec::new(); - let v1 = MNT4753Fr::rand(&mut rng); - let v2 = MNT4753Fr::rand(&mut rng); - vec_elem_4753.push(v1); - vec_elem_4753.push(v2); + let mut state = Vec::new(); + for i in 0..P::T { + let elem = FpGadget::::from_value( + cs.ns(|| format!("hardcode_state_{}",i)), + &P::AFTER_ZERO_PERM[i] + ); + state.push(elem); + } - let primitive_result = { - let mut digest = MNT4PoseidonHash::init(None); - vec_elem_4753.into_iter().for_each(|elem| { digest.update(elem);}); - digest.finalize() - }; + Ok(Self { + state, + pending: Vec::with_capacity(P::R), + _parameters: PhantomData, + _sbox: PhantomData, + _sbox_gadget: PhantomData, + }) + } - let v1_gadget = Mnt4FieldGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); - let v2_gadget = Mnt4FieldGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + fn enforce_absorb>( + &mut self, + mut cs: CS, + elems: &[Self::DataGadget] + ) -> Result<(), SynthesisError> { + elems.iter().enumerate().map(|(i, f)| { + self.pending.push(f.clone()); + if self.pending.len() == P::R { + // add the elements to the state vector. Add rate elements + for (j, (input, state)) in self.pending.iter().zip(self.state.iter_mut()).enumerate() { + state.add_in_place(cs.ns(|| format!("add_input_{}_{}_to_state", i, j)), input)?; + } + // apply permutation after adding the input vector + Self::poseidon_perm(cs.ns(|| format!("poseidon_perm_{}", i)), &mut self.state)?; + + self.pending.clear(); + } + Ok(()) + }).collect::>()?; + Ok(()) + } - let mut vec_elem_gadget = Vec::new(); - vec_elem_gadget.push(v1_gadget); - vec_elem_gadget.push(v2_gadget); + fn enforce_squeeze>( + &self, + mut cs: CS, + num: usize + ) -> Result, SynthesisError> { + let mut state = self.state.clone(); + for (i, (input, state)) in self.pending.iter().zip(state.iter_mut()).enumerate() { + state.add_in_place(cs.ns(|| format!("add_input_{}_to_state", i)), input)?; + } + let mut output = Vec::with_capacity(num); + for i in 0..num { + Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut state)?; + output.push(state[0].clone()) + } + Ok(output) + } +} - let gadget_result = - MNT4PoseidonHashGadget::check_evaluation_gadget( - cs.ns(||"check_poseidon_gadget"), - vec_elem_gadget.as_slice()).unwrap(); +#[cfg(test)] +mod test { + use crate::{ + MNT4PoseidonHashGadget, MNT6PoseidonHashGadget, + BN382FqPoseidonHashGadget, BN382FrPoseidonHashGadget, + }; - println!("number of constraints total: {}", cs.num_constraints()); + use algebra::fields::PrimeField; + use crate::crh::test::{ + field_based_hash_gadget_native_test, algebraic_sponge_gadget_native_test + }; - assert_eq!(primitive_result, gadget_result.value.unwrap()); - assert!(cs.is_satisfied()); + fn generate_inputs(num: usize) -> Vec{ + let mut inputs = Vec::with_capacity(num); + for i in 1..=num { + let input = F::from(i as u32); + inputs.push(input); + } + inputs } #[test] - fn crh_mnt6_753_primitive_gadget_test() { - - let mut rng = &mut thread_rng(); - let mut cs = TestConstraintSystem::::new(); - - let mut vec_elem_6753 = Vec::new(); - let v1 = MNT6753Fr::rand(&mut rng); - let v2 = MNT6753Fr::rand(&mut rng); - vec_elem_6753.push(v1); - vec_elem_6753.push(v2); - - let primitive_result = { - let mut digest = MNT6PoseidonHash::init(None); - vec_elem_6753.into_iter().for_each(|elem| { digest.update(elem); }); - digest.finalize() - }; - - let v1_gadget = Mnt6FieldGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); - let v2_gadget = Mnt6FieldGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); - - let mut vec_elem_gadget = Vec::new(); - vec_elem_gadget.push(v1_gadget); - vec_elem_gadget.push(v2_gadget); - - let gadget_result = - MNT6PoseidonHashGadget::check_evaluation_gadget( - cs.ns(||"check_poseidon_gadget"), - vec_elem_gadget.as_slice()).unwrap(); - - println!("number of constraints total: {}", cs.num_constraints()); - - assert_eq!(primitive_result, gadget_result.value.unwrap()); - assert!(cs.is_satisfied()); + fn poseidon_mnt4_753_gadget_native_test() { + field_based_hash_gadget_native_test::<_, _, MNT4PoseidonHashGadget>(generate_inputs(2)); + algebraic_sponge_gadget_native_test::<_, _, MNT4PoseidonHashGadget>(generate_inputs(5)); } #[test] - fn crh_bn382_fr_primitive_gadget_test() { - - let mut rng = &mut thread_rng(); - let mut cs = TestConstraintSystem::::new(); - - let mut vec_elem = Vec::new(); - let v1 = BN382Fr::rand(&mut rng); - let v2 = BN382Fr::rand(&mut rng); - vec_elem.push(v1); - vec_elem.push(v2); - - let primitive_result = { - let mut digest = BN382FrPoseidonHash::init(None); - vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); - digest.finalize() - }; - - let v1_gadget = BN382FrGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); - let v2_gadget = BN382FrGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); - - let mut vec_elem_gadget = Vec::new(); - vec_elem_gadget.push(v1_gadget); - vec_elem_gadget.push(v2_gadget); - - let gadget_result = - BN382FrPoseidonHashGadget::check_evaluation_gadget( - cs.ns(||"check_poseidon_gadget"), - vec_elem_gadget.as_slice()).unwrap(); - - println!("number of constraints total: {}", cs.num_constraints()); - - assert_eq!(primitive_result, gadget_result.value.unwrap()); - assert!(cs.is_satisfied()); + fn poseidon_mnt6_753_gadget_native_test() { + field_based_hash_gadget_native_test::<_, _, MNT6PoseidonHashGadget>(generate_inputs(2)); + algebraic_sponge_gadget_native_test::<_, _, MNT6PoseidonHashGadget>(generate_inputs(5)); } #[test] - fn crh_bn382_fq_primitive_gadget_test() { - - let mut rng = &mut thread_rng(); - let mut cs = TestConstraintSystem::::new(); - - let mut vec_elem = Vec::new(); - let v1 = BN382Fq::rand(&mut rng); - let v2 = BN382Fq::rand(&mut rng); - vec_elem.push(v1); - vec_elem.push(v2); - - let primitive_result = { - let mut digest = BN382FqPoseidonHash::init(None); - vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); - digest.finalize() - }; - - let v1_gadget = BN382FqGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); - let v2_gadget = BN382FqGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); - - let mut vec_elem_gadget = Vec::new(); - vec_elem_gadget.push(v1_gadget); - vec_elem_gadget.push(v2_gadget); - - let gadget_result = - BN382FqPoseidonHashGadget::check_evaluation_gadget( - cs.ns(||"check_poseidon_gadget"), - vec_elem_gadget.as_slice()).unwrap(); - - println!("number of constraints total: {}", cs.num_constraints()); + fn poseidon_bn382_fr_gadget_native_test() { + field_based_hash_gadget_native_test::<_, _, BN382FrPoseidonHashGadget>(generate_inputs(2)); + algebraic_sponge_gadget_native_test::<_, _, BN382FrPoseidonHashGadget>(generate_inputs(5)); + } - assert_eq!(primitive_result, gadget_result.value.unwrap()); - assert!(cs.is_satisfied()); + #[test] + fn poseidon_bn382_fq_gadget_native_test() { + field_based_hash_gadget_native_test::<_, _, BN382FqPoseidonHashGadget>(generate_inputs(2)); + algebraic_sponge_gadget_native_test::<_, _, BN382FqPoseidonHashGadget>(generate_inputs(5)); } } \ No newline at end of file From 5df4e63cb5c7a28fe25f20da48b2db6543de2aae Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Mon, 11 Jan 2021 18:19:11 +0100 Subject: [PATCH 36/63] Changed squeeze logic --- primitives/src/crh/mod.rs | 15 +++----- primitives/src/crh/poseidon/mod.rs | 41 ++++----------------- r1cs/gadgets/crypto/src/crh/mod.rs | 2 +- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 9 ++--- 4 files changed, 18 insertions(+), 49 deletions(-) diff --git a/primitives/src/crh/mod.rs b/primitives/src/crh/mod.rs index 1d216a186..0b0b70b6d 100644 --- a/primitives/src/crh/mod.rs +++ b/primitives/src/crh/mod.rs @@ -116,11 +116,8 @@ pub trait AlgebraicSponge: Clone { fn new() -> Self; /// Update the sponge with `elems` fn absorb(&mut self, elems: Vec); - /// Output `num` field elements from the sponge. This function - /// is idempotent and calling it multiple times will result - /// in the same outputs, unless more absorbing are performed - /// in between the calls. - fn squeeze(&self, num: usize) -> Vec; + /// Output `num` field elements from the sponge. + fn squeeze(&mut self, num: usize) -> Vec; } #[cfg(test)] @@ -178,7 +175,7 @@ mod test { pub(crate) fn algebraic_sponge_test, F: PrimeField>( to_absorb: Vec, - expected_squeezes: Vec + expected_squeeze: F ) { let mut sponge = H::new(); @@ -186,10 +183,8 @@ mod test { // Absorb all field elements sponge.absorb(to_absorb); - // Squeeze and check the outputs - for i in 0..expected_squeezes.len() { - assert_eq!(&expected_squeezes[..i + 1], &sponge.squeeze(i + 1)[..]); - } + // Squeeze and check the output + assert_eq!(expected_squeeze, sponge.squeeze(1)[0]); } #[ignore] diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 37135deae..9bf51b2b9 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -227,15 +227,14 @@ impl AlgebraicSponge for PoseidonHash }) } - fn squeeze(&self, num: usize) -> Vec { - let mut state = self.state.clone(); - for (input, s) in self.pending.iter().zip(state.iter_mut()) { + fn squeeze(&mut self, num: usize) -> Vec { + for (input, s) in self.pending.iter().zip(self.state.iter_mut()) { *s += input; } let mut output = Vec::with_capacity(num); for _ in 0..num { - Self::poseidon_perm(&mut state); - output.push(state[0].clone()); + Self::poseidon_perm(&mut self.state); + output.push(self.state[0].clone()); } output } @@ -288,13 +287,7 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - vec![ - MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), - MNT4753Fr::new(BigInteger768([16127953875295592987, 11894863219027726126, 17701631661641187911, 14870672795897948467, 12477792521878046393, 7933118744616181152, 16504185330957910903, 4440754255912752398, 2147815826017548215, 15556058995384616380, 7316328326052908756, 488587201854075])), - MNT4753Fr::new(BigInteger768([17093615125500557324, 5853740299004434536, 14185517698974334849, 15081129818867394374, 4393775450585412195, 15317350057972385858, 602096567370343479, 171645566249469757, 213587553721144028, 16770187529782220214, 10656253922486106039, 183907258171817])), - MNT4753Fr::new(BigInteger768([12712297803466521417, 5718281485803573501, 13963200307320285636, 13279387328772122744, 11400771971860800684, 18129978631072081884, 16152730030736233432, 4443584430842639200, 10168547976596639262, 8852760702638429316, 6245616001490582246, 290914933918621])), - MNT4753Fr::new(BigInteger768([10000480287694253354, 5873338108557543580, 14250396374254092226, 15940814885061001617, 7624733801679967429, 10913153568558026344, 10086885331318146225, 5264350148957133820, 9338271530149930761, 15261863060094932371, 15830626088040155644, 456905335294658])) - ] + MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), ); } @@ -323,13 +316,7 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - vec![ - MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), - MNT6753Fr::new(BigInteger768([893755365716394547, 9594068362757650017, 10451094618402356015, 6337497625726267689, 4160278191670220893, 6010491150125800070, 828252792235881440, 2673899143833542881, 13863607618619424503, 10731000306034932792, 12767597931406600360, 152088456622435])), - MNT6753Fr::new(BigInteger768([2814201016530476081, 8511720540093155210, 4852589771558571678, 13110129496171929816, 4735221329350745796, 12663409230803838109, 11568212364226125976, 1693070022169342918, 2888127900540921339, 4204338349274483900, 15311382501005232626, 438220753471979])), - MNT6753Fr::new(BigInteger768([1775158153332815483, 2026417705400082199, 11123169942942274855, 14330277722886619530, 7836191979464539572, 4865965751577341882, 16998150036867812011, 2739207342391276882, 4247579097230352822, 6464967486406868296, 10032824663714337053, 463362661909267])), - MNT6753Fr::new(BigInteger768([17595647052173133652, 5444801609492079542, 17111761943624358533, 9849391399095026693, 263233265735065436, 1281866738651078101, 2333944581006551597, 13500573177506341637, 10203063908384511927, 15054379420590094900, 13913006388276371623, 451783078041284])) - ] + MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), ); } @@ -352,13 +339,7 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - vec![ - BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), - BN382Fr::new(BigInteger384([696581192457039113, 7735026456746748023, 2858087404435942973, 8551026292503659964, 10649071471792522052, 1622107112684056397])), - BN382Fr::new(BigInteger384([13847543644949650964, 4311663852800204305, 4992676739644232980, 4027896082677996619, 12253082643656956806, 534636992911167858])), - BN382Fr::new(BigInteger384([13260537455622274637, 17371511872105869645, 1623345855391475943, 1872797973978834237, 7609952746869694608, 847112821092614604])), - BN382Fr::new(BigInteger384([2836595273011902376, 5748666575747773318, 13745164138914401597, 11231420449817912461, 3298276789500282573, 1513701281573365844])) - ] + BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), ); } @@ -373,13 +354,7 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - vec![ - BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), - BN382Fq::new(BigInteger384([4268335443493036543, 5752606093574636763, 7217511812669325408, 5182020843125294140, 5400661559267345372, 2261580635543305540])), - BN382Fq::new(BigInteger384([1487056021032845247, 4971413697289841114, 829985713515651434, 17668516547215117574, 6183480290866190120, 2494711740844925696])), - BN382Fq::new(BigInteger384([12440731074295045789, 13776548474636848476, 9611723257742392848, 14113646477500207966, 2479383220929757679, 2462018425115041259])), - BN382Fq::new(BigInteger384([13447602317280700149, 7333172335365879673, 3401105980077026956, 7168529825556409731, 18013175927097546368, 369466729188096152])), - ] + BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), ); } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/mod.rs b/r1cs/gadgets/crypto/src/crh/mod.rs index 1f38ab7ca..9f13c6c09 100644 --- a/r1cs/gadgets/crypto/src/crh/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/mod.rs @@ -72,7 +72,7 @@ pub trait AlgebraicSpongeGadget, ConstraintF: Pr ) -> Result<(), SynthesisError>; fn enforce_squeeze>( - &self, + &mut self, cs: CS, num: usize, ) -> Result, SynthesisError>; diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index 12e3ecaaa..d62b10b4a 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -316,18 +316,17 @@ for PoseidonHashGadget } fn enforce_squeeze>( - &self, + &mut self, mut cs: CS, num: usize ) -> Result, SynthesisError> { - let mut state = self.state.clone(); - for (i, (input, state)) in self.pending.iter().zip(state.iter_mut()).enumerate() { + for (i, (input, state)) in self.pending.iter().zip(self.state.iter_mut()).enumerate() { state.add_in_place(cs.ns(|| format!("add_input_{}_to_state", i)), input)?; } let mut output = Vec::with_capacity(num); for i in 0..num { - Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut state)?; - output.push(state[0].clone()) + Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut self.state)?; + output.push(self.state[0].clone()) } Ok(output) } From fb60c471bf353ee610d7fa1dd07a7d360c7e7056 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 12 Jan 2021 02:12:46 +0200 Subject: [PATCH 37/63] Unit-tests and small bugfixes --- .../src/fft/domain/basic_radix_2_domain.rs | 28 ++++++----- .../src/fft/domain/mixed_radix_2_domain.rs | 33 ++++++------ algebra-utils/src/fft/domain/test.rs | 11 +++- algebra-utils/src/msm/variable_base.rs | 50 +++++++++++++++---- 4 files changed, 84 insertions(+), 38 deletions(-) diff --git a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs index 8b3e0d721..f10e17e2a 100644 --- a/algebra-utils/src/fft/domain/basic_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/basic_radix_2_domain.rs @@ -94,18 +94,7 @@ impl BasicRadix2Domain { fn best_fft(a: &mut [F], worker: &Worker, omega: F, log_n: u32) { #[cfg(feature = "gpu")] if get_gpu_min_length() <= 1 << log_n { - match get_kernels() { - Ok(kernels) => { - match kernels[0].radix_fft(a, &omega, log_n) { - Ok(_) => {}, - Err(error) => { panic!("{}", error); } - } - }, - Err(error) => { - panic!("{}", error); - } - } - return; + return Self::gpu_fft(a, omega, log_n); } let log_cpus = worker.log_num_cpus(); @@ -117,6 +106,21 @@ impl BasicRadix2Domain { } } + #[cfg(feature = "gpu")] + pub (crate) fn gpu_fft(a: &mut [F], omega: F, log_n: u32) { + match get_kernels() { + Ok(kernels) => { + match kernels[0].radix_fft(a, &omega, log_n) { + Ok(_) => {}, + Err(error) => { panic!("{}", error); } + } + }, + Err(error) => { + panic!("{}", error); + } + } + } + pub(crate) fn serial_fft(a: &mut [F], omega: F, log_n: u32) { #[inline] fn bitreverse(mut n: u32, l: u32) -> u32 { diff --git a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs index 63972b1d4..3fed8a2c8 100644 --- a/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs +++ b/algebra-utils/src/fft/domain/mixed_radix_2_domain.rs @@ -355,29 +355,34 @@ impl MixedRadix2Domain { }); } + + #[cfg(feature = "gpu")] + pub(crate) fn mixed_gpu_fft(a: &mut [F], omega: F, log_n: u32) { + match get_kernels() { + Ok(kernels) => { + match kernels[0].radix_fft(a, &omega, log_n) { + Ok(_) => {}, + Err(error) => { panic!("{}", error); } + } + }, + Err(error) => { + panic!("{}", error); + } + } + } + fn best_fft(a: &mut [F], _worker: &Worker, omega: F, log_n: u32) { #[cfg(feature = "gpu")] if get_gpu_min_length() <= 1 << log_n { - match get_kernels() { - Ok(kernels) => { - match kernels[0].radix_fft(a, &omega, log_n) { - Ok(_) => {}, - Err(error) => { panic!("{}", error); } - } - }, - Err(error) => { - panic!("{}", error); - } - } - return; + return Self::mixed_gpu_fft(a, omega, log_n); } let log_cpus = _worker.log_num_cpus(); if log_n <= log_cpus { - Self::mixed_serial_fft(a, omega, log_n); + return Self::mixed_serial_fft(a, omega, log_n); } else { - Self::mixed_parallel_fft(a, _worker, omega, log_n, log_cpus); + return Self::mixed_parallel_fft(a, _worker, omega, log_n, log_cpus); } } } diff --git a/algebra-utils/src/fft/domain/test.rs b/algebra-utils/src/fft/domain/test.rs index a13515990..91d3a02ca 100644 --- a/algebra-utils/src/fft/domain/test.rs +++ b/algebra-utils/src/fft/domain/test.rs @@ -53,7 +53,7 @@ fn fft_composition() { } #[test] -fn parallel_fft_consistency() { +fn fft_consistency() { fn test_consistency(rng: &mut R) { let worker = Worker::new(); @@ -64,17 +64,26 @@ fn parallel_fft_consistency() { let mut v1 = (0..d).map(|_| E::Fr::rand(rng)).collect::>(); let mut v2 = v1.clone(); + #[cfg(feature = "gpu")] + let mut v3 = v1.clone(); + let domain = get_best_evaluation_domain::(v1.len()).unwrap(); for log_cpus in log_d..min(log_d + 1, 3) { if log_d < ::Params::TWO_ADICITY{ BasicRadix2Domain::parallel_fft(&mut v1, &worker, domain.group_gen(), log_d, log_cpus); BasicRadix2Domain::serial_fft(&mut v2, domain.group_gen(), log_d); + #[cfg(feature = "gpu")] + BasicRadix2Domain::gpu_fft(&mut v3, domain.group_gen(), log_d); } else { MixedRadix2Domain::mixed_parallel_fft(&mut v1, &worker, domain.group_gen(), log_d, log_cpus); MixedRadix2Domain::mixed_serial_fft(&mut v2, domain.group_gen(), log_d); + #[cfg(feature = "gpu")] + MixedRadix2Domain::mixed_gpu_fft(&mut v3, domain.group_gen(), log_d); } assert_eq!(v1, v2); + #[cfg(feature = "gpu")] + assert_eq!(v1, v3); } } } diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 04806c3fb..4d8a7888d 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -11,6 +11,7 @@ use crossbeam::thread; pub struct VariableBaseMSM; impl VariableBaseMSM { + pub fn multi_scalar_mul_affine( bases: &[G], scalars: &[::BigInt], @@ -92,7 +93,7 @@ impl VariableBaseMSM { }) + lowest } - fn msm_inner( + pub fn multi_scalar_mul_mixed( bases: &[G], scalars: &[::BigInt], ) -> G::Projective { @@ -167,6 +168,21 @@ impl VariableBaseMSM { }) + lowest } + fn msm_inner_cpu( + bases: &[G], + scalars: &[::BigInt] + ) -> G::Projective + where + G: AffineCurve, + G::Projective: ProjectiveCurve + { + #[cfg(not(feature = "msm_affine"))] + return Self::multi_scalar_mul_mixed(bases, scalars); + + #[cfg(feature = "msm_affine")] + return Self::multi_scalar_mul_affine(bases, scalars); + } + #[cfg(feature = "gpu")] fn msm_inner_gpu( bases: &[G], @@ -224,7 +240,7 @@ impl VariableBaseMSM { if cpu_n > 0 { threads.push(s.spawn( move |_| -> Result { - let acc = Self::multi_scalar_mul_affine(cpu_bases, cpu_scalars); + let acc = Self::msm_inner_cpu(cpu_bases, cpu_scalars); Ok(acc) } )) @@ -251,7 +267,7 @@ impl VariableBaseMSM { ) -> G::Projective { #[cfg(not(feature = "gpu"))] - return Self::multi_scalar_mul_affine(bases, scalars); + return Self::msm_inner_cpu(bases, scalars); #[cfg(feature = "gpu")] return Self::msm_inner_gpu(bases, scalars); @@ -281,7 +297,7 @@ mod test { #[test] fn test_all_variants() { - const SAMPLES: usize = 1 << 10; + const SAMPLES: usize = 1 << 12; let mut rng = XorShiftRng::seed_from_u64(234872845u64); @@ -293,16 +309,22 @@ mod test { .collect::>(); let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let fast = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + let mixed = VariableBaseMSM::multi_scalar_mul_mixed(g.as_slice(), v.as_slice()); let affine = VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); - assert_eq!(naive, fast); - assert_eq!(naive, affine) + #[cfg(feature = "gpu")] + let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + + assert_eq!(naive, mixed); + assert_eq!(naive, affine); + + #[cfg(feature = "gpu")] + assert_eq!(naive, gpu); } #[test] fn test_with_unequal_numbers() { - const SAMPLES: usize = 1 << 10; + const SAMPLES: usize = 1 << 12; let mut rng = XorShiftRng::seed_from_u64(234872845u64); @@ -314,10 +336,16 @@ mod test { .collect::>(); let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let fast = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + let mixed = VariableBaseMSM::multi_scalar_mul_mixed(g.as_slice(), v.as_slice()); let affine = VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); - assert_eq!(naive, fast); - assert_eq!(naive, affine) + #[cfg(feature = "gpu")] + let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + + assert_eq!(naive, mixed); + assert_eq!(naive, affine); + + #[cfg(feature = "gpu")] + assert_eq!(naive, gpu); } } From 7b6376ca94b9947b613f5c8d1bf5240071f5848d Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 12 Jan 2021 02:16:08 +0200 Subject: [PATCH 38/63] Local development cargo settings --- Cargo.toml | 9 +++++++++ algebra-utils/Cargo.toml | 8 +++++--- primitives/Cargo.toml | 1 - 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cffc64d5b..84c085af7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,12 @@ lto = "thin" incremental = true debug-assertions = true debug = true + +# Uncomment these lines for local development paths + +# [patch.'https://github.com/HorizenOfficial/ginger-lib'] +# algebra = { path = './algebra' } + +# [patch.'https://github.com/HorizenOfficial/ginger-algebra-ocl'] +# algebra-kernels = { path = '../ginger-algebra-ocl/algebra-kernels' } +# algebra-cl-gen = { path = '../ginger-algebra-ocl/algebra-cl-gen' } diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 9b48b6d6f..fbc605ad5 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -36,14 +36,16 @@ blake2 = "0.7" criterion = "0.3.3" rand_xorshift = { version = "0.2" } paste = "1.0" -algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub", "mnt4_753", "mnt6_753"] } -algebra-utils = { path = "../algebra-utils", features = [ "parallel", "fft" ] } -algebra-kernels = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", features = ["bn_382", "tweedle", "bls12_381", "jubjub"] } bench-utils = { path = "../bench-utils" } +algebra-utils = { path = "../algebra-utils", features = ["dev"] } [features] +default = [ "parallel", "fft", "msm_affiine" ] +dev = [ "bls12_381", "bn_382", "tweedle", "mnt4_753", "mnt6_753" ] + parallel = [ "rayon" ] fft = [] +msm_affiine = [] gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] llvm_asm = [ "algebra/llvm_asm" ] diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index dc298abf4..d11f248e8 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -100,4 +100,3 @@ name = "poseidon_mht" path = "benches/crypto_primitives/poseidon_mht.rs" harness = false required-features = ["merkle_tree", "mnt4_753", "mnt6_753"] - From 7a491d115bdbda009062f635a633f6696cd8cdc7 Mon Sep 17 00:00:00 2001 From: Marcelo Kaihara Date: Tue, 12 Jan 2021 17:04:28 +0100 Subject: [PATCH 39/63] msm for cpu with optimized window sizes --- algebra-utils/src/msm/variable_base.rs | 380 ++++++++++++++++++++++--- 1 file changed, 340 insertions(+), 40 deletions(-) diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 4d8a7888d..64bcba470 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -1,6 +1,8 @@ use algebra::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, ProjectiveCurve}; use rayon::prelude::*; +use std::any::TypeId; + #[cfg(feature = "gpu")] use algebra_kernels::msm::{get_cpu_utilization, get_kernels, get_gpu_min_length}; #[cfg(feature = "gpu")] @@ -12,15 +14,225 @@ pub struct VariableBaseMSM; impl VariableBaseMSM { - pub fn multi_scalar_mul_affine( + // Function that recodes the scalars into SD numbers + // The output is a vector + pub fn recode_sd( + scalar: &::BigInt, + c: usize + ) -> Vec { + + let num_bits = + ::Params::MODULUS_BITS as usize; + + let window_starts: Vec<_> = (0..num_bits).step_by(c).collect(); + + let mut vec_coeff = Vec::new(); + + window_starts.iter().rev().for_each(|x| { + let mut scal = (*scalar).clone(); + scal.divn(*x as u32); + // We mod the remaining bits by the window size. + let a = scal.as_ref()[0] % (1 << c); + vec_coeff.push(a as i64); + }); + + for idx in (0..vec_coeff.len()).rev() { + if vec_coeff[idx] >= (1 << (c-1)) { + vec_coeff[idx] -= 1 << c; + if idx!= 0 { + vec_coeff[idx-1] += 1; + } + } + } + + // last element is the least significant digit + return vec_coeff; + + } + + // Recodes in SD the portions of the scalar divided in c bits + // Takes as input the carry_in and generates the vector of SD digits corresponding to + // the processing chunk and the carry_out + // For example: for 4 cores, it takes the carry_in and + // generates carry_out, a_(i+3), a_(i+2), a_(i+1), a_i + #[inline] + pub fn recode_sd_chunk( + scalar: &::BigInt, + c: usize, + chunk_pos: usize, + num_cores: usize, + vec_coeff: &mut Vec, + carry_in: &mut i64 + ) { + + // starting bit position of the chunk + let start_w_bit = chunk_pos * (c * num_cores); + + for i in 0..num_cores { + let windows_starts = start_w_bit + i * c; + let mut scal = (*scalar).clone(); + scal.divn(windows_starts as u32); + let mut a = (scal.as_ref()[0] % (1 << c)) as i64 + *carry_in; + if a >= (1 << (c-1)) { + a -= 1 << c; + *carry_in = 1; + } else { + *carry_in = 0; + } + (*vec_coeff)[i] = a; + } + } + + pub fn multi_scalar_mul_affine_sd_c( bases: &[G], scalars: &[::BigInt], + c:usize ) -> G::Projective { - let c = if scalars.len() < 32 { - 3 - } else { - (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize - }; + + let cc = 1 << c; + + let num_bits = + ::Params::MODULUS_BITS as usize; + + let zero = G::zero().into_projective(); + + // The number of windows of the scalars in groups of c bits + let num_w = (num_bits as f64 / c as f64).ceil() as usize; + // The number of cores present + let cpus = rayon::current_num_threads(); + // The number of chunks of cpus digits + let num_chunks = (num_w as f64/cpus as f64).floor() as usize; + // The remaining digits to process sequentially + let remaining_digits = num_w - (num_chunks * cpus); + + let mut window_sums = Vec::new(); + let mut small_window_sums:Vec<_>; + + let mut carry_vec = vec![0; scalars.len()]; + let mut vec_coeff = vec![vec![0; cpus]; scalars.len()]; + + for i in 0..num_chunks { + // index of the digit within the small window of cpus number of digits + let idx: Vec<_> = (0..cpus).rev().collect(); + + vec_coeff.par_iter_mut().zip(carry_vec.par_iter_mut()).enumerate().for_each( |(l, (v1, c1))| { + Self::recode_sd_chunk::(&scalars[l], c, i, cpus, v1, c1); + }); + + small_window_sums = idx + .into_par_iter() + .map(|w_idx| { + // We don't need the "zero" bucket, we use 2^c-1 bucket for units + let mut buckets = vec![Vec::with_capacity(bases.len() / cc * 2); cc / 2]; + for i in 0..scalars.len() { + if !scalars[i].is_zero() { + + let scalar = vec_coeff[i][w_idx]; + + // If the scalar is non-zero, we update the corresponding + // bucket. + // (Recall that `buckets` doesn't have a zero bucket.) + if scalar != 0 && bases[i].is_zero() == false { + if scalar < 0 { + buckets[(-scalar - 1) as usize].push(-(bases[i])); + } else { + buckets[(scalar - 1) as usize].push(bases[i]); + } + } + } + } + G::add_points(&mut buckets); + let mut res = zero.clone(); + + let mut running_sum = zero.clone(); + for b in buckets[0..cc / 2].iter_mut().rev() { + if b.len() != 0 && b[0].is_zero() == false { + running_sum.add_assign_mixed(&b[0]) + } + res += &running_sum; + } + + res + }) + .collect(); + + small_window_sums.iter().rev().for_each(|x| { + window_sums.push(x.clone()); + }); + } + + if remaining_digits != 0 { + + let idx:Vec<_> = (0..remaining_digits).rev().collect(); + + vec_coeff.par_iter_mut().zip(carry_vec.par_iter_mut()).enumerate().for_each( |(l, (v1, c1))| { + Self::recode_sd_chunk::(&scalars[l], c, num_chunks, cpus, v1, c1); + }); + + // Each window is of size `c`. + // We divide up the bits 0..num_bits into windows of size `c`, and + // in parallel process each such window. + small_window_sums = idx + .into_par_iter() + .map(|w_idx| { + // We don't need the "zero" bucket, we use 2^c-1 bucket for units + let mut buckets = vec![Vec::with_capacity(bases.len() / cc * 2); cc / 2]; + for i in 0..scalars.len() { + if !scalars[i].is_zero() { + + let scalar = vec_coeff[i][w_idx]; + + // If the scalar is non-zero, we update the corresponding + // bucket. + // (Recall that `buckets` doesn't have a zero bucket.) + if scalar != 0 && bases[i].is_zero() == false { + if scalar < 0 { + buckets[(-scalar - 1) as usize].push(-(bases[i])); + } else { + buckets[(scalar - 1) as usize].push(bases[i]); + } + } + } + } + G::add_points(&mut buckets); + let mut res = zero.clone(); + + let mut running_sum = zero.clone(); + for b in buckets[0..cc / 2].iter_mut().rev() { + if b.len() != 0 && b[0].is_zero() == false { + running_sum.add_assign_mixed(&b[0]) + } + res += &running_sum; + } + res + }) + .collect(); + + small_window_sums.iter().rev().for_each(|x| { + window_sums.push(x.clone()); + }); + } + + // We store the sum for the lowest window. + let lowest = window_sums.first().unwrap(); + + // We're traversing windows from high to low. + window_sums[1..].iter().rev().fold(zero, |mut total, sum_i| { + total += sum_i; + for _ in 0..c { + total.double_in_place(); + } + total + }) + lowest + } + + + pub fn multi_scalar_mul_affine_c( + bases: &[G], + scalars: &[::BigInt], + c: usize + ) -> G::Projective { + let cc = 1 << c; let num_bits = @@ -37,12 +249,12 @@ impl VariableBaseMSM { .into_par_iter() .map(|w_start| { // We don't need the "zero" bucket, we use 2^c-1 bucket for units - let mut buckets = vec![Vec::with_capacity(bases.len()/cc * 2); cc]; + let mut buckets = vec![Vec::with_capacity(bases.len()/cc*2); cc]; scalars.iter().zip(bases).filter(|(s, _)| !s.is_zero()).for_each(|(&scalar, base)| { if scalar == fr_one { // We only process unit scalars once in the first window. if w_start == 0 && base.is_zero() == false { - buckets[cc - 1].push(*base); + buckets[cc-1].push(*base); } } else { let mut scalar = scalar; @@ -63,14 +275,10 @@ impl VariableBaseMSM { } }); G::add_points(&mut buckets); - let mut res = if buckets[cc - 1].len() == 0 { - zero - } else { - buckets[cc - 1][0].into_projective() - }; + let mut res = if buckets[cc-1].len() == 0 {zero} else {buckets[cc-1][0].into_projective()}; let mut running_sum = zero; - for b in buckets[0..cc - 1].iter_mut().rev() { + for b in buckets[0..cc-1].iter_mut().rev() { if b.len() != 0 && b[0].is_zero() == false { running_sum.add_assign_mixed(&b[0]) } @@ -93,15 +301,11 @@ impl VariableBaseMSM { }) + lowest } - pub fn multi_scalar_mul_mixed( + pub fn msm_inner_c( bases: &[G], scalars: &[::BigInt], + c:usize ) -> G::Projective { - let c = if scalars.len() < 32 { - 3 - } else { - (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() + 2.0).ceil() as usize - }; let num_bits = ::Params::MODULUS_BITS as usize; @@ -176,11 +380,50 @@ impl VariableBaseMSM { G: AffineCurve, G::Projective: ProjectiveCurve { - #[cfg(not(feature = "msm_affine"))] - return Self::multi_scalar_mul_mixed(bases, scalars); - #[cfg(feature = "msm_affine")] - return Self::multi_scalar_mul_affine(bases, scalars); + let scal_len = scalars.len(); + + if TypeId::of::() == TypeId::of::() + { + let c: usize = if scal_len < 32 { + 3 + } else if (scal_len < 1 << 17) || (scal_len > 1 << 23) { + (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize + } else if scal_len < 1 << 21 { + 12 + } else { + 16 + }; + return Self::multi_scalar_mul_affine_sd_c(bases, scalars, c); + } else if TypeId::of::() == TypeId::of::() { + if scal_len < 1 << 17 { + let c: usize = if scal_len < 32 { + 3 + } else { + (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize + }; + return Self::multi_scalar_mul_affine_sd_c(bases, scalars, c); + } else if scal_len < 1 << 19 { + let c: usize = 11; + return Self::multi_scalar_mul_affine_sd_c(bases, scalars, c); + } else if scal_len < 1 << 23 { + let c: usize = 11; + return Self::multi_scalar_mul_affine_c(bases, scalars, c); + } else if scal_len < 1 << 24 { + let c: usize = 16; + return Self::msm_inner_c(bases, scalars, c); + } else { + let c: usize = (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize; + return Self::msm_inner_c(bases, scalars, c); + } + } else { + let c: usize = if scal_len < 32 { + 3 + } else { + (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize + }; + return Self::multi_scalar_mul_affine_c(bases, scalars, c); + } } #[cfg(feature = "gpu")] @@ -277,8 +520,14 @@ impl VariableBaseMSM { #[cfg(test)] mod test { use super::*; - use algebra::curves::bls12_381::G1Projective; - use algebra::fields::bls12_381::Fr; + + use algebra::curves::bn_382::G1Projective as Bn382G1Projective; + use algebra::fields::bn_382::Fr as Bn382Fr; + use algebra::curves::tweedle::dee::Projective as TweedleDee; + use algebra::fields::tweedle::Fr as TweedleFr; + use algebra::curves::bls12_381::G1Projective as BlsG1Projective; + use algebra::fields::bls12_381::Fr as BlsFr; + use rand::SeedableRng; use rand_xorshift::XorShiftRng; use algebra::UniformRand; @@ -295,57 +544,108 @@ mod test { acc } + #[cfg(feature = "tweedle")] #[test] - fn test_all_variants() { + fn test_all_variants_tweedle() { const SAMPLES: usize = 1 << 12; let mut rng = XorShiftRng::seed_from_u64(234872845u64); let v = (0..SAMPLES) - .map(|_| Fr::rand(&mut rng).into_repr()) + .map(|_| TweedleFr::rand(&mut rng).into_repr()) .collect::>(); let g = (0..SAMPLES) - .map(|_| G1Projective::rand(&mut rng).into_affine()) + .map(|_| TweedleDee::rand(&mut rng).into_affine()) .collect::>(); let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let mixed = VariableBaseMSM::multi_scalar_mul_mixed(g.as_slice(), v.as_slice()); - let affine = VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); + let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); + + let c = 16; + let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(),c); + let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(),c); + let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(),c); + #[cfg(feature = "gpu")] - let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + + assert_eq!(naive, fast); - assert_eq!(naive, mixed); assert_eq!(naive, affine); + assert_eq!(naive, affine_sd); + assert_eq!(naive, inner); #[cfg(feature = "gpu")] assert_eq!(naive, gpu); } #[test] - fn test_with_unequal_numbers() { + fn test_all_variants_bn382() { const SAMPLES: usize = 1 << 12; let mut rng = XorShiftRng::seed_from_u64(234872845u64); - let v = (0..SAMPLES-1) - .map(|_| Fr::rand(&mut rng).into_repr()) + let v = (0..SAMPLES) + .map(|_| Bn382Fr::rand(&mut rng).into_repr()) .collect::>(); let g = (0..SAMPLES) - .map(|_| G1Projective::rand(&mut rng).into_affine()) + .map(|_| Bn382G1Projective::rand(&mut rng).into_affine()) .collect::>(); let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let mixed = VariableBaseMSM::multi_scalar_mul_mixed(g.as_slice(), v.as_slice()); - let affine = VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); + let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); + + let c = 16; + let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(),c); + let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(),c); + let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(),c); #[cfg(feature = "gpu")] let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); - assert_eq!(naive, mixed); + assert_eq!(naive, fast); + + assert_eq!(naive, affine); + assert_eq!(naive, affine_sd); + assert_eq!(naive, inner); + + #[cfg(feature = "gpu")] + assert_eq!(naive, gpu); + } + + #[test] + fn test_all_variants_bls() { + const SAMPLES: usize = 1 << 12; + + let mut rng = XorShiftRng::seed_from_u64(234872845u64); + + let v = (0..SAMPLES) + .map(|_| BlsFr::rand(&mut rng).into_repr()) + .collect::>(); + let g = (0..SAMPLES) + .map(|_| BlsG1Projective::rand(&mut rng).into_affine()) + .collect::>(); + + let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); + let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); + + let c = 16; + let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(),c); + let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(),c); + let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(),c); + + #[cfg(feature = "gpu")] + let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + + assert_eq!(naive, fast); + assert_eq!(naive, affine); + assert_eq!(naive, affine_sd); + assert_eq!(naive, inner); #[cfg(feature = "gpu")] assert_eq!(naive, gpu); } + } From 52ee7bcfb7915fb51875e16bd540ecbe178a3d07 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Thu, 14 Jan 2021 23:05:39 +0200 Subject: [PATCH 40/63] Affine feature typo fixed and same curve for GPU and CPU tests is used --- algebra-utils/Cargo.toml | 4 ++-- algebra-utils/src/fft/domain/mod.rs | 3 --- algebra-utils/src/fft/domain/test.rs | 11 ----------- algebra-utils/src/fft/polynomial/dense.rs | 3 --- algebra-utils/src/fft/polynomial/sparse.rs | 3 --- 5 files changed, 2 insertions(+), 22 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index fbc605ad5..322f12a2c 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -40,12 +40,12 @@ bench-utils = { path = "../bench-utils" } algebra-utils = { path = "../algebra-utils", features = ["dev"] } [features] -default = [ "parallel", "fft", "msm_affiine" ] +default = [ "parallel", "fft", "msm_affine" ] dev = [ "bls12_381", "bn_382", "tweedle", "mnt4_753", "mnt6_753" ] parallel = [ "rayon" ] fft = [] -msm_affiine = [] +msm_affine = [] gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] llvm_asm = [ "algebra/llvm_asm" ] diff --git a/algebra-utils/src/fft/domain/mod.rs b/algebra-utils/src/fft/domain/mod.rs index b2b8d9d00..510860379 100644 --- a/algebra-utils/src/fft/domain/mod.rs +++ b/algebra-utils/src/fft/domain/mod.rs @@ -264,9 +264,6 @@ pub fn sample_element_outside_domain< mod tests { use crate::get_best_evaluation_domain; use algebra::Field; - #[cfg(not(feature = "gpu"))] - use algebra::fields::mnt6753::fr::Fr; - #[cfg(feature = "gpu")] use algebra::fields::bls12_381::fr::Fr; use rand::{Rng, thread_rng}; diff --git a/algebra-utils/src/fft/domain/test.rs b/algebra-utils/src/fft/domain/test.rs index 91d3a02ca..0a0146f7e 100644 --- a/algebra-utils/src/fft/domain/test.rs +++ b/algebra-utils/src/fft/domain/test.rs @@ -1,7 +1,4 @@ use algebra::{UniformRand, Field, PrimeField, FpParameters}; -#[cfg(not(feature = "gpu"))] -use algebra::curves::{mnt6753::MNT6, PairingEngine}; -#[cfg(feature = "gpu")] use algebra::curves::{bls12_381::Bls12_381, PairingEngine}; use crate::{domain::*, multicore::*}; use rand; @@ -45,10 +42,6 @@ fn fft_composition() { let rng = &mut rand::thread_rng(); - #[cfg(not(feature = "gpu"))] - test_fft_composition::(rng); - - #[cfg(feature = "gpu")] test_fft_composition::(rng); } @@ -91,9 +84,5 @@ fn fft_consistency() { let rng = &mut rand::thread_rng(); - #[cfg(not(feature = "gpu"))] - test_consistency::(rng); - - #[cfg(feature = "gpu")] test_consistency::(rng); } \ No newline at end of file diff --git a/algebra-utils/src/fft/polynomial/dense.rs b/algebra-utils/src/fft/polynomial/dense.rs index 7a1c48219..4e568a53d 100644 --- a/algebra-utils/src/fft/polynomial/dense.rs +++ b/algebra-utils/src/fft/polynomial/dense.rs @@ -361,9 +361,6 @@ impl<'a, 'b, F: PrimeField> Mul<&'a DensePolynomial> for &'b DensePolynomial< mod tests { use crate::domain::get_best_evaluation_domain; use crate::polynomial::*; - #[cfg(not(feature = "gpu"))] - use algebra::fields::mnt6753::fr::Fr; - #[cfg(feature = "gpu")] use algebra::fields::bls12_381::fr::Fr; use algebra::fields::Field; use algebra::UniformRand; diff --git a/algebra-utils/src/fft/polynomial/sparse.rs b/algebra-utils/src/fft/polynomial/sparse.rs index 92ec7f9a5..5875e4f37 100644 --- a/algebra-utils/src/fft/polynomial/sparse.rs +++ b/algebra-utils/src/fft/polynomial/sparse.rs @@ -128,9 +128,6 @@ impl Into> for SparsePolynomial { #[cfg(test)] mod tests { use crate::{get_best_evaluation_domain, DensePolynomial, SparsePolynomial}; - #[cfg(not(feature = "gpu"))] - use algebra::fields::mnt6753::fr::Fr; - #[cfg(feature = "gpu")] use algebra::fields::bls12_381::fr::Fr; use algebra::Field; From f756ac463e18f2e80ada36fff4e7f47605e387dc Mon Sep 17 00:00:00 2001 From: Phoinic Date: Fri, 15 Jan 2021 01:39:37 +0200 Subject: [PATCH 41/63] Removing crossbeam dependency --- algebra-utils/Cargo.toml | 3 +- algebra-utils/src/msm/variable_base.rs | 53 +++++++++++--------------- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 322f12a2c..a76a94f3d 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -29,7 +29,6 @@ rayon = { version = "1", optional = true } # gpu feature algebra-kernels = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } algebra-cl-gen = { git = "https://github.com/HorizenOfficial/ginger-algebra-ocl", branch = "ginger_ocl", optional = true } -crossbeam = { version = "0.7", optional = true } [dev-dependencies] blake2 = "0.7" @@ -46,7 +45,7 @@ dev = [ "bls12_381", "bn_382", "tweedle", "mnt4_753", "mnt6_753" ] parallel = [ "rayon" ] fft = [] msm_affine = [] -gpu = [ "algebra-kernels", "algebra-cl-gen", "crossbeam" ] +gpu = [ "parallel", "algebra-kernels", "algebra-cl-gen" ] llvm_asm = [ "algebra/llvm_asm" ] bls12_377 = [ "algebra-kernels/bls12_377", "algebra/bls12_377" ] diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 4d8a7888d..ed88b4a0e 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -1,12 +1,9 @@ use algebra::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, ProjectiveCurve}; use rayon::prelude::*; +use std::sync::{Arc, Mutex}; #[cfg(feature = "gpu")] use algebra_kernels::msm::{get_cpu_utilization, get_kernels, get_gpu_min_length}; -#[cfg(feature = "gpu")] -use algebra_cl_gen::gpu::GPUError; -#[cfg(feature = "gpu")] -use crossbeam::thread; pub struct VariableBaseMSM; @@ -192,8 +189,6 @@ impl VariableBaseMSM { G: AffineCurve, G::Projective: ProjectiveCurve { - let zero = G::Projective::zero(); - let mut n = bases.len(); let cpu_n; @@ -214,9 +209,9 @@ impl VariableBaseMSM { let chunk_size = ((n as f64) / (num_devices as f64)).ceil() as usize; - match thread::scope(|s| -> Result { - let mut acc = G::Projective::zero(); - let mut threads = Vec::new(); + let results = Arc::new(Mutex::new(vec![])); + + rayon::scope(|s| { if n > 0 { for ((bases, scalars), kern) in bases @@ -224,41 +219,39 @@ impl VariableBaseMSM { .zip(scalars.chunks(chunk_size)) .zip(kernels.iter()) { - threads.push(s.spawn( - move |_| -> Result { + let results = Arc::clone(&results); + s.spawn( + move |_| { let mut acc = G::Projective::zero(); for (bases, scalars) in bases.chunks(kern.n).zip(scalars.chunks(kern.n)) { - let result = kern.msm(bases, scalars, bases.len())?; - acc.add_assign_mixed(&result.into_affine()); + let result = kern.msm(bases, scalars, bases.len()); + acc.add_assign_mixed(&result.unwrap().into_affine()); } - Ok(acc) + results.lock().unwrap().push(acc); }, - )); + ); } } if cpu_n > 0 { - threads.push(s.spawn( - move |_| -> Result { + let results = Arc::clone(&results); + s.spawn( + move |_| { let acc = Self::msm_inner_cpu(cpu_bases, cpu_scalars); - Ok(acc) + results.lock().unwrap().push(acc); } - )) + ); } + }); - let mut results = vec![]; - for t in threads { - results.push(t.join()); - } - for r in results { - acc.add_assign_mixed(&r??.into_affine()); - } + let mut acc = G::Projective::zero(); + let results = Arc::try_unwrap(results).unwrap().lock().unwrap().clone(); - Ok(acc) - }) { - Ok(res) => res.unwrap(), - Err(_) => zero + for r in results.into_iter() { + acc.add_assign_mixed(&r.into_affine()); } + + acc } pub fn multi_scalar_mul( From 4865d36cef9ccb5a88c105c91bcb500f6fa8979b Mon Sep 17 00:00:00 2001 From: Phoinic Date: Fri, 15 Jan 2021 01:49:31 +0200 Subject: [PATCH 42/63] Separate tests for CPU and GPU --- algebra-utils/src/fft/domain/test.rs | 41 +++++++++++++++----- algebra-utils/src/msm/variable_base.rs | 52 ++++++++++++++++++++------ 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/algebra-utils/src/fft/domain/test.rs b/algebra-utils/src/fft/domain/test.rs index 0a0146f7e..93280a415 100644 --- a/algebra-utils/src/fft/domain/test.rs +++ b/algebra-utils/src/fft/domain/test.rs @@ -57,26 +57,49 @@ fn fft_consistency() { let mut v1 = (0..d).map(|_| E::Fr::rand(rng)).collect::>(); let mut v2 = v1.clone(); - #[cfg(feature = "gpu")] - let mut v3 = v1.clone(); - let domain = get_best_evaluation_domain::(v1.len()).unwrap(); for log_cpus in log_d..min(log_d + 1, 3) { if log_d < ::Params::TWO_ADICITY{ BasicRadix2Domain::parallel_fft(&mut v1, &worker, domain.group_gen(), log_d, log_cpus); BasicRadix2Domain::serial_fft(&mut v2, domain.group_gen(), log_d); - #[cfg(feature = "gpu")] - BasicRadix2Domain::gpu_fft(&mut v3, domain.group_gen(), log_d); } else { MixedRadix2Domain::mixed_parallel_fft(&mut v1, &worker, domain.group_gen(), log_d, log_cpus); MixedRadix2Domain::mixed_serial_fft(&mut v2, domain.group_gen(), log_d); - #[cfg(feature = "gpu")] - MixedRadix2Domain::mixed_gpu_fft(&mut v3, domain.group_gen(), log_d); } assert_eq!(v1, v2); - #[cfg(feature = "gpu")] - assert_eq!(v1, v3); + } + } + } + } + + let rng = &mut rand::thread_rng(); + + test_consistency::(rng); +} + +#[test] +#[cfg(feature = "gpu")] +fn fft_consistency_gpu() { + fn test_consistency(rng: &mut R) { + for _ in 0..5 { + for log_d in 0..18 { + let d = 1 << log_d; + + let mut v1 = (0..d).map(|_| E::Fr::rand(rng)).collect::>(); + let mut v2 = v1.clone(); + + let domain = get_best_evaluation_domain::(v1.len()).unwrap(); + + for _ in log_d..min(log_d + 1, 3) { + if log_d < ::Params::TWO_ADICITY{ + BasicRadix2Domain::serial_fft(&mut v1, domain.group_gen(), log_d); + BasicRadix2Domain::gpu_fft(&mut v2, domain.group_gen(), log_d); + } else { + MixedRadix2Domain::mixed_serial_fft(&mut v1, domain.group_gen(), log_d); + MixedRadix2Domain::mixed_gpu_fft(&mut v2, domain.group_gen(), log_d); + } + assert_eq!(v1, v2); } } } diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index ed88b4a0e..b309e50f4 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -1,9 +1,10 @@ use algebra::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, ProjectiveCurve}; use rayon::prelude::*; -use std::sync::{Arc, Mutex}; #[cfg(feature = "gpu")] use algebra_kernels::msm::{get_cpu_utilization, get_kernels, get_gpu_min_length}; +#[cfg(feature = "gpu")] +use std::sync::{Arc, Mutex}; pub struct VariableBaseMSM; @@ -305,14 +306,8 @@ mod test { let mixed = VariableBaseMSM::multi_scalar_mul_mixed(g.as_slice(), v.as_slice()); let affine = VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); - #[cfg(feature = "gpu")] - let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); - assert_eq!(naive, mixed); assert_eq!(naive, affine); - - #[cfg(feature = "gpu")] - assert_eq!(naive, gpu); } #[test] @@ -332,13 +327,48 @@ mod test { let mixed = VariableBaseMSM::multi_scalar_mul_mixed(g.as_slice(), v.as_slice()); let affine = VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); - #[cfg(feature = "gpu")] - let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); - assert_eq!(naive, mixed); assert_eq!(naive, affine); + } + + + #[test] + #[cfg(feature = "gpu")] + fn test_all_variants_gpu() { + const SAMPLES: usize = 1 << 12; + + let mut rng = XorShiftRng::seed_from_u64(234872845u64); + + let v = (0..SAMPLES) + .map(|_| Fr::rand(&mut rng).into_repr()) + .collect::>(); + let g = (0..SAMPLES) + .map(|_| G1Projective::rand(&mut rng).into_affine()) + .collect::>(); + + let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); + let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + + assert_eq!(naive, gpu); + } + + #[test] + #[cfg(feature = "gpu")] + fn test_with_unequal_numbers_gpu() { + const SAMPLES: usize = 1 << 12; + + let mut rng = XorShiftRng::seed_from_u64(234872845u64); + + let v = (0..SAMPLES-1) + .map(|_| Fr::rand(&mut rng).into_repr()) + .collect::>(); + let g = (0..SAMPLES) + .map(|_| G1Projective::rand(&mut rng).into_affine()) + .collect::>(); + + let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); + let gpu = VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); - #[cfg(feature = "gpu")] assert_eq!(naive, gpu); } } From c71c48fe872df92dac504749051ba2141ae7f163 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 18 Jan 2021 22:31:44 +0200 Subject: [PATCH 43/63] Tweedle fields unit-tests: base --- algebra/src/fields/tweedle/mod.rs | 2 + algebra/src/fields/tweedle/tests.rs | 450 ++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 algebra/src/fields/tweedle/tests.rs diff --git a/algebra/src/fields/tweedle/mod.rs b/algebra/src/fields/tweedle/mod.rs index 1c2f05b49..6612de8d5 100644 --- a/algebra/src/fields/tweedle/mod.rs +++ b/algebra/src/fields/tweedle/mod.rs @@ -4,3 +4,5 @@ pub use self::fr::*; pub mod fq; pub use self::fq::*; +#[cfg(test)] +mod tests; diff --git a/algebra/src/fields/tweedle/tests.rs b/algebra/src/fields/tweedle/tests.rs new file mode 100644 index 000000000..264220591 --- /dev/null +++ b/algebra/src/fields/tweedle/tests.rs @@ -0,0 +1,450 @@ +use crate::{ + biginteger::BigInteger256 as BigInteger, + bytes::{FromBytes, ToBytes}, + fields::{ + tweedle::{fq::Fq, fr::Fr}, + tests::{field_test, primefield_test}, + Field, + LegendreSymbol::*, + PrimeField, SquareRootField, + }, +}; +use std::str::FromStr; + +#[test] +fn test_tweedle_fr() { + let a: Fr = rand::random(); + let b: Fr = rand::random(); + field_test(a, b); + primefield_test::(); +} + +#[test] +fn test_tweedle_fq() { + let a: Fq = rand::random(); + let b: Fq = rand::random(); + field_test(a, b); + primefield_test::(); +} + +#[test] +fn test_fq_add() { + let f1 = Fq::from_str( + "18386742314266644595564329008376577163854043021652781768352795308532764650733", + ) + .unwrap(); + let f2 = Fq::from_str( + "39786307610986038981023499868190793548353538256264351797285876981647142458383", + ) + .unwrap(); + let f3 = Fq::from_str( + "277005306594585864802336372223416785563173966008267311744504363842750431482", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); + assert_eq!(f1 + &f2, f3); +} + +#[test] +fn test_fq_add_one() { + let f1 = Fq::from_str( + "4946875394261337176810256604189376311946643975348516311606738923340201185904", + ) + .unwrap(); + let f2 = Fq::from_str( + "4946875394261337176810256604189376311946643975348516311606738923340201185905", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert_eq!(f1 + &Fq::one(), f2); +} + +#[test] +fn test_fq_mul() { + let f1 = Fq::from_str( + "24703123148064348394273033316595937198355721297494556079070134653139656190956", + ) + .unwrap(); + let f2 = Fq::from_str( + "38196797080882758914424853878212529985425118523754343117256179679117054302131", + ) + .unwrap(); + let f3 = Fq::from_str( + "38057113854472161555556064369220825628027487067886761874351491955834635348140", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); + assert_eq!(f1 * &f2, f3); +} + +#[test] +fn test_fq_triple_mul() { + let f1 = Fq::from_str( + "23834398828139479510988224171342199299644042568628082836691700490363123893905", + ) + .unwrap(); + let f2 = Fq::from_str( + "48343809612844640454129919255697536258606705076971130519928764925719046689317", + ) + .unwrap(); + let f3 = Fq::from_str( + "22704845471524346880579660022678666462201713488283356385810726260959369106033", + ) + .unwrap(); + let f4 = Fq::from_str( + "18897508522635316277030308074760673440128491438505204942623624791502972539393", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); + assert_eq!(f1 * &f2 * &f3, f4); +} + +#[test] +fn test_fq_div() { + let f1 = Fq::from_str( + "31892744363926593013886463524057935370302352424137349660481695792871889573091", + ) + .unwrap(); + let f2 = Fq::from_str( + "47695868328933459965610498875668250916462767196500056002116961816137113470902", + ) + .unwrap(); + let f3 = Fq::from_str( + "10565087619621820656254220984570060779538680183776893272687321117751927412212", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); + assert_eq!(f1 / &f2, f3); +} + +#[test] +fn test_fq_sub() { + let f1 = Fq::from_str( + "18695869713129401390241150743745601908470616448391638969502807001833388904079", + ) + .unwrap(); + let f2 = Fq::from_str( + "10105476028534616828778879109836101003805485072436929139123765141153277007373", + ) + .unwrap(); + let f3 = Fq::from_str( + "8590393684594784561462271633909500904665131375954709830379041860680111896706", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); + assert_eq!(f1 - &f2, f3); +} + +#[test] +fn test_fq_double_in_place() { + let mut f1 = Fq::from_str( + "29729289787452206300641229002276778748586801323231253291984198106063944136114", + ) + .unwrap(); + let f3 = Fq::from_str( + "1562534956246314889496965500209603570529195334553640330074228285790731594594", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f3.is_zero()); + f1.double_in_place(); + assert_eq!(f1, f3); +} + +#[test] +fn test_fq_double_in_place_thrice() { + let mut f1 = Fq::from_str( + "32768907806651393940832831055386272949401004221411141755415956893066040832473", + ) + .unwrap(); + let f3 = Fq::from_str( + "1619061669249711823627932173542390925308200867699235900803899476011121610431", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f3.is_zero()); + f1.double_in_place(); + f1.double_in_place(); + f1.double_in_place(); + assert_eq!(f1, f3); +} + +#[test] +fn test_fq_generate_random_tweedle_point() { + let d = Fq::from_str( + "19257038036680949359750312669786877991949435402254120286184196891950884077233", + ) + .unwrap(); + let y = Fq::from_str( + "20269054604167148422407276086932743904275456233139568486008667107872965128512", + ) + .unwrap(); + let x2 = Fq::from_str( + "35041048504708632193693740149219726446678304552734087046982753200179718192840", + ) + .unwrap(); + + let computed_y2 = y.square(); + let y2 = Fq::from_str( + "22730681238307918419349440108285755984465605552827817317611903495170775437833", + ) + .unwrap(); + assert_eq!(y2, computed_y2); + + let computed_dy2 = d * &computed_y2; + let dy2 = Fq::from_str( + "24720347560552809545835752815204882739669031262711919770503096707526812943411", + ) + .unwrap(); + assert_eq!(dy2, computed_dy2); + + let computed_divisor = computed_dy2 + &Fq::one(); + let divisor = Fq::from_str( + "24720347560552809545835752815204882739669031262711919770503096707526812943412", + ) + .unwrap(); + assert_eq!(divisor, computed_divisor); + + let computed_x2 = (computed_y2 - &Fq::one()) / &computed_divisor; + assert_eq!(x2, computed_x2); + + let x = Fq::from_str( + "15337652609730546173818014678723269532482775720866471265774032070871608223361", + ) + .unwrap(); + let computed_x = computed_x2.sqrt().unwrap(); + assert_eq!(computed_x.square(), x2); + assert_eq!(x, computed_x); + + fn add<'a>(curr: (Fq, Fq), other: &'a (Fq, Fq)) -> (Fq, Fq) { + let y1y2 = curr.1 * &other.1; + let x1x2 = curr.0 * &other.0; + let d = Fq::from_str( + "19257038036680949359750312669786877991949435402254120286184196891950884077233", + ) + .unwrap(); + let dx1x2y1y2 = d * &y1y2 * &x1x2; + + let d1 = Fq::one() + &dx1x2y1y2; + let d2 = Fq::one() - &dx1x2y1y2; + + let x1y2 = curr.0 * &other.1; + let y1x2 = curr.1 * &other.0; + + let x = (x1y2 + &y1x2) / &d1; + let y = (y1y2 + &x1x2) / &d2; + + (x, y) + } + + let result = add((x, y), &(x, y)); + let result = add(result, &result); + let result = add(result, &result); + + let point_x = Fq::from_str( + "47259664076168047050113154262636619161204477920503059672059915868534495873964", + ) + .unwrap(); + let point_y = Fq::from_str( + "19016409245280491801573912449420132838852726543024859389273314249842195919690", + ) + .unwrap(); + assert_eq!((point_x, point_y), result); +} + +#[test] +fn test_fq_square_in_place() { + let mut f1 = Fq::from_str( + "34864651240005695523200639428464570946052769938774601449735727714436878540682", + ) + .unwrap(); + let f3 = + Fq::from_str("213133100629336594719108316042277780359104840987226496279264105585804377948") + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f3.is_zero()); + f1.square_in_place(); + assert_eq!(f1, f3); +} + +#[test] +fn test_fq_sqrt() { + let f1 = Fq::from_str( + "10875927553327821418567659853801220899541454800710193788767706167237535308235", + ) + .unwrap(); + let f3 = Fq::from_str( + "10816221372957505053219354782681292880545918527618367765651802809826238616708", + ) + .unwrap(); + assert_eq!(f1.sqrt().unwrap(), f3); +} + +#[test] +fn test_fq_from_str() { + let f1_from_repr = Fq::from_repr(BigInteger([ + 0xab8a2535947d1a77, + 0x9ba74cbfda0bbcda, + 0xe928b59724d60baf, + 0x1cccaaeb9bb1680a, + ])); + let f1 = Fq::from_str( + "13026376210409056429264774981357153555336288129100724591327877625017068755575", + ) + .unwrap(); + let f2_from_repr = Fq::from_repr(BigInteger([ + 0x97e9103775d2f35c, + 0xbe6756b6c587544b, + 0x6ee38c3afd88ef4b, + 0x2bacd150f540c677, + ])); + let f2 = Fq::from_str( + "19754794831832707859764530223239420866832328728734160755396495950822165902172", + ) + .unwrap(); + assert_eq!(f1_from_repr, f1); + assert_eq!(f2_from_repr, f2); +} + +#[test] +fn test_fq_legendre() { + assert_eq!(QuadraticResidue, Fq::one().legendre()); + assert_eq!(Zero, Fq::zero().legendre()); + + let e = BigInteger([ + 0x0dbc5349cd5664da, + 0x8ac5b6296e3ae29d, + 0x127cb819feceaa3b, + 0x3a6b21fb03867191, + ]); + assert_eq!(QuadraticResidue, Fq::from_repr(e).legendre()); + let e = BigInteger([ + 0x96341aefd047c045, + 0x9b5f4254500a4d65, + 0x1ee08223b68ac240, + 0x31d9cd545c0ec7c6, + ]); + assert_eq!(QuadraticNonResidue, Fq::from_repr(e).legendre()); +} + +#[test] +fn test_fq_bytes() { + let f1_from_repr = Fq::from_repr(BigInteger([ + 0xab8a2535947d1a77, + 0x9ba74cbfda0bbcda, + 0xe928b59724d60baf, + 0x1cccaaeb9bb1680a, + ])); + + let mut f1_bytes = [0u8; 32]; + f1_from_repr.write(f1_bytes.as_mut()).unwrap(); + + let f1 = Fq::read(f1_bytes.as_ref()).unwrap(); + assert_eq!(f1_from_repr, f1); +} + +#[test] +fn test_fr_add() { + let f1 = Fr::from_repr(BigInteger([ + 0xc81265fb4130fe0c, + 0xb308836c14e22279, + 0x699e887f96bff372, + 0x84ecc7e76c11ad, + ])); + let f2 = Fr::from_repr(BigInteger([ + 0x71875719b422efb8, + 0x43658e68a93612, + 0x9fa756be2011e833, + 0xaa2b2cb08dac497, + ])); + let f3 = Fr::from_repr(BigInteger([ + 0x3999bd14f553edc4, + 0xb34be8fa7d8b588c, + 0x945df3db6d1dba5, + 0xb279f92f046d645, + ])); + assert_eq!(f1 + &f2, f3); +} + +#[test] +fn test_fr_mul() { + let f1 = Fr::from_repr(BigInteger([ + 0xc81265fb4130fe0c, + 0xb308836c14e22279, + 0x699e887f96bff372, + 0x84ecc7e76c11ad, + ])); + let f2 = Fr::from_repr(BigInteger([ + 0x71875719b422efb8, + 0x43658e68a93612, + 0x9fa756be2011e833, + 0xaa2b2cb08dac497, + ])); + let f3 = Fr::from_repr(BigInteger([ + 0xf628897043db7339, + 0x15beccc45da84542, + 0x291fa8ad05b401fb, + 0x1a4b21d583e6284b + ])); + assert_eq!(f1 * &f2, f3); +} + + +#[test] +fn test_fr_bytes() { + let f1_from_repr = Fr::from_repr(BigInteger([ + 0xc81265fb4130fe0c, + 0xb308836c14e22279, + 0x699e887f96bff372, + 0x84ecc7e76c11ad, + ])); + + let mut f1_bytes = [0u8; 32]; + f1_from_repr.write(f1_bytes.as_mut()).unwrap(); + + let f1 = Fr::read(f1_bytes.as_ref()).unwrap(); + assert_eq!(f1_from_repr, f1); +} + +#[test] +fn test_fr_from_str() { + let f100_from_repr = Fr::from_repr(BigInteger([0x64, 0, 0, 0])); + let f100 = Fr::from_str("100").unwrap(); + assert_eq!(f100_from_repr, f100); +} + +#[test] +#[ignore] +fn print_field() { + println!("one: {:?}", Fq::one()); + println!("zero: {:?}", Fq::zero()); + println!( + "256 in repr: {:?}", + Fq::from_repr(BigInteger([0, 0, 1, 255])) + ); + println!("256: {:?}", Fq::from_str("256").unwrap().into_repr()); + println!("1024: {:?}", Fq::from_str("1024").unwrap().into_repr()); + println!( + "255 to bytes: {:?}", + to_bytes![Fq::from_str("255").unwrap().into_repr()].unwrap() + ); + println!( + "256 to bytes: {:?}", + to_bytes![Fq::from_str("256").unwrap().into_repr()].unwrap() + ); + println!( + "1023 to bytes: {:?}", + to_bytes![Fq::from_str("1023").unwrap().into_repr()].unwrap() + ); +} From 93e29df6df2bed64b4ed16247e2ae58297ab43c3 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 19 Jan 2021 01:39:01 +0200 Subject: [PATCH 44/63] Tweedle unit-tests --- algebra/src/curves/tweedle/dee.rs | 3 +- algebra/src/curves/tweedle/mod.rs | 3 + algebra/src/curves/tweedle/tests.rs | 177 ++++++++++++++++++++++ algebra/src/fields/tweedle/tests.rs | 221 ++++++++-------------------- 4 files changed, 245 insertions(+), 159 deletions(-) create mode 100644 algebra/src/curves/tweedle/tests.rs diff --git a/algebra/src/curves/tweedle/dee.rs b/algebra/src/curves/tweedle/dee.rs index 7c5afc0d9..55802f9e3 100644 --- a/algebra/src/curves/tweedle/dee.rs +++ b/algebra/src/curves/tweedle/dee.rs @@ -1,10 +1,11 @@ +use crate::field_new; use crate::{ biginteger::BigInteger256, curves::{ models::short_weierstrass_jacobian::{GroupAffine, GroupProjective}, ModelParameters, SWModelParameters }, - Field, field_new, + Field, fields::tweedle::* }; diff --git a/algebra/src/curves/tweedle/mod.rs b/algebra/src/curves/tweedle/mod.rs index 8021b1bf5..f010cea10 100644 --- a/algebra/src/curves/tweedle/mod.rs +++ b/algebra/src/curves/tweedle/mod.rs @@ -1,2 +1,5 @@ pub mod dee; pub mod dum; + +#[cfg(test)] +mod tests; diff --git a/algebra/src/curves/tweedle/tests.rs b/algebra/src/curves/tweedle/tests.rs new file mode 100644 index 000000000..89568a5d3 --- /dev/null +++ b/algebra/src/curves/tweedle/tests.rs @@ -0,0 +1,177 @@ +use crate::{ + curves::{ + models::SWModelParameters, tweedle::*, + tests::curve_tests, + AffineCurve, ProjectiveCurve, + }, + groups::tests::group_test, + fields::{Field, SquareRootField, tweedle::*}, +}; +use std::ops::{AddAssign, MulAssign}; +use std::str::FromStr; + +use rand::{ + Rng, SeedableRng +}; +use rand_xorshift::XorShiftRng; + +#[test] +fn test_dee_projective_curve() { + curve_tests::(); +} + +#[test] +fn test_dee_projective_group() { + let mut rng = XorShiftRng::seed_from_u64(1234567890u64); + let a: dee::Projective = rng.gen(); + let b: dee::Projective = rng.gen(); + group_test(a, b); +} + +#[test] +fn test_dee_generator() { + let generator = dee::Affine::prime_subgroup_generator(); + assert!(generator.is_on_curve()); + assert!(generator.is_in_correct_subgroup_assuming_on_curve()); +} + +#[test] +fn test_dum_projective_curve() { + curve_tests::(); +} + +#[test] +fn test_dum_projective_group() { + let mut rng = XorShiftRng::seed_from_u64(1234567890u64); + let a: dum::Projective = rng.gen(); + let b: dum::Projective = rng.gen(); + group_test(a, b); +} + +#[test] +fn test_dum_generator() { + let generator = dum::Affine::prime_subgroup_generator(); + assert!(generator.is_on_curve()); + assert!(generator.is_in_correct_subgroup_assuming_on_curve()); +} + +#[test] +fn test_dee_generator_raw() { + let mut x = Fq::zero(); + let mut i = 0; + loop { + // y^2 = x^3 + b + let mut rhs = x; + rhs.square_in_place(); + rhs.mul_assign(&x); + rhs.add_assign(&dee::TweedledeeParameters::COEFF_B); + + if let Some(y) = rhs.sqrt() { + let p = dee::Affine::new(x, if y < -y { y } else { -y }, false); + assert!(p.is_in_correct_subgroup_assuming_on_curve()); + + let dee = p.scale_by_cofactor(); + assert_eq!(dee.into_affine(), p); + + if !dee.is_zero() { + assert_eq!(i, 1); + let dee = dee::Affine::from(dee); + + assert!(dee.is_in_correct_subgroup_assuming_on_curve()); + + assert_eq!(dee, dee::Affine::prime_subgroup_generator()); + break; + } + } + + i += 1; + x.add_assign(&Fq::one()); + } +} + +#[test] +fn test_dum_generator_raw() { + let mut x = Fr::zero(); + let mut i = 0; + loop { + // y^2 = x^3 + b + let mut rhs = x; + rhs.square_in_place(); + rhs.mul_assign(&x); + rhs.add_assign(&dum::TweedledumParameters::COEFF_B); + + if let Some(y) = rhs.sqrt() { + let p = dum::Affine::new(x, if y < -y { y } else { -y }, false); + assert!(p.is_in_correct_subgroup_assuming_on_curve()); + + let dum = p.scale_by_cofactor(); + assert_eq!(dum.into_affine(), p); + + if !dum.is_zero() { + assert_eq!(i, 1); + let dum = dum::Affine::from(dum); + + assert!(dum.is_in_correct_subgroup_assuming_on_curve()); + + assert_eq!(dum, dum::Affine::prime_subgroup_generator()); + break; + } + } + + i += 1; + x.add_assign(&Fr::one()); + } +} + +#[test] +fn test_dee_addition_correctness() { + let mut p = dee::Projective::new( + Fq::from_str("17071515411234329267051251142008744532074161438140426170549136904789606209155").unwrap(), + Fq::from_str("9067370984564524093871625068725679070040168060994636121507153477916099620826").unwrap(), + Fq::one(), + ); + + p.add_assign(&dee::Projective::new( + Fq::from_str("5902988235118225415057554152593109689819081116067139376852243422243422684655").unwrap(), + Fq::from_str("9237374262095944048575165674046716194558759078123659312337709713005853948132").unwrap(), + Fq::one(), + )); + + let p = dee::Affine::from(p); + + assert_eq!( + p, + dee::Affine::new( + Fq::from_str("17272972729543522859996365140537720509583378385403153153034405894416507370075").unwrap(), + Fq::from_str("10919319153241406943315020022865635527830995765162202572118118072098170575117").unwrap(), + false, + ) + ); +} + + +#[test] +fn test_dum_addition_correctness() { + let mut p = dum::Projective::new( + Fr::from_str("21118483776076764996122757821606091900059043860162004907989579660882026321197").unwrap(), + Fr::from_str("9025588652913915603174720117986570170395425582417356177673155554443430464689").unwrap(), + Fr::one(), + ); + + p.add_assign(&dum::Projective::new( + Fr::from_str("20385173229981432379197513268506886433340219379830521001646291041798263137109").unwrap(), + Fr::from_str("16494790468966191765270742698088328193228887152919586743292725150337386016283").unwrap(), + Fr::one(), + )); + + let p = dum::Affine::from(p); + + assert_eq!( + p, + dum::Affine::new( + Fr::from_str("3707088439511374954709258634608802460084680838305626554041952787711711292620").unwrap(), + Fr::from_str("21427612888550306000000889405343941940930914059283626531936541886782117113518").unwrap(), + false, + ) + ); +} diff --git a/algebra/src/fields/tweedle/tests.rs b/algebra/src/fields/tweedle/tests.rs index 264220591..3383aa015 100644 --- a/algebra/src/fields/tweedle/tests.rs +++ b/algebra/src/fields/tweedle/tests.rs @@ -34,11 +34,11 @@ fn test_fq_add() { ) .unwrap(); let f2 = Fq::from_str( - "39786307610986038981023499868190793548353538256264351797285876981647142458383", + "19786307610986038981023499868190793548353538256264351797285876981647142458383", ) .unwrap(); let f3 = Fq::from_str( - "277005306594585864802336372223416785563173966008267311744504363842750431482", + "9225027615923634720695082624395393748885377621962700438691588327011328770299", ) .unwrap(); assert!(!f1.is_zero()); @@ -50,11 +50,11 @@ fn test_fq_add() { #[test] fn test_fq_add_one() { let f1 = Fq::from_str( - "4946875394261337176810256604189376311946643975348516311606738923340201185904", + "2946875394261337176810256604189376311946643975348516311606738923340201185904", ) .unwrap(); let f2 = Fq::from_str( - "4946875394261337176810256604189376311946643975348516311606738923340201185905", + "2946875394261337176810256604189376311946643975348516311606738923340201185905", ) .unwrap(); assert!(!f1.is_zero()); @@ -69,11 +69,11 @@ fn test_fq_mul() { ) .unwrap(); let f2 = Fq::from_str( - "38196797080882758914424853878212529985425118523754343117256179679117054302131", + "18196797080882758914424853878212529985425118523754343117256179679117054302131", ) .unwrap(); let f3 = Fq::from_str( - "38057113854472161555556064369220825628027487067886761874351491955834635348140", + "17200426197156579651574285400495776861464966086836221879823411702083205504671", ) .unwrap(); assert!(!f1.is_zero()); @@ -89,7 +89,7 @@ fn test_fq_triple_mul() { ) .unwrap(); let f2 = Fq::from_str( - "48343809612844640454129919255697536258606705076971130519928764925719046689317", + "28343809612844640454129919255697536258606705076971130519928764925719046689317", ) .unwrap(); let f3 = Fq::from_str( @@ -97,7 +97,7 @@ fn test_fq_triple_mul() { ) .unwrap(); let f4 = Fq::from_str( - "18897508522635316277030308074760673440128491438505204942623624791502972539393", + "16214848981638217704332828370994953257254063208571075715629895139281735615384", ) .unwrap(); assert!(!f1.is_zero()); @@ -109,15 +109,15 @@ fn test_fq_triple_mul() { #[test] fn test_fq_div() { let f1 = Fq::from_str( - "31892744363926593013886463524057935370302352424137349660481695792871889573091", + "28343809612844640454129919255697536258606705076971130519928764925719046689317", ) .unwrap(); let f2 = Fq::from_str( - "47695868328933459965610498875668250916462767196500056002116961816137113470902", + "10565087619621820656254220984570060779538680183776893272687321117751927412212", ) .unwrap(); let f3 = Fq::from_str( - "10565087619621820656254220984570060779538680183776893272687321117751927412212", + "18524871784212090982875844178168704466262002646942949074484608991277082160887", ) .unwrap(); assert!(!f1.is_zero()); @@ -149,11 +149,11 @@ fn test_fq_sub() { #[test] fn test_fq_double_in_place() { let mut f1 = Fq::from_str( - "29729289787452206300641229002276778748586801323231253291984198106063944136114", + "27729289787452206300641229002276778748586801323231253291984198106063944136114", ) .unwrap(); let f3 = Fq::from_str( - "1562534956246314889496965500209603570529195334553640330074228285790731594594", + "26510557265575363745389711752381580533851398990508073457021312248959309933411", ) .unwrap(); assert!(!f1.is_zero()); @@ -165,11 +165,11 @@ fn test_fq_double_in_place() { #[test] fn test_fq_double_in_place_thrice() { let mut f1 = Fq::from_str( - "32768907806651393940832831055386272949401004221411141755415956893066040832473", + "12768907806651393940832831055386272949401004221411141755415956893066040832473", ) .unwrap(); let f3 = Fq::from_str( - "1619061669249711823627932173542390925308200867699235900803899476011121610431", + "15307195525224004958984409686574252705241422803425834662486403255022591643333", ) .unwrap(); assert!(!f1.is_zero()); @@ -180,97 +180,14 @@ fn test_fq_double_in_place_thrice() { assert_eq!(f1, f3); } -#[test] -fn test_fq_generate_random_tweedle_point() { - let d = Fq::from_str( - "19257038036680949359750312669786877991949435402254120286184196891950884077233", - ) - .unwrap(); - let y = Fq::from_str( - "20269054604167148422407276086932743904275456233139568486008667107872965128512", - ) - .unwrap(); - let x2 = Fq::from_str( - "35041048504708632193693740149219726446678304552734087046982753200179718192840", - ) - .unwrap(); - - let computed_y2 = y.square(); - let y2 = Fq::from_str( - "22730681238307918419349440108285755984465605552827817317611903495170775437833", - ) - .unwrap(); - assert_eq!(y2, computed_y2); - - let computed_dy2 = d * &computed_y2; - let dy2 = Fq::from_str( - "24720347560552809545835752815204882739669031262711919770503096707526812943411", - ) - .unwrap(); - assert_eq!(dy2, computed_dy2); - - let computed_divisor = computed_dy2 + &Fq::one(); - let divisor = Fq::from_str( - "24720347560552809545835752815204882739669031262711919770503096707526812943412", - ) - .unwrap(); - assert_eq!(divisor, computed_divisor); - - let computed_x2 = (computed_y2 - &Fq::one()) / &computed_divisor; - assert_eq!(x2, computed_x2); - - let x = Fq::from_str( - "15337652609730546173818014678723269532482775720866471265774032070871608223361", - ) - .unwrap(); - let computed_x = computed_x2.sqrt().unwrap(); - assert_eq!(computed_x.square(), x2); - assert_eq!(x, computed_x); - - fn add<'a>(curr: (Fq, Fq), other: &'a (Fq, Fq)) -> (Fq, Fq) { - let y1y2 = curr.1 * &other.1; - let x1x2 = curr.0 * &other.0; - let d = Fq::from_str( - "19257038036680949359750312669786877991949435402254120286184196891950884077233", - ) - .unwrap(); - let dx1x2y1y2 = d * &y1y2 * &x1x2; - - let d1 = Fq::one() + &dx1x2y1y2; - let d2 = Fq::one() - &dx1x2y1y2; - - let x1y2 = curr.0 * &other.1; - let y1x2 = curr.1 * &other.0; - - let x = (x1y2 + &y1x2) / &d1; - let y = (y1y2 + &x1x2) / &d2; - - (x, y) - } - - let result = add((x, y), &(x, y)); - let result = add(result, &result); - let result = add(result, &result); - - let point_x = Fq::from_str( - "47259664076168047050113154262636619161204477920503059672059915868534495873964", - ) - .unwrap(); - let point_y = Fq::from_str( - "19016409245280491801573912449420132838852726543024859389273314249842195919690", - ) - .unwrap(); - assert_eq!((point_x, point_y), result); -} - #[test] fn test_fq_square_in_place() { let mut f1 = Fq::from_str( - "34864651240005695523200639428464570946052769938774601449735727714436878540682", + "21864651240005695523200639428464570946052769938774601449735727714436878540682", ) .unwrap(); let f3 = - Fq::from_str("213133100629336594719108316042277780359104840987226496279264105585804377948") + Fq::from_str("19581484219153942072047858331099766329275818131597627721493461404774907481642") .unwrap(); assert!(!f1.is_zero()); assert!(!f3.is_zero()); @@ -281,11 +198,11 @@ fn test_fq_square_in_place() { #[test] fn test_fq_sqrt() { let f1 = Fq::from_str( - "10875927553327821418567659853801220899541454800710193788767706167237535308235", + "10875927553327821418567659853801220899541454800710193788767706167237535308236", ) .unwrap(); let f3 = Fq::from_str( - "10816221372957505053219354782681292880545918527618367765651802809826238616708", + "14305375816171855067009304014627046917501979889993032068503214923182596004917", ) .unwrap(); assert_eq!(f1.sqrt().unwrap(), f3); @@ -294,20 +211,20 @@ fn test_fq_sqrt() { #[test] fn test_fq_from_str() { let f1_from_repr = Fq::from_repr(BigInteger([ - 0xab8a2535947d1a77, - 0x9ba74cbfda0bbcda, - 0xe928b59724d60baf, - 0x1cccaaeb9bb1680a, + 0x17a655e2b3cd9f8a, + 0xe98745acbc60cf8, + 0x8318964c0b265e48, + 0x3056f43c9ee293fd ])); let f1 = Fq::from_str( - "13026376210409056429264774981357153555336288129100724591327877625017068755575", + "21864651240005695523200639428464570946052769938774601449735727714436878540682", ) .unwrap(); let f2_from_repr = Fq::from_repr(BigInteger([ 0x97e9103775d2f35c, 0xbe6756b6c587544b, 0x6ee38c3afd88ef4b, - 0x2bacd150f540c677, + 0x2bacd150f540c677 ])); let f2 = Fq::from_str( "19754794831832707859764530223239420866832328728734160755396495950822165902172", @@ -322,20 +239,14 @@ fn test_fq_legendre() { assert_eq!(QuadraticResidue, Fq::one().legendre()); assert_eq!(Zero, Fq::zero().legendre()); - let e = BigInteger([ - 0x0dbc5349cd5664da, - 0x8ac5b6296e3ae29d, - 0x127cb819feceaa3b, - 0x3a6b21fb03867191, - ]); - assert_eq!(QuadraticResidue, Fq::from_repr(e).legendre()); - let e = BigInteger([ - 0x96341aefd047c045, - 0x9b5f4254500a4d65, - 0x1ee08223b68ac240, - 0x31d9cd545c0ec7c6, - ]); - assert_eq!(QuadraticNonResidue, Fq::from_repr(e).legendre()); + let e = Fq::from_str( + "19754794831832707859764530223239420866832328728734160755396495950822165902172", + ).unwrap(); + assert_eq!(QuadraticResidue, e.legendre()); + let e = Fq::from_str( + "7894070009960485405056471228743059385328854667547937089962899125529157892247", + ).unwrap(); + assert_eq!(QuadraticNonResidue, e.legendre()); } #[test] @@ -356,47 +267,41 @@ fn test_fq_bytes() { #[test] fn test_fr_add() { - let f1 = Fr::from_repr(BigInteger([ - 0xc81265fb4130fe0c, - 0xb308836c14e22279, - 0x699e887f96bff372, - 0x84ecc7e76c11ad, - ])); - let f2 = Fr::from_repr(BigInteger([ - 0x71875719b422efb8, - 0x43658e68a93612, - 0x9fa756be2011e833, - 0xaa2b2cb08dac497, - ])); - let f3 = Fr::from_repr(BigInteger([ - 0x3999bd14f553edc4, - 0xb34be8fa7d8b588c, - 0x945df3db6d1dba5, - 0xb279f92f046d645, - ])); + let f1 = Fr::from_str( + "28343809612844640454129919255697536258606705076971130519928764925719046689317", + ) + .unwrap(); + let f2 = Fr::from_str( + "10565087619621820656254220984570060779538680183776893272687321117751927412212", + ) + .unwrap(); + let f3 = Fr::from_str( + "9960874923137412254491393988095620074823181604792704735842768974107331995672", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); assert_eq!(f1 + &f2, f3); } #[test] fn test_fr_mul() { - let f1 = Fr::from_repr(BigInteger([ - 0xc81265fb4130fe0c, - 0xb308836c14e22279, - 0x699e887f96bff372, - 0x84ecc7e76c11ad, - ])); - let f2 = Fr::from_repr(BigInteger([ - 0x71875719b422efb8, - 0x43658e68a93612, - 0x9fa756be2011e833, - 0xaa2b2cb08dac497, - ])); - let f3 = Fr::from_repr(BigInteger([ - 0xf628897043db7339, - 0x15beccc45da84542, - 0x291fa8ad05b401fb, - 0x1a4b21d583e6284b - ])); + let f1 = Fr::from_str( + "24703123148064348394273033316595937198355721297494556079070134653139656190956", + ) + .unwrap(); + let f2 = Fr::from_str( + "18196797080882758914424853878212529985425118523754343117256179679117054302131", + ) + .unwrap(); + let f3 = Fr::from_str( + "3313453718804050382618227313767372842847071020036631866735220624776250855218", + ) + .unwrap(); + assert!(!f1.is_zero()); + assert!(!f2.is_zero()); + assert!(!f3.is_zero()); assert_eq!(f1 * &f2, f3); } From 4bacbe9e4c4b60fb7cb42e86a217e25c58877902 Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Tue, 19 Jan 2021 10:56:22 +0100 Subject: [PATCH 45/63] Revert "Merge branch 'all' into algebra_ocl" This reverts commit a0b423f2052f47672cd1c1c0b25692014d336df1, reversing changes made to 35d81135b9e82be4a0dd3ae7ad79843afc946e15. --- primitives/src/crh/mod.rs | 15 +++++--- primitives/src/crh/poseidon/mod.rs | 41 +++++++++++++++++---- r1cs/gadgets/crypto/src/crh/mod.rs | 2 +- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 9 +++-- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/primitives/src/crh/mod.rs b/primitives/src/crh/mod.rs index 0b0b70b6d..1d216a186 100644 --- a/primitives/src/crh/mod.rs +++ b/primitives/src/crh/mod.rs @@ -116,8 +116,11 @@ pub trait AlgebraicSponge: Clone { fn new() -> Self; /// Update the sponge with `elems` fn absorb(&mut self, elems: Vec); - /// Output `num` field elements from the sponge. - fn squeeze(&mut self, num: usize) -> Vec; + /// Output `num` field elements from the sponge. This function + /// is idempotent and calling it multiple times will result + /// in the same outputs, unless more absorbing are performed + /// in between the calls. + fn squeeze(&self, num: usize) -> Vec; } #[cfg(test)] @@ -175,7 +178,7 @@ mod test { pub(crate) fn algebraic_sponge_test, F: PrimeField>( to_absorb: Vec, - expected_squeeze: F + expected_squeezes: Vec ) { let mut sponge = H::new(); @@ -183,8 +186,10 @@ mod test { // Absorb all field elements sponge.absorb(to_absorb); - // Squeeze and check the output - assert_eq!(expected_squeeze, sponge.squeeze(1)[0]); + // Squeeze and check the outputs + for i in 0..expected_squeezes.len() { + assert_eq!(&expected_squeezes[..i + 1], &sponge.squeeze(i + 1)[..]); + } } #[ignore] diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 9bf51b2b9..37135deae 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -227,14 +227,15 @@ impl AlgebraicSponge for PoseidonHash }) } - fn squeeze(&mut self, num: usize) -> Vec { - for (input, s) in self.pending.iter().zip(self.state.iter_mut()) { + fn squeeze(&self, num: usize) -> Vec { + let mut state = self.state.clone(); + for (input, s) in self.pending.iter().zip(state.iter_mut()) { *s += input; } let mut output = Vec::with_capacity(num); for _ in 0..num { - Self::poseidon_perm(&mut self.state); - output.push(self.state[0].clone()); + Self::poseidon_perm(&mut state); + output.push(state[0].clone()); } output } @@ -287,7 +288,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), + vec![ + MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), + MNT4753Fr::new(BigInteger768([16127953875295592987, 11894863219027726126, 17701631661641187911, 14870672795897948467, 12477792521878046393, 7933118744616181152, 16504185330957910903, 4440754255912752398, 2147815826017548215, 15556058995384616380, 7316328326052908756, 488587201854075])), + MNT4753Fr::new(BigInteger768([17093615125500557324, 5853740299004434536, 14185517698974334849, 15081129818867394374, 4393775450585412195, 15317350057972385858, 602096567370343479, 171645566249469757, 213587553721144028, 16770187529782220214, 10656253922486106039, 183907258171817])), + MNT4753Fr::new(BigInteger768([12712297803466521417, 5718281485803573501, 13963200307320285636, 13279387328772122744, 11400771971860800684, 18129978631072081884, 16152730030736233432, 4443584430842639200, 10168547976596639262, 8852760702638429316, 6245616001490582246, 290914933918621])), + MNT4753Fr::new(BigInteger768([10000480287694253354, 5873338108557543580, 14250396374254092226, 15940814885061001617, 7624733801679967429, 10913153568558026344, 10086885331318146225, 5264350148957133820, 9338271530149930761, 15261863060094932371, 15830626088040155644, 456905335294658])) + ] ); } @@ -316,7 +323,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), + vec![ + MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), + MNT6753Fr::new(BigInteger768([893755365716394547, 9594068362757650017, 10451094618402356015, 6337497625726267689, 4160278191670220893, 6010491150125800070, 828252792235881440, 2673899143833542881, 13863607618619424503, 10731000306034932792, 12767597931406600360, 152088456622435])), + MNT6753Fr::new(BigInteger768([2814201016530476081, 8511720540093155210, 4852589771558571678, 13110129496171929816, 4735221329350745796, 12663409230803838109, 11568212364226125976, 1693070022169342918, 2888127900540921339, 4204338349274483900, 15311382501005232626, 438220753471979])), + MNT6753Fr::new(BigInteger768([1775158153332815483, 2026417705400082199, 11123169942942274855, 14330277722886619530, 7836191979464539572, 4865965751577341882, 16998150036867812011, 2739207342391276882, 4247579097230352822, 6464967486406868296, 10032824663714337053, 463362661909267])), + MNT6753Fr::new(BigInteger768([17595647052173133652, 5444801609492079542, 17111761943624358533, 9849391399095026693, 263233265735065436, 1281866738651078101, 2333944581006551597, 13500573177506341637, 10203063908384511927, 15054379420590094900, 13913006388276371623, 451783078041284])) + ] ); } @@ -339,7 +352,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), + vec![ + BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), + BN382Fr::new(BigInteger384([696581192457039113, 7735026456746748023, 2858087404435942973, 8551026292503659964, 10649071471792522052, 1622107112684056397])), + BN382Fr::new(BigInteger384([13847543644949650964, 4311663852800204305, 4992676739644232980, 4027896082677996619, 12253082643656956806, 534636992911167858])), + BN382Fr::new(BigInteger384([13260537455622274637, 17371511872105869645, 1623345855391475943, 1872797973978834237, 7609952746869694608, 847112821092614604])), + BN382Fr::new(BigInteger384([2836595273011902376, 5748666575747773318, 13745164138914401597, 11231420449817912461, 3298276789500282573, 1513701281573365844])) + ] ); } @@ -354,7 +373,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), + vec![ + BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), + BN382Fq::new(BigInteger384([4268335443493036543, 5752606093574636763, 7217511812669325408, 5182020843125294140, 5400661559267345372, 2261580635543305540])), + BN382Fq::new(BigInteger384([1487056021032845247, 4971413697289841114, 829985713515651434, 17668516547215117574, 6183480290866190120, 2494711740844925696])), + BN382Fq::new(BigInteger384([12440731074295045789, 13776548474636848476, 9611723257742392848, 14113646477500207966, 2479383220929757679, 2462018425115041259])), + BN382Fq::new(BigInteger384([13447602317280700149, 7333172335365879673, 3401105980077026956, 7168529825556409731, 18013175927097546368, 369466729188096152])), + ] ); } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/mod.rs b/r1cs/gadgets/crypto/src/crh/mod.rs index 9f13c6c09..1f38ab7ca 100644 --- a/r1cs/gadgets/crypto/src/crh/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/mod.rs @@ -72,7 +72,7 @@ pub trait AlgebraicSpongeGadget, ConstraintF: Pr ) -> Result<(), SynthesisError>; fn enforce_squeeze>( - &mut self, + &self, cs: CS, num: usize, ) -> Result, SynthesisError>; diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index d62b10b4a..12e3ecaaa 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -316,17 +316,18 @@ for PoseidonHashGadget } fn enforce_squeeze>( - &mut self, + &self, mut cs: CS, num: usize ) -> Result, SynthesisError> { - for (i, (input, state)) in self.pending.iter().zip(self.state.iter_mut()).enumerate() { + let mut state = self.state.clone(); + for (i, (input, state)) in self.pending.iter().zip(state.iter_mut()).enumerate() { state.add_in_place(cs.ns(|| format!("add_input_{}_to_state", i)), input)?; } let mut output = Vec::with_capacity(num); for i in 0..num { - Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut self.state)?; - output.push(self.state[0].clone()) + Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut state)?; + output.push(state[0].clone()) } Ok(output) } From d5d44f2c76da569fa6d697f639d9217cc1fe2216 Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Tue, 19 Jan 2021 11:04:35 +0100 Subject: [PATCH 46/63] Revert "Merge branch 'all' into algebra_ocl" This reverts commit 35d81135b9e82be4a0dd3ae7ad79843afc946e15, reversing changes made to 9849e49cd2e353ea1e8646386675bd58b1864c6d. --- primitives/src/crh/mod.rs | 64 +---- primitives/src/crh/poseidon/mod.rs | 267 +++++++++----------- primitives/src/lib.rs | 7 + r1cs/gadgets/crypto/src/crh/mod.rs | 106 +------- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 259 +++++++++++-------- 5 files changed, 285 insertions(+), 418 deletions(-) diff --git a/primitives/src/crh/mod.rs b/primitives/src/crh/mod.rs index 1d216a186..0eada8a89 100644 --- a/primitives/src/crh/mod.rs +++ b/primitives/src/crh/mod.rs @@ -1,5 +1,5 @@ use algebra::{ - Field, PrimeField, bytes::ToBytes + Field, bytes::ToBytes }; use rand::Rng; use std::hash::Hash; @@ -110,24 +110,11 @@ pub trait BatchFieldBasedHash { } } -/// the trait for algebraic sponge -pub trait AlgebraicSponge: Clone { - /// Initialize the sponge - fn new() -> Self; - /// Update the sponge with `elems` - fn absorb(&mut self, elems: Vec); - /// Output `num` field elements from the sponge. This function - /// is idempotent and calling it multiple times will result - /// in the same outputs, unless more absorbing are performed - /// in between the calls. - fn squeeze(&self, num: usize) -> Vec; -} - #[cfg(test)] mod test { use algebra::{ - fields::mnt4753::Fr as MNT4753Fr, Field, PrimeField, UniformRand + fields::mnt4753::Fr as MNT4753Fr, Field, UniformRand }; use super::BatchFieldBasedHash; @@ -137,9 +124,6 @@ mod test { use rand_xorshift::XorShiftRng; use rand::SeedableRng; - use crate::{ - FieldBasedHash, AlgebraicSponge - }; struct DummyMNT4BatchPoseidonHash; @@ -148,50 +132,6 @@ mod test { type BaseHash = MNT4PoseidonHash; } - pub(crate) fn field_based_hash_test( - personalization: Option<&[H::Data]>, - inputs: Vec, - expected_output: H::Data - ) - { - // Test H(inputs) == expected_output - let mut digest = H::init(personalization); - inputs.iter().for_each(|fe| { digest.update(fe.clone()); }); - let output = digest.finalize(); - assert_eq!(output, expected_output, "Outputs do not match"); - - let inputs_len = inputs.len(); - if inputs_len > 1 { - let final_elem = inputs[inputs_len - 1].clone(); - // Test finalize() holding the state and allowing updates in between different calls to it - digest.reset(None); - inputs.into_iter().take(inputs_len - 1).for_each(|fe| { digest.update(fe); }); - - digest.finalize(); - digest.update(final_elem); - assert_eq!(output, digest.finalize()); - - //Test finalize() being idempotent - assert_eq!(output, digest.finalize()); - } - } - - pub(crate) fn algebraic_sponge_test, F: PrimeField>( - to_absorb: Vec, - expected_squeezes: Vec - ) - { - let mut sponge = H::new(); - - // Absorb all field elements - sponge.absorb(to_absorb); - - // Squeeze and check the outputs - for i in 0..expected_squeezes.len() { - assert_eq!(&expected_squeezes[..i + 1], &sponge.squeeze(i + 1)[..]); - } - } - #[ignore] #[test] fn test_default_batch_hash_implementation() { diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 37135deae..0834b1986 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -17,7 +17,6 @@ pub use self::parameters::*; pub mod sbox; pub use self::sbox::*; -use crate::AlgebraicSponge; pub trait PoseidonParameters: 'static + FieldBasedHashParameters + Clone { const T: usize; // Number of S-Boxes @@ -30,11 +29,7 @@ pub trait PoseidonParameters: 'static + FieldBasedHashParameters + Clone { const MDS_CST: &'static[Self::Fr]; // The MDS matrix } -#[derive(Derivative)] -#[derivative( - Clone(bound = ""), - Debug(bound = "") -)] +#[derive(Debug)] pub struct PoseidonHash, SB: PoseidonSBox

>{ state: Vec, pending: Vec, @@ -49,21 +44,22 @@ impl PoseidonHash SB: PoseidonSBox

, { #[inline] - fn apply_permutation(&mut self, add_c2: bool) { + fn apply_permutation(&mut self) { for (input, state) in self.pending.iter().zip(self.state.iter_mut()) { *state += input; } - if add_c2 { self.state[P::R] += &P::C2 }; + self.state[P::R] += &P::C2; Self::poseidon_perm(&mut self.state); } #[inline] - fn _finalize(&self, state: &mut Vec, add_c2: bool) -> F { + fn _finalize(&self) -> F { + let mut state = self.state.clone(); for (input, s) in self.pending.iter().zip(state.iter_mut()) { *s += input; } - if add_c2 { state[P::R] += &P::C2; } - Self::poseidon_perm(state); + state[P::R] += &P::C2; + Self::poseidon_perm(&mut state); state[0] } @@ -138,8 +134,6 @@ impl FieldBasedHash for PoseidonHash type Parameters = P; fn init(personalization: Option<&[Self::Data]>) -> Self { - assert_eq!(P::T - P::R, 1, "The assumption that the capacity is one field element is not satisfied."); - let mut state = Vec::with_capacity(P::T); for i in 0..P::T { state.push(P::AFTER_ZERO_PERM[i]); @@ -186,7 +180,7 @@ impl FieldBasedHash for PoseidonHash fn update(&mut self, input: Self::Data) -> &mut Self { self.pending.push(input); if self.pending.len() == P::R { - self.apply_permutation(true); + self.apply_permutation(); self.pending.clear(); } self @@ -194,7 +188,7 @@ impl FieldBasedHash for PoseidonHash fn finalize(&self) -> Self::Data { if !self.pending.is_empty() { - self._finalize(&mut self.state.clone(), true) + self._finalize() } else { self.state[0] } @@ -207,130 +201,118 @@ impl FieldBasedHash for PoseidonHash } } -impl AlgebraicSponge for PoseidonHash - where - F: PrimeField, - P: PoseidonParameters, - SB: PoseidonSBox

, -{ - fn new() -> Self { - Self::init(None) - } - - fn absorb(&mut self, elems: Vec) { - elems.into_iter().for_each(|f| { - self.pending.push(f); - if self.pending.len() == P::R { - self.apply_permutation(false); - self.pending.clear(); - } - }) - } - - fn squeeze(&self, num: usize) -> Vec { - let mut state = self.state.clone(); - for (input, s) in self.pending.iter().zip(state.iter_mut()) { - *s += input; - } - let mut output = Vec::with_capacity(num); - for _ in 0..num { - Self::poseidon_perm(&mut state); - output.push(state[0].clone()); - } - output - } -} - #[cfg(test)] mod test { - use algebra::{fields::{ - mnt4753::Fr as MNT4753Fr, - mnt6753::Fr as MNT6753Fr, - }, PrimeField}; + use algebra::{ + fields::{ + mnt4753::Fr as MNT4753Fr, + mnt6753::Fr as MNT6753Fr, + }, + }; + use std::str::FromStr; use algebra::biginteger::BigInteger768; use crate::crh::{ poseidon::parameters::{ mnt4753::MNT4PoseidonHash, mnt6753::MNT6PoseidonHash, }, - test::{field_based_hash_test, algebraic_sponge_test} + FieldBasedHash, }; - fn generate_inputs(num: usize) -> Vec{ - let mut inputs = Vec::with_capacity(num); - for i in 1..=num { - let input = F::from(i as u32); - inputs.push(input); - } - inputs + #[test] + fn test_poseidon_hash_mnt4() { + + // Regression test + let expected_output = MNT4753Fr::new(BigInteger768([120759599714708995, 15132412086599307425, 1270378153255747692, 3280164418217209635, 5680179791594071572, 2475152338055275001, 9455820118751334058, 6363436228419696186, 3538976751580678769, 14987158621073838958, 10703097083485496843, 48481977539350])); + let mut poseidon_digest = MNT4PoseidonHash::init(None); + let input = [MNT4753Fr::from_str("1").unwrap(), MNT4753Fr::from_str("2").unwrap()]; + + let output = poseidon_digest + .update(input[0]) + .update(input[1]) + .finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); + + // Test finalize() holding the state and allowing updates in between different calls to it + poseidon_digest + .reset(None) + .update(input[0].clone()); + poseidon_digest.finalize(); + poseidon_digest.update(input[1].clone()); + assert_eq!(output, poseidon_digest.finalize()); + + //Test finalize() being idempotent + assert_eq!(output, poseidon_digest.finalize()); } #[test] - fn test_poseidon_hash_mnt4() { - field_based_hash_test::( - None, - generate_inputs(1), - MNT4753Fr::new(BigInteger768([10133114337753187244, 13011129467758174047, 14520750556687040981, 911508844858788085, 1859877757310385382, 9602832310351473622, 8300303689130833769, 981323167857397563, 5760566649679562093, 8644351468476031499, 10679665778836668809, 404482168782668])) - ); - - field_based_hash_test::( - None, - generate_inputs(2), - MNT4753Fr::new(BigInteger768([120759599714708995, 15132412086599307425, 1270378153255747692, 3280164418217209635, 5680179791594071572, 2475152338055275001, 9455820118751334058, 6363436228419696186, 3538976751580678769, 14987158621073838958, 10703097083485496843, 48481977539350])) - ); - - field_based_hash_test::( - None, - generate_inputs(3), - MNT4753Fr::new(BigInteger768([5991160601160569512, 9804741598782512164, 8257389273544061943, 15170134696519047397, 9908596892162673198, 7815454566429677811, 9000639780203615183, 8443915450757188195, 1987926952117715938, 17724141978374492147, 13890449093436164383, 191068391234529])) - - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), - MNT4753Fr::new(BigInteger768([16127953875295592987, 11894863219027726126, 17701631661641187911, 14870672795897948467, 12477792521878046393, 7933118744616181152, 16504185330957910903, 4440754255912752398, 2147815826017548215, 15556058995384616380, 7316328326052908756, 488587201854075])), - MNT4753Fr::new(BigInteger768([17093615125500557324, 5853740299004434536, 14185517698974334849, 15081129818867394374, 4393775450585412195, 15317350057972385858, 602096567370343479, 171645566249469757, 213587553721144028, 16770187529782220214, 10656253922486106039, 183907258171817])), - MNT4753Fr::new(BigInteger768([12712297803466521417, 5718281485803573501, 13963200307320285636, 13279387328772122744, 11400771971860800684, 18129978631072081884, 16152730030736233432, 4443584430842639200, 10168547976596639262, 8852760702638429316, 6245616001490582246, 290914933918621])), - MNT4753Fr::new(BigInteger768([10000480287694253354, 5873338108557543580, 14250396374254092226, 15940814885061001617, 7624733801679967429, 10913153568558026344, 10086885331318146225, 5264350148957133820, 9338271530149930761, 15261863060094932371, 15830626088040155644, 456905335294658])) - ] - ); + fn test_poseidon_hash_mnt4_single_element() { + let expected_output = MNT4753Fr::new(BigInteger768([10133114337753187244, 13011129467758174047, 14520750556687040981, 911508844858788085, 1859877757310385382, 9602832310351473622, 8300303689130833769, 981323167857397563, 5760566649679562093, 8644351468476031499, 10679665778836668809, 404482168782668])); + let mut poseidon_digest = MNT4PoseidonHash::init(None); + poseidon_digest.update(MNT4753Fr::from_str("1").unwrap()); + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); } #[test] - fn test_poseidon_hash_mnt6() { - let expected_output = MNT6753Fr::new(BigInteger768([9820480440897423048, 13953114361017832007, 6124683910518350026, 12198883805142820977, 16542063359667049427, 16554395404701520536, 6092728884107650560, 1511127385771028618, 14755502041894115317, 9806346309586473535, 5880260960930089738, 191119811429922])); - field_based_hash_test::( - None, - generate_inputs(1), - expected_output - ); + fn test_poseidon_hash_mnt4_three_element() { + let expected_output = MNT4753Fr::new(BigInteger768([5991160601160569512, 9804741598782512164, 8257389273544061943, 15170134696519047397, 9908596892162673198, 7815454566429677811, 9000639780203615183, 8443915450757188195, 1987926952117715938, 17724141978374492147, 13890449093436164383, 191068391234529])); + let mut poseidon_digest = MNT4PoseidonHash::init(None); + + for i in 1..=3{ + poseidon_digest.update(MNT4753Fr::from(i as u64)); + } + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); + } + + #[test] + fn test_poseidon_hash_mnt6() { let expected_output = MNT6753Fr::new(BigInteger768([8195238283171732026, 13694263410588344527, 1885103367289967816, 17142467091011072910, 13844754763865913168, 14332001103319040991, 8911700442280604823, 6452872831806760781, 17467681867740706391, 5384727593134901588, 2343350281633109128, 244405261698305])); - field_based_hash_test::( - None, - generate_inputs(2), - expected_output - ); + let mut poseidon_digest = MNT6PoseidonHash::init(None); + let input = [MNT6753Fr::from_str("1").unwrap(), MNT6753Fr::from_str("2").unwrap()]; + + let output = poseidon_digest + .update(input[0]) + .update(input[1]) + .finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); + + // Test finalize() holding the state and allowing updates in between different calls to it + poseidon_digest + .reset(None) + .update(input[0].clone()); + poseidon_digest.finalize(); + poseidon_digest.update(input[1].clone()); + assert_eq!(output, poseidon_digest.finalize()); + + //Test finalize() being idempotent + assert_eq!(output, poseidon_digest.finalize()); + } + #[test] + fn test_poseidon_hash_mnt6_single_element() { + let expected_output = MNT6753Fr::new(BigInteger768([9820480440897423048, 13953114361017832007, 6124683910518350026, 12198883805142820977, 16542063359667049427, 16554395404701520536, 6092728884107650560, 1511127385771028618, 14755502041894115317, 9806346309586473535, 5880260960930089738, 191119811429922])); + let mut poseidon_digest = MNT6PoseidonHash::init(None); + let input = MNT6753Fr::from_str("1").unwrap(); + poseidon_digest.update(input); + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); + } + + #[test] + fn test_poseidon_hash_mnt6_three_element() { let expected_output = MNT6753Fr::new(BigInteger768([13800884891843937189, 3814452749758584714, 14612220153016028606, 15886322817426727111, 12444362646204085653, 5214641378156871899, 4248022398370599899, 5982332416470364372, 3842784910369906888, 11445718704595887413, 5723531295320926061, 101830932453997])); - field_based_hash_test::( - None, - generate_inputs(3), - expected_output - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), - MNT6753Fr::new(BigInteger768([893755365716394547, 9594068362757650017, 10451094618402356015, 6337497625726267689, 4160278191670220893, 6010491150125800070, 828252792235881440, 2673899143833542881, 13863607618619424503, 10731000306034932792, 12767597931406600360, 152088456622435])), - MNT6753Fr::new(BigInteger768([2814201016530476081, 8511720540093155210, 4852589771558571678, 13110129496171929816, 4735221329350745796, 12663409230803838109, 11568212364226125976, 1693070022169342918, 2888127900540921339, 4204338349274483900, 15311382501005232626, 438220753471979])), - MNT6753Fr::new(BigInteger768([1775158153332815483, 2026417705400082199, 11123169942942274855, 14330277722886619530, 7836191979464539572, 4865965751577341882, 16998150036867812011, 2739207342391276882, 4247579097230352822, 6464967486406868296, 10032824663714337053, 463362661909267])), - MNT6753Fr::new(BigInteger768([17595647052173133652, 5444801609492079542, 17111761943624358533, 9849391399095026693, 263233265735065436, 1281866738651078101, 2333944581006551597, 13500573177506341637, 10203063908384511927, 15054379420590094900, 13913006388276371623, 451783078041284])) - ] - ); + let mut poseidon_digest = MNT6PoseidonHash::init(None); + + for i in 1..=3{ + let input = MNT6753Fr::from(i as u64); + poseidon_digest.update(input); + } + + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); } use algebra::{ @@ -344,42 +326,25 @@ mod test { #[test] fn test_poseidon_hash_bn382_fr() { let expected_output = BN382Fr::new(BigInteger384([5374955110091081208, 9708994766202121080, 14988884941712225891, 5210165913215347951, 13114182334648522197, 392522167697949297])); - field_based_hash_test::( - None, - generate_inputs(2), - expected_output - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), - BN382Fr::new(BigInteger384([696581192457039113, 7735026456746748023, 2858087404435942973, 8551026292503659964, 10649071471792522052, 1622107112684056397])), - BN382Fr::new(BigInteger384([13847543644949650964, 4311663852800204305, 4992676739644232980, 4027896082677996619, 12253082643656956806, 534636992911167858])), - BN382Fr::new(BigInteger384([13260537455622274637, 17371511872105869645, 1623345855391475943, 1872797973978834237, 7609952746869694608, 847112821092614604])), - BN382Fr::new(BigInteger384([2836595273011902376, 5748666575747773318, 13745164138914401597, 11231420449817912461, 3298276789500282573, 1513701281573365844])) - ] - ); + + let mut digest = BN382FrPoseidonHash::init(None); + digest.update(BN382Fr::from_str("1").unwrap()); + digest.update(BN382Fr::from_str("2").unwrap()); + let output = digest.finalize(); + + assert_eq!(output, expected_output, "Outputs do not match for BN382Fr"); } #[test] fn test_poseidon_hash_bn382_fq() { let expected_output = BN382Fq::new(BigInteger384([10704305393280846886, 13510271104066299406, 8759721062701909552, 14597420682011858322, 7770486455870140465, 1389855295932765543])); - field_based_hash_test::( - None, - generate_inputs(2), - expected_output - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), - BN382Fq::new(BigInteger384([4268335443493036543, 5752606093574636763, 7217511812669325408, 5182020843125294140, 5400661559267345372, 2261580635543305540])), - BN382Fq::new(BigInteger384([1487056021032845247, 4971413697289841114, 829985713515651434, 17668516547215117574, 6183480290866190120, 2494711740844925696])), - BN382Fq::new(BigInteger384([12440731074295045789, 13776548474636848476, 9611723257742392848, 14113646477500207966, 2479383220929757679, 2462018425115041259])), - BN382Fq::new(BigInteger384([13447602317280700149, 7333172335365879673, 3401105980077026956, 7168529825556409731, 18013175927097546368, 369466729188096152])), - ] - ); + + let mut digest = BN382FqPoseidonHash::init(None); + digest.update(BN382Fq::from_str("1").unwrap()); + digest.update(BN382Fq::from_str("2").unwrap()); + let output = digest.finalize(); + + assert_eq!(output, expected_output, "Outputs do not match for BN382Fq"); } + } \ No newline at end of file diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 8475d57e3..f8ca20945 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,6 +1,13 @@ #[macro_use] extern crate bench_utils; +#[cfg(any( + feature = "commitment", + feature = "merkle_tree", + feature = "prf", + feature = "signature", + feature = "vrf" +))] #[macro_use] extern crate derivative; diff --git a/r1cs/gadgets/crypto/src/crh/mod.rs b/r1cs/gadgets/crypto/src/crh/mod.rs index 1f38ab7ca..6546d24bc 100644 --- a/r1cs/gadgets/crypto/src/crh/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/mod.rs @@ -1,6 +1,4 @@ -use algebra::{ - Field, PrimeField -}; +use algebra::Field; use std::fmt::Debug; use primitives::crh::{ @@ -19,7 +17,6 @@ pub use self::sbox::*; pub mod poseidon; pub use self::poseidon::*; -use primitives::AlgebraicSponge; pub trait FixedLengthCRHGadget: Sized { type OutputGadget: EqGadget @@ -58,105 +55,4 @@ pub trait FieldHasherGadget< cs: CS, personalization: Option<&[HG::DataGadget]> ) -> Result; -} - -pub trait AlgebraicSpongeGadget, ConstraintF: PrimeField>: Sized { - type DataGadget: FieldGadget; - - fn new>(cs: CS) -> Result; - - fn enforce_absorb>( - &mut self, - cs: CS, - input: &[Self::DataGadget], - ) -> Result<(), SynthesisError>; - - fn enforce_squeeze>( - &self, - cs: CS, - num: usize, - ) -> Result, SynthesisError>; -} - -#[cfg(test)] -mod test { - use algebra::PrimeField; - use primitives::{ - FieldBasedHash, AlgebraicSponge - }; - use crate::{ - FieldBasedHashGadget, AlgebraicSpongeGadget, - }; - use r1cs_std::{ - fields::fp::FpGadget, - test_constraint_system::TestConstraintSystem, - alloc::AllocGadget, - }; - use r1cs_core::ConstraintSystem; - - pub(crate) fn field_based_hash_gadget_native_test< - F: PrimeField, - H: FieldBasedHash, - HG: FieldBasedHashGadget> - >(inputs: Vec) - { - let mut cs = TestConstraintSystem::::new(); - - let primitive_result = { - let mut digest = H::init(None); - inputs.iter().for_each(|elem| { digest.update(*elem);}); - digest.finalize() - }; - - let mut input_gadgets = Vec::with_capacity(inputs.len()); - inputs.into_iter().enumerate().for_each(|(i, elem)|{ - let elem_gadget = HG::DataGadget::alloc( - cs.ns(|| format!("alloc input {}", i)), - || Ok(elem) - ).unwrap(); - input_gadgets.push(elem_gadget); - }); - - let gadget_result = HG::check_evaluation_gadget( - cs.ns(||"check_poseidon_gadget"), - input_gadgets.as_slice() - ).unwrap(); - - assert_eq!(primitive_result, gadget_result.value.unwrap()); - assert!(cs.is_satisfied()); - } - - pub(crate) fn algebraic_sponge_gadget_native_test< - F: PrimeField, - H: AlgebraicSponge, - HG: AlgebraicSpongeGadget> - >(inputs: Vec) - { - let mut cs = TestConstraintSystem::::new(); - - let mut primitive_sponge = H::new(); - primitive_sponge.absorb(inputs.clone()); - - let mut input_gadgets = Vec::with_capacity(inputs.len()); - inputs.iter().enumerate().for_each(|(i, elem)|{ - let elem_gadget = HG::DataGadget::alloc( - cs.ns(|| format!("alloc input {}", i)), - || Ok(elem.clone()) - ).unwrap(); - input_gadgets.push(elem_gadget); - }); - - let mut sponge_gadget = HG::new(cs.ns(|| "new poseidon sponge")).unwrap(); - sponge_gadget.enforce_absorb(cs.ns(|| "absorb inputs"), input_gadgets.as_slice()).unwrap(); - - for i in 0..inputs.len() { - let output_gadgets = sponge_gadget.enforce_squeeze( - cs.ns(|| format!("squeeze {} field elements", i + 1)), - i + 1 - ).unwrap().iter().map(|fe_gadget| fe_gadget.value.unwrap()).collect::>(); - assert_eq!(output_gadgets, primitive_sponge.squeeze(i + 1)); - } - - assert!(cs.is_satisfied()); - } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index 12e3ecaaa..c5269cf39 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -29,7 +29,6 @@ pub mod bn382; #[cfg(feature = "bn_382")] pub use self::bn382::*; use primitives::PoseidonSBox; -use crate::AlgebraicSpongeGadget; pub struct PoseidonHashGadget < @@ -39,9 +38,7 @@ pub struct PoseidonHashGadget SBG: SBoxGadget, > { - state: Vec>, - pending: Vec>, - + _field: PhantomData, _parameters: PhantomData

, _sbox: PhantomData, _sbox_gadget: PhantomData, @@ -111,6 +108,7 @@ impl< (*d).add_constant_in_place(cs.ns(|| format!("add_constant_2_{}", round_cst_idx)), &rc)?; round_cst_idx += 1; } + } // Second full rounds @@ -262,119 +260,180 @@ impl FieldBasedHashGadget AlgebraicSpongeGadget, ConstraintF> -for PoseidonHashGadget - where - ConstraintF: PrimeField, - P: PoseidonParameters, - SB: PoseidonSBox

, - SBG: SBoxGadget, -{ - type DataGadget = FpGadget; - - fn new>(mut cs: CS) -> Result { - assert_eq!(P::T - P::R, 1, "The assumption that the capacity is one field element is not satisfied."); - - let mut state = Vec::new(); - for i in 0..P::T { - let elem = FpGadget::::from_value( - cs.ns(|| format!("hardcode_state_{}",i)), - &P::AFTER_ZERO_PERM[i] - ); - state.push(elem); - } - - Ok(Self { - state, - pending: Vec::with_capacity(P::R), - _parameters: PhantomData, - _sbox: PhantomData, - _sbox_gadget: PhantomData, - }) - } - - fn enforce_absorb>( - &mut self, - mut cs: CS, - elems: &[Self::DataGadget] - ) -> Result<(), SynthesisError> { - elems.iter().enumerate().map(|(i, f)| { - self.pending.push(f.clone()); - if self.pending.len() == P::R { - // add the elements to the state vector. Add rate elements - for (j, (input, state)) in self.pending.iter().zip(self.state.iter_mut()).enumerate() { - state.add_in_place(cs.ns(|| format!("add_input_{}_{}_to_state", i, j)), input)?; - } - // apply permutation after adding the input vector - Self::poseidon_perm(cs.ns(|| format!("poseidon_perm_{}", i)), &mut self.state)?; - - self.pending.clear(); - } - Ok(()) - }).collect::>()?; - Ok(()) - } - - fn enforce_squeeze>( - &self, - mut cs: CS, - num: usize - ) -> Result, SynthesisError> { - let mut state = self.state.clone(); - for (i, (input, state)) in self.pending.iter().zip(state.iter_mut()).enumerate() { - state.add_in_place(cs.ns(|| format!("add_input_{}_to_state", i)), input)?; - } - let mut output = Vec::with_capacity(num); - for i in 0..num { - Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut state)?; - output.push(state[0].clone()) - } - Ok(output) - } -} - #[cfg(test)] mod test { + use rand::thread_rng; + use r1cs_std::test_constraint_system::TestConstraintSystem; + use primitives::crh::{ + FieldBasedHash, + MNT4PoseidonHash, MNT6PoseidonHash, + BN382FrPoseidonHash, BN382FqPoseidonHash, + }; use crate::{ MNT4PoseidonHashGadget, MNT6PoseidonHashGadget, BN382FqPoseidonHashGadget, BN382FrPoseidonHashGadget, }; - - use algebra::fields::PrimeField; - use crate::crh::test::{ - field_based_hash_gadget_native_test, algebraic_sponge_gadget_native_test - }; - - fn generate_inputs(num: usize) -> Vec{ - let mut inputs = Vec::with_capacity(num); - for i in 1..=num { - let input = F::from(i as u32); - inputs.push(input); + use r1cs_std::{ + alloc::AllocGadget, + instantiated::{ + mnt4_753::FqGadget as Mnt6FieldGadget, + mnt6_753::FqGadget as Mnt4FieldGadget, + bn_382::FqGadget as BN382FqGadget, + bn_382::g::FqGadget as BN382FrGadget, } - inputs - } + }; + use r1cs_core::ConstraintSystem; + use algebra::UniformRand; + use super::*; + + use algebra::fields::{ + mnt4753::Fr as MNT4753Fr, + mnt6753::Fr as MNT6753Fr, + bn_382::Fr as BN382Fr, + bn_382::Fq as BN382Fq, + }; #[test] - fn poseidon_mnt4_753_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, MNT4PoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, MNT4PoseidonHashGadget>(generate_inputs(5)); + fn crh_mnt4_753_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem_4753 = Vec::new(); + let v1 = MNT4753Fr::rand(&mut rng); + let v2 = MNT4753Fr::rand(&mut rng); + vec_elem_4753.push(v1); + vec_elem_4753.push(v2); + + let primitive_result = { + let mut digest = MNT4PoseidonHash::init(None); + vec_elem_4753.into_iter().for_each(|elem| { digest.update(elem);}); + digest.finalize() + }; + + let v1_gadget = Mnt4FieldGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = Mnt4FieldGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + MNT4PoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } #[test] - fn poseidon_mnt6_753_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, MNT6PoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, MNT6PoseidonHashGadget>(generate_inputs(5)); + fn crh_mnt6_753_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem_6753 = Vec::new(); + let v1 = MNT6753Fr::rand(&mut rng); + let v2 = MNT6753Fr::rand(&mut rng); + vec_elem_6753.push(v1); + vec_elem_6753.push(v2); + + let primitive_result = { + let mut digest = MNT6PoseidonHash::init(None); + vec_elem_6753.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = Mnt6FieldGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = Mnt6FieldGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + MNT6PoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } #[test] - fn poseidon_bn382_fr_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, BN382FrPoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, BN382FrPoseidonHashGadget>(generate_inputs(5)); + fn crh_bn382_fr_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem = Vec::new(); + let v1 = BN382Fr::rand(&mut rng); + let v2 = BN382Fr::rand(&mut rng); + vec_elem.push(v1); + vec_elem.push(v2); + + let primitive_result = { + let mut digest = BN382FrPoseidonHash::init(None); + vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = BN382FrGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = BN382FrGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + BN382FrPoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } #[test] - fn poseidon_bn382_fq_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, BN382FqPoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, BN382FqPoseidonHashGadget>(generate_inputs(5)); + fn crh_bn382_fq_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem = Vec::new(); + let v1 = BN382Fq::rand(&mut rng); + let v2 = BN382Fq::rand(&mut rng); + vec_elem.push(v1); + vec_elem.push(v2); + + let primitive_result = { + let mut digest = BN382FqPoseidonHash::init(None); + vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = BN382FqGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = BN382FqGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + BN382FqPoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } } \ No newline at end of file From e2cfa150e50457d3685c2b6dcc74e306984789a6 Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Tue, 19 Jan 2021 11:19:10 +0100 Subject: [PATCH 47/63] Revert "Merge branch 'all' into algebra_ocl" This reverts commit a0b423f2052f47672cd1c1c0b25692014d336df1, reversing changes made to 35d81135b9e82be4a0dd3ae7ad79843afc946e15. --- primitives/src/crh/mod.rs | 15 +++++--- primitives/src/crh/poseidon/mod.rs | 41 +++++++++++++++++---- r1cs/gadgets/crypto/src/crh/mod.rs | 2 +- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 9 +++-- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/primitives/src/crh/mod.rs b/primitives/src/crh/mod.rs index 0b0b70b6d..1d216a186 100644 --- a/primitives/src/crh/mod.rs +++ b/primitives/src/crh/mod.rs @@ -116,8 +116,11 @@ pub trait AlgebraicSponge: Clone { fn new() -> Self; /// Update the sponge with `elems` fn absorb(&mut self, elems: Vec); - /// Output `num` field elements from the sponge. - fn squeeze(&mut self, num: usize) -> Vec; + /// Output `num` field elements from the sponge. This function + /// is idempotent and calling it multiple times will result + /// in the same outputs, unless more absorbing are performed + /// in between the calls. + fn squeeze(&self, num: usize) -> Vec; } #[cfg(test)] @@ -175,7 +178,7 @@ mod test { pub(crate) fn algebraic_sponge_test, F: PrimeField>( to_absorb: Vec, - expected_squeeze: F + expected_squeezes: Vec ) { let mut sponge = H::new(); @@ -183,8 +186,10 @@ mod test { // Absorb all field elements sponge.absorb(to_absorb); - // Squeeze and check the output - assert_eq!(expected_squeeze, sponge.squeeze(1)[0]); + // Squeeze and check the outputs + for i in 0..expected_squeezes.len() { + assert_eq!(&expected_squeezes[..i + 1], &sponge.squeeze(i + 1)[..]); + } } #[ignore] diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 9bf51b2b9..37135deae 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -227,14 +227,15 @@ impl AlgebraicSponge for PoseidonHash }) } - fn squeeze(&mut self, num: usize) -> Vec { - for (input, s) in self.pending.iter().zip(self.state.iter_mut()) { + fn squeeze(&self, num: usize) -> Vec { + let mut state = self.state.clone(); + for (input, s) in self.pending.iter().zip(state.iter_mut()) { *s += input; } let mut output = Vec::with_capacity(num); for _ in 0..num { - Self::poseidon_perm(&mut self.state); - output.push(self.state[0].clone()); + Self::poseidon_perm(&mut state); + output.push(state[0].clone()); } output } @@ -287,7 +288,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), + vec![ + MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), + MNT4753Fr::new(BigInteger768([16127953875295592987, 11894863219027726126, 17701631661641187911, 14870672795897948467, 12477792521878046393, 7933118744616181152, 16504185330957910903, 4440754255912752398, 2147815826017548215, 15556058995384616380, 7316328326052908756, 488587201854075])), + MNT4753Fr::new(BigInteger768([17093615125500557324, 5853740299004434536, 14185517698974334849, 15081129818867394374, 4393775450585412195, 15317350057972385858, 602096567370343479, 171645566249469757, 213587553721144028, 16770187529782220214, 10656253922486106039, 183907258171817])), + MNT4753Fr::new(BigInteger768([12712297803466521417, 5718281485803573501, 13963200307320285636, 13279387328772122744, 11400771971860800684, 18129978631072081884, 16152730030736233432, 4443584430842639200, 10168547976596639262, 8852760702638429316, 6245616001490582246, 290914933918621])), + MNT4753Fr::new(BigInteger768([10000480287694253354, 5873338108557543580, 14250396374254092226, 15940814885061001617, 7624733801679967429, 10913153568558026344, 10086885331318146225, 5264350148957133820, 9338271530149930761, 15261863060094932371, 15830626088040155644, 456905335294658])) + ] ); } @@ -316,7 +323,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), + vec![ + MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), + MNT6753Fr::new(BigInteger768([893755365716394547, 9594068362757650017, 10451094618402356015, 6337497625726267689, 4160278191670220893, 6010491150125800070, 828252792235881440, 2673899143833542881, 13863607618619424503, 10731000306034932792, 12767597931406600360, 152088456622435])), + MNT6753Fr::new(BigInteger768([2814201016530476081, 8511720540093155210, 4852589771558571678, 13110129496171929816, 4735221329350745796, 12663409230803838109, 11568212364226125976, 1693070022169342918, 2888127900540921339, 4204338349274483900, 15311382501005232626, 438220753471979])), + MNT6753Fr::new(BigInteger768([1775158153332815483, 2026417705400082199, 11123169942942274855, 14330277722886619530, 7836191979464539572, 4865965751577341882, 16998150036867812011, 2739207342391276882, 4247579097230352822, 6464967486406868296, 10032824663714337053, 463362661909267])), + MNT6753Fr::new(BigInteger768([17595647052173133652, 5444801609492079542, 17111761943624358533, 9849391399095026693, 263233265735065436, 1281866738651078101, 2333944581006551597, 13500573177506341637, 10203063908384511927, 15054379420590094900, 13913006388276371623, 451783078041284])) + ] ); } @@ -339,7 +352,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), + vec![ + BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), + BN382Fr::new(BigInteger384([696581192457039113, 7735026456746748023, 2858087404435942973, 8551026292503659964, 10649071471792522052, 1622107112684056397])), + BN382Fr::new(BigInteger384([13847543644949650964, 4311663852800204305, 4992676739644232980, 4027896082677996619, 12253082643656956806, 534636992911167858])), + BN382Fr::new(BigInteger384([13260537455622274637, 17371511872105869645, 1623345855391475943, 1872797973978834237, 7609952746869694608, 847112821092614604])), + BN382Fr::new(BigInteger384([2836595273011902376, 5748666575747773318, 13745164138914401597, 11231420449817912461, 3298276789500282573, 1513701281573365844])) + ] ); } @@ -354,7 +373,13 @@ mod test { algebraic_sponge_test::( generate_inputs(5), - BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), + vec![ + BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), + BN382Fq::new(BigInteger384([4268335443493036543, 5752606093574636763, 7217511812669325408, 5182020843125294140, 5400661559267345372, 2261580635543305540])), + BN382Fq::new(BigInteger384([1487056021032845247, 4971413697289841114, 829985713515651434, 17668516547215117574, 6183480290866190120, 2494711740844925696])), + BN382Fq::new(BigInteger384([12440731074295045789, 13776548474636848476, 9611723257742392848, 14113646477500207966, 2479383220929757679, 2462018425115041259])), + BN382Fq::new(BigInteger384([13447602317280700149, 7333172335365879673, 3401105980077026956, 7168529825556409731, 18013175927097546368, 369466729188096152])), + ] ); } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/mod.rs b/r1cs/gadgets/crypto/src/crh/mod.rs index 9f13c6c09..1f38ab7ca 100644 --- a/r1cs/gadgets/crypto/src/crh/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/mod.rs @@ -72,7 +72,7 @@ pub trait AlgebraicSpongeGadget, ConstraintF: Pr ) -> Result<(), SynthesisError>; fn enforce_squeeze>( - &mut self, + &self, cs: CS, num: usize, ) -> Result, SynthesisError>; diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index d62b10b4a..12e3ecaaa 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -316,17 +316,18 @@ for PoseidonHashGadget } fn enforce_squeeze>( - &mut self, + &self, mut cs: CS, num: usize ) -> Result, SynthesisError> { - for (i, (input, state)) in self.pending.iter().zip(self.state.iter_mut()).enumerate() { + let mut state = self.state.clone(); + for (i, (input, state)) in self.pending.iter().zip(state.iter_mut()).enumerate() { state.add_in_place(cs.ns(|| format!("add_input_{}_to_state", i)), input)?; } let mut output = Vec::with_capacity(num); for i in 0..num { - Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut self.state)?; - output.push(self.state[0].clone()) + Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut state)?; + output.push(state[0].clone()) } Ok(output) } From 649337c7863ba8ac6d714551c9edef8b592e05b1 Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Tue, 19 Jan 2021 11:22:21 +0100 Subject: [PATCH 48/63] Revert "Merge branch 'all' into algebra_ocl" This reverts commit 35d81135b9e82be4a0dd3ae7ad79843afc946e15, reversing changes made to 9849e49cd2e353ea1e8646386675bd58b1864c6d. --- primitives/src/crh/mod.rs | 64 +---- primitives/src/crh/poseidon/mod.rs | 267 +++++++++----------- primitives/src/lib.rs | 7 + r1cs/gadgets/crypto/src/crh/mod.rs | 106 +------- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 259 +++++++++++-------- 5 files changed, 285 insertions(+), 418 deletions(-) diff --git a/primitives/src/crh/mod.rs b/primitives/src/crh/mod.rs index 1d216a186..0eada8a89 100644 --- a/primitives/src/crh/mod.rs +++ b/primitives/src/crh/mod.rs @@ -1,5 +1,5 @@ use algebra::{ - Field, PrimeField, bytes::ToBytes + Field, bytes::ToBytes }; use rand::Rng; use std::hash::Hash; @@ -110,24 +110,11 @@ pub trait BatchFieldBasedHash { } } -/// the trait for algebraic sponge -pub trait AlgebraicSponge: Clone { - /// Initialize the sponge - fn new() -> Self; - /// Update the sponge with `elems` - fn absorb(&mut self, elems: Vec); - /// Output `num` field elements from the sponge. This function - /// is idempotent and calling it multiple times will result - /// in the same outputs, unless more absorbing are performed - /// in between the calls. - fn squeeze(&self, num: usize) -> Vec; -} - #[cfg(test)] mod test { use algebra::{ - fields::mnt4753::Fr as MNT4753Fr, Field, PrimeField, UniformRand + fields::mnt4753::Fr as MNT4753Fr, Field, UniformRand }; use super::BatchFieldBasedHash; @@ -137,9 +124,6 @@ mod test { use rand_xorshift::XorShiftRng; use rand::SeedableRng; - use crate::{ - FieldBasedHash, AlgebraicSponge - }; struct DummyMNT4BatchPoseidonHash; @@ -148,50 +132,6 @@ mod test { type BaseHash = MNT4PoseidonHash; } - pub(crate) fn field_based_hash_test( - personalization: Option<&[H::Data]>, - inputs: Vec, - expected_output: H::Data - ) - { - // Test H(inputs) == expected_output - let mut digest = H::init(personalization); - inputs.iter().for_each(|fe| { digest.update(fe.clone()); }); - let output = digest.finalize(); - assert_eq!(output, expected_output, "Outputs do not match"); - - let inputs_len = inputs.len(); - if inputs_len > 1 { - let final_elem = inputs[inputs_len - 1].clone(); - // Test finalize() holding the state and allowing updates in between different calls to it - digest.reset(None); - inputs.into_iter().take(inputs_len - 1).for_each(|fe| { digest.update(fe); }); - - digest.finalize(); - digest.update(final_elem); - assert_eq!(output, digest.finalize()); - - //Test finalize() being idempotent - assert_eq!(output, digest.finalize()); - } - } - - pub(crate) fn algebraic_sponge_test, F: PrimeField>( - to_absorb: Vec, - expected_squeezes: Vec - ) - { - let mut sponge = H::new(); - - // Absorb all field elements - sponge.absorb(to_absorb); - - // Squeeze and check the outputs - for i in 0..expected_squeezes.len() { - assert_eq!(&expected_squeezes[..i + 1], &sponge.squeeze(i + 1)[..]); - } - } - #[ignore] #[test] fn test_default_batch_hash_implementation() { diff --git a/primitives/src/crh/poseidon/mod.rs b/primitives/src/crh/poseidon/mod.rs index 37135deae..0834b1986 100644 --- a/primitives/src/crh/poseidon/mod.rs +++ b/primitives/src/crh/poseidon/mod.rs @@ -17,7 +17,6 @@ pub use self::parameters::*; pub mod sbox; pub use self::sbox::*; -use crate::AlgebraicSponge; pub trait PoseidonParameters: 'static + FieldBasedHashParameters + Clone { const T: usize; // Number of S-Boxes @@ -30,11 +29,7 @@ pub trait PoseidonParameters: 'static + FieldBasedHashParameters + Clone { const MDS_CST: &'static[Self::Fr]; // The MDS matrix } -#[derive(Derivative)] -#[derivative( - Clone(bound = ""), - Debug(bound = "") -)] +#[derive(Debug)] pub struct PoseidonHash, SB: PoseidonSBox

>{ state: Vec, pending: Vec, @@ -49,21 +44,22 @@ impl PoseidonHash SB: PoseidonSBox

, { #[inline] - fn apply_permutation(&mut self, add_c2: bool) { + fn apply_permutation(&mut self) { for (input, state) in self.pending.iter().zip(self.state.iter_mut()) { *state += input; } - if add_c2 { self.state[P::R] += &P::C2 }; + self.state[P::R] += &P::C2; Self::poseidon_perm(&mut self.state); } #[inline] - fn _finalize(&self, state: &mut Vec, add_c2: bool) -> F { + fn _finalize(&self) -> F { + let mut state = self.state.clone(); for (input, s) in self.pending.iter().zip(state.iter_mut()) { *s += input; } - if add_c2 { state[P::R] += &P::C2; } - Self::poseidon_perm(state); + state[P::R] += &P::C2; + Self::poseidon_perm(&mut state); state[0] } @@ -138,8 +134,6 @@ impl FieldBasedHash for PoseidonHash type Parameters = P; fn init(personalization: Option<&[Self::Data]>) -> Self { - assert_eq!(P::T - P::R, 1, "The assumption that the capacity is one field element is not satisfied."); - let mut state = Vec::with_capacity(P::T); for i in 0..P::T { state.push(P::AFTER_ZERO_PERM[i]); @@ -186,7 +180,7 @@ impl FieldBasedHash for PoseidonHash fn update(&mut self, input: Self::Data) -> &mut Self { self.pending.push(input); if self.pending.len() == P::R { - self.apply_permutation(true); + self.apply_permutation(); self.pending.clear(); } self @@ -194,7 +188,7 @@ impl FieldBasedHash for PoseidonHash fn finalize(&self) -> Self::Data { if !self.pending.is_empty() { - self._finalize(&mut self.state.clone(), true) + self._finalize() } else { self.state[0] } @@ -207,130 +201,118 @@ impl FieldBasedHash for PoseidonHash } } -impl AlgebraicSponge for PoseidonHash - where - F: PrimeField, - P: PoseidonParameters, - SB: PoseidonSBox

, -{ - fn new() -> Self { - Self::init(None) - } - - fn absorb(&mut self, elems: Vec) { - elems.into_iter().for_each(|f| { - self.pending.push(f); - if self.pending.len() == P::R { - self.apply_permutation(false); - self.pending.clear(); - } - }) - } - - fn squeeze(&self, num: usize) -> Vec { - let mut state = self.state.clone(); - for (input, s) in self.pending.iter().zip(state.iter_mut()) { - *s += input; - } - let mut output = Vec::with_capacity(num); - for _ in 0..num { - Self::poseidon_perm(&mut state); - output.push(state[0].clone()); - } - output - } -} - #[cfg(test)] mod test { - use algebra::{fields::{ - mnt4753::Fr as MNT4753Fr, - mnt6753::Fr as MNT6753Fr, - }, PrimeField}; + use algebra::{ + fields::{ + mnt4753::Fr as MNT4753Fr, + mnt6753::Fr as MNT6753Fr, + }, + }; + use std::str::FromStr; use algebra::biginteger::BigInteger768; use crate::crh::{ poseidon::parameters::{ mnt4753::MNT4PoseidonHash, mnt6753::MNT6PoseidonHash, }, - test::{field_based_hash_test, algebraic_sponge_test} + FieldBasedHash, }; - fn generate_inputs(num: usize) -> Vec{ - let mut inputs = Vec::with_capacity(num); - for i in 1..=num { - let input = F::from(i as u32); - inputs.push(input); - } - inputs + #[test] + fn test_poseidon_hash_mnt4() { + + // Regression test + let expected_output = MNT4753Fr::new(BigInteger768([120759599714708995, 15132412086599307425, 1270378153255747692, 3280164418217209635, 5680179791594071572, 2475152338055275001, 9455820118751334058, 6363436228419696186, 3538976751580678769, 14987158621073838958, 10703097083485496843, 48481977539350])); + let mut poseidon_digest = MNT4PoseidonHash::init(None); + let input = [MNT4753Fr::from_str("1").unwrap(), MNT4753Fr::from_str("2").unwrap()]; + + let output = poseidon_digest + .update(input[0]) + .update(input[1]) + .finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); + + // Test finalize() holding the state and allowing updates in between different calls to it + poseidon_digest + .reset(None) + .update(input[0].clone()); + poseidon_digest.finalize(); + poseidon_digest.update(input[1].clone()); + assert_eq!(output, poseidon_digest.finalize()); + + //Test finalize() being idempotent + assert_eq!(output, poseidon_digest.finalize()); } #[test] - fn test_poseidon_hash_mnt4() { - field_based_hash_test::( - None, - generate_inputs(1), - MNT4753Fr::new(BigInteger768([10133114337753187244, 13011129467758174047, 14520750556687040981, 911508844858788085, 1859877757310385382, 9602832310351473622, 8300303689130833769, 981323167857397563, 5760566649679562093, 8644351468476031499, 10679665778836668809, 404482168782668])) - ); - - field_based_hash_test::( - None, - generate_inputs(2), - MNT4753Fr::new(BigInteger768([120759599714708995, 15132412086599307425, 1270378153255747692, 3280164418217209635, 5680179791594071572, 2475152338055275001, 9455820118751334058, 6363436228419696186, 3538976751580678769, 14987158621073838958, 10703097083485496843, 48481977539350])) - ); - - field_based_hash_test::( - None, - generate_inputs(3), - MNT4753Fr::new(BigInteger768([5991160601160569512, 9804741598782512164, 8257389273544061943, 15170134696519047397, 9908596892162673198, 7815454566429677811, 9000639780203615183, 8443915450757188195, 1987926952117715938, 17724141978374492147, 13890449093436164383, 191068391234529])) - - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - MNT4753Fr::new(BigInteger768([5523198498380909748, 115671896985227974, 1569791264643314974, 10995686465166995133, 13403013599916971011, 9712036026598684290, 2998254759663594264, 8111306964576313791, 14787788173217046374, 5019183223370964031, 2046072629858084037, 254417771852919])), - MNT4753Fr::new(BigInteger768([16127953875295592987, 11894863219027726126, 17701631661641187911, 14870672795897948467, 12477792521878046393, 7933118744616181152, 16504185330957910903, 4440754255912752398, 2147815826017548215, 15556058995384616380, 7316328326052908756, 488587201854075])), - MNT4753Fr::new(BigInteger768([17093615125500557324, 5853740299004434536, 14185517698974334849, 15081129818867394374, 4393775450585412195, 15317350057972385858, 602096567370343479, 171645566249469757, 213587553721144028, 16770187529782220214, 10656253922486106039, 183907258171817])), - MNT4753Fr::new(BigInteger768([12712297803466521417, 5718281485803573501, 13963200307320285636, 13279387328772122744, 11400771971860800684, 18129978631072081884, 16152730030736233432, 4443584430842639200, 10168547976596639262, 8852760702638429316, 6245616001490582246, 290914933918621])), - MNT4753Fr::new(BigInteger768([10000480287694253354, 5873338108557543580, 14250396374254092226, 15940814885061001617, 7624733801679967429, 10913153568558026344, 10086885331318146225, 5264350148957133820, 9338271530149930761, 15261863060094932371, 15830626088040155644, 456905335294658])) - ] - ); + fn test_poseidon_hash_mnt4_single_element() { + let expected_output = MNT4753Fr::new(BigInteger768([10133114337753187244, 13011129467758174047, 14520750556687040981, 911508844858788085, 1859877757310385382, 9602832310351473622, 8300303689130833769, 981323167857397563, 5760566649679562093, 8644351468476031499, 10679665778836668809, 404482168782668])); + let mut poseidon_digest = MNT4PoseidonHash::init(None); + poseidon_digest.update(MNT4753Fr::from_str("1").unwrap()); + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); } #[test] - fn test_poseidon_hash_mnt6() { - let expected_output = MNT6753Fr::new(BigInteger768([9820480440897423048, 13953114361017832007, 6124683910518350026, 12198883805142820977, 16542063359667049427, 16554395404701520536, 6092728884107650560, 1511127385771028618, 14755502041894115317, 9806346309586473535, 5880260960930089738, 191119811429922])); - field_based_hash_test::( - None, - generate_inputs(1), - expected_output - ); + fn test_poseidon_hash_mnt4_three_element() { + let expected_output = MNT4753Fr::new(BigInteger768([5991160601160569512, 9804741598782512164, 8257389273544061943, 15170134696519047397, 9908596892162673198, 7815454566429677811, 9000639780203615183, 8443915450757188195, 1987926952117715938, 17724141978374492147, 13890449093436164383, 191068391234529])); + let mut poseidon_digest = MNT4PoseidonHash::init(None); + + for i in 1..=3{ + poseidon_digest.update(MNT4753Fr::from(i as u64)); + } + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT4753."); + } + + #[test] + fn test_poseidon_hash_mnt6() { let expected_output = MNT6753Fr::new(BigInteger768([8195238283171732026, 13694263410588344527, 1885103367289967816, 17142467091011072910, 13844754763865913168, 14332001103319040991, 8911700442280604823, 6452872831806760781, 17467681867740706391, 5384727593134901588, 2343350281633109128, 244405261698305])); - field_based_hash_test::( - None, - generate_inputs(2), - expected_output - ); + let mut poseidon_digest = MNT6PoseidonHash::init(None); + let input = [MNT6753Fr::from_str("1").unwrap(), MNT6753Fr::from_str("2").unwrap()]; + + let output = poseidon_digest + .update(input[0]) + .update(input[1]) + .finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); + + // Test finalize() holding the state and allowing updates in between different calls to it + poseidon_digest + .reset(None) + .update(input[0].clone()); + poseidon_digest.finalize(); + poseidon_digest.update(input[1].clone()); + assert_eq!(output, poseidon_digest.finalize()); + + //Test finalize() being idempotent + assert_eq!(output, poseidon_digest.finalize()); + } + #[test] + fn test_poseidon_hash_mnt6_single_element() { + let expected_output = MNT6753Fr::new(BigInteger768([9820480440897423048, 13953114361017832007, 6124683910518350026, 12198883805142820977, 16542063359667049427, 16554395404701520536, 6092728884107650560, 1511127385771028618, 14755502041894115317, 9806346309586473535, 5880260960930089738, 191119811429922])); + let mut poseidon_digest = MNT6PoseidonHash::init(None); + let input = MNT6753Fr::from_str("1").unwrap(); + poseidon_digest.update(input); + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); + } + + #[test] + fn test_poseidon_hash_mnt6_three_element() { let expected_output = MNT6753Fr::new(BigInteger768([13800884891843937189, 3814452749758584714, 14612220153016028606, 15886322817426727111, 12444362646204085653, 5214641378156871899, 4248022398370599899, 5982332416470364372, 3842784910369906888, 11445718704595887413, 5723531295320926061, 101830932453997])); - field_based_hash_test::( - None, - generate_inputs(3), - expected_output - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - MNT6753Fr::new(BigInteger768([4415375432859735514, 15277127492869068266, 6420528934628268057, 5636828761846368316, 15914884428340991861, 12211035015422291435, 9014434969167954921, 15632055196340174537, 1936740514626417030, 2037074531769378557, 3262429322356753926, 159992276980186])), - MNT6753Fr::new(BigInteger768([893755365716394547, 9594068362757650017, 10451094618402356015, 6337497625726267689, 4160278191670220893, 6010491150125800070, 828252792235881440, 2673899143833542881, 13863607618619424503, 10731000306034932792, 12767597931406600360, 152088456622435])), - MNT6753Fr::new(BigInteger768([2814201016530476081, 8511720540093155210, 4852589771558571678, 13110129496171929816, 4735221329350745796, 12663409230803838109, 11568212364226125976, 1693070022169342918, 2888127900540921339, 4204338349274483900, 15311382501005232626, 438220753471979])), - MNT6753Fr::new(BigInteger768([1775158153332815483, 2026417705400082199, 11123169942942274855, 14330277722886619530, 7836191979464539572, 4865965751577341882, 16998150036867812011, 2739207342391276882, 4247579097230352822, 6464967486406868296, 10032824663714337053, 463362661909267])), - MNT6753Fr::new(BigInteger768([17595647052173133652, 5444801609492079542, 17111761943624358533, 9849391399095026693, 263233265735065436, 1281866738651078101, 2333944581006551597, 13500573177506341637, 10203063908384511927, 15054379420590094900, 13913006388276371623, 451783078041284])) - ] - ); + let mut poseidon_digest = MNT6PoseidonHash::init(None); + + for i in 1..=3{ + let input = MNT6753Fr::from(i as u64); + poseidon_digest.update(input); + } + + let output = poseidon_digest.finalize(); + assert_eq!(output, expected_output, "Outputs do not match for MNT6753."); } use algebra::{ @@ -344,42 +326,25 @@ mod test { #[test] fn test_poseidon_hash_bn382_fr() { let expected_output = BN382Fr::new(BigInteger384([5374955110091081208, 9708994766202121080, 14988884941712225891, 5210165913215347951, 13114182334648522197, 392522167697949297])); - field_based_hash_test::( - None, - generate_inputs(2), - expected_output - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - BN382Fr::new(BigInteger384([10936988494830768508, 13847454081411578749, 11142634849204675481, 15630701206177827142, 9268091518839142138, 1696903081923115093])), - BN382Fr::new(BigInteger384([696581192457039113, 7735026456746748023, 2858087404435942973, 8551026292503659964, 10649071471792522052, 1622107112684056397])), - BN382Fr::new(BigInteger384([13847543644949650964, 4311663852800204305, 4992676739644232980, 4027896082677996619, 12253082643656956806, 534636992911167858])), - BN382Fr::new(BigInteger384([13260537455622274637, 17371511872105869645, 1623345855391475943, 1872797973978834237, 7609952746869694608, 847112821092614604])), - BN382Fr::new(BigInteger384([2836595273011902376, 5748666575747773318, 13745164138914401597, 11231420449817912461, 3298276789500282573, 1513701281573365844])) - ] - ); + + let mut digest = BN382FrPoseidonHash::init(None); + digest.update(BN382Fr::from_str("1").unwrap()); + digest.update(BN382Fr::from_str("2").unwrap()); + let output = digest.finalize(); + + assert_eq!(output, expected_output, "Outputs do not match for BN382Fr"); } #[test] fn test_poseidon_hash_bn382_fq() { let expected_output = BN382Fq::new(BigInteger384([10704305393280846886, 13510271104066299406, 8759721062701909552, 14597420682011858322, 7770486455870140465, 1389855295932765543])); - field_based_hash_test::( - None, - generate_inputs(2), - expected_output - ); - - algebraic_sponge_test::( - generate_inputs(5), - vec![ - BN382Fq::new(BigInteger384([1720359977283232686, 13054139547712885489, 5187034200847661218, 4192055198669470320, 9342360683435217824, 2331312681920757379])), - BN382Fq::new(BigInteger384([4268335443493036543, 5752606093574636763, 7217511812669325408, 5182020843125294140, 5400661559267345372, 2261580635543305540])), - BN382Fq::new(BigInteger384([1487056021032845247, 4971413697289841114, 829985713515651434, 17668516547215117574, 6183480290866190120, 2494711740844925696])), - BN382Fq::new(BigInteger384([12440731074295045789, 13776548474636848476, 9611723257742392848, 14113646477500207966, 2479383220929757679, 2462018425115041259])), - BN382Fq::new(BigInteger384([13447602317280700149, 7333172335365879673, 3401105980077026956, 7168529825556409731, 18013175927097546368, 369466729188096152])), - ] - ); + + let mut digest = BN382FqPoseidonHash::init(None); + digest.update(BN382Fq::from_str("1").unwrap()); + digest.update(BN382Fq::from_str("2").unwrap()); + let output = digest.finalize(); + + assert_eq!(output, expected_output, "Outputs do not match for BN382Fq"); } + } \ No newline at end of file diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 8475d57e3..f8ca20945 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,6 +1,13 @@ #[macro_use] extern crate bench_utils; +#[cfg(any( + feature = "commitment", + feature = "merkle_tree", + feature = "prf", + feature = "signature", + feature = "vrf" +))] #[macro_use] extern crate derivative; diff --git a/r1cs/gadgets/crypto/src/crh/mod.rs b/r1cs/gadgets/crypto/src/crh/mod.rs index 1f38ab7ca..6546d24bc 100644 --- a/r1cs/gadgets/crypto/src/crh/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/mod.rs @@ -1,6 +1,4 @@ -use algebra::{ - Field, PrimeField -}; +use algebra::Field; use std::fmt::Debug; use primitives::crh::{ @@ -19,7 +17,6 @@ pub use self::sbox::*; pub mod poseidon; pub use self::poseidon::*; -use primitives::AlgebraicSponge; pub trait FixedLengthCRHGadget: Sized { type OutputGadget: EqGadget @@ -58,105 +55,4 @@ pub trait FieldHasherGadget< cs: CS, personalization: Option<&[HG::DataGadget]> ) -> Result; -} - -pub trait AlgebraicSpongeGadget, ConstraintF: PrimeField>: Sized { - type DataGadget: FieldGadget; - - fn new>(cs: CS) -> Result; - - fn enforce_absorb>( - &mut self, - cs: CS, - input: &[Self::DataGadget], - ) -> Result<(), SynthesisError>; - - fn enforce_squeeze>( - &self, - cs: CS, - num: usize, - ) -> Result, SynthesisError>; -} - -#[cfg(test)] -mod test { - use algebra::PrimeField; - use primitives::{ - FieldBasedHash, AlgebraicSponge - }; - use crate::{ - FieldBasedHashGadget, AlgebraicSpongeGadget, - }; - use r1cs_std::{ - fields::fp::FpGadget, - test_constraint_system::TestConstraintSystem, - alloc::AllocGadget, - }; - use r1cs_core::ConstraintSystem; - - pub(crate) fn field_based_hash_gadget_native_test< - F: PrimeField, - H: FieldBasedHash, - HG: FieldBasedHashGadget> - >(inputs: Vec) - { - let mut cs = TestConstraintSystem::::new(); - - let primitive_result = { - let mut digest = H::init(None); - inputs.iter().for_each(|elem| { digest.update(*elem);}); - digest.finalize() - }; - - let mut input_gadgets = Vec::with_capacity(inputs.len()); - inputs.into_iter().enumerate().for_each(|(i, elem)|{ - let elem_gadget = HG::DataGadget::alloc( - cs.ns(|| format!("alloc input {}", i)), - || Ok(elem) - ).unwrap(); - input_gadgets.push(elem_gadget); - }); - - let gadget_result = HG::check_evaluation_gadget( - cs.ns(||"check_poseidon_gadget"), - input_gadgets.as_slice() - ).unwrap(); - - assert_eq!(primitive_result, gadget_result.value.unwrap()); - assert!(cs.is_satisfied()); - } - - pub(crate) fn algebraic_sponge_gadget_native_test< - F: PrimeField, - H: AlgebraicSponge, - HG: AlgebraicSpongeGadget> - >(inputs: Vec) - { - let mut cs = TestConstraintSystem::::new(); - - let mut primitive_sponge = H::new(); - primitive_sponge.absorb(inputs.clone()); - - let mut input_gadgets = Vec::with_capacity(inputs.len()); - inputs.iter().enumerate().for_each(|(i, elem)|{ - let elem_gadget = HG::DataGadget::alloc( - cs.ns(|| format!("alloc input {}", i)), - || Ok(elem.clone()) - ).unwrap(); - input_gadgets.push(elem_gadget); - }); - - let mut sponge_gadget = HG::new(cs.ns(|| "new poseidon sponge")).unwrap(); - sponge_gadget.enforce_absorb(cs.ns(|| "absorb inputs"), input_gadgets.as_slice()).unwrap(); - - for i in 0..inputs.len() { - let output_gadgets = sponge_gadget.enforce_squeeze( - cs.ns(|| format!("squeeze {} field elements", i + 1)), - i + 1 - ).unwrap().iter().map(|fe_gadget| fe_gadget.value.unwrap()).collect::>(); - assert_eq!(output_gadgets, primitive_sponge.squeeze(i + 1)); - } - - assert!(cs.is_satisfied()); - } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index 12e3ecaaa..c5269cf39 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -29,7 +29,6 @@ pub mod bn382; #[cfg(feature = "bn_382")] pub use self::bn382::*; use primitives::PoseidonSBox; -use crate::AlgebraicSpongeGadget; pub struct PoseidonHashGadget < @@ -39,9 +38,7 @@ pub struct PoseidonHashGadget SBG: SBoxGadget, > { - state: Vec>, - pending: Vec>, - + _field: PhantomData, _parameters: PhantomData

, _sbox: PhantomData, _sbox_gadget: PhantomData, @@ -111,6 +108,7 @@ impl< (*d).add_constant_in_place(cs.ns(|| format!("add_constant_2_{}", round_cst_idx)), &rc)?; round_cst_idx += 1; } + } // Second full rounds @@ -262,119 +260,180 @@ impl FieldBasedHashGadget AlgebraicSpongeGadget, ConstraintF> -for PoseidonHashGadget - where - ConstraintF: PrimeField, - P: PoseidonParameters, - SB: PoseidonSBox

, - SBG: SBoxGadget, -{ - type DataGadget = FpGadget; - - fn new>(mut cs: CS) -> Result { - assert_eq!(P::T - P::R, 1, "The assumption that the capacity is one field element is not satisfied."); - - let mut state = Vec::new(); - for i in 0..P::T { - let elem = FpGadget::::from_value( - cs.ns(|| format!("hardcode_state_{}",i)), - &P::AFTER_ZERO_PERM[i] - ); - state.push(elem); - } - - Ok(Self { - state, - pending: Vec::with_capacity(P::R), - _parameters: PhantomData, - _sbox: PhantomData, - _sbox_gadget: PhantomData, - }) - } - - fn enforce_absorb>( - &mut self, - mut cs: CS, - elems: &[Self::DataGadget] - ) -> Result<(), SynthesisError> { - elems.iter().enumerate().map(|(i, f)| { - self.pending.push(f.clone()); - if self.pending.len() == P::R { - // add the elements to the state vector. Add rate elements - for (j, (input, state)) in self.pending.iter().zip(self.state.iter_mut()).enumerate() { - state.add_in_place(cs.ns(|| format!("add_input_{}_{}_to_state", i, j)), input)?; - } - // apply permutation after adding the input vector - Self::poseidon_perm(cs.ns(|| format!("poseidon_perm_{}", i)), &mut self.state)?; - - self.pending.clear(); - } - Ok(()) - }).collect::>()?; - Ok(()) - } - - fn enforce_squeeze>( - &self, - mut cs: CS, - num: usize - ) -> Result, SynthesisError> { - let mut state = self.state.clone(); - for (i, (input, state)) in self.pending.iter().zip(state.iter_mut()).enumerate() { - state.add_in_place(cs.ns(|| format!("add_input_{}_to_state", i)), input)?; - } - let mut output = Vec::with_capacity(num); - for i in 0..num { - Self::poseidon_perm(cs.ns(|| format!("squeeze field {}", i)), &mut state)?; - output.push(state[0].clone()) - } - Ok(output) - } -} - #[cfg(test)] mod test { + use rand::thread_rng; + use r1cs_std::test_constraint_system::TestConstraintSystem; + use primitives::crh::{ + FieldBasedHash, + MNT4PoseidonHash, MNT6PoseidonHash, + BN382FrPoseidonHash, BN382FqPoseidonHash, + }; use crate::{ MNT4PoseidonHashGadget, MNT6PoseidonHashGadget, BN382FqPoseidonHashGadget, BN382FrPoseidonHashGadget, }; - - use algebra::fields::PrimeField; - use crate::crh::test::{ - field_based_hash_gadget_native_test, algebraic_sponge_gadget_native_test - }; - - fn generate_inputs(num: usize) -> Vec{ - let mut inputs = Vec::with_capacity(num); - for i in 1..=num { - let input = F::from(i as u32); - inputs.push(input); + use r1cs_std::{ + alloc::AllocGadget, + instantiated::{ + mnt4_753::FqGadget as Mnt6FieldGadget, + mnt6_753::FqGadget as Mnt4FieldGadget, + bn_382::FqGadget as BN382FqGadget, + bn_382::g::FqGadget as BN382FrGadget, } - inputs - } + }; + use r1cs_core::ConstraintSystem; + use algebra::UniformRand; + use super::*; + + use algebra::fields::{ + mnt4753::Fr as MNT4753Fr, + mnt6753::Fr as MNT6753Fr, + bn_382::Fr as BN382Fr, + bn_382::Fq as BN382Fq, + }; #[test] - fn poseidon_mnt4_753_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, MNT4PoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, MNT4PoseidonHashGadget>(generate_inputs(5)); + fn crh_mnt4_753_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem_4753 = Vec::new(); + let v1 = MNT4753Fr::rand(&mut rng); + let v2 = MNT4753Fr::rand(&mut rng); + vec_elem_4753.push(v1); + vec_elem_4753.push(v2); + + let primitive_result = { + let mut digest = MNT4PoseidonHash::init(None); + vec_elem_4753.into_iter().for_each(|elem| { digest.update(elem);}); + digest.finalize() + }; + + let v1_gadget = Mnt4FieldGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = Mnt4FieldGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + MNT4PoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } #[test] - fn poseidon_mnt6_753_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, MNT6PoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, MNT6PoseidonHashGadget>(generate_inputs(5)); + fn crh_mnt6_753_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem_6753 = Vec::new(); + let v1 = MNT6753Fr::rand(&mut rng); + let v2 = MNT6753Fr::rand(&mut rng); + vec_elem_6753.push(v1); + vec_elem_6753.push(v2); + + let primitive_result = { + let mut digest = MNT6PoseidonHash::init(None); + vec_elem_6753.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = Mnt6FieldGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = Mnt6FieldGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + MNT6PoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } #[test] - fn poseidon_bn382_fr_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, BN382FrPoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, BN382FrPoseidonHashGadget>(generate_inputs(5)); + fn crh_bn382_fr_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem = Vec::new(); + let v1 = BN382Fr::rand(&mut rng); + let v2 = BN382Fr::rand(&mut rng); + vec_elem.push(v1); + vec_elem.push(v2); + + let primitive_result = { + let mut digest = BN382FrPoseidonHash::init(None); + vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = BN382FrGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = BN382FrGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + BN382FrPoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } #[test] - fn poseidon_bn382_fq_gadget_native_test() { - field_based_hash_gadget_native_test::<_, _, BN382FqPoseidonHashGadget>(generate_inputs(2)); - algebraic_sponge_gadget_native_test::<_, _, BN382FqPoseidonHashGadget>(generate_inputs(5)); + fn crh_bn382_fq_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem = Vec::new(); + let v1 = BN382Fq::rand(&mut rng); + let v2 = BN382Fq::rand(&mut rng); + vec_elem.push(v1); + vec_elem.push(v2); + + let primitive_result = { + let mut digest = BN382FqPoseidonHash::init(None); + vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = BN382FqGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = BN382FqGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + BN382FqPoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); } } \ No newline at end of file From 683462b9fc2225e7bc72f41c37caa9b31acd86c4 Mon Sep 17 00:00:00 2001 From: Marcelo Kaihara Date: Thu, 28 Jan 2021 08:42:23 +0100 Subject: [PATCH 49/63] Minor correction on variable_base --- algebra-utils/src/msm/variable_base.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 04bd09cab..01606741b 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -602,6 +602,7 @@ mod test { #[cfg(feature = "gpu")] let gpu = VariableBaseMSM::msm_inner_gpu(g.as_slice(), v.as_slice()); + assert_eq!(naive, fast); assert_eq!(naive, affine); assert_eq!(naive, affine_sd); assert_eq!(naive, inner); @@ -634,6 +635,8 @@ mod test { #[cfg(feature = "gpu")] let gpu = VariableBaseMSM::msm_inner_gpu(g.as_slice(), v.as_slice()); + assert_eq!(naive, fast); + assert_eq!(naive, affine); assert_eq!(naive, affine_sd); assert_eq!(naive, inner); From a18ce2f161708a6ab6bcd8c733b12d627b767ab3 Mon Sep 17 00:00:00 2001 From: Marcelo Kaihara Date: Thu, 28 Jan 2021 09:00:54 +0100 Subject: [PATCH 50/63] Changed benches for msm --- .../benches/msm/variable_msm_bn382.rs | 35 ++----------------- .../benches/msm/variable_msm_tweedle.rs | 35 ++----------------- 2 files changed, 6 insertions(+), 64 deletions(-) diff --git a/algebra-utils/benches/msm/variable_msm_bn382.rs b/algebra-utils/benches/msm/variable_msm_bn382.rs index a724b8b90..2014f6c7f 100644 --- a/algebra-utils/benches/msm/variable_msm_bn382.rs +++ b/algebra-utils/benches/msm/variable_msm_bn382.rs @@ -57,7 +57,7 @@ fn load_data(samples: usize) -> (Vec,Vec) { (v, g) } -fn variable_msm_affine(c: &mut Criterion) { +fn variable_msm(c: &mut Criterion) { let mut group = c.benchmark_group("variable_base_msm_affine-bn382-variable number of bases = number of scalars"); let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); @@ -73,36 +73,7 @@ fn variable_msm_affine(c: &mut Criterion) { || format!("****************{}*******************", samples), || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); - //VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), PARAM_C); - VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - }, - BatchSize::PerIteration); - }); - } -} - -fn variable_msm_fast(c: &mut Criterion) { - let mut group = c.benchmark_group("variable_base_msm_fast-bn382-variable number of bases = number of scalars"); - let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); - - - for &samples in samples.iter() { - group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { - b.iter_batched(|| { - let (v, g) = load_data(samples); - (v, g) - }, - |(v, g)| { - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - - VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); add_to_trace!( || format!("****************{}*******************", samples), || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) @@ -116,7 +87,7 @@ fn variable_msm_fast(c: &mut Criterion) { criterion_group! { name = variable_msm_eval_bn382; config = Criterion::default().sample_size(10); - targets = variable_msm_fast, variable_msm_affine, + targets = variable_msm, } criterion_main! ( diff --git a/algebra-utils/benches/msm/variable_msm_tweedle.rs b/algebra-utils/benches/msm/variable_msm_tweedle.rs index ce84b4c17..6668d9739 100644 --- a/algebra-utils/benches/msm/variable_msm_tweedle.rs +++ b/algebra-utils/benches/msm/variable_msm_tweedle.rs @@ -57,7 +57,7 @@ fn load_data(samples: usize) -> (Vec,Vec) { (v, g) } -fn variable_msm_affine(c: &mut Criterion) { +fn variable_msm(c: &mut Criterion) { let mut group = c.benchmark_group("variable_base_msm_affine-tweedle-variable number of bases = number of scalars"); let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); @@ -73,36 +73,7 @@ fn variable_msm_affine(c: &mut Criterion) { || format!("****************{}*******************", samples), || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); - //VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), PARAM_C); - VariableBaseMSM::multi_scalar_mul_affine(g.as_slice(), v.as_slice()); - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - }, - BatchSize::PerIteration); - }); - } -} - -fn variable_msm_fast(c: &mut Criterion) { - let mut group = c.benchmark_group("variable_base_msm_fast-tweedle-variable number of bases = number of scalars"); - let samples = (14..=23).map(|i| 2usize.pow(i)).collect::>(); - - - for &samples in samples.iter() { - group.bench_with_input(BenchmarkId::from_parameter(samples), &samples, |b, _samples| { - b.iter_batched(|| { - let (v, g) = load_data(samples); - (v, g) - }, - |(v, g)| { - add_to_trace!( - || format!("****************{}*******************", samples), - || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) - ); - - VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); + VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); add_to_trace!( || format!("****************{}*******************", samples), || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) @@ -116,7 +87,7 @@ fn variable_msm_fast(c: &mut Criterion) { criterion_group! { name = variable_msm_eval_tweedle; config = Criterion::default().sample_size(10); - targets = variable_msm_fast, variable_msm_affine, + targets = variable_msm, } criterion_main! ( From a2f74883a64f0096d0fcad529e69616ae61a4d22 Mon Sep 17 00:00:00 2001 From: Marcelo Kaihara Date: Thu, 28 Jan 2021 09:04:12 +0100 Subject: [PATCH 51/63] Changed benches MSM --- algebra-utils/benches/msm/variable_msm_bn382.rs | 2 +- algebra-utils/benches/msm/variable_msm_tweedle.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/algebra-utils/benches/msm/variable_msm_bn382.rs b/algebra-utils/benches/msm/variable_msm_bn382.rs index 2014f6c7f..51af221b6 100644 --- a/algebra-utils/benches/msm/variable_msm_bn382.rs +++ b/algebra-utils/benches/msm/variable_msm_bn382.rs @@ -73,7 +73,7 @@ fn variable_msm(c: &mut Criterion) { || format!("****************{}*******************", samples), || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); - VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); + VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); add_to_trace!( || format!("****************{}*******************", samples), || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) diff --git a/algebra-utils/benches/msm/variable_msm_tweedle.rs b/algebra-utils/benches/msm/variable_msm_tweedle.rs index 6668d9739..8f5ac502b 100644 --- a/algebra-utils/benches/msm/variable_msm_tweedle.rs +++ b/algebra-utils/benches/msm/variable_msm_tweedle.rs @@ -73,7 +73,7 @@ fn variable_msm(c: &mut Criterion) { || format!("****************{}*******************", samples), || format!("--->START TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) ); - VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); + VariableBaseMSM::multi_scalar_mul(g.as_slice(), v.as_slice()); add_to_trace!( || format!("****************{}*******************", samples), || format!("--->END TIMESTAMP: {:?}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()) From 77bd942b9297502c5faa3b1ae5b041469402b24b Mon Sep 17 00:00:00 2001 From: Phoinic Date: Tue, 9 Feb 2021 23:57:22 +0200 Subject: [PATCH 52/63] MSM issues bugfix --- algebra-utils/src/msm/variable_base.rs | 7 +++---- proof-systems/src/gm17/prover.rs | 18 +++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 01606741b..a0e4e876a 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -382,7 +382,6 @@ impl VariableBaseMSM { G: AffineCurve, G::Projective: ProjectiveCurve { - let scal_len = scalars.len(); if TypeId::of::() == TypeId::of::() @@ -396,7 +395,7 @@ impl VariableBaseMSM { } else { 16 }; - return Self::multi_scalar_mul_affine_sd_c(bases, scalars, c); + return Self::multi_scalar_mul_affine_c(bases, scalars, c); } else if TypeId::of::() == TypeId::of::() { if scal_len < 1 << 17 { let c: usize = if scal_len < 32 { @@ -404,10 +403,10 @@ impl VariableBaseMSM { } else { (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize }; - return Self::multi_scalar_mul_affine_sd_c(bases, scalars, c); + return Self::multi_scalar_mul_affine_c(bases, scalars, c); } else if scal_len < 1 << 19 { let c: usize = 11; - return Self::multi_scalar_mul_affine_sd_c(bases, scalars, c); + return Self::multi_scalar_mul_affine_c(bases, scalars, c); } else if scal_len < 1 << 23 { let c: usize = 11; return Self::multi_scalar_mul_affine_c(bases, scalars, c); diff --git a/proof-systems/src/gm17/prover.rs b/proof-systems/src/gm17/prover.rs index f2d886dd9..9e4bff888 100644 --- a/proof-systems/src/gm17/prover.rs +++ b/proof-systems/src/gm17/prover.rs @@ -265,8 +265,8 @@ where // Compute A let a_acc_time = start_timer!(|| "Compute A"); let (a_inputs_source, a_aux_source) = params.get_a_query(prover.num_inputs)?; - let a_inputs_acc = VariableBaseMSM::multi_scalar_mul_affine(a_inputs_source, &input_assignment); - let a_aux_acc = VariableBaseMSM::multi_scalar_mul_affine(a_aux_source, &aux_assignment); + let a_inputs_acc = VariableBaseMSM::multi_scalar_mul(a_inputs_source, &input_assignment); + let a_aux_acc = VariableBaseMSM::multi_scalar_mul(a_aux_source, &aux_assignment); let r_g = params.get_g_gamma_z()?.mul(r); let d1_g = params.get_g_gamma_z()?.mul(d1); @@ -282,8 +282,8 @@ where let b_acc_time = start_timer!(|| "Compute B"); let (b_inputs_source, b_aux_source) = params.get_b_query(prover.num_inputs)?; - let b_inputs_acc = VariableBaseMSM::multi_scalar_mul_affine(b_inputs_source, &input_assignment); - let b_aux_acc = VariableBaseMSM::multi_scalar_mul_affine(b_aux_source, &aux_assignment); + let b_inputs_acc = VariableBaseMSM::multi_scalar_mul(b_inputs_source, &input_assignment); + let b_aux_acc = VariableBaseMSM::multi_scalar_mul(b_aux_source, &aux_assignment); let r_h = params.get_h_gamma_z()?.mul(r); let d1_h = params.get_h_gamma_z()?.mul(d1); @@ -303,14 +303,14 @@ where let c1_acc_time = start_timer!(|| "Compute C1"); let (_, c1_aux_source) = params.get_c_query_1(0)?; - let c1_acc = VariableBaseMSM::multi_scalar_mul_affine(c1_aux_source, &aux_assignment); + let c1_acc = VariableBaseMSM::multi_scalar_mul(c1_aux_source, &aux_assignment); end_timer!(c1_acc_time); let c2_acc_time = start_timer!(|| "Compute C2"); let (c2_inputs_source, c2_aux_source) = params.get_c_query_2(prover.num_inputs)?; - let c2_inputs_acc = VariableBaseMSM::multi_scalar_mul_affine(c2_inputs_source, &input_assignment); - let c2_aux_acc = VariableBaseMSM::multi_scalar_mul_affine(c2_aux_source, &aux_assignment); + let c2_inputs_acc = VariableBaseMSM::multi_scalar_mul(c2_inputs_source, &input_assignment); + let c2_aux_acc = VariableBaseMSM::multi_scalar_mul(c2_aux_source, &aux_assignment); let c2_acc = c2_inputs_acc + &c2_aux_acc; end_timer!(c2_acc_time); @@ -319,8 +319,8 @@ where let g_acc_time = start_timer!(|| "Compute G"); let (g_inputs_source, g_aux_source) = params.get_g_gamma2_z_t(prover.num_inputs)?; - let g_inputs_acc = VariableBaseMSM::multi_scalar_mul_affine(g_inputs_source, &h_input); - let g_aux_acc = VariableBaseMSM::multi_scalar_mul_affine(g_aux_source, &h_aux); + let g_inputs_acc = VariableBaseMSM::multi_scalar_mul(g_inputs_source, &h_input); + let g_aux_acc = VariableBaseMSM::multi_scalar_mul(g_aux_source, &h_aux); let g_acc = g_inputs_acc + &g_aux_acc; end_timer!(g_acc_time); From 4052bf492ec61d684d14fff50334c1fe72fc054a Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Fri, 12 Feb 2021 11:42:57 +0100 Subject: [PATCH 53/63] Refactored MSM tests --- algebra-utils/Cargo.toml | 2 +- algebra-utils/src/msm/variable_base.rs | 109 +++++++------------------ 2 files changed, 32 insertions(+), 79 deletions(-) diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index a76a94f3d..8f42e9a5f 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -57,7 +57,7 @@ sw6 = [ "algebra-kernels/sw6", "algebra/sw6" ] mnt4_753 = [ "algebra-kernels/mnt4_753", "algebra/mnt4_753" ] mnt6_298 = [ "algebra-kernels/mnt6_298", "algebra/mnt6_298" ] mnt6_753 = [ "algebra-kernels/mnt6_753", "algebra/mnt6_753" ] -bn_382 = [ "algebra-kernels/bn_382", "algebra/bls12_377" ] +bn_382 = [ "algebra-kernels/bn_382", "algebra/bn_382" ] tweedle = [ "algebra-kernels/tweedle", "algebra/tweedle" ] [build-dependencies] diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index a0e4e876a..773f96353 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -519,13 +519,12 @@ mod test { use super::*; use algebra::curves::bn_382::G1Projective as Bn382G1Projective; - use algebra::fields::bn_382::Fr as Bn382Fr; + use algebra::curves::bn_382::g::Projective as Bn382GProjective; use algebra::curves::tweedle::dee::Projective as TweedleDee; - use algebra::fields::tweedle::Fr as TweedleFr; + use algebra::curves::tweedle::dum::Projective as TweedleDum; use algebra::curves::bls12_381::G1Projective as BlsG1Projective; - use algebra::fields::bls12_381::Fr as BlsFr; - use rand::SeedableRng; + use rand::{SeedableRng, Rng}; use rand_xorshift::XorShiftRng; use algebra::UniformRand; @@ -541,28 +540,24 @@ mod test { acc } - #[cfg(feature = "tweedle")] - #[test] - fn test_all_variants_tweedle() { - const SAMPLES: usize = 1 << 12; - - let mut rng = XorShiftRng::seed_from_u64(234872845u64); - - let v = (0..SAMPLES) - .map(|_| TweedleFr::rand(&mut rng).into_repr()) + fn test_all_variants( + samples: usize, + c: usize, + rng: &mut R, + ) { + let v = (0..samples) + .map(|_| G::ScalarField::rand(rng).into_repr()) .collect::>(); - let g = (0..SAMPLES) - .map(|_| TweedleDee::rand(&mut rng).into_affine()) + let g = (0..samples) + .map(|_| G::rand(rng).into_affine()) .collect::>(); let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); - let c = 16; - let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(),c); - let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(),c); - let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(),c); - + let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), c); + let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), c); + let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(), c); #[cfg(feature = "gpu")] let gpu = VariableBaseMSM::msm_inner_gpu(g.as_slice(), v.as_slice()); @@ -577,71 +572,29 @@ mod test { assert_eq!(naive, gpu); } + #[cfg(feature = "tweedle")] #[test] - fn test_all_variants_bn382() { - const SAMPLES: usize = 1 << 12; - - let mut rng = XorShiftRng::seed_from_u64(234872845u64); - - let v = (0..SAMPLES) - .map(|_| Bn382Fr::rand(&mut rng).into_repr()) - .collect::>(); - let g = (0..SAMPLES) - .map(|_| Bn382G1Projective::rand(&mut rng).into_affine()) - .collect::>(); - - let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); - - let c = 16; - let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(),c); - let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(),c); - let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(),c); + fn test_all_variants_tweedle() { + let rng = &mut XorShiftRng::seed_from_u64(234872845u64); - #[cfg(feature = "gpu")] - let gpu = VariableBaseMSM::msm_inner_gpu(g.as_slice(), v.as_slice()); + test_all_variants::(1 << 12, 16, rng); + test_all_variants::(1 << 12, 16, rng); + } - assert_eq!(naive, fast); - assert_eq!(naive, affine); - assert_eq!(naive, affine_sd); - assert_eq!(naive, inner); + #[cfg(feature = "bn_382")] + #[test] + fn test_all_variants_bn382() { + let rng = &mut XorShiftRng::seed_from_u64(234872845u64); - #[cfg(feature = "gpu")] - assert_eq!(naive, gpu); + test_all_variants::(1 << 12, 16, rng); + test_all_variants::(1 << 12, 16, rng); } + #[cfg(feature = "bls12_381")] #[test] fn test_all_variants_bls() { - const SAMPLES: usize = 1 << 12; + let rng = &mut XorShiftRng::seed_from_u64(234872845u64); - let mut rng = XorShiftRng::seed_from_u64(234872845u64); - - let v = (0..SAMPLES) - .map(|_| BlsFr::rand(&mut rng).into_repr()) - .collect::>(); - let g = (0..SAMPLES) - .map(|_| BlsG1Projective::rand(&mut rng).into_affine()) - .collect::>(); - - let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); - let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); - - let c = 16; - let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(),c); - let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(),c); - let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(),c); - - #[cfg(feature = "gpu")] - let gpu = VariableBaseMSM::msm_inner_gpu(g.as_slice(), v.as_slice()); - - assert_eq!(naive, fast); - - assert_eq!(naive, affine); - assert_eq!(naive, affine_sd); - assert_eq!(naive, inner); - - #[cfg(feature = "gpu")] - assert_eq!(naive, gpu); + test_all_variants::(1 << 12, 16, rng); } - -} +} \ No newline at end of file From 03bcf6b0393489cd42dc406656595f81a3d7d749 Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Fri, 12 Feb 2021 11:48:37 +0100 Subject: [PATCH 54/63] Disabled multi_scalar_mul_affine_sd_c function --- algebra-utils/src/msm/variable_base.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 773f96353..2ee1d97d9 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -81,6 +81,9 @@ impl VariableBaseMSM { } } + //TODO: Seems that this function has problems not captured by the UTs. + // Thus for the moment its invokation is disabled. + #[allow(unused)] pub fn multi_scalar_mul_affine_sd_c( bases: &[G], scalars: &[::BigInt], @@ -556,7 +559,7 @@ mod test { let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), c); - let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), c); + //let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), c); let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(), c); #[cfg(feature = "gpu")] @@ -565,7 +568,7 @@ mod test { assert_eq!(naive, fast); assert_eq!(naive, affine); - assert_eq!(naive, affine_sd); + //assert_eq!(naive, affine_sd); assert_eq!(naive, inner); #[cfg(feature = "gpu")] From 691ad918d34b5fa35a33f104d24a2ed744a78774 Mon Sep 17 00:00:00 2001 From: Paolo Tagliaferri Date: Tue, 9 Mar 2021 10:58:05 +0100 Subject: [PATCH 55/63] Added MHT parameters for TweedleFr. --- .../field_based_mht/parameters/mod.rs | 7 +- .../field_based_mht/parameters/tweedle_fr.rs | 78 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fr.rs diff --git a/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs b/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs index 1ca5e50c9..9872c4245 100644 --- a/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs +++ b/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs @@ -6,4 +6,9 @@ pub use self::mnt4753::*; #[cfg(feature = "mnt6_753")] pub mod mnt6753; #[cfg(feature = "mnt6_753")] -pub use self::mnt6753::*; \ No newline at end of file +pub use self::mnt6753::*; + +#[cfg(feature = "tweedle")] +pub mod tweedle_fr; +#[cfg(feature = "tweedle")] +pub use self::tweedle_fr::*; \ No newline at end of file diff --git a/primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fr.rs b/primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fr.rs new file mode 100644 index 000000000..f5b758fce --- /dev/null +++ b/primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fr.rs @@ -0,0 +1,78 @@ +use algebra::{ + fields::tweedle::Fr as TweedleFr, + biginteger::BigInteger256, + field_new, +}; +use crate::{ + crh::TweedleFrPoseidonHash, + merkle_tree::field_based_mht::FieldBasedMerkleTreePrecomputedEmptyConstants +}; + +pub const TWEEDLE_MHT_POSEIDON_PARAMETERS: FieldBasedMerkleTreePrecomputedEmptyConstants<'static, TweedleFrPoseidonHash> = + FieldBasedMerkleTreePrecomputedEmptyConstants { + nodes: &[ + field_new!(TweedleFr, BigInteger256([0, 0, 0, 0])), + field_new!(TweedleFr, BigInteger256([1685121506851839463, 16981548520505137274, 8913412180966583038, 3862086594483176853])), + field_new!(TweedleFr, BigInteger256([11170234764586973796, 10725839658946531096, 4089526305768698754, 1460429405770838413])), + field_new!(TweedleFr, BigInteger256([17916607642221592882, 8899562254223372899, 5718113766989047716, 1076406490778760958])), + field_new!(TweedleFr, BigInteger256([16814393994791617149, 4003549585878224960, 91189797674671164, 2489268348396502646])), + field_new!(TweedleFr, BigInteger256([3460562161953312097, 9272175926981975155, 3088781530878338181, 408762626573460268])), + field_new!(TweedleFr, BigInteger256([4239231910949981686, 8869286273077200517, 15652728562557699831, 3576102463490196815])), + field_new!(TweedleFr, BigInteger256([13380559706935466086, 9731495717823444557, 13485044794068855700, 920123060019082593])), + field_new!(TweedleFr, BigInteger256([11296480562263487099, 13017529970429918980, 15492229384387414211, 1785749344954309826])), + field_new!(TweedleFr, BigInteger256([9738206838161957894, 11701328267258081479, 11712994190976813369, 484156460220120380])), + field_new!(TweedleFr, BigInteger256([3442436595719325694, 2431894943368234580, 17363188394577578270, 1614283916602080385])), + field_new!(TweedleFr, BigInteger256([3972068898698943381, 11117259520378692208, 4253450360934634403, 239101287040501995])), + field_new!(TweedleFr, BigInteger256([16580610996142154741, 7643908918402835608, 4538907510080444171, 4263606647859070795])), + field_new!(TweedleFr, BigInteger256([8592329819226182315, 13382013060597509488, 8836783333517823500, 3786991317438607835])), + field_new!(TweedleFr, BigInteger256([1773237737270872796, 2410057326158883883, 2737246428764964492, 143982332310609966])), + field_new!(TweedleFr, BigInteger256([2707616787051394019, 11722910454912726756, 3333932516671235313, 2519035104169477350])), + field_new!(TweedleFr, BigInteger256([5813486669979523104, 622781981755528836, 3795306211510301966, 2280896473682328864])), + field_new!(TweedleFr, BigInteger256([9884651142463613651, 11192489360191969729, 3533957099232207802, 4365455770905630450])), + field_new!(TweedleFr, BigInteger256([11940960536276443993, 12237559331804864182, 855310162320223754, 3250995830672065852])), + field_new!(TweedleFr, BigInteger256([9844345352101824289, 11007606007155221061, 5337768567583173935, 1757712574894454062])), + field_new!(TweedleFr, BigInteger256([17397097032371215469, 2560985447691462466, 5873153672621324816, 3004853082856123488])), + field_new!(TweedleFr, BigInteger256([2906639260900593014, 12565622307387416057, 18208249875710924485, 3076942007405729816])), + field_new!(TweedleFr, BigInteger256([12332293864653714593, 6336761349198557987, 14481492470913974358, 4413622281835599417])), + field_new!(TweedleFr, BigInteger256([79692058390698902, 14504666139340959355, 16768104803024975328, 369341246831639552])), + field_new!(TweedleFr, BigInteger256([2621547940131718999, 17743506990112205174, 6971752532124278629, 3241396862924145590])), + field_new!(TweedleFr, BigInteger256([11163086857151067005, 12984510300292820262, 4717994806295806048, 4495298772085010977])), + field_new!(TweedleFr, BigInteger256([15531065475439967178, 10139480523449757505, 6054301480319923629, 683911869248719980])), + field_new!(TweedleFr, BigInteger256([3902755205937944407, 13093206721129864441, 16246765226559434352, 2735622140097895633])), + field_new!(TweedleFr, BigInteger256([8690158721593369984, 730875283828647497, 3841607634391808388, 2371594890750177334])), + field_new!(TweedleFr, BigInteger256([3026815083929086599, 14419444751560137298, 3651949377921605765, 3671437283458210474])), + field_new!(TweedleFr, BigInteger256([14126118267082632123, 6827034892773261391, 5556113879686593587, 4539405425966083639])), + field_new!(TweedleFr, BigInteger256([11865934732736629922, 2696435346237195560, 18058422909608662479, 2071268813115074451])), + field_new!(TweedleFr, BigInteger256([13347092608138479115, 4066036543997219427, 7959630727080163169, 3601068210152443865])), + field_new!(TweedleFr, BigInteger256([15138377926095811795, 15380039026895908568, 271121507124550600, 1024255194234800819])), + field_new!(TweedleFr, BigInteger256([10134471144513638072, 16831793127198349974, 6339097251062257493, 541654095494825270])), + field_new!(TweedleFr, BigInteger256([15800878851654609259, 9774427126525231605, 14726151358032257215, 2809506730656175605])), + field_new!(TweedleFr, BigInteger256([12250046100357603655, 3019385177324988069, 844813400383977349, 2799285112129997345])), + field_new!(TweedleFr, BigInteger256([5411213645516041177, 16651961682340139834, 2931464647892840002, 4405490370974890431])), + field_new!(TweedleFr, BigInteger256([18074358143639506426, 14767712014724128887, 14587381883459330445, 4481815717901469638])), + field_new!(TweedleFr, BigInteger256([3551361605813546439, 13978661106348185458, 11925279340031940548, 2940381839804134085])), + ], + merkle_arity: 2, + max_height: 40, + }; + +#[cfg(test)] +mod test { + + use algebra::Field; + use crate::FieldBasedHash; + + use super::*; + + #[test] + fn generate_binary_tweedle_fr_mht_nodes() { + let mut empty_node = TWEEDLE_MHT_POSEIDON_PARAMETERS.nodes[0].clone(); + let mut digest = TweedleFrPoseidonHash::init(None); + assert_eq!(empty_node, TweedleFr::zero()); + for node in TWEEDLE_MHT_POSEIDON_PARAMETERS.nodes { + assert_eq!(node, &empty_node); + empty_node = digest.update(empty_node).update(empty_node).finalize(); + digest.reset(None); + } + } +} \ No newline at end of file From 942f6780b1072911dcd03eeb260cb283b7c34a8a Mon Sep 17 00:00:00 2001 From: Paolo Tagliaferri Date: Tue, 9 Mar 2021 11:35:11 +0100 Subject: [PATCH 56/63] Added MHT parameters for TweedleFq. --- .../field_based_mht/parameters/mod.rs | 7 +- .../field_based_mht/parameters/tweedle_fq.rs | 79 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fq.rs diff --git a/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs b/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs index 9872c4245..78e224cee 100644 --- a/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs +++ b/primitives/src/merkle_tree/field_based_mht/parameters/mod.rs @@ -11,4 +11,9 @@ pub use self::mnt6753::*; #[cfg(feature = "tweedle")] pub mod tweedle_fr; #[cfg(feature = "tweedle")] -pub use self::tweedle_fr::*; \ No newline at end of file +pub use self::tweedle_fr::*; + +#[cfg(feature = "tweedle")] +pub mod tweedle_fq; +#[cfg(feature = "tweedle")] +pub use self::tweedle_fq::*; \ No newline at end of file diff --git a/primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fq.rs b/primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fq.rs new file mode 100644 index 000000000..1c77f3af3 --- /dev/null +++ b/primitives/src/merkle_tree/field_based_mht/parameters/tweedle_fq.rs @@ -0,0 +1,79 @@ +use algebra::{ + fields::tweedle::Fq as TweedleFq, + biginteger::BigInteger256, + field_new, +}; +use crate::{ + crh::TweedleFqPoseidonHash, + merkle_tree::field_based_mht::FieldBasedMerkleTreePrecomputedEmptyConstants +}; + +pub const TWEEDLE_MHT_POSEIDON_PARAMETERS: FieldBasedMerkleTreePrecomputedEmptyConstants<'static, TweedleFqPoseidonHash> = + FieldBasedMerkleTreePrecomputedEmptyConstants { + nodes: &[ + field_new!(TweedleFq, BigInteger256([0, 0, 0, 0])), + field_new!(TweedleFq, BigInteger256([571543258846690045, 9668423315943487211, 15207571892648283347, 3663924216008466650])), + field_new!(TweedleFq, BigInteger256([10778557592461781281, 11984799518140201179, 2571166438057034436, 629803531019169725])), + field_new!(TweedleFq, BigInteger256([6871636724756646462, 3484289217997285770, 3000874065703614192, 2796436783780722855])), + field_new!(TweedleFq, BigInteger256([11838309199946986802, 10155190646586623382, 336855880205130279, 158629538639247276])), + field_new!(TweedleFq, BigInteger256([14943339878831194207, 13192097247327085693, 5085182607549724242, 2255744529189892787])), + field_new!(TweedleFq, BigInteger256([7124593205276977911, 8126059895816433281, 14260036020018279865, 580380414137426687])), + field_new!(TweedleFq, BigInteger256([16309038711545651388, 9700414788382122041, 17593203076567032839, 253339774425262520])), + field_new!(TweedleFq, BigInteger256([8026198812057767294, 12166615334933888636, 17293997816524785879, 1204660232066268032])), + field_new!(TweedleFq, BigInteger256([13840429540424223271, 7681698952893986773, 9093328272281851588, 4317631845197999317])), + field_new!(TweedleFq, BigInteger256([17170819557109769928, 13077165284746759684, 9718823032838762762, 778309504895909109])), + field_new!(TweedleFq, BigInteger256([7302228933726229670, 14583436203428232677, 9256280630789845642, 1873124199492643836])), + field_new!(TweedleFq, BigInteger256([15632610128094042405, 9106879591513009003, 9867905173030384440, 3679103318047557138])), + field_new!(TweedleFq, BigInteger256([7388243960322030670, 192384297547752948, 3649460664909835242, 2377682990568558769])), + field_new!(TweedleFq, BigInteger256([8222037919444997324, 7552392084958492131, 10196076608464915493, 972931266042573743])), + field_new!(TweedleFq, BigInteger256([15179813854997755876, 4576615728861278660, 4432978691367244153, 377249182599729143])), + field_new!(TweedleFq, BigInteger256([8415453835421799802, 159670292208859624, 10093279529070276428, 683577367638365250])), + field_new!(TweedleFq, BigInteger256([1705514417400041153, 8104715774837867555, 1604666249687595008, 1718540246517011352])), + field_new!(TweedleFq, BigInteger256([3106586344929884088, 12604014976963021940, 14941654086871049416, 1796249794521945983])), + field_new!(TweedleFq, BigInteger256([12306187078288342226, 18075230345054452704, 2250232372322656700, 1393668042369361428])), + field_new!(TweedleFq, BigInteger256([9901014253566146408, 6309992963587958344, 18327337189316048182, 3551981072898796842])), + field_new!(TweedleFq, BigInteger256([8424632191310658728, 13604397007409059277, 70297432654782297, 1824998006916282])), + field_new!(TweedleFq, BigInteger256([9389159271072994794, 383058273291972027, 3094348671782137718, 2802101639537513285])), + field_new!(TweedleFq, BigInteger256([6504340763230613420, 7000444624509376541, 772870430002558621, 3136684393202156441])), + field_new!(TweedleFq, BigInteger256([3077878160248966332, 7651061762786739276, 435622970363907226, 871362818751305609])), + field_new!(TweedleFq, BigInteger256([6764346170664065078, 5701295996014916338, 9907541422780291194, 406025697723730783])), + field_new!(TweedleFq, BigInteger256([15337870352556216650, 17240637251346786929, 16657671777892818449, 4248533460348833687])), + field_new!(TweedleFq, BigInteger256([15141414463247834924, 3947877385284521085, 10325289222213006259, 133474861880832361])), + field_new!(TweedleFq, BigInteger256([7774265652202884015, 14196928893921398148, 3994864145852144822, 3788408521048825298])), + field_new!(TweedleFq, BigInteger256([13460979225624197582, 2854962726347594994, 2507205771340844751, 782717480761294878])), + field_new!(TweedleFq, BigInteger256([9218764651569921222, 14783048489367764321, 1860118199089236812, 3275820416787028656])), + field_new!(TweedleFq, BigInteger256([6894305244269020474, 7481595221889851342, 7545346601923237583, 2139408109164766047])), + field_new!(TweedleFq, BigInteger256([13736147359952143660, 17838473895319673341, 12647349159691564885, 95960444169122746])), + field_new!(TweedleFq, BigInteger256([12541085295221823975, 13896768330440314379, 9679776598296919375, 4371357490743947697])), + field_new!(TweedleFq, BigInteger256([3351841092989306828, 8818505759265875365, 17507019339920634550, 1027927906586394565])), + field_new!(TweedleFq, BigInteger256([263081558962384528, 11155991400747393067, 12047319978152389222, 3161227911408142498])), + field_new!(TweedleFq, BigInteger256([3033078567847722316, 5036883075489769711, 16030446542911205686, 1255515577017969382])), + field_new!(TweedleFq, BigInteger256([707421069506632178, 6441456127568615151, 13518932038066042860, 2775176351271429968])), + field_new!(TweedleFq, BigInteger256([2114812755799901667, 14805651240254429060, 9942828430926628780, 1604022438159857064])), + field_new!(TweedleFq, BigInteger256([3416724247890429757, 3892440074538534684, 17646806795228152946, 2408891754829793116])) + + ], + merkle_arity: 2, + max_height: 40, + }; + +#[cfg(test)] +mod test { + + use algebra::Field; + use crate::FieldBasedHash; + + use super::*; + + #[test] + fn generate_binary_tweedle_fq_mht_nodes() { + let mut empty_node = TWEEDLE_MHT_POSEIDON_PARAMETERS.nodes[0].clone(); + let mut digest = TweedleFqPoseidonHash::init(None); + assert_eq!(empty_node, TweedleFq::zero()); + for node in TWEEDLE_MHT_POSEIDON_PARAMETERS.nodes { + assert_eq!(node, &empty_node); + empty_node = digest.update(empty_node).update(empty_node).finalize(); + digest.reset(None); + } + } +} \ No newline at end of file From 5c59592ecc6678b71c6df7e3988fc6e96b7d3cd9 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Wed, 10 Mar 2021 21:34:14 +0200 Subject: [PATCH 57/63] Remove custom definition for MSM --- algebra-utils/src/msm/variable_base.rs | 266 +------------------------ 1 file changed, 6 insertions(+), 260 deletions(-) diff --git a/algebra-utils/src/msm/variable_base.rs b/algebra-utils/src/msm/variable_base.rs index 2ee1d97d9..527deadcc 100644 --- a/algebra-utils/src/msm/variable_base.rs +++ b/algebra-utils/src/msm/variable_base.rs @@ -1,8 +1,6 @@ use algebra::{AffineCurve, BigInteger, Field, FpParameters, PrimeField, ProjectiveCurve}; use rayon::prelude::*; -use std::any::TypeId; - #[cfg(feature = "gpu")] use algebra_kernels::msm::{get_cpu_utilization, get_kernels, get_gpu_min_length}; #[cfg(feature = "gpu")] @@ -12,222 +10,6 @@ pub struct VariableBaseMSM; impl VariableBaseMSM { - // Function that recodes the scalars into SD numbers - // The output is a vector - pub fn recode_sd( - scalar: &::BigInt, - c: usize - ) -> Vec { - - let num_bits = - ::Params::MODULUS_BITS as usize; - - let window_starts: Vec<_> = (0..num_bits).step_by(c).collect(); - - let mut vec_coeff = Vec::new(); - - window_starts.iter().rev().for_each(|x| { - let mut scal = (*scalar).clone(); - scal.divn(*x as u32); - // We mod the remaining bits by the window size. - let a = scal.as_ref()[0] % (1 << c); - vec_coeff.push(a as i64); - }); - - for idx in (0..vec_coeff.len()).rev() { - if vec_coeff[idx] >= (1 << (c-1)) { - vec_coeff[idx] -= 1 << c; - if idx!= 0 { - vec_coeff[idx-1] += 1; - } - } - } - - // last element is the least significant digit - return vec_coeff; - - } - - // Recodes in SD the portions of the scalar divided in c bits - // Takes as input the carry_in and generates the vector of SD digits corresponding to - // the processing chunk and the carry_out - // For example: for 4 cores, it takes the carry_in and - // generates carry_out, a_(i+3), a_(i+2), a_(i+1), a_i - #[inline] - pub fn recode_sd_chunk( - scalar: &::BigInt, - c: usize, - chunk_pos: usize, - num_cores: usize, - vec_coeff: &mut Vec, - carry_in: &mut i64 - ) { - - // starting bit position of the chunk - let start_w_bit = chunk_pos * (c * num_cores); - - for i in 0..num_cores { - let windows_starts = start_w_bit + i * c; - let mut scal = (*scalar).clone(); - scal.divn(windows_starts as u32); - let mut a = (scal.as_ref()[0] % (1 << c)) as i64 + *carry_in; - if a >= (1 << (c-1)) { - a -= 1 << c; - *carry_in = 1; - } else { - *carry_in = 0; - } - (*vec_coeff)[i] = a; - } - } - - //TODO: Seems that this function has problems not captured by the UTs. - // Thus for the moment its invokation is disabled. - #[allow(unused)] - pub fn multi_scalar_mul_affine_sd_c( - bases: &[G], - scalars: &[::BigInt], - c:usize - ) -> G::Projective { - - let cc = 1 << c; - - let num_bits = - ::Params::MODULUS_BITS as usize; - - let zero = G::zero().into_projective(); - - // The number of windows of the scalars in groups of c bits - let num_w = (num_bits as f64 / c as f64).ceil() as usize; - // The number of cores present - let cpus = rayon::current_num_threads(); - // The number of chunks of cpus digits - let num_chunks = (num_w as f64/cpus as f64).floor() as usize; - // The remaining digits to process sequentially - let remaining_digits = num_w - (num_chunks * cpus); - - let mut window_sums = Vec::new(); - let mut small_window_sums:Vec<_>; - - let mut carry_vec = vec![0; scalars.len()]; - let mut vec_coeff = vec![vec![0; cpus]; scalars.len()]; - - for i in 0..num_chunks { - // index of the digit within the small window of cpus number of digits - let idx: Vec<_> = (0..cpus).rev().collect(); - - vec_coeff.par_iter_mut().zip(carry_vec.par_iter_mut()).enumerate().for_each( |(l, (v1, c1))| { - Self::recode_sd_chunk::(&scalars[l], c, i, cpus, v1, c1); - }); - - small_window_sums = idx - .into_par_iter() - .map(|w_idx| { - // We don't need the "zero" bucket, we use 2^c-1 bucket for units - let mut buckets = vec![Vec::with_capacity(bases.len() / cc * 2); cc / 2]; - for i in 0..scalars.len() { - if !scalars[i].is_zero() { - - let scalar = vec_coeff[i][w_idx]; - - // If the scalar is non-zero, we update the corresponding - // bucket. - // (Recall that `buckets` doesn't have a zero bucket.) - if scalar != 0 && bases[i].is_zero() == false { - if scalar < 0 { - buckets[(-scalar - 1) as usize].push(-(bases[i])); - } else { - buckets[(scalar - 1) as usize].push(bases[i]); - } - } - } - } - G::add_points(&mut buckets); - let mut res = zero.clone(); - - let mut running_sum = zero.clone(); - for b in buckets[0..cc / 2].iter_mut().rev() { - if b.len() != 0 && b[0].is_zero() == false { - running_sum.add_assign_mixed(&b[0]) - } - res += &running_sum; - } - - res - }) - .collect(); - - small_window_sums.iter().rev().for_each(|x| { - window_sums.push(x.clone()); - }); - } - - if remaining_digits != 0 { - - let idx:Vec<_> = (0..remaining_digits).rev().collect(); - - vec_coeff.par_iter_mut().zip(carry_vec.par_iter_mut()).enumerate().for_each( |(l, (v1, c1))| { - Self::recode_sd_chunk::(&scalars[l], c, num_chunks, cpus, v1, c1); - }); - - // Each window is of size `c`. - // We divide up the bits 0..num_bits into windows of size `c`, and - // in parallel process each such window. - small_window_sums = idx - .into_par_iter() - .map(|w_idx| { - // We don't need the "zero" bucket, we use 2^c-1 bucket for units - let mut buckets = vec![Vec::with_capacity(bases.len() / cc * 2); cc / 2]; - for i in 0..scalars.len() { - if !scalars[i].is_zero() { - - let scalar = vec_coeff[i][w_idx]; - - // If the scalar is non-zero, we update the corresponding - // bucket. - // (Recall that `buckets` doesn't have a zero bucket.) - if scalar != 0 && bases[i].is_zero() == false { - if scalar < 0 { - buckets[(-scalar - 1) as usize].push(-(bases[i])); - } else { - buckets[(scalar - 1) as usize].push(bases[i]); - } - } - } - } - G::add_points(&mut buckets); - let mut res = zero.clone(); - - let mut running_sum = zero.clone(); - for b in buckets[0..cc / 2].iter_mut().rev() { - if b.len() != 0 && b[0].is_zero() == false { - running_sum.add_assign_mixed(&b[0]) - } - res += &running_sum; - } - res - }) - .collect(); - - small_window_sums.iter().rev().for_each(|x| { - window_sums.push(x.clone()); - }); - } - - // We store the sum for the lowest window. - let lowest = window_sums.first().unwrap(); - - // We're traversing windows from high to low. - window_sums[1..].iter().rev().fold(zero, |mut total, sum_i| { - total += sum_i; - for _ in 0..c { - total.double_in_place(); - } - total - }) + lowest - } - - pub fn multi_scalar_mul_affine_c( bases: &[G], scalars: &[::BigInt], @@ -387,47 +169,13 @@ impl VariableBaseMSM { { let scal_len = scalars.len(); - if TypeId::of::() == TypeId::of::() - { - let c: usize = if scal_len < 32 { - 3 - } else if (scal_len < 1 << 17) || (scal_len > 1 << 23) { - (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize - } else if scal_len < 1 << 21 { - 12 - } else { - 16 - }; - return Self::multi_scalar_mul_affine_c(bases, scalars, c); - } else if TypeId::of::() == TypeId::of::() { - if scal_len < 1 << 17 { - let c: usize = if scal_len < 32 { - 3 - } else { - (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize - }; - return Self::multi_scalar_mul_affine_c(bases, scalars, c); - } else if scal_len < 1 << 19 { - let c: usize = 11; - return Self::multi_scalar_mul_affine_c(bases, scalars, c); - } else if scal_len < 1 << 23 { - let c: usize = 11; - return Self::multi_scalar_mul_affine_c(bases, scalars, c); - } else if scal_len < 1 << 24 { - let c: usize = 16; - return Self::msm_inner_c(bases, scalars, c); - } else { - let c: usize = (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize; - return Self::msm_inner_c(bases, scalars, c); - } + let c: usize = if scal_len < 32 { + 3 } else { - let c: usize = if scal_len < 32 { - 3 - } else { - (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize - }; - return Self::multi_scalar_mul_affine_c(bases, scalars, c); - } + (2.0 / 3.0 * (f64::from(scalars.len() as u32)).log2() - 2.0).ceil() as usize + }; + + return Self::multi_scalar_mul_affine_c(bases, scalars, c); } #[cfg(feature = "gpu")] @@ -559,7 +307,6 @@ mod test { let fast = VariableBaseMSM::msm_inner_cpu(g.as_slice(), v.as_slice()); let affine = VariableBaseMSM::multi_scalar_mul_affine_c(g.as_slice(), v.as_slice(), c); - //let affine_sd = VariableBaseMSM::multi_scalar_mul_affine_sd_c(g.as_slice(), v.as_slice(), c); let inner = VariableBaseMSM::msm_inner_c(g.as_slice(), v.as_slice(), c); #[cfg(feature = "gpu")] @@ -568,7 +315,6 @@ mod test { assert_eq!(naive, fast); assert_eq!(naive, affine); - //assert_eq!(naive, affine_sd); assert_eq!(naive, inner); #[cfg(feature = "gpu")] From 5666b47c18c3858ef1ea3a8bcf7a78222e3bff5c Mon Sep 17 00:00:00 2001 From: Phoinic Date: Thu, 18 Mar 2021 23:42:06 +0200 Subject: [PATCH 58/63] Add tweedle to r1cs --- algebra-utils/Cargo.toml | 1 - r1cs/gadgets/crypto/Cargo.toml | 5 +- r1cs/gadgets/crypto/src/crh/poseidon/mod.rs | 83 +++++++++++++++++++ .../crypto/src/crh/poseidon/tweedle.rs | 25 ++++++ r1cs/gadgets/std/src/instantiated/mod.rs | 5 +- .../std/src/instantiated/tweedle/curves.rs | 28 +++++++ .../std/src/instantiated/tweedle/fields.rs | 27 ++++++ .../std/src/instantiated/tweedle/mod.rs | 5 ++ 8 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 r1cs/gadgets/crypto/src/crh/poseidon/tweedle.rs create mode 100644 r1cs/gadgets/std/src/instantiated/tweedle/curves.rs create mode 100644 r1cs/gadgets/std/src/instantiated/tweedle/fields.rs create mode 100644 r1cs/gadgets/std/src/instantiated/tweedle/mod.rs diff --git a/algebra-utils/Cargo.toml b/algebra-utils/Cargo.toml index 8f42e9a5f..7f0ba6853 100644 --- a/algebra-utils/Cargo.toml +++ b/algebra-utils/Cargo.toml @@ -55,7 +55,6 @@ edwards_sw6 = [ "algebra-kernels/edwards_sw6", "algebra/edwards_sw6" ] jubjub = [ "algebra-kernels/jubjub", "algebra/jubjub" ] sw6 = [ "algebra-kernels/sw6", "algebra/sw6" ] mnt4_753 = [ "algebra-kernels/mnt4_753", "algebra/mnt4_753" ] -mnt6_298 = [ "algebra-kernels/mnt6_298", "algebra/mnt6_298" ] mnt6_753 = [ "algebra-kernels/mnt6_753", "algebra/mnt6_753" ] bn_382 = [ "algebra-kernels/bn_382", "algebra/bn_382" ] tweedle = [ "algebra-kernels/tweedle", "algebra/tweedle" ] diff --git a/r1cs/gadgets/crypto/Cargo.toml b/r1cs/gadgets/crypto/Cargo.toml index 2c02a484d..87ef02137 100644 --- a/r1cs/gadgets/crypto/Cargo.toml +++ b/r1cs/gadgets/crypto/Cargo.toml @@ -45,6 +45,7 @@ nizk = ["proof-systems"] # For Poseidon CRH / Merkle Tree mnt4_753 = ["primitives/mnt4_753"] mnt6_753 = ["primitives/mnt6_753"] +tweedle = ["primitives/tweedle"] bn_382 = ["primitives/bn_382"] llvm_asm = ["algebra/llvm_asm"] @@ -52,5 +53,5 @@ llvm_asm = ["algebra/llvm_asm"] [dev-dependencies] rand_xorshift = { version = "0.2" } algebra = { git = "https://github.com/HorizenOfficial/ginger-lib", branch = "algebra_ocl", features = ["bls12_381", "sw6"] } -r1cs-std = { path = "../std", features = ["jubjub", "edwards_sw6", "bls12_377", "mnt4_753", "mnt6_753", "bn_382"] } -r1cs-crypto = { path = "../crypto", features = ["mnt4_753", "mnt6_753", "bn_382"] } \ No newline at end of file +r1cs-std = { path = "../std", features = ["jubjub", "edwards_sw6", "bls12_377", "mnt4_753", "mnt6_753", "bn_382", "tweedle"] } +r1cs-crypto = { path = "../crypto", features = ["mnt4_753", "mnt6_753", "bn_382", "tweedle"] } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs index c5269cf39..60f0fffe3 100644 --- a/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs +++ b/r1cs/gadgets/crypto/src/crh/poseidon/mod.rs @@ -24,6 +24,11 @@ pub mod mnt6753; #[cfg(feature = "mnt6_753")] pub use self::mnt6753::*; +#[cfg(feature = "tweedle")] +pub mod tweedle; +#[cfg(feature = "tweedle")] +pub use self::tweedle::*; + #[cfg(feature = "bn_382")] pub mod bn382; #[cfg(feature = "bn_382")] @@ -268,10 +273,12 @@ mod test { FieldBasedHash, MNT4PoseidonHash, MNT6PoseidonHash, BN382FrPoseidonHash, BN382FqPoseidonHash, + TweedleFrPoseidonHash, TweedleFqPoseidonHash, }; use crate::{ MNT4PoseidonHashGadget, MNT6PoseidonHashGadget, BN382FqPoseidonHashGadget, BN382FrPoseidonHashGadget, + TweedleFqPoseidonHashGadget, TweedleFrPoseidonHashGadget, }; use r1cs_std::{ alloc::AllocGadget, @@ -280,6 +287,8 @@ mod test { mnt6_753::FqGadget as Mnt4FieldGadget, bn_382::FqGadget as BN382FqGadget, bn_382::g::FqGadget as BN382FrGadget, + tweedle::FqGadget as TweedleFqGadget, + tweedle::FrGadget as TweedleFrGadget, } }; use r1cs_core::ConstraintSystem; @@ -291,6 +300,8 @@ mod test { mnt6753::Fr as MNT6753Fr, bn_382::Fr as BN382Fr, bn_382::Fq as BN382Fq, + tweedle::Fr as TweedleFr, + tweedle::Fq as TweedleFq, }; #[test] @@ -436,4 +447,76 @@ mod test { assert_eq!(primitive_result, gadget_result.value.unwrap()); assert!(cs.is_satisfied()); } + + #[test] + fn crh_tweedle_fr_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem = Vec::new(); + let v1 = TweedleFr::rand(&mut rng); + let v2 = TweedleFr::rand(&mut rng); + vec_elem.push(v1); + vec_elem.push(v2); + + let primitive_result = { + let mut digest = TweedleFrPoseidonHash::init(None); + vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = TweedleFrGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = TweedleFrGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + TweedleFrPoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); + } + + #[test] + fn crh_tweedle_fq_primitive_gadget_test() { + + let mut rng = &mut thread_rng(); + let mut cs = TestConstraintSystem::::new(); + + let mut vec_elem = Vec::new(); + let v1 = TweedleFq::rand(&mut rng); + let v2 = TweedleFq::rand(&mut rng); + vec_elem.push(v1); + vec_elem.push(v2); + + let primitive_result = { + let mut digest = TweedleFqPoseidonHash::init(None); + vec_elem.into_iter().for_each(|elem| { digest.update(elem); }); + digest.finalize() + }; + + let v1_gadget = TweedleFqGadget::alloc(cs.ns(|| "alloc_v1"),|| Ok(v1)).unwrap(); + let v2_gadget = TweedleFqGadget::alloc(cs.ns(|| "alloc_v2"),|| Ok(v2)).unwrap(); + + let mut vec_elem_gadget = Vec::new(); + vec_elem_gadget.push(v1_gadget); + vec_elem_gadget.push(v2_gadget); + + let gadget_result = + TweedleFqPoseidonHashGadget::check_evaluation_gadget( + cs.ns(||"check_poseidon_gadget"), + vec_elem_gadget.as_slice()).unwrap(); + + println!("number of constraints total: {}", cs.num_constraints()); + + assert_eq!(primitive_result, gadget_result.value.unwrap()); + assert!(cs.is_satisfied()); + } } \ No newline at end of file diff --git a/r1cs/gadgets/crypto/src/crh/poseidon/tweedle.rs b/r1cs/gadgets/crypto/src/crh/poseidon/tweedle.rs new file mode 100644 index 000000000..114958e14 --- /dev/null +++ b/r1cs/gadgets/crypto/src/crh/poseidon/tweedle.rs @@ -0,0 +1,25 @@ +use algebra::fields::tweedle::{Fq, Fr}; +use primitives::crh::parameters::{ + TweedleFqPoseidonParameters, TweedleFqQuinticSbox, + TweedleFrPoseidonParameters, TweedleFrQuinticSbox, +}; +use crate::crh::{ + sbox::QuinticSBoxGadget, + poseidon::PoseidonHashGadget, +}; + +type TweedleFqQuinticSboxGadget = QuinticSBoxGadget; +pub type TweedleFqPoseidonHashGadget = PoseidonHashGadget< + Fq, + TweedleFqPoseidonParameters, + TweedleFqQuinticSbox, + TweedleFqQuinticSboxGadget +>; + +type TweedleFrQuinticSboxGadget = QuinticSBoxGadget; +pub type TweedleFrPoseidonHashGadget = PoseidonHashGadget< + Fr, + TweedleFrPoseidonParameters, + TweedleFrQuinticSbox, + TweedleFrQuinticSboxGadget +>; diff --git a/r1cs/gadgets/std/src/instantiated/mod.rs b/r1cs/gadgets/std/src/instantiated/mod.rs index e96e3722c..210c79f75 100644 --- a/r1cs/gadgets/std/src/instantiated/mod.rs +++ b/r1cs/gadgets/std/src/instantiated/mod.rs @@ -17,4 +17,7 @@ pub mod jubjub; pub mod mnt4_753; #[cfg(feature = "mnt6_753")] -pub mod mnt6_753; \ No newline at end of file +pub mod mnt6_753; + +#[cfg(feature = "tweedle")] +pub mod tweedle; diff --git a/r1cs/gadgets/std/src/instantiated/tweedle/curves.rs b/r1cs/gadgets/std/src/instantiated/tweedle/curves.rs new file mode 100644 index 000000000..42779b9f5 --- /dev/null +++ b/r1cs/gadgets/std/src/instantiated/tweedle/curves.rs @@ -0,0 +1,28 @@ +use algebra::{ + fields::tweedle::{Fq, Fr}, + curves::tweedle::{ + dee::TweedledeeParameters, + dum::TweedledumParameters, + } +}; +use crate::{ + groups::curves::short_weierstrass::short_weierstrass_jacobian::AffineGadget, + instantiated::tweedle::{FqGadget, FrGadget}, +}; + +pub type TweedleDeeGadget = AffineGadget; +pub type TweedleDumGadget = AffineGadget; + +#[test] +fn test_dee() { + crate::groups::test::group_test_with_unsafe_add::< + _, _, TweedleDeeGadget + >(); +} + +#[test] +fn test_dum() { + crate::groups::test::group_test_with_unsafe_add::< + _, _, TweedleDumGadget + >(); +} \ No newline at end of file diff --git a/r1cs/gadgets/std/src/instantiated/tweedle/fields.rs b/r1cs/gadgets/std/src/instantiated/tweedle/fields.rs new file mode 100644 index 000000000..245391285 --- /dev/null +++ b/r1cs/gadgets/std/src/instantiated/tweedle/fields.rs @@ -0,0 +1,27 @@ +use algebra::fields::tweedle::{Fq, Fr}; +use crate::fields::fp::FpGadget; + +pub type FqGadget = FpGadget; +pub type FrGadget = FpGadget; + +#[test] +fn test_fq() { + use crate::fields::tests::*; + + field_test::<_, Fq, FqGadget>(); + frobenius_tests::(13); + equ_verdict_fp_gadget_test::(); + from_bits_fp_gadget_test::(); + bit_fp_gadgets_test::(); +} + +#[test] +fn test_fr() { + use crate::fields::tests::*; + + field_test::<_, Fr, FrGadget>(); + frobenius_tests::(13); + equ_verdict_fp_gadget_test::(); + from_bits_fp_gadget_test::(); + bit_fp_gadgets_test::(); +} \ No newline at end of file diff --git a/r1cs/gadgets/std/src/instantiated/tweedle/mod.rs b/r1cs/gadgets/std/src/instantiated/tweedle/mod.rs new file mode 100644 index 000000000..5d9009b45 --- /dev/null +++ b/r1cs/gadgets/std/src/instantiated/tweedle/mod.rs @@ -0,0 +1,5 @@ +mod curves; +mod fields; + +pub use curves::*; +pub use fields::*; \ No newline at end of file From c0764d4461ca753cc7eb9a1eb8710960ddf64a7b Mon Sep 17 00:00:00 2001 From: Phoinic Date: Fri, 19 Mar 2021 08:56:45 +0200 Subject: [PATCH 59/63] ToConstraintFieldGadget trait implementation for SWAffineGadget --- .../signature/schnorr/field_based_schnorr.rs | 2 +- r1cs/gadgets/std/src/to_field_gadget_vec.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs b/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs index deb7487aa..93b4f2de2 100644 --- a/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs +++ b/r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs @@ -299,7 +299,7 @@ impl ToConstraintFieldGadget for FieldBasedSchn where ConstraintF: PrimeField, G: Group, - GG: GroupGadget + ToConstraintFieldGadget>, + GG: GroupGadget + ToConstraintFieldGadget>, { type FieldGadget = FpGadget; diff --git a/r1cs/gadgets/std/src/to_field_gadget_vec.rs b/r1cs/gadgets/std/src/to_field_gadget_vec.rs index cec998c72..a3c967bb6 100644 --- a/r1cs/gadgets/std/src/to_field_gadget_vec.rs +++ b/r1cs/gadgets/std/src/to_field_gadget_vec.rs @@ -6,6 +6,7 @@ use algebra::{ use crate::{ fields::FieldGadget, + groups::curves::short_weierstrass::short_weierstrass_jacobian::AffineGadget as SWAffineGadget, groups::curves::short_weierstrass::short_weierstrass_projective::AffineGadget as SWPAffineGadget, groups::curves::twisted_edwards::AffineGadget as TEAffineGadget, }; @@ -48,6 +49,24 @@ impl ToConstraintFieldGadget for () { } } +impl ToConstraintFieldGadget for SWAffineGadget + where + M: SWModelParameters, + ConstraintF: PrimeField, + FG: FieldGadget + + ToConstraintFieldGadget>, +{ + type FieldGadget = FpGadget; + + #[inline] + fn to_field_gadget_elements>(&self, mut cs: CS) -> Result, Error> { + let mut x_fe = self.x.to_field_gadget_elements(cs.ns(|| "x"))?; + let y_fe = self.y.to_field_gadget_elements(cs.ns(|| "y"))?; + x_fe.extend_from_slice(&y_fe); + Ok(x_fe) + } +} + impl ToConstraintFieldGadget for SWPAffineGadget where M: SWModelParameters, From ba0e2d7a0c1d5f7cdd6758e4e92728826470b62c Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 22 Mar 2021 03:48:13 +0200 Subject: [PATCH 60/63] ToBytes / FromBytes implementation for polynomials --- Cargo.toml | 13 ++++----- algebra-utils/src/fft/evaluations.rs | 33 ++++++++++++++++++++++- algebra-utils/src/fft/polynomial/dense.rs | 26 ++++++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 84c085af7..19548ad76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,9 +36,10 @@ debug = true # Uncomment these lines for local development paths -# [patch.'https://github.com/HorizenOfficial/ginger-lib'] -# algebra = { path = './algebra' } - -# [patch.'https://github.com/HorizenOfficial/ginger-algebra-ocl'] -# algebra-kernels = { path = '../ginger-algebra-ocl/algebra-kernels' } -# algebra-cl-gen = { path = '../ginger-algebra-ocl/algebra-cl-gen' } +#[patch.'https://github.com/HorizenOfficial/ginger-lib'] +#algebra = { path = './algebra' } +#primitives = { path = './primitives' } +# +#[patch.'https://github.com/HorizenOfficial/ginger-algebra-ocl'] +#algebra-kernels = { path = '../ginger-algebra-ocl/algebra-kernels' } +#algebra-cl-gen = { path = '../ginger-algebra-ocl/algebra-cl-gen' } diff --git a/algebra-utils/src/fft/evaluations.rs b/algebra-utils/src/fft/evaluations.rs index af43b6460..c5f0085f4 100644 --- a/algebra-utils/src/fft/evaluations.rs +++ b/algebra-utils/src/fft/evaluations.rs @@ -2,7 +2,7 @@ use std::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; use algebra::PrimeField; -use crate::{DensePolynomial, EvaluationDomain}; +use crate::{DensePolynomial, EvaluationDomain, get_best_evaluation_domain}; /// Stores a polynomial in evaluation form. pub struct Evaluations { @@ -34,6 +34,37 @@ impl Evaluations { } } +impl algebra::ToBytes for Evaluations +{ + fn write(&self, mut w: W) -> std::io::Result<()> { + (self.evals.len() as u64).write(&mut w)?; + for e in self.evals.iter() { + e.write(&mut w)?; + } + Ok(()) + } +} + +impl algebra::FromBytes for Evaluations +{ + #[inline] + fn read(mut reader: Read) -> std::io::Result> { + let evals_count = u64::read(&mut reader) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + let mut evals = vec![]; + for _ in 0..evals_count { + let eval = F::read(&mut reader) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + evals.push(eval); + } + let domain = get_best_evaluation_domain::(evals.len()).unwrap(); + Ok(Evaluations:: { + evals, + domain + }) + } +} + impl std::ops::Index for Evaluations { type Output = F; diff --git a/algebra-utils/src/fft/polynomial/dense.rs b/algebra-utils/src/fft/polynomial/dense.rs index 4e568a53d..e291749b8 100644 --- a/algebra-utils/src/fft/polynomial/dense.rs +++ b/algebra-utils/src/fft/polynomial/dense.rs @@ -15,6 +15,32 @@ pub struct DensePolynomial { pub coeffs: Vec, } +impl algebra::ToBytes for DensePolynomial +{ + fn write(&self, mut w: W) -> std::io::Result<()> { + (self.coeffs.len() as u64).write(&mut w)?; + for c in self.coeffs.iter() { + c.write(&mut w)?; + } + Ok(()) + } +} + +impl algebra::FromBytes for DensePolynomial +{ + fn read(mut reader: Read) -> std::io::Result> { + let mut coeffs = vec![]; + let coeffs_count = u64::read(&mut reader) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + for _ in 0..coeffs_count { + let coeff = F::read(&mut reader) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + coeffs.push(coeff); + } + Ok(DensePolynomial::from_coefficients_vec(coeffs)) + } +} + impl fmt::Debug for DensePolynomial { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { for (i, coeff) in self.coeffs.iter().enumerate().filter(|(_, c)| !c.is_zero()) { From a1d2f0ead8d2fc71c4559e2bcd8f4989396c8121 Mon Sep 17 00:00:00 2001 From: Phoinic Date: Mon, 22 Mar 2021 17:53:12 +0200 Subject: [PATCH 61/63] Parameters converted to hex representation --- algebra/src/fields/tweedle/fr.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/algebra/src/fields/tweedle/fr.rs b/algebra/src/fields/tweedle/fr.rs index a1f7dfa84..097de4520 100644 --- a/algebra/src/fields/tweedle/fr.rs +++ b/algebra/src/fields/tweedle/fr.rs @@ -13,24 +13,24 @@ impl FpParameters for FrParameters { // 28948022309329048855892746252171976963322203655955319056773317069363642105857 const MODULUS: BigInteger = BigInteger([ - 11619397960441266177, - 255193519591741881, - 0, - 4611686018427387904, + 0xa14064e200000001, + 0x38aa1276c3f59b9, + 0x0, + 0x4000000000000000 ]); const R: BigInteger = BigInteger([ - 2035294266095304701, - 17681163514934325971, - 18446744073709551615, - 4611686018427387903, + 0x1c3ed159fffffffd, + 0xf5601c89bb41f2d3, + 0xffffffffffffffff, + 0x3fffffffffffffff ]); const R2: BigInteger = BigInteger([ - 2885853259929485328, - 10494584067553537908, - 15959394653775906393, - 56485833754855950, + 0x280c9c4000000010, + 0x91a4409b5400af74, + 0xdd7b28e19094c659, + 0xc8ad9107ccca0e ]); const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([ @@ -48,10 +48,10 @@ impl FpParameters for FrParameters { // GENERATOR = 5 const GENERATOR: BigInteger = BigInteger([ - 592367636130562029, - 13598067201466455865, - 18446744073709551615, - 4611686018427387903, + 0x8388339ffffffed, + 0xbcb60a12f74c5739, + 0xffffffffffffffff, + 0x3fffffffffffffff ]); const MODULUS_BITS: u32 = 255; From 47a86da3f25249d3a71bb7d27ffcce8d0df563c1 Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto Date: Wed, 24 Mar 2021 10:59:08 +0100 Subject: [PATCH 62/63] Added get_leaves() function to InMemoryOptimizedMHT --- .../field_based_mht/optimized/mod.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs b/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs index d8d39e91e..d353d88ae 100644 --- a/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs +++ b/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs @@ -135,6 +135,11 @@ impl FieldBasedOptimizedMHT { } } + #[allow(dead_code)] + fn get_leaves(&self) -> &[T::Data] { + &self.array_nodes[self.initial_pos[0]..self.new_elem_pos[0]] + } + fn batch_hash(input: &mut [T::Data], output: &mut [T::Data], parent_level: usize) { let mut i = 0; @@ -349,12 +354,17 @@ mod test { let height = 20; let num_leaves = 2usize.pow(height as u32); let mut tree = MNT4PoseidonMHT::init(height, num_leaves); + assert_eq!(tree.get_leaves().len(), 0); let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + let mut leaves = Vec::new(); for _ in 0..num_leaves { - tree.append(MNT4753Fr::rand(&mut rng)); + let r = MNT4753Fr::rand(&mut rng); + leaves.push(r); + tree.append(r); } tree.finalize_in_place(); assert_eq!(tree.root().unwrap(), expected_output, "Output of the Merkle tree computation for MNT4 does not match to the expected value."); + assert_eq!(tree.get_leaves(), leaves.as_slice(), ""); } #[test] @@ -363,12 +373,17 @@ mod test { let height = 20; let num_leaves = 2usize.pow(height as u32); let mut tree = MNT6PoseidonMHT::init(height, num_leaves); + assert_eq!(tree.get_leaves().len(), 0); let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + let mut leaves = Vec::new(); for _ in 0..num_leaves { - tree.append(MNT6753Fr::rand(&mut rng)); + let r = MNT6753Fr::rand(&mut rng); + leaves.push(r); + tree.append(r); } tree.finalize_in_place(); assert_eq!(tree.root().unwrap(), expected_output, "Output of the Merkle tree computation for MNT6 does not match to the expected value."); + assert_eq!(tree.get_leaves(), leaves.as_slice()); } #[test] From 35d5bf65aac2370b3cbfc4027a5f1097949c76bf Mon Sep 17 00:00:00 2001 From: DanieleDiBenedetto <50587279+DanieleDiBenedetto@users.noreply.github.com> Date: Wed, 24 Mar 2021 18:51:38 +0100 Subject: [PATCH 63/63] Change visibility of get_leaves() function --- primitives/src/merkle_tree/field_based_mht/optimized/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs b/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs index d353d88ae..4ea5caabb 100644 --- a/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs +++ b/primitives/src/merkle_tree/field_based_mht/optimized/mod.rs @@ -135,8 +135,7 @@ impl FieldBasedOptimizedMHT { } } - #[allow(dead_code)] - fn get_leaves(&self) -> &[T::Data] { + pub fn get_leaves(&self) -> &[T::Data] { &self.array_nodes[self.initial_pos[0]..self.new_elem_pos[0]] } @@ -657,4 +656,4 @@ mod test { assert_eq!(path, path_deserialized); } } -} \ No newline at end of file +}