Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

[word lo/hi] support u16 range lookup #1427

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
11 changes: 8 additions & 3 deletions zkevm-circuits/src/bin/stats/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use itertools::Itertools;
use mock::MOCK_ACCOUNTS;
use std::env;
use zkevm_circuits::evm_circuit::{
param::{LOOKUP_CONFIG, N_BYTE_LOOKUPS, N_COPY_COLUMNS, N_PHASE1_COLUMNS, N_PHASE2_COLUMNS},
param::{
LOOKUP_CONFIG, N_COPY_COLUMNS, N_PHASE1_COLUMNS, N_PHASE2_COLUMNS, N_U16_LOOKUPS,
N_U8_LOOKUPS,
},
step::ExecutionState,
EvmCircuit,
};
Expand Down Expand Up @@ -163,8 +166,10 @@ fn get_exec_steps_occupancy() {
N_PHASE2_COLUMNS,
storage_perm,
N_COPY_COLUMNS,
byte_lookup,
N_BYTE_LOOKUPS,
u8_lookup,
N_U8_LOOKUPS,
u16_lookup,
N_U16_LOOKUPS,
fixed_table,
LOOKUP_CONFIG[0].1,
tx_table,
Expand Down
49 changes: 24 additions & 25 deletions zkevm-circuits/src/evm_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
evm_circuit::param::{MAX_STEP_HEIGHT, STEP_STATE_HEIGHT},
table::{
BlockTable, BytecodeTable, CopyTable, ExpTable, KeccakTable, LookupTable, RwTable, TxTable,
UXTable,
},
util::{Challenges, SubCircuit, SubCircuitConfig},
};
Expand All @@ -38,7 +39,8 @@ use witness::Block;
#[derive(Clone, Debug)]
pub struct EvmCircuitConfig<F> {
fixed_table: [Column<Fixed>; 4],
byte_table: [Column<Fixed>; 1],
u8_table: UXTable<8>,
u16_table: UXTable<16>,
pub execution: Box<ExecutionConfig<F>>,
// External tables
tx_table: TxTable,
Expand Down Expand Up @@ -68,6 +70,10 @@ pub struct EvmCircuitConfigArgs<F: Field> {
pub keccak_table: KeccakTable,
/// ExpTable
pub exp_table: ExpTable,
/// U8Table
pub u8_table: UXTable<8>,
/// U16Table
pub u16_table: UXTable<16>,
}

impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
Expand All @@ -85,15 +91,17 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
copy_table,
keccak_table,
exp_table,
u8_table,
u16_table,
}: Self::ConfigArgs,
) -> Self {
let fixed_table = [(); 4].map(|_| meta.fixed_column());
let byte_table = [(); 1].map(|_| meta.fixed_column());
let execution = Box::new(ExecutionConfig::configure(
meta,
challenges,
&fixed_table,
&byte_table,
&u8_table,
&u16_table,
&tx_table,
&rw_table,
&bytecode_table,
Expand All @@ -103,7 +111,8 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
&exp_table,
));

meta.annotate_lookup_any_column(byte_table[0], || "byte_range");
u8_table.annotate_columns(meta);
u16_table.annotate_columns(meta);
fixed_table.iter().enumerate().for_each(|(idx, &col)| {
meta.annotate_lookup_any_column(col, || format!("fix_table_{}", idx))
});
Expand All @@ -114,10 +123,13 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
copy_table.annotate_columns(meta);
keccak_table.annotate_columns(meta);
exp_table.annotate_columns(meta);
u8_table.annotate_columns(meta);
u16_table.annotate_columns(meta);

Self {
fixed_table,
byte_table,
u8_table,
u16_table,
execution,
tx_table,
rw_table,
Expand Down Expand Up @@ -153,25 +165,6 @@ impl<F: Field> EvmCircuitConfig<F> {
},
)
}

/// Load byte table
pub fn load_byte_table(&self, layouter: &mut impl Layouter<F>) -> Result<(), Error> {
layouter.assign_region(
|| "byte table",
|mut region| {
for offset in 0..256 {
region.assign_fixed(
|| "",
self.byte_table[0],
offset,
|| Value::known(F::from(offset as u64)),
)?;
}

Ok(())
},
)
}
}

