github.com/MetalBlockchain/subnet-evm@v0.4.9/core/blockchain_reader.go (about)

     1  // (c) 2019-2021, 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 2021 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 core
    28  
    29  import (
    30  	"fmt"
    31  	"math/big"
    32  
    33  	"github.com/MetalBlockchain/subnet-evm/commontype"
    34  	"github.com/MetalBlockchain/subnet-evm/consensus"
    35  	"github.com/MetalBlockchain/subnet-evm/constants"
    36  	"github.com/MetalBlockchain/subnet-evm/core/rawdb"
    37  	"github.com/MetalBlockchain/subnet-evm/core/state"
    38  	"github.com/MetalBlockchain/subnet-evm/core/state/snapshot"
    39  	"github.com/MetalBlockchain/subnet-evm/core/types"
    40  	"github.com/MetalBlockchain/subnet-evm/core/vm"
    41  	"github.com/MetalBlockchain/subnet-evm/params"
    42  	"github.com/MetalBlockchain/subnet-evm/precompile"
    43  	"github.com/ethereum/go-ethereum/common"
    44  	"github.com/ethereum/go-ethereum/event"
    45  )
    46  
    47  // CurrentHeader retrieves the current head header of the canonical chain. The
    48  // header is retrieved from the HeaderChain's internal cache.
    49  func (bc *BlockChain) CurrentHeader() *types.Header {
    50  	return bc.hc.CurrentHeader()
    51  }
    52  
    53  // CurrentBlock retrieves the current head block of the canonical chain. The
    54  // block is retrieved from the blockchain's internal cache.
    55  func (bc *BlockChain) CurrentBlock() *types.Block {
    56  	return bc.currentBlock.Load().(*types.Block)
    57  }
    58  
    59  // HasHeader checks if a block header is present in the database or not, caching
    60  // it if present.
    61  func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
    62  	return bc.hc.HasHeader(hash, number)
    63  }
    64  
    65  // GetHeader retrieves a block header from the database by hash and number,
    66  // caching it if found.
    67  func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header {
    68  	return bc.hc.GetHeader(hash, number)
    69  }
    70  
    71  // GetHeaderByHash retrieves a block header from the database by hash, caching it if
    72  // found.
    73  func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header {
    74  	return bc.hc.GetHeaderByHash(hash)
    75  }
    76  
    77  // GetHeaderByNumber retrieves a block header from the database by number,
    78  // caching it (associated with its hash) if found.
    79  func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
    80  	return bc.hc.GetHeaderByNumber(number)
    81  }
    82  
    83  // GetBody retrieves a block body (transactions and uncles) from the database by
    84  // hash, caching it if found.
    85  func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
    86  	// Short circuit if the body's already in the cache, retrieve otherwise
    87  	if cached, ok := bc.bodyCache.Get(hash); ok {
    88  		body := cached.(*types.Body)
    89  		return body
    90  	}
    91  	number := bc.hc.GetBlockNumber(hash)
    92  	if number == nil {
    93  		return nil
    94  	}
    95  	body := rawdb.ReadBody(bc.db, hash, *number)
    96  	if body == nil {
    97  		return nil
    98  	}
    99  	// Cache the found body for next time and return
   100  	bc.bodyCache.Add(hash, body)
   101  	return body
   102  }
   103  
   104  // HasBlock checks if a block is fully present in the database or not.
   105  func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
   106  	if bc.blockCache.Contains(hash) {
   107  		return true
   108  	}
   109  	if !bc.HasHeader(hash, number) {
   110  		return false
   111  	}
   112  	return rawdb.HasBody(bc.db, hash, number)
   113  }
   114  
   115  // HasFastBlock checks if a fast block is fully present in the database or not.
   116  func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool {
   117  	if !bc.HasBlock(hash, number) {
   118  		return false
   119  	}
   120  	if bc.receiptsCache.Contains(hash) {
   121  		return true
   122  	}
   123  	return rawdb.HasReceipts(bc.db, hash, number)
   124  }
   125  
   126  // GetBlock retrieves a block from the database by hash and number,
   127  // caching it if found.
   128  func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
   129  	// Short circuit if the block's already in the cache, retrieve otherwise
   130  	if block, ok := bc.blockCache.Get(hash); ok {
   131  		return block.(*types.Block)
   132  	}
   133  	block := rawdb.ReadBlock(bc.db, hash, number)
   134  	if block == nil {
   135  		return nil
   136  	}
   137  	// Cache the found block for next time and return
   138  	bc.blockCache.Add(block.Hash(), block)
   139  	return block
   140  }
   141  
   142  // GetBlockByHash retrieves a block from the database by hash, caching it if found.
   143  func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
   144  	number := bc.hc.GetBlockNumber(hash)
   145  	if number == nil {
   146  		return nil
   147  	}
   148  	return bc.GetBlock(hash, *number)
   149  }
   150  
   151  // GetBlockByNumber retrieves a block from the database by number, caching it
   152  // (associated with its hash) if found.
   153  func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block {
   154  	hash := rawdb.ReadCanonicalHash(bc.db, number)
   155  	if hash == (common.Hash{}) {
   156  		return nil
   157  	}
   158  	return bc.GetBlock(hash, number)
   159  }
   160  
   161  // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
   162  // [deprecated by eth/62]
   163  func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
   164  	number := bc.hc.GetBlockNumber(hash)
   165  	if number == nil {
   166  		return nil
   167  	}
   168  	for i := 0; i < n; i++ {
   169  		block := bc.GetBlock(hash, *number)
   170  		if block == nil {
   171  			break
   172  		}
   173  		blocks = append(blocks, block)
   174  		hash = block.ParentHash()
   175  		*number--
   176  	}
   177  	return
   178  }
   179  
   180  // GetReceiptsByHash retrieves the receipts for all transactions in a given block.
   181  func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
   182  	if receipts, ok := bc.receiptsCache.Get(hash); ok {
   183  		return receipts.(types.Receipts)
   184  	}
   185  	number := rawdb.ReadHeaderNumber(bc.db, hash)
   186  	if number == nil {
   187  		return nil
   188  	}
   189  	receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig)
   190  	if receipts == nil {
   191  		return nil
   192  	}
   193  	bc.receiptsCache.Add(hash, receipts)
   194  	return receipts
   195  }
   196  
   197  // GetCanonicalHash returns the canonical hash for a given block number
   198  func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash {
   199  	return bc.hc.GetCanonicalHash(number)
   200  }
   201  
   202  // GetTransactionLookup retrieves the lookup associate with the given transaction
   203  // hash from the cache or database.
   204  func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry {
   205  	// Short circuit if the txlookup already in the cache, retrieve otherwise
   206  	if lookup, exist := bc.txLookupCache.Get(hash); exist {
   207  		return lookup.(*rawdb.LegacyTxLookupEntry)
   208  	}
   209  	tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
   210  	if tx == nil {
   211  		return nil
   212  	}
   213  	lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex}
   214  	bc.txLookupCache.Add(hash, lookup)
   215  	return lookup
   216  }
   217  
   218  // HasState checks if state trie is fully present in the database or not.
   219  func (bc *BlockChain) HasState(hash common.Hash) bool {
   220  	_, err := bc.stateCache.OpenTrie(hash)
   221  	return err == nil
   222  }
   223  
   224  // HasBlockAndState checks if a block and associated state trie is fully present
   225  // in the database or not, caching it if present.
   226  func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
   227  	// Check first that the block itself is known
   228  	block := bc.GetBlock(hash, number)
   229  	if block == nil {
   230  		return false
   231  	}
   232  	return bc.HasState(block.Root())
   233  }
   234  
   235  // TrieNode retrieves a blob of data associated with a trie node
   236  // either from ephemeral in-memory cache, or from persistent storage.
   237  func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
   238  	return bc.stateCache.TrieDB().RawNode(hash)
   239  }
   240  
   241  // ContractCode retrieves a blob of data associated with a contract hash
   242  // either from ephemeral in-memory cache, or from persistent storage.
   243  func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) {
   244  	return bc.stateCache.ContractCode(common.Hash{}, hash)
   245  }
   246  
   247  // State returns a new mutable state based on the current HEAD block.
   248  func (bc *BlockChain) State() (*state.StateDB, error) {
   249  	return bc.StateAt(bc.CurrentBlock().Root())
   250  }
   251  
   252  // StateAt returns a new mutable state based on a particular point in time.
   253  func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
   254  	return state.New(root, bc.stateCache, bc.snaps)
   255  }
   256  
   257  // Config retrieves the chain's fork configuration.
   258  func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }
   259  
   260  // Engine retrieves the blockchain's consensus engine.
   261  func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }
   262  
   263  // Snapshots returns the blockchain snapshot tree.
   264  func (bc *BlockChain) Snapshots() *snapshot.Tree {
   265  	return bc.snaps
   266  }
   267  
   268  // Validator returns the current validator.
   269  func (bc *BlockChain) Validator() Validator {
   270  	return bc.validator
   271  }
   272  
   273  // Processor returns the current processor.
   274  func (bc *BlockChain) Processor() Processor {
   275  	return bc.processor
   276  }
   277  
   278  // StateCache returns the caching database underpinning the blockchain instance.
   279  func (bc *BlockChain) StateCache() state.Database {
   280  	return bc.stateCache
   281  }
   282  
   283  // GasLimit returns the gas limit of the current HEAD block.
   284  func (bc *BlockChain) GasLimit() uint64 {
   285  	return bc.CurrentBlock().GasLimit()
   286  }
   287  
   288  // Genesis retrieves the chain's genesis block.
   289  func (bc *BlockChain) Genesis() *types.Block {
   290  	return bc.genesisBlock
   291  }
   292  
   293  // GetVMConfig returns the block chain VM config.
   294  func (bc *BlockChain) GetVMConfig() *vm.Config {
   295  	return &bc.vmConfig
   296  }
   297  
   298  // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent.
   299  func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription {
   300  	return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch))
   301  }
   302  
   303  // SubscribeChainEvent registers a subscription of ChainEvent.
   304  func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription {
   305  	return bc.scope.Track(bc.chainFeed.Subscribe(ch))
   306  }
   307  
   308  // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.
   309  func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription {
   310  	return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
   311  }
   312  
   313  // SubscribeChainSideEvent registers a subscription of ChainSideEvent.
   314  func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
   315  	return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
   316  }
   317  
   318  // SubscribeLogsEvent registers a subscription of []*types.Log.
   319  func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   320  	return bc.scope.Track(bc.logsFeed.Subscribe(ch))
   321  }
   322  
   323  // SubscribeBlockProcessingEvent registers a subscription of bool where true means
   324  // block processing has started while false means it has stopped.
   325  func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription {
   326  	return bc.scope.Track(bc.blockProcFeed.Subscribe(ch))
   327  }
   328  
   329  // SubscribeChainAcceptedEvent registers a subscription of ChainEvent.
   330  func (bc *BlockChain) SubscribeChainAcceptedEvent(ch chan<- ChainEvent) event.Subscription {
   331  	return bc.scope.Track(bc.chainAcceptedFeed.Subscribe(ch))
   332  }
   333  
   334  // SubscribeAcceptedLogsEvent registers a subscription of accepted []*types.Log.
   335  func (bc *BlockChain) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription {
   336  	return bc.scope.Track(bc.logsAcceptedFeed.Subscribe(ch))
   337  }
   338  
   339  // SubscribeAcceptedTransactionEvent registers a subscription of accepted transactions
   340  func (bc *BlockChain) SubscribeAcceptedTransactionEvent(ch chan<- NewTxsEvent) event.Subscription {
   341  	return bc.scope.Track(bc.txAcceptedFeed.Subscribe(ch))
   342  }
   343  
   344  // GetFeeConfigAt returns the fee configuration and the last changed block number at [parent].
   345  // If FeeConfigManager is activated at [parent], returns the fee config in the precompile contract state.
   346  // Otherwise returns the fee config in the chain config.
   347  // Assumes that a valid configuration is stored when the precompile is activated.
   348  func (bc *BlockChain) GetFeeConfigAt(parent *types.Header) (commontype.FeeConfig, *big.Int, error) {
   349  	config := bc.Config()
   350  	bigTime := new(big.Int).SetUint64(parent.Time)
   351  	if !config.IsFeeConfigManager(bigTime) {
   352  		return config.FeeConfig, common.Big0, nil
   353  	}
   354  
   355  	// try to return it from the cache
   356  	if cached, hit := bc.feeConfigCache.Get(parent.Root); hit {
   357  		cachedFeeConfig, ok := cached.(*cacheableFeeConfig)
   358  		if !ok {
   359  			return commontype.EmptyFeeConfig, nil, fmt.Errorf("expected type cacheableFeeConfig, got %T", cached)
   360  		}
   361  		return cachedFeeConfig.feeConfig, cachedFeeConfig.lastChangedAt, nil
   362  	}
   363  
   364  	stateDB, err := bc.StateAt(parent.Root)
   365  	if err != nil {
   366  		return commontype.EmptyFeeConfig, nil, err
   367  	}
   368  
   369  	storedFeeConfig := precompile.GetStoredFeeConfig(stateDB)
   370  	// this should not return an invalid fee config since it's assumed that
   371  	// StoreFeeConfig returns an error when an invalid fee config is attempted to be stored.
   372  	// However an external stateDB call can modify the contract state.
   373  	// This check is added to add a defense in-depth.
   374  	if err := storedFeeConfig.Verify(); err != nil {
   375  		return commontype.EmptyFeeConfig, nil, err
   376  	}
   377  	lastChangedAt := precompile.GetFeeConfigLastChangedAt(stateDB)
   378  	cacheable := &cacheableFeeConfig{feeConfig: storedFeeConfig, lastChangedAt: lastChangedAt}
   379  	// add it to the cache
   380  	bc.feeConfigCache.Add(parent.Root, cacheable)
   381  	return storedFeeConfig, lastChangedAt, nil
   382  }
   383  
   384  // GetCoinbaseAt returns the configured coinbase address at [parent].
   385  // If RewardManager is activated at [parent], returns the reward manager config in the precompile contract state.
   386  // If fee recipients are allowed, returns true in the second return value.
   387  func (bc *BlockChain) GetCoinbaseAt(parent *types.Header) (common.Address, bool, error) {
   388  	config := bc.Config()
   389  	bigTime := new(big.Int).SetUint64(parent.Time)
   390  
   391  	if !config.IsSubnetEVM(bigTime) {
   392  		return constants.BlackholeAddr, false, nil
   393  	}
   394  
   395  	if !config.IsRewardManager(bigTime) {
   396  		if bc.chainConfig.AllowFeeRecipients {
   397  			return common.Address{}, true, nil
   398  		} else {
   399  			return constants.BlackholeAddr, false, nil
   400  		}
   401  	}
   402  
   403  	// try to return it from the cache
   404  	if cached, hit := bc.coinbaseConfigCache.Get(parent.Root); hit {
   405  		cachedCoinbaseConfig, ok := cached.(*cacheableCoinbaseConfig)
   406  		if !ok {
   407  			return common.Address{}, false, fmt.Errorf("expected type cachedCoinbaseConfig, got %T", cached)
   408  		}
   409  		return cachedCoinbaseConfig.coinbaseAddress, cachedCoinbaseConfig.allowFeeRecipients, nil
   410  	}
   411  
   412  	stateDB, err := bc.StateAt(parent.Root)
   413  	if err != nil {
   414  		return common.Address{}, false, err
   415  	}
   416  	rewardAddress, feeRecipients := precompile.GetStoredRewardAddress(stateDB)
   417  
   418  	cacheable := &cacheableCoinbaseConfig{coinbaseAddress: rewardAddress, allowFeeRecipients: feeRecipients}
   419  	bc.coinbaseConfigCache.Add(parent.Root, cacheable)
   420  	return rewardAddress, feeRecipients, nil
   421  }
   422  
   423  // GetLogs fetches all logs from a given block.
   424  func (bc *BlockChain) GetLogs(hash common.Hash, number uint64) [][]*types.Log {
   425  	logs, ok := bc.acceptedLogsCache.Get(hash) // this cache is thread-safe
   426  	if ok {
   427  		return logs
   428  	}
   429  	return rawdb.ReadLogs(bc.db, hash, number)
   430  }