github.com/dim4egster/coreth@v0.10.2/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  	"github.com/dim4egster/coreth/consensus"
    31  	"github.com/dim4egster/coreth/core/rawdb"
    32  	"github.com/dim4egster/coreth/core/state"
    33  	"github.com/dim4egster/coreth/core/state/snapshot"
    34  	"github.com/dim4egster/coreth/core/types"
    35  	"github.com/dim4egster/coreth/core/vm"
    36  	"github.com/dim4egster/coreth/params"
    37  	"github.com/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/event"
    39  )
    40  
    41  // CurrentHeader retrieves the current head header of the canonical chain. The
    42  // header is retrieved from the HeaderChain's internal cache.
    43  func (bc *BlockChain) CurrentHeader() *types.Header {
    44  	return bc.hc.CurrentHeader()
    45  }
    46  
    47  // CurrentBlock retrieves the current head block of the canonical chain. The
    48  // block is retrieved from the blockchain's internal cache.
    49  func (bc *BlockChain) CurrentBlock() *types.Block {
    50  	return bc.currentBlock.Load().(*types.Block)
    51  }
    52  
    53  // HasHeader checks if a block header is present in the database or not, caching
    54  // it if present.
    55  func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
    56  	return bc.hc.HasHeader(hash, number)
    57  }
    58  
    59  // GetHeader retrieves a block header from the database by hash and number,
    60  // caching it if found.
    61  func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header {
    62  	return bc.hc.GetHeader(hash, number)
    63  }
    64  
    65  // GetHeaderByHash retrieves a block header from the database by hash, caching it if
    66  // found.
    67  func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header {
    68  	return bc.hc.GetHeaderByHash(hash)
    69  }
    70  
    71  // GetHeaderByNumber retrieves a block header from the database by number,
    72  // caching it (associated with its hash) if found.
    73  func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
    74  	return bc.hc.GetHeaderByNumber(number)
    75  }
    76  
    77  // GetBody retrieves a block body (transactions and uncles) from the database by
    78  // hash, caching it if found.
    79  func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
    80  	// Short circuit if the body's already in the cache, retrieve otherwise
    81  	if cached, ok := bc.bodyCache.Get(hash); ok {
    82  		body := cached.(*types.Body)
    83  		return body
    84  	}
    85  	number := bc.hc.GetBlockNumber(hash)
    86  	if number == nil {
    87  		return nil
    88  	}
    89  	body := rawdb.ReadBody(bc.db, hash, *number)
    90  	if body == nil {
    91  		return nil
    92  	}
    93  	// Cache the found body for next time and return
    94  	bc.bodyCache.Add(hash, body)
    95  	return body
    96  }
    97  
    98  // HasBlock checks if a block is fully present in the database or not.
    99  func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
   100  	if bc.blockCache.Contains(hash) {
   101  		return true
   102  	}
   103  	if !bc.HasHeader(hash, number) {
   104  		return false
   105  	}
   106  	return rawdb.HasBody(bc.db, hash, number)
   107  }
   108  
   109  // HasFastBlock checks if a fast block is fully present in the database or not.
   110  func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool {
   111  	if !bc.HasBlock(hash, number) {
   112  		return false
   113  	}
   114  	if bc.receiptsCache.Contains(hash) {
   115  		return true
   116  	}
   117  	return rawdb.HasReceipts(bc.db, hash, number)
   118  }
   119  
   120  // GetBlock retrieves a block from the database by hash and number,
   121  // caching it if found.
   122  func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
   123  	// Short circuit if the block's already in the cache, retrieve otherwise
   124  	if block, ok := bc.blockCache.Get(hash); ok {
   125  		return block.(*types.Block)
   126  	}
   127  	block := rawdb.ReadBlock(bc.db, hash, number)
   128  	if block == nil {
   129  		return nil
   130  	}
   131  	// Cache the found block for next time and return
   132  	bc.blockCache.Add(block.Hash(), block)
   133  	return block
   134  }
   135  
   136  // GetBlockByHash retrieves a block from the database by hash, caching it if found.
   137  func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
   138  	number := bc.hc.GetBlockNumber(hash)
   139  	if number == nil {
   140  		return nil
   141  	}
   142  	return bc.GetBlock(hash, *number)
   143  }
   144  
   145  // GetBlockByNumber retrieves a block from the database by number, caching it
   146  // (associated with its hash) if found.
   147  func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block {
   148  	hash := rawdb.ReadCanonicalHash(bc.db, number)
   149  	if hash == (common.Hash{}) {
   150  		return nil
   151  	}
   152  	return bc.GetBlock(hash, number)
   153  }
   154  
   155  // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
   156  // [deprecated by eth/62]
   157  func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
   158  	number := bc.hc.GetBlockNumber(hash)
   159  	if number == nil {
   160  		return nil
   161  	}
   162  	for i := 0; i < n; i++ {
   163  		block := bc.GetBlock(hash, *number)
   164  		if block == nil {
   165  			break
   166  		}
   167  		blocks = append(blocks, block)
   168  		hash = block.ParentHash()
   169  		*number--
   170  	}
   171  	return
   172  }
   173  
   174  // GetReceiptsByHash retrieves the receipts for all transactions in a given block.
   175  func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
   176  	if receipts, ok := bc.receiptsCache.Get(hash); ok {
   177  		return receipts.(types.Receipts)
   178  	}
   179  	number := rawdb.ReadHeaderNumber(bc.db, hash)
   180  	if number == nil {
   181  		return nil
   182  	}
   183  	receipts := rawdb.ReadReceipts(bc.db, hash, *number, bc.chainConfig)
   184  	if receipts == nil {
   185  		return nil
   186  	}
   187  	bc.receiptsCache.Add(hash, receipts)
   188  	return receipts
   189  }
   190  
   191  // GetCanonicalHash returns the canonical hash for a given block number
   192  func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash {
   193  	return bc.hc.GetCanonicalHash(number)
   194  }
   195  
   196  // GetTransactionLookup retrieves the lookup associate with the given transaction
   197  // hash from the cache or database.
   198  func (bc *BlockChain) GetTransactionLookup(hash common.Hash) *rawdb.LegacyTxLookupEntry {
   199  	// Short circuit if the txlookup already in the cache, retrieve otherwise
   200  	if lookup, exist := bc.txLookupCache.Get(hash); exist {
   201  		return lookup.(*rawdb.LegacyTxLookupEntry)
   202  	}
   203  	tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash)
   204  	if tx == nil {
   205  		return nil
   206  	}
   207  	lookup := &rawdb.LegacyTxLookupEntry{BlockHash: blockHash, BlockIndex: blockNumber, Index: txIndex}
   208  	bc.txLookupCache.Add(hash, lookup)
   209  	return lookup
   210  }
   211  
   212  // HasState checks if state trie is fully present in the database or not.
   213  func (bc *BlockChain) HasState(hash common.Hash) bool {
   214  	_, err := bc.stateCache.OpenTrie(hash)
   215  	return err == nil
   216  }
   217  
   218  // HasBlockAndState checks if a block and associated state trie is fully present
   219  // in the database or not, caching it if present.
   220  func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
   221  	// Check first that the block itself is known
   222  	block := bc.GetBlock(hash, number)
   223  	if block == nil {
   224  		return false
   225  	}
   226  	return bc.HasState(block.Root())
   227  }
   228  
   229  // TrieNode retrieves a blob of data associated with a trie node
   230  // either from ephemeral in-memory cache, or from persistent storage.
   231  func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
   232  	return bc.stateCache.TrieDB().RawNode(hash)
   233  }
   234  
   235  // ContractCode retrieves a blob of data associated with a contract hash
   236  // either from ephemeral in-memory cache, or from persistent storage.
   237  func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) {
   238  	return bc.stateCache.ContractCode(common.Hash{}, hash)
   239  }
   240  
   241  // State returns a new mutable state based on the current HEAD block.
   242  func (bc *BlockChain) State() (*state.StateDB, error) {
   243  	return bc.StateAt(bc.CurrentBlock().Root())
   244  }
   245  
   246  // StateAt returns a new mutable state based on a particular point in time.
   247  func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
   248  	return state.New(root, bc.stateCache, bc.snaps)
   249  }
   250  
   251  // Config retrieves the chain's fork configuration.
   252  func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }
   253  
   254  // Engine retrieves the blockchain's consensus engine.
   255  func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }
   256  
   257  // Snapshots returns the blockchain snapshot tree.
   258  func (bc *BlockChain) Snapshots() *snapshot.Tree {
   259  	return bc.snaps
   260  }
   261  
   262  // Validator returns the current validator.
   263  func (bc *BlockChain) Validator() Validator {
   264  	return bc.validator
   265  }
   266  
   267  // Processor returns the current processor.
   268  func (bc *BlockChain) Processor() Processor {
   269  	return bc.processor
   270  }
   271  
   272  // StateCache returns the caching database underpinning the blockchain instance.
   273  func (bc *BlockChain) StateCache() state.Database {
   274  	return bc.stateCache
   275  }
   276  
   277  // GasLimit returns the gas limit of the current HEAD block.
   278  func (bc *BlockChain) GasLimit() uint64 {
   279  	return bc.CurrentBlock().GasLimit()
   280  }
   281  
   282  // Genesis retrieves the chain's genesis block.
   283  func (bc *BlockChain) Genesis() *types.Block {
   284  	return bc.genesisBlock
   285  }
   286  
   287  // GetVMConfig returns the block chain VM config.
   288  func (bc *BlockChain) GetVMConfig() *vm.Config {
   289  	return &bc.vmConfig
   290  }
   291  
   292  // SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent.
   293  func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription {
   294  	return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch))
   295  }
   296  
   297  // SubscribeChainEvent registers a subscription of ChainEvent.
   298  func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription {
   299  	return bc.scope.Track(bc.chainFeed.Subscribe(ch))
   300  }
   301  
   302  // SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.
   303  func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription {
   304  	return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
   305  }
   306  
   307  // SubscribeChainSideEvent registers a subscription of ChainSideEvent.
   308  func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
   309  	return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
   310  }
   311  
   312  // SubscribeLogsEvent registers a subscription of []*types.Log.
   313  func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   314  	return bc.scope.Track(bc.logsFeed.Subscribe(ch))
   315  }
   316  
   317  // SubscribeBlockProcessingEvent registers a subscription of bool where true means
   318  // block processing has started while false means it has stopped.
   319  func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription {
   320  	return bc.scope.Track(bc.blockProcFeed.Subscribe(ch))
   321  }
   322  
   323  // SubscribeChainAcceptedEvent registers a subscription of ChainEvent.
   324  func (bc *BlockChain) SubscribeChainAcceptedEvent(ch chan<- ChainEvent) event.Subscription {
   325  	return bc.scope.Track(bc.chainAcceptedFeed.Subscribe(ch))
   326  }
   327  
   328  // SubscribeAcceptedLogsEvent registers a subscription of accepted []*types.Log.
   329  func (bc *BlockChain) SubscribeAcceptedLogsEvent(ch chan<- []*types.Log) event.Subscription {
   330  	return bc.scope.Track(bc.logsAcceptedFeed.Subscribe(ch))
   331  }
   332  
   333  // SubscribeAcceptedTransactionEvent registers a subscription of accepted transactions
   334  func (bc *BlockChain) SubscribeAcceptedTransactionEvent(ch chan<- NewTxsEvent) event.Subscription {
   335  	return bc.scope.Track(bc.txAcceptedFeed.Subscribe(ch))
   336  }