blockchain: Add parent to blockNode constructor.

This commit is contained in:
Jim Posen 2017-09-14 19:32:36 -07:00 committed by Dave Collins
parent a4d22d8384
commit 31444f5890
6 changed files with 37 additions and 51 deletions

View File

@ -63,13 +63,8 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags)
// Create a new block node for the block and add it to the in-memory // Create a new block node for the block and add it to the in-memory
// block chain (could be either a side chain or the main chain). // block chain (could be either a side chain or the main chain).
blockHeader := &block.MsgBlock().Header blockHeader := &block.MsgBlock().Header
newNode := newBlockNode(blockHeader, blockHeight) newNode := newBlockNode(blockHeader, prevNode)
newNode.status = statusDataStored newNode.status = statusDataStored
if prevNode != nil {
newNode.parent = prevNode
newNode.height = blockHeight
newNode.workSum.Add(prevNode.workSum, newNode.workSum)
}
b.index.AddNode(newNode) b.index.AddNode(newNode)
// Connect the passed block to the chain while respecting proper chain // Connect the passed block to the chain while respecting proper chain

View File

@ -101,33 +101,33 @@ type blockNode struct {
status blockStatus status blockStatus
} }
// initBlockNode initializes a block node from the given header and height. The // initBlockNode initializes a block node from the given header and parent node,
// node is completely disconnected from the chain and the workSum value is just // calculating the height and workSum from the respective fields on the parent.
// the work for the passed block. The work sum must be updated accordingly when
// the node is inserted into a chain.
//
// This function is NOT safe for concurrent access. It must only be called when // This function is NOT safe for concurrent access. It must only be called when
// initially creating a node. // initially creating a node.
func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, height int32) { func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *blockNode) {
*node = blockNode{ *node = blockNode{
hash: blockHeader.BlockHash(), hash: blockHeader.BlockHash(),
workSum: CalcWork(blockHeader.Bits), workSum: CalcWork(blockHeader.Bits),
height: height,
version: blockHeader.Version, version: blockHeader.Version,
bits: blockHeader.Bits, bits: blockHeader.Bits,
nonce: blockHeader.Nonce, nonce: blockHeader.Nonce,
timestamp: blockHeader.Timestamp.Unix(), timestamp: blockHeader.Timestamp.Unix(),
merkleRoot: blockHeader.MerkleRoot, merkleRoot: blockHeader.MerkleRoot,
} }
if parent != nil {
node.parent = parent
node.height = parent.height + 1
node.workSum = node.workSum.Add(parent.workSum, node.workSum)
}
} }
// newBlockNode returns a new block node for the given block header. It is // newBlockNode returns a new block node for the given block header and parent
// completely disconnected from the chain and the workSum value is just the work // node, calculating the height and workSum from the respective fields on the
// for the passed block. The work sum must be updated accordingly when the node // parent. This function is NOT safe for concurrent access.
// is inserted into a chain. func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode {
func newBlockNode(blockHeader *wire.BlockHeader, height int32) *blockNode {
var node blockNode var node blockNode
initBlockNode(&node, blockHeader, height) initBlockNode(&node, blockHeader, parent)
return &node return &node
} }

View File

