use std::convert::TryInto; use crate::circuit_data::CircuitConfig; use crate::constraint_polynomial::ConstraintPolynomial; use crate::field::field::Field; use crate::gates::deterministic_gate::DeterministicGate; use crate::gates::gate::{Gate, GateRef}; use crate::generator::{SimpleGenerator, WitnessGenerator2}; use crate::gmimc::gmimc_permute; use crate::target::Target2; use crate::wire::Wire; use crate::witness::PartialWitness; use std::sync::Arc; /// Evaluates a full GMiMC permutation, and writes the output to the next gate's first `width` /// wires (which could be the input of another `GMiMCGate`). #[derive(Debug)] pub struct GMiMCGate { round_constants: Arc<[F; R]>, } impl GMiMCGate { fn new() -> GateRef { todo!() } } impl Gate for GMiMCGate { fn id(&self) -> String { // TODO: Add W/R format!("{:?}", self) } fn constraints(&self, config: CircuitConfig) -> Vec> { unimplemented!() } fn generators(&self, config: CircuitConfig, gate_index: usize, local_constants: Vec, next_constants: Vec) -> Vec>> { let generator = GMiMCGenerator:: { round_constants: self.round_constants.clone(), gate_index, }; vec![Box::new(generator)] } } struct GMiMCGenerator { round_constants: Arc<[F; R]>, gate_index: usize, } impl SimpleGenerator for GMiMCGenerator { fn dependencies(&self) -> Vec { (0..W) .map(|i| Target2::Wire( Wire { gate: self.gate_index, input: i })) .collect() } fn run_once(&mut self, witness: &PartialWitness) -> PartialWitness { let mut inputs: [F; W] = [F::ZERO; W]; for i in 0..W { inputs[i] = witness.get_wire( Wire { gate: self.gate_index, input: i }); } let outputs = gmimc_permute::(inputs, self.round_constants.clone()); let mut result = PartialWitness::new(); for i in 0..W { result.set_wire( Wire { gate: self.gate_index + 1, input: i }, outputs[i]); } result } }