github.com/MetalBlockchain/subnet-evm@v0.4.9/core/headerchain.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 core
    28  
    29  import (
    30  	crand "crypto/rand"
    31  	"math"
    32  	"math/big"
    33  	mrand "math/rand"
    34  	"sync/atomic"
    35  
    36  	"github.com/MetalBlockchain/subnet-evm/consensus"
    37  	"github.com/MetalBlockchain/subnet-evm/core/rawdb"
    38  	"github.com/MetalBlockchain/subnet-evm/core/types"
    39  	"github.com/MetalBlockchain/subnet-evm/ethdb"
    40  	"github.com/MetalBlockchain/subnet-evm/params"
    41  	"github.com/ethereum/go-ethereum/common"
    42  	lru "github.com/hashicorp/golang-lru"
    43  )
    44  
    45  const (
    46  	headerCacheLimit = 512
    47  	tdCacheLimit     = 1024
    48  	numberCacheLimit = 2048
    49  )
    50  
    51  // HeaderChain implements the basic block header chain logic that is shared by
    52  // core.BlockChain and light.LightChain. It is not usable in itself, only as
    53  // a part of either structure.
    54  //
    55  // HeaderChain is responsible for maintaining the header chain including the
    56  // header query and updating.
    57  //
    58  // The components maintained by headerchain includes:
    59  // (1) header (2) block hash -> number mapping (3) canonical number -> hash mapping
    60  // and (4) head header flag.
    61  //
    62  // It is not thread safe either, the encapsulating chain structures should do
    63  // the necessary mutex locking/unlocking.
    64  type HeaderChain struct {
    65  	config *params.ChainConfig
    66  
    67  	chainDb       ethdb.Database
    68  	genesisHeader *types.Header
    69  
    70  	currentHeader     atomic.Value // Current head of the header chain (may be above the block chain!)
    71  	currentHeaderHash common.Hash  // Hash of the current head of the header chain (prevent recomputing all the time)
    72  
    73  	headerCache         *lru.Cache                       // Cache for the most recent block headers
    74  	tdCache             *lru.Cache                       // Cache for the most recent block total difficulties
    75  	numberCache         *lru.Cache                       // Cache for the most recent block numbers
    76  	acceptedNumberCache FIFOCache[uint64, *types.Header] // Cache for most recent accepted heights to headers (only modified in accept)
    77  
    78  	rand   *mrand.Rand
    79  	engine consensus.Engine
    80  }
    81  
    82  // NewHeaderChain creates a new HeaderChain structure. ProcInterrupt points
    83  // to the parent's interrupt semaphore.
    84  func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, cacheConfig *CacheConfig, engine consensus.Engine) (*HeaderChain, error) {
    85  	headerCache, _ := lru.New(headerCacheLimit)
    86  	tdCache, _ := lru.New(tdCacheLimit)
    87  	numberCache, _ := lru.New(numberCacheLimit)
    88  	acceptedNumberCache := NewFIFOCache[uint64, *types.Header](cacheConfig.AcceptedCacheSize)
    89  
    90  	// Seed a fast but crypto originating random generator
    91  	seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	hc := &HeaderChain{
    97  		config:              config,
    98  		chainDb:             chainDb,
    99  		headerCache:         headerCache,
   100  		tdCache:             tdCache,
   101  		numberCache:         numberCache,
   102  		acceptedNumberCache: acceptedNumberCache,
   103  		rand:                mrand.New(mrand.NewSource(seed.Int64())),
   104  		engine:              engine,
   105  	}
   106  
   107  	hc.genesisHeader = hc.GetHeaderByNumber(0)
   108  	if hc.genesisHeader == nil {
   109  		return nil, ErrNoGenesis
   110  	}
   111  
   112  	hc.currentHeader.Store(hc.genesisHeader)
   113  	if head := rawdb.ReadHeadBlockHash(chainDb); head != (common.Hash{}) {
   114  		if chead := hc.GetHeaderByHash(head); chead != nil {
   115  			hc.currentHeader.Store(chead)
   116  		}
   117  	}
   118  	hc.currentHeaderHash = hc.CurrentHeader().Hash()
   119  
   120  	return hc, nil
   121  }
   122  
   123  // GetBlockNumber retrieves the block number belonging to the given hash
   124  // from the cache or database
   125  func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
   126  	if cached, ok := hc.numberCache.Get(hash); ok {
   127  		number := cached.(uint64)
   128  		return &number
   129  	}
   130  	number := rawdb.ReadHeaderNumber(hc.chainDb, hash)
   131  	if number != nil {
   132  		hc.numberCache.Add(hash, *number)
   133  	}
   134  	return number
   135  }
   136  
   137  // GetHeader retrieves a block header from the database by hash and number,
   138  // caching it if found.
   139  func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header {
   140  	// Short circuit if the header's already in the cache, retrieve otherwise
   141  	if header, ok := hc.headerCache.Get(hash); ok {
   142  		return header.(*types.Header)
   143  	}
   144  	header := rawdb.ReadHeader(hc.chainDb, hash, number)
   145  	if header == nil {
   146  		return nil
   147  	}
   148  	// Cache the found header for next time and return
   149  	hc.headerCache.Add(hash, header)
   150  	return header
   151  }
   152  
   153  // GetHeaderByHash retrieves a block header from the database by hash, caching it if
   154  // found.
   155  func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header {
   156  	number := hc.GetBlockNumber(hash)
   157  	if number == nil {
   158  		return nil
   159  	}
   160  	return hc.GetHeader(hash, *number)
   161  }
   162  
   163  // HasHeader checks if a block header is present in the database or not.
   164  // In theory, if header is present in the database, all relative components
   165  // like td and hash->number should be present too.
   166  func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool {
   167  	if hc.numberCache.Contains(hash) || hc.headerCache.Contains(hash) {
   168  		return true
   169  	}
   170  	return rawdb.HasHeader(hc.chainDb, hash, number)
   171  }
   172  
   173  // GetHeaderByNumber retrieves a block header from the database by number,
   174  // caching it (associated with its hash) if found.
   175  func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
   176  	if cachedHeader, ok := hc.acceptedNumberCache.Get(number); ok {
   177  		return cachedHeader
   178  	}
   179  	hash := rawdb.ReadCanonicalHash(hc.chainDb, number)
   180  	if hash == (common.Hash{}) {
   181  		return nil
   182  	}
   183  	return hc.GetHeader(hash, number)
   184  }
   185  
   186  func (hc *HeaderChain) GetCanonicalHash(number uint64) common.Hash {
   187  	return rawdb.ReadCanonicalHash(hc.chainDb, number)
   188  }
   189  
   190  // CurrentHeader retrieves the current head header of the canonical chain. The
   191  // header is retrieved from the HeaderChain's internal cache.
   192  func (hc *HeaderChain) CurrentHeader() *types.Header {
   193  	return hc.currentHeader.Load().(*types.Header)
   194  }
   195  
   196  // SetCurrentHeader sets the in-memory head header marker of the canonical chan
   197  // as the given header.
   198  func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
   199  	hc.currentHeader.Store(head)
   200  	hc.currentHeaderHash = head.Hash()
   201  }
   202  
   203  // SetGenesis sets a new genesis block header for the chain
   204  func (hc *HeaderChain) SetGenesis(head *types.Header) {
   205  	hc.genesisHeader = head
   206  }
   207  
   208  // Config retrieves the header chain's chain configuration.
   209  func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config }
   210  
   211  // Engine retrieves the header chain's consensus engine.
   212  func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine }
   213  
   214  // GetBlock implements consensus.ChainReader, and returns nil for every input as
   215  // a header chain does not have blocks available for retrieval.
   216  func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block {
   217  	return nil
   218  }