p2p/discover: avoid dropping unverified nodes when table is almost empty (#21396)
This change improves discovery behavior in small networks. Very small networks would often fail to bootstrap because all member nodes were dropping table content due to findnode failure. The check is now changed to avoid dropping nodes on findnode failure when their bucket is almost empty. It also relaxes the liveness check requirement for FINDNODE/v4 response nodes, returning unverified nodes as results when there aren't any verified nodes yet. The "findnode failed" log now reports whether the node was dropped instead of the number of results. The value of the "results" was always zero by definition. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
@ -324,7 +324,16 @@ func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target v4wire.Pubke
|
||||
Target: target,
|
||||
Expiration: uint64(time.Now().Add(expiration).Unix()),
|
||||
})
|
||||
return nodes, <-rm.errc
|
||||
// Ensure that callers don't see a timeout if the node actually responded. Since
|
||||
// findnode can receive more than one neighbors response, the reply matcher will be
|
||||
// active until the remote node sends enough nodes. If the remote end doesn't have
|
||||
// enough nodes the reply matcher will time out waiting for the second reply, but
|
||||
// there's no need for an error in that case.
|
||||
err := <-rm.errc
|
||||
if err == errTimeout && rm.reply != nil {
|
||||
err = nil
|
||||
}
|
||||
return nodes, err
|
||||
}
|
||||
|
||||
// RequestENR sends enrRequest to the given node and waits for a response.
|
||||
@ -453,9 +462,9 @@ func (t *UDPv4) loop() {
|
||||
if p.from == r.from && p.ptype == r.data.Kind() && p.ip.Equal(r.ip) {
|
||||
ok, requestDone := p.callback(r.data)
|
||||
matched = matched || ok
|
||||
p.reply = r.data
|
||||
// Remove the matcher if callback indicates that all replies have been received.
|
||||
if requestDone {
|
||||
p.reply = r.data
|
||||
p.errc <- nil
|
||||
plist.Remove(el)
|
||||
}
|
||||
@ -715,9 +724,7 @@ func (t *UDPv4) handleFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno
|
||||
|
||||
// Determine closest nodes.
|
||||
target := enode.ID(crypto.Keccak256Hash(req.Target[:]))
|
||||
t.tab.mutex.Lock()
|
||||
closest := t.tab.closest(target, bucketSize, true).entries
|
||||
t.tab.mutex.Unlock()
|
||||
closest := t.tab.findnodeByID(target, bucketSize, true).entries
|
||||
|
||||
// Send neighbors in chunks with at most maxNeighbors per packet
|
||||
// to stay below the packet size limit.
|
||||
|
Reference in New Issue
Block a user