mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
[DEV-169] add to BlockDAG TipHashes() and HighestTipHash() and remove Tiphashes() and SelectedTipHash from VirtualBlock (#82)
* [DEV-169] add to BlockDAG TipHashes() and HighestTipHash() and remove Tiphashes() and SelectedTipHash from VirtualBlock * [DEV-169] move highest node logic to separate method of blockset
This commit is contained in:
parent
2f3e0a609c
commit
3c88184b38
@ -35,6 +35,16 @@ func (bs blockSet) maxHeight() int32 {
|
||||
return maxHeight
|
||||
}
|
||||
|
||||
func (bs blockSet) highest() *blockNode {
|
||||
var highest *blockNode
|
||||
for _, node := range bs {
|
||||
if highest.height < node.height || daghash.Less(&highest.hash, &node.hash) {
|
||||
highest = node
|
||||
}
|
||||
}
|
||||
return highest
|
||||
}
|
||||
|
||||
// add adds a block to this BlockSet
|
||||
func (bs blockSet) add(block *blockNode) {
|
||||
bs[block.hash] = block
|
||||
|
@ -516,7 +516,7 @@ func (dag *BlockDAG) connectBlock(node *blockNode, block *util.Block) error {
|
||||
// Atomically insert info into the database.
|
||||
err = dag.db.Update(func(dbTx database.Tx) error {
|
||||
// Update best block state.
|
||||
err := dbPutDAGTipHashes(dbTx, dag.virtual.TipHashes())
|
||||
err := dbPutDAGTipHashes(dbTx, dag.TipHashes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -930,6 +930,17 @@ func (dag *BlockDAG) Height() int32 {
|
||||
return dag.virtual.tips().maxHeight()
|
||||
}
|
||||
|
||||
// TipHashes returns the hashes of the DAG's tips
|
||||
func (dag *BlockDAG) TipHashes() []daghash.Hash {
|
||||
return dag.virtual.tips().hashes()
|
||||
}
|
||||
|
||||
// HighestTipHash returns the hash of the highest tip.
|
||||
// This function is a placeholder for places that aren't DAG-compatible, and it's needed to be removed in the future
|
||||
func (dag *BlockDAG) HighestTipHash() daghash.Hash {
|
||||
return dag.virtual.tips().highest().hash
|
||||
}
|
||||
|
||||
// HeaderByHash returns the block header identified by the given hash or an
|
||||
// error if it doesn't exist.
|
||||
func (dag *BlockDAG) HeaderByHash(hash *daghash.Hash) (wire.BlockHeader, error) {
|
||||
|
@ -811,7 +811,7 @@ func (dag *BlockDAG) createDAGState() error {
|
||||
}
|
||||
|
||||
// Store the current DAG tip hashes into the database.
|
||||
err = dbPutDAGTipHashes(dbTx, dag.virtual.TipHashes())
|
||||
err = dbPutDAGTipHashes(dbTx, dag.TipHashes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -272,14 +272,13 @@ func TestFullBlocks(t *testing.T) {
|
||||
item.Name, block.Hash(), blockHeight)
|
||||
|
||||
// Ensure hash and height match.
|
||||
virtualBlock := dag.VirtualBlock()
|
||||
if virtualBlock.SelectedTipHash() != item.Block.BlockHash() ||
|
||||
dag.Height() != blockHeight { //TODO: (Ori) the use of dag.Height() and virtualBlock.SelectedTipHash() is wrong, and was done only for compilation
|
||||
if dag.HighestTipHash() != item.Block.BlockHash() ||
|
||||
dag.Height() != blockHeight { //TODO: (Ori) the use of dag.Height() and virtualBlock.HighestTipHash() is wrong, and was done only for compilation
|
||||
|
||||
t.Fatalf("block %q (hash %s, height %d) should be "+
|
||||
"the current tip -- got (hash %s, height %d)",
|
||||
item.Name, block.Hash(), blockHeight, virtualBlock.SelectedTipHash(),
|
||||
dag.Height()) //TODO: (Ori) the use of dag.Height() and virtualBlock.SelectedTipHash() is wrong, and was done only for compilation
|
||||
item.Name, block.Hash(), blockHeight, dag.HighestTipHash(),
|
||||
dag.Height()) //TODO: (Ori) the use of dag.Height() and virtualBlock.HighestTipHash() is wrong, and was done only for compilation
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ package blockdag
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/daglabs/btcd/dagconfig/daghash"
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
@ -101,16 +100,6 @@ func (v *VirtualBlock) SelectedTip() *blockNode {
|
||||
return v.selectedParent
|
||||
}
|
||||
|
||||
// TipHashes returns the hashes of the tips of the virtual block.
|
||||
func (v *VirtualBlock) TipHashes() []daghash.Hash {
|
||||
return v.tips().hashes()
|
||||
}
|
||||
|
||||
// SelectedTipHash returns the hash of the selected tip of the virtual block.
|
||||
func (v *VirtualBlock) SelectedTipHash() daghash.Hash {
|
||||
return v.SelectedTip().hash
|
||||
}
|
||||
|
||||
// GetUTXOEntry returns the requested unspent transaction output. The returned
|
||||
// instance must be treated as immutable since it is shared by all callers.
|
||||
//
|
||||
|
@ -38,9 +38,9 @@ func loadBlockDB() (database.DB, error) {
|
||||
// returns a slice of found candidates, if any. It also stops searching for
|
||||
// candidates at the last checkpoint that is already hard coded since there
|
||||
// is no point in finding candidates before already existing checkpoints.
|
||||
func findCandidates(dag *blockdag.BlockDAG, selectedTipHash *daghash.Hash) ([]*dagconfig.Checkpoint, error) {
|
||||
func findCandidates(dag *blockdag.BlockDAG, highestTipHash *daghash.Hash) ([]*dagconfig.Checkpoint, error) {
|
||||
// Start with the selected tip.
|
||||
block, err := dag.BlockByHash(selectedTipHash)
|
||||
block, err := dag.BlockByHash(highestTipHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -162,12 +162,11 @@ func main() {
|
||||
|
||||
// Get the latest block hash and height from the database and report
|
||||
// status.
|
||||
virtualBlock := dag.VirtualBlock()
|
||||
fmt.Printf("Block database loaded with block height %d\n", dag.Height())
|
||||
|
||||
// Find checkpoint candidates.
|
||||
selectedTipHash := virtualBlock.SelectedTipHash()
|
||||
candidates, err := findCandidates(dag, &selectedTipHash)
|
||||
highestTipHash := dag.HighestTipHash()
|
||||
candidates, err := findCandidates(dag, &highestTipHash)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Unable to identify candidates:", err)
|
||||
return
|
||||
|
@ -162,7 +162,7 @@ func (m *CPUMiner) submitBlock(block *util.Block) bool {
|
||||
// a new block, but the check only happens periodically, so it is
|
||||
// possible a block was found and submitted in between.
|
||||
msgBlock := block.MsgBlock()
|
||||
if !daghash.AreEqual(msgBlock.Header.PrevBlocks, m.g.VirtualBlock().TipHashes()) {
|
||||
if !daghash.AreEqual(msgBlock.Header.PrevBlocks, m.g.TipHashes()) {
|
||||
log.Debugf("Block submitted via CPU miner with previous "+
|
||||
"blocks %s is stale", msgBlock.Header.PrevBlocks)
|
||||
return false
|
||||
@ -247,8 +247,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32,
|
||||
hashesCompleted = 0
|
||||
|
||||
// The current block is stale if the DAG has changed.
|
||||
virtualBlock := m.g.VirtualBlock()
|
||||
if !daghash.AreEqual(header.PrevBlocks, virtualBlock.TipHashes()) {
|
||||
if !daghash.AreEqual(header.PrevBlocks, m.g.TipHashes()) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -717,8 +717,8 @@ mempoolLoop:
|
||||
var msgBlock wire.MsgBlock
|
||||
msgBlock.Header = wire.BlockHeader{
|
||||
Version: nextBlockVersion,
|
||||
NumPrevBlocks: byte(len(virtualBlock.TipHashes())),
|
||||
PrevBlocks: virtualBlock.TipHashes(),
|
||||
NumPrevBlocks: byte(len(g.dag.TipHashes())),
|
||||
PrevBlocks: g.dag.TipHashes(),
|
||||
MerkleRoot: *merkles[len(merkles)-1],
|
||||
Timestamp: ts,
|
||||
Bits: reqDifficulty,
|
||||
@ -820,6 +820,11 @@ func (g *BlkTmplGenerator) DAGHeight() int32 {
|
||||
return g.dag.Height()
|
||||
}
|
||||
|
||||
// TipHashes returns the hashes of the DAG's tips
|
||||
func (g *BlkTmplGenerator) TipHashes() []daghash.Hash {
|
||||
return g.dag.TipHashes()
|
||||
}
|
||||
|
||||
// TxSource returns the associated transaction source.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
|
@ -392,9 +392,8 @@ func (sm *SyncManager) handleDonePeerMsg(peer *peerpkg.Peer) {
|
||||
if sm.syncPeer == peer {
|
||||
sm.syncPeer = nil
|
||||
if sm.headersFirstMode {
|
||||
virtualBlock := sm.dag.VirtualBlock()
|
||||
selectedTipHash := virtualBlock.SelectedTipHash()
|
||||
sm.resetHeaderState(&selectedTipHash, sm.dag.Height()) //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
highestTipHash := sm.dag.HighestTipHash()
|
||||
sm.resetHeaderState(&highestTipHash, sm.dag.Height()) //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
}
|
||||
sm.startSync()
|
||||
}
|
||||
@ -616,10 +615,9 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) {
|
||||
|
||||
// Update this peer's latest block height, for future
|
||||
// potential sync node candidacy.
|
||||
virtualBlock := sm.dag.VirtualBlock()
|
||||
selectedTipHash := virtualBlock.SelectedTipHash()
|
||||
highestTipHash := sm.dag.HighestTipHash()
|
||||
heightUpdate = sm.dag.Height() //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
blkHashUpdate = &selectedTipHash
|
||||
blkHashUpdate = &highestTipHash
|
||||
|
||||
// Clear the rejected transactions.
|
||||
sm.rejectedTxns = make(map[daghash.Hash]struct{})
|
||||
@ -1389,13 +1387,12 @@ func New(config *Config) (*SyncManager, error) {
|
||||
feeEstimator: config.FeeEstimator,
|
||||
}
|
||||
|
||||
virtualBlock := sm.dag.VirtualBlock()
|
||||
selectedTipHash := virtualBlock.SelectedTipHash()
|
||||
highestTipHash := sm.dag.HighestTipHash()
|
||||
if !config.DisableCheckpoints {
|
||||
// Initialize the next checkpoint based on the current height.
|
||||
sm.nextCheckpoint = sm.findNextHeaderCheckpoint(sm.dag.Height()) //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
if sm.nextCheckpoint != nil {
|
||||
sm.resetHeaderState(&selectedTipHash, sm.dag.Height()) //TODO: (Ori) This is probably wrong. Done only for compilation)
|
||||
sm.resetHeaderState(&highestTipHash, sm.dag.Height()) //TODO: (Ori) This is probably wrong. Done only for compilation)
|
||||
}
|
||||
} else {
|
||||
log.Info("Checkpoints are disabled")
|
||||
|
@ -290,9 +290,8 @@ func newServerPeer(s *Server, isPersistent bool) *Peer {
|
||||
// newestBlock returns the current best block hash and height using the format
|
||||
// required by the configuration for the peer package.
|
||||
func (sp *Peer) newestBlock() (*daghash.Hash, int32, error) {
|
||||
virtualBlock := sp.server.DAG.VirtualBlock()
|
||||
selectedTipHash := virtualBlock.SelectedTipHash()
|
||||
return &selectedTipHash, sp.server.DAG.Height(), nil //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
highestTipHash := sp.server.DAG.HighestTipHash()
|
||||
return &highestTipHash, sp.server.DAG.Height(), nil //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
}
|
||||
|
||||
// addKnownAddresses adds the given addresses to the set of known addresses to
|
||||
@ -1308,9 +1307,9 @@ func (s *Server) pushBlockMsg(sp *Peer, hash *daghash.Hash, doneChan chan<- stru
|
||||
// to trigger it to issue another getblocks message for the next
|
||||
// batch of inventory.
|
||||
if sendInv {
|
||||
selectedTipHash := sp.server.DAG.VirtualBlock().SelectedTipHash()
|
||||
highestTipHash := sp.server.DAG.HighestTipHash()
|
||||
invMsg := wire.NewMsgInvSizeHint(1)
|
||||
iv := wire.NewInvVect(wire.InvTypeBlock, &selectedTipHash)
|
||||
iv := wire.NewInvVect(wire.InvTypeBlock, &highestTipHash)
|
||||
invMsg.AddInvVect(iv)
|
||||
sp.QueueMessage(invMsg, doneChan)
|
||||
sp.continueHash = nil
|
||||
|
@ -1008,9 +1008,8 @@ func handleGetBestBlock(s *Server, cmd interface{}, closeChan <-chan struct{}) (
|
||||
// All other "get block" commands give either the height, the
|
||||
// hash, or both but require the block SHA. This gets both for
|
||||
// the best block.
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
result := &btcjson.GetBestBlockResult{
|
||||
Hash: virtualBlock.SelectedTipHash().String(),
|
||||
Hash: s.cfg.DAG.HighestTipHash().String(),
|
||||
Height: s.cfg.DAG.Height(), //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
}
|
||||
return result, nil
|
||||
@ -1018,8 +1017,7 @@ func handleGetBestBlock(s *Server, cmd interface{}, closeChan <-chan struct{}) (
|
||||
|
||||
// handleGetBestBlockHash implements the getbestblockhash command.
|
||||
func handleGetBestBlockHash(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
return virtualBlock.SelectedTipHash().String(), nil
|
||||
return s.cfg.DAG.HighestTipHash().String(), nil
|
||||
}
|
||||
|
||||
// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the
|
||||
@ -1173,7 +1171,7 @@ func handleGetBlockDAGInfo(s *Server, cmd interface{}, closeChan <-chan struct{}
|
||||
DAG: params.Name,
|
||||
Blocks: dag.Height(), //TODO: (Ori) This is wrong. Done only for compilation
|
||||
Headers: dag.Height(), //TODO: (Ori) This is wrong. Done only for compilation
|
||||
TipHashes: daghash.Strings(virtualBlock.TipHashes()),
|
||||
TipHashes: daghash.Strings(dag.TipHashes()),
|
||||
Difficulty: getDifficultyRatio(virtualBlock.SelectedTip().Header().Bits, params),
|
||||
MedianTime: virtualBlock.SelectedTip().CalcPastMedianTime().Unix(),
|
||||
Pruned: false,
|
||||
@ -1490,7 +1488,7 @@ func (state *gbtWorkState) updateBlockTemplate(s *Server, useCoinbaseValue bool)
|
||||
var msgBlock *wire.MsgBlock
|
||||
var targetDifficulty string
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
tipHashes := virtualBlock.TipHashes()
|
||||
tipHashes := s.cfg.DAG.TipHashes()
|
||||
template := state.template
|
||||
if template == nil || state.tipHashes == nil ||
|
||||
!daghash.AreEqual(state.tipHashes, tipHashes) ||
|
||||
@ -2050,7 +2048,7 @@ func handleGetBlockTemplateProposal(s *Server, request *btcjson.TemplateRequest)
|
||||
block := util.NewBlock(&msgBlock)
|
||||
|
||||
// Ensure the block is building from the expected previous blocks.
|
||||
expectedPrevHashes := s.cfg.DAG.VirtualBlock().TipHashes()
|
||||
expectedPrevHashes := s.cfg.DAG.TipHashes()
|
||||
prevHashes := block.MsgBlock().Header.PrevBlocks
|
||||
if !daghash.AreEqual(expectedPrevHashes, prevHashes) {
|
||||
return "bad-prevblk", nil
|
||||
@ -2283,8 +2281,8 @@ func handleGetMiningInfo(s *Server, cmd interface{}, closeChan <-chan struct{})
|
||||
}
|
||||
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
selectedTipHash := virtualBlock.SelectedTipHash()
|
||||
selectedBlock, err := s.cfg.DAG.BlockByHash(&selectedTipHash)
|
||||
highestTipHash := s.cfg.DAG.HighestTipHash()
|
||||
selectedBlock, err := s.cfg.DAG.BlockByHash(&highestTipHash)
|
||||
if err != nil {
|
||||
return nil, &btcjson.RPCError{
|
||||
Code: btcjson.ErrRPCInternal.Code,
|
||||
@ -2548,8 +2546,7 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
return nil, internalRPCError(errStr, "")
|
||||
}
|
||||
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
bestBlockHash = virtualBlock.SelectedTipHash().String()
|
||||
bestBlockHash = s.cfg.DAG.HighestTipHash().String()
|
||||
confirmations = 0
|
||||
value = txOut.Value
|
||||
pkScript = txOut.PkScript
|
||||
@ -2570,8 +2567,7 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
bestBlockHash = virtualBlock.SelectedTipHash().String()
|
||||
bestBlockHash = s.cfg.DAG.HighestTipHash().String()
|
||||
confirmations = 1 + s.cfg.DAG.Height() - entry.BlockHeight() //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
value = entry.Amount()
|
||||
pkScript = entry.PkScript()
|
||||
@ -3322,7 +3318,6 @@ func handleValidateAddress(s *Server, cmd interface{}, closeChan <-chan struct{}
|
||||
}
|
||||
|
||||
func verifyDAG(s *Server, level, depth int32) error {
|
||||
virtualBlock := s.cfg.DAG.VirtualBlock()
|
||||
finishHeight := s.cfg.DAG.Height() - depth //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
if finishHeight < 0 {
|
||||
finishHeight = 0
|
||||
@ -3330,7 +3325,7 @@ func verifyDAG(s *Server, level, depth int32) error {
|
||||
log.Infof("Verifying chain for %d blocks at level %d",
|
||||
s.cfg.DAG.Height()-finishHeight, level) //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
|
||||
currentHash := virtualBlock.SelectedTipHash()
|
||||
currentHash := s.cfg.DAG.HighestTipHash()
|
||||
for height := s.cfg.DAG.Height(); height > finishHeight; { //TODO: (Ori) This is probably wrong. Done only for compilation
|
||||
// Level 0 just looks up the block.
|
||||
block, err := s.cfg.DAG.BlockByHash(¤tHash)
|
||||
|
Loading…
x
Reference in New Issue
Block a user