From 1144738f85199f906433c2fae5fe3755a22ba4f3 Mon Sep 17 00:00:00 2001 From: ChihChengLiang Date: Wed, 15 Jun 2022 00:46:10 +0200 Subject: [PATCH] replace iota with generic --- keccak256/src/permutation/circuit.rs | 21 ++-- keccak256/src/permutation/iota.rs | 179 +-------------------------- keccak256/src/permutation/mixing.rs | 44 ++++--- 3 files changed, 43 insertions(+), 201 deletions(-) diff --git a/keccak256/src/permutation/circuit.rs b/keccak256/src/permutation/circuit.rs index fdd52dca2d..8e9425d492 100644 --- a/keccak256/src/permutation/circuit.rs +++ b/keccak256/src/permutation/circuit.rs @@ -3,7 +3,7 @@ use crate::{ common::{NEXT_INPUTS_LANES, PERMUTATION, ROUND_CONSTANTS}, keccak_arith::*, permutation::{ - base_conversion::BaseConversionConfig, generic::GenericConfig, iota::IotaConfig, + base_conversion::BaseConversionConfig, generic::GenericConfig, iota::IotaConstants, mixing::MixingConfig, pi::pi_gate_permutation, rho::RhoConfig, tables::FromBase9TableConfig, theta::ThetaConfig, xi::XiConfig, }, @@ -16,13 +16,12 @@ use halo2_proofs::{ }; use itertools::Itertools; use std::convert::TryInto; - #[derive(Clone, Debug)] pub struct KeccakFConfig { + generic: GenericConfig, theta_config: ThetaConfig, rho_config: RhoConfig, xi_config: XiConfig, - iota_config: IotaConfig, from_b9_table: FromBase9TableConfig, base_conversion_config: BaseConversionConfig, mixing_config: MixingConfig, @@ -44,7 +43,6 @@ impl KeccakFConfig { .try_into() .unwrap(); - let flag = meta.advice_column(); let fixed = [ meta.fixed_column(), meta.fixed_column(), @@ -58,7 +56,6 @@ impl KeccakFConfig { let rho_config = RhoConfig::configure(meta, state, fixed, &generic); // xi let xi_config = XiConfig::configure(meta.selector(), meta, state); - let iota_config = IotaConfig::configure(meta, state[0], flag, fixed[0]); // Allocate space for the activation flag of the base_conversion. let base_conv_activator = meta.advice_column(); @@ -77,8 +74,7 @@ impl KeccakFConfig { // Mixing will make sure that the flag is binary constrained and that // the out state matches the expected result. - let mixing_config = - MixingConfig::configure(meta, &from_b9_table, iota_config.clone(), state); + let mixing_config = MixingConfig::configure(meta, &from_b9_table, state, generic.clone()); // Allocate the `out state correctness` gate selector let q_out = meta.selector(); @@ -97,10 +93,10 @@ impl KeccakFConfig { }); KeccakFConfig { + generic, theta_config, rho_config, xi_config, - iota_config, from_b9_table, base_conversion_config, mixing_config, @@ -162,9 +158,12 @@ impl KeccakFConfig { } // iota_b9 - state[0] = self - .iota_config - .assign_round_b9(layouter, state[0].clone(), round_idx)?; + let iota_constants = IotaConstants::default(); + state[0] = self.generic.add_fixed( + layouter, + state[0].clone(), + iota_constants.a4_times_round_constants_b9[round_idx], + )?; // The resulting state is in Base-9 now. We now convert it to // base_13 which is what Theta requires again at the diff --git a/keccak256/src/permutation/iota.rs b/keccak256/src/permutation/iota.rs index 76e7aa2122..7aa2b2f116 100644 --- a/keccak256/src/permutation/iota.rs +++ b/keccak256/src/permutation/iota.rs @@ -2,62 +2,17 @@ use crate::arith_helpers::{convert_b2_to_b13, convert_b2_to_b9, A4}; use crate::common::{PERMUTATION, ROUND_CONSTANTS}; use crate::gate_helpers::biguint_to_f; use eth_types::Field; -use halo2_proofs::circuit::AssignedCell; -use halo2_proofs::circuit::Layouter; -use halo2_proofs::{ - plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Selector}, - poly::Rotation, -}; use itertools::Itertools; use std::convert::TryInto; #[derive(Clone, Debug)] -pub struct IotaConfig { - q_enable: Selector, - lane00: Column, - flag: Column, - round_constant: Column, - round_constant_b13: F, - a4_times_round_constants_b9: [F; PERMUTATION], +pub struct IotaConstants { + pub round_constant_b13: F, + pub a4_times_round_constants_b9: [F; PERMUTATION], } -impl IotaConfig { - /// Iota step adds a round constant to the first lane. - /// - /// We enable the gate to handle 3 different cases: - /// - /// The first case takes place in the first 23 rounds, the prover MUST add - /// the `A4` times round constant in base 9. We enforce it by requiring the - /// flag equal to one. - /// - /// The second the third cases happen in the 24-th - /// round. It depends if prover wants to absorb new input or not, which is - /// indicated by the flag. - /// - /// If prover doesn't want to absorb new input, - /// then add `A4 * round_constant_b9` as the previous 23-th round did. - /// - /// Otherwise, apply the round constant in base 13 to the state, which has - /// been mixed with new input and converted form base 9 to base 13. - pub fn configure( - meta: &mut ConstraintSystem, - lane00: Column, - flag: Column, - round_constant: Column, - ) -> Self { - let q_enable = meta.selector(); - meta.enable_equality(lane00); - meta.enable_equality(flag); - - meta.create_gate("iota", |meta| { - let q_enable = meta.query_selector(q_enable); - let flag = meta.query_advice(flag, Rotation::cur()); - let lane00_next = meta.query_advice(lane00, Rotation::next()); - let lane00 = meta.query_advice(lane00, Rotation::cur()); - let round_constant = meta.query_fixed(round_constant, Rotation::cur()); - vec![q_enable * (lane00_next - lane00 - flag * round_constant)] - }); - +impl Default for IotaConstants { + fn default() -> Self { let round_constant_b13 = biguint_to_f::(&convert_b2_to_b13(ROUND_CONSTANTS[PERMUTATION - 1])); @@ -72,132 +27,8 @@ impl IotaConfig { .unwrap(); Self { - q_enable, - lane00, - flag, - round_constant, round_constant_b13, a4_times_round_constants_b9, } } - - /// The first 23 rounds. (No mixing logic involved). - /// - /// Applies IotaB9 steady-step logic. - /// It consists of: `new_lane_00 - (lane00 * ROUND_CTANTS[round]) == 0`. - pub fn assign_round_b9( - &self, - layouter: &mut impl Layouter, - lane00: AssignedCell, - round: usize, - ) -> Result, Error> { - layouter.assign_region( - || "IotaB9", - |mut region| { - let offset = 0; - self.q_enable.enable(&mut region, offset)?; - lane00.copy_advice(|| "lane 00", &mut region, self.lane00, offset)?; - // In the normal round, we must add round constant. constrain flag to 1. - let flag = region.assign_advice(|| "flag", self.flag, offset, || Ok(F::one()))?; - region.constrain_constant(flag.cell(), F::one())?; - - let constant = self.a4_times_round_constants_b9[round]; - region.assign_fixed( - || "A4 * round_constant_b9", - self.round_constant, - offset, - || Ok(constant), - )?; - - let offset = 1; - region.assign_advice( - || "lane 00 + A4 * round_constant_b9", - self.lane00, - offset, - || Ok(lane00.value().cloned().unwrap_or_default() + constant), - ) - }, - ) - } - - /// The 24-th round. Copy the flag `no_mixing` here. - /// - /// If `no_mixing` is true: add `A4 * round_constant_b9` - /// Otherwise, do nothing and return the orignal lane value in the next cell - pub fn assign_b9_last_round( - &self, - layouter: &mut impl Layouter, - lane00: AssignedCell, - flag: AssignedCell, - ) -> Result, Error> { - layouter.assign_region( - || "IotaB9", - |mut region| { - let offset = 0; - self.q_enable.enable(&mut region, offset)?; - lane00.copy_advice(|| "lane 00", &mut region, self.lane00, offset)?; - flag.copy_advice(|| "flag", &mut region, self.flag, offset)?; - - let constant = self.a4_times_round_constants_b9[PERMUTATION - 1]; - region.assign_fixed( - || "A4 * round_constant_b9", - self.round_constant, - offset, - || Ok(constant), - )?; - - let offset = 1; - region.assign_advice( - || "lane 00 + A4 * round_constant_b9", - self.lane00, - offset, - || { - let flag = flag.value().cloned().unwrap_or_default(); - let lane00 = lane00.value().cloned().unwrap_or_default(); - Ok(lane00 + flag * constant) - }, - ) - }, - ) - } - - /// The 24-th round. Copy the flag `mixing` here. - /// - /// If `mixing` is true: add round constant in base 13. - /// Otherwise, do nothing and return the orignal lane value in the next cell - pub fn assign_round_b13( - &self, - layouter: &mut impl Layouter, - lane00: AssignedCell, - flag: AssignedCell, - ) -> Result, Error> { - layouter.assign_region( - || "IotaB9", - |mut region| { - let offset = 0; - self.q_enable.enable(&mut region, offset)?; - lane00.copy_advice(|| "lane 00", &mut region, self.lane00, offset)?; - flag.copy_advice(|| "flag", &mut region, self.flag, offset)?; - - region.assign_fixed( - || "round_constant_b13", - self.round_constant, - offset, - || Ok(self.round_constant_b13), - )?; - - let offset = 1; - region.assign_advice( - || "lane 00 + round_constant_b13", - self.lane00, - offset, - || { - let lane00 = lane00.value().cloned().unwrap_or_default(); - let flag = flag.value().cloned().unwrap_or_default(); - Ok(lane00 + flag * self.round_constant_b13) - }, - ) - }, - ) - } } diff --git a/keccak256/src/permutation/mixing.rs b/keccak256/src/permutation/mixing.rs index 4c2972ebc1..0a6290ae54 100644 --- a/keccak256/src/permutation/mixing.rs +++ b/keccak256/src/permutation/mixing.rs @@ -1,35 +1,35 @@ use super::super::arith_helpers::*; +use super::generic::GenericConfig; use super::tables::FromBase9TableConfig; -use super::{absorb::AbsorbConfig, base_conversion::BaseConversionConfig, iota::IotaConfig}; +use super::{absorb::AbsorbConfig, base_conversion::BaseConversionConfig, iota::IotaConstants}; use crate::common::*; use crate::keccak_arith::KeccakFArith; use eth_types::Field; -use halo2_proofs::circuit::{AssignedCell, Region}; -use halo2_proofs::plonk::{Expression, Selector}; -use halo2_proofs::poly::Rotation; use halo2_proofs::{ - circuit::Layouter, - plonk::{Advice, Column, ConstraintSystem, Error}, + circuit::{AssignedCell, Layouter, Region}, + plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, + poly::Rotation, }; use std::convert::TryInto; #[derive(Clone, Debug)] pub struct MixingConfig { - iota_config: IotaConfig, + iota_constants: IotaConstants, absorb_config: AbsorbConfig, base_conv_config: BaseConversionConfig, state: [Column; 25], flag: Column, q_flag: Selector, q_out_copy: Selector, + generic: GenericConfig, } impl MixingConfig { pub fn configure( meta: &mut ConstraintSystem, table: &FromBase9TableConfig, - iota_config: IotaConfig, state: [Column; 25], + generic: GenericConfig, ) -> MixingConfig { // Allocate space for the flag column from which we will copy to all of // the sub-configs. @@ -99,15 +99,17 @@ impl MixingConfig { // the equality with the out_state of the permutation. [q_enable * ((left_side + right_side) - out_state)] }); + let iota_constants = IotaConstants::default(); MixingConfig { - iota_config, + iota_constants, absorb_config, base_conv_config, state, flag, q_flag, q_out_copy, + generic, } } @@ -207,10 +209,14 @@ impl MixingConfig { // IotaB9 let non_mix_res = { let mut state = in_state.clone(); - state[0] = self.iota_config.assign_b9_last_round( + // If `no_mixing` is true: add `A4 * round_constant_b9` + // Otherwise, do nothing and return the orignal lane value in the + // next cell + state[0] = self.generic.conditional_add_const( layouter, state[0].clone(), negated_flag.clone(), + self.iota_constants.a4_times_round_constants_b9[PERMUTATION - 1], )?; state }; @@ -238,9 +244,15 @@ impl MixingConfig { let mix_res = { let mut base_conv_cells = base_conv_cells; - base_conv_cells[0] = - self.iota_config - .assign_round_b13(layouter, base_conv_cells[0].clone(), flag)?; + // If `mixing` is true: add round constant in base 13. + // Otherwise, do nothing and return the orignal lane value in the + // next cell + base_conv_cells[0] = self.generic.conditional_add_const( + layouter, + base_conv_cells[0].clone(), + flag, + self.iota_constants.round_constant_b13, + )?; base_conv_cells }; @@ -279,7 +291,6 @@ impl MixingConfig { mod tests { use super::*; use crate::common::{State, ROUND_CONSTANTS}; - use crate::permutation::iota::IotaConfig; use halo2_proofs::circuit::Layouter; use halo2_proofs::pairing::bn256::Fr as Fp; use halo2_proofs::plonk::{ConstraintSystem, Error}; @@ -326,10 +337,11 @@ mod tests { .try_into() .unwrap(); let fixed = meta.fixed_column(); - let iota_config = IotaConfig::configure(meta, state[0], state[1], fixed); + let generic = + GenericConfig::configure(meta, state[0..3].try_into().unwrap(), fixed); MyConfig { - mixing_conf: MixingConfig::configure(meta, &table, iota_config, state), + mixing_conf: MixingConfig::configure(meta, &table, state, generic), table, } }