Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: fix the cell type to support larger memory accessing range #247

Merged
merged 4 commits into from
Apr 14, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 3 additions & 9 deletions crates/cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,6 @@ impl Config {
result
};

if cfg!(not(feature = "continuation")) {
if result.tables.execution_tables.etable.len() != 1 {
return Err(anyhow::anyhow!(
"Only support single slice for non-continuation mode.\nYou could increase K or enable continuation feature."
));
}
}

{
if let Some(context_output_filename) = context_output_filename {
let context_output_path = output_dir.join(context_output_filename);
Expand Down Expand Up @@ -318,8 +310,10 @@ impl Config {

let progress_bar = ProgressBar::new(result.tables.execution_tables.etable.len() as u64);

let mut slices = loader.slice(result).into_iter().enumerate().peekable();
let mut slices = loader.slice(result)?.into_iter().enumerate().peekable();
while let Some((index, circuit)) = slices.next() {
let circuit = circuit?;

let _is_finalized_circuit = slices.peek().is_none();

if mock_test {
Expand Down
1 change: 1 addition & 0 deletions crates/zkwasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ strum = "0.24.1"
strum_macros = "0.24.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0.58"
ff = "0.12"
sha2 = "0.10.6"
anyhow.workspace = true
Expand Down
37 changes: 36 additions & 1 deletion crates/zkwasm/src/circuits/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use halo2_proofs::plonk::Expression;
use halo2_proofs::plonk::VirtualCells;
use num_bigint::BigUint;

use crate::circuits::etable::EVENT_TABLE_ENTRY_ROWS;
use crate::circuits::utils::bn_to_field;
use crate::circuits::utils::Context;
use crate::constant_from;
use crate::nextn;

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -79,6 +81,11 @@ impl<F: FieldExt> AllocatedU64Cell<F> {
#[derive(Debug, Clone, Copy)]
pub(crate) struct AllocatedU32Cell<F: FieldExt> {
pub(crate) u16_cells_le: [AllocatedU16Cell<F>; 2],
}

#[derive(Debug, Clone, Copy)]
pub(crate) struct AllocatedU32PermutationCell<F: FieldExt> {
pub(crate) u16_cells_le: [AllocatedU16Cell<F>; 2],
pub(crate) u32_cell: AllocatedUnlimitedCell<F>,
}

Expand Down Expand Up @@ -160,13 +167,41 @@ impl<F: FieldExt> CellExpression<F> for AllocatedCommonRangeCell<F> {

impl<F: FieldExt> AllocatedU32Cell<F> {
pub(crate) fn expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
self.u32_cell.curr_expr(meta)
self.u16_cells_le[0].curr_expr(meta)
+ (self.u16_cells_le[1].curr_expr(meta) * constant_from!(1 << 16))
}

pub(crate) fn curr_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
self.expr(meta)
}

pub(crate) fn assign(&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())?;
}

Ok(())
}
}

#[allow(dead_code)]
impl<F: FieldExt> AllocatedU32PermutationCell<F> {
pub(crate) fn expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
self.curr_expr(meta)
}

pub(crate) fn curr_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
self.u32_cell.expr(meta)
}

pub(crate) fn next_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
nextn!(
meta,
self.u32_cell.cell.col,
self.u32_cell.cell.rot + EVENT_TABLE_ENTRY_ROWS
)
}

pub(crate) fn assign(
&self,
ctx: &mut Context<'_, F>,
Expand Down
89 changes: 58 additions & 31 deletions crates/zkwasm/src/circuits/etable/allocator.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::AllocatedU32StateCell;
use super::EVENT_TABLE_ENTRY_ROWS;
use crate::circuits::bit_table::BitTableOp;
use crate::circuits::cell::*;
Expand All @@ -9,7 +10,6 @@ use crate::circuits::traits::ConfigureLookupTable;
use crate::circuits::utils::bit::BitColumn;
use crate::circuits::utils::common_range::CommonRangeColumn;
use crate::circuits::utils::u16::U16Column;
use crate::circuits::utils::u32_state::AllocatedU32StateCell;
use crate::circuits::utils::u8::U8Column;
use crate::circuits::Context;
use crate::circuits::Lookup;
Expand Down Expand Up @@ -66,24 +66,6 @@ impl_cell!(AllocatedCommonRangeCell);
impl_cell!(AllocatedUnlimitedCell);
impl_cell!(AllocatedJumpTableLookupCell);

impl<F: FieldExt> EventTableCellExpression<F> for AllocatedU32Cell<F> {
fn next_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
nextn!(
meta,
self.u32_cell.cell.col,
self.u32_cell.cell.rot + EVENT_TABLE_ENTRY_ROWS as i32
)
}

fn prev_expr(&self, meta: &mut VirtualCells<'_, F>) -> Expression<F> {
nextn!(
meta,
self.u32_cell.cell.col,
self.u32_cell.cell.rot - EVENT_TABLE_ENTRY_ROWS as i32
)
}
}

#[derive(Debug, Clone, Copy)]
pub(crate) struct AllocatedJumpTableLookupCell<F: FieldExt> {
pub(crate) cell: AllocatedCell<F>,
Expand Down Expand Up @@ -184,14 +166,16 @@ pub(crate) enum EventTableCellType {

const BIT_COLUMNS: usize = 12;
const U8_COLUMNS: usize = 1;
const U32_CELLS: usize = if cfg!(feature = "continuation") {
const U32_CELLS: usize = 2;
const U32_PERMUTATION_CELLS: usize = if cfg!(feature = "continuation") {
10
} else {
0
};
const U64_CELLS: usize = 5;
const U16_COLUMNS: usize = U64_CELLS + (U32_CELLS / 2);
const COMMON_RANGE_COLUMNS: usize = if cfg!(feature = "continuation") { 5 } else { 7 };
const U16_COLUMNS: usize =
U64_CELLS + ((U32_CELLS + U32_PERMUTATION_CELLS).next_multiple_of(2) / 2);
const COMMON_RANGE_COLUMNS: usize = if cfg!(feature = "continuation") { 4 } else { 6 };
const UNLIMITED_COLUMNS: usize = if cfg!(feature = "continuation") {
10
} else {
Expand Down Expand Up @@ -229,6 +213,7 @@ impl<F: FieldExt> AllocatedBitTableLookupCells<F> {
pub(crate) struct AllocatorFreeCellsProfiler {
free_cells: BTreeMap<EventTableCellType, (usize, u32)>,
free_u32_cells: usize,
free_u32_permutation_cells: usize,
free_u64_cells: usize,
}

Expand All @@ -237,6 +222,7 @@ impl AllocatorFreeCellsProfiler {
Self {
free_cells: allocator.free_cells.clone(),
free_u32_cells: allocator.free_u32_cells.len(),
free_u32_permutation_cells: allocator.free_u32_permutation_cells.len(),
free_u64_cells: allocator.free_u64_cells.len(),
}
}
Expand All @@ -254,18 +240,40 @@ impl AllocatorFreeCellsProfiler {
}

self.free_u32_cells = usize::min(self.free_u32_cells, allocator.free_u32_cells.len());
self.free_u32_permutation_cells = usize::min(
self.free_u32_permutation_cells,
allocator.free_u32_permutation_cells.len(),
);
self.free_u64_cells = usize::min(self.free_u64_cells, allocator.free_u64_cells.len());
}

pub(crate) fn assert_no_free_cells<F: FieldExt>(&self, allocator: &EventTableCellAllocator<F>) {
for (t, (i, j)) in &self.free_cells {
let cols = allocator.all_cols.get(t).unwrap();

assert!(*i == cols.len() || (*i == cols.len() - 1 && *j > 0));
assert!(
*i == cols.len() || (*i == cols.len() - 1 && *j > 0),
"unused {:?} col should be removed: {}.",
t,
cols.len() - *i - (*j != 0) as usize
);
}

assert!(self.free_u32_cells == 0);
assert!(self.free_u64_cells == 0);
assert!(
self.free_u32_cells == 0,
"unused u32 cells should be removed: {:?}.",
self.free_u32_cells
);
assert!(
self.free_u32_permutation_cells == 0,
"unused u32 permutation cells should be removed: {:?}.",
self.free_u32_permutation_cells
);
assert!(
self.free_u64_cells == 0,
"unused u64 cells should be removed: {:?}.",
self.free_u64_cells
);
}
}

Expand All @@ -275,6 +283,7 @@ pub(crate) struct EventTableCellAllocator<F: FieldExt> {
pub(crate) free_cells: BTreeMap<EventTableCellType, (usize, u32)>,
all_cols: BTreeMap<EventTableCellType, Vec<Vec<Column<Advice>>>>,
free_u32_cells: Vec<AllocatedU32Cell<F>>,
free_u32_permutation_cells: Vec<AllocatedU32PermutationCell<F>>,
free_u64_cells: Vec<AllocatedU64Cell<F>>,
_mark: PhantomData<F>,
}
Expand All @@ -293,11 +302,17 @@ impl<F: FieldExt> EventTableCellAllocator<F> {
}
}

pub(super) fn prepare_alloc_u32_cell(
pub(super) fn prepare_alloc_u32_cell(&mut self) -> AllocatedU32Cell<F> {
let u16_cells_le = [0; 2].map(|_| self.alloc_u16_cell());

AllocatedU32Cell { u16_cells_le }
}

pub(super) fn prepare_alloc_u32_permutation_cell(
&mut self,
meta: &mut ConstraintSystem<F>,
enable: impl Fn(&mut VirtualCells<'_, F>) -> Expression<F>,
) -> AllocatedU32Cell<F> {
) -> AllocatedU32PermutationCell<F> {
let u16_cells_le = [0; 2].map(|_| self.alloc_u16_cell());
let u32_cell = self.alloc_unlimited_cell();
meta.create_gate("c9. u32 decompose", |meta| {
Expand All @@ -312,7 +327,7 @@ impl<F: FieldExt> EventTableCellAllocator<F> {
});
meta.enable_equality(u32_cell.cell.col);

AllocatedU32Cell {
AllocatedU32PermutationCell {
u16_cells_le,
u32_cell,
}
Expand Down Expand Up @@ -352,9 +367,14 @@ impl<F: FieldExt> EventTableCellAllocator<F> {
) -> Self {
let mut allocator = Self::_new(meta, k, sel, rtable, mtable, jtable, cols);
for _ in 0..U32_CELLS {
let cell = allocator.prepare_alloc_u32_cell(meta, |meta| fixed_curr!(meta, sel));
let cell = allocator.prepare_alloc_u32_cell();
allocator.free_u32_cells.push(cell);
}
for _ in 0..U32_PERMUTATION_CELLS {
let cell =
allocator.prepare_alloc_u32_permutation_cell(meta, |meta| fixed_curr!(meta, sel));
allocator.free_u32_permutation_cells.push(cell);
}
for _ in 0..U64_CELLS {
let cell = allocator.prepare_alloc_u64_cell(meta, |meta| fixed_curr!(meta, sel));
allocator.free_u64_cells.push(cell);
Expand Down Expand Up @@ -462,6 +482,7 @@ impl<F: FieldExt> EventTableCellAllocator<F> {
.into_iter(),
),
free_u32_cells: vec![],
free_u32_permutation_cells: vec![],
free_u64_cells: vec![],
_mark: PhantomData,
}
Expand Down Expand Up @@ -522,7 +543,7 @@ impl<F: FieldExt> EventTableCellAllocator<F> {
pub(crate) fn alloc_u32_state_cell(&mut self) -> AllocatedU32StateCell<F> {
cfg_if::cfg_if! {
if #[cfg(feature = "continuation")] {
self.alloc_u32_cell()
self.alloc_u32_permutation_cell()
} else {
self.alloc_common_range_cell()
}
Expand Down Expand Up @@ -731,11 +752,17 @@ impl<F: FieldExt> EventTableCellAllocator<F> {
cell
}

#[allow(dead_code)]
pub(crate) fn alloc_u32_cell(&mut self) -> AllocatedU32Cell<F> {
self.free_u32_cells.pop().expect("no more free u32 cells")
}

#[allow(dead_code)]
pub(crate) fn alloc_u32_permutation_cell(&mut self) -> AllocatedU32PermutationCell<F> {
self.free_u32_permutation_cells
.pop()
.expect("no more free u32 permutation cells")
}

pub(crate) fn alloc_u64_cell(&mut self) -> AllocatedU64Cell<F> {
self.free_u64_cells.pop().expect("no more free u64 cells")
}
Expand Down
29 changes: 0 additions & 29 deletions crates/zkwasm/src/circuits/etable/assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,35 +124,6 @@ impl<F: FieldExt> EventTableChip<F> {
#[cfg(feature = "continuation")]
let jops = assign_common_range_advice!(jops_cell, state.jops);

// if let Some(assigned_pre_initialization_state) = assigned_pre_initialization_state {
// macro_rules! constrain_equal {
// ($field:ident) => {
// ctx.region.constrain_equal(
// $field.cell(),
// assigned_pre_initialization_state.$field.cell(),
// )?;
// };
// }

// constrain_equal!(eid);
// constrain_equal!(fid);
// constrain_equal!(iid);
// constrain_equal!(sp);
// constrain_equal!(frame_id);

// constrain_equal!(host_public_inputs);
// constrain_equal!(context_in_index);
// constrain_equal!(context_out_index);
// constrain_equal!(external_host_call_call_index);

// constrain_equal!(initial_memory_pages);
// constrain_equal!(maximal_memory_pages);

// #[cfg(feature = "continuation")]
// constrain_equal!(jops);
// }

// The context will be stepped by EVENT_TABLE_ENTRY_ROWS.
ctx.step(EVENT_TABLE_ENTRY_ROWS as usize);

Ok(InitializationState {
Expand Down
6 changes: 5 additions & 1 deletion crates/zkwasm/src/circuits/etable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use super::rtable::RangeTableConfig;
use super::traits::ConfigureLookupTable;
use super::utils::step_status::StepStatus;
use super::utils::table_entry::EventTableEntryWithMemoryInfo;
use super::utils::u32_state::AllocatedU32StateCell;
use super::utils::Context;
use crate::circuits::etable::op_configure::op_bin::BinConfigBuilder;
use crate::circuits::etable::op_configure::op_bin_bit::BinBitConfigBuilder;
Expand Down Expand Up @@ -68,6 +67,11 @@ mod op_configure;
pub(crate) mod allocator;
pub(crate) mod constraint_builder;

#[cfg(feature = "continuation")]
type AllocatedU32StateCell<F> = AllocatedU32PermutationCell<F>;
#[cfg(not(feature = "continuation"))]
type AllocatedU32StateCell<F> = AllocatedCommonRangeCell<F>;

pub(crate) const EVENT_TABLE_ENTRY_ROWS: i32 = 4;
pub(crate) const OP_CAPABILITY: usize = 32;

Expand Down
Loading
Loading