github.com/amazechain/amc@v0.1.3/internal/api/api_backend.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"github.com/amazechain/amc/accounts"
    24  	common2 "github.com/amazechain/amc/common"
    25  	types "github.com/amazechain/amc/common/block"
    26  	"github.com/amazechain/amc/common/transaction"
    27  	common "github.com/amazechain/amc/common/types"
    28  	"github.com/amazechain/amc/internal"
    29  	"github.com/amazechain/amc/internal/vm"
    30  	"github.com/amazechain/amc/internal/vm/evmtypes"
    31  	"github.com/amazechain/amc/modules/rawdb"
    32  	rpc "github.com/amazechain/amc/modules/rpc/jsonrpc"
    33  	"github.com/amazechain/amc/modules/state"
    34  	"github.com/amazechain/amc/params"
    35  	"github.com/holiman/uint256"
    36  	"github.com/ledgerwatch/erigon-lib/kv"
    37  )
    38  
    39  // API implements ethapi.Backend for full nodes
    40  //type API struct {
    41  //	extRPCEnabled       bool
    42  //	allowUnprotectedTxs bool
    43  //	eth                 *node.Node
    44  //	//gpo                 *gasprice.Oracle
    45  //}
    46  
    47  // ChainConfig returns the active chain configuration.
    48  func (b *API) ChainConfig() *params.ChainConfig {
    49  	return b.chainConfig
    50  }
    51  
    52  func (b *API) CurrentBlock() *types.Header {
    53  	return b.bc.CurrentBlock().Header().(*types.Header)
    54  }
    55  
    56  //func (b *API) SetHead(number uint64) {
    57  //	b.eth.handler.downloader.Cancel()
    58  //	b.bc.SetHead(number)
    59  //}
    60  
    61  func (b *API) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
    62  	// Pending block is only known by the miner
    63  	//if number == rpc.PendingBlockNumber {
    64  	//	block := b.eth.Miner().PendingBlock()
    65  	//	return block.Header(), nil
    66  	//}
    67  	// Otherwise resolve and return the block
    68  	if number == rpc.LatestBlockNumber {
    69  		return b.bc.CurrentBlock().Header().(*types.Header), nil
    70  	}
    71  	//if number == rpc.FinalizedBlockNumber {
    72  	//	if !b.eth.Merger().TDDReached() {
    73  	//		return nil, errors.New("'finalized' tag not supported on pre-merge network")
    74  	//	}
    75  	//	block := b.eth.blockchain.CurrentFinalBlock()
    76  	//	if block != nil {
    77  	//		return block, nil
    78  	//	}
    79  	//	return nil, errors.New("finalized block not found")
    80  	//}
    81  	//if number == rpc.SafeBlockNumber {
    82  	//	if !b.eth.Merger().TDDReached() {
    83  	//		return nil, errors.New("'safe' tag not supported on pre-merge network")
    84  	//	}
    85  	//	block := b.eth.blockchain.CurrentSafeBlock()
    86  	//	if block != nil {
    87  	//		return block, nil
    88  	//	}
    89  	//	return nil, errors.New("safe block not found")
    90  	//}
    91  	return b.bc.GetHeaderByNumber(uint256.NewInt(uint64(number.Int64()))).(*types.Header), nil
    92  }
    93  
    94  func (b *API) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
    95  	if blockNr, ok := blockNrOrHash.Number(); ok {
    96  		return b.HeaderByNumber(ctx, blockNr)
    97  	}
    98  	if hash, ok := blockNrOrHash.Hash(); ok {
    99  		header, _ := b.bc.GetHeaderByHash(hash)
   100  		if header == nil {
   101  			return nil, errors.New("header for hash not found")
   102  		}
   103  		if blockNrOrHash.RequireCanonical && b.bc.(*internal.BlockChain).GetCanonicalHash(header.Number64()) != hash {
   104  			return nil, errors.New("hash is not currently canonical")
   105  		}
   106  		return header.(*types.Header), nil
   107  	}
   108  	return nil, errors.New("invalid arguments; neither block nor hash specified")
   109  }
   110  
   111  func (b *API) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   112  	iHeader, _ := b.bc.GetHeaderByHash(hash)
   113  	return iHeader.(*types.Header), nil
   114  }
   115  
   116  func (b *API) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   117  	// Pending block is only known by the miner
   118  	//if number == rpc.PendingBlockNumber {
   119  	//	block := b.minPendingBlock()
   120  	//	return block, nil
   121  	//}
   122  	// Otherwise resolve and return the block
   123  	if number == rpc.LatestBlockNumber {
   124  		header := b.bc.CurrentBlock()
   125  		return b.bc.GetBlock(header.Hash(), header.Number64().Uint64()).(*types.Block), nil
   126  	}
   127  	//if number == rpc.FinalizedBlockNumber {
   128  	//	if !b.eth.Merger().TDDReached() {
   129  	//		return nil, errors.New("'finalized' tag not supported on pre-merge network")
   130  	//	}
   131  	//	header := b.eth.blockchain.CurrentFinalBlock()
   132  	//	return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
   133  	//}
   134  	//if number == rpc.SafeBlockNumber {
   135  	//	//if !b.eth.Merger().TDDReached() {
   136  	//	//	return nil, errors.New("'safe' tag not supported on pre-merge network")
   137  	//	//}
   138  	//	header := b.BlockChain().CurrentBlock()
   139  	//	return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
   140  	//}
   141  	iBlock, err := b.bc.GetBlockByNumber(uint256.NewInt(uint64(number)))
   142  	if nil != err {
   143  		return nil, err
   144  	}
   145  	return iBlock.(*types.Block), nil
   146  }
   147  
   148  func (b *API) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   149  	iBlock, _ := b.bc.GetBlockByHash(hash)
   150  	return iBlock.(*types.Block), nil
   151  }
   152  
   153  // GetBody returns body of a block. It does not resolve special block numbers.
   154  //func (b *API) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
   155  //	if number < 0 || hash == (common.Hash{}) {
   156  //		return nil, errors.New("invalid arguments; expect hash and no special block numbers")
   157  //	}
   158  //	if body := b.bc.GetBody(hash); body != nil {
   159  //		return body, nil
   160  //	}
   161  //	return nil, errors.New("block body not found")
   162  //}
   163  
   164  func (b *API) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
   165  	if blockNr, ok := blockNrOrHash.Number(); ok {
   166  		return b.BlockByNumber(ctx, blockNr)
   167  	}
   168  	if hash, ok := blockNrOrHash.Hash(); ok {
   169  		header, _ := b.bc.GetHeaderByHash(hash)
   170  		if header == nil {
   171  			return nil, errors.New("header for hash not found")
   172  		}
   173  		if blockNrOrHash.RequireCanonical && b.bc.(*internal.BlockChain).GetCanonicalHash(header.Number64()) != hash {
   174  			return nil, errors.New("hash is not currently canonical")
   175  		}
   176  		block := b.bc.GetBlock(hash, header.Number64().Uint64())
   177  		if block == nil {
   178  			return nil, errors.New("header found, but block body is missing")
   179  		}
   180  		return block.(*types.Block), nil
   181  	}
   182  	return nil, errors.New("invalid arguments; neither block nor hash specified")
   183  }
   184  
   185  //func (b *API) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
   186  //	return b.eth.miner.PendingBlockAndReceipts()
   187  //}
   188  
   189  //func (b *API) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
   190  //	// Pending state is only known by the miner
   191  //	if number == rpc.PendingBlockNumber {
   192  //		block, state := b.eth.miner.Pending()
   193  //		return state, block.Header(), nil
   194  //	}
   195  //	// Otherwise resolve the block number and return its state
   196  //	header, err := b.HeaderByNumber(ctx, number)
   197  //	if err != nil {
   198  //		return nil, nil, err
   199  //	}
   200  //	if header == nil {
   201  //		return nil, nil, errors.New("header not found")
   202  //	}
   203  //	stateDb, err := b.bc.StateAt(header.Root)
   204  //	return stateDb, header, err
   205  //}
   206  
   207  //func (b *API) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
   208  //	if blockNr, ok := blockNrOrHash.Number(); ok {
   209  //		return b.StateAndHeaderByNumber(ctx, blockNr)
   210  //	}
   211  //	if hash, ok := blockNrOrHash.Hash(); ok {
   212  //		header, err := b.HeaderByHash(ctx, hash)
   213  //		if err != nil {
   214  //			return nil, nil, err
   215  //		}
   216  //		if header == nil {
   217  //			return nil, nil, errors.New("header for hash not found")
   218  //		}
   219  //		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   220  //			return nil, nil, errors.New("hash is not currently canonical")
   221  //		}
   222  //		stateDb, err := b.bc.StateAt(header.Root)
   223  //		return stateDb, header, err
   224  //	}
   225  //	return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
   226  //}
   227  
   228  func (b *API) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
   229  	return b.bc.GetReceipts(hash)
   230  
   231  }
   232  
   233  //func (b *API) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
   234  //	return rawdb.ReadLogs(b.eth.chainDb, hash, number, b.ChainConfig()), nil
   235  //}
   236  
   237  func (b *API) GetTd(ctx context.Context, hash common.Hash) *uint256.Int {
   238  	if header, _ := b.bc.GetHeaderByHash(hash); header != nil {
   239  		return b.bc.GetTd(hash, header.Number64())
   240  	}
   241  	return nil
   242  }
   243  
   244  func (b *API) GetEVM(ctx context.Context, msg *transaction.Message, state *state.IntraBlockState, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) {
   245  	if vmConfig == nil {
   246  		//vmConfig = b.bc.GetVMConfig()
   247  		vmConfig = &vm.Config{}
   248  	}
   249  	txContext := internal.NewEVMTxContext(msg)
   250  	getHeader := func(hash common.Hash, n uint64) *types.Header {
   251  		h := b.bc.GetHeader(hash, uint256.NewInt(n))
   252  		return h.(*types.Header)
   253  	}
   254  	context := internal.NewEVMBlockContext(header, internal.GetHashFn(header, getHeader), b.bc.Engine(), nil)
   255  	return vm.NewEVM(context, txContext, state, b.bc.Config(), *vmConfig), state.Error, nil
   256  }
   257  
   258  //func (b *API) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   259  //	return b.bc.SubscribeRemovedLogsEvent(ch)
   260  //}
   261  
   262  //func (b *API) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
   263  //	return b.eth.miner.SubscribePendingLogs(ch)
   264  //}
   265  //
   266  //func (b *API) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
   267  //	return b.bc.SubscribeChainEvent(ch)
   268  //}
   269  //
   270  //func (b *API) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
   271  //	return b.bc.SubscribeChainHeadEvent(ch)
   272  //}
   273  //
   274  //func (b *API) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
   275  //	return b.bc.SubscribeChainSideEvent(ch)
   276  //}
   277  
   278  //func (b *API) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   279  //	return b.bc.SubscribeLogsEvent(ch)
   280  //}
   281  
   282  //func (b *API) SendTx(ctx context.Context, signedTx *types.Transaction) error {
   283  //	return b.eth.txPool.AddLocal(signedTx)
   284  //}
   285  //
   286  //func (b *API) GetPoolTransactions() (types.Transactions, error) {
   287  //	pending := b.eth.txPool.Pending(false)
   288  //	var txs types.Transactions
   289  //	for _, batch := range pending {
   290  //		txs = append(txs, batch...)
   291  //	}
   292  //	return txs, nil
   293  //}
   294  //
   295  //func (b *API) GetPoolTransaction(hash common.Hash) *types.Transaction {
   296  //	return b.eth.txPool.Get(hash)
   297  //}
   298  
   299  func (b *API) GetTransaction(ctx context.Context, txHash common.Hash) (*transaction.Transaction, common.Hash, uint64, uint64, error) {
   300  	var t *transaction.Transaction
   301  	var blockHash common.Hash
   302  	var index uint64
   303  	var err error
   304  	var blockNumber uint64
   305  	b.db.View(ctx, func(tx kv.Tx) error {
   306  		t, blockHash, blockNumber, index, err = rawdb.ReadTransactionByHash(tx, txHash)
   307  		return err
   308  	})
   309  	return t, blockHash, blockNumber, index, nil
   310  }
   311  
   312  //func (b *API) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
   313  //	return b.eth.txPool.Nonce(addr), nil
   314  //}
   315  //
   316  //func (b *API) Stats() (pending int, queued int) {
   317  //	return b.eth.txPool.Stats()
   318  //}
   319  //
   320  //func (b *API) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
   321  //	return b.eth.TxPool().Content()
   322  //}
   323  //
   324  //func (b *API) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) {
   325  //	return b.eth.TxPool().ContentFrom(addr)
   326  //}
   327  //
   328  //func (b *API) TxPool() *txpool.TxPool {
   329  //	return b.eth.TxPool()
   330  //}
   331  
   332  //func (b *API) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   333  //	return b.eth.TxPool().SubscribeNewTxsEvent(ch)
   334  //}
   335  //
   336  //func (b *API) SyncProgress() ethereum.SyncProgress {
   337  //	return b.eth.Downloader().Progress()
   338  //}
   339  //
   340  //func (b *API) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
   341  //	return b.gpo.SuggestTipCap(ctx)
   342  //}
   343  //
   344  //func (b *API) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
   345  //	return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
   346  //}
   347  
   348  func (b *API) ChainDb() kv.RwDB {
   349  	return b.db
   350  }
   351  
   352  //func (b *API) EventMux() *event.TypeMux {
   353  //	return b.eth.EventMux()
   354  //}
   355  
   356  func (b *API) AccountManager() *accounts.Manager {
   357  	return b.accountManager
   358  }
   359  
   360  //func (b *API) ExtRPCEnabled() bool {
   361  //	return b.extRPCEnabled
   362  //}
   363  
   364  //func (b *API) UnprotectedAllowed() bool {
   365  //	return b.allowUnprotectedTxs
   366  //}
   367  
   368  //func (b *API) RPCGasCap() uint64 {
   369  //	return b.eth.config.RPCGasCap
   370  //}
   371  //
   372  //func (b *API) RPCEVMTimeout() time.Duration {
   373  //	return b.eth.config.RPCEVMTimeout
   374  //}
   375  //
   376  //func (b *API) RPCTxFeeCap() float64 {
   377  //	return b.eth.config.RPCTxFeeCap
   378  //}
   379  
   380  //func (b *API) BloomStatus() (uint64, uint64) {
   381  //	sections, _, _ := b.eth.bloomIndexer.Sections()
   382  //	return params.BloomBitsBlocks, sections
   383  //}
   384  //
   385  //func (b *API) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
   386  //	for i := 0; i < bloomFilterThreads; i++ {
   387  //		go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
   388  //	}
   389  //}
   390  
   391  func (b *API) CurrentHeader() *types.Header {
   392  	return b.bc.CurrentBlock().Header().(*types.Header)
   393  }
   394  
   395  //func (b *API) Miner() *miner.Miner {
   396  //	return b..Miner().(*miner.Miner)
   397  //}
   398  
   399  //func (b *API) StateAtBlock(ctx context.Context, tx kv.Tx, block *types.Block /*reexec uint64, base *state.IntraBlockState, readOnly bool, preferDisk bool*/) (*state.IntraBlockState, tracers.StateReleaseFunc, error) {
   400  //	return b.bc.StateAt(tx, block.Number64().Uint64()), nil, nil
   401  //}
   402  //
   403  //func (b *API) StateAtTransaction(ctx context.Context, tx kv.Tx, block *types.Block, txIndex int /*, reexec uint64*/) (*transaction.Message, evmtypes.BlockContext, *state.IntraBlockState, tracers.StateReleaseFunc, error) {
   404  //	return .StateAtTransaction(ctx, tx, block, txIndex /*, reexec*/)
   405  //}
   406  
   407  // stateAtTransaction returns the execution environment of a certain transaction.
   408  func (eth *API) StateAtTransaction(ctx context.Context, dbTx kv.Tx, blk *types.Block, txIndex int) (*transaction.Message, evmtypes.BlockContext, *state.IntraBlockState, error) {
   409  	// Short circuit if it's genesis block.
   410  	if blk.Number64().Uint64() == 0 {
   411  		return nil, evmtypes.BlockContext{}, nil, errors.New("no transaction in genesis")
   412  	}
   413  	// Create the parent state database
   414  	parent := eth.BlockChain().GetBlock(blk.ParentHash(), blk.Number64().Uint64()-1).(*types.Block)
   415  	if parent == nil {
   416  		return nil, evmtypes.BlockContext{}, nil, fmt.Errorf("parent %#x not found", blk.ParentHash())
   417  	}
   418  	// Lookup the statedb of parent block from the live database,
   419  	// otherwise regenerate it on the flight.
   420  
   421  	statedb, err := eth.StateAtBlock(ctx, dbTx, parent)
   422  	if err != nil {
   423  		return nil, evmtypes.BlockContext{}, nil, err
   424  	}
   425  	if txIndex == 0 && len(blk.Transactions()) == 0 {
   426  		return nil, evmtypes.BlockContext{}, statedb, nil
   427  	}
   428  	// Recompute transactions up to the target index.
   429  	signer := transaction.MakeSigner(eth.BlockChain().Config(), blk.Number64().ToBig())
   430  	getHeader := func(hash common.Hash, number uint64) *types.Header {
   431  		return rawdb.ReadHeader(dbTx, hash, number)
   432  	}
   433  	blockContext := internal.NewEVMBlockContext(blk.Header().(*types.Header), internal.GetHashFn(blk.Header().(*types.Header), getHeader), eth.Engine(), nil)
   434  	vmenv := vm.NewEVM(blockContext, evmtypes.TxContext{}, statedb, eth.BlockChain().Config(), vm.Config{})
   435  	rules := vmenv.ChainRules()
   436  
   437  	for idx, tx := range blk.Transactions() {
   438  		//// Assemble the transaction call message and return if the requested offset
   439  		//msg, _ := tx.AsMessage(signer, blk.BaseFee64())
   440  		//txContext := internal.NewEVMTxContext(msg)
   441  		//
   442  		//if idx == txIndex {
   443  		//	return msg, blockContext, statedb, release, nil
   444  		//}
   445  		//vmenv.Reset()
   446  		//// Not yet the searched for transaction, execute on top of the current state
   447  		//statedb.Prepare(tx.Hash(), blk.Hash(), idx)
   448  		//if _, err := internal.ApplyMessage(vmenv, msg, new(common.GasPool).AddGas(tx.Gas()), true, false); err != nil {
   449  		//	return nil, evmtypes.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
   450  		//}
   451  		//// Ensure any modifications are committed to the state
   452  		//// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   453  		//statedb.FinalizeTx(rules, )
   454  		statedb.Prepare(tx.Hash(), blk.Hash(), idx)
   455  
   456  		// Assemble the transaction call message and return if the requested offset
   457  		msg, _ := tx.AsMessage(signer, blk.BaseFee64())
   458  		if msg.FeeCap().IsZero() && eth.Engine() != nil {
   459  			syscall := func(contract common.Address, data []byte) ([]byte, error) {
   460  				return internal.SysCallContract(contract, data, *eth.BlockChain().Config(), statedb, blk.Header().(*types.Header), eth.Engine() /* constCall */)
   461  			}
   462  			msg.SetIsFree(eth.Engine().IsServiceTransaction(msg.From(), syscall))
   463  		}
   464  
   465  		TxContext := internal.NewEVMTxContext(msg)
   466  		if idx == txIndex {
   467  			return &msg, blockContext, statedb, nil
   468  		}
   469  		vmenv.Reset(TxContext, statedb)
   470  		// Not yet the searched for transaction, execute on top of the current state
   471  		if _, err := internal.ApplyMessage(vmenv, msg, new(common2.GasPool).AddGas(tx.Gas()), true /* refunds */, false /* gasBailout */); err != nil {
   472  			return nil, evmtypes.BlockContext{}, nil, fmt.Errorf("transaction %x failed: %w", tx.Hash(), err)
   473  		}
   474  		// Ensure any modifications are committed to the state
   475  		// Only delete empty objects if EIP161 (part of Spurious Dragon) is in effect
   476  		_ = statedb.FinalizeTx(rules, statedb.GetStateReader().(*state.PlainState))
   477  
   478  		if idx+1 == len(blk.Transactions()) {
   479  			// Return the state from evaluating all txs in the block, note no msg or TxContext in this case
   480  			return nil, blockContext, statedb, nil
   481  		}
   482  	}
   483  	return nil, evmtypes.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blk.Hash())
   484  }
   485  
   486  // StateAtBlock retrieves the state database associated with a certain block.
   487  // If no state is locally available for the given block, a number of blocks
   488  // are attempted to be reexecuted to generate the desired state. The optional
   489  // base layer statedb can be provided which is regarded as the statedb of the
   490  // parent block.
   491  //
   492  // An additional release function will be returned if the requested state is
   493  // available. Release is expected to be invoked when the returned state is no longer needed.
   494  // Its purpose is to prevent resource leaking. Though it can be noop in some cases.
   495  //
   496  // Parameters:
   497  //   - block:      The block for which we want the state(state = block.Root)
   498  //   - reexec:     The maximum number of blocks to reprocess trying to obtain the desired state
   499  //   - base:       If the caller is tracing multiple blocks, the caller can provide the parent
   500  //     state continuously from the callsite.
   501  //   - readOnly:   If true, then the live 'blockchain' state database is used. No mutation should
   502  //     be made from caller, e.g. perform Commit or other 'save-to-disk' changes.
   503  //     Otherwise, the trash generated by caller may be persisted permanently.
   504  //   - preferDisk: this arg can be used by the caller to signal that even though the 'base' is
   505  //     provided, it would be preferable to start from a fresh state, if we have it
   506  //     on disk.
   507  func (eth *API) StateAtBlock(ctx context.Context, tx kv.Tx, blk *types.Block) (statedb *state.IntraBlockState, err error) {
   508  	var (
   509  		//current *block.Block
   510  		//// database state.Database
   511  		//report = true
   512  		origin = blk.Number64().Uint64()
   513  	)
   514  	// The state is only for reading purposes, check the state presence in
   515  	// live database.
   516  	//if readOnly {
   517  	// The state is available in live database, create a reference
   518  	// on top to prevent garbage collection and return a release
   519  	// function to deref it.
   520  	statedb = eth.BlockChain().StateAt(tx, origin)
   521  	//statedb.Database().TrieDB().Reference(block.Root(), common.Hash{})
   522  	return statedb, nil
   523  	//}
   524  	//}
   525  	// The state is both for reading and writing, or it's unavailable in disk,
   526  	// try to construct/recover the state over an ephemeral trie.Database for
   527  	// isolating the live one.
   528  	//if base != nil {
   529  	//	if preferDisk {
   530  	//		// Create an ephemeral trie.Database for isolating the live one. Otherwise
   531  	//		// the internal junks created by tracing will be persisted into the disk.
   532  	//		database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16})
   533  	//		if statedb, err = state.New(block.Root(), database, nil); err == nil {
   534  	//			log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
   535  	//			return statedb, noopReleaser, nil
   536  	//		}
   537  	//	}
   538  	//	// The optional base statedb is given, mark the start point as parent block
   539  	//	statedb, database, report = base, base.Database(), false
   540  	//	current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
   541  	//} else {
   542  	// Otherwise, try to reexec blocks until we find a state or reach our limit
   543  	//current = block
   544  
   545  	// Create an ephemeral trie.Database for isolating the live one. Otherwise
   546  	// the internal junks created by tracing will be persisted into the disk.
   547  	// database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16})
   548  
   549  	// If we didn't check the live database, do check state over ephemeral database,
   550  	// otherwise we would rewind past a persisted block (specific corner case is
   551  	// chain tracing from the genesis).
   552  	//if !readOnly {
   553  	//	statedb, err = state.New(current.Root(), database, nil)
   554  	//	if err == nil {
   555  	//		return statedb, noopReleaser, nil
   556  	//	}
   557  	//}
   558  	//// Database does not have the state for the given block, try to regenerate
   559  	//for i := uint64(0); i < reexec; i++ {
   560  	//	if err := ctx.Err(); err != nil {
   561  	//		return nil, nil, err
   562  	//	}
   563  	//	if current.NumberU64() == 0 {
   564  	//		return nil, nil, errors.New("genesis state is missing")
   565  	//	}
   566  	//	parent := eth.blockchain.GetBlock(current.ParentHash(), current.NumberU64()-1)
   567  	//	if parent == nil {
   568  	//		return nil, nil, fmt.Errorf("missing block %v %d", current.ParentHash(), current.NumberU64()-1)
   569  	//	}
   570  	//	current = parent
   571  	//
   572  	//	statedb, err = state.New(current.Root(), database, nil)
   573  	//	if err == nil {
   574  	//		break
   575  	//	}
   576  	//}
   577  	//if err != nil {
   578  	//	switch err.(type) {
   579  	//	case *trie.MissingNodeError:
   580  	//		return nil, nil, fmt.Errorf("required historical state unavailable (reexec=%d)", reexec)
   581  	//	default:
   582  	//		return nil, nil, err
   583  	//	}
   584  	//}
   585  	//}
   586  	// State is available at historical point, re-execute the blocks on top for
   587  	// the desired state.
   588  	//var (
   589  	//	start  = time.Now()
   590  	//	logged time.Time
   591  	//	parent common.Hash
   592  	//)
   593  	//for current.NumberU64() < origin {
   594  	//	if err := ctx.Err(); err != nil {
   595  	//		return nil, nil, err
   596  	//	}
   597  	//	// Print progress logs if long enough time elapsed
   598  	//	if time.Since(logged) > 8*time.Second && report {
   599  	//		log.Info("Regenerating historical state", "block", current.NumberU64()+1, "target", origin, "remaining", origin-current.NumberU64()-1, "elapsed", time.Since(start))
   600  	//		logged = time.Now()
   601  	//	}
   602  	//	// Retrieve the next block to regenerate and process it
   603  	//	next := current.NumberU64() + 1
   604  	//	if current = eth.blockchain.GetBlockByNumber(next); current == nil {
   605  	//		return nil, nil, fmt.Errorf("block #%d not found", next)
   606  	//	}
   607  	//	_, _, _, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{})
   608  	//	if err != nil {
   609  	//		return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err)
   610  	//	}
   611  	//	// Finalize the state so any modifications are written to the trie
   612  	//	root, err := statedb.Commit(eth.blockchain.Config().IsEIP158(current.Number()))
   613  	//	if err != nil {
   614  	//		return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w",
   615  	//			current.NumberU64(), current.Root().Hex(), err)
   616  	//	}
   617  	//	statedb, err = state.New(root, database, nil)
   618  	//	if err != nil {
   619  	//		return nil, nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err)
   620  	//	}
   621  	//	// Hold the state reference and also drop the parent state
   622  	//	// to prevent accumulating too many nodes in memory.
   623  	//	database.TrieDB().Reference(root, common.Hash{})
   624  	//	if parent != (common.Hash{}) {
   625  	//		database.TrieDB().Dereference(parent)
   626  	//	}
   627  	//	parent = root
   628  	//}
   629  	//if report {
   630  	//	nodes, imgs := database.TrieDB().Size()
   631  	//	log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs)
   632  	//}
   633  	//return statedb, func() { database.TrieDB().Dereference(block.Root()) }, nil
   634  }