diff --git a/domain/consensus/database/serialization/block_ghostdag_data.go b/domain/consensus/database/serialization/block_ghostdag_data.go index 29f9df9d6..f6afc6e29 100644 --- a/domain/consensus/database/serialization/block_ghostdag_data.go +++ b/domain/consensus/database/serialization/block_ghostdag_data.go @@ -3,12 +3,11 @@ package serialization import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager" "math/big" ) // BlockGHOSTDAGDataToDBBlockGHOSTDAGData converts BlockGHOSTDAGData to DbBlockGhostdagData -func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData model.BlockGHOSTDAGData) *DbBlockGhostdagData { +func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData *model.BlockGHOSTDAGData) *DbBlockGhostdagData { var selectedParent *DbHash if blockGHOSTDAGData.SelectedParent() != nil { selectedParent = DomainHashToDbHash(blockGHOSTDAGData.SelectedParent()) @@ -25,7 +24,7 @@ func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData model.BlockGHOSTDA } // DBBlockGHOSTDAGDataToBlockGHOSTDAGData converts DbBlockGhostdagData to BlockGHOSTDAGData -func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdagData) (model.BlockGHOSTDAGData, error) { +func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdagData) (*model.BlockGHOSTDAGData, error) { var selectedParent *externalapi.DomainHash if dbBlockGHOSTDAGData.SelectedParent != nil { var err error @@ -50,7 +49,7 @@ func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdag return nil, err } - return ghostdagmanager.NewBlockGHOSTDAGData( + return model.NewBlockGHOSTDAGData( dbBlockGHOSTDAGData.BlueScore, new(big.Int).SetBytes(dbBlockGHOSTDAGData.BlueWork), selectedParent, diff --git a/domain/consensus/datastructures/ghostdagdatastore/ghostdagdatastore.go b/domain/consensus/datastructures/ghostdagdatastore/ghostdagdatastore.go index c8b1a7c01..8c61ba06d 100644 --- a/domain/consensus/datastructures/ghostdagdatastore/ghostdagdatastore.go +++ b/domain/consensus/datastructures/ghostdagdatastore/ghostdagdatastore.go @@ -13,20 +13,20 @@ var bucket = dbkeys.MakeBucket([]byte("block-ghostdag-data")) // ghostdagDataStore represents a store of BlockGHOSTDAGData type ghostdagDataStore struct { - staging map[externalapi.DomainHash]model.BlockGHOSTDAGData + staging map[externalapi.DomainHash]*model.BlockGHOSTDAGData cache *lrucache.LRUCache } // New instantiates a new GHOSTDAGDataStore func New(cacheSize int) model.GHOSTDAGDataStore { return &ghostdagDataStore{ - staging: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData), + staging: make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData), cache: lrucache.New(cacheSize), } } // Stage stages the given blockGHOSTDAGData for the given blockHash -func (gds *ghostdagDataStore) Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData model.BlockGHOSTDAGData) { +func (gds *ghostdagDataStore) Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData *model.BlockGHOSTDAGData) { gds.staging[*blockHash] = blockGHOSTDAGData } @@ -35,7 +35,7 @@ func (gds *ghostdagDataStore) IsStaged() bool { } func (gds *ghostdagDataStore) Discard() { - gds.staging = make(map[externalapi.DomainHash]model.BlockGHOSTDAGData) + gds.staging = make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData) } func (gds *ghostdagDataStore) Commit(dbTx model.DBTransaction) error { @@ -56,13 +56,13 @@ func (gds *ghostdagDataStore) Commit(dbTx model.DBTransaction) error { } // Get gets the blockGHOSTDAGData associated with the given blockHash -func (gds *ghostdagDataStore) Get(dbContext model.DBReader, blockHash *externalapi.DomainHash) (model.BlockGHOSTDAGData, error) { +func (gds *ghostdagDataStore) Get(dbContext model.DBReader, blockHash *externalapi.DomainHash) (*model.BlockGHOSTDAGData, error) { if blockGHOSTDAGData, ok := gds.staging[*blockHash]; ok { return blockGHOSTDAGData, nil } if blockGHOSTDAGData, ok := gds.cache.Get(blockHash); ok { - return blockGHOSTDAGData.(model.BlockGHOSTDAGData), nil + return blockGHOSTDAGData.(*model.BlockGHOSTDAGData), nil } blockGHOSTDAGDataBytes, err := dbContext.Get(gds.hashAsKey(blockHash)) @@ -82,11 +82,11 @@ func (gds *ghostdagDataStore) hashAsKey(hash *externalapi.DomainHash) model.DBKe return bucket.Key(hash.ByteSlice()) } -func (gds *ghostdagDataStore) serializeBlockGHOSTDAGData(blockGHOSTDAGData model.BlockGHOSTDAGData) ([]byte, error) { +func (gds *ghostdagDataStore) serializeBlockGHOSTDAGData(blockGHOSTDAGData *model.BlockGHOSTDAGData) ([]byte, error) { return proto.Marshal(serialization.BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData)) } -func (gds *ghostdagDataStore) deserializeBlockGHOSTDAGData(blockGHOSTDAGDataBytes []byte) (model.BlockGHOSTDAGData, error) { +func (gds *ghostdagDataStore) deserializeBlockGHOSTDAGData(blockGHOSTDAGDataBytes []byte) (*model.BlockGHOSTDAGData, error) { dbBlockGHOSTDAGData := &serialization.DbBlockGhostdagData{} err := proto.Unmarshal(blockGHOSTDAGDataBytes, dbBlockGHOSTDAGData) if err != nil { diff --git a/domain/consensus/model/externalapi/hash.go b/domain/consensus/model/externalapi/hash.go index 02317d888..b6baa24e7 100644 --- a/domain/consensus/model/externalapi/hash.go +++ b/domain/consensus/model/externalapi/hash.go @@ -105,3 +105,21 @@ func HashesEqual(a, b []*DomainHash) bool { } return true } + +func cmp(a, b *DomainHash) int { + // We compare the hashes backwards because Hash is stored as a little endian byte array. + for i := DomainHashSize - 1; i >= 0; i-- { + switch { + case a.hashArray[i] < b.hashArray[i]: + return -1 + case a.hashArray[i] > b.hashArray[i]: + return 1 + } + } + return 0 +} + +// Less returns true iff hash a is less than hash b +func Less(a, b *DomainHash) bool { + return cmp(a, b) < 0 +} diff --git a/domain/consensus/model/ghostdag.go b/domain/consensus/model/ghostdag.go index efe5be5c9..5b77cd83d 100644 --- a/domain/consensus/model/ghostdag.go +++ b/domain/consensus/model/ghostdag.go @@ -6,16 +6,74 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" ) -// BlockGHOSTDAGData represents GHOSTDAG data for some block -type BlockGHOSTDAGData interface { - BlueScore() uint64 - BlueWork() *big.Int - SelectedParent() *externalapi.DomainHash - MergeSetBlues() []*externalapi.DomainHash - MergeSetReds() []*externalapi.DomainHash - MergeSet() []*externalapi.DomainHash - BluesAnticoneSizes() map[externalapi.DomainHash]KType -} - // KType defines the size of GHOSTDAG consensus algorithm K parameter. type KType byte + +// BlockGHOSTDAGData represents GHOSTDAG data for some block +type BlockGHOSTDAGData struct { + blueScore uint64 + blueWork *big.Int + selectedParent *externalapi.DomainHash + mergeSetBlues []*externalapi.DomainHash + mergeSetReds []*externalapi.DomainHash + bluesAnticoneSizes map[externalapi.DomainHash]KType +} + +// NewBlockGHOSTDAGData creates a new instance of BlockGHOSTDAGData +func NewBlockGHOSTDAGData( + blueScore uint64, + blueWork *big.Int, + selectedParent *externalapi.DomainHash, + mergeSetBlues []*externalapi.DomainHash, + mergeSetReds []*externalapi.DomainHash, + bluesAnticoneSizes map[externalapi.DomainHash]KType) *BlockGHOSTDAGData { + + return &BlockGHOSTDAGData{ + blueScore: blueScore, + blueWork: blueWork, + selectedParent: selectedParent, + mergeSetBlues: mergeSetBlues, + mergeSetReds: mergeSetReds, + bluesAnticoneSizes: bluesAnticoneSizes, + } +} + +// BlueScore returns the BlueScore of the block +func (bgd *BlockGHOSTDAGData) BlueScore() uint64 { + return bgd.blueScore +} + +// BlueWork returns the BlueWork of the block +func (bgd *BlockGHOSTDAGData) BlueWork() *big.Int { + return bgd.blueWork +} + +// SelectedParent returns the SelectedParent of the block +func (bgd *BlockGHOSTDAGData) SelectedParent() *externalapi.DomainHash { + return bgd.selectedParent +} + +// MergeSetBlues returns the MergeSetBlues of the block (not a copy) +func (bgd *BlockGHOSTDAGData) MergeSetBlues() []*externalapi.DomainHash { + return bgd.mergeSetBlues +} + +// MergeSetReds returns the MergeSetReds of the block (not a copy) +func (bgd *BlockGHOSTDAGData) MergeSetReds() []*externalapi.DomainHash { + return bgd.mergeSetReds +} + +// BluesAnticoneSizes returns a map between the blocks in its MergeSetBlues and the size of their anticone +func (bgd *BlockGHOSTDAGData) BluesAnticoneSizes() map[externalapi.DomainHash]KType { + return bgd.bluesAnticoneSizes +} + +// MergeSet returns the whole MergeSet of the block (equivalent to MergeSetBlues+MergeSetReds) +func (bgd *BlockGHOSTDAGData) MergeSet() []*externalapi.DomainHash { + mergeSet := make([]*externalapi.DomainHash, len(bgd.mergeSetBlues)+len(bgd.mergeSetReds)) + copy(mergeSet, bgd.mergeSetBlues) + if len(bgd.mergeSetReds) > 0 { + copy(mergeSet[len(bgd.mergeSetBlues):], bgd.mergeSetReds) + } + return mergeSet +} diff --git a/domain/consensus/model/interface_datastructures_ghostdagdatastore.go b/domain/consensus/model/interface_datastructures_ghostdagdatastore.go index 4e20e3408..13522feb1 100644 --- a/domain/consensus/model/interface_datastructures_ghostdagdatastore.go +++ b/domain/consensus/model/interface_datastructures_ghostdagdatastore.go @@ -5,7 +5,7 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" // GHOSTDAGDataStore represents a store of BlockGHOSTDAGData type GHOSTDAGDataStore interface { Store - Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData BlockGHOSTDAGData) + Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData *BlockGHOSTDAGData) IsStaged() bool - Get(dbContext DBReader, blockHash *externalapi.DomainHash) (BlockGHOSTDAGData, error) + Get(dbContext DBReader, blockHash *externalapi.DomainHash) (*BlockGHOSTDAGData, error) } diff --git a/domain/consensus/model/interface_processes_ghostdagmanager.go b/domain/consensus/model/interface_processes_ghostdagmanager.go index 1222d5565..f7cbab390 100644 --- a/domain/consensus/model/interface_processes_ghostdagmanager.go +++ b/domain/consensus/model/interface_processes_ghostdagmanager.go @@ -6,6 +6,6 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" type GHOSTDAGManager interface { GHOSTDAG(blockHash *externalapi.DomainHash) error ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error) - Less(blockHashA *externalapi.DomainHash, ghostdagDataA BlockGHOSTDAGData, - blockHashB *externalapi.DomainHash, ghostdagDataB BlockGHOSTDAGData) bool + Less(blockHashA *externalapi.DomainHash, ghostdagDataA *BlockGHOSTDAGData, + blockHashB *externalapi.DomainHash, ghostdagDataB *BlockGHOSTDAGData) bool } diff --git a/domain/consensus/processes/consensusstatemanager/calculate_past_utxo.go b/domain/consensus/processes/consensusstatemanager/calculate_past_utxo.go index 349f1ba5d..eccd1cc80 100644 --- a/domain/consensus/processes/consensusstatemanager/calculate_past_utxo.go +++ b/domain/consensus/processes/consensusstatemanager/calculate_past_utxo.go @@ -109,7 +109,7 @@ func (csm *consensusStateManager) restorePastUTXO(blockHash *externalapi.DomainH } func (csm *consensusStateManager) applyMergeSetBlocks(blockHash *externalapi.DomainHash, - selectedParentPastUTXODiff model.MutableUTXODiff, ghostdagData model.BlockGHOSTDAGData) ( + selectedParentPastUTXODiff model.MutableUTXODiff, ghostdagData *model.BlockGHOSTDAGData) ( externalapi.AcceptanceData, model.MutableUTXODiff, error) { log.Debugf("applyMergeSetBlocks start for block %s", blockHash) diff --git a/domain/consensus/processes/consensusstatemanager/multisets.go b/domain/consensus/processes/consensusstatemanager/multisets.go index 644e4f687..8099ed49b 100644 --- a/domain/consensus/processes/consensusstatemanager/multisets.go +++ b/domain/consensus/processes/consensusstatemanager/multisets.go @@ -10,7 +10,7 @@ import ( ) func (csm *consensusStateManager) calculateMultiset( - acceptanceData externalapi.AcceptanceData, blockGHOSTDAGData model.BlockGHOSTDAGData) (model.Multiset, error) { + acceptanceData externalapi.AcceptanceData, blockGHOSTDAGData *model.BlockGHOSTDAGData) (model.Multiset, error) { log.Debugf("calculateMultiset start for block with selected parent %s", blockGHOSTDAGData.SelectedParent()) defer log.Debugf("calculateMultiset end for block with selected parent %s", blockGHOSTDAGData.SelectedParent()) diff --git a/domain/consensus/processes/dagtraversalmanager/block_heap.go b/domain/consensus/processes/dagtraversalmanager/block_heap.go index a305e97f2..46b099c3b 100644 --- a/domain/consensus/processes/dagtraversalmanager/block_heap.go +++ b/domain/consensus/processes/dagtraversalmanager/block_heap.go @@ -9,7 +9,7 @@ import ( type blockHeapNode struct { hash *externalapi.DomainHash - ghostdagData model.BlockGHOSTDAGData + ghostdagData *model.BlockGHOSTDAGData } func (left *blockHeapNode) less(right *blockHeapNode, gm model.GHOSTDAGManager) bool { @@ -152,12 +152,8 @@ func (sbh *sizedUpBlockHeap) pop() *externalapi.DomainHash { return heap.Pop(&sbh.impl).(*blockHeapNode).hash } -// tryPush tries to push the block onto the heap, if the heap is full and it's less than the minimum it rejects it -func (sbh *sizedUpBlockHeap) tryPush(blockHash *externalapi.DomainHash) (bool, error) { - ghostdagData, err := sbh.ghostdagStore.Get(sbh.dbContext, blockHash) - if err != nil { - return false, err - } +// tryPushWithGHOSTDAGData is just like tryPush but the caller provides the ghostdagData of the block. +func (sbh *sizedUpBlockHeap) tryPushWithGHOSTDAGData(blockHash *externalapi.DomainHash, ghostdagData *model.BlockGHOSTDAGData) (bool, error) { node := &blockHeapNode{ hash: blockHash, ghostdagData: ghostdagData, @@ -173,3 +169,12 @@ func (sbh *sizedUpBlockHeap) tryPush(blockHash *externalapi.DomainHash) (bool, e heap.Push(&sbh.impl, node) return true, nil } + +// tryPush tries to push the block onto the heap, if the heap is full and it's less than the minimum it rejects it +func (sbh *sizedUpBlockHeap) tryPush(blockHash *externalapi.DomainHash) (bool, error) { + ghostdagData, err := sbh.ghostdagStore.Get(sbh.dbContext, blockHash) + if err != nil { + return false, err + } + return sbh.tryPushWithGHOSTDAGData(blockHash, ghostdagData) +} diff --git a/domain/consensus/processes/dagtraversalmanager/window.go b/domain/consensus/processes/dagtraversalmanager/window.go index b2c6439c9..a8d806a78 100644 --- a/domain/consensus/processes/dagtraversalmanager/window.go +++ b/domain/consensus/processes/dagtraversalmanager/window.go @@ -18,7 +18,11 @@ func (dtm *dagTraversalManager) BlueWindow(startingBlock *externalapi.DomainHash windowHeap := dtm.newSizedUpHeap(windowSize) for windowHeap.len() <= windowSize && currentGHOSTDAGData.SelectedParent() != nil { - added, err := windowHeap.tryPush(currentGHOSTDAGData.SelectedParent()) + selectedParentGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentGHOSTDAGData.SelectedParent()) + if err != nil { + return nil, err + } + added, err := windowHeap.tryPushWithGHOSTDAGData(currentGHOSTDAGData.SelectedParent(), selectedParentGHOSTDAGData) if err != nil { return nil, err } @@ -55,10 +59,7 @@ func (dtm *dagTraversalManager) BlueWindow(startingBlock *externalapi.DomainHash } } currentHash = currentGHOSTDAGData.SelectedParent() - currentGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash) - if err != nil { - return nil, err - } + currentGHOSTDAGData = selectedParentGHOSTDAGData } window := make([]*externalapi.DomainHash, 0, windowSize) diff --git a/domain/consensus/processes/difficultymanager/blockwindow.go b/domain/consensus/processes/difficultymanager/blockwindow.go index 3f795f140..9f070f286 100644 --- a/domain/consensus/processes/difficultymanager/blockwindow.go +++ b/domain/consensus/processes/difficultymanager/blockwindow.go @@ -3,7 +3,6 @@ package difficultymanager import ( "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/util" - "github.com/kaspanet/kaspad/util/bigintpool" "github.com/pkg/errors" "math" "math/big" @@ -72,19 +71,14 @@ func (window *blockWindow) remove(n int) { *window = (*window)[:len(*window)-1] } -func (window blockWindow) averageTarget(averageTarget *big.Int) { - averageTarget.SetInt64(0) - - target := bigintpool.Acquire(0) - defer bigintpool.Release(target) +func (window blockWindow) averageTarget() *big.Int { + averageTarget := new(big.Int) + targetTmp := new(big.Int) for _, block := range window { - util.CompactToBigWithDestination(block.Bits, target) - averageTarget.Add(averageTarget, target) + util.CompactToBigWithDestination(block.Bits, targetTmp) + averageTarget.Add(averageTarget, targetTmp) } - - windowLen := bigintpool.Acquire(int64(len(window))) - defer bigintpool.Release(windowLen) - averageTarget.Div(averageTarget, windowLen) + return averageTarget.Div(averageTarget, big.NewInt(int64(len(window)))) } func (window blockWindow) medianTimestamp() (int64, error) { diff --git a/domain/consensus/processes/difficultymanager/difficultymanager.go b/domain/consensus/processes/difficultymanager/difficultymanager.go index 87939a8da..c82a6716a 100644 --- a/domain/consensus/processes/difficultymanager/difficultymanager.go +++ b/domain/consensus/processes/difficultymanager/difficultymanager.go @@ -7,7 +7,6 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/util" - "github.com/kaspanet/kaspad/util/bigintpool" ) // DifficultyManager provides a method to resolve the @@ -74,24 +73,13 @@ func (dm *difficultyManager) RequiredDifficulty(blockHash *externalapi.DomainHas } // find bluestParent - bluestParent := parents[0] - bluestGhostDAG, err := dm.ghostdagStore.Get(dm.databaseContext, bluestParent) + bluestParent, err := dm.ghostdagManager.ChooseSelectedParent(parents...) if err != nil { return 0, err } - for i := 1; i < len(parents); i++ { - parentGhostDAG, err := dm.ghostdagStore.Get(dm.databaseContext, parents[i]) - if err != nil { - return 0, err - } - newBluest, err := dm.ghostdagManager.ChooseSelectedParent(bluestParent, parents[i]) - if err != nil { - return 0, err - } - if bluestParent != newBluest { - bluestParent = newBluest - bluestGhostDAG = parentGhostDAG - } + bluestGhostDAG, err := dm.ghostdagStore.Get(dm.databaseContext, bluestParent) + if err != nil { + return 0, err } // Not enough blocks for building a difficulty window. @@ -113,20 +101,12 @@ func (dm *difficultyManager) RequiredDifficulty(blockHash *externalapi.DomainHas // averageWindowTarget * (windowMinTimestamp / (targetTimePerBlock * windowSize)) // The result uses integer division which means it will be slightly // rounded down. - newTarget := bigintpool.Acquire(0) - defer bigintpool.Release(newTarget) - windowTimeStampDifference := bigintpool.Acquire(windowMaxTimeStamp - windowMinTimestamp) - defer bigintpool.Release(windowTimeStampDifference) - targetTimePerBlock := bigintpool.Acquire(dm.targetTimePerBlock.Milliseconds()) - defer bigintpool.Release(targetTimePerBlock) - difficultyAdjustmentWindowSize := bigintpool.Acquire(int64(dm.difficultyAdjustmentWindowSize)) - defer bigintpool.Release(difficultyAdjustmentWindowSize) - - targetsWindow.averageTarget(newTarget) + div := new(big.Int) + newTarget := targetsWindow.averageTarget() newTarget. - Mul(newTarget, windowTimeStampDifference). - Div(newTarget, targetTimePerBlock). - Div(newTarget, difficultyAdjustmentWindowSize) + Mul(newTarget, div.SetInt64(windowMaxTimeStamp-windowMinTimestamp)). + Div(newTarget, div.SetInt64(dm.targetTimePerBlock.Milliseconds())). + Div(newTarget, div.SetUint64(uint64(dm.difficultyAdjustmentWindowSize))) if newTarget.Cmp(dm.powMax) > 0 { return util.BigToCompact(dm.powMax), nil } diff --git a/domain/consensus/processes/ghostdag2/ghostdagimpl.go b/domain/consensus/processes/ghostdag2/ghostdagimpl.go index 23773708b..0b6fee8eb 100644 --- a/domain/consensus/processes/ghostdag2/ghostdagimpl.go +++ b/domain/consensus/processes/ghostdag2/ghostdagimpl.go @@ -3,8 +3,6 @@ package ghostdag2 import ( "sort" - "github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager" - "math/big" "github.com/kaspanet/kaspad/domain/consensus/model" @@ -116,7 +114,7 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error myWork.Add(myWork, util.CalcWork(header.Bits())) } - e := ghostdagmanager.NewBlockGHOSTDAGData(myScore, myWork, selectedParent, mergeSetBlues, mergeSetReds, nil) + e := model.NewBlockGHOSTDAGData(myScore, myWork, selectedParent, mergeSetBlues, mergeSetReds, nil) gh.dataStore.Stage(blockCandidate, e) return nil } @@ -391,13 +389,13 @@ func (gh *ghostdagHelper) sortByBlueWork(arr []*externalapi.DomainHash) error { /* --------------------------------------------- */ -func (gh *ghostdagHelper) BlockData(blockHash *externalapi.DomainHash) (model.BlockGHOSTDAGData, error) { +func (gh *ghostdagHelper) BlockData(blockHash *externalapi.DomainHash) (*model.BlockGHOSTDAGData, error) { return gh.dataStore.Get(gh.dbAccess, blockHash) } func (gh *ghostdagHelper) ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error) { panic("implement me") } -func (gh *ghostdagHelper) Less(blockHashA *externalapi.DomainHash, ghostdagDataA model.BlockGHOSTDAGData, blockHashB *externalapi.DomainHash, ghostdagDataB model.BlockGHOSTDAGData) bool { +func (gh *ghostdagHelper) Less(blockHashA *externalapi.DomainHash, ghostdagDataA *model.BlockGHOSTDAGData, blockHashB *externalapi.DomainHash, ghostdagDataB *model.BlockGHOSTDAGData) bool { panic("implement me") } diff --git a/domain/consensus/processes/ghostdagmanager/compare.go b/domain/consensus/processes/ghostdagmanager/compare.go index d5143513c..3b0b3777a 100644 --- a/domain/consensus/processes/ghostdagmanager/compare.go +++ b/domain/consensus/processes/ghostdagmanager/compare.go @@ -3,7 +3,6 @@ package ghostdagmanager import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/utils/hashes" ) func (gm *ghostdagManager) findSelectedParent(parentHashes []*externalapi.DomainHash) (*externalapi.DomainHash, error) { @@ -53,16 +52,15 @@ func (gm *ghostdagManager) ChooseSelectedParent(blockHashes ...*externalapi.Doma return selectedParent, nil } -func (gm *ghostdagManager) Less(blockHashA *externalapi.DomainHash, ghostdagDataA model.BlockGHOSTDAGData, - blockHashB *externalapi.DomainHash, ghostdagDataB model.BlockGHOSTDAGData) bool { - +func (gm *ghostdagManager) Less(blockHashA *externalapi.DomainHash, ghostdagDataA *model.BlockGHOSTDAGData, + blockHashB *externalapi.DomainHash, ghostdagDataB *model.BlockGHOSTDAGData) bool { switch ghostdagDataA.BlueWork().Cmp(ghostdagDataB.BlueWork()) { case -1: return true case 1: return false case 0: - return hashes.Less(blockHashA, blockHashB) + return externalapi.Less(blockHashA, blockHashB) default: panic("big.Int.Cmp is defined to always return -1/1/0 and nothing else") } diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag.go b/domain/consensus/processes/ghostdagmanager/ghostdag.go index 6eb056b6a..488dbf088 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdag.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdag.go @@ -8,6 +8,19 @@ import ( "math/big" ) +type blockGHOSTDAGData struct { + blueScore uint64 + blueWork *big.Int + selectedParent *externalapi.DomainHash + mergeSetBlues []*externalapi.DomainHash + mergeSetReds []*externalapi.DomainHash + bluesAnticoneSizes map[externalapi.DomainHash]model.KType +} + +func (bg *blockGHOSTDAGData) toModel() *model.BlockGHOSTDAGData { + return model.NewBlockGHOSTDAGData(bg.blueScore, bg.blueWork, bg.selectedParent, bg.mergeSetBlues, bg.mergeSetReds, bg.bluesAnticoneSizes) +} + // GHOSTDAG runs the GHOSTDAG protocol and calculates the block BlockGHOSTDAGData by the given parents. // The function calculates MergeSetBlues by iterating over the blocks in // the anticone of the new block selected parent (which is the parent with the @@ -57,7 +70,7 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error { } for _, blueCandidate := range mergeSetWithoutSelectedParent { - isBlue, candidateAnticoneSize, candidateBluesAnticoneSizes, err := gm.checkBlueCandidate(newBlockData, blueCandidate) + isBlue, candidateAnticoneSize, candidateBluesAnticoneSizes, err := gm.checkBlueCandidate(newBlockData.toModel(), blueCandidate) if err != nil { return err } @@ -96,22 +109,22 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error { newBlockData.blueWork.SetUint64(0) } - gm.ghostdagDataStore.Stage(blockHash, newBlockData) + gm.ghostdagDataStore.Stage(blockHash, newBlockData.toModel()) return nil } type chainBlockData struct { hash *externalapi.DomainHash - blockData model.BlockGHOSTDAGData + blockData *model.BlockGHOSTDAGData } -func (gm *ghostdagManager) checkBlueCandidate(newBlockData *blockGHOSTDAGData, blueCandidate *externalapi.DomainHash) ( +func (gm *ghostdagManager) checkBlueCandidate(newBlockData *model.BlockGHOSTDAGData, blueCandidate *externalapi.DomainHash) ( isBlue bool, candidateAnticoneSize model.KType, candidateBluesAnticoneSizes map[externalapi.DomainHash]model.KType, err error) { // The maximum length of node.blues can be K+1 because // it contains the selected parent. - if model.KType(len(newBlockData.mergeSetBlues)) == gm.k+1 { + if model.KType(len(newBlockData.MergeSetBlues())) == gm.k+1 { return false, 0, nil, nil } @@ -153,7 +166,7 @@ func (gm *ghostdagManager) checkBlueCandidate(newBlockData *blockGHOSTDAGData, b return true, candidateAnticoneSize, candidateBluesAnticoneSizes, nil } -func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData model.BlockGHOSTDAGData, +func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData *model.BlockGHOSTDAGData, chainBlock chainBlockData, blueCandidate *externalapi.DomainHash, candidateBluesAnticoneSizes map[externalapi.DomainHash]model.KType, candidateAnticoneSize *model.KType) (isBlue, isRed bool, err error) { @@ -218,7 +231,7 @@ func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData model.B // blueAnticoneSize returns the blue anticone size of 'block' from the worldview of 'context'. // Expects 'block' to be in the blue set of 'context' -func (gm *ghostdagManager) blueAnticoneSize(block *externalapi.DomainHash, context model.BlockGHOSTDAGData) (model.KType, error) { +func (gm *ghostdagManager) blueAnticoneSize(block *externalapi.DomainHash, context *model.BlockGHOSTDAGData) (model.KType, error) { for current := context; current != nil; { if blueAnticoneSize, ok := current.BluesAnticoneSizes()[*block]; ok { return blueAnticoneSize, nil diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag_data.go b/domain/consensus/processes/ghostdagmanager/ghostdag_data.go deleted file mode 100644 index 49fc39090..000000000 --- a/domain/consensus/processes/ghostdagmanager/ghostdag_data.go +++ /dev/null @@ -1,69 +0,0 @@ -package ghostdagmanager - -import ( - "github.com/kaspanet/kaspad/domain/consensus/model" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "math/big" -) - -type blockGHOSTDAGData struct { - blueScore uint64 - blueWork *big.Int - selectedParent *externalapi.DomainHash - mergeSetBlues []*externalapi.DomainHash - mergeSetReds []*externalapi.DomainHash - bluesAnticoneSizes map[externalapi.DomainHash]model.KType -} - -// NewBlockGHOSTDAGData creates a new instance of model.BlockGHOSTDAGData -func NewBlockGHOSTDAGData( - blueScore uint64, - blueWork *big.Int, - selectedParent *externalapi.DomainHash, - mergeSetBlues []*externalapi.DomainHash, - mergeSetReds []*externalapi.DomainHash, - bluesAnticoneSizes map[externalapi.DomainHash]model.KType) model.BlockGHOSTDAGData { - - return &blockGHOSTDAGData{ - blueScore: blueScore, - blueWork: blueWork, - selectedParent: selectedParent, - mergeSetBlues: mergeSetBlues, - mergeSetReds: mergeSetReds, - bluesAnticoneSizes: bluesAnticoneSizes, - } -} - -func (bgd *blockGHOSTDAGData) BlueScore() uint64 { - return bgd.blueScore -} - -func (bgd *blockGHOSTDAGData) BlueWork() *big.Int { - return bgd.blueWork -} - -func (bgd *blockGHOSTDAGData) SelectedParent() *externalapi.DomainHash { - return bgd.selectedParent -} - -func (bgd *blockGHOSTDAGData) MergeSetBlues() []*externalapi.DomainHash { - return bgd.mergeSetBlues -} - -func (bgd *blockGHOSTDAGData) MergeSetReds() []*externalapi.DomainHash { - return bgd.mergeSetReds -} - -func (bgd *blockGHOSTDAGData) BluesAnticoneSizes() map[externalapi.DomainHash]model.KType { - return bgd.bluesAnticoneSizes -} - -func (bgd *blockGHOSTDAGData) MergeSet() []*externalapi.DomainHash { - mergeSet := make([]*externalapi.DomainHash, len(bgd.mergeSetBlues)+len(bgd.mergeSetReds)) - copy(mergeSet, bgd.mergeSetBlues) - if len(bgd.mergeSetReds) > 0 { - copy(mergeSet[len(bgd.mergeSetBlues):], bgd.mergeSetReds) - } - - return mergeSet -} diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag_test.go b/domain/consensus/processes/ghostdagmanager/ghostdag_test.go index f5485da2f..f11de5c5e 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdag_test.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdag_test.go @@ -63,14 +63,14 @@ func TestGHOSTDAG(t *testing.T) { } ghostdagDataStore := &GHOSTDAGDataStoreImpl{ - dagMap: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData), + dagMap: make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData), } blockHeadersStore := &blockHeadersStore{ dagMap: make(map[externalapi.DomainHash]externalapi.BlockHeader), } - blockGHOSTDAGDataGenesis := ghostdagmanager.NewBlockGHOSTDAGData(0, new(big.Int), nil, nil, nil, nil) + blockGHOSTDAGDataGenesis := model.NewBlockGHOSTDAGData(0, new(big.Int), nil, nil, nil, nil) genesisHeader := params.GenesisBlock.Header genesisWork := util.CalcWork(genesisHeader.Bits()) @@ -160,7 +160,7 @@ func TestGHOSTDAG(t *testing.T) { } dagTopology.parentsMap = make(map[externalapi.DomainHash][]*externalapi.DomainHash) dagTopology.parentsMap[genesisHash] = nil - ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]model.BlockGHOSTDAGData) + ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData) ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis blockHeadersStore.dagMap = make(map[externalapi.DomainHash]externalapi.BlockHeader) blockHeadersStore.dagMap[genesisHash] = genesisHeader @@ -202,10 +202,10 @@ func StringToDomainHashSlice(stringIDArr []string) []*externalapi.DomainHash { /* ---------------------- */ type GHOSTDAGDataStoreImpl struct { - dagMap map[externalapi.DomainHash]model.BlockGHOSTDAGData + dagMap map[externalapi.DomainHash]*model.BlockGHOSTDAGData } -func (ds *GHOSTDAGDataStoreImpl) Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData model.BlockGHOSTDAGData) { +func (ds *GHOSTDAGDataStoreImpl) Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData *model.BlockGHOSTDAGData) { ds.dagMap[*blockHash] = blockGHOSTDAGData } @@ -221,7 +221,7 @@ func (ds *GHOSTDAGDataStoreImpl) Commit(dbTx model.DBTransaction) error { panic("implement me") } -func (ds *GHOSTDAGDataStoreImpl) Get(dbContext model.DBReader, blockHash *externalapi.DomainHash) (model.BlockGHOSTDAGData, error) { +func (ds *GHOSTDAGDataStoreImpl) Get(dbContext model.DBReader, blockHash *externalapi.DomainHash) (*model.BlockGHOSTDAGData, error) { v, ok := ds.dagMap[*blockHash] if ok { return v, nil diff --git a/domain/consensus/utils/hashes/compare.go b/domain/consensus/utils/hashes/compare.go deleted file mode 100644 index fdf16db18..000000000 --- a/domain/consensus/utils/hashes/compare.go +++ /dev/null @@ -1,31 +0,0 @@ -package hashes - -import ( - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" -) - -// cmp compares two hashes and returns: -// -// -1 if a < b -// 0 if a == b -// +1 if a > b -// -func cmp(a, b *externalapi.DomainHash) int { - aBytes := a.ByteArray() - bBytes := b.ByteArray() - // We compare the hashes backwards because Hash is stored as a little endian byte array. - for i := externalapi.DomainHashSize - 1; i >= 0; i-- { - switch { - case aBytes[i] < bBytes[i]: - return -1 - case aBytes[i] > bBytes[i]: - return 1 - } - } - return 0 -} - -// Less returns true iff hash a is less than hash b -func Less(a, b *externalapi.DomainHash) bool { - return cmp(a, b) < 0 -} diff --git a/domain/consensus/utils/transactionid/compare.go b/domain/consensus/utils/transactionid/compare.go index 918c54206..ab28853c2 100644 --- a/domain/consensus/utils/transactionid/compare.go +++ b/domain/consensus/utils/transactionid/compare.go @@ -2,10 +2,9 @@ package transactionid import ( "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/utils/hashes" ) // Less returns true iff transaction ID a is less than hash b func Less(a, b *externalapi.DomainTransactionID) bool { - return hashes.Less((*externalapi.DomainHash)(a), (*externalapi.DomainHash)(b)) + return externalapi.Less((*externalapi.DomainHash)(a), (*externalapi.DomainHash)(b)) } diff --git a/util/bigintpool/pool.go b/util/bigintpool/pool.go deleted file mode 100644 index d2eab80ff..000000000 --- a/util/bigintpool/pool.go +++ /dev/null @@ -1,25 +0,0 @@ -package bigintpool - -import ( - "math/big" - "sync" -) - -var bigIntPool = sync.Pool{ - New: func() interface{} { - return big.NewInt(0) - }, -} - -// Acquire acquires a big.Int from the pool and -// initializes it to x. -func Acquire(x int64) *big.Int { - bigInt := bigIntPool.Get().(*big.Int) - bigInt.SetInt64(x) - return bigInt -} - -// Release returns the given big.Int to the pool. -func Release(toRelease *big.Int) { - bigIntPool.Put(toRelease) -}