Skip to content

Commit

Permalink
replace iota with generic (scroll-tech#571)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChihChengLiang authored Jun 20, 2022
1 parent 4d54891 commit 998c493
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 201 deletions.
21 changes: 10 additions & 11 deletions keccak256/src/permutation/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand All @@ -16,13 +16,12 @@ use halo2_proofs::{
};
use itertools::Itertools;
use std::convert::TryInto;

#[derive(Clone, Debug)]
pub struct KeccakFConfig<F: Field> {
generic: GenericConfig<F>,
theta_config: ThetaConfig<F>,
rho_config: RhoConfig<F>,
xi_config: XiConfig<F>,
iota_config: IotaConfig<F>,
from_b9_table: FromBase9TableConfig<F>,
base_conversion_config: BaseConversionConfig<F>,
mixing_config: MixingConfig<F>,
Expand All @@ -44,7 +43,6 @@ impl<F: Field> KeccakFConfig<F> {
.try_into()
.unwrap();

let flag = meta.advice_column();
let fixed = [
meta.fixed_column(),
meta.fixed_column(),
Expand All @@ -58,7 +56,6 @@ impl<F: Field> KeccakFConfig<F> {
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();
Expand All @@ -77,8 +74,7 @@ impl<F: Field> KeccakFConfig<F> {

// 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();
Expand All @@ -97,10 +93,10 @@ impl<F: Field> KeccakFConfig<F> {
});

KeccakFConfig {
generic,
theta_config,
rho_config,
xi_config,
iota_config,
from_b9_table,
base_conversion_config,
mixing_config,
Expand Down Expand Up @@ -162,9 +158,12 @@ impl<F: Field> KeccakFConfig<F> {
}

// 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
Expand Down
179 changes: 5 additions & 174 deletions keccak256/src/permutation/iota.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F> {
q_enable: Selector,
lane00: Column<Advice>,
flag: Column<Advice>,
round_constant: Column<Fixed>,
round_constant_b13: F,
a4_times_round_constants_b9: [F; PERMUTATION],
pub struct IotaConstants<F> {
pub round_constant_b13: F,
pub a4_times_round_constants_b9: [F; PERMUTATION],
}

impl<F: Field> IotaConfig<F> {
/// 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<F>,
lane00: Column<Advice>,
flag: Column<Advice>,
round_constant: Column<Fixed>,
) -> 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<F: Field> Default for IotaConstants<F> {
fn default() -> Self {
let round_constant_b13 =
biguint_to_f::<F>(&convert_b2_to_b13(ROUND_CONSTANTS[PERMUTATION - 1]));

Expand All @@ -72,132 +27,8 @@ impl<F: Field> IotaConfig<F> {
.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<F>,
lane00: AssignedCell<F, F>,
round: usize,
) -> Result<AssignedCell<F, F>, 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<F>,
lane00: AssignedCell<F, F>,
flag: AssignedCell<F, F>,
) -> Result<AssignedCell<F, F>, 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<F>,
lane00: AssignedCell<F, F>,
flag: AssignedCell<F, F>,
) -> Result<AssignedCell<F, F>, 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)
},
)
},
)
}
}
44 changes: 28 additions & 16 deletions keccak256/src/permutation/mixing.rs
Original file line number Diff line number Diff line change
@@ -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<F> {
iota_config: IotaConfig<F>,
iota_constants: IotaConstants<F>,
absorb_config: AbsorbConfig<F>,
base_conv_config: BaseConversionConfig<F>,
state: [Column<Advice>; 25],
flag: Column<Advice>,
q_flag: Selector,
q_out_copy: Selector,
generic: GenericConfig<F>,
}

impl<F: Field> MixingConfig<F> {
pub fn configure(
meta: &mut ConstraintSystem<F>,
table: &FromBase9TableConfig<F>,
iota_config: IotaConfig<F>,
state: [Column<Advice>; 25],
generic: GenericConfig<F>,
) -> MixingConfig<F> {
// Allocate space for the flag column from which we will copy to all of
// the sub-configs.
Expand Down Expand Up @@ -99,15 +99,17 @@ impl<F: Field> MixingConfig<F> {
// 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,
}
}

Expand Down Expand Up @@ -207,10 +209,14 @@ impl<F: Field> MixingConfig<F> {
// 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
};
Expand Down Expand Up @@ -238,9 +244,15 @@ impl<F: Field> MixingConfig<F> {
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
};

Expand Down Expand Up @@ -279,7 +291,6 @@ impl<F: Field> MixingConfig<F> {
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};
Expand Down Expand Up @@ -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,
}
}
Expand Down

0 comments on commit 998c493

Please sign in to comment.