Skip to content

Commit

Permalink
Handle edge cases of gas checking in zero tracer
Browse files Browse the repository at this point in the history
  • Loading branch information
cffls committed Mar 25, 2024
1 parent bc7d8a9 commit e1f22f4
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 11 deletions.
21 changes: 21 additions & 0 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"sort"

"encoding/hex"

"github.com/holiman/uint256"
libcommon "github.com/ledgerwatch/erigon-lib/common"
types2 "github.com/ledgerwatch/erigon-lib/types"
Expand Down Expand Up @@ -399,6 +400,26 @@ func (sdb *IntraBlockState) GetIncarnation(addr libcommon.Address) uint64 {
return 0
}

func (sdb *IntraBlockState) HasLiveAccount(addr libcommon.Address) bool {
if stateObject := sdb.stateObjects[addr]; stateObject != nil {
return true
}
return false
}

func (sdb *IntraBlockState) HasLiveState(addr libcommon.Address, key *libcommon.Hash) bool {
if stateObject := sdb.stateObjects[addr]; stateObject != nil {
if _, ok := stateObject.originStorage[*key]; ok {
return true
}

if _, ok := stateObject.dirtyStorage[*key]; ok {
return true
}
}
return false
}

// Selfdestruct marks the given account as suicided.
// This clears the account balance.
//
Expand Down
2 changes: 2 additions & 0 deletions core/vm/evmtypes/evmtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ type IntraBlockState interface {
GetCommittedState(libcommon.Address, *libcommon.Hash, *uint256.Int)
GetState(address libcommon.Address, slot *libcommon.Hash, outValue *uint256.Int)
SetState(libcommon.Address, *libcommon.Hash, uint256.Int)
HasLiveAccount(addr libcommon.Address) bool
HasLiveState(addr libcommon.Address, key *libcommon.Hash) bool

Selfdestruct(libcommon.Address) bool
HasSelfdestructed(libcommon.Address) bool
Expand Down
55 changes: 44 additions & 11 deletions eth/tracers/native/zero.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ func (t *zeroTracer) CaptureTxStart(gasLimit uint64) {

// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
func (t *zeroTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
if err != nil {
// Only continue if the error is nil or if the error is out of gas and the opcode is SSTORE, CALL, or SELFDESTRUCT
if !(err == nil || (err == vm.ErrOutOfGas && (op == vm.SSTORE || op == vm.CALL || op == vm.SELFDESTRUCT))) {
return
}

Expand All @@ -107,16 +108,42 @@ func (t *zeroTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
switch {
case stackLen >= 1 && op == vm.SLOAD:
slot := libcommon.Hash(stackData[stackLen-1].Bytes32())
t.addAccountToTrace(caller)
t.addSLOADToAccount(caller, slot)
case stackLen >= 1 && op == vm.SSTORE:
slot := libcommon.Hash(stackData[stackLen-1].Bytes32())

// If the SSTORE is out of gas and the slot is in live state, we will add the slot to account read
if err == vm.ErrOutOfGas {
if t.env.IntraBlockState().HasLiveState(caller, &slot) {
t.addAccountToTrace(caller)
t.addSLOADToAccount(caller, slot)
}
return
}
t.addAccountToTrace(caller)
t.addSSTOREToAccount(caller, slot, stackData[stackLen-2].Clone())
case stackLen >= 1 && (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT):
addr := libcommon.Address(stackData[stackLen-1].Bytes20())

if err == vm.ErrOutOfGas && op == vm.SELFDESTRUCT {
if t.env.IntraBlockState().HasLiveAccount(addr) {
t.addAccountToTrace(addr)
}
return
}
t.addAccountToTrace(addr)
t.addOpCodeToAccount(addr, op)
case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE):
addr := libcommon.Address(stackData[stackLen-2].Bytes20())

// If the call is out of gas, we will add account but not the opcode
if err == vm.ErrOutOfGas && op == vm.CALL {
if t.env.IntraBlockState().HasLiveAccount(addr) {
t.addAccountToTrace(addr)
}
return
}
t.addAccountToTrace(addr)
t.addOpCodeToAccount(addr, op)
case op == vm.CREATE:
Expand Down Expand Up @@ -228,17 +255,23 @@ func (t *zeroTracer) CaptureTxEnd(restGas uint64) {

// We don't need to provide the actual bytecode UNLESS the opcode is the following:
// DELEGATECALL, CALL, STATICCALL, CALLCODE, EXTCODECOPY, EXTCODEHASH, EXTCODESIZE
if trace.CodeUsage != nil && trace.CodeUsage.Read != nil && t.addrOpCodes[addr] != nil {
opCodes := []vm.OpCode{vm.DELEGATECALL, vm.CALL, vm.STATICCALL, vm.CALLCODE, vm.EXTCODECOPY,
vm.EXTCODEHASH, vm.EXTCODESIZE}
keep := false
for _, opCode := range opCodes {
if _, ok := t.addrOpCodes[addr][opCode]; ok {
keep = true
break
if trace.CodeUsage != nil && trace.CodeUsage.Read != nil {
if t.addrOpCodes[addr] != nil {
// We don't need to provide the actual bytecode UNLESS the opcode is the following:
// DELEGATECALL, CALL, STATICCALL, CALLCODE, EXTCODECOPY, EXTCODEHASH, EXTCODESIZE
opCodes := []vm.OpCode{vm.DELEGATECALL, vm.CALL, vm.STATICCALL, vm.CALLCODE, vm.EXTCODECOPY,
vm.EXTCODEHASH, vm.EXTCODESIZE}
keep := false
for _, opCode := range opCodes {
if _, ok := t.addrOpCodes[addr][opCode]; ok {
keep = true
break
}
}
}
if !keep {
if !keep {
trace.CodeUsage = nil
}
} else {
trace.CodeUsage = nil
}
}
Expand Down

0 comments on commit e1f22f4

Please sign in to comment.