p2p/discover: move node to fast revalidation list on inbound endpoint update

This commit is contained in:
Felix Lange 2024-05-28 18:49:45 +02:00
parent ddcabb198f
commit 3148497f2b
2 changed files with 22 additions and 17 deletions

View file

@ -513,12 +513,9 @@ func (tab *Table) handleAddNode(req addNodeOp) bool {
} }
b := tab.bucket(req.node.ID()) b := tab.bucket(req.node.ID())
n, wasUpdated := tab.bumpInBucket(b, req.node.Node, req.isInbound) n, _ := tab.bumpInBucket(b, req.node.Node, req.isInbound)
if n != nil { if n != nil {
// Already in bucket. // Already in bucket.
if wasUpdated {
n.isValidatedLive = false
}
return false return false
} }
if len(b.entries) >= bucketSize { if len(b.entries) >= bucketSize {
@ -627,7 +624,9 @@ func (tab *Table) bumpInBucket(b *bucket, newRecord *enode.Node, isInbound bool)
} }
// Check if there is an endpoint update and validate against IP limits. // Check if there is an endpoint update and validate against IP limits.
if newRecord.IPAddr() != b.entries[i].IPAddr() { ipchanged := newRecord.IPAddr() != n.IPAddr()
portchanged := newRecord.UDP() != n.UDP()
if ipchanged {
tab.removeIP(b, n.IP()) tab.removeIP(b, n.IP())
if !tab.addIP(b, newRecord.IP()) { if !tab.addIP(b, newRecord.IP()) {
// It doesn't fit with the limit, put the previous record back. // It doesn't fit with the limit, put the previous record back.
@ -636,8 +635,15 @@ func (tab *Table) bumpInBucket(b *bucket, newRecord *enode.Node, isInbound bool)
} }
} }
// Apply update.
n.Node = newRecord n.Node = newRecord
return n, true
// Endpoint changes cause the node to be considered unverified.
if ipchanged || portchanged {
tab.revalidation.nodeEndpointChanged(tab, n)
return n, true
}
return n, false
} }
func (tab *Table) handleTrackRequest(op trackRequestOp) { func (tab *Table) handleTrackRequest(op trackRequestOp) {

View file

@ -65,6 +65,12 @@ func (tr *tableRevalidation) nodeRemoved(n *node) {
n.revalList.remove(n) n.revalList.remove(n)
} }
// nodeEndpointChanged is called when a change in IP or port is detected.
func (tr *tableRevalidation) nodeEndpointChanged(tab *Table, n *node) {
n.isValidatedLive = false
tr.moveToList(&tr.fast, n, tab.cfg.Clock.Now(), &tab.rand)
}
// run performs node revalidation. // run performs node revalidation.
// It returns the next time it should be invoked, which is used in the Table main loop // It returns the next time it should be invoked, which is used in the Table main loop
// to schedule a timer. However, run can be called at any time. // to schedule a timer. However, run can be called at any time.
@ -146,11 +152,11 @@ func (tr *tableRevalidation) handleResponse(tab *Table, resp revalidationRespons
defer tab.mutex.Unlock() defer tab.mutex.Unlock()
if !resp.didRespond { if !resp.didRespond {
// Revalidation failed.
n.livenessChecks /= 3 n.livenessChecks /= 3
if n.livenessChecks <= 0 { if n.livenessChecks <= 0 {
tab.deleteInBucket(b, n.ID()) tab.deleteInBucket(b, n.ID())
} else { } else {
tab.log.Debug("Node revalidation failed", "b", b.index, "id", n.ID(), "checks", n.livenessChecks, "q", n.revalList.name)
tr.moveToList(&tr.fast, n, now, &tab.rand) tr.moveToList(&tr.fast, n, now, &tab.rand)
} }
return return
@ -159,22 +165,15 @@ func (tr *tableRevalidation) handleResponse(tab *Table, resp revalidationRespons
// The node responded. // The node responded.
n.livenessChecks++ n.livenessChecks++
n.isValidatedLive = true n.isValidatedLive = true
tab.log.Debug("Node revalidated", "b", b.index, "id", n.ID(), "checks", n.livenessChecks, "q", n.revalList.name)
var endpointChanged bool var endpointChanged bool
if resp.newRecord != nil { if resp.newRecord != nil {
_, endpointChanged = tab.bumpInBucket(b, resp.newRecord, false) _, endpointChanged = tab.bumpInBucket(b, resp.newRecord, false)
if endpointChanged {
// If the node changed its advertised endpoint, the updated ENR is not served
// until it has been revalidated.
n.isValidatedLive = false
}
} }
tab.log.Debug("Revalidated node", "b", b.index, "id", n.ID(), "checks", n.livenessChecks, "q", n.revalList)
// Move node over to slow queue after first validation. // Node moves to slow list if it passed and hasn't changed.
if !endpointChanged { if !endpointChanged {
tr.moveToList(&tr.slow, n, now, &tab.rand) tr.moveToList(&tr.slow, n, now, &tab.rand)
} else {
tr.moveToList(&tr.fast, n, now, &tab.rand)
} }
} }