github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/eth/tracers/api.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  	"bufio"
    21  	"context"
    22  	"encoding/json"
    23  	"errors"
    24  	"fmt"
    25  	"math/big"
    26  	"os"
    27  	"runtime"
    28  	"sync"
    29  	"time"
    30  
    31  	"github.com/ethereum/go-ethereum/common"
    32  	"github.com/ethereum/go-ethereum/common/hexutil"
    33  	"github.com/ethereum/go-ethereum/consensus"
    34  	"github.com/ethereum/go-ethereum/core"
    35  	"github.com/ethereum/go-ethereum/core/rawdb"
    36  	"github.com/ethereum/go-ethereum/core/state"
    37  	"github.com/ethereum/go-ethereum/core/types"
    38  	"github.com/ethereum/go-ethereum/core/vm"
    39  	"github.com/ethereum/go-ethereum/eth/tracers/logger"
    40  	"github.com/ethereum/go-ethereum/ethdb"
    41  	"github.com/ethereum/go-ethereum/internal/ethapi"
    42  	"github.com/ethereum/go-ethereum/log"
    43  	"github.com/ethereum/go-ethereum/params"
    44  	"github.com/ethereum/go-ethereum/rlp"
    45  	"github.com/ethereum/go-ethereum/rpc"
    46  )
    47  
    48  const (
    49  	// defaultTraceTimeout is the amount of time a single transaction can execute
    50  	// by default before being forcefully aborted.
    51  	defaultTraceTimeout = 5 * time.Second
    52  
    53  	// defaultTraceReexec is the number of blocks the tracer is willing to go back
    54  	// and reexecute to produce missing historical state necessary to run a specific
    55  	// trace.
    56  	defaultTraceReexec = uint64(128)
    57  
    58  	// defaultTracechainMemLimit is the size of the triedb, at which traceChain
    59  	// switches over and tries to use a disk-backed database instead of building
    60  	// on top of memory.
    61  	// For non-archive nodes, this limit _will_ be overblown, as disk-backed tries
    62  	// will only be found every ~15K blocks or so.
    63  	defaultTracechainMemLimit = common.StorageSize(500 * 1024 * 1024)
    64  
    65  	// maximumPendingTraceStates is the maximum number of states allowed waiting
    66  	// for tracing. The creation of trace state will be paused if the unused
    67  	// trace states exceed this limit.
    68  	maximumPendingTraceStates = 128
    69  )
    70  
    71  var errTxNotFound = errors.New("transaction not found")
    72  
    73  // StateReleaseFunc is used to deallocate resources held by constructing a
    74  // historical state for tracing purposes.
    75  type StateReleaseFunc func()
    76  
    77  // Backend interface provides the common API services (that are provided by
    78  // both full and light clients) with access to necessary functions.
    79  type Backend interface {
    80  	HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
    81  	HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
    82  	BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
    83  	BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
    84  	GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
    85  	RPCGasCap() uint64
    86  	ChainConfig() *params.ChainConfig
    87  	Engine() consensus.Engine
    88  	ChainDb() ethdb.Database
    89  	StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error)
    90  	StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error)
    91  }
    92  
    93  // API is the collection of tracing APIs exposed over the private debugging endpoint.
    94  type API struct {
    95  	backend Backend
    96  }
    97  
    98  // NewAPI creates a new API definition for the tracing methods of the Ethereum service.
    99  func NewAPI(backend Backend) *API {
   100  	return &API{backend: backend}
   101  }
   102  
   103  // chainContext constructs the context reader which is used by the evm for reading
   104  // the necessary chain context.
   105  func (api *API) chainContext(ctx context.Context) core.ChainContext {
   106  	return ethapi.NewChainContext(ctx, api.backend)
   107  }
   108  
   109  // blockByNumber is the wrapper of the chain access function offered by the backend.
   110  // It will return an error if the block is not found.
   111  func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   112  	block, err := api.backend.BlockByNumber(ctx, number)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	if block == nil {
   117  		return nil, fmt.Errorf("block #%d not found", number)
   118  	}
   119  	return block, nil
   120  }
   121  
   122  // blockByHash is the wrapper of the chain access function offered by the backend.
   123  // It will return an error if the block is not found.
   124  func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   125  	block, err := api.backend.BlockByHash(ctx, hash)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  	if block == nil {
   130  		return nil, fmt.Errorf("block %s not found", hash.Hex())
   131  	}
   132  	return block, nil
   133  }
   134  
   135  // blockByNumberAndHash is the wrapper of the chain access function offered by
   136  // the backend. It will return an error if the block is not found.
   137  //
   138  // Note this function is friendly for the light client which can only retrieve the
   139  // historical(before the CHT) header/block by number.
   140  func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, error) {
   141  	block, err := api.blockByNumber(ctx, number)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	if block.Hash() == hash {
   146  		return block, nil
   147  	}
   148  	return api.blockByHash(ctx, hash)
   149  }
   150  
   151  // TraceConfig holds extra parameters to trace functions.
   152  type TraceConfig struct {
   153  	*logger.Config
   154  	Tracer  *string
   155  	Timeout *string
   156  	Reexec  *uint64
   157  	// Config specific to given tracer. Note struct logger
   158  	// config are historically embedded in main object.
   159  	TracerConfig json.RawMessage
   160  }
   161  
   162  // TraceCallConfig is the config for traceCall API. It holds one more
   163  // field to override the state for tracing.
   164  type TraceCallConfig struct {
   165  	TraceConfig
   166  	StateOverrides *ethapi.StateOverride
   167  	BlockOverrides *ethapi.BlockOverrides
   168  	TxIndex        *hexutil.Uint
   169  }
   170  
   171  // StdTraceConfig holds extra parameters to standard-json trace functions.
   172  type StdTraceConfig struct {
   173  	logger.Config
   174  	Reexec *uint64
   175  	TxHash common.Hash
   176  }
   177  
   178  // txTraceResult is the result of a single transaction trace.
   179  type txTraceResult struct {
   180  	TxHash common.Hash `json:"txHash"`           // transaction hash
   181  	Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
   182  	Error  string      `json:"error,omitempty"`  // Trace failure produced by the tracer
   183  }
   184  
   185  // blockTraceTask represents a single block trace task when an entire chain is
   186  // being traced.
   187  type blockTraceTask struct {
   188  	statedb *state.StateDB   // Intermediate state prepped for tracing
   189  	block   *types.Block     // Block to trace the transactions from
   190  	release StateReleaseFunc // The function to release the held resource for this task
   191  	results []*txTraceResult // Trace results produced by the task
   192  }
   193  
   194  // blockTraceResult represents the results of tracing a single block when an entire
   195  // chain is being traced.
   196  type blockTraceResult struct {
   197  	Block  hexutil.Uint64   `json:"block"`  // Block number corresponding to this trace
   198  	Hash   common.Hash      `json:"hash"`   // Block hash corresponding to this trace
   199  	Traces []*txTraceResult `json:"traces"` // Trace results produced by the task
   200  }
   201  
   202  // txTraceTask represents a single transaction trace task when an entire block
   203  // is being traced.
   204  type txTraceTask struct {
   205  	statedb *state.StateDB // Intermediate state prepped for tracing
   206  	index   int            // Transaction offset in the block
   207  }
   208  
   209  // TraceChain returns the structured logs created during the execution of EVM
   210  // between two blocks (excluding start) and returns them as a JSON object.
   211  func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { // Fetch the block interval that we want to trace
   212  	from, err := api.blockByNumber(ctx, start)
   213  	if err != nil {
   214  		return nil, err
   215  	}
   216  	to, err := api.blockByNumber(ctx, end)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  	if from.Number().Cmp(to.Number()) >= 0 {
   221  		return nil, fmt.Errorf("end block (#%d) needs to come after start block (#%d)", end, start)
   222  	}
   223  	// Tracing a chain is a **long** operation, only do with subscriptions
   224  	notifier, supported := rpc.NotifierFromContext(ctx)
   225  	if !supported {
   226  		return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
   227  	}
   228  	sub := notifier.CreateSubscription()
   229  
   230  	resCh := api.traceChain(from, to, config, sub.Err())
   231  	go func() {
   232  		for result := range resCh {
   233  			notifier.Notify(sub.ID, result)
   234  		}
   235  	}()
   236  	return sub, nil
   237  }
   238  
   239  // traceChain configures a new tracer according to the provided configuration, and
   240  // executes all the transactions contained within. The tracing chain range includes
   241  // the end block but excludes the start one. The return value will be one item per
   242  // transaction, dependent on the requested tracer.
   243  // The tracing procedure should be aborted in case the closed signal is received.
   244  func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan error) chan *blockTraceResult {
   245  	reexec := defaultTraceReexec
   246  	if config != nil && config.Reexec != nil {
   247  		reexec = *config.Reexec
   248  	}
   249  	blocks := int(end.NumberU64() - start.NumberU64())
   250  	threads := runtime.NumCPU()
   251  	if threads > blocks {
   252  		threads = blocks
   253  	}
   254  	var (
   255  		pend    = new(sync.WaitGroup)
   256  		ctx     = context.Background()
   257  		taskCh  = make(chan *blockTraceTask, threads)
   258  		resCh   = make(chan *blockTraceTask, threads)
   259  		tracker = newStateTracker(maximumPendingTraceStates, start.NumberU64())
   260  	)
   261  	for th := 0; th < threads; th++ {
   262  		pend.Add(1)
   263  		go func() {
   264  			defer pend.Done()
   265  
   266  			// Fetch and execute the block trace taskCh
   267  			for task := range taskCh {
   268  				var (
   269  					signer   = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
   270  					blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
   271  				)
   272  				// Trace all the transactions contained within
   273  				for i, tx := range task.block.Transactions() {
   274  					msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
   275  					txctx := &Context{
   276  						BlockHash:   task.block.Hash(),
   277  						BlockNumber: task.block.Number(),
   278  						TxIndex:     i,
   279  						TxHash:      tx.Hash(),
   280  					}
   281  					res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config)
   282  					if err != nil {
   283  						task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
   284  						log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
   285  						break
   286  					}
   287  					task.results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res}
   288  				}
   289  				// Tracing state is used up, queue it for de-referencing. Note the
   290  				// state is the parent state of trace block, use block.number-1 as
   291  				// the state number.
   292  				tracker.releaseState(task.block.NumberU64()-1, task.release)
   293  
   294  				// Stream the result back to the result catcher or abort on teardown
   295  				select {
   296  				case resCh <- task:
   297  				case <-closed:
   298  					return
   299  				}
   300  			}
   301  		}()
   302  	}
   303  	// Start a goroutine to feed all the blocks into the tracers
   304  	go func() {
   305  		var (
   306  			logged  time.Time
   307  			begin   = time.Now()
   308  			number  uint64
   309  			traced  uint64
   310  			failed  error
   311  			statedb *state.StateDB
   312  			release StateReleaseFunc
   313  		)
   314  		// Ensure everything is properly cleaned up on any exit path
   315  		defer func() {
   316  			close(taskCh)
   317  			pend.Wait()
   318  
   319  			// Clean out any pending release functions of trace states.
   320  			tracker.callReleases()
   321  
   322  			// Log the chain result
   323  			switch {
   324  			case failed != nil:
   325  				log.Warn("Chain tracing failed", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin), "err", failed)
   326  			case number < end.NumberU64():
   327  				log.Warn("Chain tracing aborted", "start", start.NumberU64(), "end", end.NumberU64(), "abort", number, "transactions", traced, "elapsed", time.Since(begin))
   328  			default:
   329  				log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin))
   330  			}
   331  			close(resCh)
   332  		}()
   333  		// Feed all the blocks both into the tracer, as well as fast process concurrently
   334  		for number = start.NumberU64(); number < end.NumberU64(); number++ {
   335  			// Stop tracing if interruption was requested
   336  			select {
   337  			case <-closed:
   338  				return
   339  			default:
   340  			}
   341  			// Print progress logs if long enough time elapsed
   342  			if time.Since(logged) > 8*time.Second {
   343  				logged = time.Now()
   344  				log.Info("Tracing chain segment", "start", start.NumberU64(), "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin))
   345  			}
   346  			// Retrieve the parent block and target block for tracing.
   347  			block, err := api.blockByNumber(ctx, rpc.BlockNumber(number))
   348  			if err != nil {
   349  				failed = err
   350  				break
   351  			}
   352  			next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1))
   353  			if err != nil {
   354  				failed = err
   355  				break
   356  			}
   357  			// Make sure the state creator doesn't go too far. Too many unprocessed
   358  			// trace state may cause the oldest state to become stale(e.g. in
   359  			// path-based scheme).
   360  			if err = tracker.wait(number); err != nil {
   361  				failed = err
   362  				break
   363  			}
   364  			// Prepare the statedb for tracing. Don't use the live database for
   365  			// tracing to avoid persisting state junks into the database. Switch
   366  			// over to `preferDisk` mode only if the memory usage exceeds the
   367  			// limit, the trie database will be reconstructed from scratch only
   368  			// if the relevant state is available in disk.
   369  			var preferDisk bool
   370  			if statedb != nil {
   371  				s1, s2, s3 := statedb.Database().TrieDB().Size()
   372  				preferDisk = s1+s2+s3 > defaultTracechainMemLimit
   373  			}
   374  			statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk)
   375  			if err != nil {
   376  				failed = err
   377  				break
   378  			}
   379  			// Insert block's parent beacon block root in the state
   380  			// as per EIP-4788.
   381  			if beaconRoot := next.BeaconRoot(); beaconRoot != nil {
   382  				context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
   383  				vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
   384  				core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
   385  			}
   386  			// Clean out any pending release functions of trace state. Note this
   387  			// step must be done after constructing tracing state, because the
   388  			// tracing state of block next depends on the parent state and construction
   389  			// may fail if we release too early.
   390  			tracker.callReleases()
   391  
   392  			// Send the block over to the concurrent tracers (if not in the fast-forward phase)
   393  			txs := next.Transactions()
   394  			select {
   395  			case taskCh <- &blockTraceTask{statedb: statedb.Copy(), block: next, release: release, results: make([]*txTraceResult, len(txs))}:
   396  			case <-closed:
   397  				tracker.releaseState(number, release)
   398  				return
   399  			}
   400  			traced += uint64(len(txs))
   401  		}
   402  	}()
   403  
   404  	// Keep reading the trace results and stream them to result channel.
   405  	retCh := make(chan *blockTraceResult)
   406  	go func() {
   407  		defer close(retCh)
   408  		var (
   409  			next = start.NumberU64() + 1
   410  			done = make(map[uint64]*blockTraceResult)
   411  		)
   412  		for res := range resCh {
   413  			// Queue up next received result
   414  			result := &blockTraceResult{
   415  				Block:  hexutil.Uint64(res.block.NumberU64()),
   416  				Hash:   res.block.Hash(),
   417  				Traces: res.results,
   418  			}
   419  			done[uint64(result.Block)] = result
   420  
   421  			// Stream completed traces to the result channel
   422  			for result, ok := done[next]; ok; result, ok = done[next] {
   423  				if len(result.Traces) > 0 || next == end.NumberU64() {
   424  					// It will be blocked in case the channel consumer doesn't take the
   425  					// tracing result in time(e.g. the websocket connect is not stable)
   426  					// which will eventually block the entire chain tracer. It's the
   427  					// expected behavior to not waste node resources for a non-active user.
   428  					retCh <- result
   429  				}
   430  				delete(done, next)
   431  				next++
   432  			}
   433  		}
   434  	}()
   435  	return retCh
   436  }
   437  
   438  // TraceBlockByNumber returns the structured logs created during the execution of
   439  // EVM and returns them as a JSON object.
   440  func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
   441  	block, err := api.blockByNumber(ctx, number)
   442  	if err != nil {
   443  		return nil, err
   444  	}
   445  	return api.traceBlock(ctx, block, config)
   446  }
   447  
   448  // TraceBlockByHash returns the structured logs created during the execution of
   449  // EVM and returns them as a JSON object.
   450  func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
   451  	block, err := api.blockByHash(ctx, hash)
   452  	if err != nil {
   453  		return nil, err
   454  	}
   455  	return api.traceBlock(ctx, block, config)
   456  }
   457  
   458  // TraceBlock returns the structured logs created during the execution of EVM
   459  // and returns them as a JSON object.
   460  func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *TraceConfig) ([]*txTraceResult, error) {
   461  	block := new(types.Block)
   462  	if err := rlp.DecodeBytes(blob, block); err != nil {
   463  		return nil, fmt.Errorf("could not decode block: %v", err)
   464  	}
   465  	return api.traceBlock(ctx, block, config)
   466  }
   467  
   468  // TraceBlockFromFile returns the structured logs created during the execution of
   469  // EVM and returns them as a JSON object.
   470  func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*txTraceResult, error) {
   471  	blob, err := os.ReadFile(file)
   472  	if err != nil {
   473  		return nil, fmt.Errorf("could not read file: %v", err)
   474  	}
   475  	return api.TraceBlock(ctx, blob, config)
   476  }
   477  
   478  // TraceBadBlock returns the structured logs created during the execution of
   479  // EVM against a block pulled from the pool of bad ones and returns them as a JSON
   480  // object.
   481  func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
   482  	block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
   483  	if block == nil {
   484  		return nil, fmt.Errorf("bad block %#x not found", hash)
   485  	}
   486  	return api.traceBlock(ctx, block, config)
   487  }
   488  
   489  // StandardTraceBlockToFile dumps the structured logs created during the
   490  // execution of EVM to the local file system and returns a list of files
   491  // to the caller.
   492  func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
   493  	block, err := api.blockByHash(ctx, hash)
   494  	if err != nil {
   495  		return nil, err
   496  	}
   497  	return api.standardTraceBlockToFile(ctx, block, config)
   498  }
   499  
   500  // IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
   501  // of intermediate roots: the stateroot after each transaction.
   502  func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
   503  	block, _ := api.blockByHash(ctx, hash)
   504  	if block == nil {
   505  		// Check in the bad blocks
   506  		block = rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
   507  	}
   508  	if block == nil {
   509  		return nil, fmt.Errorf("block %#x not found", hash)
   510  	}
   511  	if block.NumberU64() == 0 {
   512  		return nil, errors.New("genesis is not traceable")
   513  	}
   514  	parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
   515  	if err != nil {
   516  		return nil, err
   517  	}
   518  	reexec := defaultTraceReexec
   519  	if config != nil && config.Reexec != nil {
   520  		reexec = *config.Reexec
   521  	}
   522  	statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
   523  	if err != nil {
   524  		return nil, err
   525  	}
   526  	defer release()
   527  	var (
   528  		roots              []common.Hash
   529  		signer             = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
   530  		chainConfig        = api.backend.ChainConfig()
   531  		vmctx              = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
   532  		deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
   533  	)
   534  	if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
   535  		vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
   536  		core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
   537  	}
   538  	for i, tx := range block.Transactions() {
   539  		if err := ctx.Err(); err != nil {
   540  			return nil, err
   541  		}
   542  		var (
   543  			msg, _    = core.TransactionToMessage(tx, signer, block.BaseFee())
   544  			txContext = core.NewEVMTxContext(msg)
   545  			vmenv     = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
   546  		)
   547  		statedb.SetTxContext(tx.Hash(), i)
   548  		if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
   549  			log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
   550  			// We intentionally don't return the error here: if we do, then the RPC server will not
   551  			// return the roots. Most likely, the caller already knows that a certain transaction fails to
   552  			// be included, but still want the intermediate roots that led to that point.
   553  			// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
   554  			// executable.
   555  			// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
   556  			return roots, nil
   557  		}
   558  		// calling IntermediateRoot will internally call Finalize on the state
   559  		// so any modifications are written to the trie
   560  		roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
   561  	}
   562  	return roots, nil
   563  }
   564  
   565  // StandardTraceBadBlockToFile dumps the structured logs created during the
   566  // execution of EVM against a block pulled from the pool of bad ones to the
   567  // local file system and returns a list of files to the caller.
   568  func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
   569  	block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
   570  	if block == nil {
   571  		return nil, fmt.Errorf("bad block %#x not found", hash)
   572  	}
   573  	return api.standardTraceBlockToFile(ctx, block, config)
   574  }
   575  
   576  // traceBlock configures a new tracer according to the provided configuration, and
   577  // executes all the transactions contained within. The return value will be one item
   578  // per transaction, dependent on the requested tracer.
   579  func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
   580  	if block.NumberU64() == 0 {
   581  		return nil, errors.New("genesis is not traceable")
   582  	}
   583  	// Prepare base state
   584  	parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
   585  	if err != nil {
   586  		return nil, err
   587  	}
   588  	reexec := defaultTraceReexec
   589  	if config != nil && config.Reexec != nil {
   590  		reexec = *config.Reexec
   591  	}
   592  	statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
   593  	if err != nil {
   594  		return nil, err
   595  	}
   596  	defer release()
   597  	// JS tracers have high overhead. In this case run a parallel
   598  	// process that generates states in one thread and traces txes
   599  	// in separate worker threads.
   600  	if config != nil && config.Tracer != nil && *config.Tracer != "" {
   601  		if isJS := DefaultDirectory.IsJS(*config.Tracer); isJS {
   602  			return api.traceBlockParallel(ctx, block, statedb, config)
   603  		}
   604  	}
   605  	// Native tracers have low overhead
   606  	var (
   607  		txs       = block.Transactions()
   608  		blockHash = block.Hash()
   609  		blockCtx  = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
   610  		signer    = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
   611  		results   = make([]*txTraceResult, len(txs))
   612  	)
   613  	if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
   614  		vmenv := vm.NewEVM(blockCtx, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
   615  		core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
   616  	}
   617  	for i, tx := range txs {
   618  		// Generate the next state snapshot fast without tracing
   619  		msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
   620  		txctx := &Context{
   621  			BlockHash:   blockHash,
   622  			BlockNumber: block.Number(),
   623  			TxIndex:     i,
   624  			TxHash:      tx.Hash(),
   625  		}
   626  		res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
   627  		if err != nil {
   628  			return nil, err
   629  		}
   630  		results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res}
   631  	}
   632  	return results, nil
   633  }
   634  
   635  // traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread
   636  // runs along and executes txes without tracing enabled to generate their prestate.
   637  // Worker threads take the tasks and the prestate and trace them.
   638  func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) {
   639  	// Execute all the transaction contained within the block concurrently
   640  	var (
   641  		txs       = block.Transactions()
   642  		blockHash = block.Hash()
   643  		signer    = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
   644  		results   = make([]*txTraceResult, len(txs))
   645  		pend      sync.WaitGroup
   646  	)
   647  	threads := runtime.NumCPU()
   648  	if threads > len(txs) {
   649  		threads = len(txs)
   650  	}
   651  	jobs := make(chan *txTraceTask, threads)
   652  	for th := 0; th < threads; th++ {
   653  		pend.Add(1)
   654  		go func() {
   655  			defer pend.Done()
   656  			// Fetch and execute the next transaction trace tasks
   657  			for task := range jobs {
   658  				msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee())
   659  				txctx := &Context{
   660  					BlockHash:   blockHash,
   661  					BlockNumber: block.Number(),
   662  					TxIndex:     task.index,
   663  					TxHash:      txs[task.index].Hash(),
   664  				}
   665  				// Reconstruct the block context for each transaction
   666  				// as the GetHash function of BlockContext is not safe for
   667  				// concurrent use.
   668  				// See: https://github.com/ethereum/go-ethereum/issues/29114
   669  				blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
   670  				res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
   671  				if err != nil {
   672  					results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
   673  					continue
   674  				}
   675  				results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Result: res}
   676  			}
   677  		}()
   678  	}
   679  
   680  	// Feed the transactions into the tracers and return
   681  	var failed error
   682  	blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
   683  txloop:
   684  	for i, tx := range txs {
   685  		// Send the trace task over for execution
   686  		task := &txTraceTask{statedb: statedb.Copy(), index: i}
   687  		select {
   688  		case <-ctx.Done():
   689  			failed = ctx.Err()
   690  			break txloop
   691  		case jobs <- task:
   692  		}
   693  
   694  		// Generate the next state snapshot fast without tracing
   695  		msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
   696  		statedb.SetTxContext(tx.Hash(), i)
   697  		vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{})
   698  		if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
   699  			failed = err
   700  			break txloop
   701  		}
   702  		// Finalize the state so any modifications are written to the trie
   703  		// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   704  		statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
   705  	}
   706  
   707  	close(jobs)
   708  	pend.Wait()
   709  
   710  	// If execution failed in between, abort
   711  	if failed != nil {
   712  		return nil, failed
   713  	}
   714  	return results, nil
   715  }
   716  
   717  // standardTraceBlockToFile configures a new tracer which uses standard JSON output,
   718  // and traces either a full block or an individual transaction. The return value will
   719  // be one filename per transaction traced.
   720  func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) {
   721  	// If we're tracing a single transaction, make sure it's present
   722  	if config != nil && config.TxHash != (common.Hash{}) {
   723  		if !containsTx(block, config.TxHash) {
   724  			return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash)
   725  		}
   726  	}
   727  	if block.NumberU64() == 0 {
   728  		return nil, errors.New("genesis is not traceable")
   729  	}
   730  	parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
   731  	if err != nil {
   732  		return nil, err
   733  	}
   734  	reexec := defaultTraceReexec
   735  	if config != nil && config.Reexec != nil {
   736  		reexec = *config.Reexec
   737  	}
   738  	statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
   739  	if err != nil {
   740  		return nil, err
   741  	}
   742  	defer release()
   743  	// Retrieve the tracing configurations, or use default values
   744  	var (
   745  		logConfig logger.Config
   746  		txHash    common.Hash
   747  	)
   748  	if config != nil {
   749  		logConfig = config.Config
   750  		txHash = config.TxHash
   751  	}
   752  	logConfig.Debug = true
   753  
   754  	// Execute transaction, either tracing all or just the requested one
   755  	var (
   756  		dumps       []string
   757  		signer      = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
   758  		chainConfig = api.backend.ChainConfig()
   759  		vmctx       = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
   760  		canon       = true
   761  	)
   762  	// Check if there are any overrides: the caller may wish to enable a future
   763  	// fork when executing this block. Note, such overrides are only applicable to the
   764  	// actual specified block, not any preceding blocks that we have to go through
   765  	// in order to obtain the state.
   766  	// Therefore, it's perfectly valid to specify `"futureForkBlock": 0`, to enable `futureFork`
   767  	if config != nil && config.Overrides != nil {
   768  		// Note: This copies the config, to not screw up the main config
   769  		chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
   770  	}
   771  	if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
   772  		vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
   773  		core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
   774  	}
   775  	for i, tx := range block.Transactions() {
   776  		// Prepare the transaction for un-traced execution
   777  		var (
   778  			msg, _    = core.TransactionToMessage(tx, signer, block.BaseFee())
   779  			txContext = core.NewEVMTxContext(msg)
   780  			vmConf    vm.Config
   781  			dump      *os.File
   782  			writer    *bufio.Writer
   783  			err       error
   784  		)
   785  		// If the transaction needs tracing, swap out the configs
   786  		if tx.Hash() == txHash || txHash == (common.Hash{}) {
   787  			// Generate a unique temporary file to dump it into
   788  			prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
   789  			if !canon {
   790  				prefix = fmt.Sprintf("%valt-", prefix)
   791  			}
   792  			dump, err = os.CreateTemp(os.TempDir(), prefix)
   793  			if err != nil {
   794  				return nil, err
   795  			}
   796  			dumps = append(dumps, dump.Name())
   797  
   798  			// Swap out the noop logger to the standard tracer
   799  			writer = bufio.NewWriter(dump)
   800  			vmConf = vm.Config{
   801  				Tracer:                  logger.NewJSONLogger(&logConfig, writer),
   802  				EnablePreimageRecording: true,
   803  			}
   804  		}
   805  		// Execute the transaction and flush any traces to disk
   806  		vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
   807  		statedb.SetTxContext(tx.Hash(), i)
   808  		vmConf.Tracer.OnTxStart(vmenv.GetVMContext(), tx, msg.From)
   809  		vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
   810  		vmConf.Tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, err)
   811  		if writer != nil {
   812  			writer.Flush()
   813  		}
   814  		if dump != nil {
   815  			dump.Close()
   816  			log.Info("Wrote standard trace", "file", dump.Name())
   817  		}
   818  		if err != nil {
   819  			return dumps, err
   820  		}
   821  		// Finalize the state so any modifications are written to the trie
   822  		// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   823  		statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
   824  
   825  		// If we've traced the transaction we were looking for, abort
   826  		if tx.Hash() == txHash {
   827  			break
   828  		}
   829  	}
   830  	return dumps, nil
   831  }
   832  
   833  // containsTx reports whether the transaction with a certain hash
   834  // is contained within the specified block.
   835  func containsTx(block *types.Block, hash common.Hash) bool {
   836  	for _, tx := range block.Transactions() {
   837  		if tx.Hash() == hash {
   838  			return true
   839  		}
   840  	}
   841  	return false
   842  }
   843  
   844  // TraceTransaction returns the structured logs created during the execution of EVM
   845  // and returns them as a JSON object.
   846  func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
   847  	found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
   848  	if err != nil {
   849  		return nil, ethapi.NewTxIndexingError()
   850  	}
   851  	// Only mined txes are supported
   852  	if !found {
   853  		return nil, errTxNotFound
   854  	}
   855  	// It shouldn't happen in practice.
   856  	if blockNumber == 0 {
   857  		return nil, errors.New("genesis is not traceable")
   858  	}
   859  	reexec := defaultTraceReexec
   860  	if config != nil && config.Reexec != nil {
   861  		reexec = *config.Reexec
   862  	}
   863  	block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash)
   864  	if err != nil {
   865  		return nil, err
   866  	}
   867  	tx, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
   868  	if err != nil {
   869  		return nil, err
   870  	}
   871  	defer release()
   872  	msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee())
   873  	if err != nil {
   874  		return nil, err
   875  	}
   876  
   877  	txctx := &Context{
   878  		BlockHash:   blockHash,
   879  		BlockNumber: block.Number(),
   880  		TxIndex:     int(index),
   881  		TxHash:      hash,
   882  	}
   883  	return api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config)
   884  }
   885  
   886  // TraceCall lets you trace a given eth_call. It collects the structured logs
   887  // created during the execution of EVM if the given transaction was added on
   888  // top of the provided block and returns them as a JSON object.
   889  // If no transaction index is specified, the trace will be conducted on the state
   890  // after executing the specified block. However, if a transaction index is provided,
   891  // the trace will be conducted on the state after executing the specified transaction
   892  // within the specified block.
   893  func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
   894  	// Try to retrieve the specified block
   895  	var (
   896  		err     error
   897  		block   *types.Block
   898  		statedb *state.StateDB
   899  		release StateReleaseFunc
   900  	)
   901  	if hash, ok := blockNrOrHash.Hash(); ok {
   902  		block, err = api.blockByHash(ctx, hash)
   903  	} else if number, ok := blockNrOrHash.Number(); ok {
   904  		if number == rpc.PendingBlockNumber {
   905  			// We don't have access to the miner here. For tracing 'future' transactions,
   906  			// it can be done with block- and state-overrides instead, which offers
   907  			// more flexibility and stability than trying to trace on 'pending', since
   908  			// the contents of 'pending' is unstable and probably not a true representation
   909  			// of what the next actual block is likely to contain.
   910  			return nil, errors.New("tracing on top of pending is not supported")
   911  		}
   912  		block, err = api.blockByNumber(ctx, number)
   913  	} else {
   914  		return nil, errors.New("invalid arguments; neither block nor hash specified")
   915  	}
   916  	if err != nil {
   917  		return nil, err
   918  	}
   919  	// try to recompute the state
   920  	reexec := defaultTraceReexec
   921  	if config != nil && config.Reexec != nil {
   922  		reexec = *config.Reexec
   923  	}
   924  
   925  	if config != nil && config.TxIndex != nil {
   926  		_, _, statedb, release, err = api.backend.StateAtTransaction(ctx, block, int(*config.TxIndex), reexec)
   927  	} else {
   928  		statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
   929  	}
   930  	if err != nil {
   931  		return nil, err
   932  	}
   933  	defer release()
   934  
   935  	vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
   936  	// Apply the customization rules if required.
   937  	if config != nil {
   938  		if err := config.StateOverrides.Apply(statedb); err != nil {
   939  			return nil, err
   940  		}
   941  		config.BlockOverrides.Apply(&vmctx)
   942  	}
   943  	// Execute the trace
   944  	if err := args.CallDefaults(api.backend.RPCGasCap(), vmctx.BaseFee, api.backend.ChainConfig().ChainID); err != nil {
   945  		return nil, err
   946  	}
   947  	var (
   948  		msg         = args.ToMessage(vmctx.BaseFee)
   949  		tx          = args.ToTransaction()
   950  		traceConfig *TraceConfig
   951  	)
   952  	if config != nil {
   953  		traceConfig = &config.TraceConfig
   954  	}
   955  	return api.traceTx(ctx, tx, msg, new(Context), vmctx, statedb, traceConfig)
   956  }
   957  
   958  // traceTx configures a new tracer according to the provided configuration, and
   959  // executes the given message in the provided environment. The return value will
   960  // be tracer dependent.
   961  func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
   962  	var (
   963  		tracer  *Tracer
   964  		err     error
   965  		timeout = defaultTraceTimeout
   966  		usedGas uint64
   967  	)
   968  	if config == nil {
   969  		config = &TraceConfig{}
   970  	}
   971  	// Default tracer is the struct logger
   972  	if config.Tracer == nil {
   973  		logger := logger.NewStructLogger(config.Config)
   974  		tracer = &Tracer{
   975  			Hooks:     logger.Hooks(),
   976  			GetResult: logger.GetResult,
   977  			Stop:      logger.Stop,
   978  		}
   979  	} else {
   980  		tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig)
   981  		if err != nil {
   982  			return nil, err
   983  		}
   984  	}
   985  	vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
   986  	statedb.SetLogger(tracer.Hooks)
   987  
   988  	// Define a meaningful timeout of a single transaction trace
   989  	if config.Timeout != nil {
   990  		if timeout, err = time.ParseDuration(*config.Timeout); err != nil {
   991  			return nil, err
   992  		}
   993  	}
   994  	deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
   995  	go func() {
   996  		<-deadlineCtx.Done()
   997  		if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
   998  			tracer.Stop(errors.New("execution timeout"))
   999  			// Stop evm execution. Note cancellation is not necessarily immediate.
  1000  			vmenv.Cancel()
  1001  		}
  1002  	}()
  1003  	defer cancel()
  1004  
  1005  	// Call Prepare to clear out the statedb access list
  1006  	statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
  1007  	_, err = core.ApplyTransactionWithEVM(message, api.backend.ChainConfig(), new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, vmenv)
  1008  	if err != nil {
  1009  		return nil, fmt.Errorf("tracing failed: %w", err)
  1010  	}
  1011  	return tracer.GetResult()
  1012  }
  1013  
  1014  // APIs return the collection of RPC services the tracer package offers.
  1015  func APIs(backend Backend) []rpc.API {
  1016  	// Append all the local APIs and return
  1017  	return []rpc.API{
  1018  		{
  1019  			Namespace: "debug",
  1020  			Service:   NewAPI(backend),
  1021  		},
  1022  	}
  1023  }
  1024  
  1025  // overrideConfig returns a copy of original with forks enabled by override enabled,
  1026  // along with a boolean that indicates whether the copy is canonical (equivalent to the original).
  1027  // Note: the Clique-part is _not_ deep copied
  1028  func overrideConfig(original *params.ChainConfig, override *params.ChainConfig) (*params.ChainConfig, bool) {
  1029  	copy := new(params.ChainConfig)
  1030  	*copy = *original
  1031  	canon := true
  1032  
  1033  	// Apply forks (after Berlin) to the copy.
  1034  	if block := override.BerlinBlock; block != nil {
  1035  		copy.BerlinBlock = block
  1036  		canon = false
  1037  	}
  1038  	if block := override.LondonBlock; block != nil {
  1039  		copy.LondonBlock = block
  1040  		canon = false
  1041  	}
  1042  	if block := override.ArrowGlacierBlock; block != nil {
  1043  		copy.ArrowGlacierBlock = block
  1044  		canon = false
  1045  	}
  1046  	if block := override.GrayGlacierBlock; block != nil {
  1047  		copy.GrayGlacierBlock = block
  1048  		canon = false
  1049  	}
  1050  	if block := override.MergeNetsplitBlock; block != nil {
  1051  		copy.MergeNetsplitBlock = block
  1052  		canon = false
  1053  	}
  1054  	if timestamp := override.ShanghaiTime; timestamp != nil {
  1055  		copy.ShanghaiTime = timestamp
  1056  		canon = false
  1057  	}
  1058  	if timestamp := override.CancunTime; timestamp != nil {
  1059  		copy.CancunTime = timestamp
  1060  		canon = false
  1061  	}
  1062  	if timestamp := override.PragueTime; timestamp != nil {
  1063  		copy.PragueTime = timestamp
  1064  		canon = false
  1065  	}
  1066  	if timestamp := override.VerkleTime; timestamp != nil {
  1067  		copy.VerkleTime = timestamp
  1068  		canon = false
  1069  	}
  1070  
  1071  	return copy, canon
  1072  }