mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
Always request orphan roots, even when you get an inv of a known orphan (#1436)
Co-authored-by: Svarog <feanorr@gmail.com>
This commit is contained in:
parent
abef96e3de
commit
319ab6cfcd
@ -4,6 +4,8 @@ import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashset"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -160,3 +162,49 @@ func (f *FlowContext) unorphanBlock(orphanHash externalapi.DomainHash) (*externa
|
||||
log.Infof("Unorphaned block %s", orphanHash)
|
||||
return blockInsertionResult, true, nil
|
||||
}
|
||||
|
||||
// GetOrphanRoots returns the roots of the missing ancestors DAG of the given orphan
|
||||
func (f *FlowContext) GetOrphanRoots(orphan *externalapi.DomainHash) ([]*externalapi.DomainHash, bool, error) {
|
||||
onEnd := logger.LogAndMeasureExecutionTime(log, "GetOrphanRoots")
|
||||
defer onEnd()
|
||||
|
||||
f.orphansMutex.RLock()
|
||||
defer f.orphansMutex.RUnlock()
|
||||
|
||||
_, ok := f.orphans[*orphan]
|
||||
if !ok {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
queue := []*externalapi.DomainHash{orphan}
|
||||
addedToQueueSet := hashset.New()
|
||||
addedToQueueSet.Add(orphan)
|
||||
|
||||
roots := []*externalapi.DomainHash{}
|
||||
for len(queue) > 0 {
|
||||
var current *externalapi.DomainHash
|
||||
current, queue = queue[0], queue[1:]
|
||||
|
||||
block, ok := f.orphans[*current]
|
||||
if !ok {
|
||||
blockInfo, err := f.domain.Consensus().GetBlockInfo(current)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if !blockInfo.Exists || blockInfo.BlockStatus == externalapi.StatusHeaderOnly {
|
||||
roots = append(roots, current)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
for _, parent := range block.Header.ParentHashes() {
|
||||
if !addedToQueueSet.Contains(parent) {
|
||||
queue = append(queue, parent)
|
||||
addedToQueueSet.Add(parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return roots, true, nil
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ type RelayInvsContext interface {
|
||||
SharedRequestedBlocks() *SharedRequestedBlocks
|
||||
Broadcast(message appmessage.Message) error
|
||||
AddOrphan(orphanBlock *externalapi.DomainBlock)
|
||||
GetOrphanRoots(orphanHash *externalapi.DomainHash) ([]*externalapi.DomainHash, bool, error)
|
||||
IsOrphan(blockHash *externalapi.DomainHash) bool
|
||||
IsIBDRunning() bool
|
||||
TrySetIBDRunning(ibdPeer *peerpkg.Peer) bool
|
||||
@ -71,7 +72,7 @@ func (flow *handleRelayInvsFlow) start() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if blockInfo.Exists {
|
||||
if blockInfo.Exists && blockInfo.BlockStatus != externalapi.StatusHeaderOnly {
|
||||
if blockInfo.BlockStatus == externalapi.StatusInvalid {
|
||||
return protocolerrors.Errorf(true, "sent inv of an invalid block %s",
|
||||
inv.Hash)
|
||||
@ -81,7 +82,11 @@ func (flow *handleRelayInvsFlow) start() error {
|
||||
}
|
||||
|
||||
if flow.IsOrphan(inv.Hash) {
|
||||
log.Debugf("Block %s is a known orphan. continuing...", inv.Hash)
|
||||
log.Debugf("Block %s is a known orphan. Requesting its missing ancestors", inv.Hash)
|
||||
err := flow.AddOrphanRootsToQueue(inv.Hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@ -107,7 +112,7 @@ func (flow *handleRelayInvsFlow) start() error {
|
||||
return err
|
||||
}
|
||||
if len(missingParents) > 0 {
|
||||
log.Debugf("Block %s contains orphans: %s", inv.Hash, missingParents)
|
||||
log.Debugf("Block %s is orphan and has missing parents: %s", inv.Hash, missingParents)
|
||||
err := flow.processOrphan(block, missingParents)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -238,9 +243,10 @@ func (flow *handleRelayInvsFlow) processOrphan(block *externalapi.DomainBlock, m
|
||||
}
|
||||
if isBlockInOrphanResolutionRange {
|
||||
log.Debugf("Block %s is within orphan resolution range. "+
|
||||
"Adding it to the orphan set and requesting its missing parents", blockHash)
|
||||
flow.addToOrphanSetAndRequestMissingParents(block, missingParents)
|
||||
return nil
|
||||
"Adding it to the orphan set", blockHash)
|
||||
flow.AddOrphan(block)
|
||||
log.Debugf("Requesting block %s missing ancestors", blockHash)
|
||||
return flow.AddOrphanRootsToQueue(blockHash)
|
||||
}
|
||||
|
||||
// Start IBD unless we already are in IBD
|
||||
@ -277,13 +283,25 @@ func (flow *handleRelayInvsFlow) isBlockInOrphanResolutionRange(blockHash *exter
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (flow *handleRelayInvsFlow) addToOrphanSetAndRequestMissingParents(
|
||||
block *externalapi.DomainBlock, missingParents []*externalapi.DomainHash) {
|
||||
|
||||
flow.AddOrphan(block)
|
||||
invMessages := make([]*appmessage.MsgInvRelayBlock, len(missingParents))
|
||||
for i, missingParent := range missingParents {
|
||||
invMessages[i] = appmessage.NewMsgInvBlock(missingParent)
|
||||
func (flow *handleRelayInvsFlow) AddOrphanRootsToQueue(orphan *externalapi.DomainHash) error {
|
||||
orphanRoots, orphanExists, err := flow.GetOrphanRoots(orphan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !orphanExists {
|
||||
log.Infof("Orphan block %s was missing from the orphan pool while requesting for its roots. This "+
|
||||
"probably happened because it was randomly evicted immediately after it was added.", orphan)
|
||||
}
|
||||
|
||||
log.Infof("Block %s has %d missing ancestors. Adding them to the invs queue...", orphan, len(orphanRoots))
|
||||
|
||||
invMessages := make([]*appmessage.MsgInvRelayBlock, len(orphanRoots))
|
||||
for i, root := range orphanRoots {
|
||||
log.Debugf("Adding block %s missing ancestor %s to the invs queue", orphan, root)
|
||||
invMessages[i] = appmessage.NewMsgInvBlock(root)
|
||||
}
|
||||
|
||||
flow.invsQueue = append(invMessages, flow.invsQueue...)
|
||||
return nil
|
||||
}
|
||||
|
@ -10,7 +10,8 @@ import (
|
||||
// current virtual. This process may result in a new virtual block
|
||||
// getting created
|
||||
func (csm *consensusStateManager) AddBlock(blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, error) {
|
||||
logger.LogAndMeasureExecutionTime(log, "csm.AddBlock")
|
||||
onEnd := logger.LogAndMeasureExecutionTime(log, "csm.AddBlock")
|
||||
defer onEnd()
|
||||
|
||||
log.Debugf("Resolving whether the block %s is the next virtual selected parent", blockHash)
|
||||
isCandidateToBeNextVirtualSelectedParent, err := csm.isCandidateToBeNextVirtualSelectedParent(blockHash)
|
||||
|
Loading…
x
Reference in New Issue
Block a user