github.com/dim4egster/coreth@v0.10.2/plugin/evm/vm.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package evm
     5  
     6  import (
     7  	"context"
     8  	"encoding/binary"
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  	"math/big"
    14  	"os"
    15  	"path/filepath"
    16  	"strings"
    17  	"sync"
    18  	"time"
    19  
    20  	avalanchegoMetrics "github.com/dim4egster/qmallgo/api/metrics"
    21  
    22  	"github.com/dim4egster/coreth/consensus/dummy"
    23  	corethConstants "github.com/dim4egster/coreth/constants"
    24  	"github.com/dim4egster/coreth/core"
    25  	"github.com/dim4egster/coreth/core/rawdb"
    26  	"github.com/dim4egster/coreth/core/state"
    27  	"github.com/dim4egster/coreth/core/types"
    28  	"github.com/dim4egster/coreth/eth"
    29  	"github.com/dim4egster/coreth/eth/ethconfig"
    30  	"github.com/dim4egster/coreth/ethdb"
    31  	corethPrometheus "github.com/dim4egster/coreth/metrics/prometheus"
    32  	"github.com/dim4egster/coreth/miner"
    33  	"github.com/dim4egster/coreth/node"
    34  	"github.com/dim4egster/coreth/params"
    35  	"github.com/dim4egster/coreth/peer"
    36  	"github.com/dim4egster/coreth/plugin/evm/message"
    37  	"github.com/dim4egster/coreth/rpc"
    38  	statesyncclient "github.com/dim4egster/coreth/sync/client"
    39  	"github.com/dim4egster/coreth/sync/client/stats"
    40  	"github.com/dim4egster/coreth/sync/handlers"
    41  	handlerstats "github.com/dim4egster/coreth/sync/handlers/stats"
    42  	"github.com/dim4egster/coreth/trie"
    43  
    44  	"github.com/prometheus/client_golang/prometheus"
    45  	// Force-load tracer engine to trigger registration
    46  	//
    47  	// We must import this package (not referenced elsewhere) so that the native "callTracer"
    48  	// is added to a map of client-accessible tracers. In geth, this is done
    49  	// inside of cmd/geth.
    50  	_ "github.com/dim4egster/coreth/eth/tracers/native"
    51  
    52  	"github.com/dim4egster/coreth/metrics"
    53  	"github.com/ethereum/go-ethereum/common"
    54  	"github.com/ethereum/go-ethereum/log"
    55  	"github.com/ethereum/go-ethereum/rlp"
    56  
    57  	avalancheRPC "github.com/gorilla/rpc/v2"
    58  
    59  	"github.com/dim4egster/qmallgo/cache"
    60  	"github.com/dim4egster/qmallgo/codec"
    61  	"github.com/dim4egster/qmallgo/codec/linearcodec"
    62  	"github.com/dim4egster/qmallgo/database"
    63  	"github.com/dim4egster/qmallgo/database/manager"
    64  	"github.com/dim4egster/qmallgo/database/prefixdb"
    65  	"github.com/dim4egster/qmallgo/database/versiondb"
    66  	"github.com/dim4egster/qmallgo/ids"
    67  	"github.com/dim4egster/qmallgo/snow"
    68  	"github.com/dim4egster/qmallgo/snow/choices"
    69  	"github.com/dim4egster/qmallgo/snow/consensus/snowman"
    70  	"github.com/dim4egster/qmallgo/snow/engine/snowman/block"
    71  	"github.com/dim4egster/qmallgo/utils/constants"
    72  	"github.com/dim4egster/qmallgo/utils/crypto"
    73  	"github.com/dim4egster/qmallgo/utils/formatting/address"
    74  	"github.com/dim4egster/qmallgo/utils/logging"
    75  	"github.com/dim4egster/qmallgo/utils/math"
    76  	"github.com/dim4egster/qmallgo/utils/perms"
    77  	"github.com/dim4egster/qmallgo/utils/profiler"
    78  	"github.com/dim4egster/qmallgo/utils/timer/mockable"
    79  	"github.com/dim4egster/qmallgo/utils/units"
    80  	"github.com/dim4egster/qmallgo/vms/components/avax"
    81  	"github.com/dim4egster/qmallgo/vms/components/chain"
    82  	"github.com/dim4egster/qmallgo/vms/secp256k1fx"
    83  
    84  	commonEng "github.com/dim4egster/qmallgo/snow/engine/common"
    85  
    86  	avalancheJSON "github.com/dim4egster/qmallgo/utils/json"
    87  )
    88  
    89  const (
    90  	x2cRateInt64       int64 = 1_000_000_000
    91  	x2cRateMinus1Int64 int64 = x2cRateInt64 - 1
    92  
    93  	// Prefixes for metrics gatherers
    94  	ethMetricsPrefix        = "eth"
    95  	chainStateMetricsPrefix = "chain_state"
    96  )
    97  
    98  var (
    99  	// x2cRate is the conversion rate between the smallest denomination on the X-Chain
   100  	// 1 nAVAX and the smallest denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei.
   101  	// This is only required for AVAX because the denomination of 1 AVAX is 9 decimal
   102  	// places on the X and P chains, but is 18 decimal places within the EVM.
   103  	x2cRate       = big.NewInt(x2cRateInt64)
   104  	x2cRateMinus1 = big.NewInt(x2cRateMinus1Int64)
   105  
   106  	_ block.ChainVM                  = &VM{}
   107  	_ block.StateSyncableVM          = &VM{}
   108  	_ block.HeightIndexedChainVM     = &VM{}
   109  	_ statesyncclient.EthBlockParser = &VM{}
   110  )
   111  
   112  const (
   113  	// Max time from current time allowed for blocks, before they're considered future blocks
   114  	// and fail verification
   115  	maxFutureBlockTime   = 10 * time.Second
   116  	maxUTXOsToFetch      = 1024
   117  	defaultMempoolSize   = 4096
   118  	codecVersion         = uint16(0)
   119  	secpFactoryCacheSize = 1024
   120  
   121  	decidedCacheSize    = 100
   122  	missingCacheSize    = 50
   123  	unverifiedCacheSize = 50
   124  
   125  	targetAtomicTxsSize = 40 * units.KiB
   126  )
   127  
   128  // Define the API endpoints for the VM
   129  const (
   130  	avaxEndpoint   = "/avax"
   131  	adminEndpoint  = "/admin"
   132  	ethRPCEndpoint = "/rpc"
   133  	ethWSEndpoint  = "/ws"
   134  )
   135  
   136  var (
   137  	// Set last accepted key to be longer than the keys used to store accepted block IDs.
   138  	lastAcceptedKey        = []byte("last_accepted_key")
   139  	acceptedPrefix         = []byte("snowman_accepted")
   140  	metadataPrefix         = []byte("metadata")
   141  	ethDBPrefix            = []byte("ethdb")
   142  	pruneRejectedBlocksKey = []byte("pruned_rejected_blocks")
   143  
   144  	// Prefixes for atomic trie
   145  	atomicTrieDBPrefix     = []byte("atomicTrieDB")
   146  	atomicTrieMetaDBPrefix = []byte("atomicTrieMetaDB")
   147  )
   148  
   149  var (
   150  	errEmptyBlock                     = errors.New("empty block")
   151  	errUnsupportedFXs                 = errors.New("unsupported feature extensions")
   152  	errInvalidBlock                   = errors.New("invalid block")
   153  	errInvalidAddr                    = errors.New("invalid hex address")
   154  	errInsufficientAtomicTxFee        = errors.New("atomic tx fee too low for atomic mempool")
   155  	errAssetIDMismatch                = errors.New("asset IDs in the input don't match the utxo")
   156  	errNoImportInputs                 = errors.New("tx has no imported inputs")
   157  	errInputsNotSortedUnique          = errors.New("inputs not sorted and unique")
   158  	errPublicKeySignatureMismatch     = errors.New("signature doesn't match public key")
   159  	errWrongChainID                   = errors.New("tx has wrong chain ID")
   160  	errInsufficientFunds              = errors.New("insufficient funds")
   161  	errNoExportOutputs                = errors.New("tx has no export outputs")
   162  	errOutputsNotSorted               = errors.New("tx outputs not sorted")
   163  	errOutputsNotSortedUnique         = errors.New("outputs not sorted and unique")
   164  	errOverflowExport                 = errors.New("overflow when computing export amount + txFee")
   165  	errInvalidNonce                   = errors.New("invalid nonce")
   166  	errConflictingAtomicInputs        = errors.New("invalid block due to conflicting atomic inputs")
   167  	errUnclesUnsupported              = errors.New("uncles unsupported")
   168  	errRejectedParent                 = errors.New("rejected parent")
   169  	errInsufficientFundsForFee        = errors.New("insufficient AVAX funds to pay transaction fee")
   170  	errNoEVMOutputs                   = errors.New("tx has no EVM outputs")
   171  	errNilBaseFeeApricotPhase3        = errors.New("nil base fee is invalid after apricotPhase3")
   172  	errNilExtDataGasUsedApricotPhase4 = errors.New("nil extDataGasUsed is invalid after apricotPhase4")
   173  	errNilBlockGasCostApricotPhase4   = errors.New("nil blockGasCost is invalid after apricotPhase4")
   174  	errConflictingAtomicTx            = errors.New("conflicting atomic tx present")
   175  	errTooManyAtomicTx                = errors.New("too many atomic tx")
   176  	errMissingAtomicTxs               = errors.New("cannot build a block with non-empty extra data and zero atomic transactions")
   177  	errInvalidExtraStateRoot          = errors.New("invalid ExtraStateRoot")
   178  )
   179  
   180  var originalStderr *os.File
   181  
   182  // legacyApiNames maps pre geth v1.10.20 api names to their updated counterparts.
   183  // used in attachEthService for backward configuration compatibility.
   184  var legacyApiNames = map[string]string{
   185  	"internal-public-eth":              "internal-eth",
   186  	"internal-public-blockchain":       "internal-blockchain",
   187  	"internal-public-transaction-pool": "internal-transaction",
   188  	"internal-public-tx-pool":          "internal-tx-pool",
   189  	"internal-public-debug":            "internal-debug",
   190  	"internal-private-debug":           "internal-debug",
   191  	"internal-public-account":          "internal-account",
   192  	"internal-private-personal":        "internal-personal",
   193  
   194  	"public-eth":        "eth",
   195  	"public-eth-filter": "eth-filter",
   196  	"private-admin":     "admin",
   197  	"public-debug":      "debug",
   198  	"private-debug":     "debug",
   199  }
   200  
   201  func init() {
   202  	// Preserve [os.Stderr] prior to the call in plugin/main.go to plugin.Serve(...).
   203  	// Preserving the log level allows us to update the root handler while writing to the original
   204  	// [os.Stderr] that is being piped through to the logger via the rpcchainvm.
   205  	originalStderr = os.Stderr
   206  }
   207  
   208  // VM implements the snowman.ChainVM interface
   209  type VM struct {
   210  	ctx *snow.Context
   211  	// *chain.State helps to implement the VM interface by wrapping blocks
   212  	// with an efficient caching layer.
   213  	*chain.State
   214  
   215  	config Config
   216  
   217  	chainID     *big.Int
   218  	networkID   uint64
   219  	genesisHash common.Hash
   220  	chainConfig *params.ChainConfig
   221  	ethConfig   ethconfig.Config
   222  
   223  	// pointers to eth constructs
   224  	eth        *eth.Ethereum
   225  	txPool     *core.TxPool
   226  	blockChain *core.BlockChain
   227  	miner      *miner.Miner
   228  
   229  	// [db] is the VM's current database managed by ChainState
   230  	db *versiondb.Database
   231  
   232  	// metadataDB is used to store one off keys.
   233  	metadataDB database.Database
   234  
   235  	// [chaindb] is the database supplied to the Ethereum backend
   236  	chaindb ethdb.Database
   237  
   238  	// [acceptedBlockDB] is the database to store the last accepted
   239  	// block.
   240  	acceptedBlockDB database.Database
   241  
   242  	toEngine chan<- commonEng.Message
   243  
   244  	syntacticBlockValidator BlockValidator
   245  
   246  	// [atomicTxRepository] maintains two indexes on accepted atomic txs.
   247  	// - txID to accepted atomic tx
   248  	// - block height to list of atomic txs accepted on block at that height
   249  	atomicTxRepository AtomicTxRepository
   250  	// [atomicTrie] maintains a merkle forest of [height]=>[atomic txs].
   251  	atomicTrie AtomicTrie
   252  	// [atomicBackend] abstracts verification and processing of atomic transactions
   253  	atomicBackend AtomicBackend
   254  
   255  	builder *blockBuilder
   256  
   257  	gossiper Gossiper
   258  
   259  	baseCodec codec.Registry
   260  	codec     codec.Manager
   261  	clock     mockable.Clock
   262  	mempool   *Mempool
   263  
   264  	shutdownChan chan struct{}
   265  	shutdownWg   sync.WaitGroup
   266  
   267  	fx          secp256k1fx.Fx
   268  	secpFactory crypto.FactorySECP256K1R
   269  
   270  	// Continuous Profiler
   271  	profiler profiler.ContinuousProfiler
   272  
   273  	peer.Network
   274  	client       peer.NetworkClient
   275  	networkCodec codec.Manager
   276  
   277  	// Metrics
   278  	multiGatherer avalanchegoMetrics.MultiGatherer
   279  
   280  	bootstrapped bool
   281  	IsPlugin     bool
   282  
   283  	logger CorethLogger
   284  	// State sync server and client
   285  	StateSyncServer
   286  	StateSyncClient
   287  }
   288  
   289  // Codec implements the secp256k1fx interface
   290  func (vm *VM) Codec() codec.Manager { return vm.codec }
   291  
   292  // CodecRegistry implements the secp256k1fx interface
   293  func (vm *VM) CodecRegistry() codec.Registry { return vm.baseCodec }
   294  
   295  // Clock implements the secp256k1fx interface
   296  func (vm *VM) Clock() *mockable.Clock { return &vm.clock }
   297  
   298  // Logger implements the secp256k1fx interface
   299  func (vm *VM) Logger() logging.Logger { return vm.ctx.Log }
   300  
   301  /*
   302   ******************************************************************************
   303   ********************************* Snowman API ********************************
   304   ******************************************************************************
   305   */
   306  
   307  // implements SnowmanPlusPlusVM interface
   308  func (vm *VM) GetActivationTime() time.Time {
   309  	return time.Unix(vm.chainConfig.ApricotPhase4BlockTimestamp.Int64(), 0)
   310  }
   311  
   312  // Initialize implements the snowman.ChainVM interface
   313  func (vm *VM) Initialize(
   314  	ctx *snow.Context,
   315  	dbManager manager.Manager,
   316  	genesisBytes []byte,
   317  	upgradeBytes []byte,
   318  	configBytes []byte,
   319  	toEngine chan<- commonEng.Message,
   320  	fxs []*commonEng.Fx,
   321  	appSender commonEng.AppSender,
   322  ) error {
   323  	vm.config.SetDefaults()
   324  	if len(configBytes) > 0 {
   325  		if err := json.Unmarshal(configBytes, &vm.config); err != nil {
   326  			return fmt.Errorf("failed to unmarshal config %s: %w", string(configBytes), err)
   327  		}
   328  	}
   329  	if err := vm.config.Validate(); err != nil {
   330  		return err
   331  	}
   332  
   333  	vm.ctx = ctx
   334  
   335  	// Create logger
   336  	alias, err := vm.ctx.BCLookup.PrimaryAlias(vm.ctx.ChainID)
   337  	if err != nil {
   338  		alias = vm.ctx.ChainID.String()
   339  	}
   340  
   341  	var writer io.Writer = vm.ctx.Log
   342  	if vm.IsPlugin {
   343  		writer = originalStderr
   344  	}
   345  
   346  	corethLogger, err := InitLogger(alias, vm.config.LogLevel, vm.config.LogJSONFormat, writer)
   347  	if err != nil {
   348  		return fmt.Errorf("failed to initialize logger due to: %w ", err)
   349  	}
   350  	vm.logger = corethLogger
   351  
   352  	log.Info("Initializing Coreth VM", "Version", Version, "Config", vm.config)
   353  
   354  	if len(fxs) > 0 {
   355  		return errUnsupportedFXs
   356  	}
   357  
   358  	// Enable debug-level metrics that might impact runtime performance
   359  	metrics.EnabledExpensive = vm.config.MetricsExpensiveEnabled
   360  
   361  	vm.toEngine = toEngine
   362  	vm.shutdownChan = make(chan struct{}, 1)
   363  	baseDB := dbManager.Current().Database
   364  	// Use NewNested rather than New so that the structure of the database
   365  	// remains the same regardless of the provided baseDB type.
   366  	vm.chaindb = Database{prefixdb.NewNested(ethDBPrefix, baseDB)}
   367  	vm.db = versiondb.New(baseDB)
   368  	vm.acceptedBlockDB = prefixdb.New(acceptedPrefix, vm.db)
   369  	vm.metadataDB = prefixdb.New(metadataPrefix, vm.db)
   370  	g := new(core.Genesis)
   371  	if err := json.Unmarshal(genesisBytes, g); err != nil {
   372  		return err
   373  	}
   374  
   375  	var extDataHashes map[common.Hash]common.Hash
   376  	// Set the chain config for mainnet/fuji chain IDs
   377  	switch {
   378  	case g.Config.ChainID.Cmp(params.AvalancheMainnetChainID) == 0:
   379  		g.Config = params.AvalancheMainnetChainConfig
   380  		extDataHashes = mainnetExtDataHashes
   381  	case g.Config.ChainID.Cmp(params.AvalancheFujiChainID) == 0:
   382  		g.Config = params.AvalancheFujiChainConfig
   383  		extDataHashes = fujiExtDataHashes
   384  	case g.Config.ChainID.Cmp(params.AvalancheLocalChainID) == 0:
   385  		g.Config = params.AvalancheLocalChainConfig
   386  	}
   387  	vm.syntacticBlockValidator = NewBlockValidator(extDataHashes)
   388  
   389  	// Ensure that non-standard commit interval is only allowed for the local network
   390  	if g.Config.ChainID.Cmp(params.AvalancheLocalChainID) != 0 {
   391  		if vm.config.CommitInterval != defaultCommitInterval {
   392  			return fmt.Errorf("cannot start non-local network with commit interval %d", vm.config.CommitInterval)
   393  		}
   394  		if vm.config.StateSyncCommitInterval != defaultSyncableCommitInterval {
   395  			return fmt.Errorf("cannot start non-local network with syncable interval %d", vm.config.StateSyncCommitInterval)
   396  		}
   397  	}
   398  
   399  	// Free the memory of the extDataHash map that is not used (i.e. if mainnet
   400  	// config, free fuji)
   401  	fujiExtDataHashes = nil
   402  	mainnetExtDataHashes = nil
   403  
   404  	vm.chainID = g.Config.ChainID
   405  
   406  	vm.ethConfig = ethconfig.NewDefaultConfig()
   407  	vm.ethConfig.Genesis = g
   408  	vm.ethConfig.NetworkId = vm.chainID.Uint64()
   409  
   410  	// Set minimum price for mining and default gas price oracle value to the min
   411  	// gas price to prevent so transactions and blocks all use the correct fees
   412  	vm.ethConfig.RPCGasCap = vm.config.RPCGasCap
   413  	vm.ethConfig.RPCEVMTimeout = vm.config.APIMaxDuration.Duration
   414  	vm.ethConfig.RPCTxFeeCap = vm.config.RPCTxFeeCap
   415  	vm.ethConfig.TxPool.NoLocals = !vm.config.LocalTxsEnabled
   416  	vm.ethConfig.AllowUnfinalizedQueries = vm.config.AllowUnfinalizedQueries
   417  	vm.ethConfig.AllowUnprotectedTxs = vm.config.AllowUnprotectedTxs
   418  	vm.ethConfig.Preimages = vm.config.Preimages
   419  	vm.ethConfig.Pruning = vm.config.Pruning
   420  	vm.ethConfig.AcceptorQueueLimit = vm.config.AcceptorQueueLimit
   421  	vm.ethConfig.PopulateMissingTries = vm.config.PopulateMissingTries
   422  	vm.ethConfig.PopulateMissingTriesParallelism = vm.config.PopulateMissingTriesParallelism
   423  	vm.ethConfig.AllowMissingTries = vm.config.AllowMissingTries
   424  	vm.ethConfig.SnapshotDelayInit = vm.config.StateSyncEnabled
   425  	vm.ethConfig.SnapshotAsync = vm.config.SnapshotAsync
   426  	vm.ethConfig.SnapshotVerify = vm.config.SnapshotVerify
   427  	vm.ethConfig.OfflinePruning = vm.config.OfflinePruning
   428  	vm.ethConfig.OfflinePruningBloomFilterSize = vm.config.OfflinePruningBloomFilterSize
   429  	vm.ethConfig.OfflinePruningDataDirectory = vm.config.OfflinePruningDataDirectory
   430  	vm.ethConfig.CommitInterval = vm.config.CommitInterval
   431  
   432  	// Create directory for offline pruning
   433  	if len(vm.ethConfig.OfflinePruningDataDirectory) != 0 {
   434  		if err := os.MkdirAll(vm.ethConfig.OfflinePruningDataDirectory, perms.ReadWriteExecute); err != nil {
   435  			log.Error("failed to create offline pruning data directory", "error", err)
   436  			return err
   437  		}
   438  	}
   439  
   440  	vm.genesisHash = vm.ethConfig.Genesis.ToBlock(nil).Hash()
   441  
   442  	vm.chainConfig = g.Config
   443  	vm.networkID = vm.ethConfig.NetworkId
   444  	vm.secpFactory = crypto.FactorySECP256K1R{Cache: cache.LRU{Size: secpFactoryCacheSize}}
   445  
   446  	vm.codec = Codec
   447  
   448  	// TODO: read size from settings
   449  	vm.mempool = NewMempool(ctx.AVAXAssetID, defaultMempoolSize)
   450  
   451  	lastAcceptedHash, lastAcceptedHeight, err := vm.readLastAccepted()
   452  	if err != nil {
   453  		return err
   454  	}
   455  	log.Info(fmt.Sprintf("lastAccepted = %s", lastAcceptedHash))
   456  
   457  	if err := vm.initializeMetrics(); err != nil {
   458  		return err
   459  	}
   460  
   461  	// initialize peer network
   462  	vm.networkCodec = message.Codec
   463  	vm.Network = peer.NewNetwork(appSender, vm.networkCodec, ctx.NodeID, vm.config.MaxOutboundActiveRequests)
   464  	vm.client = peer.NewNetworkClient(vm.Network)
   465  
   466  	if err := vm.initializeChain(lastAcceptedHash); err != nil {
   467  		return err
   468  	}
   469  	// initialize bonus blocks on mainnet
   470  	var (
   471  		bonusBlockHeights     map[uint64]ids.ID
   472  		canonicalBlockHeights []uint64
   473  	)
   474  	if vm.chainID.Cmp(params.AvalancheMainnetChainID) == 0 {
   475  		bonusBlockHeights = bonusBlockMainnetHeights
   476  		canonicalBlockHeights = canonicalBlockMainnetHeights
   477  	}
   478  
   479  	// initialize atomic repository
   480  	vm.atomicTxRepository, err = NewAtomicTxRepository(
   481  		vm.db, vm.codec, lastAcceptedHeight,
   482  		bonusBlockHeights, canonicalBlockHeights,
   483  		vm.getAtomicTxFromPreApricot5BlockByHeight,
   484  	)
   485  	if err != nil {
   486  		return fmt.Errorf("failed to create atomic repository: %w", err)
   487  	}
   488  	vm.atomicBackend, err = NewAtomicBackend(
   489  		vm.db, vm.ctx.SharedMemory, bonusBlockHeights, vm.atomicTxRepository, lastAcceptedHeight, lastAcceptedHash, vm.config.CommitInterval,
   490  	)
   491  	if err != nil {
   492  		return fmt.Errorf("failed to create atomic backend: %w", err)
   493  	}
   494  	vm.atomicTrie = vm.atomicBackend.AtomicTrie()
   495  
   496  	go vm.ctx.Log.RecoverAndPanic(vm.startContinuousProfiler)
   497  
   498  	// The Codec explicitly registers the types it requires from the secp256k1fx
   499  	// so [vm.baseCodec] is a dummy codec use to fulfill the secp256k1fx VM
   500  	// interface. The fx will register all of its types, which can be safely
   501  	// ignored by the VM's codec.
   502  	vm.baseCodec = linearcodec.NewDefault()
   503  
   504  	if err := vm.fx.Initialize(vm); err != nil {
   505  		return err
   506  	}
   507  
   508  	vm.initializeStateSyncServer()
   509  	return vm.initializeStateSyncClient(lastAcceptedHeight)
   510  }
   511  
   512  func (vm *VM) initializeMetrics() error {
   513  	vm.multiGatherer = avalanchegoMetrics.NewMultiGatherer()
   514  	// If metrics are enabled, register the default metrics regitry
   515  	if metrics.Enabled {
   516  		gatherer := corethPrometheus.Gatherer(metrics.DefaultRegistry)
   517  		if err := vm.multiGatherer.Register(ethMetricsPrefix, gatherer); err != nil {
   518  			return err
   519  		}
   520  		// Register [multiGatherer] after registerers have been registered to it
   521  		if err := vm.ctx.Metrics.Register(vm.multiGatherer); err != nil {
   522  			return err
   523  		}
   524  	}
   525  	return nil
   526  }
   527  
   528  func (vm *VM) initializeChain(lastAcceptedHash common.Hash) error {
   529  	nodecfg := &node.Config{
   530  		CorethVersion:         Version,
   531  		KeyStoreDir:           vm.config.KeystoreDirectory,
   532  		ExternalSigner:        vm.config.KeystoreExternalSigner,
   533  		InsecureUnlockAllowed: vm.config.KeystoreInsecureUnlockAllowed,
   534  	}
   535  	node, err := node.New(nodecfg)
   536  	if err != nil {
   537  		return err
   538  	}
   539  	vm.eth, err = eth.New(
   540  		node,
   541  		&vm.ethConfig,
   542  		vm.createConsensusCallbacks(),
   543  		vm.chaindb,
   544  		vm.config.EthBackendSettings(),
   545  		lastAcceptedHash,
   546  		&vm.clock,
   547  	)
   548  	if err != nil {
   549  		return err
   550  	}
   551  	vm.eth.SetEtherbase(corethConstants.BlackholeAddr)
   552  	vm.txPool = vm.eth.TxPool()
   553  	vm.blockChain = vm.eth.BlockChain()
   554  	vm.miner = vm.eth.Miner()
   555  
   556  	// start goroutines to update the tx pool gas minimum gas price when upgrades go into effect
   557  	vm.handleGasPriceUpdates()
   558  
   559  	vm.eth.Start()
   560  	return vm.initChainState(vm.blockChain.LastAcceptedBlock())
   561  }
   562  
   563  // initializeStateSyncClient initializes the client for performing state sync.
   564  // If state sync is disabled, this function will wipe any ongoing summary from
   565  // disk to ensure that we do not continue syncing from an invalid snapshot.
   566  func (vm *VM) initializeStateSyncClient(lastAcceptedHeight uint64) error {
   567  	// parse nodeIDs from state sync IDs in vm config
   568  	var stateSyncIDs []ids.NodeID
   569  	if vm.config.StateSyncEnabled && len(vm.config.StateSyncIDs) > 0 {
   570  		nodeIDs := strings.Split(vm.config.StateSyncIDs, ",")
   571  		stateSyncIDs = make([]ids.NodeID, len(nodeIDs))
   572  		for i, nodeIDString := range nodeIDs {
   573  			nodeID, err := ids.NodeIDFromString(nodeIDString)
   574  			if err != nil {
   575  				return fmt.Errorf("failed to parse %s as NodeID: %w", nodeIDString, err)
   576  			}
   577  			stateSyncIDs[i] = nodeID
   578  		}
   579  	}
   580  
   581  	vm.StateSyncClient = NewStateSyncClient(&stateSyncClientConfig{
   582  		chain: vm.eth,
   583  		state: vm.State,
   584  		client: statesyncclient.NewClient(
   585  			&statesyncclient.ClientConfig{
   586  				NetworkClient:    vm.client,
   587  				Codec:            vm.networkCodec,
   588  				Stats:            stats.NewClientSyncerStats(),
   589  				StateSyncNodeIDs: stateSyncIDs,
   590  				BlockParser:      vm,
   591  			},
   592  		),
   593  		enabled:            vm.config.StateSyncEnabled,
   594  		skipResume:         vm.config.StateSyncSkipResume,
   595  		stateSyncMinBlocks: vm.config.StateSyncMinBlocks,
   596  		lastAcceptedHeight: lastAcceptedHeight, // TODO clean up how this is passed around
   597  		chaindb:            vm.chaindb,
   598  		metadataDB:         vm.metadataDB,
   599  		acceptedBlockDB:    vm.acceptedBlockDB,
   600  		db:                 vm.db,
   601  		atomicBackend:      vm.atomicBackend,
   602  		toEngine:           vm.toEngine,
   603  	})
   604  
   605  	// If StateSync is disabled, clear any ongoing summary so that we will not attempt to resume
   606  	// sync using a snapshot that has been modified by the node running normal operations.
   607  	if !vm.config.StateSyncEnabled {
   608  		return vm.StateSyncClient.StateSyncClearOngoingSummary()
   609  	}
   610  
   611  	return nil
   612  }
   613  
   614  // initializeStateSyncServer should be called after [vm.chain] is initialized.
   615  func (vm *VM) initializeStateSyncServer() {
   616  	vm.StateSyncServer = NewStateSyncServer(&stateSyncServerConfig{
   617  		Chain:            vm.blockChain,
   618  		AtomicTrie:       vm.atomicTrie,
   619  		SyncableInterval: vm.config.StateSyncCommitInterval,
   620  	})
   621  
   622  	vm.setAppRequestHandlers()
   623  }
   624  
   625  func (vm *VM) initChainState(lastAcceptedBlock *types.Block) error {
   626  	block, err := vm.newBlock(lastAcceptedBlock)
   627  	if err != nil {
   628  		return fmt.Errorf("failed to create block wrapper for the last accepted block: %w", err)
   629  	}
   630  	block.status = choices.Accepted
   631  
   632  	config := &chain.Config{
   633  		DecidedCacheSize:    decidedCacheSize,
   634  		MissingCacheSize:    missingCacheSize,
   635  		UnverifiedCacheSize: unverifiedCacheSize,
   636  		GetBlockIDAtHeight:  vm.GetBlockIDAtHeight,
   637  		GetBlock:            vm.getBlock,
   638  		UnmarshalBlock:      vm.parseBlock,
   639  		BuildBlock:          vm.buildBlock,
   640  		LastAcceptedBlock:   block,
   641  	}
   642  
   643  	// Register chain state metrics
   644  	chainStateRegisterer := prometheus.NewRegistry()
   645  	state, err := chain.NewMeteredState(chainStateRegisterer, config)
   646  	if err != nil {
   647  		return fmt.Errorf("could not create metered state: %w", err)
   648  	}
   649  	vm.State = state
   650  
   651  	return vm.multiGatherer.Register(chainStateMetricsPrefix, chainStateRegisterer)
   652  }
   653  
   654  func (vm *VM) createConsensusCallbacks() *dummy.ConsensusCallbacks {
   655  	return &dummy.ConsensusCallbacks{
   656  		OnFinalizeAndAssemble: vm.onFinalizeAndAssemble,
   657  		OnExtraStateChange:    vm.onExtraStateChange,
   658  	}
   659  }
   660  
   661  func (vm *VM) preBatchOnFinalizeAndAssemble(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, *big.Int, *big.Int, error) {
   662  	for {
   663  		tx, exists := vm.mempool.NextTx()
   664  		if !exists {
   665  			break
   666  		}
   667  		// Take a snapshot of [state] before calling verifyTx so that if the transaction fails verification
   668  		// we can revert to [snapshot].
   669  		// Note: snapshot is taken inside the loop because you cannot revert to the same snapshot more than
   670  		// once.
   671  		snapshot := state.Snapshot()
   672  		rules := vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time))
   673  		if err := vm.verifyTx(tx, header.ParentHash, header.BaseFee, state, rules); err != nil {
   674  			// Discard the transaction from the mempool on failed verification.
   675  			vm.mempool.DiscardCurrentTx(tx.ID())
   676  			state.RevertToSnapshot(snapshot)
   677  			continue
   678  		}
   679  
   680  		atomicTxBytes, err := vm.codec.Marshal(codecVersion, tx)
   681  		if err != nil {
   682  			// Discard the transaction from the mempool and error if the transaction
   683  			// cannot be marshalled. This should never happen.
   684  			vm.mempool.DiscardCurrentTx(tx.ID())
   685  			return nil, nil, nil, fmt.Errorf("failed to marshal atomic transaction %s due to %w", tx.ID(), err)
   686  		}
   687  		var contribution, gasUsed *big.Int
   688  		if rules.IsApricotPhase4 {
   689  			contribution, gasUsed, err = tx.BlockFeeContribution(rules.IsApricotPhase5, vm.ctx.AVAXAssetID, header.BaseFee)
   690  			if err != nil {
   691  				return nil, nil, nil, err
   692  			}
   693  		}
   694  		return atomicTxBytes, contribution, gasUsed, nil
   695  	}
   696  
   697  	if len(txs) == 0 {
   698  		// this could happen due to the async logic of geth tx pool
   699  		return nil, nil, nil, errEmptyBlock
   700  	}
   701  
   702  	return nil, nil, nil, nil
   703  }
   704  
   705  // assumes that we are in at least Apricot Phase 5.
   706  func (vm *VM) postBatchOnFinalizeAndAssemble(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, *big.Int, *big.Int, error) {
   707  	var (
   708  		batchAtomicTxs    []*Tx
   709  		batchAtomicUTXOs  ids.Set
   710  		batchContribution *big.Int = new(big.Int).Set(common.Big0)
   711  		batchGasUsed      *big.Int = new(big.Int).Set(common.Big0)
   712  		rules                      = vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time))
   713  		size              int
   714  	)
   715  
   716  	for {
   717  		tx, exists := vm.mempool.NextTx()
   718  		if !exists {
   719  			break
   720  		}
   721  
   722  		// Ensure that adding [tx] to the block will not exceed the block size soft limit.
   723  		txSize := len(tx.SignedBytes())
   724  		if size+txSize > targetAtomicTxsSize {
   725  			vm.mempool.CancelCurrentTx(tx.ID())
   726  			break
   727  		}
   728  
   729  		var (
   730  			txGasUsed, txContribution *big.Int
   731  			err                       error
   732  		)
   733  
   734  		// Note: we do not need to check if we are in at least ApricotPhase4 here because
   735  		// we assume that this function will only be called when the block is in at least
   736  		// ApricotPhase5.
   737  		txContribution, txGasUsed, err = tx.BlockFeeContribution(true, vm.ctx.AVAXAssetID, header.BaseFee)
   738  		if err != nil {
   739  			return nil, nil, nil, err
   740  		}
   741  		// ensure [gasUsed] + [batchGasUsed] doesnt exceed the [atomicGasLimit]
   742  		if totalGasUsed := new(big.Int).Add(batchGasUsed, txGasUsed); totalGasUsed.Cmp(params.AtomicGasLimit) > 0 {
   743  			// Send [tx] back to the mempool's tx heap.
   744  			vm.mempool.CancelCurrentTx(tx.ID())
   745  			break
   746  		}
   747  
   748  		if batchAtomicUTXOs.Overlaps(tx.InputUTXOs()) {
   749  			// Discard the transaction from the mempool since it will fail verification
   750  			// after this block has been accepted.
   751  			// Note: if the proposed block is not accepted, the transaction may still be
   752  			// valid, but we discard it early here based on the assumption that the proposed
   753  			// block will most likely be accepted.
   754  			// Discard the transaction from the mempool on failed verification.
   755  			vm.mempool.DiscardCurrentTx(tx.ID())
   756  			continue
   757  		}
   758  
   759  		snapshot := state.Snapshot()
   760  		if err := vm.verifyTx(tx, header.ParentHash, header.BaseFee, state, rules); err != nil {
   761  			// Discard the transaction from the mempool and reset the state to [snapshot]
   762  			// if it fails verification here.
   763  			// Note: prior to this point, we have not modified [state] so there is no need to
   764  			// revert to a snapshot if we discard the transaction prior to this point.
   765  			vm.mempool.DiscardCurrentTx(tx.ID())
   766  			state.RevertToSnapshot(snapshot)
   767  			continue
   768  		}
   769  
   770  		batchAtomicTxs = append(batchAtomicTxs, tx)
   771  		batchAtomicUTXOs.Union(tx.InputUTXOs())
   772  		// Add the [txGasUsed] to the [batchGasUsed] when the [tx] has passed verification
   773  		batchGasUsed.Add(batchGasUsed, txGasUsed)
   774  		batchContribution.Add(batchContribution, txContribution)
   775  		size += txSize
   776  	}
   777  
   778  	// In Clementine the block header must include the atomic trie root.
   779  	if rules.IsClementine {
   780  		// Pass common.Hash{} as the current block's hash to the atomic backend, this avoids
   781  		// pinning changes to the atomic trie in memory, as we are still computing the header
   782  		// for this block and don't have its hash yet. Here we calculate the root of the atomic
   783  		// trie to store in the block header.
   784  		atomicTrieRoot, err := vm.atomicBackend.InsertTxs(common.Hash{}, header.Number.Uint64(), header.ParentHash, batchAtomicTxs)
   785  		if err != nil {
   786  			return nil, nil, nil, err
   787  		}
   788  		header.ExtraStateRoot = atomicTrieRoot
   789  	}
   790  
   791  	// If there is a non-zero number of transactions, marshal them and return the byte slice
   792  	// for the block's extra data along with the contribution and gas used.
   793  	if len(batchAtomicTxs) > 0 {
   794  		atomicTxBytes, err := vm.codec.Marshal(codecVersion, batchAtomicTxs)
   795  		if err != nil {
   796  			// If we fail to marshal the batch of atomic transactions for any reason,
   797  			// discard the entire set of current transactions.
   798  			vm.mempool.DiscardCurrentTxs()
   799  			return nil, nil, nil, fmt.Errorf("failed to marshal batch of atomic transactions due to %w", err)
   800  		}
   801  		return atomicTxBytes, batchContribution, batchGasUsed, nil
   802  	}
   803  
   804  	// If there are no regular transactions and there were also no atomic transactions to be included,
   805  	// then the block is empty and should be considered invalid.
   806  	if len(txs) == 0 {
   807  		// this could happen due to the async logic of geth tx pool
   808  		return nil, nil, nil, errEmptyBlock
   809  	}
   810  
   811  	// If there are no atomic transactions, but there is a non-zero number of regular transactions, then
   812  	// we return a nil slice with no contribution from the atomic transactions and a nil error.
   813  	return nil, nil, nil, nil
   814  }
   815  
   816  func (vm *VM) onFinalizeAndAssemble(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, *big.Int, *big.Int, error) {
   817  	if !vm.chainConfig.IsApricotPhase5(new(big.Int).SetUint64(header.Time)) {
   818  		return vm.preBatchOnFinalizeAndAssemble(header, state, txs)
   819  	}
   820  	return vm.postBatchOnFinalizeAndAssemble(header, state, txs)
   821  }
   822  
   823  func (vm *VM) onExtraStateChange(block *types.Block, state *state.StateDB) (*big.Int, *big.Int, error) {
   824  	var (
   825  		batchContribution *big.Int = big.NewInt(0)
   826  		batchGasUsed      *big.Int = big.NewInt(0)
   827  		header                     = block.Header()
   828  		rules                      = vm.chainConfig.AvalancheRules(header.Number, new(big.Int).SetUint64(header.Time))
   829  	)
   830  
   831  	txs, err := ExtractAtomicTxs(block.ExtData(), rules.IsApricotPhase5, vm.codec)
   832  	if err != nil {
   833  		return nil, nil, err
   834  	}
   835  
   836  	// If [atomicBackend] is nil, the VM is still initializing and is reprocessing accepted blocks.
   837  	if vm.atomicBackend != nil {
   838  		if vm.atomicBackend.IsBonus(block.NumberU64(), block.Hash()) {
   839  			log.Info("skipping atomic tx verification on bonus block", "block", block.Hash())
   840  		} else {
   841  			// Verify [txs] do not conflict with themselves or ancestor blocks.
   842  			if err := vm.verifyTxs(txs, block.ParentHash(), block.BaseFee(), block.NumberU64(), rules); err != nil {
   843  				return nil, nil, err
   844  			}
   845  		}
   846  		// Update the atomic backend with [txs] from this block.
   847  		atomicRoot, err := vm.atomicBackend.InsertTxs(block.Hash(), block.NumberU64(), block.ParentHash(), txs)
   848  		if err != nil {
   849  			return nil, nil, err
   850  		}
   851  		if rules.IsClementine {
   852  			// In Clementine, the atomic trie root should be in ExtraStateRoot.
   853  			if header.ExtraStateRoot != atomicRoot {
   854  				return nil, nil, fmt.Errorf(
   855  					"%w: (expected %s) (got %s)", errInvalidExtraStateRoot, header.ExtraStateRoot, atomicRoot,
   856  				)
   857  			}
   858  		}
   859  	}
   860  
   861  	// If there are no transactions, we can return early.
   862  	if len(txs) == 0 {
   863  		return nil, nil, nil
   864  	}
   865  
   866  	for _, tx := range txs {
   867  		if err := tx.UnsignedAtomicTx.EVMStateTransfer(vm.ctx, state); err != nil {
   868  			return nil, nil, err
   869  		}
   870  		// If ApricotPhase4 is enabled, calculate the block fee contribution
   871  		if rules.IsApricotPhase4 {
   872  			contribution, gasUsed, err := tx.BlockFeeContribution(rules.IsApricotPhase5, vm.ctx.AVAXAssetID, block.BaseFee())
   873  			if err != nil {
   874  				return nil, nil, err
   875  			}
   876  
   877  			batchContribution.Add(batchContribution, contribution)
   878  			batchGasUsed.Add(batchGasUsed, gasUsed)
   879  		}
   880  
   881  		// If ApricotPhase5 is enabled, enforce that the atomic gas used does not exceed the
   882  		// atomic gas limit.
   883  		if rules.IsApricotPhase5 {
   884  			// Ensure that [tx] does not push [block] above the atomic gas limit.
   885  			if batchGasUsed.Cmp(params.AtomicGasLimit) == 1 {
   886  				return nil, nil, fmt.Errorf("atomic gas used (%d) by block (%s), exceeds atomic gas limit (%d)", batchGasUsed, block.Hash().Hex(), params.AtomicGasLimit)
   887  			}
   888  		}
   889  	}
   890  	return batchContribution, batchGasUsed, nil
   891  }
   892  
   893  func (vm *VM) pruneChain() error {
   894  	if !vm.config.Pruning {
   895  		return nil
   896  	}
   897  	pruned, err := vm.db.Has(pruneRejectedBlocksKey)
   898  	if err != nil {
   899  		return fmt.Errorf("failed to check if the VM has pruned rejected blocks: %w", err)
   900  	}
   901  	if pruned {
   902  		return nil
   903  	}
   904  
   905  	lastAcceptedHeight := vm.LastAcceptedBlock().Height()
   906  	if err := vm.blockChain.RemoveRejectedBlocks(0, lastAcceptedHeight); err != nil {
   907  		return err
   908  	}
   909  	heightBytes := make([]byte, 8)
   910  	binary.PutUvarint(heightBytes, lastAcceptedHeight)
   911  	if err := vm.db.Put(pruneRejectedBlocksKey, heightBytes); err != nil {
   912  		return err
   913  	}
   914  	return vm.db.Commit()
   915  }
   916  
   917  func (vm *VM) SetState(state snow.State) error {
   918  	switch state {
   919  	case snow.StateSyncing:
   920  		vm.bootstrapped = false
   921  		return nil
   922  	case snow.Bootstrapping:
   923  		vm.bootstrapped = false
   924  		if err := vm.StateSyncClient.Error(); err != nil {
   925  			return err
   926  		}
   927  		return vm.fx.Bootstrapping()
   928  	case snow.NormalOp:
   929  		// Initialize goroutines related to block building once we enter normal operation as there is no need to handle mempool gossip before this point.
   930  		vm.initBlockBuilding()
   931  		vm.bootstrapped = true
   932  		return vm.fx.Bootstrapped()
   933  	default:
   934  		return snow.ErrUnknownState
   935  	}
   936  }
   937  
   938  // initBlockBuilding starts goroutines to manage block building
   939  func (vm *VM) initBlockBuilding() {
   940  	// NOTE: gossip network must be initialized first otherwise ETH tx gossip will not work.
   941  	gossipStats := NewGossipStats()
   942  	vm.gossiper = vm.createGossiper(gossipStats)
   943  	vm.builder = vm.NewBlockBuilder(vm.toEngine)
   944  	vm.builder.awaitSubmittedTxs()
   945  	vm.Network.SetGossipHandler(NewGossipHandler(vm, gossipStats))
   946  }
   947  
   948  // setAppRequestHandlers sets the request handlers for the VM to serve state sync
   949  // requests.
   950  func (vm *VM) setAppRequestHandlers() {
   951  	// Create separate EVM TrieDB (read only) for serving leafs requests.
   952  	// We create a separate TrieDB here, so that it has a separate cache from the one
   953  	// used by the node when processing blocks.
   954  	evmTrieDB := trie.NewDatabaseWithConfig(
   955  		vm.chaindb,
   956  		&trie.Config{
   957  			Cache: vm.config.StateSyncServerTrieCache,
   958  		},
   959  	)
   960  	syncRequestHandler := handlers.NewSyncHandler(
   961  		vm.blockChain,
   962  		evmTrieDB,
   963  		vm.atomicTrie.TrieDB(),
   964  		vm.networkCodec,
   965  		handlerstats.NewHandlerStats(metrics.Enabled),
   966  	)
   967  	vm.Network.SetRequestHandler(syncRequestHandler)
   968  }
   969  
   970  // Shutdown implements the snowman.ChainVM interface
   971  func (vm *VM) Shutdown() error {
   972  	if vm.ctx == nil {
   973  		return nil
   974  	}
   975  	vm.Network.Shutdown()
   976  	if err := vm.StateSyncClient.Shutdown(); err != nil {
   977  		log.Error("error stopping state syncer", "err", err)
   978  	}
   979  	close(vm.shutdownChan)
   980  	vm.eth.Stop()
   981  	vm.shutdownWg.Wait()
   982  	return nil
   983  }
   984  
   985  // buildBlock builds a block to be wrapped by ChainState
   986  func (vm *VM) buildBlock() (snowman.Block, error) {
   987  	block, err := vm.miner.GenerateBlock()
   988  	vm.builder.handleGenerateBlock()
   989  	if err != nil {
   990  		vm.mempool.CancelCurrentTxs()
   991  		return nil, err
   992  	}
   993  
   994  	// Note: the status of block is set by ChainState
   995  	blk, err := vm.newBlock(block)
   996  	if err != nil {
   997  		vm.mempool.DiscardCurrentTxs()
   998  		return nil, err
   999  	}
  1000  	if err != nil {
  1001  		return nil, err
  1002  	}
  1003  
  1004  	// Verify is called on a non-wrapped block here, such that this
  1005  	// does not add [blk] to the processing blocks map in ChainState.
  1006  	//
  1007  	// TODO cache verification since Verify() will be called by the
  1008  	// consensus engine as well.
  1009  	//
  1010  	// Note: this is only called when building a new block, so caching
  1011  	// verification will only be a significant optimization for nodes
  1012  	// that produce a large number of blocks.
  1013  	// We call verify without writes here to avoid generating a reference
  1014  	// to the blk state root in the triedb when we are going to call verify
  1015  	// again from the consensus engine with writes enabled.
  1016  	if err := blk.verify(false /*=writes*/); err != nil {
  1017  		vm.mempool.CancelCurrentTxs()
  1018  		return nil, fmt.Errorf("block failed verification due to: %w", err)
  1019  	}
  1020  
  1021  	log.Debug(fmt.Sprintf("Built block %s", blk.ID()))
  1022  	// Marks the current transactions from the mempool as being successfully issued
  1023  	// into a block.
  1024  	vm.mempool.IssueCurrentTxs()
  1025  	return blk, nil
  1026  }
  1027  
  1028  // parseBlock parses [b] into a block to be wrapped by ChainState.
  1029  func (vm *VM) parseBlock(b []byte) (snowman.Block, error) {
  1030  	ethBlock := new(types.Block)
  1031  	if err := rlp.DecodeBytes(b, ethBlock); err != nil {
  1032  		return nil, err
  1033  	}
  1034  
  1035  	// Note: the status of block is set by ChainState
  1036  	block, err := vm.newBlock(ethBlock)
  1037  	if err != nil {
  1038  		return nil, err
  1039  	}
  1040  	// Performing syntactic verification in ParseBlock allows for
  1041  	// short-circuiting bad blocks before they are processed by the VM.
  1042  	if err := block.syntacticVerify(); err != nil {
  1043  		return nil, fmt.Errorf("syntactic block verification failed: %w", err)
  1044  	}
  1045  	return block, nil
  1046  }
  1047  
  1048  func (vm *VM) ParseEthBlock(b []byte) (*types.Block, error) {
  1049  	block, err := vm.parseBlock(b)
  1050  	if err != nil {
  1051  		return nil, err
  1052  	}
  1053  
  1054  	return block.(*Block).ethBlock, nil
  1055  }
  1056  
  1057  // getBlock attempts to retrieve block [id] from the VM to be wrapped
  1058  // by ChainState.
  1059  func (vm *VM) getBlock(id ids.ID) (snowman.Block, error) {
  1060  	ethBlock := vm.blockChain.GetBlockByHash(common.Hash(id))
  1061  	// If [ethBlock] is nil, return [database.ErrNotFound] here
  1062  	// so that the miss is considered cacheable.
  1063  	if ethBlock == nil {
  1064  		return nil, database.ErrNotFound
  1065  	}
  1066  	// Note: the status of block is set by ChainState
  1067  	return vm.newBlock(ethBlock)
  1068  }
  1069  
  1070  // SetPreference sets what the current tail of the chain is
  1071  func (vm *VM) SetPreference(blkID ids.ID) error {
  1072  	// Since each internal handler used by [vm.State] always returns a block
  1073  	// with non-nil ethBlock value, GetBlockInternal should never return a
  1074  	// (*Block) with a nil ethBlock value.
  1075  	block, err := vm.GetBlockInternal(blkID)
  1076  	if err != nil {
  1077  		return fmt.Errorf("failed to set preference to %s: %w", blkID, err)
  1078  	}
  1079  
  1080  	return vm.blockChain.SetPreference(block.(*Block).ethBlock)
  1081  }
  1082  
  1083  // VerifyHeightIndex always returns a nil error since the index is maintained by
  1084  // vm.blockChain.
  1085  func (vm *VM) VerifyHeightIndex() error {
  1086  	return nil
  1087  }
  1088  
  1089  // GetBlockAtHeight implements the HeightIndexedChainVM interface and returns the
  1090  // canonical block at [blkHeight].
  1091  // If [blkHeight] is less than the height of the last accepted block, this will return
  1092  // the block accepted at that height. Otherwise, it may return a blkID that has not yet
  1093  // been accepted.
  1094  // Note: the engine assumes that if a block is not found at [blkHeight], then
  1095  // [database.ErrNotFound] will be returned. This indicates that the VM has state synced
  1096  // and does not have all historical blocks available.
  1097  func (vm *VM) GetBlockIDAtHeight(blkHeight uint64) (ids.ID, error) {
  1098  	ethBlock := vm.blockChain.GetBlockByNumber(blkHeight)
  1099  	if ethBlock == nil {
  1100  		return ids.ID{}, database.ErrNotFound
  1101  	}
  1102  
  1103  	return ids.ID(ethBlock.Hash()), nil
  1104  }
  1105  
  1106  func (vm *VM) Version() (string, error) {
  1107  	return Version, nil
  1108  }
  1109  
  1110  // NewHandler returns a new Handler for a service where:
  1111  //   * The handler's functionality is defined by [service]
  1112  //     [service] should be a gorilla RPC service (see https://www.gorillatoolkit.org/pkg/rpc/v2)
  1113  //   * The name of the service is [name]
  1114  //   * The LockOption is the first element of [lockOption]
  1115  //     By default the LockOption is WriteLock
  1116  //     [lockOption] should have either 0 or 1 elements. Elements beside the first are ignored.
  1117  func newHandler(name string, service interface{}, lockOption ...commonEng.LockOption) (*commonEng.HTTPHandler, error) {
  1118  	server := avalancheRPC.NewServer()
  1119  	server.RegisterCodec(avalancheJSON.NewCodec(), "application/json")
  1120  	server.RegisterCodec(avalancheJSON.NewCodec(), "application/json;charset=UTF-8")
  1121  	if err := server.RegisterService(service, name); err != nil {
  1122  		return nil, err
  1123  	}
  1124  
  1125  	var lock commonEng.LockOption = commonEng.WriteLock
  1126  	if len(lockOption) != 0 {
  1127  		lock = lockOption[0]
  1128  	}
  1129  	return &commonEng.HTTPHandler{LockOptions: lock, Handler: server}, nil
  1130  }
  1131  
  1132  // CreateHandlers makes new http handlers that can handle API calls
  1133  func (vm *VM) CreateHandlers() (map[string]*commonEng.HTTPHandler, error) {
  1134  	handler := rpc.NewServer(vm.config.APIMaxDuration.Duration)
  1135  	enabledAPIs := vm.config.EthAPIs()
  1136  	if err := attachEthService(handler, vm.eth.APIs(), enabledAPIs); err != nil {
  1137  		return nil, err
  1138  	}
  1139  
  1140  	primaryAlias, err := vm.ctx.BCLookup.PrimaryAlias(vm.ctx.ChainID)
  1141  	if err != nil {
  1142  		return nil, fmt.Errorf("failed to get primary alias for chain due to %w", err)
  1143  	}
  1144  	apis := make(map[string]*commonEng.HTTPHandler)
  1145  	avaxAPI, err := newHandler("avax", &AvaxAPI{vm})
  1146  	if err != nil {
  1147  		return nil, fmt.Errorf("failed to register service for AVAX API due to %w", err)
  1148  	}
  1149  	enabledAPIs = append(enabledAPIs, "avax")
  1150  	apis[avaxEndpoint] = avaxAPI
  1151  
  1152  	if vm.config.CorethAdminAPIEnabled {
  1153  		adminAPI, err := newHandler("admin", NewAdminService(vm, os.ExpandEnv(fmt.Sprintf("%s_coreth_performance_%s", vm.config.CorethAdminAPIDir, primaryAlias))))
  1154  		if err != nil {
  1155  			return nil, fmt.Errorf("failed to register service for admin API due to %w", err)
  1156  		}
  1157  		apis[adminEndpoint] = adminAPI
  1158  		enabledAPIs = append(enabledAPIs, "coreth-admin")
  1159  	}
  1160  
  1161  	if vm.config.SnowmanAPIEnabled {
  1162  		if err := handler.RegisterName("snowman", &SnowmanAPI{vm}); err != nil {
  1163  			return nil, err
  1164  		}
  1165  		enabledAPIs = append(enabledAPIs, "snowman")
  1166  	}
  1167  
  1168  	log.Info(fmt.Sprintf("Enabled APIs: %s", strings.Join(enabledAPIs, ", ")))
  1169  	apis[ethRPCEndpoint] = &commonEng.HTTPHandler{
  1170  		LockOptions: commonEng.NoLock,
  1171  		Handler:     handler,
  1172  	}
  1173  	apis[ethWSEndpoint] = &commonEng.HTTPHandler{
  1174  		LockOptions: commonEng.NoLock,
  1175  		Handler: handler.WebsocketHandlerWithDuration(
  1176  			[]string{"*"},
  1177  			vm.config.APIMaxDuration.Duration,
  1178  			vm.config.WSCPURefillRate.Duration,
  1179  			vm.config.WSCPUMaxStored.Duration,
  1180  		),
  1181  	}
  1182  
  1183  	return apis, nil
  1184  }
  1185  
  1186  // CreateStaticHandlers makes new http handlers that can handle API calls
  1187  func (vm *VM) CreateStaticHandlers() (map[string]*commonEng.HTTPHandler, error) {
  1188  	handler := rpc.NewServer(0)
  1189  	if err := handler.RegisterName("static", &StaticService{}); err != nil {
  1190  		return nil, err
  1191  	}
  1192  
  1193  	return map[string]*commonEng.HTTPHandler{
  1194  		"/rpc": {LockOptions: commonEng.NoLock, Handler: handler},
  1195  	}, nil
  1196  }
  1197  
  1198  /*
  1199   ******************************************************************************
  1200   *********************************** Helpers **********************************
  1201   ******************************************************************************
  1202   */
  1203  
  1204  // conflicts returns an error if [inputs] conflicts with any of the atomic inputs contained in [ancestor]
  1205  // or any of its ancestor blocks going back to the last accepted block in its ancestry. If [ancestor] is
  1206  // accepted, then nil will be returned immediately.
  1207  // If the ancestry of [ancestor] cannot be fetched, then [errRejectedParent] may be returned.
  1208  func (vm *VM) conflicts(inputs ids.Set, ancestor *Block) error {
  1209  	for ancestor.Status() != choices.Accepted {
  1210  		// If any of the atomic transactions in the ancestor conflict with [inputs]
  1211  		// return an error.
  1212  		for _, atomicTx := range ancestor.atomicTxs {
  1213  			if inputs.Overlaps(atomicTx.InputUTXOs()) {
  1214  				return errConflictingAtomicInputs
  1215  			}
  1216  		}
  1217  
  1218  		// Move up the chain.
  1219  		nextAncestorID := ancestor.Parent()
  1220  		// If the ancestor is unknown, then the parent failed
  1221  		// verification when it was called.
  1222  		// If the ancestor is rejected, then this block shouldn't be
  1223  		// inserted into the canonical chain because the parent is
  1224  		// will be missing.
  1225  		// If the ancestor is processing, then the block may have
  1226  		// been verified.
  1227  		nextAncestorIntf, err := vm.GetBlockInternal(nextAncestorID)
  1228  		if err != nil {
  1229  			return errRejectedParent
  1230  		}
  1231  
  1232  		if blkStatus := nextAncestorIntf.Status(); blkStatus == choices.Unknown || blkStatus == choices.Rejected {
  1233  			return errRejectedParent
  1234  		}
  1235  		nextAncestor, ok := nextAncestorIntf.(*Block)
  1236  		if !ok {
  1237  			return fmt.Errorf("ancestor block %s had unexpected type %T", nextAncestor.ID(), nextAncestorIntf)
  1238  		}
  1239  		ancestor = nextAncestor
  1240  	}
  1241  
  1242  	return nil
  1243  }
  1244  
  1245  // getAtomicTx returns the requested transaction, status, and height.
  1246  // If the status is Unknown, then the returned transaction will be nil.
  1247  func (vm *VM) getAtomicTx(txID ids.ID) (*Tx, Status, uint64, error) {
  1248  	if tx, height, err := vm.atomicTxRepository.GetByTxID(txID); err == nil {
  1249  		return tx, Accepted, height, nil
  1250  	} else if err != database.ErrNotFound {
  1251  		return nil, Unknown, 0, err
  1252  	}
  1253  	tx, dropped, found := vm.mempool.GetTx(txID)
  1254  	switch {
  1255  	case found && dropped:
  1256  		return tx, Dropped, 0, nil
  1257  	case found:
  1258  		return tx, Processing, 0, nil
  1259  	default:
  1260  		return nil, Unknown, 0, nil
  1261  	}
  1262  }
  1263  
  1264  // ParseAddress takes in an address and produces the ID of the chain it's for
  1265  // the ID of the address
  1266  func (vm *VM) ParseAddress(addrStr string) (ids.ID, ids.ShortID, error) {
  1267  	chainIDAlias, hrp, addrBytes, err := address.Parse(addrStr)
  1268  	if err != nil {
  1269  		return ids.ID{}, ids.ShortID{}, err
  1270  	}
  1271  
  1272  	chainID, err := vm.ctx.BCLookup.Lookup(chainIDAlias)
  1273  	if err != nil {
  1274  		return ids.ID{}, ids.ShortID{}, err
  1275  	}
  1276  
  1277  	expectedHRP := constants.GetHRP(vm.ctx.NetworkID)
  1278  	if hrp != expectedHRP {
  1279  		return ids.ID{}, ids.ShortID{}, fmt.Errorf("expected hrp %q but got %q",
  1280  			expectedHRP, hrp)
  1281  	}
  1282  
  1283  	addr, err := ids.ToShortID(addrBytes)
  1284  	if err != nil {
  1285  		return ids.ID{}, ids.ShortID{}, err
  1286  	}
  1287  	return chainID, addr, nil
  1288  }
  1289  
  1290  // issueTx verifies [tx] as valid to be issued on top of the currently preferred block
  1291  // and then issues [tx] into the mempool if valid.
  1292  func (vm *VM) issueTx(tx *Tx, local bool) error {
  1293  	if err := vm.verifyTxAtTip(tx); err != nil {
  1294  		if !local {
  1295  			// unlike local txs, invalid remote txs are recorded as discarded
  1296  			// so that they won't be requested again
  1297  			txID := tx.ID()
  1298  			vm.mempool.discardedTxs.Put(txID, tx)
  1299  			log.Debug("failed to verify remote tx being issued to the mempool",
  1300  				"txID", txID,
  1301  				"err", err,
  1302  			)
  1303  			return nil
  1304  		}
  1305  		return err
  1306  	}
  1307  	// add to mempool and possibly re-gossip
  1308  	if err := vm.mempool.AddTx(tx); err != nil {
  1309  		if !local {
  1310  			// unlike local txs, invalid remote txs are recorded as discarded
  1311  			// so that they won't be requested again
  1312  			txID := tx.ID()
  1313  			vm.mempool.discardedTxs.Put(tx.ID(), tx)
  1314  			log.Debug("failed to issue remote tx to mempool",
  1315  				"txID", txID,
  1316  				"err", err,
  1317  			)
  1318  			return nil
  1319  		}
  1320  		return err
  1321  	}
  1322  	// NOTE: Gossiping of the issued [Tx] is handled in [AddTx]
  1323  	return nil
  1324  }
  1325  
  1326  // verifyTxAtTip verifies that [tx] is valid to be issued on top of the currently preferred block
  1327  func (vm *VM) verifyTxAtTip(tx *Tx) error {
  1328  	// Note: we fetch the current block and then the state at that block instead of the current state directly
  1329  	// since we need the header of the current block below.
  1330  	preferredBlock := vm.blockChain.CurrentBlock()
  1331  	preferredState, err := vm.blockChain.StateAt(preferredBlock.Root())
  1332  	if err != nil {
  1333  		return fmt.Errorf("failed to retrieve block state at tip while verifying atomic tx: %w", err)
  1334  	}
  1335  	rules := vm.currentRules()
  1336  	parentHeader := preferredBlock.Header()
  1337  	var nextBaseFee *big.Int
  1338  	timestamp := vm.clock.Time().Unix()
  1339  	bigTimestamp := big.NewInt(timestamp)
  1340  	if vm.chainConfig.IsApricotPhase3(bigTimestamp) {
  1341  		_, nextBaseFee, err = dummy.EstimateNextBaseFee(vm.chainConfig, parentHeader, uint64(timestamp))
  1342  		if err != nil {
  1343  			// Return extremely detailed error since CalcBaseFee should never encounter an issue here
  1344  			return fmt.Errorf("failed to calculate base fee with parent timestamp (%d), parent ExtraData: (0x%x), and current timestamp (%d): %w", parentHeader.Time, parentHeader.Extra, timestamp, err)
  1345  		}
  1346  	}
  1347  
  1348  	return vm.verifyTx(tx, parentHeader.Hash(), nextBaseFee, preferredState, rules)
  1349  }
  1350  
  1351  // verifyTx verifies that [tx] is valid to be issued into a block with parent block [parentHash]
  1352  // and validated at [state] using [rules] as the current rule set.
  1353  // Note: verifyTx may modify [state]. If [state] needs to be properly maintained, the caller is responsible
  1354  // for reverting to the correct snapshot after calling this function. If this function is called with a
  1355  // throwaway state, then this is not necessary.
  1356  func (vm *VM) verifyTx(tx *Tx, parentHash common.Hash, baseFee *big.Int, state *state.StateDB, rules params.Rules) error {
  1357  	parentIntf, err := vm.GetBlockInternal(ids.ID(parentHash))
  1358  	if err != nil {
  1359  		return fmt.Errorf("failed to get parent block: %w", err)
  1360  	}
  1361  	parent, ok := parentIntf.(*Block)
  1362  	if !ok {
  1363  		return fmt.Errorf("parent block %s had unexpected type %T", parentIntf.ID(), parentIntf)
  1364  	}
  1365  	if err := tx.UnsignedAtomicTx.SemanticVerify(vm, tx, parent, baseFee, rules); err != nil {
  1366  		return err
  1367  	}
  1368  	return tx.UnsignedAtomicTx.EVMStateTransfer(vm.ctx, state)
  1369  }
  1370  
  1371  // verifyTxs verifies that [txs] are valid to be issued into a block with parent block [parentHash]
  1372  // using [rules] as the current rule set.
  1373  func (vm *VM) verifyTxs(txs []*Tx, parentHash common.Hash, baseFee *big.Int, height uint64, rules params.Rules) error {
  1374  	// Ensure that the parent was verified and inserted correctly.
  1375  	if !vm.blockChain.HasBlock(parentHash, height-1) {
  1376  		return errRejectedParent
  1377  	}
  1378  
  1379  	ancestorID := ids.ID(parentHash)
  1380  	// If the ancestor is unknown, then the parent failed verification when
  1381  	// it was called.
  1382  	// If the ancestor is rejected, then this block shouldn't be inserted
  1383  	// into the canonical chain because the parent will be missing.
  1384  	ancestorInf, err := vm.GetBlockInternal(ancestorID)
  1385  	if err != nil {
  1386  		return errRejectedParent
  1387  	}
  1388  	if blkStatus := ancestorInf.Status(); blkStatus == choices.Unknown || blkStatus == choices.Rejected {
  1389  		return errRejectedParent
  1390  	}
  1391  	ancestor, ok := ancestorInf.(*Block)
  1392  	if !ok {
  1393  		return fmt.Errorf("expected parent block %s, to be *Block but is %T", ancestor.ID(), ancestorInf)
  1394  	}
  1395  
  1396  	// Ensure each tx in [txs] doesn't conflict with any other atomic tx in
  1397  	// a processing ancestor block.
  1398  	inputs := &ids.Set{}
  1399  	for _, atomicTx := range txs {
  1400  		utx := atomicTx.UnsignedAtomicTx
  1401  		if err := utx.SemanticVerify(vm, atomicTx, ancestor, baseFee, rules); err != nil {
  1402  			return fmt.Errorf("invalid block due to failed semanatic verify: %w at height %d", err, height)
  1403  		}
  1404  		txInputs := utx.InputUTXOs()
  1405  		if inputs.Overlaps(txInputs) {
  1406  			return errConflictingAtomicInputs
  1407  		}
  1408  		inputs.Union(txInputs)
  1409  	}
  1410  	return nil
  1411  }
  1412  
  1413  // GetAtomicUTXOs returns the utxos that at least one of the provided addresses is
  1414  // referenced in.
  1415  func (vm *VM) GetAtomicUTXOs(
  1416  	chainID ids.ID,
  1417  	addrs ids.ShortSet,
  1418  	startAddr ids.ShortID,
  1419  	startUTXOID ids.ID,
  1420  	limit int,
  1421  ) ([]*avax.UTXO, ids.ShortID, ids.ID, error) {
  1422  	if limit <= 0 || limit > maxUTXOsToFetch {
  1423  		limit = maxUTXOsToFetch
  1424  	}
  1425  
  1426  	addrsList := make([][]byte, addrs.Len())
  1427  	for i, addr := range addrs.List() {
  1428  		addrsList[i] = addr.Bytes()
  1429  	}
  1430  
  1431  	allUTXOBytes, lastAddr, lastUTXO, err := vm.ctx.SharedMemory.Indexed(
  1432  		chainID,
  1433  		addrsList,
  1434  		startAddr.Bytes(),
  1435  		startUTXOID[:],
  1436  		limit,
  1437  	)
  1438  	if err != nil {
  1439  		return nil, ids.ShortID{}, ids.ID{}, fmt.Errorf("error fetching atomic UTXOs: %w", err)
  1440  	}
  1441  
  1442  	lastAddrID, err := ids.ToShortID(lastAddr)
  1443  	if err != nil {
  1444  		lastAddrID = ids.ShortEmpty
  1445  	}
  1446  	lastUTXOID, err := ids.ToID(lastUTXO)
  1447  	if err != nil {
  1448  		lastUTXOID = ids.Empty
  1449  	}
  1450  
  1451  	utxos := make([]*avax.UTXO, len(allUTXOBytes))
  1452  	for i, utxoBytes := range allUTXOBytes {
  1453  		utxo := &avax.UTXO{}
  1454  		if _, err := vm.codec.Unmarshal(utxoBytes, utxo); err != nil {
  1455  			return nil, ids.ShortID{}, ids.ID{}, fmt.Errorf("error parsing UTXO: %w", err)
  1456  		}
  1457  		utxos[i] = utxo
  1458  	}
  1459  	return utxos, lastAddrID, lastUTXOID, nil
  1460  }
  1461  
  1462  // GetSpendableFunds returns a list of EVMInputs and keys (in corresponding
  1463  // order) to total [amount] of [assetID] owned by [keys].
  1464  // Note: we return [][]*crypto.PrivateKeySECP256K1R even though each input
  1465  // corresponds to a single key, so that the signers can be passed in to
  1466  // [tx.Sign] which supports multiple keys on a single input.
  1467  func (vm *VM) GetSpendableFunds(
  1468  	keys []*crypto.PrivateKeySECP256K1R,
  1469  	assetID ids.ID,
  1470  	amount uint64,
  1471  ) ([]EVMInput, [][]*crypto.PrivateKeySECP256K1R, error) {
  1472  	// Note: current state uses the state of the preferred block.
  1473  	state, err := vm.blockChain.State()
  1474  	if err != nil {
  1475  		return nil, nil, err
  1476  	}
  1477  	inputs := []EVMInput{}
  1478  	signers := [][]*crypto.PrivateKeySECP256K1R{}
  1479  	// Note: we assume that each key in [keys] is unique, so that iterating over
  1480  	// the keys will not produce duplicated nonces in the returned EVMInput slice.
  1481  	for _, key := range keys {
  1482  		if amount == 0 {
  1483  			break
  1484  		}
  1485  		addr := GetEthAddress(key)
  1486  		var balance uint64
  1487  		if assetID == vm.ctx.AVAXAssetID {
  1488  			// If the asset is AVAX, we divide by the x2cRate to convert back to the correct
  1489  			// denomination of AVAX that can be exported.
  1490  			balance = new(big.Int).Div(state.GetBalance(addr), x2cRate).Uint64()
  1491  		} else {
  1492  			balance = state.GetBalanceMultiCoin(addr, common.Hash(assetID)).Uint64()
  1493  		}
  1494  		if balance == 0 {
  1495  			continue
  1496  		}
  1497  		if amount < balance {
  1498  			balance = amount
  1499  		}
  1500  		nonce, err := vm.GetCurrentNonce(addr)
  1501  		if err != nil {
  1502  			return nil, nil, err
  1503  		}
  1504  		inputs = append(inputs, EVMInput{
  1505  			Address: addr,
  1506  			Amount:  balance,
  1507  			AssetID: assetID,
  1508  			Nonce:   nonce,
  1509  		})
  1510  		signers = append(signers, []*crypto.PrivateKeySECP256K1R{key})
  1511  		amount -= balance
  1512  	}
  1513  
  1514  	if amount > 0 {
  1515  		return nil, nil, errInsufficientFunds
  1516  	}
  1517  
  1518  	return inputs, signers, nil
  1519  }
  1520  
  1521  // GetSpendableAVAXWithFee returns a list of EVMInputs and keys (in corresponding
  1522  // order) to total [amount] + [fee] of [AVAX] owned by [keys].
  1523  // This function accounts for the added cost of the additional inputs needed to
  1524  // create the transaction and makes sure to skip any keys with a balance that is
  1525  // insufficient to cover the additional fee.
  1526  // Note: we return [][]*crypto.PrivateKeySECP256K1R even though each input
  1527  // corresponds to a single key, so that the signers can be passed in to
  1528  // [tx.Sign] which supports multiple keys on a single input.
  1529  func (vm *VM) GetSpendableAVAXWithFee(
  1530  	keys []*crypto.PrivateKeySECP256K1R,
  1531  	amount uint64,
  1532  	cost uint64,
  1533  	baseFee *big.Int,
  1534  ) ([]EVMInput, [][]*crypto.PrivateKeySECP256K1R, error) {
  1535  	// Note: current state uses the state of the preferred block.
  1536  	state, err := vm.blockChain.State()
  1537  	if err != nil {
  1538  		return nil, nil, err
  1539  	}
  1540  
  1541  	initialFee, err := calculateDynamicFee(cost, baseFee)
  1542  	if err != nil {
  1543  		return nil, nil, err
  1544  	}
  1545  
  1546  	newAmount, err := math.Add64(amount, initialFee)
  1547  	if err != nil {
  1548  		return nil, nil, err
  1549  	}
  1550  	amount = newAmount
  1551  
  1552  	inputs := []EVMInput{}
  1553  	signers := [][]*crypto.PrivateKeySECP256K1R{}
  1554  	// Note: we assume that each key in [keys] is unique, so that iterating over
  1555  	// the keys will not produce duplicated nonces in the returned EVMInput slice.
  1556  	for _, key := range keys {
  1557  		if amount == 0 {
  1558  			break
  1559  		}
  1560  
  1561  		prevFee, err := calculateDynamicFee(cost, baseFee)
  1562  		if err != nil {
  1563  			return nil, nil, err
  1564  		}
  1565  
  1566  		newCost := cost + EVMInputGas
  1567  		newFee, err := calculateDynamicFee(newCost, baseFee)
  1568  		if err != nil {
  1569  			return nil, nil, err
  1570  		}
  1571  
  1572  		additionalFee := newFee - prevFee
  1573  
  1574  		addr := GetEthAddress(key)
  1575  		// Since the asset is AVAX, we divide by the x2cRate to convert back to
  1576  		// the correct denomination of AVAX that can be exported.
  1577  		balance := new(big.Int).Div(state.GetBalance(addr), x2cRate).Uint64()
  1578  		// If the balance for [addr] is insufficient to cover the additional cost
  1579  		// of adding an input to the transaction, skip adding the input altogether
  1580  		if balance <= additionalFee {
  1581  			continue
  1582  		}
  1583  
  1584  		// Update the cost for the next iteration
  1585  		cost = newCost
  1586  
  1587  		newAmount, err := math.Add64(amount, additionalFee)
  1588  		if err != nil {
  1589  			return nil, nil, err
  1590  		}
  1591  		amount = newAmount
  1592  
  1593  		// Use the entire [balance] as an input, but if the required [amount]
  1594  		// is less than the balance, update the [inputAmount] to spend the
  1595  		// minimum amount to finish the transaction.
  1596  		inputAmount := balance
  1597  		if amount < balance {
  1598  			inputAmount = amount
  1599  		}
  1600  		nonce, err := vm.GetCurrentNonce(addr)
  1601  		if err != nil {
  1602  			return nil, nil, err
  1603  		}
  1604  		inputs = append(inputs, EVMInput{
  1605  			Address: addr,
  1606  			Amount:  inputAmount,
  1607  			AssetID: vm.ctx.AVAXAssetID,
  1608  			Nonce:   nonce,
  1609  		})
  1610  		signers = append(signers, []*crypto.PrivateKeySECP256K1R{key})
  1611  		amount -= inputAmount
  1612  	}
  1613  
  1614  	if amount > 0 {
  1615  		return nil, nil, errInsufficientFunds
  1616  	}
  1617  
  1618  	return inputs, signers, nil
  1619  }
  1620  
  1621  // GetCurrentNonce returns the nonce associated with the address at the
  1622  // preferred block
  1623  func (vm *VM) GetCurrentNonce(address common.Address) (uint64, error) {
  1624  	// Note: current state uses the state of the preferred block.
  1625  	state, err := vm.blockChain.State()
  1626  	if err != nil {
  1627  		return 0, err
  1628  	}
  1629  	return state.GetNonce(address), nil
  1630  }
  1631  
  1632  // currentRules returns the chain rules for the current block.
  1633  func (vm *VM) currentRules() params.Rules {
  1634  	header := vm.eth.APIBackend.CurrentHeader()
  1635  	return vm.chainConfig.AvalancheRules(header.Number, big.NewInt(int64(header.Time)))
  1636  }
  1637  
  1638  func (vm *VM) startContinuousProfiler() {
  1639  	// If the profiler directory is empty, return immediately
  1640  	// without creating or starting a continuous profiler.
  1641  	if vm.config.ContinuousProfilerDir == "" {
  1642  		return
  1643  	}
  1644  	vm.profiler = profiler.NewContinuous(
  1645  		filepath.Join(vm.config.ContinuousProfilerDir),
  1646  		vm.config.ContinuousProfilerFrequency.Duration,
  1647  		vm.config.ContinuousProfilerMaxFiles,
  1648  	)
  1649  	defer vm.profiler.Shutdown()
  1650  
  1651  	vm.shutdownWg.Add(1)
  1652  	go func() {
  1653  		defer vm.shutdownWg.Done()
  1654  		log.Info("Dispatching continuous profiler", "dir", vm.config.ContinuousProfilerDir, "freq", vm.config.ContinuousProfilerFrequency, "maxFiles", vm.config.ContinuousProfilerMaxFiles)
  1655  		err := vm.profiler.Dispatch()
  1656  		if err != nil {
  1657  			log.Error("continuous profiler failed", "err", err)
  1658  		}
  1659  	}()
  1660  	// Wait for shutdownChan to be closed
  1661  	<-vm.shutdownChan
  1662  }
  1663  
  1664  func (vm *VM) estimateBaseFee(ctx context.Context) (*big.Int, error) {
  1665  	// Get the base fee to use
  1666  	baseFee, err := vm.eth.APIBackend.EstimateBaseFee(ctx)
  1667  	if err != nil {
  1668  		return nil, err
  1669  	}
  1670  	if baseFee == nil {
  1671  		baseFee = initialBaseFee
  1672  	} else {
  1673  		// give some breathing room
  1674  		baseFee.Mul(baseFee, big.NewInt(11))
  1675  		baseFee.Div(baseFee, big.NewInt(10))
  1676  	}
  1677  
  1678  	return baseFee, nil
  1679  }
  1680  
  1681  func (vm *VM) getAtomicTxFromPreApricot5BlockByHeight(height uint64) (*Tx, error) {
  1682  	blk := vm.blockChain.GetBlockByNumber(height)
  1683  	if blk == nil {
  1684  		return nil, nil
  1685  	}
  1686  	return ExtractAtomicTx(blk.ExtData(), vm.codec)
  1687  }
  1688  
  1689  // readLastAccepted reads the last accepted hash from [acceptedBlockDB] and returns the
  1690  // last accepted block hash and height by reading directly from [vm.chaindb] instead of relying
  1691  // on [chain].
  1692  // Note: assumes chaindb, ethConfig, and genesisHash have been initialized.
  1693  func (vm *VM) readLastAccepted() (common.Hash, uint64, error) {
  1694  	// Attempt to load last accepted block to determine if it is necessary to
  1695  	// initialize state with the genesis block.
  1696  	lastAcceptedBytes, lastAcceptedErr := vm.acceptedBlockDB.Get(lastAcceptedKey)
  1697  	switch {
  1698  	case lastAcceptedErr == database.ErrNotFound:
  1699  		// If there is nothing in the database, return the genesis block hash and height
  1700  		return vm.genesisHash, 0, nil
  1701  	case lastAcceptedErr != nil:
  1702  		return common.Hash{}, 0, fmt.Errorf("failed to get last accepted block ID due to: %w", lastAcceptedErr)
  1703  	case len(lastAcceptedBytes) != common.HashLength:
  1704  		return common.Hash{}, 0, fmt.Errorf("last accepted bytes should have been length %d, but found %d", common.HashLength, len(lastAcceptedBytes))
  1705  	default:
  1706  		lastAcceptedHash := common.BytesToHash(lastAcceptedBytes)
  1707  		height := rawdb.ReadHeaderNumber(vm.chaindb, lastAcceptedHash)
  1708  		if height == nil {
  1709  			return common.Hash{}, 0, fmt.Errorf("failed to retrieve header number of last accepted block: %s", lastAcceptedHash)
  1710  		}
  1711  		return lastAcceptedHash, *height, nil
  1712  	}
  1713  }
  1714  
  1715  // attachEthService registers the backend RPC services provided by Ethereum
  1716  // to the provided handler under their assigned namespaces.
  1717  func attachEthService(handler *rpc.Server, apis []rpc.API, names []string) error {
  1718  	enabledServicesSet := make(map[string]struct{})
  1719  	for _, ns := range names {
  1720  		// handle pre geth v1.10.20 api names as aliases for their updated values
  1721  		// to allow configurations to be backwards compatible.
  1722  		if newName, isLegacy := legacyApiNames[ns]; isLegacy {
  1723  			log.Info("deprecated api name referenced in configuration.", "deprecated", ns, "new", newName)
  1724  			enabledServicesSet[newName] = struct{}{}
  1725  			continue
  1726  		}
  1727  
  1728  		enabledServicesSet[ns] = struct{}{}
  1729  	}
  1730  
  1731  	apiSet := make(map[string]rpc.API)
  1732  	for _, api := range apis {
  1733  		if existingAPI, exists := apiSet[api.Name]; exists {
  1734  			return fmt.Errorf("duplicated API name: %s, namespaces %s and %s", api.Name, api.Namespace, existingAPI.Namespace)
  1735  		}
  1736  		apiSet[api.Name] = api
  1737  	}
  1738  
  1739  	for name := range enabledServicesSet {
  1740  		api, exists := apiSet[name]
  1741  		if !exists {
  1742  			return fmt.Errorf("API service %s not found", name)
  1743  		}
  1744  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
  1745  			return err
  1746  		}
  1747  	}
  1748  
  1749  	return nil
  1750  }