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

Commit

Permalink
rw_table fingerprints equality at last chunk last row
Browse files Browse the repository at this point in the history
  • Loading branch information
hero78119 committed Oct 25, 2023
1 parent 47b4d06 commit 943fa3b
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 226 deletions.
4 changes: 2 additions & 2 deletions gadgets/src/permutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use itertools::Itertools;
/// Config for PermutationChipConfig
#[derive(Clone, Debug)]
pub struct PermutationChipConfig<F> {
// column
acc_fingerprints: Column<Advice>,
/// acc_fingerprints
pub acc_fingerprints: Column<Advice>,
row_fingerprints: Column<Advice>,
alpha: Column<Advice>,
power_of_gamma: Vec<Column<Advice>>,
Expand Down
254 changes: 41 additions & 213 deletions zkevm-circuits/src/evm_circuit.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
//! The EVM circuit implementation.
use gadgets::{
is_zero::{IsZeroChip, IsZeroConfig, IsZeroInstruction},
permutation::{PermutationChip, PermutationChipConfig},
util::Expr,
};
use gadgets::permutation::{PermutationChip, PermutationChipConfig};
use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value},
circuit::{Layouter, SimpleFloorPlanner, Value},
plonk::*,
poly::Rotation,
};

mod execution;
Expand All @@ -21,23 +16,21 @@ pub(crate) mod util;
pub(crate) mod test;
#[cfg(feature = "test-circuits")]
pub use self::EvmCircuit as TestEvmCircuit;
use self::{step::HasExecutionState, witness::rw::ToVec};
use self::{
step::HasExecutionState, util::chunkctx_config::ChunkContextConfig, witness::rw::ToVec,
};

pub use crate::witness;
use crate::{
evm_circuit::{
param::{MAX_STEP_HEIGHT, STEP_STATE_HEIGHT},
util::rlc,
},
evm_circuit::param::{MAX_STEP_HEIGHT, STEP_STATE_HEIGHT},
table::{
chunkctx_table::{ChunkCtxFieldTag, ChunkCtxTable},
BlockTable, BytecodeTable, CopyTable, ExpTable, KeccakTable, LookupTable, RwTable, TxTable,
UXTable,
chunkctx_table::ChunkCtxTable, BlockTable, BytecodeTable, CopyTable, ExpTable, KeccakTable,
LookupTable, RwTable, TxTable, UXTable,
},
util::{Challenges, SubCircuit, SubCircuitConfig},
witness::RwMap,
};
use bus_mapping::{circuit_input_builder::ChunkContext, evm::OpcodeId};
use bus_mapping::evm::OpcodeId;
use eth_types::Field;
use execution::ExecutionConfig;
use itertools::Itertools;
Expand All @@ -61,25 +54,15 @@ pub struct EvmCircuitConfig<F> {
copy_table: CopyTable,
keccak_table: KeccakTable,
exp_table: ExpTable,
chunkctx_table: ChunkCtxTable,

// rw permutation config
rw_permutation_config: PermutationChipConfig<F>,
/// rw permutation config
pub rw_permutation_config: PermutationChipConfig<F>,

// pi for carry over previous chunk context
pi_pre_continuity: Column<Instance>,
// pi for carry over chunk context to the next chunk
pi_next_continuity: Column<Instance>,
// pi for permutation challenge
pi_permutation_challenges: Column<Instance>,

// chunk context related field
chunk_index: Column<Advice>,
chunk_index_next: Column<Advice>,
total_chunks: Column<Advice>,
q_chunk_context: Selector,
is_first_chunk: IsZeroConfig<F>,
is_last_chunk: IsZeroConfig<F>,
}

/// Circuit configuration arguments
Expand All @@ -104,6 +87,13 @@ pub struct EvmCircuitConfigArgs<F: Field> {
pub u8_table: UXTable<8>,
/// U16Table
pub u16_table: UXTable<16>,
/// ChunkCtxTable
pub chunkctx_table: ChunkCtxTable,

/// is first chunk selector
pub is_first_chunk: Expression<F>,
/// is last chunk selector
pub is_last_chunk: Expression<F>,
}

impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
Expand All @@ -123,59 +113,12 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
exp_table,
u8_table,
u16_table,
chunkctx_table,
is_first_chunk,
is_last_chunk,
}: Self::ConfigArgs,
) -> Self {
// chunk context
let chunk_index = meta.advice_column();
let chunk_index_inv = meta.advice_column();
let chunk_index_next = meta.advice_column();
let chunk_diff = meta.advice_column();
let total_chunks = meta.advice_column();
let q_chunk_context = meta.complex_selector();

let fixed_table = [(); 4].map(|_| meta.fixed_column());
let chunkctx_table = ChunkCtxTable::construct(meta);

[
(ChunkCtxFieldTag::CurrentChunkIndex.expr(), chunk_index),
(ChunkCtxFieldTag::NextChunkIndex.expr(), chunk_index_next),
(ChunkCtxFieldTag::TotalChunks.expr(), total_chunks),
]
.iter()
.for_each(|(tag_expr, value_col)| {
meta.lookup_any("chunk context lookup", |meta| {
let q_chunk_context = meta.query_selector(q_chunk_context);
let value_col_expr = meta.query_advice(*value_col, Rotation::cur());

vec![(
q_chunk_context
* rlc::expr(
&[tag_expr.clone(), value_col_expr],
challenges.lookup_input(),
),
rlc::expr(&chunkctx_table.table_exprs(meta), challenges.lookup_input()),
)]
});
});

let is_first_chunk = IsZeroChip::configure(
meta,
|meta| meta.query_selector(q_chunk_context),
|meta| meta.query_advice(chunk_index, Rotation::cur()),
chunk_index_inv,
);

let is_last_chunk = IsZeroChip::configure(
meta,
|meta| meta.query_selector(q_chunk_context),
|meta| {
let chunk_index = meta.query_advice(chunk_index, Rotation::cur());
let total_chunks = meta.query_advice(total_chunks, Rotation::cur());

total_chunks - chunk_index - 1.expr()
},
chunk_diff,
);

let execution = Box::new(ExecutionConfig::configure(
meta,
Expand All @@ -191,8 +134,8 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
&keccak_table,
&exp_table,
&chunkctx_table,
&is_first_chunk,
&is_last_chunk,
is_first_chunk,
is_last_chunk,
));

fixed_table.iter().enumerate().for_each(|(idx, &col)| {
Expand Down Expand Up @@ -221,9 +164,6 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
meta.enable_equality(pi_pre_continuity);
meta.enable_equality(pi_next_continuity);
meta.enable_equality(pi_permutation_challenges);
meta.enable_equality(chunk_index);
meta.enable_equality(chunk_index_next);
meta.enable_equality(total_chunks);

Self {
fixed_table,
Expand All @@ -237,30 +177,14 @@ impl<F: Field> SubCircuitConfig<F> for EvmCircuitConfig<F> {
copy_table,
keccak_table,
exp_table,
chunkctx_table,
rw_permutation_config,
pi_pre_continuity,
pi_next_continuity,
pi_permutation_challenges,
chunk_index,
chunk_index_next,
total_chunks,
is_first_chunk,
is_last_chunk,
q_chunk_context,
}
}
}

/// chunk_index, chunk_index_next, total_chunk, initial_rwc, end_rwc
type AssignedChunkContextCell<F> = (
AssignedCell<F, F>,
AssignedCell<F, F>,
AssignedCell<F, F>,
AssignedCell<F, F>,
AssignedCell<F, F>,
);

impl<F: Field> EvmCircuitConfig<F> {
/// Load fixed table
pub fn load_fixed_table(
Expand All @@ -284,75 +208,6 @@ impl<F: Field> EvmCircuitConfig<F> {
},
)
}

/// assign chunk context
pub fn assign_chunk_context(
&self,
layouter: &mut impl Layouter<F>,
chunk_context: &ChunkContext,
max_offset_index: usize,
) -> Result<AssignedChunkContextCell<F>, Error> {
let (
chunk_index_cell,
chunk_index_next_cell,
total_chunk_cell,
initial_rwc_cell,
end_rwc_cell,
) = self.chunkctx_table.load(layouter, chunk_context)?;

let is_first_chunk = IsZeroChip::construct(self.is_first_chunk.clone());
let is_last_chunk = IsZeroChip::construct(self.is_last_chunk.clone());
layouter.assign_region(
|| "chunk context",
|mut region| {
for offset in 0..max_offset_index + 1 {
self.q_chunk_context.enable(&mut region, offset)?;

region.assign_advice(
|| "chunk_index",
self.chunk_index,
offset,
|| Value::known(F::from(chunk_context.chunk_index as u64)),
)?;

region.assign_advice(
|| "chunk_index_next",
self.chunk_index_next,
offset,
|| Value::known(F::from(chunk_context.chunk_index as u64 + 1u64)),
)?;

region.assign_advice(
|| "total_chunks",
self.total_chunks,
offset,
|| Value::known(F::from(chunk_context.total_chunks as u64)),
)?;

is_first_chunk.assign(
&mut region,
offset,
Value::known(F::from(chunk_context.chunk_index as u64)),
)?;
is_last_chunk.assign(
&mut region,
offset,
Value::known(F::from(
(chunk_context.total_chunks - chunk_context.chunk_index - 1) as u64,
)),
)?;
}
Ok(())
},
)?;
Ok((
chunk_index_cell,
chunk_index_next_cell,
total_chunk_cell,
initial_rwc_cell,
end_rwc_cell,
))
}
}

/// Tx Circuit for verifying transaction signatures
Expand Down Expand Up @@ -456,10 +311,7 @@ impl<F: Field> SubCircuit<F> for EvmCircuit<F> {

config.load_fixed_table(layouter, self.fixed_table_tags.clone())?;

let max_offset_index = config.execution.assign_block(layouter, block, challenges)?;

let (prev_chunk_index, next_chunk_index_next, total_chunks, initial_rwc, end_rwc) =
config.assign_chunk_context(layouter, &block.chunk_context, max_offset_index)?;
config.execution.assign_block(layouter, block, challenges)?;

let (rw_rows_padding, _) = RwMap::table_assignments_padding(
&block.rws.table_assignments(true),
Expand Down Expand Up @@ -508,55 +360,26 @@ impl<F: Field> SubCircuit<F> for EvmCircuit<F> {
layouter.constrain_instance(cell.cell(), config.pi_permutation_challenges, i)
})?;
// constraints prev,next fingerprints
[vec![
prev_continuous_fingerprint_cell,
prev_chunk_index,
total_chunks.clone(),
initial_rwc,
]]
.iter()
.flatten()
.enumerate()
.try_for_each(|(i, cell)| {
layouter.constrain_instance(cell.cell(), config.pi_pre_continuity, i)
})?;
[vec![
next_continuous_fingerprint_cell,
next_chunk_index_next,
total_chunks,
end_rwc,
]]
.iter()
.flatten()
.enumerate()
.try_for_each(|(i, cell)| {
layouter.constrain_instance(cell.cell(), config.pi_next_continuity, i)
})?;
layouter.constrain_instance(
prev_continuous_fingerprint_cell.cell(),
config.pi_pre_continuity,
0,
)?;
layouter.constrain_instance(
next_continuous_fingerprint_cell.cell(),
config.pi_next_continuity,
0,
)?;
Ok(())
}

/// Compute the public inputs for this circuit.
fn instance(&self) -> Vec<Vec<F>> {
let block = self.block.as_ref().unwrap();

let (rw_table_chunked_index, rw_table_total_chunks) = (
block.chunk_context.chunk_index,
block.chunk_context.total_chunks,
);

vec![
vec![
block.permu_chronological_rwtable_prev_continuous_fingerprint,
F::from(rw_table_chunked_index as u64),
F::from(rw_table_total_chunks as u64),
F::from(block.chunk_context.initial_rwc as u64),
],
vec![
block.permu_chronological_rwtable_next_continuous_fingerprint,
F::from(rw_table_chunked_index as u64) + F::ONE,
F::from(rw_table_total_chunks as u64),
F::from(block.chunk_context.end_rwc as u64),
],
vec![block.permu_chronological_rwtable_prev_continuous_fingerprint],
vec![block.permu_chronological_rwtable_next_continuous_fingerprint],
vec![block.permu_alpha, block.permu_gamma],
]
}
Expand Down Expand Up @@ -670,6 +493,8 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
let u16_table = UXTable::construct(meta);
let challenges = Challenges::construct(meta);
let challenges_expr = challenges.exprs(meta);
let chunkctx_table = ChunkCtxTable::construct(meta);
let chunkctx_config = ChunkContextConfig::new(meta, &challenges_expr);

(
EvmCircuitConfig::new(
Expand All @@ -685,6 +510,9 @@ impl<F: Field> Circuit<F> for EvmCircuit<F> {
exp_table,
u8_table,
u16_table,
chunkctx_table,
is_first_chunk: chunkctx_config.is_first_chunk.expr(),
is_last_chunk: chunkctx_config.is_last_chunk.expr(),
},
),
challenges,
Expand Down
Loading

0 comments on commit 943fa3b

Please sign in to comment.