Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
owner := common.Address{}
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()), owner)
if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err)
return nil, fmt.Errorf("tracing failed: %w", err)
}

// Depending on the tracer type, format and return the output
Expand Down
129 changes: 129 additions & 0 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"
"context"
"crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"math/big"
Expand Down Expand Up @@ -305,6 +306,108 @@ func TestTraceCall(t *testing.T) {
}
}

func TestOverridenTraceCall(t *testing.T) {
t.Parallel()

// Initialize test accounts
accounts := newAccounts(3)
genesis := &core.Genesis{
Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
},
}
genBlocks := 10
signer := types.HomesteadSigner{}
api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, big.NewInt(0), nil), signer, accounts[0].key)
b.AddTx(tx)
}))
randomAccounts, tracer := newAccounts(3), "callTracer"

var testSuite = []struct {
blockNumber rpc.BlockNumber
call ethapi.TransactionArgs
config *TraceCallConfig
expectErr error
expect *callTrace
}{
// Succcessful call with state overriding
{
blockNumber: rpc.LatestBlockNumber,
call: ethapi.TransactionArgs{
From: &randomAccounts[0].addr,
To: &randomAccounts[1].addr,
Value: (*hexutil.Big)(big.NewInt(1000)),
},
config: &TraceCallConfig{
TraceConfig: TraceConfig{Tracer: &tracer},
StateOverrides: &ethapi.StateOverride{
randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(big.NewInt(9000000000000000000))},
},
},
expectErr: nil,
expect: &callTrace{
Type: "CALL",
From: randomAccounts[0].addr,
To: randomAccounts[1].addr,
Gas: newRPCUint64(24979000),
GasUsed: newRPCUint64(0),
Value: (*hexutil.Big)(big.NewInt(1000)),
},
},
// Invalid call without state overriding
{
blockNumber: rpc.LatestBlockNumber,
call: ethapi.TransactionArgs{
From: &randomAccounts[0].addr,
To: &randomAccounts[1].addr,
Value: (*hexutil.Big)(big.NewInt(1000)),
},
config: &TraceCallConfig{
TraceConfig: TraceConfig{Tracer: &tracer},
StateOverrides: &ethapi.StateOverride{
randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(big.NewInt(1250000000000000000))},
},
},
expectErr: core.ErrInsufficientFunds,
expect: nil,
},
}
for _, testspec := range testSuite {
result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
if testspec.expectErr != nil {
if err == nil {
t.Errorf("Expect error %v, get nothing", testspec.expectErr)
continue
}
if !errors.Is(err, testspec.expectErr) {
t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
}
} else {
if err != nil {
t.Errorf("Expect no error, get %v", err)
continue
}
ret := new(callTrace)
if err := json.Unmarshal(result.(json.RawMessage), ret); err != nil {
t.Fatalf("failed to unmarshal trace result: %v", err)
}
if !jsonEqual(ret, testspec.expect) {
// uncomment this for easier debugging
//have, _ := json.MarshalIndent(ret, "", " ")
//want, _ := json.MarshalIndent(testspec.expect, "", " ")
//t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, testspec.expect)
}
}
}
}

func TestTraceTransaction(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -469,3 +572,29 @@ func newAccounts(n int) (accounts Accounts) {
sort.Sort(accounts)
return accounts
}

func newRPCBalance(balance *big.Int) **hexutil.Big {
rpcBalance := (*hexutil.Big)(balance)
return &rpcBalance
}

func newRPCUint64(number uint64) *hexutil.Uint64 {
rpcUint64 := hexutil.Uint64(number)
return &rpcUint64
}

func newRPCBytes(bytes []byte) *hexutil.Bytes {
rpcBytes := hexutil.Bytes(bytes)
return &rpcBytes
}

func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.Hash {
if len(keys) != len(vals) {
panic("invalid input")
}
m := make(map[common.Hash]common.Hash)
for i := 0; i < len(keys); i++ {
m[keys[i]] = vals[i]
}
return &m
}