mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-07 14:46:44 +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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blockInfo.BlueScore = ghostdagData.BlueScore
|
blockInfo.BlueScore = ghostdagData.BlueScore()
|
||||||
|
|
||||||
isBlockInHeaderPruningPointFuture, err := s.syncManager.IsBlockInHeaderPruningPointFuture(blockHash)
|
isBlockInHeaderPruningPointFuture, err := s.syncManager.IsBlockInHeaderPruningPointFuture(blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -196,7 +196,7 @@ func (s *consensus) GetVirtualSelectedParent() (*externalapi.DomainBlock, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
func (s *consensus) CreateBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) {
|
||||||
|
@ -3,26 +3,27 @@ package serialization
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockGHOSTDAGDataToDBBlockGHOSTDAGData converts BlockGHOSTDAGData to DbBlockGhostdagData
|
// BlockGHOSTDAGDataToDBBlockGHOSTDAGData converts BlockGHOSTDAGData to DbBlockGhostdagData
|
||||||
func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData *model.BlockGHOSTDAGData) *DbBlockGhostdagData {
|
func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData model.BlockGHOSTDAGData) *DbBlockGhostdagData {
|
||||||
var selectedParent *DbHash
|
var selectedParent *DbHash
|
||||||
if blockGHOSTDAGData.SelectedParent != nil {
|
if blockGHOSTDAGData.SelectedParent() != nil {
|
||||||
selectedParent = DomainHashToDbHash(blockGHOSTDAGData.SelectedParent)
|
selectedParent = DomainHashToDbHash(blockGHOSTDAGData.SelectedParent())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DbBlockGhostdagData{
|
return &DbBlockGhostdagData{
|
||||||
BlueScore: blockGHOSTDAGData.BlueScore,
|
BlueScore: blockGHOSTDAGData.BlueScore(),
|
||||||
SelectedParent: selectedParent,
|
SelectedParent: selectedParent,
|
||||||
MergeSetBlues: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetBlues),
|
MergeSetBlues: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetBlues()),
|
||||||
MergeSetReds: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetReds),
|
MergeSetReds: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetReds()),
|
||||||
BluesAnticoneSizes: bluesAnticoneSizesToDBBluesAnticoneSizes(blockGHOSTDAGData.BluesAnticoneSizes),
|
BluesAnticoneSizes: bluesAnticoneSizesToDBBluesAnticoneSizes(blockGHOSTDAGData.BluesAnticoneSizes()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DBBlockGHOSTDAGDataToBlockGHOSTDAGData converts DbBlockGhostdagData to BlockGHOSTDAGData
|
// DBBlockGHOSTDAGDataToBlockGHOSTDAGData converts DbBlockGhostdagData to BlockGHOSTDAGData
|
||||||
func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdagData) (*model.BlockGHOSTDAGData, error) {
|
func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdagData) (model.BlockGHOSTDAGData, error) {
|
||||||
var selectedParent *externalapi.DomainHash
|
var selectedParent *externalapi.DomainHash
|
||||||
if dbBlockGHOSTDAGData.SelectedParent != nil {
|
if dbBlockGHOSTDAGData.SelectedParent != nil {
|
||||||
var err error
|
var err error
|
||||||
@ -47,11 +48,11 @@ func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdag
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &model.BlockGHOSTDAGData{
|
return ghostdagmanager.NewBlockGHOSTDAGData(
|
||||||
BlueScore: dbBlockGHOSTDAGData.BlueScore,
|
dbBlockGHOSTDAGData.BlueScore,
|
||||||
SelectedParent: selectedParent,
|
selectedParent,
|
||||||
MergeSetBlues: mergetSetBlues,
|
mergetSetBlues,
|
||||||
MergeSetReds: mergetSetReds,
|
mergetSetReds,
|
||||||
BluesAnticoneSizes: bluesAnticoneSizes,
|
bluesAnticoneSizes,
|
||||||
}, nil
|
), nil
|
||||||
}
|
}
|
||||||
|
@ -13,21 +13,21 @@ var bucket = dbkeys.MakeBucket([]byte("block-ghostdag-data"))
|
|||||||
|
|
||||||
// ghostdagDataStore represents a store of BlockGHOSTDAGData
|
// ghostdagDataStore represents a store of BlockGHOSTDAGData
|
||||||
type ghostdagDataStore struct {
|
type ghostdagDataStore struct {
|
||||||
staging map[externalapi.DomainHash]*model.BlockGHOSTDAGData
|
staging map[externalapi.DomainHash]model.BlockGHOSTDAGData
|
||||||
cache *lrucache.LRUCache
|
cache *lrucache.LRUCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// New instantiates a new GHOSTDAGDataStore
|
// New instantiates a new GHOSTDAGDataStore
|
||||||
func New(cacheSize int) model.GHOSTDAGDataStore {
|
func New(cacheSize int) model.GHOSTDAGDataStore {
|
||||||
return &ghostdagDataStore{
|
return &ghostdagDataStore{
|
||||||
staging: make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData),
|
staging: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData),
|
||||||
cache: lrucache.New(cacheSize),
|
cache: lrucache.New(cacheSize),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stage stages the given blockGHOSTDAGData for the given blockHash
|
// 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.Clone()
|
gds.staging[*blockHash] = blockGHOSTDAGData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gds *ghostdagDataStore) IsStaged() bool {
|
func (gds *ghostdagDataStore) IsStaged() bool {
|
||||||
@ -35,7 +35,7 @@ func (gds *ghostdagDataStore) IsStaged() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gds *ghostdagDataStore) Discard() {
|
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 {
|
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
|
// 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 {
|
if blockGHOSTDAGData, ok := gds.staging[*blockHash]; ok {
|
||||||
return blockGHOSTDAGData.Clone(), nil
|
return blockGHOSTDAGData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if blockGHOSTDAGData, ok := gds.cache.Get(blockHash); ok {
|
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))
|
blockGHOSTDAGDataBytes, err := dbContext.Get(gds.hashAsKey(blockHash))
|
||||||
@ -75,18 +75,18 @@ func (gds *ghostdagDataStore) Get(dbContext model.DBReader, blockHash *externala
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
gds.cache.Add(blockHash, blockGHOSTDAGData)
|
gds.cache.Add(blockHash, blockGHOSTDAGData)
|
||||||
return blockGHOSTDAGData.Clone(), nil
|
return blockGHOSTDAGData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gds *ghostdagDataStore) hashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
func (gds *ghostdagDataStore) hashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
||||||
return bucket.Key(hash[:])
|
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))
|
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{}
|
dbBlockGHOSTDAGData := &serialization.DbBlockGhostdagData{}
|
||||||
err := proto.Unmarshal(blockGHOSTDAGDataBytes, dbBlockGHOSTDAGData)
|
err := proto.Unmarshal(blockGHOSTDAGDataBytes, dbBlockGHOSTDAGData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -63,24 +63,23 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
|||||||
dbManager := consensusdatabase.New(db)
|
dbManager := consensusdatabase.New(db)
|
||||||
|
|
||||||
// Data Structures
|
// Data Structures
|
||||||
storeCacheSize := 200
|
acceptanceDataStore := acceptancedatastore.New(200)
|
||||||
acceptanceDataStore := acceptancedatastore.New(storeCacheSize)
|
blockStore, err := blockstore.New(dbManager, 200)
|
||||||
blockStore, err := blockstore.New(dbManager, storeCacheSize)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
blockHeaderStore, err := blockheaderstore.New(dbManager, storeCacheSize)
|
blockHeaderStore, err := blockheaderstore.New(dbManager, 10_000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
blockRelationStore := blockrelationstore.New(storeCacheSize)
|
blockRelationStore := blockrelationstore.New(200)
|
||||||
blockStatusStore := blockstatusstore.New(storeCacheSize)
|
blockStatusStore := blockstatusstore.New(200)
|
||||||
multisetStore := multisetstore.New(storeCacheSize)
|
multisetStore := multisetstore.New(200)
|
||||||
pruningStore := pruningstore.New()
|
pruningStore := pruningstore.New()
|
||||||
reachabilityDataStore := reachabilitydatastore.New(storeCacheSize)
|
reachabilityDataStore := reachabilitydatastore.New(200)
|
||||||
utxoDiffStore := utxodiffstore.New(storeCacheSize)
|
utxoDiffStore := utxodiffstore.New(200)
|
||||||
consensusStateStore := consensusstatestore.New()
|
consensusStateStore := consensusstatestore.New()
|
||||||
ghostdagDataStore := ghostdagdatastore.New(storeCacheSize)
|
ghostdagDataStore := ghostdagdatastore.New(10_000)
|
||||||
headerTipsStore := headertipsstore.New()
|
headerTipsStore := headertipsstore.New()
|
||||||
|
|
||||||
// Processes
|
// 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)
|
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")
|
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
|
// Make sure it's actually blue
|
||||||
found := false
|
found := false
|
||||||
for _, blue := range virtualGhotDagData.MergeSetBlues {
|
for _, blue := range virtualGhotDagData.MergeSetBlues() {
|
||||||
if *blue == *kosherizingBlockHash {
|
if *blue == *kosherizingBlockHash {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
@ -356,7 +356,7 @@ func TestBoundedMergeDepth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Make sure it's actually blue
|
// Make sure it's actually blue
|
||||||
found = false
|
found = false
|
||||||
for _, blue := range virtualGhotDagData.MergeSetBlues {
|
for _, blue := range virtualGhotDagData.MergeSetBlues() {
|
||||||
if *blue == *kosherizingBlockHash {
|
if *blue == *kosherizingBlockHash {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
|
@ -3,32 +3,12 @@ package model
|
|||||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
|
||||||
// BlockGHOSTDAGData represents GHOSTDAG data for some block
|
// BlockGHOSTDAGData represents GHOSTDAG data for some block
|
||||||
type BlockGHOSTDAGData struct {
|
type BlockGHOSTDAGData interface {
|
||||||
BlueScore uint64
|
BlueScore() uint64
|
||||||
SelectedParent *externalapi.DomainHash
|
SelectedParent() *externalapi.DomainHash
|
||||||
MergeSetBlues []*externalapi.DomainHash
|
MergeSetBlues() []*externalapi.DomainHash
|
||||||
MergeSetReds []*externalapi.DomainHash
|
MergeSetReds() []*externalapi.DomainHash
|
||||||
BluesAnticoneSizes map[externalapi.DomainHash]KType
|
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// KType defines the size of GHOSTDAG consensus algorithm K parameter.
|
// 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
|
// GHOSTDAGDataStore represents a store of BlockGHOSTDAGData
|
||||||
type GHOSTDAGDataStore interface {
|
type GHOSTDAGDataStore interface {
|
||||||
Store
|
Store
|
||||||
Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData *BlockGHOSTDAGData)
|
Stage(blockHash *externalapi.DomainHash, blockGHOSTDAGData BlockGHOSTDAGData)
|
||||||
IsStaged() bool
|
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 {
|
type GHOSTDAGManager interface {
|
||||||
GHOSTDAG(blockHash *externalapi.DomainHash) error
|
GHOSTDAG(blockHash *externalapi.DomainHash) error
|
||||||
ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error)
|
ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error)
|
||||||
Less(blockHashA *externalapi.DomainHash, ghostdagDataA *BlockGHOSTDAGData,
|
Less(blockHashA *externalapi.DomainHash, ghostdagDataA BlockGHOSTDAGData,
|
||||||
blockHashB *externalapi.DomainHash, ghostdagDataB *BlockGHOSTDAGData) bool
|
blockHashB *externalapi.DomainHash, ghostdagDataB BlockGHOSTDAGData) bool
|
||||||
}
|
}
|
||||||
|
@ -96,13 +96,13 @@ func (bb *testBlockBuilder) buildBlockWithParents(parentHashes []*externalapi.Do
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent)
|
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if selectedParentStatus == externalapi.StatusDisqualifiedFromChain {
|
if selectedParentStatus == externalapi.StatusDisqualifiedFromChain {
|
||||||
return nil, nil, errors.Errorf("Error building block with selectedParent %s with status DisqualifiedFromChain",
|
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)
|
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("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",
|
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 {
|
if logClosureErr != nil {
|
||||||
return logClosureErr
|
return logClosureErr
|
||||||
|
@ -39,7 +39,7 @@ func (v *blockValidator) checkBlockTransactionsFinalized(blockHash *externalapi.
|
|||||||
|
|
||||||
// Ensure all transactions in the block are finalized.
|
// Ensure all transactions in the block are finalized.
|
||||||
for _, tx := range block.Transactions {
|
for _, tx := range block.Transactions {
|
||||||
if !v.isFinalizedTransaction(tx, ghostdagData.BlueScore, blockTime) {
|
if !v.isFinalizedTransaction(tx, ghostdagData.BlueScore(), blockTime) {
|
||||||
txID := consensushashing.TransactionID(tx)
|
txID := consensushashing.TransactionID(tx)
|
||||||
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains unfinalized "+
|
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains unfinalized "+
|
||||||
"transaction %s", txID)
|
"transaction %s", txID)
|
||||||
|
@ -115,7 +115,7 @@ func (v *blockValidator) checkMergeSizeLimit(hash *externalapi.DomainHash) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeSetSize := len(ghostdagData.MergeSetReds) + len(ghostdagData.MergeSetBlues)
|
mergeSetSize := len(ghostdagData.MergeSetReds()) + len(ghostdagData.MergeSetBlues())
|
||||||
|
|
||||||
if uint64(mergeSetSize) > v.mergeSetSizeLimit {
|
if uint64(mergeSetSize) > v.mergeSetSizeLimit {
|
||||||
return errors.Wrapf(ruleerrors.ErrViolatingMergeLimit,
|
return errors.Wrapf(ruleerrors.ErrViolatingMergeLimit,
|
||||||
|
@ -31,8 +31,8 @@ func (c coinbaseManager) ExpectedCoinbaseTransaction(blockHash *externalapi.Doma
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues))
|
txOuts := make([]*externalapi.DomainTransactionOutput, 0, len(ghostdagData.MergeSetBlues()))
|
||||||
for i, blue := range ghostdagData.MergeSetBlues {
|
for i, blue := range ghostdagData.MergeSetBlues() {
|
||||||
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(blue, acceptanceData[i])
|
txOut, hasReward, err := c.coinbaseOutputForBlueBlock(blue, acceptanceData[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ func (c coinbaseManager) calcBlockSubsidy(blockHash *externalapi.DomainHash) (ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Equivalent to: baseSubsidy / 2^(blueScore/subsidyHalvingInterval)
|
// 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
|
// New instantiates a new CoinbaseManager
|
||||||
|
@ -80,8 +80,8 @@ func (csm *consensusStateManager) isNextVirtualSelectedParent(blockHash *externa
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Tracef("Selecting the next selected parent between "+
|
log.Tracef("Selecting the next selected parent between "+
|
||||||
"the block %s the current selected parent %s", blockHash, virtualGhostdagData.SelectedParent)
|
"the block %s the current selected parent %s", blockHash, virtualGhostdagData.SelectedParent())
|
||||||
nextVirtualSelectedParent, err := csm.ghostdagManager.ChooseSelectedParent(virtualGhostdagData.SelectedParent, blockHash)
|
nextVirtualSelectedParent, err := csm.ghostdagManager.ChooseSelectedParent(virtualGhostdagData.SelectedParent(), blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ func (csm *consensusStateManager) CalculatePastUTXOAndAcceptanceData(blockHash *
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Tracef("Restoring the past UTXO of block %s with selectedParent %s",
|
log.Tracef("Restoring the past UTXO of block %s with selectedParent %s",
|
||||||
blockHash, blockGHOSTDAGData.SelectedParent)
|
blockHash, blockGHOSTDAGData.SelectedParent())
|
||||||
selectedParentPastUTXO, err := csm.restorePastUTXO(blockGHOSTDAGData.SelectedParent)
|
selectedParentPastUTXO, err := csm.restorePastUTXO(blockGHOSTDAGData.SelectedParent())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@ -108,13 +108,13 @@ func (csm *consensusStateManager) restorePastUTXO(blockHash *externalapi.DomainH
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (csm *consensusStateManager) applyBlueBlocks(blockHash *externalapi.DomainHash,
|
func (csm *consensusStateManager) applyBlueBlocks(blockHash *externalapi.DomainHash,
|
||||||
selectedParentPastUTXODiff model.MutableUTXODiff, ghostdagData *model.BlockGHOSTDAGData) (
|
selectedParentPastUTXODiff model.MutableUTXODiff, ghostdagData model.BlockGHOSTDAGData) (
|
||||||
model.AcceptanceData, model.MutableUTXODiff, error) {
|
model.AcceptanceData, model.MutableUTXODiff, error) {
|
||||||
|
|
||||||
log.Tracef("applyBlueBlocks start for block %s", blockHash)
|
log.Tracef("applyBlueBlocks start for block %s", blockHash)
|
||||||
defer log.Tracef("applyBlueBlocks end 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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ func (csm *consensusStateManager) applyBlueBlocks(blockHash *externalapi.DomainH
|
|||||||
transactionID, blueBlockHash)
|
transactionID, blueBlockHash)
|
||||||
|
|
||||||
isAccepted, accumulatedMass, err = csm.maybeAcceptTransaction(transaction, blockHash, isSelectedParent,
|
isAccepted, accumulatedMass, err = csm.maybeAcceptTransaction(transaction, blockHash, isSelectedParent,
|
||||||
accumulatedUTXODiff, accumulatedMass, selectedParentMedianTime, ghostdagData.BlueScore)
|
accumulatedUTXODiff, accumulatedMass, selectedParentMedianTime, ghostdagData.BlueScore())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -10,22 +10,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (csm *consensusStateManager) calculateMultiset(
|
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)
|
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)
|
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. " +
|
log.Tracef("Selected parent is nil, which could only happen for the genesis. " +
|
||||||
"The genesis, by definition, has an empty multiset")
|
"The genesis, by definition, has an empty multiset")
|
||||||
return multiset.New(), nil
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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 _, blockAcceptanceData := range acceptanceData {
|
||||||
for i, transactionAcceptanceData := range blockAcceptanceData.TransactionAcceptanceData {
|
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)
|
log.Tracef("Is transaction %s a coinbase transaction: %t", transactionID, isCoinbase)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
err = addTransactionToMultiset(ms, transaction, blockGHOSTDAGData.BlueScore, isCoinbase)
|
err = addTransactionToMultiset(ms, transaction, blockGHOSTDAGData.BlueScore(), isCoinbase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ func (csm *consensusStateManager) boundedMergeBreakingParents(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, redBlock := range virtualGHOSTDAGData.MergeSetReds {
|
for _, redBlock := range virtualGHOSTDAGData.MergeSetReds() {
|
||||||
log.Tracef("Check whether red block %s is kosherized", redBlock)
|
log.Tracef("Check whether red block %s is kosherized", redBlock)
|
||||||
isFinalityPointInPast, err := csm.dagTopologyManager.IsAncestorOf(virtualFinalityPoint, redBlock)
|
isFinalityPointInPast, err := csm.dagTopologyManager.IsAncestorOf(virtualFinalityPoint, redBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -79,7 +79,7 @@ func (csm *consensusStateManager) findSelectedParentStatus(unverifiedBlocks []*e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return csm.blockStatusStore.Get(csm.databaseContext, lastUnverifiedBlockGHOSTDAGData.SelectedParent)
|
return csm.blockStatusStore.Get(csm.databaseContext, lastUnverifiedBlockGHOSTDAGData.SelectedParent())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (csm *consensusStateManager) getUnverifiedChainBlocks(
|
func (csm *consensusStateManager) getUnverifiedChainBlocks(
|
||||||
@ -110,13 +110,13 @@ func (csm *consensusStateManager) getUnverifiedChainBlocks(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentBlockGHOSTDAGData.SelectedParent == nil {
|
if currentBlockGHOSTDAGData.SelectedParent() == nil {
|
||||||
log.Tracef("Genesis block reached. Returning all the "+
|
log.Tracef("Genesis block reached. Returning all the "+
|
||||||
"unverified blocks prior to it: %s", unverifiedBlocks)
|
"unverified blocks prior to it: %s", unverifiedBlocks)
|
||||||
return unverifiedBlocks, nil
|
return unverifiedBlocks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
currentHash = currentBlockGHOSTDAGData.SelectedParent
|
currentHash = currentBlockGHOSTDAGData.SelectedParent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type blockHeapNode struct {
|
type blockHeapNode struct {
|
||||||
hash *externalapi.DomainHash
|
hash *externalapi.DomainHash
|
||||||
ghostdagData *model.BlockGHOSTDAGData
|
ghostdagData model.BlockGHOSTDAGData
|
||||||
}
|
}
|
||||||
|
|
||||||
// baseHeap is an implementation for heap.Interface that sorts blocks by their height
|
// 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 {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("ghostdagDataStore is missing ghostdagData for: %v. '%s' ", spi.current, err))
|
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
|
return spi.current != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,17 +75,17 @@ func (dtm *dagTraversalManager) BlockAtDepth(highHash *externalapi.DomainHash, d
|
|||||||
}
|
}
|
||||||
|
|
||||||
requiredBlueScore := uint64(0)
|
requiredBlueScore := uint64(0)
|
||||||
if highBlockGHOSTDAGData.BlueScore > depth {
|
if highBlockGHOSTDAGData.BlueScore() > depth {
|
||||||
requiredBlueScore = highBlockGHOSTDAGData.BlueScore - depth
|
requiredBlueScore = highBlockGHOSTDAGData.BlueScore() - depth
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
|
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
|
||||||
// If we used `BlockIterator` we'd need to do more calls to `ghostdagDataStore` so we can get the blueScore
|
// If we used `BlockIterator` we'd need to do more calls to `ghostdagDataStore` so we can get the blueScore
|
||||||
for currentBlockGHOSTDAGData.BlueScore >= requiredBlueScore {
|
for currentBlockGHOSTDAGData.BlueScore() >= requiredBlueScore {
|
||||||
if currentBlockGHOSTDAGData.SelectedParent == nil { // genesis
|
if currentBlockGHOSTDAGData.SelectedParent() == nil { // genesis
|
||||||
return currentBlockHash, nil
|
return currentBlockHash, nil
|
||||||
}
|
}
|
||||||
currentBlockHash = currentBlockGHOSTDAGData.SelectedParent
|
currentBlockHash = currentBlockGHOSTDAGData.SelectedParent()
|
||||||
currentBlockGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockHash)
|
currentBlockGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -104,15 +104,15 @@ func (dtm *dagTraversalManager) LowestChainBlockAboveOrEqualToBlueScore(highHash
|
|||||||
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
|
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
|
||||||
iterator := dtm.SelectedParentIterator(highHash)
|
iterator := dtm.SelectedParentIterator(highHash)
|
||||||
for iterator.Next() {
|
for iterator.Next() {
|
||||||
selectedParentBlockGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockGHOSTDAGData.SelectedParent)
|
selectedParentBlockGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentBlockGHOSTDAGData.SelectedParent())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if selectedParentBlockGHOSTDAGData.BlueScore < blueScore {
|
if selectedParentBlockGHOSTDAGData.BlueScore() < blueScore {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
currentHash = selectedParentBlockGHOSTDAGData.SelectedParent
|
currentHash = selectedParentBlockGHOSTDAGData.SelectedParent()
|
||||||
currentBlockGHOSTDAGData = selectedParentBlockGHOSTDAGData
|
currentBlockGHOSTDAGData = selectedParentBlockGHOSTDAGData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@ func (dtm *dagTraversalManager) BlueWindow(startingBlock *externalapi.DomainHash
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for uint64(len(window)) < windowSize && currentGHOSTDAGData.SelectedParent != nil {
|
for uint64(len(window)) < windowSize && currentGHOSTDAGData.SelectedParent() != nil {
|
||||||
for _, blue := range currentGHOSTDAGData.MergeSetBlues {
|
for _, blue := range currentGHOSTDAGData.MergeSetBlues() {
|
||||||
window = append(window, blue)
|
window = append(window, blue)
|
||||||
if uint64(len(window)) == windowSize {
|
if uint64(len(window)) == windowSize {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentHash = currentGHOSTDAGData.SelectedParent
|
currentHash = currentGHOSTDAGData.SelectedParent()
|
||||||
currentGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash)
|
currentGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package difficultymanager
|
package difficultymanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/util"
|
"github.com/kaspanet/kaspad/util"
|
||||||
"github.com/kaspanet/kaspad/util/bigintpool"
|
"github.com/kaspanet/kaspad/util/bigintpool"
|
||||||
"math/big"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DifficultyManager provides a method to resolve the
|
// 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.
|
// Not enough blocks for building a difficulty window.
|
||||||
if bluestGhostDAG.BlueScore < dm.difficultyAdjustmentWindowSize+1 {
|
if bluestGhostDAG.BlueScore() < dm.difficultyAdjustmentWindowSize+1 {
|
||||||
return dm.genesisBits()
|
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
|
package ghostdag2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ghostdagHelper struct {
|
type ghostdagHelper struct {
|
||||||
@ -44,7 +47,7 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
blockScore := blockData.BlueScore
|
blockScore := blockData.BlueScore()
|
||||||
if blockScore > maxNum {
|
if blockScore > maxNum {
|
||||||
selectedParent = parent
|
selectedParent = parent
|
||||||
maxNum = blockScore
|
maxNum = blockScore
|
||||||
@ -91,13 +94,8 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error
|
|||||||
}
|
}
|
||||||
myScore += uint64(len(mergeSetBlues))
|
myScore += uint64(len(mergeSetBlues))
|
||||||
|
|
||||||
e := model.BlockGHOSTDAGData{
|
e := ghostdagmanager.NewBlockGHOSTDAGData(myScore, selectedParent, mergeSetBlues, mergeSetReds, nil)
|
||||||
BlueScore: myScore,
|
gh.dataStore.Stage(blockCandidate, e)
|
||||||
SelectedParent: selectedParent,
|
|
||||||
MergeSetBlues: mergeSetBlues,
|
|
||||||
MergeSetReds: mergeSetReds,
|
|
||||||
}
|
|
||||||
gh.dataStore.Stage(blockCandidate, &e)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +218,7 @@ func (gh *ghostdagHelper) validateKCluster(chain *externalapi.DomainHash, checke
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if mergeSetReds := dataStore.MergeSetReds; contains(checkedBlock, mergeSetReds) {
|
if mergeSetReds := dataStore.MergeSetReds(); contains(checkedBlock, mergeSetReds) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -326,14 +324,14 @@ func (gh *ghostdagHelper) findBlueSet(blueSet *[]*externalapi.DomainHash, select
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mergeSetBlue := blockData.MergeSetBlues
|
mergeSetBlue := blockData.MergeSetBlues()
|
||||||
for _, blue := range mergeSetBlue {
|
for _, blue := range mergeSetBlue {
|
||||||
if contains(blue, *blueSet) {
|
if contains(blue, *blueSet) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
*blueSet = append(*blueSet, blue)
|
*blueSet = append(*blueSet, blue)
|
||||||
}
|
}
|
||||||
selectedParent = blockData.SelectedParent
|
selectedParent = blockData.SelectedParent()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -356,10 +354,10 @@ func (gh *ghostdagHelper) sortByBlueScore(arr []*externalapi.DomainHash) error {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if blockLeft.BlueScore < blockRight.BlueScore {
|
if blockLeft.BlueScore() < blockRight.BlueScore() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if blockLeft.BlueScore == blockRight.BlueScore {
|
if blockLeft.BlueScore() == blockRight.BlueScore() {
|
||||||
return ismoreHash(arr[j], arr[i])
|
return ismoreHash(arr[j], arr[i])
|
||||||
}
|
}
|
||||||
return false
|
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)
|
return gh.dataStore.Get(gh.dbAccess, blockHash)
|
||||||
}
|
}
|
||||||
func (gh *ghostdagHelper) ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
func (gh *ghostdagHelper) ChooseSelectedParent(blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
||||||
panic("implement me")
|
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")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
@ -53,11 +53,11 @@ func (gm *ghostdagManager) ChooseSelectedParent(blockHashes ...*externalapi.Doma
|
|||||||
return selectedParent, nil
|
return selectedParent, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *ghostdagManager) Less(blockHashA *externalapi.DomainHash, ghostdagDataA *model.BlockGHOSTDAGData,
|
func (gm *ghostdagManager) Less(blockHashA *externalapi.DomainHash, ghostdagDataA model.BlockGHOSTDAGData,
|
||||||
blockHashB *externalapi.DomainHash, ghostdagDataB *model.BlockGHOSTDAGData) bool {
|
blockHashB *externalapi.DomainHash, ghostdagDataB model.BlockGHOSTDAGData) bool {
|
||||||
|
|
||||||
blockBlueScoreA := ghostdagDataA.BlueScore
|
blockBlueScoreA := ghostdagDataA.BlueScore()
|
||||||
blockBlueScoreB := ghostdagDataB.BlueScore
|
blockBlueScoreB := ghostdagDataB.BlueScore()
|
||||||
if blockBlueScoreA == blockBlueScoreB {
|
if blockBlueScoreA == blockBlueScoreB {
|
||||||
return hashes.Less(blockHashA, blockHashB)
|
return hashes.Less(blockHashA, blockHashB)
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@ import (
|
|||||||
//
|
//
|
||||||
// For further details see the article https://eprint.iacr.org/2018/104.pdf
|
// For further details see the article https://eprint.iacr.org/2018/104.pdf
|
||||||
func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
||||||
newBlockData := &model.BlockGHOSTDAGData{
|
newBlockData := &blockGHOSTDAGData{
|
||||||
MergeSetBlues: make([]*externalapi.DomainHash, 0),
|
mergeSetBlues: make([]*externalapi.DomainHash, 0),
|
||||||
MergeSetReds: make([]*externalapi.DomainHash, 0),
|
mergeSetReds: make([]*externalapi.DomainHash, 0),
|
||||||
BluesAnticoneSizes: make(map[externalapi.DomainHash]model.KType),
|
bluesAnticoneSizes: make(map[externalapi.DomainHash]model.KType),
|
||||||
}
|
}
|
||||||
|
|
||||||
blockParents, err := gm.dagTopologyManager.Parents(blockHash)
|
blockParents, err := gm.dagTopologyManager.Parents(blockHash)
|
||||||
@ -43,12 +43,12 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
newBlockData.SelectedParent = selectedParent
|
newBlockData.selectedParent = selectedParent
|
||||||
newBlockData.MergeSetBlues = append(newBlockData.MergeSetBlues, selectedParent)
|
newBlockData.mergeSetBlues = append(newBlockData.mergeSetBlues, selectedParent)
|
||||||
newBlockData.BluesAnticoneSizes[*selectedParent] = 0
|
newBlockData.bluesAnticoneSizes[*selectedParent] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeSetWithoutSelectedParent, err := gm.mergeSetWithoutSelectedParent(newBlockData.SelectedParent, blockParents)
|
mergeSetWithoutSelectedParent, err := gm.mergeSetWithoutSelectedParent(newBlockData.selectedParent, blockParents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -61,25 +61,25 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
|||||||
|
|
||||||
if isBlue {
|
if isBlue {
|
||||||
// No k-cluster violation found, we can now set the candidate block as blue
|
// No k-cluster violation found, we can now set the candidate block as blue
|
||||||
newBlockData.MergeSetBlues = append(newBlockData.MergeSetBlues, blueCandidate)
|
newBlockData.mergeSetBlues = append(newBlockData.mergeSetBlues, blueCandidate)
|
||||||
newBlockData.BluesAnticoneSizes[*blueCandidate] = candidateAnticoneSize
|
newBlockData.bluesAnticoneSizes[*blueCandidate] = candidateAnticoneSize
|
||||||
for blue, blueAnticoneSize := range candidateBluesAnticoneSizes {
|
for blue, blueAnticoneSize := range candidateBluesAnticoneSizes {
|
||||||
newBlockData.BluesAnticoneSizes[blue] = blueAnticoneSize + 1
|
newBlockData.bluesAnticoneSizes[blue] = blueAnticoneSize + 1
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newBlockData.MergeSetReds = append(newBlockData.MergeSetReds, blueCandidate)
|
newBlockData.mergeSetReds = append(newBlockData.mergeSetReds, blueCandidate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isGenesis {
|
if !isGenesis {
|
||||||
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, newBlockData.SelectedParent)
|
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, newBlockData.selectedParent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
newBlockData.BlueScore = selectedParentGHOSTDAGData.BlueScore + uint64(len(newBlockData.MergeSetBlues))
|
newBlockData.blueScore = selectedParentGHOSTDAGData.BlueScore() + uint64(len(newBlockData.mergeSetBlues))
|
||||||
} else {
|
} else {
|
||||||
// Genesis's blue score is defined to be 0.
|
// Genesis's blue score is defined to be 0.
|
||||||
newBlockData.BlueScore = 0
|
newBlockData.blueScore = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
gm.ghostdagDataStore.Stage(blockHash, newBlockData)
|
gm.ghostdagDataStore.Stage(blockHash, newBlockData)
|
||||||
@ -89,15 +89,15 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
|
|||||||
|
|
||||||
type chainBlockData struct {
|
type chainBlockData struct {
|
||||||
hash *externalapi.DomainHash
|
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) {
|
isBlue bool, candidateAnticoneSize model.KType, candidateBluesAnticoneSizes map[externalapi.DomainHash]model.KType, err error) {
|
||||||
|
|
||||||
// The maximum length of node.blues can be K+1 because
|
// The maximum length of node.blues can be K+1 because
|
||||||
// it contains the selected parent.
|
// 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
|
return false, 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,12 +126,12 @@ func (gm *ghostdagManager) checkBlueCandidate(newBlockData *model.BlockGHOSTDAGD
|
|||||||
return false, 0, nil, nil
|
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 {
|
if err != nil {
|
||||||
return false, 0, nil, err
|
return false, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
chainBlock = chainBlockData{hash: chainBlock.blockData.SelectedParent,
|
chainBlock = chainBlockData{hash: chainBlock.blockData.SelectedParent(),
|
||||||
blockData: selectedParentGHOSTDAGData,
|
blockData: selectedParentGHOSTDAGData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@ func (gm *ghostdagManager) checkBlueCandidate(newBlockData *model.BlockGHOSTDAGD
|
|||||||
return true, candidateAnticoneSize, candidateBluesAnticoneSizes, nil
|
return true, candidateAnticoneSize, candidateBluesAnticoneSizes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData *model.BlockGHOSTDAGData,
|
func (gm *ghostdagManager) checkBlueCandidateWithChainBlock(newBlockData model.BlockGHOSTDAGData,
|
||||||
chainBlock chainBlockData, blueCandidate *externalapi.DomainHash,
|
chainBlock chainBlockData, blueCandidate *externalapi.DomainHash,
|
||||||
candidateBluesAnticoneSizes map[externalapi.DomainHash]model.KType,
|
candidateBluesAnticoneSizes map[externalapi.DomainHash]model.KType,
|
||||||
candidateAnticoneSize *model.KType) (isBlue, isRed bool, err error) {
|
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.
|
// Skip blocks that exist in the past of blueCandidate.
|
||||||
isAncestorOfBlueCandidate, err := gm.dagTopologyManager.IsAncestorOf(block, blueCandidate)
|
isAncestorOfBlueCandidate, err := gm.dagTopologyManager.IsAncestorOf(block, blueCandidate)
|
||||||
if err != nil {
|
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'.
|
// blueAnticoneSize returns the blue anticone size of 'block' from the worldview of 'context'.
|
||||||
// Expects 'block' to be in the blue set 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; {
|
for current := context; current != nil; {
|
||||||
if blueAnticoneSize, ok := current.BluesAnticoneSizes[*block]; ok {
|
if blueAnticoneSize, ok := current.BluesAnticoneSizes()[*block]; ok {
|
||||||
return blueAnticoneSize, nil
|
return blueAnticoneSize, nil
|
||||||
}
|
}
|
||||||
if current.SelectedParent == nil {
|
if current.SelectedParent() == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
current, err = gm.ghostdagDataStore.Get(gm.databaseContext, current.SelectedParent)
|
current, err = gm.ghostdagDataStore.Get(gm.databaseContext, current.SelectedParent())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
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 (
|
import (
|
||||||
"encoding/json"
|
"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"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"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
|
// TestGHOSTDAG iterates over several dag simulations, and checks
|
||||||
@ -47,15 +50,9 @@ func TestGHOSTDAG(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ghostdagDataStore := &GHOSTDAGDataStoreImpl{
|
ghostdagDataStore := &GHOSTDAGDataStoreImpl{
|
||||||
dagMap: make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData),
|
dagMap: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData),
|
||||||
}
|
|
||||||
var blockGHOSTDAGDataGenesis = &model.BlockGHOSTDAGData{
|
|
||||||
BlueScore: 0,
|
|
||||||
SelectedParent: nil,
|
|
||||||
MergeSetBlues: nil,
|
|
||||||
MergeSetReds: nil,
|
|
||||||
BluesAnticoneSizes: nil,
|
|
||||||
}
|
}
|
||||||
|
blockGHOSTDAGDataGenesis := ghostdagmanager.NewBlockGHOSTDAGData(0, nil, nil, nil, nil)
|
||||||
|
|
||||||
var testsCounter int
|
var testsCounter int
|
||||||
err := filepath.Walk("../../testdata/dags", func(path string, info os.FileInfo, err error) error {
|
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:
|
//NOTE: FOR ADDING/REMOVING AN IMPLEMENTATION CHANGE BELOW:
|
||||||
implementationFactories := []implManager{
|
implementationFactories := []implManager{
|
||||||
{New, "Original"},
|
{ghostdagmanager.New, "Original"},
|
||||||
{ghostdag2.New, "Tal's impl"},
|
{ghostdag2.New, "Tal's impl"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,30 +107,30 @@ func TestGHOSTDAG(t *testing.T) {
|
|||||||
factory.implName, info.Name(), testBlockData.ID, err)
|
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.",
|
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.",
|
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.",
|
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.",
|
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 = make(map[externalapi.DomainHash][]*externalapi.DomainHash)
|
||||||
dagTopology.parentsMap[genesisHash] = nil
|
dagTopology.parentsMap[genesisHash] = nil
|
||||||
ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]*model.BlockGHOSTDAGData)
|
ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]model.BlockGHOSTDAGData)
|
||||||
ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis
|
ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +169,10 @@ func StringToByteArray(stringIDArr []string) []*externalapi.DomainHash {
|
|||||||
|
|
||||||
/* ---------------------- */
|
/* ---------------------- */
|
||||||
type GHOSTDAGDataStoreImpl struct {
|
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
|
ds.dagMap[*blockHash] = blockGHOSTDAGData
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +188,7 @@ func (ds *GHOSTDAGDataStoreImpl) Commit(dbTx model.DBTransaction) error {
|
|||||||
panic("implement me")
|
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]
|
v, ok := ds.dagMap[*blockHash]
|
||||||
if ok {
|
if ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
|
@ -46,7 +46,7 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(blockHash *externalapi.Doma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return nil on genesis
|
// Return nil on genesis
|
||||||
if ghostdagData.SelectedParent == nil {
|
if ghostdagData.SelectedParent() == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(blockHash *externalapi.Doma
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, red := range ghostdagData.MergeSetReds {
|
for _, red := range ghostdagData.MergeSetReds() {
|
||||||
doesRedHaveFinalityPointInPast, err := mdm.dagTopologyManager.IsAncestorOf(finalityPoint, red)
|
doesRedHaveFinalityPointInPast, err := mdm.dagTopologyManager.IsAncestorOf(finalityPoint, red)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -85,9 +85,9 @@ func (mdm mergeDepthManager) NonBoundedMergeDepthViolatingBlues(blockHash *exter
|
|||||||
return nil, err
|
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)
|
notViolatingFinality, err := mdm.hasFinalityPointInOthersSelectedChain(blockHash, blue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package pastmediantimemanager
|
package pastmediantimemanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// pastMedianTimeManager provides a method to resolve the
|
// pastMedianTimeManager provides a method to resolve the
|
||||||
@ -44,7 +45,7 @@ func (pmtm *pastMedianTimeManager) PastMedianTime(blockHash *externalapi.DomainH
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
selectedParentHash := blockGHOSTDAGData.SelectedParent
|
selectedParentHash := blockGHOSTDAGData.SelectedParent()
|
||||||
|
|
||||||
// Genesis block
|
// Genesis block
|
||||||
if selectedParentHash == nil {
|
if selectedParentHash == nil {
|
||||||
|
@ -99,14 +99,14 @@ func (pm *pruningManager) FindNextPruningPoint() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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.
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This means the pruning point is still genesis.
|
// This means the pruning point is still genesis.
|
||||||
if virtual.BlueScore <= pm.pruningDepth+pm.finalityInterval {
|
if virtual.BlueScore() <= pm.pruningDepth+pm.finalityInterval {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ func (pm *pruningManager) FindNextPruningPoint() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actually check if the pruning point changed
|
// 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)
|
err = pm.savePruningPoint(candidatePHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 this is the genesis node, simply initialize it and return
|
||||||
if ghostdagData.SelectedParent == nil {
|
if ghostdagData.SelectedParent() == nil {
|
||||||
rt.stageReindexRoot(blockHash)
|
rt.stageReindexRoot(blockHash)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -56,16 +56,16 @@ func (rt *reachabilityManager) AddBlock(blockHash *externalapi.DomainHash) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert the node into the selected parent's reachability tree
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the block to the futureCoveringSets of all the blocks
|
// Add the block to the futureCoveringSets of all the blocks
|
||||||
// in the merget set
|
// in the merget set
|
||||||
mergeSet := make([]*externalapi.DomainHash, len(ghostdagData.MergeSetBlues)+len(ghostdagData.MergeSetReds))
|
mergeSet := make([]*externalapi.DomainHash, len(ghostdagData.MergeSetBlues())+len(ghostdagData.MergeSetReds()))
|
||||||
copy(mergeSet, ghostdagData.MergeSetBlues)
|
copy(mergeSet, ghostdagData.MergeSetBlues())
|
||||||
copy(mergeSet[len(ghostdagData.MergeSetBlues):], ghostdagData.MergeSetReds)
|
copy(mergeSet[len(ghostdagData.MergeSetBlues()):], ghostdagData.MergeSetReds())
|
||||||
|
|
||||||
for _, current := range mergeSet {
|
for _, current := range mergeSet {
|
||||||
err = rt.insertToFutureCoveringSet(current, blockHash)
|
err = rt.insertToFutureCoveringSet(current, blockHash)
|
||||||
|
@ -814,7 +814,7 @@ func (rt *reachabilityManager) maybeMoveReindexRoot(reindexRoot, newTreeNode *ex
|
|||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if newTreeNodeGHOSTDAGData.BlueScore-reindexRootChosenChildGHOSTDAGData.BlueScore < rt.reindexWindow {
|
if newTreeNodeGHOSTDAGData.BlueScore()-reindexRootChosenChildGHOSTDAGData.BlueScore() < rt.reindexWindow {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,12 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore
|
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore()
|
||||||
highBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, highHash)
|
highBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
highBlockBlueScore := highBlockGHOSTDAGData.BlueScore
|
highBlockBlueScore := highBlockGHOSTDAGData.BlueScore()
|
||||||
if lowBlockBlueScore >= highBlockBlueScore {
|
if lowBlockBlueScore >= highBlockBlueScore {
|
||||||
return nil, errors.Errorf("low hash blueScore >= high hash blueScore (%d >= %d)",
|
return nil, errors.Errorf("low hash blueScore >= high hash blueScore (%d >= %d)",
|
||||||
lowBlockBlueScore, highBlockBlueScore)
|
lowBlockBlueScore, highBlockBlueScore)
|
||||||
@ -37,7 +37,7 @@ func (sm *syncManager) antiPastHashesBetween(lowHash, highHash *externalapi.Doma
|
|||||||
// fairly accurate because we presume that most DAG blocks are
|
// fairly accurate because we presume that most DAG blocks are
|
||||||
// blue.
|
// blue.
|
||||||
for highBlockBlueScore-lowBlockBlueScore+1 > maxHashesInAntiPastHashesBetween {
|
for highBlockBlueScore-lowBlockBlueScore+1 > maxHashesInAntiPastHashesBetween {
|
||||||
highHash = highBlockGHOSTDAGData.SelectedParent
|
highHash = highBlockGHOSTDAGData.SelectedParent()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect every node in highHash's past (including itself) but
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
highHash = highBlockGHOSTDAGData.SelectedParent
|
highHash = highBlockGHOSTDAGData.SelectedParent()
|
||||||
|
|
||||||
lowBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, lowHash)
|
lowBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, lowHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore
|
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore()
|
||||||
|
|
||||||
currentHash := highHash
|
currentHash := highHash
|
||||||
step := uint64(1)
|
step := uint64(1)
|
||||||
@ -32,7 +32,7 @@ func (sm *syncManager) createBlockLocator(lowHash, highHash *externalapi.DomainH
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
currentBlockBlueScore := currentBlockGHOSTDAGData.BlueScore
|
currentBlockBlueScore := currentBlockGHOSTDAGData.BlueScore()
|
||||||
|
|
||||||
// Nothing more to add once the low node has been added.
|
// Nothing more to add once the low node has been added.
|
||||||
if currentBlockBlueScore <= lowBlockBlueScore {
|
if currentBlockBlueScore <= lowBlockBlueScore {
|
||||||
@ -47,7 +47,7 @@ func (sm *syncManager) createBlockLocator(lowHash, highHash *externalapi.DomainH
|
|||||||
// final node is lowNode.
|
// final node is lowNode.
|
||||||
nextBlueScore := currentBlockBlueScore - step
|
nextBlueScore := currentBlockBlueScore - step
|
||||||
if currentBlockBlueScore < step {
|
if currentBlockBlueScore < step {
|
||||||
nextBlueScore = lowBlockGHOSTDAGData.BlueScore
|
nextBlueScore = lowBlockGHOSTDAGData.BlueScore()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk down currentHash's selected parent chain to the appropriate ancestor
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return virtualGHOSTDAGData.SelectedParent, nil
|
return virtualGHOSTDAGData.SelectedParent(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *syncManager) headerVirtualSelectedParentHash() (*externalapi.DomainHash, error) {
|
func (sm *syncManager) headerVirtualSelectedParentHash() (*externalapi.DomainHash, error) {
|
||||||
|
@ -59,7 +59,7 @@ func (v *transactionValidator) checkTransactionCoinbaseMaturity(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
txBlueScore := ghostdagData.BlueScore
|
txBlueScore := ghostdagData.BlueScore()
|
||||||
var missingOutpoints []*externalapi.DomainOutpoint
|
var missingOutpoints []*externalapi.DomainOutpoint
|
||||||
for _, input := range tx.Inputs {
|
for _, input := range tx.Inputs {
|
||||||
utxoEntry := input.UTXOEntry
|
utxoEntry := input.UTXOEntry
|
||||||
@ -166,7 +166,7 @@ func (v *transactionValidator) checkTransactionSequenceLock(povBlockHash *extern
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !v.sequenceLockActive(sequenceLock, ghostdagData.BlueScore, medianTime) {
|
if !v.sequenceLockActive(sequenceLock, ghostdagData.BlueScore(), medianTime) {
|
||||||
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains "+
|
return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "block contains "+
|
||||||
"transaction whose input sequence "+
|
"transaction whose input sequence "+
|
||||||
"locks are not met")
|
"locks are not met")
|
||||||
@ -270,16 +270,16 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
selectedParentGHOSTDAGData, err := v.ghostdagDataStore.Get(v.databaseContext,
|
selectedParentGHOSTDAGData, err := v.ghostdagDataStore.Get(v.databaseContext,
|
||||||
baseGHOSTDAGData.SelectedParent)
|
baseGHOSTDAGData.SelectedParent())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if selectedParentGHOSTDAGData.BlueScore <= inputBlueScore {
|
if selectedParentGHOSTDAGData.BlueScore() <= inputBlueScore {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
baseHash = baseGHOSTDAGData.SelectedParent
|
baseHash = baseGHOSTDAGData.SelectedParent()
|
||||||
baseGHOSTDAGData = selectedParentGHOSTDAGData
|
baseGHOSTDAGData = selectedParentGHOSTDAGData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user