p2p/discover: update

This commit is contained in:
Felix Lange 2024-04-18 09:58:59 +02:00
parent 70b8918ea0
commit 0a4b314244
3 changed files with 41 additions and 47 deletions

View file

@ -435,7 +435,7 @@ func (tab *Table) loadSeedNodes() {
age := time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP()))
tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age)
}
tab.addSeenNode(seed)
tab.handleAddNode(addNodeRequest{node: seed, isLive: true})
}
}

View file

@ -17,7 +17,6 @@
package discover
import (
"fmt"
"slices"
"time"
@ -28,8 +27,8 @@ import (
const never = ^mclock.AbsTime(0)
type tableRevalidation struct {
newNodes revalidationQueue
nodes revalidationQueue
newNodes revalidationList
nodes revalidationList
activeReq map[enode.ID]struct{}
}
@ -43,14 +42,14 @@ type revalidationResponse struct {
func (tr *tableRevalidation) init(cfg *Config) {
tr.activeReq = make(map[enode.ID]struct{})
tr.newNodes.nextTime = never
tr.newNodes.interval = cfg.PingInterval
tr.newNodes.interval = cfg.PingInterval / 3
tr.nodes.nextTime = never
tr.nodes.interval = cfg.PingInterval
}
// nodeAdded is called when the table receives a new node.
func (tr *tableRevalidation) nodeAdded(tab *Table, n *node) {
tr.newNodes.push(n, tab.rand)
tr.newNodes.push(n, tab.cfg.Clock.Now(), tab.rand)
}
// nodeRemoved is called when a node was removed from the table.
@ -71,11 +70,11 @@ func (tr *tableRevalidation) nextTime() mclock.AbsTime {
func (tr *tableRevalidation) run(tab *Table, now mclock.AbsTime) {
if n := tr.newNodes.get(now, tab.rand, tr.activeReq); n != nil {
tr.startRequest(tab, n, true)
tr.newNodes.schedule(tab.rand)
tr.newNodes.schedule(now, tab.rand)
}
if n := tr.nodes.get(now, tab.rand, tr.activeReq); n != nil {
tr.startRequest(tab, n, false)
tr.nodes.schedule(tab.rand)
tr.nodes.schedule(now, tab.rand)
}
}
@ -87,16 +86,24 @@ func (tr *tableRevalidation) startRequest(tab *Table, n *node, newNode bool) {
tr.activeReq[n.ID()] = struct{}{}
resp := revalidationResponse{n: n, isNewNode: newNode}
go func() {
// Fetch the node while holding lock.
tab.mutex.Lock()
node := n.Node
tab.mutex.Unlock()
go tab.doRevalidate(resp, node)
}
func (tab *Table) doRevalidate(resp revalidationResponse, node *enode.Node) {
// Ping the selected node and wait for a pong response.
remoteSeq, err := tab.net.ping(unwrapNode(n))
remoteSeq, err := tab.net.ping(node)
resp.didRespond = err == nil
// Also fetch record if the node replied and returned a higher sequence number.
if remoteSeq > n.Seq() {
newrec, err := tab.net.RequestENR(unwrapNode(n))
if remoteSeq > node.Seq() {
newrec, err := tab.net.RequestENR(node)
if err != nil {
tab.log.Debug("ENR request failed", "id", n.ID(), "addr", n.addr(), "err", err)
tab.log.Debug("ENR request failed", "id", node.ID(), "err", err)
} else {
resp.newRecord = newrec
}
@ -106,7 +113,6 @@ func (tr *tableRevalidation) startRequest(tab *Table, n *node, newNode bool) {
case tab.revalidateResp <- resp:
case <-tab.closed:
}
}()
}
// handleResponse processes the result of a revalidation request.
@ -143,7 +149,7 @@ func (tr *tableRevalidation) handleResponse(tab *Table, resp revalidationRespons
// Move node over to main queue after first validation.
if resp.isNewNode {
tr.newNodes.remove(n)
tr.nodes.push(n, tab.rand)
tr.nodes.push(n, tab.cfg.Clock.Now(), tab.rand)
}
// Store potential seeds in database.
@ -152,15 +158,15 @@ func (tr *tableRevalidation) handleResponse(tab *Table, resp revalidationRespons
}
}
// revalidationQueue holds a list nodes and the next revalidation time.
type revalidationQueue struct {
// revalidationList holds a list nodes and the next revalidation time.
type revalidationList struct {
nodes []*node
nextTime mclock.AbsTime
interval time.Duration
}
// get returns a random node from the queue. Nodes in the 'exclude' map are not returned.
func (rq *revalidationQueue) get(now mclock.AbsTime, rand randomSource, exclude map[enode.ID]struct{}) *node {
func (rq *revalidationList) get(now mclock.AbsTime, rand randomSource, exclude map[enode.ID]struct{}) *node {
if now < rq.nextTime || len(rq.nodes) == 0 {
return nil
}
@ -174,18 +180,18 @@ func (rq *revalidationQueue) get(now mclock.AbsTime, rand randomSource, exclude
return nil
}
func (rq *revalidationQueue) push(n *node, rand randomSource) {
func (rq *revalidationList) push(n *node, now mclock.AbsTime, rand randomSource) {
rq.nodes = append(rq.nodes, n)
if rq.nextTime == never {
rq.schedule(rand)
rq.schedule(now, rand)
}
}
func (rq *revalidationQueue) schedule(rand randomSource) {
rq.nextTime = mclock.AbsTime(rand.Int63n(int64(rq.interval)))
func (rq *revalidationList) schedule(now mclock.AbsTime, rand randomSource) {
rq.nextTime = now.Add(time.Duration(rand.Int63n(int64(rq.interval))))
}
func (rq *revalidationQueue) remove(n *node) bool {
func (rq *revalidationList) remove(n *node) bool {
i := slices.Index(rq.nodes, n)
if i == -1 {
return false
@ -196,9 +202,3 @@ func (rq *revalidationQueue) remove(n *node) bool {
}
return true
}
func printIDs(list []*node) {
for i, n := range list {
fmt.Println(" - ", i, n.ID())
}
}

View file

@ -120,7 +120,7 @@ func fillTable(tab *Table, nodes []*node, setLive bool) {
tab.addSeenNode(n)
}
}
7
type pingRecorder struct {
mu sync.Mutex
cond *sync.Cond
@ -157,12 +157,6 @@ func (t *pingRecorder) Self() *enode.Node { return nullNode }
func (t *pingRecorder) lookupSelf() []*enode.Node { return nil }
func (t *pingRecorder) lookupRandom() []*enode.Node { return nil }
func (t *pingRecorder) wasPinged(id enode.ID) bool {
t.mu.Lock()
defer t.mu.Unlock()
return slices.ContainsFunc(t.pinged, func(n *enode.Node) bool { return n.ID() == id })
}
func (t *pingRecorder) waitPing(timeout time.Duration) *enode.Node {
t.mu.Lock()
defer t.mu.Unlock()