Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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