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

Commit 5dd697b

Browse files
lightsinglispc
andauthored
refactor for stateless block verifier (#1236)
* move CodeDB and StateDB * update execute_precompiled * fix precompile * fix doc * add revm primitives conversion * update zktrie * clean deps --------- Co-authored-by: Zhang Zhuo <mycinbrin@gmail.com>
1 parent a53859c commit 5dd697b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+660
-1184
lines changed

Cargo.lock

Lines changed: 106 additions & 715 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ members = [
33
"zkevm-circuits",
44
"bus-mapping",
55
"geth-utils",
6-
"keccak256",
76
"zktrie",
87
"gadgets",
98
"integration-tests",
@@ -62,7 +61,8 @@ strum_macros = "0.25"
6261
subtle = "2.4"
6362
tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] }
6463
url = "2.2"
65-
revm-precompile = { git = "https://github.com/scroll-tech/revm", branch = "scroll-fix" }
64+
revm-precompile = { git = "https://github.com/scroll-tech/revm", rev = "9ecb479" } # v35
65+
revm-primitives = { git = "https://github.com/scroll-tech/revm", rev = "9ecb479" } # v35
6666
c-kzg = "1.0.0"
6767

6868
[patch.crates-io]

bus-mapping/src/circuit_input_builder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ use crate::{
1818
evm::opcodes::{gen_associated_ops, gen_associated_steps},
1919
operation::{self, CallContextField, Operation, RWCounter, StartOp, StorageOp, RW},
2020
rpc::GethClient,
21-
state_db::{self, CodeDB, StateDB},
22-
util::{hash_code_keccak, KECCAK_CODE_HASH_EMPTY},
21+
util::KECCAK_CODE_HASH_EMPTY,
2322
};
2423
pub use access::{Access, AccessSet, AccessValue, CodeSource};
2524
pub use block::{Block, BlockContext};
@@ -30,6 +29,7 @@ use eth_types::{
3029
evm_types::{GasCost, OpcodeId},
3130
geth_types::{self, TxType},
3231
sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData},
32+
state_db::{self, CodeDB, StateDB},
3333
Address, GethExecTrace, ToBigEndian, ToWord, Word, H256,
3434
};
3535
use ethers_providers::JsonRpcClient;
@@ -40,7 +40,7 @@ pub use execution::{
4040
};
4141
use hex::decode_to_slice;
4242

43-
use eth_types::sign_types::get_dummy_tx;
43+
use eth_types::{sign_types::get_dummy_tx, utils::hash_code_keccak};
4444
use ethers_core::utils::keccak256;
4545
pub use input_state_ref::CircuitInputStateRef;
4646
use itertools::Itertools;

bus-mapping/src/circuit_input_builder/input_state_ref.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ use crate::{
1919
StackOp, Target, TxAccessListAccountOp, TxAccessListAccountStorageOp, TxLogField, TxLogOp,
2020
TxReceiptField, TxReceiptOp, RW,
2121
},
22-
precompile::{is_precompiled, PrecompileCalls},
23-
state_db::{CodeDB, StateDB},
22+
precompile::PrecompileCalls,
2423
Error,
2524
};
2625
use eth_types::{
@@ -30,6 +29,8 @@ use eth_types::{
3029
memory::{MemoryRange, MemoryWordRange},
3130
Gas, GasCost, Memory, MemoryAddress, MemoryRef, OpcodeId, StackAddress, MAX_CODE_SIZE,
3231
},
32+
state_db::{CodeDB, StateDB},
33+
utils::is_precompiled,
3334
Address, Bytecode, GethExecStep, ToAddress, ToBigEndian, ToWord, Word, H256, U256,
3435
};
3536
use ethers_core::utils::{get_contract_address, get_create2_address};

bus-mapping/src/circuit_input_builder/l2.rs

