From 17d46aca93bccde7893a6fdc86fd34960540a21d Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Mon, 30 Oct 2023 17:36:47 +0800 Subject: [PATCH] unify etable assignment --- crates/zkwasm/src/circuits/cell.rs | 54 ++--------- .../zkwasm/src/circuits/etable/allocator.rs | 43 +++++++-- crates/zkwasm/src/circuits/etable/assign.rs | 89 ++++++++++++------- crates/zkwasm/src/circuits/etable/mod.rs | 30 ++++--- .../circuits/etable/op_configure/op_call.rs | 2 +- .../etable/op_configure/op_call_indirect.rs | 2 +- .../zkwasm/src/circuits/test_circuit/mod.rs | 9 +- crates/zkwasm/src/continuation/slice.rs | 59 ++++++------ 8 files changed, 164 insertions(+), 124 deletions(-) diff --git a/crates/zkwasm/src/circuits/cell.rs b/crates/zkwasm/src/circuits/cell.rs index ecff8d0b6..f4ca00928 100644 --- a/crates/zkwasm/src/circuits/cell.rs +++ b/crates/zkwasm/src/circuits/cell.rs @@ -14,6 +14,11 @@ use crate::circuits::utils::bn_to_field; use crate::circuits::utils::Context; use crate::nextn; +#[cfg(feature = "continuation")] +pub(crate) type AllocatedStateCell = AllocatedU32Cell; +#[cfg(not(feature = "continuation"))] +pub(crate) type AllocatedStateCell = AllocatedCommonRangeCell; + #[derive(Debug, Clone, Copy)] pub(crate) struct AllocatedCell { pub(crate) col: Column, @@ -48,11 +53,6 @@ pub(crate) trait CellExpression { ) -> Result, Error> { self.assign(ctx, if value { F::one() } else { F::zero() }) } - fn assign_constant( - &self, - ctx: &mut Context<'_, F>, - value: F, - ) -> Result, Error>; } impl CellExpression for AllocatedCell { @@ -68,19 +68,6 @@ impl CellExpression for AllocatedCell { || Ok(value), ) } - - fn assign_constant( - &self, - ctx: &mut Context<'_, F>, - value: F, - ) -> Result, Error> { - ctx.region.assign_advice_from_constant( - || "assign cell", - self.col, - (ctx.offset as i32 + self.rot) as usize, - value, - ) - } } #[derive(Debug, Clone, Copy)] @@ -105,6 +92,10 @@ impl AllocatedU32Cell { pub(crate) fn expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { self.u32_cell.expr(meta) } + + pub(crate) fn curr_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { + self.u32_cell.expr(meta) + } } #[derive(Debug, Clone, Copy)] @@ -149,21 +140,6 @@ macro_rules! define_cell { self.0.assign(ctx, value) } - - fn assign_constant( - &self, - ctx: &mut Context<'_, F>, - value: F, - ) -> Result, Error> { - assert!( - value <= $limit, - "assigned value {:?} exceeds the limit {:?}", - value, - $limit - ); - - self.0.assign_constant(ctx, value) - } } }; } @@ -188,18 +164,6 @@ impl AllocatedU32Cell { } self.u32_cell.assign(ctx, (value as u64).into()) } - - pub(crate) fn assign_constant( - &self, - ctx: &mut Context<'_, F>, - value: u32, - ) -> Result, Error> { - for i in 0..2 { - self.u16_cells_le[i].assign(ctx, (((value >> (i * 16)) & 0xffffu32) as u64).into())?; - } - - self.u32_cell.assign_constant(ctx, (value as u64).into()) - } } impl AllocatedU64Cell { diff --git a/crates/zkwasm/src/circuits/etable/allocator.rs b/crates/zkwasm/src/circuits/etable/allocator.rs index da053e0ce..017a137cf 100644 --- a/crates/zkwasm/src/circuits/etable/allocator.rs +++ b/crates/zkwasm/src/circuits/etable/allocator.rs @@ -43,6 +43,24 @@ impl EventTableCellExpression for AllocatedCell { } } +impl EventTableCellExpression for AllocatedU32Cell { + fn next_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { + nextn!( + meta, + self.u32_cell.0.col, + self.u32_cell.0.rot + EVENT_TABLE_ENTRY_ROWS as i32 + ) + } + + fn prev_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression { + nextn!( + meta, + self.u32_cell.0.col, + self.u32_cell.0.rot - EVENT_TABLE_ENTRY_ROWS as i32 + ) + } +} + macro_rules! impl_cell { ($x: ident) => { impl EventTableCellExpression for $x { @@ -157,11 +175,11 @@ pub(crate) enum EventTableCellType { const BIT_COLUMNS: usize = 12; const U8_COLUMNS: usize = 1; // Should be the multiple of 2. -const U32_CELLS: usize = 2; +const U32_CELLS: usize = if cfg!(feature = "continuation") { 2 } else { 0 }; const U64_CELLS: usize = 5; const U16_COLUMNS: usize = U64_CELLS + (U32_CELLS / 2); const COMMON_RANGE_COLUMNS: usize = 7; -const UNLIMITED_COLUMNS: usize = 8; +const UNLIMITED_COLUMNS: usize = if cfg!(feature = "continuation") { 8 } else { 7 }; const MEMORY_TABLE_LOOKUP_COLUMNS: usize = 2; const JUMP_TABLE_LOOKUP_COLUMNS: usize = 1; @@ -231,6 +249,7 @@ impl EventTableCellAllocator { * enable(meta), ] }); + meta.enable_equality(u32_cell.0.col); AllocatedU32Cell { u16_cells_le, u32_cell, @@ -431,6 +450,18 @@ impl EventTableCellAllocator { AllocatedCommonRangeCell(self.alloc(&EventTableCellType::CommonRange)) } + pub(crate) fn alloc_state_cell(&mut self) -> AllocatedStateCell { + #[cfg(not(feature = "continuation"))] + { + AllocatedCommonRangeCell(self.alloc(&EventTableCellType::CommonRange)) + } + + #[cfg(feature = "continuation")] + { + self.alloc_u32_cell() + } + } + pub(crate) fn alloc_u8_cell(&mut self) -> AllocatedU8Cell { AllocatedU8Cell(self.alloc(&EventTableCellType::U8)) } @@ -451,7 +482,7 @@ impl EventTableCellAllocator { &mut self, name: &'static str, constraint_builder: &mut ConstraintBuilder, - eid: AllocatedU32Cell, + eid: AllocatedStateCell, location_type: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, offset: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, is_i32: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, @@ -501,7 +532,7 @@ impl EventTableCellAllocator { &mut self, name: &'static str, constraint_builder: &mut ConstraintBuilder, - eid: AllocatedU32Cell, + eid: AllocatedStateCell, location_type: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, offset: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, is_i32: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, @@ -542,7 +573,7 @@ impl EventTableCellAllocator { &mut self, name: &'static str, constraint_builder: &mut ConstraintBuilder, - eid: AllocatedU32Cell, + eid: AllocatedStateCell, location_type: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, offset: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, is_i32: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, @@ -590,7 +621,7 @@ impl EventTableCellAllocator { &mut self, name: &'static str, constraint_builder: &mut ConstraintBuilder, - eid: AllocatedU32Cell, + eid: AllocatedStateCell, location_type: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, offset: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, is_i32: impl Fn(&mut VirtualCells<'_, F>) -> Expression + 'static, diff --git a/crates/zkwasm/src/circuits/etable/assign.rs b/crates/zkwasm/src/circuits/etable/assign.rs index 6c04b703c..51291303d 100644 --- a/crates/zkwasm/src/circuits/etable/assign.rs +++ b/crates/zkwasm/src/circuits/etable/assign.rs @@ -114,46 +114,60 @@ impl EventTableChip { configure_table: &ConfigureTable, initialization_state: &InitializationState, ) -> Result, Error> { - macro_rules! assign_advice { + #[cfg(feature = "continuation")] + macro_rules! assign_state_advice { ($cell:ident, $value:expr) => { self.config.common_config.$cell.assign(ctx, $value)?.cell() }; } - let eid = assign_advice!(eid_cell, initialization_state.eid); - let fid = assign_advice!(fid_cell, F::from(initialization_state.fid as u64)); - let iid = assign_advice!(iid_cell, F::from(initialization_state.iid as u64)); - let sp = assign_advice!(sp_cell, F::from(initialization_state.sp as u64)); - let frame_id = assign_advice!(frame_id_cell, F::from(initialization_state.frame_id as u64)); + #[cfg(not(feature = "continuation"))] + macro_rules! assign_state_advice { + ($cell:ident, $value:expr) => { + assign_common_range_advice!($cell, $value) + }; + } - let host_public_inputs = assign_advice!( - input_index_cell, - F::from(initialization_state.host_public_inputs as u64) - ); - let context_in_index = assign_advice!( + macro_rules! assign_common_range_advice { + ($cell:ident, $value:expr) => { + self.config + .common_config + .$cell + .assign(ctx, F::from($value as u64))? + .cell() + }; + } + + let eid = assign_state_advice!(eid_cell, initialization_state.eid); + let fid = assign_common_range_advice!(fid_cell, initialization_state.fid); + let iid = assign_common_range_advice!(iid_cell, initialization_state.iid); + let sp = assign_common_range_advice!(sp_cell, initialization_state.sp); + let frame_id = assign_state_advice!(frame_id_cell, initialization_state.frame_id); + + let host_public_inputs = + assign_common_range_advice!(input_index_cell, initialization_state.host_public_inputs); + let context_in_index = assign_common_range_advice!( context_input_index_cell, - F::from(initialization_state.context_in_index as u64) + initialization_state.context_in_index ); - let context_out_index = assign_advice!( + let context_out_index = assign_common_range_advice!( context_output_index_cell, - F::from(initialization_state.context_out_index as u64) + initialization_state.context_out_index ); - let external_host_call_call_index = assign_advice!( + let external_host_call_call_index = assign_common_range_advice!( external_host_call_index_cell, - F::from(initialization_state.external_host_call_call_index as u64) + initialization_state.external_host_call_call_index ); - let initial_memory_pages = assign_advice!( - mpages_cell, - F::from(initialization_state.initial_memory_pages as u64) - ); - let maximal_memory_pages = assign_advice!( + let initial_memory_pages = + assign_common_range_advice!(mpages_cell, initialization_state.initial_memory_pages); + let maximal_memory_pages = assign_common_range_advice!( maximal_memory_pages_cell, - F::from(configure_table.maximal_memory_pages as u64) + configure_table.maximal_memory_pages ); #[cfg(feature = "continuation")] - let jops = assign_advice!(jops_cell, F::from(initialization_state.jops as u64)); + let jops = assign_common_range_advice!(jops_cell, initialization_state.jops); Ok(InitializationState { eid, @@ -184,6 +198,24 @@ impl EventTableChip { rest_ops: Vec<(u32, u32)>, initialization_state: &InitializationState, ) -> Result<(), Error> { + #[cfg(feature = "continuation")] + macro_rules! assign_state_advice { + ($cell:ident, $value:expr) => { + self.config.common_config.$cell.assign(ctx, $value)?.cell() + }; + } + + #[cfg(not(feature = "continuation"))] + macro_rules! assign_state_advice { + ($cell:ident, $value:expr) => { + self.config + .common_config + .$cell + .assign(ctx, F::from($value as u64))? + .cell() + }; + } + macro_rules! assign_advice { ($cell:ident, $value:expr) => { self.config.common_config.$cell.assign(ctx, $value)? @@ -292,8 +324,8 @@ impl EventTableChip { maximal_memory_pages_cell, F::from(configure_table.maximal_memory_pages as u64) ); - assign_advice!(frame_id_cell, F::from(entry.eentry.last_jump_eid as u64)); - assign_advice!(eid_cell, entry.eentry.eid); + assign_state_advice!(frame_id_cell, entry.eentry.last_jump_eid); + assign_state_advice!(eid_cell, entry.eentry.eid); assign_advice!(fid_cell, F::from(entry.eentry.inst.fid as u64)); assign_advice!(iid_cell, F::from(entry.eentry.inst.iid as u64)); assign_advice!(itable_lookup_cell, bn_to_field(&entry.eentry.inst.encode())); @@ -320,14 +352,11 @@ impl EventTableChip { } // Assign terminate status - assign_advice!(eid_cell, status.last().unwrap().eid); + assign_state_advice!(eid_cell, status.last().unwrap().eid); assign_advice!(fid_cell, F::from(status.last().unwrap().fid as u64)); assign_advice!(iid_cell, F::from(status.last().unwrap().iid as u64)); assign_advice!(sp_cell, F::from(status.last().unwrap().sp as u64)); - assign_advice!( - frame_id_cell, - F::from(status.last().unwrap().last_jump_eid as u64) - ); + assign_state_advice!(frame_id_cell, status.last().unwrap().last_jump_eid); assign_advice!( mpages_cell, F::from(status.last().unwrap().allocated_memory_pages as u64) diff --git a/crates/zkwasm/src/circuits/etable/mod.rs b/crates/zkwasm/src/circuits/etable/mod.rs index 04305a2bd..db3938fe9 100644 --- a/crates/zkwasm/src/circuits/etable/mod.rs +++ b/crates/zkwasm/src/circuits/etable/mod.rs @@ -79,17 +79,22 @@ pub struct EventTableCommonConfig { rest_mops_cell: AllocatedCommonRangeCell, rest_jops_cell: AllocatedCommonRangeCell, + #[cfg(feature = "continuation")] + jops_cell: AllocatedCommonRangeCell, + pub(crate) input_index_cell: AllocatedCommonRangeCell, pub(crate) context_input_index_cell: AllocatedCommonRangeCell, pub(crate) context_output_index_cell: AllocatedCommonRangeCell, external_host_call_index_cell: AllocatedCommonRangeCell, pub(crate) sp_cell: AllocatedCommonRangeCell, mpages_cell: AllocatedCommonRangeCell, - frame_id_cell: AllocatedCommonRangeCell, - pub(crate) eid_cell: AllocatedU32Cell, + maximal_memory_pages_cell: AllocatedCommonRangeCell, + + frame_id_cell: AllocatedStateCell, + pub(crate) eid_cell: AllocatedStateCell, + fid_cell: AllocatedCommonRangeCell, iid_cell: AllocatedCommonRangeCell, - maximal_memory_pages_cell: AllocatedCommonRangeCell, itable_lookup_cell: AllocatedUnlimitedCell, brtable_lookup_cell: AllocatedUnlimitedCell, @@ -231,19 +236,22 @@ impl EventTableConfig { let rest_mops_cell = allocator.alloc_common_range_cell(); let rest_jops_cell = allocator.alloc_common_range_cell(); + #[cfg(feature = "continuation")] + let jops_cell = allocator.alloc_common_range_cell(); let input_index_cell = allocator.alloc_common_range_cell(); let context_input_index_cell = allocator.alloc_common_range_cell(); let context_output_index_cell = allocator.alloc_common_range_cell(); let external_host_call_index_cell = allocator.alloc_common_range_cell(); - let sp_cell = allocator.alloc_common_range_cell(); - let mpages_cell = allocator.alloc_common_range_cell(); - let frame_id_cell = allocator.alloc_common_range_cell(); - let eid_cell = allocator.alloc_u32_cell(); + + let eid_cell = allocator.alloc_state_cell(); + let frame_id_cell = allocator.alloc_state_cell(); + let fid_cell = allocator.alloc_common_range_cell(); let iid_cell = allocator.alloc_common_range_cell(); + let sp_cell = allocator.alloc_common_range_cell(); + let mpages_cell = allocator.alloc_common_range_cell(); let maximal_memory_pages_cell = allocator.alloc_common_range_cell(); - meta.enable_equality(eid_cell.u32_cell.0.col); // We only need to enable equality for the cells of states let used_common_range_cells_for_state = allocator .free_cells @@ -273,6 +281,8 @@ impl EventTableConfig { ops, rest_mops_cell, rest_jops_cell, + #[cfg(feature = "continuation")] + jops_cell, input_index_cell, context_input_index_cell, context_output_index_cell, @@ -521,9 +531,7 @@ impl EventTableConfig { meta.create_gate("c6a. eid change", |meta| { vec![ - (eid_cell.u32_cell.next_expr(meta) - - eid_cell.u32_cell.curr_expr(meta) - - constant_from!(1)) + (eid_cell.next_expr(meta) - eid_cell.curr_expr(meta) - constant_from!(1)) * enabled_cell.curr_expr(meta) * fixed_curr!(meta, step_sel), ] diff --git a/crates/zkwasm/src/circuits/etable/op_configure/op_call.rs b/crates/zkwasm/src/circuits/etable/op_configure/op_call.rs index a06471ead..3f6e88976 100644 --- a/crates/zkwasm/src/circuits/etable/op_configure/op_call.rs +++ b/crates/zkwasm/src/circuits/etable/op_configure/op_call.rs @@ -107,7 +107,7 @@ impl EventTableOpcodeConfig for CallConfig { meta: &mut VirtualCells<'_, F>, common_config: &EventTableCommonConfig, ) -> Option> { - Some(common_config.eid_cell.u32_cell.curr_expr(meta)) + Some(common_config.eid_cell.curr_expr(meta)) } fn next_fid( diff --git a/crates/zkwasm/src/circuits/etable/op_configure/op_call_indirect.rs b/crates/zkwasm/src/circuits/etable/op_configure/op_call_indirect.rs index 5921e2f45..745df4c92 100644 --- a/crates/zkwasm/src/circuits/etable/op_configure/op_call_indirect.rs +++ b/crates/zkwasm/src/circuits/etable/op_configure/op_call_indirect.rs @@ -196,7 +196,7 @@ impl EventTableOpcodeConfig for CallIndirectConfig { meta: &mut VirtualCells<'_, F>, common_config: &EventTableCommonConfig, ) -> Option> { - Some(common_config.eid_cell.u32_cell.curr_expr(meta)) + Some(common_config.eid_cell.curr_expr(meta)) } fn next_fid( diff --git a/crates/zkwasm/src/circuits/test_circuit/mod.rs b/crates/zkwasm/src/circuits/test_circuit/mod.rs index 44bf39f72..a534e4668 100644 --- a/crates/zkwasm/src/circuits/test_circuit/mod.rs +++ b/crates/zkwasm/src/circuits/test_circuit/mod.rs @@ -46,7 +46,11 @@ use crate::runtime::memory_event_of_step; use super::config::zkwasm_k; use super::image_table::ImageTableConfig; -pub const VAR_COLUMNS: usize = 53; +pub const VAR_COLUMNS: usize = if cfg!(feature = "continuation") { + 53 +} else { + 51 +}; // Reserve a few rows to keep usable rows away from blind rows. // The maximal step size of all tables is bit_table::STEP_SIZE. @@ -130,9 +134,6 @@ impl Circuit for TestCircuit { assert_eq!(cols.count(), 0); - #[cfg(feature = "continuation")] - let state_table = StateTableConfig::configure(meta); - let max_available_rows = (1 << zkwasm_k()) - (meta.blinding_factors() + 1 + RESERVE_ROWS); debug!("max_available_rows: {:?}", max_available_rows); diff --git a/crates/zkwasm/src/continuation/slice.rs b/crates/zkwasm/src/continuation/slice.rs index 88535752c..49734a1a4 100644 --- a/crates/zkwasm/src/continuation/slice.rs +++ b/crates/zkwasm/src/continuation/slice.rs @@ -40,41 +40,48 @@ impl Slices { let slices = etable_slices .into_iter() .enumerate() - .map(|(current_slice, etable_slice)| Slice { - table: Tables { - compilation_tables: CompilationTable { - itable: table.compilation_tables.itable.clone(), - // TODO: imtable should be updated. - imtable: table.compilation_tables.imtable.clone(), - elem_table: table.compilation_tables.elem_table.clone(), - configure_table: table.compilation_tables.configure_table, - static_jtable: table.compilation_tables.static_jtable.clone(), - // TODO: fid_of_entry should be updated or removed. - fid_of_entry: table.compilation_tables.fid_of_entry, - }, - execution_tables: ExecutionTable { - initialization_state: if current_slice == 0 { - table.execution_tables.initialization_state.clone() - } else { - let first_etable_entry = etable_slice.first().unwrap(); + .map(|(current_slice, etable_slice)| { + let first_etable_entry = etable_slice.first().unwrap(); - InitializationState { + Slice { + table: Tables { + compilation_tables: CompilationTable { + itable: table.compilation_tables.itable.clone(), + // TODO: imtable should be updated. + imtable: table.compilation_tables.imtable.clone(), + elem_table: table.compilation_tables.elem_table.clone(), + configure_table: table.compilation_tables.configure_table, + static_jtable: table.compilation_tables.static_jtable.clone(), + // TODO: fid_of_entry should be updated or removed. + pre_initialization_state: InitializationState { eid: first_etable_entry.eid, fid: first_etable_entry.inst.fid, iid: first_etable_entry.inst.iid, frame_id: first_etable_entry.last_jump_eid, sp: first_etable_entry.sp, + + host_public_inputs: todo!(), + context_in_index: todo!(), + context_out_index: todo!(), + external_host_call_call_index: todo!(), + initial_memory_pages: first_etable_entry.allocated_memory_pages, - rest_jops: todo!(), - is_very_first_step: false, - } + maximal_memory_pages: table + .compilation_tables + .configure_table + .maximal_memory_pages, + + jops: todo!(), + }, + }, + execution_tables: ExecutionTable { + etable: EventTable::new(etable_slice), + jtable: table.execution_tables.jtable.clone(), }, - etable: EventTable::new(etable_slice), - jtable: table.execution_tables.jtable.clone(), }, - }, - current_slice, - total_slice, + current_slice, + total_slice, + } }) .collect();