From 156fd45b83b5923daa1046dc4159a5a226ac4c7d Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 20 Dec 2021 16:07:14 +0100 Subject: [PATCH 1/4] Add GMiMC config --- src/plonk/config.rs | 111 ++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/src/plonk/config.rs b/src/plonk/config.rs index e448bc7c..c77ce5f5 100644 --- a/src/plonk/config.rs +++ b/src/plonk/config.rs @@ -8,10 +8,12 @@ use crate::field::extension_field::quadratic::QuadraticExtension; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::RichField; use crate::field::goldilocks_field::GoldilocksField; +use crate::gates::gmimc::GMiMCGate; use crate::gates::poseidon::PoseidonGate; use crate::hash::hash_types::{BytesHash, HashOut}; use crate::hash::hashing::{ - compress, hash_n_to_hash, PlonkyPermutation, PoseidonPermutation, SPONGE_WIDTH, + compress, hash_n_to_hash, GMiMCPermutation, PlonkyPermutation, PoseidonPermutation, + SPONGE_WIDTH, }; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; @@ -106,55 +108,54 @@ impl AlgebraicHasher for PoseidonHash { } } -// TODO: Remove width from `GMiMCGate` to make this work. -// #[derive(Copy, Clone, Debug, Eq, PartialEq)] -// pub struct GMiMCHash; -// impl Hasher for GMiMCHash { -// const HASH_SIZE: usize = 4 * 8; -// type Hash = HashOut; -// -// fn hash(input: Vec, pad: bool) -> Self::Hash { -// hash_n_to_hash::>::Permutation>(input, pad) -// } -// -// fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { -// compress::>::Permutation>(left, right) -// } -// } -// -// impl AlgebraicHasher for GMiMCHash { -// type Permutation = GMiMCPermutation; -// -// fn permute_swapped( -// inputs: [Target; WIDTH], -// swap: BoolTarget, -// builder: &mut CircuitBuilder, -// ) -> [Target; WIDTH] -// where -// F: 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..W { -// 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..W) -// .map(|i| Target::wire(gate, input: GMiMCGate::wire_output(i))) -// .collect::>() -// .try_into() -// .unwrap() -// } -// } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct GMiMCHash; +impl Hasher for GMiMCHash { + const HASH_SIZE: usize = 4 * 8; + type Hash = HashOut; + + fn hash(input: Vec, pad: bool) -> Self::Hash { + hash_n_to_hash::>::Permutation>(input, pad) + } + + fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { + compress::>::Permutation>(left, right) + } +} + +impl AlgebraicHasher for GMiMCHash { + type Permutation = GMiMCPermutation; + + fn permute_swapped( + inputs: [Target; SPONGE_WIDTH], + swap: BoolTarget, + builder: &mut CircuitBuilder, + ) -> [Target; SPONGE_WIDTH] + where + F: 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() + } +} /// Keccak-256 hash function. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -225,6 +226,16 @@ impl AlgebraicConfig<2> for PoseidonGoldilocksConfig { type InnerHasher = PoseidonHash; } +/// Configuration using GMiMC over the Goldilocks field. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct GMiMCGoldilocksConfig; +impl AlgebraicConfig<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; From 2e4bea59eecb59eabc48181a68934370f80f0d6d Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 20 Dec 2021 16:16:05 +0100 Subject: [PATCH 2/4] Multi-hash test --- src/plonk/recursive_verifier.rs | 60 ++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index a5f5c7dd..c71cb14c 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -137,7 +137,9 @@ mod tests { use crate::hash::merkle_proofs::MerkleProofTarget; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_data::VerifierOnlyCircuitData; - use crate::plonk::config::{GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig}; + use crate::plonk::config::{ + GMiMCGoldilocksConfig, GenericConfig, KeccakGoldilocksConfig, PoseidonGoldilocksConfig, + }; use crate::plonk::proof::{ CompressedProofWithPublicInputs, OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs, @@ -485,6 +487,62 @@ mod tests { Ok(()) } + #[test] + #[ignore] + fn test_recursive_verifier_multi_hash() -> Result<()> { + init_logger(); + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type GC = GMiMCGoldilocksConfig; + type KC = KeccakGoldilocksConfig; + type F = >::F; + + let config = CircuitConfig::standard_recursion_config(); + let (proof, vd, cd) = dummy_proof::(&config, 4_000)?; + + let (proof, vd, cd) = + recursive_proof::(proof, vd, cd, &config, &config, Some(13), false, false)?; + test_serialization(&proof, &cd)?; + + let (proof, vd, cd) = recursive_proof::( + proof, + vd, + cd, + &config, + &config, + Some(13), + false, + false, + )?; + test_serialization(&proof, &cd)?; + + let (proof, vd, cd) = recursive_proof::( + proof, + vd, + cd, + &config, + &config, + Some(13), + false, + false, + )?; + test_serialization(&proof, &cd)?; + + let (proof, vd, cd) = recursive_proof::( + proof, + vd, + cd, + &config, + &config, + Some(13), + false, + false, + )?; + test_serialization(&proof, &cd)?; + + Ok(()) + } + /// Creates a dummy proof which should have roughly `num_dummy_gates` gates. fn dummy_proof, C: GenericConfig, const D: usize>( config: &CircuitConfig, From fd03a187ce97b185d06ffecfd30942a59080c36f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 20 Dec 2021 16:46:31 +0100 Subject: [PATCH 3/4] Minor --- src/plonk/recursive_verifier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index c71cb14c..30d72e80 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -528,7 +528,7 @@ mod tests { )?; test_serialization(&proof, &cd)?; - let (proof, vd, cd) = recursive_proof::( + let (proof, _vd, cd) = recursive_proof::( proof, vd, cd, From 514cca7ebb61732c5d6bec026e8999210ea7a25f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 20 Dec 2021 19:13:12 +0100 Subject: [PATCH 4/4] PR feedback --- src/plonk/recursive_verifier.rs | 44 ++++++++------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 30d72e80..461f2089 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -492,52 +492,28 @@ mod tests { fn test_recursive_verifier_multi_hash() -> Result<()> { init_logger(); const D: usize = 2; - type C = PoseidonGoldilocksConfig; + type PC = PoseidonGoldilocksConfig; type GC = GMiMCGoldilocksConfig; type KC = KeccakGoldilocksConfig; - type F = >::F; + type F = >::F; let config = CircuitConfig::standard_recursion_config(); - let (proof, vd, cd) = dummy_proof::(&config, 4_000)?; + let (proof, vd, cd) = dummy_proof::(&config, 4_000)?; let (proof, vd, cd) = - recursive_proof::(proof, vd, cd, &config, &config, Some(13), false, false)?; + 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, - Some(13), - false, - false, - )?; + 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, - Some(13), - false, - false, - )?; + 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, - Some(13), - false, - false, - )?; + let (proof, _vd, cd) = + recursive_proof::(proof, vd, cd, &config, &config, None, false, false)?; test_serialization(&proof, &cd)?; Ok(())