diff --git a/zkevm-circuits/src/evm_circuit/execution/codesize.rs b/zkevm-circuits/src/evm_circuit/execution/codesize.rs index 04d735e6ca..3b51a0d1db 100644 --- a/zkevm-circuits/src/evm_circuit/execution/codesize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/codesize.rs @@ -49,11 +49,12 @@ impl ExecutionGadget for CodesizeGadget { ..Default::default() }; let same_context = SameContextGadget::construct(cb, opcode, step_state_transition); - #[cfg(not(feature = "dual_bytecode"))] - let code_len_gadget = BytecodeLengthGadget::construct(cb, code_hash); - #[cfg(feature = "dual_bytecode")] - let code_len_gadget = - BytecodeLengthGadget::construct(cb, code_hash, same_context.is_first_sub_bytecode()); + let code_len_gadget = BytecodeLengthGadget::construct( + cb, + code_hash, + #[cfg(feature = "dual_bytecode")] + same_context.is_first_sub_bytecode(), + ); cb.require_equal( "Constraint: bytecode length lookup == codesize", diff --git a/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs b/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs index 729bfd236f..5002f3e926 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_invalid_jump.rs @@ -42,13 +42,11 @@ impl ExecutionGadget for ErrorInvalidJumpGadget { fn configure(cb: &mut EVMConstraintBuilder) -> Self { let is_first_bytecode_table = cb.query_cell(); - #[cfg(not(feature = "dual_bytecode"))] - let code_len_gadget = BytecodeLengthGadget::construct(cb, cb.curr.state.code_hash.clone()); - #[cfg(feature = "dual_bytecode")] let code_len_gadget = BytecodeLengthGadget::construct( cb, cb.curr.state.code_hash.clone(), + #[cfg(feature = "dual_bytecode")] is_first_bytecode_table.expr(), ); diff --git a/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs b/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs index f7b93246b9..2d3bda63be 100644 --- a/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs @@ -3,7 +3,7 @@ use crate::{ param::{N_BYTES_ACCOUNT_ADDRESS, N_BYTES_MEMORY_WORD_SIZE, N_BYTES_U64}, step::ExecutionState, util::{ - common_gadget::{SameContextGadget, WordByteCapGadget}, + common_gadget::{BytecodeLengthGadget, SameContextGadget, WordByteCapGadget}, constraint_builder::{ ConstrainBuilderCommon, EVMConstraintBuilder, ReversionInfo, StepStateTransition, Transition, @@ -40,10 +40,12 @@ pub(crate) struct ExtcodecopyGadget { is_warm: Cell, code_hash: Cell, not_exists: IsZeroGadget, - code_size: Cell, + code_len_gadget: BytecodeLengthGadget, copy_rwc_inc: Cell, memory_expansion: MemoryExpansionGadget, memory_copier_gas: MemoryCopierGasGadget, + #[cfg(feature = "dual_bytecode")] + is_first_bytecode_table: Cell, } impl ExecutionGadget for ExtcodecopyGadget { @@ -53,16 +55,34 @@ impl ExecutionGadget for ExtcodecopyGadget { fn configure(cb: &mut EVMConstraintBuilder) -> Self { let opcode = cb.query_cell(); + let is_first_bytecode_table = cb.query_bool(); let external_address_word = cb.query_word_rlc(); let external_address = from_bytes::expr(&external_address_word.cells[..N_BYTES_ACCOUNT_ADDRESS]); - let code_size = cb.query_cell(); - + //let code_size = cb.query_cell(); let memory_length = cb.query_word_rlc(); let memory_offset = cb.query_cell_phase2(); - let code_offset = WordByteCapGadget::construct(cb, code_size.expr()); + + let code_hash = cb.query_cell_phase2(); + let not_exists = IsZeroGadget::construct(cb, code_hash.clone().expr()); + let exists = not::expr(not_exists.expr()); + + // the reason why not use `same_context.is_first_sub_bytecode` to construct `code_len_gadget` includes + // 1: `same_context` requires rw_counter_offset info, which depends on `code_offset` info, the latter relies on + // `code_len` of `code_len_gadget` + // 2: `same_context.is_first_sub_bytecode` returns current call bytecode info, in extcodecopy, code_hash is not + // necessary current call code hash. + let code_len_gadget = cb.condition(exists.expr(), |cb| { + BytecodeLengthGadget::construct( + cb, + code_hash.clone(), + #[cfg(feature = "dual_bytecode")] + is_first_bytecode_table.expr(), + ) + }); + let code_offset = WordByteCapGadget::construct(cb, code_len_gadget.code_length.expr()); cb.stack_pop(external_address_word.expr()); cb.stack_pop(memory_offset.expr()); @@ -80,19 +100,17 @@ impl ExecutionGadget for ExtcodecopyGadget { Some(&mut reversion_info), ); - let code_hash = cb.query_cell_phase2(); cb.account_read( external_address.expr(), AccountFieldTag::CodeHash, code_hash.expr(), ); - let not_exists = IsZeroGadget::construct(cb, code_hash.expr()); - let exists = not::expr(not_exists.expr()); - cb.condition(exists.expr(), |cb| { - cb.bytecode_length(code_hash.expr(), code_size.expr()); - }); + cb.condition(not_exists.expr(), |cb| { - cb.require_zero("code_size is zero when non_exists", code_size.expr()); + cb.require_zero( + "code_size is zero when non_exists", + code_len_gadget.code_length.expr(), + ); }); let memory_address = MemoryAddressGadget::construct(cb, memory_offset, memory_length); @@ -115,7 +133,7 @@ impl ExecutionGadget for ExtcodecopyGadget { let src_addr = select::expr( code_offset.lt_cap(), code_offset.valid_value(), - code_size.expr(), + code_len_gadget.code_length.expr(), ); cb.copy_table_lookup( @@ -124,7 +142,7 @@ impl ExecutionGadget for ExtcodecopyGadget { cb.curr.state.call_id.expr(), CopyDataType::Memory.expr(), src_addr, - code_size.expr(), + code_len_gadget.code_length.expr(), memory_address.offset(), memory_address.length(), 0.expr(), @@ -159,10 +177,12 @@ impl ExecutionGadget for ExtcodecopyGadget { is_warm, code_hash, not_exists, - code_size, + code_len_gadget, copy_rwc_inc, memory_expansion, memory_copier_gas, + #[cfg(feature = "dual_bytecode")] + is_first_bytecode_table, } } @@ -215,9 +235,9 @@ impl ExecutionGadget for ExtcodecopyGadget { .bytes .len() as u64 }; - self.code_size - .assign(region, offset, Value::known(F::from(code_size)))?; + self.code_len_gadget + .assign(region, offset, block, call, code_size)?; self.code_offset .assign(region, offset, code_offset, F::from(code_size))?; @@ -245,6 +265,12 @@ impl ExecutionGadget for ExtcodecopyGadget { memory_expansion_gas_cost, )?; + #[cfg(feature = "dual_bytecode")] + self.is_first_bytecode_table.assign( + region, + offset, + Value::known(F::from(block.is_first_bytecode(&code_hash))), + )?; Ok(()) } }