Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NIT-2640] Add EVM tracing for Stylus programs #2530

Merged
merged 31 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4916517
Add EVM tracing for Stylus programs
gligneul Jul 22, 2024
17383cc
Merge branch 'master' into gligneul/stylus-tracing
gligneul Jul 30, 2024
dcf63f7
Merge branch 'master' into gligneul/stylus-tracing
gligneul Jul 30, 2024
1896ae2
Merge branch 'master' into gligneul/stylus-tracing
gligneul Jul 30, 2024
8e08db3
Improve call and exit in stylus tracing
gligneul Jul 31, 2024
9ae5f81
Merge remote-tracking branch 'refs/remotes/origin/gligneul/stylus-tra…
gligneul Jul 31, 2024
3fc95e6
Merge remote-tracking branch 'origin/master' into gligneul/stylus-tra…
gligneul Jul 31, 2024
bd680dd
Merge branch 'master' into gligneul/stylus-tracing
gligneul Jul 31, 2024
8668262
Add skeleton for wasm/evm trace equivalence test
gligneul Jul 31, 2024
1934ae6
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 1, 2024
eeeeb87
Add equivalence test between wasm and evm traces
gligneul Aug 1, 2024
db0a7d0
Revert change to nitro-testnode
gligneul Aug 1, 2024
9c49c87
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 5, 2024
f149133
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 6, 2024
dd14c87
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 7, 2024
45eb7bf
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 8, 2024
28f3c87
Properly handle the stylus cache when tracing
gligneul Aug 9, 2024
a88b62a
Report remaining gas instead of start gas
gligneul Aug 9, 2024
50b2fb4
Check return opcodes in equivalence test
gligneul Aug 9, 2024
d3273f8
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 9, 2024
8056328
Add helpers to append load and store to multicall
gligneul Aug 9, 2024
8960b3c
Use helpers to build multicall args
gligneul Aug 9, 2024
dee3720
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 9, 2024
09228fc
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 12, 2024
c6d983c
Fix typo in hostio name
gligneul Aug 13, 2024
2a7749d
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 13, 2024
3196b7a
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 13, 2024
d6ea435
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 14, 2024
822b4ca
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 14, 2024
710f61b
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 15, 2024
5a6b060
Merge branch 'master' into gligneul/stylus-tracing
gligneul Aug 15, 2024
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
9 changes: 5 additions & 4 deletions arbitrator/wasm-libraries/user-host-trait/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ pub trait UserHost<DR: DataReader>: GasMeteredMachine {
fn return_data_size(&mut self) -> Result<u32, Self::Err> {
self.buy_ink(HOSTIO_INK)?;
let len = *self.evm_return_data_len();
trace!("return_data_size", self, be!(len), &[], len)
trace!("return_data_size", self, &[], be!(len), len)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't I see a signature change for the trace! macro in this PR?
Was it modified in an earlier PR?

Copy link
Contributor Author

@gligneul gligneul Jul 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trace macro was already working correctly on the Stylus side. This PR adds the trace handling on the host/nitro side.

Regarding this change, I swapped the arguments and outputs to better reflect the semantics of the fields. The return value was being sent as an argument instead of an output. It wasn't a problem until now because this was not being used before.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you might need a corresponding change to cargo-stylus here, but I'm not sure https://github.com/OffchainLabs/cargo-stylus/blob/794221e183cdfd791a2b5be04ec2ab762b381269/replay/src/trace.rs#L367

(also applies to the other tracing order changes)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened a PR on cargo stylus updating the API: OffchainLabs/cargo-stylus#73

}

/// Emits an EVM log with the given number of topics and data, the first bytes of which should
Expand Down Expand Up @@ -629,7 +629,8 @@ pub trait UserHost<DR: DataReader>: GasMeteredMachine {
self.buy_gas(gas_cost)?;

let code = code.slice();
trace!("account_code_size", self, address, &[], code.len() as u32)
let len = code.len() as u32;
trace!("account_code_size", self, address, be!(len), len)
}

/// Gets the code hash of the account at the given address. The semantics are equivalent
Expand Down Expand Up @@ -735,7 +736,7 @@ pub trait UserHost<DR: DataReader>: GasMeteredMachine {
fn evm_gas_left(&mut self) -> Result<u64, Self::Err> {
self.buy_ink(HOSTIO_INK)?;
let gas = self.gas_left()?;
trace!("evm_gas_left", self, be!(gas), &[], gas)
trace!("evm_gas_left", self, &[], be!(gas), gas)
}

/// Gets the amount of ink remaining after paying for the cost of this hostio. The semantics
Expand All @@ -747,7 +748,7 @@ pub trait UserHost<DR: DataReader>: GasMeteredMachine {
fn evm_ink_left(&mut self) -> Result<u64, Self::Err> {
self.buy_ink(HOSTIO_INK)?;
let ink = self.ink_ready()?;
trace!("evm_ink_left", self, be!(ink), &[], ink)
trace!("evm_ink_left", self, &[], be!(ink), ink)
}

/// Computes `value ÷ exponent` using 256-bit math, writing the result to the first.
Expand Down
37 changes: 2 additions & 35 deletions arbos/programs/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,10 @@ func newApiClosures(
actingAddress := contract.Address() // not necessarily WASM
readOnly := interpreter.ReadOnly()
evm := interpreter.Evm()
depth := evm.Depth()
db := evm.StateDB
chainConfig := evm.ChainConfig()

getBytes32 := func(key common.Hash) (common.Hash, uint64) {
if tracingInfo != nil {
tracingInfo.RecordStorageGet(key)
}
cost := vm.WasmStateLoadCost(db, actingAddress, key)
return db.GetState(actingAddress, key), cost
}
Expand All @@ -82,9 +78,6 @@ func newApiClosures(
value := common.BytesToHash(data[32:64])
data = data[64:]

if tracingInfo != nil {
tracingInfo.RecordStorageSet(key, value)
}
if readOnly {
return WriteProtection
}
Expand Down Expand Up @@ -144,22 +137,7 @@ func newApiClosures(

// Tracing: emit the call (value transfer is done later in evm.Call)
if tracingInfo != nil {
var args []uint256.Int
args = append(args, *uint256.NewInt(gas)) // gas
args = append(args, *uint256.NewInt(0).SetBytes(contract.Bytes())) // to address
if opcode == vm.CALL {
args = append(args, *uint256.NewInt(0).SetBytes(value.Bytes())) // call value
}
args = append(args, *uint256.NewInt(0)) // memory offset
args = append(args, *uint256.NewInt(uint64(len(input)))) // memory length
args = append(args, *uint256.NewInt(0)) // return offset
args = append(args, *uint256.NewInt(0)) // return size
s := &vm.ScopeContext{
Memory: util.TracingMemoryFromBytes(input),
Stack: util.TracingStackFromArgs(args...),
Contract: scope.Contract,
}
tracingInfo.Tracer.CaptureState(0, opcode, startGas, baseCost+gas, s, []byte{}, depth, nil)
tracingInfo.CaptureStylusCall(opcode, contract, value, input, gas, startGas, baseCost)
}

var ret []byte
Expand Down Expand Up @@ -217,11 +195,6 @@ func newApiClosures(
one64th := gas / 64
gas -= one64th

// Tracing: emit the create
if tracingInfo != nil {
tracingInfo.Tracer.CaptureState(0, opcode, startGas, baseCost+gas, scope, []byte{}, depth, nil)
}

var res []byte
var addr common.Address // zero on failure
var returnGas uint64
Expand All @@ -243,9 +216,6 @@ func newApiClosures(
return addr, res, cost, nil
}
emitLog := func(topics []common.Hash, data []byte) error {
if tracingInfo != nil {
tracingInfo.RecordEmitLog(topics, data)
}
if readOnly {
return vm.ErrWriteProtection
}
Expand Down Expand Up @@ -284,10 +254,7 @@ func newApiClosures(
}
captureHostio := func(name string, args, outs []byte, startInk, endInk uint64) {
tracingInfo.Tracer.CaptureStylusHostio(name, args, outs, startInk, endInk)
if name == "evm_gas_left" || name == "evm_ink_left" {
tracingInfo.Tracer.CaptureState(0, vm.GAS, 0, 0, scope, []byte{}, depth, nil)
tracingInfo.Tracer.CaptureState(0, vm.POP, 0, 0, scope, []byte{}, depth, nil)
}
tracingInfo.CaptureEVMTraceForHostio(name, args, outs, startInk, endInk)
}

return func(req RequestType, input []byte) ([]byte, []byte, uint64) {
Expand Down
3 changes: 3 additions & 0 deletions arbos/programs/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ func callProgram(
if status == userFailure && debug {
log.Warn("program failure", "err", err, "msg", msg, "program", address, "depth", depth)
}
if tracingInfo != nil {
tracingInfo.CaptureStylusExit(uint8(status), data, err, scope.Contract.Gas)
}
return data, err
}

Expand Down
Loading
Loading