p2p/discover: add initial discovery v5 implementation (#20750)
This adds an implementation of the current discovery v5 spec. There is full integration with cmd/devp2p and enode.Iterator in this version. In theory we could enable the new protocol as a replacement of discovery v4 at any time. In practice, there will likely be a few more changes to the spec and implementation before this can happen.
This commit is contained in:
@ -24,7 +24,6 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
@ -56,6 +55,23 @@ func nodeAtDistance(base enode.ID, ld int, ip net.IP) *node {
|
||||
return wrapNode(enode.SignNull(&r, idAtDistance(base, ld)))
|
||||
}
|
||||
|
||||
// nodesAtDistance creates n nodes for which enode.LogDist(base, node.ID()) == ld.
|
||||
func nodesAtDistance(base enode.ID, ld int, n int) []*enode.Node {
|
||||
results := make([]*enode.Node, n)
|
||||
for i := range results {
|
||||
results[i] = unwrapNode(nodeAtDistance(base, ld, intIP(i)))
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func nodesToRecords(nodes []*enode.Node) []*enr.Record {
|
||||
records := make([]*enr.Record, len(nodes))
|
||||
for i := range nodes {
|
||||
records[i] = nodes[i].Record()
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
// idAtDistance returns a random hash such that enode.LogDist(a, b) == n
|
||||
func idAtDistance(a enode.ID, n int) (b enode.ID) {
|
||||
if n == 0 {
|
||||
@ -173,9 +189,16 @@ func hasDuplicates(slice []*node) bool {
|
||||
}
|
||||
|
||||
func checkNodesEqual(got, want []*enode.Node) error {
|
||||
if reflect.DeepEqual(got, want) {
|
||||
return nil
|
||||
if len(got) == len(want) {
|
||||
for i := range got {
|
||||
if !nodeEqual(got[i], want[i]) {
|
||||
goto NotEqual
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
NotEqual:
|
||||
output := new(bytes.Buffer)
|
||||
fmt.Fprintf(output, "got %d nodes:\n", len(got))
|
||||
for _, n := range got {
|
||||
@ -188,6 +211,10 @@ func checkNodesEqual(got, want []*enode.Node) error {
|
||||
return errors.New(output.String())
|
||||
}
|
||||
|
||||
func nodeEqual(n1 *enode.Node, n2 *enode.Node) bool {
|
||||
return n1.ID() == n2.ID() && n1.IP().Equal(n2.IP())
|
||||
}
|
||||
|
||||
func sortByID(nodes []*enode.Node) {
|
||||
sort.Slice(nodes, func(i, j int) bool {
|
||||
return string(nodes[i].ID().Bytes()) < string(nodes[j].ID().Bytes())
|
||||
|
Reference in New Issue
Block a user