diff --git a/domain/consensus/factory.go b/domain/consensus/factory.go index 4e95ca67b..222fe0016 100644 --- a/domain/consensus/factory.go +++ b/domain/consensus/factory.go @@ -153,6 +153,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat dagTraversalManager, coinbaseManager, mergeDepthManager, + pruningStore, blockStore, ghostdagDataStore, diff --git a/domain/consensus/model/interface_processes_blockvalidator.go b/domain/consensus/model/interface_processes_blockvalidator.go index 0cdc771e7..12dde50d0 100644 --- a/domain/consensus/model/interface_processes_blockvalidator.go +++ b/domain/consensus/model/interface_processes_blockvalidator.go @@ -11,5 +11,5 @@ type BlockValidator interface { ValidateBodyInIsolation(blockHash *externalapi.DomainHash) error ValidateHeaderInContext(blockHash *externalapi.DomainHash) error ValidateBodyInContext(blockHash *externalapi.DomainHash) error - ValidateProofOfWorkAndDifficulty(blockHash *externalapi.DomainHash) error + ValidatePruningPointViolationAndProofOfWorkAndDifficulty(blockHash *externalapi.DomainHash) error } diff --git a/domain/consensus/model/interface_processes_pruningmanager.go b/domain/consensus/model/interface_processes_pruningmanager.go index b6e0ea85f..09322ebad 100644 --- a/domain/consensus/model/interface_processes_pruningmanager.go +++ b/domain/consensus/model/interface_processes_pruningmanager.go @@ -1,9 +1,6 @@ package model -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - // PruningManager resolves and manages the current pruning point type PruningManager interface { FindNextPruningPoint() error - PruningPoint() (*externalapi.DomainHash, error) } diff --git a/domain/consensus/processes/blockprocessor/validateandinsertblock.go b/domain/consensus/processes/blockprocessor/validateandinsertblock.go index 5c18947f0..f521c9b52 100644 --- a/domain/consensus/processes/blockprocessor/validateandinsertblock.go +++ b/domain/consensus/processes/blockprocessor/validateandinsertblock.go @@ -240,7 +240,7 @@ func (bp *blockProcessor) validateBlock(block *externalapi.DomainBlock, mode *ex return err } - err = bp.blockValidator.ValidateProofOfWorkAndDifficulty(blockHash) + err = bp.blockValidator.ValidatePruningPointViolationAndProofOfWorkAndDifficulty(blockHash) if err != nil { return err } diff --git a/domain/consensus/processes/blockvalidator/blockvalidator.go b/domain/consensus/processes/blockvalidator/blockvalidator.go index 91bdf2bd8..7c3fa4e10 100644 --- a/domain/consensus/processes/blockvalidator/blockvalidator.go +++ b/domain/consensus/processes/blockvalidator/blockvalidator.go @@ -28,6 +28,7 @@ type blockValidator struct { dagTraversalManager model.DAGTraversalManager coinbaseManager model.CoinbaseManager mergeDepthManager model.MergeDepthManager + pruningStore model.PruningStore blockStore model.BlockStore ghostdagDataStore model.GHOSTDAGDataStore @@ -52,6 +53,7 @@ func New(powMax *big.Int, dagTraversalManager model.DAGTraversalManager, coinbaseManager model.CoinbaseManager, mergeDepthManager model.MergeDepthManager, + pruningStore model.PruningStore, blockStore model.BlockStore, ghostdagDataStore model.GHOSTDAGDataStore, @@ -75,6 +77,7 @@ func New(powMax *big.Int, dagTraversalManager: dagTraversalManager, coinbaseManager: coinbaseManager, mergeDepthManager: mergeDepthManager, + pruningStore: pruningStore, blockStore: blockStore, ghostdagDataStore: ghostdagDataStore, diff --git a/domain/consensus/processes/blockvalidator/proof_of_work.go b/domain/consensus/processes/blockvalidator/proof_of_work.go index 6014a0282..e6de47b69 100644 --- a/domain/consensus/processes/blockvalidator/proof_of_work.go +++ b/domain/consensus/processes/blockvalidator/proof_of_work.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" ) -func (v *blockValidator) ValidateProofOfWorkAndDifficulty(blockHash *externalapi.DomainHash) error { +func (v *blockValidator) ValidatePruningPointViolationAndProofOfWorkAndDifficulty(blockHash *externalapi.DomainHash) error { header, err := v.blockHeaderStore.BlockHeader(v.databaseContext, blockHash) if err != nil { return err @@ -25,6 +25,11 @@ func (v *blockValidator) ValidateProofOfWorkAndDifficulty(blockHash *externalapi return err } + err = v.checkPruningPointViolation(header) + if err != nil { + return err + } + err = v.checkProofOfWork(header) if err != nil { return err @@ -119,3 +124,31 @@ func (v *blockValidator) checkParentsExist(header *externalapi.DomainBlockHeader return nil } +func (v *blockValidator) checkPruningPointViolation(header *externalapi.DomainBlockHeader) error { + // check if the pruning point is on past of at least one parent of the header's parents. + + hasPruningPoint, err := v.pruningStore.HasPruningPoint(v.databaseContext) + if err != nil { + return err + } + + //If hasPruningPoint has a false value, it means that it's the genesis - so no violation can exist. + if !hasPruningPoint { + return nil + } + + pruningPoint, err := v.pruningStore.PruningPoint(v.databaseContext) + if err != nil { + return err + } + + isAncestorOfAny, err := v.dagTopologyManager.IsAncestorOfAny(pruningPoint, header.ParentHashes) + if err != nil { + return err + } + if isAncestorOfAny { + return nil + } + return errors.Wrapf(ruleerrors.ErrPruningPointViolation, + "expected pruning point to be in block %d past.", header.Bits) +} diff --git a/domain/consensus/processes/pruningmanager/pruningmanager.go b/domain/consensus/processes/pruningmanager/pruningmanager.go index 36c397dc2..9dda97c9d 100644 --- a/domain/consensus/processes/pruningmanager/pruningmanager.go +++ b/domain/consensus/processes/pruningmanager/pruningmanager.go @@ -73,15 +73,28 @@ func New( // FindNextPruningPoint finds the next pruning point from the // given blockHash func (pm *pruningManager) FindNextPruningPoint() error { + hasPruningPoint, err := pm.pruningStore.HasPruningPoint(pm.databaseContext) + if err != nil { + return err + } + + if !hasPruningPoint { + err = pm.savePruningPoint(pm.genesisHash) + if err != nil { + return err + } + } + + currentP, err := pm.pruningStore.PruningPoint(pm.databaseContext) + if err != nil { + return err + } + virtual, err := pm.ghostdagDataStore.Get(pm.databaseContext, model.VirtualBlockHash) if err != nil { return err } - currentP, err := pm.PruningPoint() - if err != nil { - return err - } currentPGhost, err := pm.ghostdagDataStore.Get(pm.databaseContext, currentP) if err != nil { return err @@ -118,26 +131,6 @@ func (pm *pruningManager) FindNextPruningPoint() error { return pm.deletePastBlocks(currentP) } -// PruningPoint returns the hash of the current pruning point -func (pm *pruningManager) PruningPoint() (*externalapi.DomainHash, error) { - hasPruningPoint, err := pm.pruningStore.HasPruningPoint(pm.databaseContext) - if err != nil { - return nil, err - } - if hasPruningPoint { - return pm.pruningStore.PruningPoint(pm.databaseContext) - } - - // If there's no pruning point yet, set genesis as the pruning point. - // This is the genesis because it means `FindNextPruningPoint()` has never been called before, - // if this is part of the first `FindNextPruningPoint()` call, then it might move the pruning point forward. - err = pm.savePruningPoint(pm.genesisHash) - if err != nil { - return nil, err - } - return pm.genesisHash, nil -} - func (pm *pruningManager) deletePastBlocks(pruningPoint *externalapi.DomainHash) error { // Go over all P.Past and P.AC that's not in V.Past queue := pm.dagTraversalManager.NewDownHeap() diff --git a/domain/consensus/ruleerrors/rule_error.go b/domain/consensus/ruleerrors/rule_error.go index 8b0367b89..6dab741f2 100644 --- a/domain/consensus/ruleerrors/rule_error.go +++ b/domain/consensus/ruleerrors/rule_error.go @@ -233,6 +233,9 @@ var ( ErrMalformedUTXO = newRuleError("ErrMalformedUTXO") ErrWrongPruningPointHash = newRuleError("ErrWrongPruningPointHash") + + //ErrPruningPointViolation indicates that the pruning point isn't in the block past. + ErrPruningPointViolation = newRuleError("ErrPruningPointViolation") ) // RuleError identifies a rule violation. It is used to indicate that