Lines changed: 7 additions & 238 deletions
Original file line numberDiff line numberDiff line change
@@ -2,247 +2,16 @@ pub use super::block::{Block, BlockContext};
22
use crate::{
33
circuit_input_builder::{self, BlockHead, CircuitInputBuilder, CircuitsParams},
44
error::Error,
5-
precompile::is_precompiled,
6-
state_db::{self, CodeDB, StateDB},
75
};
86
use eth_types::{
97
self,
10-
evm_types::OpcodeId,
11-
l2_types::{BlockTrace, EthBlock, ExecStep, StorageTrace},
12-
Address, ToWord, Word, H256,
8+
l2_types::{BlockTrace, EthBlock, StorageTrace},
9+
state_db::{self, CodeDB, StateDB},
10+
Address, ToWord, Word,
1311
};
1412
use ethers_core::types::Bytes;
15-
use mpt_zktrie::state::{AccountData, ZktrieState};
16-
use std::collections::hash_map::{Entry, HashMap};
17-
18-
impl From<&AccountData> for state_db::Account {
19-
fn from(acc_data: &AccountData) -> Self {
20-
if acc_data.keccak_code_hash.is_zero() {
21-
state_db::Account::zero()
22-
} else {
23-
Self {
24-
nonce: acc_data.nonce.into(),
25-
balance: acc_data.balance,
26-
code_hash: acc_data.poseidon_code_hash,
27-
keccak_code_hash: acc_data.keccak_code_hash,
28-
code_size: acc_data.code_size.into(),
29-
storage: Default::default(),
30-
}
31-
}
32-
}
33-
}
34-
35-
fn decode_bytecode(bytecode: &str) -> Result<Vec<u8>, Error> {
36-
let mut stripped = if let Some(stripped) = bytecode.strip_prefix("0x") {
37-
stripped.to_string()
38-
} else {
39-
bytecode.to_string()
40-
};
41-
42-
let bytecode_len = stripped.len() as u64;
43-
if (bytecode_len & 1) != 0 {
44-
stripped = format!("0{stripped}");
45-
}
46-
47-
hex::decode(stripped).map_err(Error::HexError)
48-
}
49-
50-
fn trace_code(
51-
cdb: &mut CodeDB,
52-
code_hash: Option<H256>,
53-
code: Bytes,
54-
step: &ExecStep,
55-
addr: Option<Address>,
56-
sdb: &StateDB,
57-
) {
58-
// first, try to read from sdb
59-
// let stack = match step.stack.as_ref() {
60-
// Some(stack) => stack,
61-
// None => {
62-
// log::error!("stack underflow, step {step:?}");
63-
// return;
64-
// }
65-
// };
66-
// if stack_pos >= stack.len() {
67-
// log::error!("stack underflow, step {step:?}");
68-
// return;
69-
// }
70-
// let addr = stack[stack.len() - stack_pos - 1].to_address(); //stack N-stack_pos
71-
//
72-
let code_hash = code_hash.or_else(|| {
73-
addr.and_then(|addr| {
74-
let (_existed, acc_data) = sdb.get_account(&addr);
75-
if acc_data.code_hash != CodeDB::empty_code_hash() && !code.is_empty() {
76-
// they must be same
77-
Some(acc_data.code_hash)
78-
} else {
79-
// let us re-calculate it
80-
None
81-
}
82-
})
83-
});
84-
let code_hash = match code_hash {
85-
Some(code_hash) => {
86-
if code_hash.is_zero() {
87-
CodeDB::hash(&code)
88-
} else {
89-
if log::log_enabled!(log::Level::Trace) {
90-
assert_eq!(
91-
code_hash,
92-
CodeDB::hash(&code),
93-
"bytecode len {:?}, step {:?}",
94-
code.len(),
95-
step
96-
);
97-
}
98-
code_hash
99-
}
100-
}
101-
None => {
102-
let hash = CodeDB::hash(&code);
103-
log::debug!(
104-
"hash_code done: addr {addr:?}, size {}, hash {hash:?}",
105-
&code.len()
106-
);
107-
hash
108-
}
109-
};
110-
111-
cdb.0.entry(code_hash).or_insert_with(|| {
112-
log::trace!(
113-
"trace code addr {:?}, size {} hash {:?}",
114-
addr,
115-
&code.len(),
116-
code_hash
117-
);
118-
code.to_vec()
119-
});
120-
}
121-
122-
fn update_codedb(cdb: &mut CodeDB, sdb: &StateDB, block: &BlockTrace) -> Result<(), Error> {
123-
log::debug!("build_codedb for block {:?}", block.header.number);
124-
for (er_idx, execution_result) in block.execution_results.iter().enumerate() {
125-
if let Some(bytecode) = &execution_result.byte_code {
126-
let bytecode = decode_bytecode(bytecode)?.to_vec();
127-
128-
let code_hash = execution_result
129-
.to
130-
.as_ref()
131-
.and_then(|t| t.poseidon_code_hash)
132-
.unwrap_or_else(|| CodeDB::hash(&bytecode));
133-
let code_hash = if code_hash.is_zero() {
134-
CodeDB::hash(&bytecode)
135-
} else {
136-
code_hash
137-
};
138-
if let Entry::Vacant(e) = cdb.0.entry(code_hash) {
139-
e.insert(bytecode);
140-
//log::debug!("inserted tx bytecode {:?} {:?}", code_hash, hash);
141-
}
142-
if execution_result.account_created.is_none() {
143-
//assert_eq!(Some(hash), execution_result.code_hash);
144-
}
145-
}
146-
147-
// filter all precompile calls, empty calls and create
148-
let mut call_trace = execution_result
149-
.call_trace
150-
.flatten_trace(&execution_result.prestate)
151-
.into_iter()
152-
.filter(|call| {
153-
let is_call_to_precompile = call.to.as_ref().map(is_precompiled).unwrap_or(false);
154-
let is_call_to_empty = call.gas_used.is_zero()
155-
&& !call.call_type.is_create()
156-
&& call.is_callee_code_empty;
157-
!(is_call_to_precompile || is_call_to_empty || call.call_type.is_create())
158-
})
159-
.collect::<Vec<_>>();
160-
log::trace!("call_trace: {call_trace:?}");
161-
162-
for (idx, step) in execution_result.exec_steps.iter().enumerate().rev() {
163-
if step.op.is_create() {
164-
continue;
165-
}
166-
let call = if step.op.is_call_or_create() {
167-
// filter call to empty/precompile/!precheck_ok
168-
if let Some(next_step) = execution_result.exec_steps.get(idx + 1) {
169-
// the call doesn't have inner steps, it could be:
170-
// - a call to a precompiled contract
171-
// - a call to an empty account
172-
// - a call that !is_precheck_ok
173-
if next_step.depth != step.depth + 1 {
174-
log::trace!("skip call step due to no inner step, curr: {step:?}, next: {next_step:?}");
175-
continue;
176-
}
177-
} else {
178-
// this is the final step, no inner steps
179-
log::trace!("skip call step due this is the final step: {step:?}");
180-
continue;
181-
}
182-
let call = call_trace.pop();
183-
log::trace!("call_trace pop: {call:?}, current step: {step:?}");
184-
call
185-
} else {
186-
None
187-
};
188-
189-
if let Some(data) = &step.extra_data {
190-
match step.op {
191-
OpcodeId::CALL
192-
| OpcodeId::CALLCODE
193-
| OpcodeId::DELEGATECALL
194-
| OpcodeId::STATICCALL => {
195-
let call = call.unwrap();
196-
assert_eq!(call.call_type, step.op, "{call:?}");
197-
let code_idx = if block.transactions[er_idx].to.is_none() {
198-
0
199-
} else {
200-
1
201-
};
202-
let callee_code = data.get_code_at(code_idx);
203-
// TODO: make nil code ("0x") is not None and assert None case
204-
// assert!(
205-
// callee_code.is_none(),
206-
// "invalid trace: cannot get code of call: {step:?}"
207-
// );
208-
let code_hash = match step.op {
209-
OpcodeId::CALL | OpcodeId::CALLCODE => data.get_code_hash_at(1),
210-
OpcodeId::STATICCALL => data.get_code_hash_at(0),
211-
_ => None,
212-
};
213-
let addr = call.to.unwrap();
214-
trace_code(
215-
cdb,
216-
code_hash,
217-
callee_code.unwrap_or_default(),
218-
step,
219-
Some(addr),
220-
sdb,
221-
);
222-
}
223-
OpcodeId::CREATE | OpcodeId::CREATE2 => {
224-
// notice we do not need to insert code for CREATE,
225-
// bustmapping do this job
226-
unreachable!()
227-
}
228-
OpcodeId::EXTCODESIZE | OpcodeId::EXTCODECOPY => {
229-
let code = data.get_code_at(0);
230-
if code.is_none() {
231-
log::warn!("unable to fetch code from step. {step:?}");
232-
continue;
233-
}
234-
trace_code(cdb, None, code.unwrap(), step, None, sdb);
235-
}
236-
237-
_ => {}
238-
}
239-
}
240-
}
241-
}
242-
243-
log::debug!("updating codedb done");
244-
Ok(())
245-
}
13+
use mpt_zktrie::state::ZktrieState;
14+
use std::collections::hash_map::HashMap;
24615

