diff --git a/plonky2/benches/hashing.rs b/plonky2/benches/hashing.rs index 2d17dba1..a968d957 100644 --- a/plonky2/benches/hashing.rs +++ b/plonky2/benches/hashing.rs @@ -3,7 +3,6 @@ use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use plonky2::field::goldilocks_field::GoldilocksField; -use plonky2::hash::gmimc::GMiMC; use plonky2::hash::hash_types::{BytesHash, RichField}; use plonky2::hash::hashing::SPONGE_WIDTH; use plonky2::hash::keccak::KeccakHash; @@ -11,16 +10,6 @@ use plonky2::hash::poseidon::Poseidon; use plonky2::plonk::config::Hasher; use tynm::type_name; -pub(crate) fn bench_gmimc, const WIDTH: usize>(c: &mut Criterion) { - c.bench_function(&format!("gmimc<{}, {}>", type_name::(), WIDTH), |b| { - b.iter_batched( - || F::rand_arr::(), - |state| F::gmimc_permute(state), - BatchSize::SmallInput, - ) - }); -} - pub(crate) fn bench_keccak(c: &mut Criterion) { c.bench_function("keccak256", |b| { b.iter_batched( @@ -45,7 +34,6 @@ pub(crate) fn bench_poseidon(c: &mut Criterion) { } fn criterion_benchmark(c: &mut Criterion) { - bench_gmimc::(c); bench_poseidon::(c); bench_keccak::(c); } diff --git a/plonky2/src/bin/generate_constants.rs b/plonky2/src/bin/generate_constants.rs index eb35aec3..d9757aff 100644 --- a/plonky2/src/bin/generate_constants.rs +++ b/plonky2/src/bin/generate_constants.rs @@ -11,7 +11,6 @@ use rand_chacha::ChaCha8Rng; // range of GoldilocksField, then verify that each constant also fits in GoldilocksField. const SAMPLE_RANGE_END: u64 = 0xffffffff70000001; -// const N: usize = 101; // For GMiMC // const N: usize = 8 * 30; // For Posiedon-8 const N: usize = 12 * 30; // For Posiedon-12 diff --git a/plonky2/src/gates/gate_tree.rs b/plonky2/src/gates/gate_tree.rs index 029616a8..2f670337 100644 --- a/plonky2/src/gates/gate_tree.rs +++ b/plonky2/src/gates/gate_tree.rs @@ -228,9 +228,9 @@ mod tests { use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::base_sum::BaseSumGate; use crate::gates::constant::ConstantGate; - use crate::gates::gmimc::GMiMCGate; use crate::gates::interpolation::HighDegreeInterpolationGate; use crate::gates::noop::NoopGate; + use crate::gates::poseidon::PoseidonGate; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; #[test] @@ -245,7 +245,7 @@ mod tests { GateRef::new(ConstantGate { num_consts: 4 }), GateRef::new(ArithmeticExtensionGate { num_ops: 4 }), GateRef::new(BaseSumGate::<4>::new(4)), - GateRef::new(GMiMCGate::::new()), + GateRef::new(PoseidonGate::::new()), GateRef::new(HighDegreeInterpolationGate::new(2)), ]; @@ -276,7 +276,7 @@ mod tests { assert!( gates_with_prefix .iter() - .all(|(g, p)| g.0.degree() + g.0.num_constants() + p.len() <= 8), + .all(|(g, p)| g.0.degree() + g.0.num_constants() + p.len() <= 9), "Total degree is larger than 8." ); diff --git a/plonky2/src/gates/gmimc.rs b/plonky2/src/gates/gmimc.rs deleted file mode 100644 index fdfb8673..00000000 --- a/plonky2/src/gates/gmimc.rs +++ /dev/null @@ -1,433 +0,0 @@ -use std::marker::PhantomData; - -use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::Field; -use plonky2_field::packed_field::PackedField; - -use crate::gates::gate::Gate; -use crate::gates::packed_util::PackedEvaluableBase; -use crate::gates::util::StridedConstraintConsumer; -use crate::hash::gmimc; -use crate::hash::gmimc::GMiMC; -use crate::hash::hash_types::RichField; -use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; -use crate::iop::target::Target; -use crate::iop::wire::Wire; -use crate::iop::witness::{PartitionWitness, Witness}; -use crate::plonk::circuit_builder::CircuitBuilder; -use crate::plonk::vars::{ - EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, - EvaluationVarsBasePacked, -}; - -/// Evaluates a full GMiMC permutation with 12 state elements. -/// -/// This also has some extra features to make it suitable for efficiently verifying Merkle proofs. -/// It has a flag which can be used to swap the first four inputs with the next four, for ordering -/// sibling digests. -#[derive(Debug)] -pub struct GMiMCGate< - F: RichField + Extendable + GMiMC, - const D: usize, - const WIDTH: usize, -> { - _phantom: PhantomData, -} - -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. - pub fn wire_input(i: usize) -> usize { - i - } - - /// The wire index for the `i`th output to the permutation. - pub fn wire_output(i: usize) -> usize { - 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 * WIDTH; - - /// A wire which stores the input to the `i`th cubing. - fn wire_cubing_input(i: usize) -> usize { - 2 * WIDTH + 1 + i - } - - /// End of wire indices, exclusive. - fn end() -> usize { - 2 * WIDTH + 1 + gmimc::NUM_ROUNDS - } -} - -impl + GMiMC, const D: usize, const WIDTH: usize> Gate - for GMiMCGate -{ - fn id(&self) -> String { - format!(" {:?}", WIDTH, self) - } - - fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let mut constraints = Vec::with_capacity(self.num_constraints()); - - // Assert that `swap` is binary. - let swap = vars.local_wires[Self::WIRE_SWAP]; - constraints.push(swap * (swap - F::Extension::ONE)); - - let mut state = Vec::with_capacity(12); - for i in 0..4 { - let a = vars.local_wires[i]; - let b = vars.local_wires[i + 4]; - state.push(a + swap * (b - a)); - } - for i in 0..4 { - let a = vars.local_wires[i + 4]; - let b = vars.local_wires[i]; - state.push(a + swap * (b - a)); - } - for i in 8..12 { - state.push(vars.local_wires[i]); - } - - // Value that is implicitly added to each element. - // See https://affine.group/2020/02/starkware-challenge - let mut addition_buffer = F::Extension::ZERO; - - 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(); - addition_buffer += f; - state[active] -= f; - } - - for i in 0..WIDTH { - state[i] += addition_buffer; - constraints.push(state[i] - vars.local_wires[Self::wire_output(i)]); - } - - constraints - } - - fn eval_unfiltered_base_one( - &self, - _vars: EvaluationVarsBase, - _yield_constr: StridedConstraintConsumer, - ) { - panic!("use eval_unfiltered_base_packed instead"); - } - - fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - self.eval_unfiltered_base_batch_packed(vars_base) - } - - fn eval_unfiltered_recursively( - &self, - builder: &mut CircuitBuilder, - vars: EvaluationTargets, - ) -> Vec> { - let mut constraints = Vec::with_capacity(self.num_constraints()); - - let swap = vars.local_wires[Self::WIRE_SWAP]; - constraints.push(builder.mul_sub_extension(swap, swap, swap)); - - let mut state = Vec::with_capacity(12); - for i in 0..4 { - let a = vars.local_wires[i]; - let b = vars.local_wires[i + 4]; - let delta = builder.sub_extension(b, a); - state.push(builder.mul_add_extension(swap, delta, a)); - } - for i in 0..4 { - let a = vars.local_wires[i + 4]; - let b = vars.local_wires[i]; - let delta = builder.sub_extension(b, a); - state.push(builder.mul_add_extension(swap, delta, a)); - } - for i in 8..12 { - state.push(vars.local_wires[i]); - } - - // Value that is implicitly added to each element. - // See https://affine.group/2020/02/starkware-challenge - let mut addition_buffer = builder.zero_extension(); - - for r in 0..gmimc::NUM_ROUNDS { - let active = r % WIDTH; - - 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)]; - constraints.push(builder.sub_extension(cubing_input, cubing_input_wire)); - let f = builder.cube_extension(cubing_input_wire); - addition_buffer = builder.add_extension(addition_buffer, f); - state[active] = builder.sub_extension(state[active], f); - } - - 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)])); - } - - constraints - } - - fn generators( - &self, - gate_index: usize, - _local_constants: &[F], - ) -> Vec>> { - let gen = GMiMCGenerator:: { - gate_index, - _phantom: PhantomData, - }; - vec![Box::new(gen.adapter())] - } - - fn num_wires(&self) -> usize { - Self::end() - } - - fn num_constants(&self) -> usize { - 0 - } - - fn degree(&self) -> usize { - 3 - } - - fn num_constraints(&self) -> usize { - gmimc::NUM_ROUNDS + WIDTH + 1 - } -} - -impl + GMiMC, const D: usize, const WIDTH: usize> - PackedEvaluableBase for GMiMCGate -{ - fn eval_unfiltered_base_packed>( - &self, - vars: EvaluationVarsBasePacked

, - mut yield_constr: StridedConstraintConsumer

, - ) { - // Assert that `swap` is binary. - let swap = vars.local_wires[Self::WIRE_SWAP]; - yield_constr.one(swap * (swap - F::ONE)); - - let mut state = Vec::with_capacity(12); - for i in 0..4 { - let a = vars.local_wires[i]; - let b = vars.local_wires[i + 4]; - state.push(a + swap * (b - a)); - } - for i in 0..4 { - let a = vars.local_wires[i + 4]; - let b = vars.local_wires[i]; - state.push(a + swap * (b - a)); - } - for i in 8..12 { - state.push(vars.local_wires[i]); - } - - // Value that is implicitly added to each element. - // See https://affine.group/2020/02/starkware-challenge - let mut addition_buffer = P::ZEROS; - - 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)]; - yield_constr.one(cubing_input - cubing_input_wire); - let f = cubing_input_wire.square() * cubing_input_wire; - addition_buffer += f; - state[active] -= f; - } - - for i in 0..WIDTH { - state[i] += addition_buffer; - yield_constr.one(state[i] - vars.local_wires[Self::wire_output(i)]); - } - } -} - -#[derive(Debug)] -struct GMiMCGenerator< - F: RichField + Extendable + GMiMC, - const D: usize, - const WIDTH: usize, -> { - gate_index: usize, - _phantom: PhantomData, -} - -impl + GMiMC, const D: usize, const WIDTH: usize> - SimpleGenerator for GMiMCGenerator -{ - fn dependencies(&self) -> Vec { - 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 - .into_iter() - .map(|input| { - Target::Wire(Wire { - gate: self.gate_index, - input, - }) - }) - .collect() - } - - fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let mut state = (0..WIDTH) - .map(|i| { - witness.get_wire(Wire { - gate: self.gate_index, - input: GMiMCGate::::wire_input(i), - }) - }) - .collect::>(); - - let swap_value = witness.get_wire(Wire { - gate: self.gate_index, - input: GMiMCGate::::WIRE_SWAP, - }); - debug_assert!(swap_value == F::ZERO || swap_value == F::ONE); - if swap_value == F::ONE { - for i in 0..4 { - state.swap(i, 4 + i); - } - } - - // 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..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), - }, - cubing_input, - ); - let f = cubing_input.cube(); - addition_buffer += f; - state[active] -= f; - } - - for i in 0..WIDTH { - state[i] += addition_buffer; - out_buffer.set_wire( - Wire { - gate: self.gate_index, - input: GMiMCGate::::wire_output(i), - }, - state[i], - ); - } - } -} - -#[cfg(test)] -mod tests { - use anyhow::Result; - use plonky2_field::field_types::Field; - use plonky2_field::goldilocks_field::GoldilocksField; - - use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; - use crate::gates::gmimc::GMiMCGate; - use crate::hash::gmimc::GMiMC; - use crate::iop::generator::generate_partial_witness; - use crate::iop::wire::Wire; - use crate::iop::witness::{PartialWitness, Witness}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - #[test] - fn generated_output() { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - const WIDTH: usize = 12; - - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::new(config); - type Gate = GMiMCGate; - let gate = Gate::new(); - let gate_index = builder.add_gate(gate, vec![]); - let circuit = builder.build_prover::(); - - let permutation_inputs = (0..WIDTH).map(F::from_canonical_usize).collect::>(); - - let mut inputs = PartialWitness::new(); - inputs.set_wire( - Wire { - gate: gate_index, - input: Gate::WIRE_SWAP, - }, - F::ZERO, - ); - for i in 0..WIDTH { - inputs.set_wire( - Wire { - gate: gate_index, - input: Gate::wire_input(i), - }, - permutation_inputs[i], - ); - } - - let witness = generate_partial_witness(inputs, &circuit.prover_only, &circuit.common); - - let expected_outputs: [F; WIDTH] = - F::gmimc_permute_naive(permutation_inputs.try_into().unwrap()); - for i in 0..WIDTH { - let out = witness.get_wire(Wire { - gate: 0, - input: Gate::wire_output(i), - }); - assert_eq!(out, expected_outputs[i]); - } - } - - #[test] - fn low_degree() { - type F = GoldilocksField; - const WIDTH: usize = 12; - let gate = GMiMCGate::::new(); - test_low_degree(gate) - } - - #[test] - fn eval_fns() -> Result<()> { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - const WIDTH: usize = 12; - let gate = GMiMCGate::::new(); - test_eval_fns::(gate) - } -} diff --git a/plonky2/src/gates/mod.rs b/plonky2/src/gates/mod.rs index aae46dc5..a3f92615 100644 --- a/plonky2/src/gates/mod.rs +++ b/plonky2/src/gates/mod.rs @@ -11,7 +11,6 @@ pub mod constant; pub mod exponentiation; pub mod gate; pub mod gate_tree; -pub mod gmimc; pub mod interpolation; pub mod low_degree_interpolation; pub mod multiplication_extension; diff --git a/plonky2/src/hash/gmimc.rs b/plonky2/src/hash/gmimc.rs deleted file mode 100644 index 050bdeec..00000000 --- a/plonky2/src/hash/gmimc.rs +++ /dev/null @@ -1,168 +0,0 @@ -use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::Field; -use plonky2_field::goldilocks_field::GoldilocksField; -use unroll::unroll_for_loops; - -use crate::gates::gmimc::GMiMCGate; -use crate::hash::hash_types::{HashOut, RichField}; -use crate::hash::hashing::{compress, hash_n_to_hash, PlonkyPermutation, SPONGE_WIDTH}; -use crate::iop::target::{BoolTarget, Target}; -use crate::plonk::circuit_builder::CircuitBuilder; -use crate::plonk::config::{AlgebraicHasher, Hasher}; - -pub(crate) const NUM_ROUNDS: usize = 101; - -pub trait GMiMC: Field -where - [u64; NUM_ROUNDS]: Sized, -{ - const ROUND_CONSTANTS: [u64; NUM_ROUNDS]; - - #[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, &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 - } - - #[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 - } -} - -/// See `generate_constants` about how these were generated. -#[rustfmt::skip] -const GOLDILOCKS_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, -]; - -impl GMiMC<8> for GoldilocksField { - const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = GOLDILOCKS_ROUND_CONSTANTS; -} - -impl GMiMC<12> for GoldilocksField { - const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = GOLDILOCKS_ROUND_CONSTANTS; -} - -pub struct GMiMCPermutation; -impl PlonkyPermutation for GMiMCPermutation { - fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH] { - F::gmimc_permute(input) - } -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct GMiMCHash; -impl Hasher for GMiMCHash { - const HASH_SIZE: usize = 4 * 8; - type Hash = HashOut; - type Permutation = GMiMCPermutation; - - fn hash(input: &[F], pad: bool) -> Self::Hash { - hash_n_to_hash::(input, pad) - } - - fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { - compress::(left, right) - } -} - -impl AlgebraicHasher for GMiMCHash { - fn permute_swapped( - inputs: [Target; SPONGE_WIDTH], - swap: BoolTarget, - builder: &mut CircuitBuilder, - ) -> [Target; SPONGE_WIDTH] - where - F: RichField + Extendable, - { - let gate_type = GMiMCGate::::new(); - let gate = builder.add_gate(gate_type, vec![]); - - let swap_wire = GMiMCGate::::WIRE_SWAP; - let swap_wire = Target::wire(gate, swap_wire); - builder.connect(swap.target, swap_wire); - - // Route input wires. - for i in 0..SPONGE_WIDTH { - let in_wire = GMiMCGate::::wire_input(i); - let in_wire = Target::wire(gate, in_wire); - builder.connect(inputs[i], in_wire); - } - - // Collect output wires. - (0..SPONGE_WIDTH) - .map(|i| Target::wire(gate, GMiMCGate::::wire_output(i))) - .collect::>() - .try_into() - .unwrap() - } -} - -#[cfg(test)] -mod tests { - use plonky2_field::goldilocks_field::GoldilocksField; - - 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() { - check_consistency::(); - } -} diff --git a/plonky2/src/hash/hash_types.rs b/plonky2/src/hash/hash_types.rs index 674486c8..51a93fdc 100644 --- a/plonky2/src/hash/hash_types.rs +++ b/plonky2/src/hash/hash_types.rs @@ -3,13 +3,12 @@ use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::hash::gmimc::GMiMC; use crate::hash::poseidon::Poseidon; use crate::iop::target::Target; use crate::plonk::config::GenericHashOut; /// 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> + Poseidon {} +pub trait RichField: PrimeField + Poseidon {} impl RichField for GoldilocksField {} diff --git a/plonky2/src/hash/mod.rs b/plonky2/src/hash/mod.rs index 5a8ccb3f..b8293920 100644 --- a/plonky2/src/hash/mod.rs +++ b/plonky2/src/hash/mod.rs @@ -1,5 +1,4 @@ mod arch; -pub mod gmimc; pub mod hash_types; pub mod hashing; pub mod keccak; @@ -8,4 +7,3 @@ pub mod merkle_tree; pub mod path_compression; pub mod poseidon; pub mod poseidon_goldilocks; -pub mod rescue; diff --git a/plonky2/src/hash/rescue.rs b/plonky2/src/hash/rescue.rs deleted file mode 100644 index 59e9d265..00000000 --- a/plonky2/src/hash/rescue.rs +++ /dev/null @@ -1,457 +0,0 @@ -//! Implements Rescue Prime. - -use plonky2_field::field_types::Field; -use unroll::unroll_for_loops; - -const ROUNDS: usize = 8; - -const W: usize = 12; - -const MDS: [[u64; W]; W] = [ - [ - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - 3074457345215605419, - 11068046442776179508, - 13835058053470224385, - 6148914690431210838, - 9223372035646816257, - 1, - ], - [ - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - 3074457345215605419, - 11068046442776179508, - 13835058053470224385, - 6148914690431210838, - 9223372035646816257, - ], - [ - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - 3074457345215605419, - 11068046442776179508, - 13835058053470224385, - 6148914690431210838, - ], - [ - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - 3074457345215605419, - 11068046442776179508, - 13835058053470224385, - ], - [ - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - 3074457345215605419, - 11068046442776179508, - ], - [ - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - 3074457345215605419, - ], - [ - 1024819115071868473, - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - 2635249153041947502, - ], - [ - 9708812669101911849, - 1024819115071868473, - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - 16140901062381928449, - ], - [ - 2767011610694044877, - 9708812669101911849, - 1024819115071868473, - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - 2049638230143736946, - ], - [ - 878416384347315834, - 2767011610694044877, - 9708812669101911849, - 1024819115071868473, - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - 5534023221388089754, - ], - [ - 17608255704416649217, - 878416384347315834, - 2767011610694044877, - 9708812669101911849, - 1024819115071868473, - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - 16769767337539665921, - ], - [ - 15238614667590392076, - 17608255704416649217, - 878416384347315834, - 2767011610694044877, - 9708812669101911849, - 1024819115071868473, - 3255307777287111620, - 17293822566837780481, - 15987178195121148178, - 1317624576520973751, - 5675921252705733081, - 10760600708254618966, - ], -]; - -const RESCUE_CONSTANTS: [[u64; W]; ROUNDS * 2] = [ - [ - 12050887499329086906, - 1748247961703512657, - 315780861775001585, - 2827656358919812970, - 13335864861236723579, - 3010729529365640897, - 8463534053828271146, - 2528500966106598845, - 8969871077123422281, - 1002624930202741107, - 599979829006456404, - 4386170815218774254, - ], - [ - 5771413917591851532, - 11946802620311685142, - 4759792267858670262, - 6879094914431255667, - 3985911073214909073, - 1542850118294175816, - 5393560436452023029, - 8331250756632997735, - 3395511836281190608, - 17601255793194446503, - 12848459944475727152, - 11995465655754698601, - ], - [ - 14063960046551560130, - 14790209580166185143, - 5509023472758717841, - 1274395897760495573, - 16719545989415697758, - 17865948122414223407, - 3919263713959798649, - 5633741078654387163, - 15665612362287352054, - 3418834727998553015, - 5324019631954832682, - 17962066557010997431, - ], - [ - 3282193104189649752, - 18423507935939999211, - 9035104445528866459, - 30842260240043277, - 3896337933354935129, - 6615548113269323045, - 6625827707190475694, - 6677757329269550670, - 11419013193186889337, - 17111888851716383760, - 12075517898615128691, - 8139844272075088233, - ], - [ - 8872892112814161072, - 17529364346566228604, - 7526576514327158912, - 850359069964902700, - 9679332912197531902, - 10591229741059812071, - 12759208863825924546, - 14552519355635838750, - 16066249893409806278, - 11283035366525176262, - 1047378652379935387, - 17032498397644511356, - ], - [ - 2938626421478254042, - 10375267398354586672, - 13728514869380643947, - 16707318479225743731, - 9785828188762698567, - 8610686976269299752, - 5478372191917042178, - 12716344455538470365, - 9968276048553747246, - 14746805727771473956, - 4822070620124107028, - 9901161649549513416, - ], - [ - 13458162407040644078, - 4045792126424269312, - 9709263167782315020, - 2163173014916005515, - 17079206331095671215, - 2556388076102629669, - 6582772486087242347, - 1239959540200663058, - 18268236910639895687, - 12499012548657350745, - 17213068585339946119, - 7641451088868756688, - ], - [ - 14674555473338434116, - 14624532976317185113, - 13625541984298615970, - 7612892294159054770, - 12294028208969561574, - 6067206081581804358, - 5778082506883496792, - 7389487446513884800, - 12929525660730020877, - 18244350162788654296, - 15285920877034454694, - 3640669683987215349, - ], - [ - 6737585134029996281, - 1826890539455248546, - 289376081355380231, - 10782622161517803787, - 12978425540147835172, - 9828233103297278473, - 16384075371934678711, - 3187492301890791304, - 12985433735185968457, - 9470935291631377473, - 16328323199113140151, - 16218490552434224203, - ], - [ - 6188809977565251499, - 18437718710937437067, - 4530469469895539008, - 9596355277372723349, - 13602518824447658705, - 8759976068576854281, - 10504320064094929535, - 3980760429843656150, - 14609448298151012462, - 5839843841558860609, - 10283805260656050418, - 7239168159249274821, - ], - [ - 3604243611640027441, - 5237321927316578323, - 5071861664926666316, - 13025405632646149705, - 3285281651566464074, - 12121596060272825779, - 1900602777802961569, - 8122527981264852045, - 6731303887159752901, - 9197659817406857040, - 844741616904786364, - 14249777686667858094, - ], - [ - 8602844218963499297, - 10133401373828451640, - 11618292280328565166, - 8828272598402499582, - 4252246265076774689, - 9760449011955070998, - 10233981507028897480, - 10427510555228840014, - 1007817664531124790, - 4465396600980659145, - 7727267420665314215, - 7904022788946844554, - ], - [ - 11418297156527169222, - 15865399053509010196, - 1727198235391450850, - 16557095577717348672, - 1524052121709169653, - 14531367160053894310, - 4071756280138432327, - 10333204220115446291, - 16584144375833061215, - 12237566480526488368, - 11090440024401607208, - 18281335018830792766, - ], - [ - 16152169547074248135, - 18338155611216027761, - 15842640128213925612, - 14687926435880145351, - 13259626900273707210, - 6187877366876303234, - 10312881470701795438, - 1924945292721719446, - 2278209355262975917, - 3250749056007953206, - 11589006946114672195, - 241829012299953928, - ], - [ - 11244459446597052449, - 7319043416418482137, - 8148526814449636806, - 9054933038587901070, - 550333919248348827, - 5513167392062632770, - 12644459803778263764, - 9903621375535446226, - 16390581784506871871, - 14586524717888286021, - 6975796306584548762, - 5200407948555191573, - ], - [ - 2855794043288846965, - 1259443213892506318, - 6145351706926586935, - 3853784494234324998, - 5871277378086513850, - 9414363368707862566, - 11946957446931890832, - 308083693687568600, - 12712587722369770461, - 6792392698104204991, - 16465224002344550280, - 10282380383506806095, - ], -]; - -pub fn rescue(mut xs: [F; W]) -> [F; W] { - for r in 0..8 { - xs = sbox_layer_a(xs); - xs = mds_layer(xs); - xs = constant_layer(xs, &RESCUE_CONSTANTS[r * 2]); - - xs = sbox_layer_b(xs); - xs = mds_layer(xs); - xs = constant_layer(xs, &RESCUE_CONSTANTS[r * 2 + 1]); - } - xs -} - -#[unroll_for_loops] -fn sbox_layer_a(x: [F; W]) -> [F; W] { - let mut result = [F::ZERO; W]; - for i in 0..W { - result[i] = x[i].cube(); - } - result -} - -#[unroll_for_loops] -fn sbox_layer_b(x: [F; W]) -> [F; W] { - let mut result = [F::ZERO; W]; - for i in 0..W { - result[i] = x[i].cube_root(); - } - result -} - -#[unroll_for_loops] -fn mds_layer(x: [F; W]) -> [F; W] { - let mut result = [F::ZERO; W]; - for r in 0..W { - for c in 0..W { - result[r] += F::from_canonical_u64(MDS[r][c]) * x[c]; - } - } - result -} - -#[unroll_for_loops] -fn constant_layer(xs: [F; W], con: &[u64; W]) -> [F; W] { - let mut result = [F::ZERO; W]; - for i in 0..W { - result[i] = xs[i] + F::from_canonical_u64(con[i]); - } - result -} diff --git a/plonky2/src/plonk/config.rs b/plonky2/src/plonk/config.rs index 72d5487e..281d0025 100644 --- a/plonky2/src/plonk/config.rs +++ b/plonky2/src/plonk/config.rs @@ -5,7 +5,6 @@ use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::goldilocks_field::GoldilocksField; use serde::{de::DeserializeOwned, Serialize}; -use crate::hash::gmimc::GMiMCHash; use crate::hash::hash_types::HashOut; use crate::hash::hash_types::RichField; use crate::hash::hashing::{PlonkyPermutation, SPONGE_WIDTH}; @@ -76,16 +75,6 @@ impl GenericConfig<2> for PoseidonGoldilocksConfig { type InnerHasher = PoseidonHash; } -/// Configuration using GMiMC over the Goldilocks field. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct GMiMCGoldilocksConfig; -impl GenericConfig<2> for GMiMCGoldilocksConfig { - type F = GoldilocksField; - type FE = QuadraticExtension; - type Hasher = GMiMCHash; - type InnerHasher = GMiMCHash; -} - /// Configuration using truncated Keccak over the Goldilocks field. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct KeccakGoldilocksConfig; diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index fbe1ad53..fccaea5c 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -212,9 +212,7 @@ mod tests { use crate::gates::noop::NoopGate; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_data::VerifierOnlyCircuitData; - use crate::plonk::config::{ - GMiMCGoldilocksConfig, GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig, - }; + use crate::plonk::config::{GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig}; use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; use crate::plonk::prover::prove; use crate::util::timing::TimingTree; @@ -352,7 +350,6 @@ mod tests { init_logger(); const D: usize = 2; type PC = PoseidonGoldilocksConfig; - type GC = GMiMCGoldilocksConfig; type KC = KeccakGoldilocksConfig; type F = >::F; @@ -363,16 +360,8 @@ mod tests { recursive_proof::(proof, vd, cd, &config, &config, None, false, false)?; test_serialization(&proof, &cd)?; - let (proof, vd, cd) = - recursive_proof::(proof, vd, cd, &config, &config, None, false, false)?; - test_serialization(&proof, &cd)?; - - let (proof, vd, cd) = - recursive_proof::(proof, vd, cd, &config, &config, None, false, false)?; - test_serialization(&proof, &cd)?; - let (proof, _vd, cd) = - recursive_proof::(proof, vd, cd, &config, &config, None, false, false)?; + recursive_proof::(proof, vd, cd, &config, &config, None, false, false)?; test_serialization(&proof, &cd)?; Ok(())