From 88d9dd7f8ac5d6b7b0a6964a0ed0bae66dd381ea Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Sat, 1 Feb 2025 11:22:09 -0500 Subject: [PATCH 01/17] rescue works --- Cargo.toml | 18 +- crypto-primitives/Cargo.toml | 30 +- .../src/commitment/blake2s/constraints.rs | 10 +- .../src/commitment/blake2s/mod.rs | 2 +- .../src/commitment/constraints.rs | 4 +- .../commitment/injective_map/constraints.rs | 2 +- .../src/commitment/injective_map/mod.rs | 2 +- crypto-primitives/src/commitment/mod.rs | 4 +- .../src/commitment/pedersen/constraints.rs | 133 ++- .../src/commitment/pedersen/mod.rs | 2 +- .../src/crh/bowe_hopwood/constraints.rs | 271 +++-- crypto-primitives/src/crh/bowe_hopwood/mod.rs | 2 +- crypto-primitives/src/crh/constraints.rs | 6 +- .../src/crh/injective_map/constraints.rs | 8 +- .../src/crh/injective_map/mod.rs | 2 +- crypto-primitives/src/crh/mod.rs | 5 +- .../src/crh/pedersen/constraints.rs | 208 ++-- crypto-primitives/src/crh/pedersen/mod.rs | 2 +- .../src/crh/poseidon/constraints.rs | 8 +- crypto-primitives/src/crh/poseidon/mod.rs | 4 +- .../src/crh/rescue/gr1cs_constraints.rs | 202 ++++ crypto-primitives/src/crh/rescue/mod.rs | 102 ++ .../src/crh/rescue/r1cs_constraints.rs | 156 +++ .../src/crh/sha256/constraints.rs | 14 +- crypto-primitives/src/crh/sha256/mod.rs | 2 +- .../src/encryption/constraints.rs | 2 +- .../src/encryption/elgamal/constraints.rs | 126 +-- .../src/encryption/elgamal/mod.rs | 2 +- crypto-primitives/src/encryption/mod.rs | 4 +- .../src/merkle_tree/constraints.rs | 18 +- crypto-primitives/src/merkle_tree/mod.rs | 2 +- .../src/merkle_tree/tests/constraints.rs | 952 +++++++++--------- .../src/merkle_tree/tests/mod.rs | 2 +- .../src/merkle_tree/tests/test_utils.rs | 2 +- .../src/prf/blake2s/constraints.rs | 22 +- crypto-primitives/src/prf/blake2s/mod.rs | 2 +- crypto-primitives/src/prf/constraints.rs | 4 +- crypto-primitives/src/prf/mod.rs | 4 +- .../src/signature/constraints.rs | 2 +- crypto-primitives/src/signature/mod.rs | 4 +- .../src/signature/schnorr/constraints.rs | 4 +- .../src/signature/schnorr/mod.rs | 2 +- crypto-primitives/src/snark/constraints.rs | 8 +- crypto-primitives/src/snark/mod.rs | 4 +- .../src/sponge/constraints/absorb.rs | 10 +- .../src/sponge/constraints/mod.rs | 6 +- crypto-primitives/src/sponge/mod.rs | 8 +- .../src/sponge/poseidon/constraints.rs | 28 +- crypto-primitives/src/sponge/poseidon/mod.rs | 2 +- .../src/sponge/rescue/gr1cs_constraints.rs | 400 ++++++++ .../src/sponge/rescue/grain_lfsr.rs | 218 ++++ crypto-primitives/src/sponge/rescue/mod.rs | 396 ++++++++ crypto-primitives/src/sponge/rescue/tests.rs | 729 ++++++++++++++ crypto-primitives/src/sponge/rescue/traits.rs | 351 +++++++ 54 files changed, 3529 insertions(+), 984 deletions(-) create mode 100644 crypto-primitives/src/crh/rescue/gr1cs_constraints.rs create mode 100644 crypto-primitives/src/crh/rescue/mod.rs create mode 100644 crypto-primitives/src/crh/rescue/r1cs_constraints.rs create mode 100644 crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs create mode 100644 crypto-primitives/src/sponge/rescue/grain_lfsr.rs create mode 100644 crypto-primitives/src/sponge/rescue/mod.rs create mode 100644 crypto-primitives/src/sponge/rescue/tests.rs create mode 100644 crypto-primitives/src/sponge/rescue/traits.rs diff --git a/Cargo.toml b/Cargo.toml index afe68c49..c378d3d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,13 +6,13 @@ members = [ resolver = "2" [workspace.package] -version = "0.4.0" +version = "0.5.0" authors = [ "arkworks contributors" ] description = "A library of useful cryptographic primitives" homepage = "https://arkworks.rs" repository = "https://github.com/arkworks-rs/crypto-primitives" documentation = "https://docs.rs/ark-crypto-primitives/" -keywords = [ "r1cs", "pedersen", "blake2s", "snark", "schnorr" ] +keywords = [ "gr1cs", "pedersen", "blake2s", "snark", "schnorr" ] categories = ["cryptography"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" @@ -42,17 +42,3 @@ lto = "thin" incremental = true debug-assertions = true debug = true - -[patch.crates-io] -ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" } -ark-ff = { git = "https://github.com/arkworks-rs/algebra/" } -ark-ec = { git = "https://github.com/arkworks-rs/algebra/" } -ark-poly = { git = "https://github.com/arkworks-rs/algebra/" } -ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" } -ark-std = { git = "https://github.com/arkworks-rs/std/" } - -ark-ed-on-bls12-377 = { git = "https://github.com/arkworks-rs/algebra/" } -ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/algebra/" } -ark-bls12-377 = { git = "https://github.com/arkworks-rs/algebra/" } -ark-mnt4-298 = { git = "https://github.com/arkworks-rs/algebra/" } -ark-mnt6-298 = { git = "https://github.com/arkworks-rs/algebra/" } diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index 5799c154..b75645f6 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -15,21 +15,21 @@ edition.workspace = true ################################# Dependencies ################################ [dependencies] -ark-crypto-primitives-macros = { version = "^0.4.0", path = "../macros" } +ark-crypto-primitives-macros = { version = "^0.5.0", path = "../macros" } -ark-ff = { version = "^0.4.0", default-features = false } -ark-ec = { version = "^0.4.0", default-features = false } -ark-std = { version = "^0.4.0", default-features = false } -ark-relations = { version = "^0.4.0", default-features = false } -ark-serialize = { version = "^0.4.0", default-features = false, features = [ "derive" ] } +ark-ff = { version = "^0.5.0", default-features = false } +ark-ec = { version = "^0.5.0", default-features = false } +ark-std = { version = "^0.5.0", default-features = false } +ark-relations = { git = "https://github.com/arkworks-rs/snark.git", default-features = true } +ark-serialize = { version = "^0.5.0", default-features = false, features = [ "derive" ] } blake2 = { version = "0.10", default-features = false } sha2 = { version = "0.10", default-features = false } digest = { version = "0.10", default-features = false } merlin = { version = "3.0.0", default-features = false, optional = true } - -ark-r1cs-std = { version = "^0.4.0", optional = true, default-features = false } -ark-snark = { version = "^0.4.0", default-features = false } +num-bigint = "0.4.4" +ark-r1cs-std = { path = "../../r1cs-std", optional = true, default-features = false} +ark-snark = { version = "^0.5.0", default-features = false } rayon = { version = "1.0", optional = true } derivative = { version = "2.0", features = ["use_core"] } @@ -42,6 +42,7 @@ std = [ "ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std" ] print-trace = [ "ark-std/print-trace" ] parallel = [ "std", "rayon", "ark-ec/parallel", "ark-std/parallel", "ark-ff/parallel" ] r1cs = [ "ark-r1cs-std", "tracing" ] +gr1cs = [ "ark-r1cs-std", "tracing" ] crh = [ "sponge" ] sponge = [ "merlin" ] commitment = [ "crh" ] @@ -58,11 +59,12 @@ ahash = { version = "0.8", default-features = false} fnv = { version = "1.0", default-features = false } [dev-dependencies] -ark-ed-on-bls12-377 = { version = "^0.4.0", default-features = false } -ark-ed-on-bls12-381 = { version = "^0.4.0", default-features = false, features = [ "r1cs" ] } -ark-bls12-377 = { version = "^0.4.0", default-features = false, features = [ "curve", "r1cs" ] } -ark-mnt4-298 = { version = "^0.4.0", default-features = false, features = [ "curve", "r1cs" ] } -ark-mnt6-298 = { version = "^0.4.0", default-features = false, features = [ "r1cs" ] } +ark-ed-on-bls12-377 = { version = "^0.5.0", default-features = false } +ark-ed-on-bls12-381 = { version = "^0.5.0", default-features = false } +ark-bls12-377 = { version = "^0.5.0", default-features = false, features = [ "curve"] } +ark-bls12-381 = { version = "^0.5.0", default-features = false, features = [ "curve"] } +ark-mnt4-298 = { version = "^0.5.0", default-features = false, features = [ "curve"] } +ark-mnt6-298 = { version = "^0.5.0", default-features = false } criterion = { version = "0.4" } ################################# Benchmarks ################################## diff --git a/crypto-primitives/src/commitment/blake2s/constraints.rs b/crypto-primitives/src/commitment/blake2s/constraints.rs index 3989d974..9fd72bf6 100644 --- a/crypto-primitives/src/commitment/blake2s/constraints.rs +++ b/crypto-primitives/src/commitment/blake2s/constraints.rs @@ -4,7 +4,7 @@ use crate::{ }; use ark_ff::{Field, PrimeField}; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; use ark_std::borrow::Borrow; #[derive(Clone)] @@ -20,7 +20,7 @@ impl CommitmentGadget for CommGadget { type ParametersVar = ParametersVar; type RandomnessVar = RandomnessVar; - #[tracing::instrument(target = "r1cs", skip(input, r))] + #[tracing::instrument(target = "gr1cs", skip(input, r))] fn commit( _: &Self::ParametersVar, input: &[UInt8], @@ -40,7 +40,7 @@ impl CommitmentGadget for CommGadget { } impl AllocVar<(), ConstraintF> for ParametersVar { - #[tracing::instrument(target = "r1cs", skip(_cs, _f))] + #[tracing::instrument(target = "gr1cs", skip(_cs, _f))] fn new_variable>( _cs: impl Into>, _f: impl FnOnce() -> Result, @@ -51,7 +51,7 @@ impl AllocVar<(), ConstraintF> for ParametersVar { } impl AllocVar<[u8; 32], ConstraintF> for RandomnessVar { - #[tracing::instrument(target = "r1cs", skip(cs, f))] + #[tracing::instrument(target = "gr1cs", skip(cs, f))] fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, @@ -77,7 +77,7 @@ mod test { }; use ark_ed_on_bls12_381::Fq as Fr; use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::ConstraintSystem; + use ark_relations::gr1cs::ConstraintSystem; use ark_std::rand::Rng; #[test] diff --git a/crypto-primitives/src/commitment/blake2s/mod.rs b/crypto-primitives/src/commitment/blake2s/mod.rs index 724f3771..9a5c104b 100644 --- a/crypto-primitives/src/commitment/blake2s/mod.rs +++ b/crypto-primitives/src/commitment/blake2s/mod.rs @@ -5,7 +5,7 @@ use digest::Digest; pub struct Commitment; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; impl CommitmentScheme for Commitment { diff --git a/crypto-primitives/src/commitment/constraints.rs b/crypto-primitives/src/commitment/constraints.rs index e7a533ee..304ba178 100644 --- a/crypto-primitives/src/commitment/constraints.rs +++ b/crypto-primitives/src/commitment/constraints.rs @@ -1,14 +1,14 @@ use crate::commitment::CommitmentScheme; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; use ark_std::fmt::Debug; pub trait CommitmentGadget { type OutputVar: EqGadget + ToBytesGadget + AllocVar - + R1CSVar + + GR1CSVar + Clone + Sized + Debug; diff --git a/crypto-primitives/src/commitment/injective_map/constraints.rs b/crypto-primitives/src/commitment/injective_map/constraints.rs index 13a9d67f..5af9f2a9 100644 --- a/crypto-primitives/src/commitment/injective_map/constraints.rs +++ b/crypto-primitives/src/commitment/injective_map/constraints.rs @@ -12,7 +12,7 @@ use ark_r1cs_std::{ groups::{CurveVar, GroupOpsBounds}, uint8::UInt8, }; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; use ark_std::marker::PhantomData; type ConstraintF = <::BaseField as Field>::BasePrimeField; diff --git a/crypto-primitives/src/commitment/injective_map/mod.rs b/crypto-primitives/src/commitment/injective_map/mod.rs index ca32904c..d7a050e4 100644 --- a/crypto-primitives/src/commitment/injective_map/mod.rs +++ b/crypto-primitives/src/commitment/injective_map/mod.rs @@ -6,7 +6,7 @@ use crate::{ use ark_ec::CurveGroup; use ark_std::{marker::PhantomData, rand::Rng}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub struct PedersenCommCompressor, W: pedersen::Window> { diff --git a/crypto-primitives/src/commitment/mod.rs b/crypto-primitives/src/commitment/mod.rs index c94db15b..6b845d63 100644 --- a/crypto-primitives/src/commitment/mod.rs +++ b/crypto-primitives/src/commitment/mod.rs @@ -7,9 +7,9 @@ pub mod blake2s; pub mod injective_map; pub mod pedersen; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub use constraints::*; pub trait CommitmentScheme { diff --git a/crypto-primitives/src/commitment/pedersen/constraints.rs b/crypto-primitives/src/commitment/pedersen/constraints.rs index 8dec380a..757a0009 100644 --- a/crypto-primitives/src/commitment/pedersen/constraints.rs +++ b/crypto-primitives/src/commitment/pedersen/constraints.rs @@ -8,7 +8,7 @@ use ark_ff::{ Zero, }; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; use ark_serialize::CanonicalSerialize; use ark_std::{borrow::Borrow, iter, marker::PhantomData}; @@ -138,69 +138,68 @@ where } } -#[cfg(test)] -mod test { - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq, Fr}; - use ark_std::{test_rng, UniformRand}; - - use crate::{ - commitment::{ - pedersen::{constraints::CommGadget, Commitment, Randomness}, - CommitmentGadget, CommitmentScheme, - }, - crh::pedersen, - }; - use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::ConstraintSystem; - - /// Checks that the primitive Pedersen commitment matches the gadget version - #[test] - fn commitment_gadget_test() { - let cs = ConstraintSystem::::new_ref(); - - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct Window; - - impl pedersen::Window for Window { - const WINDOW_SIZE: usize = 4; - const NUM_WINDOWS: usize = 9; - } - - let input = [1u8; 4]; - - let rng = &mut test_rng(); - - type TestCOMM = Commitment; - type TestCOMMGadget = CommGadget; - - let randomness = Randomness(Fr::rand(rng)); - - let parameters = Commitment::::setup(rng).unwrap(); - let primitive_result = - Commitment::::commit(¶meters, &input, &randomness).unwrap(); - - let mut input_var = vec![]; - for input_byte in input.iter() { - input_var.push(UInt8::new_witness(cs.clone(), || Ok(*input_byte)).unwrap()); - } - - let randomness_var = - >::RandomnessVar::new_witness( - ark_relations::ns!(cs, "gadget_randomness"), - || Ok(&randomness), - ) - .unwrap(); - let parameters_var = - >::ParametersVar::new_witness( - ark_relations::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = - TestCOMMGadget::commit(¶meters_var, &input_var, &randomness_var).unwrap(); - - let primitive_result = primitive_result; - assert_eq!(primitive_result, result_var.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } -} +// #[cfg(test)] +// mod test { +// use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq, Fr}; +// use ark_std::{test_rng, UniformRand}; + +// use crate::{ +// commitment::{ +// pedersen::{constraints::CommGadget, Commitment, Randomness}, +// CommitmentGadget, CommitmentScheme, +// }, +// crh::pedersen, +// }; +// use ark_r1cs_std::prelude::*; +// use ark_relations::gr1cs::ConstraintSystem; + +// /// Checks that the primitive Pedersen commitment matches the gadget version +// #[test] +// fn commitment_gadget_test() { +// let cs = ConstraintSystem::::new_ref(); + +// #[derive(Clone, PartialEq, Eq, Hash)] +// pub(super) struct Window; + +// impl pedersen::Window for Window { +// const WINDOW_SIZE: usize = 4; +// const NUM_WINDOWS: usize = 9; +// } + +// let input = [1u8; 4]; + +// let rng = &mut test_rng(); + +// type TestCOMM = Commitment; +// type TestCOMMGadget = CommGadget; + +// let randomness = Randomness(Fr::rand(rng)); + +// let parameters = Commitment::::setup(rng).unwrap(); +// let primitive_result = +// Commitment::::commit(¶meters, &input, &randomness).unwrap(); + +// let mut input_var = vec![]; +// for input_byte in input.iter() { +// input_var.push(UInt8::new_witness(cs.clone(), || Ok(*input_byte)).unwrap()); +// } + +// let randomness_var = +// >::RandomnessVar::new_witness( +// ark_relations::ns!(cs, "gadget_randomness"), +// || Ok(&randomness), +// ) +// .unwrap(); +// let parameters_var = +// >::ParametersVar::new_witness( +// ark_relations::ns!(cs, "gadget_parameters"), +// || Ok(¶meters), +// ) +// .unwrap(); +// let result_var = +// TestCOMMGadget::commit(¶meters_var, &input_var, &randomness_var).unwrap(); + +// assert_eq!(primitive_result, result_var.value().unwrap()); +// assert!(cs.is_satisfied().unwrap()); +// } +// } diff --git a/crypto-primitives/src/commitment/pedersen/mod.rs b/crypto-primitives/src/commitment/pedersen/mod.rs index 96345322..a039b69e 100644 --- a/crypto-primitives/src/commitment/pedersen/mod.rs +++ b/crypto-primitives/src/commitment/pedersen/mod.rs @@ -11,7 +11,7 @@ use ark_serialize::CanonicalSerialize; use ark_std::vec::Vec; use ark_std::{marker::PhantomData, rand::Rng, UniformRand}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; #[derive(Clone)] diff --git a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs index fd0c433b..167f9461 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs @@ -9,7 +9,7 @@ use ark_ec::{ }; use ark_ff::Field; use ark_r1cs_std::{groups::curves::twisted_edwards::AffineVar, prelude::*}; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, iter, marker::PhantomData}; @@ -48,7 +48,7 @@ where type OutputVar = F; type ParametersVar = ParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters, input))] + #[tracing::instrument(target = "gr1cs", skip(parameters, input))] fn evaluate( parameters: &Self::ParametersVar, input: &Self::InputVar, @@ -117,7 +117,7 @@ where type OutputVar = F; type ParametersVar = ParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters))] + #[tracing::instrument(target = "gr1cs", skip(parameters))] fn evaluate( parameters: &Self::ParametersVar, left_input: &Self::InputVar, @@ -156,7 +156,7 @@ where P: TECurveConfig, W: Window, { - #[tracing::instrument(target = "r1cs", skip(_cs, f))] + #[tracing::instrument(target = "gr1cs", skip(_cs, f))] fn new_variable>>( _cs: impl Into>>, f: impl FnOnce() -> Result, @@ -170,135 +170,134 @@ where } } -#[cfg(test)] -mod test { - use ark_std::rand::Rng; - - use crate::crh::bowe_hopwood; - use crate::crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; - use crate::crh::{CRHScheme, CRHSchemeGadget}; - use ark_ed_on_bls12_381::{constraints::FqVar, EdwardsConfig, Fq as Fr}; - use ark_r1cs_std::{alloc::AllocVar, uint8::UInt8, R1CSVar}; - use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef}; - use ark_std::test_rng; - - type TestCRH = bowe_hopwood::CRH; - type TestCRHGadget = bowe_hopwood::constraints::CRHGadget; - - type TestTwoToOneCRH = bowe_hopwood::TwoToOneCRH; - type TestTwoToOneCRHGadget = bowe_hopwood::constraints::TwoToOneCRHGadget; - - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct Window; - - impl pedersen::Window for Window { - const WINDOW_SIZE: usize = 63; - const NUM_WINDOWS: usize = 8; - } - - fn generate_u8_input( - cs: ConstraintSystemRef, - size: usize, - rng: &mut R, - ) -> (Vec, Vec>) { - let mut input = vec![1u8; size]; - rng.fill_bytes(&mut input); - - let mut input_bytes = vec![]; - for byte in input.iter() { - input_bytes.push(UInt8::new_witness(cs.clone(), || Ok(byte)).unwrap()); - } - (input, input_bytes) - } - - #[test] - fn test_native_equality() { - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - let (input, input_var) = generate_u8_input(cs.clone(), 189, rng); - println!("number of constraints for input: {}", cs.num_constraints()); - - let parameters = TestCRH::setup(rng).unwrap(); - let primitive_result = TestCRH::evaluate(¶meters, input.as_slice()).unwrap(); - - let parameters_var = - >::ParametersVar::new_witness( - ark_relations::ns!(cs, "parameters_var"), - || Ok(¶meters), - ) - .unwrap(); - println!( - "number of constraints for input + params: {}", - cs.num_constraints() - ); - - let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); - - println!("number of constraints total: {}", cs.num_constraints()); - - assert_eq!(primitive_result, result_var.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } - - #[test] - fn test_native_two_to_one_equality() { - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - // Max input size is 63 bytes. That leaves 31 for the left half, 31 for the right, and 1 - // byte of padding. - let (left_input, left_input_var) = generate_u8_input(cs.clone(), 31, rng); - let (right_input, right_input_var) = generate_u8_input(cs.clone(), 31, rng); - let parameters = TestTwoToOneCRH::setup(rng).unwrap(); - let primitive_result = - TestTwoToOneCRH::evaluate(¶meters, left_input.as_slice(), right_input.as_slice()) - .unwrap(); - - let parameters_var = >::ParametersVar::new_witness( - ark_relations::ns!(cs, "parameters_var"), - || Ok(¶meters), - ) - .unwrap(); - - let result_var = - TestTwoToOneCRHGadget::evaluate(¶meters_var, &left_input_var, &right_input_var) - .unwrap(); - - let primitive_result = primitive_result; - assert_eq!(primitive_result, result_var.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } - - #[should_panic] - #[test] - fn test_input_size_check() { - // Pick parameters that are far too small for a CRH - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct TooSmallWindow; - impl pedersen::Window for TooSmallWindow { - const WINDOW_SIZE: usize = 1; - const NUM_WINDOWS: usize = 1; - } - type TestCRH = bowe_hopwood::CRH; - type TestCRHGadget = bowe_hopwood::constraints::CRHGadget; - - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - let (_, input_var) = generate_u8_input(cs.clone(), 189, rng); - println!("number of constraints for input: {}", cs.num_constraints()); - - let parameters = TestCRH::setup(rng).unwrap(); - let parameters_var = - >::ParametersVar::new_witness( - ark_relations::ns!(cs, "parameters_var"), - || Ok(¶meters), - ) - .unwrap(); - let _ = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); - } -} +// #[cfg(test)] +// mod test { +// use ark_std::rand::Rng; + +// use crate::crh::bowe_hopwood; +// use crate::crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; +// use crate::crh::{CRHScheme, CRHSchemeGadget}; +// use ark_ed_on_bls12_381::{constraints::FqVar, EdwardsConfig, Fq as Fr}; +// use ark_r1cs_std::{alloc::AllocVar, uint8::UInt8, R1CSVar}; +// use ark_relations::gr1cs::{ConstraintSystem, ConstraintSystemRef}; +// use ark_std::test_rng; + +// type TestCRH = bowe_hopwood::CRH; +// type TestCRHGadget = bowe_hopwood::constraints::CRHGadget; + +// type TestTwoToOneCRH = bowe_hopwood::TwoToOneCRH; +// type TestTwoToOneCRHGadget = bowe_hopwood::constraints::TwoToOneCRHGadget; + +// #[derive(Clone, PartialEq, Eq, Hash)] +// pub(super) struct Window; + +// impl pedersen::Window for Window { +// const WINDOW_SIZE: usize = 63; +// const NUM_WINDOWS: usize = 8; +// } + +// fn generate_u8_input( +// cs: ConstraintSystemRef, +// size: usize, +// rng: &mut R, +// ) -> (Vec, Vec>) { +// let mut input = vec![1u8; size]; +// rng.fill_bytes(&mut input); + +// let mut input_bytes = vec![]; +// for byte in input.iter() { +// input_bytes.push(UInt8::new_witness(cs.clone(), || Ok(byte)).unwrap()); +// } +// (input, input_bytes) +// } + +// #[test] +// fn test_native_equality() { +// let rng = &mut test_rng(); +// let cs = ConstraintSystem::::new_ref(); + +// let (input, input_var) = generate_u8_input(cs.clone(), 189, rng); +// println!("number of constraints for input: {}", cs.num_constraints()); + +// let parameters = TestCRH::setup(rng).unwrap(); +// let primitive_result = TestCRH::evaluate(¶meters, input.as_slice()).unwrap(); + +// let parameters_var = +// >::ParametersVar::new_witness( +// ark_relations::ns!(cs, "parameters_var"), +// || Ok(¶meters), +// ) +// .unwrap(); +// println!( +// "number of constraints for input + params: {}", +// cs.num_constraints() +// ); + +// let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); + +// println!("number of constraints total: {}", cs.num_constraints()); + +// assert_eq!(primitive_result, result_var.value().unwrap()); +// assert!(cs.is_satisfied().unwrap()); +// } + +// #[test] +// fn test_native_two_to_one_equality() { +// let rng = &mut test_rng(); +// let cs = ConstraintSystem::::new_ref(); + +// // Max input size is 63 bytes. That leaves 31 for the left half, 31 for the right, and 1 +// // byte of padding. +// let (left_input, left_input_var) = generate_u8_input(cs.clone(), 31, rng); +// let (right_input, right_input_var) = generate_u8_input(cs.clone(), 31, rng); +// let parameters = TestTwoToOneCRH::setup(rng).unwrap(); +// let primitive_result = +// TestTwoToOneCRH::evaluate(¶meters, left_input.as_slice(), right_input.as_slice()) +// .unwrap(); + +// let parameters_var = >::ParametersVar::new_witness( +// ark_relations::ns!(cs, "parameters_var"), +// || Ok(¶meters), +// ) +// .unwrap(); + +// let result_var = +// TestTwoToOneCRHGadget::evaluate(¶meters_var, &left_input_var, &right_input_var) +// .unwrap(); + +// assert_eq!(primitive_result, result_var.value().unwrap()); +// assert!(cs.is_satisfied().unwrap()); +// } + +// #[should_panic] +// #[test] +// fn test_input_size_check() { +// // Pick parameters that are far too small for a CRH +// #[derive(Clone, PartialEq, Eq, Hash)] +// pub(super) struct TooSmallWindow; +// impl pedersen::Window for TooSmallWindow { +// const WINDOW_SIZE: usize = 1; +// const NUM_WINDOWS: usize = 1; +// } +// type TestCRH = bowe_hopwood::CRH; +// type TestCRHGadget = bowe_hopwood::constraints::CRHGadget; + +// let rng = &mut test_rng(); +// let cs = ConstraintSystem::::new_ref(); + +// let (_, input_var) = generate_u8_input(cs.clone(), 189, rng); +// println!("number of constraints for input: {}", cs.num_constraints()); + +// let parameters = TestCRH::setup(rng).unwrap(); +// let parameters_var = +// >::ParametersVar::new_witness( +// ark_relations::ns!(cs, "parameters_var"), +// || Ok(¶meters), +// ) +// .unwrap(); +// let _ = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); +// } +// } diff --git a/crypto-primitives/src/crh/bowe_hopwood/mod.rs b/crypto-primitives/src/crh/bowe_hopwood/mod.rs index 89a4ca27..715e5b52 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/mod.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/mod.rs @@ -25,7 +25,7 @@ use ark_std::{ #[cfg(feature = "parallel")] use rayon::prelude::*; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub const CHUNK_SIZE: usize = 3; diff --git a/crypto-primitives/src/crh/constraints.rs b/crypto-primitives/src/crh/constraints.rs index 28ea34b4..a4c40ee2 100644 --- a/crypto-primitives/src/crh/constraints.rs +++ b/crypto-primitives/src/crh/constraints.rs @@ -1,7 +1,7 @@ use crate::crh::{CRHScheme, TwoToOneCRHScheme}; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; use ark_std::fmt::Debug; pub trait CRHSchemeGadget: Sized { @@ -10,7 +10,7 @@ pub trait CRHSchemeGadget: Sized { + ToBytesGadget + CondSelectGadget + AllocVar - + R1CSVar + + GR1CSVar + Debug + Clone + Sized; @@ -28,7 +28,7 @@ pub trait TwoToOneCRHSchemeGadget: Siz + ToBytesGadget + CondSelectGadget + AllocVar - + R1CSVar + + GR1CSVar + Debug + Clone + Sized; diff --git a/crypto-primitives/src/crh/injective_map/constraints.rs b/crypto-primitives/src/crh/injective_map/constraints.rs index 5d034c99..6f211b09 100644 --- a/crypto-primitives/src/crh/injective_map/constraints.rs +++ b/crypto-primitives/src/crh/injective_map/constraints.rs @@ -14,7 +14,7 @@ use ark_ff::fields::{Field, PrimeField}; use ark_r1cs_std::{ fields::fp::FpVar, groups::curves::twisted_edwards::AffineVar as TEVar, prelude::*, }; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; use ark_std::{fmt::Debug, marker::PhantomData}; type ConstraintF = <::BaseField as Field>::BasePrimeField; @@ -27,7 +27,7 @@ where + ToBytesGadget> + CondSelectGadget> + AllocVar> - + R1CSVar, Value = I::Output> + + GR1CSVar, Value = I::Output> + Debug + Clone + Sized; @@ -82,7 +82,7 @@ where type OutputVar = IG::OutputVar; type ParametersVar = ped_constraints::CRHParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters, input))] + #[tracing::instrument(target = "gr1cs", skip(parameters, input))] fn evaluate( parameters: &Self::ParametersVar, input: &Self::InputVar, @@ -127,7 +127,7 @@ where type OutputVar = IG::OutputVar; type ParametersVar = ped_constraints::CRHParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters))] + #[tracing::instrument(target = "gr1cs", skip(parameters))] fn evaluate( parameters: &Self::ParametersVar, left_input: &Self::InputVar, diff --git a/crypto-primitives/src/crh/injective_map/mod.rs b/crypto-primitives/src/crh/injective_map/mod.rs index f84ea1f8..072fbeb0 100644 --- a/crypto-primitives/src/crh/injective_map/mod.rs +++ b/crypto-primitives/src/crh/injective_map/mod.rs @@ -10,7 +10,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, fmt::Debug, hash::Hash, marker::PhantomData, rand::Rng}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub trait InjectiveMap { diff --git a/crypto-primitives/src/crh/mod.rs b/crypto-primitives/src/crh/mod.rs index e0e214b7..1e835472 100644 --- a/crypto-primitives/src/crh/mod.rs +++ b/crypto-primitives/src/crh/mod.rs @@ -4,13 +4,14 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{borrow::Borrow, fmt::Debug, hash::Hash, rand::Rng}; pub mod bowe_hopwood; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub mod injective_map; pub mod pedersen; pub mod poseidon; +pub mod rescue; pub mod sha256; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub use constraints::*; /// Interface to CRH. Note that in this release, while all implementations of `CRH` have fixed length, diff --git a/crypto-primitives/src/crh/pedersen/constraints.rs b/crypto-primitives/src/crh/pedersen/constraints.rs index ce7aa49f..72ebd502 100644 --- a/crypto-primitives/src/crh/pedersen/constraints.rs +++ b/crypto-primitives/src/crh/pedersen/constraints.rs @@ -5,7 +5,7 @@ use crate::crh::{ use ark_ec::CurveGroup; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, iter, marker::PhantomData}; @@ -45,7 +45,7 @@ where type OutputVar = GG; type ParametersVar = CRHParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters, input))] + #[tracing::instrument(target = "gr1cs", skip(parameters, input))] fn evaluate( parameters: &Self::ParametersVar, input: &Self::InputVar, @@ -100,7 +100,7 @@ where type OutputVar = GG; type ParametersVar = CRHParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters))] + #[tracing::instrument(target = "gr1cs", skip(parameters))] fn evaluate( parameters: &Self::ParametersVar, left_input: &Self::InputVar, @@ -116,7 +116,7 @@ where CRHGadget::::evaluate(parameters, &chained_input) } - #[tracing::instrument(target = "r1cs", skip(parameters))] + #[tracing::instrument(target = "gr1cs", skip(parameters))] fn compress( parameters: &Self::ParametersVar, left_input: &Self::OutputVar, @@ -135,7 +135,7 @@ where GG: CurveVar>, for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, { - #[tracing::instrument(target = "r1cs", skip(_cs, f))] + #[tracing::instrument(target = "gr1cs", skip(_cs, f))] fn new_variable>>( _cs: impl Into>>, f: impl FnOnce() -> Result, @@ -149,103 +149,101 @@ where } } -#[cfg(test)] -mod test { - use crate::crh::{ - pedersen, CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, - }; - use ark_ec::CurveGroup; - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq as Fr}; - use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef}; - use ark_std::rand::Rng; - use ark_std::{test_rng, UniformRand}; - - type TestCRH = pedersen::CRH; - type TestCRHGadget = pedersen::constraints::CRHGadget; - - type TestTwoToOneCRH = pedersen::TwoToOneCRH; - type TestTwoToOneCRHGadget = - pedersen::constraints::TwoToOneCRHGadget; - - #[derive(Clone, PartialEq, Eq, Hash)] - pub(super) struct Window; - - impl pedersen::Window for Window { - const WINDOW_SIZE: usize = 127; - const NUM_WINDOWS: usize = 9; - } - - fn generate_u8_input( - cs: ConstraintSystemRef, - size: usize, - rng: &mut R, - ) -> (Vec, Vec>) { - let mut input = vec![1u8; size]; - rng.fill_bytes(&mut input); - - let mut input_bytes = vec![]; - for byte in input.iter() { - input_bytes.push(UInt8::new_witness(cs.clone(), || Ok(byte)).unwrap()); - } - (input, input_bytes) - } - - fn generate_affine( - cs: ConstraintSystemRef, - rng: &mut R, - ) -> (::Affine, EdwardsVar) { - let val = ::Affine::rand(rng); - let val_var = EdwardsVar::new_witness(cs.clone(), || Ok(val.clone())).unwrap(); - (val, val_var) - } - - #[test] - fn test_native_equality() { - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - let (input, input_var) = generate_u8_input(cs.clone(), 128, rng); - - let parameters = TestCRH::setup(rng).unwrap(); - let primitive_result = TestCRH::evaluate(¶meters, input.as_slice()).unwrap(); - - let parameters_var = pedersen::constraints::CRHParametersVar::new_constant( - ark_relations::ns!(cs, "CRH Parameters"), - ¶meters, - ) - .unwrap(); - - let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); - - let primitive_result = primitive_result; - assert_eq!(primitive_result, result_var.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } - - #[test] - fn test_naive_two_to_one_equality() { - let rng = &mut test_rng(); - let cs = ConstraintSystem::::new_ref(); - - let (left_input, left_input_var) = generate_affine(cs.clone(), rng); - let (right_input, right_input_var) = generate_affine(cs.clone(), rng); - let parameters = TestTwoToOneCRH::setup(rng).unwrap(); - let primitive_result = - TestTwoToOneCRH::compress(¶meters, left_input, right_input).unwrap(); - - let parameters_var = pedersen::constraints::CRHParametersVar::new_constant( - ark_relations::ns!(cs, "CRH Parameters"), - ¶meters, - ) - .unwrap(); - - let result_var = - TestTwoToOneCRHGadget::compress(¶meters_var, &left_input_var, &right_input_var) - .unwrap(); - - let primitive_result = primitive_result; - assert_eq!(primitive_result, result_var.value().unwrap().into_affine()); - assert!(cs.is_satisfied().unwrap()); - } -} +// #[cfg(test)] +// mod test { +// use crate::crh::{ +// pedersen, CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, +// }; +// use ark_ec::CurveGroup; +// use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq as Fr}; +// use ark_r1cs_std::prelude::*; +// use ark_relations::gr1cs::{ConstraintSystem, ConstraintSystemRef}; +// use ark_std::rand::Rng; +// use ark_std::{test_rng, UniformRand}; + +// type TestCRH = pedersen::CRH; +// type TestCRHGadget = pedersen::constraints::CRHGadget; + +// type TestTwoToOneCRH = pedersen::TwoToOneCRH; +// type TestTwoToOneCRHGadget = +// pedersen::constraints::TwoToOneCRHGadget; + +// #[derive(Clone, PartialEq, Eq, Hash)] +// pub(super) struct Window; + +// impl pedersen::Window for Window { +// const WINDOW_SIZE: usize = 127; +// const NUM_WINDOWS: usize = 9; +// } + +// fn generate_u8_input( +// cs: ConstraintSystemRef, +// size: usize, +// rng: &mut R, +// ) -> (Vec, Vec>) { +// let mut input = vec![1u8; size]; +// rng.fill_bytes(&mut input); + +// let mut input_bytes = vec![]; +// for byte in input.iter() { +// input_bytes.push(UInt8::new_witness(cs.clone(), || Ok(byte)).unwrap()); +// } +// (input, input_bytes) +// } + +// fn generate_affine( +// cs: ConstraintSystemRef, +// rng: &mut R, +// ) -> (::Affine, EdwardsVar) { +// let val = ::Affine::rand(rng); +// let val_var = EdwardsVar::new_witness(cs.clone(), || Ok(val.clone())).unwrap(); +// (val, val_var) +// } + +// #[test] +// fn test_native_equality() { +// let rng = &mut test_rng(); +// let cs = ConstraintSystem::::new_ref(); + +// let (input, input_var) = generate_u8_input(cs.clone(), 128, rng); + +// let parameters = TestCRH::setup(rng).unwrap(); +// let primitive_result = TestCRH::evaluate(¶meters, input.as_slice()).unwrap(); + +// let parameters_var = pedersen::constraints::CRHParametersVar::new_constant( +// ark_relations::ns!(cs, "CRH Parameters"), +// ¶meters, +// ) +// .unwrap(); + +// let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); + +// assert_eq!(primitive_result, result_var.value().unwrap()); +// assert!(cs.is_satisfied().unwrap()); +// } + +// #[test] +// fn test_naive_two_to_one_equality() { +// let rng = &mut test_rng(); +// let cs = ConstraintSystem::::new_ref(); + +// let (left_input, left_input_var) = generate_affine(cs.clone(), rng); +// let (right_input, right_input_var) = generate_affine(cs.clone(), rng); +// let parameters = TestTwoToOneCRH::setup(rng).unwrap(); +// let primitive_result = +// TestTwoToOneCRH::compress(¶meters, left_input, right_input).unwrap(); + +// let parameters_var = pedersen::constraints::CRHParametersVar::new_constant( +// ark_relations::ns!(cs, "CRH Parameters"), +// ¶meters, +// ) +// .unwrap(); + +// let result_var = +// TestTwoToOneCRHGadget::compress(¶meters_var, &left_input_var, &right_input_var) +// .unwrap(); + +// assert_eq!(primitive_result, result_var.value().unwrap().into_affine()); +// assert!(cs.is_satisfied().unwrap()); +// } +// } diff --git a/crypto-primitives/src/crh/pedersen/mod.rs b/crypto-primitives/src/crh/pedersen/mod.rs index 6fb1650f..4147cdc6 100644 --- a/crypto-primitives/src/crh/pedersen/mod.rs +++ b/crypto-primitives/src/crh/pedersen/mod.rs @@ -17,7 +17,7 @@ use ark_std::{ #[cfg(feature = "parallel")] use rayon::prelude::*; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub trait Window: Clone { diff --git a/crypto-primitives/src/crh/poseidon/constraints.rs b/crypto-primitives/src/crh/poseidon/constraints.rs index ef7219ed..0215b531 100644 --- a/crypto-primitives/src/crh/poseidon/constraints.rs +++ b/crypto-primitives/src/crh/poseidon/constraints.rs @@ -14,9 +14,9 @@ use ark_ff::PrimeField; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, fields::fp::FpVar, - R1CSVar, + GR1CSVar, }; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, marker::PhantomData}; @@ -125,9 +125,9 @@ mod test { use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::{ fields::fp::{AllocatedFp, FpVar}, - R1CSVar, + GR1CSVar, }; - use ark_relations::r1cs::ConstraintSystem; + use ark_relations::gr1cs::ConstraintSystem; use ark_std::UniformRand; #[test] diff --git a/crypto-primitives/src/crh/poseidon/mod.rs b/crypto-primitives/src/crh/poseidon/mod.rs index 4b24e8cd..d32fa36a 100644 --- a/crypto-primitives/src/crh/poseidon/mod.rs +++ b/crypto-primitives/src/crh/poseidon/mod.rs @@ -9,9 +9,9 @@ use crate::{ use ark_ff::PrimeField; use ark_std::{borrow::Borrow, marker::PhantomData, rand::Rng}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; - +//TODO: CHange this r1cs to gr1cs in the future in a seperate PR pub struct CRH { field_phantom: PhantomData, } diff --git a/crypto-primitives/src/crh/rescue/gr1cs_constraints.rs b/crypto-primitives/src/crh/rescue/gr1cs_constraints.rs new file mode 100644 index 00000000..1cb08ebe --- /dev/null +++ b/crypto-primitives/src/crh/rescue/gr1cs_constraints.rs @@ -0,0 +1,202 @@ +use crate::crh::rescue::{TwoToOneCRH, CRH}; +use crate::crh::CRHScheme; +use crate::crh::{ + constraints::CRHSchemeGadget as CRHGadgetTrait, + constraints::TwoToOneCRHSchemeGadget as TwoToOneCRHGadgetTrait, +}; +use crate::sponge::constraints::CryptographicSpongeVar; +use crate::sponge::rescue::gr1cs_constraints::RescueSpongeVar; +use crate::sponge::rescue::RescueConfig; + +use crate::sponge::Absorb; +use ark_ff::PrimeField; +use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; +use ark_r1cs_std::fields::fp::FpVar; +use ark_r1cs_std::GR1CSVar; +use ark_relations::gr1cs::{Namespace, SynthesisError}; +use ark_std::borrow::Borrow; +use ark_std::marker::PhantomData; + +#[cfg(not(feature = "std"))] +use ark_std::vec::Vec; + +#[derive(Clone)] +pub struct CRHParametersVar { + pub parameters: RescueConfig, +} + +pub struct CRHGadget { + field_phantom: PhantomData, +} + +impl CRHGadgetTrait, F> for CRHGadget { + type InputVar = [FpVar]; + type OutputVar = FpVar; + type ParametersVar = CRHParametersVar; + + fn evaluate( + parameters: &Self::ParametersVar, + input: &Self::InputVar, + ) -> Result { + let cs = input.cs(); + + if cs.is_none() { + let mut constant_input = Vec::new(); + for var in input.iter() { + constant_input.push(var.value()?); + } + Ok(FpVar::Constant( + CRH::::evaluate(¶meters.parameters, constant_input).unwrap(), + )) + } else { + let mut sponge = RescueSpongeVar::new(cs, ¶meters.parameters); + sponge.absorb(&input)?; + let res = sponge.squeeze_field_elements(1)?; + + Ok(res[0].clone()) + } + } +} + +pub struct TwoToOneCRHGadget { + field_phantom: PhantomData, +} + +impl TwoToOneCRHGadgetTrait, F> for TwoToOneCRHGadget { + type InputVar = FpVar; + type OutputVar = FpVar; + type ParametersVar = CRHParametersVar; + + fn evaluate( + parameters: &Self::ParametersVar, + left_input: &Self::InputVar, + right_input: &Self::InputVar, + ) -> Result { + Self::compress(parameters, left_input, right_input) + } + + fn compress( + parameters: &Self::ParametersVar, + left_input: &Self::OutputVar, + right_input: &Self::OutputVar, + ) -> Result { + let cs = left_input.cs().or(right_input.cs()); + + if cs.is_none() { + Ok(FpVar::Constant( + CRH::::evaluate( + ¶meters.parameters, + vec![left_input.value()?, right_input.value()?], + ) + .unwrap(), + )) + } else { + let mut sponge = RescueSpongeVar::new(cs, ¶meters.parameters); + sponge.absorb(left_input)?; + sponge.absorb(right_input)?; + let res = sponge.squeeze_field_elements(1)?; + Ok(res[0].clone()) + } + } +} + +impl AllocVar, F> for CRHParametersVar { + fn new_variable>>( + _cs: impl Into>, + f: impl FnOnce() -> Result, + _mode: AllocationMode, + ) -> Result { + f().and_then(|param| { + let parameters = param.borrow().clone(); + + Ok(Self { parameters }) + }) + } +} + +#[cfg(test)] +mod test { + use core::str::FromStr; + + use crate::crh::rescue::gr1cs_constraints::{CRHGadget, CRHParametersVar, TwoToOneCRHGadget}; + use crate::crh::rescue::{TwoToOneCRH, CRH}; + use crate::crh::{constraints::CRHSchemeGadget, CRHScheme}; + use crate::crh::{constraints::TwoToOneCRHSchemeGadget, TwoToOneCRHScheme}; + use crate::sponge::rescue::RescueConfig; + use ark_bls12_381::Fr; + use ark_ff::UniformRand; + use ark_r1cs_std::alloc::AllocVar; + use ark_r1cs_std::fields::fp::{AllocatedFp, FpVar}; + use ark_r1cs_std::GR1CSVar; + use ark_relations::gr1cs::predicate::PredicateConstraintSystem; + use ark_relations::gr1cs::ConstraintSystem; + use num_bigint::BigUint; + + #[test] + fn test_consistency() { + let mut test_rng = ark_std::test_rng(); + + // The following way of generating the MDS matrix is incorrect + // and is only for test purposes. + + let mut mds = vec![vec![]; 4]; + for i in 0..4 { + for _ in 0..4 { + mds[i].push(Fr::rand(&mut test_rng)); + } + } + + let mut ark = vec![vec![]; 25]; + for i in 0..25 { + for _ in 0..4 { + ark[i].push(Fr::rand(&mut test_rng)); + } + } + + let mut test_a = Vec::new(); + let mut test_b = Vec::new(); + for _ in 0..9 { + test_a.push(Fr::rand(&mut test_rng)); + test_b.push(Fr::rand(&mut test_rng)); + } + let alpha_inv: BigUint = BigUint::from_str( + "20974350070050476191779096203274386335076221000211055129041463479975432473805", + ) + .unwrap(); + let params = RescueConfig::::new(12, 5, alpha_inv, mds, ark, 3, 1); + let crh_a = CRH::::evaluate(¶ms, test_a.clone()).unwrap(); + let crh_b = CRH::::evaluate(¶ms, test_b.clone()).unwrap(); + let crh = TwoToOneCRH::::compress(¶ms, crh_a, crh_b).unwrap(); + + let cs = ConstraintSystem::::new_ref(); + let pow_pred = PredicateConstraintSystem::new_polynomial_predicate( + 2, + vec![ + (Fr::from(1u8), vec![(5, 0)]), + (Fr::from(-1i8), vec![(0, 1)]), + ], + ); + cs.register_predicate("POW", pow_pred).unwrap(); + let mut test_a_g = Vec::new(); + let mut test_b_g = Vec::new(); + + for elem in test_a.iter() { + test_a_g.push(FpVar::Var( + AllocatedFp::::new_witness(cs.clone(), || Ok(elem)).unwrap(), + )); + } + for elem in test_b.iter() { + test_b_g.push(FpVar::Var( + AllocatedFp::::new_witness(cs.clone(), || Ok(elem)).unwrap(), + )); + } + + let params_g = CRHParametersVar::::new_witness(cs.clone(), || Ok(params)).unwrap(); + let crh_a_g = CRHGadget::::evaluate(¶ms_g, &test_a_g).unwrap(); + let crh_b_g = CRHGadget::::evaluate(¶ms_g, &test_b_g).unwrap(); + let crh_g = TwoToOneCRHGadget::::compress(¶ms_g, &crh_a_g, &crh_b_g).unwrap(); + assert_eq!(crh_a, crh_a_g.value().unwrap()); + assert_eq!(crh_b, crh_b_g.value().unwrap()); + assert_eq!(crh, crh_g.value().unwrap()); + } +} diff --git a/crypto-primitives/src/crh/rescue/mod.rs b/crypto-primitives/src/crh/rescue/mod.rs new file mode 100644 index 00000000..b3d25daa --- /dev/null +++ b/crypto-primitives/src/crh/rescue/mod.rs @@ -0,0 +1,102 @@ +use crate::{ + crh::{CRHScheme, TwoToOneCRHScheme}, + sponge::{ + rescue::{RescueConfig, RescueSponge}, + Absorb, CryptographicSponge, + }, + Error, +}; +use ark_ff::PrimeField; +use ark_std::{borrow::Borrow, marker::PhantomData, rand::Rng}; + + +#[cfg(feature = "gr1cs")] +pub mod gr1cs_constraints; + + + + +/// The Rescue collision-resistant hash function introduced in [SAD20][sad] +/// +/// [sad]: https://eprint.iacr.org/2020/1143.pdf +pub struct CRH { + field_phantom: PhantomData, +} + +impl CRHScheme for CRH { + /// The input to Rescue is a list of field elements. + type Input = [F]; + /// The output of Rescue is a single field element. One can change this to a list of field elements to squeeze more outputs. + type Output = F; + /// The parameters for the Rescue sponge, e.g. the number of rounds, mdsm, s-box specifications, etc. + type Parameters = RescueConfig; + + /// Compute the parameters for the Rescue sponge. + fn setup(_rng: &mut R) -> Result { + // automatic generation of parameters are not implemented yet + // therefore, the developers must specify the parameters themselves + unimplemented!() + } + + /// Evaluate the Rescue sponge on the input. + fn evaluate>( + parameters: &Self::Parameters, + input: T, + ) -> Result { + let input = input.borrow(); + + let mut sponge = RescueSponge::new(parameters); + sponge.absorb(&input); + let res = sponge.squeeze_field_elements::(1); + Ok(res[0]) + } +} + + +/// The 2-to-1 version of the Rescue collision-resistant hash function introduced in [SAD20][sad] used in Merkle trees. +/// +/// [sad]: https://eprint.iacr.org/2020/1143.pdf +pub struct TwoToOneCRH { + field_phantom: PhantomData, +} + +impl TwoToOneCRHScheme for TwoToOneCRH { + /// Each of the inputs to the list are field elements. + type Input = F; + /// The output of Rescue is a single field element. One can change this to a list of field elements to squeeze more outputs. + type Output = F; + /// The parameters for the Rescue sponge, e.g. the number of rounds, mdsm, s-box specifications, etc. + type Parameters = RescueConfig; + + /// Compute the parameters for the Rescue sponge. + fn setup(_rng: &mut R) -> Result { + // automatic generation of parameters are not implemented yet + // therefore, the developers must specify the parameters themselves + unimplemented!() + } + + /// Evaluate the Rescue sponge on the inputs left and right. + fn evaluate>( + parameters: &Self::Parameters, + left_input: T, + right_input: T, + ) -> Result { + Self::compress(parameters, left_input, right_input) + } + + /// Compress the inputs left and right using the Rescue sponge. + fn compress>( + parameters: &Self::Parameters, + left_input: T, + right_input: T, + ) -> Result { + let left_input = left_input.borrow(); + let right_input = right_input.borrow(); + + let mut sponge = RescueSponge::new(parameters); + sponge.absorb(left_input); + sponge.absorb(right_input); + let res = sponge.squeeze_field_elements::(1); + Ok(res[0]) + } +} diff --git a/crypto-primitives/src/crh/rescue/r1cs_constraints.rs b/crypto-primitives/src/crh/rescue/r1cs_constraints.rs new file mode 100644 index 00000000..e8bf69e1 --- /dev/null +++ b/crypto-primitives/src/crh/rescue/r1cs_constraints.rs @@ -0,0 +1,156 @@ +use ark_ff::PrimeField; + + + +const RESCUE_ROUNDS: usize = 12; + +/// This is our demo circuit for proving knowledge of the +/// preimage of a Rescue hash invocation. +#[derive(Clone)] +struct RescueDemo { + input: Option>, + image: Option, + config: RescueConfig, + N: usize, +} + +pub fn create_test_rescue_parameter( + rng: &mut impl Rng, +) -> RescueConfig { + let mut mds = vec![vec![]; 4]; + for i in 0..4 { + for _ in 0..4 { + mds[i].push(F::rand(rng)); + } + } + + let mut ark = vec![vec![]; 25]; + for i in 0..(2 * RESCUE_ROUNDS + 1) { + for _ in 0..4 { + ark[i].push(F::rand(rng)); + } + } + let alpha_inv: BigUint = BigUint::from_str( + "20974350070050476191779096203274386335076221000211055129041463479975432473805", + ) + .unwrap(); + let params = RescueConfig::::new(RESCUE_ROUNDS, 5, alpha_inv, mds, ark, 3, 1); + params +} + +impl ConstraintSynthesizer + for RescueDemo +{ + fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { + cs.clone().register_predicate( + gr1cs::MUL, + LocalPredicate::new( + 3, + gr1cs::predicate::LocalPredicateType::Polynomial( + gr1cs::polynomial::Polynomial::new( + 3, + vec![(F::ONE, vec![1, 1, 0]), (F::ZERO - F::ONE, vec![0, 0, 1])], + ) + .unwrap(), + ), + ), + ); + + + let params_g = + CRHParametersVar::::new_witness(cs.clone(), || Ok(self.config.clone())).unwrap(); + + for _ in 0..self.N { + let mut input_g = Vec::new(); + + for elem in self + .input + .clone() + .ok_or(SynthesisError::AssignmentMissing) + .unwrap() + { + input_g.push(FpVar::new_witness(cs.clone(), || Ok(elem)).unwrap()); + } + + let crh_a_g: FpVar = CRHGadget::::evaluate(¶ms_g, &input_g).unwrap(); + let image_instance: FpVar = FpVar::new_input(cs.clone(), || { + Ok(self.image.ok_or(SynthesisError::AssignmentMissing).unwrap()) + }) + .unwrap(); + crh_a_g.enforce_equal(&image_instance); + } + Ok(()) + } +} + + +#[test] +fn test_rescue() { + + const N: usize = 100; + // We're going to use the Groth16 proving system. + + + // This may not be cryptographically safe, use + // `OsRng` (for example) in production software. + let mut rng = ark_std::rand::rngs::StdRng::seed_from_u64(test_rng().next_u64()); + let config = create_test_rescue_parameter(&mut rng); + + // Generate a random preimage and compute the image + let mut input = Vec::new(); + for _ in 0..9 { + input.push(Fr::rand(&mut rng)); + } + let expected_image = CRH::::evaluate(&config, input.clone()).unwrap(); + + let c = RescueDemo:: { + input: Some(input.clone()), + image: Some(expected_image), + config: config.clone(), + N + }; + + /////////////////////////////////////////////////////////////////////////////////// + // Create parameters for our circuit + println!("Creating SRS..."); + let mut setup_time: Duration = Duration::new(0, 0); + + let start = Instant::now(); + + let (pk, vk) = { Varuna::::setup(&mut rng, c.clone()) }; + + setup_time += start.elapsed(); + std::println!("Setup time = {}", setup_time.as_millis()); + /////////////////////////////////////////////// + // Creating the proof + + println!("Creating proofs..."); + + let mut total_proving: Duration = Duration::new(0, 0); + + let start = Instant::now(); + + // Create a groth16 proof with our parameters. + let proof = Varuna::::prove(&mut rng, c, pk); + total_proving += start.elapsed(); + + std::println!("Totall Prover time = {}", total_proving.as_millis()); + + /////////////////////////////////////////////// + // Verifying the proof + let mut total_verifying: Duration = Duration::new(0, 0); + let start = Instant::now(); + assert!(Varuna::::verify( + &mut rng, + proof, + vk, + &[expected_image;N] + )); + + // proof.write(&mut proof_vec).unwrap(); + + // let proof = Proof::read(&proof_vec[..]).unwrap(); + // Check the proof + + total_verifying += start.elapsed(); +} diff --git a/crypto-primitives/src/crh/sha256/constraints.rs b/crypto-primitives/src/crh/sha256/constraints.rs index 6bee0060..cdf7fc59 100644 --- a/crypto-primitives/src/crh/sha256/constraints.rs +++ b/crypto-primitives/src/crh/sha256/constraints.rs @@ -13,9 +13,9 @@ use ark_r1cs_std::{ select::CondSelectGadget, uint32::UInt32, uint8::UInt8, - R1CSVar, + GR1CSVar, }; -use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; +use ark_relations::gr1cs::{ConstraintSystemRef, Namespace, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, iter, marker::PhantomData}; @@ -303,7 +303,7 @@ impl AllocVar, ConstraintF> for DigestVar R1CSVar for DigestVar { +impl GR1CSVar for DigestVar { type Value = [u8; 32]; fn cs(&self) -> ConstraintSystemRef { @@ -332,7 +332,7 @@ where type OutputVar = DigestVar; type ParametersVar = UnitVar; - #[tracing::instrument(target = "r1cs", skip(_parameters))] + #[tracing::instrument(target = "gr1cs", skip(_parameters))] fn evaluate( _parameters: &Self::ParametersVar, input: &Self::InputVar, @@ -349,7 +349,7 @@ where type OutputVar = DigestVar; type ParametersVar = UnitVar; - #[tracing::instrument(target = "r1cs", skip(_parameters))] + #[tracing::instrument(target = "gr1cs", skip(_parameters))] fn evaluate( _parameters: &Self::ParametersVar, left_input: &Self::InputVar, @@ -361,7 +361,7 @@ where h.finalize() } - #[tracing::instrument(target = "r1cs", skip(parameters))] + #[tracing::instrument(target = "gr1cs", skip(parameters))] fn compress( parameters: &Self::ParametersVar, left_input: &Self::OutputVar, @@ -385,7 +385,7 @@ mod test { use crate::crh::{sha256::digest::Digest, CRHScheme, TwoToOneCRHScheme}; use ark_bls12_377::Fr; - use ark_relations::{ns, r1cs::ConstraintSystem}; + use ark_relations::{ns, gr1cs::ConstraintSystem}; use ark_std::rand::RngCore; const TEST_LENGTHS: &[usize] = &[ diff --git a/crypto-primitives/src/crh/sha256/mod.rs b/crypto-primitives/src/crh/sha256/mod.rs index d07b36ab..d63b45f9 100644 --- a/crypto-primitives/src/crh/sha256/mod.rs +++ b/crypto-primitives/src/crh/sha256/mod.rs @@ -10,7 +10,7 @@ use sha2::digest::Digest; // Re-export the RustCrypto Sha256 type and its associated traits pub use sha2::{digest, Sha256}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; // Implement the CRH traits for SHA-256 diff --git a/crypto-primitives/src/encryption/constraints.rs b/crypto-primitives/src/encryption/constraints.rs index 503f733a..d5f773c0 100644 --- a/crypto-primitives/src/encryption/constraints.rs +++ b/crypto-primitives/src/encryption/constraints.rs @@ -1,7 +1,7 @@ use crate::encryption::AsymmetricEncryptionScheme; use ark_ff::fields::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; use ark_std::fmt::Debug; pub trait AsymmetricEncryptionGadget { diff --git a/crypto-primitives/src/encryption/elgamal/constraints.rs b/crypto-primitives/src/encryption/elgamal/constraints.rs index aa7b2a7f..d526ac62 100644 --- a/crypto-primitives/src/encryption/elgamal/constraints.rs +++ b/crypto-primitives/src/encryption/elgamal/constraints.rs @@ -8,7 +8,7 @@ use ark_ff::{ Zero, }; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; use ark_serialize::CanonicalSerialize; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -236,74 +236,74 @@ where } } -#[cfg(test)] -mod test { - use crate::encryption::constraints::AsymmetricEncryptionGadget; - use ark_std::{test_rng, UniformRand}; +// #[cfg(test)] +// mod test { +// use crate::encryption::constraints::AsymmetricEncryptionGadget; +// use ark_std::{test_rng, UniformRand}; - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq}; +// use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq}; - use crate::encryption::elgamal::{constraints::ElGamalEncGadget, ElGamal, Randomness}; - use crate::encryption::AsymmetricEncryptionScheme; - use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::ConstraintSystem; +// use crate::encryption::elgamal::{constraints::ElGamalEncGadget, ElGamal, Randomness}; +// use crate::encryption::AsymmetricEncryptionScheme; +// use ark_r1cs_std::prelude::*; +// use ark_relations::gr1cs::ConstraintSystem; - #[test] - fn test_elgamal_gadget() { - let rng = &mut test_rng(); +// #[test] +// fn test_elgamal_gadget() { +// let rng = &mut test_rng(); - type MyEnc = ElGamal; - type MyGadget = ElGamalEncGadget; +// type MyEnc = ElGamal; +// type MyGadget = ElGamalEncGadget; - // compute primitive result - let parameters = MyEnc::setup(rng).unwrap(); - let (pk, _) = MyEnc::keygen(¶meters, rng).unwrap(); - let msg = JubJub::rand(rng).into(); - let randomness = Randomness::rand(rng); - let primitive_result = MyEnc::encrypt(¶meters, &pk, &msg, &randomness).unwrap(); +// // compute primitive result +// let parameters = MyEnc::setup(rng).unwrap(); +// let (pk, _) = MyEnc::keygen(¶meters, rng).unwrap(); +// let msg = JubJub::rand(rng).into(); +// let randomness = Randomness::rand(rng); +// let primitive_result = MyEnc::encrypt(¶meters, &pk, &msg, &randomness).unwrap(); - // construct constraint system - let cs = ConstraintSystem::::new_ref(); - let randomness_var = - >::RandomnessVar::new_witness( - ark_relations::ns!(cs, "gadget_randomness"), - || Ok(&randomness), - ) - .unwrap(); - let parameters_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "gadget_parameters"), - ¶meters, - ) - .unwrap(); - let msg_var = - >::PlaintextVar::new_witness( - ark_relations::ns!(cs, "gadget_message"), - || Ok(&msg), - ) - .unwrap(); - let pk_var = - >::PublicKeyVar::new_witness( - ark_relations::ns!(cs, "gadget_public_key"), - || Ok(&pk), - ) - .unwrap(); +// // construct constraint system +// let cs = ConstraintSystem::::new_ref(); +// let randomness_var = +// >::RandomnessVar::new_witness( +// ark_relations::ns!(cs, "gadget_randomness"), +// || Ok(&randomness), +// ) +// .unwrap(); +// let parameters_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "gadget_parameters"), +// ¶meters, +// ) +// .unwrap(); +// let msg_var = +// >::PlaintextVar::new_witness( +// ark_relations::ns!(cs, "gadget_message"), +// || Ok(&msg), +// ) +// .unwrap(); +// let pk_var = +// >::PublicKeyVar::new_witness( +// ark_relations::ns!(cs, "gadget_public_key"), +// || Ok(&pk), +// ) +// .unwrap(); - // use gadget - let result_var = - MyGadget::encrypt(¶meters_var, &msg_var, &randomness_var, &pk_var).unwrap(); +// // use gadget +// let result_var = +// MyGadget::encrypt(¶meters_var, &msg_var, &randomness_var, &pk_var).unwrap(); - // check that result equals expected ciphertext in the constraint system - let expected_var = - >::OutputVar::new_input( - ark_relations::ns!(cs, "gadget_expected"), - || Ok(&primitive_result), - ) - .unwrap(); - expected_var.enforce_equal(&result_var).unwrap(); +// // check that result equals expected ciphertext in the constraint system +// let expected_var = +// >::OutputVar::new_input( +// ark_relations::ns!(cs, "gadget_expected"), +// || Ok(&primitive_result), +// ) +// .unwrap(); +// expected_var.enforce_equal(&result_var).unwrap(); - assert_eq!(primitive_result.0, result_var.c1.value().unwrap()); - assert_eq!(primitive_result.1, result_var.c2.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - } -} +// assert_eq!(primitive_result.0, result_var.c1.value().unwrap()); +// assert_eq!(primitive_result.1, result_var.c2.value().unwrap()); +// assert!(cs.is_satisfied().unwrap()); +// } +// } diff --git a/crypto-primitives/src/encryption/elgamal/mod.rs b/crypto-primitives/src/encryption/elgamal/mod.rs index 107710c7..aa47d49f 100644 --- a/crypto-primitives/src/encryption/elgamal/mod.rs +++ b/crypto-primitives/src/encryption/elgamal/mod.rs @@ -3,7 +3,7 @@ use ark_ec::{AdditiveGroup, CurveGroup}; use ark_ff::{fields::PrimeField, UniformRand}; use ark_std::{marker::PhantomData, ops::Mul, rand::Rng}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub struct ElGamal { diff --git a/crypto-primitives/src/encryption/mod.rs b/crypto-primitives/src/encryption/mod.rs index 5c721eb0..08e8d9a3 100644 --- a/crypto-primitives/src/encryption/mod.rs +++ b/crypto-primitives/src/encryption/mod.rs @@ -1,10 +1,10 @@ use crate::Error; use ark_std::rand::Rng; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub mod elgamal; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub use constraints::*; pub trait AsymmetricEncryptionScheme { diff --git a/crypto-primitives/src/merkle_tree/constraints.rs b/crypto-primitives/src/merkle_tree/constraints.rs index 83ae4f5b..0658c701 100644 --- a/crypto-primitives/src/merkle_tree/constraints.rs +++ b/crypto-primitives/src/merkle_tree/constraints.rs @@ -4,7 +4,7 @@ use crate::{ }; use ark_ff::PrimeField; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, fmt::Debug}; @@ -43,7 +43,7 @@ pub trait ConfigGadget { + EqGadget + ToBytesGadget + CondSelectGadget - + R1CSVar + + GR1CSVar + Debug + Clone + Sized; @@ -55,7 +55,7 @@ pub trait ConfigGadget { + EqGadget + ToBytesGadget + CondSelectGadget - + R1CSVar + + GR1CSVar + Debug + Clone + Sized; @@ -98,7 +98,7 @@ where P: Config, F: PrimeField, { - #[tracing::instrument(target = "r1cs", skip(cs, f))] + #[tracing::instrument(target = "gr1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, f: impl FnOnce() -> Result, @@ -143,7 +143,7 @@ impl> PathVar { /// Set the leaf index of the path to a given value. Verifier can use function before calling `verify` /// to check the correctness leaf position. /// * `leaf_index`: leaf index encoded in little-endian format - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] pub fn set_leaf_position(&mut self, leaf_index: Vec>) { // The path to a leaf is described by the branching // decisions taken at each node. This corresponds to the position @@ -178,7 +178,7 @@ impl> PathVar { } /// Calculate the root of the Merkle tree assuming that `leaf` is the leaf on the path defined by `self`. - #[tracing::instrument(target = "r1cs", skip(self, leaf_params, two_to_one_params))] + #[tracing::instrument(target = "gr1cs", skip(self, leaf_params, two_to_one_params))] pub fn calculate_root( &self, leaf_params: &LeafParam, @@ -224,7 +224,7 @@ impl> PathVar { /// Check that hashing a Merkle tree path according to `self`, and /// with `leaf` as the leaf, leads to a Merkle tree root equalling `root`. - #[tracing::instrument(target = "r1cs", skip(self, leaf_params, two_to_one_params))] + #[tracing::instrument(target = "gr1cs", skip(self, leaf_params, two_to_one_params))] pub fn verify_membership( &self, leaf_params: &LeafParam, @@ -238,7 +238,7 @@ impl> PathVar { /// Check that `old_leaf` is the leaf of the Merkle tree on the path defined by /// `self`, and then compute the new root when replacing `old_leaf` by `new_leaf`. - #[tracing::instrument(target = "r1cs", skip(self, leaf_params, two_to_one_params))] + #[tracing::instrument(target = "gr1cs", skip(self, leaf_params, two_to_one_params))] pub fn update_leaf( &self, leaf_params: &LeafParam, @@ -255,7 +255,7 @@ impl> PathVar { /// Check that `old_leaf` is the leaf of the Merkle tree on the path defined by /// `self`, and then compute the expected new root when replacing `old_leaf` by `new_leaf`. /// Return a boolean indicating whether expected new root equals `new_root`. - #[tracing::instrument(target = "r1cs", skip(self, leaf_params, two_to_one_params))] + #[tracing::instrument(target = "gr1cs", skip(self, leaf_params, two_to_one_params))] pub fn update_and_check( &self, leaf_params: &LeafParam, diff --git a/crypto-primitives/src/merkle_tree/mod.rs b/crypto-primitives/src/merkle_tree/mod.rs index 0e48e94b..c23c14d2 100644 --- a/crypto-primitives/src/merkle_tree/mod.rs +++ b/crypto-primitives/src/merkle_tree/mod.rs @@ -19,7 +19,7 @@ use hashbrown::HashMap; #[cfg(feature = "parallel")] use rayon::prelude::*; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; #[cfg(test)] diff --git a/crypto-primitives/src/merkle_tree/tests/constraints.rs b/crypto-primitives/src/merkle_tree/tests/constraints.rs index ab55dc83..6651d2ef 100644 --- a/crypto-primitives/src/merkle_tree/tests/constraints.rs +++ b/crypto-primitives/src/merkle_tree/tests/constraints.rs @@ -1,476 +1,476 @@ -mod byte_mt_tests { - use crate::crh::{ - pedersen, CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, - }; - use crate::merkle_tree::{ - constraints::{BytesVarDigestConverter, ConfigGadget, PathVar}, - ByteDigestConverter, Config, MerkleTree, - }; - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq}; - use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::ConstraintSystem; - - #[derive(Clone)] - pub(super) struct Window4x256; - impl pedersen::Window for Window4x256 { - const WINDOW_SIZE: usize = 4; - const NUM_WINDOWS: usize = 256; - } - - type LeafH = pedersen::CRH; - type LeafHG = pedersen::constraints::CRHGadget; - - type CompressH = pedersen::TwoToOneCRH; - type CompressHG = pedersen::constraints::TwoToOneCRHGadget; - - type LeafVar = [UInt8]; - - struct JubJubMerkleTreeParams; - - impl Config for JubJubMerkleTreeParams { - type Leaf = [u8]; - type LeafDigest = ::Output; - type LeafInnerDigestConverter = ByteDigestConverter; - - type InnerDigest = ::Output; - type LeafHash = LeafH; - type TwoToOneHash = CompressH; - } - - type ConstraintF = Fq; - struct JubJubMerkleTreeParamsVar; - impl ConfigGadget for JubJubMerkleTreeParamsVar { - type Leaf = LeafVar; - type LeafDigest = >::OutputVar; - type LeafInnerConverter = BytesVarDigestConverter; - type InnerDigest = - >::OutputVar; - type LeafHash = LeafHG; - type TwoToOneHash = CompressHG; - } - - type JubJubMerkleTree = MerkleTree; - - /// Generate a merkle tree, its constraints, and test its constraints - fn merkle_tree_test( - leaves: &[Vec], - use_bad_root: bool, - update_query: Option<(usize, Vec)>, - ) -> () { - let mut rng = ark_std::test_rng(); - - let leaf_crh_params = ::setup(&mut rng).unwrap(); - let two_to_one_crh_params = ::setup(&mut rng).unwrap(); - let mut tree = - JubJubMerkleTree::new(&leaf_crh_params, &two_to_one_crh_params, leaves).unwrap(); - let root = tree.root(); - for (i, leaf) in leaves.iter().enumerate() { - let cs = ConstraintSystem::::new_ref(); - let proof = tree.generate_proof(i).unwrap(); - assert!(proof - .verify( - &leaf_crh_params, - &two_to_one_crh_params, - &root, - leaf.as_slice() - ) - .unwrap()); - - // Allocate Merkle Tree Root - let root = >::OutputVar::new_witness( - ark_relations::ns!(cs, "new_digest"), - || { - if use_bad_root { - Ok(::Output::default()) - } else { - Ok(root) - } - }, - ) - .unwrap(); - - let constraints_from_digest = cs.num_constraints(); - println!("constraints from digest: {}", constraints_from_digest); - - // Allocate Parameters for CRH - let leaf_crh_params_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "leaf_crh_parameter"), - &leaf_crh_params, - ) - .unwrap(); - let two_to_one_crh_params_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "two_to_one_crh_parameter"), - &two_to_one_crh_params, - ) - .unwrap(); - - let constraints_from_params = cs.num_constraints() - constraints_from_digest; - println!("constraints from parameters: {}", constraints_from_params); - - // Allocate Leaf - let leaf_g = UInt8::new_input_vec(cs.clone(), leaf).unwrap(); - - let constraints_from_leaf = - cs.num_constraints() - constraints_from_params - constraints_from_digest; - println!("constraints from leaf: {}", constraints_from_leaf); - - // Allocate Merkle Tree Path - let cw: PathVar = - PathVar::new_witness(ark_relations::ns!(cs, "new_witness"), || Ok(&proof)).unwrap(); - - let constraints_from_path = cs.num_constraints() - - constraints_from_params - - constraints_from_digest - - constraints_from_leaf; - println!("constraints from path: {}", constraints_from_path); - - assert!(cs.is_satisfied().unwrap()); - assert!(cw - .verify_membership( - &leaf_crh_params_var, - &two_to_one_crh_params_var, - &root, - &leaf_g, - ) - .unwrap() - .value() - .unwrap()); - let setup_constraints = constraints_from_leaf - + constraints_from_digest - + constraints_from_params - + constraints_from_path; - println!( - "number of constraints: {}", - cs.num_constraints() - setup_constraints - ); - - assert!( - cs.is_satisfied().unwrap(), - "verification constraints not satisfied" - ); - } - - // check update - if let Some(update_query) = update_query { - let cs = ConstraintSystem::::new_ref(); - // allocate parameters for CRH - let leaf_crh_params_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "leaf_crh_parameter"), - &leaf_crh_params, - ) - .unwrap(); - let two_to_one_crh_params_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "two_to_one_crh_parameter"), - &two_to_one_crh_params, - ) - .unwrap(); - - // allocate old leaf and new leaf - let old_leaf_var = - UInt8::new_input_vec(ark_relations::ns!(cs, "old_leaf"), &leaves[update_query.0]) - .unwrap(); - let new_leaf_var = - UInt8::new_input_vec(ark_relations::ns!(cs, "new_leaf"), &update_query.1).unwrap(); - // - // suppose the verifier already knows old root, new root, old leaf, new leaf, and the original path (so they are public) - let old_root = tree.root(); - let old_root_var = >::OutputVar::new_input( - ark_relations::ns!(cs, "old_root"), - || Ok(old_root), - ) - .unwrap(); - let old_path = tree.generate_proof(update_query.0).unwrap(); - let old_path_var: PathVar = - PathVar::new_input(ark_relations::ns!(cs, "old_path"), || Ok(old_path)).unwrap(); - let new_root = { - tree.update(update_query.0, &update_query.1).unwrap(); - tree.root() - }; - let new_root_var = >::OutputVar::new_input( - ark_relations::ns!(cs, "new_root"), - || Ok(new_root), - ) - .unwrap(); - // verifier need to get a proof (the witness) to show the known new root is correct - assert!(old_path_var - .update_and_check( - &leaf_crh_params_var, - &two_to_one_crh_params_var, - &old_root_var, - &new_root_var, - &old_leaf_var, - &new_leaf_var, - ) - .unwrap() - .value() - .unwrap()); - assert!(cs.is_satisfied().unwrap()) - } - } - - #[test] - fn good_root_test() { - let mut leaves = Vec::new(); - for i in 0..4u8 { - let input = vec![i; 30]; - leaves.push(input); - } - merkle_tree_test(&leaves, false, Some((3usize, vec![7u8; 30]))); - } - - #[test] - #[should_panic] - fn bad_root_test() { - let mut leaves = Vec::new(); - for i in 0..4u8 { - let input = vec![i; 30]; - leaves.push(input); - } - merkle_tree_test(&leaves, true, None); - } -} - -mod field_mt_tests { - use crate::crh::{poseidon, CRHSchemeGadget, TwoToOneCRHSchemeGadget}; - use crate::merkle_tree::{ - constraints::{ConfigGadget, PathVar}, - tests::test_utils::poseidon_parameters, - Config, IdentityDigestConverter, MerkleTree, - }; - use ark_r1cs_std::{ - alloc::AllocVar, convert::ToBitsGadget, fields::fp::FpVar, uint32::UInt32, R1CSVar, - }; - use ark_relations::r1cs::ConstraintSystem; - use ark_std::{test_rng, One, UniformRand}; - - type F = ark_ed_on_bls12_381::Fr; - type H = poseidon::CRH; - type HG = poseidon::constraints::CRHGadget; - type TwoToOneH = poseidon::TwoToOneCRH; - type TwoToOneHG = poseidon::constraints::TwoToOneCRHGadget; - - type LeafVar = [FpVar]; - - struct FieldMTConfig; - impl Config for FieldMTConfig { - type Leaf = [F]; - type LeafDigest = F; - type LeafInnerDigestConverter = IdentityDigestConverter; - type InnerDigest = F; - type LeafHash = H; - type TwoToOneHash = TwoToOneH; - } - - struct FieldMTConfigVar; - - impl ConfigGadget for FieldMTConfigVar { - type Leaf = LeafVar; - type LeafDigest = FpVar; - type LeafInnerConverter = IdentityDigestConverter>; - type InnerDigest = FpVar; - type LeafHash = HG; - type TwoToOneHash = TwoToOneHG; - } - - type FieldMT = MerkleTree; - - fn merkle_tree_test( - leaves: &[Vec], - use_bad_root: bool, - update_query: Option<(usize, Vec)>, - ) { - let leaf_crh_params = poseidon_parameters(); - let two_to_one_params = leaf_crh_params.clone(); - let mut tree = FieldMT::new(&leaf_crh_params, &two_to_one_params, leaves).unwrap(); - let root = tree.root(); - for (i, leaf) in leaves.iter().enumerate() { - let cs = ConstraintSystem::::new_ref(); - let proof = tree.generate_proof(i).unwrap(); - assert!(proof - .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) - .unwrap()); - // Allocate MT root - let root = FpVar::new_witness(cs.clone(), || { - if use_bad_root { - Ok(root + F::one()) - } else { - Ok(root) - } - }) - .unwrap(); - - let constraints_from_digest = cs.num_constraints(); - println!("constraints from digest: {}", constraints_from_digest); - - let leaf_crh_params_var = >::ParametersVar::new_constant( - ark_relations::ns!(cs, "leaf_crh_params"), - &leaf_crh_params, - ) - .unwrap(); - - let two_to_one_crh_params_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "two_to_one_params"), - &leaf_crh_params, - ) - .unwrap(); - - let constraints_from_params = cs.num_constraints() - constraints_from_digest; - println!("constraints from parameters: {}", constraints_from_params); - - // Allocate Leaf - let leaf_g: Vec<_> = leaf - .iter() - .map(|x| FpVar::new_input(cs.clone(), || Ok(*x)).unwrap()) - .collect(); - - let constraints_from_leaf = - cs.num_constraints() - constraints_from_params - constraints_from_digest; - println!("constraints from leaf: {}", constraints_from_leaf); - - // Allocate MT Path - let mut cw = PathVar::::new_witness( - ark_relations::ns!(cs, "new_witness"), - || Ok(&proof), - ) - .unwrap(); - - let constraints_from_path = cs.num_constraints() - - constraints_from_params - - constraints_from_digest - - constraints_from_leaf; - println!("constraints from path: {}", constraints_from_path); - assert!(cs.is_satisfied().unwrap()); - - // try replace the path index - let leaf_pos = UInt32::new_witness(cs.clone(), || Ok(i as u32)) - .unwrap() - .to_bits_le() - .unwrap(); - cw.set_leaf_position(leaf_pos.clone()); - - // check if get_leaf_position is correct - let expected_leaf_pos = leaf_pos.value().unwrap(); - let mut actual_leaf_pos = cw.get_leaf_position().value().unwrap(); - actual_leaf_pos.extend((0..(32 - actual_leaf_pos.len())).map(|_| false)); - assert_eq!(expected_leaf_pos, actual_leaf_pos); - - assert!(cw - .verify_membership( - &leaf_crh_params_var, - &two_to_one_crh_params_var, - &root, - &leaf_g - ) - .unwrap() - .value() - .unwrap()); - - let setup_constraints = constraints_from_leaf - + constraints_from_digest - + constraints_from_params - + constraints_from_path; - - println!( - "number of constraints for verification: {}", - cs.num_constraints() - setup_constraints - ); - - assert!( - cs.is_satisfied().unwrap(), - "verification constraints not satisfied" - ); - } - - // check update - - if let Some(update_query) = update_query { - let cs = ConstraintSystem::::new_ref(); - // allocate parameters for CRH - let leaf_crh_params_var = >::ParametersVar::new_constant( - ark_relations::ns!(cs, "leaf_crh_params"), - &leaf_crh_params, - ) - .unwrap(); - - let two_to_one_crh_params_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "two_to_one_params"), - &leaf_crh_params, - ) - .unwrap(); - - let old_leaf_var: Vec<_> = leaves[update_query.0] - .iter() - .map(|x| FpVar::new_input(cs.clone(), || Ok(*x)).unwrap()) - .collect(); - let new_leaf_var: Vec<_> = update_query - .1 - .iter() - .map(|x| FpVar::new_input(cs.clone(), || Ok(*x)).unwrap()) - .collect(); - - let old_root = tree.root(); - let old_root_var = FpVar::new_input(cs.clone(), || Ok(old_root)).unwrap(); - - let old_path = tree.generate_proof(update_query.0).unwrap(); - let old_path_var = PathVar::::new_input( - ark_relations::ns!(cs, "old_path"), - || Ok(old_path), - ) - .unwrap(); - let new_root = { - tree.update(update_query.0, update_query.1.as_slice()) - .unwrap(); - tree.root() - }; - let new_root_var = FpVar::new_witness(cs.clone(), || Ok(new_root)).unwrap(); - - assert!(old_path_var - .update_and_check( - &leaf_crh_params_var, - &two_to_one_crh_params_var, - &old_root_var, - &new_root_var, - &old_leaf_var, - &new_leaf_var - ) - .unwrap() - .value() - .unwrap()); - - assert!(cs.is_satisfied().unwrap()) - } - } - - #[test] - fn good_root_test() { - let mut rng = test_rng(); - let mut rand_leaves = || (0..2).map(|_| F::rand(&mut rng)).collect(); - - let mut leaves: Vec> = Vec::new(); - for _ in 0..128u8 { - leaves.push(rand_leaves()) - } - - merkle_tree_test(&leaves, false, Some((3, rand_leaves()))) - } - - #[test] - #[should_panic] - fn bad_root_test() { - let mut rng = test_rng(); - let mut rand_leaves = || (0..2).map(|_| F::rand(&mut rng)).collect(); - - let mut leaves: Vec> = Vec::new(); - for _ in 0..128u8 { - leaves.push(rand_leaves()) - } - - merkle_tree_test(&leaves, true, Some((3, rand_leaves()))) - } -} +// mod byte_mt_tests { +// use crate::crh::{ +// pedersen, CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, +// }; +// use crate::merkle_tree::{ +// constraints::{BytesVarDigestConverter, ConfigGadget, PathVar}, +// ByteDigestConverter, Config, MerkleTree, +// }; +// use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq}; +// use ark_r1cs_std::prelude::*; +// use ark_relations::gr1cs::ConstraintSystem; + +// #[derive(Clone)] +// pub(super) struct Window4x256; +// impl pedersen::Window for Window4x256 { +// const WINDOW_SIZE: usize = 4; +// const NUM_WINDOWS: usize = 256; +// } + +// type LeafH = pedersen::CRH; +// type LeafHG = pedersen::constraints::CRHGadget; + +// type CompressH = pedersen::TwoToOneCRH; +// type CompressHG = pedersen::constraints::TwoToOneCRHGadget; + +// type LeafVar = [UInt8]; + +// struct JubJubMerkleTreeParams; + +// impl Config for JubJubMerkleTreeParams { +// type Leaf = [u8]; +// type LeafDigest = ::Output; +// type LeafInnerDigestConverter = ByteDigestConverter; + +// type InnerDigest = ::Output; +// type LeafHash = LeafH; +// type TwoToOneHash = CompressH; +// } + +// type ConstraintF = Fq; +// struct JubJubMerkleTreeParamsVar; +// impl ConfigGadget for JubJubMerkleTreeParamsVar { +// type Leaf = LeafVar; +// type LeafDigest = >::OutputVar; +// type LeafInnerConverter = BytesVarDigestConverter; +// type InnerDigest = +// >::OutputVar; +// type LeafHash = LeafHG; +// type TwoToOneHash = CompressHG; +// } + +// type JubJubMerkleTree = MerkleTree; + +// /// Generate a merkle tree, its constraints, and test its constraints +// fn merkle_tree_test( +// leaves: &[Vec], +// use_bad_root: bool, +// update_query: Option<(usize, Vec)>, +// ) -> () { +// let mut rng = ark_std::test_rng(); + +// let leaf_crh_params = ::setup(&mut rng).unwrap(); +// let two_to_one_crh_params = ::setup(&mut rng).unwrap(); +// let mut tree = +// JubJubMerkleTree::new(&leaf_crh_params, &two_to_one_crh_params, leaves).unwrap(); +// let root = tree.root(); +// for (i, leaf) in leaves.iter().enumerate() { +// let cs = ConstraintSystem::::new_ref(); +// let proof = tree.generate_proof(i).unwrap(); +// assert!(proof +// .verify( +// &leaf_crh_params, +// &two_to_one_crh_params, +// &root, +// leaf.as_slice() +// ) +// .unwrap()); + +// // Allocate Merkle Tree Root +// let root = >::OutputVar::new_witness( +// ark_relations::ns!(cs, "new_digest"), +// || { +// if use_bad_root { +// Ok(::Output::default()) +// } else { +// Ok(root) +// } +// }, +// ) +// .unwrap(); + +// let constraints_from_digest = cs.num_constraints(); +// println!("constraints from digest: {}", constraints_from_digest); + +// // Allocate Parameters for CRH +// let leaf_crh_params_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "leaf_crh_parameter"), +// &leaf_crh_params, +// ) +// .unwrap(); +// let two_to_one_crh_params_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "two_to_one_crh_parameter"), +// &two_to_one_crh_params, +// ) +// .unwrap(); + +// let constraints_from_params = cs.num_constraints() - constraints_from_digest; +// println!("constraints from parameters: {}", constraints_from_params); + +// // Allocate Leaf +// let leaf_g = UInt8::new_input_vec(cs.clone(), leaf).unwrap(); + +// let constraints_from_leaf = +// cs.num_constraints() - constraints_from_params - constraints_from_digest; +// println!("constraints from leaf: {}", constraints_from_leaf); + +// // Allocate Merkle Tree Path +// let cw: PathVar = +// PathVar::new_witness(ark_relations::ns!(cs, "new_witness"), || Ok(&proof)).unwrap(); + +// let constraints_from_path = cs.num_constraints() +// - constraints_from_params +// - constraints_from_digest +// - constraints_from_leaf; +// println!("constraints from path: {}", constraints_from_path); + +// assert!(cs.is_satisfied().unwrap()); +// assert!(cw +// .verify_membership( +// &leaf_crh_params_var, +// &two_to_one_crh_params_var, +// &root, +// &leaf_g, +// ) +// .unwrap() +// .value() +// .unwrap()); +// let setup_constraints = constraints_from_leaf +// + constraints_from_digest +// + constraints_from_params +// + constraints_from_path; +// println!( +// "number of constraints: {}", +// cs.num_constraints() - setup_constraints +// ); + +// assert!( +// cs.is_satisfied().unwrap(), +// "verification constraints not satisfied" +// ); +// } + +// // check update +// if let Some(update_query) = update_query { +// let cs = ConstraintSystem::::new_ref(); +// // allocate parameters for CRH +// let leaf_crh_params_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "leaf_crh_parameter"), +// &leaf_crh_params, +// ) +// .unwrap(); +// let two_to_one_crh_params_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "two_to_one_crh_parameter"), +// &two_to_one_crh_params, +// ) +// .unwrap(); + +// // allocate old leaf and new leaf +// let old_leaf_var = +// UInt8::new_input_vec(ark_relations::ns!(cs, "old_leaf"), &leaves[update_query.0]) +// .unwrap(); +// let new_leaf_var = +// UInt8::new_input_vec(ark_relations::ns!(cs, "new_leaf"), &update_query.1).unwrap(); +// // +// // suppose the verifier already knows old root, new root, old leaf, new leaf, and the original path (so they are public) +// let old_root = tree.root(); +// let old_root_var = >::OutputVar::new_input( +// ark_relations::ns!(cs, "old_root"), +// || Ok(old_root), +// ) +// .unwrap(); +// let old_path = tree.generate_proof(update_query.0).unwrap(); +// let old_path_var: PathVar = +// PathVar::new_input(ark_relations::ns!(cs, "old_path"), || Ok(old_path)).unwrap(); +// let new_root = { +// tree.update(update_query.0, &update_query.1).unwrap(); +// tree.root() +// }; +// let new_root_var = >::OutputVar::new_input( +// ark_relations::ns!(cs, "new_root"), +// || Ok(new_root), +// ) +// .unwrap(); +// // verifier need to get a proof (the witness) to show the known new root is correct +// assert!(old_path_var +// .update_and_check( +// &leaf_crh_params_var, +// &two_to_one_crh_params_var, +// &old_root_var, +// &new_root_var, +// &old_leaf_var, +// &new_leaf_var, +// ) +// .unwrap() +// .value() +// .unwrap()); +// assert!(cs.is_satisfied().unwrap()) +// } +// } + +// #[test] +// fn good_root_test() { +// let mut leaves = Vec::new(); +// for i in 0..4u8 { +// let input = vec![i; 30]; +// leaves.push(input); +// } +// merkle_tree_test(&leaves, false, Some((3usize, vec![7u8; 30]))); +// } + +// #[test] +// #[should_panic] +// fn bad_root_test() { +// let mut leaves = Vec::new(); +// for i in 0..4u8 { +// let input = vec![i; 30]; +// leaves.push(input); +// } +// merkle_tree_test(&leaves, true, None); +// } +// } + +// mod field_mt_tests { +// use crate::crh::{poseidon, CRHSchemeGadget, TwoToOneCRHSchemeGadget}; +// use crate::merkle_tree::{ +// constraints::{ConfigGadget, PathVar}, +// tests::test_utils::poseidon_parameters, +// Config, IdentityDigestConverter, MerkleTree, +// }; +// use ark_r1cs_std::{ +// alloc::AllocVar, convert::ToBitsGadget, fields::fp::FpVar, uint32::UInt32, R1CSVar, +// }; +// use ark_relations::gr1cs::ConstraintSystem; +// use ark_std::{test_rng, One, UniformRand}; + +// type F = ark_ed_on_bls12_381::Fr; +// type H = poseidon::CRH; +// type HG = poseidon::constraints::CRHGadget; +// type TwoToOneH = poseidon::TwoToOneCRH; +// type TwoToOneHG = poseidon::constraints::TwoToOneCRHGadget; + +// type LeafVar = [FpVar]; + +// struct FieldMTConfig; +// impl Config for FieldMTConfig { +// type Leaf = [F]; +// type LeafDigest = F; +// type LeafInnerDigestConverter = IdentityDigestConverter; +// type InnerDigest = F; +// type LeafHash = H; +// type TwoToOneHash = TwoToOneH; +// } + +// struct FieldMTConfigVar; + +// impl ConfigGadget for FieldMTConfigVar { +// type Leaf = LeafVar; +// type LeafDigest = FpVar; +// type LeafInnerConverter = IdentityDigestConverter>; +// type InnerDigest = FpVar; +// type LeafHash = HG; +// type TwoToOneHash = TwoToOneHG; +// } + +// type FieldMT = MerkleTree; + +// fn merkle_tree_test( +// leaves: &[Vec], +// use_bad_root: bool, +// update_query: Option<(usize, Vec)>, +// ) { +// let leaf_crh_params = poseidon_parameters(); +// let two_to_one_params = leaf_crh_params.clone(); +// let mut tree = FieldMT::new(&leaf_crh_params, &two_to_one_params, leaves).unwrap(); +// let root = tree.root(); +// for (i, leaf) in leaves.iter().enumerate() { +// let cs = ConstraintSystem::::new_ref(); +// let proof = tree.generate_proof(i).unwrap(); +// assert!(proof +// .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) +// .unwrap()); +// // Allocate MT root +// let root = FpVar::new_witness(cs.clone(), || { +// if use_bad_root { +// Ok(root + F::one()) +// } else { +// Ok(root) +// } +// }) +// .unwrap(); + +// let constraints_from_digest = cs.num_constraints(); +// println!("constraints from digest: {}", constraints_from_digest); + +// let leaf_crh_params_var = >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "leaf_crh_params"), +// &leaf_crh_params, +// ) +// .unwrap(); + +// let two_to_one_crh_params_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "two_to_one_params"), +// &leaf_crh_params, +// ) +// .unwrap(); + +// let constraints_from_params = cs.num_constraints() - constraints_from_digest; +// println!("constraints from parameters: {}", constraints_from_params); + +// // Allocate Leaf +// let leaf_g: Vec<_> = leaf +// .iter() +// .map(|x| FpVar::new_input(cs.clone(), || Ok(*x)).unwrap()) +// .collect(); + +// let constraints_from_leaf = +// cs.num_constraints() - constraints_from_params - constraints_from_digest; +// println!("constraints from leaf: {}", constraints_from_leaf); + +// // Allocate MT Path +// let mut cw = PathVar::::new_witness( +// ark_relations::ns!(cs, "new_witness"), +// || Ok(&proof), +// ) +// .unwrap(); + +// let constraints_from_path = cs.num_constraints() +// - constraints_from_params +// - constraints_from_digest +// - constraints_from_leaf; +// println!("constraints from path: {}", constraints_from_path); +// assert!(cs.is_satisfied().unwrap()); + +// // try replace the path index +// let leaf_pos = UInt32::new_witness(cs.clone(), || Ok(i as u32)) +// .unwrap() +// .to_bits_le() +// .unwrap(); +// cw.set_leaf_position(leaf_pos.clone()); + +// // check if get_leaf_position is correct +// let expected_leaf_pos = leaf_pos.value().unwrap(); +// let mut actual_leaf_pos = cw.get_leaf_position().value().unwrap(); +// actual_leaf_pos.extend((0..(32 - actual_leaf_pos.len())).map(|_| false)); +// assert_eq!(expected_leaf_pos, actual_leaf_pos); + +// assert!(cw +// .verify_membership( +// &leaf_crh_params_var, +// &two_to_one_crh_params_var, +// &root, +// &leaf_g +// ) +// .unwrap() +// .value() +// .unwrap()); + +// let setup_constraints = constraints_from_leaf +// + constraints_from_digest +// + constraints_from_params +// + constraints_from_path; + +// println!( +// "number of constraints for verification: {}", +// cs.num_constraints() - setup_constraints +// ); + +// assert!( +// cs.is_satisfied().unwrap(), +// "verification constraints not satisfied" +// ); +// } + +// // check update + +// if let Some(update_query) = update_query { +// let cs = ConstraintSystem::::new_ref(); +// // allocate parameters for CRH +// let leaf_crh_params_var = >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "leaf_crh_params"), +// &leaf_crh_params, +// ) +// .unwrap(); + +// let two_to_one_crh_params_var = +// >::ParametersVar::new_constant( +// ark_relations::ns!(cs, "two_to_one_params"), +// &leaf_crh_params, +// ) +// .unwrap(); + +// let old_leaf_var: Vec<_> = leaves[update_query.0] +// .iter() +// .map(|x| FpVar::new_input(cs.clone(), || Ok(*x)).unwrap()) +// .collect(); +// let new_leaf_var: Vec<_> = update_query +// .1 +// .iter() +// .map(|x| FpVar::new_input(cs.clone(), || Ok(*x)).unwrap()) +// .collect(); + +// let old_root = tree.root(); +// let old_root_var = FpVar::new_input(cs.clone(), || Ok(old_root)).unwrap(); + +// let old_path = tree.generate_proof(update_query.0).unwrap(); +// let old_path_var = PathVar::::new_input( +// ark_relations::ns!(cs, "old_path"), +// || Ok(old_path), +// ) +// .unwrap(); +// let new_root = { +// tree.update(update_query.0, update_query.1.as_slice()) +// .unwrap(); +// tree.root() +// }; +// let new_root_var = FpVar::new_witness(cs.clone(), || Ok(new_root)).unwrap(); + +// assert!(old_path_var +// .update_and_check( +// &leaf_crh_params_var, +// &two_to_one_crh_params_var, +// &old_root_var, +// &new_root_var, +// &old_leaf_var, +// &new_leaf_var +// ) +// .unwrap() +// .value() +// .unwrap()); + +// assert!(cs.is_satisfied().unwrap()) +// } +// } + +// #[test] +// fn good_root_test() { +// let mut rng = test_rng(); +// let mut rand_leaves = || (0..2).map(|_| F::rand(&mut rng)).collect(); + +// let mut leaves: Vec> = Vec::new(); +// for _ in 0..128u8 { +// leaves.push(rand_leaves()) +// } + +// merkle_tree_test(&leaves, false, Some((3, rand_leaves()))) +// } + +// #[test] +// #[should_panic] +// fn bad_root_test() { +// let mut rng = test_rng(); +// let mut rand_leaves = || (0..2).map(|_| F::rand(&mut rng)).collect(); + +// let mut leaves: Vec> = Vec::new(); +// for _ in 0..128u8 { +// leaves.push(rand_leaves()) +// } + +// merkle_tree_test(&leaves, true, Some((3, rand_leaves()))) +// } +// } diff --git a/crypto-primitives/src/merkle_tree/tests/mod.rs b/crypto-primitives/src/merkle_tree/tests/mod.rs index 4f18d6eb..a03e1883 100644 --- a/crypto-primitives/src/merkle_tree/tests/mod.rs +++ b/crypto-primitives/src/merkle_tree/tests/mod.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] mod constraints; mod test_utils; diff --git a/crypto-primitives/src/merkle_tree/tests/test_utils.rs b/crypto-primitives/src/merkle_tree/tests/test_utils.rs index 9da40354..e1ff2f9c 100644 --- a/crypto-primitives/src/merkle_tree/tests/test_utils.rs +++ b/crypto-primitives/src/merkle_tree/tests/test_utils.rs @@ -653,5 +653,5 @@ pub(crate) fn poseidon_parameters() -> PoseidonConfig { PoseidonConfig::::new(full_rounds, partial_rounds, alpha, mds, ark, 2, 1) } -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] mod constraints {} diff --git a/crypto-primitives/src/prf/blake2s/constraints.rs b/crypto-primitives/src/prf/blake2s/constraints.rs index c0c180b9..f6a2296f 100644 --- a/crypto-primitives/src/prf/blake2s/constraints.rs +++ b/crypto-primitives/src/prf/blake2s/constraints.rs @@ -1,7 +1,7 @@ use crate::prf::PRFGadget; use ark_ff::PrimeField; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; +use ark_relations::gr1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use ark_std::borrow::Borrow; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -295,14 +295,14 @@ pub struct Blake2sGadget; pub struct OutputVar(pub Vec>); impl EqGadget for OutputVar { - #[tracing::instrument(target = "r1cs")] + #[tracing::instrument(target = "gr1cs")] fn is_eq(&self, other: &Self) -> Result, SynthesisError> { self.0.is_eq(&other.0) } /// If `should_enforce == true`, enforce that `self` and `other` are equal; /// else, enforce a vacuously true statement. - #[tracing::instrument(target = "r1cs")] + #[tracing::instrument(target = "gr1cs")] fn conditional_enforce_equal( &self, other: &Self, @@ -313,7 +313,7 @@ impl EqGadget for OutputVar { /// If `should_enforce == true`, enforce that `self` and `other` are not /// equal; else, enforce a vacuously true statement. - #[tracing::instrument(target = "r1cs")] + #[tracing::instrument(target = "gr1cs")] fn conditional_enforce_not_equal( &self, other: &Self, @@ -333,7 +333,7 @@ impl ToBytesGadget for OutputVar AllocVar<[u8; 32], ConstraintF> for OutputVar { - #[tracing::instrument(target = "r1cs", skip(cs, f))] + #[tracing::instrument(target = "gr1cs", skip(cs, f))] fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, @@ -348,7 +348,7 @@ impl AllocVar<[u8; 32], ConstraintF> for OutputVar R1CSVar for OutputVar { +impl GR1CSVar for OutputVar { type Value = [u8; 32]; fn cs(&self) -> ConstraintSystemRef { @@ -367,14 +367,14 @@ impl R1CSVar for OutputVar { impl PRFGadget for Blake2sGadget { type OutputVar = OutputVar; - #[tracing::instrument(target = "r1cs", skip(cs))] + #[tracing::instrument(target = "gr1cs", skip(cs))] fn new_seed(cs: impl Into>, seed: &[u8; 32]) -> Vec> { let ns = cs.into(); let cs = ns.cs(); UInt8::new_witness_vec(ark_relations::ns!(cs, "New Blake2s seed"), seed).unwrap() } - #[tracing::instrument(target = "r1cs", skip(seed, input))] + #[tracing::instrument(target = "gr1cs", skip(seed, input))] fn evaluate(seed: &[UInt8], input: &[UInt8]) -> Result { assert_eq!(seed.len(), 32); let input: Vec<_> = seed @@ -396,7 +396,7 @@ mod test { use ark_std::rand::Rng; use crate::prf::blake2s::{constraints::evaluate_blake2s, Blake2s as B2SPRF}; - use ark_relations::r1cs::ConstraintSystem; + use ark_relations::gr1cs::ConstraintSystem; use blake2::Blake2s256; use digest::{Digest, FixedOutput}; @@ -444,8 +444,8 @@ mod test { if !cs.is_satisfied().unwrap() { println!( - "which is unsatisfied: {:?}", - cs.which_is_unsatisfied().unwrap() + "which predicate is unsatisfied: {:?}", + cs.which_predicate_is_unsatisfied().unwrap() ); } assert!(cs.is_satisfied().unwrap()); diff --git a/crypto-primitives/src/prf/blake2s/mod.rs b/crypto-primitives/src/prf/blake2s/mod.rs index 5addc754..97e17801 100644 --- a/crypto-primitives/src/prf/blake2s/mod.rs +++ b/crypto-primitives/src/prf/blake2s/mod.rs @@ -4,7 +4,7 @@ use ark_std::vec::Vec; use blake2::{Blake2s256 as B2s, Blake2sMac}; use digest::Digest; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; #[derive(Clone)] diff --git a/crypto-primitives/src/prf/constraints.rs b/crypto-primitives/src/prf/constraints.rs index 2e64729d..63792905 100644 --- a/crypto-primitives/src/prf/constraints.rs +++ b/crypto-primitives/src/prf/constraints.rs @@ -1,7 +1,7 @@ use crate::prf::PRF; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; use ark_std::fmt::Debug; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -10,7 +10,7 @@ pub trait PRFGadget { type OutputVar: EqGadget + ToBytesGadget + AllocVar - + R1CSVar + + GR1CSVar + Clone + Debug; diff --git a/crypto-primitives/src/prf/mod.rs b/crypto-primitives/src/prf/mod.rs index 5aef9297..f86df3f7 100644 --- a/crypto-primitives/src/prf/mod.rs +++ b/crypto-primitives/src/prf/mod.rs @@ -3,9 +3,9 @@ use crate::Error; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{fmt::Debug, hash::Hash}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub use constraints::*; pub mod blake2s; diff --git a/crypto-primitives/src/signature/constraints.rs b/crypto-primitives/src/signature/constraints.rs index 860a8efb..4a9cea37 100644 --- a/crypto-primitives/src/signature/constraints.rs +++ b/crypto-primitives/src/signature/constraints.rs @@ -1,7 +1,7 @@ use crate::signature::SignatureScheme; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; pub trait SigVerifyGadget { type ParametersVar: AllocVar + Clone; diff --git a/crypto-primitives/src/signature/mod.rs b/crypto-primitives/src/signature/mod.rs index 577c6d73..8009de33 100644 --- a/crypto-primitives/src/signature/mod.rs +++ b/crypto-primitives/src/signature/mod.rs @@ -2,9 +2,9 @@ use crate::Error; use ark_serialize::CanonicalSerialize; use ark_std::{hash::Hash, rand::Rng}; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub use constraints::*; pub mod schnorr; diff --git a/crypto-primitives/src/signature/schnorr/constraints.rs b/crypto-primitives/src/signature/schnorr/constraints.rs index f87089c3..26a7ea3d 100644 --- a/crypto-primitives/src/signature/schnorr/constraints.rs +++ b/crypto-primitives/src/signature/schnorr/constraints.rs @@ -5,7 +5,7 @@ use crate::signature::{ use ark_ec::CurveGroup; use ark_ff::Field; use ark_r1cs_std::prelude::*; -use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_relations::gr1cs::{Namespace, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, marker::PhantomData}; @@ -57,7 +57,7 @@ where type ParametersVar = ParametersVar; type PublicKeyVar = PublicKeyVar; - #[tracing::instrument(target = "r1cs", skip(parameters, public_key, randomness))] + #[tracing::instrument(target = "gr1cs", skip(parameters, public_key, randomness))] fn randomize( parameters: &Self::ParametersVar, public_key: &Self::PublicKeyVar, diff --git a/crypto-primitives/src/signature/schnorr/mod.rs b/crypto-primitives/src/signature/schnorr/mod.rs index c27513f3..16240ea4 100644 --- a/crypto-primitives/src/signature/schnorr/mod.rs +++ b/crypto-primitives/src/signature/schnorr/mod.rs @@ -10,7 +10,7 @@ use ark_std::vec::Vec; use ark_std::{hash::Hash, marker::PhantomData, ops::Mul, rand::Rng}; use digest::Digest; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; pub struct Schnorr { diff --git a/crypto-primitives/src/snark/constraints.rs b/crypto-primitives/src/snark/constraints.rs index ae4a39f0..4a2e98b6 100644 --- a/crypto-primitives/src/snark/constraints.rs +++ b/crypto-primitives/src/snark/constraints.rs @@ -11,7 +11,7 @@ use ark_r1cs_std::{ }; use ark_relations::{ lc, ns, - r1cs::{ + gr1cs::{ ConstraintSynthesizer, ConstraintSystemRef, LinearCombination, Namespace, OptimizationGoal, SynthesisError, }, @@ -52,7 +52,7 @@ pub trait SNARKGadget> { /// /// The default implementation does not omit such checks, and just invokes /// `Self::ProofVar::new_variable`. - #[tracing::instrument(target = "r1cs", skip(cs, f))] + #[tracing::instrument(target = "gr1cs", skip(cs, f))] fn new_proof_unchecked>( cs: impl Into>, f: impl FnOnce() -> Result, @@ -70,7 +70,7 @@ pub trait SNARKGadget> { /// /// The default implementation does not omit such checks, and just invokes /// `Self::VerifyingKeyVar::new_variable`. - #[tracing::instrument(target = "r1cs", skip(cs, f))] + #[tracing::instrument(target = "gr1cs", skip(cs, f))] fn new_verification_key_unchecked>( cs: impl Into>, f: impl FnOnce() -> Result, @@ -632,7 +632,7 @@ where let limb = AllocatedFp::::new_witness(ns!(cs, "limb"), || Ok(limb_value))?; lc = lc - limb.variable; - cs.enforce_constraint(lc!(), lc!(), lc).unwrap(); + cs.enforce_r1cs_constraint(lc!(), lc!(), lc).unwrap(); limbs.push(FpVar::from(limb)); } diff --git a/crypto-primitives/src/snark/mod.rs b/crypto-primitives/src/snark/mod.rs index 967580a4..778b4e2e 100644 --- a/crypto-primitives/src/snark/mod.rs +++ b/crypto-primitives/src/snark/mod.rs @@ -1,6 +1,6 @@ -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub use constraints::*; pub use ark_snark::*; diff --git a/crypto-primitives/src/sponge/constraints/absorb.rs b/crypto-primitives/src/sponge/constraints/absorb.rs index 5235f164..7681d557 100644 --- a/crypto-primitives/src/sponge/constraints/absorb.rs +++ b/crypto-primitives/src/sponge/constraints/absorb.rs @@ -13,7 +13,7 @@ use ark_r1cs_std::{ }, uint8::UInt8, }; -use ark_relations::r1cs::SynthesisError; +use ark_relations::gr1cs::SynthesisError; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -255,7 +255,7 @@ mod tests { use ark_ff::PrimeField; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::uint8::UInt8; - use ark_r1cs_std::R1CSVar; + use ark_r1cs_std::GR1CSVar; use ark_r1cs_std::{ alloc::AllocVar, groups::curves::{ @@ -263,14 +263,14 @@ mod tests { twisted_edwards::AffineVar as TEAffineVar, }, }; - use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef}; + use ark_relations::gr1cs::{ConstraintSystem, ConstraintSystemRef}; use ark_relations::*; use ark_std::{test_rng, UniformRand, Zero}; fn sw_curve_consistency_check( cs: ConstraintSystemRef, g: SWProjective, - ) -> r1cs::Result<()> + ) -> gr1cs::Result<()> where C: SWCurveConfig, C::BaseField: PrimeField, @@ -299,7 +299,7 @@ mod tests { Ok(()) } - fn te_curve_consistency_check(g: TEProjective) -> r1cs::Result<()> + fn te_curve_consistency_check(g: TEProjective) -> gr1cs::Result<()> where C: TECurveConfig, C::BaseField: PrimeField, diff --git a/crypto-primitives/src/sponge/constraints/mod.rs b/crypto-primitives/src/sponge/constraints/mod.rs index 51acebb1..a08e715c 100644 --- a/crypto-primitives/src/sponge/constraints/mod.rs +++ b/crypto-primitives/src/sponge/constraints/mod.rs @@ -11,11 +11,11 @@ use ark_r1cs_std::{ fp::{AllocatedFp, FpVar}, }, uint8::UInt8, - R1CSVar, + GR1CSVar, }; use ark_relations::{ lc, - r1cs::{ConstraintSystemRef, LinearCombination, SynthesisError}, + gr1cs::{ConstraintSystemRef, LinearCombination, SynthesisError}, }; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -78,7 +78,7 @@ pub fn bits_le_to_emulated<'a, F: PrimeField, CF: PrimeField>( let gadget = AllocatedFp::new_witness(ark_relations::ns!(cs, "alloc"), || Ok(val[k])).unwrap(); lc[k] = lc[k].clone() - (CF::one(), gadget.variable); - cs.enforce_constraint(lc!(), lc!(), lc[k].clone()).unwrap(); + cs.enforce_r1cs_constraint(lc!(), lc!(), lc[k].clone()).unwrap(); limbs.push(FpVar::::from(gadget)); } diff --git a/crypto-primitives/src/sponge/mod.rs b/crypto-primitives/src/sponge/mod.rs index 47a2c202..eb568bbe 100644 --- a/crypto-primitives/src/sponge/mod.rs +++ b/crypto-primitives/src/sponge/mod.rs @@ -3,12 +3,18 @@ use ark_ff::PrimeField; use ark_std::vec::Vec; /// Infrastructure for the constraints counterparts. -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; mod absorb; pub use absorb::*; + +/// The sponge for [Rescue][sad] +/// +/// [sad]: https://eprint.iacr.org/2020/1143.pdf +pub mod rescue; + /// The sponge for Poseidon /// /// This implementation of Poseidon is entirely from Fractal's implementation in [COS20][cos] diff --git a/crypto-primitives/src/sponge/poseidon/constraints.rs b/crypto-primitives/src/sponge/poseidon/constraints.rs index 60aa800b..44652860 100644 --- a/crypto-primitives/src/sponge/poseidon/constraints.rs +++ b/crypto-primitives/src/sponge/poseidon/constraints.rs @@ -5,7 +5,7 @@ use crate::sponge::{ }; use ark_ff::PrimeField; use ark_r1cs_std::{fields::fp::FpVar, prelude::*}; -use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; +use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -35,7 +35,7 @@ impl SpongeWithGadget for PoseidonSponge { } impl PoseidonSpongeVar { - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn apply_s_box( &self, state: &mut [FpVar], @@ -55,7 +55,7 @@ impl PoseidonSpongeVar { Ok(()) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn apply_ark(&self, state: &mut [FpVar], round_number: usize) -> Result<(), SynthesisError> { for (i, state_elem) in state.iter_mut().enumerate() { *state_elem += self.parameters.ark[round_number][i]; @@ -63,7 +63,7 @@ impl PoseidonSpongeVar { Ok(()) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn apply_mds(&self, state: &mut [FpVar]) -> Result<(), SynthesisError> { let mut new_state = Vec::new(); let zero = FpVar::::zero(); @@ -79,7 +79,7 @@ impl PoseidonSpongeVar { Ok(()) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn permute(&mut self) -> Result<(), SynthesisError> { let full_rounds_over_2 = self.parameters.full_rounds / 2; let mut state = self.state.clone(); @@ -106,7 +106,7 @@ impl PoseidonSpongeVar { Ok(()) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn absorb_internal( &mut self, mut rate_start_index: usize, @@ -142,7 +142,7 @@ impl PoseidonSpongeVar { } // Squeeze |output| many elements. This does not end in a squeeze - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn squeeze_internal( &mut self, mut rate_start_index: usize, @@ -183,7 +183,7 @@ impl PoseidonSpongeVar { impl CryptographicSpongeVar> for PoseidonSpongeVar { type Parameters = PoseidonConfig; - #[tracing::instrument(target = "r1cs", skip(cs))] + #[tracing::instrument(target = "gr1cs", skip(cs))] fn new(cs: ConstraintSystemRef, parameters: &PoseidonConfig) -> Self { let zero = FpVar::::zero(); let state = vec![zero; parameters.rate + parameters.capacity]; @@ -199,12 +199,12 @@ impl CryptographicSpongeVar> for PoseidonSpo } } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn cs(&self) -> ConstraintSystemRef { self.cs.clone() } - #[tracing::instrument(target = "r1cs", skip(self, input))] + #[tracing::instrument(target = "gr1cs", skip(self, input))] fn absorb(&mut self, input: &impl AbsorbGadget) -> Result<(), SynthesisError> { let input = input.to_sponge_field_elements()?; if input.is_empty() { @@ -230,7 +230,7 @@ impl CryptographicSpongeVar> for PoseidonSpo Ok(()) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn squeeze_bytes(&mut self, num_bytes: usize) -> Result>, SynthesisError> { let usable_bytes = ((F::MODULUS_BIT_SIZE - 1) / 8) as usize; @@ -246,7 +246,7 @@ impl CryptographicSpongeVar> for PoseidonSpo Ok(bytes) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn squeeze_bits(&mut self, num_bits: usize) -> Result>, SynthesisError> { let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize; @@ -262,7 +262,7 @@ impl CryptographicSpongeVar> for PoseidonSpo Ok(bits) } - #[tracing::instrument(target = "r1cs", skip(self))] + #[tracing::instrument(target = "gr1cs", skip(self))] fn squeeze_field_elements( &mut self, num_elements: usize, @@ -301,7 +301,7 @@ mod tests { use ark_ff::{Field, PrimeField, UniformRand}; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::prelude::*; - use ark_relations::r1cs::ConstraintSystem; + use ark_relations::gr1cs::ConstraintSystem; use ark_relations::*; use ark_std::test_rng; diff --git a/crypto-primitives/src/sponge/poseidon/mod.rs b/crypto-primitives/src/sponge/poseidon/mod.rs index 471c1622..3b40bd21 100644 --- a/crypto-primitives/src/sponge/poseidon/mod.rs +++ b/crypto-primitives/src/sponge/poseidon/mod.rs @@ -9,7 +9,7 @@ use ark_std::any::TypeId; use ark_std::vec::Vec; /// constraints for Poseidon -#[cfg(feature = "r1cs")] +#[cfg(feature = "gr1cs")] pub mod constraints; #[cfg(test)] mod tests; diff --git a/crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs b/crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs new file mode 100644 index 00000000..c2109116 --- /dev/null +++ b/crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs @@ -0,0 +1,400 @@ + +use crate::sponge::constraints::AbsorbGadget; +use crate::sponge::constraints::{CryptographicSpongeVar, SpongeWithGadget}; +use crate::sponge::rescue::{RescueConfig, RescueSponge}; +use crate::sponge::DuplexSpongeMode; +use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError}; +use ark_ff::PrimeField; +use ark_r1cs_std::fields::fp::FpVar; +use ark_r1cs_std::prelude::*; + +use ark_relations::lc; +#[cfg(not(feature = "std"))] +use ark_std::vec::Vec; + +#[derive(Clone)] +/// the gadget for Rescue sponge +/// +/// This implementation of Rescue is entirely from Fractal's implementation in [COS20][cos] +/// with small syntax changes. +/// +/// [cos]: https://eprint.iacr.org/2019/1076 +pub struct RescueSpongeVar { + /// Constraint system + pub cs: ConstraintSystemRef, + + /// Sponge Parameters + pub parameters: RescueConfig, + + // Sponge State + /// The sponge's state + pub state: Vec>, + /// The mode + pub mode: DuplexSpongeMode, +} + +impl SpongeWithGadget for RescueSponge { + type Var = RescueSpongeVar; +} + +impl RescueSpongeVar { + + + fn apply_s_box( + &self, + state: &mut [FpVar], + exponent: &[u64], + alpha: u64, + // round: usize + ) -> Result<(), SynthesisError> { + let cs = state[0].cs(); + + if [alpha] == exponent { + + for state_item in state.iter_mut() { + let new_state_item = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); + match (&state_item,&new_state_item) { + (FpVar::Var(alloc_fp),FpVar::Var(new_alloc_fp)) => { + let _ = cs.enforce_constraint("POW",vec![lc!()+ alloc_fp.variable,lc!()+new_alloc_fp.variable], ); + *state_item = new_state_item; + + } + _ => { + // std::dbg!(round); + *state_item = state_item.pow_by_constant(exponent)?; + } + } + } + + } else { + for state_item in state.iter_mut() { + let new_state_item = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); + // std::dbg!(&state_item); + // std::dbg!(&new_state_item); + match (&state_item,&new_state_item) { + (FpVar::Var(alloc_fp),FpVar::Var(new_alloc_fp)) => { + let _ = cs.enforce_constraint("POW", vec![lc!()+ new_alloc_fp.variable,lc!()+alloc_fp.variable], ); + + }, + _ => { + // std::dbg!(round); + *state_item = state_item.pow_by_constant(exponent)?; + } + } + *state_item = new_state_item; + + } + } + Ok(()) + + } + + fn apply_ark(&self, state: &mut [FpVar], round_key: &Vec) -> Result<(), SynthesisError> { + for (i, state_elem) in state.iter_mut().enumerate() { + *state_elem += round_key[i]; + } + Ok(()) + } + + fn apply_mds(&self, state: &mut [FpVar]) -> Result<(), SynthesisError> { + let mut new_state = Vec::new(); + let zero = FpVar::::zero(); + for i in 0..state.len() { + let mut cur = zero.clone(); + for (j, state_elem) in state.iter().enumerate() { + let term = state_elem * self.parameters.mds[i][j]; + cur += &term; + } + new_state.push(cur); + } + state.clone_from_slice(&new_state[..state.len()]); + Ok(()) + } + + fn permute(&mut self) -> Result<(), SynthesisError> { + let mut state = self.state.clone(); + let alpha_inv: Vec = self.parameters.alpha_inv.to_u64_digits(); + let _ = self.apply_ark(&mut state, &self.parameters.arc[0]); + for (round, round_key) in self.parameters.arc[1..].iter().enumerate() { + if (round % 2) == 0 { + self.apply_s_box(&mut state, &alpha_inv, self.parameters.alpha)?; + } else { + self.apply_s_box(&mut state, &[self.parameters.alpha], self.parameters.alpha)?; + } + let _ = self.apply_mds(&mut state); + let _ = self.apply_ark(&mut state, round_key); + } + self.state = state; + Ok(()) + } + + fn absorb_internal( + &mut self, + mut rate_start_index: usize, + elements: &[FpVar], + ) -> Result<(), SynthesisError> { + let mut remaining_elements = elements; + loop { + // if we can finish in this call + if rate_start_index + remaining_elements.len() <= self.parameters.rate { + for (i, element) in remaining_elements.iter().enumerate() { + self.state[self.parameters.capacity + i + rate_start_index] += element; + } + self.mode = DuplexSpongeMode::Absorbing { + next_absorb_index: rate_start_index + remaining_elements.len(), + }; + + return Ok(()); + } + // otherwise absorb (rate - rate_start_index) elements + let num_elements_absorbed = self.parameters.rate - rate_start_index; + for (i, element) in remaining_elements + .iter() + .enumerate() + .take(num_elements_absorbed) + { + self.state[self.parameters.capacity + i + rate_start_index] += element; + } + self.permute()?; + // the input elements got truncated by num elements absorbed + remaining_elements = &remaining_elements[num_elements_absorbed..]; + rate_start_index = 0; + } + } + + // Squeeze |output| many elements. This does not end in a squeeze + fn squeeze_internal( + &mut self, + mut rate_start_index: usize, + output: &mut [FpVar], + ) -> Result<(), SynthesisError> { + let mut remaining_output = output; + loop { + // if we can finish in this call + if rate_start_index + remaining_output.len() <= self.parameters.rate { + remaining_output.clone_from_slice( + &self.state[self.parameters.capacity + rate_start_index + ..(self.parameters.capacity + remaining_output.len() + rate_start_index)], + ); + self.mode = DuplexSpongeMode::Squeezing { + next_squeeze_index: rate_start_index + remaining_output.len(), + }; + return Ok(()); + } + // otherwise squeeze (rate - rate_start_index) elements + let num_elements_squeezed = self.parameters.rate - rate_start_index; + remaining_output[..num_elements_squeezed].clone_from_slice( + &self.state[self.parameters.capacity + rate_start_index + ..(self.parameters.capacity + num_elements_squeezed + rate_start_index)], + ); + + // Unless we are done with squeezing in this call, permute. + if remaining_output.len() != self.parameters.rate { + self.permute()?; + } + // Repeat with updated output slices and rate start index + remaining_output = &mut remaining_output[num_elements_squeezed..]; + rate_start_index = 0; + } + } +} + +impl CryptographicSpongeVar> for RescueSpongeVar { + type Parameters = RescueConfig; + + fn new(cs: ConstraintSystemRef, parameters: &RescueConfig) -> Self { + let zero = FpVar::::zero(); + let state = vec![zero; parameters.rate + parameters.capacity]; + let mode = DuplexSpongeMode::Absorbing { + next_absorb_index: 0, + }; + + Self { + cs, + parameters: parameters.clone(), + state, + mode, + } + } + + fn cs(&self) -> ConstraintSystemRef { + self.cs.clone() + } + + fn absorb(&mut self, input: &impl AbsorbGadget) -> Result<(), SynthesisError> { + let input = input.to_sponge_field_elements()?; + if input.is_empty() { + return Ok(()); + } + + match self.mode { + DuplexSpongeMode::Absorbing { next_absorb_index } => { + let mut absorb_index = next_absorb_index; + if absorb_index == self.parameters.rate { + self.permute()?; + absorb_index = 0; + } + self.absorb_internal(absorb_index, input.as_slice())?; + } + DuplexSpongeMode::Squeezing { + next_squeeze_index: _, + } => { + self.permute()?; + self.absorb_internal(0, input.as_slice())?; + } + }; + + Ok(()) + } + + fn squeeze_bytes(&mut self, num_bytes: usize) -> Result>, SynthesisError> { + let usable_bytes = ((F::MODULUS_BIT_SIZE - 1) / 8) as usize; + + let num_elements = (num_bytes + usable_bytes - 1) / usable_bytes; + let src_elements = self.squeeze_field_elements(num_elements)?; + + let mut bytes: Vec> = Vec::with_capacity(usable_bytes * num_elements); + for elem in &src_elements { + bytes.extend_from_slice(&elem.to_bytes_le()?[..usable_bytes]); + } + + bytes.truncate(num_bytes); + Ok(bytes) + } + + fn squeeze_bits(&mut self, num_bits: usize) -> Result>, SynthesisError> { + let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize; + + let num_elements = (num_bits + usable_bits - 1) / usable_bits; + let src_elements = self.squeeze_field_elements(num_elements)?; + + let mut bits: Vec> = Vec::with_capacity(usable_bits * num_elements); + for elem in &src_elements { + bits.extend_from_slice(&elem.to_bits_le()?[..usable_bits]); + } + + bits.truncate(num_bits); + Ok(bits) + } + + fn squeeze_field_elements( + &mut self, + num_elements: usize, + ) -> Result>, SynthesisError> { + let zero = FpVar::zero(); + let mut squeezed_elems = vec![zero; num_elements]; + match self.mode { + DuplexSpongeMode::Absorbing { + next_absorb_index: _, + } => { + self.permute()?; + self.squeeze_internal(0, &mut squeezed_elems)?; + } + DuplexSpongeMode::Squeezing { next_squeeze_index } => { + let mut squeeze_index = next_squeeze_index; + if squeeze_index == self.parameters.rate { + self.permute()?; + squeeze_index = 0; + } + self.squeeze_internal(squeeze_index, &mut squeezed_elems)?; + } + }; + + Ok(squeezed_elems) + } +} + +#[cfg(test)] +mod tests { + use crate::sponge::constraints::CryptographicSpongeVar; + use crate::sponge::rescue::gr1cs_constraints::RescueSpongeVar; + use crate::sponge::rescue::rescue_parameters_for_test; + use crate::sponge::rescue::RescueSponge; + use crate::sponge::test::Fr; + use crate::sponge::{CryptographicSponge, FieldBasedCryptographicSponge, FieldElementSize}; + use ark_r1cs_std::alloc::AllocVar; + use ark_r1cs_std::fields::fp::FpVar; + use ark_r1cs_std::uint8::UInt8; + use ark_r1cs_std::GR1CSVar; + use ark_relations::gr1cs::ConstraintSystem; + use ark_ff::{Field, PrimeField, UniformRand}; + + use ark_relations::ns; + use ark_std::test_rng; + + #[test] + fn absorb_test() { + let mut rng = test_rng(); + let cs = ConstraintSystem::new_ref(); + + let absorb1: Vec<_> = (0..256).map(|_| Fr::rand(&mut rng)).collect(); + let absorb1_var: Vec<_> = absorb1 + .iter() + .map(|v| FpVar::new_input(ns!(cs, "absorb1"), || Ok(*v)).unwrap()) + .collect(); + + let absorb2: Vec<_> = (0..8).map(|i| vec![i, i + 1, i + 2]).collect(); + let absorb2_var: Vec<_> = absorb2 + .iter() + .map(|v| UInt8::new_input_vec(ns!(cs, "absorb2"), v).unwrap()) + .collect(); + + let sponge_params = rescue_parameters_for_test(); + + let mut native_sponge = RescueSponge::::new(&sponge_params); + let mut constraint_sponge = RescueSpongeVar::::new(cs.clone(), &sponge_params); + + native_sponge.absorb(&absorb1); + constraint_sponge.absorb(&absorb1_var).unwrap(); + + let squeeze1 = native_sponge.squeeze_native_field_elements(1); + let squeeze2 = constraint_sponge.squeeze_field_elements(1).unwrap(); + + assert_eq!(squeeze2.value().unwrap(), squeeze1); + assert!(cs.is_satisfied().unwrap()); + + native_sponge.absorb(&absorb2); + constraint_sponge.absorb(&absorb2_var).unwrap(); + + let squeeze1 = native_sponge.squeeze_native_field_elements(1); + let squeeze2 = constraint_sponge.squeeze_field_elements(1).unwrap(); + + assert_eq!(squeeze2.value().unwrap(), squeeze1); + assert!(cs.is_satisfied().unwrap()); + } + + #[test] + fn squeeze_with_sizes() { + let squeeze_bits = Fr::MODULUS_BIT_SIZE / 2; + let max_squeeze = Fr::from(2).pow(::BigInt::from(squeeze_bits)); + + let sponge_params = rescue_parameters_for_test(); + let mut native_sponge = RescueSponge::::new(&sponge_params); + + let squeeze = + native_sponge.squeeze_field_elements_with_sizes::(&[FieldElementSize::Truncated( + squeeze_bits as usize, + )])[0]; + assert!(squeeze < max_squeeze); + + let cs = ConstraintSystem::new_ref(); + let mut constraint_sponge = RescueSpongeVar::::new(cs.clone(), &sponge_params); + + let (squeeze, bits) = constraint_sponge + .squeeze_emulated_field_elements_with_sizes::(&[FieldElementSize::Truncated( + squeeze_bits as usize, + )]) + .unwrap(); + let squeeze = &squeeze[0]; + let bits = &bits[0]; + assert!(squeeze.value().unwrap() < max_squeeze); + assert_eq!(bits.len(), squeeze_bits as usize); + + // squeeze full + let (_, bits) = constraint_sponge + .squeeze_emulated_field_elements_with_sizes::(&[FieldElementSize::Full]) + .unwrap(); + let bits = &bits[0]; + assert_eq!(bits.len() as u32, Fr::MODULUS_BIT_SIZE - 1); + } +} diff --git a/crypto-primitives/src/sponge/rescue/grain_lfsr.rs b/crypto-primitives/src/sponge/rescue/grain_lfsr.rs new file mode 100644 index 00000000..544ab009 --- /dev/null +++ b/crypto-primitives/src/sponge/rescue/grain_lfsr.rs @@ -0,0 +1,218 @@ +#![allow(dead_code)] + +use ark_ff::{BigInteger, PrimeField}; +#[cfg(not(feature = "std"))] +use ark_std::vec::Vec; + +pub struct RescueGrainLFSR { + pub prime_num_bits: u64, + + pub state: [bool; 80], + pub head: usize, +} + +#[allow(unused_variables)] +impl RescueGrainLFSR { + pub fn new( + is_sbox_an_inverse: bool, + prime_num_bits: u64, + state_len: u64, + num_rounds: u64, + ) -> Self { + let mut state = [false; 80]; + + // b0, b1 describes the field + state[1] = true; + + // b2, ..., b5 describes the S-BOX + if is_sbox_an_inverse { + state[5] = true; + } else { + state[5] = false; + } + + // b6, ..., b17 are the binary representation of n (prime_num_bits) + { + let mut cur = prime_num_bits; + for i in (6..=17).rev() { + state[i] = cur & 1 == 1; + cur >>= 1; + } + } + + // b18, ..., b29 are the binary representation of t (state_len, rate + capacity) + { + let mut cur = state_len; + for i in (18..=29).rev() { + state[i] = cur & 1 == 1; + cur >>= 1; + } + } + + // b30, ..., b39 are the binary representation of R_F (the number of full rounds) + { + let mut cur = num_rounds; + for i in (30..=39).rev() { + state[i] = cur & 1 == 1; + cur >>= 1; + } + } + + // b40, ..., b49 are the binary representation of R_P (the number of partial rounds) + { + let mut cur = num_rounds; + for i in (40..=49).rev() { + state[i] = cur & 1 == 1; + cur >>= 1; + } + } + + // b50, ..., b79 are set to 1 + for i in 50..=79 { + state[i] = true; + } + + let head = 0; + + let mut res = Self { + prime_num_bits, + state, + head, + }; + res.init(); + res + } + + pub fn get_bits(&mut self, num_bits: usize) -> Vec { + let mut res = Vec::new(); + + for _ in 0..num_bits { + // Obtain the first bit + let mut new_bit = self.update(); + + // Loop until the first bit is true + while new_bit == false { + // Discard the second bit + let _ = self.update(); + // Obtain another first bit + new_bit = self.update(); + } + + // Obtain the second bit + res.push(self.update()); + } + + res + } + + pub fn get_field_elements_rejection_sampling( + &mut self, + num_elems: usize, + ) -> Vec { + assert_eq!(F::MODULUS_BIT_SIZE as u64, self.prime_num_bits); + + let mut res = Vec::new(); + for _ in 0..num_elems { + // Perform rejection sampling + loop { + // Obtain n bits and make it most-significant-bit first + let mut bits = self.get_bits(self.prime_num_bits as usize); + bits.reverse(); + + // Construct the number + let bigint = F::BigInt::from_bits_le(&bits); + + if let Some(f) = F::from_bigint(bigint) { + res.push(f); + break; + } + } + } + + res + } + + pub fn get_field_elements_mod_p(&mut self, num_elems: usize) -> Vec { + assert_eq!(F::MODULUS_BIT_SIZE as u64, self.prime_num_bits); + + let mut res = Vec::new(); + for _ in 0..num_elems { + // Obtain n bits and make it most-significant-bit first + let mut bits = self.get_bits(self.prime_num_bits as usize); + bits.reverse(); + + let bytes = bits + .chunks(8) + .map(|chunk| { + let mut result = 0u8; + for (i, bit) in chunk.iter().enumerate() { + result |= u8::from(*bit) << i + } + result + }) + .collect::>(); + + res.push(F::from_le_bytes_mod_order(&bytes)); + } + + res + } + + #[inline] + fn update(&mut self) -> bool { + let new_bit = self.state[(self.head + 62) % 80] + ^ self.state[(self.head + 51) % 80] + ^ self.state[(self.head + 38) % 80] + ^ self.state[(self.head + 23) % 80] + ^ self.state[(self.head + 13) % 80] + ^ self.state[self.head]; + self.state[self.head] = new_bit; + self.head += 1; + self.head %= 80; + + new_bit + } + + fn init(&mut self) { + for _ in 0..160 { + let _ = self.update(); + } + } +} + +#[cfg(test)] +mod test { + use crate::sponge::rescue::grain_lfsr::RescueGrainLFSR; + use crate::sponge::test::Fr; + use ark_ff::MontFp; + + #[test] + fn test_grain_lfsr_consistency() { + let mut lfsr = RescueGrainLFSR::new(false, 255, 3, 39); + + assert_eq!( + lfsr.get_field_elements_rejection_sampling::(1)[0], + MontFp!( + "27117311055620256798560880810000042840428971800021819916023577129547249660720" + ) + ); + assert_eq!( + lfsr.get_field_elements_rejection_sampling::(1)[0], + MontFp!( + "51641662388546346858987925410984003801092143452466182801674685248597955169158" + ) + ); + assert_eq!( + lfsr.get_field_elements_mod_p::(1)[0], + MontFp!( + "30468495022634911716522728179277518871747767531215914044579216845399211650580" + ) + ); + assert_eq!( + lfsr.get_field_elements_mod_p::(1)[0], + MontFp!( + "17250718238509906485015112994867732544602358855445377986727968022920517907825" + ) + ); + } +} diff --git a/crypto-primitives/src/sponge/rescue/mod.rs b/crypto-primitives/src/sponge/rescue/mod.rs new file mode 100644 index 00000000..fd1c6147 --- /dev/null +++ b/crypto-primitives/src/sponge/rescue/mod.rs @@ -0,0 +1,396 @@ +use crate::sponge::{ + field_cast, squeeze_field_elements_with_sizes_default_impl, Absorb, CryptographicSponge, + DuplexSpongeMode, FieldBasedCryptographicSponge, FieldElementSize, SpongeExt, +}; +use ark_ff::{BigInteger, PrimeField}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use ark_std::any::TypeId; + +#[cfg(not(feature = "std"))] +use ark_std::vec::Vec; + +/// constraints for Rescue +pub mod gr1cs_constraints; + +#[cfg(test)] +mod tests; +#[cfg(test)] +pub(crate) use tests::rescue_parameters_for_test; + +/// default parameters traits for Rescue +pub mod traits; +use num_bigint::BigUint; +pub use traits::*; + +mod grain_lfsr; + +/// Config and RNG used +#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] +pub struct RescueConfig { + /// Number of rounds + /// specified by parameter `N` in the [paper](https://eprint.iacr.org/2020/1143.pdf) + pub rounds: usize, + /// Exponent used in S-boxes. + pub alpha: u64, + /// Exponent used in S-boxes. + pub alpha_inv: BigUint, + /// Additive Round constants. + /// They are indexed by `ark[round_num][state_element_index]` + /// specified by parameter `round_constants` in the [paper](https://eprint.iacr.org/2020/1143.pdf) in a flattened array. + pub arc: Vec>, + /// Maximally Distance Separating (MDS) Matrix. + pub mds: Vec>, + /// The rate (in terms of number of field elements). + pub rate: usize, + /// The capacity (in terms of number of field elements). + pub capacity: usize, +} + +#[derive(Clone)] +/// A duplex sponge based using the Rescue permutation. +pub struct RescueSponge { + /// Sponge Config + pub parameters: RescueConfig, + + // Sponge State + /// Current sponge's state (current elements in the permutation block) + pub state: Vec, + /// Current mode (whether its absorbing or squeezing) + pub mode: DuplexSpongeMode, +} + +impl RescueSponge { + /// Apply the S-box to the state. the exponent can be `alpha` or `alpha_inv` depending on the position of the s-box in the permutation. + fn apply_s_box(&self, state: &mut [F], exponent: &[u64]) { + for elem in state { + *elem = elem.pow(exponent); + } + } + + /// Apply the additive round constants to the state. Depending on the round number i, the round key is fetched from `RescueConfig.arc[i]` + /// TODO: Change this to get the round number instead of the round key + fn apply_arc(&self, state: &mut [F], round_key: &Vec) { + for (i, state_elem) in state.iter_mut().enumerate() { + state_elem.add_assign(&round_key[i]); + } + } + + /// Multiply the state with the MDS matrix. The MDS matrix is stored in `RescueConfig.mds` + fn apply_mds(&self, state: &mut [F]) { + let mut new_state = Vec::new(); + for i in 0..state.len() { + let mut cur = F::zero(); + for (j, state_elem) in state.iter().enumerate() { + let term = state_elem.mul(&self.parameters.mds[i][j]); + cur.add_assign(&term); + } + new_state.push(cur); + } + state.clone_from_slice(&new_state[..state.len()]) + } + + /// The permutation function of the Rescue Sponge. It corresponds to the Algorithm 3 in the [paper](https://eprint.iacr.org/2020/1143.pdf) + fn permute(&mut self) { + let mut state = self.state.clone(); + assert_eq!(self.parameters.rounds * 2 + 1, self.parameters.arc.len()); + // TODO: Check this arc[0] + self.apply_arc(&mut state, &self.parameters.arc[0]); + for (round, round_key) in self.parameters.arc[1..].iter().enumerate() { + if (round % 2) == 0 { + self.apply_s_box(&mut state, &self.parameters.alpha_inv.to_u64_digits()); + } else { + self.apply_s_box(&mut state, &[self.parameters.alpha]); + } + self.apply_mds(&mut state); + self.apply_arc(&mut state, round_key); + } + + self.state = state; + } + + // Absorbs everything in elements, this does not end in an absorbtion. + fn absorb_internal(&mut self, mut rate_start_index: usize, elements: &[F]) { + let mut remaining_elements = elements; + + loop { + // if we can finish in this call + if rate_start_index + remaining_elements.len() <= self.parameters.rate { + for (i, element) in remaining_elements.iter().enumerate() { + self.state[self.parameters.capacity + i + rate_start_index] += element; + } + self.mode = DuplexSpongeMode::Absorbing { + next_absorb_index: rate_start_index + remaining_elements.len(), + }; + return; + } + // otherwise absorb (rate - rate_start_index) elements + let num_elements_absorbed = self.parameters.rate - rate_start_index; + for (i, element) in remaining_elements + .iter() + .enumerate() + .take(num_elements_absorbed) + { + self.state[self.parameters.capacity + i + rate_start_index] += element; + } + self.permute(); + // the input elements got truncated by num elements absorbed + remaining_elements = &remaining_elements[num_elements_absorbed..]; + rate_start_index = 0; + } + } + + // Squeeze |output| many elements. This does not end in a squeeze + fn squeeze_internal(&mut self, mut rate_start_index: usize, output: &mut [F]) { + let mut output_remaining = output; + loop { + // if we can finish in this call + if rate_start_index + output_remaining.len() <= self.parameters.rate { + output_remaining.clone_from_slice( + &self.state[self.parameters.capacity + rate_start_index + ..(self.parameters.capacity + output_remaining.len() + rate_start_index)], + ); + self.mode = DuplexSpongeMode::Squeezing { + next_squeeze_index: rate_start_index + output_remaining.len(), + }; + return; + } + // otherwise squeeze (rate - rate_start_index) elements + let num_elements_squeezed = self.parameters.rate - rate_start_index; + output_remaining[..num_elements_squeezed].clone_from_slice( + &self.state[self.parameters.capacity + rate_start_index + ..(self.parameters.capacity + num_elements_squeezed + rate_start_index)], + ); + + // Unless we are done with squeezing in this call, permute. + if output_remaining.len() != self.parameters.rate { + self.permute(); + } + // Repeat with updated output slices + output_remaining = &mut output_remaining[num_elements_squeezed..]; + rate_start_index = 0; + } + } +} + +impl RescueConfig { + /// Initialize the parameter for Rescue Sponge. + pub fn new( + rounds: usize, + alpha: u64, + alpha_inv: BigUint, + mds: Vec>, + arc: Vec>, + rate: usize, + capacity: usize, + ) -> Self { + assert_eq!(arc.len(), 2 * rounds + 1); + for item in &arc { + assert_eq!(item.len(), rate + capacity); + } + assert_eq!(mds.len(), rate + capacity); + for item in &mds { + assert_eq!(item.len(), rate + capacity); + } + Self { + rounds, + alpha, + alpha_inv, + mds, + arc, + rate, + capacity, + } + } +} + +impl CryptographicSponge for RescueSponge { + type Config = RescueConfig; + + fn new(parameters: &Self::Config) -> Self { + // The initial state of the sponge is all zeros + let state = vec![F::zero(); parameters.rate + parameters.capacity]; + + // The mode of the sponge is initially set to Absorbing the first element + // TODO: index of the field or byte? + let mode = DuplexSpongeMode::Absorbing { + next_absorb_index: 0, + }; + + Self { + parameters: parameters.clone(), + state, + mode, + } + } + + fn absorb(&mut self, input: &impl Absorb) { + let elems: Vec = input.to_sponge_field_elements_as_vec::(); + if elems.is_empty() { + return; + } + match self.mode { + DuplexSpongeMode::Absorbing { next_absorb_index } => { + let mut absorb_index = next_absorb_index; + if absorb_index == self.parameters.rate { + self.permute(); + absorb_index = 0; + } + + self.absorb_internal(absorb_index, elems.as_slice()); + } + DuplexSpongeMode::Squeezing { + next_squeeze_index: _, + } => { + self.permute(); + self.absorb_internal(0, elems.as_slice()); + } + }; + } + + fn squeeze_bytes(&mut self, num_bytes: usize) -> Vec { + let usable_bytes = ((F::MODULUS_BIT_SIZE - 1) / 8) as usize; + + let num_elements = (num_bytes + usable_bytes - 1) / usable_bytes; + let src_elements = self.squeeze_native_field_elements(num_elements); + + let mut bytes: Vec = Vec::with_capacity(usable_bytes * num_elements); + for elem in &src_elements { + let elem_bytes = elem.into_bigint().to_bytes_le(); + bytes.extend_from_slice(&elem_bytes[..usable_bytes]); + } + + bytes.truncate(num_bytes); + bytes + } + + fn squeeze_bits(&mut self, num_bits: usize) -> Vec { + let usable_bits = (F::MODULUS_BIT_SIZE - 1) as usize; + + let num_elements = (num_bits + usable_bits - 1) / usable_bits; + let src_elements = self.squeeze_native_field_elements(num_elements); + + let mut bits: Vec = Vec::with_capacity(usable_bits * num_elements); + for elem in &src_elements { + let elem_bits = elem.into_bigint().to_bits_le(); + bits.extend_from_slice(&elem_bits[..usable_bits]); + } + + bits.truncate(num_bits); + bits + } + + fn squeeze_field_elements_with_sizes( + &mut self, + sizes: &[FieldElementSize], + ) -> Vec { + if F::characteristic() == F2::characteristic() { + // native case + let mut buf = Vec::with_capacity(sizes.len()); + field_cast( + &self.squeeze_native_field_elements_with_sizes(sizes), + &mut buf, + ) + .unwrap(); + buf + } else { + squeeze_field_elements_with_sizes_default_impl(self, sizes) + } + } + + fn squeeze_field_elements(&mut self, num_elements: usize) -> Vec { + if TypeId::of::() == TypeId::of::() { + let result = self.squeeze_native_field_elements(num_elements); + let mut cast = Vec::with_capacity(result.len()); + field_cast(&result, &mut cast).unwrap(); + cast + } else { + self.squeeze_field_elements_with_sizes::( + vec![FieldElementSize::Full; num_elements].as_slice(), + ) + } + } +} + +impl FieldBasedCryptographicSponge for RescueSponge { + fn squeeze_native_field_elements(&mut self, num_elements: usize) -> Vec { + let mut squeezed_elems = vec![F::zero(); num_elements]; + match self.mode { + DuplexSpongeMode::Absorbing { + next_absorb_index: _, + } => { + self.permute(); + self.squeeze_internal(0, &mut squeezed_elems); + } + DuplexSpongeMode::Squeezing { next_squeeze_index } => { + let mut squeeze_index = next_squeeze_index; + if squeeze_index == self.parameters.rate { + self.permute(); + squeeze_index = 0; + } + self.squeeze_internal(squeeze_index, &mut squeezed_elems); + } + }; + + squeezed_elems + } +} + +#[derive(Clone)] +/// Stores the state of a Rescue Sponge. Does not store any parameter. +pub struct RescueSpongeState { + state: Vec, + mode: DuplexSpongeMode, +} + +impl SpongeExt for RescueSponge { + type State = RescueSpongeState; + + fn from_state(state: Self::State, params: &Self::Config) -> Self { + let mut sponge = Self::new(params); + sponge.mode = state.mode; + sponge.state = state.state; + sponge + } + + fn into_state(self) -> Self::State { + Self::State { + state: self.state, + mode: self.mode, + } + } +} + +// #[cfg(test)] +// mod test { +// use crate::sponge::poseidon::PoseidonDefaultConfigField; +// use crate::sponge::test::Fr; +// use crate::sponge::{ +// poseidon::PoseidonSponge, CryptographicSponge, FieldBasedCryptographicSponge, +// }; +// use ark_ff::MontFp; + +// #[test] +// fn test_poseidon_sponge_consistency() { +// let sponge_param = Fr::get_default_poseidon_parameters(2, false).unwrap(); + +// let mut sponge = PoseidonSponge::::new(&sponge_param); +// sponge.absorb(&vec![Fr::from(0u8), Fr::from(1u8), Fr::from(2u8)]); +// let res = sponge.squeeze_native_field_elements(3); +// assert_eq!( +// res[0], +// MontFp!( +// "40442793463571304028337753002242186710310163897048962278675457993207843616876" +// ) +// ); +// assert_eq!( +// res[1], +// MontFp!("2664374461699898000291153145224099287711224021716202960480903840045233645301") +// ); +// assert_eq!( +// res[2], +// MontFp!( +// "50191078828066923662070228256530692951801504043422844038937334196346054068797" +// ) +// ); +// } +// } diff --git a/crypto-primitives/src/sponge/rescue/tests.rs b/crypto-primitives/src/sponge/rescue/tests.rs new file mode 100644 index 00000000..044e00d7 --- /dev/null +++ b/crypto-primitives/src/sponge/rescue/tests.rs @@ -0,0 +1,729 @@ +use core::str::FromStr; + +use crate::sponge::rescue::{RescueConfig, RescueSponge}; +use crate::sponge::test::Fr; +use crate::sponge::{Absorb, AbsorbWithLength, CryptographicSponge, FieldBasedCryptographicSponge}; +use ark_ff::{One, PrimeField, UniformRand}; +use ark_std::test_rng; +use num_bigint::BigUint; + +fn assert_different_encodings(a: &A, b: &A) { + let bytes1 = a.to_sponge_bytes_as_vec(); + let bytes2 = b.to_sponge_bytes_as_vec(); + assert_ne!(bytes1, bytes2); + + let sponge_param = rescue_parameters_for_test(); + let mut sponge1 = RescueSponge::::new(&sponge_param); + let mut sponge2 = RescueSponge::::new(&sponge_param); + + sponge1.absorb(&a); + sponge2.absorb(&b); + + assert_ne!( + sponge1.squeeze_native_field_elements(3), + sponge2.squeeze_native_field_elements(3) + ); +} + +#[test] +fn single_field_element() { + let mut rng = test_rng(); + let elem1 = Fr::rand(&mut rng); + let elem2 = elem1 + Fr::one(); + + assert_different_encodings::(&elem1, &elem2) +} + +#[test] +fn list_with_constant_size_element() { + let mut rng = test_rng(); + let lst1: Vec<_> = (0..1024 * 8).map(|_| Fr::rand(&mut rng)).collect(); + let mut lst2 = lst1.to_vec(); + lst2[3] += Fr::one(); + + assert_different_encodings::(&lst1, &lst2) +} + +struct VariableSizeList(Vec); + +impl Absorb for VariableSizeList { + fn to_sponge_bytes(&self, dest: &mut Vec) { + self.0.to_sponge_bytes_with_length(dest) + } + + fn to_sponge_field_elements(&self, dest: &mut Vec) { + self.0.to_sponge_field_elements_with_length(dest) + } +} + +#[test] +fn list_with_nonconstant_size_element() { + let lst1 = vec![ + VariableSizeList(vec![1u8, 2, 3, 4]), + VariableSizeList(vec![5, 6]), + ]; + let lst2 = vec![ + VariableSizeList(vec![1u8, 2]), + VariableSizeList(vec![3, 4, 5, 6]), + ]; + + assert_different_encodings::(&lst1, &lst2); +} + +#[test] +fn test_squeeze_cast_native() { + let mut rng = test_rng(); + let sponge_param = rescue_parameters_for_test(); + let elem = Fr::rand(&mut rng); + let mut sponge1 = RescueSponge::::new(&sponge_param); + sponge1.absorb(&elem); + let mut sponge2 = sponge1.clone(); + + // those two should return same result + let squeezed1 = sponge1.squeeze_native_field_elements(5); + let squeezed2 = sponge2.squeeze_field_elements::(5); + + assert_eq!(squeezed1, squeezed2); +} + +#[test] +fn test_macros() { + let sponge_param = rescue_parameters_for_test(); + let mut sponge1 = RescueSponge::::new(&sponge_param); + sponge1.absorb(&vec![0, 0, 0]); + let _ = sponge1.squeeze_native_field_elements(3); + // assert_eq!(actual, expected); +} + +/// Generate default parameters (bls381-fr-only) for alpha = 17, state-size = 8 +pub(crate) fn rescue_parameters_for_test() -> RescueConfig { + let alpha: u64 = 5; + let alpha_inv: BigUint = BigUint::from_str( + "20974350070050476191779096203274386335076221000211055129041463479975432473805", + ) + .unwrap(); + let mds = vec![ + vec![ + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658699938581066864", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658699938534124913", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658699922104442063", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658694270581781713", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str("137200").map_err(|_| ()).unwrap(), + F::from_str("54762351").map_err(|_| ()).unwrap(), + F::from_str("19167800400").map_err(|_| ()).unwrap(), + F::from_str("6593435097550").map_err(|_| ()).unwrap(), + ], + vec![ + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658699938581164563", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658699938573341713", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658699935841949364", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "52435875175126190479447740508185965837690552500527637822603658698996613844913", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str("400").map_err(|_| ()).unwrap(), + F::from_str("140050").map_err(|_| ()).unwrap(), + F::from_str("48177200").map_err(|_| ()).unwrap(), + F::from_str("16531644851").map_err(|_| ()).unwrap(), + ], + ]; + + let arc = vec![ + vec![ + F::from_str( + "23134431890904997735913685390433273947519177060544011867815065124418348995661", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "7910743581020883359489900822814213105822551758045258908574127548576902234202", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "6452335108146897903818881932868089947456740590166061243393158685187431809297", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "864592593827916191968939823230510547087468030011538620003456937932684270153", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "38559831148991359569240421320742457813901373970667612903096765001678689742869", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "44432094719863142927213238093899283700039162038776502993701830158231473502718", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "13786878310315045269120166277183380710599519606157001198417893850005860761477", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "17036162502882675914728275738142065498870974756580444696024180584972335393891", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "33297391939828784001334305802801790593075215229341062678759834559352791736927", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "30500234470117650473907563119990479857361330029198334465374149341676986657115", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "28368430002799198204829257649919634676282026294040173648357765445674005961616", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "9971774186674696614989363797869882469420353008371920226950903037350505417985", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "38139940790606785825103193122238735657582566078114455777468513830487946069923", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "18494333247252274673841361720222549391212096862516923705801761369032339310465", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "39473154482456623768629668349330022458952017097397018586008411120523622633522", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "49285468826209236211279126413673418598127797981942143090059666672629931469385", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "37573115437821831291655432604342578198375078311237242116810739862690145869225", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "27159986956208459140740586738884801802553721748425801853018806317642115259465", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "50214917776783317494180761535986162125563373683868209887890350167269467512946", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "33192867848214168029937060315398544504185295780147134497700076703607952805601", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "50547084830917374624389766622731065576522729673796501202951652168746034262368", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "45100620163299107975959845063844422497694960652741628584970040113210087450662", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "28385120759308049649771453408964811097622465677204481653130542380799307518408", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "35505667235096341555371720396459529907006829254583697277239853917493427123171", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "16437023531659726503682820269358772433184823533333464461469690236822611246932", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "49360243277754004678870001664997850734809212162384644335519685096097001288746", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "8366523254506253216955925296723301364165909408966688192695903971021249968759", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "32459638038196976591500542123818841546669374539590905536922780381223051269547", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "22599560612315772755286575091483116315925260320221561394233776132305161190561", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "16229934200422104594884143900568445503380871501895946009917550290753020752637", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "17517715034137249648481695275508773137979656298150763634847149919185663637655", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "45947279115715765148360788762909806671057420057351947155669138664467561798989", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "38229297807694040917955834901740313151512726422553249211118784759282147254077", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "19221546762665803708415808219454804973762879918238939441381811045896992381109", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "33231993603873329070501348145497728179419527307416430409856815932181772452630", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "44458989315723037569515354400025898188417538412399056946002281608928012076586", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "24097312182414801078940320939859383216367533770388304058972565863202612417326", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "34256182992584397437238816392424956796177998428482016693069842948650455465667", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "27060035464776105302994958363141504784786371731529349414072592535017130374008", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "17415618923957471534182927609934477683351352413272869403402000253948609094158", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "52060491319769018565163753644800488203563135506472497361838613747294343804114", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "1576362207015741288206059930042566539467434543957819902177550750073890852683", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "8253285684584554153849658552191085295583616802943045548686466429839116309878", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "15228514972361056807058151246098278735034513446245359457360228365631138432464", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "38783524586591753822986895661611634222017618368881437223506280603887659991356", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "22924959878025315031997085972756214001369606050285016376071539202766714623098", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "38950764297104469352344857946933662562545322621139995330167708101102044854910", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "11582888283975802643911017125775178169823051538957372067698650122726375950434", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "2298059043453100803649451299470643637099839499417037430896288122564116673326", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "47452596181551524646344358930874945080161659084551765779147813564221166652068", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "24182618861502016111021387835225265356539367730170595823767549536597589758279", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "14893912374919937388411364573314859358172657326695138742923676384357192372360", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "29398955694234023746472399069867629004542497600023389447384583977723258550192", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "36431673144691658691089220672109647461388222858311362067310271835971778148239", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "36492546966674475841438383178903363293964948716421208618060366101436800890790", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "39826799880794424638601874310358734694596460435322030277945017973910646589658", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "36662659413289416298119595844374289415379142322557068765425566585291305461011", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "38017535128209347092713795357871139666671551695819603361759727956851537514709", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "25434598699479962479879799356660079088973594621334634094152711756591035511679", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "33336898409062469195367067121198433779512635331177938007459412699788883108767", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "36058492436047198232978210456456061345170502778325117411208214452676002954201", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "14929481097395660251041965124240362591858660791456046253123033940975701514456", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "46289456091709068352930110828228678138660509736781390773985243886583143161896", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "14111091112977253742344847253086777239100006548059301114340049030467157387521", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "23508471880487400547770156512200772032889406124325897152916765048940153794095", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "16427729880783669957687779378358330473153574875195990658467800363160755677791", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "40156212882518721479460476494171767350034540523507037311923208389487152164489", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "26466836315288637608098985482060993155004017219176998749277566727915735967085", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "12888991686625632077905083939301155235848796738397906807998959514789614307101", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "6784648945900955205375833568502720684047995011038533579314932408073600302438", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "44283955455419102825730907918077389640930999889828224092875982380225907905576", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "21577906067866213753420832310759166345133214697458479927528550794777093745604", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "38676501821726372170081401661551268994693205369401304895157734309488019380911", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "18529238452898077491659062501197031745896551150529843021252022108041840991725", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "39772233475672473946716838776583251658997392411594037169310522755188417064472", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "48671926799613401149453947988763058951611718216954721361239302424336671881515", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "26061735084460790107366459209731985475376433843933274332541132225962092927733", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "24476140360704277298499598001474042644853190438756563291732720884448772397090", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "35748587835271739316324970945389055874118783613333018094991998493311506731782", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "47796681825820555809507630731803833582122742147864710760222058561602842001598", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "40129439376092624311792893362370068647875773785715766199288734633835269388506", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "22953237491934857847613812618498396296702277164511710957864161394836877126161", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "29883326359097154867527259575122302865251616498628736645388175015904851526169", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "16072876630565035721133423676805583416603803842527477499864696244977108270962", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "24433700016212560423407666099058783317053813403174801115287910358608146647763", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "45621659799852625322132052822408291445398292320558577340143231454608533229003", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "46536854208059093798042581691627728318294548204429580171491758231887086308112", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "44290182871662828030169493647139274231335308414589340572678350270417540283009", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "24250445856569954871622245222941720285145845445950474905864907057534343371457", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "25464299025380640073894563298622770863524901688551682692256088582694681257991", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "48318976335409296081239636812736844416642798055771900654762783556487073695991", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "27416530804116379123268279724889870598678372756104891540114066426635076293490", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "199228435670075738810018840314890086674908720274885080714863258792386713132", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "5409167973407743302372619466704081038889320188478946053340045998738973947167", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "13434167199395645551742078879595157181938211296502254602943139432040945799876", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "38812643263458464757761860102011279525010950636150476516702289987662118941842", + ) + .map_err(|_| ()) + .unwrap(), + ], + vec![ + F::from_str( + "18052247500214455977292949825560594271643829386764412343087015646067353331355", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "68369435126047993922545267004639203490461725090813907915976375458289016380", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "2888545834527802263243399767681989249863878258231930802647884036794912638290", + ) + .map_err(|_| ()) + .unwrap(), + F::from_str( + "32483396880170305854478259671129578112226318950991647664509323211693485555524", + ) + .map_err(|_| ()) + .unwrap(), + ], + ]; + + let rounds = 12; + let capacity = 1; + let rate = 3; + RescueConfig { + rounds, + alpha, + alpha_inv, + arc, + mds, + rate, + capacity, + } +} diff --git a/crypto-primitives/src/sponge/rescue/traits.rs b/crypto-primitives/src/sponge/rescue/traits.rs new file mode 100644 index 00000000..05dc7cc2 --- /dev/null +++ b/crypto-primitives/src/sponge/rescue/traits.rs @@ -0,0 +1,351 @@ +use crate::sponge::rescue::grain_lfsr::RescueGrainLFSR; +use crate::sponge::rescue::RescueConfig; + +use ark_ff::{Field, Fp, FpConfig, PrimeField}; +#[cfg(not(feature = "std"))] +use ark_std::vec::Vec; + +/// An entry in the default Rescue parameters +pub struct RescueDefaultConfigEntry { + /// The rate (in terms of number of field elements). + pub rate: usize, + /// Exponent used in S-boxes. + pub alpha: u64, + /// Number of rounds + pub rounds: usize, + + pub skip_matrices: usize, +} + +impl RescueDefaultConfigEntry { + /// Create an entry in `RescueDefaultConfig`. + pub const fn new( + rate: usize, + alpha: u64, + rounds: usize, + skip_matrices: usize, + ) -> Self { + Self { + rate, + alpha, + rounds, + skip_matrices, + } + } +} + +/// A trait for default Rescue parameters associated with a prime field +pub trait RescueDefaultConfig: FpConfig { + /// An array of the parameters optimized for constraints + /// (rate, alpha, full_rounds, partial_rounds, skip_matrices) + /// for rate = 2, 3, 4, 5, 6, 7, 8 + /// + /// Here, `skip_matrices` denote how many matrices to skip before + /// finding one that satisfy all the requirements. + const PARAMS_OPT_FOR_CONSTRAINTS: [RescueDefaultConfigEntry; 1]; + + /// An array of the parameters optimized for weights + /// (rate, alpha, full_rounds, partial_rounds, skip_matrices) + /// for rate = 2, 3, 4, 5, 6, 7, 8 + const PARAMS_OPT_FOR_WEIGHTS: [RescueDefaultConfigEntry; 1]; +} + +/// A field with Rescue parameters associated +pub trait RescueDefaultConfigField: PrimeField { + /// Obtain the default Rescue parameters for this rate and for this prime field, + /// with a specific optimization goal. + fn get_default_rescue_parameters( + rate: usize, + optimized_for_weights: bool, + ) -> Option>; +} + +/// Internal function that uses the `RescueDefaultConfig` to compute the Rescue parameters. +pub fn get_default_rescue_parameters_internal, const N: usize>( + rate: usize, + optimized_for_weights: bool, +) -> Option>> { + let params_set = if !optimized_for_weights { + P::PARAMS_OPT_FOR_CONSTRAINTS + } else { + P::PARAMS_OPT_FOR_WEIGHTS + }; + + for param in params_set.iter() { + if param.rate == rate { + let (arc, mds) = find_rescue_ark_and_mds::>( + Fp::::MODULUS_BIT_SIZE as u64, + rate, + param.rounds as u64, + param.skip_matrices as u64, + ); + + return Some(RescueConfig { + rounds: param.rounds, + alpha: param.alpha, + alpha_inv: Fp::::inverse(&Fp::::from(param.alpha)).unwrap().into(), + arc, + mds, + rate: param.rate, + capacity: 1, + }); + } + } + + None +} + +/// Internal function that computes the ark and mds from the Rescue Grain LFSR. +pub fn find_rescue_ark_and_mds( + prime_bits: u64, + rate: usize, + rounds: u64, + skip_matrices: u64, +) -> (Vec>, Vec>) { + let mut lfsr = RescueGrainLFSR::new( + false, + prime_bits, + (rate + 1) as u64, + rounds, + ); + + let mut ark = Vec::>::with_capacity(rounds as usize); + for _ in 0..rounds { + ark.push(lfsr.get_field_elements_rejection_sampling(rate + 1)); + } + + let mut mds = Vec::>::with_capacity(rate + 1); + mds.resize(rate + 1, vec![F::zero(); rate + 1]); + for _ in 0..skip_matrices { + let _ = lfsr.get_field_elements_mod_p::(2 * (rate + 1)); + } + + // a qualifying matrix must satisfy the following requirements + // - there is no duplication among the elements in x or y + // - there is no i and j such that x[i] + y[j] = p + // - the resultant MDS passes all the three tests + + let xs = lfsr.get_field_elements_mod_p::(rate + 1); + let ys = lfsr.get_field_elements_mod_p::(rate + 1); + + for i in 0..(rate + 1) { + for j in 0..(rate + 1) { + mds[i][j] = (xs[i] + &ys[j]).inverse().unwrap(); + } + } + + (ark, mds) +} + +impl> RescueDefaultConfigField for Fp { + fn get_default_rescue_parameters( + rate: usize, + optimized_for_weights: bool, + ) -> Option> { + get_default_rescue_parameters_internal::(rate, optimized_for_weights) + } +} + +// #[cfg(test)] +// mod test { +// use crate::sponge::rescue::RescueDefaultConfigField; +// use crate::sponge::test::*; +// use ark_ff::MontFp; + +// #[test] +// fn bls12_381_fr_rescue_default_parameters_test() { +// // constraints +// let constraints_rate_2 = Fr::get_default_rescue_parameters(2, false).unwrap(); +// assert_eq!( +// constraints_rate_2.ark[0][0], +// MontFp!( +// "27117311055620256798560880810000042840428971800021819916023577129547249660720" +// ) +// ); +// assert_eq!( +// constraints_rate_2.mds[0][0], +// MontFp!( +// "26017457457808754696901916760153646963713419596921330311675236858336250747575" +// ) +// ); + +// let constraints_rate_3 = Fr::get_default_rescue_parameters(3, false).unwrap(); +// assert_eq!( +// constraints_rate_3.ark[0][0], +// MontFp!( +// "11865901593870436687704696210307853465124332568266803587887584059192277437537" +// ) +// ); +// assert_eq!( +// constraints_rate_3.mds[0][0], +// MontFp!( +// "18791275321793747281053101601584820964683215017313972132092847596434094368732" +// ) +// ); + +// let constraints_rate_4 = Fr::get_default_rescue_parameters(4, false).unwrap(); +// assert_eq!( +// constraints_rate_4.ark[0][0], +// MontFp!( +// "41775194144383840477168997387904574072980173775424253289429546852163474914621" +// ) +// ); +// assert_eq!( +// constraints_rate_4.mds[0][0], +// MontFp!( +// "42906651709148432559075674119637355642263148226238482628104108168707874713729" +// ) +// ); + +// let constraints_rate_5 = Fr::get_default_rescue_parameters(5, false).unwrap(); +// assert_eq!( +// constraints_rate_5.ark[0][0], +// MontFp!( +// "24877380261526996562448766783081897666376381975344509826094208368479247894723" +// ) +// ); +// assert_eq!( +// constraints_rate_5.mds[0][0], +// MontFp!( +// "30022080821787948421423927053079656488514459012053372877891553084525866347732" +// ) +// ); + +// let constraints_rate_6 = Fr::get_default_rescue_parameters(6, false).unwrap(); +// assert_eq!( +// constraints_rate_6.ark[0][0], +// MontFp!( +// "37928506567864057383105673253383925733025682403141583234734361541053005808936" +// ) +// ); +// assert_eq!( +// constraints_rate_6.mds[0][0], +// MontFp!( +// "49124738641420159156404016903087065194698370461819821829905285681776084204443" +// ) +// ); + +// let constraints_rate_7 = Fr::get_default_rescue_parameters(7, false).unwrap(); +// assert_eq!( +// constraints_rate_7.ark[0][0], +// MontFp!( +// "37848764121158464546907147011864524711588624175161409526679215525602690343051" +// ) +// ); +// assert_eq!( +// constraints_rate_7.mds[0][0], +// MontFp!( +// "28113878661515342855868752866874334649815072505130059513989633785080391114646" +// ) +// ); + +// let constraints_rate_8 = Fr::get_default_rescue_parameters(8, false).unwrap(); +// assert_eq!( +// constraints_rate_8.ark[0][0], +// MontFp!( +// "51456871630395278065627483917901523970718884366549119139144234240744684354360" +// ) +// ); +// assert_eq!( +// constraints_rate_8.mds[0][0], +// MontFp!( +// "12929023787467701044434927689422385731071756681420195282613396560814280256210" +// ) +// ); + +// // weights +// let weights_rate_2 = Fr::get_default_rescue_parameters(2, true).unwrap(); +// assert_eq!( +// weights_rate_2.ark[0][0], +// MontFp!( +// "25126470399169474618535500283750950727260324358529540538588217772729895991183" +// ) +// ); +// assert_eq!( +// weights_rate_2.mds[0][0], +// MontFp!( +// "46350838805835525240431215868760423854112287760212339623795708191499274188615" +// ) +// ); + +// let weights_rate_3 = Fr::get_default_rescue_parameters(3, true).unwrap(); +// assert_eq!( +// weights_rate_3.ark[0][0], +// MontFp!( +// "16345358380711600255519479157621098002794924491287389755192263320486827897573" +// ) +// ); +// assert_eq!( +// weights_rate_3.mds[0][0], +// MontFp!( +// "37432344439659887296708509941462699942272362339508052702346957525719991245918" +// ) +// ); + +// let weights_rate_4 = Fr::get_default_rescue_parameters(4, true).unwrap(); +// assert_eq!( +// weights_rate_4.ark[0][0], +// MontFp!("2997721997773001075802235431463112417440167809433966871891875582435098138600") +// ); +// assert_eq!( +// weights_rate_4.mds[0][0], +// MontFp!( +// "43959024692079347032841256941012668338943730711936867712802582656046301966186" +// ) +// ); + +// let weights_rate_5 = Fr::get_default_rescue_parameters(5, true).unwrap(); +// assert_eq!( +// weights_rate_5.ark[0][0], +// MontFp!( +// "28142027771717376151411984909531650866105717069245696861966432993496676054077" +// ) +// ); +// assert_eq!( +// weights_rate_5.mds[0][0], +// MontFp!( +// "13157425078305676755394500322568002504776463228389342308130514165393397413991" +// ) +// ); + +// let weights_rate_6 = Fr::get_default_rescue_parameters(6, true).unwrap(); +// assert_eq!( +// weights_rate_6.ark[0][0], +// MontFp!("7417004907071346600696060525974582183666365156576759507353305331252133694222") +// ); +// assert_eq!( +// weights_rate_6.mds[0][0], +// MontFp!( +// "51393878771453405560681338747290999206747890655420330824736778052231938173954" +// ) +// ); + +// let weights_rate_7 = Fr::get_default_rescue_parameters(7, true).unwrap(); +// assert_eq!( +// weights_rate_7.ark[0][0], +// MontFp!( +// "47093173418416013663709314805327945458844779999893881721688570889452680883650" +// ) +// ); +// assert_eq!( +// weights_rate_7.mds[0][0], +// MontFp!( +// "51455917624412053400160569105425532358410121118308957353565646758865245830775" +// ) +// ); + +// let weights_rate_8 = Fr::get_default_rescue_parameters(8, true).unwrap(); +// assert_eq!( +// weights_rate_8.ark[0][0], +// MontFp!( +// "16478680729975035007348178961232525927424769683353433314299437589237598655079" +// ) +// ); +// assert_eq!( +// weights_rate_8.mds[0][0], +// MontFp!( +// "39160448583049384229582837387246752222769278402304070376350288593586064961857" +// ) +// ); +// } +// } From e5c2afdca3e2e48019590156e59ff85fd4906852 Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Fri, 7 Feb 2025 14:52:46 -0500 Subject: [PATCH 02/17] rescue added without tests --- crypto-primitives/Cargo.toml | 2 +- .../src/commitment/blake2s/mod.rs | 2 +- .../src/commitment/injective_map/mod.rs | 2 +- crypto-primitives/src/commitment/mod.rs | 4 +- .../src/commitment/pedersen/mod.rs | 2 +- crypto-primitives/src/crh/bowe_hopwood/mod.rs | 2 +- .../src/crh/injective_map/mod.rs | 2 +- crypto-primitives/src/crh/mod.rs | 4 +- crypto-primitives/src/crh/pedersen/mod.rs | 2 +- crypto-primitives/src/crh/poseidon/mod.rs | 2 +- .../{gr1cs_constraints.rs => constraints.rs} | 12 +- crypto-primitives/src/crh/rescue/mod.rs | 6 +- .../src/crh/rescue/r1cs_constraints.rs | 156 ---- crypto-primitives/src/crh/sha256/mod.rs | 2 +- .../src/encryption/elgamal/mod.rs | 2 +- crypto-primitives/src/encryption/mod.rs | 4 +- crypto-primitives/src/merkle_tree/mod.rs | 2 +- .../src/merkle_tree/tests/mod.rs | 2 +- .../src/merkle_tree/tests/test_utils.rs | 2 +- crypto-primitives/src/prf/blake2s/mod.rs | 2 +- crypto-primitives/src/prf/mod.rs | 4 +- crypto-primitives/src/signature/mod.rs | 4 +- .../src/signature/schnorr/mod.rs | 2 +- crypto-primitives/src/snark/mod.rs | 4 +- crypto-primitives/src/sponge/mod.rs | 2 +- crypto-primitives/src/sponge/poseidon/mod.rs | 2 +- .../{gr1cs_constraints.rs => constraints.rs} | 135 +--- .../src/sponge/rescue/grain_lfsr.rs | 218 ------ crypto-primitives/src/sponge/rescue/mod.rs | 47 +- crypto-primitives/src/sponge/rescue/tests.rs | 729 ------------------ crypto-primitives/src/sponge/rescue/traits.rs | 351 --------- 31 files changed, 71 insertions(+), 1641 deletions(-) rename crypto-primitives/src/crh/rescue/{gr1cs_constraints.rs => constraints.rs} (93%) delete mode 100644 crypto-primitives/src/crh/rescue/r1cs_constraints.rs rename crypto-primitives/src/sponge/rescue/{gr1cs_constraints.rs => constraints.rs} (73%) delete mode 100644 crypto-primitives/src/sponge/rescue/grain_lfsr.rs delete mode 100644 crypto-primitives/src/sponge/rescue/tests.rs delete mode 100644 crypto-primitives/src/sponge/rescue/traits.rs diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index b75645f6..64978876 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -20,7 +20,7 @@ ark-crypto-primitives-macros = { version = "^0.5.0", path = "../macros" } ark-ff = { version = "^0.5.0", default-features = false } ark-ec = { version = "^0.5.0", default-features = false } ark-std = { version = "^0.5.0", default-features = false } -ark-relations = { git = "https://github.com/arkworks-rs/snark.git", default-features = true } +ark-relations = { path = "../../snark/relations/", default-features = true } ark-serialize = { version = "^0.5.0", default-features = false, features = [ "derive" ] } blake2 = { version = "0.10", default-features = false } diff --git a/crypto-primitives/src/commitment/blake2s/mod.rs b/crypto-primitives/src/commitment/blake2s/mod.rs index 9a5c104b..fe074782 100644 --- a/crypto-primitives/src/commitment/blake2s/mod.rs +++ b/crypto-primitives/src/commitment/blake2s/mod.rs @@ -5,7 +5,7 @@ use digest::Digest; pub struct Commitment; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; impl CommitmentScheme for Commitment { diff --git a/crypto-primitives/src/commitment/injective_map/mod.rs b/crypto-primitives/src/commitment/injective_map/mod.rs index d7a050e4..47aeee88 100644 --- a/crypto-primitives/src/commitment/injective_map/mod.rs +++ b/crypto-primitives/src/commitment/injective_map/mod.rs @@ -6,7 +6,7 @@ use crate::{ use ark_ec::CurveGroup; use ark_std::{marker::PhantomData, rand::Rng}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub struct PedersenCommCompressor, W: pedersen::Window> { diff --git a/crypto-primitives/src/commitment/mod.rs b/crypto-primitives/src/commitment/mod.rs index 6b845d63..83cac186 100644 --- a/crypto-primitives/src/commitment/mod.rs +++ b/crypto-primitives/src/commitment/mod.rs @@ -7,9 +7,9 @@ pub mod blake2s; pub mod injective_map; pub mod pedersen; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub use constraints::*; pub trait CommitmentScheme { diff --git a/crypto-primitives/src/commitment/pedersen/mod.rs b/crypto-primitives/src/commitment/pedersen/mod.rs index a039b69e..9a7f9f50 100644 --- a/crypto-primitives/src/commitment/pedersen/mod.rs +++ b/crypto-primitives/src/commitment/pedersen/mod.rs @@ -11,7 +11,7 @@ use ark_serialize::CanonicalSerialize; use ark_std::vec::Vec; use ark_std::{marker::PhantomData, rand::Rng, UniformRand}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; #[derive(Clone)] diff --git a/crypto-primitives/src/crh/bowe_hopwood/mod.rs b/crypto-primitives/src/crh/bowe_hopwood/mod.rs index 715e5b52..4ee8ee4f 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/mod.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/mod.rs @@ -25,7 +25,7 @@ use ark_std::{ #[cfg(feature = "parallel")] use rayon::prelude::*; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub const CHUNK_SIZE: usize = 3; diff --git a/crypto-primitives/src/crh/injective_map/mod.rs b/crypto-primitives/src/crh/injective_map/mod.rs index 072fbeb0..6038f6bb 100644 --- a/crypto-primitives/src/crh/injective_map/mod.rs +++ b/crypto-primitives/src/crh/injective_map/mod.rs @@ -10,7 +10,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; use ark_std::{borrow::Borrow, fmt::Debug, hash::Hash, marker::PhantomData, rand::Rng}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub trait InjectiveMap { diff --git a/crypto-primitives/src/crh/mod.rs b/crypto-primitives/src/crh/mod.rs index 1e835472..8e1eac3a 100644 --- a/crypto-primitives/src/crh/mod.rs +++ b/crypto-primitives/src/crh/mod.rs @@ -4,14 +4,14 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{borrow::Borrow, fmt::Debug, hash::Hash, rand::Rng}; pub mod bowe_hopwood; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub mod injective_map; pub mod pedersen; pub mod poseidon; pub mod rescue; pub mod sha256; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub use constraints::*; /// Interface to CRH. Note that in this release, while all implementations of `CRH` have fixed length, diff --git a/crypto-primitives/src/crh/pedersen/mod.rs b/crypto-primitives/src/crh/pedersen/mod.rs index 4147cdc6..5e84a5e4 100644 --- a/crypto-primitives/src/crh/pedersen/mod.rs +++ b/crypto-primitives/src/crh/pedersen/mod.rs @@ -17,7 +17,7 @@ use ark_std::{ #[cfg(feature = "parallel")] use rayon::prelude::*; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub trait Window: Clone { diff --git a/crypto-primitives/src/crh/poseidon/mod.rs b/crypto-primitives/src/crh/poseidon/mod.rs index d32fa36a..dfb87151 100644 --- a/crypto-primitives/src/crh/poseidon/mod.rs +++ b/crypto-primitives/src/crh/poseidon/mod.rs @@ -9,7 +9,7 @@ use crate::{ use ark_ff::PrimeField; use ark_std::{borrow::Borrow, marker::PhantomData, rand::Rng}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; //TODO: CHange this r1cs to gr1cs in the future in a seperate PR pub struct CRH { diff --git a/crypto-primitives/src/crh/rescue/gr1cs_constraints.rs b/crypto-primitives/src/crh/rescue/constraints.rs similarity index 93% rename from crypto-primitives/src/crh/rescue/gr1cs_constraints.rs rename to crypto-primitives/src/crh/rescue/constraints.rs index 1cb08ebe..396382ce 100644 --- a/crypto-primitives/src/crh/rescue/gr1cs_constraints.rs +++ b/crypto-primitives/src/crh/rescue/constraints.rs @@ -5,7 +5,7 @@ use crate::crh::{ constraints::TwoToOneCRHSchemeGadget as TwoToOneCRHGadgetTrait, }; use crate::sponge::constraints::CryptographicSpongeVar; -use crate::sponge::rescue::gr1cs_constraints::RescueSpongeVar; +use crate::sponge::rescue::constraints::RescueSpongeVar; use crate::sponge::rescue::RescueConfig; use crate::sponge::Absorb; @@ -114,11 +114,13 @@ impl AllocVar, F> for CRHParametersVar { - input: Option>, - image: Option, - config: RescueConfig, - N: usize, -} - -pub fn create_test_rescue_parameter( - rng: &mut impl Rng, -) -> RescueConfig { - let mut mds = vec![vec![]; 4]; - for i in 0..4 { - for _ in 0..4 { - mds[i].push(F::rand(rng)); - } - } - - let mut ark = vec![vec![]; 25]; - for i in 0..(2 * RESCUE_ROUNDS + 1) { - for _ in 0..4 { - ark[i].push(F::rand(rng)); - } - } - let alpha_inv: BigUint = BigUint::from_str( - "20974350070050476191779096203274386335076221000211055129041463479975432473805", - ) - .unwrap(); - let params = RescueConfig::::new(RESCUE_ROUNDS, 5, alpha_inv, mds, ark, 3, 1); - params -} - -impl ConstraintSynthesizer - for RescueDemo -{ - fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { - cs.clone().register_predicate( - gr1cs::MUL, - LocalPredicate::new( - 3, - gr1cs::predicate::LocalPredicateType::Polynomial( - gr1cs::polynomial::Polynomial::new( - 3, - vec![(F::ONE, vec![1, 1, 0]), (F::ZERO - F::ONE, vec![0, 0, 1])], - ) - .unwrap(), - ), - ), - ); - - - let params_g = - CRHParametersVar::::new_witness(cs.clone(), || Ok(self.config.clone())).unwrap(); - - for _ in 0..self.N { - let mut input_g = Vec::new(); - - for elem in self - .input - .clone() - .ok_or(SynthesisError::AssignmentMissing) - .unwrap() - { - input_g.push(FpVar::new_witness(cs.clone(), || Ok(elem)).unwrap()); - } - - let crh_a_g: FpVar = CRHGadget::::evaluate(¶ms_g, &input_g).unwrap(); - let image_instance: FpVar = FpVar::new_input(cs.clone(), || { - Ok(self.image.ok_or(SynthesisError::AssignmentMissing).unwrap()) - }) - .unwrap(); - crh_a_g.enforce_equal(&image_instance); - } - Ok(()) - } -} - - -#[test] -fn test_rescue() { - - const N: usize = 100; - // We're going to use the Groth16 proving system. - - - // This may not be cryptographically safe, use - // `OsRng` (for example) in production software. - let mut rng = ark_std::rand::rngs::StdRng::seed_from_u64(test_rng().next_u64()); - let config = create_test_rescue_parameter(&mut rng); - - // Generate a random preimage and compute the image - let mut input = Vec::new(); - for _ in 0..9 { - input.push(Fr::rand(&mut rng)); - } - let expected_image = CRH::::evaluate(&config, input.clone()).unwrap(); - - let c = RescueDemo:: { - input: Some(input.clone()), - image: Some(expected_image), - config: config.clone(), - N - }; - - /////////////////////////////////////////////////////////////////////////////////// - // Create parameters for our circuit - println!("Creating SRS..."); - let mut setup_time: Duration = Duration::new(0, 0); - - let start = Instant::now(); - - let (pk, vk) = { Varuna::::setup(&mut rng, c.clone()) }; - - setup_time += start.elapsed(); - std::println!("Setup time = {}", setup_time.as_millis()); - /////////////////////////////////////////////// - // Creating the proof - - println!("Creating proofs..."); - - let mut total_proving: Duration = Duration::new(0, 0); - - let start = Instant::now(); - - // Create a groth16 proof with our parameters. - let proof = Varuna::::prove(&mut rng, c, pk); - total_proving += start.elapsed(); - - std::println!("Totall Prover time = {}", total_proving.as_millis()); - - /////////////////////////////////////////////// - // Verifying the proof - let mut total_verifying: Duration = Duration::new(0, 0); - let start = Instant::now(); - assert!(Varuna::::verify( - &mut rng, - proof, - vk, - &[expected_image;N] - )); - - // proof.write(&mut proof_vec).unwrap(); - - // let proof = Proof::read(&proof_vec[..]).unwrap(); - // Check the proof - - total_verifying += start.elapsed(); -} diff --git a/crypto-primitives/src/crh/sha256/mod.rs b/crypto-primitives/src/crh/sha256/mod.rs index d63b45f9..3f1a48f6 100644 --- a/crypto-primitives/src/crh/sha256/mod.rs +++ b/crypto-primitives/src/crh/sha256/mod.rs @@ -10,7 +10,7 @@ use sha2::digest::Digest; // Re-export the RustCrypto Sha256 type and its associated traits pub use sha2::{digest, Sha256}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; // Implement the CRH traits for SHA-256 diff --git a/crypto-primitives/src/encryption/elgamal/mod.rs b/crypto-primitives/src/encryption/elgamal/mod.rs index aa47d49f..4aceb832 100644 --- a/crypto-primitives/src/encryption/elgamal/mod.rs +++ b/crypto-primitives/src/encryption/elgamal/mod.rs @@ -3,7 +3,7 @@ use ark_ec::{AdditiveGroup, CurveGroup}; use ark_ff::{fields::PrimeField, UniformRand}; use ark_std::{marker::PhantomData, ops::Mul, rand::Rng}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub struct ElGamal { diff --git a/crypto-primitives/src/encryption/mod.rs b/crypto-primitives/src/encryption/mod.rs index 08e8d9a3..87f75895 100644 --- a/crypto-primitives/src/encryption/mod.rs +++ b/crypto-primitives/src/encryption/mod.rs @@ -1,10 +1,10 @@ use crate::Error; use ark_std::rand::Rng; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub mod elgamal; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub use constraints::*; pub trait AsymmetricEncryptionScheme { diff --git a/crypto-primitives/src/merkle_tree/mod.rs b/crypto-primitives/src/merkle_tree/mod.rs index c23c14d2..b811e79f 100644 --- a/crypto-primitives/src/merkle_tree/mod.rs +++ b/crypto-primitives/src/merkle_tree/mod.rs @@ -19,7 +19,7 @@ use hashbrown::HashMap; #[cfg(feature = "parallel")] use rayon::prelude::*; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; #[cfg(test)] diff --git a/crypto-primitives/src/merkle_tree/tests/mod.rs b/crypto-primitives/src/merkle_tree/tests/mod.rs index a03e1883..2c5373d1 100644 --- a/crypto-primitives/src/merkle_tree/tests/mod.rs +++ b/crypto-primitives/src/merkle_tree/tests/mod.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] mod constraints; mod test_utils; diff --git a/crypto-primitives/src/merkle_tree/tests/test_utils.rs b/crypto-primitives/src/merkle_tree/tests/test_utils.rs index e1ff2f9c..e68c64f0 100644 --- a/crypto-primitives/src/merkle_tree/tests/test_utils.rs +++ b/crypto-primitives/src/merkle_tree/tests/test_utils.rs @@ -653,5 +653,5 @@ pub(crate) fn poseidon_parameters() -> PoseidonConfig { PoseidonConfig::::new(full_rounds, partial_rounds, alpha, mds, ark, 2, 1) } -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] mod constraints {} diff --git a/crypto-primitives/src/prf/blake2s/mod.rs b/crypto-primitives/src/prf/blake2s/mod.rs index 97e17801..8fea20d7 100644 --- a/crypto-primitives/src/prf/blake2s/mod.rs +++ b/crypto-primitives/src/prf/blake2s/mod.rs @@ -4,7 +4,7 @@ use ark_std::vec::Vec; use blake2::{Blake2s256 as B2s, Blake2sMac}; use digest::Digest; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; #[derive(Clone)] diff --git a/crypto-primitives/src/prf/mod.rs b/crypto-primitives/src/prf/mod.rs index f86df3f7..4c41143f 100644 --- a/crypto-primitives/src/prf/mod.rs +++ b/crypto-primitives/src/prf/mod.rs @@ -3,9 +3,9 @@ use crate::Error; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{fmt::Debug, hash::Hash}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub use constraints::*; pub mod blake2s; diff --git a/crypto-primitives/src/signature/mod.rs b/crypto-primitives/src/signature/mod.rs index 8009de33..f53eb0d7 100644 --- a/crypto-primitives/src/signature/mod.rs +++ b/crypto-primitives/src/signature/mod.rs @@ -2,9 +2,9 @@ use crate::Error; use ark_serialize::CanonicalSerialize; use ark_std::{hash::Hash, rand::Rng}; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub use constraints::*; pub mod schnorr; diff --git a/crypto-primitives/src/signature/schnorr/mod.rs b/crypto-primitives/src/signature/schnorr/mod.rs index 16240ea4..9231fc3b 100644 --- a/crypto-primitives/src/signature/schnorr/mod.rs +++ b/crypto-primitives/src/signature/schnorr/mod.rs @@ -10,7 +10,7 @@ use ark_std::vec::Vec; use ark_std::{hash::Hash, marker::PhantomData, ops::Mul, rand::Rng}; use digest::Digest; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; pub struct Schnorr { diff --git a/crypto-primitives/src/snark/mod.rs b/crypto-primitives/src/snark/mod.rs index 778b4e2e..d2befe46 100644 --- a/crypto-primitives/src/snark/mod.rs +++ b/crypto-primitives/src/snark/mod.rs @@ -1,6 +1,6 @@ -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub use constraints::*; pub use ark_snark::*; diff --git a/crypto-primitives/src/sponge/mod.rs b/crypto-primitives/src/sponge/mod.rs index eb568bbe..e324a2a5 100644 --- a/crypto-primitives/src/sponge/mod.rs +++ b/crypto-primitives/src/sponge/mod.rs @@ -3,7 +3,7 @@ use ark_ff::PrimeField; use ark_std::vec::Vec; /// Infrastructure for the constraints counterparts. -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; mod absorb; diff --git a/crypto-primitives/src/sponge/poseidon/mod.rs b/crypto-primitives/src/sponge/poseidon/mod.rs index 3b40bd21..5fa923c2 100644 --- a/crypto-primitives/src/sponge/poseidon/mod.rs +++ b/crypto-primitives/src/sponge/poseidon/mod.rs @@ -9,7 +9,7 @@ use ark_std::any::TypeId; use ark_std::vec::Vec; /// constraints for Poseidon -#[cfg(feature = "gr1cs")] +#[cfg(any(feature = "r1cs", feature = "gr1cs"))] pub mod constraints; #[cfg(test)] mod tests; diff --git a/crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs similarity index 73% rename from crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs rename to crypto-primitives/src/sponge/rescue/constraints.rs index c2109116..dcaa8996 100644 --- a/crypto-primitives/src/sponge/rescue/gr1cs_constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -8,7 +8,6 @@ use ark_ff::PrimeField; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::prelude::*; -use ark_relations::lc; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -39,7 +38,7 @@ impl SpongeWithGadget for RescueSponge { impl RescueSpongeVar { - + #[cfg(feature = "gr1cs")] fn apply_s_box( &self, state: &mut [FpVar], @@ -47,20 +46,20 @@ impl RescueSpongeVar { alpha: u64, // round: usize ) -> Result<(), SynthesisError> { + use ark_relations::lc; let cs = state[0].cs(); - + if [alpha] == exponent { for state_item in state.iter_mut() { let new_state_item = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); match (&state_item,&new_state_item) { (FpVar::Var(alloc_fp),FpVar::Var(new_alloc_fp)) => { - let _ = cs.enforce_constraint("POW",vec![lc!()+ alloc_fp.variable,lc!()+new_alloc_fp.variable], ); + let _ = cs.enforce_constraint("XXX",vec![lc!()+ alloc_fp.variable,lc!()+new_alloc_fp.variable], ); *state_item = new_state_item; } _ => { - // std::dbg!(round); *state_item = state_item.pow_by_constant(exponent)?; } } @@ -69,15 +68,12 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let new_state_item = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); - // std::dbg!(&state_item); - // std::dbg!(&new_state_item); match (&state_item,&new_state_item) { (FpVar::Var(alloc_fp),FpVar::Var(new_alloc_fp)) => { - let _ = cs.enforce_constraint("POW", vec![lc!()+ new_alloc_fp.variable,lc!()+alloc_fp.variable], ); + let _ = cs.enforce_constraint("XXX", vec![lc!()+ new_alloc_fp.variable,lc!()+alloc_fp.variable], ); }, _ => { - // std::dbg!(round); *state_item = state_item.pow_by_constant(exponent)?; } } @@ -89,6 +85,32 @@ impl RescueSpongeVar { } + + #[cfg(feature = "r1cs")] + fn apply_s_box( + &self, + state: &mut [FpVar], + exponent: &[u64], + alpha: u64, + // round: usize + ) -> Result<(), SynthesisError> { + + if [alpha] == exponent { + for state_item in state.iter_mut() { + *state_item = state_item.pow_by_constant(exponent)?; + } + } else { + for state_item in state.iter_mut() { + let output = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); + let expected_input = output.pow_by_constant([alpha]).unwrap(); + expected_input.enforce_equal(state_item)?; + *state_item = output; + } + } + Ok(()) + + } + fn apply_ark(&self, state: &mut [FpVar], round_key: &Vec) -> Result<(), SynthesisError> { for (i, state_elem) in state.iter_mut().enumerate() { *state_elem += round_key[i]; @@ -303,98 +325,3 @@ impl CryptographicSpongeVar> for RescueSpongeV Ok(squeezed_elems) } } - -#[cfg(test)] -mod tests { - use crate::sponge::constraints::CryptographicSpongeVar; - use crate::sponge::rescue::gr1cs_constraints::RescueSpongeVar; - use crate::sponge::rescue::rescue_parameters_for_test; - use crate::sponge::rescue::RescueSponge; - use crate::sponge::test::Fr; - use crate::sponge::{CryptographicSponge, FieldBasedCryptographicSponge, FieldElementSize}; - use ark_r1cs_std::alloc::AllocVar; - use ark_r1cs_std::fields::fp::FpVar; - use ark_r1cs_std::uint8::UInt8; - use ark_r1cs_std::GR1CSVar; - use ark_relations::gr1cs::ConstraintSystem; - use ark_ff::{Field, PrimeField, UniformRand}; - - use ark_relations::ns; - use ark_std::test_rng; - - #[test] - fn absorb_test() { - let mut rng = test_rng(); - let cs = ConstraintSystem::new_ref(); - - let absorb1: Vec<_> = (0..256).map(|_| Fr::rand(&mut rng)).collect(); - let absorb1_var: Vec<_> = absorb1 - .iter() - .map(|v| FpVar::new_input(ns!(cs, "absorb1"), || Ok(*v)).unwrap()) - .collect(); - - let absorb2: Vec<_> = (0..8).map(|i| vec![i, i + 1, i + 2]).collect(); - let absorb2_var: Vec<_> = absorb2 - .iter() - .map(|v| UInt8::new_input_vec(ns!(cs, "absorb2"), v).unwrap()) - .collect(); - - let sponge_params = rescue_parameters_for_test(); - - let mut native_sponge = RescueSponge::::new(&sponge_params); - let mut constraint_sponge = RescueSpongeVar::::new(cs.clone(), &sponge_params); - - native_sponge.absorb(&absorb1); - constraint_sponge.absorb(&absorb1_var).unwrap(); - - let squeeze1 = native_sponge.squeeze_native_field_elements(1); - let squeeze2 = constraint_sponge.squeeze_field_elements(1).unwrap(); - - assert_eq!(squeeze2.value().unwrap(), squeeze1); - assert!(cs.is_satisfied().unwrap()); - - native_sponge.absorb(&absorb2); - constraint_sponge.absorb(&absorb2_var).unwrap(); - - let squeeze1 = native_sponge.squeeze_native_field_elements(1); - let squeeze2 = constraint_sponge.squeeze_field_elements(1).unwrap(); - - assert_eq!(squeeze2.value().unwrap(), squeeze1); - assert!(cs.is_satisfied().unwrap()); - } - - #[test] - fn squeeze_with_sizes() { - let squeeze_bits = Fr::MODULUS_BIT_SIZE / 2; - let max_squeeze = Fr::from(2).pow(::BigInt::from(squeeze_bits)); - - let sponge_params = rescue_parameters_for_test(); - let mut native_sponge = RescueSponge::::new(&sponge_params); - - let squeeze = - native_sponge.squeeze_field_elements_with_sizes::(&[FieldElementSize::Truncated( - squeeze_bits as usize, - )])[0]; - assert!(squeeze < max_squeeze); - - let cs = ConstraintSystem::new_ref(); - let mut constraint_sponge = RescueSpongeVar::::new(cs.clone(), &sponge_params); - - let (squeeze, bits) = constraint_sponge - .squeeze_emulated_field_elements_with_sizes::(&[FieldElementSize::Truncated( - squeeze_bits as usize, - )]) - .unwrap(); - let squeeze = &squeeze[0]; - let bits = &bits[0]; - assert!(squeeze.value().unwrap() < max_squeeze); - assert_eq!(bits.len(), squeeze_bits as usize); - - // squeeze full - let (_, bits) = constraint_sponge - .squeeze_emulated_field_elements_with_sizes::(&[FieldElementSize::Full]) - .unwrap(); - let bits = &bits[0]; - assert_eq!(bits.len() as u32, Fr::MODULUS_BIT_SIZE - 1); - } -} diff --git a/crypto-primitives/src/sponge/rescue/grain_lfsr.rs b/crypto-primitives/src/sponge/rescue/grain_lfsr.rs deleted file mode 100644 index 544ab009..00000000 --- a/crypto-primitives/src/sponge/rescue/grain_lfsr.rs +++ /dev/null @@ -1,218 +0,0 @@ -#![allow(dead_code)] - -use ark_ff::{BigInteger, PrimeField}; -#[cfg(not(feature = "std"))] -use ark_std::vec::Vec; - -pub struct RescueGrainLFSR { - pub prime_num_bits: u64, - - pub state: [bool; 80], - pub head: usize, -} - -#[allow(unused_variables)] -impl RescueGrainLFSR { - pub fn new( - is_sbox_an_inverse: bool, - prime_num_bits: u64, - state_len: u64, - num_rounds: u64, - ) -> Self { - let mut state = [false; 80]; - - // b0, b1 describes the field - state[1] = true; - - // b2, ..., b5 describes the S-BOX - if is_sbox_an_inverse { - state[5] = true; - } else { - state[5] = false; - } - - // b6, ..., b17 are the binary representation of n (prime_num_bits) - { - let mut cur = prime_num_bits; - for i in (6..=17).rev() { - state[i] = cur & 1 == 1; - cur >>= 1; - } - } - - // b18, ..., b29 are the binary representation of t (state_len, rate + capacity) - { - let mut cur = state_len; - for i in (18..=29).rev() { - state[i] = cur & 1 == 1; - cur >>= 1; - } - } - - // b30, ..., b39 are the binary representation of R_F (the number of full rounds) - { - let mut cur = num_rounds; - for i in (30..=39).rev() { - state[i] = cur & 1 == 1; - cur >>= 1; - } - } - - // b40, ..., b49 are the binary representation of R_P (the number of partial rounds) - { - let mut cur = num_rounds; - for i in (40..=49).rev() { - state[i] = cur & 1 == 1; - cur >>= 1; - } - } - - // b50, ..., b79 are set to 1 - for i in 50..=79 { - state[i] = true; - } - - let head = 0; - - let mut res = Self { - prime_num_bits, - state, - head, - }; - res.init(); - res - } - - pub fn get_bits(&mut self, num_bits: usize) -> Vec { - let mut res = Vec::new(); - - for _ in 0..num_bits { - // Obtain the first bit - let mut new_bit = self.update(); - - // Loop until the first bit is true - while new_bit == false { - // Discard the second bit - let _ = self.update(); - // Obtain another first bit - new_bit = self.update(); - } - - // Obtain the second bit - res.push(self.update()); - } - - res - } - - pub fn get_field_elements_rejection_sampling( - &mut self, - num_elems: usize, - ) -> Vec { - assert_eq!(F::MODULUS_BIT_SIZE as u64, self.prime_num_bits); - - let mut res = Vec::new(); - for _ in 0..num_elems { - // Perform rejection sampling - loop { - // Obtain n bits and make it most-significant-bit first - let mut bits = self.get_bits(self.prime_num_bits as usize); - bits.reverse(); - - // Construct the number - let bigint = F::BigInt::from_bits_le(&bits); - - if let Some(f) = F::from_bigint(bigint) { - res.push(f); - break; - } - } - } - - res - } - - pub fn get_field_elements_mod_p(&mut self, num_elems: usize) -> Vec { - assert_eq!(F::MODULUS_BIT_SIZE as u64, self.prime_num_bits); - - let mut res = Vec::new(); - for _ in 0..num_elems { - // Obtain n bits and make it most-significant-bit first - let mut bits = self.get_bits(self.prime_num_bits as usize); - bits.reverse(); - - let bytes = bits - .chunks(8) - .map(|chunk| { - let mut result = 0u8; - for (i, bit) in chunk.iter().enumerate() { - result |= u8::from(*bit) << i - } - result - }) - .collect::>(); - - res.push(F::from_le_bytes_mod_order(&bytes)); - } - - res - } - - #[inline] - fn update(&mut self) -> bool { - let new_bit = self.state[(self.head + 62) % 80] - ^ self.state[(self.head + 51) % 80] - ^ self.state[(self.head + 38) % 80] - ^ self.state[(self.head + 23) % 80] - ^ self.state[(self.head + 13) % 80] - ^ self.state[self.head]; - self.state[self.head] = new_bit; - self.head += 1; - self.head %= 80; - - new_bit - } - - fn init(&mut self) { - for _ in 0..160 { - let _ = self.update(); - } - } -} - -#[cfg(test)] -mod test { - use crate::sponge::rescue::grain_lfsr::RescueGrainLFSR; - use crate::sponge::test::Fr; - use ark_ff::MontFp; - - #[test] - fn test_grain_lfsr_consistency() { - let mut lfsr = RescueGrainLFSR::new(false, 255, 3, 39); - - assert_eq!( - lfsr.get_field_elements_rejection_sampling::(1)[0], - MontFp!( - "27117311055620256798560880810000042840428971800021819916023577129547249660720" - ) - ); - assert_eq!( - lfsr.get_field_elements_rejection_sampling::(1)[0], - MontFp!( - "51641662388546346858987925410984003801092143452466182801674685248597955169158" - ) - ); - assert_eq!( - lfsr.get_field_elements_mod_p::(1)[0], - MontFp!( - "30468495022634911716522728179277518871747767531215914044579216845399211650580" - ) - ); - assert_eq!( - lfsr.get_field_elements_mod_p::(1)[0], - MontFp!( - "17250718238509906485015112994867732544602358855445377986727968022920517907825" - ) - ); - } -} diff --git a/crypto-primitives/src/sponge/rescue/mod.rs b/crypto-primitives/src/sponge/rescue/mod.rs index fd1c6147..7f49cbad 100644 --- a/crypto-primitives/src/sponge/rescue/mod.rs +++ b/crypto-primitives/src/sponge/rescue/mod.rs @@ -10,19 +10,11 @@ use ark_std::any::TypeId; use ark_std::vec::Vec; /// constraints for Rescue -pub mod gr1cs_constraints; +#[cfg(any(feature = "gr1cs", feature = "r1cs"))] +pub mod constraints; -#[cfg(test)] -mod tests; -#[cfg(test)] -pub(crate) use tests::rescue_parameters_for_test; - -/// default parameters traits for Rescue -pub mod traits; use num_bigint::BigUint; -pub use traits::*; -mod grain_lfsr; /// Config and RNG used #[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] @@ -359,38 +351,3 @@ impl SpongeExt for RescueSponge { } } } - -// #[cfg(test)] -// mod test { -// use crate::sponge::poseidon::PoseidonDefaultConfigField; -// use crate::sponge::test::Fr; -// use crate::sponge::{ -// poseidon::PoseidonSponge, CryptographicSponge, FieldBasedCryptographicSponge, -// }; -// use ark_ff::MontFp; - -// #[test] -// fn test_poseidon_sponge_consistency() { -// let sponge_param = Fr::get_default_poseidon_parameters(2, false).unwrap(); - -// let mut sponge = PoseidonSponge::::new(&sponge_param); -// sponge.absorb(&vec![Fr::from(0u8), Fr::from(1u8), Fr::from(2u8)]); -// let res = sponge.squeeze_native_field_elements(3); -// assert_eq!( -// res[0], -// MontFp!( -// "40442793463571304028337753002242186710310163897048962278675457993207843616876" -// ) -// ); -// assert_eq!( -// res[1], -// MontFp!("2664374461699898000291153145224099287711224021716202960480903840045233645301") -// ); -// assert_eq!( -// res[2], -// MontFp!( -// "50191078828066923662070228256530692951801504043422844038937334196346054068797" -// ) -// ); -// } -// } diff --git a/crypto-primitives/src/sponge/rescue/tests.rs b/crypto-primitives/src/sponge/rescue/tests.rs deleted file mode 100644 index 044e00d7..00000000 --- a/crypto-primitives/src/sponge/rescue/tests.rs +++ /dev/null @@ -1,729 +0,0 @@ -use core::str::FromStr; - -use crate::sponge::rescue::{RescueConfig, RescueSponge}; -use crate::sponge::test::Fr; -use crate::sponge::{Absorb, AbsorbWithLength, CryptographicSponge, FieldBasedCryptographicSponge}; -use ark_ff::{One, PrimeField, UniformRand}; -use ark_std::test_rng; -use num_bigint::BigUint; - -fn assert_different_encodings(a: &A, b: &A) { - let bytes1 = a.to_sponge_bytes_as_vec(); - let bytes2 = b.to_sponge_bytes_as_vec(); - assert_ne!(bytes1, bytes2); - - let sponge_param = rescue_parameters_for_test(); - let mut sponge1 = RescueSponge::::new(&sponge_param); - let mut sponge2 = RescueSponge::::new(&sponge_param); - - sponge1.absorb(&a); - sponge2.absorb(&b); - - assert_ne!( - sponge1.squeeze_native_field_elements(3), - sponge2.squeeze_native_field_elements(3) - ); -} - -#[test] -fn single_field_element() { - let mut rng = test_rng(); - let elem1 = Fr::rand(&mut rng); - let elem2 = elem1 + Fr::one(); - - assert_different_encodings::(&elem1, &elem2) -} - -#[test] -fn list_with_constant_size_element() { - let mut rng = test_rng(); - let lst1: Vec<_> = (0..1024 * 8).map(|_| Fr::rand(&mut rng)).collect(); - let mut lst2 = lst1.to_vec(); - lst2[3] += Fr::one(); - - assert_different_encodings::(&lst1, &lst2) -} - -struct VariableSizeList(Vec); - -impl Absorb for VariableSizeList { - fn to_sponge_bytes(&self, dest: &mut Vec) { - self.0.to_sponge_bytes_with_length(dest) - } - - fn to_sponge_field_elements(&self, dest: &mut Vec) { - self.0.to_sponge_field_elements_with_length(dest) - } -} - -#[test] -fn list_with_nonconstant_size_element() { - let lst1 = vec![ - VariableSizeList(vec![1u8, 2, 3, 4]), - VariableSizeList(vec![5, 6]), - ]; - let lst2 = vec![ - VariableSizeList(vec![1u8, 2]), - VariableSizeList(vec![3, 4, 5, 6]), - ]; - - assert_different_encodings::(&lst1, &lst2); -} - -#[test] -fn test_squeeze_cast_native() { - let mut rng = test_rng(); - let sponge_param = rescue_parameters_for_test(); - let elem = Fr::rand(&mut rng); - let mut sponge1 = RescueSponge::::new(&sponge_param); - sponge1.absorb(&elem); - let mut sponge2 = sponge1.clone(); - - // those two should return same result - let squeezed1 = sponge1.squeeze_native_field_elements(5); - let squeezed2 = sponge2.squeeze_field_elements::(5); - - assert_eq!(squeezed1, squeezed2); -} - -#[test] -fn test_macros() { - let sponge_param = rescue_parameters_for_test(); - let mut sponge1 = RescueSponge::::new(&sponge_param); - sponge1.absorb(&vec![0, 0, 0]); - let _ = sponge1.squeeze_native_field_elements(3); - // assert_eq!(actual, expected); -} - -/// Generate default parameters (bls381-fr-only) for alpha = 17, state-size = 8 -pub(crate) fn rescue_parameters_for_test() -> RescueConfig { - let alpha: u64 = 5; - let alpha_inv: BigUint = BigUint::from_str( - "20974350070050476191779096203274386335076221000211055129041463479975432473805", - ) - .unwrap(); - let mds = vec![ - vec![ - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658699938581066864", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658699938534124913", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658699922104442063", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658694270581781713", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str("137200").map_err(|_| ()).unwrap(), - F::from_str("54762351").map_err(|_| ()).unwrap(), - F::from_str("19167800400").map_err(|_| ()).unwrap(), - F::from_str("6593435097550").map_err(|_| ()).unwrap(), - ], - vec![ - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658699938581164563", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658699938573341713", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658699935841949364", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "52435875175126190479447740508185965837690552500527637822603658698996613844913", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str("400").map_err(|_| ()).unwrap(), - F::from_str("140050").map_err(|_| ()).unwrap(), - F::from_str("48177200").map_err(|_| ()).unwrap(), - F::from_str("16531644851").map_err(|_| ()).unwrap(), - ], - ]; - - let arc = vec![ - vec![ - F::from_str( - "23134431890904997735913685390433273947519177060544011867815065124418348995661", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "7910743581020883359489900822814213105822551758045258908574127548576902234202", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "6452335108146897903818881932868089947456740590166061243393158685187431809297", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "864592593827916191968939823230510547087468030011538620003456937932684270153", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "38559831148991359569240421320742457813901373970667612903096765001678689742869", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "44432094719863142927213238093899283700039162038776502993701830158231473502718", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "13786878310315045269120166277183380710599519606157001198417893850005860761477", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "17036162502882675914728275738142065498870974756580444696024180584972335393891", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "33297391939828784001334305802801790593075215229341062678759834559352791736927", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "30500234470117650473907563119990479857361330029198334465374149341676986657115", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "28368430002799198204829257649919634676282026294040173648357765445674005961616", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "9971774186674696614989363797869882469420353008371920226950903037350505417985", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "38139940790606785825103193122238735657582566078114455777468513830487946069923", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "18494333247252274673841361720222549391212096862516923705801761369032339310465", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "39473154482456623768629668349330022458952017097397018586008411120523622633522", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "49285468826209236211279126413673418598127797981942143090059666672629931469385", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "37573115437821831291655432604342578198375078311237242116810739862690145869225", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "27159986956208459140740586738884801802553721748425801853018806317642115259465", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "50214917776783317494180761535986162125563373683868209887890350167269467512946", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "33192867848214168029937060315398544504185295780147134497700076703607952805601", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "50547084830917374624389766622731065576522729673796501202951652168746034262368", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "45100620163299107975959845063844422497694960652741628584970040113210087450662", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "28385120759308049649771453408964811097622465677204481653130542380799307518408", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "35505667235096341555371720396459529907006829254583697277239853917493427123171", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "16437023531659726503682820269358772433184823533333464461469690236822611246932", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "49360243277754004678870001664997850734809212162384644335519685096097001288746", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "8366523254506253216955925296723301364165909408966688192695903971021249968759", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "32459638038196976591500542123818841546669374539590905536922780381223051269547", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "22599560612315772755286575091483116315925260320221561394233776132305161190561", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "16229934200422104594884143900568445503380871501895946009917550290753020752637", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "17517715034137249648481695275508773137979656298150763634847149919185663637655", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "45947279115715765148360788762909806671057420057351947155669138664467561798989", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "38229297807694040917955834901740313151512726422553249211118784759282147254077", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "19221546762665803708415808219454804973762879918238939441381811045896992381109", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "33231993603873329070501348145497728179419527307416430409856815932181772452630", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "44458989315723037569515354400025898188417538412399056946002281608928012076586", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "24097312182414801078940320939859383216367533770388304058972565863202612417326", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "34256182992584397437238816392424956796177998428482016693069842948650455465667", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "27060035464776105302994958363141504784786371731529349414072592535017130374008", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "17415618923957471534182927609934477683351352413272869403402000253948609094158", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "52060491319769018565163753644800488203563135506472497361838613747294343804114", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "1576362207015741288206059930042566539467434543957819902177550750073890852683", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "8253285684584554153849658552191085295583616802943045548686466429839116309878", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "15228514972361056807058151246098278735034513446245359457360228365631138432464", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "38783524586591753822986895661611634222017618368881437223506280603887659991356", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "22924959878025315031997085972756214001369606050285016376071539202766714623098", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "38950764297104469352344857946933662562545322621139995330167708101102044854910", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "11582888283975802643911017125775178169823051538957372067698650122726375950434", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "2298059043453100803649451299470643637099839499417037430896288122564116673326", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "47452596181551524646344358930874945080161659084551765779147813564221166652068", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "24182618861502016111021387835225265356539367730170595823767549536597589758279", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "14893912374919937388411364573314859358172657326695138742923676384357192372360", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "29398955694234023746472399069867629004542497600023389447384583977723258550192", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "36431673144691658691089220672109647461388222858311362067310271835971778148239", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "36492546966674475841438383178903363293964948716421208618060366101436800890790", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "39826799880794424638601874310358734694596460435322030277945017973910646589658", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "36662659413289416298119595844374289415379142322557068765425566585291305461011", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "38017535128209347092713795357871139666671551695819603361759727956851537514709", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "25434598699479962479879799356660079088973594621334634094152711756591035511679", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "33336898409062469195367067121198433779512635331177938007459412699788883108767", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "36058492436047198232978210456456061345170502778325117411208214452676002954201", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "14929481097395660251041965124240362591858660791456046253123033940975701514456", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "46289456091709068352930110828228678138660509736781390773985243886583143161896", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "14111091112977253742344847253086777239100006548059301114340049030467157387521", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "23508471880487400547770156512200772032889406124325897152916765048940153794095", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "16427729880783669957687779378358330473153574875195990658467800363160755677791", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "40156212882518721479460476494171767350034540523507037311923208389487152164489", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "26466836315288637608098985482060993155004017219176998749277566727915735967085", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "12888991686625632077905083939301155235848796738397906807998959514789614307101", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "6784648945900955205375833568502720684047995011038533579314932408073600302438", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "44283955455419102825730907918077389640930999889828224092875982380225907905576", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "21577906067866213753420832310759166345133214697458479927528550794777093745604", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "38676501821726372170081401661551268994693205369401304895157734309488019380911", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "18529238452898077491659062501197031745896551150529843021252022108041840991725", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "39772233475672473946716838776583251658997392411594037169310522755188417064472", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "48671926799613401149453947988763058951611718216954721361239302424336671881515", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "26061735084460790107366459209731985475376433843933274332541132225962092927733", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "24476140360704277298499598001474042644853190438756563291732720884448772397090", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "35748587835271739316324970945389055874118783613333018094991998493311506731782", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "47796681825820555809507630731803833582122742147864710760222058561602842001598", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "40129439376092624311792893362370068647875773785715766199288734633835269388506", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "22953237491934857847613812618498396296702277164511710957864161394836877126161", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "29883326359097154867527259575122302865251616498628736645388175015904851526169", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "16072876630565035721133423676805583416603803842527477499864696244977108270962", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "24433700016212560423407666099058783317053813403174801115287910358608146647763", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "45621659799852625322132052822408291445398292320558577340143231454608533229003", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "46536854208059093798042581691627728318294548204429580171491758231887086308112", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "44290182871662828030169493647139274231335308414589340572678350270417540283009", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "24250445856569954871622245222941720285145845445950474905864907057534343371457", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "25464299025380640073894563298622770863524901688551682692256088582694681257991", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "48318976335409296081239636812736844416642798055771900654762783556487073695991", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "27416530804116379123268279724889870598678372756104891540114066426635076293490", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "199228435670075738810018840314890086674908720274885080714863258792386713132", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "5409167973407743302372619466704081038889320188478946053340045998738973947167", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "13434167199395645551742078879595157181938211296502254602943139432040945799876", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "38812643263458464757761860102011279525010950636150476516702289987662118941842", - ) - .map_err(|_| ()) - .unwrap(), - ], - vec![ - F::from_str( - "18052247500214455977292949825560594271643829386764412343087015646067353331355", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "68369435126047993922545267004639203490461725090813907915976375458289016380", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "2888545834527802263243399767681989249863878258231930802647884036794912638290", - ) - .map_err(|_| ()) - .unwrap(), - F::from_str( - "32483396880170305854478259671129578112226318950991647664509323211693485555524", - ) - .map_err(|_| ()) - .unwrap(), - ], - ]; - - let rounds = 12; - let capacity = 1; - let rate = 3; - RescueConfig { - rounds, - alpha, - alpha_inv, - arc, - mds, - rate, - capacity, - } -} diff --git a/crypto-primitives/src/sponge/rescue/traits.rs b/crypto-primitives/src/sponge/rescue/traits.rs deleted file mode 100644 index 05dc7cc2..00000000 --- a/crypto-primitives/src/sponge/rescue/traits.rs +++ /dev/null @@ -1,351 +0,0 @@ -use crate::sponge::rescue::grain_lfsr::RescueGrainLFSR; -use crate::sponge::rescue::RescueConfig; - -use ark_ff::{Field, Fp, FpConfig, PrimeField}; -#[cfg(not(feature = "std"))] -use ark_std::vec::Vec; - -/// An entry in the default Rescue parameters -pub struct RescueDefaultConfigEntry { - /// The rate (in terms of number of field elements). - pub rate: usize, - /// Exponent used in S-boxes. - pub alpha: u64, - /// Number of rounds - pub rounds: usize, - - pub skip_matrices: usize, -} - -impl RescueDefaultConfigEntry { - /// Create an entry in `RescueDefaultConfig`. - pub const fn new( - rate: usize, - alpha: u64, - rounds: usize, - skip_matrices: usize, - ) -> Self { - Self { - rate, - alpha, - rounds, - skip_matrices, - } - } -} - -/// A trait for default Rescue parameters associated with a prime field -pub trait RescueDefaultConfig: FpConfig { - /// An array of the parameters optimized for constraints - /// (rate, alpha, full_rounds, partial_rounds, skip_matrices) - /// for rate = 2, 3, 4, 5, 6, 7, 8 - /// - /// Here, `skip_matrices` denote how many matrices to skip before - /// finding one that satisfy all the requirements. - const PARAMS_OPT_FOR_CONSTRAINTS: [RescueDefaultConfigEntry; 1]; - - /// An array of the parameters optimized for weights - /// (rate, alpha, full_rounds, partial_rounds, skip_matrices) - /// for rate = 2, 3, 4, 5, 6, 7, 8 - const PARAMS_OPT_FOR_WEIGHTS: [RescueDefaultConfigEntry; 1]; -} - -/// A field with Rescue parameters associated -pub trait RescueDefaultConfigField: PrimeField { - /// Obtain the default Rescue parameters for this rate and for this prime field, - /// with a specific optimization goal. - fn get_default_rescue_parameters( - rate: usize, - optimized_for_weights: bool, - ) -> Option>; -} - -/// Internal function that uses the `RescueDefaultConfig` to compute the Rescue parameters. -pub fn get_default_rescue_parameters_internal, const N: usize>( - rate: usize, - optimized_for_weights: bool, -) -> Option>> { - let params_set = if !optimized_for_weights { - P::PARAMS_OPT_FOR_CONSTRAINTS - } else { - P::PARAMS_OPT_FOR_WEIGHTS - }; - - for param in params_set.iter() { - if param.rate == rate { - let (arc, mds) = find_rescue_ark_and_mds::>( - Fp::::MODULUS_BIT_SIZE as u64, - rate, - param.rounds as u64, - param.skip_matrices as u64, - ); - - return Some(RescueConfig { - rounds: param.rounds, - alpha: param.alpha, - alpha_inv: Fp::::inverse(&Fp::::from(param.alpha)).unwrap().into(), - arc, - mds, - rate: param.rate, - capacity: 1, - }); - } - } - - None -} - -/// Internal function that computes the ark and mds from the Rescue Grain LFSR. -pub fn find_rescue_ark_and_mds( - prime_bits: u64, - rate: usize, - rounds: u64, - skip_matrices: u64, -) -> (Vec>, Vec>) { - let mut lfsr = RescueGrainLFSR::new( - false, - prime_bits, - (rate + 1) as u64, - rounds, - ); - - let mut ark = Vec::>::with_capacity(rounds as usize); - for _ in 0..rounds { - ark.push(lfsr.get_field_elements_rejection_sampling(rate + 1)); - } - - let mut mds = Vec::>::with_capacity(rate + 1); - mds.resize(rate + 1, vec![F::zero(); rate + 1]); - for _ in 0..skip_matrices { - let _ = lfsr.get_field_elements_mod_p::(2 * (rate + 1)); - } - - // a qualifying matrix must satisfy the following requirements - // - there is no duplication among the elements in x or y - // - there is no i and j such that x[i] + y[j] = p - // - the resultant MDS passes all the three tests - - let xs = lfsr.get_field_elements_mod_p::(rate + 1); - let ys = lfsr.get_field_elements_mod_p::(rate + 1); - - for i in 0..(rate + 1) { - for j in 0..(rate + 1) { - mds[i][j] = (xs[i] + &ys[j]).inverse().unwrap(); - } - } - - (ark, mds) -} - -impl> RescueDefaultConfigField for Fp { - fn get_default_rescue_parameters( - rate: usize, - optimized_for_weights: bool, - ) -> Option> { - get_default_rescue_parameters_internal::(rate, optimized_for_weights) - } -} - -// #[cfg(test)] -// mod test { -// use crate::sponge::rescue::RescueDefaultConfigField; -// use crate::sponge::test::*; -// use ark_ff::MontFp; - -// #[test] -// fn bls12_381_fr_rescue_default_parameters_test() { -// // constraints -// let constraints_rate_2 = Fr::get_default_rescue_parameters(2, false).unwrap(); -// assert_eq!( -// constraints_rate_2.ark[0][0], -// MontFp!( -// "27117311055620256798560880810000042840428971800021819916023577129547249660720" -// ) -// ); -// assert_eq!( -// constraints_rate_2.mds[0][0], -// MontFp!( -// "26017457457808754696901916760153646963713419596921330311675236858336250747575" -// ) -// ); - -// let constraints_rate_3 = Fr::get_default_rescue_parameters(3, false).unwrap(); -// assert_eq!( -// constraints_rate_3.ark[0][0], -// MontFp!( -// "11865901593870436687704696210307853465124332568266803587887584059192277437537" -// ) -// ); -// assert_eq!( -// constraints_rate_3.mds[0][0], -// MontFp!( -// "18791275321793747281053101601584820964683215017313972132092847596434094368732" -// ) -// ); - -// let constraints_rate_4 = Fr::get_default_rescue_parameters(4, false).unwrap(); -// assert_eq!( -// constraints_rate_4.ark[0][0], -// MontFp!( -// "41775194144383840477168997387904574072980173775424253289429546852163474914621" -// ) -// ); -// assert_eq!( -// constraints_rate_4.mds[0][0], -// MontFp!( -// "42906651709148432559075674119637355642263148226238482628104108168707874713729" -// ) -// ); - -// let constraints_rate_5 = Fr::get_default_rescue_parameters(5, false).unwrap(); -// assert_eq!( -// constraints_rate_5.ark[0][0], -// MontFp!( -// "24877380261526996562448766783081897666376381975344509826094208368479247894723" -// ) -// ); -// assert_eq!( -// constraints_rate_5.mds[0][0], -// MontFp!( -// "30022080821787948421423927053079656488514459012053372877891553084525866347732" -// ) -// ); - -// let constraints_rate_6 = Fr::get_default_rescue_parameters(6, false).unwrap(); -// assert_eq!( -// constraints_rate_6.ark[0][0], -// MontFp!( -// "37928506567864057383105673253383925733025682403141583234734361541053005808936" -// ) -// ); -// assert_eq!( -// constraints_rate_6.mds[0][0], -// MontFp!( -// "49124738641420159156404016903087065194698370461819821829905285681776084204443" -// ) -// ); - -// let constraints_rate_7 = Fr::get_default_rescue_parameters(7, false).unwrap(); -// assert_eq!( -// constraints_rate_7.ark[0][0], -// MontFp!( -// "37848764121158464546907147011864524711588624175161409526679215525602690343051" -// ) -// ); -// assert_eq!( -// constraints_rate_7.mds[0][0], -// MontFp!( -// "28113878661515342855868752866874334649815072505130059513989633785080391114646" -// ) -// ); - -// let constraints_rate_8 = Fr::get_default_rescue_parameters(8, false).unwrap(); -// assert_eq!( -// constraints_rate_8.ark[0][0], -// MontFp!( -// "51456871630395278065627483917901523970718884366549119139144234240744684354360" -// ) -// ); -// assert_eq!( -// constraints_rate_8.mds[0][0], -// MontFp!( -// "12929023787467701044434927689422385731071756681420195282613396560814280256210" -// ) -// ); - -// // weights -// let weights_rate_2 = Fr::get_default_rescue_parameters(2, true).unwrap(); -// assert_eq!( -// weights_rate_2.ark[0][0], -// MontFp!( -// "25126470399169474618535500283750950727260324358529540538588217772729895991183" -// ) -// ); -// assert_eq!( -// weights_rate_2.mds[0][0], -// MontFp!( -// "46350838805835525240431215868760423854112287760212339623795708191499274188615" -// ) -// ); - -// let weights_rate_3 = Fr::get_default_rescue_parameters(3, true).unwrap(); -// assert_eq!( -// weights_rate_3.ark[0][0], -// MontFp!( -// "16345358380711600255519479157621098002794924491287389755192263320486827897573" -// ) -// ); -// assert_eq!( -// weights_rate_3.mds[0][0], -// MontFp!( -// "37432344439659887296708509941462699942272362339508052702346957525719991245918" -// ) -// ); - -// let weights_rate_4 = Fr::get_default_rescue_parameters(4, true).unwrap(); -// assert_eq!( -// weights_rate_4.ark[0][0], -// MontFp!("2997721997773001075802235431463112417440167809433966871891875582435098138600") -// ); -// assert_eq!( -// weights_rate_4.mds[0][0], -// MontFp!( -// "43959024692079347032841256941012668338943730711936867712802582656046301966186" -// ) -// ); - -// let weights_rate_5 = Fr::get_default_rescue_parameters(5, true).unwrap(); -// assert_eq!( -// weights_rate_5.ark[0][0], -// MontFp!( -// "28142027771717376151411984909531650866105717069245696861966432993496676054077" -// ) -// ); -// assert_eq!( -// weights_rate_5.mds[0][0], -// MontFp!( -// "13157425078305676755394500322568002504776463228389342308130514165393397413991" -// ) -// ); - -// let weights_rate_6 = Fr::get_default_rescue_parameters(6, true).unwrap(); -// assert_eq!( -// weights_rate_6.ark[0][0], -// MontFp!("7417004907071346600696060525974582183666365156576759507353305331252133694222") -// ); -// assert_eq!( -// weights_rate_6.mds[0][0], -// MontFp!( -// "51393878771453405560681338747290999206747890655420330824736778052231938173954" -// ) -// ); - -// let weights_rate_7 = Fr::get_default_rescue_parameters(7, true).unwrap(); -// assert_eq!( -// weights_rate_7.ark[0][0], -// MontFp!( -// "47093173418416013663709314805327945458844779999893881721688570889452680883650" -// ) -// ); -// assert_eq!( -// weights_rate_7.mds[0][0], -// MontFp!( -// "51455917624412053400160569105425532358410121118308957353565646758865245830775" -// ) -// ); - -// let weights_rate_8 = Fr::get_default_rescue_parameters(8, true).unwrap(); -// assert_eq!( -// weights_rate_8.ark[0][0], -// MontFp!( -// "16478680729975035007348178961232525927424769683353433314299437589237598655079" -// ) -// ); -// assert_eq!( -// weights_rate_8.mds[0][0], -// MontFp!( -// "39160448583049384229582837387246752222769278402304070376350288593586064961857" -// ) -// ); -// } -// } From 1623c70a84df9b1aef1cecbbf75f1f156fa963a9 Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Fri, 7 Feb 2025 14:53:28 -0500 Subject: [PATCH 03/17] fmt --- crypto-primitives/src/crh/rescue/mod.rs | 7 +-- .../src/crh/sha256/constraints.rs | 2 +- crypto-primitives/src/snark/constraints.rs | 2 +- .../src/sponge/constraints/mod.rs | 5 +- crypto-primitives/src/sponge/mod.rs | 5 +- .../src/sponge/rescue/constraints.rs | 49 ++++++++++--------- crypto-primitives/src/sponge/rescue/mod.rs | 1 - 7 files changed, 34 insertions(+), 37 deletions(-) diff --git a/crypto-primitives/src/crh/rescue/mod.rs b/crypto-primitives/src/crh/rescue/mod.rs index 93710947..84811ef3 100644 --- a/crypto-primitives/src/crh/rescue/mod.rs +++ b/crypto-primitives/src/crh/rescue/mod.rs @@ -9,13 +9,11 @@ use crate::{ use ark_ff::PrimeField; use ark_std::{borrow::Borrow, marker::PhantomData, rand::Rng}; - #[cfg(any(feature = "gr1cs", feature = "r1cs"))] pub mod constraints; - /// The Rescue collision-resistant hash function introduced in [SAD20][sad] -/// +/// /// [sad]: https://eprint.iacr.org/2020/1143.pdf pub struct CRH { field_phantom: PhantomData, @@ -50,9 +48,8 @@ impl CRHScheme for CRH { } } - /// The 2-to-1 version of the Rescue collision-resistant hash function introduced in [SAD20][sad] used in Merkle trees. -/// +/// /// [sad]: https://eprint.iacr.org/2020/1143.pdf pub struct TwoToOneCRH { field_phantom: PhantomData, diff --git a/crypto-primitives/src/crh/sha256/constraints.rs b/crypto-primitives/src/crh/sha256/constraints.rs index cdf7fc59..acf46890 100644 --- a/crypto-primitives/src/crh/sha256/constraints.rs +++ b/crypto-primitives/src/crh/sha256/constraints.rs @@ -385,7 +385,7 @@ mod test { use crate::crh::{sha256::digest::Digest, CRHScheme, TwoToOneCRHScheme}; use ark_bls12_377::Fr; - use ark_relations::{ns, gr1cs::ConstraintSystem}; + use ark_relations::{gr1cs::ConstraintSystem, ns}; use ark_std::rand::RngCore; const TEST_LENGTHS: &[usize] = &[ diff --git a/crypto-primitives/src/snark/constraints.rs b/crypto-primitives/src/snark/constraints.rs index 4a2e98b6..6033b966 100644 --- a/crypto-primitives/src/snark/constraints.rs +++ b/crypto-primitives/src/snark/constraints.rs @@ -10,11 +10,11 @@ use ark_r1cs_std::{ prelude::*, }; use ark_relations::{ - lc, ns, gr1cs::{ ConstraintSynthesizer, ConstraintSystemRef, LinearCombination, Namespace, OptimizationGoal, SynthesisError, }, + lc, ns, }; use ark_snark::{CircuitSpecificSetupSNARK, UniversalSetupSNARK, SNARK}; #[cfg(not(feature = "std"))] diff --git a/crypto-primitives/src/sponge/constraints/mod.rs b/crypto-primitives/src/sponge/constraints/mod.rs index a08e715c..4a9356f8 100644 --- a/crypto-primitives/src/sponge/constraints/mod.rs +++ b/crypto-primitives/src/sponge/constraints/mod.rs @@ -14,8 +14,8 @@ use ark_r1cs_std::{ GR1CSVar, }; use ark_relations::{ - lc, gr1cs::{ConstraintSystemRef, LinearCombination, SynthesisError}, + lc, }; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -78,7 +78,8 @@ pub fn bits_le_to_emulated<'a, F: PrimeField, CF: PrimeField>( let gadget = AllocatedFp::new_witness(ark_relations::ns!(cs, "alloc"), || Ok(val[k])).unwrap(); lc[k] = lc[k].clone() - (CF::one(), gadget.variable); - cs.enforce_r1cs_constraint(lc!(), lc!(), lc[k].clone()).unwrap(); + cs.enforce_r1cs_constraint(lc!(), lc!(), lc[k].clone()) + .unwrap(); limbs.push(FpVar::::from(gadget)); } diff --git a/crypto-primitives/src/sponge/mod.rs b/crypto-primitives/src/sponge/mod.rs index e324a2a5..48a096d1 100644 --- a/crypto-primitives/src/sponge/mod.rs +++ b/crypto-primitives/src/sponge/mod.rs @@ -9,9 +9,8 @@ pub mod constraints; mod absorb; pub use absorb::*; - -/// The sponge for [Rescue][sad] -/// +/// The sponge for [Rescue][sad] +/// /// [sad]: https://eprint.iacr.org/2020/1143.pdf pub mod rescue; diff --git a/crypto-primitives/src/sponge/rescue/constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs index dcaa8996..512d2cd6 100644 --- a/crypto-primitives/src/sponge/rescue/constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -1,12 +1,11 @@ - use crate::sponge::constraints::AbsorbGadget; use crate::sponge::constraints::{CryptographicSpongeVar, SpongeWithGadget}; use crate::sponge::rescue::{RescueConfig, RescueSponge}; use crate::sponge::DuplexSpongeMode; -use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError}; use ark_ff::PrimeField; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::prelude::*; +use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; @@ -37,7 +36,6 @@ impl SpongeWithGadget for RescueSponge { } impl RescueSpongeVar { - #[cfg(feature = "gr1cs")] fn apply_s_box( &self, @@ -48,44 +46,47 @@ impl RescueSpongeVar { ) -> Result<(), SynthesisError> { use ark_relations::lc; let cs = state[0].cs(); - - if [alpha] == exponent { + if [alpha] == exponent { for state_item in state.iter_mut() { - let new_state_item = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); - match (&state_item,&new_state_item) { - (FpVar::Var(alloc_fp),FpVar::Var(new_alloc_fp)) => { - let _ = cs.enforce_constraint("XXX",vec![lc!()+ alloc_fp.variable,lc!()+new_alloc_fp.variable], ); + let new_state_item = + FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))) + .unwrap(); + match (&state_item, &new_state_item) { + (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { + let _ = cs.enforce_constraint( + "XXX", + vec![lc!() + alloc_fp.variable, lc!() + new_alloc_fp.variable], + ); *state_item = new_state_item; - } _ => { *state_item = state_item.pow_by_constant(exponent)?; } } } - } else { for state_item in state.iter_mut() { - let new_state_item = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); - match (&state_item,&new_state_item) { - (FpVar::Var(alloc_fp),FpVar::Var(new_alloc_fp)) => { - let _ = cs.enforce_constraint("XXX", vec![lc!()+ new_alloc_fp.variable,lc!()+alloc_fp.variable], ); - - }, + let new_state_item = + FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))) + .unwrap(); + match (&state_item, &new_state_item) { + (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { + let _ = cs.enforce_constraint( + "XXX", + vec![lc!() + new_alloc_fp.variable, lc!() + alloc_fp.variable], + ); + } _ => { *state_item = state_item.pow_by_constant(exponent)?; } } *state_item = new_state_item; - } } Ok(()) - } - #[cfg(feature = "r1cs")] fn apply_s_box( &self, @@ -94,21 +95,21 @@ impl RescueSpongeVar { alpha: u64, // round: usize ) -> Result<(), SynthesisError> { - if [alpha] == exponent { for state_item in state.iter_mut() { *state_item = state_item.pow_by_constant(exponent)?; } } else { for state_item in state.iter_mut() { - let output = FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))).unwrap(); - let expected_input = output.pow_by_constant([alpha]).unwrap(); + let output = + FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))) + .unwrap(); + let expected_input = output.pow_by_constant([alpha]).unwrap(); expected_input.enforce_equal(state_item)?; *state_item = output; } } Ok(()) - } fn apply_ark(&self, state: &mut [FpVar], round_key: &Vec) -> Result<(), SynthesisError> { diff --git a/crypto-primitives/src/sponge/rescue/mod.rs b/crypto-primitives/src/sponge/rescue/mod.rs index 7f49cbad..0c984f1f 100644 --- a/crypto-primitives/src/sponge/rescue/mod.rs +++ b/crypto-primitives/src/sponge/rescue/mod.rs @@ -15,7 +15,6 @@ pub mod constraints; use num_bigint::BigUint; - /// Config and RNG used #[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] pub struct RescueConfig { From 4d574404c601393aa7a3adbcfcc8e1425d5100ca Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Wed, 12 Feb 2025 16:50:43 -0500 Subject: [PATCH 04/17] work --- crypto-primitives/Cargo.toml | 2 +- .../src/crh/rescue/constraints.rs | 32 ++-------------- crypto-primitives/src/crh/rescue/mod.rs | 6 +-- .../src/sponge/rescue/constraints.rs | 2 +- crypto-primitives/src/sponge/rescue/mod.rs | 37 +++++++++++++++++++ 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index 64978876..8607c70e 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -29,7 +29,7 @@ digest = { version = "0.10", default-features = false } merlin = { version = "3.0.0", default-features = false, optional = true } num-bigint = "0.4.4" ark-r1cs-std = { path = "../../r1cs-std", optional = true, default-features = false} -ark-snark = { version = "^0.5.0", default-features = false } +ark-snark = { path = "../../snark/snark/", default-features = false } rayon = { version = "1.0", optional = true } derivative = { version = "2.0", features = ["use_core"] } diff --git a/crypto-primitives/src/crh/rescue/constraints.rs b/crypto-primitives/src/crh/rescue/constraints.rs index 396382ce..3470f72d 100644 --- a/crypto-primitives/src/crh/rescue/constraints.rs +++ b/crypto-primitives/src/crh/rescue/constraints.rs @@ -94,7 +94,7 @@ impl TwoToOneCRHGadgetTrait, F> for TwoTo let mut sponge = RescueSpongeVar::new(cs, ¶meters.parameters); sponge.absorb(left_input)?; sponge.absorb(right_input)?; - let res = sponge.squeeze_field_elements(1)?; + let res = sponge.squeeze_field_elements(parameters.parameters.output_size)?; Ok(res[0].clone()) } } @@ -118,54 +118,30 @@ impl AllocVar, F> for CRHParametersVar::new(12, 5, alpha_inv, mds, ark, 3, 1); + let params = RescueConfig::::test_conf(); let crh_a = CRH::::evaluate(¶ms, test_a.clone()).unwrap(); let crh_b = CRH::::evaluate(¶ms, test_b.clone()).unwrap(); let crh = TwoToOneCRH::::compress(¶ms, crh_a, crh_b).unwrap(); diff --git a/crypto-primitives/src/crh/rescue/mod.rs b/crypto-primitives/src/crh/rescue/mod.rs index 84811ef3..5c5fdd41 100644 --- a/crypto-primitives/src/crh/rescue/mod.rs +++ b/crypto-primitives/src/crh/rescue/mod.rs @@ -8,7 +8,7 @@ use crate::{ }; use ark_ff::PrimeField; use ark_std::{borrow::Borrow, marker::PhantomData, rand::Rng}; - +use ark_std::vec::Vec; #[cfg(any(feature = "gr1cs", feature = "r1cs"))] pub mod constraints; @@ -43,7 +43,7 @@ impl CRHScheme for CRH { let mut sponge = RescueSponge::new(parameters); sponge.absorb(&input); - let res = sponge.squeeze_field_elements::(1); + let res: Vec = sponge.squeeze_field_elements::(parameters.output_size); Ok(res[0]) } } @@ -91,7 +91,7 @@ impl TwoToOneCRHScheme for TwoToOneCRH { let mut sponge = RescueSponge::new(parameters); sponge.absorb(left_input); sponge.absorb(right_input); - let res = sponge.squeeze_field_elements::(1); + let res = sponge.squeeze_field_elements::(parameters.output_size); Ok(res[0]) } } diff --git a/crypto-primitives/src/sponge/rescue/constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs index 512d2cd6..bc5d449d 100644 --- a/crypto-primitives/src/sponge/rescue/constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -36,7 +36,7 @@ impl SpongeWithGadget for RescueSponge { } impl RescueSpongeVar { - #[cfg(feature = "gr1cs")] + #[cfg(all(feature = "gr1cs", not(feature = "r1cs")))] fn apply_s_box( &self, state: &mut [FpVar], diff --git a/crypto-primitives/src/sponge/rescue/mod.rs b/crypto-primitives/src/sponge/rescue/mod.rs index 0c984f1f..d6ca0d4d 100644 --- a/crypto-primitives/src/sponge/rescue/mod.rs +++ b/crypto-primitives/src/sponge/rescue/mod.rs @@ -13,6 +13,7 @@ use ark_std::vec::Vec; #[cfg(any(feature = "gr1cs", feature = "r1cs"))] pub mod constraints; +// use digest::Output; use num_bigint::BigUint; /// Config and RNG used @@ -35,6 +36,8 @@ pub struct RescueConfig { pub rate: usize, /// The capacity (in terms of number of field elements). pub capacity: usize, + // /// The number of field elements to output. + pub output_size: usize, } #[derive(Clone)] @@ -173,6 +176,7 @@ impl RescueConfig { arc: Vec>, rate: usize, capacity: usize, + output_size: usize, ) -> Self { assert_eq!(arc.len(), 2 * rounds + 1); for item in &arc { @@ -190,8 +194,41 @@ impl RescueConfig { arc, rate, capacity, + output_size, } } + + + // This is a temporary config to use for Garuda and Pari Benchamrks + // It has several issues inclusing: alpha is fixed to 5 now. It shouldn't be fixed. + // Also, the output length is not used at the moment and only one output is returned. + #[allow(clippy::too_many_arguments)] + pub fn test_conf() -> Self + where + num_bigint::BigUint: std::convert::From<::BigInt>, + { + let mut test_rng = ark_std::test_rng(); + + // The following way of generating the MDS matrix is incorrect + // and is only for test purposes. + + let mut mds = vec![vec![]; 4]; + for i in 0..4 { + for _ in 0..4 { + mds[i].push(F::rand(&mut test_rng)); + } + } + + let mut ark = vec![vec![]; 25]; + for i in 0..25 { + for _ in 0..4 { + ark[i].push(F::rand(&mut test_rng)); + } + } + let modulus = BigUint::from(F::MODULUS); + let alpha_inv = BigUint::from(5u8.into()).modinv(&(&modulus-BigUint::from(1u8.into()))).unwrap(); + Self::new(12, 5, alpha_inv, mds, ark, 3, 1, 1) + } } impl CryptographicSponge for RescueSponge { From 5d5a5dc3dc6a6089ff64b6bdeb703f9997bf782d Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Fri, 7 Mar 2025 11:35:47 -0500 Subject: [PATCH 05/17] work --- crypto-primitives/src/sponge/rescue/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto-primitives/src/sponge/rescue/mod.rs b/crypto-primitives/src/sponge/rescue/mod.rs index d6ca0d4d..79d31579 100644 --- a/crypto-primitives/src/sponge/rescue/mod.rs +++ b/crypto-primitives/src/sponge/rescue/mod.rs @@ -205,7 +205,7 @@ impl RescueConfig { #[allow(clippy::too_many_arguments)] pub fn test_conf() -> Self where - num_bigint::BigUint: std::convert::From<::BigInt>, + num_bigint::BigUint: ark_std::convert::From<::BigInt>, { let mut test_rng = ark_std::test_rng(); From 48bd818bb5b31f8f198d44688bbb908fc0f6ac66 Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Wed, 12 Mar 2025 19:29:47 -0400 Subject: [PATCH 06/17] work --- crypto-primitives/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index 8607c70e..3f1db591 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -20,7 +20,7 @@ ark-crypto-primitives-macros = { version = "^0.5.0", path = "../macros" } ark-ff = { version = "^0.5.0", default-features = false } ark-ec = { version = "^0.5.0", default-features = false } ark-std = { version = "^0.5.0", default-features = false } -ark-relations = { path = "../../snark/relations/", default-features = true } +ark-relations = { git = "https://github.com/alireza-shirzad/snark.git", default-features = true } ark-serialize = { version = "^0.5.0", default-features = false, features = [ "derive" ] } blake2 = { version = "0.10", default-features = false } @@ -28,8 +28,8 @@ sha2 = { version = "0.10", default-features = false } digest = { version = "0.10", default-features = false } merlin = { version = "3.0.0", default-features = false, optional = true } num-bigint = "0.4.4" -ark-r1cs-std = { path = "../../r1cs-std", optional = true, default-features = false} -ark-snark = { path = "../../snark/snark/", default-features = false } +ark-r1cs-std = {git = "https://github.com/alireza-shirzad/r1cs-std.git", default-features = true, optional = true} +ark-snark = { git = "https://github.com/alireza-shirzad/snark.git", default-features = true } rayon = { version = "1.0", optional = true } derivative = { version = "2.0", features = ["use_core"] } From c8be045198e06f69d35fafb76f680bc52baf486f Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Mon, 17 Mar 2025 14:29:46 -0400 Subject: [PATCH 07/17] ci fixed --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32c9e9b7..b57a2238 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: toolchain: ${{ matrix.rust }} override: true - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry @@ -108,7 +108,7 @@ jobs: target: aarch64-unknown-none override: true - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry From 8ede34674cc0db39da4958f17a295dc50c08ce7a Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Wed, 19 Mar 2025 20:22:28 -0400 Subject: [PATCH 08/17] update dependencies in Cargo.toml --- crypto-primitives/Cargo.toml | 77 +++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index 3f1db591..86488e9d 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -20,32 +20,45 @@ ark-crypto-primitives-macros = { version = "^0.5.0", path = "../macros" } ark-ff = { version = "^0.5.0", default-features = false } ark-ec = { version = "^0.5.0", default-features = false } ark-std = { version = "^0.5.0", default-features = false } -ark-relations = { git = "https://github.com/alireza-shirzad/snark.git", default-features = true } -ark-serialize = { version = "^0.5.0", default-features = false, features = [ "derive" ] } +ark-relations = { version = "0.5.0", default-features = true } +ark-serialize = { version = "^0.5.0", default-features = false, features = [ + "derive", +] } blake2 = { version = "0.10", default-features = false } sha2 = { version = "0.10", default-features = false } digest = { version = "0.10", default-features = false } merlin = { version = "3.0.0", default-features = false, optional = true } num-bigint = "0.4.4" -ark-r1cs-std = {git = "https://github.com/alireza-shirzad/r1cs-std.git", default-features = true, optional = true} -ark-snark = { git = "https://github.com/alireza-shirzad/snark.git", default-features = true } +ark-r1cs-std = { version = "0.5.0", default-features = true, optional = true } +ark-snark = { version = "0.5.0", default-features = true } rayon = { version = "1.0", optional = true } derivative = { version = "2.0", features = ["use_core"] } -tracing = { version = "0.1", default-features = false, features = [ "attributes" ], optional = true } -hashbrown = { version = "0.14", default-features = false, features = ["inline-more", "allocator-api2"], optional = true } +tracing = { version = "0.1", default-features = false, features = [ + "attributes", +], optional = true } +hashbrown = { version = "0.14", default-features = false, features = [ + "inline-more", + "allocator-api2", +], optional = true } [features] default = ["std"] -std = [ "ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std" ] -print-trace = [ "ark-std/print-trace" ] -parallel = [ "std", "rayon", "ark-ec/parallel", "ark-std/parallel", "ark-ff/parallel" ] -r1cs = [ "ark-r1cs-std", "tracing" ] -gr1cs = [ "ark-r1cs-std", "tracing" ] -crh = [ "sponge" ] -sponge = [ "merlin" ] -commitment = [ "crh" ] +std = ["ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std"] +print-trace = ["ark-std/print-trace"] +parallel = [ + "std", + "rayon", + "ark-ec/parallel", + "ark-std/parallel", + "ark-ff/parallel", +] +r1cs = ["ark-r1cs-std", "tracing"] +gr1cs = ["ark-r1cs-std", "tracing"] +crh = ["sponge"] +sponge = ["merlin"] +commitment = ["crh"] merkle_tree = ["crh", "hashbrown"] encryption = [] prf = [] @@ -53,7 +66,7 @@ snark = [] signature = [] [target.'cfg(all(target_has_atomic = "8", target_has_atomic = "16", target_has_atomic = "32", target_has_atomic = "64", target_has_atomic = "ptr"))'.dependencies] -ahash = { version = "0.8", default-features = false} +ahash = { version = "0.8", default-features = false } [target.'cfg(not(all(target_has_atomic = "8", target_has_atomic = "16", target_has_atomic = "32", target_has_atomic = "64", target_has_atomic = "ptr")))'.dependencies] fnv = { version = "1.0", default-features = false } @@ -61,9 +74,15 @@ fnv = { version = "1.0", default-features = false } [dev-dependencies] ark-ed-on-bls12-377 = { version = "^0.5.0", default-features = false } ark-ed-on-bls12-381 = { version = "^0.5.0", default-features = false } -ark-bls12-377 = { version = "^0.5.0", default-features = false, features = [ "curve"] } -ark-bls12-381 = { version = "^0.5.0", default-features = false, features = [ "curve"] } -ark-mnt4-298 = { version = "^0.5.0", default-features = false, features = [ "curve"] } +ark-bls12-377 = { version = "^0.5.0", default-features = false, features = [ + "curve", +] } +ark-bls12-381 = { version = "^0.5.0", default-features = false, features = [ + "curve", +] } +ark-mnt4-298 = { version = "^0.5.0", default-features = false, features = [ + "curve", +] } ark-mnt6-298 = { version = "^0.5.0", default-features = false } criterion = { version = "0.4" } @@ -73,28 +92,40 @@ criterion = { version = "0.4" } name = "pedersen_crh" path = "benches/crh.rs" harness = false -required-features = [ "crh" ] +required-features = ["crh"] [[bench]] name = "pedersen_comm" path = "benches/comm.rs" harness = false -required-features = [ "commitment" ] +required-features = ["commitment"] [[bench]] name = "blake2s_prf" path = "benches/prf.rs" harness = false -required-features = [ "prf" ] +required-features = ["prf"] [[bench]] name = "schnorr_sig" path = "benches/signature.rs" harness = false -required-features = [ "signature" ] +required-features = ["signature"] [[bench]] name = "merkle_tree" path = "benches/merkle_tree.rs" harness = false -required-features = [ "merkle_tree" ] +required-features = ["merkle_tree"] + + +[patch.crates-io] +ark-relations = { git = "https://github.com/arkworks-rs/snark.git" } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std.git" } +ark-snark = { git = "https://github.com/arkworks-rs/snark.git" } +ark-ed-on-bls12-377 = { git = "https://github.com/arkworks-rs/algebra.git" } +ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/algebra.git" } +ark-bls12-377 = { git = "https://github.com/arkworks-rs/algebra.git" } +ark-bls12-381 = { git = "https://github.com/arkworks-rs/algebra.git" } +ark-mnt4-298 = { git = "https://github.com/arkworks-rs/algebra.git" } +ark-mnt6-298 = { git = "https://github.com/arkworks-rs/algebra.git" } From 6e9daac9bbe46a190ec7c49d530727bee16ca39e Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 20 Mar 2025 12:20:49 -0400 Subject: [PATCH 09/17] Tweak --- crypto-primitives/Cargo.toml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index 86488e9d..b4c5e1d6 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -117,15 +117,3 @@ name = "merkle_tree" path = "benches/merkle_tree.rs" harness = false required-features = ["merkle_tree"] - - -[patch.crates-io] -ark-relations = { git = "https://github.com/arkworks-rs/snark.git" } -ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std.git" } -ark-snark = { git = "https://github.com/arkworks-rs/snark.git" } -ark-ed-on-bls12-377 = { git = "https://github.com/arkworks-rs/algebra.git" } -ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/algebra.git" } -ark-bls12-377 = { git = "https://github.com/arkworks-rs/algebra.git" } -ark-bls12-381 = { git = "https://github.com/arkworks-rs/algebra.git" } -ark-mnt4-298 = { git = "https://github.com/arkworks-rs/algebra.git" } -ark-mnt6-298 = { git = "https://github.com/arkworks-rs/algebra.git" } From f42c033906cd78d311ff112dbd6cf26d0e1063c0 Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Sat, 12 Apr 2025 10:23:36 -0400 Subject: [PATCH 10/17] patch --- Cargo.toml | 15 +++++++++------ crypto-primitives/Cargo.toml | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c378d3d1..fe9acf0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,15 @@ [workspace] -members = [ - "crypto-primitives", - "macros", -] +members = ["crypto-primitives", "macros"] resolver = "2" [workspace.package] version = "0.5.0" -authors = [ "arkworks contributors" ] +authors = ["arkworks contributors"] description = "A library of useful cryptographic primitives" homepage = "https://arkworks.rs" repository = "https://github.com/arkworks-rs/crypto-primitives" documentation = "https://docs.rs/ark-crypto-primitives/" -keywords = [ "gr1cs", "pedersen", "blake2s", "snark", "schnorr" ] +keywords = ["gr1cs", "pedersen", "blake2s", "snark", "schnorr"] categories = ["cryptography"] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" @@ -42,3 +39,9 @@ lto = "thin" incremental = true debug-assertions = true debug = true + + +[patch.crates-io] +ark-relations = { git = "https://github.com/alireza-shirzad/snark" } +ark-r1cs-std = { git = "https://github.com/alireza-shirzad/r1cs-std" } +ark-snark = { git = "https://github.com/alireza-shirzad/snark" } diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index b4c5e1d6..d20b0870 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -117,3 +117,4 @@ name = "merkle_tree" path = "benches/merkle_tree.rs" harness = false required-features = ["merkle_tree"] + From 208ce207c248b9543959e78a51262a228997da5d Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Sat, 12 Apr 2025 10:42:24 -0400 Subject: [PATCH 11/17] work --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fe9acf0d..7f0752e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,6 @@ debug = true [patch.crates-io] -ark-relations = { git = "https://github.com/alireza-shirzad/snark" } -ark-r1cs-std = { git = "https://github.com/alireza-shirzad/r1cs-std" } -ark-snark = { git = "https://github.com/alireza-shirzad/snark" } +ark-relations = { git = "https://github.com/arkworks-rs/snark" } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std" } +ark-snark = { git = "https://github.com/arkworks-rs/snark" } From c9508305a1ece0155dbd5081e0121f41313496d4 Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Sat, 12 Apr 2025 10:52:54 -0400 Subject: [PATCH 12/17] work --- Cargo.toml | 5 ----- crypto-primitives/Cargo.toml | 7 +++---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7f0752e5..8b2cb9be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,8 +40,3 @@ incremental = true debug-assertions = true debug = true - -[patch.crates-io] -ark-relations = { git = "https://github.com/arkworks-rs/snark" } -ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std" } -ark-snark = { git = "https://github.com/arkworks-rs/snark" } diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index d20b0870..9d708622 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -20,7 +20,7 @@ ark-crypto-primitives-macros = { version = "^0.5.0", path = "../macros" } ark-ff = { version = "^0.5.0", default-features = false } ark-ec = { version = "^0.5.0", default-features = false } ark-std = { version = "^0.5.0", default-features = false } -ark-relations = { version = "0.5.0", default-features = true } +ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = true } ark-serialize = { version = "^0.5.0", default-features = false, features = [ "derive", ] } @@ -30,8 +30,8 @@ sha2 = { version = "0.10", default-features = false } digest = { version = "0.10", default-features = false } merlin = { version = "3.0.0", default-features = false, optional = true } num-bigint = "0.4.4" -ark-r1cs-std = { version = "0.5.0", default-features = true, optional = true } -ark-snark = { version = "0.5.0", default-features = true } +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = true, optional = true } +ark-snark = { git = "https://github.com/arkworks-rs/snark", default-features = true } rayon = { version = "1.0", optional = true } derivative = { version = "2.0", features = ["use_core"] } @@ -117,4 +117,3 @@ name = "merkle_tree" path = "benches/merkle_tree.rs" harness = false required-features = ["merkle_tree"] - From 84d59a3817503673004d5e12f31e35a9d5897b56 Mon Sep 17 00:00:00 2001 From: Alireza Shirzad Date: Sat, 12 Apr 2025 11:01:40 -0400 Subject: [PATCH 13/17] work --- crypto-primitives/Cargo.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crypto-primitives/Cargo.toml b/crypto-primitives/Cargo.toml index 9d708622..49682f54 100644 --- a/crypto-primitives/Cargo.toml +++ b/crypto-primitives/Cargo.toml @@ -72,18 +72,18 @@ ahash = { version = "0.8", default-features = false } fnv = { version = "1.0", default-features = false } [dev-dependencies] -ark-ed-on-bls12-377 = { version = "^0.5.0", default-features = false } -ark-ed-on-bls12-381 = { version = "^0.5.0", default-features = false } -ark-bls12-377 = { version = "^0.5.0", default-features = false, features = [ +ark-ed-on-bls12-377 = { git = "https://github.com/arkworks-rs/algebra", default-features = false } +ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/algebra", default-features = false } +ark-bls12-377 = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = [ "curve", ] } -ark-bls12-381 = { version = "^0.5.0", default-features = false, features = [ +ark-bls12-381 = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = [ "curve", ] } -ark-mnt4-298 = { version = "^0.5.0", default-features = false, features = [ +ark-mnt4-298 = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = [ "curve", ] } -ark-mnt6-298 = { version = "^0.5.0", default-features = false } +ark-mnt6-298 = { git = "https://github.com/arkworks-rs/algebra", default-features = false } criterion = { version = "0.4" } ################################# Benchmarks ################################## From 953272964d02dcca7c1c39fb4b0b441b30b4323d Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 14 Apr 2025 20:04:32 -0400 Subject: [PATCH 14/17] Tweak --- crypto-primitives/src/sponge/rescue/constraints.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crypto-primitives/src/sponge/rescue/constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs index bc5d449d..fd8af943 100644 --- a/crypto-primitives/src/sponge/rescue/constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -50,8 +50,7 @@ impl RescueSpongeVar { if [alpha] == exponent { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))) - .unwrap(); + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent)))?; match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( @@ -68,8 +67,7 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))) - .unwrap(); + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent)))?; match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( @@ -102,8 +100,7 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let output = - FpVar::new_witness(self.cs(), || Ok(state_item.value()?.pow(exponent))) - .unwrap(); + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent)))?; let expected_input = output.pow_by_constant([alpha]).unwrap(); expected_input.enforce_equal(state_item)?; *state_item = output; From 792b1a8273eafbdcc6b88ae6aa020023491a8cfb Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 14 Apr 2025 20:06:43 -0400 Subject: [PATCH 15/17] Tweak --- crypto-primitives/src/sponge/rescue/constraints.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto-primitives/src/sponge/rescue/constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs index fd8af943..35e8c5d0 100644 --- a/crypto-primitives/src/sponge/rescue/constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -50,7 +50,7 @@ impl RescueSpongeVar { if [alpha] == exponent { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent)))?; + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( @@ -67,7 +67,7 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent)))?; + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( @@ -100,7 +100,7 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let output = - FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent)))?; + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); let expected_input = output.pow_by_constant([alpha]).unwrap(); expected_input.enforce_equal(state_item)?; *state_item = output; From f4d6c906c96aae0f7d2e4efb1a0e96de4a8ab3c0 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 14 Apr 2025 20:08:55 -0400 Subject: [PATCH 16/17] Tweak --- crypto-primitives/src/sponge/rescue/constraints.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto-primitives/src/sponge/rescue/constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs index 35e8c5d0..d820e364 100644 --- a/crypto-primitives/src/sponge/rescue/constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -50,7 +50,7 @@ impl RescueSpongeVar { if [alpha] == exponent { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); + FpVar::new_witness(self.cs(), || dbg!(state_item.value()).map(|e| e.pow(exponent))).unwrap(); match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( @@ -67,7 +67,7 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); + FpVar::new_witness(self.cs(), || dbg!(state_item.value()).map(|e| e.pow(exponent))).unwrap(); match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( From d9e0a1d15b32661954e6c2654e9cabb0c5743938 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 14 Apr 2025 23:10:59 -0400 Subject: [PATCH 17/17] Tweak --- crypto-primitives/src/sponge/rescue/constraints.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto-primitives/src/sponge/rescue/constraints.rs b/crypto-primitives/src/sponge/rescue/constraints.rs index d820e364..35e8c5d0 100644 --- a/crypto-primitives/src/sponge/rescue/constraints.rs +++ b/crypto-primitives/src/sponge/rescue/constraints.rs @@ -50,7 +50,7 @@ impl RescueSpongeVar { if [alpha] == exponent { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || dbg!(state_item.value()).map(|e| e.pow(exponent))).unwrap(); + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint( @@ -67,7 +67,7 @@ impl RescueSpongeVar { } else { for state_item in state.iter_mut() { let new_state_item = - FpVar::new_witness(self.cs(), || dbg!(state_item.value()).map(|e| e.pow(exponent))).unwrap(); + FpVar::new_witness(self.cs(), || state_item.value().map(|e| e.pow(exponent))).unwrap(); match (&state_item, &new_state_item) { (FpVar::Var(alloc_fp), FpVar::Var(new_alloc_fp)) => { let _ = cs.enforce_constraint(