mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-05 13:46:42 +00:00
[NOD-1548] Re-add test difficulty + Make GHOSTDAGData immutable + don't clone in store (#1178)
* [NOD-1548] Readd TestDifficulty * [NOD-1548] Make GHOSTDAGData immutable + don't clone in store Co-authored-by: Ori Newman <orinewman1@gmail.com>
This commit is contained in:
parent
f97b8f7580
commit
33eaf9edac
@ -134,7 +134,7 @@ func (s *consensus) GetBlockInfo(blockHash *externalapi.DomainHash) (*externalap
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockInfo.BlueScore = ghostdagData.BlueScore
|
||||
blockInfo.BlueScore = ghostdagData.BlueScore()
|
||||
|
||||
isBlockInHeaderPruningPointFuture, err := s.syncManager.IsBlockInHeaderPruningPointFuture(blockHash)
|
||||
if err != nil {
|
||||
@ -196,7 +196,7 @@ func (s *consensus) GetVirtualSelectedParent() (*externalapi.DomainBlock, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.blockStore.Block(s.databaseContext, virtualGHOSTDAGData.SelectedParent)
|
||||
return s.blockStore.Block(s.databaseContext, virtualGHOSTDAGData.SelectedParent())
|
||||
}
|
||||
|
||||
func (s *consensus) CreateBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) {
|
||||
|
@ -3,26 +3,27 @@ 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"
|
||||
)
|
||||
|
||||
// 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)
|
||||
if blockGHOSTDAGData.SelectedParent() != nil {
|
||||
selectedParent = DomainHashToDbHash(blockGHOSTDAGData.SelectedParent())
|
||||
}
|
||||
|
||||
return &DbBlockGhostdagData{
|
||||
BlueScore: blockGHOSTDAGData.BlueScore,
|
||||
BlueScore: blockGHOSTDAGData.BlueScore(),
|
||||
SelectedParent: selectedParent,
|
||||
MergeSetBlues: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetBlues),
|
||||
MergeSetReds: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetReds),
|
||||
BluesAnticoneSizes: bluesAnticoneSizesToDBBluesAnticoneSizes(blockGHOSTDAGData.BluesAnticoneSizes),
|
||||
MergeSetBlues: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetBlues()),
|
||||
MergeSetReds: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetReds()),
|
||||
BluesAnticoneSizes: bluesAnticoneSizesToDBBluesAnticoneSizes(blockGHOSTDAGData.BluesAnticoneSizes()),
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -47,11 +48,11 @@ func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdag
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.BlockGHOSTDAGData{
|
||||
BlueScore: dbBlockGHOSTDAGData.BlueScore,
|
||||
SelectedParent: selectedParent,
|
||||
MergeSetBlues: mergetSetBlues,
|
||||
MergeSetReds: mergetSetReds,
|
||||
BluesAnticoneSizes: bluesAnticoneSizes,
|
||||
}, nil
|
||||
return ghostdagmanager.NewBlockGHOSTDAGData(
|
||||
dbBlockGHOSTDAGData.BlueScore,
|
||||
selectedParent,
|
||||
mergetSetBlues,
|
||||
mergetSetReds,
|
||||
bluesAnticoneSizes,
|
||||
), nil
|
||||
}
|
||||
|
@ -13,21 +13,21 @@ 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) {
|
||||
gds.staging[*blockHash] = blockGHOSTDAGData.Clone()
|
||||
func (gds *ghostdagDataStore) Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData model.BlockGHOSTDAGData) {
|
||||
gds.staging[*blockHash] = blockGHOSTDAGData
|
||||
}
|
||||
|
||||
func (gds *ghostdagDataStore) IsStaged() bool {
|
||||
@ -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.Clone(), nil
|
||||
return blockGHOSTDAGData, nil
|
||||
}
|
||||
|
||||
if blockGHOSTDAGData, ok := gds.cache.Get(blockHash); ok {
|
||||
return blockGHOSTDAGData.(*model.BlockGHOSTDAGData).Clone(), nil
|
||||
return blockGHOSTDAGData.(model.BlockGHOSTDAGData), nil
|
||||
}
|
||||
|
||||
blockGHOSTDAGDataBytes, err := dbContext.Get(gds.hashAsKey(blockHash))
|
||||
@ -75,18 +75,18 @@ func (gds *ghostdagDataStore) Get(dbContext model.DBReader, blockHash *externala
|
||||
return nil, err
|
||||
}
|
||||
gds.cache.Add(blockHash, blockGHOSTDAGData)
|
||||
return blockGHOSTDAGData.Clone(), nil
|
||||
return blockGHOSTDAGData, nil
|
||||
}
|
||||
|
||||
func (gds *ghostdagDataStore) hashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
||||
return bucket.Key(hash[:])
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -63,24 +63,23 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
dbManager := consensusdatabase.New(db)
|
||||
|
||||
// Data Structures
|
||||
storeCacheSize := 200
|
||||
acceptanceDataStore := acceptancedatastore.New(storeCacheSize)
|
||||
blockStore, err := blockstore.New(dbManager, storeCacheSize)
|
||||
acceptanceDataStore := acceptancedatastore.New(200)
|
||||
blockStore, err := blockstore.New(dbManager, 200)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockHeaderStore, err := blockheaderstore.New(dbManager, storeCacheSize)
|
||||
blockHeaderStore, err := blockheaderstore.New(dbManager, 10_000)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockRelationStore := blockrelationstore.New(storeCacheSize)
|
||||
blockStatusStore := blockstatusstore.New(storeCacheSize)
|
||||
multisetStore := multisetstore.New(storeCacheSize)
|
||||
blockRelationStore := blockrelationstore.New(200)
|
||||
blockStatusStore := blockstatusstore.New(200)
|
||||
multisetStore := multisetstore.New(200)
|
||||
pruningStore := pruningstore.New()
|
||||
reachabilityDataStore := reachabilitydatastore.New(storeCacheSize)
|
||||
utxoDiffStore := utxodiffstore.New(storeCacheSize)
|
||||
reachabilityDataStore := reachabilitydatastore.New(200)
|
||||
utxoDiffStore := utxodiffstore.New(200)
|
||||
consensusStateStore := consensusstatestore.New()
|
||||
ghostdagDataStore := ghostdagdatastore.New(storeCacheSize)
|
||||
ghostdagDataStore := ghostdagdatastore.New(10_000)
|
||||
headerTipsStore := headertipsstore.New()
|
||||
|
||||
// Processes
|
||||
|
@ -155,7 +155,7 @@ func TestFinality(t *testing.T) {
|
||||
t.Fatalf("TestFinality: Failed getting the ghost dag data of the sidechain tip: %v", err)
|
||||
}
|
||||
|
||||
if selectedTipGhostDagData.BlueScore > sideChainTipGhostDagData.BlueScore {
|
||||
if selectedTipGhostDagData.BlueScore() > sideChainTipGhostDagData.BlueScore() {
|
||||
t.Fatalf("sideChainTip is not the bluest tip when it is expected to be")
|
||||
}
|
||||
|
||||
@ -308,7 +308,7 @@ func TestBoundedMergeDepth(t *testing.T) {
|
||||
}
|
||||
// Make sure it's actually blue
|
||||
found := false
|
||||
for _, blue := range virtualGhotDagData.MergeSetBlues {
|
||||
for _, blue := range virtualGhotDagData.MergeSetBlues() {
|
||||
if *blue == *kosherizingBlockHash {
|
||||
found = true
|
||||
break
|
||||
@ -356,7 +356,7 @@ func TestBoundedMergeDepth(t *testing.T) {
|
||||
}
|
||||
// Make sure it's actually blue
|
||||
found = false
|
||||
for _, blue := range virtualGhotDagData.MergeSetBlues {
|
||||
for _, blue := range virtualGhotDagData.MergeSetBlues() {
|
||||
if *blue == *kosherizingBlockHash {
|
||||
found = true
|
||||
break
|
||||
|
@ -3,32 +3,12 @@ package model
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
// BlockGHOSTDAGData represents GHOSTDAG data for some block
|
||||
type BlockGHOSTDAGData struct {
|
||||
BlueScore uint64
|
||||
SelectedParent *externalapi.DomainHash
|
||||
MergeSetBlues []*externalapi.DomainHash
|
||||
MergeSetReds []*externalapi.DomainHash
|
||||
BluesAnticoneSizes map[externalapi.DomainHash]KType
|
||||
}
|
||||
|
||||
// Clone returns a clone of BlockGHOSTDAGData
|
||||
func (bgd *BlockGHOSTDAGData) Clone() *BlockGHOSTDAGData {
|
||||
if bgd == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bluesAnticoneSizesClone := make(map[externalapi.DomainHash]KType, len(bgd.BluesAnticoneSizes))
|
||||
for hash, size := range bgd.BluesAnticoneSizes {
|
||||
bluesAnticoneSizesClone[hash] = size
|
||||
}
|
||||
|
||||
return &BlockGHOSTDAGData{
|
||||
BlueScore: bgd.BlueScore,
|
||||
SelectedParent: bgd.SelectedParent.Clone(),
|
||||
MergeSetBlues: externalapi.CloneHashes(bgd.MergeSetBlues),
|
||||
MergeSetReds: externalapi.CloneHashes(bgd.MergeSetReds),
|
||||
BluesAnticoneSizes: bluesAnticoneSizesClone,
|
||||
}
|
||||
type BlockGHOSTDAGData interface {
|
||||
BlueScore() uint64
|
||||
SelectedParent() *externalapi.DomainHash
|
||||
MergeSetBlues() []*externalapi.DomainHash
|
||||
MergeSetReds() []*externalapi.DomainHash
|
||||
BluesAnticoneSizes() map[externalapi.DomainHash]KType
|
||||
}
|
||||
|
||||
// KType defines the size of GHOSTDAG consensus algorithm K parameter.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -96,13 +96,13 @@ func (bb *testBlockBuilder) buildBlockWithParents(parentHashes []*externalapi.Do
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent)
|
||||
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if selectedParentStatus == externalapi.StatusDisqualifiedFromChain {
|
||||
return nil, nil, errors.Errorf("Error building block with selectedParent %s with status DisqualifiedFromChain",
|
||||
ghostdagData.SelectedParent)
|
||||
ghostdagData.SelectedParent())
|
||||
}
|
||||
|
||||
pastUTXO, acceptanceData, multiset, err := bb.consensusStateManager.CalculatePastUTXOAndAcceptanceData(tempBlockHash)
|
||||
|
@ -170,7 +170,7 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
|
||||
return fmt.Sprintf("Failed to get sync info: %s", err)
|
||||
}
|
||||
return fmt.Sprintf("New virtual's blue score: %d. Sync state: %s. Block count: %d. Header count: %d",
|
||||
virtualGhostDAGData.BlueScore, syncInfo.State, syncInfo.BlockCount, syncInfo.HeaderCount)
|
||||
virtualGhostDAGData.BlueScore(), syncInfo.State, syncInfo.BlockCount, syncInfo.HeaderCount)
|
||||
}))
|
||||
if logClosureErr != nil {
|
||||
return logClosureErr
|
||||
|
@ -39,7 +39,7 @@ func (v *blockValidator) checkBlockTransactionsFinalized(blockHash *externalapi.
|
||||
|
||||
// Ensure all transactions in the block are finalized.
|
||||
for _, tx := range block.Transactions {
|
||||
if !v.isFinalizedTransaction(tx, ghostdagData.BlueScore, blockTime) {
|
||||
if !v.isFinalizedTransaction(tx, ghostdagData.BlueScore(), blockTime) {
|
||||
txID := consensushashing.TransactionID(tx)
|
||||
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains unfinalized "+
|
||||
"transaction %s", txID)
|
||||
|
@ -115,7 +115,7 @@ func (v *blockValidator) checkMergeSizeLimit(hash *externalapi.DomainHash) error
|
||||
return err
|
||||
}
|
||||
|
||||
mergeSetSize := len(ghostdagData.MergeSetReds) + len(ghostdagData.MergeSetBlues)
|
||||
mergeSetSize := len(ghostdagData.MergeSetReds()) + len(ghostdagData.MergeSetBlues())
|
||||
|
||||
if uint64(mergeSetSize) > v.mergeSetSizeLimit {
|
||||
return errors.Wrapf(ruleerrors.ErrViolatingMergeLimit,
|
||||
|
@ -31,8 +31,8 @@ func (c coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.Doma
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues))
|
||||
for i, blue := range ghostdagData.MergeSetBlues {
|
||||
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues()))
|
||||
for i, blue := range ghostdagData.MergeSetBlues() {
|
||||
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(blue, acceptanceData[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -43,7 +43,7 @@ func (c coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.Doma
|
||||
}
|
||||
}
|
||||
|
||||
payload, err := c.serializeCoinbasePayload(ghostdagData.BlueScore, coinbaseData)
|
||||
payload, err := c.serializeCoinbasePayload(ghostdagData.BlueScore(), coinbaseData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -120,7 +120,7 @@ func (c coinbaseManager) calcBlockSubsidy(blockHash *externalapi.DomainHash) (ui
|
||||
}
|
||||
|
||||
// Equivalent to: baseSubsidy / 2^(blueScore/subsidyHalvingInterval)
|
||||
return c.baseSubsidy >> uint(ghostdagData.BlueScore/c.subsidyReductionInterval), nil
|
||||
return c.baseSubsidy >> uint(ghostdagData.BlueScore()/c.subsidyReductionInterval), nil
|
||||
}
|
||||
|
||||
// New instantiates a new CoinbaseManager
|
||||
|
@ -80,8 +80,8 @@ func (csm *consensusStateManager) isNextVirtualSelectedParent(blockHash *externa
|
||||
}
|
||||
|
||||
log.Tracef("Selecting the next selected parent between "+
|
||||
"the block %s the current selected parent %s", blockHash, virtualGhostdagData.SelectedParent)
|
||||
nextVirtualSelectedParent, err := csm.ghostdagManager.ChooseSelectedParent(virtualGhostdagData.SelectedParent, blockHash)
|
||||
"the block %s the current selected parent %s", blockHash, virtualGhostdagData.SelectedParent())
|
||||
nextVirtualSelectedParent, err := csm.ghostdagManager.ChooseSelectedParent(virtualGhostdagData.SelectedParent(), blockHash)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ func (csm *consensusStateManager) CalculatePastUTXOAndAcceptanceData(blockHash *
|
||||
}
|
||||
|
||||
log.Tracef("Restoring the past UTXO of block %s with selectedParent %s",
|
||||
blockHash, blockGHOSTDAGData.SelectedParent)
|
||||
selectedParentPastUTXO, err := csm.restorePastUTXO(blockGHOSTDAGData.SelectedParent)
|
||||
blockHash, blockGHOSTDAGData.SelectedParent())
|
||||
selectedParentPastUTXO, err := csm.restorePastUTXO(blockGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@ -108,13 +108,13 @@ func (csm *consensusStateManager) restorePastUTXO(blockHash *externalapi.DomainH
|
||||
}
|
||||
|
||||
func (csm *consensusStateManager) applyBlueBlocks(blockHash *externalapi.DomainHash,
|
||||
selectedParentPastUTXODiff model.MutableUTXODiff, ghostdagData *model.BlockGHOSTDAGData) (
|
||||
selectedParentPastUTXODiff model.MutableUTXODiff, ghostdagData model.BlockGHOSTDAGData) (
|
||||
model.AcceptanceData, model.MutableUTXODiff, error) {
|
||||
|
||||
log.Tracef("applyBlueBlocks start for block %s", blockHash)
|
||||
defer log.Tracef("applyBlueBlocks end for block %s", blockHash)
|
||||
|
||||
blueBlocks, err := csm.blockStore.Blocks(csm.databaseContext, ghostdagData.MergeSetBlues)
|
||||
blueBlocks, err := csm.blockStore.Blocks(csm.databaseContext, ghostdagData.MergeSetBlues())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -146,7 +146,7 @@ func (csm *consensusStateManager) applyBlueBlocks(blockHash *externalapi.DomainH
|
||||
transactionID, blueBlockHash)
|
||||
|
||||
isAccepted, accumulatedMass, err = csm.maybeAcceptTransaction(transaction, blockHash, isSelectedParent,
|
||||
accumulatedUTXODiff, accumulatedMass, selectedParentMedianTime, ghostdagData.BlueScore)
|
||||
accumulatedUTXODiff, accumulatedMass, selectedParentMedianTime, ghostdagData.BlueScore())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -10,22 +10,22 @@ import (
|
||||
)
|
||||
|
||||
func (csm *consensusStateManager) calculateMultiset(
|
||||
acceptanceData model.AcceptanceData, blockGHOSTDAGData *model.BlockGHOSTDAGData) (model.Multiset, error) {
|
||||
acceptanceData model.AcceptanceData, blockGHOSTDAGData model.BlockGHOSTDAGData) (model.Multiset, error) {
|
||||
|
||||
log.Tracef("calculateMultiset start for block with selected parent %s", blockGHOSTDAGData.SelectedParent)
|
||||
defer log.Tracef("calculateMultiset end for block with selected parent %s", blockGHOSTDAGData.SelectedParent)
|
||||
log.Tracef("calculateMultiset start for block with selected parent %s", blockGHOSTDAGData.SelectedParent())
|
||||
defer log.Tracef("calculateMultiset end for block with selected parent %s", blockGHOSTDAGData.SelectedParent())
|
||||
|
||||
if blockGHOSTDAGData.SelectedParent == nil {
|
||||
if blockGHOSTDAGData.SelectedParent() == nil {
|
||||
log.Tracef("Selected parent is nil, which could only happen for the genesis. " +
|
||||
"The genesis, by definition, has an empty multiset")
|
||||
return multiset.New(), nil
|
||||
}
|
||||
|
||||
ms, err := csm.multisetStore.Get(csm.databaseContext, blockGHOSTDAGData.SelectedParent)
|
||||
ms, err := csm.multisetStore.Get(csm.databaseContext, blockGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Tracef("The multiset for the selected parent %s is: %s", blockGHOSTDAGData.SelectedParent, ms.Hash())
|
||||
log.Tracef("The multiset for the selected parent %s is: %s", blockGHOSTDAGData.SelectedParent(), ms.Hash())
|
||||
|
||||
for _, blockAcceptanceData := range acceptanceData {
|
||||
for i, transactionAcceptanceData := range blockAcceptanceData.TransactionAcceptanceData {
|
||||
@ -40,7 +40,7 @@ func (csm *consensusStateManager) calculateMultiset(
|
||||
log.Tracef("Is transaction %s a coinbase transaction: %t", transactionID, isCoinbase)
|
||||
|
||||
var err error
|
||||
err = addTransactionToMultiset(ms, transaction, blockGHOSTDAGData.BlueScore, isCoinbase)
|
||||
err = addTransactionToMultiset(ms, transaction, blockGHOSTDAGData.BlueScore(), isCoinbase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ func (csm *consensusStateManager) boundedMergeBreakingParents(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, redBlock := range virtualGHOSTDAGData.MergeSetReds {
|
||||
for _, redBlock := range virtualGHOSTDAGData.MergeSetReds() {
|
||||
log.Tracef("Check whether red block %s is kosherized", redBlock)
|
||||
isFinalityPointInPast, err := csm.dagTopologyManager.IsAncestorOf(virtualFinalityPoint, redBlock)
|
||||
if err != nil {
|
||||
|
@ -79,7 +79,7 @@ func (csm *consensusStateManager) findSelectedParentStatus(unverifiedBlocks []*e
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return csm.blockStatusStore.Get(csm.databaseContext, lastUnverifiedBlockGHOSTDAGData.SelectedParent)
|
||||
return csm.blockStatusStore.Get(csm.databaseContext, lastUnverifiedBlockGHOSTDAGData.SelectedParent())
|
||||
}
|
||||
|
||||
func (csm *consensusStateManager) getUnverifiedChainBlocks(
|
||||
@ -110,13 +110,13 @@ func (csm *consensusStateManager) getUnverifiedChainBlocks(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if currentBlockGHOSTDAGData.SelectedParent == nil {
|
||||
if currentBlockGHOSTDAGData.SelectedParent() == nil {
|
||||
log.Tracef("Genesis block reached. Returning all the "+
|
||||
"unverified blocks prior to it: %s", unverifiedBlocks)
|
||||
return unverifiedBlocks, nil
|
||||
}
|
||||
|
||||
currentHash = currentBlockGHOSTDAGData.SelectedParent
|
||||
currentHash = currentBlockGHOSTDAGData.SelectedParent()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
type blockHeapNode struct {
|
||||
hash *externalapi.DomainHash
|
||||
ghostdagData *model.BlockGHOSTDAGData
|
||||
ghostdagData model.BlockGHOSTDAGData
|
||||
}
|
||||
|
||||
// baseHeap is an implementation for heap.Interface that sorts blocks by their height
|
||||
|
@ -32,7 +32,7 @@ func (spi *selectedParentIterator) Next() bool {
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("ghostdagDataStore is missing ghostdagData for: %v. '%s' ", spi.current, err))
|
||||
}
|
||||
spi.current = ghostdagData.SelectedParent
|
||||
spi.current = ghostdagData.SelectedParent()
|
||||
return spi.current != nil
|
||||
}
|
||||
|
||||
@ -75,17 +75,17 @@ func (dtm *dagTraversalManager) BlockAtDepth(highHash *externalapi.DomainHash, d
|
||||
}
|
||||
|
||||
requiredBlueScore := uint64(0)
|
||||
if highBlockGHOSTDAGData.BlueScore > depth {
|
||||
requiredBlueScore = highBlockGHOSTDAGData.BlueScore - depth
|
||||
if highBlockGHOSTDAGData.BlueScore() > depth {
|
||||
requiredBlueScore = highBlockGHOSTDAGData.BlueScore() - depth
|
||||
}
|
||||
|
||||
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
|
||||
// If we used `BlockIterator` we'd need to do more calls to `ghostdagDataStore` so we can get the blueScore
|
||||
for currentBlockGHOSTDAGData.BlueScore >= requiredBlueScore {
|
||||
if currentBlockGHOSTDAGData.SelectedParent == nil { // genesis
|
||||
for currentBlockGHOSTDAGData.BlueScore() >= requiredBlueScore {
|
||||
if currentBlockGHOSTDAGData.SelectedParent() == nil { // genesis
|
||||
return currentBlockHash, nil
|
||||
}
|
||||
currentBlockHash = currentBlockGHOSTDAGData.SelectedParent
|
||||
currentBlockHash = currentBlockGHOSTDAGData.SelectedParent()
|
||||
currentBlockGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -104,15 +104,15 @@ func (dtm *dagTraversalManager) LowestChainBlockAboveOrEqualToBlueScore(highHash
|
||||
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
|
||||
iterator := dtm.SelectedParentIterator(highHash)
|
||||
for iterator.Next() {
|
||||
selectedParentBlockGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockGHOSTDAGData.SelectedParent)
|
||||
selectedParentBlockGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if selectedParentBlockGHOSTDAGData.BlueScore < blueScore {
|
||||
if selectedParentBlockGHOSTDAGData.BlueScore() < blueScore {
|
||||
break
|
||||
}
|
||||
currentHash = selectedParentBlockGHOSTDAGData.SelectedParent
|
||||
currentHash = selectedParentBlockGHOSTDAGData.SelectedParent()
|
||||
currentBlockGHOSTDAGData = selectedParentBlockGHOSTDAGData
|
||||
}
|
||||
|
||||
|
@ -15,15 +15,15 @@ func (dtm *dagTraversalManager) BlueWindow(startingBlock *externalapi.DomainHash
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for uint64(len(window)) < windowSize && currentGHOSTDAGData.SelectedParent != nil {
|
||||
for _, blue := range currentGHOSTDAGData.MergeSetBlues {
|
||||
for uint64(len(window)) < windowSize && currentGHOSTDAGData.SelectedParent() != nil {
|
||||
for _, blue := range currentGHOSTDAGData.MergeSetBlues() {
|
||||
window = append(window, blue)
|
||||
if uint64(len(window)) == windowSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
currentHash = currentGHOSTDAGData.SelectedParent
|
||||
currentHash = currentGHOSTDAGData.SelectedParent()
|
||||
currentGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1,12 +1,13 @@
|
||||
package difficultymanager
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DifficultyManager provides a method to resolve the
|
||||
@ -94,7 +95,7 @@ func (dm *difficultyManager) RequiredDifficulty(blockHash *externalapi.DomainHas
|
||||
}
|
||||
|
||||
// Not enough blocks for building a difficulty window.
|
||||
if bluestGhostDAG.BlueScore < dm.difficultyAdjustmentWindowSize+1 {
|
||||
if bluestGhostDAG.BlueScore() < dm.difficultyAdjustmentWindowSize+1 {
|
||||
return dm.genesisBits()
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,203 @@
|
||||
package difficultymanager_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
)
|
||||
|
||||
func TestDifficulty(t *testing.T) {
|
||||
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
|
||||
params.K = 1
|
||||
params.DifficultyAdjustmentWindowSize = 264
|
||||
|
||||
factory := consensus.NewFactory()
|
||||
tc, teardown, err := factory.NewTestConsensus(params, "TestDifficulty")
|
||||
if err != nil {
|
||||
t.Fatalf("Error setting up consensus: %+v", err)
|
||||
}
|
||||
defer teardown()
|
||||
|
||||
addBlock := func(blockTime int64, parents ...*externalapi.DomainHash) (*externalapi.DomainBlock, *externalapi.DomainHash) {
|
||||
bluestParent, err := tc.GHOSTDAGManager().ChooseSelectedParent(parents...)
|
||||
if err != nil {
|
||||
t.Fatalf("ChooseSelectedParent: %+v", err)
|
||||
}
|
||||
|
||||
if blockTime == 0 {
|
||||
header, err := tc.BlockHeaderStore().BlockHeader(tc.DatabaseContext(), bluestParent)
|
||||
if err != nil {
|
||||
t.Fatalf("BlockHeader: %+v", err)
|
||||
}
|
||||
|
||||
blockTime = header.TimeInMilliseconds + params.TargetTimePerBlock.Milliseconds()
|
||||
}
|
||||
|
||||
block, _, err := tc.BuildBlockWithParents(parents, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildBlockWithParents: %+v", err)
|
||||
}
|
||||
|
||||
block.Header.TimeInMilliseconds = blockTime
|
||||
err = tc.ValidateAndInsertBlock(block)
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateAndInsertBlock: %+v", err)
|
||||
}
|
||||
|
||||
return block, consensushashing.BlockHash(block)
|
||||
}
|
||||
|
||||
minimumTime := func(parents ...*externalapi.DomainHash) int64 {
|
||||
var tempHash externalapi.DomainHash
|
||||
tc.BlockRelationStore().StageBlockRelation(&tempHash, &model.BlockRelations{
|
||||
Parents: parents,
|
||||
Children: nil,
|
||||
})
|
||||
defer tc.BlockRelationStore().Discard()
|
||||
|
||||
err = tc.GHOSTDAGManager().GHOSTDAG(&tempHash)
|
||||
if err != nil {
|
||||
t.Fatalf("GHOSTDAG: %+v", err)
|
||||
}
|
||||
defer tc.GHOSTDAGDataStore().Discard()
|
||||
|
||||
pastMedianTime, err := tc.PastMedianTimeManager().PastMedianTime(&tempHash)
|
||||
if err != nil {
|
||||
t.Fatalf("PastMedianTime: %+v", err)
|
||||
}
|
||||
|
||||
return pastMedianTime + 1
|
||||
}
|
||||
|
||||
addBlockWithMinimumTime := func(parents ...*externalapi.DomainHash) (*externalapi.DomainBlock, *externalapi.DomainHash) {
|
||||
minTime := minimumTime(parents...)
|
||||
return addBlock(minTime, parents...)
|
||||
}
|
||||
|
||||
tipHash := params.GenesisHash
|
||||
tip := params.GenesisBlock
|
||||
for i := uint64(0); i < params.DifficultyAdjustmentWindowSize; i++ {
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits != params.GenesisBlock.Header.Bits {
|
||||
t.Fatalf("As long as the bluest parent's blue score is less then the difficulty adjustment " +
|
||||
"window size, the difficulty should be the same as genesis'")
|
||||
}
|
||||
}
|
||||
for i := uint64(0); i < params.DifficultyAdjustmentWindowSize+100; i++ {
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits != params.GenesisBlock.Header.Bits {
|
||||
t.Fatalf("As long as the block rate remains the same, the difficulty shouldn't change")
|
||||
}
|
||||
}
|
||||
|
||||
blockInThePast, tipHash := addBlockWithMinimumTime(tipHash)
|
||||
if blockInThePast.Header.Bits != tip.Header.Bits {
|
||||
t.Fatalf("The difficulty should only change when blockInThePast is in the past of a block bluest parent")
|
||||
}
|
||||
tip = blockInThePast
|
||||
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits != blockInThePast.Header.Bits {
|
||||
t.Fatalf("The difficulty should only change when blockInThePast is in the past of a block bluest parent")
|
||||
}
|
||||
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if compareBits(tip.Header.Bits, blockInThePast.Header.Bits) >= 0 {
|
||||
t.Fatalf("tip.bits should be smaller than blockInThePast.bits because blockInThePast increased the " +
|
||||
"block rate, so the difficulty should increase as well")
|
||||
}
|
||||
|
||||
var expectedBits uint32
|
||||
switch params.Name {
|
||||
case "kaspa-testnet", "kaspa-devnet":
|
||||
expectedBits = uint32(0x1e7f83df)
|
||||
case "kaspa-mainnet", "kaspa-simnet":
|
||||
expectedBits = uint32(0x207f83df)
|
||||
}
|
||||
|
||||
if tip.Header.Bits != expectedBits {
|
||||
t.Errorf("tip.bits was expected to be %x but got %x", expectedBits, tip.Header.Bits)
|
||||
}
|
||||
|
||||
// Increase block rate to increase difficulty
|
||||
for i := uint64(0); i < params.DifficultyAdjustmentWindowSize; i++ {
|
||||
tip, tipHash = addBlockWithMinimumTime(tipHash)
|
||||
tipGHOSTDAGData, err := tc.GHOSTDAGDataStore().Get(tc.DatabaseContext(), tipHash)
|
||||
if err != nil {
|
||||
t.Fatalf("GHOSTDAGDataStore: %+v", err)
|
||||
}
|
||||
|
||||
selectedParentHeader, err := tc.BlockHeaderStore().BlockHeader(tc.DatabaseContext(),
|
||||
tipGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
t.Fatalf("BlockHeader: %+v", err)
|
||||
}
|
||||
|
||||
if compareBits(tip.Header.Bits, selectedParentHeader.Bits) > 0 {
|
||||
t.Fatalf("Because we're increasing the block rate, the difficulty can't decrease")
|
||||
}
|
||||
}
|
||||
|
||||
// Add blocks until difficulty stabilizes
|
||||
lastBits := tip.Header.Bits
|
||||
sameBitsCount := uint64(0)
|
||||
for sameBitsCount < params.DifficultyAdjustmentWindowSize+1 {
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits == lastBits {
|
||||
sameBitsCount++
|
||||
} else {
|
||||
lastBits = tip.Header.Bits
|
||||
sameBitsCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
slowBlockTime := tip.Header.TimeInMilliseconds + params.TargetTimePerBlock.Milliseconds() + 1000
|
||||
slowBlock, tipHash := addBlock(slowBlockTime, tipHash)
|
||||
if slowBlock.Header.Bits != tip.Header.Bits {
|
||||
t.Fatalf("The difficulty should only change when slowBlock is in the past of a block bluest parent")
|
||||
}
|
||||
|
||||
tip = slowBlock
|
||||
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if tip.Header.Bits != slowBlock.Header.Bits {
|
||||
t.Fatalf("The difficulty should only change when slowBlock is in the past of a block bluest parent")
|
||||
}
|
||||
tip, tipHash = addBlock(0, tipHash)
|
||||
if compareBits(tip.Header.Bits, slowBlock.Header.Bits) <= 0 {
|
||||
t.Fatalf("tip.bits should be smaller than slowBlock.bits because slowBlock decreased the block" +
|
||||
" rate, so the difficulty should decrease as well")
|
||||
}
|
||||
|
||||
_, tipHash = addBlock(0, tipHash)
|
||||
splitBlockHash := tipHash
|
||||
for i := 0; i < 100; i++ {
|
||||
_, tipHash = addBlock(0, tipHash)
|
||||
}
|
||||
blueTipHash := tipHash
|
||||
|
||||
redChainTipHash := splitBlockHash
|
||||
for i := 0; i < 10; i++ {
|
||||
_, redChainTipHash = addBlockWithMinimumTime(redChainTipHash)
|
||||
}
|
||||
tipWithRedPast, _ := addBlock(0, redChainTipHash, blueTipHash)
|
||||
tipWithoutRedPast, _ := addBlock(0, blueTipHash)
|
||||
if tipWithoutRedPast.Header.Bits != tipWithRedPast.Header.Bits {
|
||||
t.Fatalf("tipWithoutRedPast.bits should be the same as tipWithRedPast.bits because red blocks" +
|
||||
" shouldn't affect the difficulty")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func compareBits(a uint32, b uint32) int {
|
||||
aTarget := util.CompactToBig(a)
|
||||
bTarget := util.CompactToBig(b)
|
||||
return aTarget.Cmp(bTarget)
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
package ghostdag2
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type ghostdagHelper struct {
|
||||
@ -44,7 +47,7 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blockScore := blockData.BlueScore
|
||||
blockScore := blockData.BlueScore()
|
||||
if blockScore > maxNum {
|
||||
selectedParent = parent
|
||||
maxNum = blockScore
|
||||
@ -91,13 +94,8 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error
|
||||
}
|
||||
myScore += uint64(len(mergeSetBlues))
|
||||
|
||||
e := model.BlockGHOSTDAGData{
|
||||
BlueScore: myScore,
|
||||
SelectedParent: selectedParent,
|
||||
MergeSetBlues: mergeSetBlues,
|
||||
MergeSetReds: mergeSetReds,
|
||||
}
|
||||
gh.dataStore.Stage(blockCandidate, &e)
|
||||
e := ghostdagmanager.NewBlockGHOSTDAGData(myScore, selectedParent, mergeSetBlues, mergeSetReds, nil)
|
||||
gh.dataStore.Stage(blockCandidate, e)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -220,7 +218,7 @@ func (gh *ghostdagHelper) validateKCluster(chain *externalapi.DomainHash, checke
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if mergeSetReds := dataStore.MergeSetReds; contains(checkedBlock, mergeSetReds) {
|
||||
if mergeSetReds := dataStore.MergeSetReds(); contains(checkedBlock, mergeSetReds) {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
@ -326,14 +324,14 @@ func (gh *ghostdagHelper) findBlueSet(blueSet *[]*externalapi.DomainHash, select
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mergeSetBlue := blockData.MergeSetBlues
|
||||
mergeSetBlue := blockData.MergeSetBlues()
|
||||
for _, blue := range mergeSetBlue {
|
||||
if contains(blue, *blueSet) {
|
||||
continue
|
||||
}
|
||||
*blueSet = append(*blueSet, blue)
|
||||
}
|
||||
selectedParent = blockData.SelectedParent
|
||||
selectedParent = blockData.SelectedParent()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -356,10 +354,10 @@ func (gh *ghostdagHelper) sortByBlueScore(arr []*externalapi.DomainHash) error {
|
||||
return false
|
||||
}
|
||||
|
||||
if blockLeft.BlueScore < blockRight.BlueScore {
|
||||
if blockLeft.BlueScore() < blockRight.BlueScore() {
|
||||
return true
|
||||
}
|
||||
if blockLeft.BlueScore == blockRight.BlueScore {
|
||||
if blockLeft.BlueScore() == blockRight.BlueScore() {
|
||||
return ismoreHash(arr[j], arr[i])
|
||||
}
|
||||
return false
|
||||
@ -369,13 +367,13 @@ func (gh *ghostdagHelper) sortByBlueScore(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")
|
||||
}
|
||||
|
@ -53,11 +53,11 @@ 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 {
|
||||
|
||||
blockBlueScoreA := ghostdagDataA.BlueScore
|
||||
blockBlueScoreB := ghostdagDataB.BlueScore
|
||||
blockBlueScoreA := ghostdagDataA.BlueScore()
|
||||
blockBlueScoreB := ghostdagDataB.BlueScore()
|
||||
if blockBlueScoreA == blockBlueScoreB {
|
||||
return hashes.Less(blockHashA, blockHashB)
|
||||
}
|
||||
|
@ -25,10 +25,10 @@ import (
|
||||
//
|
||||
// For further details see the article https://eprint.iacr.org/2018/104.pdf
|
||||
func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
||||
newBlockData := &model.BlockGHOSTDAGData{
|
||||
MergeSetBlues: make([]*externalapi.DomainHash, 0),
|
||||
MergeSetReds: make([]*externalapi.DomainHash, 0),
|
||||
BluesAnticoneSizes: make(map[externalapi.DomainHash]model.KType),
|
||||
newBlockData := &blockGHOSTDAGData{
|
||||
mergeSetBlues: make([]*externalapi.DomainHash, 0),
|
||||
mergeSetReds: make([]*externalapi.DomainHash, 0),
|
||||
bluesAnticoneSizes: make(map[externalapi.DomainHash]model.KType),
|
||||
}
|
||||
|
||||
blockParents, err := gm.dagTopologyManager.Parents(blockHash)
|
||||
@ -43,12 +43,12 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
||||
return err
|
||||
}
|
||||
|
||||
newBlockData.SelectedParent = selectedParent
|
||||
newBlockData.MergeSetBlues = append(newBlockData.MergeSetBlues, selectedParent)
|
||||
newBlockData.BluesAnticoneSizes[*selectedParent] = 0
|
||||
newBlockData.selectedParent = selectedParent
|
||||
newBlockData.mergeSetBlues = append(newBlockData.mergeSetBlues, selectedParent)
|
||||
newBlockData.bluesAnticoneSizes[*selectedParent] = 0
|
||||
}
|
||||
|
||||
mergeSetWithoutSelectedParent, err := gm.mergeSetWithoutSelectedParent(newBlockData.SelectedParent, blockParents)
|
||||
mergeSetWithoutSelectedParent, err := gm.mergeSetWithoutSelectedParent(newBlockData.selectedParent, blockParents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -61,25 +61,25 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
||||
|
||||
if isBlue {
|
||||
// No k-cluster violation found, we can now set the candidate block as blue
|
||||
newBlockData.MergeSetBlues = append(newBlockData.MergeSetBlues, blueCandidate)
|
||||
newBlockData.BluesAnticoneSizes[*blueCandidate] = candidateAnticoneSize
|
||||
newBlockData.mergeSetBlues = append(newBlockData.mergeSetBlues, blueCandidate)
|
||||
newBlockData.bluesAnticoneSizes[*blueCandidate] = candidateAnticoneSize
|
||||
for blue, blueAnticoneSize := range candidateBluesAnticoneSizes {
|
||||
newBlockData.BluesAnticoneSizes[blue] = blueAnticoneSize + 1
|
||||
newBlockData.bluesAnticoneSizes[blue] = blueAnticoneSize + 1
|
||||
}
|
||||
} else {
|
||||
newBlockData.MergeSetReds = append(newBlockData.MergeSetReds, blueCandidate)
|
||||
newBlockData.mergeSetReds = append(newBlockData.mergeSetReds, blueCandidate)
|
||||
}
|
||||
}
|
||||
|
||||
if !isGenesis {
|
||||
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, newBlockData.SelectedParent)
|
||||
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, newBlockData.selectedParent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newBlockData.BlueScore = selectedParentGHOSTDAGData.BlueScore + uint64(len(newBlockData.MergeSetBlues))
|
||||
newBlockData.blueScore = selectedParentGHOSTDAGData.BlueScore() + uint64(len(newBlockData.mergeSetBlues))
|
||||
} else {
|
||||
// Genesis's blue score is defined to be 0.
|
||||
newBlockData.BlueScore = 0
|
||||
newBlockData.blueScore = 0
|
||||
}
|
||||
|
||||
gm.ghostdagDataStore.Stage(blockHash, newBlockData)
|
||||
@ -89,15 +89,15 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
||||
|
||||
type chainBlockData struct {
|
||||
hash *externalapi.DomainHash
|
||||
blockData *model.BlockGHOSTDAGData
|
||||
blockData model.BlockGHOSTDAGData
|
||||
}
|
||||
|
||||
func (gm *ghostdagManager) checkBlueCandidate(newBlockData *model.BlockGHOSTDAGData, blueCandidate *externalapi.DomainHash) (
|
||||
func (gm *ghostdagManager) checkBlueCandidate(newBlockData *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
|
||||
}
|
||||
|
||||
@ -126,12 +126,12 @@ func (gm *ghostdagManager) checkBlueCandidate(newBlockData *model.BlockGHOSTDAGD
|
||||
return false, 0, nil, nil
|
||||
}
|
||||
|
||||
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, chainBlock.blockData.SelectedParent)
|
||||
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, chainBlock.blockData.SelectedParent())
|
||||
if err != nil {
|
||||
return false, 0, nil, err
|
||||
}
|
||||
|
||||
chainBlock = chainBlockData{hash: chainBlock.blockData.SelectedParent,
|
||||
chainBlock = chainBlockData{hash: chainBlock.blockData.SelectedParent(),
|
||||
blockData: selectedParentGHOSTDAGData,
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ func (gm *ghostdagManager) checkBlueCandidate(newBlockData *model.BlockGHOSTDAGD
|
||||
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) {
|
||||
@ -164,7 +164,7 @@ func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData *model.
|
||||
}
|
||||
}
|
||||
|
||||
for _, block := range chainBlock.blockData.MergeSetBlues {
|
||||
for _, block := range chainBlock.blockData.MergeSetBlues() {
|
||||
// Skip blocks that exist in the past of blueCandidate.
|
||||
isAncestorOfBlueCandidate, err := gm.dagTopologyManager.IsAncestorOf(block, blueCandidate)
|
||||
if err != nil {
|
||||
@ -204,16 +204,16 @@ func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData *model.
|
||||
|
||||
// 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 {
|
||||
if blueAnticoneSize, ok := current.BluesAnticoneSizes()[*block]; ok {
|
||||
return blueAnticoneSize, nil
|
||||
}
|
||||
if current.SelectedParent == nil {
|
||||
if current.SelectedParent() == nil {
|
||||
break
|
||||
}
|
||||
var err error
|
||||
current, err = gm.ghostdagDataStore.Get(gm.databaseContext, current.SelectedParent)
|
||||
current, err = gm.ghostdagDataStore.Get(gm.databaseContext, current.SelectedParent())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
51
domain/consensus/processes/ghostdagmanager/ghostdag_data.go
Normal file
51
domain/consensus/processes/ghostdagmanager/ghostdag_data.go
Normal file
@ -0,0 +1,51 @@
|
||||
package ghostdagmanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
type blockGHOSTDAGData struct {
|
||||
blueScore uint64
|
||||
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,
|
||||
selectedParent *externalapi.DomainHash,
|
||||
mergeSetBlues []*externalapi.DomainHash,
|
||||
mergeSetReds []*externalapi.DomainHash,
|
||||
bluesAnticoneSizes map[externalapi.DomainHash]model.KType) model.BlockGHOSTDAGData {
|
||||
|
||||
return &blockGHOSTDAGData{
|
||||
blueScore: blueScore,
|
||||
selectedParent: selectedParent,
|
||||
mergeSetBlues: mergeSetBlues,
|
||||
mergeSetReds: mergeSetReds,
|
||||
bluesAnticoneSizes: bluesAnticoneSizes,
|
||||
}
|
||||
}
|
||||
|
||||
func (bgd *blockGHOSTDAGData) BlueScore() uint64 {
|
||||
return bgd.blueScore
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@ -1,14 +1,17 @@
|
||||
package ghostdagmanager
|
||||
package ghostdagmanager_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdag2"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdag2"
|
||||
)
|
||||
|
||||
// TestGHOSTDAG iterates over several dag simulations, and checks
|
||||
@ -47,15 +50,9 @@ func TestGHOSTDAG(t *testing.T) {
|
||||
}
|
||||
|
||||
ghostdagDataStore := &GHOSTDAGDataStoreImpl{
|
||||
dagMap: make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData),
|
||||
}
|
||||
var blockGHOSTDAGDataGenesis = &model.BlockGHOSTDAGData{
|
||||
BlueScore: 0,
|
||||
SelectedParent: nil,
|
||||
MergeSetBlues: nil,
|
||||
MergeSetReds: nil,
|
||||
BluesAnticoneSizes: nil,
|
||||
dagMap: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData),
|
||||
}
|
||||
blockGHOSTDAGDataGenesis := ghostdagmanager.NewBlockGHOSTDAGData(0, nil, nil, nil, nil)
|
||||
|
||||
var testsCounter int
|
||||
err := filepath.Walk("../../testdata/dags", func(path string, info os.FileInfo, err error) error {
|
||||
@ -87,7 +84,7 @@ func TestGHOSTDAG(t *testing.T) {
|
||||
|
||||
//NOTE: FOR ADDING/REMOVING AN IMPLEMENTATION CHANGE BELOW:
|
||||
implementationFactories := []implManager{
|
||||
{New, "Original"},
|
||||
{ghostdagmanager.New, "Original"},
|
||||
{ghostdag2.New, "Tal's impl"},
|
||||
}
|
||||
|
||||
@ -110,30 +107,30 @@ func TestGHOSTDAG(t *testing.T) {
|
||||
factory.implName, info.Name(), testBlockData.ID, err)
|
||||
}
|
||||
|
||||
if testBlockData.Score != (ghostdagData.BlueScore) {
|
||||
if testBlockData.Score != (ghostdagData.BlueScore()) {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected blue score %d but got %d.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.Score, ghostdagData.BlueScore)
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.Score, ghostdagData.BlueScore())
|
||||
}
|
||||
|
||||
if *StringToByte(testBlockData.SelectedParent) != *ghostdagData.SelectedParent {
|
||||
if *StringToByte(testBlockData.SelectedParent) != *ghostdagData.SelectedParent() {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected selected parent %v but got %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.SelectedParent, string(ghostdagData.SelectedParent[:]))
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.SelectedParent, ghostdagData.SelectedParent())
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetBlues), ghostdagData.MergeSetBlues) {
|
||||
if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetBlues), ghostdagData.MergeSetBlues()) {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set blues %v but got %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetBlues, hashesToStrings(ghostdagData.MergeSetBlues))
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetBlues, hashesToStrings(ghostdagData.MergeSetBlues()))
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetReds), ghostdagData.MergeSetReds) {
|
||||
if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetReds), ghostdagData.MergeSetReds()) {
|
||||
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set reds %v but got %v.",
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetReds, hashesToStrings(ghostdagData.MergeSetReds))
|
||||
factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetReds, hashesToStrings(ghostdagData.MergeSetReds()))
|
||||
}
|
||||
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@ -172,10 +169,10 @@ func StringToByteArray(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
|
||||
}
|
||||
|
||||
@ -191,7 +188,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
|
||||
|
@ -46,7 +46,7 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(blockHash *externalapi.Doma
|
||||
}
|
||||
|
||||
// Return nil on genesis
|
||||
if ghostdagData.SelectedParent == nil {
|
||||
if ghostdagData.SelectedParent() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(blockHash *externalapi.Doma
|
||||
return err
|
||||
}
|
||||
|
||||
for _, red := range ghostdagData.MergeSetReds {
|
||||
for _, red := range ghostdagData.MergeSetReds() {
|
||||
doesRedHaveFinalityPointInPast, err := mdm.dagTopologyManager.IsAncestorOf(finalityPoint, red)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -85,9 +85,9 @@ func (mdm mergeDepthManager) NonBoundedMergeDepthViolatingBlues(blockHash *exter
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonBoundedMergeDepthViolatingBlues := make([]*externalapi.DomainHash, 0, len(ghostdagData.MergeSetBlues))
|
||||
nonBoundedMergeDepthViolatingBlues := make([]*externalapi.DomainHash, 0, len(ghostdagData.MergeSetBlues()))
|
||||
|
||||
for _, blue := range ghostdagData.MergeSetBlues {
|
||||
for _, blue := range ghostdagData.MergeSetBlues() {
|
||||
notViolatingFinality, err := mdm.hasFinalityPointInOthersSelectedChain(blockHash, blue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1,10 +1,11 @@
|
||||
package pastmediantimemanager
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/pkg/errors"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// pastMedianTimeManager provides a method to resolve the
|
||||
@ -44,7 +45,7 @@ func (pmtm *pastMedianTimeManager) PastMedianTime(blockHash *externalapi.DomainH
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
selectedParentHash := blockGHOSTDAGData.SelectedParent
|
||||
selectedParentHash := blockGHOSTDAGData.SelectedParent()
|
||||
|
||||
// Genesis block
|
||||
if selectedParentHash == nil {
|
||||
|
@ -99,14 +99,14 @@ func (pm *pruningManager) FindNextPruningPoint() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentPBlueScore := currentPGhost.BlueScore
|
||||
currentPBlueScore := currentPGhost.BlueScore()
|
||||
// Because the pruning point changes only once per finality, then there's no need to even check for that if a finality interval hasn't passed.
|
||||
if virtual.BlueScore <= currentPBlueScore+pm.finalityInterval {
|
||||
if virtual.BlueScore() <= currentPBlueScore+pm.finalityInterval {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This means the pruning point is still genesis.
|
||||
if virtual.BlueScore <= pm.pruningDepth+pm.finalityInterval {
|
||||
if virtual.BlueScore() <= pm.pruningDepth+pm.finalityInterval {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ func (pm *pruningManager) FindNextPruningPoint() error {
|
||||
}
|
||||
|
||||
// Actually check if the pruning point changed
|
||||
if (currentPBlueScore / pm.finalityInterval) < (candidatePGhost.BlueScore / pm.finalityInterval) {
|
||||
if (currentPBlueScore / pm.finalityInterval) < (candidatePGhost.BlueScore() / pm.finalityInterval) {
|
||||
err = pm.savePruningPoint(candidatePHash)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -45,7 +45,7 @@ func (rt *reachabilityManager) AddBlock(blockHash *externalapi.DomainHash) error
|
||||
}
|
||||
|
||||
// If this is the genesis node, simply initialize it and return
|
||||
if ghostdagData.SelectedParent == nil {
|
||||
if ghostdagData.SelectedParent() == nil {
|
||||
rt.stageReindexRoot(blockHash)
|
||||
return nil
|
||||
}
|
||||
@ -56,16 +56,16 @@ func (rt *reachabilityManager) AddBlock(blockHash *externalapi.DomainHash) error
|
||||
}
|
||||
|
||||
// Insert the node into the selected parent's reachability tree
|
||||
err = rt.addChild(ghostdagData.SelectedParent, blockHash, reindexRoot)
|
||||
err = rt.addChild(ghostdagData.SelectedParent(), blockHash, reindexRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add the block to the futureCoveringSets of all the blocks
|
||||
// in the merget set
|
||||
mergeSet := make([]*externalapi.DomainHash, len(ghostdagData.MergeSetBlues)+len(ghostdagData.MergeSetReds))
|
||||
copy(mergeSet, ghostdagData.MergeSetBlues)
|
||||
copy(mergeSet[len(ghostdagData.MergeSetBlues):], ghostdagData.MergeSetReds)
|
||||
mergeSet := make([]*externalapi.DomainHash, len(ghostdagData.MergeSetBlues())+len(ghostdagData.MergeSetReds()))
|
||||
copy(mergeSet, ghostdagData.MergeSetBlues())
|
||||
copy(mergeSet[len(ghostdagData.MergeSetBlues()):], ghostdagData.MergeSetReds())
|
||||
|
||||
for _, current := range mergeSet {
|
||||
err = rt.insertToFutureCoveringSet(current, blockHash)
|
||||
|
@ -814,7 +814,7 @@ func (rt *reachabilityManager) maybeMoveReindexRoot(reindexRoot, newTreeNode *ex
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if newTreeNodeGHOSTDAGData.BlueScore-reindexRootChosenChildGHOSTDAGData.BlueScore < rt.reindexWindow {
|
||||
if newTreeNodeGHOSTDAGData.BlueScore()-reindexRootChosenChildGHOSTDAGData.BlueScore() < rt.reindexWindow {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
|
@ -16,12 +16,12 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore
|
||||
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore()
|
||||
highBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, highHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
highBlockBlueScore := highBlockGHOSTDAGData.BlueScore
|
||||
highBlockBlueScore := highBlockGHOSTDAGData.BlueScore()
|
||||
if lowBlockBlueScore >= highBlockBlueScore {
|
||||
return nil, errors.Errorf("low hash blueScore >= high hash blueScore (%d >= %d)",
|
||||
lowBlockBlueScore, highBlockBlueScore)
|
||||
@ -37,7 +37,7 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
||||
// fairly accurate because we presume that most DAG blocks are
|
||||
// blue.
|
||||
for highBlockBlueScore-lowBlockBlueScore+1 > maxHashesInAntiPastHashesBetween {
|
||||
highHash = highBlockGHOSTDAGData.SelectedParent
|
||||
highHash = highBlockGHOSTDAGData.SelectedParent()
|
||||
}
|
||||
|
||||
// Collect every node in highHash's past (including itself) but
|
||||
|
@ -14,13 +14,13 @@ func (sm *syncManager) createBlockLocator(lowHash, highHash *externalapi.DomainH
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
highHash = highBlockGHOSTDAGData.SelectedParent
|
||||
highHash = highBlockGHOSTDAGData.SelectedParent()
|
||||
|
||||
lowBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, lowHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore
|
||||
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore()
|
||||
|
||||
currentHash := highHash
|
||||
step := uint64(1)
|
||||
@ -32,7 +32,7 @@ func (sm *syncManager) createBlockLocator(lowHash, highHash *externalapi.DomainH
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentBlockBlueScore := currentBlockGHOSTDAGData.BlueScore
|
||||
currentBlockBlueScore := currentBlockGHOSTDAGData.BlueScore()
|
||||
|
||||
// Nothing more to add once the low node has been added.
|
||||
if currentBlockBlueScore <= lowBlockBlueScore {
|
||||
@ -47,7 +47,7 @@ func (sm *syncManager) createBlockLocator(lowHash, highHash *externalapi.DomainH
|
||||
// final node is lowNode.
|
||||
nextBlueScore := currentBlockBlueScore - step
|
||||
if currentBlockBlueScore < step {
|
||||
nextBlueScore = lowBlockGHOSTDAGData.BlueScore
|
||||
nextBlueScore = lowBlockGHOSTDAGData.BlueScore()
|
||||
}
|
||||
|
||||
// Walk down currentHash's selected parent chain to the appropriate ancestor
|
||||
|
@ -91,7 +91,7 @@ func (sm *syncManager) virtualSelectedParentHash() (*externalapi.DomainHash, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return virtualGHOSTDAGData.SelectedParent, nil
|
||||
return virtualGHOSTDAGData.SelectedParent(), nil
|
||||
}
|
||||
|
||||
func (sm *syncManager) headerVirtualSelectedParentHash() (*externalapi.DomainHash, error) {
|
||||
|
@ -59,7 +59,7 @@ func (v *transactionValidator) checkTransactionCoinbaseMaturity(
|
||||
return err
|
||||
}
|
||||
|
||||
txBlueScore := ghostdagData.BlueScore
|
||||
txBlueScore := ghostdagData.BlueScore()
|
||||
var missingOutpoints []*externalapi.DomainOutpoint
|
||||
for _, input := range tx.Inputs {
|
||||
utxoEntry := input.UTXOEntry
|
||||
@ -166,7 +166,7 @@ func (v *transactionValidator) checkTransactionSequenceLock(povBlockHash *extern
|
||||
return err
|
||||
}
|
||||
|
||||
if !v.sequenceLockActive(sequenceLock, ghostdagData.BlueScore, medianTime) {
|
||||
if !v.sequenceLockActive(sequenceLock, ghostdagData.BlueScore(), medianTime) {
|
||||
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains "+
|
||||
"transaction whose input sequence "+
|
||||
"locks are not met")
|
||||
@ -270,16 +270,16 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
||||
|
||||
for {
|
||||
selectedParentGHOSTDAGData, err := v.ghostdagDataStore.Get(v.databaseContext,
|
||||
baseGHOSTDAGData.SelectedParent)
|
||||
baseGHOSTDAGData.SelectedParent())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if selectedParentGHOSTDAGData.BlueScore <= inputBlueScore {
|
||||
if selectedParentGHOSTDAGData.BlueScore() <= inputBlueScore {
|
||||
break
|
||||
}
|
||||
|
||||
baseHash = baseGHOSTDAGData.SelectedParent
|
||||
baseHash = baseGHOSTDAGData.SelectedParent()
|
||||
baseGHOSTDAGData = selectedParentGHOSTDAGData
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user