mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
parent
9cad0a0cc0
commit
0ceeb24fb3
2 changed files with 130 additions and 1 deletions
|
|
@ -671,7 +671,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
|
||||||
owner := common.Address{}
|
owner := common.Address{}
|
||||||
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()), owner)
|
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()), owner)
|
||||||
if err != nil {
|
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
|
// Depending on the tracer type, format and return the output
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -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: ðapi.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: ðapi.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) {
|
func TestTraceTransaction(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
@ -469,3 +572,29 @@ func newAccounts(n int) (accounts Accounts) {
|
||||||
sort.Sort(accounts)
|
sort.Sort(accounts)
|
||||||
return 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
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue