Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
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
821 changes: 106 additions & 715 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ members = [
"zkevm-circuits",
"bus-mapping",
"geth-utils",
"keccak256",
"zktrie",
"gadgets",
"integration-tests",
Expand Down Expand Up @@ -62,7 +61,8 @@ strum_macros = "0.25"
subtle = "2.4"
tokio = { version = "1.13", features = ["macros", "rt-multi-thread"] }
url = "2.2"
revm-precompile = { git = "https://github.com/scroll-tech/revm", branch = "scroll-fix" }
revm-precompile = { git = "https://github.com/scroll-tech/revm", rev = "9ecb479" } # v35
revm-primitives = { git = "https://github.com/scroll-tech/revm", rev = "9ecb479" } # v35
c-kzg = "1.0.0"

[patch.crates-io]
Expand Down
6 changes: 3 additions & 3 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ use crate::{
evm::opcodes::{gen_associated_ops, gen_associated_steps},
operation::{self, CallContextField, Operation, RWCounter, StartOp, StorageOp, RW},
rpc::GethClient,
state_db::{self, CodeDB, StateDB},
util::{hash_code_keccak, KECCAK_CODE_HASH_EMPTY},
util::KECCAK_CODE_HASH_EMPTY,
};
pub use access::{Access, AccessSet, AccessValue, CodeSource};
pub use block::{Block, BlockContext};
Expand All @@ -30,6 +29,7 @@ use eth_types::{
evm_types::{GasCost, OpcodeId},
geth_types::{self, TxType},
sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData},
state_db::{self, CodeDB, StateDB},
Address, GethExecTrace, ToBigEndian, ToWord, Word, H256,
};
use ethers_providers::JsonRpcClient;
Expand All @@ -40,7 +40,7 @@ pub use execution::{
};
use hex::decode_to_slice;

use eth_types::sign_types::get_dummy_tx;
use eth_types::{sign_types::get_dummy_tx, utils::hash_code_keccak};
use ethers_core::utils::keccak256;
pub use input_state_ref::CircuitInputStateRef;
use itertools::Itertools;
Expand Down
5 changes: 3 additions & 2 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use crate::{
StackOp, Target, TxAccessListAccountOp, TxAccessListAccountStorageOp, TxLogField, TxLogOp,
TxReceiptField, TxReceiptOp, RW,
},
precompile::{is_precompiled, PrecompileCalls},
state_db::{CodeDB, StateDB},
precompile::PrecompileCalls,
Error,
};
use eth_types::{
Expand All @@ -30,6 +29,8 @@ use eth_types::{
memory::{MemoryRange, MemoryWordRange},
Gas, GasCost, Memory, MemoryAddress, MemoryRef, OpcodeId, StackAddress, MAX_CODE_SIZE,
},
state_db::{CodeDB, StateDB},
utils::is_precompiled,
Address, Bytecode, GethExecStep, ToAddress, ToBigEndian, ToWord, Word, H256, U256,
};
use ethers_core::utils::{get_contract_address, get_create2_address};
Expand Down
245 changes: 7 additions & 238 deletions bus-mapping/src/circuit_input_builder/l2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,247 +2,16 @@ pub use super::block::{Block, BlockContext};
use crate::{
circuit_input_builder::{self, BlockHead, CircuitInputBuilder, CircuitsParams},
error::Error,
precompile::is_precompiled,
state_db::{self, CodeDB, StateDB},
};
use eth_types::{
self,
evm_types::OpcodeId,
l2_types::{BlockTrace, EthBlock, ExecStep, StorageTrace},
Address, ToWord, Word, H256,
l2_types::{BlockTrace, EthBlock, StorageTrace},
state_db::{self, CodeDB, StateDB},
Address, ToWord, Word,
};
use ethers_core::types::Bytes;
use mpt_zktrie::state::{AccountData, ZktrieState};
use std::collections::hash_map::{Entry, HashMap};

impl From<&AccountData> for state_db::Account {
fn from(acc_data: &AccountData) -> Self {
if acc_data.keccak_code_hash.is_zero() {
state_db::Account::zero()
} else {
Self {
nonce: acc_data.nonce.into(),
balance: acc_data.balance,
code_hash: acc_data.poseidon_code_hash,
keccak_code_hash: acc_data.keccak_code_hash,
code_size: acc_data.code_size.into(),
storage: Default::default(),
}
}
}
}

