diff --git a/src/gadgets/hash.rs b/src/gadgets/hash.rs new file mode 100644 index 00000000..cbf8f5e2 --- /dev/null +++ b/src/gadgets/hash.rs @@ -0,0 +1,42 @@ +use std::convert::TryInto; + +use crate::circuit_builder::CircuitBuilder; +use crate::field::field::Field; +use crate::gates::gmimc::GMiMCGate; +use crate::hash::GMIMC_ROUNDS; +use crate::target::Target; +use crate::wire::Wire; + +impl CircuitBuilder { + pub fn permute(&mut self, inputs: [Target; 12]) -> [Target; 12] { + let zero = self.zero(); + let gate = self.add_gate_no_constants( + GMiMCGate::::with_automatic_constants()); + + // We don't want to swap any inputs, so set that wire to 0. + let swap_wire = GMiMCGate::::WIRE_SWAP; + let swap_wire = Target::Wire(Wire { gate, input: swap_wire }); + self.route(zero, swap_wire); + + // The old accumulator wire doesn't matter, since we won't read the new accumulator wire. + // We do have to set it to something though, so we'll arbitrary pick 0. + let old_acc_wire = GMiMCGate::::WIRE_INDEX_ACCUMULATOR_OLD; + let old_acc_wire = Target::Wire(Wire { gate, input: old_acc_wire }); + self.route(zero, old_acc_wire); + + // Route input wires. + for i in 0..12 { + let in_wire = GMiMCGate::::wire_input(i); + let in_wire = Target::Wire(Wire { gate, input: in_wire }); + self.route(inputs[i], in_wire); + } + + // Collect output wires. + (0..12) + .map(|i| Target::Wire( + Wire { gate, input: GMiMCGate::::wire_output(i) })) + .collect::>() + .try_into() + .unwrap() + } +} diff --git a/src/gadgets/merkle_proofs.rs b/src/gadgets/merkle_proofs.rs index 307ec153..9154647b 100644 --- a/src/gadgets/merkle_proofs.rs +++ b/src/gadgets/merkle_proofs.rs @@ -3,7 +3,6 @@ use std::convert::TryInto; use crate::circuit_builder::CircuitBuilder; use crate::field::field::Field; use crate::gates::gmimc::GMiMCGate; -use crate::gates::noop::NoopGate; use crate::hash::{compress, hash_or_noop}; use crate::hash::GMIMC_ROUNDS; use crate::proof::{Hash, HashTarget}; @@ -41,10 +40,6 @@ pub(crate) fn verify_merkle_proof( } impl CircuitBuilder { - pub(crate) fn permute(&mut self, state: [Target; 12]) -> [Target; 12] { - todo!() - } - /// Verifies that the given leaf data is present at the given index in the Merkle tree with the /// given root. pub(crate) fn verify_merkle_proof( diff --git a/src/gadgets/mod.rs b/src/gadgets/mod.rs index 7af6dc9e..c4f8dad4 100644 --- a/src/gadgets/mod.rs +++ b/src/gadgets/mod.rs @@ -1,3 +1,4 @@ -pub(crate) mod arithmetic; +pub mod arithmetic; +pub mod hash; pub(crate) mod merkle_proofs; pub(crate) mod split_join; diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 77c7c526..63cf8918 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -1,12 +1,12 @@ use std::sync::Arc; use crate::circuit_builder::CircuitBuilder; -use crate::vars::{EvaluationTargets, EvaluationVars}; use crate::field::field::Field; use crate::gates::gate::{Gate, GateRef}; use crate::generator::{SimpleGenerator, WitnessGenerator}; use crate::gmimc::gmimc_automatic_constants; use crate::target::Target; +use crate::vars::{EvaluationTargets, EvaluationVars}; use crate::wire::Wire; use crate::witness::PartialWitness; @@ -69,8 +69,8 @@ impl Gate for GMiMCGate { fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let mut constraints = Vec::with_capacity(W + R); - let swap = vars.local_wires[Self::WIRE_SWAP]; // Assert that `swap` is binary. + let swap = vars.local_wires[Self::WIRE_SWAP]; constraints.push(swap * (swap - F::ONE)); let old_index_acc = vars.local_wires[Self::WIRE_INDEX_ACCUMULATOR_OLD]; @@ -161,11 +161,15 @@ struct GMiMCGenerator { impl SimpleGenerator for GMiMCGenerator { fn dependencies(&self) -> Vec { - (0..W) - .map(|i| Target::Wire(Wire { - gate: self.gate_index, - input: GMiMCGate::::wire_input(i), - })) + let mut dep_input_indices = Vec::with_capacity(W + 2); + for i in 0..W { + dep_input_indices.push(GMiMCGate::::wire_input(i)); + } + dep_input_indices.push(GMiMCGate::::WIRE_SWAP); + dep_input_indices.push(GMiMCGate::::WIRE_INDEX_ACCUMULATOR_OLD); + + dep_input_indices.into_iter() + .map(|input| Target::Wire(Wire { gate: self.gate_index, input })) .collect() } @@ -268,7 +272,12 @@ mod tests { .collect::>(); let mut witness = PartialWitness::new(); - witness.set_wire(Wire { gate: 0, input: Gate::WIRE_SWAP }, F::ZERO); + witness.set_wire( + Wire { gate: 0, input: Gate::WIRE_INDEX_ACCUMULATOR_OLD }, + F::from_canonical_usize(7)); + witness.set_wire( + Wire { gate: 0, input: Gate::WIRE_SWAP }, + F::ZERO); for i in 0..W { witness.set_wire( Wire { gate: 0, input: Gate::wire_input(i) }, @@ -284,8 +293,12 @@ mod tests { for i in 0..W { let out = witness.get_wire( - Wire { gate: 1, input: Gate::wire_output(i) }); + Wire { gate: 0, input: Gate::wire_output(i) }); assert_eq!(out, expected_outputs[i]); } + + let acc_new = witness.get_wire( + Wire { gate: 0, input: Gate::WIRE_INDEX_ACCUMULATOR_NEW }); + assert_eq!(acc_new, F::from_canonical_usize(7 * 2)); } } diff --git a/src/plonk_challenger.rs b/src/plonk_challenger.rs index 8dbd2813..09276105 100644 --- a/src/plonk_challenger.rs +++ b/src/plonk_challenger.rs @@ -228,7 +228,7 @@ mod tests { let config = CircuitConfig { num_wires: 114, - num_routed_wires: 13, + num_routed_wires: 27, ..CircuitConfig::default() }; let mut builder = CircuitBuilder::::new(config);