/// Tx Circuit for verifying transaction signatures
Expand Down Expand Up @@ -270,7 +263,6 @@ impl<F: Field> SubCircuit<F> for EvmCircuit<F> {
let block = self.block.as_ref().unwrap();

config.load_fixed_table(layouter, self.fixed_table_tags.clone())?;
config.load_byte_table(layouter)?;
config.execution.assign_block(layouter, block, challenges)
}
}
Expand Down Expand Up @@ -375,6 +367,8 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
let copy_table = CopyTable::construct(meta, q_copy_table);
let keccak_table = KeccakTable::construct(meta);
let exp_table = ExpTable::construct(meta);
let u8_table = UXTable::construct(meta);
let u16_table = UXTable::construct(meta);
let challenges = Challenges::construct(meta);
let challenges_expr = challenges.exprs(meta);

Expand All @@ -390,6 +384,8 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
copy_table,
keccak_table,
exp_table,
u8_table,
u16_table,
},
),
challenges,
Expand Down Expand Up @@ -428,6 +424,9 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
.dev_load(&mut layouter, &block.sha3_inputs, &challenges)?;
config.exp_table.load(&mut layouter, block)?;

config.u8_table.load(&mut layouter)?;
config.u16_table.load(&mut layouter)?;

self.synthesize_sub(&config, &challenges, &mut layouter)
}
}
Expand Down
41 changes: 30 additions & 11 deletions zkevm-circuits/src/evm_circuit/execution.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::{
param::{
BLOCK_TABLE_LOOKUPS, BYTECODE_TABLE_LOOKUPS, COPY_TABLE_LOOKUPS, EXP_TABLE_LOOKUPS,
FIXED_TABLE_LOOKUPS, KECCAK_TABLE_LOOKUPS, N_BYTE_LOOKUPS, N_COPY_COLUMNS,
N_PHASE1_COLUMNS, RW_TABLE_LOOKUPS, TX_TABLE_LOOKUPS,
FIXED_TABLE_LOOKUPS, KECCAK_TABLE_LOOKUPS, N_COPY_COLUMNS, N_PHASE1_COLUMNS, N_U16_LOOKUPS,
N_U8_LOOKUPS, RW_TABLE_LOOKUPS, TX_TABLE_LOOKUPS,
},
step::HasExecutionState,
util::{instrumentation::Instrument, CachedRegion, CellManager, StoredExpression},
Expand Down Expand Up @@ -319,7 +319,8 @@ impl<F: Field> ExecutionConfig<F> {
meta: &mut ConstraintSystem<F>,
challenges: Challenges<Expression<F>>,
fixed_table: &dyn LookupTable<F>,
byte_table: &dyn LookupTable<F>,
u8_table: &dyn LookupTable<F>,
u16_table: &dyn LookupTable<F>,
tx_table: &dyn LookupTable<F>,
rw_table: &dyn LookupTable<F>,
bytecode_table: &dyn LookupTable<F>,
Expand Down Expand Up @@ -579,7 +580,8 @@ impl<F: Field> ExecutionConfig<F> {
Self::configure_lookup(
meta,
fixed_table,
byte_table,
u8_table,
u16_table,
tx_table,
rw_table,
bytecode_table,
Expand Down Expand Up @@ -795,7 +797,8 @@ impl<F: Field> ExecutionConfig<F> {
fn configure_lookup(
meta: &mut ConstraintSystem<F>,
fixed_table: &dyn LookupTable<F>,
byte_table: &dyn LookupTable<F>,
u8_table: &dyn LookupTable<F>,
u16_table: &dyn LookupTable<F>,
tx_table: &dyn LookupTable<F>,
rw_table: &dyn LookupTable<F>,
bytecode_table: &dyn LookupTable<F>,
Expand Down Expand Up @@ -829,11 +832,26 @@ impl<F: Field> ExecutionConfig<F> {
}
}
for column in cell_manager.columns().iter() {
if let CellType::LookupByte = column.cell_type {
meta.lookup_any("Byte lookup", |meta| {
let byte_table_expression = byte_table.table_exprs(meta)[0].clone();
vec![(column.expr(), byte_table_expression)]
});
match column.cell_type {
CellType::LookupU8 => {
meta.lookup_any("u8 lookup", |meta| {
vec![column.expr()]
.into_iter()
.zip(u8_table.table_exprs(meta).into_iter())
.map(|(expr, table)| (expr, table))
.collect()
});
}
CellType::LookupU16 => {
meta.lookup_any("u16 lookup", |meta| {
vec![column.expr()]
.into_iter()
.zip(u16_table.table_exprs(meta).into_iter())
.map(|(expr, table)| (expr, table))
.collect()
});
}
_ => (),
}
}
}
Expand Down Expand Up @@ -1034,7 +1052,8 @@ impl<F: Field> ExecutionConfig<F> {
("EVM_lookup_exp", EXP_TABLE_LOOKUPS),
("EVM_adv_phase2", N_PHASE2_COLUMNS),
("EVM_copy", N_COPY_COLUMNS),
("EVM_lookup_byte", N_BYTE_LOOKUPS),
("EVM_lookup_u8", N_U8_LOOKUPS),
("EVM_lookup_u16", N_U16_LOOKUPS),
("EVM_adv_phase1", N_PHASE1_COLUMNS),
];
let mut group_index = 0;
Expand Down
7 changes: 5 additions & 2 deletions zkevm-circuits/src/evm_circuit/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ pub const N_PHASE2_COLUMNS: usize = 4;

/// Number of Advice Phase1 columns in the EVM circuit
pub const N_PHASE1_COLUMNS: usize =
STEP_WIDTH - EVM_LOOKUP_COLS - N_PHASE2_COLUMNS - N_COPY_COLUMNS - N_BYTE_LOOKUPS;
STEP_WIDTH - EVM_LOOKUP_COLS - N_PHASE2_COLUMNS - N_COPY_COLUMNS - N_U8_LOOKUPS - N_U16_LOOKUPS;

// Number of copy columns
pub const N_COPY_COLUMNS: usize = 2;

pub const N_BYTE_LOOKUPS: usize = 24;
pub const N_U8_LOOKUPS: usize = 24;

// TODO shift #column/2 from u8 to u16
pub const N_U16_LOOKUPS: usize = 0;

/// Amount of lookup columns in the EVM circuit dedicated to lookups.
pub(crate) const EVM_LOOKUP_COLS: usize = FIXED_TABLE_LOOKUPS
Expand Down
21 changes: 16 additions & 5 deletions zkevm-circuits/src/evm_circuit/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use crate::util::{
use crate::{
evm_circuit::{
param::{
LOOKUP_CONFIG, N_BYTES_MEMORY_ADDRESS, N_BYTE_LOOKUPS, N_COPY_COLUMNS, N_PHASE2_COLUMNS,
LOOKUP_CONFIG, N_BYTES_MEMORY_ADDRESS, N_COPY_COLUMNS, N_PHASE2_COLUMNS, N_U8_LOOKUPS,
},
table::Table,
},
Expand Down Expand Up @@ -34,7 +34,7 @@ pub(crate) mod memory_gadget;

pub use gadgets::util::{and, not, or, select, sum};

use super::param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_U64};
use super::param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_U64, N_U16_LOOKUPS};

#[derive(Clone, Debug)]
pub struct Cell<F> {
Expand Down Expand Up @@ -294,7 +294,9 @@ pub(crate) enum CellType {
StoragePhase1,
StoragePhase2,
StoragePermutation,
LookupByte,
// TODO combine LookupU8, LookupU16 with Lookup(Table::U8 | Table::U16)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, why not, maybe creating a good-first-issue ?

Copy link
Member Author

@hero78119 hero78119 Jun 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

y let create good-first-issue once this feature sync back to main branch :)

LookupU8,
LookupU16,
Lookup(Table),
}

Expand Down Expand Up @@ -397,8 +399,17 @@ impl<F: Field> CellManager<F> {
}

// Mark columns used for byte lookup
for _ in 0..N_BYTE_LOOKUPS {
columns[column_idx].cell_type = CellType::LookupByte;
#[allow(clippy::reversed_empty_ranges)]
for _ in 0..N_U8_LOOKUPS {
columns[column_idx].cell_type = CellType::LookupU8;
assert_eq!(advices[column_idx].column_type().phase(), 0);
column_idx += 1;
}

// Mark columns used for byte lookup
#[allow(clippy::reversed_empty_ranges)]
for _ in 0..N_U16_LOOKUPS {
columns[column_idx].cell_type = CellType::LookupU16;
assert_eq!(advices[column_idx].column_type().phase(), 0);
column_idx += 1;
}
Expand Down
25 changes: 14 additions & 11 deletions zkevm-circuits/src/evm_circuit/util/constraint_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
}

pub(crate) fn query_byte(&mut self) -> Cell<F> {
self.query_cell_with_type(CellType::LookupByte)
self.query_cell_with_type(CellType::LookupU8)
}

// default query_word is 2 limbs. Each limb is not guaranteed to be 128 bits.
Expand Down Expand Up @@ -448,7 +448,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
}

/// query_word4_unchecked get word with 4 limbs. Each limb is not guaranteed to be 64 bits.
pub fn query_word4_unchecked<const N: usize, const N2: usize>(&mut self) -> Word4<Cell<F>> {
pub fn query_word4_unchecked<const N: usize>(&mut self) -> Word4<Cell<F>> {
Word4::new(
self.query_cells(CellType::StoragePhase1, N)
.try_into()
Expand All @@ -457,13 +457,8 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
}

// each limb is 16 bits, and any conversion to smaller limbs inherits the type check.
// TODO implement 16bits range check
pub(crate) fn query_word16<const N: usize>(&mut self) -> Word16<Cell<F>> {
Word16::new(
self.query_cells(CellType::StoragePhase1, N)
.try_into()
.unwrap(),
)
Word16::new(self.query_u16())
}

// query_word32 each limb is 8 bits, and any conversion to smaller limbs inherits the type
Expand All @@ -489,11 +484,19 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> {
}

pub(crate) fn query_bytes<const N: usize>(&mut self) -> [Cell<F>; N] {
self.query_bytes_dyn(N).try_into().unwrap()
self.query_u8_dyn(N).try_into().unwrap()
}

pub(crate) fn query_u8_dyn(&mut self, count: usize) -> Vec<Cell<F>> {
self.query_cells(CellType::LookupU8, count)
}

pub(crate) fn query_u16<const N: usize>(&mut self) -> [Cell<F>; N] {
self.query_u16_dyn(N).try_into().unwrap()
}

pub(crate) fn query_bytes_dyn(&mut self, count: usize) -> Vec<Cell<F>> {
self.query_cells(CellType::LookupByte, count)
pub(crate) fn query_u16_dyn(&mut self, count: usize) -> Vec<Cell<F>> {
self.query_cells(CellType::LookupU16, count)
}

pub(crate) fn query_cell(&mut self) -> Cell<F> {
Expand Down
9 changes: 7 additions & 2 deletions zkevm-circuits/src/evm_circuit/util/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ impl Instrument {
CellType::StoragePermutation => {
report.storage_perm = data_entry;
}
CellType::LookupByte => {
report.byte_lookup = data_entry;
CellType::LookupU8 => {
report.u8_lookup = data_entry;
}
CellType::LookupU16 => {
report.u16_lookup = data_entry;
}
CellType::Lookup(Table::Fixed) => {
report.fixed_table = data_entry;
Expand Down Expand Up @@ -116,6 +119,8 @@ pub struct ExecStateReport {
pub storage_1: StateReportRow,
pub storage_2: StateReportRow,
pub storage_perm: StateReportRow,
pub u8_lookup: StateReportRow,
pub u16_lookup: StateReportRow,
pub byte_lookup: StateReportRow,
pub fixed_table: StateReportRow,
pub tx_table: StateReportRow,
Expand Down
Loading
Loading