github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/headerchain.go (about)

     1  package core
     2  
     3  import (
     4  	crand "crypto/rand"
     5  	"errors"
     6  	"fmt"
     7  	"math"
     8  	"math/big"
     9  	mrand "math/rand"
    10  	"sync/atomic"
    11  	"time"
    12  
    13  	"github.com/quickchainproject/quickchain/common"
    14  	"github.com/quickchainproject/quickchain/consensus"
    15  	"github.com/quickchainproject/quickchain/core/types"
    16  	"github.com/quickchainproject/quickchain/qctdb"
    17  	"github.com/quickchainproject/quickchain/log"
    18  	"github.com/quickchainproject/quickchain/params"
    19  	"github.com/hashicorp/golang-lru"
    20  )
    21  
    22  const (
    23  	headerCacheLimit = 512
    24  	tdCacheLimit     = 1024
    25  	numberCacheLimit = 2048
    26  )
    27  
    28  // HeaderChain implements the basic block header chain logic that is shared by
    29  // core.BlockChain and light.LightChain. It is not usable in itself, only as
    30  // a part of either structure.
    31  // It is not thread safe either, the encapsulating chain structures should do
    32  // the necessary mutex locking/unlocking.
    33  type HeaderChain struct {
    34  	config *params.ChainConfig
    35  
    36  	chainDb       qctdb.Database
    37  	genesisHeader *types.Header
    38  
    39  	currentHeader     atomic.Value // Current head of the header chain (may be above the block chain!)
    40  	currentHeaderHash common.Hash  // Hash of the current head of the header chain (prevent recomputing all the time)
    41  
    42  	headerCache *lru.Cache // Cache for the most recent block headers
    43  	tdCache     *lru.Cache // Cache for the most recent block total difficulties
    44  	numberCache *lru.Cache // Cache for the most recent block numbers
    45  
    46  	procInterrupt func() bool
    47  
    48  	rand   *mrand.Rand
    49  	engine consensus.Engine
    50  }
    51  
    52  // NewHeaderChain creates a new HeaderChain structure.
    53  //  getValidator should return the parent's validator
    54  //  procInterrupt points to the parent's interrupt semaphore
    55  //  wg points to the parent's shutdown wait group
    56  func NewHeaderChain(chainDb qctdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) {
    57  	headerCache, _ := lru.New(headerCacheLimit)
    58  	tdCache, _ := lru.New(tdCacheLimit)
    59  	numberCache, _ := lru.New(numberCacheLimit)
    60  
    61  	// Seed a fast but crypto originating random generator
    62  	seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	hc := &HeaderChain{
    68  		config:        config,
    69  		chainDb:       chainDb,
    70  		headerCache:   headerCache,
    71  		tdCache:       tdCache,
    72  		numberCache:   numberCache,
    73  		procInterrupt: procInterrupt,
    74  		rand:          mrand.New(mrand.NewSource(seed.Int64())),
    75  		engine:        engine,
    76  	}
    77  
    78  	hc.genesisHeader = hc.GetHeaderByNumber(0)
    79  	if hc.genesisHeader == nil {
    80  		return nil, ErrNoGenesis
    81  	}
    82  
    83  	hc.currentHeader.Store(hc.genesisHeader)
    84  	if head := GetHeadBlockHash(chainDb); head != (common.Hash{}) {
    85  		if chead := hc.GetHeaderByHash(head); chead != nil {
    86  			hc.currentHeader.Store(chead)
    87  		}
    88  	}
    89  	hc.currentHeaderHash = hc.CurrentHeader().Hash()
    90  
    91  	return hc, nil
    92  }
    93  
    94  // GetBlockNumber retrieves the block number belonging to the given hash
    95  // from the cache or database
    96  func (hc *HeaderChain) GetBlockNumber(hash common.Hash) uint64 {
    97  	if cached, ok := hc.numberCache.Get(hash); ok {
    98  		return cached.(uint64)
    99  	}
   100  	number := GetBlockNumber(hc.chainDb, hash)
   101  	if number != missingNumber {
   102  		hc.numberCache.Add(hash, number)
   103  	}
   104  	return number
   105  }
   106  
   107  // WriteHeader writes a header into the local chain, given that its parent is
   108  // already known. If the total difficulty of the newly inserted header becomes
   109  // greater than the current known TD, the canonical chain is re-routed.
   110  //
   111  // Note: This method is not concurrent-safe with inserting blocks simultaneously
   112  // into the chain, as side effects caused by reorganisations cannot be emulated
   113  // without the real blocks. Hence, writing headers directly should only be done
   114  // in two scenarios: pure-header mode of operation (light clients), or properly
   115  // separated header/block phases (non-archive clients).
   116  func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, err error) {
   117  	// Cache some values to prevent constant recalculation
   118  	var (
   119  		hash   = header.Hash()
   120  		number = header.Number.Uint64()
   121  	)
   122  	// Calculate the total difficulty of the header
   123  	ptd := hc.GetTd(header.ParentHash, number-1)
   124  	if ptd == nil {
   125  		return NonStatTy, consensus.ErrUnknownAncestor
   126  	}
   127  	localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64())
   128  	externTd := new(big.Int).Add(header.Difficulty, ptd)
   129  
   130  	// Irrelevant of the canonical status, write the td and header to the database
   131  	if err := hc.WriteTd(hash, number, externTd); err != nil {
   132  		log.Crit("Failed to write header total difficulty", "err", err)
   133  	}
   134  	if err := WriteHeader(hc.chainDb, header); err != nil {
   135  		log.Crit("Failed to write header content", "err", err)
   136  	}
   137  	// If the total difficulty is higher than our known, add it to the canonical chain
   138  	// Second clause in the if statement reduces the vulnerability to selfish mining.
   139  	// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
   140  	if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) {
   141  		// Delete any canonical number assignments above the new head
   142  		for i := number + 1; ; i++ {
   143  			hash := GetCanonicalHash(hc.chainDb, i)
   144  			if hash == (common.Hash{}) {
   145  				break
   146  			}
   147  			DeleteCanonicalHash(hc.chainDb, i)
   148  		}
   149  		// Overwrite any stale canonical number assignments
   150  		var (
   151  			headHash   = header.ParentHash
   152  			headNumber = header.Number.Uint64() - 1
   153  			headHeader = hc.GetHeader(headHash, headNumber)
   154  		)
   155  		for GetCanonicalHash(hc.chainDb, headNumber) != headHash {
   156  			WriteCanonicalHash(hc.chainDb, headHash, headNumber)
   157  
   158  			headHash = headHeader.ParentHash
   159  			headNumber = headHeader.Number.Uint64() - 1
   160  			headHeader = hc.GetHeader(headHash, headNumber)
   161  		}
   162  		// Extend the canonical chain with the new header
   163  		if err := WriteCanonicalHash(hc.chainDb, hash, number); err != nil {
   164  			log.Crit("Failed to insert header number", "err", err)
   165  		}
   166  		if err := WriteHeadHeaderHash(hc.chainDb, hash); err != nil {
   167  			log.Crit("Failed to insert head header hash", "err", err)
   168  		}
   169  		hc.currentHeaderHash = hash
   170  		hc.currentHeader.Store(types.CopyHeader(header))
   171  
   172  		status = CanonStatTy
   173  	} else {
   174  		status = SideStatTy
   175  	}
   176  
   177  	hc.headerCache.Add(hash, header)
   178  	hc.numberCache.Add(hash, number)
   179  
   180  	return
   181  }
   182  
   183  // WhCallback is a callback function for inserting individual headers.
   184  // A callback is used for two reasons: first, in a LightChain, status should be
   185  // processed and light chain events sent, while in a BlockChain this is not
   186  // necessary since chain events are sent after inserting blocks. Second, the
   187  // header writes should be protected by the parent chain mutex individually.
   188  type WhCallback func(*types.Header) error
   189  
   190  func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
   191  	// Do a sanity check that the provided chain is actually ordered and linked
   192  	for i := 1; i < len(chain); i++ {
   193  		if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() {
   194  			// Chain broke ancestry, log a messge (programming error) and skip insertion
   195  			log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", chain[i].Hash(),
   196  				"parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", chain[i-1].Hash())
   197  
   198  			return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, chain[i-1].Number,
   199  				chain[i-1].Hash().Bytes()[:4], i, chain[i].Number, chain[i].Hash().Bytes()[:4], chain[i].ParentHash[:4])
   200  		}
   201  	}
   202  
   203  	// Generate the list of seal verification requests, and start the parallel verifier
   204  	seals := make([]bool, len(chain))
   205  	for i := 0; i < len(seals)/checkFreq; i++ {
   206  		index := i*checkFreq + hc.rand.Intn(checkFreq)
   207  		if index >= len(seals) {
   208  			index = len(seals) - 1
   209  		}
   210  		seals[index] = true
   211  	}
   212  	seals[len(seals)-1] = true // Last should always be verified to avoid junk
   213  
   214  	abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
   215  	defer close(abort)
   216  
   217  	// Iterate over the headers and ensure they all check out
   218  	for i, header := range chain {
   219  		// If the chain is terminating, stop processing blocks
   220  		if hc.procInterrupt() {
   221  			log.Debug("Premature abort during headers verification")
   222  			return 0, errors.New("aborted")
   223  		}
   224  		// If the header is a banned one, straight out abort
   225  		if BadHashes[header.Hash()] {
   226  			return i, ErrBlacklistedHash
   227  		}
   228  		// Otherwise wait for headers checks and ensure they pass
   229  		if err := <-results; err != nil {
   230  			return i, err
   231  		}
   232  	}
   233  
   234  	return 0, nil
   235  }
   236  
   237  // InsertHeaderChain attempts to insert the given header chain in to the local
   238  // chain, possibly creating a reorg. If an error is returned, it will return the
   239  // index number of the failing header as well an error describing what went wrong.
   240  //
   241  // The verify parameter can be used to fine tune whether nonce verification
   242  // should be done or not. The reason behind the optional check is because some
   243  // of the header retrieval mechanisms already need to verfy nonces, as well as
   244  // because nonces can be verified sparsely, not needing to check each.
   245  func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCallback, start time.Time) (int, error) {
   246  	// Collect some import statistics to report on
   247  	stats := struct{ processed, ignored int }{}
   248  	// All headers passed verification, import them into the database
   249  	for i, header := range chain {
   250  		// Short circuit insertion if shutting down
   251  		if hc.procInterrupt() {
   252  			log.Debug("Premature abort during headers import")
   253  			return i, errors.New("aborted")
   254  		}
   255  		// If the header's already known, skip it, otherwise store
   256  		if hc.HasHeader(header.Hash(), header.Number.Uint64()) {
   257  			stats.ignored++
   258  			continue
   259  		}
   260  		if err := writeHeader(header); err != nil {
   261  			return i, err
   262  		}
   263  		stats.processed++
   264  	}
   265  	// Report some public statistics so the user has a clue what's going on
   266  	last := chain[len(chain)-1]
   267  	log.Info("Imported new block headers", "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
   268  		"number", last.Number, "hash", last.Hash(), "ignored", stats.ignored)
   269  
   270  	return 0, nil
   271  }
   272  
   273  // GetBlockHashesFromHash retrieves a number of block hashes starting at a given
   274  // hash, fetching towards the genesis block.
   275  func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
   276  	// Get the origin header from which to fetch
   277  	header := hc.GetHeaderByHash(hash)
   278  	if header == nil {
   279  		return nil
   280  	}
   281  	// Iterate the headers until enough is collected or the genesis reached
   282  	chain := make([]common.Hash, 0, max)
   283  	for i := uint64(0); i < max; i++ {
   284  		next := header.ParentHash
   285  		if header = hc.GetHeader(next, header.Number.Uint64()-1); header == nil {
   286  			break
   287  		}
   288  		chain = append(chain, next)
   289  		if header.Number.Sign() == 0 {
   290  			break
   291  		}
   292  	}
   293  	return chain
   294  }
   295  
   296  // GetTd retrieves a block's total difficulty in the canonical chain from the
   297  // database by hash and number, caching it if found.
   298  func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {
   299  	// Short circuit if the td's already in the cache, retrieve otherwise
   300  	if cached, ok := hc.tdCache.Get(hash); ok {
   301  		return cached.(*big.Int)
   302  	}
   303  	td := GetTd(hc.chainDb, hash, number)
   304  	if td == nil {
   305  		return nil
   306  	}
   307  	// Cache the found body for next time and return
   308  	hc.tdCache.Add(hash, td)
   309  	return td
   310  }
   311  
   312  // GetTdByHash retrieves a block's total difficulty in the canonical chain from the
   313  // database by hash, caching it if found.
   314  func (hc *HeaderChain) GetTdByHash(hash common.Hash) *big.Int {
   315  	return hc.GetTd(hash, hc.GetBlockNumber(hash))
   316  }
   317  
   318  // WriteTd stores a block's total difficulty into the database, also caching it
   319  // along the way.
   320  func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) error {
   321  	if err := WriteTd(hc.chainDb, hash, number, td); err != nil {
   322  		return err
   323  	}
   324  	hc.tdCache.Add(hash, new(big.Int).Set(td))
   325  	return nil
   326  }
   327  
   328  // GetHeader retrieves a block header from the database by hash and number,
   329  // caching it if found.
   330  func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header {
   331  	// Short circuit if the header's already in the cache, retrieve otherwise
   332  	if header, ok := hc.headerCache.Get(hash); ok {
   333  		return header.(*types.Header)
   334  	}
   335  	header := GetHeader(hc.chainDb, hash, number)
   336  	if header == nil {
   337  		return nil
   338  	}
   339  	// Cache the found header for next time and return
   340  	hc.headerCache.Add(hash, header)
   341  	return header
   342  }
   343  
   344  // GetHeaderByHash retrieves a block header from the database by hash, caching it if
   345  // found.
   346  func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header {
   347  	return hc.GetHeader(hash, hc.GetBlockNumber(hash))
   348  }
   349  
   350  // HasHeader checks if a block header is present in the database or not.
   351  func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool {
   352  	if hc.numberCache.Contains(hash) || hc.headerCache.Contains(hash) {
   353  		return true
   354  	}
   355  	ok, _ := hc.chainDb.Has(headerKey(hash, number))
   356  	return ok
   357  }
   358  
   359  // GetHeaderByNumber retrieves a block header from the database by number,
   360  // caching it (associated with its hash) if found.
   361  func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
   362  	hash := GetCanonicalHash(hc.chainDb, number)
   363  	if hash == (common.Hash{}) {
   364  		return nil
   365  	}
   366  	return hc.GetHeader(hash, number)
   367  }
   368  
   369  // CurrentHeader retrieves the current head header of the canonical chain. The
   370  // header is retrieved from the HeaderChain's internal cache.
   371  func (hc *HeaderChain) CurrentHeader() *types.Header {
   372  	return hc.currentHeader.Load().(*types.Header)
   373  }
   374  
   375  // SetCurrentHeader sets the current head header of the canonical chain.
   376  func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
   377  	if err := WriteHeadHeaderHash(hc.chainDb, head.Hash()); err != nil {
   378  		log.Crit("Failed to insert head header hash", "err", err)
   379  	}
   380  	hc.currentHeader.Store(head)
   381  	hc.currentHeaderHash = head.Hash()
   382  }
   383  
   384  // DeleteCallback is a callback function that is called by SetHead before
   385  // each header is deleted.
   386  type DeleteCallback func(common.Hash, uint64)
   387  
   388  // SetHead rewinds the local chain to a new head. Everything above the new head
   389  // will be deleted and the new one set.
   390  func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) {
   391  	height := uint64(0)
   392  
   393  	if hdr := hc.CurrentHeader(); hdr != nil {
   394  		height = hdr.Number.Uint64()
   395  	}
   396  
   397  	for hdr := hc.CurrentHeader(); hdr != nil && hdr.Number.Uint64() > head; hdr = hc.CurrentHeader() {
   398  		hash := hdr.Hash()
   399  		num := hdr.Number.Uint64()
   400  		if delFn != nil {
   401  			delFn(hash, num)
   402  		}
   403  		DeleteHeader(hc.chainDb, hash, num)
   404  		DeleteTd(hc.chainDb, hash, num)
   405  		hc.currentHeader.Store(hc.GetHeader(hdr.ParentHash, hdr.Number.Uint64()-1))
   406  	}
   407  	// Roll back the canonical chain numbering
   408  	for i := height; i > head; i-- {
   409  		DeleteCanonicalHash(hc.chainDb, i)
   410  	}
   411  	// Clear out any stale content from the caches
   412  	hc.headerCache.Purge()
   413  	hc.tdCache.Purge()
   414  	hc.numberCache.Purge()
   415  
   416  	if hc.CurrentHeader() == nil {
   417  		hc.currentHeader.Store(hc.genesisHeader)
   418  	}
   419  	hc.currentHeaderHash = hc.CurrentHeader().Hash()
   420  
   421  	if err := WriteHeadHeaderHash(hc.chainDb, hc.currentHeaderHash); err != nil {
   422  		log.Crit("Failed to reset head header hash", "err", err)
   423  	}
   424  }
   425  
   426  // SetGenesis sets a new genesis block header for the chain
   427  func (hc *HeaderChain) SetGenesis(head *types.Header) {
   428  	hc.genesisHeader = head
   429  }
   430  
   431  // Config retrieves the header chain's chain configuration.
   432  func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config }
   433  
   434  // Engine retrieves the header chain's consensus engine.
   435  func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine }
   436  
   437  // GetBlock implements consensus.ChainReader, and returns nil for every input as
   438  // a header chain does not have blocks available for retrieval.
   439  func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block {
   440  	return nil
   441  }