mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-03-21 23:53:33 +00:00
Smal performance improvements to BlueWindow (#1343)
* Convert BlockGHOSTDAGData from an interface to a public struct with getters * Move hashes.Less to externalapi so it can access the hashes directly without copying * Reduce calls to ghostdagstore.Get in blueWindow * Simplify the logic in RequiredDifficulty and reuse big.Int * Remove bigintpool as its no longer used * Use ChooseSelectedParent in RequiredDifficulty instead of looping over the parents * Remove comment
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user