[NOD-506] Remove blockNode.height and any references to it (#522)

* [NOD-506] Remove blockNode.height.

* [NOD-506] Use blueScore instead of chainHeight in validateParents.
This commit is contained in:
stasatdaglabs 2019-12-09 14:27:53 +02:00 committed by Svarog
parent c94becf144
commit 30f0e95969
9 changed files with 65 additions and 88 deletions

View File

@ -78,9 +78,6 @@ type blockNode struct {
// hash is the double sha 256 of the block. // hash is the double sha 256 of the block.
hash *daghash.Hash hash *daghash.Hash
// height is the position in the block DAG.
height uint64
// chainHeight is the number of hops you need to go down the selected parent chain in order to get to the genesis block. // chainHeight is the number of hops you need to go down the selected parent chain in order to get to the genesis block.
chainHeight uint64 chainHeight uint64
@ -132,18 +129,10 @@ func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parents block
if len(parents) > 0 { if len(parents) > 0 {
node.blues, node.selectedParent, node.blueScore = phantom(node, phantomK) node.blues, node.selectedParent, node.blueScore = phantom(node, phantomK)
node.height = calculateNodeHeight(node)
node.chainHeight = calculateChainHeight(node) node.chainHeight = calculateChainHeight(node)
} }
} }
func calculateNodeHeight(node *blockNode) uint64 {
if node.isGenesis() {
return 0
}
return node.parents.maxHeight() + 1
}
func calculateChainHeight(node *blockNode) uint64 { func calculateChainHeight(node *blockNode) uint64 {
if node.isGenesis() { if node.isGenesis() {
return 0 return 0

View File

@ -23,17 +23,6 @@ func setFromSlice(blocks ...*blockNode) blockSet {
return set return set
} }
// maxHeight returns the height of the highest block in the block set
func (bs blockSet) maxHeight() uint64 {
var maxHeight uint64
for _, node := range bs {
if maxHeight < node.height {
maxHeight = node.height
}
}
return maxHeight
}
// add adds a block to this BlockSet // add adds a block to this BlockSet
func (bs blockSet) add(block *blockNode) { func (bs blockSet) add(block *blockNode) {
bs[*block.hash] = block bs[*block.hash] = block

View File

@ -257,7 +257,7 @@ func coinbaseInputAndOutputForBlueBlock(dag *BlockDAG, blueBlock *blockNode,
} }
} }
totalReward := CalcBlockSubsidy(blueBlock.height, dag.dagParams) + totalFees totalReward := CalcBlockSubsidy(blueBlock.blueScore, dag.dagParams) + totalFees
if totalReward == 0 { if totalReward == 0 {
return txIn, nil, nil return txIn, nil, nil

View File

@ -1598,13 +1598,13 @@ func (dag *BlockDAG) ChildHashesByHash(hash *daghash.Hash) ([]*daghash.Hash, err
return node.children.hashes(), nil return node.children.hashes(), nil
} }
// HeightToHashRange returns a range of block hashes for the given start height // ChainHeightToHashRange returns a range of block hashes for the given start chain
// and end hash, inclusive on both ends. The hashes are for all blocks that are // height and end hash, inclusive on both ends. The hashes are for all blocks that
// ancestors of endHash with height greater than or equal to startHeight. The // are ancestors of endHash with height greater than or equal to startChainHeight.
// end hash must belong to a block that is known to be valid. // The end hash must belong to a block that is known to be valid.
// //
// This function is safe for concurrent access. // This function is safe for concurrent access.
func (dag *BlockDAG) HeightToHashRange(startHeight uint64, func (dag *BlockDAG) ChainHeightToHashRange(startChainHeight uint64,
endHash *daghash.Hash, maxResults int) ([]*daghash.Hash, error) { endHash *daghash.Hash, maxResults int) ([]*daghash.Hash, error) {
endNode := dag.index.LookupNode(endHash) endNode := dag.index.LookupNode(endHash)
@ -1614,23 +1614,23 @@ func (dag *BlockDAG) HeightToHashRange(startHeight uint64,
if !dag.index.NodeStatus(endNode).KnownValid() { if !dag.index.NodeStatus(endNode).KnownValid() {
return nil, errors.Errorf("block %s is not yet validated", endHash) return nil, errors.Errorf("block %s is not yet validated", endHash)
} }
endHeight := endNode.height endChainHeight := endNode.chainHeight
if startHeight < 0 { if startChainHeight < 0 {
return nil, errors.Errorf("start height (%d) is below 0", startHeight) return nil, errors.Errorf("start chain height (%d) is below 0", startChainHeight)
} }
if startHeight > endHeight { if startChainHeight > endChainHeight {
return nil, errors.Errorf("start height (%d) is past end height (%d)", return nil, errors.Errorf("start chain height (%d) is past end chain height (%d)",
startHeight, endHeight) startChainHeight, endChainHeight)
} }
resultsLength := int(endHeight - startHeight + 1) resultsLength := int(endChainHeight - startChainHeight + 1)
if resultsLength > maxResults { if resultsLength > maxResults {
return nil, errors.Errorf("number of results (%d) would exceed max (%d)", return nil, errors.Errorf("number of results (%d) would exceed max (%d)",
resultsLength, maxResults) resultsLength, maxResults)
} }
// Walk backwards from endHeight to startHeight, collecting block hashes. // Walk backwards from endChainHeight to startChainHeight, collecting block hashes.
node := endNode node := endNode
hashes := make([]*daghash.Hash, resultsLength) hashes := make([]*daghash.Hash, resultsLength)
for i := resultsLength - 1; i >= 0; i-- { for i := resultsLength - 1; i >= 0; i-- {
@ -1654,16 +1654,16 @@ func (dag *BlockDAG) IntervalBlockHashes(endHash *daghash.Hash, interval uint64,
if !dag.index.NodeStatus(endNode).KnownValid() { if !dag.index.NodeStatus(endNode).KnownValid() {
return nil, errors.Errorf("block %s is not yet validated", endHash) return nil, errors.Errorf("block %s is not yet validated", endHash)
} }
endHeight := endNode.height endChainHeight := endNode.chainHeight
resultsLength := endHeight / interval resultsLength := endChainHeight / interval
hashes := make([]*daghash.Hash, resultsLength) hashes := make([]*daghash.Hash, resultsLength)
dag.virtual.mtx.Lock() dag.virtual.mtx.Lock()
defer dag.virtual.mtx.Unlock() defer dag.virtual.mtx.Unlock()
blockNode := endNode blockNode := endNode
for index := endHeight / interval; index > 0; index-- { for index := endChainHeight / interval; index > 0; index-- {
blockHeight := index * interval blockHeight := index * interval
blockNode = blockNode.SelectedAncestor(blockHeight) blockNode = blockNode.SelectedAncestor(blockHeight)

View File

@ -594,10 +594,10 @@ func testTip(nodes []*blockNode) *blockNode {
return nodes[len(nodes)-1] return nodes[len(nodes)-1]
} }
// TestHeightToHashRange ensures that fetching a range of block hashes by start // TestChainHeightToHashRange ensures that fetching a range of block hashes by start
// height and end hash works as expected. // chain height and end hash works as expected.
func TestHeightToHashRange(t *testing.T) { func TestChainHeightToHashRange(t *testing.T) {
// Construct a synthetic block chain with a block index consisting of // Construct a synthetic block DAG with a block index consisting of
// the following structure. // the following structure.
// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18
// \-> 16a -> 17a -> 18a (unvalidated) // \-> 16a -> 17a -> 18a (unvalidated)
@ -610,7 +610,7 @@ func TestHeightToHashRange(t *testing.T) {
blockDAG.index.AddNode(node) blockDAG.index.AddNode(node)
} }
for _, node := range branch1Nodes { for _, node := range branch1Nodes {
if node.height < 18 { if node.chainHeight < 18 {
blockDAG.index.SetStatusFlags(node, statusValid) blockDAG.index.SetStatusFlags(node, statusValid)
} }
blockDAG.index.AddNode(node) blockDAG.index.AddNode(node)
@ -619,7 +619,7 @@ func TestHeightToHashRange(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
startHeight uint64 // locator for requested inventory startChainHeight uint64 // locator for requested inventory
endHash *daghash.Hash // stop hash for locator endHash *daghash.Hash // stop hash for locator
maxResults int // max to locate, 0 = wire const maxResults int // max to locate, 0 = wire const
hashes []*daghash.Hash // expected located hashes hashes []*daghash.Hash // expected located hashes
@ -627,50 +627,50 @@ func TestHeightToHashRange(t *testing.T) {
}{ }{
{ {
name: "blocks below tip", name: "blocks below tip",
startHeight: 11, startChainHeight: 11,
endHash: branch0Nodes[14].hash, endHash: branch0Nodes[14].hash,
maxResults: 10, maxResults: 10,
hashes: nodeHashes(branch0Nodes, 10, 11, 12, 13, 14), hashes: nodeHashes(branch0Nodes, 10, 11, 12, 13, 14),
}, },
{ {
name: "blocks on main chain", name: "blocks on main chain",
startHeight: 15, startChainHeight: 15,
endHash: branch0Nodes[17].hash, endHash: branch0Nodes[17].hash,
maxResults: 10, maxResults: 10,
hashes: nodeHashes(branch0Nodes, 14, 15, 16, 17), hashes: nodeHashes(branch0Nodes, 14, 15, 16, 17),
}, },
{ {
name: "blocks on stale chain", name: "blocks on stale chain",
startHeight: 15, startChainHeight: 15,
endHash: branch1Nodes[1].hash, endHash: branch1Nodes[1].hash,
maxResults: 10, maxResults: 10,
hashes: append(nodeHashes(branch0Nodes, 14), hashes: append(nodeHashes(branch0Nodes, 14),
nodeHashes(branch1Nodes, 0, 1)...), nodeHashes(branch1Nodes, 0, 1)...),
}, },
{ {
name: "invalid start height", name: "invalid start chain height",
startHeight: 19, startChainHeight: 19,
endHash: branch0Nodes[17].hash, endHash: branch0Nodes[17].hash,
maxResults: 10, maxResults: 10,
expectError: true, expectError: true,
}, },
{ {
name: "too many results", name: "too many results",
startHeight: 1, startChainHeight: 1,
endHash: branch0Nodes[17].hash, endHash: branch0Nodes[17].hash,
maxResults: 10, maxResults: 10,
expectError: true, expectError: true,
}, },
{ {
name: "unvalidated block", name: "unvalidated block",
startHeight: 15, startChainHeight: 15,
endHash: branch1Nodes[2].hash, endHash: branch1Nodes[2].hash,
maxResults: 10, maxResults: 10,
expectError: true, expectError: true,
}, },
} }
for _, test := range tests { for _, test := range tests {
hashes, err := blockDAG.HeightToHashRange(test.startHeight, test.endHash, hashes, err := blockDAG.ChainHeightToHashRange(test.startChainHeight, test.endHash,
test.maxResults) test.maxResults)
if err != nil { if err != nil {
if !test.expectError { if !test.expectError {
@ -702,7 +702,7 @@ func TestIntervalBlockHashes(t *testing.T) {
dag.index.AddNode(node) dag.index.AddNode(node)
} }
for _, node := range branch1Nodes { for _, node := range branch1Nodes {
if node.height < 18 { if node.chainHeight < 18 {
dag.index.SetStatusFlags(node, statusValid) dag.index.SetStatusFlags(node, statusValid)
} }
dag.index.AddNode(node) dag.index.AddNode(node)

View File

@ -684,7 +684,6 @@ func (dag *BlockDAG) deserializeBlockNode(blockRow []byte) (*blockNode, error) {
node.blues[i] = dag.index.LookupNode(hash) node.blues[i] = dag.index.LookupNode(hash)
} }
node.height = calculateNodeHeight(node)
node.chainHeight = calculateChainHeight(node) node.chainHeight = calculateChainHeight(node)
return node, nil return node, nil

View File

@ -612,7 +612,7 @@ func (dag *BlockDAG) validateDifficulty(header *wire.BlockHeader, bluestParent *
// validateParents validates that no parent is an ancestor of another parent, and no parent is finalized // validateParents validates that no parent is an ancestor of another parent, and no parent is finalized
func validateParents(blockHeader *wire.BlockHeader, parents blockSet) error { func validateParents(blockHeader *wire.BlockHeader, parents blockSet) error {
minHeight := uint64(math.MaxUint64) minBlueScore := uint64(math.MaxUint64)
queue := newDownHeap() queue := newDownHeap()
visited := newSet() visited := newSet()
for _, parent := range parents { for _, parent := range parents {
@ -622,8 +622,8 @@ func validateParents(blockHeader *wire.BlockHeader, parents blockSet) error {
if parent.isFinalized { if parent.isFinalized {
return ruleError(ErrFinality, fmt.Sprintf("block %s is a finalized parent of block %s", parent.hash, blockHeader.BlockHash())) return ruleError(ErrFinality, fmt.Sprintf("block %s is a finalized parent of block %s", parent.hash, blockHeader.BlockHash()))
} }
if parent.height < minHeight { if parent.blueScore < minBlueScore {
minHeight = parent.height minBlueScore = parent.blueScore
} }
for _, grandParent := range parent.parents { for _, grandParent := range parent.parents {
if !visited.contains(grandParent) { if !visited.contains(grandParent) {
@ -640,7 +640,7 @@ func validateParents(blockHeader *wire.BlockHeader, parents blockSet) error {
current.hash, current.hash,
blockHeader.BlockHash())) blockHeader.BlockHash()))
} }
if current.height > minHeight { if current.blueScore > minBlueScore {
for _, parent := range current.parents { for _, parent := range current.parents {
if !visited.contains(parent) { if !visited.contains(parent) {
queue.Push(parent) queue.Push(parent)

View File

@ -12,7 +12,7 @@ func (sp *Peer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) {
return return
} }
hashes, err := sp.server.DAG.HeightToHashRange(msg.StartHeight, hashes, err := sp.server.DAG.ChainHeightToHashRange(msg.StartHeight,
msg.StopHash, wire.MaxGetCFiltersReqRange) msg.StopHash, wire.MaxGetCFiltersReqRange)
if err != nil { if err != nil {
peerLog.Debugf("Invalid getcfilters request: %s", err) peerLog.Debugf("Invalid getcfilters request: %s", err)

View File

@ -24,7 +24,7 @@ func (sp *Peer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
} }
// Fetch the hashes from the block index. // Fetch the hashes from the block index.
hashList, err := sp.server.DAG.HeightToHashRange(startHeight, hashList, err := sp.server.DAG.ChainHeightToHashRange(startHeight,
msg.StopHash, maxResults) msg.StopHash, maxResults)
if err != nil { if err != nil {
peerLog.Debugf("Invalid getcfheaders request: %s", err) peerLog.Debugf("Invalid getcfheaders request: %s", err)