mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-03-04 08:15:24 +00:00
apply the traversal limit logic and sort headers
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
package blockrelay
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/domain"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// RequestPastDiffContext is the interface for the context needed for the HandleRequestHeaders flow.
|
||||
type RequestPastDiffContext interface {
|
||||
Domain() domain.Domain
|
||||
Config() *config.Config
|
||||
}
|
||||
|
||||
type handleRequestPastDiffFlow struct {
|
||||
@@ -43,13 +45,13 @@ func (flow *handleRequestPastDiffFlow) start() error {
|
||||
log.Debugf("Received requestPastDiff with hasHash: %s, requestedHash: %s", hasHash, requestedHash)
|
||||
log.Debugf("Getting past(%s) setminus past(%s) to %s", requestedHash, hasHash, flow.peer)
|
||||
|
||||
// GetPastDiff is a relatively heavy operation so we limit it
|
||||
// in order to avoid locking the consensus for too long
|
||||
// maxBlocks MUST be >= MergeSetSizeLimit + 1
|
||||
const maxBlocks = 1 << 10
|
||||
blockHashes, err := flow.Domain().Consensus().GetPastDiff(hasHash, requestedHash, maxBlocks)
|
||||
// GetPastDiff is expected to be called by the syncee for getting the anticone of the header selected tip
|
||||
// intersected by past of relayed block, and is thus expected to be bounded by mergeset limit since
|
||||
// we relay blocks only if they enter virtual's mergeset. We add 2 for a small margin error.
|
||||
blockHashes, err := flow.Domain().Consensus().GetPastDiff(hasHash, requestedHash,
|
||||
flow.Config().ActiveNetParams.MergeSetSizeLimit+2)
|
||||
if err != nil {
|
||||
return protocolerrors.Wrap(true, err, "Expected hashes in anticone one of the other")
|
||||
return protocolerrors.Wrap(true, err, "Failed querying anticone")
|
||||
}
|
||||
log.Debugf("Got %d header hashes in past(%s) setminus past(%s)", len(blockHashes), requestedHash, hasHash)
|
||||
|
||||
@@ -62,6 +64,14 @@ func (flow *handleRequestPastDiffFlow) start() error {
|
||||
blockHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(blockHeader)
|
||||
}
|
||||
|
||||
// We sort the headers in bottom-up topological order before sending
|
||||
sort.Slice(blockHeaders, func(i, j int) bool {
|
||||
return blockHeaders[i].BlueWork.Cmp(blockHeaders[j].BlueWork) < 0
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blockHeadersMessage := appmessage.NewBlockHeadersMessage(blockHeaders)
|
||||
err = flow.outgoingRoute.Enqueue(blockHeadersMessage)
|
||||
if err != nil {
|
||||
|
||||
@@ -720,7 +720,7 @@ func (s *consensus) Anticone(blockHash *externalapi.DomainHash) ([]*externalapi.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.dagTraversalManager.AnticoneFromBlocks(stagingArea, tips, blockHash)
|
||||
return s.dagTraversalManager.AnticoneFromBlocks(stagingArea, tips, blockHash, 0)
|
||||
}
|
||||
|
||||
func (s *consensus) EstimateNetworkHashesPerSecond(startHash *externalapi.DomainHash, windowSize int) (uint64, error) {
|
||||
|
||||
@@ -5,3 +5,7 @@ import "github.com/pkg/errors"
|
||||
// ErrBlockNotInSelectedParentChain is returned from CreateHeadersSelectedChainBlockLocator if one of the parameters
|
||||
// passed to it are not in the headers selected parent chain
|
||||
var ErrBlockNotInSelectedParentChain = errors.New("Block is not in selected parent chain")
|
||||
|
||||
// ErrReachedMaxTraversalAllowed is returned from AnticoneFromBlocks if `maxTraversalAllowed` was specified
|
||||
// and the traversal passed it
|
||||
var ErrReachedMaxTraversalAllowed = errors.New("Traversal searching for anticone passed the maxTraversalAllowed limit")
|
||||
|
||||
@@ -10,7 +10,7 @@ type DAGTraversalManager interface {
|
||||
// from lowHash (exclusive) to highHash (inclusive) over highHash's selected parent chain
|
||||
SelectedChildIterator(stagingArea *StagingArea, highHash, lowHash *externalapi.DomainHash, includeLowHash bool) (BlockIterator, error)
|
||||
SelectedChild(stagingArea *StagingArea, highHash, lowHash *externalapi.DomainHash) (*externalapi.DomainHash, error)
|
||||
AnticoneFromBlocks(stagingArea *StagingArea, tips []*externalapi.DomainHash, blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error)
|
||||
AnticoneFromBlocks(stagingArea *StagingArea, tips []*externalapi.DomainHash, blockHash *externalapi.DomainHash, maxTraversalAllowed uint64) ([]*externalapi.DomainHash, error)
|
||||
AnticoneFromVirtualPOV(stagingArea *StagingArea, blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error)
|
||||
BlockWindow(stagingArea *StagingArea, highHash *externalapi.DomainHash, windowSize int) ([]*externalapi.DomainHash, error)
|
||||
DAABlockWindow(stagingArea *StagingArea, highHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error)
|
||||
|
||||
@@ -14,16 +14,18 @@ func (dtm *dagTraversalManager) AnticoneFromVirtualPOV(stagingArea *model.Stagin
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dtm.AnticoneFromBlocks(stagingArea, virtualParents, blockHash)
|
||||
return dtm.AnticoneFromBlocks(stagingArea, virtualParents, blockHash, 0)
|
||||
}
|
||||
|
||||
func (dtm *dagTraversalManager) AnticoneFromBlocks(stagingArea *model.StagingArea, tips []*externalapi.DomainHash, blockHash *externalapi.DomainHash) (
|
||||
func (dtm *dagTraversalManager) AnticoneFromBlocks(stagingArea *model.StagingArea, tips []*externalapi.DomainHash,
|
||||
blockHash *externalapi.DomainHash, maxTraversalAllowed uint64) (
|
||||
[]*externalapi.DomainHash, error) {
|
||||
|
||||
anticone := []*externalapi.DomainHash{}
|
||||
queue := tips
|
||||
visited := hashset.New()
|
||||
|
||||
traversalCounter := uint64(0)
|
||||
for len(queue) > 0 {
|
||||
var current *externalapi.DomainHash
|
||||
current, queue = queue[0], queue[1:]
|
||||
@@ -48,6 +50,13 @@ func (dtm *dagTraversalManager) AnticoneFromBlocks(stagingArea *model.StagingAre
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We count the number of blocks in past(tips) \setminus past(blockHash).
|
||||
// We don't use `len(visited)` since it includes some maximal blocks in past(blockHash) as well.
|
||||
traversalCounter++
|
||||
if maxTraversalAllowed > 0 && traversalCounter > maxTraversalAllowed {
|
||||
return nil, model.ErrReachedMaxTraversalAllowed
|
||||
}
|
||||
|
||||
if !blockIsAncestorOfCurrent {
|
||||
anticone = append(anticone, current)
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@ func (sm *syncManager) GetPastDiff(stagingArea *model.StagingArea, hasHash,
|
||||
hasHash,
|
||||
requestedHash)
|
||||
}
|
||||
// TODO: use maxBlocks limit
|
||||
return sm.dagTraversalManager.AnticoneFromBlocks(stagingArea, []*externalapi.DomainHash{requestedHash}, hasHash)
|
||||
return sm.dagTraversalManager.AnticoneFromBlocks(stagingArea,
|
||||
[]*externalapi.DomainHash{requestedHash}, hasHash, maxBlocks)
|
||||
}
|
||||
|
||||
func (sm *syncManager) GetMissingBlockBodyHashes(stagingArea *model.StagingArea, highHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
||||
|
||||
Reference in New Issue
Block a user