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:
Felix Lange
2020-04-08 09:57:23 +02:00
committed by GitHub
parent 671f22be38
commit b7394d7942
19 changed files with 2976 additions and 80 deletions

View File

@ -47,6 +47,7 @@ var (
errTimeout = errors.New("RPC timeout")
errClockWarp = errors.New("reply deadline too far in the future")
errClosed = errors.New("socket closed")
errLowPort = errors.New("low port")
)
const (
@ -176,7 +177,7 @@ func (t *UDPv4) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*node, error) {
if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
return nil, errors.New("not contained in netrestrict whitelist")
}
key, err := decodePubkey(rn.ID)
key, err := decodePubkey(crypto.S256(), rn.ID)
if err != nil {
return nil, err
}
@ -209,7 +210,7 @@ type UDPv4 struct {
addReplyMatcher chan *replyMatcher
gotreply chan reply
closeCtx context.Context
cancelCloseCtx func()
cancelCloseCtx context.CancelFunc
}
// replyMatcher represents a pending reply.
@ -258,6 +259,7 @@ type reply struct {
}
func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) {
cfg = cfg.withDefaults()
closeCtx, cancel := context.WithCancel(context.Background())
t := &UDPv4{
conn: c,
@ -271,9 +273,6 @@ func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) {
cancelCloseCtx: cancel,
log: cfg.Log,
}
if t.log == nil {
t.log = log.Root()
}
tab, err := newTable(t, ln.Database(), cfg.Bootnodes, t.log)
if err != nil {
@ -812,7 +811,7 @@ func (req *pingV4) preverify(t *UDPv4, from *net.UDPAddr, fromID enode.ID, fromK
if expired(req.Expiration) {
return errExpired
}
key, err := decodePubkey(fromKey)
key, err := decodePubkey(crypto.S256(), fromKey)
if err != nil {
return errors.New("invalid public key")
}