Skip to content

Commit

Permalink
revert overriding caller
Browse files Browse the repository at this point in the history
  • Loading branch information
s1na committed Apr 4, 2023
1 parent ec71233 commit e3f3129
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 130 deletions.
2 changes: 1 addition & 1 deletion core/state_transition.go
Expand Up @@ -290,7 +290,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
return nil, err
}

if st.evm.Config.Debug && st.evm.Config.Tracer != nil {
if st.evm.Config.Debug {
st.evm.Config.Tracer.CaptureTxStart(st.initialGas)
defer func() {
st.evm.Config.Tracer.CaptureTxEnd(st.gas)
Expand Down
30 changes: 7 additions & 23 deletions core/vm/evm.go
Expand Up @@ -179,7 +179,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
if !evm.StateDB.Exist(addr) {
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
// Calling a non existing account, don't do anything, but ping the tracer
if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
evm.Config.Tracer.CaptureEnd(ret, 0, nil)
Expand All @@ -195,7 +195,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)

// Capture the tracer start/end events in debug mode
if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
defer func(startGas uint64) { // Lazy evaluation of the parameters
Expand Down Expand Up @@ -223,12 +223,6 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// If the account has no code, we can abort here
// The depth-check is already done, and precompiles handled above
contract := NewContract(caller, AccountRef(addrCopy), value, gas)
if evm.Config.Debug {
// eth_call can specify a filter to select calls of a transaction and mock their caller.
if evm.Config.MockCaller != nil && evm.Config.MockCaller.Match(caller.Address(), addr, input) {
contract = NewContract(AccountRef(evm.Config.MockCaller.Caller()), AccountRef(addrCopy), value, gas)
}
}
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code)
ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas
Expand Down Expand Up @@ -271,7 +265,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
var snapshot = evm.StateDB.Snapshot()

// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
Expand All @@ -286,11 +280,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
if evm.Config.Debug {
if evm.Config.MockCaller != nil && evm.Config.MockCaller.Match(caller.Address(), addr, input) {
contract = NewContract(AccountRef(evm.Config.MockCaller.Caller()), AccountRef(caller.Address()), value, gas)
}
}
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas
Expand All @@ -317,7 +306,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
var snapshot = evm.StateDB.Snapshot()

// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
Expand Down Expand Up @@ -367,7 +356,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
evm.StateDB.AddBalance(addr, big0)

// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
Expand All @@ -384,11 +373,6 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas)
if evm.Config.Debug {
if evm.Config.MockCaller != nil && evm.Config.MockCaller.Match(caller.Address(), addr, input) {
contract = NewContract(AccountRef(evm.Config.MockCaller.Caller()), AccountRef(caller.Address()), new(big.Int), gas)
}
}
contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
Expand Down Expand Up @@ -455,7 +439,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
contract := NewContract(caller, AccountRef(address), value, gas)
contract.SetCodeOptionalHash(&address, codeAndHash)

if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
} else {
Expand Down Expand Up @@ -498,7 +482,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
}

if evm.Config.Debug && evm.Config.Tracer != nil {
if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err)
} else {
Expand Down
2 changes: 1 addition & 1 deletion core/vm/instructions.go
Expand Up @@ -826,7 +826,7 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.Suicide(scope.Contract.Address())
if interpreter.cfg.Debug && interpreter.cfg.Tracer != nil {
if interpreter.cfg.Debug {
interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
interpreter.cfg.Tracer.CaptureExit([]byte{}, 0, nil)
}
Expand Down
20 changes: 6 additions & 14 deletions core/vm/interpreter.go
Expand Up @@ -23,20 +23,12 @@ import (
"github.com/ethereum/go-ethereum/log"
)

// MockCaller will match a call based on a filter and provides a mock
// caller in case of a match.
type MockCaller interface {
Match(from common.Address, to common.Address, input []byte) bool
Caller() common.Address
}

// Config are the configuration options for the Interpreter
type Config struct {
Debug bool // Enables debugging
Tracer EVMLogger // Opcode logger
MockCaller MockCaller
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages

JumpTable *JumpTable // EVM instruction table, automatically populated if unset

Expand Down Expand Up @@ -166,7 +158,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
}()
contract.Input = input

if in.cfg.Debug && in.cfg.Tracer != nil {
if in.cfg.Debug {
defer func() {
if err != nil {
if !logged {
Expand All @@ -182,7 +174,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// the execution of one of the operations or until the done flag is set by the
// parent context.
for {
if in.cfg.Debug && in.cfg.Tracer != nil {
if in.cfg.Debug {
// Capture pre-execution values for tracing.
logged, pcCopy, gasCopy = false, pc, contract.Gas
}
Expand Down Expand Up @@ -227,14 +219,14 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
return nil, ErrOutOfGas
}
// Do tracing before memory expansion
if in.cfg.Debug && in.cfg.Tracer != nil {
if in.cfg.Debug {
in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
logged = true
}
if memorySize > 0 {
mem.Resize(memorySize)
}
} else if in.cfg.Debug && in.cfg.Tracer != nil {
} else if in.cfg.Debug {
in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
logged = true
}
Expand Down
37 changes: 1 addition & 36 deletions internal/ethapi/api.go
Expand Up @@ -17,7 +17,6 @@
package ethapi

import (
"bytes"
"context"
"encoding/hex"
"errors"
Expand Down Expand Up @@ -953,34 +952,6 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
}
}

// CallerOverride includes fields to filter out certain calls of a transaction
// and an address to replace their callers with.
type CallerOverride struct {
From *common.Address
To *common.Address
Input *hexutil.Bytes
Substitute common.Address
}

// Match determines whether a call matches the given filter.
func (co *CallerOverride) Match(from, to common.Address, input []byte) bool {
if co.From != nil && *co.From != from {
return false
}
if co.To != nil && *co.To != to {
return false
}
if co.Input != nil && !bytes.Equal(co.To.Bytes(), input) {
return false
}
return true
}

// Caller returns the substitute address to be used as caller of a call.
func (co *CallerOverride) Caller() common.Address {
return co.Substitute
}

// ChainContextBackend provides methods required to implement ChainContext.
type ChainContextBackend interface {
Engine() consensus.Engine
Expand Down Expand Up @@ -1044,12 +1015,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
if config != nil && config.BlockOverrides != nil {
config.BlockOverrides.Apply(&blockCtx)
}
vmCfg := &vm.Config{NoBaseFee: true}
if config != nil && config.CallerOverride != nil {
vmCfg.Debug = true
vmCfg.MockCaller = config.CallerOverride
}
evm, vmError, err := b.GetEVM(ctx, msg, state, header, vmCfg, &blockCtx)
evm, vmError, err := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1109,7 +1075,6 @@ func (e *revertError) ErrorData() interface{} {

type callConfig struct {
BlockOverrides *BlockOverrides
CallerOverride *CallerOverride
}

// Call executes the given transaction on the state for the given block number.
Expand Down
55 changes: 0 additions & 55 deletions internal/ethapi/api_test.go
Expand Up @@ -24,7 +24,6 @@ import (
"math/big"
"reflect"
"sort"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -435,61 +434,7 @@ func TestCall(t *testing.T) {
},
want: "0x000000000000000000000000000000000000000000000000000000000000000b",
},
// Simple call override should work
{
blockNumber: rpc.LatestBlockNumber,
call: TransactionArgs{
From: &accounts[1].addr,
To: &randomAccounts[0].addr,
},
overrides: StateOverride{
// Yul source code:
//
// object "Test" {
// code {
// let c := caller()
// mstore(0, c)
// return(0xc, 0x14)
// }
// }
randomAccounts[0].addr: OverrideAccount{Code: hex2Bytes("33806000526014600cf3")},
},
config: &callConfig{
CallerOverride: &CallerOverride{
Substitute: accounts[2].addr,
},
},
want: strings.ToLower(accounts[2].addr.Hex()),
},
// Caller shouldn't be overridden if filter doesn't match
{
blockNumber: rpc.LatestBlockNumber,
call: TransactionArgs{
From: &accounts[1].addr,
To: &randomAccounts[0].addr,
},
overrides: StateOverride{
// Yul source code:
//
// object "Test" {
// code {
// let c := caller()
// mstore(0, c)
// return(0xc, 0x14)
// }
// }
randomAccounts[0].addr: OverrideAccount{Code: hex2Bytes("33806000526014600cf3")},
},
config: &callConfig{
CallerOverride: &CallerOverride{
To: &randomAccounts[1].addr,
Substitute: accounts[2].addr,
},
},
want: strings.ToLower(accounts[1].addr.Hex()),
},
}

for i, tc := range testSuite {
result, err := api.Call(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, tc.config)
if tc.expectErr != nil {
Expand Down

0 comments on commit e3f3129

Please sign in to comment.