diff --git a/src/bin/bench_gmimc.rs b/src/bin/bench_gmimc.rs index 42c1b78a..69296942 100644 --- a/src/bin/bench_gmimc.rs +++ b/src/bin/bench_gmimc.rs @@ -4,8 +4,7 @@ use std::time::Instant; use plonky2::field::crandall_field::CrandallField; use plonky2::field::field_types::Field; -use plonky2::hash::gmimc::gmimc_permute_array; -use plonky2::hash::hashing::{GMIMC_CONSTANTS, GMIMC_ROUNDS}; +use plonky2::hash::gmimc::GMiMC; type F = CrandallField; @@ -26,7 +25,7 @@ fn main() { let hashes_per_thread = HASHES_PER_POLY * PROVER_POLYS / THREADS; let start = Instant::now(); for _ in 0..hashes_per_thread { - x = gmimc_permute_array::<_, W, GMIMC_ROUNDS>(x, GMIMC_CONSTANTS); + x = F::gmimc_permute(x); } let duration = start.elapsed(); println!("took {:?}", duration); diff --git a/src/bin/bench_hash.rs b/src/bin/bench_hash.rs index 81ec126e..b44da485 100644 --- a/src/bin/bench_hash.rs +++ b/src/bin/bench_hash.rs @@ -2,14 +2,16 @@ use std::time::Instant; use plonky2::field::crandall_field::CrandallField as F; use plonky2::field::field_types::Field; -use plonky2::hash::gmimc::gmimc_permute_array; -use plonky2::hash::hashing::{GMIMC_CONSTANTS, GMIMC_ROUNDS}; -use plonky2::hash::poseidon::PoseidonInterface; +use plonky2::hash::gmimc::GMiMC; +use plonky2::hash::poseidon::Poseidon; use plonky2::hash::rescue::rescue; #[inline] -fn gmimc_hash(x: [F; W]) -> [F; W] { - gmimc_permute_array::<_, W, GMIMC_ROUNDS>(x, GMIMC_CONSTANTS) +fn gmimc_hash(x: [F; W]) -> [F; W] +where + F: GMiMC, +{ + F::gmimc_permute(x) } #[inline] @@ -70,7 +72,7 @@ fn bench_hash(name: &str, hash: fn([F; W]) -> [F; W], gmimc_tm: fn main() { println!(" -- Width 8 (time μs, slowdown wrt GMiMC)--"); let mut tm: f64 = 0.0; - bench_hash("GMiMC", gmimc_hash::<8>, &mut tm); + // bench_hash("GMiMC", gmimc_hash::<8>, &mut tm); // Not implemented yet. bench_hash("Poseidon", poseidon8_hash, &mut tm); bench_hash("Poseidon naive", poseidon8_naive_hash, &mut tm); diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 8995543b..117403fc 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -3,7 +3,7 @@ use env_logger::Env; use log::info; use plonky2::field::crandall_field::CrandallField; use plonky2::field::extension_field::Extendable; -use plonky2::field::field_types::PrimeField; +use plonky2::field::field_types::RichField; use plonky2::fri::FriConfig; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; @@ -19,7 +19,7 @@ fn main() -> Result<()> { bench_prove::() } -fn bench_prove, const D: usize>() -> Result<()> { +fn bench_prove, const D: usize>() -> Result<()> { let config = CircuitConfig { num_wires: 126, num_routed_wires: 33, diff --git a/src/field/crandall_field.rs b/src/field/crandall_field.rs index b3d96bbe..05b17318 100644 --- a/src/field/crandall_field.rs +++ b/src/field/crandall_field.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::field::extension_field::quadratic::QuadraticCrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::extension_field::{Extendable, Frobenius}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, PrimeField, RichField}; /// EPSILON = 9 * 2**28 - 1 const EPSILON: u64 = 2415919103; @@ -458,7 +458,9 @@ impl Extendable<4> for CrandallField { type Extension = QuarticCrandallField; } -/// Faster addition for when we know that lhs.0 + rhs.0 < 2^64 + Self::ORDER. If this is the case, +impl RichField for CrandallField {} + +/// Faster addition for when we know that lhs.0 + rhs.0 < 2^64 + FIELD_ORDER. If this is the case, /// then the .to_canonical_u64() that addition usually performs is unnecessary. Omitting it saves /// three instructions. /// This function is marked unsafe because it may yield incorrect result if the condition is not diff --git a/src/field/extension_field/target.rs b/src/field/extension_field/target.rs index 0970d65e..a40013fa 100644 --- a/src/field/extension_field/target.rs +++ b/src/field/extension_field/target.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::field::extension_field::algebra::ExtensionAlgebra; use crate::field::extension_field::{Extendable, FieldExtension, OEF}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -16,14 +16,14 @@ impl ExtensionTarget { self.0 } - pub fn frobenius>( + pub fn frobenius>( &self, builder: &mut CircuitBuilder, ) -> Self { self.repeated_frobenius(1, builder) } - pub fn repeated_frobenius>( + pub fn repeated_frobenius>( &self, count: usize, builder: &mut CircuitBuilder, @@ -74,7 +74,7 @@ impl ExtensionAlgebraTarget { } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn constant_extension(&mut self, c: F::Extension) -> ExtensionTarget { let c_parts = c.to_basefield_array(); let mut parts = [self.zero(); D]; diff --git a/src/field/field_testing.rs b/src/field/field_testing.rs index 7bf7702e..c08c555e 100644 --- a/src/field/field_testing.rs +++ b/src/field/field_testing.rs @@ -1,5 +1,3 @@ -use crate::field::field_types::PrimeField; - #[macro_export] macro_rules! test_field_arithmetic { ($field:ty) => { diff --git a/src/field/field_types.rs b/src/field/field_types.rs index 82f86c65..62313826 100644 --- a/src/field/field_types.rs +++ b/src/field/field_types.rs @@ -11,8 +11,12 @@ use serde::de::DeserializeOwned; use serde::Serialize; use crate::field::extension_field::Frobenius; +use crate::hash::gmimc::GMiMC; use crate::util::bits_u64; +/// A prime order field with the features we need to use it as a base field in our argument system. +pub trait RichField: PrimeField + GMiMC<12> {} + /// A finite field. pub trait Field: 'static @@ -309,6 +313,10 @@ pub trait Field: Self::rand_from_rng(&mut rand::thread_rng()) } + fn rand_arr() -> [Self; N] { + Self::rand_vec(N).try_into().unwrap() + } + fn rand_vec(n: usize) -> Vec { (0..n).map(|_| Self::rand()).collect() } diff --git a/src/fri/commitment.rs b/src/fri/commitment.rs index 10ced5d9..99182ee6 100644 --- a/src/fri/commitment.rs +++ b/src/fri/commitment.rs @@ -2,7 +2,7 @@ use rayon::prelude::*; use crate::field::extension_field::Extendable; use crate::field::fft::DEFAULT_STRATEGY; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::fri::proof::FriProof; use crate::fri::prover::fri_proof; use crate::hash::merkle_tree::MerkleTree; @@ -20,7 +20,7 @@ use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transp pub const SALT_SIZE: usize = 2; /// Represents a batch FRI based commitment to a list of polynomials. -pub struct PolynomialBatchCommitment { +pub struct PolynomialBatchCommitment { pub polynomials: Vec>, pub merkle_tree: MerkleTree, pub degree_log: usize, @@ -28,7 +28,7 @@ pub struct PolynomialBatchCommitment { pub blinding: bool, } -impl PolynomialBatchCommitment { +impl PolynomialBatchCommitment { /// Creates a list polynomial commitment for the polynomials interpolating the values in `values`. pub(crate) fn from_values( values: Vec>, @@ -125,7 +125,7 @@ impl PolynomialBatchCommitment { timing: &mut TimingTree, ) -> (FriProof, OpeningSet) where - F: PrimeField + Extendable, + F: RichField + Extendable, { let config = &common_data.config; assert!(D > 1, "Not implemented for D=1."); @@ -280,7 +280,7 @@ mod tests { point } - fn check_batch_polynomial_commitment, const D: usize>( + fn check_batch_polynomial_commitment, const D: usize>( ) -> Result<()> { let ks = [10, 2, 10, 8]; let degree_bits = 11; diff --git a/src/fri/prover.rs b/src/fri/prover.rs index eb397b71..a0d71d98 100644 --- a/src/fri/prover.rs +++ b/src/fri/prover.rs @@ -1,7 +1,7 @@ use rayon::prelude::*; use crate::field::extension_field::{flatten, unflatten, Extendable}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::RichField; use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound, FriQueryStep}; use crate::fri::FriConfig; use crate::hash::hash_types::HashOut; @@ -16,7 +16,7 @@ use crate::util::reverse_index_bits_in_place; use crate::util::timing::TimingTree; /// Builds a FRI proof. -pub fn fri_proof, const D: usize>( +pub fn fri_proof, const D: usize>( initial_merkle_trees: &[&MerkleTree], // Coefficients of the polynomial on which the LDT is performed. Only the first `1/rate` coefficients are non-zero. lde_polynomial_coeffs: PolynomialCoeffs, @@ -66,7 +66,7 @@ pub fn fri_proof, const D: usize>( } } -fn fri_committed_trees, const D: usize>( +fn fri_committed_trees, const D: usize>( mut coeffs: PolynomialCoeffs, mut values: PolynomialValues, challenger: &mut Challenger, @@ -110,7 +110,7 @@ fn fri_committed_trees, const D: usize>( (trees, coeffs) } -fn fri_proof_of_work(current_hash: HashOut, config: &FriConfig) -> F { +fn fri_proof_of_work(current_hash: HashOut, config: &FriConfig) -> F { (0..=F::NEG_ONE.to_canonical_u64()) .into_par_iter() .find_any(|&i| { @@ -131,7 +131,7 @@ fn fri_proof_of_work(current_hash: HashOut, config: &FriConfig .expect("Proof of work failed. This is highly unlikely!") } -fn fri_prover_query_rounds, const D: usize>( +fn fri_prover_query_rounds, const D: usize>( initial_merkle_trees: &[&MerkleTree], trees: &[MerkleTree], challenger: &mut Challenger, @@ -143,7 +143,7 @@ fn fri_prover_query_rounds, const D: usize>( .collect() } -fn fri_prover_query_round, const D: usize>( +fn fri_prover_query_round, const D: usize>( initial_merkle_trees: &[&MerkleTree], trees: &[MerkleTree], challenger: &mut Challenger, diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index ed75d142..2c0d009f 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::target::{flatten_target, ExtensionTarget}; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget}; use crate::fri::FriConfig; use crate::hash::hash_types::MerkleCapTarget; @@ -14,7 +14,7 @@ use crate::util::reducing::ReducingFactorTarget; use crate::util::{log2_strict, reverse_index_bits_in_place}; use crate::with_context; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity /// and P' is the FRI reduced polynomial. fn compute_evaluation( @@ -394,7 +394,7 @@ struct PrecomputedReducedEvalsTarget { } impl PrecomputedReducedEvalsTarget { - fn from_os_and_alpha>( + fn from_os_and_alpha>( os: &OpeningSetTarget, alpha: ExtensionTarget, degree_log: usize, diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index 4479a65b..e14e586f 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -1,7 +1,7 @@ use anyhow::{ensure, Result}; use crate::field::extension_field::{flatten, Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::field::interpolation::{barycentric_weights, interpolate, interpolate2}; use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound}; use crate::fri::FriConfig; @@ -44,7 +44,7 @@ fn compute_evaluation, const D: usize>( interpolate(&points, beta, &barycentric_weights) } -fn fri_verify_proof_of_work, const D: usize>( +fn fri_verify_proof_of_work, const D: usize>( proof: &FriProof, challenger: &mut Challenger, config: &FriConfig, @@ -68,7 +68,7 @@ fn fri_verify_proof_of_work, const D: usize>( Ok(()) } -pub fn verify_fri_proof, const D: usize>( +pub fn verify_fri_proof, const D: usize>( // Openings of the PLONK polynomials. os: &OpeningSet, // Point at which the PLONK polynomials are opened. @@ -136,7 +136,7 @@ pub fn verify_fri_proof, const D: usize>( Ok(()) } -fn fri_verify_initial_proof( +fn fri_verify_initial_proof( x_index: usize, proof: &FriInitialTreeProof, initial_merkle_caps: &[MerkleCap], @@ -179,7 +179,7 @@ impl, const D: usize> PrecomputedReducedEvals { } } -fn fri_combine_initial, const D: usize>( +fn fri_combine_initial, const D: usize>( proof: &FriInitialTreeProof, alpha: F::Extension, zeta: F::Extension, @@ -244,7 +244,7 @@ fn fri_combine_initial, const D: usize>( sum } -fn fri_verifier_query_round, const D: usize>( +fn fri_verifier_query_round, const D: usize>( zeta: F::Extension, alpha: F::Extension, precomputed_reduced_evals: PrecomputedReducedEvals, diff --git a/src/gadgets/arithmetic.rs b/src/gadgets/arithmetic.rs index b8f3e1f5..21214d27 100644 --- a/src/gadgets/arithmetic.rs +++ b/src/gadgets/arithmetic.rs @@ -1,12 +1,12 @@ use std::borrow::Borrow; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::exponentiation::ExponentiationGate; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Computes `-x`. pub fn neg(&mut self, x: Target) -> Target { let neg_one = self.neg_one(); diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index a5c3d47d..d7d668a6 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::field::extension_field::FieldExtension; use crate::field::extension_field::{Extendable, OEF}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; @@ -11,7 +11,7 @@ use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Finds the last available arithmetic gate with the given constants or add one if there aren't any. /// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index /// `g` and the gate's `i`-th operation is available. @@ -440,7 +440,7 @@ struct QuotientGeneratorExtension { quotient: ExtensionTarget, } -impl, const D: usize> SimpleGenerator +impl, const D: usize> SimpleGenerator for QuotientGeneratorExtension { fn dependencies(&self) -> Vec { @@ -465,7 +465,7 @@ pub struct PowersTarget { } impl PowersTarget { - pub fn next>( + pub fn next>( &mut self, builder: &mut CircuitBuilder, ) -> ExtensionTarget { @@ -474,7 +474,7 @@ impl PowersTarget { result } - pub fn repeated_frobenius>( + pub fn repeated_frobenius>( self, k: usize, builder: &mut CircuitBuilder, @@ -487,7 +487,7 @@ impl PowersTarget { } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn powers(&mut self, base: ExtensionTarget) -> PowersTarget { PowersTarget { base, diff --git a/src/gadgets/hash.rs b/src/gadgets/hash.rs index a0502981..48a728d7 100644 --- a/src/gadgets/hash.rs +++ b/src/gadgets/hash.rs @@ -1,22 +1,25 @@ use std::convert::TryInto; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::gmimc::GMiMCGate; -use crate::hash::hashing::GMIMC_ROUNDS; +use crate::hash::gmimc::GMiMC; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::plonk::circuit_builder::CircuitBuilder; // TODO: Move to be next to native `permute`? -impl, const D: usize> CircuitBuilder { - pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] { +impl, const D: usize> CircuitBuilder { + pub fn permute(&mut self, inputs: [Target; W]) -> [Target; W] + where + F: GMiMC, + { let zero = self.zero(); - let gate_type = GMiMCGate::::new_automatic_constants(); + let gate_type = GMiMCGate::::new(); let gate = self.add_gate(gate_type, vec![]); // We don't want to swap any inputs, so set that wire to 0. - let swap_wire = GMiMCGate::::WIRE_SWAP; + let swap_wire = GMiMCGate::::WIRE_SWAP; let swap_wire = Target::Wire(Wire { gate, input: swap_wire, @@ -24,8 +27,8 @@ impl, const D: usize> CircuitBuilder { self.connect(zero, swap_wire); // Route input wires. - for i in 0..12 { - let in_wire = GMiMCGate::::wire_input(i); + for i in 0..W { + let in_wire = GMiMCGate::::wire_input(i); let in_wire = Target::Wire(Wire { gate, input: in_wire, @@ -34,11 +37,11 @@ impl, const D: usize> CircuitBuilder { } // Collect output wires. - (0..12) + (0..W) .map(|i| { Target::Wire(Wire { gate, - input: GMiMCGate::::wire_output(i), + input: GMiMCGate::::wire_output(i), }) }) .collect::>() diff --git a/src/gadgets/insert.rs b/src/gadgets/insert.rs index 9220d822..f7a8d82f 100644 --- a/src/gadgets/insert.rs +++ b/src/gadgets/insert.rs @@ -1,11 +1,11 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::insertion::InsertionGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Inserts a `Target` in a vector at a non-deterministic index. /// Note: `index` is not range-checked. pub fn insert( diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index 899dbf64..94fa7525 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -1,11 +1,11 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::interpolation::InterpolationGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Interpolate a list of point/evaluation pairs at a given point. /// Returns the evaluation of the interpolated polynomial at `evaluation_point`. pub fn interpolate( diff --git a/src/gadgets/permutation.rs b/src/gadgets/permutation.rs index c47f5f23..126846ec 100644 --- a/src/gadgets/permutation.rs +++ b/src/gadgets/permutation.rs @@ -1,10 +1,8 @@ use std::collections::BTreeMap; use std::marker::PhantomData; -use crate::field::{ - extension_field::Extendable, - field_types::{Field, PrimeField}, -}; +use crate::field::field_types::RichField; +use crate::field::{extension_field::Extendable, field_types::Field}; use crate::gates::switch::SwitchGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; @@ -12,7 +10,7 @@ use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bimap::bimap_from_lists; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Assert that two lists of expressions evaluate to permutations of one another. pub fn assert_permutation(&mut self, a: Vec>, b: Vec>) { assert_eq!( diff --git a/src/gadgets/polynomial.rs b/src/gadgets/polynomial.rs index fb3fe96a..9f631c10 100644 --- a/src/gadgets/polynomial.rs +++ b/src/gadgets/polynomial.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::reducing::ReducingFactorTarget; @@ -12,7 +12,7 @@ impl PolynomialCoeffsExtTarget { self.0.len() } - pub fn eval_scalar>( + pub fn eval_scalar>( &self, builder: &mut CircuitBuilder, point: Target, @@ -22,7 +22,7 @@ impl PolynomialCoeffsExtTarget { point.reduce(&self.0, builder) } - pub fn eval>( + pub fn eval>( &self, builder: &mut CircuitBuilder, point: ExtensionTarget, @@ -41,7 +41,7 @@ impl PolynomialCoeffsExtAlgebraTarget { point: ExtensionTarget, ) -> ExtensionAlgebraTarget where - F: PrimeField + Extendable, + F: RichField + Extendable, { let mut acc = builder.zero_ext_algebra(); for &c in self.0.iter().rev() { @@ -56,7 +56,7 @@ impl PolynomialCoeffsExtAlgebraTarget { point: ExtensionAlgebraTarget, ) -> ExtensionAlgebraTarget where - F: PrimeField + Extendable, + F: RichField + Extendable, { let mut acc = builder.zero_ext_algebra(); for &c in self.0.iter().rev() { diff --git a/src/gadgets/random_access.rs b/src/gadgets/random_access.rs index 6e0a290c..1cd44db0 100644 --- a/src/gadgets/random_access.rs +++ b/src/gadgets/random_access.rs @@ -1,11 +1,11 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::random_access::RandomAccessGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Checks that a `Target` matches a vector at a non-deterministic index. /// Note: `index` is not range-checked. pub fn random_access( diff --git a/src/gadgets/range_check.rs b/src/gadgets/range_check.rs index f53b0a7b..547abe25 100644 --- a/src/gadgets/range_check.rs +++ b/src/gadgets/range_check.rs @@ -1,12 +1,12 @@ use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Checks that `x < 2^n_log` using a `BaseSumGate`. pub fn range_check(&mut self, x: Target, n_log: usize) { let gate = self.add_gate(BaseSumGate::<2>::new(n_log), vec![]); @@ -51,7 +51,7 @@ struct LowHighGenerator { high: Target, } -impl SimpleGenerator for LowHighGenerator { +impl SimpleGenerator for LowHighGenerator { fn dependencies(&self) -> Vec { vec![self.integer] } diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index e841d1d0..1e76eeb2 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -1,10 +1,10 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Selects `x` or `y` based on `b`, i.e., this returns `if b { x } else { y }`. pub fn select_ext( &mut self, diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index 4589bbc0..0d5c9906 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -1,14 +1,14 @@ use std::borrow::Borrow; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Split the given element into a list of targets, where each one represents a /// base-B limb of the element, with little-endian ordering. pub fn split_le_base(&mut self, x: Target, num_limbs: usize) -> Vec { diff --git a/src/gadgets/split_join.rs b/src/gadgets/split_join.rs index 0b091721..dddae0be 100644 --- a/src/gadgets/split_join.rs +++ b/src/gadgets/split_join.rs @@ -1,5 +1,5 @@ use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; @@ -7,7 +7,7 @@ use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Split the given integer into a list of wires, where each one represents a /// bit of the integer, with little-endian ordering. /// Verifies that the decomposition is correct by using `k` `BaseSum<2>` gates @@ -63,7 +63,7 @@ struct SplitGenerator { bits: Vec, } -impl SimpleGenerator for SplitGenerator { +impl SimpleGenerator for SplitGenerator { fn dependencies(&self) -> Vec { vec![self.integer] } @@ -91,7 +91,7 @@ struct WireSplitGenerator { num_limbs: usize, } -impl SimpleGenerator for WireSplitGenerator { +impl SimpleGenerator for WireSplitGenerator { fn dependencies(&self) -> Vec { vec![self.integer] } diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 23765a55..af939d0d 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::extension_field::FieldExtension; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -33,7 +33,7 @@ impl ArithmeticExtensionGate { } } -impl, const D: usize> Gate for ArithmeticExtensionGate { +impl, const D: usize> Gate for ArithmeticExtensionGate { fn id(&self) -> String { format!("{:?}", self) } @@ -143,14 +143,14 @@ impl, const D: usize> Gate for ArithmeticExt } #[derive(Clone, Debug)] -struct ArithmeticExtensionGenerator, const D: usize> { +struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, const_0: F, const_1: F, i: usize, } -impl, const D: usize> SimpleGenerator +impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator { fn dependencies(&self) -> Vec { diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index 801f9e26..896ac37d 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -2,7 +2,7 @@ use std::ops::Range; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -31,7 +31,7 @@ impl BaseSumGate { } } -impl, const D: usize, const B: usize> Gate for BaseSumGate { +impl, const D: usize, const B: usize> Gate for BaseSumGate { fn id(&self) -> String { format!("{:?} + Base: {}", self, B) } @@ -134,7 +134,7 @@ pub struct BaseSplitGenerator { num_limbs: usize, } -impl SimpleGenerator for BaseSplitGenerator { +impl SimpleGenerator for BaseSplitGenerator { fn dependencies(&self) -> Vec { vec![Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)] } diff --git a/src/gates/constant.rs b/src/gates/constant.rs index 1135e8a3..7b2a8f34 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -18,7 +18,7 @@ impl ConstantGate { pub const WIRE_OUTPUT: usize = 0; } -impl, const D: usize> Gate for ConstantGate { +impl, const D: usize> Gate for ConstantGate { fn id(&self) -> String { "ConstantGate".into() } diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index c9a410c7..0fc40044 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -14,12 +14,12 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate for raising a value to a power. #[derive(Clone, Debug)] -pub(crate) struct ExponentiationGate, const D: usize> { +pub(crate) struct ExponentiationGate, const D: usize> { pub num_power_bits: usize, pub _phantom: PhantomData, } -impl, const D: usize> ExponentiationGate { +impl, const D: usize> ExponentiationGate { pub fn new(num_power_bits: usize) -> Self { Self { num_power_bits, @@ -59,7 +59,7 @@ impl, const D: usize> ExponentiationGate { } } -impl, const D: usize> Gate for ExponentiationGate { +impl, const D: usize> Gate for ExponentiationGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -205,12 +205,12 @@ impl, const D: usize> Gate for Exponentiatio } #[derive(Debug)] -struct ExponentiationGenerator, const D: usize> { +struct ExponentiationGenerator, const D: usize> { gate_index: usize, gate: ExponentiationGate, } -impl, const D: usize> SimpleGenerator +impl, const D: usize> SimpleGenerator for ExponentiationGenerator { fn dependencies(&self) -> Vec { diff --git a/src/gates/gate.rs b/src/gates/gate.rs index 0b96b791..7369796f 100644 --- a/src/gates/gate.rs +++ b/src/gates/gate.rs @@ -4,14 +4,14 @@ use std::sync::Arc; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate_tree::Tree; use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A custom gate. -pub trait Gate, const D: usize>: 'static + Send + Sync { +pub trait Gate, const D: usize>: 'static + Send + Sync { fn id(&self) -> String; fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec; @@ -108,48 +108,48 @@ pub trait Gate, const D: usize>: 'static + Send + /// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. #[derive(Clone)] -pub struct GateRef, const D: usize>(pub(crate) Arc>); +pub struct GateRef, const D: usize>(pub(crate) Arc>); -impl, const D: usize> GateRef { +impl, const D: usize> GateRef { pub fn new>(gate: G) -> GateRef { GateRef(Arc::new(gate)) } } -impl, const D: usize> PartialEq for GateRef { +impl, const D: usize> PartialEq for GateRef { fn eq(&self, other: &Self) -> bool { self.0.id() == other.0.id() } } -impl, const D: usize> Hash for GateRef { +impl, const D: usize> Hash for GateRef { fn hash(&self, state: &mut H) { self.0.id().hash(state) } } -impl, const D: usize> Eq for GateRef {} +impl, const D: usize> Eq for GateRef {} -impl, const D: usize> Debug for GateRef { +impl, const D: usize> Debug for GateRef { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { write!(f, "{}", self.0.id()) } } /// A gate along with any constants used to configure it. -pub struct GateInstance, const D: usize> { +pub struct GateInstance, const D: usize> { pub gate_ref: GateRef, pub constants: Vec, } /// Map each gate to a boolean prefix used to construct the gate's selector polynomial. #[derive(Debug, Clone)] -pub struct PrefixedGate, const D: usize> { +pub struct PrefixedGate, const D: usize> { pub gate: GateRef, pub prefix: Vec, } -impl, const D: usize> PrefixedGate { +impl, const D: usize> PrefixedGate { pub fn from_tree(tree: Tree>) -> Vec { tree.traversal() .into_iter() @@ -174,7 +174,7 @@ fn compute_filter(prefix: &[bool], constants: &[K]) -> K { .product() } -fn compute_filter_recursively, const D: usize>( +fn compute_filter_recursively, const D: usize>( builder: &mut CircuitBuilder, prefix: &[bool], constants: &[ExtensionTarget], diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index 1150464b..74b4407e 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -1,7 +1,7 @@ use anyhow::{ensure, Result}; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::hash::hash_types::HashOut; use crate::iop::witness::{PartialWitness, Witness}; @@ -17,7 +17,7 @@ const WITNESS_DEGREE: usize = WITNESS_SIZE - 1; /// Tests that the constraints imposed by the given gate are low-degree by applying them to random /// low-degree witness polynomials. -pub(crate) fn test_low_degree, G: Gate, const D: usize>( +pub(crate) fn test_low_degree, G: Gate, const D: usize>( gate: G, ) { let rate_bits = log2_ceil(gate.degree() + 1); @@ -84,7 +84,7 @@ fn random_low_degree_values(rate_bits: usize) -> Vec { .values } -pub(crate) fn test_eval_fns, G: Gate, const D: usize>( +pub(crate) fn test_eval_fns, G: Gate, const D: usize>( gate: G, ) -> Result<()> { // Test that `eval_unfiltered` and `eval_unfiltered_base` are coherent. diff --git a/src/gates/gate_tree.rs b/src/gates/gate_tree.rs index 84949e39..8546b683 100644 --- a/src/gates/gate_tree.rs +++ b/src/gates/gate_tree.rs @@ -1,7 +1,7 @@ use log::info; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::gate::GateRef; /// A binary tree where leaves hold some type `T` and other nodes are empty. @@ -51,7 +51,7 @@ impl Tree { } } -impl, const D: usize> Tree> { +impl, const D: usize> Tree> { /// The binary gate tree influences the degree `D` of the constraint polynomial and the number `C` /// of constant wires in the circuit. We want to construct a tree minimizing both values. To do so /// we iterate over possible values of `(D, C)` and try to construct a tree with these values. @@ -229,7 +229,6 @@ mod tests { use crate::gates::gmimc::GMiMCGate; use crate::gates::interpolation::InterpolationGate; use crate::gates::noop::NoopGate; - use crate::hash::hashing::GMIMC_ROUNDS; #[test] fn test_prefix_generation() { @@ -242,7 +241,7 @@ mod tests { GateRef::new(ConstantGate), GateRef::new(ArithmeticExtensionGate), GateRef::new(BaseSumGate::<4>::new(4)), - GateRef::new(GMiMCGate::::new_automatic_constants()), + GateRef::new(GMiMCGate::::new()), GateRef::new(InterpolationGate::new(4)), ]; diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 07f5e46c..ad8a8281 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -1,10 +1,11 @@ -use std::sync::Arc; +use std::marker::PhantomData; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; -use crate::hash::gmimc::gmimc_automatic_constants; +use crate::hash::gmimc; +use crate::hash::gmimc::GMiMC; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -12,9 +13,6 @@ use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; -/// The width of the permutation, in field elements. -const W: usize = 12; - /// Evaluates a full GMiMC permutation with 12 state elements, and writes the output to the next /// gate's first `width` wires (which could be the input of another `GMiMCGate`). /// @@ -23,18 +21,21 @@ const W: usize = 12; /// sibling digests. It also has an accumulator that computes the weighted sum of these flags, for /// computing the index of the leaf based on these swap bits. #[derive(Debug)] -pub struct GMiMCGate, const D: usize, const R: usize> { - constants: Arc<[F; R]>, +pub struct GMiMCGate< + F: RichField + Extendable + GMiMC, + const D: usize, + const WIDTH: usize, +> { + _phantom: PhantomData, } -impl, const D: usize, const R: usize> GMiMCGate { - pub fn new(constants: Arc<[F; R]>) -> Self { - Self { constants } - } - - pub fn new_automatic_constants() -> Self { - let constants = Arc::new(gmimc_automatic_constants::()); - Self::new(constants) +impl + GMiMC, const D: usize, const WIDTH: usize> + GMiMCGate +{ + pub fn new() -> Self { + GMiMCGate { + _phantom: PhantomData, + } } /// The wire index for the `i`th input to the permutation. @@ -44,29 +45,29 @@ impl, const D: usize, const R: usize> GMiMCGate usize { - W + i + WIDTH + i } /// If this is set to 1, the first four inputs will be swapped with the next four inputs. This /// is useful for ordering hashes in Merkle proofs. Otherwise, this should be set to 0. - pub const WIRE_SWAP: usize = 2 * W; + pub const WIRE_SWAP: usize = 2 * WIDTH; /// A wire which stores the input to the `i`th cubing. fn wire_cubing_input(i: usize) -> usize { - 2 * W + 1 + i + 2 * WIDTH + 1 + i } /// End of wire indices, exclusive. fn end() -> usize { - 2 * W + 1 + R + 2 * WIDTH + 1 + gmimc::NUM_ROUNDS } } -impl, const D: usize, const R: usize> Gate - for GMiMCGate +impl + GMiMC, const D: usize, const WIDTH: usize> Gate + for GMiMCGate { fn id(&self) -> String { - format!(" {:?}", R, self) + format!(" {:?}", WIDTH, self) } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { @@ -95,9 +96,10 @@ impl, const D: usize, const R: usize> Gate // See https://affine.group/2020/02/starkware-challenge let mut addition_buffer = F::Extension::ZERO; - for r in 0..R { - let active = r % W; - let cubing_input = state[active] + addition_buffer + self.constants[r].into(); + for r in 0..gmimc::NUM_ROUNDS { + let active = r % WIDTH; + let constant = F::from_canonical_u64(>::ROUND_CONSTANTS[r]); + let cubing_input = state[active] + addition_buffer + constant.into(); let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; constraints.push(cubing_input - cubing_input_wire); let f = cubing_input_wire.cube(); @@ -105,7 +107,7 @@ impl, const D: usize, const R: usize> Gate state[active] -= f; } - for i in 0..W { + for i in 0..WIDTH { state[i] += addition_buffer; constraints.push(state[i] - vars.local_wires[Self::wire_output(i)]); } @@ -139,9 +141,10 @@ impl, const D: usize, const R: usize> Gate // See https://affine.group/2020/02/starkware-challenge let mut addition_buffer = F::ZERO; - for r in 0..R { - let active = r % W; - let cubing_input = state[active] + addition_buffer + self.constants[r]; + for r in 0..gmimc::NUM_ROUNDS { + let active = r % WIDTH; + let constant = F::from_canonical_u64(>::ROUND_CONSTANTS[r]); + let cubing_input = state[active] + addition_buffer + constant; let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; constraints.push(cubing_input - cubing_input_wire); let f = cubing_input_wire.cube(); @@ -149,7 +152,7 @@ impl, const D: usize, const R: usize> Gate state[active] -= f; } - for i in 0..W { + for i in 0..WIDTH { state[i] += addition_buffer; constraints.push(state[i] - vars.local_wires[Self::wire_output(i)]); } @@ -188,10 +191,11 @@ impl, const D: usize, const R: usize> Gate // See https://affine.group/2020/02/starkware-challenge let mut addition_buffer = builder.zero_extension(); - for r in 0..R { - let active = r % W; + for r in 0..gmimc::NUM_ROUNDS { + let active = r % WIDTH; - let constant = builder.constant_extension(self.constants[r].into()); + let constant = F::from_canonical_u64(>::ROUND_CONSTANTS[r]); + let constant = builder.constant_extension(constant.into()); let cubing_input = builder.add_many_extension(&[state[active], addition_buffer, constant]); let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; @@ -201,7 +205,7 @@ impl, const D: usize, const R: usize> Gate state[active] = builder.sub_extension(state[active], f); } - for i in 0..W { + for i in 0..WIDTH { state[i] = builder.add_extension(state[i], addition_buffer); constraints .push(builder.sub_extension(state[i], vars.local_wires[Self::wire_output(i)])); @@ -215,9 +219,9 @@ impl, const D: usize, const R: usize> Gate gate_index: usize, _local_constants: &[F], ) -> Vec>> { - let gen = GMiMCGenerator { + let gen = GMiMCGenerator:: { gate_index, - constants: self.constants.clone(), + _phantom: PhantomData, }; vec![Box::new(gen.adapter())] } @@ -235,25 +239,29 @@ impl, const D: usize, const R: usize> Gate } fn num_constraints(&self) -> usize { - R + W + 1 + gmimc::NUM_ROUNDS + WIDTH + 1 } } #[derive(Debug)] -struct GMiMCGenerator, const D: usize, const R: usize> { +struct GMiMCGenerator< + F: RichField + Extendable + GMiMC, + const D: usize, + const WIDTH: usize, +> { gate_index: usize, - constants: Arc<[F; R]>, + _phantom: PhantomData, } -impl, const D: usize, const R: usize> SimpleGenerator - for GMiMCGenerator +impl + GMiMC, const D: usize, const WIDTH: usize> + SimpleGenerator for GMiMCGenerator { fn dependencies(&self) -> Vec { - let mut dep_input_indices = Vec::with_capacity(W + 1); - for i in 0..W { - dep_input_indices.push(GMiMCGate::::wire_input(i)); + let mut dep_input_indices = Vec::with_capacity(WIDTH + 1); + for i in 0..WIDTH { + dep_input_indices.push(GMiMCGate::::wire_input(i)); } - dep_input_indices.push(GMiMCGate::::WIRE_SWAP); + dep_input_indices.push(GMiMCGate::::WIRE_SWAP); dep_input_indices .into_iter() @@ -267,18 +275,18 @@ impl, const D: usize, const R: usize> SimpleGenera } fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let mut state = (0..W) + let mut state = (0..WIDTH) .map(|i| { witness.get_wire(Wire { gate: self.gate_index, - input: GMiMCGate::::wire_input(i), + input: GMiMCGate::::wire_input(i), }) }) .collect::>(); let swap_value = witness.get_wire(Wire { gate: self.gate_index, - input: GMiMCGate::::WIRE_SWAP, + input: GMiMCGate::::WIRE_SWAP, }); debug_assert!(swap_value == F::ZERO || swap_value == F::ONE); if swap_value == F::ONE { @@ -291,13 +299,14 @@ impl, const D: usize, const R: usize> SimpleGenera // See https://affine.group/2020/02/starkware-challenge let mut addition_buffer = F::ZERO; - for r in 0..R { - let active = r % W; - let cubing_input = state[active] + addition_buffer + self.constants[r]; + for r in 0..gmimc::NUM_ROUNDS { + let active = r % WIDTH; + let constant = F::from_canonical_u64(>::ROUND_CONSTANTS[r]); + let cubing_input = state[active] + addition_buffer + constant; out_buffer.set_wire( Wire { gate: self.gate_index, - input: GMiMCGate::::wire_cubing_input(r), + input: GMiMCGate::::wire_cubing_input(r), }, cubing_input, ); @@ -306,12 +315,12 @@ impl, const D: usize, const R: usize> SimpleGenera state[active] -= f; } - for i in 0..W { + for i in 0..WIDTH { state[i] += addition_buffer; out_buffer.set_wire( Wire { gate: self.gate_index, - input: GMiMCGate::::wire_output(i), + input: GMiMCGate::::wire_output(i), }, state[i], ); @@ -322,7 +331,6 @@ impl, const D: usize, const R: usize> SimpleGenera #[cfg(test)] mod tests { use std::convert::TryInto; - use std::sync::Arc; use anyhow::Result; @@ -330,8 +338,8 @@ mod tests { use crate::field::field_types::Field; use crate::gates::gate::Gate; use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; - use crate::gates::gmimc::{GMiMCGate, W}; - use crate::hash::gmimc::gmimc_permute_naive; + use crate::gates::gmimc::GMiMCGate; + use crate::hash::gmimc::GMiMC; use crate::iop::generator::generate_partial_witness; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -341,12 +349,11 @@ mod tests { #[test] fn generated_output() { type F = CrandallField; - const R: usize = 101; - let constants = Arc::new([F::TWO; R]); - type Gate = GMiMCGate; - let gate = Gate::new(constants.clone()); + const WIDTH: usize = 12; + type Gate = GMiMCGate; + let gate = Gate::new(); - let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); + let permutation_inputs = (0..WIDTH).map(F::from_canonical_usize).collect::>(); let mut witness = PartialWitness::new(); witness.set_wire( @@ -356,7 +363,7 @@ mod tests { }, F::ZERO, ); - for i in 0..W { + for i in 0..WIDTH { witness.set_wire( Wire { gate: 0, @@ -380,10 +387,10 @@ mod tests { &mut TimingTree::default(), ); - let expected_outputs: [F; W] = - gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); + let expected_outputs: [F; WIDTH] = + F::gmimc_permute_naive(permutation_inputs.try_into().unwrap()); - for i in 0..W { + for i in 0..WIDTH { let out = partition_witness.get_wire(Wire { gate: 0, input: Gate::wire_output(i), @@ -395,18 +402,16 @@ mod tests { #[test] fn low_degree() { type F = CrandallField; - const R: usize = 101; - let constants = Arc::new([F::TWO; R]); - let gate = GMiMCGate::::new(constants); + const WIDTH: usize = 12; + let gate = GMiMCGate::::new(); test_low_degree(gate) } #[test] fn eval_fns() -> Result<()> { type F = CrandallField; - const R: usize = 101; - let constants = Arc::new([F::TWO; R]); - let gate = GMiMCGate::::new(constants); + const WIDTH: usize = 12; + let gate = GMiMCGate::::new(); test_eval_fns(gate) } } diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 7c013499..9f1c9ac6 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -4,7 +4,7 @@ use std::ops::Range; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -15,12 +15,12 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate for inserting a value into a list at a non-deterministic location. #[derive(Clone, Debug)] -pub(crate) struct InsertionGate, const D: usize> { +pub(crate) struct InsertionGate, const D: usize> { pub vec_size: usize, _phantom: PhantomData, } -impl, const D: usize> InsertionGate { +impl, const D: usize> InsertionGate { pub fn new(vec_size: usize) -> Self { Self { vec_size, @@ -70,7 +70,7 @@ impl, const D: usize> InsertionGate { } } -impl, const D: usize> Gate for InsertionGate { +impl, const D: usize> Gate for InsertionGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -241,14 +241,12 @@ impl, const D: usize> Gate for InsertionGate } #[derive(Debug)] -struct InsertionGenerator, const D: usize> { +struct InsertionGenerator, const D: usize> { gate_index: usize, gate: InsertionGate, } -impl, const D: usize> SimpleGenerator - for InsertionGenerator -{ +impl, const D: usize> SimpleGenerator for InsertionGenerator { fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 37e94d89..a51b797d 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -5,7 +5,7 @@ use std::ops::Range; use crate::field::extension_field::algebra::PolynomialCoeffsAlgebra; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::field::interpolation::interpolant; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; use crate::gates::gate::Gate; @@ -23,12 +23,12 @@ use crate::polynomial::polynomial::PolynomialCoeffs; /// to evaluate the interpolant at. It computes the interpolant and outputs its evaluation at the /// given point. #[derive(Clone, Debug)] -pub(crate) struct InterpolationGate, const D: usize> { +pub(crate) struct InterpolationGate, const D: usize> { pub num_points: usize, _phantom: PhantomData, } -impl, const D: usize> InterpolationGate { +impl, const D: usize> InterpolationGate { pub fn new(num_points: usize) -> Self { Self { num_points, @@ -94,7 +94,7 @@ impl, const D: usize> InterpolationGate { } } -impl, const D: usize> Gate for InterpolationGate { +impl, const D: usize> Gate for InterpolationGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -215,13 +215,13 @@ impl, const D: usize> Gate for Interpolation } #[derive(Debug)] -struct InterpolationGenerator, const D: usize> { +struct InterpolationGenerator, const D: usize> { gate_index: usize, gate: InterpolationGate, _phantom: PhantomData, } -impl, const D: usize> SimpleGenerator +impl, const D: usize> SimpleGenerator for InterpolationGenerator { fn dependencies(&self) -> Vec { diff --git a/src/gates/noop.rs b/src/gates/noop.rs index d23360bb..e0c9d803 100644 --- a/src/gates/noop.rs +++ b/src/gates/noop.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::gate::Gate; use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; @@ -9,7 +9,7 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate which does nothing. pub struct NoopGate; -impl, const D: usize> Gate for NoopGate { +impl, const D: usize> Gate for NoopGate { fn id(&self) -> String { "NoopGate".into() } diff --git a/src/gates/public_input.rs b/src/gates/public_input.rs index c298511f..2c0899dd 100644 --- a/src/gates/public_input.rs +++ b/src/gates/public_input.rs @@ -2,7 +2,7 @@ use std::ops::Range; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::gate::Gate; use crate::iop::generator::WitnessGenerator; use crate::plonk::circuit_builder::CircuitBuilder; @@ -17,7 +17,7 @@ impl PublicInputGate { } } -impl, const D: usize> Gate for PublicInputGate { +impl, const D: usize> Gate for PublicInputGate { fn id(&self) -> String { "PublicInputGate".into() } diff --git a/src/gates/random_access.rs b/src/gates/random_access.rs index 5ea604d7..00b189b3 100644 --- a/src/gates/random_access.rs +++ b/src/gates/random_access.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -14,12 +14,12 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate for checking that a particular element of a list matches a given value. #[derive(Clone, Debug)] -pub(crate) struct RandomAccessGate, const D: usize> { +pub(crate) struct RandomAccessGate, const D: usize> { pub vec_size: usize, _phantom: PhantomData, } -impl, const D: usize> RandomAccessGate { +impl, const D: usize> RandomAccessGate { pub fn new(vec_size: usize) -> Self { Self { vec_size, @@ -61,7 +61,7 @@ impl, const D: usize> RandomAccessGate { } } -impl, const D: usize> Gate for RandomAccessGate { +impl, const D: usize> Gate for RandomAccessGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -188,12 +188,12 @@ impl, const D: usize> Gate for RandomAccessG } #[derive(Debug)] -struct RandomAccessGenerator, const D: usize> { +struct RandomAccessGenerator, const D: usize> { gate_index: usize, gate: RandomAccessGate, } -impl, const D: usize> SimpleGenerator +impl, const D: usize> SimpleGenerator for RandomAccessGenerator { fn dependencies(&self) -> Vec { diff --git a/src/gates/reducing.rs b/src/gates/reducing.rs index 60a9f747..013f3e27 100644 --- a/src/gates/reducing.rs +++ b/src/gates/reducing.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::extension_field::FieldExtension; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; @@ -51,7 +51,7 @@ impl ReducingGate { } } -impl, const D: usize> Gate for ReducingGate { +impl, const D: usize> Gate for ReducingGate { fn id(&self) -> String { format!("{:?}", self) } diff --git a/src/gates/switch.rs b/src/gates/switch.rs index b17ce1ab..732b6674 100644 --- a/src/gates/switch.rs +++ b/src/gates/switch.rs @@ -4,7 +4,7 @@ use array_tool::vec::Union; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, WitnessGenerator}; use crate::iop::target::Target; @@ -16,13 +16,13 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; /// A gate for conditionally swapping input values based on a boolean. #[derive(Clone, Debug)] -pub(crate) struct SwitchGate, const D: usize> { +pub(crate) struct SwitchGate, const D: usize> { pub(crate) chunk_size: usize, pub(crate) num_copies: usize, _phantom: PhantomData, } -impl, const D: usize> SwitchGate { +impl, const D: usize> SwitchGate { pub fn new(num_copies: usize, chunk_size: usize) -> Self { Self { chunk_size, @@ -66,7 +66,7 @@ impl, const D: usize> SwitchGate { } } -impl, const D: usize> Gate for SwitchGate { +impl, const D: usize> Gate for SwitchGate { fn id(&self) -> String { format!("{:?}", self, D) } @@ -194,13 +194,13 @@ impl, const D: usize> Gate for SwitchGate, const D: usize> { +struct SwitchGenerator, const D: usize> { gate_index: usize, gate: SwitchGate, copy: usize, } -impl, const D: usize> SwitchGenerator { +impl, const D: usize> SwitchGenerator { fn in_out_dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -282,7 +282,7 @@ impl, const D: usize> SwitchGenerator { } } -impl, const D: usize> WitnessGenerator for SwitchGenerator { +impl, const D: usize> WitnessGenerator for SwitchGenerator { fn watch_list(&self) -> Vec { self.in_out_dependencies() .union(self.in_switch_dependencies()) diff --git a/src/hash/gmimc.rs b/src/hash/gmimc.rs index f97ef0fd..5c4563ce 100644 --- a/src/hash/gmimc.rs +++ b/src/hash/gmimc.rs @@ -1,136 +1,99 @@ -use std::sync::Arc; - -use rand::SeedableRng; -use rand_chacha::ChaCha8Rng; use unroll::unroll_for_loops; +use crate::field::crandall_field::CrandallField; use crate::field::field_types::Field; -pub(crate) fn gmimc_automatic_constants() -> [F; R] { - let mut rng = ChaCha8Rng::seed_from_u64(0); - let mut constants = [F::ZERO; R]; - for i in 0..R { - constants[i] = F::rand_from_rng(&mut rng); - } - constants -} +pub(crate) const NUM_ROUNDS: usize = 101; -pub fn gmimc_compress( - a: [F; 4], - b: [F; 4], - constants: Arc<[F; R]>, -) -> [F; 4] { - // Sponge with r=8, c=4. - let state_0 = [ - a[0], - a[1], - a[2], - a[3], - b[0], - b[1], - b[2], - b[3], - F::ZERO, - F::ZERO, - F::ZERO, - F::ZERO, - ]; - let state_1 = gmimc_permute::(state_0, constants); - [state_1[0], state_1[1], state_1[2], state_1[3]] -} +pub trait GMiMC: Field +where + [u64; NUM_ROUNDS]: Sized, +{ + const ROUND_CONSTANTS: [u64; NUM_ROUNDS]; -/// Like `gmimc_permute`, but takes constants as an owned array. May be faster. -#[unroll_for_loops] -pub fn gmimc_permute_array( - mut xs: [F; W], - constants: [u64; R], -) -> [F; W] { - // Value that is implicitly added to each element. - // See https://affine.group/2020/02/starkware-challenge - let mut addition_buffer = F::ZERO; + #[unroll_for_loops] + fn gmimc_permute(mut xs: [Self; WIDTH]) -> [Self; WIDTH] { + // Value that is implicitly added to each element. + // See https://affine.group/2020/02/starkware-challenge + let mut addition_buffer = Self::ZERO; - for r in 0..R { - let active = r % W; - let f = (xs[active] + addition_buffer + F::from_canonical_u64(constants[r])).cube(); - addition_buffer += f; - xs[active] -= f; + for (r, &constant) in Self::ROUND_CONSTANTS.iter().enumerate() { + let active = r % WIDTH; + let f = (xs[active] + addition_buffer + Self::from_canonical_u64(constant)).cube(); + addition_buffer += f; + xs[active] -= f; + } + + for i in 0..WIDTH { + xs[i] += addition_buffer; + } + + xs } - for x_i in xs.iter_mut() { - *x_i += addition_buffer; - } - - xs -} - -#[unroll_for_loops] -pub fn gmimc_permute( - mut xs: [F; W], - constants: Arc<[F; R]>, -) -> [F; W] { - // Value that is implicitly added to each element. - // See https://affine.group/2020/02/starkware-challenge - let mut addition_buffer = F::ZERO; - - for r in 0..R { - let active = r % W; - let f = (xs[active] + addition_buffer + constants[r]).cube(); - addition_buffer += f; - xs[active] -= f; - } - - for i in 0..W { - xs[i] += addition_buffer; - } - - xs -} - -#[unroll_for_loops] -pub fn gmimc_permute_naive( - mut xs: [F; W], - constants: Arc<[F; R]>, -) -> [F; W] { - for r in 0..R { - let active = r % W; - let f = (xs[active] + constants[r]).cube(); - for i in 0..W { - if i != active { - xs[i] += f; + #[unroll_for_loops] + fn gmimc_permute_naive(mut xs: [Self; WIDTH]) -> [Self; WIDTH] { + for (r, &constant) in Self::ROUND_CONSTANTS.iter().enumerate() { + let active = r % WIDTH; + let f = (xs[active] + Self::from_canonical_u64(constant)).cube(); + for i in 0..WIDTH { + if i != active { + xs[i] += f; + } } } - } - xs + xs + } +} + +impl GMiMC<12> for CrandallField { + /// This is the result of `gmimc_automatic_constants`; i.e. it's from ChaCha20 seeded with 0. + #[rustfmt::skip] + const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = [ + 0xb585f767417ee042, 0x7746a55f77c10331, 0xb2fb0d321d356f7a, 0x0f6760a486f1621f, + 0xe10d6666b36abcdf, 0x8cae14cb455cc50b, 0xd438539cf2cee334, 0xef781c7d4c1fd8b4, + 0xcdc4a23a0aca4b1f, 0x277fa208d07b52e3, 0xe17653a300493d38, 0xc54302f27c287dc1, + 0x8628782231d47d10, 0x59cd1a8a690b49f2, 0xc3b919ad9efec0b0, 0xa484c4c637641d97, + 0x308bbd23f191398b, 0x6e4a40c1bf713cf1, 0x9a2eedb7510414fb, 0xe360c6e111c2c63b, + 0xd5c771901d4d89aa, 0xc35eae076e7d6b2f, 0x849c2656d0a09cad, 0xc0572c8c5cf1df2b, + 0xe9fa634a883b8bf3, 0xf56f6d4900fb1fdd, 0xf7d713e872a72a1b, 0x8297132b6ba47612, + 0xad6805e12ee8af1c, 0xac51d9f6485c22b9, 0x502ad7dc3bd56bf8, 0x57a1550c3761c577, + 0x66bbd30e99d311da, 0x0da2abef5e948f87, 0xf0612750443f8e94, 0x28b8ec3afb937d8c, + 0x92a756e6be54ca18, 0x70e741ec304e925d, 0x019d5ee2b037c59f, 0x6f6f2ed7a30707d1, + 0x7cf416d01e8c169c, 0x61df517bb17617df, 0x85dc499b4c67dbaa, 0x4b959b48dad27b23, + 0xe8be3e5e0dd779a0, 0xf5c0bc1e525ed8e6, 0x40b12cbf263cf853, 0xa637093f13e2ea3c, + 0x3cc3f89232e3b0c8, 0x2e479dc16bfe86c0, 0x6f49de07d6d39469, 0x213ce7beecc232de, + 0x5b043134851fc00a, 0xa2de45784a861506, 0x7103aaf97bed8dd5, 0x5326fc0dbb88a147, + 0xa9ceb750364cb77a, 0x27f8ec88cc9e991f, 0xfceb4fda8c93fb83, 0xfac6ff13b45b260e, + 0x7131aa455813380b, 0x93510360d5d68119, 0xad535b24fb96e3db, 0x4627f5c6b7efc045, + 0x645cf794e4da78a9, 0x241c70ed1ac2877f, 0xacb8e076b009e825, 0x3737e9db6477bd9d, + 0xe7ea5e344cd688ed, 0x90dee4a009214640, 0xd1b1edf7c77e74af, 0x0b65481bab42158e, + 0x99ad1aab4b4fe3e7, 0x438a7c91f1a360cd, 0xb60de3bd159088bf, 0xc99cab6b47a3e3bb, + 0x69a5ed92d5677cef, 0x5e7b329c482a9396, 0x5fc0ac0829f893c9, 0x32db82924fb757ea, + 0x0ade699c5cf24145, 0x7cc5583b46d7b5bb, 0x85df9ed31bf8abcb, 0x6604df501ad4de64, + 0xeb84f60941611aec, 0xda60883523989bd4, 0x8f97fe40bf3470bf, 0xa93f485ce0ff2b32, + 0x6704e8eebc2afb4b, 0xcee3e9ac788ad755, 0x510d0e66062a270d, 0xf6323f48d74634a0, + 0x0b508cdf04990c90, 0xf241708a4ef7ddf9, 0x60e75c28bb368f82, 0xa6217d8c3f0f9989, + 0x7159cd30f5435b53, 0x839b4e8fe97ec79f, 0x0d3f3e5e885db625, 0x8f7d83be1daea54b, + 0x780f22441e8dbc04, + ]; } #[cfg(test)] mod tests { - use std::sync::Arc; - use crate::field::crandall_field::CrandallField; - use crate::field::field_types::Field; - use crate::hash::gmimc::{gmimc_permute, gmimc_permute_naive}; + use crate::hash::gmimc::GMiMC; + + fn check_consistency, const WIDTH: usize>() { + let xs = F::rand_arr::(); + let out = F::gmimc_permute(xs); + let out_naive = F::gmimc_permute_naive(xs); + assert_eq!(out, out_naive); + } #[test] fn consistency() { - type F = CrandallField; - const W: usize = 12; - const R: usize = 101; - - let mut constants = [F::ZERO; R]; - for i in 0..R { - constants[i] = F::from_canonical_usize(i); - } - let constants = Arc::new(constants); - - let mut xs = [F::ZERO; W]; - for i in 0..W { - xs[i] = F::from_canonical_usize(i); - } - - let out = gmimc_permute::(xs, constants.clone()); - let out_naive = gmimc_permute_naive::(xs, constants); - assert_eq!(out, out_naive); + check_consistency::(); } } diff --git a/src/hash/hashing.rs b/src/hash/hashing.rs index ad3d068b..3b496445 100644 --- a/src/hash/hashing.rs +++ b/src/hash/hashing.rs @@ -1,8 +1,8 @@ //! Concrete instantiation of a hash function. use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; -use crate::hash::gmimc::gmimc_permute_array; +use crate::field::field_types::{Field, RichField}; +use crate::hash::gmimc::GMiMC; use crate::hash::hash_types::{HashOut, HashOutTarget}; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -11,115 +11,42 @@ pub(crate) const SPONGE_RATE: usize = 8; pub(crate) const SPONGE_CAPACITY: usize = 4; pub(crate) const SPONGE_WIDTH: usize = SPONGE_RATE + SPONGE_CAPACITY; -pub const GMIMC_ROUNDS: usize = 101; +pub const NUM_ROUNDS: usize = 101; + /// This is the result of `gmimc_automatic_constants`; i.e. it's from ChaCha20 seeded with 0. -pub const GMIMC_CONSTANTS: [u64; GMIMC_ROUNDS] = [ - 13080132715619999810, - 8594738768332784433, - 12896916466795114362, - 1109962092924985887, - 16216730424513838303, - 10137062674532189451, - 15292064468290167604, - 17255573296743700660, - 14827154243383347999, - 2846171648262623971, - 16246264665335217464, - 14214208089399786945, - 9667108688411000080, - 6470857421371427314, - 14103331941574951088, - 11854816474757864855, - 3498097497657653643, - 7947235693333396721, - 11110078702363612411, - 16384314114341783099, - 15404405914224921002, - 14077880832148466479, - 9555554663682579629, - 13859595359622389547, - 16859897326779206643, - 17685474422023725021, - 17858764736437889563, - 9410011023624402450, - 12495243630852222748, - 12416945299436348089, - 5776666812952701944, - 6314421663507268983, - 7402742472177291738, - 982536713292517255, - 17321168867539521172, - 2934354895304883596, - 10567510599683852824, - 8135543734546633309, - 116353493093565855, - 8029688164312877009, - 9003846638141970076, - 7052445133185619935, - 9645665433271393194, - 5446430061585660707, - 16770910636054378912, - 17708360573237778662, - 4661556288797079635, - 11977051900536351292, - 4378616569536950472, - 3334807503157233344, - 8019184736760206441, - 2395043909056213726, - 6558421058999795722, - 11735894061922784518, - 8143540539718733269, - 5991753490174091591, - 12235918792748480378, - 2880312033996085535, - 18224748117164817283, - 18070411014966027790, - 8156487614951798795, - 10615269511128318233, - 12489426406026437595, - 5055279340584943685, - 7231927320516917417, - 2602078848371820415, - 12445944370602567717, - 3978905924297801117, - 16711272946032085229, - 10439032362290464320, - 15110119873264383151, - 821141790739535246, - 11073536381779174375, - 4866839313593360589, - 13118391690850240703, - 14527674975242150843, - 7612751960041028847, - 6808090908507673494, - 6899703780195472329, - 3664666286710282218, - 783179505504239941, - 8990689242729919931, - 9646603556395461579, - 7351246026916028004, - 16970959815450893036, - 15735726859844361172, - 10347018222946250943, - 12195545879691602738, - 7423314197870213963, - 14908016118492485461, - 5840340123122280205, - 17740311464247702688, - 815306422036794512, - 17456357369997417977, - 6982651077270605698, - 11970987325834369417, - 8167785009370061651, - 9483259820363401119, - 954550221761525285, - 10339565172077536587, - 8651171085167737860, +#[rustfmt::skip] +pub const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = [ + 0xb585f767417ee042, 0x7746a55f77c10331, 0xb2fb0d321d356f7a, 0x0f6760a486f1621f, + 0xe10d6666b36abcdf, 0x8cae14cb455cc50b, 0xd438539cf2cee334, 0xef781c7d4c1fd8b4, + 0xcdc4a23a0aca4b1f, 0x277fa208d07b52e3, 0xe17653a300493d38, 0xc54302f27c287dc1, + 0x8628782231d47d10, 0x59cd1a8a690b49f2, 0xc3b919ad9efec0b0, 0xa484c4c637641d97, + 0x308bbd23f191398b, 0x6e4a40c1bf713cf1, 0x9a2eedb7510414fb, 0xe360c6e111c2c63b, + 0xd5c771901d4d89aa, 0xc35eae076e7d6b2f, 0x849c2656d0a09cad, 0xc0572c8c5cf1df2b, + 0xe9fa634a883b8bf3, 0xf56f6d4900fb1fdd, 0xf7d713e872a72a1b, 0x8297132b6ba47612, + 0xad6805e12ee8af1c, 0xac51d9f6485c22b9, 0x502ad7dc3bd56bf8, 0x57a1550c3761c577, + 0x66bbd30e99d311da, 0x0da2abef5e948f87, 0xf0612750443f8e94, 0x28b8ec3afb937d8c, + 0x92a756e6be54ca18, 0x70e741ec304e925d, 0x019d5ee2b037c59f, 0x6f6f2ed7a30707d1, + 0x7cf416d01e8c169c, 0x61df517bb17617df, 0x85dc499b4c67dbaa, 0x4b959b48dad27b23, + 0xe8be3e5e0dd779a0, 0xf5c0bc1e525ed8e6, 0x40b12cbf263cf853, 0xa637093f13e2ea3c, + 0x3cc3f89232e3b0c8, 0x2e479dc16bfe86c0, 0x6f49de07d6d39469, 0x213ce7beecc232de, + 0x5b043134851fc00a, 0xa2de45784a861506, 0x7103aaf97bed8dd5, 0x5326fc0dbb88a147, + 0xa9ceb750364cb77a, 0x27f8ec88cc9e991f, 0xfceb4fda8c93fb83, 0xfac6ff13b45b260e, + 0x7131aa455813380b, 0x93510360d5d68119, 0xad535b24fb96e3db, 0x4627f5c6b7efc045, + 0x645cf794e4da78a9, 0x241c70ed1ac2877f, 0xacb8e076b009e825, 0x3737e9db6477bd9d, + 0xe7ea5e344cd688ed, 0x90dee4a009214640, 0xd1b1edf7c77e74af, 0x0b65481bab42158e, + 0x99ad1aab4b4fe3e7, 0x438a7c91f1a360cd, 0xb60de3bd159088bf, 0xc99cab6b47a3e3bb, + 0x69a5ed92d5677cef, 0x5e7b329c482a9396, 0x5fc0ac0829f893c9, 0x32db82924fb757ea, + 0x0ade699c5cf24145, 0x7cc5583b46d7b5bb, 0x85df9ed31bf8abcb, 0x6604df501ad4de64, + 0xeb84f60941611aec, 0xda60883523989bd4, 0x8f97fe40bf3470bf, 0xa93f485ce0ff2b32, + 0x6704e8eebc2afb4b, 0xcee3e9ac788ad755, 0x510d0e66062a270d, 0xf6323f48d74634a0, + 0x0b508cdf04990c90, 0xf241708a4ef7ddf9, 0x60e75c28bb368f82, 0xa6217d8c3f0f9989, + 0x7159cd30f5435b53, 0x839b4e8fe97ec79f, 0x0d3f3e5e885db625, 0x8f7d83be1daea54b, + 0x780f22441e8dbc04, ]; /// Hash the vector if necessary to reduce its length to ~256 bits. If it already fits, this is a /// no-op. -pub fn hash_or_noop(inputs: Vec) -> HashOut { +pub fn hash_or_noop(inputs: Vec) -> HashOut { if inputs.len() <= 4 { HashOut::from_partial(inputs) } else { @@ -127,7 +54,7 @@ pub fn hash_or_noop(inputs: Vec) -> HashOut { } } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn hash_or_noop(&mut self, inputs: Vec) -> HashOutTarget { let zero = self.zero(); if inputs.len() <= 4 { @@ -184,21 +111,21 @@ impl, const D: usize> CircuitBuilder { } /// A one-way compression function which takes two ~256 bit inputs and returns a ~256 bit output. -pub fn compress(x: HashOut, y: HashOut) -> HashOut { +pub fn compress(x: HashOut, y: HashOut) -> HashOut { let mut inputs = Vec::with_capacity(8); inputs.extend(&x.elements); inputs.extend(&y.elements); hash_n_to_hash(inputs, false) } -pub fn permute(xs: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH] { - gmimc_permute_array(xs, GMIMC_CONSTANTS) -} - /// If `pad` is enabled, the message is padded using the pad10*1 rule. In general this is required /// for the hash to be secure, but it can safely be disabled in certain cases, like if the input /// length is fixed. -pub fn hash_n_to_m(mut inputs: Vec, num_outputs: usize, pad: bool) -> Vec { +pub fn hash_n_to_m>( + mut inputs: Vec, + num_outputs: usize, + pad: bool, +) -> Vec { if pad { inputs.push(F::ZERO); while (inputs.len() + 1) % SPONGE_WIDTH != 0 { @@ -214,7 +141,7 @@ pub fn hash_n_to_m(mut inputs: Vec, num_outputs: usize, pad: bool) for i in 0..input_chunk.len() { state[i] = input_chunk[i]; } - state = permute(state); + state = F::gmimc_permute(state); } // Squeeze until we have the desired number of outputs. @@ -226,14 +153,14 @@ pub fn hash_n_to_m(mut inputs: Vec, num_outputs: usize, pad: bool) return outputs; } } - state = permute(state); + state = F::gmimc_permute(state); } } -pub fn hash_n_to_hash(inputs: Vec, pad: bool) -> HashOut { +pub fn hash_n_to_hash(inputs: Vec, pad: bool) -> HashOut { HashOut::from_vec(hash_n_to_m(inputs, 4, pad)) } -pub fn hash_n_to_1(inputs: Vec, pad: bool) -> F { +pub fn hash_n_to_1(inputs: Vec, pad: bool) -> F { hash_n_to_m(inputs, 1, pad)[0] } diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index 1ccf3547..5aad9193 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -5,10 +5,10 @@ use serde::{Deserialize, Serialize}; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gmimc::GMiMCGate; use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; -use crate::hash::hashing::{compress, hash_or_noop, GMIMC_ROUNDS}; +use crate::hash::hashing::{compress, hash_or_noop}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; @@ -29,7 +29,7 @@ pub struct MerkleProofTarget { /// Verifies that the given leaf data is present at the given index in the Merkle tree with the /// given cap. -pub(crate) fn verify_merkle_proof( +pub(crate) fn verify_merkle_proof( leaf_data: Vec, leaf_index: usize, merkle_cap: &MerkleCap, @@ -54,7 +54,7 @@ pub(crate) fn verify_merkle_proof( Ok(()) } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Verifies that the given leaf data is present at the given index in the Merkle tree with the /// given cap. The index is given by it's little-endian bits. /// Note: Works only for D=4. @@ -70,10 +70,10 @@ impl, const D: usize> CircuitBuilder { let mut state: HashOutTarget = self.hash_or_noop(leaf_data); for (&bit, &sibling) in leaf_index_bits.iter().zip(&proof.siblings) { - let gate_type = GMiMCGate::::new_automatic_constants(); + let gate_type = GMiMCGate::::new(); let gate = self.add_gate(gate_type, vec![]); - let swap_wire = GMiMCGate::::WIRE_SWAP; + let swap_wire = GMiMCGate::::WIRE_SWAP; let swap_wire = Target::Wire(Wire { gate, input: swap_wire, @@ -84,7 +84,7 @@ impl, const D: usize> CircuitBuilder { .map(|i| { Target::Wire(Wire { gate, - input: GMiMCGate::::wire_input(i), + input: GMiMCGate::::wire_input(i), }) }) .collect::>(); @@ -100,7 +100,7 @@ impl, const D: usize> CircuitBuilder { .map(|i| { Target::Wire(Wire { gate, - input: GMiMCGate::::wire_output(i), + input: GMiMCGate::::wire_output(i), }) }) .collect(), @@ -136,10 +136,10 @@ impl, const D: usize> CircuitBuilder { let mut state: HashOutTarget = self.hash_or_noop(leaf_data); for (&bit, &sibling) in leaf_index_bits.iter().zip(&proof.siblings) { - let gate_type = GMiMCGate::::new_automatic_constants(); + let gate_type = GMiMCGate::::new(); let gate = self.add_gate(gate_type, vec![]); - let swap_wire = GMiMCGate::::WIRE_SWAP; + let swap_wire = GMiMCGate::::WIRE_SWAP; let swap_wire = Target::Wire(Wire { gate, input: swap_wire, @@ -150,7 +150,7 @@ impl, const D: usize> CircuitBuilder { .map(|i| { Target::Wire(Wire { gate, - input: GMiMCGate::::wire_input(i), + input: GMiMCGate::::wire_input(i), }) }) .collect::>(); @@ -166,7 +166,7 @@ impl, const D: usize> CircuitBuilder { .map(|i| { Target::Wire(Wire { gate, - input: GMiMCGate::::wire_output(i), + input: GMiMCGate::::wire_output(i), }) }) .collect(), diff --git a/src/hash/merkle_tree.rs b/src/hash/merkle_tree.rs index 9b055ef6..1bc28d5a 100644 --- a/src/hash/merkle_tree.rs +++ b/src/hash/merkle_tree.rs @@ -1,7 +1,7 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use crate::field::field_types::Field; +use crate::field::field_types::{Field, RichField}; use crate::hash::hash_types::HashOut; use crate::hash::hashing::{compress, hash_or_noop}; use crate::hash::merkle_proofs::MerkleProof; @@ -30,7 +30,7 @@ pub struct MerkleTree { pub cap: MerkleCap, } -impl MerkleTree { +impl MerkleTree { pub fn new(leaves: Vec>, cap_height: usize) -> Self { let mut layers = vec![leaves .par_iter() @@ -82,11 +82,11 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::hash::merkle_proofs::verify_merkle_proof; - fn random_data(n: usize, k: usize) -> Vec> { + fn random_data(n: usize, k: usize) -> Vec> { (0..n).map(|_| F::rand_vec(k)).collect() } - fn verify_all_leaves(leaves: Vec>, n: usize) -> Result<()> { + fn verify_all_leaves(leaves: Vec>, n: usize) -> Result<()> { let tree = MerkleTree::new(leaves.clone(), 1); for i in 0..n { let proof = tree.prove(i); diff --git a/src/hash/poseidon.rs b/src/hash/poseidon.rs index daf2dfe9..e3a8cc5d 100644 --- a/src/hash/poseidon.rs +++ b/src/hash/poseidon.rs @@ -22,6 +22,8 @@ const MAX_WIDTH: usize = 12; // we only have width 8 and 12, and 12 is bigger. : // generated from ChaCha8 with a seed of 0. In this case we need // to generate more though. We include enough for a WIDTH of 12; // smaller widths just use a subset. +// TODO: These are specific to CrandallField; for other fields they wouldn't represent uniformly +// random numbers. #[rustfmt::skip] const ALL_ROUND_CONSTANTS: [u64; MAX_WIDTH * N_ROUNDS] = [ 0xb585f767417ee042, 0x7746a55f77c10331, 0xb2fb0d321d356f7a, 0x0f6760a486f1621f, @@ -116,7 +118,7 @@ const ALL_ROUND_CONSTANTS: [u64; MAX_WIDTH * N_ROUNDS] = [ 0x4543d9df72c4831d, 0xf172d73e69f20739, 0xdfd1c4ff1eb3d868, 0xbc8dfb62d26376f7, ]; -pub trait PoseidonInterface: PrimeField +pub trait Poseidon: PrimeField where // magic to get const generic expressions to work [(); WIDTH - 1]: , @@ -335,7 +337,7 @@ where } #[rustfmt::skip] -impl PoseidonInterface<8> for CrandallField { +impl Poseidon<8> for CrandallField { // The MDS matrix we use is the circulant matrix with first row given by the vector // [ 2^x for x in MDS_MATRIX_EXPS] = [4, 1, 2, 256, 16, 8, 1, 1] // @@ -475,7 +477,7 @@ impl PoseidonInterface<8> for CrandallField { } #[rustfmt::skip] -impl PoseidonInterface<12> for CrandallField { +impl Poseidon<12> for CrandallField { // The MDS matrix we use is the circulant matrix with first row given by the vector // [ 2^x for x in MDS_MATRIX_EXPS] = [1024, 8192, 4, 1, 16, 2, 256, 128, 32768, 32, 1, 1] // @@ -683,11 +685,11 @@ impl PoseidonInterface<12> for CrandallField { mod tests { use crate::field::crandall_field::CrandallField as F; use crate::field::field_types::Field; - use crate::hash::poseidon::PoseidonInterface; + use crate::hash::poseidon::Poseidon; fn check_test_vectors(test_vectors: Vec<([u64; WIDTH], [u64; WIDTH])>) where - F: PoseidonInterface, + F: Poseidon, [(); WIDTH - 1]: , { for (input_, expected_output_) in test_vectors.into_iter() { @@ -750,7 +752,7 @@ mod tests { fn check_consistency() where - F: PoseidonInterface, + F: Poseidon, [(); WIDTH - 1]: , { let mut input = [F::ZERO; WIDTH]; diff --git a/src/iop/challenger.rs b/src/iop/challenger.rs index 8b270d66..f8b918ea 100644 --- a/src/iop/challenger.rs +++ b/src/iop/challenger.rs @@ -2,9 +2,9 @@ use std::convert::TryInto; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::RichField; use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; -use crate::hash::hashing::{permute, SPONGE_RATE, SPONGE_WIDTH}; +use crate::hash::hashing::{SPONGE_RATE, SPONGE_WIDTH}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -12,7 +12,7 @@ use crate::plonk::proof::{OpeningSet, OpeningSetTarget}; /// Observes prover messages, and generates challenges by hashing the transcript, a la Fiat-Shamir. #[derive(Clone)] -pub struct Challenger { +pub struct Challenger { sponge_state: [F; SPONGE_WIDTH], input_buffer: Vec, output_buffer: Vec, @@ -26,7 +26,7 @@ pub struct Challenger { /// design, but it can be viewed as a duplex sponge whose inputs are sometimes zero (when we perform /// multiple squeezes) and whose outputs are sometimes ignored (when we perform multiple /// absorptions). Thus the security properties of a duplex sponge still apply to our design. -impl Challenger { +impl Challenger { pub fn new() -> Challenger { Challenger { sponge_state: [F::ZERO; SPONGE_WIDTH], @@ -105,7 +105,7 @@ impl Challenger { if self.output_buffer.is_empty() { // Evaluate the permutation to produce `r` new outputs. - self.sponge_state = permute(self.sponge_state); + self.sponge_state = F::gmimc_permute(self.sponge_state); self.output_buffer = self.sponge_state[0..SPONGE_RATE].to_vec(); } @@ -160,7 +160,7 @@ impl Challenger { } // Apply the permutation. - self.sponge_state = permute(self.sponge_state); + self.sponge_state = F::gmimc_permute(self.sponge_state); } self.output_buffer = self.sponge_state[0..SPONGE_RATE].to_vec(); @@ -169,7 +169,7 @@ impl Challenger { } } -impl Default for Challenger { +impl Default for Challenger { fn default() -> Self { Self::new() } @@ -183,7 +183,7 @@ pub struct RecursiveChallenger { } impl RecursiveChallenger { - pub(crate) fn new, const D: usize>( + pub(crate) fn new, const D: usize>( builder: &mut CircuitBuilder, ) -> Self { let zero = builder.zero(); @@ -250,7 +250,7 @@ impl RecursiveChallenger { } } - pub(crate) fn get_challenge, const D: usize>( + pub(crate) fn get_challenge, const D: usize>( &mut self, builder: &mut CircuitBuilder, ) -> Target { @@ -267,7 +267,7 @@ impl RecursiveChallenger { .expect("Output buffer should be non-empty") } - pub(crate) fn get_n_challenges, const D: usize>( + pub(crate) fn get_n_challenges, const D: usize>( &mut self, builder: &mut CircuitBuilder, n: usize, @@ -275,7 +275,7 @@ impl RecursiveChallenger { (0..n).map(|_| self.get_challenge(builder)).collect() } - pub fn get_hash, const D: usize>( + pub fn get_hash, const D: usize>( &mut self, builder: &mut CircuitBuilder, ) -> HashOutTarget { @@ -289,7 +289,7 @@ impl RecursiveChallenger { } } - pub fn get_extension_challenge, const D: usize>( + pub fn get_extension_challenge, const D: usize>( &mut self, builder: &mut CircuitBuilder, ) -> ExtensionTarget { @@ -297,7 +297,7 @@ impl RecursiveChallenger { } /// Absorb any buffered inputs. After calling this, the input buffer will be empty. - fn absorb_buffered_inputs, const D: usize>( + fn absorb_buffered_inputs, const D: usize>( &mut self, builder: &mut CircuitBuilder, ) { diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 529a85b0..9c34df15 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -7,7 +7,7 @@ use log::{info, Level}; use crate::field::cosets::get_unique_coset_shifts; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::fri::commitment::PolynomialBatchCommitment; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; use crate::gates::constant::ConstantGate; @@ -37,7 +37,7 @@ use crate::util::partial_products::num_partial_products; use crate::util::timing::TimingTree; use crate::util::{log2_ceil, log2_strict, transpose, transpose_poly_values}; -pub struct CircuitBuilder, const D: usize> { +pub struct CircuitBuilder, const D: usize> { pub(crate) config: CircuitConfig, /// The types of gates used in this circuit. @@ -76,7 +76,7 @@ pub struct CircuitBuilder, const D: usize> { pub(crate) current_switch_gates: Vec, usize, usize)>>, } -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { pub fn new(config: CircuitConfig) -> Self { CircuitBuilder { config, diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 01c2c6d3..4ec27cc7 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -3,10 +3,10 @@ use std::ops::{Range, RangeFrom}; use anyhow::Result; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::FriConfig; -use crate::gates::gate::{GateInstance, PrefixedGate}; +use crate::gates::gate::PrefixedGate; use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; @@ -91,13 +91,13 @@ impl CircuitConfig { } /// Circuit data required by the prover or the verifier. -pub struct CircuitData, const D: usize> { +pub struct CircuitData, const D: usize> { pub(crate) prover_only: ProverOnlyCircuitData, pub(crate) verifier_only: VerifierOnlyCircuitData, pub(crate) common: CommonCircuitData, } -impl, const D: usize> CircuitData { +impl, const D: usize> CircuitData { pub fn prove(&self, inputs: PartialWitness) -> Result> { prove(&self.prover_only, &self.common, inputs) } @@ -114,12 +114,12 @@ impl, const D: usize> CircuitData { /// structure as succinct as we can. Thus we include various precomputed data which isn't strictly /// required, like LDEs of preprocessed polynomials. If more succinctness was desired, we could /// construct a more minimal prover structure and convert back and forth. -pub struct ProverCircuitData, const D: usize> { +pub struct ProverCircuitData, const D: usize> { pub(crate) prover_only: ProverOnlyCircuitData, pub(crate) common: CommonCircuitData, } -impl, const D: usize> ProverCircuitData { +impl, const D: usize> ProverCircuitData { pub fn prove(&self, inputs: PartialWitness) -> Result> { prove(&self.prover_only, &self.common, inputs) } @@ -127,19 +127,19 @@ impl, const D: usize> ProverCircuitData { /// Circuit data required by the prover. #[derive(Debug)] -pub struct VerifierCircuitData, const D: usize> { +pub struct VerifierCircuitData, const D: usize> { pub(crate) verifier_only: VerifierOnlyCircuitData, pub(crate) common: CommonCircuitData, } -impl, const D: usize> VerifierCircuitData { +impl, const D: usize> VerifierCircuitData { pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> { verify(proof_with_pis, &self.verifier_only, &self.common) } } /// Circuit data required by the prover, but not the verifier. -pub(crate) struct ProverOnlyCircuitData, const D: usize> { +pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub generators: Vec>>, /// Commitments to the constants polynomials and sigma polynomials. pub constants_sigmas_commitment: PolynomialBatchCommitment, @@ -164,7 +164,7 @@ pub(crate) struct VerifierOnlyCircuitData { /// Circuit data required by both the prover and the verifier. #[derive(Debug)] -pub struct CommonCircuitData, const D: usize> { +pub struct CommonCircuitData, const D: usize> { pub(crate) config: CircuitConfig, pub(crate) degree_bits: usize, @@ -193,7 +193,7 @@ pub struct CommonCircuitData, const D: usize> { pub(crate) circuit_digest: HashOut, } -impl, const D: usize> CommonCircuitData { +impl, const D: usize> CommonCircuitData { pub fn degree(&self) -> usize { 1 << self.degree_bits } diff --git a/src/plonk/plonk_common.rs b/src/plonk/plonk_common.rs index 4237ac53..dd1bf5d4 100644 --- a/src/plonk/plonk_common.rs +++ b/src/plonk/plonk_common.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::fri::commitment::SALT_SIZE; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -125,7 +125,7 @@ pub(crate) fn eval_l_1(n: usize, x: F) -> F { /// the order-`n` subgroup. /// /// Assumes `x != 1`; if `x` could be 1 then this is unsound. -pub(crate) fn eval_l_1_recursively, const D: usize>( +pub(crate) fn eval_l_1_recursively, const D: usize>( builder: &mut CircuitBuilder, n: usize, x: ExtensionTarget, @@ -163,7 +163,7 @@ pub(crate) fn reduce_with_powers(terms: &[F], alpha: F) -> F { sum } -pub(crate) fn reduce_with_powers_ext_recursive, const D: usize>( +pub(crate) fn reduce_with_powers_ext_recursive, const D: usize>( builder: &mut CircuitBuilder, terms: &[ExtensionTarget], alpha: Target, diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index e1ffd60c..68871202 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::fri::commitment::PolynomialBatchCommitment; use crate::fri::proof::{FriProof, FriProofTarget}; use crate::hash::hash_types::MerkleCapTarget; @@ -58,7 +58,7 @@ pub struct OpeningSet, const D: usize> { pub quotient_polys: Vec, } -impl, const D: usize> OpeningSet { +impl, const D: usize> OpeningSet { pub fn new( z: F::Extension, g: F::Extension, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index a8951897..7f16af04 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -3,7 +3,7 @@ use log::Level; use rayon::prelude::*; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::fri::commitment::PolynomialBatchCommitment; use crate::hash::hash_types::HashOut; use crate::hash::hashing::hash_n_to_hash; @@ -22,7 +22,7 @@ use crate::util::partial_products::partial_products; use crate::util::timing::TimingTree; use crate::util::{log2_ceil, transpose}; -pub(crate) fn prove, const D: usize>( +pub(crate) fn prove, const D: usize>( prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, inputs: PartialWitness, @@ -217,7 +217,7 @@ pub(crate) fn prove, const D: usize>( } /// Compute the partial products used in the `Z` polynomials. -fn all_wires_permutation_partial_products, const D: usize>( +fn all_wires_permutation_partial_products, const D: usize>( witness: &MatrixWitness, betas: &[F], gammas: &[F], @@ -240,7 +240,7 @@ fn all_wires_permutation_partial_products, const D /// Compute the partial products used in the `Z` polynomial. /// Returns the polynomials interpolating `partial_products(f / g)` /// where `f, g` are the products in the definition of `Z`: `Z(g^i) = f / g`. -fn wires_permutation_partial_products, const D: usize>( +fn wires_permutation_partial_products, const D: usize>( witness: &MatrixWitness, beta: F, gamma: F, @@ -294,7 +294,7 @@ fn wires_permutation_partial_products, const D: us .collect() } -fn compute_zs, const D: usize>( +fn compute_zs, const D: usize>( partial_products: &[Vec>], common_data: &CommonCircuitData, ) -> Vec> { @@ -304,7 +304,7 @@ fn compute_zs, const D: usize>( } /// Compute the `Z` polynomial by reusing the computations done in `wires_permutation_partial_products`. -fn compute_z, const D: usize>( +fn compute_z, const D: usize>( partial_products: &[PolynomialValues], common_data: &CommonCircuitData, ) -> PolynomialValues { @@ -317,7 +317,7 @@ fn compute_z, const D: usize>( plonk_z_points.into() } -fn compute_quotient_polys<'a, F: PrimeField + Extendable, const D: usize>( +fn compute_quotient_polys<'a, F: RichField + Extendable, const D: usize>( common_data: &CommonCircuitData, prover_data: &'a ProverOnlyCircuitData, public_inputs_hash: &HashOut, diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index bdb5f3d5..3bd50bec 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -1,5 +1,5 @@ use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::hash::hash_types::HashOutTarget; use crate::iop::challenger::RecursiveChallenger; use crate::plonk::circuit_builder::CircuitBuilder; @@ -10,7 +10,7 @@ use crate::plonk::vars::EvaluationTargets; use crate::util::reducing::ReducingFactorTarget; use crate::with_context; -impl, const D: usize> CircuitBuilder { +impl, const D: usize> CircuitBuilder { /// Recursively verifies an inner proof. pub fn add_recursive_verifier( &mut self, @@ -140,7 +140,7 @@ mod tests { use crate::util::log2_strict; // Construct a `FriQueryRoundTarget` with the same dimensions as the ones in `proof`. - fn get_fri_query_round, const D: usize>( + fn get_fri_query_round, const D: usize>( proof: &Proof, builder: &mut CircuitBuilder, ) -> FriQueryRoundTarget { @@ -173,7 +173,7 @@ mod tests { } // Construct a `ProofTarget` with the same dimensions as `proof`. - fn proof_to_proof_target, const D: usize>( + fn proof_to_proof_target, const D: usize>( proof_with_pis: &ProofWithPublicInputs, builder: &mut CircuitBuilder, ) -> ProofWithPublicInputsTarget { diff --git a/src/plonk/vanishing_poly.rs b/src/plonk/vanishing_poly.rs index 0df5055c..b22ebb33 100644 --- a/src/plonk/vanishing_poly.rs +++ b/src/plonk/vanishing_poly.rs @@ -1,6 +1,6 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::gate::PrefixedGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -15,7 +15,7 @@ use crate::with_context; /// Evaluate the vanishing polynomial at `x`. In this context, the vanishing polynomial is a random /// linear combination of gate constraints, plus some other terms relating to the permutation /// argument. All such terms should vanish on `H`. -pub(crate) fn eval_vanishing_poly, const D: usize>( +pub(crate) fn eval_vanishing_poly, const D: usize>( common_data: &CommonCircuitData, x: F::Extension, vars: EvaluationVars, @@ -102,7 +102,7 @@ pub(crate) fn eval_vanishing_poly, const D: usize> } /// Like `eval_vanishing_poly`, but specialized for base field points. -pub(crate) fn eval_vanishing_poly_base, const D: usize>( +pub(crate) fn eval_vanishing_poly_base, const D: usize>( common_data: &CommonCircuitData, index: usize, x: F, @@ -200,7 +200,7 @@ pub(crate) fn eval_vanishing_poly_base, const D: u /// `num_gate_constraints` is the largest number of constraints imposed by any gate. It is not /// strictly necessary, but it helps performance by ensuring that we allocate a vector with exactly /// the capacity that we need. -pub fn evaluate_gate_constraints, const D: usize>( +pub fn evaluate_gate_constraints, const D: usize>( gates: &[PrefixedGate], num_gate_constraints: usize, vars: EvaluationVars, @@ -219,7 +219,7 @@ pub fn evaluate_gate_constraints, const D: usize>( constraints } -pub fn evaluate_gate_constraints_base, const D: usize>( +pub fn evaluate_gate_constraints_base, const D: usize>( gates: &[PrefixedGate], num_gate_constraints: usize, vars: EvaluationVarsBase, @@ -238,7 +238,7 @@ pub fn evaluate_gate_constraints_base, const D: us constraints } -pub fn evaluate_gate_constraints_recursively, const D: usize>( +pub fn evaluate_gate_constraints_recursively, const D: usize>( builder: &mut CircuitBuilder, gates: &[PrefixedGate], num_gate_constraints: usize, @@ -270,7 +270,7 @@ pub fn evaluate_gate_constraints_recursively, cons /// /// Assumes `x != 1`; if `x` could be 1 then this is unsound. This is fine if `x` is a random /// variable drawn from a sufficiently large domain. -pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( +pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( builder: &mut CircuitBuilder, common_data: &CommonCircuitData, x: ExtensionTarget, diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 90a2086f..96c43d52 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -1,7 +1,7 @@ use anyhow::{ensure, Result}; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::fri::verifier::verify_fri_proof; use crate::hash::hashing::hash_n_to_hash; use crate::iop::challenger::Challenger; @@ -11,7 +11,7 @@ use crate::plonk::proof::ProofWithPublicInputs; use crate::plonk::vanishing_poly::eval_vanishing_poly; use crate::plonk::vars::EvaluationVars; -pub(crate) fn verify, const D: usize>( +pub(crate) fn verify, const D: usize>( proof_with_pis: ProofWithPublicInputs, verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, diff --git a/src/util/partial_products.rs b/src/util/partial_products.rs index 64874a1f..633047d0 100644 --- a/src/util/partial_products.rs +++ b/src/util/partial_products.rs @@ -3,7 +3,7 @@ use std::ops::Sub; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::PrimeField; +use crate::field::field_types::RichField; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; @@ -61,7 +61,7 @@ pub fn check_partial_products>( res } -pub fn check_partial_products_recursively, const D: usize>( +pub fn check_partial_products_recursively, const D: usize>( builder: &mut CircuitBuilder, v: &[ExtensionTarget], partials: &[ExtensionTarget], diff --git a/src/util/reducing.rs b/src/util/reducing.rs index cd808875..a0bbafe4 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::field::field_types::{Field, PrimeField}; +use crate::field::field_types::{Field, RichField}; use crate::gates::reducing::ReducingGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; @@ -100,7 +100,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: PrimeField + Extendable, + F: RichField + Extendable, { let max_coeffs_len = ReducingGate::::max_coeffs_len( builder.config.num_wires, @@ -149,7 +149,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: PrimeField + Extendable, + F: RichField + Extendable, { let l = terms.len(); self.count += l as u64; @@ -170,7 +170,7 @@ impl ReducingFactorTarget { builder: &mut CircuitBuilder, ) -> ExtensionTarget where - F: PrimeField + Extendable, + F: RichField + Extendable, { let exp = builder.exp_u64_extension(self.base, self.count); self.count = 0;