diff --git a/halo2-gadgets/Cargo.toml b/halo2-gadgets/Cargo.toml index a28a26a2..9bedda1d 100644 --- a/halo2-gadgets/Cargo.toml +++ b/halo2-gadgets/Cargo.toml @@ -6,6 +6,3 @@ members = [ "halo2_poseidon", "sinsemilla", ] - -[patch.crates-io] -halo2 = { git = "https://github.com/zcash/halo2.git", rev = "27c4187673a9c6ade13fbdbd4f20955530c22d7f" } diff --git a/halo2-gadgets/halo2_ecc/Cargo.toml b/halo2-gadgets/halo2_ecc/Cargo.toml index ed3139f2..54485cca 100644 --- a/halo2-gadgets/halo2_ecc/Cargo.toml +++ b/halo2-gadgets/halo2_ecc/Cargo.toml @@ -20,7 +20,7 @@ arrayvec = "0.7.0" bigint = "4" ff = "0.11" group = "0.11" -halo2 = "0.0" +halo2 = "=0.1.0-beta.1" lazy_static = "1" pasta_curves = "0.2.1" rand = "0.8" diff --git a/halo2-gadgets/halo2_ecc/src/chip.rs b/halo2-gadgets/halo2_ecc/src/chip.rs index 69fa02d7..cf242f21 100644 --- a/halo2-gadgets/halo2_ecc/src/chip.rs +++ b/halo2-gadgets/halo2_ecc/src/chip.rs @@ -86,7 +86,7 @@ impl EccPoint { self.y } - #[cfg(test)] + #[cfg(feature = "testing")] fn is_identity(&self) -> Option { self.x.value().map(|x| x == pallas::Base::zero()) } @@ -103,17 +103,6 @@ pub struct NonIdentityEccPoint { } impl NonIdentityEccPoint { - /// Constructs a point from its coordinates, without checking they are on the curve. - /// - /// This is an internal API that we only use where we know we have a valid non-identity - /// curve point (specifically inside Sinsemilla). - pub(in crate::circuit::gadget) fn from_coordinates_unchecked( - x: CellValue, - y: CellValue, - ) -> Self { - NonIdentityEccPoint { x, y } - } - /// Returns the value of this curve point, if known. pub fn point(&self) -> Option { match (self.x.value(), self.y.value()) { @@ -447,6 +436,81 @@ impl> EccInstructions for Ecc ) } + fn copy_point( + &self, + layouter: &mut impl Layouter, + point: Self::Point, + ) -> Result { + let config: witness_point::Config = self.config().into(); + let (x, y) = layouter.assign_region( + || "copy point", + |mut region| { + let x = { + let cell = region.assign_advice( + || "copy x", + config.x, + 0, + || point.x().value().ok_or(Error::SynthesisError), + )?; + region.constrain_equal(cell, point.x().cell())?; + CellValue::new(cell, point.x().value()) + }; + let y = { + let cell = region.assign_advice( + || "copy y", + config.y, + 0, + || point.y().value().ok_or(Error::SynthesisError), + )?; + region.constrain_equal(cell, point.y().cell())?; + CellValue::new(cell, point.y().value()) + }; + + Ok((x, y)) + }, + )?; + + Ok(EccPoint { x, y }) + } + + fn copy_point_non_id( + &self, + layouter: &mut impl Layouter, + x: Self::Var, + y: Self::Var, + ) -> Result { + let config: witness_point::Config = self.config().into(); + let (x, y) = layouter.assign_region( + || "copy point", + |mut region| { + let x = { + let cell = region.assign_advice( + || "copy x", + config.x, + 0, + || x.value().ok_or(Error::SynthesisError), + )?; + region.constrain_equal(cell, x.cell())?; + CellValue::new(cell, x.value()) + }; + let y = { + let cell = region.assign_advice( + || "copy y", + config.y, + 0, + || y.value().ok_or(Error::SynthesisError), + )?; + region.constrain_equal(cell, y.cell())?; + CellValue::new(cell, y.value()) + }; + + Ok((x, y)) + }, + )?; + + Ok(NonIdentityEccPoint { x, y }) + } + fn extract_p + Clone>(point: &Point) -> Self::X { let point: EccPoint = (point.clone()).into(); point.x() diff --git a/halo2-gadgets/halo2_ecc/src/chip/add.rs b/halo2-gadgets/halo2_ecc/src/chip/add.rs index 2f7eb8aa..62a8b4c9 100644 --- a/halo2-gadgets/halo2_ecc/src/chip/add.rs +++ b/halo2-gadgets/halo2_ecc/src/chip/add.rs @@ -391,7 +391,10 @@ pub mod tests { use halo2::{circuit::Layouter, plonk::Error}; use pasta_curves::{arithmetic::CurveExt, pallas}; - use crate::gadget::{EccInstructions, NonIdentityPoint}; + use crate::{ + chip::EccPoint, + gadget::{EccInstructions, NonIdentityPoint, Point}, + }; #[allow(clippy::too_many_arguments)] pub fn test_add< diff --git a/halo2-gadgets/halo2_ecc/src/chip/add_incomplete.rs b/halo2-gadgets/halo2_ecc/src/chip/add_incomplete.rs index 8695c495..8a9acd7a 100644 --- a/halo2-gadgets/halo2_ecc/src/chip/add_incomplete.rs +++ b/halo2-gadgets/halo2_ecc/src/chip/add_incomplete.rs @@ -145,11 +145,13 @@ impl Config { #[cfg(feature = "testing")] pub mod tests { - use group::{prime::PrimeCurveAffine, Curve, Group}; + use group::{Curve, Group}; use halo2::{circuit::Layouter, plonk::Error}; use pasta_curves::pallas; - use crate::gadget::{EccInstructions, NonIdentityPoint}; + use crate::{ + gadget::{EccInstructions, NonIdentityPoint}, + }; #[allow(clippy::too_many_arguments)] pub fn test_add_incomplete< @@ -171,15 +173,6 @@ pub mod tests { // Make sure P and Q are not the same point. assert_ne!(p_val, q_val); - // Generate a (0,0) point to be used in other tests. - let zero = { - Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Some(pallas::Affine::identity()), - )? - }; - // P + Q { let result = p.add_incomplete(layouter.namespace(|| "P + Q"), &q)?; diff --git a/halo2-gadgets/halo2_ecc/src/chip/mul.rs b/halo2-gadgets/halo2_ecc/src/chip/mul.rs index 5116ecb6..a42307b1 100644 --- a/halo2-gadgets/halo2_ecc/src/chip/mul.rs +++ b/halo2-gadgets/halo2_ecc/src/chip/mul.rs @@ -444,7 +444,7 @@ fn decompose_for_scalar_mul(scalar: Option) -> Vec> { #[cfg(feature = "testing")] pub mod tests { - use group::{prime::PrimeCurveAffine, Curve, Group}; + use group::{Curve, Group}; use halo2::{ circuit::{Chip, Layouter}, plonk::Error, @@ -452,7 +452,7 @@ pub mod tests { use pasta_curves::{arithmetic::FieldExt, pallas}; use crate::{ - chip::EccChip, + chip::{EccChip, EccPoint}, gadget::{EccInstructions, FixedPoints, NonIdentityPoint, Point}, }; use utilities::UtilitiesInstructions; @@ -465,15 +465,6 @@ pub mod tests { let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P let p = NonIdentityPoint::new(chip.clone(), layouter.namespace(|| "P"), Some(p_val))?; - // Generate a (0,0) point to be used in other tests. - let zero = { - Point::new( - chip.clone(), - layouter.namespace(|| "identity"), - Some(pallas::Affine::identity()), - )? - }; - let column = chip.config().advices[0]; fn constrain_equal_non_id< diff --git a/halo2-gadgets/halo2_ecc/src/chip/mul_fixed/short.rs b/halo2-gadgets/halo2_ecc/src/chip/mul_fixed/short.rs index 167702ba..df54b407 100644 --- a/halo2-gadgets/halo2_ecc/src/chip/mul_fixed/short.rs +++ b/halo2-gadgets/halo2_ecc/src/chip/mul_fixed/short.rs @@ -364,7 +364,7 @@ pub mod tests { *magnitude, *sign, )?; - value_commit_v.mul_short(layouter.namespace(|| *name), magnitude_sign)? + base.mul_short(layouter.namespace(|| *name), magnitude_sign)? }; assert!(result.inner().is_identity().unwrap()); } diff --git a/halo2-gadgets/halo2_ecc/src/chip/witness_point.rs b/halo2-gadgets/halo2_ecc/src/chip/witness_point.rs index 27388e30..dd6c7c78 100644 --- a/halo2-gadgets/halo2_ecc/src/chip/witness_point.rs +++ b/halo2-gadgets/halo2_ecc/src/chip/witness_point.rs @@ -8,7 +8,6 @@ use halo2::{ poly::Rotation, }; use pasta_curves::{arithmetic::CurveAffine, pallas}; -use utilities::copy; #[derive(Clone, Debug)] pub struct Config { @@ -147,20 +146,20 @@ impl Config { } } -#[cfg(test)] +#[cfg(feature = "testing")] pub mod tests { use halo2::circuit::Layouter; use pasta_curves::pallas; use super::*; - use crate::circuit::gadget::ecc::{EccInstructions, NonIdentityPoint}; + use crate::gadget::{EccInstructions, NonIdentityPoint}; pub fn test_witness_non_id< EccChip: EccInstructions + Clone + Eq + std::fmt::Debug, >( chip: EccChip, mut layouter: impl Layouter, - ) { + ) -> Result<(), Error> { // Witnessing the identity should return an error. NonIdentityPoint::new( chip, @@ -168,23 +167,7 @@ pub mod tests { Some(pallas::Affine::identity()), ) .expect_err("witnessing 𝒪 should return an error"); - } - pub(super) fn copy_point( - &self, - x: CellValue, - y: CellValue, - offset: usize, - region: &mut Region<'_, pallas::Base>, - ) -> Result { - // Enable `q_point` selector - self.q_point.enable(region, offset)?; - - // Copy `x` value - let x = copy(region, || "x", self.x, offset, &x)?; - // Copy `y` value - let y = copy(region, || "y", self.y, offset, &y)?; - - Ok(EccPoint { x, y }) + Ok(()) } } diff --git a/halo2-gadgets/halo2_ecc/src/gadget.rs b/halo2-gadgets/halo2_ecc/src/gadget.rs index 13c385b8..1aaa864f 100644 --- a/halo2-gadgets/halo2_ecc/src/gadget.rs +++ b/halo2-gadgets/halo2_ecc/src/gadget.rs @@ -1,9 +1,9 @@ //! Gadgets for elliptic curve operations. +use pasta_curves::arithmetic::CurveAffine; use std::fmt::Debug; use halo2::{ - arithmetic::CurveAffine, circuit::{Chip, Layouter}, plonk::Error, }; @@ -79,11 +79,19 @@ pub trait EccInstructions: /// checking that the coordinates indeed belong to a valid point. /// This maps the identity to (0, 0) in affine coordinates. fn copy_point( + &self, + layouter: &mut impl Layouter, + point: Self::Point, + ) -> Result; + + /// Copies a point given existing x- and y-coordinate variables, + /// checking that the coordinates indeed belong to a valid point. + fn copy_point_non_id( &self, layouter: &mut impl Layouter, x: Self::Var, y: Self::Var, - ) -> Result; + ) -> Result; /// Extracts the x-coordinate of a point. fn extract_p + Clone>(point: &Point) -> Self::X; @@ -199,17 +207,6 @@ impl> NonIdentityPoint { point.map(|inner| NonIdentityPoint { chip, inner }) } - /// Constructs a new point by copying in its coordinates as `x`, `y` cells. - pub fn copy( - chip: EccChip, - mut layouter: impl Layouter, - x: EccChip::Var, - y: EccChip::Var, - ) -> Result { - let point = chip.copy_point(&mut layouter, x, y); - point.map(|inner| Point { chip, inner }) - } - /// Constrains this point to be equal in value to another point. pub fn constrain_equal> + Clone>( &self, @@ -224,6 +221,17 @@ impl> NonIdentityPoint { ) } + /// Constructs a new point by copying in its coordinates as `x`, `y` cells. + pub fn copy( + chip: EccChip, + mut layouter: impl Layouter, + x: EccChip::Var, + y: EccChip::Var, + ) -> Result { + let point = chip.copy_point_non_id(&mut layouter, x, y); + point.map(|inner| NonIdentityPoint { chip, inner }) + } + /// Returns the inner point. pub fn inner(&self) -> &EccChip::NonIdentityPoint { &self.inner @@ -338,6 +346,16 @@ impl + Clone + Debug + Eq> Point, + point: EccChip::Point, + ) -> Result { + let point = chip.copy_point(&mut layouter, point); + point.map(|inner| Point { chip, inner }) + } + /// Returns the inner point. pub fn inner(&self) -> &EccChip::Point { &self.inner diff --git a/halo2-gadgets/halo2_poseidon/Cargo.toml b/halo2-gadgets/halo2_poseidon/Cargo.toml index d33f8653..04dd3339 100644 --- a/halo2-gadgets/halo2_poseidon/Cargo.toml +++ b/halo2-gadgets/halo2_poseidon/Cargo.toml @@ -21,7 +21,7 @@ pprof = { version = "0.4.2", features = ["criterion", "flamegraph"] } [dependencies] bitvec = "0.22" ff = "0.11" -halo2 = { version = "0.0", optional = true } +halo2 = { version = "=0.1.0-beta.1", optional = true } pasta_curves = "0.2.1" rand = "0.8" utilities = { package = "halo2_utilities", version = "0.0", path = "../halo2_utilities" } diff --git a/halo2-gadgets/halo2_utilities/Cargo.toml b/halo2-gadgets/halo2_utilities/Cargo.toml index d06774ee..79c6b44d 100644 --- a/halo2-gadgets/halo2_utilities/Cargo.toml +++ b/halo2-gadgets/halo2_utilities/Cargo.toml @@ -18,7 +18,7 @@ publish = false [dependencies] bigint = "4" ff = "0.11" -halo2 = "0.0" +halo2 = "=0.1.0-beta.1" pasta_curves = "0.2.1" proptest = { version = "1.0.0", optional = true } rand = "0.8" diff --git a/halo2-gadgets/sinsemilla/Cargo.toml b/halo2-gadgets/sinsemilla/Cargo.toml index a9128e1f..b66e062a 100644 --- a/halo2-gadgets/sinsemilla/Cargo.toml +++ b/halo2-gadgets/sinsemilla/Cargo.toml @@ -22,7 +22,7 @@ pprof = { version = "0.4.2", features = ["criterion", "flamegraph"] } ecc = { package = "halo2_ecc", version = "0.0", path = "../halo2_ecc" } ff = "0.11" group = "0.11" -halo2 = { version = "0.0", optional = true } +halo2 = { version = "=0.1.0-beta.1", optional = true } lazy_static = "1" pasta_curves = "0.2.1" rand = "0.8" diff --git a/halo2-gadgets/sinsemilla/src/chip.rs b/halo2-gadgets/sinsemilla/src/chip.rs index 016d7d17..aeb4d5bb 100644 --- a/halo2-gadgets/sinsemilla/src/chip.rs +++ b/halo2-gadgets/sinsemilla/src/chip.rs @@ -1,5 +1,5 @@ use super::{ - gadget::{self, CommitDomains, HashDomains, SinsemillaInstructions}, + gadget::{CommitDomains, HashDomains, SinsemillaInstructions, Point as PointTrait}, message::{Message, MessagePiece}, primitive as sinsemilla, }; @@ -26,12 +26,12 @@ mod hash_to_point; /// A point output by hash_to_point #[derive(Clone, Debug)] -struct Point { +pub struct Point { x: CellValue, y: CellValue, } -impl gadget::Point> for Point { +impl PointTrait> for Point { fn x(&self) -> CellValue { self.x } diff --git a/halo2-gadgets/sinsemilla/src/gadget.rs b/halo2-gadgets/sinsemilla/src/gadget.rs index 861a2e70..dbe33b7f 100644 --- a/halo2-gadgets/sinsemilla/src/gadget.rs +++ b/halo2-gadgets/sinsemilla/src/gadget.rs @@ -231,7 +231,7 @@ pub struct HashDomain< SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, - NonIdentityPoint = >::NonIdentityPoint, + // NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, Var = SinsemillaChip::Var, > + Clone @@ -249,7 +249,7 @@ where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, - NonIdentityPoint = >::NonIdentityPoint, + // NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, Var = SinsemillaChip::Var, > + Clone @@ -340,7 +340,7 @@ pub struct CommitDomain< SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, - NonIdentityPoint = >::NonIdentityPoint, + // NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, Var = SinsemillaChip::Var, > + Clone @@ -357,7 +357,7 @@ where SinsemillaChip: SinsemillaInstructions + Clone + Debug + Eq, EccChip: EccInstructions< C, - NonIdentityPoint = >::NonIdentityPoint, + // NonIdentityPoint = >::NonIdentityPoint, FixedPoints = >::FixedPoints, Var = SinsemillaChip::Var, > + Clone @@ -614,8 +614,8 @@ pub mod testing { None }; - NonIdentityPoint::new( - ecc_chip, + Point::new( + ecc_chip.clone(), layouter.namespace(|| "Witness expected result"), expected_result, )? diff --git a/halo2-gadgets/sinsemilla/src/merkle.rs b/halo2-gadgets/sinsemilla/src/merkle.rs index e635d118..d4416ecb 100644 --- a/halo2-gadgets/sinsemilla/src/merkle.rs +++ b/halo2-gadgets/sinsemilla/src/merkle.rs @@ -164,26 +164,20 @@ where pub mod testing { use super::{ chip::{MerkleChip, MerkleConfig}, - i2lebsp, MerklePath, L_PALLAS_BASE, MERKLE_DEPTH, + MerklePath, MERKLE_DEPTH, }; use crate::{ chip::SinsemillaChip, gadget::{CommitDomains, HashDomains}, - primitive::HashDomain, }; use ecc::gadget::FixedPoints; use utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions, Var}; - use ff::PrimeFieldBits; - use group::prime::PrimeCurveAffine; use halo2::{ circuit::{Layouter, SimpleFloorPlanner}, - dev::MockProver, - note::commitment::ExtractedNoteCommitment, plonk::{Circuit, ConstraintSystem, Error}, - tree, }; use pasta_curves::pallas; @@ -313,25 +307,29 @@ pub mod testing { path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?; if let Some(leaf_pos) = self.leaf_pos { - let domain = HashDomain { - Q: S::hash_domain().Q().to_curve(), - }; - // The expected final root - let final_root = { - let path = tree::MerklePath::new(leaf_pos, self.merkle_path.unwrap()); - let leaf = ExtractedNoteCommitment::from_bytes(&self.leaf.unwrap().to_bytes()) - .unwrap(); - path.root(leaf) - }; + let final_root = S::root( + self.merkle_path.unwrap(), + leaf_pos, + self.leaf.unwrap(), + ); // Check the computed final root against the expected final root. - assert_eq!(computed_final_root.value().unwrap(), final_root.inner()); + assert_eq!(computed_final_root.value().unwrap(), final_root); } Ok(()) } } + + pub trait MerkleTest> { + fn hash_domain() -> Hash; + fn root( + path: [pallas::Base; MERKLE_DEPTH], + leaf_pos: u32, + leaf: pallas::Base, + ) -> pallas::Base; + } } #[cfg(feature = "testing")] @@ -344,9 +342,11 @@ pub mod tests { use crate::{ gadget::{CommitDomains, HashDomains}, + merkle::{i2lebsp, L_PALLAS_BASE, MERKLE_DEPTH}, primitive::{CommitDomain, HashDomain}, }; + use ff::PrimeFieldBits; use group::Curve; use pasta_curves::pallas; @@ -406,11 +406,50 @@ pub mod tests { fn hash_domain() -> Hash { Hash } + + fn root(path: [pallas::Base; MERKLE_DEPTH], + leaf_pos: u32, + leaf: pallas::Base,) -> pallas::Base { + use group::prime::PrimeCurveAffine; + let domain = HashDomain { Q: Self::hash_domain().Q().to_curve() }; + let pos_bool = i2lebsp::<32>(leaf_pos as u64); + + // Compute the root + let mut node = leaf; + for (l, (sibling, pos)) in path.iter().zip(pos_bool.iter()).enumerate() { + let (left, right) = if *pos { + (*sibling, node) + } else { + (node, *sibling) + }; + + let l_star = i2lebsp::<10>(l as u64); + let left: Vec<_> = left + .to_le_bits() + .iter() + .by_val() + .take(L_PALLAS_BASE) + .collect(); + let right: Vec<_> = right + .to_le_bits() + .iter() + .by_val() + .take(L_PALLAS_BASE) + .collect(); + + let mut message = l_star.to_vec(); + message.extend_from_slice(&left); + message.extend_from_slice(&right); + + node = domain.hash(message.into_iter()).unwrap(); + } + node + } } #[test] fn merkle_chip() { - use crate::merkle::{i2lebsp, MERKLE_DEPTH}; + use crate::merkle::{MERKLE_DEPTH}; use halo2::dev::MockProver; use pasta_curves::arithmetic::FieldExt; use rand::random; diff --git a/src/circuit.rs b/src/circuit.rs index 13a3f6d9..57db698c 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -15,8 +15,7 @@ use pasta_curves::{ use crate::{ constants::{ - util::gen_const_array, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, - MERKLE_DEPTH_ORCHARD, + OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, MERKLE_DEPTH_ORCHARD, }, keys::{ CommitIvkRandomness, DiversifiedTransmissionKey, NullifierDerivingKey, SpendValidatingKey, @@ -48,7 +47,8 @@ use sinsemilla::{ }, }; use utilities::{ - copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var, + copy, gen_const_array, lookup_range_check::LookupRangeCheckConfig, CellValue, + UtilitiesInstructions, Var, }; use std::convert::TryInto; @@ -411,7 +411,7 @@ impl plonk::Circuit for Circuit { config.merkle_chip_2(), OrchardHashDomains::MerkleCrh, self.pos, - self.path, + path, ); let leaf = *cm_old.extract_p().inner(); merkle_inputs.calculate_root(layouter.namespace(|| "MerkleCRH"), leaf)? diff --git a/src/constants/sinsemilla.rs b/src/constants/sinsemilla.rs index b36ccabf..7825d839 100644 --- a/src/constants/sinsemilla.rs +++ b/src/constants/sinsemilla.rs @@ -303,6 +303,7 @@ fn test_orchard_domains() { #[cfg(feature = "test-ecc")] #[test] fn test_merkle_crh() { + use crate::constants::MERKLE_DEPTH_ORCHARD; use halo2::dev::MockProver; use rand::random; use sinsemilla::merkle::testing; @@ -313,6 +314,17 @@ fn test_merkle_crh() { fn hash_domain() -> OrchardHashDomains { OrchardHashDomains::MerkleCrh } + + fn root( + path: [pallas::Base; MERKLE_DEPTH_ORCHARD], + leaf_pos: u32, + leaf: pallas::Base, + ) -> pallas::Base { + use crate::{note::ExtractedNoteCommitment, tree::MerklePath}; + let path = MerklePath::new(leaf_pos, path); + let leaf = ExtractedNoteCommitment::from_bytes(&leaf.to_bytes()).unwrap(); + path.root(leaf).inner() + } } // Choose a random leaf and position diff --git a/src/tree.rs b/src/tree.rs index 2d011889..28706f8b 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -7,10 +7,10 @@ use crate::{ }, note::commitment::ExtractedNoteCommitment, }; -use halo2_utilities::utilities::gen_const_array_with_default; use incrementalmerkletree::{Altitude, Hashable}; use pasta_curves::{arithmetic::FieldExt, pallas}; use sinsemilla::primitive::HashDomain; +use utilities::gen_const_array_with_default; use ff::{Field, PrimeField, PrimeFieldBits}; use lazy_static::lazy_static;