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

Prepare bytecode refactor #1397

Merged
merged 15 commits into from
Aug 17, 2024
2 changes: 1 addition & 1 deletion aggregator/src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl ChunkInfo {
b.transactions
.iter()
.enumerate()
.filter(|(idx, tx)| !tx.is_l1_tx())
.filter(|(_idx, tx)| !tx.is_l1_tx())
.flat_map(|(idx, tx)| {
tx.to_eth_tx(
b.header.hash,
Expand Down
18 changes: 18 additions & 0 deletions bus-mapping/src/circuit_input_builder/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,24 @@ pub enum NumberOrHash {
Hash(H256),
}

impl NumberOrHash {
/// get hash value for NumberOrHash::Hash type
pub fn get_hash(&self) -> H256 {
match self {
Self::Hash(val) => *val,
_ => panic!("not a hash type"),
}
}

/// get number value for NumberOrHash::Number type
pub fn get_number(&self) -> usize {
match self {
Self::Number(val) => *val,
_ => panic!("not a number type"),
}
}
}

/// Represents all bytes related in one copy event.
///
/// - When the source is memory, `bytes` is the memory content, including masked areas. The
Expand Down
34 changes: 21 additions & 13 deletions zkevm-circuits/src/evm_circuit/execution/callop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use crate::{
step::ExecutionState,
util::{
and,
common_gadget::{CommonCallGadget, TransferGadget, TransferGadgetInfo},
common_gadget::{
BytecodeLookupGadget, CommonCallGadget, TransferGadget, TransferGadgetInfo,
},
constraint_builder::{
ConstrainBuilderCommon, EVMConstraintBuilder, ReversionInfo, StepStateTransition,
Transition::{Delta, To},
Expand Down Expand Up @@ -42,7 +44,7 @@ use std::cmp::min;
#[derive(Clone, Debug)]

pub(crate) struct CallOpGadget<F> {
opcode: Cell<F>,
opcode_gadget: BytecodeLookupGadget<F>,
is_call: IsZeroGadget<F>,
is_callcode: IsZeroGadget<F>,
is_delegatecall: IsZeroGadget<F>,
Expand Down Expand Up @@ -91,14 +93,20 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::CALL_OP;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
let opcode = cb.query_cell();
cb.opcode_lookup(opcode.expr(), 1.expr());
let is_call = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CALL.expr());
let is_callcode = IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::CALLCODE.expr());
let is_delegatecall =
IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::DELEGATECALL.expr());
let is_staticcall =
IsZeroGadget::construct(cb, opcode.expr() - OpcodeId::STATICCALL.expr());
let opcode_gadget = BytecodeLookupGadget::construct(cb);

let is_call =
IsZeroGadget::construct(cb, opcode_gadget.opcode.expr() - OpcodeId::CALL.expr());
let is_callcode =
IsZeroGadget::construct(cb, opcode_gadget.opcode.expr() - OpcodeId::CALLCODE.expr());
let is_delegatecall = IsZeroGadget::construct(
cb,
opcode_gadget.opcode.expr() - OpcodeId::DELEGATECALL.expr(),
);
let is_staticcall = IsZeroGadget::construct(
cb,
opcode_gadget.opcode.expr() - OpcodeId::STATICCALL.expr(),
);

// Use rw_counter of the step which triggers next call as its call_id.
let callee_call_id = cb.curr.state.rw_counter.clone();
Expand Down Expand Up @@ -708,7 +716,7 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
);

Self {
opcode,
opcode_gadget,
is_call,
is_callcode,
is_delegatecall,
Expand Down Expand Up @@ -841,8 +849,8 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
}
}

self.opcode
.assign(region, offset, Value::known(F::from(opcode.as_u64())))?;
self.opcode_gadget
.assign(region, offset, block, call, step)?;
self.is_call.assign(
region,
offset,
Expand Down
24 changes: 15 additions & 9 deletions zkevm-circuits/src/evm_circuit/execution/codecopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
param::{N_BYTES_MEMORY_WORD_SIZE, N_BYTES_U64},
step::ExecutionState,
util::{
common_gadget::{SameContextGadget, WordByteCapGadget},
common_gadget::{BytecodeLengthGadget, SameContextGadget, WordByteCapGadget},
constraint_builder::{
ConstrainBuilderCommon, EVMConstraintBuilder, StepStateTransition, Transition,
},
Expand Down Expand Up @@ -46,6 +46,8 @@ pub(crate) struct CodeCopyGadget<F> {
/// RW inverse counter from the copy table at the start of related copy
/// steps.
copy_rwc_inc: Cell<F>,
/// Wraps the bytecode length and lookup.
code_len_gadget: BytecodeLengthGadget<F>,
}

impl<F: Field> ExecutionGadget<F> for CodeCopyGadget<F> {
Expand Down Expand Up @@ -73,9 +75,6 @@ impl<F: Field> ExecutionGadget<F> for CodeCopyGadget<F> {
// Fetch the hash of bytecode running in current environment.
let code_hash = cb.curr.state.code_hash.clone();

// Fetch the bytecode length from the bytecode table.
cb.bytecode_length(code_hash.expr(), code_size.expr());

// Calculate the next memory size and the gas cost for this memory
// access. This also accounts for the dynamic gas required to copy bytes to
// memory.
Expand Down Expand Up @@ -128,6 +127,14 @@ impl<F: Field> ExecutionGadget<F> for CodeCopyGadget<F> {
};
let same_context = SameContextGadget::construct(cb, opcode, step_state_transition);

// Fetch the bytecode length from the bytecode table.
let code_len_gadget = BytecodeLengthGadget::construct(cb, cb.curr.state.code_hash.clone());
cb.require_equal(
"code_size == code_len_gadget::code_length",
code_size.expr(),
code_len_gadget.code_length.expr(),
);

Self {
same_context,
code_offset,
Expand All @@ -136,6 +143,7 @@ impl<F: Field> ExecutionGadget<F> for CodeCopyGadget<F> {
memory_expansion,
memory_copier_gas,
copy_rwc_inc,
code_len_gadget,
}
}

Expand All @@ -160,12 +168,10 @@ impl<F: Field> ExecutionGadget<F> for CodeCopyGadget<F> {
let [dest_offset, code_offset, size] =
[0, 1, 2].map(|i| block.rws[step.rw_indices[i]].stack_value());

let bytecode = block
.bytecodes
.get(&call.code_hash)
.expect("could not find current environment's bytecode");
let code_size = self
.code_len_gadget
.assign(region, offset, block, &call.code_hash)?;

let code_size = bytecode.bytes.len() as u64;
self.code_size
.assign(region, offset, Value::known(F::from(code_size)))?;

Expand Down
25 changes: 12 additions & 13 deletions zkevm-circuits/src/evm_circuit/execution/codesize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
evm_circuit::{
step::ExecutionState,
util::{
common_gadget::SameContextGadget,
common_gadget::{BytecodeLengthGadget, SameContextGadget},
constraint_builder::{
ConstrainBuilderCommon, EVMConstraintBuilder, StepStateTransition, Transition,
},
Expand All @@ -24,7 +24,7 @@ use super::ExecutionGadget;
pub(crate) struct CodesizeGadget<F> {
same_context: SameContextGadget<F>,
codesize_bytes: [Cell<F>; 8],
codesize: Cell<F>,
code_len_gadget: BytecodeLengthGadget<F>,
}

impl<F: Field> ExecutionGadget<F> for CodesizeGadget<F> {
Expand All @@ -38,14 +38,6 @@ impl<F: Field> ExecutionGadget<F> for CodesizeGadget<F> {
let codesize_bytes = array_init(|_| cb.query_byte());

let code_hash = cb.curr.state.code_hash.clone();
let codesize = cb.query_cell();
cb.bytecode_length(code_hash.expr(), codesize.expr());

cb.require_equal(
"Constraint: bytecode length lookup == codesize",
from_bytes::expr(&codesize_bytes),
codesize.expr(),
);

cb.stack_push(cb.word_rlc(codesize_bytes.clone().map(|c| c.expr())));

Expand All @@ -57,11 +49,18 @@ impl<F: Field> ExecutionGadget<F> for CodesizeGadget<F> {
..Default::default()
};
let same_context = SameContextGadget::construct(cb, opcode, step_state_transition);
let code_len_gadget = BytecodeLengthGadget::construct(cb, code_hash);

cb.require_equal(
"Constraint: bytecode length lookup == codesize",
from_bytes::expr(&codesize_bytes),
code_len_gadget.code_length.expr(),
);

Self {
same_context,
codesize_bytes,
codesize,
code_len_gadget,
}
}

Expand All @@ -87,8 +86,8 @@ impl<F: Field> ExecutionGadget<F> for CodesizeGadget<F> {
c.assign(region, offset, Value::known(F::from(*b as u64)))?;
}

self.codesize
.assign(region, offset, Value::known(F::from(codesize)))?;
self.code_len_gadget
.assign(region, offset, block, &call.code_hash)?;

Ok(())
}
Expand Down
15 changes: 7 additions & 8 deletions zkevm-circuits/src/evm_circuit/execution/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
},
step::ExecutionState,
util::{
common_gadget::{get_copy_bytes, TransferGadget},
common_gadget::{get_copy_bytes, BytecodeLookupGadget, TransferGadget},
constraint_builder::{
ConstrainBuilderCommon, EVMConstraintBuilder, ReversionInfo, StepStateTransition,
Transition::{Delta, To},
Expand Down Expand Up @@ -41,7 +41,7 @@ use std::iter::once;
/// Gadget for CREATE and CREATE2 opcodes
#[derive(Clone, Debug)]
pub(crate) struct CreateGadget<F, const IS_CREATE2: bool, const S: ExecutionState> {
opcode: Cell<F>,
opcode_gadget: BytecodeLookupGadget<F>,
tx_id: Cell<F>,
reversion_info: ReversionInfo<F>,
depth: Cell<F>,
Expand Down Expand Up @@ -89,13 +89,12 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
const EXECUTION_STATE: ExecutionState = S;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
let opcode = cb.query_cell();
let copy_rw_increase = cb.query_cell();
let opcode_gadget = BytecodeLookupGadget::construct(cb);

cb.opcode_lookup(opcode.expr(), 1.expr());
cb.require_equal(
"Opcode is CREATE or CREATE2",
opcode.expr(),
opcode_gadget.opcode.expr(),
if IS_CREATE2 {
OpcodeId::CREATE2
} else {
Expand Down Expand Up @@ -535,7 +534,7 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
);

Self {
opcode,
opcode_gadget,
tx_id,
reversion_info,
depth,
Expand Down Expand Up @@ -578,9 +577,9 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
) -> Result<(), Error> {
let opcode = step.opcode.unwrap();
let is_create2 = opcode == OpcodeId::CREATE2;
self.opcode
.assign(region, offset, Value::known(F::from(opcode.as_u64())))?;

self.opcode_gadget
.assign(region, offset, block, call, step)?;
self.tx_id
.assign(region, offset, Value::known(tx.id.to_scalar().unwrap()))?;
self.depth.assign(
Expand Down
20 changes: 9 additions & 11 deletions zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
param::N_BYTES_PROGRAM_COUNTER,
step::ExecutionState,
util::{
common_gadget::{CommonErrorGadget, WordByteCapGadget},
common_gadget::{BytecodeLengthGadget, CommonErrorGadget, WordByteCapGadget},
constraint_builder::{ConstrainBuilderCommon, EVMConstraintBuilder},
math_gadget::{IsEqualGadget, IsZeroGadget},
CachedRegion, Cell,
Expand All @@ -21,7 +21,6 @@ use halo2_proofs::{circuit::Value, plonk::Error};
pub(crate) struct ErrorInvalidJumpGadget<F> {
opcode: Cell<F>,
dest: WordByteCapGadget<F, N_BYTES_PROGRAM_COUNTER>,
code_len: Cell<F>,
value: Cell<F>,
is_code: Cell<F>,
push_rlc: Cell<F>,
Expand All @@ -30,6 +29,7 @@ pub(crate) struct ErrorInvalidJumpGadget<F> {
phase2_condition: Cell<F>,
is_condition_zero: IsZeroGadget<F>,
common_error_gadget: CommonErrorGadget<F>,
code_len_gadget: BytecodeLengthGadget<F>,
}

impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
Expand All @@ -38,8 +38,9 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
const EXECUTION_STATE: ExecutionState = ExecutionState::ErrorInvalidJump;

fn configure(cb: &mut EVMConstraintBuilder<F>) -> Self {
let code_len = cb.query_cell();
let dest = WordByteCapGadget::construct(cb, code_len.expr());
// Look up bytecode length
let code_len_gadget = BytecodeLengthGadget::construct(cb, cb.curr.state.code_hash.clone());
let dest = WordByteCapGadget::construct(cb, code_len_gadget.code_length.expr());

let opcode = cb.query_cell();
let value = cb.query_cell();
Expand Down Expand Up @@ -71,9 +72,6 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
cb.require_zero("condition is not zero", is_condition_zero.expr());
});

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

// If destination is in valid range, lookup for the value.
cb.condition(dest.lt_cap(), |cb| {
cb.bytecode_lookup(
Expand All @@ -95,7 +93,6 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
Self {
opcode,
dest,
code_len,
value,
is_code,
push_rlc,
Expand All @@ -104,6 +101,7 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
phase2_condition,
is_condition_zero,
common_error_gadget,
code_len_gadget,
}
}

Expand Down Expand Up @@ -132,9 +130,9 @@ impl<F: Field> ExecutionGadget<F> for ErrorInvalidJumpGadget<F> {
.bytecodes
.get(&call.code_hash)
.expect("could not find current environment's bytecode");
let code_len = code.bytes.len() as u64;
self.code_len
.assign(region, offset, Value::known(F::from(code_len)))?;
let code_len = self
.code_len_gadget
.assign(region, offset, block, &call.code_hash)?;

let dest = block.rws[step.rw_indices[0]].stack_value();
self.dest.assign(region, offset, dest, F::from(code_len))?;
Expand Down
Loading
Loading