mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-21 22:36:42 +00:00

* Add TestValidateAndInsertPruningPointWithSideBlocks * Optimize infrastracture bucket paths * Update infrastracture tests * Refactor the consensus/database layer * Remove utils/dbkeys * Use consensus/database in consensus instead of infrastructure * Fix a bug in dbBucketToDatabaseBucket and MakeBucket combination Co-authored-by: Elichai Turkel <elichai.turkel@gmail.com> Co-authored-by: stasatdaglabs <39559713+stasatdaglabs@users.noreply.github.com>
120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
package finalitymanager
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/database"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
)
|
|
|
|
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.Debugf("virtualFinalityPoint start")
|
|
defer log.Debugf("virtualFinalityPoint end")
|
|
|
|
virtualFinalityPoint, err := fm.calculateFinalityPoint(model.VirtualBlockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
log.Debugf("The current virtual finality block is: %s", virtualFinalityPoint)
|
|
|
|
return virtualFinalityPoint, nil
|
|
}
|
|
|
|
func (fm *finalityManager) FinalityPoint(blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
|
|
log.Debugf("FinalityPoint start")
|
|
defer log.Debugf("FinalityPoint end")
|
|
if blockHash.Equal(model.VirtualBlockHash) {
|
|
return fm.VirtualFinalityPoint()
|
|
}
|
|
finalityPoint, err := fm.finalityStore.FinalityPoint(fm.databaseContext, blockHash)
|
|
if err != nil {
|
|
log.Debugf("%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.Debugf("calculateFinalityPoint start")
|
|
defer log.Debugf("calculateFinalityPoint end")
|
|
ghostdagData, err := fm.ghostdagDataStore.Get(fm.databaseContext, blockHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if ghostdagData.BlueScore() < fm.finalityDepth {
|
|
log.Debugf("%s blue score lower then finality depth - returning genesis as finality point", blockHash)
|
|
return fm.genesisHash, nil
|
|
}
|
|
|
|
selectedParent := ghostdagData.SelectedParent()
|
|
if selectedParent.Equal(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.Debugf("%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.Debugf("%s's finality point is %s", blockHash, current)
|
|
return current, nil
|
|
}
|
|
|
|
current = next
|
|
}
|
|
}
|