// Copyright (c) 2015-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package blockchain import ( "math/big" "sort" "sync" "time" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" ) // blockStatus is a bit field representing the validation state of the block. type blockStatus byte const ( // statusDataStored indicates that the block's payload is stored on disk. statusDataStored blockStatus = 1 << iota // statusValid indicates that the block has been fully validated. statusValid // statusValidateFailed indicates that the block has failed validation. statusValidateFailed // statusInvalidAncestor indicates that one of the block's ancestors has // has failed validation, thus the block is also invalid. statusInvalidAncestor // statusNone indicates that the block has no validation state flags set. // // NOTE: This must be defined last in order to avoid influencing iota. statusNone blockStatus = 0 ) // HaveData returns whether the full block data is stored in the database. This // will return false for a block node where only the header is downloaded or // kept. func (status blockStatus) HaveData() bool { return status&statusDataStored != 0 } // KnownValid returns whether the block is known to be valid. This will return // false for a valid block that has not been fully validated yet. func (status blockStatus) KnownValid() bool { return status&statusValid != 0 } // KnownInvalid returns whether the block is known to be invalid. This may be // because the block itself failed validation or any of its ancestors is // invalid. This will return false for invalid blocks that have not been proven // invalid yet. func (status blockStatus) KnownInvalid() bool { return status&(statusValidateFailed|statusInvalidAncestor) != 0 } // blockNode represents a block within the block chain and is primarily used to // aid in selecting the best chain to be the main chain. The main chain is // stored into the block database. type blockNode struct { // NOTE: Additions, deletions, or modifications to the order of the // definitions in this struct should not be changed without considering // how it affects alignment on 64-bit platforms. The current order is // specifically crafted to result in minimal padding. There will be // hundreds of thousands of these in memory, so a few extra bytes of // padding adds up. // parent is the parent block for this node. parent *blockNode // ancestor is a block that is more than one block back from this node. ancestor *blockNode // hash is the double sha 256 of the block. hash chainhash.Hash // workSum is the total amount of work in the chain up to and including // this node. workSum *big.Int // height is the position in the block chain. height int32 // Some fields from block headers to aid in best chain selection and // reconstructing headers from memory. These must be treated as // immutable and are intentionally ordered to avoid padding on 64-bit // platforms. version int32 bits uint32 nonce uint32 timestamp int64 merkleRoot chainhash.Hash // status is a bitfield representing the validation state of the block. The // status field, unlike the other fields, may be written to and so should // only be accessed using the concurrent-safe NodeStatus method on // blockIndex once the node has been added to the global index. status blockStatus } // initBlockNode initializes a block node from the given header and parent node, // calculating the height and workSum from the respective fields on the parent. // This function is NOT safe for concurrent access. It must only be called when // initially creating a node. func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *blockNode) { *node = blockNode{ hash: blockHeader.BlockHash(), workSum: CalcWork(blockHeader.Bits), version: blockHeader.Version, bits: blockHeader.Bits, nonce: blockHeader.Nonce, timestamp: blockHeader.Timestamp.Unix(), merkleRoot: blockHeader.MerkleRoot, } if parent != nil { node.parent = parent node.height = parent.height + 1 node.workSum = node.workSum.Add(parent.workSum, node.workSum) node.buildAncestor() } } // newBlockNode returns a new block node for the given block header and parent // node, calculating the height and workSum from the respective fields on the // parent. This function is NOT safe for concurrent access. func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode { var node blockNode initBlockNode(&node, blockHeader, parent) return &node } // Equals compares all the fields of the block node except for the parent and // ancestor and returns true if they're equal. func (node *blockNode) Equals(other *blockNode) bool { return node.hash == other.hash && node.workSum.Cmp(other.workSum) == 0 && node.height == other.height && node.version == other.version && node.bits == other.bits && node.nonce == other.nonce && node.timestamp == other.timestamp && node.merkleRoot == other.merkleRoot && node.status == other.status } // Header constructs a block header from the node and returns it. // // This function is safe for concurrent access. func (node *blockNode) Header() wire.BlockHeader { // No lock is needed because all accessed fields are immutable. prevHash := &zeroHash if node.parent != nil { prevHash = &node.parent.hash } return wire.BlockHeader{ Version: node.version, PrevBlock: *prevHash, MerkleRoot: node.merkleRoot, Timestamp: time.Unix(node.timestamp, 0), Bits: node.bits, Nonce: node.nonce, } } // invertLowestOne turns the lowest 1 bit in the binary representation of a number into a 0. func invertLowestOne(n int32) int32 { return n & (n - 1) } // getAncestorHeight returns a suitable ancestor for the node at the given height. func getAncestorHeight(height int32) int32 { // We pop off two 1 bits of the height. // This results in a maximum of 330 steps to go back to an ancestor // from height 1<<29. return invertLowestOne(invertLowestOne(height)) } // buildAncestor sets an ancestor for the given blocknode. func (node *blockNode) buildAncestor() { if node.parent != nil { node.ancestor = node.parent.Ancestor(getAncestorHeight(node.height)) } } // Ancestor returns the ancestor block node at the provided height by following // the chain backwards from this node. The returned block will be nil when a // height is requested that is after the height of the passed node or is less // than zero. // // This function is safe for concurrent access. func (node *blockNode) Ancestor(height int32) *blockNode { if height < 0 || height > node.height { return nil } // Traverse back until we find the desired node. n := node for n != nil && n.height != height { // If there's an ancestor available, use it. Otherwise, just // follow the parent. if n.ancestor != nil { // Calculate the height for this ancestor and // check if we can take the ancestor skip. if getAncestorHeight(n.height) >= height { n = n.ancestor continue } } // We couldn't take the ancestor skip so traverse back to the parent. n = n.parent } return n } // Height returns the blockNode's height in the chain. // // NOTE: Part of the HeaderCtx interface. func (node *blockNode) Height() int32 { return node.height } // Bits returns the blockNode's nBits. // // NOTE: Part of the HeaderCtx interface. func (node *blockNode) Bits() uint32 { return node.bits } // Timestamp returns the blockNode's timestamp. // // NOTE: Part of the HeaderCtx interface. func (node *blockNode) Timestamp() int64 { return node.timestamp } // Parent returns the blockNode's parent. // // NOTE: Part of the HeaderCtx interface. func (node *blockNode) Parent() HeaderCtx { if node.parent == nil { // This is required since node.parent is a *blockNode and if we // do not explicitly return nil here, the caller may fail when // nil-checking this. return nil } return node.parent } // RelativeAncestorCtx returns the blockNode's ancestor that is distance blocks // before it in the chain. This is equivalent to the RelativeAncestor function // below except that the return type is different. // // This function is safe for concurrent access. // // NOTE: Part of the HeaderCtx interface. func (node *blockNode) RelativeAncestorCtx(distance int32) HeaderCtx { ancestor := node.RelativeAncestor(distance) if ancestor == nil { // This is required since RelativeAncestor returns a *blockNode // and if we do not explicitly return nil here, the caller may // fail when nil-checking this. return nil } return ancestor } // IsAncestor returns if the other node is an ancestor of this block node. func (node *blockNode) IsAncestor(otherNode *blockNode) bool { // Return early as false if the otherNode is nil. if otherNode == nil { return false } ancestor := node.Ancestor(otherNode.height) if ancestor == nil { return false } // If the otherNode has the same height as me, then the returned // ancestor will be me. Return false since I'm not an ancestor of me. if node.height == ancestor.height { return false } // Return true if the fetched ancestor is other node. return ancestor.Equals(otherNode) } // RelativeAncestor returns the ancestor block node a relative 'distance' blocks // before this node. This is equivalent to calling Ancestor with the node's // height minus provided distance. // // This function is safe for concurrent access. func (node *blockNode) RelativeAncestor(distance int32) *blockNode { return node.Ancestor(node.height - distance) } // CalcPastMedianTime calculates the median time of the previous few blocks // prior to, and including, the block node. // // This function is safe for concurrent access. func CalcPastMedianTime(node HeaderCtx) time.Time { // Create a slice of the previous few block timestamps used to calculate // the median per the number defined by the constant medianTimeBlocks. timestamps := make([]int64, medianTimeBlocks) numNodes := 0 iterNode := node for i := 0; i < medianTimeBlocks && iterNode != nil; i++ { timestamps[i] = iterNode.Timestamp() numNodes++ iterNode = iterNode.Parent() } // Prune the slice to the actual number of available timestamps which // will be fewer than desired near the beginning of the block chain // and sort them. timestamps = timestamps[:numNodes] sort.Sort(timeSorter(timestamps)) // NOTE: The consensus rules incorrectly calculate the median for even // numbers of blocks. A true median averages the middle two elements // for a set with an even number of elements in it. Since the constant // for the previous number of blocks to be used is odd, this is only an // issue for a few blocks near the beginning of the chain. I suspect // this is an optimization even though the result is slightly wrong for // a few of the first blocks since after the first few blocks, there // will always be an odd number of blocks in the set per the constant. // // This code follows suit to ensure the same rules are used, however, be // aware that should the medianTimeBlocks constant ever be changed to an // even number, this code will be wrong. medianTimestamp := timestamps[numNodes/2] return time.Unix(medianTimestamp, 0) } // A compile-time assertion to ensure blockNode implements the HeaderCtx // interface. var _ HeaderCtx = (*blockNode)(nil) // blockIndex provides facilities for keeping track of an in-memory index of the // block chain. Although the name block chain suggests a single chain of // blocks, it is actually a tree-shaped structure where any node can have // multiple children. However, there can only be one active branch which does // indeed form a chain from the tip all the way back to the genesis block. type blockIndex struct { // The following fields are set when the instance is created and can't // be changed afterwards, so there is no need to protect them with a // separate mutex. db database.DB chainParams *chaincfg.Params sync.RWMutex index map[chainhash.Hash]*blockNode dirty map[*blockNode]struct{} } // newBlockIndex returns a new empty instance of a block index. The index will // be dynamically populated as block nodes are loaded from the database and // manually added. func newBlockIndex(db database.DB, chainParams *chaincfg.Params) *blockIndex { return &blockIndex{ db: db, chainParams: chainParams, index: make(map[chainhash.Hash]*blockNode), dirty: make(map[*blockNode]struct{}), } } // HaveBlock returns whether or not the block index contains the provided hash. // // This function is safe for concurrent access. func (bi *blockIndex) HaveBlock(hash *chainhash.Hash) bool { bi.RLock() _, hasBlock := bi.index[*hash] bi.RUnlock() return hasBlock } // LookupNode returns the block node identified by the provided hash. It will // return nil if there is no entry for the hash. // // This function is safe for concurrent access. func (bi *blockIndex) LookupNode(hash *chainhash.Hash) *blockNode { bi.RLock() node := bi.index[*hash] bi.RUnlock() return node } // AddNode adds the provided node to the block index and marks it as dirty. // Duplicate entries are not checked so it is up to caller to avoid adding them. // // This function is safe for concurrent access. func (bi *blockIndex) AddNode(node *blockNode) { bi.Lock() bi.addNode(node) bi.dirty[node] = struct{}{} bi.Unlock() } // addNode adds the provided node to the block index, but does not mark it as // dirty. This can be used while initializing the block index. // // This function is NOT safe for concurrent access. func (bi *blockIndex) addNode(node *blockNode) { bi.index[node.hash] = node } // NodeStatus provides concurrent-safe access to the status field of a node. // // This function is safe for concurrent access. func (bi *blockIndex) NodeStatus(node *blockNode) blockStatus { bi.RLock() status := node.status bi.RUnlock() return status } // SetStatusFlags flips the provided status flags on the block node to on, // regardless of whether they were on or off previously. This does not unset any // flags currently on. // // This function is safe for concurrent access. func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) { bi.Lock() node.status |= flags bi.dirty[node] = struct{}{} bi.Unlock() } // UnsetStatusFlags flips the provided status flags on the block node to off, // regardless of whether they were on or off previously. // // This function is safe for concurrent access. func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) { bi.Lock() node.status &^= flags bi.dirty[node] = struct{}{} bi.Unlock() } // InactiveTips returns all the block nodes that aren't in the best chain. // // This function is safe for concurrent access. func (bi *blockIndex) InactiveTips(bestChain *chainView) []*blockNode { bi.RLock() defer bi.RUnlock() // Look through the entire blockindex and look for nodes that aren't in // the best chain. We're gonna keep track of all the orphans and the parents // of the orphans. orphans := make(map[chainhash.Hash]*blockNode) orphanParent := make(map[chainhash.Hash]*blockNode) for hash, node := range bi.index { found := bestChain.Contains(node) if !found { orphans[hash] = node orphanParent[node.parent.hash] = node.parent } } // If an orphan isn't pointed to by another orphan, it is a chain tip. // // We can check this by looking for the orphan in the orphan parent map. // If the orphan exists in the orphan parent map, it means that another // orphan is pointing to it. tips := make([]*blockNode, 0, len(orphans)) for hash, orphan := range orphans { _, found := orphanParent[hash] if !found { tips = append(tips, orphan) } delete(orphanParent, hash) } return tips } // flushToDB writes all dirty block nodes to the database. If all writes // succeed, this clears the dirty set. func (bi *blockIndex) flushToDB() error { bi.Lock() if len(bi.dirty) == 0 { bi.Unlock() return nil } err := bi.db.Update(func(dbTx database.Tx) error { for node := range bi.dirty { err := dbStoreBlockNode(dbTx, node) if err != nil { return err } } return nil }) // If write was successful, clear the dirty set. if err == nil { bi.dirty = make(map[*blockNode]struct{}) } bi.Unlock() return err }