Do not apply merge depth root heuristic on orphan roots (#2019)

This commit is contained in:
Michael Sutton 2022-04-13 21:06:08 +03:00 committed by GitHub
parent 2b395e34b1
commit 723aebbec9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 26 deletions

View File

@ -21,7 +21,7 @@ func (flow *handleRelayInvsFlow) receiveBlockLocator() (blockLocatorHashes []*ex
switch message := message.(type) { switch message := message.(type) {
case *appmessage.MsgInvRelayBlock: case *appmessage.MsgInvRelayBlock:
flow.invsQueue = append(flow.invsQueue, message) flow.invsQueue = append(flow.invsQueue, invRelayBlock{Hash: message.Hash, IsOrphanRoot: false})
case *appmessage.MsgBlockLocator: case *appmessage.MsgBlockLocator:
return message.BlockLocatorHashes, nil return message.BlockLocatorHashes, nil
default: default:

View File

@ -40,11 +40,16 @@ type RelayInvsContext interface {
IsNearlySynced() (bool, error) IsNearlySynced() (bool, error)
} }
type invRelayBlock struct {
Hash *externalapi.DomainHash
IsOrphanRoot bool
}
type handleRelayInvsFlow struct { type handleRelayInvsFlow struct {
RelayInvsContext RelayInvsContext
incomingRoute, outgoingRoute *router.Route incomingRoute, outgoingRoute *router.Route
peer *peerpkg.Peer peer *peerpkg.Peer
invsQueue []*appmessage.MsgInvRelayBlock invsQueue []invRelayBlock
} }
// HandleRelayInvs listens to appmessage.MsgInvRelayBlock messages, requests their corresponding blocks if they // HandleRelayInvs listens to appmessage.MsgInvRelayBlock messages, requests their corresponding blocks if they
@ -57,7 +62,7 @@ func HandleRelayInvs(context RelayInvsContext, incomingRoute *router.Route, outg
incomingRoute: incomingRoute, incomingRoute: incomingRoute,
outgoingRoute: outgoingRoute, outgoingRoute: outgoingRoute,
peer: peer, peer: peer,
invsQueue: make([]*appmessage.MsgInvRelayBlock, 0), invsQueue: make([]invRelayBlock, 0),
} }
err := flow.start() err := flow.start()
// Currently, HandleRelayInvs flow is the only place where IBD is triggered, so the channel can be closed now // Currently, HandleRelayInvs flow is the only place where IBD is triggered, so the channel can be closed now
@ -140,23 +145,27 @@ func (flow *handleRelayInvsFlow) start() error {
continue continue
} }
// Test bounded merge depth to avoid requesting irrelevant data which cannot be merged under virtual // Note we do not apply the heuristic below if inv was queued as an orphan root, since
virtualMergeDepthRoot, err := flow.Domain().Consensus().VirtualMergeDepthRoot() // that means the process started by a proper and relevant relay block
if err != nil { if !inv.IsOrphanRoot {
return err // Check bounded merge depth to avoid requesting irrelevant data which cannot be merged under virtual
} virtualMergeDepthRoot, err := flow.Domain().Consensus().VirtualMergeDepthRoot()
if !virtualMergeDepthRoot.Equal(model.VirtualGenesisBlockHash) {
mergeDepthRootHeader, err := flow.Domain().Consensus().GetBlockHeader(virtualMergeDepthRoot)
if err != nil { if err != nil {
return err return err
} }
// Since `BlueWork` respects topology, this condition means that the relay if !virtualMergeDepthRoot.Equal(model.VirtualGenesisBlockHash) {
// block is not in the future of virtual's merge depth root, and thus cannot be merged unless mergeDepthRootHeader, err := flow.Domain().Consensus().GetBlockHeader(virtualMergeDepthRoot)
// other valid blocks Kosherize it, in which case it will be obtained once the merger is relayed if err != nil {
if block.Header.BlueWork().Cmp(mergeDepthRootHeader.BlueWork()) <= 0 { return err
log.Debugf("Block %s has lower blue work than virtual's merge root %s (%d <= %d), hence we are skipping it", }
inv.Hash, virtualMergeDepthRoot, block.Header.BlueWork(), mergeDepthRootHeader.BlueWork()) // Since `BlueWork` respects topology, this condition means that the relay
continue // block is not in the future of virtual's merge depth root, and thus cannot be merged unless
// other valid blocks Kosherize it, in which case it will be obtained once the merger is relayed
if block.Header.BlueWork().Cmp(mergeDepthRootHeader.BlueWork()) <= 0 {
log.Debugf("Block %s has lower blue work than virtual's merge root %s (%d <= %d), hence we are skipping it",
inv.Hash, virtualMergeDepthRoot, block.Header.BlueWork(), mergeDepthRootHeader.BlueWork())
continue
}
} }
} }
@ -240,24 +249,24 @@ func (flow *handleRelayInvsFlow) banIfBlockIsHeaderOnly(block *externalapi.Domai
return nil return nil
} }
func (flow *handleRelayInvsFlow) readInv() (*appmessage.MsgInvRelayBlock, error) { func (flow *handleRelayInvsFlow) readInv() (invRelayBlock, error) {
if len(flow.invsQueue) > 0 { if len(flow.invsQueue) > 0 {
var inv *appmessage.MsgInvRelayBlock var inv invRelayBlock
inv, flow.invsQueue = flow.invsQueue[0], flow.invsQueue[1:] inv, flow.invsQueue = flow.invsQueue[0], flow.invsQueue[1:]
return inv, nil return inv, nil
} }
msg, err := flow.incomingRoute.Dequeue() msg, err := flow.incomingRoute.Dequeue()
if err != nil { if err != nil {
return nil, err return invRelayBlock{}, err
} }
inv, ok := msg.(*appmessage.MsgInvRelayBlock) msgInv, ok := msg.(*appmessage.MsgInvRelayBlock)
if !ok { if !ok {
return nil, protocolerrors.Errorf(true, "unexpected %s message in the block relay handleRelayInvsFlow while "+ return invRelayBlock{}, protocolerrors.Errorf(true, "unexpected %s message in the block relay handleRelayInvsFlow while "+
"expecting an inv message", msg.Command()) "expecting an inv message", msg.Command())
} }
return inv, nil return invRelayBlock{Hash: msgInv.Hash, IsOrphanRoot: false}, nil
} }
func (flow *handleRelayInvsFlow) requestBlock(requestHash *externalapi.DomainHash) (*externalapi.DomainBlock, bool, error) { func (flow *handleRelayInvsFlow) requestBlock(requestHash *externalapi.DomainHash) (*externalapi.DomainBlock, bool, error) {
@ -302,7 +311,7 @@ func (flow *handleRelayInvsFlow) readMsgBlock() (msgBlock *appmessage.MsgBlock,
switch message := message.(type) { switch message := message.(type) {
case *appmessage.MsgInvRelayBlock: case *appmessage.MsgInvRelayBlock:
flow.invsQueue = append(flow.invsQueue, message) flow.invsQueue = append(flow.invsQueue, invRelayBlock{Hash: message.Hash, IsOrphanRoot: false})
case *appmessage.MsgBlock: case *appmessage.MsgBlock:
return message, nil return message, nil
default: default:
@ -443,10 +452,10 @@ func (flow *handleRelayInvsFlow) AddOrphanRootsToQueue(orphan *externalapi.Domai
} }
log.Infof("Block %s has %d missing ancestors. Adding them to the invs queue...", orphan, len(orphanRoots)) log.Infof("Block %s has %d missing ancestors. Adding them to the invs queue...", orphan, len(orphanRoots))
invMessages := make([]*appmessage.MsgInvRelayBlock, len(orphanRoots)) invMessages := make([]invRelayBlock, len(orphanRoots))
for i, root := range orphanRoots { for i, root := range orphanRoots {
log.Debugf("Adding block %s missing ancestor %s to the invs queue", orphan, root) log.Debugf("Adding block %s missing ancestor %s to the invs queue", orphan, root)
invMessages[i] = appmessage.NewMsgInvBlock(root) invMessages[i] = invRelayBlock{Hash: root, IsOrphanRoot: true}
} }
flow.invsQueue = append(invMessages, flow.invsQueue...) flow.invsQueue = append(invMessages, flow.invsQueue...)