github.com/decred/dcrd/blockchain@v1.2.1/blockindex.go (about)

     1  // Copyright (c) 2013-2017 The btcsuite developers
     2  // Copyright (c) 2018 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package blockchain
     7  
     8  import (
     9  	"bytes"
    10  	"math/big"
    11  	"sort"
    12  	"sync"
    13  	"time"
    14  
    15  	"github.com/decred/dcrd/blockchain/stake"
    16  	"github.com/decred/dcrd/blockchain/standalone"
    17  	"github.com/decred/dcrd/chaincfg/chainhash"
    18  	"github.com/decred/dcrd/database"
    19  	"github.com/decred/dcrd/wire"
    20  )
    21  
    22  // blockStatus is a bit field representing the validation state of the block.
    23  type blockStatus byte
    24  
    25  // The following constants specify possible status bit flags for a block.
    26  //
    27  // NOTE: This section specifically does not use iota since the block status is
    28  // serialized and must be stable for long-term storage.
    29  const (
    30  	// statusNone indicates that the block has no validation state flags set.
    31  	statusNone blockStatus = 0
    32  
    33  	// statusDataStored indicates that the block's payload is stored on disk.
    34  	statusDataStored blockStatus = 1 << 0
    35  
    36  	// statusValid indicates that the block has been fully validated.  It also
    37  	// means that all of its ancestors have also been validated.
    38  	statusValid blockStatus = 1 << 1
    39  
    40  	// statusValidateFailed indicates that the block has failed validation.
    41  	statusValidateFailed blockStatus = 1 << 2
    42  
    43  	// statusInvalidAncestor indicates that one of the ancestors of the block
    44  	// has failed validation, thus the block is also invalid.
    45  	statusInvalidAncestor blockStatus = 1 << 3
    46  )
    47  
    48  // HaveData returns whether the full block data is stored in the database.  This
    49  // will return false for a block node where only the header is downloaded or
    50  // stored.
    51  func (status blockStatus) HaveData() bool {
    52  	return status&statusDataStored != 0
    53  }
    54  
    55  // KnownValid returns whether the block is known to be valid.  This will return
    56  // false for a valid block that has not been fully validated yet.
    57  func (status blockStatus) KnownValid() bool {
    58  	return status&statusValid != 0
    59  }
    60  
    61  // KnownInvalid returns whether the block is known to be invalid.  This will
    62  // return false for invalid blocks that have not been proven invalid yet.
    63  func (status blockStatus) KnownInvalid() bool {
    64  	return status&(statusValidateFailed|statusInvalidAncestor) != 0
    65  }
    66  
    67  // blockNode represents a block within the block chain and is primarily used to
    68  // aid in selecting the best chain to be the main chain.  The main chain is
    69  // stored into the block database.
    70  type blockNode struct {
    71  	// NOTE: Additions, deletions, or modifications to the order of the
    72  	// definitions in this struct should not be changed without considering
    73  	// how it affects alignment on 64-bit platforms.  The current order is
    74  	// specifically crafted to result in minimal padding.  There will be
    75  	// hundreds of thousands of these in memory, so a few extra bytes of
    76  	// padding adds up.
    77  
    78  	// parent is the parent block for this node.
    79  	parent *blockNode
    80  
    81  	// hash is the hash of the block this node represents.
    82  	hash chainhash.Hash
    83  
    84  	// workSum is the total amount of work in the chain up to and including
    85  	// this node.
    86  	workSum *big.Int
    87  
    88  	// Some fields from block headers to aid in best chain selection and
    89  	// reconstructing headers from memory.  These must be treated as
    90  	// immutable and are intentionally ordered to avoid padding on 64-bit
    91  	// platforms.
    92  	height       int64
    93  	voteBits     uint16
    94  	finalState   [6]byte
    95  	blockVersion int32
    96  	voters       uint16
    97  	freshStake   uint8
    98  	revocations  uint8
    99  	poolSize     uint32
   100  	bits         uint32
   101  	sbits        int64
   102  	timestamp    int64
   103  	merkleRoot   chainhash.Hash
   104  	stakeRoot    chainhash.Hash
   105  	blockSize    uint32
   106  	nonce        uint32
   107  	extraData    [32]byte
   108  	stakeVersion uint32
   109  
   110  	// status is a bitfield representing the validation state of the block.
   111  	// This field, unlike the other fields, may be changed after the block
   112  	// node is created, so it must only be accessed or updated using the
   113  	// concurrent-safe NodeStatus, SetStatusFlags, and UnsetStatusFlags
   114  	// methods on blockIndex once the node has been added to the index.
   115  	status blockStatus
   116  
   117  	// stakeNode contains all the consensus information required for the
   118  	// staking system.  The node also caches information required to add or
   119  	// remove stake nodes, so that the stake node itself may be pruneable
   120  	// to save memory while maintaining high throughput efficiency for the
   121  	// evaluation of sidechains.
   122  	stakeNode      *stake.Node
   123  	newTickets     []chainhash.Hash
   124  	ticketsVoted   []chainhash.Hash
   125  	ticketsRevoked []chainhash.Hash
   126  
   127  	// Keep track of all vote version and bits in this block.
   128  	votes []stake.VoteVersionTuple
   129  }
   130  
   131  // initBlockNode initializes a block node from the given header, initialization
   132  // vector for the ticket lottery, and parent node.  The workSum is calculated
   133  // based on the parent, or, in the case no parent is provided, it will just be
   134  // the work for the passed block.
   135  //
   136  // This function is NOT safe for concurrent access.  It must only be called when
   137  // initially creating a node.
   138  func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *blockNode) {
   139  	*node = blockNode{
   140  		hash:         blockHeader.BlockHash(),
   141  		workSum:      standalone.CalcWork(blockHeader.Bits),
   142  		height:       int64(blockHeader.Height),
   143  		blockVersion: blockHeader.Version,
   144  		voteBits:     blockHeader.VoteBits,
   145  		finalState:   blockHeader.FinalState,
   146  		voters:       blockHeader.Voters,
   147  		freshStake:   blockHeader.FreshStake,
   148  		poolSize:     blockHeader.PoolSize,
   149  		bits:         blockHeader.Bits,
   150  		sbits:        blockHeader.SBits,
   151  		timestamp:    blockHeader.Timestamp.Unix(),
   152  		merkleRoot:   blockHeader.MerkleRoot,
   153  		stakeRoot:    blockHeader.StakeRoot,
   154  		revocations:  blockHeader.Revocations,
   155  		blockSize:    blockHeader.Size,
   156  		nonce:        blockHeader.Nonce,
   157  		extraData:    blockHeader.ExtraData,
   158  		stakeVersion: blockHeader.StakeVersion,
   159  	}
   160  	if parent != nil {
   161  		node.parent = parent
   162  		node.workSum = node.workSum.Add(parent.workSum, node.workSum)
   163  	}
   164  }
   165  
   166  // newBlockNode returns a new block node for the given block header and parent
   167  // node.  The workSum is calculated based on the parent, or, in the case no
   168  // parent is provided, it will just be the work for the passed block.
   169  func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode {
   170  	var node blockNode
   171  	initBlockNode(&node, blockHeader, parent)
   172  	return &node
   173  }
   174  
   175  // Header constructs a block header from the node and returns it.
   176  //
   177  // This function is safe for concurrent access.
   178  func (node *blockNode) Header() wire.BlockHeader {
   179  	// No lock is needed because all accessed fields are immutable.
   180  	prevHash := zeroHash
   181  	if node.parent != nil {
   182  		prevHash = &node.parent.hash
   183  	}
   184  	return wire.BlockHeader{
   185  		Version:      node.blockVersion,
   186  		PrevBlock:    *prevHash,
   187  		MerkleRoot:   node.merkleRoot,
   188  		StakeRoot:    node.stakeRoot,
   189  		VoteBits:     node.voteBits,
   190  		FinalState:   node.finalState,
   191  		Voters:       node.voters,
   192  		FreshStake:   node.freshStake,
   193  		Revocations:  node.revocations,
   194  		PoolSize:     node.poolSize,
   195  		Bits:         node.bits,
   196  		SBits:        node.sbits,
   197  		Height:       uint32(node.height),
   198  		Size:         node.blockSize,
   199  		Timestamp:    time.Unix(node.timestamp, 0),
   200  		Nonce:        node.nonce,
   201  		ExtraData:    node.extraData,
   202  		StakeVersion: node.stakeVersion,
   203  	}
   204  }
   205  
   206  // lotteryIV returns the initialization vector for the deterministic PRNG used
   207  // to determine winning tickets.
   208  //
   209  // This function is safe for concurrent access.
   210  func (node *blockNode) lotteryIV() chainhash.Hash {
   211  	// Serialize the block header for use in calculating the initialization
   212  	// vector for the ticket lottery.  The only way this can fail is if the
   213  	// process is out of memory in which case it would panic anyways, so
   214  	// although panics are generally frowned upon in package code, it is
   215  	// acceptable here.
   216  	buf := bytes.NewBuffer(make([]byte, 0, wire.MaxBlockHeaderPayload))
   217  	header := node.Header()
   218  	if err := header.Serialize(buf); err != nil {
   219  		panic(err)
   220  	}
   221  
   222  	return stake.CalcHash256PRNGIV(buf.Bytes())
   223  }
   224  
   225  // populateTicketInfo sets prunable ticket information in the provided block
   226  // node.
   227  //
   228  // This function is NOT safe for concurrent access.  It must only be called when
   229  // initially creating a node or when protected by the chain lock.
   230  func (node *blockNode) populateTicketInfo(spentTickets *stake.SpentTicketsInBlock) {
   231  	node.ticketsVoted = spentTickets.VotedTickets
   232  	node.ticketsRevoked = spentTickets.RevokedTickets
   233  	node.votes = spentTickets.Votes
   234  }
   235  
   236  // Ancestor returns the ancestor block node at the provided height by following
   237  // the chain backwards from this node.  The returned block will be nil when a
   238  // height is requested that is after the height of the passed node or is less
   239  // than zero.
   240  //
   241  // This function is safe for concurrent access.
   242  func (node *blockNode) Ancestor(height int64) *blockNode {
   243  	if height < 0 || height > node.height {
   244  		return nil
   245  	}
   246  
   247  	n := node
   248  	for ; n != nil && n.height != height; n = n.parent {
   249  		// Intentionally left blank
   250  	}
   251  
   252  	return n
   253  }
   254  
   255  // RelativeAncestor returns the ancestor block node a relative 'distance' blocks
   256  // before this node.  This is equivalent to calling Ancestor with the node's
   257  // height minus provided distance.
   258  //
   259  // This function is safe for concurrent access.
   260  func (node *blockNode) RelativeAncestor(distance int64) *blockNode {
   261  	return node.Ancestor(node.height - distance)
   262  }
   263  
   264  // CalcPastMedianTime calculates the median time of the previous few blocks
   265  // prior to, and including, the block node.
   266  //
   267  // This function is safe for concurrent access.
   268  func (node *blockNode) CalcPastMedianTime() time.Time {
   269  	// Create a slice of the previous few block timestamps used to calculate
   270  	// the median per the number defined by the constant medianTimeBlocks.
   271  	timestamps := make([]int64, medianTimeBlocks)
   272  	numNodes := 0
   273  	iterNode := node
   274  	for i := 0; i < medianTimeBlocks && iterNode != nil; i++ {
   275  		timestamps[i] = iterNode.timestamp
   276  		numNodes++
   277  
   278  		iterNode = iterNode.parent
   279  	}
   280  
   281  	// Prune the slice to the actual number of available timestamps which
   282  	// will be fewer than desired near the beginning of the block chain
   283  	// and sort them.
   284  	timestamps = timestamps[:numNodes]
   285  	sort.Sort(timeSorter(timestamps))
   286  
   287  	// NOTE: The consensus rules incorrectly calculate the median for even
   288  	// numbers of blocks.  A true median averages the middle two elements
   289  	// for a set with an even number of elements in it.   Since the constant
   290  	// for the previous number of blocks to be used is odd, this is only an
   291  	// issue for a few blocks near the beginning of the chain.  I suspect
   292  	// this is an optimization even though the result is slightly wrong for
   293  	// a few of the first blocks since after the first few blocks, there
   294  	// will always be an odd number of blocks in the set per the constant.
   295  	//
   296  	// This code follows suit to ensure the same rules are used, however, be
   297  	// aware that should the medianTimeBlocks constant ever be changed to an
   298  	// even number, this code will be wrong.
   299  	medianTimestamp := timestamps[numNodes/2]
   300  	return time.Unix(medianTimestamp, 0)
   301  }
   302  
   303  // blockIndex provides facilities for keeping track of an in-memory index of the
   304  // block chain.  Although the name block chain suggests a single chain of
   305  // blocks, it is actually a tree-shaped structure where any node can have
   306  // multiple children.  However, there can only be one active branch which does
   307  // indeed form a chain from the tip all the way back to the genesis block.
   308  type blockIndex struct {
   309  	// The following fields are set when the instance is created and can't
   310  	// be changed afterwards, so there is no need to protect them with a
   311  	// separate mutex.
   312  	db database.DB
   313  
   314  	// These following fields are protected by the embedded mutex.
   315  	//
   316  	// index contains an entry for every known block tracked by the block
   317  	// index.
   318  	//
   319  	// modified contains an entry for all nodes that have been modified
   320  	// since the last time the index was flushed to disk.
   321  	//
   322  	// chainTips contains an entry with the tip of all known side chains.
   323  	sync.RWMutex
   324  	index     map[chainhash.Hash]*blockNode
   325  	modified  map[*blockNode]struct{}
   326  	chainTips map[int64][]*blockNode
   327  }
   328  
   329  // newBlockIndex returns a new empty instance of a block index.  The index will
   330  // be dynamically populated as block nodes are loaded from the database and
   331  // manually added.
   332  func newBlockIndex(db database.DB) *blockIndex {
   333  	return &blockIndex{
   334  		db:        db,
   335  		index:     make(map[chainhash.Hash]*blockNode),
   336  		modified:  make(map[*blockNode]struct{}),
   337  		chainTips: make(map[int64][]*blockNode),
   338  	}
   339  }
   340  
   341  // HaveBlock returns whether or not the block index contains the provided hash
   342  // and the block data is available.
   343  //
   344  // This function is safe for concurrent access.
   345  func (bi *blockIndex) HaveBlock(hash *chainhash.Hash) bool {
   346  	bi.RLock()
   347  	node := bi.index[*hash]
   348  	hasBlock := node != nil && node.status.HaveData()
   349  	bi.RUnlock()
   350  	return hasBlock
   351  }
   352  
   353  // addNode adds the provided node to the block index.  Duplicate entries are not
   354  // checked so it is up to caller to avoid adding them.
   355  //
   356  // This function MUST be called with the block index lock held (for writes).
   357  func (bi *blockIndex) addNode(node *blockNode) {
   358  	bi.index[node.hash] = node
   359  
   360  	// Since the block index does not support nodes that do not connect to
   361  	// an existing node (except the genesis block), all new nodes are either
   362  	// extending an existing chain or are on a side chain, but in either
   363  	// case, are a new chain tip.  In the case the node is extending a
   364  	// chain, the parent is no longer a tip.
   365  	bi.addChainTip(node)
   366  	if node.parent != nil {
   367  		bi.removeChainTip(node.parent)
   368  	}
   369  }
   370  
   371  // AddNode adds the provided node to the block index and marks it as modified.
   372  // Duplicate entries are not checked so it is up to caller to avoid adding them.
   373  //
   374  // This function is safe for concurrent access.
   375  func (bi *blockIndex) AddNode(node *blockNode) {
   376  	bi.Lock()
   377  	bi.addNode(node)
   378  	bi.modified[node] = struct{}{}
   379  	bi.Unlock()
   380  }
   381  
   382  // addChainTip adds the passed block node as a new chain tip.
   383  //
   384  // This function MUST be called with the block index lock held (for writes).
   385  func (bi *blockIndex) addChainTip(tip *blockNode) {
   386  	bi.chainTips[tip.height] = append(bi.chainTips[tip.height], tip)
   387  }
   388  
   389  // removeChainTip removes the passed block node from the available chain tips.
   390  //
   391  // This function MUST be called with the block index lock held (for writes).
   392  func (bi *blockIndex) removeChainTip(tip *blockNode) {
   393  	nodes := bi.chainTips[tip.height]
   394  	for i, n := range nodes {
   395  		if n == tip {
   396  			copy(nodes[i:], nodes[i+1:])
   397  			nodes[len(nodes)-1] = nil
   398  			nodes = nodes[:len(nodes)-1]
   399  			break
   400  		}
   401  	}
   402  
   403  	// Either update the map entry for the height with the remaining nodes
   404  	// or remove it altogether if there are no more nodes left.
   405  	if len(nodes) == 0 {
   406  		delete(bi.chainTips, tip.height)
   407  	} else {
   408  		bi.chainTips[tip.height] = nodes
   409  	}
   410  }
   411  
   412  // lookupNode returns the block node identified by the provided hash.  It will
   413  // return nil if there is no entry for the hash.
   414  //
   415  // This function MUST be called with the block index lock held (for reads).
   416  func (bi *blockIndex) lookupNode(hash *chainhash.Hash) *blockNode {
   417  	return bi.index[*hash]
   418  }
   419  
   420  // LookupNode returns the block node identified by the provided hash.  It will
   421  // return nil if there is no entry for the hash.
   422  //
   423  // This function is safe for concurrent access.
   424  func (bi *blockIndex) LookupNode(hash *chainhash.Hash) *blockNode {
   425  	bi.RLock()
   426  	node := bi.lookupNode(hash)
   427  	bi.RUnlock()
   428  	return node
   429  }
   430  
   431  // NodeStatus returns the status associated with the provided node.
   432  //
   433  // This function is safe for concurrent access.
   434  func (bi *blockIndex) NodeStatus(node *blockNode) blockStatus {
   435  	bi.RLock()
   436  	status := node.status
   437  	bi.RUnlock()
   438  	return status
   439  }
   440  
   441  // SetStatusFlags sets the provided status flags for the given block node
   442  // regardless of their previous state.  It does not unset any flags.
   443  //
   444  // This function is safe for concurrent access.
   445  func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) {
   446  	bi.Lock()
   447  	origStatus := node.status
   448  	node.status |= flags
   449  	if node.status != origStatus {
   450  		bi.modified[node] = struct{}{}
   451  	}
   452  	bi.Unlock()
   453  }
   454  
   455  // UnsetStatusFlags unsets the provided status flags for the given block node
   456  // regardless of their previous state.
   457  //
   458  // This function is safe for concurrent access.
   459  func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) {
   460  	bi.Lock()
   461  	origStatus := node.status
   462  	node.status &^= flags
   463  	if node.status != origStatus {
   464  		bi.modified[node] = struct{}{}
   465  	}
   466  	bi.Unlock()
   467  }
   468  
   469  // flush writes all of the modified block nodes to the database and clears the
   470  // set of modified nodes if it succeeds.
   471  func (bi *blockIndex) flush() error {
   472  	// Nothing to flush if there are no modified nodes.
   473  	bi.Lock()
   474  	if len(bi.modified) == 0 {
   475  		bi.Unlock()
   476  		return nil
   477  	}
   478  
   479  	// Write all of the nodes in the set of modified nodes to the database.
   480  	err := bi.db.Update(func(dbTx database.Tx) error {
   481  		for node := range bi.modified {
   482  			err := dbPutBlockNode(dbTx, node)
   483  			if err != nil {
   484  				return err
   485  			}
   486  		}
   487  		return nil
   488  	})
   489  	if err != nil {
   490  		bi.Unlock()
   491  		return err
   492  	}
   493  
   494  	// Clear the set of modified nodes.
   495  	bi.modified = make(map[*blockNode]struct{})
   496  	bi.Unlock()
   497  	return nil
   498  }