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