gitlab.com/flarenetwork/coreth@v0.1.1/eth/api_backend.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2015 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package eth
    28  
    29  import (
    30  	"context"
    31  	"errors"
    32  	"math/big"
    33  	"time"
    34  
    35  	"github.com/ethereum/go-ethereum/common"
    36  	"github.com/ethereum/go-ethereum/eth/downloader"
    37  	"github.com/ethereum/go-ethereum/ethdb"
    38  	"github.com/ethereum/go-ethereum/event"
    39  	"gitlab.com/flarenetwork/coreth/accounts"
    40  	"gitlab.com/flarenetwork/coreth/consensus"
    41  	"gitlab.com/flarenetwork/coreth/core"
    42  	"gitlab.com/flarenetwork/coreth/core/bloombits"
    43  	"gitlab.com/flarenetwork/coreth/core/rawdb"
    44  	"gitlab.com/flarenetwork/coreth/core/state"
    45  	"gitlab.com/flarenetwork/coreth/core/types"
    46  	"gitlab.com/flarenetwork/coreth/core/vm"
    47  	"gitlab.com/flarenetwork/coreth/eth/gasprice"
    48  	"gitlab.com/flarenetwork/coreth/params"
    49  	"gitlab.com/flarenetwork/coreth/rpc"
    50  )
    51  
    52  var (
    53  	ErrUnfinalizedData = errors.New("cannot query unfinalized data")
    54  	errExpired         = errors.New("request expired")
    55  )
    56  
    57  // EthAPIBackend implements ethapi.Backend for full nodes
    58  type EthAPIBackend struct {
    59  	extRPCEnabled       bool
    60  	allowUnprotectedTxs bool
    61  	eth                 *Ethereum
    62  	gpo                 *gasprice.Oracle
    63  }
    64  
    65  // ChainConfig returns the active chain configuration.
    66  func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
    67  	return b.eth.blockchain.Config()
    68  }
    69  
    70  func (b *EthAPIBackend) GetVMConfig() *vm.Config {
    71  	return b.eth.blockchain.GetVMConfig()
    72  }
    73  
    74  func (b *EthAPIBackend) CurrentBlock() *types.Block {
    75  	return b.eth.blockchain.CurrentBlock()
    76  }
    77  
    78  func (b *EthAPIBackend) LastAcceptedBlock() *types.Block {
    79  	return b.eth.LastAcceptedBlock()
    80  }
    81  
    82  func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
    83  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
    84  		return nil, errExpired
    85  	}
    86  	// Treat requests for the pending, latest, or accepted block
    87  	// identically.
    88  	acceptedBlock := b.eth.LastAcceptedBlock()
    89  	if number.IsAccepted() {
    90  		return acceptedBlock.Header(), nil
    91  	}
    92  
    93  	if !b.GetVMConfig().AllowUnfinalizedQueries && acceptedBlock != nil {
    94  		if number.Int64() > acceptedBlock.Number().Int64() {
    95  			return nil, ErrUnfinalizedData
    96  		}
    97  	}
    98  
    99  	return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil
   100  }
   101  
   102  func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
   103  	if blockNr, ok := blockNrOrHash.Number(); ok {
   104  		return b.HeaderByNumber(ctx, blockNr)
   105  	}
   106  	if hash, ok := blockNrOrHash.Hash(); ok {
   107  		header := b.eth.blockchain.GetHeaderByHash(hash)
   108  		if header == nil {
   109  			return nil, errors.New("header for hash not found")
   110  		}
   111  		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   112  			return nil, errors.New("hash is not currently canonical")
   113  		}
   114  		return header, nil
   115  	}
   116  	return nil, errors.New("invalid arguments; neither block nor hash specified")
   117  }
   118  
   119  func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   120  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   121  		return nil, errExpired
   122  	}
   123  	return b.eth.blockchain.GetHeaderByHash(hash), nil
   124  }
   125  
   126  func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   127  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   128  		return nil, errExpired
   129  	}
   130  	// Treat requests for the pending, latest, or accepted block
   131  	// identically.
   132  	acceptedBlock := b.eth.LastAcceptedBlock()
   133  	if number.IsAccepted() {
   134  		return acceptedBlock, nil
   135  	}
   136  
   137  	if !b.GetVMConfig().AllowUnfinalizedQueries && acceptedBlock != nil {
   138  		if number.Int64() > acceptedBlock.Number().Int64() {
   139  			return nil, ErrUnfinalizedData
   140  		}
   141  	}
   142  
   143  	return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
   144  }
   145  
   146  func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   147  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   148  		return nil, errExpired
   149  	}
   150  	return b.eth.blockchain.GetBlockByHash(hash), nil
   151  }
   152  
   153  func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
   154  	if blockNr, ok := blockNrOrHash.Number(); ok {
   155  		return b.BlockByNumber(ctx, blockNr)
   156  	}
   157  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   158  		return nil, errExpired
   159  	}
   160  	if hash, ok := blockNrOrHash.Hash(); ok {
   161  		header := b.eth.blockchain.GetHeaderByHash(hash)
   162  		if header == nil {
   163  			return nil, errors.New("header for hash not found")
   164  		}
   165  		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   166  			return nil, errors.New("hash is not currently canonical")
   167  		}
   168  		block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64())
   169  		if block == nil {
   170  			return nil, errors.New("header found, but block body is missing")
   171  		}
   172  		return block, nil
   173  	}
   174  	return nil, errors.New("invalid arguments; neither block nor hash specified")
   175  }
   176  
   177  func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
   178  	// Request the block by its number and retrieve its state
   179  	header, err := b.HeaderByNumber(ctx, number)
   180  	if err != nil {
   181  		return nil, nil, err
   182  	}
   183  	if header == nil {
   184  		return nil, nil, errors.New("header not found")
   185  	}
   186  	stateDb, err := b.eth.BlockChain().StateAt(header.Root)
   187  	return stateDb, header, err
   188  }
   189  
   190  func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
   191  	if blockNr, ok := blockNrOrHash.Number(); ok {
   192  		return b.StateAndHeaderByNumber(ctx, blockNr)
   193  	}
   194  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   195  		return nil, nil, errExpired
   196  	}
   197  	if hash, ok := blockNrOrHash.Hash(); ok {
   198  		header, err := b.HeaderByHash(ctx, hash)
   199  		if err != nil {
   200  			return nil, nil, err
   201  		}
   202  		if header == nil {
   203  			return nil, nil, errors.New("header for hash not found")
   204  		}
   205  		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   206  			return nil, nil, errors.New("hash is not currently canonical")
   207  		}
   208  		stateDb, err := b.eth.BlockChain().StateAt(header.Root)
   209  		return stateDb, header, err
   210  	}
   211  	return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
   212  }
   213  
   214  func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
   215  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   216  		return nil, errExpired
   217  	}
   218  	return b.eth.blockchain.GetReceiptsByHash(hash), nil
   219  }
   220  
   221  func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
   222  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   223  		return nil, errExpired
   224  	}
   225  	receipts := b.eth.blockchain.GetReceiptsByHash(hash)
   226  	if receipts == nil {
   227  		return nil, nil
   228  	}
   229  	logs := make([][]*types.Log, len(receipts))
   230  	for i, receipt := range receipts {
   231  		logs[i] = receipt.Logs
   232  	}
   233  	return logs, nil
   234  }
   235  
   236  func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
   237  	return b.eth.blockchain.GetTdByHash(hash)
   238  }
   239  
   240  func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) {
   241  	vmError := func() error { return nil }
   242  	if vmConfig == nil {
   243  		vmConfig = b.eth.blockchain.GetVMConfig()
   244  	}
   245  	txContext := core.NewEVMTxContext(msg)
   246  	context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
   247  	return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), vmError, nil
   248  }
   249  
   250  func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   251  	return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch)
   252  }
   253  
   254  func (b *EthAPIBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
   255  	return b.eth.miner.SubscribePendingLogs(ch)
   256  }
   257  
   258  func (b *EthAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
   259  	return b.eth.BlockChain().SubscribeChainEvent(ch)
   260  }
   261  
   262  func (b *EthAPIBackend) SubscribeChainAcceptedEvent(ch chan<- core.ChainEvent) event.Subscription {
   263  	return b.eth.BlockChain().SubscribeChainAcceptedEvent(ch)
   264  }
   265  
   266  func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
   267  	return b.eth.BlockChain().SubscribeChainHeadEvent(ch)
   268  }
   269  
   270  func (b *EthAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
   271  	return b.eth.BlockChain().SubscribeChainSideEvent(ch)
   272  }
   273  
   274  func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   275  	return b.eth.BlockChain().SubscribeLogsEvent(ch)
   276  }
   277  
   278  func (b *EthAPIBackend) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription {
   279  	return b.eth.BlockChain().SubscribeAcceptedLogsEvent(ch)
   280  }
   281  
   282  func (b *EthAPIBackend) SubscribeAcceptedTransactionEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   283  	return b.eth.BlockChain().SubscribeAcceptedTransactionEvent(ch)
   284  }
   285  
   286  func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
   287  	if deadline, exists := ctx.Deadline(); exists && time.Until(deadline) < 0 {
   288  		return errExpired
   289  	}
   290  	err := b.eth.txPool.AddLocal(signedTx)
   291  	return err
   292  }
   293  
   294  func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
   295  	pending, err := b.eth.txPool.Pending(false)
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  	var txs types.Transactions
   300  	for _, batch := range pending {
   301  		txs = append(txs, batch...)
   302  	}
   303  	return txs, nil
   304  }
   305  
   306  func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction {
   307  	return b.eth.txPool.Get(hash)
   308  }
   309  
   310  func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
   311  	tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash)
   312  
   313  	// Respond as if the transaction does not exist if it is not yet in an
   314  	// accepted block. We explicitly choose not to error here to avoid breaking
   315  	// expectations with clients (expect an empty response when a transaction
   316  	// does not exist).
   317  	acceptedBlock := b.eth.LastAcceptedBlock()
   318  	if !b.GetVMConfig().AllowUnfinalizedQueries && acceptedBlock != nil && tx != nil {
   319  		if blockNumber > acceptedBlock.NumberU64() {
   320  			return nil, common.Hash{}, 0, 0, nil
   321  		}
   322  	}
   323  
   324  	return tx, blockHash, blockNumber, index, nil
   325  }
   326  
   327  func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
   328  	return b.eth.txPool.Nonce(addr), nil
   329  }
   330  
   331  func (b *EthAPIBackend) Stats() (pending int, queued int) {
   332  	return b.eth.txPool.Stats()
   333  }
   334  
   335  func (b *EthAPIBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
   336  	return b.eth.TxPool().Content()
   337  }
   338  
   339  func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) {
   340  	return b.eth.TxPool().ContentFrom(addr)
   341  }
   342  
   343  func (b *EthAPIBackend) TxPool() *core.TxPool {
   344  	return b.eth.TxPool()
   345  }
   346  
   347  func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   348  	return b.eth.TxPool().SubscribeNewTxsEvent(ch)
   349  }
   350  
   351  func (b *EthAPIBackend) Downloader() *downloader.Downloader {
   352  	return b.eth.Downloader()
   353  }
   354  
   355  func (b *EthAPIBackend) EstimateBaseFee(ctx context.Context) (*big.Int, error) {
   356  	return b.gpo.EstimateBaseFee(ctx)
   357  }
   358  
   359  func (b *EthAPIBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
   360  	return b.gpo.SuggestPrice(ctx)
   361  }
   362  
   363  func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
   364  	return b.gpo.SuggestTipCap(ctx)
   365  }
   366  
   367  // TODO(aaronbuchwald) uncomment after migrating gasprice changes from v1.10.6
   368  // func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
   369  // 	return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
   370  // }
   371  
   372  func (b *EthAPIBackend) ChainDb() ethdb.Database {
   373  	return b.eth.ChainDb()
   374  }
   375  
   376  func (b *EthAPIBackend) EventMux() *event.TypeMux {
   377  	return b.eth.EventMux()
   378  }
   379  
   380  func (b *EthAPIBackend) AccountManager() *accounts.Manager {
   381  	return b.eth.AccountManager()
   382  }
   383  
   384  func (b *EthAPIBackend) ExtRPCEnabled() bool {
   385  	return b.extRPCEnabled
   386  }
   387  
   388  func (b *EthAPIBackend) UnprotectedAllowed() bool {
   389  	return b.allowUnprotectedTxs
   390  }
   391  
   392  func (b *EthAPIBackend) RPCGasCap() uint64 {
   393  	return b.eth.config.RPCGasCap
   394  }
   395  
   396  func (b *EthAPIBackend) RPCTxFeeCap() float64 {
   397  	return b.eth.config.RPCTxFeeCap
   398  }
   399  
   400  func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
   401  	sections, _, _ := b.eth.bloomIndexer.Sections()
   402  	return params.BloomBitsBlocks, sections
   403  }
   404  
   405  func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
   406  	for i := 0; i < bloomFilterThreads; i++ {
   407  		go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
   408  	}
   409  }
   410  
   411  func (b *EthAPIBackend) Engine() consensus.Engine {
   412  	return b.eth.engine
   413  }
   414  
   415  func (b *EthAPIBackend) CurrentHeader() *types.Header {
   416  	return b.eth.blockchain.CurrentHeader()
   417  }
   418  
   419  func (b *EthAPIBackend) GetMaxBlocksPerRequest() int64 {
   420  	return b.eth.settings.MaxBlocksPerRequest
   421  }
   422  
   423  func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) {
   424  	return b.eth.stateAtBlock(block, reexec, base, checkLive)
   425  }
   426  
   427  func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
   428  	return b.eth.stateAtTransaction(block, txIndex, reexec)
   429  }