Ori Newman 7390651072
Remove HF1 activation code (#2042)
* Remove HF1 activation code

* Remove test with an overflow

* Fix "max sompi amount is never dust"

* Remove estimatedHeaderUpperBound logic
2022-05-05 20:35:17 +03:00

263 lines
8.8 KiB
Go

package mergedepthmanager
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/pkg/errors"
)
type mergeDepthManager struct {
databaseContext model.DBReader
dagTopologyManager model.DAGTopologyManager
dagTraversalManager model.DAGTraversalManager
finalityManager model.FinalityManager
genesisHash *externalapi.DomainHash
mergeDepth uint64
ghostdagDataStore model.GHOSTDAGDataStore
mergeDepthRootStore model.MergeDepthRootStore
daaBlocksStore model.DAABlocksStore
pruningStore model.PruningStore
finalityStore model.FinalityStore
}
// New instantiates a new MergeDepthManager
func New(
databaseContext model.DBReader,
dagTopologyManager model.DAGTopologyManager,
dagTraversalManager model.DAGTraversalManager,
finalityManager model.FinalityManager,
genesisHash *externalapi.DomainHash,
mergeDepth uint64,
ghostdagDataStore model.GHOSTDAGDataStore,
mergeDepthRootStore model.MergeDepthRootStore,
daaBlocksStore model.DAABlocksStore,
pruningStore model.PruningStore,
finalityStore model.FinalityStore) model.MergeDepthManager {
return &mergeDepthManager{
databaseContext: databaseContext,
dagTopologyManager: dagTopologyManager,
dagTraversalManager: dagTraversalManager,
finalityManager: finalityManager,
genesisHash: genesisHash,
mergeDepth: mergeDepth,
ghostdagDataStore: ghostdagDataStore,
mergeDepthRootStore: mergeDepthRootStore,
daaBlocksStore: daaBlocksStore,
pruningStore: pruningStore,
finalityStore: finalityStore,
}
}
// CheckBoundedMergeDepth is used for validation, so must follow the HF1 DAA score for determining the correct depth to verify
func (mdm *mergeDepthManager) CheckBoundedMergeDepth(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) error {
ghostdagData, err := mdm.ghostdagDataStore.Get(mdm.databaseContext, stagingArea, blockHash, false)
if err != nil {
return err
}
// Return nil on genesis
if ghostdagData.SelectedParent() == nil {
return nil
}
mergeDepthRoot, err := mdm.MergeDepthRoot(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return err
}
// We call FinalityPoint in order to save it to storage.
_, err = mdm.finalityManager.FinalityPoint(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return err
}
nonBoundedMergeDepthViolatingBlues, err := mdm.NonBoundedMergeDepthViolatingBlues(stagingArea, blockHash, mergeDepthRoot)
if err != nil {
return err
}
for _, red := range ghostdagData.MergeSetReds() {
doesRedHaveMergeRootInPast, err := mdm.dagTopologyManager.IsAncestorOf(stagingArea, mergeDepthRoot, red)
if err != nil {
return err
}
if doesRedHaveMergeRootInPast {
continue
}
isRedInPastOfAnyNonMergeDepthViolatingBlue, err :=
mdm.dagTopologyManager.IsAncestorOfAny(stagingArea, red, nonBoundedMergeDepthViolatingBlues)
if err != nil {
return err
}
if !isRedInPastOfAnyNonMergeDepthViolatingBlue {
return errors.Wrapf(ruleerrors.ErrViolatingBoundedMergeDepth, "block is violating bounded merge depth")
}
}
return nil
}
func (mdm *mergeDepthManager) NonBoundedMergeDepthViolatingBlues(
stagingArea *model.StagingArea, blockHash, mergeDepthRoot *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
ghostdagData, err := mdm.ghostdagDataStore.Get(mdm.databaseContext, stagingArea, blockHash, false)
if err != nil {
return nil, err
}
nonBoundedMergeDepthViolatingBlues := make([]*externalapi.DomainHash, 0, len(ghostdagData.MergeSetBlues()))
if err != nil {
return nil, err
}
for _, blue := range ghostdagData.MergeSetBlues() {
isMergeDepthRootInSelectedChainOfBlue, err := mdm.dagTopologyManager.IsInSelectedParentChainOf(stagingArea, mergeDepthRoot, blue)
if err != nil {
return nil, err
}
if isMergeDepthRootInSelectedChainOfBlue {
nonBoundedMergeDepthViolatingBlues = append(nonBoundedMergeDepthViolatingBlues, blue)
}
}
return nonBoundedMergeDepthViolatingBlues, nil
}
func (mdm *mergeDepthManager) VirtualMergeDepthRoot(stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
log.Tracef("VirtualMergeDepthRoot start")
defer log.Tracef("VirtualMergeDepthRoot end")
virtualMergeDepthRoot, err := mdm.calculateMergeDepthRoot(stagingArea, model.VirtualBlockHash, false)
if err != nil {
return nil, err
}
log.Debugf("The current virtual merge depth root is: %s", virtualMergeDepthRoot)
return virtualMergeDepthRoot, nil
}
func (mdm *mergeDepthManager) MergeDepthRoot(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) (*externalapi.DomainHash, error) {
log.Tracef("MergeDepthRoot start")
defer log.Tracef("MergeDepthRoot end")
if blockHash.Equal(model.VirtualBlockHash) {
return mdm.VirtualMergeDepthRoot(stagingArea)
}
root, err := mdm.mergeDepthRootStore.MergeDepthRoot(mdm.databaseContext, stagingArea, blockHash)
if err != nil {
log.Debugf("%s merge depth root not found in store - calculating", blockHash)
if errors.Is(err, database.ErrNotFound) {
return mdm.calculateAndStageMergeDepthRoot(stagingArea, blockHash, isBlockWithTrustedData)
}
return nil, err
}
return root, nil
}
func (mdm *mergeDepthManager) calculateAndStageMergeDepthRoot(
stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) (*externalapi.DomainHash, error) {
root, err := mdm.calculateMergeDepthRoot(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return nil, err
}
mdm.mergeDepthRootStore.StageMergeDepthRoot(stagingArea, blockHash, root)
return root, nil
}
func (mdm *mergeDepthManager) calculateMergeDepthRoot(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) (
*externalapi.DomainHash, error) {
log.Tracef("calculateMergeDepthRoot start")
defer log.Tracef("calculateMergeDepthRoot end")
if isBlockWithTrustedData {
return model.VirtualGenesisBlockHash, nil
}
ghostdagData, err := mdm.ghostdagDataStore.Get(mdm.databaseContext, stagingArea, blockHash, false)
if err != nil {
return nil, err
}
if ghostdagData.BlueScore() < mdm.mergeDepth {
log.Debugf("%s blue score lower then merge depth - returning genesis as merge depth root", blockHash)
return mdm.genesisHash, nil
}
pruningPoint, err := mdm.pruningStore.PruningPoint(mdm.databaseContext, stagingArea)
if err != nil {
return nil, err
}
pruningPointGhostdagData, err := mdm.ghostdagDataStore.Get(mdm.databaseContext, stagingArea, pruningPoint, false)
if err != nil {
return nil, err
}
if ghostdagData.BlueScore() < pruningPointGhostdagData.BlueScore()+mdm.mergeDepth {
log.Debugf("%s blue score less than merge depth over pruning point - returning virtual genesis as merge depth root", blockHash)
return model.VirtualGenesisBlockHash, nil
}
isPruningPointOnChain, err := mdm.dagTopologyManager.IsInSelectedParentChainOf(stagingArea, pruningPoint, blockHash)
if err != nil {
return nil, err
}
if !isPruningPointOnChain {
log.Debugf("pruning point not in selected chain of %s - returning virtual genesis as merge depth root", blockHash)
return model.VirtualGenesisBlockHash, nil
}
selectedParent := ghostdagData.SelectedParent()
if selectedParent.Equal(mdm.genesisHash) {
return mdm.genesisHash, nil
}
current, err := mdm.mergeDepthRootStore.MergeDepthRoot(mdm.databaseContext, stagingArea, ghostdagData.SelectedParent())
if database.IsNotFoundError(err) {
// This should only occur for a few blocks following the upgrade
log.Debugf("merge point root not in store for %s, falling back to finality point", ghostdagData.SelectedParent())
current, err = mdm.finalityStore.FinalityPoint(mdm.databaseContext, stagingArea, ghostdagData.SelectedParent())
if err != nil {
return nil, err
}
} else if err != nil {
return nil, err
}
// In this case we expect the pruning point or a block above it to be the merge depth root.
// Note that above we already verified the chain and distance conditions for this
if current.Equal(model.VirtualGenesisBlockHash) {
current = pruningPoint
}
requiredBlueScore := ghostdagData.BlueScore() - mdm.mergeDepth
log.Debugf("%s's merge depth root is the one having the highest blue score lower then %d", blockHash, requiredBlueScore)
var next *externalapi.DomainHash
for {
next, err = mdm.dagTopologyManager.ChildInSelectedParentChainOf(stagingArea, current, blockHash)
if err != nil {
return nil, err
}
nextGHOSTDAGData, err := mdm.ghostdagDataStore.Get(mdm.databaseContext, stagingArea, next, false)
if err != nil {
return nil, err
}
if nextGHOSTDAGData.BlueScore() >= requiredBlueScore {
log.Debugf("%s's merge depth root is %s", blockHash, current)
return current, nil
}
current = next
}
}