Skip to content

Commit

Permalink
feat: stack reconstruct (#993)
Browse files Browse the repository at this point in the history
* init reconstruct

* add StackPopOnlyOpcode

* impl arthmetic opcode stack output

* impl get block header field opcode

* impl blockhash

* impl PC, MSIZE, GAS

* remove StackOnlyOpcode

* add strict check

* impl PUSHn

* impl Address

* cleanup stack usage

* impl ORIGIN

* use prestate

* rename to enable-stack

* cleanup stack usage

* disable trace_tests

* fix and add assert

* fix doc test

* fix cfg

* use callTracer

* do not parse call when is_precheck not ok

* do not parse call in create precheck not ok

* fix offset

* fix compile

* disable tracer_tests

* fix test

* fix caller_address

* fix parse_call

* silent more fields

* unbound recursion

* remove stack usage

* update LoggerConfig

* cleanup

* fix root

* fix test

* fix doc test

* cleanup

* upgrade geth version

* add feature switch

* add missing

* add call tracer and prestate tracer

* handle precheck failed call

* why ignore not working

* add l2 prestate

* use go1.20

* 0x5c/5e assigned by cankun

* update l2geth

* fix merge

* clippy

* fix call trace

* fix call trace

* fix merge

* recover test

* fix stack_pointer

* fix update_codedb

* handle last step error

* fix order

* fix order

* skip empty

* fix oog step

* fix stack_pointer

* fix create empty

* fix ErrorCreationCode

* try fix call empty

* try fix call empty

* fix precompile fail

* fix precompile fail

* fix create in tx

* fix output

* fix test

* fix call to self in create

* clippy

* downgrade submodule

* clippy

---------

Co-authored-by: DreamWuGit <wwuwwei@126.com>
  • Loading branch information
lightsing and DreamWuGit authored Feb 7, 2024
1 parent e90ea7e commit d622d66
Show file tree
Hide file tree
Showing 70 changed files with 1,223 additions and 925 deletions.
2 changes: 1 addition & 1 deletion bus-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ rand.workspace = true
rayon.workspace = true

[features]
default = ["test", "enable-stack", "enable-storage"]
default = ["test", "enable-storage"]
test = ["mock", "rand"]
scroll = ["eth-types/scroll", "mock?/scroll"]
# Enable shanghai feature of mock only if mock is enabled (by test).
Expand Down
121 changes: 66 additions & 55 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ pub use call::{Call, CallContext, CallKind};
use core::fmt::Debug;
use eth_types::{
self,
evm_types::{GasCost, OpcodeId},
evm_types::GasCost,
geth_types,
sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData},
Address, GethExecStep, GethExecTrace, ToBigEndian, ToWord, Word, H256,
Address, GethExecTrace, ToBigEndian, ToWord, Word, H256,
};
use ethers_providers::JsonRpcClient;
pub use execution::{
Expand All @@ -55,6 +55,9 @@ 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 @@ -616,53 +619,58 @@ impl<'a> CircuitInputBuilder {
state_ref.call().map(|c| c.call_id).unwrap_or(0),
state_ref.call_ctx()?.memory.len(),
geth_step.refund.0,
if geth_step.op.is_push_with_data() {
format!("{:?}", geth_trace.struct_logs.get(index + 1).map(|step| step.stack.last()))
} 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)
)
} 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),
)
} 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),
if geth_step.op == OpcodeId::CREATE2 {
format!("salt {:?}", geth_step.stack.nth_last(3))
} else {
"".to_string()
}
)
} else if matches!(geth_step.op, OpcodeId::SSTORE) {
format!(
"{:?} {:?} {:?}",
state_ref.call().map(|c| c.address),
geth_step.stack.last(),
geth_step.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))
).collect_vec().join(" ")
{
#[cfg(feature = "enable-stack")]
if geth_step.op.is_push_with_data() {
format!("{:?}", geth_trace.struct_logs.get(index + 1).map(|step| step.stack.last()))
} 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)
)
} 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),
)
} 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),
if geth_step.op == OpcodeId::CREATE2 {
format!("salt {:?}", geth_step.stack.nth_last(3))
} else {
"".to_string()
}
)
} else if matches!(geth_step.op, OpcodeId::SSTORE) {
format!(
"{:?} {:?} {:?}",
state_ref.call().map(|c| c.address),
geth_step.stack.last(),
geth_step.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))
).collect_vec().join(" ")
}
#[cfg(not(feature = "enable-stack"))]
"N/A".to_string()
}
);
debug_assert_eq!(
Expand Down Expand Up @@ -910,9 +918,9 @@ pub fn keccak_inputs_tx_circuit(txs: &[geth_types::Transaction]) -> Result<Vec<V
}

/// Retrieve the init_code from memory for {CREATE, CREATE2}
pub fn get_create_init_code(call_ctx: &CallContext, step: &GethExecStep) -> Result<Vec<u8>, Error> {
let offset = step.stack.nth_last(1)?.low_u64() as usize;
let length = step.stack.nth_last(2)?.as_usize();
pub fn get_create_init_code(call_ctx: &CallContext) -> Result<Vec<u8>, Error> {
let offset = call_ctx.stack.nth_last(1)?.low_u64() as usize;
let length = call_ctx.stack.nth_last(2)?.as_usize();

let mem_len = call_ctx.memory.0.len();
let mut result = vec![0u8; length];
Expand All @@ -925,9 +933,12 @@ pub fn get_create_init_code(call_ctx: &CallContext, step: &GethExecStep) -> Resu
}

/// Retrieve the memory offset and length of call.
pub fn get_call_memory_offset_length(step: &GethExecStep, nth: usize) -> Result<(u64, u64), Error> {
let offset = step.stack.nth_last(nth)?;
let length = step.stack.nth_last(nth + 1)?;
pub fn get_call_memory_offset_length(
call_ctx: &CallContext,
nth: usize,
) -> Result<(u64, u64), Error> {
let offset = call_ctx.stack.nth_last(nth)?;
let length = call_ctx.stack.nth_last(nth + 1)?;
if length.is_zero() {
Ok((0, 0))
} else {
Expand Down
6 changes: 4 additions & 2 deletions bus-mapping/src/circuit_input_builder/call.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::CodeSource;
use crate::{exec_trace::OperationRef, Error};
use eth_types::{
evm_types::{Memory, OpcodeId},
evm_types::{Memory, OpcodeId, Stack},
Address, Hash, Word,
};

Expand Down Expand Up @@ -130,7 +130,7 @@ impl Call {
}

/// Context of a [`Call`].
#[derive(Debug, Default)]
#[derive(Debug, Clone, Default)]
pub struct CallContext {
/// Index of call
pub index: usize,
Expand All @@ -143,6 +143,8 @@ pub struct CallContext {
pub call_data: Vec<u8>,
/// memory context of current call
pub memory: Memory,
/// stack context of current call
pub stack: Stack,
/// return data buffer
pub return_data: Vec<u8>,
}
Expand Down
2 changes: 1 addition & 1 deletion bus-mapping/src/circuit_input_builder/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl ExecStep {
ExecStep {
exec_state: ExecState::Op(step.op),
pc: step.pc,
stack_size: step.stack.0.len(),
stack_size: call_ctx.stack.0.len(),
memory_size: call_ctx.memory.len(),
gas_left: step.gas,
gas_cost: step.gas_cost,
Expand Down
Loading

0 comments on commit d622d66

Please sign in to comment.