Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.
Merged
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
67 changes: 23 additions & 44 deletions zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ use crate::{
param::N_BYTES_PROGRAM_COUNTER,
step::ExecutionState,
util::{
and,
common_gadget::{CommonErrorGadget, WordByteRangeGadget},
common_gadget::{CommonErrorGadget, WordByteCapGadget},
constraint_builder::ConstraintBuilder,
math_gadget::{IsEqualGadget, IsZeroGadget, LtGadget},
select, CachedRegion, Cell,
math_gadget::{IsEqualGadget, IsZeroGadget},
CachedRegion, Cell,
},
witness::{Block, Call, ExecStep, Transaction},
},
Expand All @@ -21,11 +20,10 @@ use halo2_proofs::{circuit::Value, plonk::Error};
#[derive(Clone, Debug)]
pub(crate) struct ErrorInvalidJumpGadget<F> {
opcode: Cell<F>,
dest_word: WordByteRangeGadget<F, N_BYTES_PROGRAM_COUNTER>,
dest: WordByteCapGadget<F, N_BYTES_PROGRAM_COUNTER>,
code_len: Cell<F>,
value: Cell<F>,
is_code: Cell<F>,
dest_lt_code_len: LtGadget<F, N_BYTES_PROGRAM_COUNTER>,
is_jump_dest: IsEqualGadget<F>,
is_jumpi: IsEqualGadget<F>,
phase2_condition: Cell<F>,
Expand All @@ -39,12 +37,8 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::ErrorInvalidJump;

fn configure(cb: &mut ConstraintBuilder<F>) -> Self {
let dest_word = WordByteRangeGadget::construct(cb);
let dest = select::expr(
dest_word.within_range(),
dest_word.valid_value(),
u64::MAX.expr(),
);
let code_len = cb.query_cell();
let dest = WordByteCapGadget::construct(cb, code_len.expr());

let opcode = cb.query_cell();
let value = cb.query_cell();
Expand All @@ -67,7 +61,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
let is_condition_zero = IsZeroGadget::construct(cb, phase2_condition.expr());

// Pop the value from the stack
cb.stack_pop(dest_word.original_word());
cb.stack_pop(dest.original_word());

cb.condition(is_jumpi.expr(), |cb| {
cb.stack_pop(phase2_condition.expr());
Expand All @@ -76,38 +70,31 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
});

// Look up bytecode length
let code_len = cb.query_cell();
cb.bytecode_length(cb.curr.state.code_hash.expr(), code_len.expr());

let dest_lt_code_len = LtGadget::construct(cb, dest.expr(), code_len.expr());

// If destination is in valid range, lookup for the value.
cb.condition(
and::expr([dest_word.within_range(), dest_lt_code_len.expr()]),
|cb| {
cb.bytecode_lookup(
cb.curr.state.code_hash.expr(),
dest.expr(),
is_code.expr(),
value.expr(),
);
cb.require_zero(
"is_code is false or not JUMPDEST",
is_code.expr() * is_jump_dest.expr(),
);
},
);
cb.condition(dest.lt_cap(), |cb| {
cb.bytecode_lookup(
cb.curr.state.code_hash.expr(),
dest.valid_value(),
is_code.expr(),
value.expr(),
);
cb.require_zero(
"is_code is false or not JUMPDEST",
is_code.expr() * is_jump_dest.expr(),
);
});

let common_error_gadget =
CommonErrorGadget::construct(cb, opcode.expr(), 3.expr() + is_jumpi.expr());

Self {
opcode,
dest_word,
dest,
code_len,
value,
is_code,
dest_lt_code_len,
is_jump_dest,
is_jumpi,
phase2_condition,
Expand All @@ -130,9 +117,6 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
self.opcode
.assign(region, offset, Value::known(F::from(opcode.as_u64())))?;

let dest = block.rws[step.rw_indices[0]].stack_value();
let dest_within_range = self.dest_word.assign(region, offset, dest)?;

let condition = if is_jumpi {
block.rws[step.rw_indices[1]].stack_value()
} else {
Expand All @@ -148,13 +132,11 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
self.code_len
.assign(region, offset, Value::known(F::from(code_len)))?;

let dest = if dest_within_range {
dest.as_u64()
} else {
u64::MAX
};
let dest = block.rws[step.rw_indices[0]].stack_value();
self.dest.assign(region, offset, dest, F::from(code_len))?;

// set default value in case can not find value, is_code from bytecode table
let dest = u64::try_from(dest).unwrap_or(code_len);
let mut code_pair = [0u8, 0u8];
if dest < code_len {
// get real value from bytecode table
Expand All @@ -172,9 +154,6 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
F::from(OpcodeId::JUMPDEST.as_u64()),
)?;

self.dest_lt_code_len
.assign(region, offset, F::from(dest), F::from(code_len))?;

self.is_jumpi.assign(
region,
offset,
Expand Down