mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-22 23:07:04 +00:00

* Get rid of insertMode * Rename AddBlockToVirtual->AddBlock * When F is not in the future of P, enforce finality with P and not with F. * Don't allow blocks with invalid parents or with missing block body * Check finality violation before checking block status * Implement CalculateIndependentPruningPoint * Move checkBlockStatus to validateBlock * Add ValidateBlock to block processor interface * Adjust SetPruningPoint to the new IBD flow * Add pruning store to CSM's constructor * Flip wrong condition on AddHeaderTip * Fix func (hts *headerSelectedTipStore) Has * Fix block stage order * Call to ValidateBodyInContext from validatePostProofOfWork * Enable overrideDAGParams * Update log * Rename SetPruningPoint to ValidateAndInsertPruningPoint and move most of its logic inside block processor * Rename hasValidatedHeader->hasValidatedOnlyHeader * Fix typo * Name return values for fetchMissingUTXOSet * Add comment * Return ErrMissingParents when block body is missing * Add logs and comments * Fix merge error * Fix pruning point calculation to be by virtual selected parent * Replace CalculateIndependentPruningPoint to CalculatePruningPointByHeaderSelectedTip * Fix isAwaitingUTXOSet to check pruning point by headers * Change isAwaitingUTXOSet indication * Remove IsBlockInHeaderPruningPointFuture from BlockInfo * Fix LowestChainBlockAboveOrEqualToBlueScore * Add validateNewPruningPointTransactions * Add validateNewPruningAgainstPastUTXO * Rename set_pruning_utxo_set.go to update_pruning_utxo_set.go * Check missing block body hashes by missing block instead of status * Validate pruning point against past UTXO with the pruning point as block hash * Remove virtualHeaderHash * Fix comment * Fix imports
120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
package finalitymanager
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/infrastructure/db/database"
|
|
)
|
|
|
|
type finalityManager struct {
|
|
databaseContext model.DBReader
|
|
dagTopologyManager model.DAGTopologyManager
|
|
finalityStore model.FinalityStore
|
|
ghostdagDataStore model.GHOSTDAGDataStore
|
|
genesisHash *externalapi.DomainHash
|
|
finalityDepth uint64
|
|
}
|
|
|
|
// New instantiates a new FinalityManager
|
|
func New(databaseContext model.DBReader,
|
|
dagTopologyManager model.DAGTopologyManager,
|
|
finalityStore model.FinalityStore,
|
|
ghostdagDataStore model.GHOSTDAGDataStore,
|
|
genesisHash *externalapi.DomainHash,
|
|
finalityDepth uint64) model.FinalityManager {
|
|
|
|
return &finalityManager{
|
|
databaseContext: databaseContext,
|
|
genesisHash: genesisHash,
|
|
dagTopologyManager: dagTopologyManager,
|
|
finalityStore: finalityStore,
|
|
ghostdagDataStore: ghostdagDataStore,
|
|
finalityDepth: finalityDepth,
|
|
}
|
|
}
|
|
|
|
func (fm *finalityManager) VirtualFinalityPoint() (*externalapi.DomainHash, error) {
|
|
log.Tracef("virtualFinalityPoint start")
|
|
defer log.Tracef("virtualFinalityPoint end")
|
|
|
|
virtualFinalityPoint, err := fm.calculateFinalityPoint(model.VirtualBlockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
log.Tracef("The current virtual finality block is: %s", virtualFinalityPoint)
|
|
|
|
return virtualFinalityPoint, nil
|
|
}
|
|
|
|
func (fm *finalityManager) FinalityPoint(blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
|
log.Tracef("FinalityPoint start")
|
|
defer log.Tracef("FinalityPoint end")
|
|
if *blockHash == *model.VirtualBlockHash {
|
|
return fm.VirtualFinalityPoint()
|
|
}
|
|
finalityPoint, err := fm.finalityStore.FinalityPoint(fm.databaseContext, blockHash)
|
|
if err != nil {
|
|
log.Tracef("%s finality point not found in store - calculating", blockHash)
|
|
if errors.Is(err, database.ErrNotFound) {
|
|
return fm.calculateAndStageFinalityPoint(blockHash)
|
|
}
|
|
return nil, err
|
|
}
|
|
return finalityPoint, nil
|
|
}
|
|
|
|
func (fm *finalityManager) calculateAndStageFinalityPoint(blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
|
finalityPoint, err := fm.calculateFinalityPoint(blockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fm.finalityStore.StageFinalityPoint(blockHash, finalityPoint)
|
|
return finalityPoint, nil
|
|
}
|
|
|
|
func (fm *finalityManager) calculateFinalityPoint(blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
|
log.Tracef("calculateFinalityPoint start")
|
|
defer log.Tracef("calculateFinalityPoint end")
|
|
ghostdagData, err := fm.ghostdagDataStore.Get(fm.databaseContext, blockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if ghostdagData.BlueScore() < fm.finalityDepth {
|
|
log.Tracef("%s blue score lower then finality depth - returning genesis as finality point", blockHash)
|
|
return fm.genesisHash, nil
|
|
}
|
|
|
|
selectedParent := ghostdagData.SelectedParent()
|
|
if *selectedParent == *fm.genesisHash {
|
|
return fm.genesisHash, nil
|
|
}
|
|
|
|
current, err := fm.finalityStore.FinalityPoint(fm.databaseContext, ghostdagData.SelectedParent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
requiredBlueScore := ghostdagData.BlueScore() - fm.finalityDepth
|
|
log.Tracef("%s's finality point is the one having the highest blue score lower then %d", blockHash, requiredBlueScore)
|
|
|
|
var next *externalapi.DomainHash
|
|
for {
|
|
next, err = fm.dagTopologyManager.ChildInSelectedParentChainOf(current, blockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nextGHOSTDAGData, err := fm.ghostdagDataStore.Get(fm.databaseContext, next)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if nextGHOSTDAGData.BlueScore() >= requiredBlueScore {
|
|
log.Tracef("%s's finality point is %s", blockHash, current)
|
|
return current, nil
|
|
}
|
|
|
|
current = next
|
|
}
|
|
}
|