Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Closed
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
33 changes: 31 additions & 2 deletions keccak256/src/circuit/word_builder.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,47 @@
// Added until this is used by another component
#![allow(dead_code)]
use super::BYTES_PER_WORD;
use crate::permutation::tables::RangeCheckConfig;
use eth_types::Field;
use halo2_proofs::{
circuit::{AssignedCell, Layouter},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector, TableColumn},
poly::Rotation,
};
use std::marker::PhantomData;

pub type Byte = u8;
pub type AssignedByte<F> = AssignedCell<F, F>;
pub type AssignedWord<F> = AssignedCell<F, F>;

#[derive(Debug, Clone)]
pub struct RangeCheckConfig<F, const K: u64> {
pub range: TableColumn,
_marker: PhantomData<F>,
}

impl<F: Field, const K: u64> RangeCheckConfig<F, K> {
pub(crate) fn load(&self, layouter: &mut impl Layouter<F>) -> Result<(), Error> {
layouter.assign_table(
|| "range",
|mut table| {
for i in 0..=K {
table.assign_cell(|| "range", self.range, i as usize, || Ok(F::from(i)))?;
}
Ok(())
},
)
}
// dead_code reason: WordBuilderConfig is using it. We defer the decision to
// remove this after WordBuilderConfig is complete
#[allow(dead_code)]
pub(crate) fn configure(meta: &mut ConstraintSystem<F>) -> Self {
Self {
range: meta.lookup_table_column(),
_marker: PhantomData,
}
}
}

