From 359b16fca96ff7a03f1778f3fbdb229a80566dab Mon Sep 17 00:00:00 2001 From: stasatdaglabs <39559713+stasatdaglabs@users.noreply.github.com> Date: Thu, 16 Jan 2020 13:09:16 +0200 Subject: [PATCH] [NOD-616] Remove blockNode.chainHeight (#586) * [NOD-616] Remove unused methods from BlockDAG. * [NOD-616] Remove Height from GetRawMempoolVerboseResult and TxDesc. * [NOD-616] Replaced BlockDAG.ChainHeight with SelectedTipBlueScore. * [NOD-616] Remove the unused BlockChainHeightByHash. * [NOD-616] Remove the unused blockChainHeight from checkBlockHeaderContext. * [NOD-616] Remove chainHeight from util.Block. * [NOD-616] Remove TestChainHeight. * [NOD-616] Update unknown rule activation warning to use blueScore. * [NOD-616] Update thresholdState to use blueScore instead of chainHeight. * [NOD-616] Update blockLocator to use blueScore instead of chainHeight. * [NOD-616] Remove blockNode.chainHeight. * [NOD-616] Fix comments and variable names. * [NOD-616] Replace a weird for loop with a while loop. * [NOD-616] Fix a comment. * [NOD-616] Remove pre-allocation in blockLocator. * [NOD-616] Coalesce checks that startHash and stopHash are not the same into the same condition. * [NOD-616] Fix a comment. * [NOD-616] Remove weird blueScore logic around childHashStrings. * [NOD-616] Fix hash pointer comparison. * [NOD-616] Fix a comment. * [NOD-616] Add ban score to peers misusing GetBlockLocator. * [NOD-616] Replace adding ban score with disconnecting. * [NOD-616] Add blueScore to FilteredBlockAddedNtfn. --- blockdag/accept.go | 2 +- blockdag/blockindex_test.go | 2 +- blockdag/blocklocator.go | 58 ++--- blockdag/blocknode.go | 29 +-- blockdag/blocknode_test.go | 97 -------- blockdag/dag.go | 100 +-------- blockdag/dag_test.go | 225 +------------------ blockdag/dagio.go | 2 - blockdag/thresholdstate.go | 6 +- blockdag/validate.go | 4 +- blockdag/validate_test.go | 35 ++- blockdag/versionbits.go | 4 +- integration/rpctest/blockgen.go | 28 +-- integration/rpctest/rpc_harness.go | 5 +- mempool/mempool.go | 19 +- mempool/mempool_test.go | 7 +- mining/mining.go | 4 - rpcmodel/rpc_results.go | 3 - rpcmodel/rpc_websocket_notifications.go | 6 +- rpcmodel/rpc_websocket_notifications_test.go | 8 +- server/p2p/on_get_block_locator.go | 19 +- server/p2p/p2p.go | 1 - server/rpc/common.go | 27 +-- server/rpc/handle_get_block_header.go | 21 +- server/rpc/handle_get_block_template.go | 8 +- server/rpc/rpcwebsocket.go | 3 +- util/block.go | 31 +-- util/block_test.go | 8 - 28 files changed, 136 insertions(+), 626 deletions(-) delete mode 100644 blockdag/blocknode_test.go diff --git a/blockdag/accept.go b/blockdag/accept.go index 597446edd..1dc2f7399 100644 --- a/blockdag/accept.go +++ b/blockdag/accept.go @@ -80,7 +80,7 @@ func (dag *BlockDAG) maybeAcceptBlock(block *util.Block, flags BehaviorFlags) er } } - block.SetChainHeight(newNode.chainHeight) + block.SetBlueScore(newNode.blueScore) // Connect the passed block to the DAG. This also handles validation of the // transaction scripts. diff --git a/blockdag/blockindex_test.go b/blockdag/blockindex_test.go index 5f87b8d8a..15f5f0b91 100644 --- a/blockdag/blockindex_test.go +++ b/blockdag/blockindex_test.go @@ -19,7 +19,7 @@ func TestAncestorErrors(t *testing.T) { defer teardownFunc() node := newTestNode(dag, newSet(), int32(0x10000000), 0, time.Unix(0, 0)) - node.chainHeight = 2 + node.blueScore = 2 ancestor := node.SelectedAncestor(3) if ancestor != nil { t.Errorf("TestAncestorErrors: Ancestor() unexpectedly returned a node. Expected: ") diff --git a/blockdag/blocklocator.go b/blockdag/blocklocator.go index 6998a31b1..d1e7e2592 100644 --- a/blockdag/blocklocator.go +++ b/blockdag/blocklocator.go @@ -1,8 +1,8 @@ package blockdag import ( - "github.com/kaspanet/kaspad/util" "github.com/kaspanet/kaspad/util/daghash" + "github.com/pkg/errors" ) // BlockLocator is used to help locate a specific block. The algorithm for @@ -29,7 +29,7 @@ type BlockLocator []*daghash.Hash // known. // // This function is safe for concurrent access. -func (dag *BlockDAG) BlockLocatorFromHashes(startHash, stopHash *daghash.Hash) BlockLocator { +func (dag *BlockDAG) BlockLocatorFromHashes(startHash, stopHash *daghash.Hash) (BlockLocator, error) { dag.dagLock.RLock() defer dag.dagLock.RUnlock() startNode := dag.index.LookupNode(startHash) @@ -40,15 +40,6 @@ func (dag *BlockDAG) BlockLocatorFromHashes(startHash, stopHash *daghash.Hash) B return dag.blockLocator(startNode, stopNode) } -// LatestBlockLocator returns a block locator for the current tips of the DAG. -// -// This function is safe for concurrent access. -func (dag *BlockDAG) LatestBlockLocator() BlockLocator { - dag.dagLock.RLock() - defer dag.dagLock.RUnlock() - return dag.blockLocator(nil, nil) -} - // blockLocator returns a block locator for the passed start and stop nodes. // The default value for the start node is the selected tip, and the default // values of the stop node is the genesis block. @@ -56,7 +47,7 @@ func (dag *BlockDAG) LatestBlockLocator() BlockLocator { // See the BlockLocator type comments for more details. // // This function MUST be called with the DAG state lock held (for reads). -func (dag *BlockDAG) blockLocator(startNode, stopNode *blockNode) BlockLocator { +func (dag *BlockDAG) blockLocator(startNode, stopNode *blockNode) (BlockLocator, error) { // Use the selected tip if requested. if startNode == nil { startNode = dag.virtual.selectedParent @@ -70,51 +61,36 @@ func (dag *BlockDAG) blockLocator(startNode, stopNode *blockNode) BlockLocator { // block locator won't contain the start node. startNode = startNode.selectedParent - // If the start node or the stop node are not in the - // virtual's selected parent chain, we replace them with their - // closest selected parent that is part of the virtual's - // selected parent chain. - for !dag.IsInSelectedParentChain(stopNode.hash) { - stopNode = stopNode.selectedParent - } - - for !dag.IsInSelectedParentChain(startNode.hash) { - startNode = startNode.selectedParent - } - - // Calculate the max number of entries that will ultimately be in the - // block locator. See the description of the algorithm for how these - // numbers are derived. - - // startNode.hash + stopNode.hash. - // Then floor(log2(startNode.chainHeight-stopNode.chainHeight)) entries for the skip portion. - maxEntries := 2 + util.FastLog2Floor(startNode.chainHeight-stopNode.chainHeight) - locator := make(BlockLocator, 0, maxEntries) - + node := startNode step := uint64(1) - for node := startNode; node != nil; { + locator := make(BlockLocator, 0) + for node != nil { locator = append(locator, node.hash) // Nothing more to add once the stop node has been added. - if node.chainHeight == stopNode.chainHeight { + if node.blueScore <= stopNode.blueScore { + if node != stopNode { + return nil, errors.Errorf("startNode and stopNode are " + + "not in the same selected parent chain.") + } break } - // Calculate chainHeight of previous node to include ensuring the + // Calculate blueScore of previous node to include ensuring the // final node is stopNode. - nextChainHeight := node.chainHeight - step - if nextChainHeight < stopNode.chainHeight { - nextChainHeight = stopNode.chainHeight + nextBlueScore := node.blueScore - step + if nextBlueScore < stopNode.blueScore { + nextBlueScore = stopNode.blueScore } // walk backwards through the nodes to the correct ancestor. - node = node.SelectedAncestor(nextChainHeight) + node = node.SelectedAncestor(nextBlueScore) // Double the distance between included hashes. step *= 2 } - return locator + return locator, nil } // FindNextLocatorBoundaries returns the lowest unknown block locator, hash diff --git a/blockdag/blocknode.go b/blockdag/blocknode.go index 6c2c118c8..127aa414d 100644 --- a/blockdag/blocknode.go +++ b/blockdag/blocknode.go @@ -83,9 +83,6 @@ type blockNode struct { // hash is the double sha 256 of the block. hash *daghash.Hash - // 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 - // Some fields from block headers to aid in reconstructing headers // from memory. These must be treated as immutable and are intentionally // ordered to avoid padding on 64-bit platforms. @@ -107,13 +104,6 @@ type blockNode struct { isFinalized bool } -func calculateChainHeight(node *blockNode) uint64 { - if node.isGenesis() { - return 0 - } - return node.selectedParent.chainHeight + 1 -} - // newBlockNode returns a new block node for the given block header and parents, and the // anticone of its selected parent (parent with highest blue score). // selectedParentAnticone is used to update reachability data we store for future reachability queries. @@ -146,7 +136,6 @@ func (dag *BlockDAG) newBlockNode(blockHeader *wire.BlockHeader, parents blockSe if err != nil { panic(errors.Wrap(err, "unexpected error in GHOSTDAG")) } - node.chainHeight = calculateChainHeight(node) } return node, selectedParentAnticone } @@ -183,31 +172,31 @@ func (node *blockNode) Header() *wire.BlockHeader { } } -// SelectedAncestor returns the ancestor block node at the provided chain-height by following +// SelectedAncestor returns the ancestor block node at the provided blue score by following // the selected-parents 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. +// blue score is requested that is higher than the blue score of the passed node. // // This function is safe for concurrent access. -func (node *blockNode) SelectedAncestor(chainHeight uint64) *blockNode { - if chainHeight < 0 || chainHeight > node.chainHeight { +func (node *blockNode) SelectedAncestor(blueScore uint64) *blockNode { + if blueScore < 0 || blueScore > node.blueScore { return nil } n := node - for ; n != nil && n.chainHeight != chainHeight; n = n.selectedParent { - // Intentionally left blank + for n != nil && n.blueScore > blueScore { + n = n.selectedParent } return n } // RelativeAncestor returns the ancestor block node a relative 'distance' of -// chain-blocks before this node. This is equivalent to calling Ancestor with -// the node's chain-height minus provided distance. +// blue blocks before this node. This is equivalent to calling Ancestor with +// the node's blue score minus provided distance. // // This function is safe for concurrent access. func (node *blockNode) RelativeAncestor(distance uint64) *blockNode { - return node.SelectedAncestor(node.chainHeight - distance) + return node.SelectedAncestor(node.blueScore - distance) } // CalcPastMedianTime returns the median time of the previous few blocks diff --git a/blockdag/blocknode_test.go b/blockdag/blocknode_test.go deleted file mode 100644 index 11c1e7f15..000000000 --- a/blockdag/blocknode_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package blockdag - -import ( - "github.com/kaspanet/kaspad/dagconfig" - "github.com/kaspanet/kaspad/wire" - "testing" -) - -func TestChainHeight(t *testing.T) { - // Create a new database and DAG instance to run tests against. - params := dagconfig.SimnetParams - params.K = 2 - dag, teardownFunc, err := DAGSetup("TestChainHeight", Config{ - DAGParams: ¶ms, - }) - if err != nil { - t.Fatalf("TestChainHeight: Failed to setup DAG instance: %s", err) - } - defer teardownFunc() - - block0 := dag.dagParams.GenesisBlock - block1 := prepareAndProcessBlock(t, dag, block0) - block2 := prepareAndProcessBlock(t, dag, block0) - block3 := prepareAndProcessBlock(t, dag, block0) - block4 := prepareAndProcessBlock(t, dag, block1, block2, block3) - block5 := prepareAndProcessBlock(t, dag, block1, block2, block3) - block6 := prepareAndProcessBlock(t, dag, block1, block2, block3) - block7 := prepareAndProcessBlock(t, dag, block0) - block8 := prepareAndProcessBlock(t, dag, block7) - block9 := prepareAndProcessBlock(t, dag, block8) - block10 := prepareAndProcessBlock(t, dag, block9, block6) - - // Because nodes 7 & 8 were mined secretly, block10's selected - // parent will be block6, although block9 is higher. So in this - // case, block10.height and block10.chainHeight will be different - - tests := []struct { - block *wire.MsgBlock - expectedChainHeight uint64 - }{ - { - block: block0, - expectedChainHeight: 0, - }, - { - block: block1, - expectedChainHeight: 1, - }, - { - block: block2, - expectedChainHeight: 1, - }, - { - block: block3, - expectedChainHeight: 1, - }, - { - block: block4, - expectedChainHeight: 2, - }, - { - block: block5, - expectedChainHeight: 2, - }, - { - block: block6, - expectedChainHeight: 2, - }, - { - block: block7, - expectedChainHeight: 1, - }, - { - block: block8, - expectedChainHeight: 2, - }, - { - block: block9, - expectedChainHeight: 3, - }, - { - block: block10, - expectedChainHeight: 3, - }, - } - - for _, test := range tests { - node := dag.index.LookupNode(test.block.BlockHash()) - if node.chainHeight != test.expectedChainHeight { - t.Errorf("block %s expected chain height %v but got %v", node, test.expectedChainHeight, node.chainHeight) - } - if calculateChainHeight(node) != test.expectedChainHeight { - t.Errorf("block %s expected calculated chain height %v but got %v", node, test.expectedChainHeight, node.chainHeight) - } - } - -} diff --git a/blockdag/dag.go b/blockdag/dag.go index 8872781f7..b812c7fd2 100644 --- a/blockdag/dag.go +++ b/blockdag/dag.go @@ -1516,10 +1516,9 @@ func (dag *BlockDAG) SelectedParentChain(startHash *daghash.Hash) ([]*daghash.Ha return removedChainHashes, addedChainHashes, nil } -// ChainHeight return the chain-height of the selected tip. In other words - it returns -// the length of the dag's selected-parent chain -func (dag *BlockDAG) ChainHeight() uint64 { - return dag.selectedTip().chainHeight +// SelectedTipBlueScore returns the blue score of the selected tip. +func (dag *BlockDAG) SelectedTipBlueScore() uint64 { + return dag.selectedTip().blueScore } // VirtualBlueScore returns the blue score of the current virtual block @@ -1561,20 +1560,6 @@ func (dag *BlockDAG) HeaderByHash(hash *daghash.Hash) (*wire.BlockHeader, error) return node.Header(), nil } -// BlockChainHeightByHash returns the chain height of the block with the given -// hash in the DAG. -// -// This function is safe for concurrent access. -func (dag *BlockDAG) BlockChainHeightByHash(hash *daghash.Hash) (uint64, error) { - node := dag.index.LookupNode(hash) - if node == nil { - str := fmt.Sprintf("block %s is not in the DAG", hash) - return 0, errNotInDAG(str) - } - - return node.chainHeight, nil -} - // ChildHashesByHash returns the child hashes of the block with the given hash in the // DAG. // @@ -1608,81 +1593,6 @@ func (dag *BlockDAG) SelectedParentHash(blockHash *daghash.Hash) (*daghash.Hash, return node.selectedParent.hash, nil } -// ChainHeightToHashRange returns a range of block hashes for the given start chain -// height and end hash, inclusive on both ends. The hashes are for all blocks that -// are ancestors of endHash with height greater than or equal to startChainHeight. -// The end hash must belong to a block that is known to be valid. -// -// This function is safe for concurrent access. -func (dag *BlockDAG) ChainHeightToHashRange(startChainHeight uint64, - endHash *daghash.Hash, maxResults int) ([]*daghash.Hash, error) { - - endNode := dag.index.LookupNode(endHash) - if endNode == nil { - return nil, errors.Errorf("no known block header with hash %s", endHash) - } - if !dag.index.NodeStatus(endNode).KnownValid() { - return nil, errors.Errorf("block %s is not yet validated", endHash) - } - endChainHeight := endNode.chainHeight - - if startChainHeight < 0 { - return nil, errors.Errorf("start chain height (%d) is below 0", startChainHeight) - } - if startChainHeight > endChainHeight { - return nil, errors.Errorf("start chain height (%d) is past end chain height (%d)", - startChainHeight, endChainHeight) - } - - resultsLength := int(endChainHeight - startChainHeight + 1) - if resultsLength > maxResults { - return nil, errors.Errorf("number of results (%d) would exceed max (%d)", - resultsLength, maxResults) - } - - // Walk backwards from endChainHeight to startChainHeight, collecting block hashes. - node := endNode - hashes := make([]*daghash.Hash, resultsLength) - for i := resultsLength - 1; i >= 0; i-- { - hashes[i] = node.hash - node = node.selectedParent - } - return hashes, nil -} - -// IntervalBlockHashes returns hashes for all blocks that are ancestors of -// endHash where the block height is a positive multiple of interval. -// -// This function is safe for concurrent access. -func (dag *BlockDAG) IntervalBlockHashes(endHash *daghash.Hash, interval uint64, -) ([]*daghash.Hash, error) { - - endNode := dag.index.LookupNode(endHash) - if endNode == nil { - return nil, errors.Errorf("no known block header with hash %s", endHash) - } - if !dag.index.NodeStatus(endNode).KnownValid() { - return nil, errors.Errorf("block %s is not yet validated", endHash) - } - endChainHeight := endNode.chainHeight - - resultsLength := endChainHeight / interval - hashes := make([]*daghash.Hash, resultsLength) - - dag.virtual.mtx.Lock() - defer dag.virtual.mtx.Unlock() - - blockNode := endNode - for index := endChainHeight / interval; index > 0; index-- { - blockHeight := index * interval - blockNode = blockNode.SelectedAncestor(blockHeight) - - hashes[index-1] = blockNode.hash - } - - return hashes, nil -} - // getBlueBlocksHashesBetween returns the hashes of the blocks after the provided // start hash until the provided stop hash is reached, or up to the // provided max number of block hashes. @@ -2055,8 +1965,8 @@ func New(config *Config) (*BlockDAG, error) { } selectedTip := dag.selectedTip() - log.Infof("DAG state (chain height %d, hash %s)", - selectedTip.chainHeight, selectedTip.hash) + log.Infof("DAG state (blue score %d, hash %s)", + selectedTip.blueScore, selectedTip.hash) return dag, nil } diff --git a/blockdag/dag_test.go b/blockdag/dag_test.go index 1a00eb57b..bffdc7e0a 100644 --- a/blockdag/dag_test.go +++ b/blockdag/dag_test.go @@ -8,12 +8,9 @@ import ( "fmt" "os" "path/filepath" - "reflect" "testing" "time" - "math/rand" - "github.com/kaspanet/kaspad/dagconfig" "github.com/kaspanet/kaspad/database" "github.com/kaspanet/kaspad/txscript" @@ -271,7 +268,7 @@ func TestCalcSequenceLock(t *testing.T) { TxID: *targetTx.ID(), Index: 0, } - prevUtxoChainHeight := uint64(numBlocksToGenerate) - 4 + prevUtxoBlueScore := uint64(numBlocksToGenerate) - 4 // Obtain the past median time from the PoV of the input created above. // The past median time for the input is the past median time from the PoV @@ -283,7 +280,7 @@ func TestCalcSequenceLock(t *testing.T) { // the MTP will be calculated from the PoV of the yet-to-be-mined // block. nextMedianTime := node.PastMedianTime(dag).Unix() - nextBlockChainHeight := int32(numBlocksToGenerate) + 1 + nextBlockBlueScore := int32(numBlocksToGenerate) + 1 // Add an additional transaction which will serve as our unconfirmed // output. @@ -369,7 +366,7 @@ func TestCalcSequenceLock(t *testing.T) { utxoSet: utxoSet, want: &SequenceLock{ Seconds: medianTime + (5 << wire.SequenceLockTimeGranularity) - 1, - BlockBlueScore: int64(prevUtxoChainHeight) + 3, + BlockBlueScore: int64(prevUtxoBlueScore) + 3, }, }, // Transaction with a single input. The input's sequence number @@ -382,7 +379,7 @@ func TestCalcSequenceLock(t *testing.T) { utxoSet: utxoSet, want: &SequenceLock{ Seconds: -1, - BlockBlueScore: int64(prevUtxoChainHeight) + 2, + BlockBlueScore: int64(prevUtxoBlueScore) + 2, }, }, // A transaction with two inputs with lock times expressed in @@ -421,7 +418,7 @@ func TestCalcSequenceLock(t *testing.T) { utxoSet: utxoSet, want: &SequenceLock{ Seconds: -1, - BlockBlueScore: int64(prevUtxoChainHeight) + 10, + BlockBlueScore: int64(prevUtxoBlueScore) + 10, }, }, // A transaction with multiple inputs. Two inputs are time @@ -447,7 +444,7 @@ func TestCalcSequenceLock(t *testing.T) { utxoSet: utxoSet, want: &SequenceLock{ Seconds: medianTime + (13 << wire.SequenceLockTimeGranularity) - 1, - BlockBlueScore: int64(prevUtxoChainHeight) + 8, + BlockBlueScore: int64(prevUtxoBlueScore) + 8, }, }, // A transaction with a single unconfirmed input. As the input @@ -463,7 +460,7 @@ func TestCalcSequenceLock(t *testing.T) { mempool: true, want: &SequenceLock{ Seconds: -1, - BlockBlueScore: int64(nextBlockChainHeight) + 1, + BlockBlueScore: int64(nextBlockBlueScore) + 1, }, }, // A transaction with a single unconfirmed input. The input has @@ -544,214 +541,6 @@ func TestCalcPastMedianTime(t *testing.T) { t.Errorf("TestCalcPastMedianTime: expected past median time of block %v to be %v seconds from genesis but got %v", test.blockNumber, test.expectedSecondsSinceGenesis, secondsSinceGenesis) } } - -} - -// nodeHashes is a convenience function that returns the hashes for all of the -// passed indexes of the provided nodes. It is used to construct expected hash -// slices in the tests. -func nodeHashes(nodes []*blockNode, indexes ...int) []*daghash.Hash { - hashes := make([]*daghash.Hash, 0, len(indexes)) - for _, idx := range indexes { - hashes = append(hashes, nodes[idx].hash) - } - return hashes -} - -// testNoncePrng provides a deterministic prng for the nonce in generated fake -// nodes. The ensures that the node have unique hashes. -var testNoncePrng = rand.New(rand.NewSource(0)) - -// chainedNodes returns the specified number of nodes constructed such that each -// subsequent node points to the previous one to create a chain. The first node -// will point to the passed parent which can be nil if desired. -func chainedNodes(dag *BlockDAG, parents blockSet, numNodes int) []*blockNode { - nodes := make([]*blockNode, numNodes) - tips := parents - for i := 0; i < numNodes; i++ { - // This is invalid, but all that is needed is enough to get the - // synthetic tests to work. - header := wire.BlockHeader{ - Nonce: testNoncePrng.Uint64(), - HashMerkleRoot: &daghash.ZeroHash, - AcceptedIDMerkleRoot: &daghash.ZeroHash, - UTXOCommitment: &daghash.ZeroHash, - } - header.ParentHashes = tips.hashes() - nodes[i], _ = dag.newBlockNode(&header, tips) - tips = setFromSlice(nodes[i]) - } - return nodes -} - -// testTip is a convenience function to grab the tip of a chain of block nodes -// created via chainedNodes. -func testTip(nodes []*blockNode) *blockNode { - return nodes[len(nodes)-1] -} - -// TestChainHeightToHashRange ensures that fetching a range of block hashes by start -// chain height and end hash works as expected. -func TestChainHeightToHashRange(t *testing.T) { - // Construct a synthetic block DAG with a block index consisting of - // the following structure. - // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 - // \-> 16a -> 17a -> 18a (unvalidated) - tip := testTip - dag := newTestDAG(&dagconfig.SimnetParams) - branch0Nodes := chainedNodes(dag, setFromSlice(dag.genesis), 18) - branch1Nodes := chainedNodes(dag, setFromSlice(branch0Nodes[14]), 3) - for _, node := range branch0Nodes { - dag.index.SetStatusFlags(node, statusValid) - dag.index.AddNode(node) - } - for _, node := range branch1Nodes { - if node.chainHeight < 18 { - dag.index.SetStatusFlags(node, statusValid) - } - dag.index.AddNode(node) - } - dag.virtual.SetTips(setFromSlice(tip(branch0Nodes))) - - tests := []struct { - name string - startChainHeight uint64 // locator for requested inventory - endHash *daghash.Hash // stop hash for locator - maxResults int // max to locate, 0 = wire const - hashes []*daghash.Hash // expected located hashes - expectError bool - }{ - { - name: "blocks below tip", - startChainHeight: 11, - endHash: branch0Nodes[14].hash, - maxResults: 10, - hashes: nodeHashes(branch0Nodes, 10, 11, 12, 13, 14), - }, - { - name: "blocks on main chain", - startChainHeight: 15, - endHash: branch0Nodes[17].hash, - maxResults: 10, - hashes: nodeHashes(branch0Nodes, 14, 15, 16, 17), - }, - { - name: "blocks on stale chain", - startChainHeight: 15, - endHash: branch1Nodes[1].hash, - maxResults: 10, - hashes: append(nodeHashes(branch0Nodes, 14), - nodeHashes(branch1Nodes, 0, 1)...), - }, - { - name: "invalid start chain height", - startChainHeight: 19, - endHash: branch0Nodes[17].hash, - maxResults: 10, - expectError: true, - }, - { - name: "too many results", - startChainHeight: 1, - endHash: branch0Nodes[17].hash, - maxResults: 10, - expectError: true, - }, - { - name: "unvalidated block", - startChainHeight: 15, - endHash: branch1Nodes[2].hash, - maxResults: 10, - expectError: true, - }, - } - for _, test := range tests { - hashes, err := dag.ChainHeightToHashRange(test.startChainHeight, test.endHash, - test.maxResults) - if err != nil { - if !test.expectError { - t.Errorf("%s: unexpected error: %v", test.name, err) - } - continue - } - - if !reflect.DeepEqual(hashes, test.hashes) { - t.Errorf("%s: unxpected hashes -- got %v, want %v", - test.name, hashes, test.hashes) - } - } -} - -// TestIntervalBlockHashes ensures that fetching block hashes at specified -// intervals by end hash works as expected. -func TestIntervalBlockHashes(t *testing.T) { - // Construct a synthetic block DAG with a block index consisting of - // the following structure. - // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 - // \-> 16a -> 17a -> 18a (unvalidated) - tip := testTip - dag := newTestDAG(&dagconfig.SimnetParams) - branch0Nodes := chainedNodes(dag, setFromSlice(dag.genesis), 18) - branch1Nodes := chainedNodes(dag, setFromSlice(branch0Nodes[14]), 3) - for _, node := range branch0Nodes { - dag.index.SetStatusFlags(node, statusValid) - dag.index.AddNode(node) - } - for _, node := range branch1Nodes { - if node.chainHeight < 18 { - dag.index.SetStatusFlags(node, statusValid) - } - dag.index.AddNode(node) - } - dag.virtual.SetTips(setFromSlice(tip(branch0Nodes))) - - tests := []struct { - name string - endHash *daghash.Hash - interval uint64 - hashes []*daghash.Hash - expectError bool - }{ - { - name: "blocks on main chain", - endHash: branch0Nodes[17].hash, - interval: 8, - hashes: nodeHashes(branch0Nodes, 7, 15), - }, - { - name: "blocks on stale chain", - endHash: branch1Nodes[1].hash, - interval: 8, - hashes: append(nodeHashes(branch0Nodes, 7), - nodeHashes(branch1Nodes, 0)...), - }, - { - name: "no results", - endHash: branch0Nodes[17].hash, - interval: 20, - hashes: []*daghash.Hash{}, - }, - { - name: "unvalidated block", - endHash: branch1Nodes[2].hash, - interval: 8, - expectError: true, - }, - } - for _, test := range tests { - hashes, err := dag.IntervalBlockHashes(test.endHash, test.interval) - if err != nil { - if !test.expectError { - t.Errorf("%s: unexpected error: %v", test.name, err) - } - continue - } - - if !reflect.DeepEqual(hashes, test.hashes) { - t.Errorf("%s: unxpected hashes -- got %v, want %v", - test.name, hashes, test.hashes) - } - } } func TestNew(t *testing.T) { diff --git a/blockdag/dagio.go b/blockdag/dagio.go index 2da270172..ec8bfc248 100644 --- a/blockdag/dagio.go +++ b/blockdag/dagio.go @@ -717,8 +717,6 @@ func (dag *BlockDAG) deserializeBlockNode(blockRow []byte) (*blockNode, error) { } } - node.chainHeight = calculateChainHeight(node) - return node, nil } diff --git a/blockdag/thresholdstate.go b/blockdag/thresholdstate.go index 007a80f1a..bbeb5217b 100644 --- a/blockdag/thresholdstate.go +++ b/blockdag/thresholdstate.go @@ -130,15 +130,15 @@ func (dag *BlockDAG) thresholdState(prevNode *blockNode, checker thresholdCondit // The threshold state for the window that contains the genesis block is // defined by definition. confirmationWindow := checker.MinerConfirmationWindow() - if prevNode == nil || (prevNode.chainHeight+1) < confirmationWindow { + if prevNode == nil || (prevNode.blueScore+1) < confirmationWindow { return ThresholdDefined, nil } // Get the ancestor that is the last block of the previous confirmation // window in order to get its threshold state. This can be done because // the state is the same for all blocks within a given window. - prevNode = prevNode.SelectedAncestor(prevNode.chainHeight - - (prevNode.chainHeight+1)%confirmationWindow) + prevNode = prevNode.SelectedAncestor(prevNode.blueScore - + (prevNode.blueScore+1)%confirmationWindow) // Iterate backwards through each of the previous confirmation windows // to find the most recently cached threshold state. diff --git a/blockdag/validate.go b/blockdag/validate.go index b335cd897..24e4ef704 100644 --- a/blockdag/validate.go +++ b/blockdag/validate.go @@ -555,7 +555,7 @@ func (dag *BlockDAG) checkBlockSanity(block *util.Block, flags BehaviorFlags) (t // - BFFastAdd: No checks are performed. // // This function MUST be called with the dag state lock held (for writes). -func (dag *BlockDAG) checkBlockHeaderContext(header *wire.BlockHeader, bluestParent *blockNode, blockChainHeight uint64, fastAdd bool) error { +func (dag *BlockDAG) checkBlockHeaderContext(header *wire.BlockHeader, bluestParent *blockNode, fastAdd bool) error { if !fastAdd { if err := dag.validateDifficulty(header, bluestParent); err != nil { return err @@ -661,7 +661,7 @@ func (dag *BlockDAG) checkBlockContext(block *util.Block, parents blockSet, flag // Perform all block header related validation checks. header := &block.MsgBlock().Header - if err = dag.checkBlockHeaderContext(header, bluestParent, block.ChainHeight(), fastAdd); err != nil { + if err = dag.checkBlockHeaderContext(header, bluestParent, fastAdd); err != nil { return err } diff --git a/blockdag/validate_test.go b/blockdag/validate_test.go index 0a427af65..7ac60e60b 100644 --- a/blockdag/validate_test.go +++ b/blockdag/validate_test.go @@ -28,35 +28,35 @@ func TestSequenceLocksActive(t *testing.T) { } tests := []struct { - seqLock *SequenceLock - blockChainHeight uint64 - mtp time.Time + seqLock *SequenceLock + blockBlueScore uint64 + mtp time.Time want bool }{ - // Block based sequence lock with equal block height. - {seqLock: seqLock(1000, -1), blockChainHeight: 1001, mtp: time.Unix(9, 0), want: true}, + // Block based sequence lock with equal block blue score. + {seqLock: seqLock(1000, -1), blockBlueScore: 1001, mtp: time.Unix(9, 0), want: true}, // Time based sequence lock with mtp past the absolute time. - {seqLock: seqLock(-1, 30), blockChainHeight: 2, mtp: time.Unix(31, 0), want: true}, + {seqLock: seqLock(-1, 30), blockBlueScore: 2, mtp: time.Unix(31, 0), want: true}, - // Block based sequence lock with current height below seq lock block height. - {seqLock: seqLock(1000, -1), blockChainHeight: 90, mtp: time.Unix(9, 0), want: false}, + // Block based sequence lock with current blue score below seq lock block blue score. + {seqLock: seqLock(1000, -1), blockBlueScore: 90, mtp: time.Unix(9, 0), want: false}, // Time based sequence lock with current time before lock time. - {seqLock: seqLock(-1, 30), blockChainHeight: 2, mtp: time.Unix(29, 0), want: false}, + {seqLock: seqLock(-1, 30), blockBlueScore: 2, mtp: time.Unix(29, 0), want: false}, - // Block based sequence lock at the same height, so shouldn't yet be active. - {seqLock: seqLock(1000, -1), blockChainHeight: 1000, mtp: time.Unix(9, 0), want: false}, + // Block based sequence lock at the same blue score, so shouldn't yet be active. + {seqLock: seqLock(1000, -1), blockBlueScore: 1000, mtp: time.Unix(9, 0), want: false}, // Time based sequence lock with current time equal to lock time, so shouldn't yet be active. - {seqLock: seqLock(-1, 30), blockChainHeight: 2, mtp: time.Unix(30, 0), want: false}, + {seqLock: seqLock(-1, 30), blockBlueScore: 2, mtp: time.Unix(30, 0), want: false}, } t.Logf("Running %d sequence locks tests", len(tests)) for i, test := range tests { got := SequenceLockActive(test.seqLock, - test.blockChainHeight, test.mtp) + test.blockBlueScore, test.mtp) if got != test.want { t.Fatalf("SequenceLockActive #%d got %v want %v", i, got, test.want) @@ -515,42 +515,39 @@ func TestPastMedianTime(t *testing.T) { } // Checks that a block is valid if it has timestamp equals to past median time - chainHeight := tip.chainHeight + 1 node := newTestNode(dag, setFromSlice(tip), blockVersion, dag.powMaxBits, tip.PastMedianTime(dag)) header := node.Header() - err := dag.checkBlockHeaderContext(header, node.parents.bluest(), chainHeight, false) + err := dag.checkBlockHeaderContext(header, node.parents.bluest(), false) if err != nil { t.Errorf("TestPastMedianTime: unexpected error from checkBlockHeaderContext: %v"+ "(a block with timestamp equals to past median time should be valid)", err) } // Checks that a block is valid if its timestamp is after past median time - chainHeight = tip.chainHeight + 1 node = newTestNode(dag, setFromSlice(tip), blockVersion, dag.powMaxBits, tip.PastMedianTime(dag).Add(time.Second)) header = node.Header() - err = dag.checkBlockHeaderContext(header, node.parents.bluest(), chainHeight, false) + err = dag.checkBlockHeaderContext(header, node.parents.bluest(), false) if err != nil { t.Errorf("TestPastMedianTime: unexpected error from checkBlockHeaderContext: %v"+ "(a block with timestamp bigger than past median time should be valid)", err) } // Checks that a block is invalid if its timestamp is before past median time - chainHeight = tip.chainHeight + 1 node = newTestNode(dag, setFromSlice(tip), blockVersion, 0, tip.PastMedianTime(dag).Add(-time.Second)) header = node.Header() - err = dag.checkBlockHeaderContext(header, node.parents.bluest(), chainHeight, false) + err = dag.checkBlockHeaderContext(header, node.parents.bluest(), false) if err == nil { t.Errorf("TestPastMedianTime: unexpected success: block should be invalid if its timestamp is before past median time") } diff --git a/blockdag/versionbits.go b/blockdag/versionbits.go index 1b8f52b72..e2f894a90 100644 --- a/blockdag/versionbits.go +++ b/blockdag/versionbits.go @@ -250,9 +250,9 @@ func (dag *BlockDAG) warnUnknownRuleActivations(node *blockNode) error { case ThresholdLockedIn: window := checker.MinerConfirmationWindow() - activationChainHeight := window - (node.chainHeight % window) + activationBlueScore := window - (node.blueScore % window) log.Warnf("Unknown new rules are about to activate in "+ - "%d blocks (bit %d)", activationChainHeight, bit) + "%d blueScore (bit %d)", activationBlueScore, bit) } } diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index 7f4e7ceef..5337ce5c5 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -87,14 +87,14 @@ func solveBlock(header *wire.BlockHeader, targetDifficulty *big.Int) bool { // standardCoinbaseScript returns a standard script suitable for use as the // signature script of the coinbase transaction of a new block. In particular, -// it starts with the block height that is required by version 2 blocks. -func standardCoinbaseScript(nextBlockHeight uint64, extraNonce uint64) ([]byte, error) { - return txscript.NewScriptBuilder().AddInt64(int64(nextBlockHeight)). +// it starts with the block blue score. +func standardCoinbaseScript(nextBlueScore uint64, extraNonce uint64) ([]byte, error) { + return txscript.NewScriptBuilder().AddInt64(int64(nextBlueScore)). AddInt64(int64(extraNonce)).Script() } // createCoinbaseTx returns a coinbase transaction paying an appropriate -// subsidy based on the passed block height to the provided address. +// subsidy based on the passed block blue score to the provided address. func createCoinbaseTx(coinbaseScript []byte, nextBlueScore uint64, addr util.Address, mineTo []wire.TxOut, net *dagconfig.Params) (*util.Tx, error) { @@ -133,27 +133,27 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlueScore uint64, // initialized), then the timestamp of the previous block will be used plus 1 // second is used. Passing nil for the previous block results in a block that // builds off of the genesis block for the specified chain. -func CreateBlock(parentBlock *util.Block, inclusionTxs []*util.Tx, - blockVersion int32, blockTime time.Time, miningAddr util.Address, - mineTo []wire.TxOut, net *dagconfig.Params, powMaxBits uint32) (*util.Block, error) { +func CreateBlock(parentBlock *util.Block, parentBlueScore uint64, + inclusionTxs []*util.Tx, blockVersion int32, blockTime time.Time, + miningAddr util.Address, mineTo []wire.TxOut, net *dagconfig.Params, + powMaxBits uint32) (*util.Block, error) { var ( - parentHash *daghash.Hash - blockChainHeight uint64 - parentBlockTime time.Time + parentHash *daghash.Hash + blockBlueScore uint64 + parentBlockTime time.Time ) // If the parent block isn't specified, then we'll construct a block // that builds off of the genesis block for the chain. if parentBlock == nil { parentHash = net.GenesisHash - blockChainHeight = 1 parentBlockTime = net.GenesisBlock.Header.Timestamp.Add(time.Minute) } else { parentHash = parentBlock.Hash() - blockChainHeight = parentBlock.ChainHeight() + 1 parentBlockTime = parentBlock.MsgBlock().Header.Timestamp } + blockBlueScore = parentBlueScore + 1 // If a target block time was specified, then use that as the header's // timestamp. Otherwise, add one second to the parent block unless @@ -167,11 +167,11 @@ func CreateBlock(parentBlock *util.Block, inclusionTxs []*util.Tx, } extraNonce := uint64(0) - coinbaseScript, err := standardCoinbaseScript(blockChainHeight, extraNonce) + coinbaseScript, err := standardCoinbaseScript(blockBlueScore, extraNonce) if err != nil { return nil, err } - coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockChainHeight, + coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockBlueScore, miningAddr, mineTo, net) if err != nil { return nil, err diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 7d63bc5cf..b68db3d53 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -440,17 +440,14 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs( return nil, err } - selectedTipBlueScore := selectedTip.BlueScore mBlock, err := h.Node.GetBlock(selectedTipHash, nil) if err != nil { return nil, err } - parentBlock := util.NewBlock(mBlock) - parentBlock.SetChainHeight(selectedTipBlueScore) // Create a new block including the specified transactions - newBlock, err := CreateBlock(parentBlock, txns, blockVersion, + newBlock, err := CreateBlock(parentBlock, selectedTip.BlueScore, txns, blockVersion, blockTime, h.wallet.coinbaseAddr, mineTo, h.ActiveNet, h.powMaxBits) if err != nil { return nil, err diff --git a/mempool/mempool.go b/mempool/mempool.go index 5a931420a..34148634c 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -58,10 +58,6 @@ type Config struct { // associated with. DAGParams *dagconfig.Params - // DAGChainHeight defines the function to use to access the chain - // height of the DAG - DAGChainHeight func() uint64 - // MedianTimePast defines the function to use in order to access the // median time past calculated from the point-of-view of the current // selected tip. @@ -683,14 +679,13 @@ func (mp *TxPool) RemoveDoubleSpends(tx *util.Tx) { // helper for maybeAcceptTransaction. // // This function MUST be called with the mempool lock held (for writes). -func (mp *TxPool) addTransaction(tx *util.Tx, height uint64, blueScore uint64, fee uint64, parentsInPool []*wire.Outpoint) (*TxDesc, error) { +func (mp *TxPool) addTransaction(tx *util.Tx, fee uint64, parentsInPool []*wire.Outpoint) (*TxDesc, error) { // Add the transaction to the pool and mark the referenced outpoints // as spent by the pool. txD := &TxDesc{ TxDesc: mining.TxDesc{ Tx: tx, Added: time.Now(), - Height: height, Fee: fee, FeePerKB: fee * 1000 / uint64(tx.MsgTx().SerializeSize()), }, @@ -789,7 +784,7 @@ func (mp *TxPool) FetchTransaction(txID *daghash.TxID) (*util.Tx, error) { // more details. // // This function MUST be called with the mempool lock held (for writes). -func (mp *TxPool) maybeAcceptTransaction(tx *util.Tx, isNew, rejectDupOrphans bool) ([]*daghash.TxID, *TxDesc, error) { +func (mp *TxPool) maybeAcceptTransaction(tx *util.Tx, rejectDupOrphans bool) ([]*daghash.TxID, *TxDesc, error) { txID := tx.ID() // Don't accept the transaction if it already exists in the pool. This @@ -1018,8 +1013,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *util.Tx, isNew, rejectDupOrphans bo } // Add to transaction pool. - bestHeight := mp.cfg.DAGChainHeight() - txD, err := mp.addTransaction(tx, bestHeight, nextBlockBlueScore, txFee, parentsInPool) + txD, err := mp.addTransaction(tx, txFee, parentsInPool) if err != nil { return nil, nil, err } @@ -1047,7 +1041,7 @@ func (mp *TxPool) MaybeAcceptTransaction(tx *util.Tx, isNew bool) ([]*daghash.Tx defer mp.cfg.DAG.RUnlock() mp.mtx.Lock() defer mp.mtx.Unlock() - hashes, txD, err := mp.maybeAcceptTransaction(tx, isNew, true) + hashes, txD, err := mp.maybeAcceptTransaction(tx, true) return hashes, txD, err } @@ -1089,7 +1083,7 @@ func (mp *TxPool) processOrphans(acceptedTx *util.Tx) []*TxDesc { // Potentially accept an orphan into the tx pool. for _, tx := range orphans { missing, txD, err := mp.maybeAcceptTransaction( - tx, true, false) + tx, false) if err != nil { // The orphan is now invalid, so there // is no way any other orphans which @@ -1176,7 +1170,7 @@ func (mp *TxPool) ProcessTransaction(tx *util.Tx, allowOrphan bool, tag Tag) ([] defer mp.mtx.Unlock() // Potentially accept the transaction to the memory pool. - missingParents, txD, err := mp.maybeAcceptTransaction(tx, true, true) + missingParents, txD, err := mp.maybeAcceptTransaction(tx, true) if err != nil { return nil, err } @@ -1315,7 +1309,6 @@ func (mp *TxPool) RawMempoolVerbose() map[string]*rpcmodel.GetRawMempoolVerboseR Size: int32(tx.MsgTx().SerializeSize()), Fee: util.Amount(desc.Fee).ToKAS(), Time: desc.Added.Unix(), - Height: desc.Height, Depends: make([]string, 0), } for _, txIn := range tx.MsgTx().TxIn { diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 097759c6f..ea64d6850 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -349,7 +349,6 @@ func newPoolHarness(t *testing.T, dagParams *dagconfig.Params, numOutputs uint32 MaxTxVersion: 1, }, DAGParams: ¶ms, - DAGChainHeight: fDAG.BlueScore, MedianTimePast: fDAG.MedianTimePast, CalcSequenceLockNoLock: calcSequenceLock, SigCache: nil, @@ -542,8 +541,8 @@ func TestProcessTransaction(t *testing.T) { } //Checks that a coinbase transaction cannot be added to the mempool - curHeight := harness.dag.BlueScore() - coinbase, err := harness.CreateCoinbaseTx(curHeight+1, 1) + currentBlueScore := harness.dag.BlueScore() + coinbase, err := harness.CreateCoinbaseTx(currentBlueScore+1, 1) if err != nil { t.Errorf("CreateCoinbaseTx: %v", err) } @@ -638,7 +637,7 @@ func TestProcessTransaction(t *testing.T) { t.Fatalf("PayToAddrScript: unexpected error: %v", err) } p2shTx := util.NewTx(wire.NewNativeMsgTx(1, nil, []*wire.TxOut{{Value: 5000000000, ScriptPubKey: p2shScriptPubKey}})) - if isAccepted, err := harness.txPool.mpUTXOSet.AddTx(p2shTx.MsgTx(), curHeight+1); err != nil { + if isAccepted, err := harness.txPool.mpUTXOSet.AddTx(p2shTx.MsgTx(), currentBlueScore+1); err != nil { t.Fatalf("AddTx unexpectedly failed. Error: %s", err) } else if !isAccepted { t.Fatalf("AddTx unexpectedly didn't add tx %s", p2shTx.ID()) diff --git a/mining/mining.go b/mining/mining.go index 5ab43d66a..877482157 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -32,10 +32,6 @@ type TxDesc struct { // Added is the time when the entry was added to the source pool. Added time.Time - // Height is the block height when the entry was added to the the source - // pool. - Height uint64 - // Fee is the total fee the transaction associated with the entry pays. Fee uint64 diff --git a/rpcmodel/rpc_results.go b/rpcmodel/rpc_results.go index 041f79bce..09e2ddba8 100644 --- a/rpcmodel/rpc_results.go +++ b/rpcmodel/rpc_results.go @@ -12,7 +12,6 @@ import "encoding/json" type GetBlockHeaderVerboseResult struct { Hash string `json:"hash"` Confirmations uint64 `json:"confirmations"` - Height uint64 `json:"height"` Version int32 `json:"version"` VersionHex string `json:"versionHex"` HashMerkleRoot string `json:"hashMerkleRoot"` @@ -33,7 +32,6 @@ type GetBlockVerboseResult struct { Hash string `json:"hash"` Confirmations uint64 `json:"confirmations"` Size int32 `json:"size"` - Height uint64 `json:"height"` BlueScore uint64 `json:"blueScore"` IsChainBlock bool `json:"isChainBlock"` Version int32 `json:"version"` @@ -265,7 +263,6 @@ type GetRawMempoolVerboseResult struct { Size int32 `json:"size"` Fee float64 `json:"fee"` Time int64 `json:"time"` - Height uint64 `json:"height"` Depends []string `json:"depends"` } diff --git a/rpcmodel/rpc_websocket_notifications.go b/rpcmodel/rpc_websocket_notifications.go index 2b6e1a6d3..f5f3abf9b 100644 --- a/rpcmodel/rpc_websocket_notifications.go +++ b/rpcmodel/rpc_websocket_notifications.go @@ -37,16 +37,16 @@ const ( // FilteredBlockAddedNtfn defines the filteredBlockAdded JSON-RPC // notification. type FilteredBlockAddedNtfn struct { - ChainHeight uint64 + BlueScore uint64 Header string SubscribedTxs []string } // NewFilteredBlockAddedNtfn returns a new instance which can be used to // issue a filteredBlockAdded JSON-RPC notification. -func NewFilteredBlockAddedNtfn(chainHeight uint64, header string, subscribedTxs []string) *FilteredBlockAddedNtfn { +func NewFilteredBlockAddedNtfn(blueScore uint64, header string, subscribedTxs []string) *FilteredBlockAddedNtfn { return &FilteredBlockAddedNtfn{ - ChainHeight: chainHeight, + BlueScore: blueScore, Header: header, SubscribedTxs: subscribedTxs, } diff --git a/rpcmodel/rpc_websocket_notifications_test.go b/rpcmodel/rpc_websocket_notifications_test.go index eaf145e8f..dbedad3e4 100644 --- a/rpcmodel/rpc_websocket_notifications_test.go +++ b/rpcmodel/rpc_websocket_notifications_test.go @@ -35,14 +35,14 @@ func TestRPCServerWebsocketNotifications(t *testing.T) { { name: "filteredBlockAdded", newNtfn: func() (interface{}, error) { - return rpcmodel.NewCommand("filteredBlockAdded", 100000, "header", []string{"tx0", "tx1"}) + return rpcmodel.NewCommand("filteredBlockAdded", 100, "header", []string{"tx0", "tx1"}) }, staticNtfn: func() interface{} { - return rpcmodel.NewFilteredBlockAddedNtfn(100000, "header", []string{"tx0", "tx1"}) + return rpcmodel.NewFilteredBlockAddedNtfn(100, "header", []string{"tx0", "tx1"}) }, - marshalled: `{"jsonrpc":"1.0","method":"filteredBlockAdded","params":[100000,"header",["tx0","tx1"]],"id":null}`, + marshalled: `{"jsonrpc":"1.0","method":"filteredBlockAdded","params":[100,"header",["tx0","tx1"]],"id":null}`, unmarshalled: &rpcmodel.FilteredBlockAddedNtfn{ - ChainHeight: 100000, + BlueScore: 100, Header: "header", SubscribedTxs: []string{"tx0", "tx1"}, }, diff --git a/server/p2p/on_get_block_locator.go b/server/p2p/on_get_block_locator.go index fb79a2958..f2ec35cff 100644 --- a/server/p2p/on_get_block_locator.go +++ b/server/p2p/on_get_block_locator.go @@ -1,6 +1,7 @@ package p2p import ( + "fmt" "github.com/kaspanet/kaspad/peer" "github.com/kaspanet/kaspad/wire" ) @@ -8,15 +9,19 @@ import ( // OnGetBlockLocator is invoked when a peer receives a getlocator kaspa // message. func (sp *Peer) OnGetBlockLocator(_ *peer.Peer, msg *wire.MsgGetBlockLocator) { - locator := sp.server.DAG.BlockLocatorFromHashes(msg.StartHash, msg.StopHash) - - if len(locator) == 0 { - peerLog.Infof("Couldn't build a block locator between blocks %s and %s"+ - " that was requested from peer %s", - sp) + locator, err := sp.server.DAG.BlockLocatorFromHashes(msg.StartHash, msg.StopHash) + if err != nil || len(locator) == 0 { + warning := fmt.Sprintf("Couldn't build a block locator between blocks "+ + "%s and %s that was requested from peer %s", msg.StartHash, msg.StopHash, sp) + if err != nil { + warning = fmt.Sprintf("%s: %s", warning, err) + } + peerLog.Warnf(warning) + sp.Disconnect() return } - err := sp.PushBlockLocatorMsg(locator) + + err = sp.PushBlockLocatorMsg(locator) if err != nil { peerLog.Errorf("Failed to send block locator message to peer %s: %s", sp, err) diff --git a/server/p2p/p2p.go b/server/p2p/p2p.go index 61bc46ea0..786c670ee 100644 --- a/server/p2p/p2p.go +++ b/server/p2p/p2p.go @@ -1662,7 +1662,6 @@ func NewServer(listenAddrs []string, db database.DB, dagParams *dagconfig.Params MaxTxVersion: 1, }, DAGParams: dagParams, - DAGChainHeight: func() uint64 { return s.DAG.ChainHeight() }, MedianTimePast: func() time.Time { return s.DAG.CalcPastMedianTime() }, CalcSequenceLockNoLock: func(tx *util.Tx, utxoSet blockdag.UTXOSet) (*blockdag.SequenceLock, error) { return s.DAG.CalcSequenceLockNoLock(tx, utxoSet, true) diff --git a/server/rpc/common.go b/server/rpc/common.go index 0c2f68749..9e5bfe53c 100644 --- a/server/rpc/common.go +++ b/server/rpc/common.go @@ -210,23 +210,19 @@ func buildGetBlockVerboseResult(s *Server, block *util.Block, isVerboseTx bool) params := s.cfg.DAGParams blockHeader := block.MsgBlock().Header - // Get the block chain height. - blockChainHeight, err := s.cfg.DAG.BlockChainHeightByHash(hash) + blockBlueScore, err := s.cfg.DAG.BlueScoreByBlockHash(hash) if err != nil { - context := "Failed to obtain block height" + context := "Could not get block blue score" return nil, internalRPCError(err.Error(), context) } // Get the hashes for the next blocks unless there are none. - var nextHashStrings []string - if blockChainHeight < s.cfg.DAG.ChainHeight() { //TODO: (Ori) This is probably wrong. Done only for compilation - childHashes, err := s.cfg.DAG.ChildHashesByHash(hash) - if err != nil { - context := "No next block" - return nil, internalRPCError(err.Error(), context) - } - nextHashStrings = daghash.Strings(childHashes) + childHashes, err := s.cfg.DAG.ChildHashesByHash(hash) + if err != nil { + context := "No next block" + return nil, internalRPCError(err.Error(), context) } + childHashStrings := daghash.Strings(childHashes) blockConfirmations, err := s.cfg.DAG.BlockConfirmationsByHashNoLock(hash) if err != nil { @@ -234,12 +230,6 @@ func buildGetBlockVerboseResult(s *Server, block *util.Block, isVerboseTx bool) return nil, internalRPCError(err.Error(), context) } - blockBlueScore, err := s.cfg.DAG.BlueScoreByBlockHash(hash) - if err != nil { - context := "Could not get block blue score" - return nil, internalRPCError(err.Error(), context) - } - selectedParentHash, err := s.cfg.DAG.SelectedParentHash(hash) if err != nil { context := "Could not get block selected parent" @@ -264,13 +254,12 @@ func buildGetBlockVerboseResult(s *Server, block *util.Block, isVerboseTx bool) Nonce: blockHeader.Nonce, Time: blockHeader.Timestamp.Unix(), Confirmations: blockConfirmations, - Height: blockChainHeight, BlueScore: blockBlueScore, IsChainBlock: isChainBlock, Size: int32(block.MsgBlock().SerializeSize()), Bits: strconv.FormatInt(int64(blockHeader.Bits), 16), Difficulty: getDifficultyRatio(blockHeader.Bits, params), - NextHashes: nextHashStrings, + NextHashes: childHashStrings, } if isVerboseTx { diff --git a/server/rpc/handle_get_block_header.go b/server/rpc/handle_get_block_header.go index 0332a0dd2..ce61e7418 100644 --- a/server/rpc/handle_get_block_header.go +++ b/server/rpc/handle_get_block_header.go @@ -40,23 +40,13 @@ func handleGetBlockHeader(s *Server, cmd interface{}, closeChan <-chan struct{}) // The verbose flag is set, so generate the JSON object and return it. - // Get the block chain height from chain. - blockChainHeight, err := s.cfg.DAG.BlockChainHeightByHash(hash) + // Get the hashes for the next blocks unless there are none. + childHashes, err := s.cfg.DAG.ChildHashesByHash(hash) if err != nil { - context := "Failed to obtain block height" + context := "No next block" return nil, internalRPCError(err.Error(), context) } - - // Get the hashes for the next blocks unless there are none. - var nextHashStrings []string - if blockChainHeight < s.cfg.DAG.ChainHeight() { //TODO: (Ori) This is probably wrong. Done only for compilation - childHashes, err := s.cfg.DAG.ChildHashesByHash(hash) - if err != nil { - context := "No next block" - return nil, internalRPCError(err.Error(), context) - } - nextHashStrings = daghash.Strings(childHashes) - } + childHashStrings := daghash.Strings(childHashes) blockConfirmations, err := s.cfg.DAG.BlockConfirmationsByHash(hash) if err != nil { @@ -74,12 +64,11 @@ func handleGetBlockHeader(s *Server, cmd interface{}, closeChan <-chan struct{}) blockHeaderReply := rpcmodel.GetBlockHeaderVerboseResult{ Hash: c.Hash, Confirmations: blockConfirmations, - Height: blockChainHeight, Version: blockHeader.Version, VersionHex: fmt.Sprintf("%08x", blockHeader.Version), HashMerkleRoot: blockHeader.HashMerkleRoot.String(), AcceptedIDMerkleRoot: blockHeader.AcceptedIDMerkleRoot.String(), - NextHashes: nextHashStrings, + NextHashes: childHashStrings, ParentHashes: daghash.Strings(blockHeader.ParentHashes), SelectedParentHash: selectedParentHash.String(), Nonce: blockHeader.Nonce, diff --git a/server/rpc/handle_get_block_template.go b/server/rpc/handle_get_block_template.go index 85a32ee32..09026a359 100644 --- a/server/rpc/handle_get_block_template.go +++ b/server/rpc/handle_get_block_template.go @@ -106,11 +106,11 @@ func handleGetBlockTemplate(s *Server, cmd interface{}, closeChan <-chan struct{ // No point in generating templates or processing proposals before // the DAG is synced. Note that we make a special check for when - // we have nothing besides the genesis block (chainHeight == 0), + // we have nothing besides the genesis block (blueScore == 0), // because in that state IsCurrent may still return true. - currentChainHeight := s.cfg.DAG.ChainHeight() - if (currentChainHeight != 0 && !s.cfg.SyncMgr.IsCurrent()) || - (currentChainHeight == 0 && !s.cfg.CPUMiner.ShouldMineOnGenesis()) { + currentBlueScore := s.cfg.DAG.SelectedTipBlueScore() + if (currentBlueScore != 0 && !s.cfg.SyncMgr.IsCurrent()) || + (currentBlueScore == 0 && !s.cfg.CPUMiner.ShouldMineOnGenesis()) { return nil, &rpcmodel.RPCError{ Code: rpcmodel.ErrRPCClientInInitialDownload, Message: "Kaspa is downloading blocks...", diff --git a/server/rpc/rpcwebsocket.go b/server/rpc/rpcwebsocket.go index f058ce5bf..f9af308e4 100644 --- a/server/rpc/rpcwebsocket.go +++ b/server/rpc/rpcwebsocket.go @@ -665,8 +665,7 @@ func (m *wsNotificationManager) notifyFilteredBlockAdded(clients map[chan struct "added notification: %s", err) return } - ntfn := rpcmodel.NewFilteredBlockAddedNtfn(block.ChainHeight(), - hex.EncodeToString(w.Bytes()), nil) + ntfn := rpcmodel.NewFilteredBlockAddedNtfn(block.BlueScore(), hex.EncodeToString(w.Bytes()), nil) // Search for relevant transactions for each client and save them // serialized in hex encoding for the notification. diff --git a/util/block.go b/util/block.go index 055afe1ba..5f177dff4 100644 --- a/util/block.go +++ b/util/block.go @@ -8,7 +8,6 @@ import ( "bytes" "fmt" "io" - "math" "time" "github.com/kaspanet/kaspad/util/daghash" @@ -20,10 +19,6 @@ import ( type OutOfRangeError string const ( - // BlockHeightUnknown is the value returned for a block height that is unknown. - // This is typically because the block has not been inserted into the DAG yet. - BlockHeightUnknown = math.MaxUint64 - // CoinbaseTransactionIndex is the index of the coinbase transaction in every block CoinbaseTransactionIndex = 0 ) @@ -41,9 +36,9 @@ type Block struct { msgBlock *wire.MsgBlock // Underlying MsgBlock serializedBlock []byte // Serialized bytes for the block blockHash *daghash.Hash // Cached block hash - chainHeight uint64 // Selected-chain height transactions []*Tx // Transactions txnsGenerated bool // ALL wrapped transactions generated + blueScore uint64 // Blue score } // MsgBlock returns the underlying wire.MsgBlock for the Block. @@ -189,17 +184,6 @@ func (b *Block) TxLoc() ([]wire.TxLoc, error) { return txLocs, err } -// ChainHeight returns the saved chan height of the block . This value -// will be BlockHeightUnknown if it hasn't already explicitly been set. -func (b *Block) ChainHeight() uint64 { - return b.chainHeight -} - -// SetChainHeight sets the chain height of the block. -func (b *Block) SetChainHeight(chainHeight uint64) { - b.chainHeight = chainHeight -} - // IsGenesis returns whether or not this block is the genesis block. func (b *Block) IsGenesis() bool { return b.MsgBlock().Header.IsGenesis() @@ -215,12 +199,21 @@ func (b *Block) Timestamp() time.Time { return b.msgBlock.Header.Timestamp } +// BlueScore returns this block's blue score. +func (b *Block) BlueScore() uint64 { + return b.blueScore +} + +// SetBlueScore sets the blue score of the block. +func (b *Block) SetBlueScore(blueScore uint64) { + b.blueScore = blueScore +} + // NewBlock returns a new instance of a kaspa block given an underlying // wire.MsgBlock. See Block. func NewBlock(msgBlock *wire.MsgBlock) *Block { return &Block{ - msgBlock: msgBlock, - chainHeight: BlockHeightUnknown, + msgBlock: msgBlock, } } diff --git a/util/block_test.go b/util/block_test.go index 96f22394c..f91f4738b 100644 --- a/util/block_test.go +++ b/util/block_test.go @@ -29,14 +29,6 @@ func TestBlock(t *testing.T) { spew.Sdump(msgBlock), spew.Sdump(&Block100000)) } - // Ensure block chain height set and get work properly. - wantChainHeight := uint64(100000) - b.SetChainHeight(wantChainHeight) - if gotChainHeight := b.ChainHeight(); gotChainHeight != wantChainHeight { - t.Errorf("ChainHeight: mismatched chain height - got %v, want %v", - gotChainHeight, wantChainHeight) - } - // Hash for block 100,000. wantHashStr := "839a8e072e6d402128f6f9a32ffc012e471e071e8ef8405552b1e58ef7b681f0" wantHash, err := daghash.NewHashFromStr(wantHashStr)