github.com/ethereum/go-ethereum@v1.16.1/eth/tracers/api_test.go (about)

     1  // Copyright 2021 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package tracers
    18  
    19  import (
    20  	"context"
    21  	"crypto/ecdsa"
    22  	"encoding/json"
    23  	"errors"
    24  	"fmt"
    25  	"math/big"
    26  	"os"
    27  	"reflect"
    28  	"slices"
    29  	"sync/atomic"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/ethereum/go-ethereum/common"
    34  	"github.com/ethereum/go-ethereum/common/hexutil"
    35  	"github.com/ethereum/go-ethereum/consensus"
    36  	"github.com/ethereum/go-ethereum/consensus/beacon"
    37  	"github.com/ethereum/go-ethereum/consensus/ethash"
    38  	"github.com/ethereum/go-ethereum/core"
    39  	"github.com/ethereum/go-ethereum/core/rawdb"
    40  	"github.com/ethereum/go-ethereum/core/state"
    41  	"github.com/ethereum/go-ethereum/core/tracing"
    42  	"github.com/ethereum/go-ethereum/core/types"
    43  	"github.com/ethereum/go-ethereum/core/vm"
    44  	"github.com/ethereum/go-ethereum/crypto"
    45  	"github.com/ethereum/go-ethereum/eth/tracers/logger"
    46  	"github.com/ethereum/go-ethereum/ethdb"
    47  	"github.com/ethereum/go-ethereum/internal/ethapi"
    48  	"github.com/ethereum/go-ethereum/internal/ethapi/override"
    49  	"github.com/ethereum/go-ethereum/params"
    50  	"github.com/ethereum/go-ethereum/rpc"
    51  )
    52  
    53  var (
    54  	errStateNotFound = errors.New("state not found")
    55  	errBlockNotFound = errors.New("block not found")
    56  )
    57  
    58  type testBackend struct {
    59  	chainConfig *params.ChainConfig
    60  	engine      consensus.Engine
    61  	chaindb     ethdb.Database
    62  	chain       *core.BlockChain
    63  
    64  	refHook func() // Hook is invoked when the requested state is referenced
    65  	relHook func() // Hook is invoked when the requested state is released
    66  }
    67  
    68  // newTestBackend creates a new test backend. OBS: After test is done, teardown must be
    69  // invoked in order to release associated resources.
    70  func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
    71  	backend := &testBackend{
    72  		chainConfig: gspec.Config,
    73  		engine:      ethash.NewFaker(),
    74  		chaindb:     rawdb.NewMemoryDatabase(),
    75  	}
    76  	// Generate blocks for testing
    77  	_, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
    78  
    79  	// Import the canonical chain
    80  	options := &core.BlockChainConfig{
    81  		TrieCleanLimit: 256,
    82  		TrieDirtyLimit: 256,
    83  		TrieTimeLimit:  5 * time.Minute,
    84  		SnapshotLimit:  0,
    85  		ArchiveMode:    true, // Archive mode
    86  	}
    87  	chain, err := core.NewBlockChain(backend.chaindb, gspec, backend.engine, options)
    88  	if err != nil {
    89  		t.Fatalf("failed to create tester chain: %v", err)
    90  	}
    91  	if n, err := chain.InsertChain(blocks); err != nil {
    92  		t.Fatalf("block %d: failed to insert into chain: %v", n, err)
    93  	}
    94  	backend.chain = chain
    95  	return backend
    96  }
    97  
    98  func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
    99  	return b.chain.GetHeaderByHash(hash), nil
   100  }
   101  
   102  func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
   103  	if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
   104  		return b.chain.CurrentHeader(), nil
   105  	}
   106  	return b.chain.GetHeaderByNumber(uint64(number)), nil
   107  }
   108  
   109  func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   110  	return b.chain.GetBlockByHash(hash), nil
   111  }
   112  
   113  func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   114  	if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
   115  		return b.chain.GetBlockByNumber(b.chain.CurrentBlock().Number.Uint64()), nil
   116  	}
   117  	return b.chain.GetBlockByNumber(uint64(number)), nil
   118  }
   119  
   120  func (b *testBackend) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) {
   121  	tx, hash, blockNumber, index := rawdb.ReadCanonicalTransaction(b.chaindb, txHash)
   122  	return tx != nil, tx, hash, blockNumber, index
   123  }
   124  
   125  func (b *testBackend) TxIndexDone() bool {
   126  	return true
   127  }
   128  
   129  func (b *testBackend) RPCGasCap() uint64 {
   130  	return 25000000
   131  }
   132  
   133  func (b *testBackend) ChainConfig() *params.ChainConfig {
   134  	return b.chainConfig
   135  }
   136  
   137  func (b *testBackend) Engine() consensus.Engine {
   138  	return b.engine
   139  }
   140  
   141  func (b *testBackend) ChainDb() ethdb.Database {
   142  	return b.chaindb
   143  }
   144  
   145  // teardown releases the associated resources.
   146  func (b *testBackend) teardown() {
   147  	b.chain.Stop()
   148  }
   149  
   150  func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) {
   151  	statedb, err := b.chain.StateAt(block.Root())
   152  	if err != nil {
   153  		return nil, nil, errStateNotFound
   154  	}
   155  	if b.refHook != nil {
   156  		b.refHook()
   157  	}
   158  	release := func() {
   159  		if b.relHook != nil {
   160  			b.relHook()
   161  		}
   162  	}
   163  	return statedb, release, nil
   164  }
   165  
   166  func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) {
   167  	parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
   168  	if parent == nil {
   169  		return nil, vm.BlockContext{}, nil, nil, errBlockNotFound
   170  	}
   171  	statedb, release, err := b.StateAtBlock(ctx, parent, reexec, nil, true, false)
   172  	if err != nil {
   173  		return nil, vm.BlockContext{}, nil, nil, errStateNotFound
   174  	}
   175  	if txIndex == 0 && len(block.Transactions()) == 0 {
   176  		return nil, vm.BlockContext{}, statedb, release, nil
   177  	}
   178  	// Recompute transactions up to the target index.
   179  	signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time())
   180  	context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
   181  	evm := vm.NewEVM(context, statedb, b.chainConfig, vm.Config{})
   182  	for idx, tx := range block.Transactions() {
   183  		if idx == txIndex {
   184  			return tx, context, statedb, release, nil
   185  		}
   186  		msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
   187  		if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
   188  			return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
   189  		}
   190  		statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
   191  	}
   192  	return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
   193  }
   194  
   195  type stateTracer struct {
   196  	Balance map[common.Address]*hexutil.Big
   197  	Nonce   map[common.Address]hexutil.Uint64
   198  	Storage map[common.Address]map[common.Hash]common.Hash
   199  }
   200  
   201  func newStateTracer(ctx *Context, cfg json.RawMessage, chainCfg *params.ChainConfig) (*Tracer, error) {
   202  	t := &stateTracer{
   203  		Balance: make(map[common.Address]*hexutil.Big),
   204  		Nonce:   make(map[common.Address]hexutil.Uint64),
   205  		Storage: make(map[common.Address]map[common.Hash]common.Hash),
   206  	}
   207  	return &Tracer{
   208  		GetResult: func() (json.RawMessage, error) {
   209  			return json.Marshal(t)
   210  		},
   211  		Hooks: &tracing.Hooks{
   212  			OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
   213  				t.Balance[addr] = (*hexutil.Big)(new)
   214  			},
   215  			OnNonceChange: func(addr common.Address, prev, new uint64) {
   216  				t.Nonce[addr] = hexutil.Uint64(new)
   217  			},
   218  			OnStorageChange: func(addr common.Address, slot common.Hash, prev, new common.Hash) {
   219  				if t.Storage[addr] == nil {
   220  					t.Storage[addr] = make(map[common.Hash]common.Hash)
   221  				}
   222  				t.Storage[addr][slot] = new
   223  			},
   224  		},
   225  	}, nil
   226  }
   227  
   228  func TestStateHooks(t *testing.T) {
   229  	t.Parallel()
   230  
   231  	// Initialize test accounts
   232  	var (
   233  		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   234  		from    = crypto.PubkeyToAddress(key.PublicKey)
   235  		to      = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
   236  		genesis = &core.Genesis{
   237  			Config: params.TestChainConfig,
   238  			Alloc: types.GenesisAlloc{
   239  				from: {Balance: big.NewInt(params.Ether)},
   240  				to: {
   241  					Code: []byte{
   242  						byte(vm.PUSH1), 0x2a, // stack: [42]
   243  						byte(vm.PUSH1), 0x0, // stack: [0, 42]
   244  						byte(vm.SSTORE), // stack: []
   245  						byte(vm.STOP),
   246  					},
   247  				},
   248  			},
   249  		}
   250  		genBlocks = 2
   251  		signer    = types.HomesteadSigner{}
   252  		nonce     = uint64(0)
   253  		backend   = newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
   254  			// Transfer from account[0] to account[1]
   255  			//    value: 1000 wei
   256  			//    fee:   0 wei
   257  			tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   258  				Nonce:    nonce,
   259  				To:       &to,
   260  				Value:    big.NewInt(1000),
   261  				Gas:      params.TxGas,
   262  				GasPrice: b.BaseFee(),
   263  				Data:     nil}),
   264  				signer, key)
   265  			b.AddTx(tx)
   266  			nonce++
   267  		})
   268  	)
   269  	defer backend.teardown()
   270  	DefaultDirectory.Register("stateTracer", newStateTracer, false)
   271  	api := NewAPI(backend)
   272  	tracer := "stateTracer"
   273  	res, err := api.TraceCall(context.Background(), ethapi.TransactionArgs{From: &from, To: &to, Value: (*hexutil.Big)(big.NewInt(1000))}, rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber), &TraceCallConfig{TraceConfig: TraceConfig{Tracer: &tracer}})
   274  	if err != nil {
   275  		t.Fatalf("failed to trace call: %v", err)
   276  	}
   277  	expected := `{"Balance":{"0x00000000000000000000000000000000deadbeef":"0x3e8","0x71562b71999873db5b286df957af199ec94617f7":"0xde0975924ed6f90"},"Nonce":{"0x71562b71999873db5b286df957af199ec94617f7":"0x3"},"Storage":{"0x00000000000000000000000000000000deadbeef":{"0x0000000000000000000000000000000000000000000000000000000000000000":"0x000000000000000000000000000000000000000000000000000000000000002a"}}}`
   278  	if expected != fmt.Sprintf("%s", res) {
   279  		t.Fatalf("unexpected trace result: have %s want %s", res, expected)
   280  	}
   281  }
   282  
   283  func TestTraceCall(t *testing.T) {
   284  	t.Parallel()
   285  
   286  	// Initialize test accounts
   287  	accounts := newAccounts(3)
   288  	genesis := &core.Genesis{
   289  		Config: params.TestChainConfig,
   290  		Alloc: types.GenesisAlloc{
   291  			accounts[0].addr: {Balance: big.NewInt(params.Ether)},
   292  			accounts[1].addr: {Balance: big.NewInt(params.Ether)},
   293  			accounts[2].addr: {Balance: big.NewInt(params.Ether)},
   294  		},
   295  	}
   296  	genBlocks := 10
   297  	signer := types.HomesteadSigner{}
   298  	nonce := uint64(0)
   299  	backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
   300  		// Transfer from account[0] to account[1]
   301  		//    value: 1000 wei
   302  		//    fee:   0 wei
   303  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   304  			Nonce:    nonce,
   305  			To:       &accounts[1].addr,
   306  			Value:    big.NewInt(1000),
   307  			Gas:      params.TxGas,
   308  			GasPrice: b.BaseFee(),
   309  			Data:     nil}),
   310  			signer, accounts[0].key)
   311  		b.AddTx(tx)
   312  		nonce++
   313  
   314  		if i == genBlocks-2 {
   315  			// Transfer from account[0] to account[2]
   316  			tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
   317  				Nonce:    nonce,
   318  				To:       &accounts[2].addr,
   319  				Value:    big.NewInt(1000),
   320  				Gas:      params.TxGas,
   321  				GasPrice: b.BaseFee(),
   322  				Data:     nil}),
   323  				signer, accounts[0].key)
   324  			b.AddTx(tx)
   325  			nonce++
   326  
   327  			// Transfer from account[0] to account[1] again
   328  			tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
   329  				Nonce:    nonce,
   330  				To:       &accounts[1].addr,
   331  				Value:    big.NewInt(1000),
   332  				Gas:      params.TxGas,
   333  				GasPrice: b.BaseFee(),
   334  				Data:     nil}),
   335  				signer, accounts[0].key)
   336  			b.AddTx(tx)
   337  			nonce++
   338  		}
   339  	})
   340  
   341  	uintPtr := func(i int) *hexutil.Uint { x := hexutil.Uint(i); return &x }
   342  
   343  	defer backend.teardown()
   344  	api := NewAPI(backend)
   345  	var testSuite = []struct {
   346  		blockNumber rpc.BlockNumber
   347  		call        ethapi.TransactionArgs
   348  		config      *TraceCallConfig
   349  		expectErr   error
   350  		expect      string
   351  	}{
   352  		// Standard JSON trace upon the genesis, plain transfer.
   353  		{
   354  			blockNumber: rpc.BlockNumber(0),
   355  			call: ethapi.TransactionArgs{
   356  				From:  &accounts[0].addr,
   357  				To:    &accounts[1].addr,
   358  				Value: (*hexutil.Big)(big.NewInt(1000)),
   359  			},
   360  			config:    nil,
   361  			expectErr: nil,
   362  			expect:    `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
   363  		},
   364  		// Standard JSON trace upon the head, plain transfer.
   365  		{
   366  			blockNumber: rpc.BlockNumber(genBlocks),
   367  			call: ethapi.TransactionArgs{
   368  				From:  &accounts[0].addr,
   369  				To:    &accounts[1].addr,
   370  				Value: (*hexutil.Big)(big.NewInt(1000)),
   371  			},
   372  			config:    nil,
   373  			expectErr: nil,
   374  			expect:    `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
   375  		},
   376  		// Upon the last state, default to the post block's state
   377  		{
   378  			blockNumber: rpc.BlockNumber(genBlocks - 1),
   379  			call: ethapi.TransactionArgs{
   380  				From:  &accounts[2].addr,
   381  				To:    &accounts[0].addr,
   382  				Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
   383  			},
   384  			config: nil,
   385  			expect: `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
   386  		},
   387  		// Before the first transaction, should be failed
   388  		{
   389  			blockNumber: rpc.BlockNumber(genBlocks - 1),
   390  			call: ethapi.TransactionArgs{
   391  				From:  &accounts[2].addr,
   392  				To:    &accounts[0].addr,
   393  				Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
   394  			},
   395  			config:    &TraceCallConfig{TxIndex: uintPtr(0)},
   396  			expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
   397  		},
   398  		// Before the target transaction, should be failed
   399  		{
   400  			blockNumber: rpc.BlockNumber(genBlocks - 1),
   401  			call: ethapi.TransactionArgs{
   402  				From:  &accounts[2].addr,
   403  				To:    &accounts[0].addr,
   404  				Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
   405  			},
   406  			config:    &TraceCallConfig{TxIndex: uintPtr(1)},
   407  			expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
   408  		},
   409  		// After the target transaction, should be succeeded
   410  		{
   411  			blockNumber: rpc.BlockNumber(genBlocks - 1),
   412  			call: ethapi.TransactionArgs{
   413  				From:  &accounts[2].addr,
   414  				To:    &accounts[0].addr,
   415  				Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
   416  			},
   417  			config:    &TraceCallConfig{TxIndex: uintPtr(2)},
   418  			expectErr: nil,
   419  			expect:    `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
   420  		},
   421  		// Standard JSON trace upon the non-existent block, error expects
   422  		{
   423  			blockNumber: rpc.BlockNumber(genBlocks + 1),
   424  			call: ethapi.TransactionArgs{
   425  				From:  &accounts[0].addr,
   426  				To:    &accounts[1].addr,
   427  				Value: (*hexutil.Big)(big.NewInt(1000)),
   428  			},
   429  			config:    nil,
   430  			expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
   431  			//expect:    nil,
   432  		},
   433  		// Standard JSON trace upon the latest block
   434  		{
   435  			blockNumber: rpc.LatestBlockNumber,
   436  			call: ethapi.TransactionArgs{
   437  				From:  &accounts[0].addr,
   438  				To:    &accounts[1].addr,
   439  				Value: (*hexutil.Big)(big.NewInt(1000)),
   440  			},
   441  			config:    nil,
   442  			expectErr: nil,
   443  			expect:    `{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}`,
   444  		},
   445  		// Tracing on 'pending' should fail:
   446  		{
   447  			blockNumber: rpc.PendingBlockNumber,
   448  			call: ethapi.TransactionArgs{
   449  				From:  &accounts[0].addr,
   450  				To:    &accounts[1].addr,
   451  				Value: (*hexutil.Big)(big.NewInt(1000)),
   452  			},
   453  			config:    nil,
   454  			expectErr: errors.New("tracing on top of pending is not supported"),
   455  		},
   456  		{
   457  			blockNumber: rpc.LatestBlockNumber,
   458  			call: ethapi.TransactionArgs{
   459  				From:  &accounts[0].addr,
   460  				Input: &hexutil.Bytes{0x43}, // blocknumber
   461  			},
   462  			config: &TraceCallConfig{
   463  				BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
   464  			},
   465  			expectErr: nil,
   466  			expect: ` {"gas":53018,"failed":false,"returnValue":"0x","structLogs":[
   467  		{"pc":0,"op":"NUMBER","gas":24946984,"gasCost":2,"depth":1,"stack":[]},
   468  		{"pc":1,"op":"STOP","gas":24946982,"gasCost":0,"depth":1,"stack":["0x1337"]}]}`,
   469  		},
   470  	}
   471  	for i, testspec := range testSuite {
   472  		result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
   473  		if testspec.expectErr != nil {
   474  			if err == nil {
   475  				t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
   476  				continue
   477  			}
   478  			if !reflect.DeepEqual(err.Error(), testspec.expectErr.Error()) {
   479  				t.Errorf("test %d: error mismatch, want '%v', got '%v'", i, testspec.expectErr, err)
   480  			}
   481  		} else {
   482  			if err != nil {
   483  				t.Errorf("test %d: expect no error, got %v", i, err)
   484  				continue
   485  			}
   486  			var have *logger.ExecutionResult
   487  			if err := json.Unmarshal(result.(json.RawMessage), &have); err != nil {
   488  				t.Errorf("test %d: failed to unmarshal result %v", i, err)
   489  			}
   490  			var want *logger.ExecutionResult
   491  			if err := json.Unmarshal([]byte(testspec.expect), &want); err != nil {
   492  				t.Errorf("test %d: failed to unmarshal result %v", i, err)
   493  			}
   494  			if !reflect.DeepEqual(have, want) {
   495  				t.Errorf("test %d: result mismatch, want %v, got %v", i, testspec.expect, string(result.(json.RawMessage)))
   496  			}
   497  		}
   498  	}
   499  }
   500  
   501  func TestTraceTransaction(t *testing.T) {
   502  	t.Parallel()
   503  
   504  	// Initialize test accounts
   505  	accounts := newAccounts(2)
   506  	genesis := &core.Genesis{
   507  		Config: params.TestChainConfig,
   508  		Alloc: types.GenesisAlloc{
   509  			accounts[0].addr: {Balance: big.NewInt(params.Ether)},
   510  			accounts[1].addr: {Balance: big.NewInt(params.Ether)},
   511  		},
   512  	}
   513  	target := common.Hash{}
   514  	signer := types.HomesteadSigner{}
   515  	backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) {
   516  		// Transfer from account[0] to account[1]
   517  		//    value: 1000 wei
   518  		//    fee:   0 wei
   519  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   520  			Nonce:    uint64(i),
   521  			To:       &accounts[1].addr,
   522  			Value:    big.NewInt(1000),
   523  			Gas:      params.TxGas,
   524  			GasPrice: b.BaseFee(),
   525  			Data:     nil}),
   526  			signer, accounts[0].key)
   527  		b.AddTx(tx)
   528  		target = tx.Hash()
   529  	})
   530  	defer backend.chain.Stop()
   531  	api := NewAPI(backend)
   532  	result, err := api.TraceTransaction(context.Background(), target, nil)
   533  	if err != nil {
   534  		t.Errorf("Failed to trace transaction %v", err)
   535  	}
   536  	var have *logger.ExecutionResult
   537  	if err := json.Unmarshal(result.(json.RawMessage), &have); err != nil {
   538  		t.Errorf("failed to unmarshal result %v", err)
   539  	}
   540  	if !reflect.DeepEqual(have, &logger.ExecutionResult{
   541  		Gas:         params.TxGas,
   542  		Failed:      false,
   543  		ReturnValue: []byte{},
   544  		StructLogs:  []json.RawMessage{},
   545  	}) {
   546  		t.Error("Transaction tracing result is different")
   547  	}
   548  
   549  	// Test non-existent transaction
   550  	_, err = api.TraceTransaction(context.Background(), common.Hash{42}, nil)
   551  	if !errors.Is(err, errTxNotFound) {
   552  		t.Fatalf("want %v, have %v", errTxNotFound, err)
   553  	}
   554  }
   555  
   556  func TestTraceBlock(t *testing.T) {
   557  	t.Parallel()
   558  
   559  	// Initialize test accounts
   560  	accounts := newAccounts(3)
   561  	genesis := &core.Genesis{
   562  		Config: params.TestChainConfig,
   563  		Alloc: types.GenesisAlloc{
   564  			accounts[0].addr: {Balance: big.NewInt(params.Ether)},
   565  			accounts[1].addr: {Balance: big.NewInt(params.Ether)},
   566  			accounts[2].addr: {Balance: big.NewInt(params.Ether)},
   567  		},
   568  	}
   569  	genBlocks := 10
   570  	signer := types.HomesteadSigner{}
   571  	var txHash common.Hash
   572  	backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
   573  		// Transfer from account[0] to account[1]
   574  		//    value: 1000 wei
   575  		//    fee:   0 wei
   576  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   577  			Nonce:    uint64(i),
   578  			To:       &accounts[1].addr,
   579  			Value:    big.NewInt(1000),
   580  			Gas:      params.TxGas,
   581  			GasPrice: b.BaseFee(),
   582  			Data:     nil}),
   583  			signer, accounts[0].key)
   584  		b.AddTx(tx)
   585  		txHash = tx.Hash()
   586  	})
   587  	defer backend.chain.Stop()
   588  	api := NewAPI(backend)
   589  
   590  	var testSuite = []struct {
   591  		blockNumber rpc.BlockNumber
   592  		config      *TraceConfig
   593  		want        string
   594  		expectErr   error
   595  	}{
   596  		// Trace genesis block, expect error
   597  		{
   598  			blockNumber: rpc.BlockNumber(0),
   599  			expectErr:   errors.New("genesis is not traceable"),
   600  		},
   601  		// Trace head block
   602  		{
   603  			blockNumber: rpc.BlockNumber(genBlocks),
   604  			want:        fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, txHash),
   605  		},
   606  		// Trace non-existent block
   607  		{
   608  			blockNumber: rpc.BlockNumber(genBlocks + 1),
   609  			expectErr:   fmt.Errorf("block #%d not found", genBlocks+1),
   610  		},
   611  		// Trace latest block
   612  		{
   613  			blockNumber: rpc.LatestBlockNumber,
   614  			want:        fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, txHash),
   615  		},
   616  		// Trace pending block
   617  		{
   618  			blockNumber: rpc.PendingBlockNumber,
   619  			want:        fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, txHash),
   620  		},
   621  	}
   622  	for i, tc := range testSuite {
   623  		result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
   624  		if tc.expectErr != nil {
   625  			if err == nil {
   626  				t.Errorf("test %d, want error %v", i, tc.expectErr)
   627  				continue
   628  			}
   629  			if !reflect.DeepEqual(err, tc.expectErr) {
   630  				t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err)
   631  			}
   632  			continue
   633  		}
   634  		if err != nil {
   635  			t.Errorf("test %d, want no error, have %v", i, err)
   636  			continue
   637  		}
   638  		have, _ := json.Marshal(result)
   639  		want := tc.want
   640  		if string(have) != want {
   641  			t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want)
   642  		}
   643  	}
   644  }
   645  
   646  func TestTracingWithOverrides(t *testing.T) {
   647  	t.Parallel()
   648  	// Initialize test accounts
   649  	accounts := newAccounts(3)
   650  	ecRecoverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
   651  	storageAccount := common.Address{0x13, 37}
   652  	genesis := &core.Genesis{
   653  		Config: params.TestChainConfig,
   654  		Alloc: types.GenesisAlloc{
   655  			accounts[0].addr: {Balance: big.NewInt(params.Ether)},
   656  			accounts[1].addr: {Balance: big.NewInt(params.Ether)},
   657  			accounts[2].addr: {Balance: big.NewInt(params.Ether)},
   658  			// An account with existing storage
   659  			storageAccount: {
   660  				Balance: new(big.Int),
   661  				Storage: map[common.Hash]common.Hash{
   662  					common.HexToHash("0x03"): common.HexToHash("0x33"),
   663  					common.HexToHash("0x04"): common.HexToHash("0x44"),
   664  				},
   665  			},
   666  		},
   667  	}
   668  	genBlocks := 10
   669  	signer := types.HomesteadSigner{}
   670  	backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
   671  		// Transfer from account[0] to account[1]
   672  		//    value: 1000 wei
   673  		//    fee:   0 wei
   674  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
   675  			Nonce:    uint64(i),
   676  			To:       &accounts[1].addr,
   677  			Value:    big.NewInt(1000),
   678  			Gas:      params.TxGas,
   679  			GasPrice: b.BaseFee(),
   680  			Data:     nil}),
   681  			signer, accounts[0].key)
   682  		b.AddTx(tx)
   683  	})
   684  	defer backend.chain.Stop()
   685  	api := NewAPI(backend)
   686  	randomAccounts := newAccounts(3)
   687  	type res struct {
   688  		Gas         int
   689  		Failed      bool
   690  		ReturnValue string
   691  	}
   692  	var testSuite = []struct {
   693  		blockNumber rpc.BlockNumber
   694  		call        ethapi.TransactionArgs
   695  		config      *TraceCallConfig
   696  		expectErr   error
   697  		want        string
   698  	}{
   699  		// Call which can only succeed if state is state overridden
   700  		{
   701  			blockNumber: rpc.LatestBlockNumber,
   702  			call: ethapi.TransactionArgs{
   703  				From:  &randomAccounts[0].addr,
   704  				To:    &randomAccounts[1].addr,
   705  				Value: (*hexutil.Big)(big.NewInt(1000)),
   706  			},
   707  			config: &TraceCallConfig{
   708  				StateOverrides: &override.StateOverride{
   709  					randomAccounts[0].addr: override.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
   710  				},
   711  			},
   712  			want: `{"gas":21000,"failed":false,"returnValue":"0x"}`,
   713  		},
   714  		// Invalid call without state overriding
   715  		{
   716  			blockNumber: rpc.LatestBlockNumber,
   717  			call: ethapi.TransactionArgs{
   718  				From:  &randomAccounts[0].addr,
   719  				To:    &randomAccounts[1].addr,
   720  				Value: (*hexutil.Big)(big.NewInt(1000)),
   721  			},
   722  			config:    &TraceCallConfig{},
   723  			expectErr: core.ErrInsufficientFunds,
   724  		},
   725  		// Successful simple contract call
   726  		//
   727  		// // SPDX-License-Identifier: GPL-3.0
   728  		//
   729  		//  pragma solidity >=0.7.0 <0.8.0;
   730  		//
   731  		//  /**
   732  		//   * @title Storage
   733  		//   * @dev Store & retrieve value in a variable
   734  		//   */
   735  		//  contract Storage {
   736  		//      uint256 public number;
   737  		//      constructor() {
   738  		//          number = block.number;
   739  		//      }
   740  		//  }
   741  		{
   742  			blockNumber: rpc.LatestBlockNumber,
   743  			call: ethapi.TransactionArgs{
   744  				From: &randomAccounts[0].addr,
   745  				To:   &randomAccounts[2].addr,
   746  				Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
   747  			},
   748  			config: &TraceCallConfig{
   749  				//Tracer: &tracer,
   750  				StateOverrides: &override.StateOverride{
   751  					randomAccounts[2].addr: override.OverrideAccount{
   752  						Code:      newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
   753  						StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
   754  					},
   755  				},
   756  			},
   757  			want: `{"gas":23347,"failed":false,"returnValue":"0x000000000000000000000000000000000000000000000000000000000000007b"}`,
   758  		},
   759  		{ // Override blocknumber
   760  			blockNumber: rpc.LatestBlockNumber,
   761  			call: ethapi.TransactionArgs{
   762  				From: &accounts[0].addr,
   763  				// BLOCKNUMBER PUSH1 MSTORE
   764  				Input: newRPCBytes(common.Hex2Bytes("4360005260206000f3")),
   765  			},
   766  			config: &TraceCallConfig{
   767  				BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
   768  			},
   769  			want: `{"gas":59537,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000001337"}`,
   770  		},
   771  		{ // Override blocknumber, and query a blockhash
   772  			blockNumber: rpc.LatestBlockNumber,
   773  			call: ethapi.TransactionArgs{
   774  				From: &accounts[0].addr,
   775  				Input: &hexutil.Bytes{
   776  					0x60, 0x00, 0x40, // BLOCKHASH(0)
   777  					0x60, 0x00, 0x52, // STORE memory offset 0
   778  					0x61, 0x13, 0x36, 0x40, // BLOCKHASH(0x1336)
   779  					0x60, 0x20, 0x52, // STORE memory offset 32
   780  					0x61, 0x13, 0x37, 0x40, // BLOCKHASH(0x1337)
   781  					0x60, 0x40, 0x52, // STORE memory offset 64
   782  					0x60, 0x60, 0x60, 0x00, 0xf3, // RETURN (0-96)
   783  
   784  				}, // blocknumber
   785  			},
   786  			config: &TraceCallConfig{
   787  				BlockOverrides: &override.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
   788  			},
   789  			want: `{"gas":72666,"failed":false,"returnValue":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
   790  		},
   791  		/*
   792  			pragma solidity =0.8.12;
   793  
   794  			contract Test {
   795  			    uint private x;
   796  
   797  			    function test2() external {
   798  			        x = 1337;
   799  			        revert();
   800  			    }
   801  
   802  			    function test() external returns (uint) {
   803  			        x = 1;
   804  			        try this.test2() {} catch (bytes memory) {}
   805  			        return x;
   806  			    }
   807  			}
   808  		*/
   809  		{ // First with only code override, not storage override
   810  			blockNumber: rpc.LatestBlockNumber,
   811  			call: ethapi.TransactionArgs{
   812  				From: &randomAccounts[0].addr,
   813  				To:   &randomAccounts[2].addr,
   814  				Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
   815  			},
   816  			config: &TraceCallConfig{
   817  				StateOverrides: &override.StateOverride{
   818  					randomAccounts[2].addr: override.OverrideAccount{
   819  						Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060325760003560e01c806366e41cb7146037578063f8a8fd6d14603f575b600080fd5b603d6057565b005b60456062565b60405190815260200160405180910390f35b610539600090815580fd5b60006001600081905550306001600160a01b03166366e41cb76040518163ffffffff1660e01b8152600401600060405180830381600087803b15801560a657600080fd5b505af192505050801560b6575060015b60e9573d80801560e1576040519150601f19603f3d011682016040523d82523d6000602084013e60e6565b606091505b50505b506000549056fea26469706673582212205ce45de745a5308f713cb2f448589177ba5a442d1a2eff945afaa8915961b4d064736f6c634300080c0033")),
   820  					},
   821  				},
   822  			},
   823  			want: `{"gas":44100,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000001"}`,
   824  		},
   825  		{ // Same again, this time with storage override
   826  			blockNumber: rpc.LatestBlockNumber,
   827  			call: ethapi.TransactionArgs{
   828  				From: &randomAccounts[0].addr,
   829  				To:   &randomAccounts[2].addr,
   830  				Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
   831  			},
   832  			config: &TraceCallConfig{
   833  				StateOverrides: &override.StateOverride{
   834  					randomAccounts[2].addr: override.OverrideAccount{
   835  						Code:  newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060325760003560e01c806366e41cb7146037578063f8a8fd6d14603f575b600080fd5b603d6057565b005b60456062565b60405190815260200160405180910390f35b610539600090815580fd5b60006001600081905550306001600160a01b03166366e41cb76040518163ffffffff1660e01b8152600401600060405180830381600087803b15801560a657600080fd5b505af192505050801560b6575060015b60e9573d80801560e1576040519150601f19603f3d011682016040523d82523d6000602084013e60e6565b606091505b50505b506000549056fea26469706673582212205ce45de745a5308f713cb2f448589177ba5a442d1a2eff945afaa8915961b4d064736f6c634300080c0033")),
   836  						State: newStates([]common.Hash{{}}, []common.Hash{{}}),
   837  					},
   838  				},
   839  			},
   840  			//want: `{"gas":46900,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000539"}`,
   841  			want: `{"gas":44100,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000001"}`,
   842  		},
   843  		{ // No state override
   844  			blockNumber: rpc.LatestBlockNumber,
   845  			call: ethapi.TransactionArgs{
   846  				From: &randomAccounts[0].addr,
   847  				To:   &storageAccount,
   848  				Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
   849  			},
   850  			config: &TraceCallConfig{
   851  				StateOverrides: &override.StateOverride{
   852  					storageAccount: override.OverrideAccount{
   853  						Code: newRPCBytes([]byte{
   854  							// SLOAD(3) + SLOAD(4) (which is 0x77)
   855  							byte(vm.PUSH1), 0x04,
   856  							byte(vm.SLOAD),
   857  							byte(vm.PUSH1), 0x03,
   858  							byte(vm.SLOAD),
   859  							byte(vm.ADD),
   860  							// 0x77 -> MSTORE(0)
   861  							byte(vm.PUSH1), 0x00,
   862  							byte(vm.MSTORE),
   863  							// RETURN (0, 32)
   864  							byte(vm.PUSH1), 32,
   865  							byte(vm.PUSH1), 00,
   866  							byte(vm.RETURN),
   867  						}),
   868  					},
   869  				},
   870  			},
   871  			want: `{"gas":25288,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000077"}`,
   872  		},
   873  		{ // Full state override
   874  			// The original storage is
   875  			// 3: 0x33
   876  			// 4: 0x44
   877  			// With a full override, where we set 3:0x11, the slot 4 should be
   878  			// removed. So SLOT(3)+SLOT(4) should be 0x11.
   879  			blockNumber: rpc.LatestBlockNumber,
   880  			call: ethapi.TransactionArgs{
   881  				From: &randomAccounts[0].addr,
   882  				To:   &storageAccount,
   883  				Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
   884  			},
   885  			config: &TraceCallConfig{
   886  				StateOverrides: &override.StateOverride{
   887  					storageAccount: override.OverrideAccount{
   888  						Code: newRPCBytes([]byte{
   889  							// SLOAD(3) + SLOAD(4) (which is now 0x11 + 0x00)
   890  							byte(vm.PUSH1), 0x04,
   891  							byte(vm.SLOAD),
   892  							byte(vm.PUSH1), 0x03,
   893  							byte(vm.SLOAD),
   894  							byte(vm.ADD),
   895  							// 0x11 -> MSTORE(0)
   896  							byte(vm.PUSH1), 0x00,
   897  							byte(vm.MSTORE),
   898  							// RETURN (0, 32)
   899  							byte(vm.PUSH1), 32,
   900  							byte(vm.PUSH1), 00,
   901  							byte(vm.RETURN),
   902  						}),
   903  						State: newStates(
   904  							[]common.Hash{common.HexToHash("0x03")},
   905  							[]common.Hash{common.HexToHash("0x11")}),
   906  					},
   907  				},
   908  			},
   909  			want: `{"gas":25288,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000011"}`,
   910  		},
   911  		{ // Partial state override
   912  			// The original storage is
   913  			// 3: 0x33
   914  			// 4: 0x44
   915  			// With a partial override, where we set 3:0x11, the slot 4 as before.
   916  			// So SLOT(3)+SLOT(4) should be 0x55.
   917  			blockNumber: rpc.LatestBlockNumber,
   918  			call: ethapi.TransactionArgs{
   919  				From: &randomAccounts[0].addr,
   920  				To:   &storageAccount,
   921  				Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), //
   922  			},
   923  			config: &TraceCallConfig{
   924  				StateOverrides: &override.StateOverride{
   925  					storageAccount: override.OverrideAccount{
   926  						Code: newRPCBytes([]byte{
   927  							// SLOAD(3) + SLOAD(4) (which is now 0x11 + 0x44)
   928  							byte(vm.PUSH1), 0x04,
   929  							byte(vm.SLOAD),
   930  							byte(vm.PUSH1), 0x03,
   931  							byte(vm.SLOAD),
   932  							byte(vm.ADD),
   933  							// 0x55 -> MSTORE(0)
   934  							byte(vm.PUSH1), 0x00,
   935  							byte(vm.MSTORE),
   936  							// RETURN (0, 32)
   937  							byte(vm.PUSH1), 32,
   938  							byte(vm.PUSH1), 00,
   939  							byte(vm.RETURN),
   940  						}),
   941  						StateDiff: map[common.Hash]common.Hash{
   942  							common.HexToHash("0x03"): common.HexToHash("0x11"),
   943  						},
   944  					},
   945  				},
   946  			},
   947  			want: `{"gas":25288,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000055"}`,
   948  		},
   949  		{ // Call to precompile ECREC (0x01), but code was modified to add 1 to input
   950  			blockNumber: rpc.LatestBlockNumber,
   951  			call: ethapi.TransactionArgs{
   952  				From: &randomAccounts[0].addr,
   953  				To:   &ecRecoverAddress,
   954  				Data: newRPCBytes(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")),
   955  			},
   956  			config: &TraceCallConfig{
   957  				StateOverrides: &override.StateOverride{
   958  					randomAccounts[0].addr: override.OverrideAccount{
   959  						Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether))),
   960  					},
   961  					ecRecoverAddress: override.OverrideAccount{
   962  						// The code below adds one to input
   963  						Code:             newRPCBytes(common.Hex2Bytes("60003560010160005260206000f3")),
   964  						MovePrecompileTo: &randomAccounts[2].addr,
   965  					},
   966  				},
   967  			},
   968  			want: `{"gas":21167,"failed":false,"returnValue":"0x0000000000000000000000000000000000000000000000000000000000000002"}`,
   969  		},
   970  		{ // Call to ECREC Precompiled on a different address, expect the original behaviour of ECREC precompile
   971  			blockNumber: rpc.LatestBlockNumber,
   972  			call: ethapi.TransactionArgs{
   973  				From: &randomAccounts[0].addr,
   974  				To:   &randomAccounts[2].addr, // Moved EcRecover
   975  				Data: newRPCBytes(common.Hex2Bytes("82f3df49d3645876de6313df2bbe9fbce593f21341a7b03acdb9423bc171fcc9000000000000000000000000000000000000000000000000000000000000001cba13918f50da910f2d55a7ea64cf716ba31dad91856f45908dde900530377d8a112d60f36900d18eb8f9d3b4f85a697b545085614509e3520e4b762e35d0d6bd")),
   976  			},
   977  			config: &TraceCallConfig{
   978  				StateOverrides: &override.StateOverride{
   979  					randomAccounts[0].addr: override.OverrideAccount{
   980  						Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether))),
   981  					},
   982  					ecRecoverAddress: override.OverrideAccount{
   983  						// The code below adds one to input
   984  						Code:             newRPCBytes(common.Hex2Bytes("60003560010160005260206000f3")),
   985  						MovePrecompileTo: &randomAccounts[2].addr, // Move EcRecover to this address
   986  					},
   987  				},
   988  			},
   989  			want: `{"gas":25664,"failed":false,"returnValue":"0x000000000000000000000000c6e93f4c1920eaeaa1e699f76a7a8c18e3056074"}`,
   990  		},
   991  	}
   992  	for i, tc := range testSuite {
   993  		result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
   994  		if tc.expectErr != nil {
   995  			if err == nil {
   996  				t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
   997  				continue
   998  			}
   999  			if !errors.Is(err, tc.expectErr) {
  1000  				t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err)
  1001  			}
  1002  			continue
  1003  		}
  1004  		if err != nil {
  1005  			t.Errorf("test %d: want no error, have %v", i, err)
  1006  			continue
  1007  		}
  1008  		// Turn result into res-struct
  1009  		var (
  1010  			have res
  1011  			want res
  1012  		)
  1013  		resBytes, _ := json.Marshal(result)
  1014  		json.Unmarshal(resBytes, &have)
  1015  		json.Unmarshal([]byte(tc.want), &want)
  1016  		if !reflect.DeepEqual(have, want) {
  1017  			t.Logf("result: %v\n", string(resBytes))
  1018  			t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, have, want)
  1019  		}
  1020  	}
  1021  }
  1022  
  1023  type Account struct {
  1024  	key  *ecdsa.PrivateKey
  1025  	addr common.Address
  1026  }
  1027  
  1028  func newAccounts(n int) (accounts []Account) {
  1029  	for i := 0; i < n; i++ {
  1030  		key, _ := crypto.GenerateKey()
  1031  		addr := crypto.PubkeyToAddress(key.PublicKey)
  1032  		accounts = append(accounts, Account{key: key, addr: addr})
  1033  	}
  1034  	slices.SortFunc(accounts, func(a, b Account) int { return a.addr.Cmp(b.addr) })
  1035  	return accounts
  1036  }
  1037  
  1038  func newRPCBalance(balance *big.Int) *hexutil.Big {
  1039  	rpcBalance := (*hexutil.Big)(balance)
  1040  	return rpcBalance
  1041  }
  1042  
  1043  func newRPCBytes(bytes []byte) *hexutil.Bytes {
  1044  	rpcBytes := hexutil.Bytes(bytes)
  1045  	return &rpcBytes
  1046  }
  1047  
  1048  func newStates(keys []common.Hash, vals []common.Hash) map[common.Hash]common.Hash {
  1049  	if len(keys) != len(vals) {
  1050  		panic("invalid input")
  1051  	}
  1052  	m := make(map[common.Hash]common.Hash)
  1053  	for i := 0; i < len(keys); i++ {
  1054  		m[keys[i]] = vals[i]
  1055  	}
  1056  	return m
  1057  }
  1058  
  1059  func TestTraceChain(t *testing.T) {
  1060  	// Initialize test accounts
  1061  	accounts := newAccounts(3)
  1062  	genesis := &core.Genesis{
  1063  		Config: params.TestChainConfig,
  1064  		Alloc: types.GenesisAlloc{
  1065  			accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  1066  			accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  1067  			accounts[2].addr: {Balance: big.NewInt(params.Ether)},
  1068  		},
  1069  	}
  1070  	genBlocks := 50
  1071  	signer := types.HomesteadSigner{}
  1072  
  1073  	var (
  1074  		ref   atomic.Uint32 // total refs has made
  1075  		rel   atomic.Uint32 // total rels has made
  1076  		nonce uint64
  1077  	)
  1078  	backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  1079  		// Transfer from account[0] to account[1]
  1080  		//    value: 1000 wei
  1081  		//    fee:   0 wei
  1082  		for j := 0; j < i+1; j++ {
  1083  			tx, _ := types.SignTx(types.NewTransaction(nonce, accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
  1084  			b.AddTx(tx)
  1085  			nonce += 1
  1086  		}
  1087  	})
  1088  	backend.refHook = func() { ref.Add(1) }
  1089  	backend.relHook = func() { rel.Add(1) }
  1090  	api := NewAPI(backend)
  1091  
  1092  	single := `{"txHash":"0x0000000000000000000000000000000000000000000000000000000000000000","result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}`
  1093  	var cases = []struct {
  1094  		start  uint64
  1095  		end    uint64
  1096  		config *TraceConfig
  1097  	}{
  1098  		{0, 50, nil},  // the entire chain range, blocks [1, 50]
  1099  		{10, 20, nil}, // the middle chain range, blocks [11, 20]
  1100  	}
  1101  	for _, c := range cases {
  1102  		ref.Store(0)
  1103  		rel.Store(0)
  1104  
  1105  		from, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start))
  1106  		to, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end))
  1107  		resCh := api.traceChain(from, to, c.config, nil)
  1108  
  1109  		next := c.start + 1
  1110  		for result := range resCh {
  1111  			if have, want := uint64(result.Block), next; have != want {
  1112  				t.Fatalf("unexpected tracing block, have %d want %d", have, want)
  1113  			}
  1114  			if have, want := len(result.Traces), int(next); have != want {
  1115  				t.Fatalf("unexpected result length, have %d want %d", have, want)
  1116  			}
  1117  			for _, trace := range result.Traces {
  1118  				trace.TxHash = common.Hash{}
  1119  				blob, _ := json.Marshal(trace)
  1120  				if have, want := string(blob), single; have != want {
  1121  					t.Fatalf("unexpected tracing result, have\n%v\nwant:\n%v", have, want)
  1122  				}
  1123  			}
  1124  			next += 1
  1125  		}
  1126  		if next != c.end+1 {
  1127  			t.Error("Missing tracing block")
  1128  		}
  1129  
  1130  		if nref, nrel := ref.Load(), rel.Load(); nref != nrel {
  1131  			t.Errorf("Ref and deref actions are not equal, ref %d rel %d", nref, nrel)
  1132  		}
  1133  	}
  1134  }
  1135  
  1136  // newTestMergedBackend creates a post-merge chain
  1137  func newTestMergedBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
  1138  	backend := &testBackend{
  1139  		chainConfig: gspec.Config,
  1140  		engine:      beacon.New(ethash.NewFaker()),
  1141  		chaindb:     rawdb.NewMemoryDatabase(),
  1142  	}
  1143  	// Generate blocks for testing
  1144  	_, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
  1145  
  1146  	// Import the canonical chain
  1147  	options := &core.BlockChainConfig{
  1148  		TrieCleanLimit: 256,
  1149  		TrieDirtyLimit: 256,
  1150  		TrieTimeLimit:  5 * time.Minute,
  1151  		SnapshotLimit:  0,
  1152  		ArchiveMode:    true, // Archive mode
  1153  	}
  1154  	chain, err := core.NewBlockChain(backend.chaindb, gspec, backend.engine, options)
  1155  	if err != nil {
  1156  		t.Fatalf("failed to create tester chain: %v", err)
  1157  	}
  1158  	if n, err := chain.InsertChain(blocks); err != nil {
  1159  		t.Fatalf("block %d: failed to insert into chain: %v", n, err)
  1160  	}
  1161  	backend.chain = chain
  1162  	return backend
  1163  }
  1164  
  1165  func TestTraceBlockWithBasefee(t *testing.T) {
  1166  	t.Parallel()
  1167  	accounts := newAccounts(1)
  1168  	target := common.HexToAddress("0x1111111111111111111111111111111111111111")
  1169  	genesis := &core.Genesis{
  1170  		Config: params.AllDevChainProtocolChanges,
  1171  		Alloc: types.GenesisAlloc{
  1172  			accounts[0].addr: {Balance: big.NewInt(1 * params.Ether)},
  1173  			target: {Nonce: 1, Code: []byte{
  1174  				byte(vm.BASEFEE), byte(vm.STOP),
  1175  			}},
  1176  		},
  1177  	}
  1178  	genBlocks := 1
  1179  	signer := types.HomesteadSigner{}
  1180  	var txHash common.Hash
  1181  	var baseFee = new(big.Int)
  1182  	backend := newTestMergedBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  1183  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
  1184  			Nonce:    uint64(i),
  1185  			To:       &target,
  1186  			Value:    big.NewInt(0),
  1187  			Gas:      5 * params.TxGas,
  1188  			GasPrice: b.BaseFee(),
  1189  			Data:     nil}),
  1190  			signer, accounts[0].key)
  1191  		b.AddTx(tx)
  1192  		txHash = tx.Hash()
  1193  		baseFee.Set(b.BaseFee())
  1194  	})
  1195  	defer backend.chain.Stop()
  1196  	api := NewAPI(backend)
  1197  
  1198  	var testSuite = []struct {
  1199  		blockNumber rpc.BlockNumber
  1200  		config      *TraceConfig
  1201  		want        string
  1202  	}{
  1203  		// Trace head block
  1204  		{
  1205  			blockNumber: rpc.BlockNumber(genBlocks),
  1206  			want:        fmt.Sprintf(`[{"txHash":"%#x","result":{"gas":21002,"failed":false,"returnValue":"0x","structLogs":[{"pc":0,"op":"BASEFEE","gas":84000,"gasCost":2,"depth":1,"stack":[]},{"pc":1,"op":"STOP","gas":83998,"gasCost":0,"depth":1,"stack":["%#x"]}]}}]`, txHash, baseFee),
  1207  		},
  1208  	}
  1209  	for i, tc := range testSuite {
  1210  		result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
  1211  		if err != nil {
  1212  			t.Errorf("test %d, want no error, have %v", i, err)
  1213  			continue
  1214  		}
  1215  		have, _ := json.Marshal(result)
  1216  		want := tc.want
  1217  		if string(have) != want {
  1218  			t.Errorf("test %d, result mismatch\nhave: %v\nwant: %v\n", i, string(have), want)
  1219  		}
  1220  	}
  1221  }
  1222  
  1223  func TestStandardTraceBlockToFile(t *testing.T) {
  1224  	var (
  1225  		// A sender who makes transactions, has some funds
  1226  		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1227  		address = crypto.PubkeyToAddress(key.PublicKey)
  1228  		funds   = big.NewInt(1000000000000000)
  1229  
  1230  		// first contract the sender transacts with
  1231  		aa     = common.HexToAddress("0x7217d81b76bdd8707601e959454e3d776aee5f43")
  1232  		aaCode = []byte{byte(vm.PUSH1), 0x00, byte(vm.POP)}
  1233  
  1234  		// second contract the sender transacts with
  1235  		bb     = common.HexToAddress("0x7217d81b76bdd8707601e959454e3d776aee5f44")
  1236  		bbCode = []byte{byte(vm.PUSH2), 0x00, 0x01, byte(vm.POP)}
  1237  	)
  1238  
  1239  	genesis := &core.Genesis{
  1240  		Config: params.TestChainConfig,
  1241  		Alloc: types.GenesisAlloc{
  1242  			address: {Balance: funds},
  1243  			aa: {
  1244  				Code:    aaCode,
  1245  				Nonce:   1,
  1246  				Balance: big.NewInt(0),
  1247  			},
  1248  			bb: {
  1249  				Code:    bbCode,
  1250  				Nonce:   1,
  1251  				Balance: big.NewInt(0),
  1252  			},
  1253  		},
  1254  	}
  1255  	txHashs := make([]common.Hash, 0, 2)
  1256  	backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) {
  1257  		b.SetCoinbase(common.Address{1})
  1258  		// first tx to aa
  1259  		tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
  1260  			Nonce:    0,
  1261  			To:       &aa,
  1262  			Value:    big.NewInt(0),
  1263  			Gas:      50000,
  1264  			GasPrice: b.BaseFee(),
  1265  			Data:     nil,
  1266  		}), types.HomesteadSigner{}, key)
  1267  		b.AddTx(tx)
  1268  		txHashs = append(txHashs, tx.Hash())
  1269  		// second tx to bb
  1270  		tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
  1271  			Nonce:    1,
  1272  			To:       &bb,
  1273  			Value:    big.NewInt(1),
  1274  			Gas:      100000,
  1275  			GasPrice: b.BaseFee(),
  1276  			Data:     nil,
  1277  		}), types.HomesteadSigner{}, key)
  1278  		b.AddTx(tx)
  1279  		txHashs = append(txHashs, tx.Hash())
  1280  	})
  1281  	defer backend.chain.Stop()
  1282  
  1283  	var testSuite = []struct {
  1284  		blockNumber rpc.BlockNumber
  1285  		config      *StdTraceConfig
  1286  		want        []string
  1287  	}{
  1288  		{
  1289  			// test that all traces in the block were outputted if no trace config is specified
  1290  			blockNumber: rpc.LatestBlockNumber,
  1291  			config:      nil,
  1292  			want: []string{
  1293  				`{"pc":0,"op":96,"gas":"0x7148","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
  1294  {"pc":2,"op":80,"gas":"0x7145","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP"}
  1295  {"pc":3,"op":0,"gas":"0x7143","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"}
  1296  {"output":"","gasUsed":"0x5"}
  1297  `,
  1298  				`{"pc":0,"op":97,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH2"}
  1299  {"pc":3,"op":80,"gas":"0x13495","gasCost":"0x2","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"POP"}
  1300  {"pc":4,"op":0,"gas":"0x13493","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"}
  1301  {"output":"","gasUsed":"0x5"}
  1302  `,
  1303  			},
  1304  		},
  1305  		{
  1306  			// test that only a specific tx is traced if specified
  1307  			blockNumber: rpc.LatestBlockNumber,
  1308  			config:      &StdTraceConfig{TxHash: txHashs[1]},
  1309  			want: []string{
  1310  				`{"pc":0,"op":97,"gas":"0x13498","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH2"}
  1311  {"pc":3,"op":80,"gas":"0x13495","gasCost":"0x2","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"POP"}
  1312  {"pc":4,"op":0,"gas":"0x13493","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"STOP"}
  1313  {"output":"","gasUsed":"0x5"}
  1314  `,
  1315  			},
  1316  		},
  1317  	}
  1318  
  1319  	api := NewAPI(backend)
  1320  	for i, tc := range testSuite {
  1321  		block, _ := api.blockByNumber(context.Background(), tc.blockNumber)
  1322  		txTraces, err := api.StandardTraceBlockToFile(context.Background(), block.Hash(), tc.config)
  1323  		if err != nil {
  1324  			t.Fatalf("test index %d received error %v", i, err)
  1325  		}
  1326  		for j, traceFileName := range txTraces {
  1327  			traceReceived, err := os.ReadFile(traceFileName)
  1328  			if err != nil {
  1329  				t.Fatalf("could not read trace file: %v", err)
  1330  			}
  1331  			if tc.want[j] != string(traceReceived) {
  1332  				t.Fatalf("unexpected trace result.  expected\n'%s'\n\nreceived\n'%s'\n", tc.want[j], string(traceReceived))
  1333  			}
  1334  		}
  1335  	}
  1336  }