@ -1071,7 +1071,7 @@ func (b *BlockChain) createChainState() error {
genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock)
genesisBlock.SetHeight(0) genesisBlock.SetHeight(0)
header := &genesisBlock.MsgBlock().Header header := &genesisBlock.MsgBlock().Header
node := newBlockNode(header, 0) node := newBlockNode(header, nil)
node.status = statusDataStored | statusValid node.status = statusDataStored | statusValid
b.bestChain.SetTip(node) b.bestChain.SetTip(node)
@ -1216,36 +1216,37 @@ func (b *BlockChain) initChainState() error {
return err return err
} }
// Initialize the block node for the block, connect it, // Determine the parent block node. Since we iterate block headers
// and add it to the block index. // in order of height, if the blocks are mostly linear there is a
node := &blockNodes[i] // very good chance the previous header processed is the parent.
initBlockNode(node, &header, 0) var parent *blockNode
node.status = statusDataStored | statusValid
if lastNode == nil { if lastNode == nil {
if node.hash != *b.chainParams.GenesisHash { blockHash := header.BlockHash()
if !blockHash.IsEqual(b.chainParams.GenesisHash) {
return AssertError(fmt.Sprintf("initChainState: Expected "+ return AssertError(fmt.Sprintf("initChainState: Expected "+
"first entry in block index to be genesis block, "+ "first entry in block index to be genesis block, "+
"found %s", header.BlockHash())) "found %s", blockHash))
} }
} else { } else if header.PrevBlock == lastNode.hash {
// Since we iterate block headers in order of height, if the // Since we iterate block headers in order of height, if the
// blocks are mostly linear there is a very good chance the // blocks are mostly linear there is a very good chance the
// previous header processed is the parent. // previous header processed is the parent.
parent := lastNode parent = lastNode
if header.PrevBlock != parent.hash { } else {
parent = b.index.LookupNode(&header.PrevBlock) parent = b.index.LookupNode(&header.PrevBlock)
}
if parent == nil { if parent == nil {
return AssertError(fmt.Sprintf("initChainState: Could "+ return AssertError(fmt.Sprintf("initChainState: Could "+
"not find parent for block %s", header.BlockHash())) "not find parent for block %s", header.BlockHash()))
} }
node.parent = parent
node.height = parent.height + 1
node.workSum = node.workSum.Add(parent.workSum, node.workSum)
} }
// Initialize the block node for the block, connect it,
// and add it to the block index.
node := &blockNodes[i]
initBlockNode(node, &header, parent)
node.status = statusDataStored | statusValid
b.index.AddNode(node) b.index.AddNode(node)
lastNode = node lastNode = node
i++ i++
} }

View File

@ -27,16 +27,11 @@ func chainedNodes(parent *blockNode, numNodes int) []*blockNode {
// This is invalid, but all that is needed is enough to get the // This is invalid, but all that is needed is enough to get the
// synthetic tests to work. // synthetic tests to work.
header := wire.BlockHeader{Nonce: testNoncePrng.Uint32()} header := wire.BlockHeader{Nonce: testNoncePrng.Uint32()}
height := int32(0)
if tip != nil { if tip != nil {
header.PrevBlock = tip.hash header.PrevBlock = tip.hash
height = tip.height + 1
} }
node := newBlockNode(&header, height) nodes[i] = newBlockNode(&header, tip)
node.parent = tip tip = nodes[i]
tip = node
nodes[i] = node
} }
return nodes return nodes
} }

View File

@ -261,7 +261,7 @@ func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) {
func newFakeChain(params *chaincfg.Params) *BlockChain { func newFakeChain(params *chaincfg.Params) *BlockChain {
// Create a genesis block node and block index index populated with it // Create a genesis block node and block index index populated with it
// for use when creating the fake chain below. // for use when creating the fake chain below.
node := newBlockNode(&params.GenesisBlock.Header, 0) node := newBlockNode(&params.GenesisBlock.Header, nil)
index := newBlockIndex(nil, params) index := newBlockIndex(nil, params)
index.AddNode(node) index.AddNode(node)
@ -291,8 +291,5 @@ func newFakeNode(parent *blockNode, blockVersion int32, bits uint32, timestamp t
Bits: bits, Bits: bits,
Timestamp: timestamp, Timestamp: timestamp,
} }
node := newBlockNode(header, parent.height+1) return newBlockNode(header, parent)
node.parent = parent
node.workSum.Add(parent.workSum, node.workSum)
return node
} }

View File

@ -1274,8 +1274,6 @@ func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error {
// is not needed and thus extra work can be avoided. // is not needed and thus extra work can be avoided.
view := NewUtxoViewpoint() view := NewUtxoViewpoint()
view.SetBestHash(&tip.hash) view.SetBestHash(&tip.hash)
newNode := newBlockNode(&header, tip.height+1) newNode := newBlockNode(&header, tip)
newNode.parent = tip
newNode.workSum = newNode.workSum.Add(tip.workSum, newNode.workSum)
return b.checkConnectBlock(newNode, block, view, nil) return b.checkConnectBlock(newNode, block, view, nil)
} }