cmd/devp2p: improve crawl timestamp handling

This commit is contained in:
Felix Lange 2019-10-18 12:18:26 +02:00
parent 00d05619d8
commit 1098aef26a
3 changed files with 28 additions and 20 deletions

View file

@ -111,38 +111,40 @@ func (c *crawler) runIterator(done chan<- enode.Iterator, it enode.Iterator) {
} }
func (c *crawler) updateNode(n *enode.Node) { func (c *crawler) updateNode(n *enode.Node) {
existing, ok := c.output[n.ID()] node, ok := c.output[n.ID()]
// Skip validation of recently-seen nodes. // Skip validation of recently-seen nodes.
if ok && time.Since(existing.LastSeen) < c.revalidateInterval { if ok && time.Since(node.LastCheck) < c.revalidateInterval {
return return
} }
// Request the node record. // Request the node record.
nn, err := c.disc.RequestENR(n) nn, err := c.disc.RequestENR(n)
node.LastCheck = truncNow()
if err != nil { if err != nil {
if existing.Checks == 0 { if node.Score == 0 {
// Node doesn't implement EIP-868.
log.Debug("Skipping node", "id", n.ID()) log.Debug("Skipping node", "id", n.ID())
return return
} }
existing.Checks /= 2 node.Score /= 2
} else { } else {
if !ok { node.N = nn
existing.FirstSeen = truncNow() node.Seq = nn.Seq()
node.Score++
if node.FirstResponse.IsZero() {
node.FirstResponse = node.LastCheck
} }
existing.N = nn node.LastResponse = node.LastCheck
existing.Seq = nn.Seq()
existing.LastSeen = truncNow()
existing.Checks++
} }
// Store/update node in output set. // Store/update node in output set.
if existing.Checks <= 0 { if node.Score <= 0 {
log.Info("Removing node", "id", n.ID()) log.Info("Removing node", "id", n.ID())
delete(c.output, n.ID()) delete(c.output, n.ID())
} else { } else {
log.Info("Updating node", "id", n.ID(), "seq", existing.Seq, "checks", existing.Checks) log.Info("Updating node", "id", n.ID(), "seq", n.Seq(), "score", node.Score)
c.output[n.ID()] = existing c.output[n.ID()] = node
} }
} }

View file

@ -36,11 +36,17 @@ const jsonIndent = " "
type nodeSet map[enode.ID]nodeJSON type nodeSet map[enode.ID]nodeJSON
type nodeJSON struct { type nodeJSON struct {
Seq uint64 `json:"seq"` Seq uint64 `json:"seq"`
N *enode.Node `json:"record"` N *enode.Node `json:"record"`
FirstSeen time.Time `json:"firstSeen,omitempty"`
LastSeen time.Time `json:"lastSeen,omitempty"` // The score tracks how many liveness checks were performed. It is incremented by one
Checks int `json:"checks"` // every time the node passes a check, and halved every time it doesn't.
Score int `json:"score,omitempty"`
// These two track the time of last successful contact.
FirstResponse time.Time `json:"firstResponse,omitempty"`
LastResponse time.Time `json:"lastResponse,omitempty"`
// This one tracks the time of our last attempt to contact the node.
LastCheck time.Time `json:"lastCheck,omitempty"`
} }
func loadNodesJSON(file string) nodeSet { func loadNodesJSON(file string) nodeSet {
@ -79,7 +85,7 @@ func (ns nodeSet) nodes() []*enode.Node {
func (ns nodeSet) add(nodes ...*enode.Node) { func (ns nodeSet) add(nodes ...*enode.Node) {
for _, n := range nodes { for _, n := range nodes {
ns[n.ID()] = nodeJSON{Seq: n.Seq(), N: n, FirstSeen: truncNow()} ns[n.ID()] = nodeJSON{Seq: n.Seq(), N: n}
} }
} }

View file

@ -148,7 +148,7 @@ func minAgeFilter(args []string) (nodeFilter, error) {
return nil, err return nil, err
} }
f := func(n nodeJSON) bool { f := func(n nodeJSON) bool {
age := n.LastSeen.Sub(n.FirstSeen) age := n.LastResponse.Sub(n.FirstResponse)
return age >= minage return age >= minage
} }
return f, nil return f, nil