Svarog f1451406f7
Add support for multiple staging areas (#1633)
* Add StagingArea struct

* Implemented staging areas in blockStore

* Move blockStagingShard to separate folder

* Apply staging shard to acceptanceDataStore

* Update blockHeaderStore with StagingArea

* Add StagingArea to BlockRelationStore

* Add StagingArea to blockStatusStore

* Add StagingArea to consensusStateStore

* Add StagingArea to daaBlocksStore

* Add StagingArea to finalityStore

* Add StagingArea to ghostdagDataStore

* Add StagingArea to headersSelectedChainStore and headersSelectedTipStore

* Add StagingArea to multisetStore

* Add StagingArea to pruningStore

* Add StagingArea to reachabilityDataStore

* Add StagingArea to utxoDiffStore

* Fix forgotten compilation error

* Update reachability manager and some more things with StagingArea

* Add StagingArea to dagTopologyManager, and some more

* Add StagingArea to GHOSTDAGManager, and some more

* Add StagingArea to difficultyManager, and some more

* Add StagingArea to dagTraversalManager, and some more

* Add StagingArea to headerTipsManager, and some more

* Add StagingArea to constnsusStateManager, pastMedianTimeManager

* Add StagingArea to transactionValidator

* Add StagingArea to finalityManager

* Add StagingArea to mergeDepthManager

* Add StagingArea to pruningManager

* Add StagingArea to rest of ValidateAndInsertBlock

* Add StagingArea to blockValidator

* Add StagingArea to coinbaseManager

* Add StagingArea to syncManager

* Add StagingArea to blockBuilder

* Update consensus with StagingArea

* Add StagingArea to ghostdag2

* Fix remaining compilation errors

* Update names of stagingShards

* Fix forgotten stagingArea passing

* Mark stagingShard.isCommited = true once commited

* Move isStaged to stagingShard, so that it's available without going through store

* Make blockHeaderStore count be avilable from stagingShard

* Fix remaining forgotten stagingArea passing

* commitAllChanges should call dbTx.Commit in the end

* Fix all tests tests in blockValidator

* Fix all tests in consensusStateManager and some more

* Fix all tests in pruningManager

* Add many missing stagingAreas in tests

* Fix many tests

* Fix most of all other tests

* Fix ghostdag_test.go

* Add comment to StagingArea

* Make list of StagingShards an array

* Add comment to StagingShardID

* Make sure all staging shards are pointer-receiver

* Undo bucket rename in block_store

* Typo: isCommited -> isCommitted

* Add comment explaining why stagingArea.shards is an array
2021-03-29 10:34:11 +03:00

123 lines
3.8 KiB
Go

package syncmanager
import (
"github.com/kaspanet/kaspad/domain/consensus/database"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/pkg/errors"
)
// createBlockLocator creates a block locator for the passed high and low hashes.
// See the BlockLocator type comments for more details.
func (sm *syncManager) createBlockLocator(stagingArea *model.StagingArea, lowHash, highHash *externalapi.DomainHash,
limit uint32) (externalapi.BlockLocator, error) {
lowBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, stagingArea, lowHash)
if err != nil {
return nil, err
}
lowBlockBlueScore := lowBlockGHOSTDAGData.BlueScore()
currentHash := highHash
step := uint64(1)
locator := make(externalapi.BlockLocator, 0)
// The loop will break if we reached the limit or if we got to lowHash.
for {
locator = append(locator, currentHash)
// Stop if we've reached the limit (if it's set)
if limit > 0 && uint32(len(locator)) == limit {
break
}
currentBlockGHOSTDAGData, err := sm.ghostdagDataStore.Get(sm.databaseContext, stagingArea, currentHash)
if err != nil {
return nil, err
}
currentBlockBlueScore := currentBlockGHOSTDAGData.BlueScore()
// Nothing more to add once the low node has been added.
if currentBlockBlueScore <= lowBlockBlueScore {
isCurrentHashInSelectedParentChainOfLowHash, err :=
sm.dagTopologyManager.IsInSelectedParentChainOf(stagingArea, currentHash, lowHash)
if err != nil {
return nil, err
}
if !isCurrentHashInSelectedParentChainOfLowHash {
return nil, errors.Errorf("highHash and lowHash are " +
"not in the same selected parent chain.")
}
break
}
// Calculate blueScore of previous node to include ensuring the
// 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
currentHash, err = sm.dagTraversalManager.LowestChainBlockAboveOrEqualToBlueScore(stagingArea, currentHash, nextBlueScore)
if err != nil {
return nil, err
}
// Double the distance between included hashes
step *= 2
}
return locator, nil
}
func (sm *syncManager) createHeadersSelectedChainBlockLocator(stagingArea *model.StagingArea,
lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) {
if highHash.Equal(sm.genesisBlockHash) && lowHash.Equal(sm.genesisBlockHash) {
return externalapi.BlockLocator{sm.genesisBlockHash}, nil
}
lowHashIndex, err := sm.headersSelectedChainStore.GetIndexByHash(sm.databaseContext, stagingArea, lowHash)
if err != nil {
if database.IsNotFoundError(err) {
return nil, errors.Wrapf(model.ErrBlockNotInSelectedParentChain,
"LowHash %s is not in selected parent chain", lowHash)
}
return nil, err
}
highHashIndex, err := sm.headersSelectedChainStore.GetIndexByHash(sm.databaseContext, stagingArea, highHash)
if err != nil {
if database.IsNotFoundError(err) {
return nil, errors.Wrapf(model.ErrBlockNotInSelectedParentChain,
"LowHash %s is not in selected parent chain", lowHash)
}
return nil, err
}
if highHashIndex < lowHashIndex {
return nil, errors.Errorf("cannot build block locator while highHash is lower than lowHash")
}
locator := externalapi.BlockLocator{}
currentIndex := highHashIndex
step := uint64(1)
for currentIndex > lowHashIndex {
blockHash, err := sm.headersSelectedChainStore.GetHashByIndex(sm.databaseContext, stagingArea, currentIndex)
if err != nil {
return nil, err
}
locator = append(locator, blockHash)
if currentIndex < step {
break
}
currentIndex -= step
step *= 2
}
locator = append(locator, lowHash)
return locator, nil
}