Skip to content

Commit

Permalink
testool: upgrade for cancun and other fixes (#1221)
Browse files Browse the repository at this point in the history
* wip

* update codehash

* done

* ok

* Reapply "feat: enable basefee opcode"

This reverts commit 4ba4f60.

* fix

* remove shanghai

* lint

* enable cancun and shanghai for l1 tracer

* fix 1559

* done
  • Loading branch information
lispc authored Apr 24, 2024
1 parent c5e952e commit a487780
Show file tree
Hide file tree
Showing 41 changed files with 9,926 additions and 8,152 deletions.
2 changes: 0 additions & 2 deletions bus-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ rayon.workspace = true
default = ["test"]
test = ["mock", "rand"]
scroll = ["eth-types/scroll", "mock?/scroll"]
# Enable shanghai feature of mock only if mock is enabled (by test).
shanghai = ["eth-types/shanghai", "mock?/shanghai"]
strict-ccc = []
tracer-tests = ["enable-memory"]
enable-stack = ["eth-types/enable-stack", "mock?/enable-stack"]
Expand Down
61 changes: 31 additions & 30 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ pub use call::{Call, CallContext, CallKind};
use core::fmt::Debug;
use eth_types::{
self,
evm_types::GasCost,
geth_types,
geth_types::TxType,
evm_types::{GasCost, OpcodeId},
geth_types::{self, TxType},
sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData},
Address, GethExecTrace, ToBigEndian, ToWord, Word, H256,
};
Expand All @@ -56,9 +55,6 @@ pub use transaction::{
Transaction, TransactionContext, TxL1Fee, TX_L1_COMMIT_EXTRA_COST, TX_L1_FEE_PRECISION,
};

#[cfg(feature = "enable-stack")]
use eth_types::evm_types::OpcodeId;