fn decode_bytecode(bytecode: &str) -> Result<Vec<u8>, Error> {
let mut stripped = if let Some(stripped) = bytecode.strip_prefix("0x") {
stripped.to_string()
} else {
bytecode.to_string()
};

let bytecode_len = stripped.len() as u64;
if (bytecode_len & 1) != 0 {
stripped = format!("0{stripped}");
}

hex::decode(stripped).map_err(Error::HexError)
}

fn trace_code(
cdb: &mut CodeDB,
code_hash: Option<H256>,
code: Bytes,
step: &ExecStep,
addr: Option<Address>,
sdb: &StateDB,
) {
// first, try to read from sdb
// let stack = match step.stack.as_ref() {
// Some(stack) => stack,
// None => {
// log::error!("stack underflow, step {step:?}");
// return;
// }
// };
// if stack_pos >= stack.len() {
// log::error!("stack underflow, step {step:?}");
// return;
// }
// let addr = stack[stack.len() - stack_pos - 1].to_address(); //stack N-stack_pos
//
let code_hash = code_hash.or_else(|| {
addr.and_then(|addr| {
let (_existed, acc_data) = sdb.get_account(&addr);
if acc_data.code_hash != CodeDB::empty_code_hash() && !code.is_empty() {
// they must be same
Some(acc_data.code_hash)
} else {
// let us re-calculate it
None
}
})
});
let code_hash = match code_hash {
Some(code_hash) => {
if code_hash.is_zero() {
CodeDB::hash(&code)
} else {
if log::log_enabled!(log::Level::Trace) {
assert_eq!(
code_hash,
CodeDB::hash(&code),
"bytecode len {:?}, step {:?}",
code.len(),
step
);
}
code_hash
}
}
None => {
let hash = CodeDB::hash(&code);
log::debug!(
"hash_code done: addr {addr:?}, size {}, hash {hash:?}",
&code.len()
);
hash
}
};

cdb.0.entry(code_hash).or_insert_with(|| {
log::trace!(
"trace code addr {:?}, size {} hash {:?}",
addr,
&code.len(),
code_hash
);
code.to_vec()
});
}

fn update_codedb(cdb: &mut CodeDB, sdb: &StateDB, block: &BlockTrace) -> Result<(), Error> {
log::debug!("build_codedb for block {:?}", block.header.number);
for (er_idx, execution_result) in block.execution_results.iter().enumerate() {
if let Some(bytecode) = &execution_result.byte_code {
let bytecode = decode_bytecode(bytecode)?.to_vec();

let code_hash = execution_result
.to
.as_ref()
.and_then(|t| t.poseidon_code_hash)
.unwrap_or_else(|| CodeDB::hash(&bytecode));
let code_hash = if code_hash.is_zero() {
CodeDB::hash(&bytecode)
} else {
code_hash
};
if let Entry::Vacant(e) = cdb.0.entry(code_hash) {
e.insert(bytecode);
//log::debug!("inserted tx bytecode {:?} {:?}", code_hash, hash);
}
if execution_result.account_created.is_none() {
//assert_eq!(Some(hash), execution_result.code_hash);
}
}

// filter all precompile calls, empty calls and create
let mut call_trace = execution_result
.call_trace
.flatten_trace(&execution_result.prestate)
.into_iter()
.filter(|call| {
let is_call_to_precompile = call.to.as_ref().map(is_precompiled).unwrap_or(false);
let is_call_to_empty = call.gas_used.is_zero()
&& !call.call_type.is_create()
&& call.is_callee_code_empty;
!(is_call_to_precompile || is_call_to_empty || call.call_type.is_create())
})
.collect::<Vec<_>>();
log::trace!("call_trace: {call_trace:?}");

for (idx, step) in execution_result.exec_steps.iter().enumerate().rev() {
if step.op.is_create() {
continue;
}
let call = if step.op.is_call_or_create() {
// filter call to empty/precompile/!precheck_ok
if let Some(next_step) = execution_result.exec_steps.get(idx + 1) {
// the call doesn't have inner steps, it could be:
// - a call to a precompiled contract
// - a call to an empty account
// - a call that !is_precheck_ok
if next_step.depth != step.depth + 1 {
log::trace!("skip call step due to no inner step, curr: {step:?}, next: {next_step:?}");
continue;
}
} else {
// this is the final step, no inner steps
log::trace!("skip call step due this is the final step: {step:?}");
continue;
}
let call = call_trace.pop();
log::trace!("call_trace pop: {call:?}, current step: {step:?}");
call
} else {
None
};

if let Some(data) = &step.extra_data {
match step.op {
OpcodeId::CALL
| OpcodeId::CALLCODE
| OpcodeId::DELEGATECALL
| OpcodeId::STATICCALL => {
let call = call.unwrap();
assert_eq!(call.call_type, step.op, "{call:?}");
let code_idx = if block.transactions[er_idx].to.is_none() {
0
} else {
1
};
let callee_code = data.get_code_at(code_idx);
// TODO: make nil code ("0x") is not None and assert None case
// assert!(
// callee_code.is_none(),
// "invalid trace: cannot get code of call: {step:?}"
// );
let code_hash = match step.op {
OpcodeId::CALL | OpcodeId::CALLCODE => data.get_code_hash_at(1),
OpcodeId::STATICCALL => data.get_code_hash_at(0),
_ => None,
};
let addr = call.to.unwrap();
trace_code(
cdb,
code_hash,
callee_code.unwrap_or_default(),
step,
Some(addr),
sdb,
);
}
OpcodeId::CREATE | OpcodeId::CREATE2 => {
// notice we do not need to insert code for CREATE,
// bustmapping do this job
unreachable!()
}
OpcodeId::EXTCODESIZE | OpcodeId::EXTCODECOPY => {
let code = data.get_code_at(0);
if code.is_none() {
log::warn!("unable to fetch code from step. {step:?}");
continue;
}
trace_code(cdb, None, code.unwrap(), step, None, sdb);
}

_ => {}
}
}
}
}

log::debug!("updating codedb done");
Ok(())
}
use mpt_zktrie::state::ZktrieState;
use std::collections::hash_map::HashMap;

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