#[derive(Debug, Clone)]
/// Gets 8 Advice columns with the 8bytes to form the word + the final word
/// value of the composed bytes at the end.
Expand Down
80 changes: 21 additions & 59 deletions keccak256/src/permutation/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use crate::{
common::{NEXT_INPUTS_LANES, PERMUTATION},
permutation::{
generic::GenericConfig,
tables::{Base13toBase9TableConfig, FromBase9TableConfig, StackableTable},
},
permutation::{generic::GenericConfig, tables::LookupConfig},
};
use eth_types::Field;
use halo2_proofs::{
Expand All @@ -12,28 +9,22 @@ use halo2_proofs::{
};
use itertools::Itertools;

use super::{
components::{
assign_next_input, assign_rho, assign_theta, assign_xi, convert_from_b9_to_b13,
convert_to_b9_mul_a4, pi_gate_permutation, IotaConstants,
},
tables::FromBinaryTableConfig,
use super::components::{
assign_next_input, assign_rho, assign_theta, assign_xi, convert_from_b9_to_b13,
convert_to_b9_mul_a4, pi_gate_permutation, IotaConstants,
};

#[derive(Clone, Debug)]
pub struct KeccakFConfig<F: Field> {
generic: GenericConfig<F>,
stackable: StackableTable<F>,
base13to9_config: Base13toBase9TableConfig<F>,
from_b9_table: FromBase9TableConfig<F>,
from_b2_table: FromBinaryTableConfig<F>,
lookup_config: LookupConfig<F>,
pub advice: Column<Advice>,
}

impl<F: Field> KeccakFConfig<F> {
// We assume state is received in base-9.
pub fn configure(meta: &mut ConstraintSystem<F>) -> Self {
let advices: [Column<Advice>; 3] = (0..3)
let advices: [Column<Advice>; 4] = (0..4)
.map(|_| {
let column = meta.advice_column();
meta.enable_equality(column);
Expand All @@ -44,47 +35,23 @@ impl<F: Field> KeccakFConfig<F> {
.unwrap();

let fixed = meta.fixed_column();
let generic = GenericConfig::configure(meta, advices, fixed);
let stackable_cols: [TableColumn; 3] = (0..3)
let generic = GenericConfig::configure(meta, advices[0..3].try_into().unwrap(), fixed);
let lookup_cols: [TableColumn; 4] = (0..4)
.map(|_| meta.lookup_table_column())
.collect_vec()
.try_into()
.unwrap();
let base13to9_cols: [TableColumn; 3] = (0..3)
.map(|_| meta.lookup_table_column())
.collect_vec()
.try_into()
.unwrap();
let from_base9_cols: [TableColumn; 3] = (0..3)
.map(|_| meta.lookup_table_column())
.collect_vec()
.try_into()
.unwrap();
let from_base2_cols: [TableColumn; 3] = (0..3)
.map(|_| meta.lookup_table_column())
.collect_vec()
.try_into()
.unwrap();
let stackable = StackableTable::configure(meta, advices, stackable_cols);
let base13to9_config = Base13toBase9TableConfig::configure(meta, advices, base13to9_cols);
let from_b9_table = FromBase9TableConfig::configure(meta, advices, from_base9_cols);
let from_b2_table = FromBinaryTableConfig::configure(meta, advices, from_base2_cols);
let lookup_config = LookupConfig::configure(meta, advices, lookup_cols);

Self {
generic,
stackable,
base13to9_config,
from_b9_table,
from_b2_table,
lookup_config,
advice: advices[0],
}
}

pub fn load(&mut self, layouter: &mut impl Layouter<F>) -> Result<(), Error> {
self.stackable.load(layouter)?;
self.base13to9_config.load(layouter)?;
self.from_b9_table.load(layouter)?;
self.from_b2_table.load(layouter)
self.lookup_config.load(layouter)
}

// Result b13 state for next round, b2 state for end result
Expand All @@ -101,13 +68,7 @@ impl<F: Field> KeccakFConfig<F> {
for round_idx in 0..PERMUTATION {
// State in base-13
state = assign_theta(&self.generic, layouter, &state)?;
state = assign_rho(
layouter,
&self.base13to9_config,
&self.generic,
&self.stackable,
&state,
)?;
state = assign_rho(layouter, &self.lookup_config, &self.generic, &state)?;
// Outputs in base-9 which is what Pi requires
state = pi_gate_permutation(&state);
state = assign_xi(&self.generic, layouter, &state)?;
Expand All @@ -127,11 +88,11 @@ impl<F: Field> KeccakFConfig<F> {
// base_13 which is what Theta requires again at the
// start of the loop.
state =
convert_from_b9_to_b13(layouter, &self.from_b9_table, &self.generic, state, false)?
convert_from_b9_to_b13(layouter, &self.lookup_config, &self.generic, state, false)?
.0;
}
let (f_mix, f_no_mix) = self
.stackable
.lookup_config
.assign_boolean_flag(layouter, next_mixing.is_some())?;
state[0] = self.generic.conditional_add_const(
layouter,
Expand All @@ -143,15 +104,15 @@ impl<F: Field> KeccakFConfig<F> {

// Convert to base 9 and multiply by A4
let next_input =
convert_to_b9_mul_a4(layouter, &self.from_b2_table, &self.generic, &next_input)?;
convert_to_b9_mul_a4(layouter, &self.lookup_config, &self.generic, &next_input)?;

for (i, input) in next_input.iter().enumerate() {
state[i] = self
.generic
.conditional_add_advice(layouter, &state[i], &f_mix, input)?;
}
let (mut state_b13, state_b2) =
convert_from_b9_to_b13(layouter, &self.from_b9_table, &self.generic, state, true)?;
convert_from_b9_to_b13(layouter, &self.lookup_config, &self.generic, state, true)?;
let state_b2 = state_b2.unwrap();
state_b13[0] = self.generic.conditional_add_const(
layouter,
Expand Down Expand Up @@ -304,6 +265,7 @@ mod tests {
// Generate next_input as `[Fp;NEXT_INPUTS_LANES]`
let next_input_fp: [Fp; NEXT_INPUTS_LANES] =
state_bigint_to_field(StateBigInt::from(next_input));
let k = 18;

// When we pass no `mixing_inputs`, we perform the full keccak round
// ending with Mixing executing IotaB9
Expand All @@ -316,7 +278,7 @@ mod tests {
next_mixing: None,
};

let prover = MockProver::<Fp>::run(17, &circuit, vec![]).unwrap();
let prover = MockProver::<Fp>::run(k, &circuit, vec![]).unwrap();

assert_eq!(prover.verify(), Ok(()), "is_mixing: false");

Expand All @@ -327,7 +289,7 @@ mod tests {
out_state: out_state_non_mix,
next_mixing: None,
};
let k = 17;

let prover = MockProver::<Fp>::run(k, &circuit, vec![]).unwrap();

#[cfg(feature = "dev-graph")]
Expand All @@ -354,7 +316,7 @@ mod tests {
next_mixing: Some(next_input_fp),
};

let prover = MockProver::<Fp>::run(17, &circuit, vec![]).unwrap();
let prover = MockProver::<Fp>::run(k, &circuit, vec![]).unwrap();

assert_eq!(prover.verify(), Ok(()), "is_mixing: true");

Expand All @@ -366,7 +328,7 @@ mod tests {
next_mixing: Some(next_input_fp),
};

let prover = MockProver::<Fp>::run(17, &circuit, vec![]).unwrap();
let prover = MockProver::<Fp>::run(k, &circuit, vec![]).unwrap();

assert!(prover.verify().is_err());
}
Expand Down
Loading