github.com/klaytn/klaytn@v1.10.2/node/cn/api_backend.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of go-ethereum.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from eth/api_backend.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package cn
    22  
    23  import (
    24  	"context"
    25  	"fmt"
    26  	"math/big"
    27  	"time"
    28  
    29  	"github.com/klaytn/klaytn"
    30  	"github.com/klaytn/klaytn/accounts"
    31  	"github.com/klaytn/klaytn/blockchain"
    32  	"github.com/klaytn/klaytn/blockchain/bloombits"
    33  	"github.com/klaytn/klaytn/blockchain/state"
    34  	"github.com/klaytn/klaytn/blockchain/types"
    35  	"github.com/klaytn/klaytn/blockchain/vm"
    36  	"github.com/klaytn/klaytn/common"
    37  	"github.com/klaytn/klaytn/consensus"
    38  	"github.com/klaytn/klaytn/event"
    39  	"github.com/klaytn/klaytn/networks/rpc"
    40  	"github.com/klaytn/klaytn/node/cn/gasprice"
    41  	"github.com/klaytn/klaytn/params"
    42  	"github.com/klaytn/klaytn/storage/database"
    43  )
    44  
    45  // CNAPIBackend implements api.Backend for full nodes
    46  type CNAPIBackend struct {
    47  	cn  *CN
    48  	gpo *gasprice.Oracle
    49  }
    50  
    51  // GetTxLookupInfoAndReceipt retrieves a tx and lookup info and receipt for a given transaction hash.
    52  func (b *CNAPIBackend) GetTxLookupInfoAndReceipt(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, *types.Receipt) {
    53  	return b.cn.blockchain.GetTxLookupInfoAndReceipt(txHash)
    54  }
    55  
    56  // GetTxAndLookupInfoInCache retrieves a tx and lookup info for a given transaction hash in cache.
    57  func (b *CNAPIBackend) GetTxAndLookupInfoInCache(txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
    58  	return b.cn.blockchain.GetTxAndLookupInfoInCache(txHash)
    59  }
    60  
    61  // GetBlockReceiptsInCache retrieves receipts for a given block hash in cache.
    62  func (b *CNAPIBackend) GetBlockReceiptsInCache(blockHash common.Hash) types.Receipts {
    63  	return b.cn.blockchain.GetBlockReceiptsInCache(blockHash)
    64  }
    65  
    66  // GetTxLookupInfoAndReceiptInCache retrieves a tx and lookup info and receipt for a given transaction hash in cache.
    67  func (b *CNAPIBackend) GetTxLookupInfoAndReceiptInCache(txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, *types.Receipt) {
    68  	return b.cn.blockchain.GetTxLookupInfoAndReceiptInCache(txHash)
    69  }
    70  
    71  func (b *CNAPIBackend) ChainConfig() *params.ChainConfig {
    72  	return b.cn.chainConfig
    73  }
    74  
    75  func (b *CNAPIBackend) CurrentBlock() *types.Block {
    76  	return b.cn.blockchain.CurrentBlock()
    77  }
    78  
    79  func (b *CNAPIBackend) SetHead(number uint64) {
    80  	b.cn.protocolManager.Downloader().Cancel()
    81  	b.cn.protocolManager.SetSyncStop(true)
    82  	b.cn.blockchain.SetHead(number)
    83  	b.cn.protocolManager.SetSyncStop(false)
    84  }
    85  
    86  func (b *CNAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
    87  	// Pending block is only known by the miner
    88  	if blockNr == rpc.PendingBlockNumber {
    89  		block := b.cn.miner.PendingBlock()
    90  		return block.Header(), nil
    91  	}
    92  	// Otherwise resolve and return the block
    93  	if blockNr == rpc.LatestBlockNumber {
    94  		return b.cn.blockchain.CurrentBlock().Header(), nil
    95  	}
    96  	header := b.cn.blockchain.GetHeaderByNumber(uint64(blockNr))
    97  	if header == nil {
    98  		return nil, fmt.Errorf("the header does not exist (block number: %d)", blockNr)
    99  	}
   100  	return header, nil
   101  }
   102  
   103  func (b *CNAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
   104  	if blockNr, ok := blockNrOrHash.Number(); ok {
   105  		return b.HeaderByNumber(ctx, blockNr)
   106  	}
   107  	if hash, ok := blockNrOrHash.Hash(); ok {
   108  		header, err := b.HeaderByHash(ctx, hash)
   109  		if err != nil {
   110  			return nil, err
   111  		}
   112  		return header, nil
   113  	}
   114  	return nil, fmt.Errorf("invalid arguments; neither block nor hash specified")
   115  }
   116  
   117  func (b *CNAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   118  	if header := b.cn.blockchain.GetHeaderByHash(hash); header != nil {
   119  		return header, nil
   120  	}
   121  	return nil, fmt.Errorf("the header does not exist (hash: %d)", hash)
   122  }
   123  
   124  func (b *CNAPIBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
   125  	// Pending block is only known by the miner
   126  	if blockNr == rpc.PendingBlockNumber {
   127  		block := b.cn.miner.PendingBlock()
   128  		return block, nil
   129  	}
   130  	// Otherwise resolve and return the block
   131  	if blockNr == rpc.LatestBlockNumber {
   132  		return b.cn.blockchain.CurrentBlock(), nil
   133  	}
   134  	block := b.cn.blockchain.GetBlockByNumber(uint64(blockNr))
   135  	if block == nil {
   136  		return nil, fmt.Errorf("the block does not exist (block number: %d)", blockNr)
   137  	}
   138  	return block, nil
   139  }
   140  
   141  func (b *CNAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
   142  	if blockNr, ok := blockNrOrHash.Number(); ok {
   143  		return b.BlockByNumber(ctx, blockNr)
   144  	}
   145  	if hash, ok := blockNrOrHash.Hash(); ok {
   146  		block, err := b.BlockByHash(ctx, hash)
   147  		if err != nil {
   148  			return nil, err
   149  		}
   150  		return block, nil
   151  	}
   152  	return nil, fmt.Errorf("invalid arguments; neither block nor hash specified")
   153  }
   154  
   155  func (b *CNAPIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
   156  	// Pending state is only known by the miner
   157  	if blockNr == rpc.PendingBlockNumber {
   158  		block, state := b.cn.miner.Pending()
   159  		return state, block.Header(), nil
   160  	}
   161  	// Otherwise resolve the block number and return its state
   162  	header, err := b.HeaderByNumber(ctx, blockNr)
   163  	if header == nil || err != nil {
   164  		return nil, nil, err
   165  	}
   166  	stateDb, err := b.cn.BlockChain().StateAt(header.Root)
   167  	return stateDb, header, err
   168  }
   169  
   170  func (b *CNAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
   171  	if blockNr, ok := blockNrOrHash.Number(); ok {
   172  		return b.StateAndHeaderByNumber(ctx, blockNr)
   173  	}
   174  	if hash, ok := blockNrOrHash.Hash(); ok {
   175  		header := b.cn.blockchain.GetHeaderByHash(hash)
   176  		if header == nil {
   177  			return nil, nil, fmt.Errorf("header for hash not found")
   178  		}
   179  		stateDb, err := b.cn.BlockChain().StateAt(header.Root)
   180  		return stateDb, header, err
   181  	}
   182  	return nil, nil, fmt.Errorf("invalid arguments; neither block nor hash specified")
   183  }
   184  
   185  func (b *CNAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   186  	block := b.cn.blockchain.GetBlockByHash(hash)
   187  	if block == nil {
   188  		return nil, fmt.Errorf("the block does not exist (block hash: %s)", hash.String())
   189  	}
   190  	return block, nil
   191  }
   192  
   193  // GetTxAndLookupInfo retrieves a tx and lookup info for a given transaction hash.
   194  func (b *CNAPIBackend) GetTxAndLookupInfo(hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
   195  	return b.cn.blockchain.GetTxAndLookupInfo(hash)
   196  }
   197  
   198  // GetBlockReceipts retrieves the receipts for all transactions with given block hash.
   199  func (b *CNAPIBackend) GetBlockReceipts(ctx context.Context, hash common.Hash) types.Receipts {
   200  	return b.cn.blockchain.GetReceiptsByBlockHash(hash)
   201  }
   202  
   203  func (b *CNAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
   204  	return b.cn.blockchain.GetLogsByHash(hash), nil
   205  }
   206  
   207  func (b *CNAPIBackend) GetTd(blockHash common.Hash) *big.Int {
   208  	return b.cn.blockchain.GetTdByHash(blockHash)
   209  }
   210  
   211  func (b *CNAPIBackend) GetEVM(ctx context.Context, msg blockchain.Message, state *state.StateDB, header *types.Header, vmCfg vm.Config) (*vm.EVM, func() error, error) {
   212  	vmError := func() error { return nil }
   213  
   214  	context := blockchain.NewEVMContext(msg, header, b.cn.BlockChain(), nil)
   215  	return vm.NewEVM(context, state, b.cn.chainConfig, &vmCfg), vmError, nil
   216  }
   217  
   218  func (b *CNAPIBackend) SubscribeRemovedLogsEvent(ch chan<- blockchain.RemovedLogsEvent) event.Subscription {
   219  	return b.cn.BlockChain().SubscribeRemovedLogsEvent(ch)
   220  }
   221  
   222  func (b *CNAPIBackend) SubscribeChainEvent(ch chan<- blockchain.ChainEvent) event.Subscription {
   223  	return b.cn.BlockChain().SubscribeChainEvent(ch)
   224  }
   225  
   226  func (b *CNAPIBackend) SubscribeChainHeadEvent(ch chan<- blockchain.ChainHeadEvent) event.Subscription {
   227  	return b.cn.BlockChain().SubscribeChainHeadEvent(ch)
   228  }
   229  
   230  func (b *CNAPIBackend) SubscribeChainSideEvent(ch chan<- blockchain.ChainSideEvent) event.Subscription {
   231  	return b.cn.BlockChain().SubscribeChainSideEvent(ch)
   232  }
   233  
   234  func (b *CNAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   235  	return b.cn.BlockChain().SubscribeLogsEvent(ch)
   236  }
   237  
   238  func (b *CNAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
   239  	return b.cn.txPool.AddLocal(signedTx)
   240  }
   241  
   242  func (b *CNAPIBackend) GetPoolTransactions() (types.Transactions, error) {
   243  	pending, err := b.cn.txPool.Pending()
   244  	if err != nil {
   245  		return nil, err
   246  	}
   247  	var txs types.Transactions
   248  	for _, batch := range pending {
   249  		txs = append(txs, batch...)
   250  	}
   251  	return txs, nil
   252  }
   253  
   254  func (b *CNAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction {
   255  	return b.cn.txPool.Get(hash)
   256  }
   257  
   258  func (b *CNAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) uint64 {
   259  	return b.cn.txPool.GetPendingNonce(addr)
   260  }
   261  
   262  func (b *CNAPIBackend) Stats() (pending int, queued int) {
   263  	return b.cn.txPool.Stats()
   264  }
   265  
   266  func (b *CNAPIBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
   267  	return b.cn.TxPool().Content()
   268  }
   269  
   270  func (b *CNAPIBackend) SubscribeNewTxsEvent(ch chan<- blockchain.NewTxsEvent) event.Subscription {
   271  	return b.cn.TxPool().SubscribeNewTxsEvent(ch)
   272  }
   273  
   274  func (b *CNAPIBackend) Progress() klaytn.SyncProgress {
   275  	return b.cn.Progress()
   276  }
   277  
   278  func (b *CNAPIBackend) ProtocolVersion() int {
   279  	return b.cn.ProtocolVersion()
   280  }
   281  
   282  // SuggestPrice returns the baseFee * 2 if the current block is magma hard forked.
   283  // Other cases, it returns the unitPrice.
   284  func (b *CNAPIBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
   285  	return b.gpo.SuggestPrice(ctx)
   286  }
   287  
   288  func (b *CNAPIBackend) UpperBoundGasPrice(ctx context.Context) *big.Int {
   289  	bignum := b.CurrentBlock().Number()
   290  	pset, err := b.cn.governance.EffectiveParams(bignum.Uint64() + 1)
   291  	if err != nil {
   292  		return nil
   293  	}
   294  	if b.cn.chainConfig.IsMagmaForkEnabled(bignum) {
   295  		return new(big.Int).SetUint64(pset.UpperBoundBaseFee())
   296  	} else {
   297  		return new(big.Int).SetUint64(pset.UnitPrice())
   298  	}
   299  }
   300  
   301  func (b *CNAPIBackend) LowerBoundGasPrice(ctx context.Context) *big.Int {
   302  	bignum := b.CurrentBlock().Number()
   303  	pset, err := b.cn.governance.EffectiveParams(bignum.Uint64() + 1)
   304  	if err != nil {
   305  		return nil
   306  	}
   307  	if b.cn.chainConfig.IsMagmaForkEnabled(bignum) {
   308  		return new(big.Int).SetUint64(pset.LowerBoundBaseFee())
   309  	} else {
   310  		return new(big.Int).SetUint64(pset.UnitPrice())
   311  	}
   312  }
   313  
   314  func (b *CNAPIBackend) ChainDB() database.DBManager {
   315  	return b.cn.ChainDB()
   316  }
   317  
   318  func (b *CNAPIBackend) EventMux() *event.TypeMux {
   319  	return b.cn.EventMux()
   320  }
   321  
   322  func (b *CNAPIBackend) AccountManager() accounts.AccountManager {
   323  	return b.cn.AccountManager()
   324  }
   325  
   326  func (b *CNAPIBackend) BloomStatus() (uint64, uint64) {
   327  	sections, _, _ := b.cn.bloomIndexer.Sections()
   328  	return params.BloomBitsBlocks, sections
   329  }
   330  
   331  func (b *CNAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
   332  	for i := 0; i < bloomFilterThreads; i++ {
   333  		go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.cn.bloomRequests)
   334  	}
   335  }
   336  
   337  func (b *CNAPIBackend) IsParallelDBWrite() bool {
   338  	return b.cn.BlockChain().IsParallelDBWrite()
   339  }
   340  
   341  func (b *CNAPIBackend) IsSenderTxHashIndexingEnabled() bool {
   342  	return b.cn.BlockChain().IsSenderTxHashIndexingEnabled()
   343  }
   344  
   345  func (b *CNAPIBackend) RPCGasCap() *big.Int {
   346  	return b.cn.config.RPCGasCap
   347  }
   348  
   349  func (b *CNAPIBackend) RPCEVMTimeout() time.Duration {
   350  	return b.cn.config.RPCEVMTimeout
   351  }
   352  
   353  func (b *CNAPIBackend) RPCTxFeeCap() float64 {
   354  	return b.cn.config.RPCTxFeeCap
   355  }
   356  
   357  func (b *CNAPIBackend) Engine() consensus.Engine {
   358  	return b.cn.engine
   359  }
   360  
   361  func (b *CNAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (*state.StateDB, error) {
   362  	return b.cn.stateAtBlock(block, reexec, base, checkLive, preferDisk)
   363  }
   364  
   365  func (b *CNAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (blockchain.Message, vm.Context, *state.StateDB, error) {
   366  	return b.cn.stateAtTransaction(block, txIndex, reexec)
   367  }
   368  
   369  func (b *CNAPIBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
   370  	return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
   371  }