24716
fn dump_code_db(cdb: &CodeDB) {
24817
for (k, v) in &cdb.0 {
@@ -404,7 +173,7 @@ impl CircuitInputBuilder {
404173

405174
let mut code_db = CodeDB::new();
406175
code_db.insert(Vec::new());
407-
update_codedb(&mut code_db, &sdb, &l2_trace)?;
176+
code_db.update_codedb(&sdb, &l2_trace)?;
408177

409178
let mut builder_block = circuit_input_builder::Block::from_headers(&[], circuits_params);
410179
builder_block.chain_id = chain_id;
@@ -475,7 +244,7 @@ impl CircuitInputBuilder {
475244
*self.sdb.get_storage_mut(&addr, &key).1 = val;
476245
}
477246

478-
update_codedb(&mut self.code_db, &self.sdb, &l2_trace)?;
247+
self.code_db.update_codedb(&self.sdb, &l2_trace)?;
479248

480249
self.apply_l2_trace(l2_trace, !more)?;
481250
Ok(())

bus-mapping/src/circuit_input_builder/tracer_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use crate::{
44
ContractAddressCollisionError, DepthError, ExecError, InsufficientBalanceError, OogError,
55
},
66
operation::RWCounter,
7-
state_db::Account,
87
};
98
use eth_types::{
109
address, bytecode,
1110
evm_types::{stack::Stack, Gas, Memory, OpcodeId},
1211
geth_types::GethData,
12+
state_db::Account,
1313
word, Bytecode, GethExecError, GethExecStep, Hash, ToAddress, ToWord, Word,
1414
};
1515
use mock::test_ctx::{helpers::*, LoggerConfig, TestContext};

bus-mapping/src/circuit_input_builder/transaction.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
//! Transaction & TransactionContext utility module.
22
33
use super::{call::ReversionGroup, Call, CallContext, CallKind, CodeSource, ExecStep};
4-
use crate::{
5-
l2_predeployed::l1_gas_price_oracle,
6-
state_db::{CodeDB, StateDB},
7-
Error,
8-
};
4+
use crate::{l2_predeployed::l1_gas_price_oracle, Error};
95
use eth_types::{
106
evm_types::{gas_utils::tx_data_gas_cost, OpcodeId},
117
geth_types,
128
geth_types::{get_rlp_unsigned, TxType},
9+
state_db::{CodeDB, StateDB},
1310
AccessList, Address, GethExecTrace, Signature, Word, H256,
1411
};
1512
use ethers_core::utils::get_contract_address;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ mod balance_tests {
9191
circuit_input_builder::ExecState,
9292
mock::BlockData,
9393
operation::{AccountOp, CallContextOp, StackOp, RW},
94-
state_db::CodeDB,
9594
};
9695
use eth_types::{
9796
address, bytecode,
9897
evm_types::{OpcodeId, StackAddress},
9998
geth_types::GethData,
99+
state_db::CodeDB,
100100
Bytecode, ToWord, Word, U256,
101101
};
102102
use mock::TestContext;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ use crate::{
1111
operation::{
1212
AccountField, AccountOp, CallContextField, StorageOp, TxReceiptField, TxRefundOp, RW,
1313
},
14-
precompile::{execute_precompiled, is_precompiled, PrecompileCalls},
15-
state_db::CodeDB,
14+
precompile::{execute_precompiled, PrecompileCalls},
1615
Error,
1716
};
1817
use eth_types::{
1918
evm_types::{
2019
gas_utils::{tx_access_list_gas_cost, tx_data_gas_cost},
2120
GasCost, MAX_REFUND_QUOTIENT_OF_GAS_USED,
2221
},
22+
state_db::CodeDB,
23+
utils::is_precompiled,
2324
Bytecode, ToWord, Word,
2425
};
2526
use ethers_core::utils::get_contract_address;

0 commit comments

Comments
 (0)