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