let mut code_db = CodeDB::new();
code_db.insert(Vec::new());
update_codedb(&mut code_db, &sdb, &l2_trace)?;
code_db.update_codedb(&sdb, &l2_trace)?;

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

update_codedb(&mut self.code_db, &self.sdb, &l2_trace)?;
self.code_db.update_codedb(&self.sdb, &l2_trace)?;

self.apply_l2_trace(l2_trace, !more)?;
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion bus-mapping/src/circuit_input_builder/tracer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::{
ContractAddressCollisionError, DepthError, ExecError, InsufficientBalanceError, OogError,
},
operation::RWCounter,
state_db::Account,
};
use eth_types::{
address, bytecode,
evm_types::{stack::Stack, Gas, Memory, OpcodeId},
geth_types::GethData,
state_db::Account,
word, Bytecode, GethExecError, GethExecStep, Hash, ToAddress, ToWord, Word,
};
use mock::test_ctx::{helpers::*, LoggerConfig, TestContext};
Expand Down
7 changes: 2 additions & 5 deletions bus-mapping/src/circuit_input_builder/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
//! Transaction & TransactionContext utility module.

use super::{call::ReversionGroup, Call, CallContext, CallKind, CodeSource, ExecStep};
use crate::{
l2_predeployed::l1_gas_price_oracle,
state_db::{CodeDB, StateDB},
Error,
};
use crate::{l2_predeployed::l1_gas_price_oracle, Error};
use eth_types::{
evm_types::{gas_utils::tx_data_gas_cost, OpcodeId},
geth_types,
geth_types::{get_rlp_unsigned, TxType},
state_db::{CodeDB, StateDB},
AccessList, Address, GethExecTrace, Signature, Word, H256,
};
use ethers_core::utils::get_contract_address;
Expand Down
2 changes: 1 addition & 1 deletion bus-mapping/src/evm/opcodes/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ mod balance_tests {
circuit_input_builder::ExecState,
mock::BlockData,
operation::{AccountOp, CallContextOp, StackOp, RW},
state_db::CodeDB,
};
use eth_types::{
address, bytecode,
evm_types::{OpcodeId, StackAddress},
geth_types::GethData,
state_db::CodeDB,
Bytecode, ToWord, Word, U256,
};
use mock::TestContext;
Expand Down
5 changes: 3 additions & 2 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ use crate::{
operation::{
AccountField, AccountOp, CallContextField, StorageOp, TxReceiptField, TxRefundOp, RW,
},
precompile::{execute_precompiled, is_precompiled, PrecompileCalls},
state_db::CodeDB,
precompile::{execute_precompiled, PrecompileCalls},
Error,
};
use eth_types::{
evm_types::{
gas_utils::{tx_access_list_gas_cost, tx_data_gas_cost},
GasCost, MAX_REFUND_QUOTIENT_OF_GAS_USED,
},
state_db::CodeDB,
utils::is_precompiled,
Bytecode, ToWord, Word,
};
use ethers_core::utils::get_contract_address;
Expand Down
Loading