Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit c34c889

Browse files
lispced255
andauthored
Fix EXTCODECOPY with empty account (#846)
* Fix EXTCODECOPY with empty account (#1429) We treat empty accounts by storing their code_hash in the RwTable as 0. EXTCODECOPY was obtaining the bytecode length by querying the bytecode table with code_hash=0 on existing accounts, but that entry should be invalid (there's no bytecode with code_hash=0). Skip the bytecode table length lookup when code_hash=0. I've also reintroduced the `Block::debug_print_txs_steps_rw_ops` function, updated to use the new `Block::get_rws` API. This function is not used in the code, but it's very convenient to call it when debugging. Resolve privacy-ethereum#1190 - [x] Bug fix (non-breaking change which fixes an issue) * fix --------- Co-authored-by: Eduard S <eduardsanou@posteo.net>
1 parent 15f90f3 commit c34c889

File tree

4 files changed

+14
-25
lines changed

4 files changed

+14
-25
lines changed

bus-mapping/src/evm/opcodes/extcodecopy.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ use eth_types::{Bytecode, GethExecStep, ToAddress, ToWord, H256, U256};
1111
#[derive(Clone, Copy, Debug)]
1212
pub(crate) struct Extcodecopy;
1313

14-
// TODO: Update to treat code_hash == 0 as account not_exists once the circuit
15-
// is implemented https://github.com/privacy-scaling-explorations/zkevm-circuits/pull/720
16-
1714
impl Opcode for Extcodecopy {
1815
fn gen_associated_ops(
1916
state: &mut CircuitInputStateRef,

bus-mapping/src/state_db.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
1111

1212
lazy_static! {
1313
static ref ACCOUNT_ZERO: Account = Account::zero();
14+
/// Hash value for empty code hash.
1415
static ref EMPTY_CODE_HASH: Hash = CodeDB::hash(&[]);
1516
/// bytes of empty code hash, in little endian order.
1617
pub static ref EMPTY_CODE_HASH_LE: [u8; 32] = {

zkevm-circuits/src/evm_circuit/execution/extcodecopy.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
Transition,
1010
},
1111
from_bytes,
12+
math_gadget::IsZeroGadget,
1213
memory_gadget::{
1314
CommonMemoryAddressGadget, MemoryAddressGadget, MemoryCopierGasGadget,
1415
MemoryExpansionGadget,
@@ -36,6 +37,7 @@ pub(crate) struct ExtcodecopyGadget<F> {
3637
reversion_info: ReversionInfo<F>,
3738
is_warm: Cell<F>,
3839
code_hash: Cell<F>,
40+
not_exists: IsZeroGadget<F>,
3941
code_size: Cell<F>,
4042
copy_rwc_inc: Cell<F>,
4143
memory_expansion: MemoryExpansionGadget<F, 1, N_BYTES_MEMORY_WORD_SIZE>,
@@ -82,11 +84,14 @@ impl<F: Field> ExecutionGadget<F> for ExtcodecopyGadget<F> {
8284
AccountFieldTag::CodeHash,
8385
code_hash.expr(),
8486
);
85-
// TODO: If external_address doesn't exist, we will get code_hash = 0. With
86-
// this value, the bytecode_length lookup will not work, and the copy
87-
// from code_hash = 0 will not work. We should use EMPTY_HASH when
88-
// code_hash = 0.
89-
cb.bytecode_length(code_hash.expr(), code_size.expr());
87+
let not_exists = IsZeroGadget::construct(cb, code_hash.expr());
88+
let exists = not::expr(not_exists.expr());
89+
cb.condition(exists.expr(), |cb| {
90+
cb.bytecode_length(code_hash.expr(), code_size.expr());
91+
});
92+
cb.condition(not_exists.expr(), |cb| {
93+
cb.require_zero("code_size is zero when non_exists", code_size.expr());
94+
});
9095

9196
let memory_address = MemoryAddressGadget::construct(cb, memory_offset, memory_length);
9297
let memory_expansion = MemoryExpansionGadget::construct(cb, [memory_address.end_offset()]);
@@ -151,6 +156,7 @@ impl<F: Field> ExecutionGadget<F> for ExtcodecopyGadget<F> {
151156
is_warm,
152157
reversion_info,
153158
code_hash,
159+
not_exists,
154160
code_size,
155161
copy_rwc_inc,
156162
memory_expansion,
@@ -193,6 +199,8 @@ impl<F: Field> ExecutionGadget<F> for ExtcodecopyGadget<F> {
193199
let code_hash = block.rws[step.rw_indices[8]].account_value_pair().0;
194200
self.code_hash
195201
.assign(region, offset, region.code_hash(code_hash))?;
202+
self.not_exists
203+
.assign_value(region, offset, region.code_hash(code_hash))?;
196204

197205
let code_size = if code_hash.is_zero() {
198206
0

zkevm-circuits/src/table.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,23 +1108,6 @@ impl BytecodeTable {
11081108
|| "bytecode table",
11091109
|mut region| {
11101110
let mut offset = 0;
1111-
1112-
region.assign_fixed(
1113-
|| "bytecode table all-zero row",
1114-
self.q_enable,
1115-
offset,
1116-
|| Value::known(F::one()),
1117-
)?;
1118-
for column in <BytecodeTable as LookupTable<F>>::advice_columns(self) {
1119-
region.assign_advice(
1120-
|| "bytecode table all-zero row",
1121-
column,
1122-
offset,
1123-
|| Value::known(F::zero()),
1124-
)?;
1125-
}
1126-
offset += 1;
1127-
11281111
let bytecode_table_columns =
11291112
<BytecodeTable as LookupTable<F>>::advice_columns(self);
11301113
for bytecode in bytecodes.clone() {

0 commit comments

Comments
 (0)