[NOD-1555] Use stageDiff to update virtualDiffParents (#1139)

* [NOD-1555] Filter ancestors in updateVirtualDiffParents

* [NOD-1555] Use stageDiff to update virtualDiffParents

* [NOD-1555] Don't add existing blocks in addToVirtualDiffParents

* [NOD-1555] Remove redundant check

* [NOD-1555] Fix log and rename removeAncestorsFromVirtualDiffParents->removeAncestorsFromVirtualDiffParentsAndAssignDiffChild

* [NOD-1555] Add logs

* [NOD-1555] Fix comment

* [NOD-1555] Fix logs
This commit is contained in:
Ori Newman 2020-11-23 05:09:39 -08:00 committed by GitHub
parent dec9ef5f75
commit c1505b4748
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 79 deletions

View File

@ -62,7 +62,7 @@ func (bss *blockStatusStore) Get(dbContext model.DBReader, blockHash *externalap
return 0, err
}
return bss.deserializeHeader(statusBytes)
return bss.deserializeBlockStatus(statusBytes)
}
// Exists returns true if the blockStatus for the given blockHash exists
@ -84,7 +84,7 @@ func (bss *blockStatusStore) serializeBlockStatus(status externalapi.BlockStatus
return proto.Marshal(dbBlockStatus)
}
func (bss *blockStatusStore) deserializeHeader(statusBytes []byte) (externalapi.BlockStatus, error) {
func (bss *blockStatusStore) deserializeBlockStatus(statusBytes []byte) (externalapi.BlockStatus, error) {
dbBlockStatus := &serialization.DbBlockStatus{}
err := proto.Unmarshal(statusBytes, dbBlockStatus)
if err != nil {

View File

@ -157,67 +157,67 @@ func (csm *consensusStateManager) resolveSingleBlockStatus(blockHash *externalap
csm.multisetStore.Stage(blockHash, multiset)
log.Tracef("Staging the utxoDiff of block %s", blockHash)
err = csm.utxoDiffStore.Stage(blockHash, pastUTXODiff, nil)
err = csm.stageDiff(blockHash, pastUTXODiff, nil)
if err != nil {
return 0, err
}
log.Tracef("Updating the parent utxoDiffs of block %s", blockHash)
err = csm.updateParentDiffs(blockHash, pastUTXODiff)
log.Tracef("Remove block ancestors from virtual diff parents and assign %s as their diff child", blockHash)
err = csm.removeAncestorsFromVirtualDiffParentsAndAssignDiffChild(blockHash, pastUTXODiff)
if err != nil {
return 0, err
}
return externalapi.StatusValid, nil
}
func (csm *consensusStateManager) updateParentDiffs(
blockHash *externalapi.DomainHash, pastUTXODiff *model.UTXODiff) error {
log.Tracef("updateParentDiffs start for block %s", blockHash)
defer log.Tracef("updateParentDiffs end for block %s", blockHash)
parentHashes, err := csm.dagTopologyManager.Parents(blockHash)
func (csm *consensusStateManager) removeAncestorsFromVirtualDiffParentsAndAssignDiffChild(
blockHash *externalapi.DomainHash, pastUTXODiff *model.UTXODiff) error {
log.Tracef("removeAncestorsFromVirtualDiffParentsAndAssignDiffChild start for block %s", blockHash)
defer log.Tracef("removeAncestorsFromVirtualDiffParentsAndAssignDiffChild end for block %s", blockHash)
if *blockHash == *csm.genesisHash {
log.Tracef("Genesis block doesn't have ancestors to remove from the virtual diff parents")
return nil
}
virtualDiffParents, err := csm.consensusStateStore.VirtualDiffParents(csm.databaseContext)
if err != nil {
return err
}
log.Tracef("Parent hashes for block %s are: %s", blockHash, parentHashes)
for _, parentHash := range parentHashes {
// skip all parents that already have a utxo-diff child
parentHasUTXODiffChild, err := csm.utxoDiffStore.HasUTXODiffChild(csm.databaseContext, parentHash)
if err != nil {
return err
}
if parentHasUTXODiffChild {
log.Tracef("Skipping parent %s of block %s because it "+
"already has a UTXO diff-child", parentHash, blockHash)
for _, virtualDiffParent := range virtualDiffParents {
if *virtualDiffParent == *blockHash {
log.Tracef("Skipping updating virtual diff parent %s "+
"because it was updated before.", virtualDiffParent)
continue
}
parentStatus, err := csm.blockStatusStore.Get(csm.databaseContext, parentHash)
isAncestorOfBlock, err := csm.dagTopologyManager.IsAncestorOf(virtualDiffParent, blockHash)
if err != nil {
return err
}
if parentStatus != externalapi.StatusValid {
log.Tracef("Skipping parent %s of block %s because it "+
"has a non-valid status %s", parentHash, blockHash, parentStatus)
if !isAncestorOfBlock {
log.Tracef("Skipping block %s because it's not an "+
"ancestor of %s", virtualDiffParent, blockHash)
continue
}
// parents that didn't have a utxo-diff child until now were actually virtual's diffParents.
// Update them to have the new block as their utxo-diff child
log.Tracef("Resolving new UTXO diff of parent %s", parentHash)
parentCurrentDiff, err := csm.utxoDiffStore.UTXODiff(csm.databaseContext, parentHash)
log.Tracef("Updating %s to be the diff child of %s", blockHash, virtualDiffParent)
currentDiff, err := csm.utxoDiffStore.UTXODiff(csm.databaseContext, virtualDiffParent)
if err != nil {
return err
}
parentNewDiff, err := utxoalgebra.DiffFrom(pastUTXODiff, parentCurrentDiff)
newDiff, err := utxoalgebra.DiffFrom(pastUTXODiff, currentDiff)
if err != nil {
return err
}
log.Tracef("The new UTXO diff parent %s resolved to: %s", parentHash, parentNewDiff)
log.Tracef("Staging the new UTXO diff and diff child for parent %s", parentHash)
err = csm.utxoDiffStore.Stage(parentHash, parentNewDiff, blockHash)
err = csm.stageDiff(virtualDiffParent, newDiff, blockHash)
if err != nil {
return err
}

View File

@ -90,7 +90,7 @@ func (csm *consensusStateManager) setPruningPointUTXOSet(serializedUTXOSet []byt
}
log.Tracef("Updating the header tips pruning point diff parents with an empty UTXO diff")
err = csm.updateVirtualDiffParents(headerTipsPruningPoint, model.NewUTXODiff())
err = csm.updateVirtualDiffParents(model.NewUTXODiff())
if err != nil {
return err
}

View File

@ -4,7 +4,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/processes/consensusstatemanager/utxoalgebra"
"github.com/kaspanet/kaspad/domain/consensus/utils/hashset"
)
func (csm *consensusStateManager) updateVirtual(newBlockHash *externalapi.DomainHash, tips []*externalapi.DomainHash) error {
@ -51,7 +50,7 @@ func (csm *consensusStateManager) updateVirtual(newBlockHash *externalapi.Domain
}
log.Tracef("Updating the virtual diff parents after adding %s to the DAG", newBlockHash)
err = csm.updateVirtualDiffParents(newBlockHash, virtualUTXODiff)
err = csm.updateVirtualDiffParents(virtualUTXODiff)
if err != nil {
return err
}
@ -59,52 +58,16 @@ func (csm *consensusStateManager) updateVirtual(newBlockHash *externalapi.Domain
return nil
}
func (csm *consensusStateManager) updateVirtualDiffParents(
newBlockHash *externalapi.DomainHash, virtualUTXODiff *model.UTXODiff) error {
func (csm *consensusStateManager) updateVirtualDiffParents(virtualUTXODiff *model.UTXODiff) error {
log.Tracef("updateVirtualDiffParents start")
defer log.Tracef("updateVirtualDiffParents end")
log.Tracef("updateVirtualDiffParents start for block %s", newBlockHash)
defer log.Tracef("updateVirtualDiffParents end for block %s", newBlockHash)
var newVirtualDiffParents []*externalapi.DomainHash
if *newBlockHash == *csm.genesisHash {
log.Tracef("Block %s is the genesis, so by definition "+
"it is the only member of the new virtual diff parents set", newBlockHash)
newVirtualDiffParents = []*externalapi.DomainHash{newBlockHash}
} else {
oldVirtualDiffParents, err := csm.consensusStateStore.VirtualDiffParents(csm.databaseContext)
if err != nil {
return err
}
log.Tracef("The old virtual's diff parents are: %s", oldVirtualDiffParents)
// If the status of the new block is not `Valid` - virtualDiffParents didn't change
status, err := csm.blockStatusStore.Get(csm.databaseContext, newBlockHash)
if err != nil {
return err
}
if status != externalapi.StatusValid {
log.Tracef("The status of the new block %s is non-valid. "+
"As such, don't change the diff parents of the virtual", newBlockHash)
newVirtualDiffParents = oldVirtualDiffParents
} else {
log.Tracef("Block %s is valid. Updating the virtual diff parents", newBlockHash)
newBlockParentsSlice, err := csm.dagTopologyManager.Parents(newBlockHash)
if err != nil {
return err
}
newBlockParents := hashset.NewFromSlice(newBlockParentsSlice...)
newVirtualDiffParents = []*externalapi.DomainHash{newBlockHash}
for _, virtualDiffParent := range oldVirtualDiffParents {
if !newBlockParents.Contains(virtualDiffParent) {
newVirtualDiffParents = append(newVirtualDiffParents, virtualDiffParent)
}
}
}
virtualDiffParents, err := csm.consensusStateStore.VirtualDiffParents(csm.databaseContext)
if err != nil {
return err
}
log.Tracef("The new virtual diff parents are: %s", newVirtualDiffParents)
for _, virtualDiffParent := range newVirtualDiffParents {
for _, virtualDiffParent := range virtualDiffParents {
log.Tracef("Calculating new UTXO diff for virtual diff parent %s", virtualDiffParent)
virtualDiffParentUTXODiff, err := csm.utxoDiffStore.UTXODiff(csm.databaseContext, virtualDiffParent)
if err != nil {
@ -114,13 +77,13 @@ func (csm *consensusStateManager) updateVirtualDiffParents(
if err != nil {
return err
}
log.Tracef("Staging new UTXO diff for virtual diff parent %s: %s", virtualDiffParent, newDiff)
err = csm.utxoDiffStore.Stage(virtualDiffParent, newDiff, nil)
err = csm.stageDiff(virtualDiffParent, newDiff, nil)
if err != nil {
return err
}
}
log.Tracef("Staging the new virtual UTXO diff parents")
return csm.consensusStateStore.StageVirtualDiffParents(newVirtualDiffParents)
return nil
}

View File

@ -0,0 +1,84 @@
package consensusstatemanager
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/pkg/errors"
)
func (csm *consensusStateManager) stageDiff(blockHash *externalapi.DomainHash,
utxoDiff *model.UTXODiff, utxoDiffChild *externalapi.DomainHash) error {
log.Tracef("stageDiff start for block %s", blockHash)
defer log.Tracef("stageDiff end for block %s", blockHash)
log.Tracef("Staging block %s as the diff child of %s", utxoDiffChild, blockHash)
err := csm.utxoDiffStore.Stage(blockHash, utxoDiff, utxoDiffChild)
if err != nil {
return err
}
if utxoDiffChild == nil {
log.Tracef("Adding block %s to the virtual diff parents", blockHash)
return csm.addToVirtualDiffParents(blockHash)
}
log.Tracef("Removing block %s from the virtual diff parents", blockHash)
return csm.removeFromVirtualDiffParents(blockHash)
}
func (csm *consensusStateManager) addToVirtualDiffParents(blockHash *externalapi.DomainHash) error {
log.Tracef("addToVirtualDiffParents start for block %s", blockHash)
defer log.Tracef("addToVirtualDiffParents end for block %s", blockHash)
var oldVirtualDiffParents []*externalapi.DomainHash
if *blockHash != *csm.genesisHash {
var err error
oldVirtualDiffParents, err = csm.consensusStateStore.VirtualDiffParents(csm.databaseContext)
if err != nil {
return err
}
}
isInVirtualDiffParents := false
for _, diffParent := range oldVirtualDiffParents {
if *diffParent == *blockHash {
isInVirtualDiffParents = true
break
}
}
if isInVirtualDiffParents {
log.Tracef("Block %s is already a virtual diff parent, so there's no need to add it", blockHash)
return nil
}
newVirtualDiffParents := append([]*externalapi.DomainHash{blockHash}, oldVirtualDiffParents...)
log.Tracef("Staging virtual diff parents after adding %s to it", blockHash)
return csm.consensusStateStore.StageVirtualDiffParents(newVirtualDiffParents)
}
func (csm *consensusStateManager) removeFromVirtualDiffParents(blockHash *externalapi.DomainHash) error {
log.Tracef("removeFromVirtualDiffParents start for block %s", blockHash)
defer log.Tracef("removeFromVirtualDiffParents end for block %s", blockHash)
oldVirtualDiffParents, err := csm.consensusStateStore.VirtualDiffParents(csm.databaseContext)
if err != nil {
return err
}
newVirtualDiffParents := make([]*externalapi.DomainHash, 0, len(oldVirtualDiffParents)-1)
for _, diffParent := range oldVirtualDiffParents {
if *diffParent != *blockHash {
newVirtualDiffParents = append(newVirtualDiffParents, diffParent)
}
}
if len(newVirtualDiffParents) != len(oldVirtualDiffParents)-1 {
return errors.Errorf("expected to remove one member from virtual diff parents and "+
"have a length of %d but got length of %d", len(oldVirtualDiffParents)-1, len(newVirtualDiffParents))
}
log.Tracef("Staging virtual diff parents after removing %s from it", blockHash)
return csm.consensusStateStore.StageVirtualDiffParents(newVirtualDiffParents)
}