[Issue - #1126] - Checking pruning point violation - pruning point in the past. (#1160)

* [NOD-1126]
1. Change function name in BlockValidator interface from: "ValidateProofOfWorkAndDifficulty" to "ValidatePruningPointViolationAndProofOfWorkAndDifficulty".
2. Add to the blockValidator struct the pruningManager (also added to the function "New" Respectively).
3. Added new function "checkPruningPointViolation" of blockValidator type.
4. Add new internal check - "checkPruningPointViolation", on the function "ValidateProofOfWorkAndDifficulty".(The third check).
5. Add new error rule - "ErrPruningPointViolation".

* [Issue-1126]
1. Remove the function "PruningPoint" from PruningManager interface.
2. Changes in blockValidator struct - remove pruningManager, and adding pruningStore.
3. Reads for "pruningPoint" function from pruningStore instead of pruningManager (because of note 1 above) in the functions: * "checkPruningPointViolation" of type blockValidator.
             * "FindNextPruningPoint" of type pruningManager.

* [Issue-1126]
1. Add missing error handling.

* [Issue-1126] Changes in function "checkPruningPointViolation": If header = genesis, stop checking and return nil.

* [Issue-1126] In function "checkPruningPointViolation" - change from a for loop to the "IsAncestorOfAny" function.

* [#1126] "FindNextPruningPoint" - save the pruning point in case the point is the genesis and change code internal order.

* [#1126] "FindNextPruningPoint" - cosmetics change.

* [#1126] "FindNextPruningPoint" - remove "return nil" when there is no pruning point on the if expression.

Co-authored-by: tal <tal@daglabs.com>
This commit is contained in:
talelbaz 2020-11-30 09:57:15 +02:00 committed by GitHub
parent a1af992d15
commit f407c44a8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 30 deletions

View File

@ -153,6 +153,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
dagTraversalManager,
coinbaseManager,
mergeDepthManager,
pruningStore,
blockStore,
ghostdagDataStore,

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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,

View File

@ -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)
}

View File

@ -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()

View File

@ -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