mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
add tracing apis to gethclient
This commit is contained in:
parent
b85c183ea7
commit
62f178bc85
2 changed files with 395 additions and 9 deletions
|
|
@ -29,6 +29,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -78,6 +80,20 @@ type StorageResult struct {
|
||||||
Proof []string `json:"proof"`
|
Proof []string `json:"proof"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TxTraceResult is the result of a single transaction trace.
|
||||||
|
type TxTraceResult struct {
|
||||||
|
TxHash common.Hash `json:"txHash"` // transaction hash
|
||||||
|
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
|
||||||
|
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockTraceResult is the result of TraceChain
|
||||||
|
type BlockTraceResult struct {
|
||||||
|
Block hexutil.Uint64 `json:"block"` // Block number corresponding to this trace
|
||||||
|
Hash common.Hash `json:"hash"` // Block hash corresponding to this trace
|
||||||
|
Traces []interface{} `json:"traces"` // Trace results produced by the task
|
||||||
|
}
|
||||||
|
|
||||||
// GetProof returns the account and storage values of the specified account including the Merkle-proof.
|
// GetProof returns the account and storage values of the specified account including the Merkle-proof.
|
||||||
// The block number can be nil, in which case the value is taken from the latest known block.
|
// The block number can be nil, in which case the value is taken from the latest known block.
|
||||||
func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []string, blockNumber *big.Int) (*AccountResult, error) {
|
func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []string, blockNumber *big.Int) (*AccountResult, error) {
|
||||||
|
|
@ -204,6 +220,46 @@ func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- co
|
||||||
return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions")
|
return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TraceCall lets you trace a given eth_call
|
||||||
|
func (ec *Client) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *tracers.TraceCallConfig) (interface{}, error) {
|
||||||
|
var result interface{}
|
||||||
|
err := ec.c.CallContext(ctx, &result, "debug_traceCall", args, blockNrOrHash, config)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceTransaction returns the structured logs created during the execution of EVM
|
||||||
|
func (ec *Client) TraceTransaction(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) (interface{}, error) {
|
||||||
|
var result interface{}
|
||||||
|
err := ec.c.CallContext(ctx, &result, "debug_traceTransaction", hash, config)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceChain TraceChaiin subscribes to chain, receiving results from channel BlockTraceResult
|
||||||
|
func (ec *Client) TraceChain(ctx context.Context, ch chan<- BlockTraceResult, start, end rpc.BlockNumber, config *tracers.TraceConfig) (*rpc.ClientSubscription, error) {
|
||||||
|
return ec.c.Subscribe(ctx, "debug", ch, "traceChain", start, end, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceBlock returns the structured logs created during the execution of EVM
|
||||||
|
func (ec *Client) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *tracers.TraceConfig) ([]*TxTraceResult, error) {
|
||||||
|
var result []*TxTraceResult
|
||||||
|
err := ec.c.CallContext(ctx, &result, "debug_traceBlock", blob, config)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceBlockByNumber returns the structured logs created during the execution of EVM
|
||||||
|
func (ec *Client) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *tracers.TraceConfig) ([]*TxTraceResult, error) {
|
||||||
|
var result []*TxTraceResult
|
||||||
|
err := ec.c.CallContext(ctx, &result, "debug_traceBlockByNumber", number, config)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceBlockByHash returns the structured logs created during the execution of EVM
|
||||||
|
func (ec *Client) TraceBlockByHash(ctx context.Context, hash common.Hash, config *tracers.TraceConfig) ([]*TxTraceResult, error) {
|
||||||
|
var result []*TxTraceResult
|
||||||
|
err := ec.c.CallContext(ctx, &result, "debug_traceBlockByHash", hash, config)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
func toBlockNumArg(number *big.Int) string {
|
func toBlockNumArg(number *big.Int) string {
|
||||||
if number == nil {
|
if number == nil {
|
||||||
return "latest"
|
return "latest"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
|
|
@ -31,7 +38,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -39,11 +45,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
testSlot = common.HexToHash("0xdeadbeef")
|
testSlot = common.HexToHash("0xdeadbeef")
|
||||||
testValue = crypto.Keccak256Hash(testSlot[:])
|
testValue = crypto.Keccak256Hash(testSlot[:])
|
||||||
testBalance = big.NewInt(2e15)
|
testBalance = big.NewInt(2e15)
|
||||||
|
testBlocks []*types.Block
|
||||||
|
testTransactionHash common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
|
func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
|
||||||
|
|
@ -64,6 +72,9 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
|
||||||
n.RegisterAPIs([]rpc.API{{
|
n.RegisterAPIs([]rpc.API{{
|
||||||
Namespace: "eth",
|
Namespace: "eth",
|
||||||
Service: filters.NewFilterAPI(filterSystem, false),
|
Service: filters.NewFilterAPI(filterSystem, false),
|
||||||
|
}, {
|
||||||
|
Namespace: "debug",
|
||||||
|
Service: tracers.NewAPI(ethservice.APIBackend),
|
||||||
}})
|
}})
|
||||||
|
|
||||||
// Import the test chain.
|
// Import the test chain.
|
||||||
|
|
@ -83,12 +94,26 @@ func generateTestChain() (*core.Genesis, []*types.Block) {
|
||||||
ExtraData: []byte("test genesis"),
|
ExtraData: []byte("test genesis"),
|
||||||
Timestamp: 9000,
|
Timestamp: 9000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
generate := func(i int, g *core.BlockGen) {
|
generate := func(i int, g *core.BlockGen) {
|
||||||
g.OffsetTime(5)
|
g.OffsetTime(5)
|
||||||
g.SetExtra([]byte("test"))
|
g.SetExtra([]byte("test"))
|
||||||
|
|
||||||
|
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||||
|
Nonce: 0,
|
||||||
|
To: &testAddr,
|
||||||
|
Value: big.NewInt(1000),
|
||||||
|
Gas: params.TxGas,
|
||||||
|
GasPrice: g.BaseFee(),
|
||||||
|
Data: nil,
|
||||||
|
}), signer, testKey)
|
||||||
|
g.AddTx(tx)
|
||||||
|
testTransactionHash = tx.Hash()
|
||||||
}
|
}
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 1, generate)
|
_, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 1, generate)
|
||||||
blocks = append([]*types.Block{genesis.ToBlock()}, blocks...)
|
blocks = append([]*types.Block{genesis.ToBlock()}, blocks...)
|
||||||
|
testBlocks = blocks
|
||||||
return genesis, blocks
|
return genesis, blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,6 +154,24 @@ func TestGethClient(t *testing.T) {
|
||||||
}, {
|
}, {
|
||||||
"TestCallContractWithBlockOverrides",
|
"TestCallContractWithBlockOverrides",
|
||||||
func(t *testing.T) { testCallContractWithBlockOverrides(t, client) },
|
func(t *testing.T) { testCallContractWithBlockOverrides(t, client) },
|
||||||
|
}, {
|
||||||
|
"TestTraceTransaction",
|
||||||
|
func(t *testing.T) { testTraceTransaction(t, client) },
|
||||||
|
}, {
|
||||||
|
"TestTraceCall",
|
||||||
|
func(t *testing.T) { testTraceCall(t, client) },
|
||||||
|
}, {
|
||||||
|
"TestTraceChain",
|
||||||
|
func(t *testing.T) { testTraceChain(t, client) },
|
||||||
|
}, {
|
||||||
|
"TestTraceBlock",
|
||||||
|
func(t *testing.T) { testTraceBlock(t, client) },
|
||||||
|
}, {
|
||||||
|
"TestTraceBlockByNumber",
|
||||||
|
func(t *testing.T) { testTraceBlockByNumber(t, client) },
|
||||||
|
}, {
|
||||||
|
"TestTraceBlockByHash",
|
||||||
|
func(t *testing.T) { testTraceBlockByHash(t, client) },
|
||||||
},
|
},
|
||||||
// The testaccesslist is a bit time-sensitive: the newTestBackend imports
|
// The testaccesslist is a bit time-sensitive: the newTestBackend imports
|
||||||
// one block. The `testAcessList` fails if the miner has not yet created a
|
// one block. The `testAcessList` fails if the miner has not yet created a
|
||||||
|
|
@ -154,7 +197,7 @@ func testAccessList(t *testing.T, client *rpc.Client) {
|
||||||
From: testAddr,
|
From: testAddr,
|
||||||
To: &common.Address{},
|
To: &common.Address{},
|
||||||
Gas: 21000,
|
Gas: 21000,
|
||||||
GasPrice: big.NewInt(765625000),
|
GasPrice: big.NewInt(766599825),
|
||||||
Value: big.NewInt(1),
|
Value: big.NewInt(1),
|
||||||
}
|
}
|
||||||
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
|
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
|
||||||
|
|
@ -317,7 +360,7 @@ func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
// Create transaction
|
// Create transaction
|
||||||
tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
|
tx := types.NewTransaction(1, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
|
||||||
signer := types.LatestSignerForChainID(chainID)
|
signer := types.LatestSignerForChainID(chainID)
|
||||||
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
|
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -351,7 +394,7 @@ func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
// Create transaction
|
// Create transaction
|
||||||
tx := types.NewTransaction(1, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
|
tx := types.NewTransaction(2, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
|
||||||
signer := types.LatestSignerForChainID(chainID)
|
signer := types.LatestSignerForChainID(chainID)
|
||||||
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
|
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -518,3 +561,290 @@ func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) {
|
||||||
t.Fatalf("unexpected result: %x", res)
|
t.Fatalf("unexpected result: %x", res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testTraceTransaction(t *testing.T, client *rpc.Client) {
|
||||||
|
ec := New(client)
|
||||||
|
|
||||||
|
var testSuite = []struct {
|
||||||
|
txHash common.Hash
|
||||||
|
config *tracers.TraceConfig
|
||||||
|
expectErr error
|
||||||
|
expect interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
txHash: testTransactionHash,
|
||||||
|
config: nil,
|
||||||
|
expectErr: nil,
|
||||||
|
expect: map[string]interface{}{
|
||||||
|
"gas": 21000,
|
||||||
|
"failed": false,
|
||||||
|
"returnValue": "",
|
||||||
|
"structLogs": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
txHash: testTransactionHash,
|
||||||
|
config: &tracers.TraceConfig{
|
||||||
|
Config: &logger.Config{
|
||||||
|
EnableMemory: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: nil,
|
||||||
|
expect: map[string]interface{}{
|
||||||
|
"gas": 21000,
|
||||||
|
"failed": false,
|
||||||
|
"returnValue": "",
|
||||||
|
"structLogs": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, testspec := range testSuite {
|
||||||
|
result, err := ec.TraceTransaction(context.Background(), testspec.txHash, testspec.config)
|
||||||
|
if testspec.expectErr != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||||
|
t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d: expect no error, got %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if reflect.DeepEqual(testspec, result) {
|
||||||
|
t.Errorf("test %d: result mismatch, want %v, get %v", i, testspec.expect, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTraceCall(t *testing.T, client *rpc.Client) {
|
||||||
|
ec := New(client)
|
||||||
|
|
||||||
|
var testSuite = []struct {
|
||||||
|
blockNumber rpc.BlockNumber
|
||||||
|
call ethapi.TransactionArgs
|
||||||
|
config *tracers.TraceCallConfig
|
||||||
|
expectErr error
|
||||||
|
expect interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
call: ethapi.TransactionArgs{
|
||||||
|
From: &testAddr,
|
||||||
|
To: &testAddr,
|
||||||
|
},
|
||||||
|
config: nil,
|
||||||
|
expectErr: nil,
|
||||||
|
expect: map[string]interface{}{
|
||||||
|
"gas": 21000,
|
||||||
|
"failed": false,
|
||||||
|
"returnValue": "",
|
||||||
|
"structLogs": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// with config
|
||||||
|
{
|
||||||
|
call: ethapi.TransactionArgs{
|
||||||
|
From: &testAddr,
|
||||||
|
To: &testAddr,
|
||||||
|
},
|
||||||
|
config: &tracers.TraceCallConfig{
|
||||||
|
TraceConfig: tracers.TraceConfig{
|
||||||
|
Config: &logger.Config{
|
||||||
|
EnableMemory: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: nil,
|
||||||
|
expect: map[string]interface{}{
|
||||||
|
"gas": 21000,
|
||||||
|
"failed": false,
|
||||||
|
"returnValue": "",
|
||||||
|
"structLogs": nil,
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
for i, testspec := range testSuite {
|
||||||
|
result, err := ec.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
|
||||||
|
if testspec.expectErr != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||||
|
t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d: expect no error, got %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if reflect.DeepEqual(testspec, result) {
|
||||||
|
t.Errorf("test %d: result mismatch, want %v, get %v", i, testspec.expect, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTraceChain(t *testing.T, client *rpc.Client) {
|
||||||
|
ec := New(client)
|
||||||
|
|
||||||
|
ch := make(chan BlockTraceResult)
|
||||||
|
_, err := ec.TraceChain(context.Background(), ch, 0, 1, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("testTraceChain error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
traceBlock := <-ch
|
||||||
|
traceTxHash := common.HexToHash(traceBlock.Traces[0].(map[string]interface{})["txHash"].(string))
|
||||||
|
if traceTxHash != testTransactionHash {
|
||||||
|
t.Errorf("result mismatch, want %v, get %v", testTransactionHash, traceTxHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTraceBlock(t *testing.T, client *rpc.Client) {
|
||||||
|
ec := New(client)
|
||||||
|
|
||||||
|
block := testBlocks[1]
|
||||||
|
b, err := rlp.EncodeToBytes(block)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("")
|
||||||
|
}
|
||||||
|
var testSuite = []struct {
|
||||||
|
blob hexutil.Bytes
|
||||||
|
config *tracers.TraceConfig
|
||||||
|
expectErr error
|
||||||
|
expect []*TxTraceResult
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
blob: b,
|
||||||
|
config: nil,
|
||||||
|
expectErr: nil,
|
||||||
|
expect: []*TxTraceResult{{TxHash: testTransactionHash}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blob: b,
|
||||||
|
config: nil,
|
||||||
|
expectErr: nil,
|
||||||
|
expect: []*TxTraceResult{{TxHash: testTransactionHash}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, testspec := range testSuite {
|
||||||
|
result, err := ec.TraceBlock(context.Background(), testspec.blob, testspec.config)
|
||||||
|
if testspec.expectErr != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||||
|
t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d: expect no error, got %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if testspec.expect[0].TxHash != result[0].TxHash {
|
||||||
|
t.Errorf("test %d: result mismatch, want %v, get %v", i, testspec.expect[0].TxHash, testspec.expect[0].TxHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTraceBlockByNumber(t *testing.T, client *rpc.Client) {
|
||||||
|
ec := New(client)
|
||||||
|
|
||||||
|
var testSuite = []struct {
|
||||||
|
blockNumber rpc.BlockNumber
|
||||||
|
config *tracers.TraceConfig
|
||||||
|
expectErr error
|
||||||
|
expect []*TxTraceResult
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
blockNumber: 1,
|
||||||
|
config: nil,
|
||||||
|
expectErr: nil,
|
||||||
|
expect: []*TxTraceResult{{TxHash: testTransactionHash}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blockNumber: 1,
|
||||||
|
config: &tracers.TraceConfig{
|
||||||
|
Config: &logger.Config{
|
||||||
|
EnableMemory: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: nil,
|
||||||
|
expect: []*TxTraceResult{{TxHash: testTransactionHash}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, testspec := range testSuite {
|
||||||
|
result, err := ec.TraceBlockByNumber(context.Background(), testspec.blockNumber, testspec.config)
|
||||||
|
if testspec.expectErr != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||||
|
t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d: expect no error, got %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if testspec.expect[0].TxHash != result[0].TxHash {
|
||||||
|
t.Errorf("test %d: result mismatch, want %v, get %v", i, testspec.expect[0].TxHash, testspec.expect[0].TxHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTraceBlockByHash(t *testing.T, client *rpc.Client) {
|
||||||
|
ec := New(client)
|
||||||
|
|
||||||
|
var testSuite = []struct {
|
||||||
|
blockNumber rpc.BlockNumber
|
||||||
|
hash common.Hash
|
||||||
|
config *tracers.TraceConfig
|
||||||
|
expectErr error
|
||||||
|
expect []*TxTraceResult
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
hash: testBlocks[1].Hash(),
|
||||||
|
config: nil,
|
||||||
|
expectErr: nil,
|
||||||
|
expect: []*TxTraceResult{{TxHash: testTransactionHash}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hash: testBlocks[1].Hash(),
|
||||||
|
config: &tracers.TraceConfig{
|
||||||
|
Config: &logger.Config{
|
||||||
|
EnableMemory: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectErr: nil,
|
||||||
|
expect: []*TxTraceResult{{TxHash: testTransactionHash}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, testspec := range testSuite {
|
||||||
|
result, err := ec.TraceBlockByHash(context.Background(), testspec.hash, testspec.config)
|
||||||
|
if testspec.expectErr != nil {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||||
|
t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d: expect no error, got %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if testspec.expect[0].TxHash != result[0].TxHash {
|
||||||
|
t.Errorf("test %d: result mismatch, want %v, get %v", i, testspec.expect[0].TxHash, testspec.expect[0].TxHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue