diff --git a/blockdag/chain.go b/blockdag/chain.go index a47b26a0a..69c36bf5a 100644 --- a/blockdag/chain.go +++ b/blockdag/chain.go @@ -69,7 +69,7 @@ type BestState struct { // newBestState returns a new best stats instance for the given parameters. func newBestState(node *blockNode, blockSize, numTxns, - totalTxns uint64, medianTime time.Time) *BestState { +totalTxns uint64, medianTime time.Time) *BestState { return &BestState{ Hash: node.hash, @@ -348,7 +348,7 @@ func (b *BlockChain) CalcSequenceLock(tx *btcutil.Tx, utxoView *UtxoViewpoint, m b.chainLock.Lock() defer b.chainLock.Unlock() - return b.calcSequenceLock(b.bestChain.Tips()[0], tx, utxoView, mempool) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + return b.calcSequenceLock(b.bestChain.SelectedTip(), tx, utxoView, mempool) } // calcSequenceLock computes the relative lock-times for the passed @@ -536,7 +536,7 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List // Start from the end of the main chain and work backwards until the // common ancestor adding each block to the list of nodes to detach from // the main chain. - for n := b.bestChain.Tips()[0]; n != nil && n != forkNode; n = n.selectedParent { + for n := b.bestChain.SelectedTip(); n != nil && n != forkNode; n = n.selectedParent { detachNodes.PushBack(n) } @@ -557,7 +557,7 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint, stxos []spentTxOut) error { // Make sure it's extending the end of the best chain. prevHash := block.MsgBlock().Header.SelectedPrevBlock() - if !prevHash.IsEqual(&b.bestChain.Tips()[0].hash) { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if !prevHash.IsEqual(&b.bestChain.SelectedTip().hash) { return AssertError("connectBlock must be called with a block " + "that extends the main chain") } @@ -678,7 +678,7 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error { // Make sure the node being disconnected is the end of the best chain. - if !node.hash.IsEqual(&b.bestChain.Tips()[0].hash) { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if !node.hash.IsEqual(&b.bestChain.SelectedTip().hash) { return AssertError("disconnectBlock must be called with the " + "block at the end of the main chain") } @@ -819,7 +819,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // database and using that information to unspend all of the spent txos // and remove the utxos created by the blocks. view := NewUtxoViewpoint() - view.SetBestHash(&b.bestChain.Tips()[0].hash) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + view.SetBestHash(&b.bestChain.SelectedTip().hash) for e := detachNodes.Front(); e != nil; e = e.Next() { n := e.Value.(*blockNode) var block *btcutil.Block @@ -940,7 +940,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // view to be valid from the viewpoint of each block being connected or // disconnected. view = NewUtxoViewpoint() - view.SetBestHash(&b.bestChain.Tips()[0].hash) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + view.SetBestHash(&b.bestChain.SelectedTip().hash) // Disconnect blocks from the main chain. for i, e := 0, detachNodes.Front(); e != nil; i, e = i+1, e.Next() { @@ -1030,7 +1030,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // We are extending the main (best) chain with a new block. This is the // most common case. parentHash := block.MsgBlock().Header.SelectedPrevBlock() - if parentHash.IsEqual(&b.bestChain.Tips()[0].hash) { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if parentHash.IsEqual(&b.bestChain.SelectedTip().hash) { // Skip checks if node has already been fully validated. fastAdd = fastAdd || b.index.NodeStatus(node).KnownValid() @@ -1094,7 +1094,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // We're extending (or creating) a side chain, but the cumulative // work for this new side chain is not enough to make it the new chain. - if node.workSum.Cmp(b.bestChain.Tips()[0].workSum) <= 0 { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if node.workSum.Cmp(b.bestChain.SelectedTip().workSum) <= 0 { // Log information about how the block is forking the chain. fork := b.bestChain.FindFork(node) if fork.hash.IsEqual(parentHash) { @@ -1145,7 +1145,7 @@ func (b *BlockChain) isCurrent() bool { // Not current if the latest main (best) chain height is before the // latest known good checkpoint (when checkpoints are enabled). checkpoint := b.LatestCheckpoint() - if checkpoint != nil && b.bestChain.Tips()[0].height < checkpoint.Height { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if checkpoint != nil && b.bestChain.SelectedTip().height < checkpoint.Height { return false } @@ -1155,7 +1155,7 @@ func (b *BlockChain) isCurrent() bool { // The chain appears to be current if none of the checks reported // otherwise. minus24Hours := b.timeSource.AdjustedTime().Add(-24 * time.Hour).Unix() - return b.bestChain.Tips()[0].timestamp >= minus24Hours // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + return b.bestChain.SelectedTip().timestamp >= minus24Hours } // IsCurrent returns whether or not the chain believes it is current. Several @@ -1449,7 +1449,7 @@ func (b *BlockChain) locateInventory(locator BlockLocator, hashStop *daghash.Has } // Calculate how many entries are needed. - total := uint32((b.bestChain.Tips()[0].height - startNode.height) + 1) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + total := uint32((b.bestChain.SelectedTip().height - startNode.height) + 1) if stopNode != nil && b.bestChain.Contains(stopNode) && stopNode.height >= startNode.height { @@ -1706,7 +1706,7 @@ func New(config *Config) (*BlockChain, error) { return nil, err } - bestNode := b.bestChain.Tips()[0] // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + bestNode := b.bestChain.SelectedTip() log.Infof("Chain state (height %d, hash %v, totaltx %d, work %v)", bestNode.height, bestNode.hash, b.stateSnapshot.TotalTxns, bestNode.workSum) diff --git a/blockdag/chain_test.go b/blockdag/chain_test.go index ebda9fa18..0874379ff 100644 --- a/blockdag/chain_test.go +++ b/blockdag/chain_test.go @@ -126,7 +126,7 @@ func TestCalcSequenceLock(t *testing.T) { // Generate enough synthetic blocks to activate CSV. chain := newFakeChain(netParams) - node := chain.bestChain.Tips()[0] // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + node := chain.bestChain.SelectedTip() blockTime := node.Header().Timestamp numBlocksToActivate := (netParams.MinerConfirmationWindow * 3) for i := uint32(0); i < numBlocksToActivate; i++ { diff --git a/blockdag/chainview.go b/blockdag/chainview.go index 855f4d9f5..1c7db669d 100644 --- a/blockdag/chainview.go +++ b/blockdag/chainview.go @@ -103,6 +103,14 @@ func (c *chainView) Tips() []*blockNode { return []*blockNode{tip} // TODO: (Stas) This is wrong. Modified only to satisfy compilation. } +// SelecedTip returns the current selected tip block node for the chain view. +// It will return nil if there is no tip. +// +// This function is safe for concurrent access. +func (view *chainView) SelectedTip() *blockNode { + return view.Tips()[0] +} + // setTip sets the chain view to use the provided block node as the current tip // and ensures the view is consistent by populating it with the nodes obtained // by walking backwards all the way to genesis block as necessary. Further diff --git a/blockdag/chainview_test.go b/blockdag/chainview_test.go index 3c822eddd..a8bacae00 100644 --- a/blockdag/chainview_test.go +++ b/blockdag/chainview_test.go @@ -185,12 +185,12 @@ testLoop: } // Ensure the active and side chain tips are the expected nodes. - if test.view.Tips()[0] != test.tip { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if test.view.SelectedTip() != test.tip { t.Errorf("%s: unexpected active view tip -- got %v, "+ "want %v", test.name, test.view.Tips(), test.tip) continue } - if test.side.Tips()[0] != test.sideTip { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if test.side.SelectedTip() != test.sideTip { t.Errorf("%s: unexpected active view tip -- got %v, "+ "want %v", test.name, test.side.Tips(), test.sideTip) @@ -199,14 +199,14 @@ testLoop: // Ensure that regardless of the order the two chains are // compared they both return the expected fork point. - forkNode := test.view.FindFork(test.side.Tips()[0]) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + forkNode := test.view.FindFork(test.side.SelectedTip()) if forkNode != test.fork { t.Errorf("%s: unexpected fork node (view, side) -- "+ "got %v, want %v", test.name, forkNode, test.fork) continue } - forkNode = test.side.FindFork(test.view.Tips()[0]) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + forkNode = test.side.FindFork(test.view.SelectedTip()) if forkNode != test.fork { t.Errorf("%s: unexpected fork node (side, view) -- "+ "got %v, want %v", test.name, forkNode, @@ -216,8 +216,8 @@ testLoop: // Ensure that the fork point for a node that is already part // of the chain view is the node itself. - forkNode = test.view.FindFork(test.view.Tips()[0]) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. - if forkNode != test.view.Tips()[0] { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + forkNode = test.view.FindFork(test.view.SelectedTip()) + if forkNode != test.view.SelectedTip() { t.Errorf("%s: unexpected fork node (view, tip) -- "+ "got %v, want %v", test.name, forkNode, test.view.Tips()) @@ -394,7 +394,7 @@ testLoop: for i, tip := range test.tips { // Ensure the view tip is the expected node. test.view.SetTip(tip) - if test.view.Tips()[0] != tip { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if test.view.SelectedTip() != tip { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. t.Errorf("%s: unexpected view tip -- got %v, "+ "want %v", test.name, test.view.Tips(), tip) diff --git a/blockdag/checkpoints.go b/blockdag/checkpoints.go index a478c443f..ade205c38 100644 --- a/blockdag/checkpoints.go +++ b/blockdag/checkpoints.go @@ -130,7 +130,7 @@ func (b *BlockChain) findPreviousCheckpoint() (*blockNode, error) { // When there is a next checkpoint and the height of the current best // chain does not exceed it, the current checkpoint lockin is still // the latest known checkpoint. - if b.bestChain.Tips()[0].height < b.nextCheckpoint.Height { // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + if b.bestChain.SelectedTip().height < b.nextCheckpoint.Height { return b.checkpointNode, nil } @@ -218,7 +218,7 @@ func (b *BlockChain) IsCheckpointCandidate(block *btcutil.Block) (bool, error) { // A checkpoint must be at least CheckpointConfirmations blocks // before the end of the main chain. - mainChainHeight := b.bestChain.Tips()[0].height // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + mainChainHeight := b.bestChain.SelectedTip().height if node.height > (mainChainHeight - CheckpointConfirmations) { return false, nil } diff --git a/blockdag/difficulty.go b/blockdag/difficulty.go index dbb483d22..33d27b1fd 100644 --- a/blockdag/difficulty.go +++ b/blockdag/difficulty.go @@ -306,7 +306,7 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim // This function is safe for concurrent access. func (b *BlockChain) CalcNextRequiredDifficulty(timestamp time.Time) (uint32, error) { b.chainLock.Lock() - difficulty, err := b.calcNextRequiredDifficulty(b.bestChain.Tips()[0], timestamp) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + difficulty, err := b.calcNextRequiredDifficulty(b.bestChain.SelectedTip(), timestamp) b.chainLock.Unlock() return difficulty, err } diff --git a/blockdag/thresholdstate.go b/blockdag/thresholdstate.go index 605b5adb3..861788ab9 100644 --- a/blockdag/thresholdstate.go +++ b/blockdag/thresholdstate.go @@ -265,7 +265,7 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit // This function is safe for concurrent access. func (b *BlockChain) ThresholdState(deploymentID uint32) (ThresholdState, error) { b.chainLock.Lock() - state, err := b.deploymentState(b.bestChain.Tips()[0], deploymentID) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + state, err := b.deploymentState(b.bestChain.SelectedTip(), deploymentID) b.chainLock.Unlock() return state, err @@ -277,7 +277,7 @@ func (b *BlockChain) ThresholdState(deploymentID uint32) (ThresholdState, error) // This function is safe for concurrent access. func (b *BlockChain) IsDeploymentActive(deploymentID uint32) (bool, error) { b.chainLock.Lock() - state, err := b.deploymentState(b.bestChain.Tips()[0], deploymentID) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + state, err := b.deploymentState(b.bestChain.SelectedTip(), deploymentID) b.chainLock.Unlock() if err != nil { return false, err @@ -316,7 +316,7 @@ func (b *BlockChain) initThresholdCaches() error { // threshold state for each of them. This will ensure the caches are // populated and any states that needed to be recalculated due to // definition changes is done now. - prevNode := b.bestChain.Tips()[0].selectedParent // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + prevNode := b.bestChain.SelectedTip().selectedParent for bit := uint32(0); bit < vbNumBits; bit++ { checker := bitConditionChecker{bit: bit, chain: b} cache := &b.warningCaches[bit] @@ -340,7 +340,7 @@ func (b *BlockChain) initThresholdCaches() error { if b.isCurrent() { // Warn if a high enough percentage of the last blocks have // unexpected versions. - bestNode := b.bestChain.Tips()[0] // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + bestNode := b.bestChain.SelectedTip() if err := b.warnUnknownVersions(bestNode); err != nil { return err } diff --git a/blockdag/validate.go b/blockdag/validate.go index 8c0bc993e..ba70b5a8d 100644 --- a/blockdag/validate.go +++ b/blockdag/validate.go @@ -1210,7 +1210,7 @@ func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error { // This only checks whether the block can be connected to the tip of the // current chain. - tip := b.bestChain.Tips()[0] // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + tip := b.bestChain.SelectedTip() header := block.MsgBlock().Header if tip.hash != *header.SelectedPrevBlock() { str := fmt.Sprintf("previous block must be the current chain tip %v, "+ diff --git a/blockdag/versionbits.go b/blockdag/versionbits.go index bab9f593c..f6dfa534b 100644 --- a/blockdag/versionbits.go +++ b/blockdag/versionbits.go @@ -224,7 +224,7 @@ func (b *BlockChain) calcNextBlockVersion(prevNode *blockNode) (int32, error) { // This function is safe for concurrent access. func (b *BlockChain) CalcNextBlockVersion() (int32, error) { b.chainLock.Lock() - version, err := b.calcNextBlockVersion(b.bestChain.Tips()[0]) // TODO: (Stas) This is wrong. Modified only to satisfy compilation. + version, err := b.calcNextBlockVersion(b.bestChain.SelectedTip()) b.chainLock.Unlock() return version, err }