/// Setup parameters for ECC-related precompile calls.
#[derive(Debug, Clone, Copy)]
pub struct PrecompileEcParams {
Expand Down Expand Up @@ -623,38 +619,45 @@ impl<'a> CircuitInputBuilder {
state_ref.call_ctx()?.memory.len(),
geth_step.refund.0,
{
#[cfg(feature = "enable-stack")]
let stack = &state_ref.call_ctx()?.stack;
if geth_step.op.is_push_with_data() {
format!("{:?}", geth_trace.struct_logs.get(index + 1).map(|step| step.stack.last()))
#[cfg(feature = "enable-stack")]
{
format!("{:?}", geth_trace.struct_logs.get(index + 1).map(|step| step.stack.last()))
}
#[cfg(not(feature = "enable-stack"))]
{
"N/A".to_string()
}
} else if geth_step.op.is_call_without_value() {
format!(
"{:?} {:40x} {:?} {:?} {:?} {:?}",
geth_step.stack.last(),
geth_step.stack.nth_last(1).unwrap_or_default(),
geth_step.stack.nth_last(2),
geth_step.stack.nth_last(3),
geth_step.stack.nth_last(4),
geth_step.stack.nth_last(5)
stack.last(),
stack.nth_last(1).unwrap_or_default(),
stack.nth_last(2),
stack.nth_last(3),
stack.nth_last(4),
stack.nth_last(5)
)
} else if geth_step.op.is_call_with_value() {
format!(
"{:?} {:40x} {:?} {:?} {:?} {:?} {:?}",
geth_step.stack.last(),
geth_step.stack.nth_last(1).unwrap_or_default(),
geth_step.stack.nth_last(2),
geth_step.stack.nth_last(3),
geth_step.stack.nth_last(4),
geth_step.stack.nth_last(5),
geth_step.stack.nth_last(6),
stack.last(),
stack.nth_last(1).unwrap_or_default(),
stack.nth_last(2),
stack.nth_last(3),
stack.nth_last(4),
stack.nth_last(5),
stack.nth_last(6),
)
} else if geth_step.op.is_create() {
format!(
"value {:?} offset {:?} size {:?} {}",
geth_step.stack.last(),
geth_step.stack.nth_last(1),
geth_step.stack.nth_last(2),
stack.last(),
stack.nth_last(1),
stack.nth_last(2),
if geth_step.op == OpcodeId::CREATE2 {
format!("salt {:?}", geth_step.stack.nth_last(3))
format!("salt {:?}", stack.nth_last(3))
} else {
"".to_string()
}
Expand All @@ -663,17 +666,15 @@ impl<'a> CircuitInputBuilder {
format!(
"{:?} {:?} {:?}",
state_ref.call().map(|c| c.address),
geth_step.stack.last(),
geth_step.stack.nth_last(1),
stack.last(),
stack.nth_last(1),
)
} else {
let stack_input_num = 1024 - geth_step.op.valid_stack_ptr_range().1 as usize;
(0..stack_input_num).map(|i|
format!("{:?}", geth_step.stack.nth_last(i))
format!("{:?}", stack.nth_last(i))
).collect_vec().join(" ")
}
#[cfg(not(feature = "enable-stack"))]
"N/A".to_string()
}
);
debug_assert_eq!(
Expand Down
6 changes: 4 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 @@ -1160,7 +1160,7 @@ impl<'a> CircuitInputStateRef<'a> {
.tx_ctx
.call_is_success
.get(self.tx.calls().len() - self.tx_ctx.call_is_success_offset)
.unwrap();
.expect("fail to get call_is_success");
let mut call = self.parse_call_partial(step)?;
call.is_success = is_success;
call.is_persistent = self.call()?.is_persistent && is_success;
Expand Down Expand Up @@ -1352,13 +1352,15 @@ impl<'a> CircuitInputStateRef<'a> {

#[cfg(feature = "scroll")]
let keccak_code_hash = H256(ethers_core::utils::keccak256(&code));
let code_len = code.len();
let code_hash = self.code_db.insert(code);
log::debug!("call_success_create with code len {code_len} codehash {code_hash:?}");

let (found, callee_account) = self.sdb.get_account_mut(&call.address);
if !found {
return Err(Error::AccountNotFound(call.address));
}

//callee_account.storage.clear();
// already updated in return_revert.rs with check_update_sdb_account
debug_assert_eq!(callee_account.code_hash, code_hash);
#[cfg(feature = "scroll")]
Expand Down
9 changes: 2 additions & 7 deletions bus-mapping/src/evm/opcodes/begin_end_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<Vec<ExecSt
}

// Add caller, callee and coinbase (only for Shanghai) to access list.
#[cfg(feature = "shanghai")]
let accessed_addresses = [
call.caller_address,
call.address,
Expand All @@ -171,8 +170,6 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<Vec<ExecSt
.unwrap()
.coinbase,
];
#[cfg(not(feature = "shanghai"))]
let accessed_addresses = [call.caller_address, call.address];
for address in accessed_addresses {
let is_warm_prev = !state.sdb.add_account_to_access_list(address);
state.tx_access_list_account_write(
Expand All @@ -185,14 +182,11 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<Vec<ExecSt
}

// Calculate gas cost of init code only for EIP-3860 of Shanghai.
#[cfg(feature = "shanghai")]
let init_code_gas_cost = if state.tx.is_create() {
(state.tx.input.len() as u64 + 31) / 32 * eth_types::evm_types::INIT_CODE_WORD_GAS
} else {
0
};
#[cfg(not(feature = "shanghai"))]
let init_code_gas_cost = 0;

// Calculate intrinsic gas cost
let call_data_gas_cost = tx_data_gas_cost(&state.tx.input);
Expand All @@ -211,7 +205,8 @@ pub fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<Vec<ExecSt
let callee_account = &state.sdb.get_account(&call.address).1.clone();
let is_precompile = is_precompiled(&call.address);
let callee_exists = !callee_account.is_empty();
if !callee_exists && call.value.is_zero() {
//if !callee_exists && call.value.is_zero() {
if callee_account.code_hash == CodeDB::empty_code_hash() {
// The account is empty (codehash and nonce be 0) while storage is non empty.
// It is an impossible case for any real world scenario.
// The "clear" helps with testool.
Expand Down
2 changes: 2 additions & 0 deletions bus-mapping/src/evm/opcodes/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ impl<const IS_CREATE2: bool> Opcode for Create<IS_CREATE2> {
// handle keccak_table_lookup
let keccak_input = if IS_CREATE2 {
let salt = stack_inputs[3];
log::trace!("create2 initcode {}", hex::encode(&initialization_code));
log::trace!("create2 caller {:?}", caller.address);
assert_eq!(
address,
get_create2_address(
Expand Down
3 changes: 1 addition & 2 deletions eth-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ base64.workspace = true
[features]
default = ["warn-unimplemented"]
warn-unimplemented = []
shanghai = []
scroll = []

# trace heap allocation related feature switches
enable-stack = []
enable-memory = []
enable-storage = []
enable-storage = []
1 change: 0 additions & 1 deletion eth-types/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,6 @@ mod tests {
assert_eq!(code.code, code2.code);
}

#[cfg(feature = "shanghai")]
#[test]
fn test_asm_disasm_for_shanghai() {
let code = bytecode! {
Expand Down
10 changes: 0 additions & 10 deletions eth-types/src/evm_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ pub const MAX_REFUND_QUOTIENT_OF_GAS_USED: usize = 5;
/// Gas stipend when CALL or CALLCODE is attached with value.
pub const GAS_STIPEND_CALL_WITH_VALUE: u64 = 2300;

#[cfg(feature = "shanghai")]
mod gas_create {
// For EIP-3860, there are 2 special gas cost constraints in geth
// [gasCreate2Eip3860](https://github.com/ethereum/go-ethereum/blob/eb83e7c54021573eaceb14236af3a7a8c64f6027/core/vm/gas_table.go#L321)
Expand All @@ -93,15 +92,6 @@ mod gas_create {
/// Gas per code word for CREATE2.
pub const CREATE2_GAS_PER_CODE_WORD: u64 = INIT_CODE_WORD_GAS + super::GasCost::COPY_SHA3.0;
}
#[cfg(not(feature = "shanghai"))]
mod gas_create {
/// Maximum init code size (0x1FFFFFFFE0) if not EIP-3860.
pub use super::MAX_EXPANDED_MEMORY_ADDRESS as MAX_INIT_CODE_SIZE;
/// Gas per code word for CREATE if not EIP-3860.
pub const CREATE_GAS_PER_CODE_WORD: u64 = 0;
/// Gas per code word for CREATE2 if not EIP-3860.
pub const CREATE2_GAS_PER_CODE_WORD: u64 = super::GasCost::COPY_SHA3.0;
}
pub use gas_create::*;

/// Defines the gas consumption.
Expand Down
30 changes: 5 additions & 25 deletions eth-types/src/evm_types/opcode_ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,16 +318,10 @@ pub enum OpcodeId {
}

impl OpcodeId {
#[cfg(feature = "shanghai")]
/// Returns `true` if the `OpcodeId` is a `PUSHn` (including `PUSH0`).
pub fn is_push(&self) -> bool {
self.as_u8() >= Self::PUSH0.as_u8() && self.as_u8() <= Self::PUSH32.as_u8()
}
#[cfg(not(feature = "shanghai"))]
/// Returns `true` if the `OpcodeId` is a `PUSHn`.
pub fn is_push(&self) -> bool {
self.as_u8() >= Self::PUSH1.as_u8() && self.as_u8() <= Self::PUSH32.as_u8()
}

/// Returns `true` if the `OpcodeId` is a `PUSH1` .. `PUSH32` (excluding `PUSH0`).
pub fn is_push_with_data(&self) -> bool {
Expand Down Expand Up @@ -970,7 +964,6 @@ impl From<u8> for OpcodeId {
0x58u8 => OpcodeId::PC,
0x59u8 => OpcodeId::MSIZE,
0x5bu8 => OpcodeId::JUMPDEST,
#[cfg(feature = "shanghai")]
0x5fu8 => OpcodeId::PUSH0,
0x60u8 => OpcodeId::PUSH1,
0x61u8 => OpcodeId::PUSH2,
Expand Down Expand Up @@ -1059,7 +1052,6 @@ impl From<u8> for OpcodeId {
0x45u8 => OpcodeId::GASLIMIT,
0x46u8 => OpcodeId::CHAINID,
0x47u8 => OpcodeId::SELFBALANCE,
#[cfg(not(feature = "scroll"))]
0x48u8 => OpcodeId::BASEFEE,
0x54u8 => OpcodeId::SLOAD,
0x55u8 => OpcodeId::SSTORE,
Expand Down Expand Up @@ -1127,10 +1119,7 @@ impl FromStr for OpcodeId {
"PC" => OpcodeId::PC,
"MSIZE" => OpcodeId::MSIZE,
"JUMPDEST" => OpcodeId::JUMPDEST,
#[cfg(feature = "shanghai")]
"PUSH0" => OpcodeId::PUSH0,
#[cfg(not(feature = "shanghai"))]
"PUSH0" => OpcodeId::INVALID(0x5f),
"PUSH1" => OpcodeId::PUSH1,
"PUSH2" => OpcodeId::PUSH2,
"PUSH3" => OpcodeId::PUSH3,
Expand Down Expand Up @@ -1236,12 +1225,12 @@ impl FromStr for OpcodeId {
#[cfg(not(feature = "scroll"))]
"SELFDESTRUCT" => OpcodeId::SELFDESTRUCT,
"CHAINID" => OpcodeId::CHAINID,
#[cfg(not(feature = "scroll"))]
"BASEFEE" => OpcodeId::BASEFEE,
#[cfg(feature = "scroll")]
"BASEFEE" => OpcodeId::INVALID(0x48),
"TLOAD" => OpcodeId::INVALID(0xb3),
"TSTORE" => OpcodeId::INVALID(0xb4),
"BLOBHASH" => OpcodeId::INVALID(0x49),
"BLOBBASEFEE" => OpcodeId::INVALID(0x4a),
"TLOAD" => OpcodeId::INVALID(0x5c),
"TSTORE" => OpcodeId::INVALID(0x5d),
"MCOPY" => OpcodeId::INVALID(0x5e),
_ => {
// Parse an invalid opcode value as reported by geth
static RE: LazyLock<Regex> = LazyLock::new(|| {
Expand Down Expand Up @@ -1282,13 +1271,7 @@ mod opcode_ids_tests {

#[test]
fn push_n() {
#[cfg(feature = "shanghai")]
assert!(matches!(OpcodeId::push_n(0), Ok(OpcodeId::PUSH0)));
#[cfg(not(feature = "shanghai"))]
assert!(matches!(
OpcodeId::push_n(0),
Err(Error::InvalidOpConversion)
));
assert!(matches!(OpcodeId::push_n(1), Ok(OpcodeId::PUSH1)));
assert!(matches!(OpcodeId::push_n(10), Ok(OpcodeId::PUSH10)));
assert!(matches!(
Expand All @@ -1299,10 +1282,7 @@ mod opcode_ids_tests {

#[test]
fn postfix() {
#[cfg(feature = "shanghai")]
assert_eq!(OpcodeId::PUSH0.postfix(), Some(0));
#[cfg(not(feature = "shanghai"))]
assert_eq!(OpcodeId::PUSH0.postfix(), None);
assert_eq!(OpcodeId::PUSH1.postfix(), Some(1));
assert_eq!(OpcodeId::PUSH10.postfix(), Some(10));
assert_eq!(OpcodeId::LOG2.postfix(), Some(2));
Expand Down
9 changes: 9 additions & 0 deletions eth-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,15 @@ impl GethCallTrace {
if self.is_precheck_failed() {
return call_is_success;
}
if self.error.as_deref() == Some(GethExecError::InsufficientBalance.error()) {
return call_is_success;
}
if self.error.as_deref() == Some(GethExecError::Depth.error()) {
return call_is_success;
}
if self.error.as_deref() == Some(GethExecError::NonceUintOverflow.error()) {
return call_is_success;
}
call_is_success.push(self.error.is_none());
for call in &self.calls {
call_is_success = call.gen_call_is_success(call_is_success);
Expand Down
40 changes: 2 additions & 38 deletions external-tracer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,34 +77,8 @@ impl LoggerConfig {
/// Configuration structure for `params.ChainConfig`
#[derive(Clone, Debug, Default, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct ChainConfig {
/// Archimedes switch time (nil = no fork, 0 = already on)
pub archimedes_block: Option<u64>,
/// Shanghai switch time (nil = no fork, 0 = already on shanghai)
/// Scroll EVM use the name `ShanghaiBlock` instead
pub shanghai_time: Option<u64>,
/// TerminalTotalDifficulty is the amount of total difficulty reached by
/// the network that triggers the consensus upgrade.
pub terminal_total_difficulty: Option<u64>,
/// TerminalTotalDifficultyPassed is a flag specifying that the network already
/// passed the terminal total difficulty. Its purpose is to disable legacy sync
/// even without having seen the TTD locally (safer long term).
pub terminal_total_difficulty_passed: bool,
}
pub struct ChainConfig {}

impl ChainConfig {
/// Create a chain config for Shanghai fork.
pub fn shanghai() -> Self {
Self {
archimedes_block: None,
shanghai_time: Some(0),
terminal_total_difficulty: Some(0),
terminal_total_difficulty_passed: true,
}
}
}

/// Creates a trace for the specified config
#[cfg(not(feature = "scroll"))]
pub fn trace(config: &TraceConfig) -> Result<Vec<GethExecTrace>, Error> {
let trace_config = &serde_json::to_string_pretty(&config).unwrap();
Expand All @@ -125,17 +99,7 @@ pub fn trace(config: &TraceConfig) -> Result<Vec<GethExecTrace>, Error> {
/// Creates a l2-trace for the specified config
#[cfg(feature = "scroll")]
pub fn l2trace(config: &TraceConfig) -> Result<BlockTrace, Error> {
let mut l2_config = config.clone();
if let Some(chain_config) = l2_config.chain_config.as_mut() {
chain_config.archimedes_block = Some(0);
} else {
l2_config.chain_config = Some(ChainConfig {
archimedes_block: Some(0),
shanghai_time: None,
terminal_total_difficulty: None,
terminal_total_difficulty_passed: false,
});
}
let l2_config = config.clone();
let trace_config = &serde_json::to_string_pretty(&l2_config).unwrap();
log::trace!("trace config: {}", trace_config);
// Get the trace
Expand Down
Loading

0 comments on commit a487780

Please sign in to comment.