mirror of
https://github.com/logos-messaging/go-discover.git
synced 2026-01-06 23:13:10 +00:00
chore: get latest changes from go-ethereum
This commit is contained in:
parent
85a2ce36f6
commit
069eee20a3
@ -37,7 +37,7 @@ type UDPConn interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type V5Config struct {
|
type V5Config struct {
|
||||||
ProtocolID [6]byte
|
ProtocolID *[6]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config holds settings for the discovery listener.
|
// Config holds settings for the discovery listener.
|
||||||
@ -51,9 +51,8 @@ type Config struct {
|
|||||||
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
|
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
|
||||||
Log log.Logger // if set, log messages go here
|
Log log.Logger // if set, log messages go here
|
||||||
ValidSchemes enr.IdentityScheme // allowed identity schemes
|
ValidSchemes enr.IdentityScheme // allowed identity schemes
|
||||||
|
V5Config V5Config // DiscV5 settings
|
||||||
Clock mclock.Clock
|
Clock mclock.Clock
|
||||||
ValidNodeFn func(enode.Node) bool // function to validate a node before it's added to routing tables
|
|
||||||
V5Config V5Config // DiscV5 settings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg Config) withDefaults() Config {
|
func (cfg Config) withDefaults() Config {
|
||||||
@ -66,8 +65,8 @@ func (cfg Config) withDefaults() Config {
|
|||||||
if cfg.Clock == nil {
|
if cfg.Clock == nil {
|
||||||
cfg.Clock = mclock.System{}
|
cfg.Clock = mclock.System{}
|
||||||
}
|
}
|
||||||
if len(cfg.V5Config.ProtocolID) == 0 {
|
if cfg.V5Config.ProtocolID == nil {
|
||||||
cfg.V5Config.ProtocolID = v5wire.DefaultProtocolID
|
cfg.V5Config.ProtocolID = &v5wire.DefaultProtocolID
|
||||||
}
|
}
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ package discover
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
@ -141,7 +142,7 @@ func (it *lookup) slowdown() {
|
|||||||
func (it *lookup) query(n *node, reply chan<- []*node) {
|
func (it *lookup) query(n *node, reply chan<- []*node) {
|
||||||
fails := it.tab.db.FindFails(n.ID(), n.IP())
|
fails := it.tab.db.FindFails(n.ID(), n.IP())
|
||||||
r, err := it.queryfunc(n)
|
r, err := it.queryfunc(n)
|
||||||
if err == errClosed {
|
if errors.Is(err, errClosed) {
|
||||||
// Avoid recording failures on shutdown.
|
// Avoid recording failures on shutdown.
|
||||||
reply <- nil
|
reply <- nil
|
||||||
return
|
return
|
||||||
|
|||||||
@ -108,7 +108,7 @@ func sntpDrift(measurements int) (time.Duration, error) {
|
|||||||
// Calculate the drift based on an assumed answer time of RRT/2
|
// Calculate the drift based on an assumed answer time of RRT/2
|
||||||
drifts = append(drifts, sent.Sub(t)+elapsed/2)
|
drifts = append(drifts, sent.Sub(t)+elapsed/2)
|
||||||
}
|
}
|
||||||
// Calculate average drif (drop two extremities to avoid outliers)
|
// Calculate average drift (drop two extremities to avoid outliers)
|
||||||
sort.Sort(durationSlice(drifts))
|
sort.Sort(durationSlice(drifts))
|
||||||
|
|
||||||
drift := time.Duration(0)
|
drift := time.Duration(0)
|
||||||
|
|||||||
@ -458,7 +458,6 @@ func (tab *Table) bucketAtDistance(d int) *bucket {
|
|||||||
return tab.buckets[d-bucketMinDistance-1]
|
return tab.buckets[d-bucketMinDistance-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// addSeenNode adds a node which may or may not be live to the end of a bucket. If the
|
// addSeenNode adds a node which may or may not be live to the end of a bucket. If the
|
||||||
// bucket has space available, adding the node succeeds immediately. Otherwise, the node is
|
// bucket has space available, adding the node succeeds immediately. Otherwise, the node is
|
||||||
// added to the replacements list.
|
// added to the replacements list.
|
||||||
@ -498,7 +497,6 @@ func (tab *Table) addSeenNode(n *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
|
||||||
// addVerifiedNode adds a node whose existence has been verified recently to the front of a
|
// addVerifiedNode adds a node whose existence has been verified recently to the front of a
|
||||||
// bucket. If the node is already in the bucket, it is moved to the front. If the bucket
|
// bucket. If the node is already in the bucket, it is moved to the front. If the bucket
|
||||||
// has no space, the node is added to the replacements list.
|
// has no space, the node is added to the replacements list.
|
||||||
|
|||||||
@ -134,8 +134,8 @@ func newPingRecorder() *pingRecorder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setRecord updates a node record. Future calls to ping and
|
// updateRecord updates a node record. Future calls to ping and
|
||||||
// requestENR will return this record.
|
// RequestENR will return this record.
|
||||||
func (t *pingRecorder) updateRecord(n *enode.Node) {
|
func (t *pingRecorder) updateRecord(n *enode.Node) {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
@ -162,7 +162,7 @@ func (t *pingRecorder) ping(n *enode.Node) (seq uint64, err error) {
|
|||||||
return seq, nil
|
return seq, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// requestENR simulates an ENR request.
|
// RequestENR simulates an ENR request.
|
||||||
func (t *pingRecorder) RequestENR(n *enode.Node) (*enode.Node, error) {
|
func (t *pingRecorder) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
|
|||||||
@ -328,13 +328,13 @@ func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target v4wire.Pubke
|
|||||||
// enough nodes the reply matcher will time out waiting for the second reply, but
|
// enough nodes the reply matcher will time out waiting for the second reply, but
|
||||||
// there's no need for an error in that case.
|
// there's no need for an error in that case.
|
||||||
err := <-rm.errc
|
err := <-rm.errc
|
||||||
if err == errTimeout && rm.reply != nil {
|
if errors.Is(err, errTimeout) && rm.reply != nil {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
return nodes, err
|
return nodes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestENR sends enrRequest to the given node and waits for a response.
|
// RequestENR sends ENRRequest to the given node and waits for a response.
|
||||||
func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
addr := &net.UDPAddr{IP: n.IP(), Port: n.UDP()}
|
addr := &net.UDPAddr{IP: n.IP(), Port: n.UDP()}
|
||||||
t.ensureBond(n.ID(), addr)
|
t.ensureBond(n.ID(), addr)
|
||||||
@ -525,8 +525,8 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) {
|
|||||||
t.log.Debug("Temporary UDP read error", "err", err)
|
t.log.Debug("Temporary UDP read error", "err", err)
|
||||||
continue
|
continue
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
// Shut down the loop for permament errors.
|
// Shut down the loop for permanent errors.
|
||||||
if err != io.EOF {
|
if !errors.Is(err, io.EOF) {
|
||||||
t.log.Debug("UDP read error", "err", err)
|
t.log.Debug("UDP read error", "err", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@ -284,6 +284,7 @@ func TestUDPv4_findnode(t *testing.T) {
|
|||||||
test.waitPacketOut(func(p *v4wire.Neighbors, to *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Neighbors, to *net.UDPAddr, hash []byte) {
|
||||||
if len(p.Nodes) != len(want) {
|
if len(p.Nodes) != len(want) {
|
||||||
t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize)
|
t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for i, n := range p.Nodes {
|
for i, n := range p.Nodes {
|
||||||
if n.ID.ID() != want[i].ID() {
|
if n.ID.ID() != want[i].ID() {
|
||||||
@ -312,7 +313,7 @@ func TestUDPv4_findnodeMultiReply(t *testing.T) {
|
|||||||
test.table.db.UpdateLastPingReceived(rid, test.remoteaddr.IP, time.Now())
|
test.table.db.UpdateLastPingReceived(rid, test.remoteaddr.IP, time.Now())
|
||||||
|
|
||||||
// queue a pending findnode request
|
// queue a pending findnode request
|
||||||
resultc, errc := make(chan []*node), make(chan error)
|
resultc, errc := make(chan []*node, 1), make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
rid := encodePubkey(&test.remotekey.PublicKey).id()
|
rid := encodePubkey(&test.remotekey.PublicKey).id()
|
||||||
ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget)
|
ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget)
|
||||||
@ -489,7 +490,7 @@ func TestUDPv4_EIP868(t *testing.T) {
|
|||||||
t.Fatalf("invalid record: %v", err)
|
t.Fatalf("invalid record: %v", err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(n, wantNode) {
|
if !reflect.DeepEqual(n, wantNode) {
|
||||||
t.Fatalf("wrong node in enrResponse: %v", n)
|
t.Fatalf("wrong node in ENRResponse: %v", n)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -60,7 +60,7 @@ type (
|
|||||||
Pong struct {
|
Pong struct {
|
||||||
// This field should mirror the UDP envelope address
|
// This field should mirror the UDP envelope address
|
||||||
// of the ping packet, which provides a way to discover the
|
// of the ping packet, which provides a way to discover the
|
||||||
// the external address (after NAT).
|
// external address (after NAT).
|
||||||
To Endpoint
|
To Endpoint
|
||||||
ReplyTok []byte // This contains the hash of the ping packet.
|
ReplyTok []byte // This contains the hash of the ping packet.
|
||||||
Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
|
Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
|
||||||
@ -86,23 +86,23 @@ type (
|
|||||||
Rest []rlp.RawValue `rlp:"tail"`
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// enrRequest queries for the remote node's record.
|
// ENRRequest queries for the remote node's record.
|
||||||
ENRRequest struct {
|
ENRRequest struct {
|
||||||
Expiration uint64
|
Expiration uint64
|
||||||
// Ignore additional fields (for forward compatibility).
|
// Ignore additional fields (for forward compatibility).
|
||||||
Rest []rlp.RawValue `rlp:"tail"`
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// enrResponse is the reply to enrRequest.
|
// ENRResponse is the reply to ENRRequest.
|
||||||
ENRResponse struct {
|
ENRResponse struct {
|
||||||
ReplyTok []byte // Hash of the enrRequest packet.
|
ReplyTok []byte // Hash of the ENRRequest packet.
|
||||||
Record enr.Record
|
Record enr.Record
|
||||||
// Ignore additional fields (for forward compatibility).
|
// Ignore additional fields (for forward compatibility).
|
||||||
Rest []rlp.RawValue `rlp:"tail"`
|
Rest []rlp.RawValue `rlp:"tail"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// This number is the maximum number of neighbor nodes in a Neighbors packet.
|
// MaxNeighbors is the maximum number of neighbor nodes in a Neighbors packet.
|
||||||
const MaxNeighbors = 12
|
const MaxNeighbors = 12
|
||||||
|
|
||||||
// This code computes the MaxNeighbors constant value.
|
// This code computes the MaxNeighbors constant value.
|
||||||
@ -161,8 +161,9 @@ func NewEndpoint(addr *net.UDPAddr, tcpPort uint16) Endpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Packet interface {
|
type Packet interface {
|
||||||
// packet name and type for logging purposes.
|
// Name is the name of the package, for logging purposes.
|
||||||
Name() string
|
Name() string
|
||||||
|
// Kind is the packet type, for logging purposes.
|
||||||
Kind() byte
|
Kind() byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -54,7 +54,7 @@ type codecV5 interface {
|
|||||||
// Encode encodes a packet.
|
// Encode encodes a packet.
|
||||||
Encode(enode.ID, string, v5wire.Packet, *v5wire.Whoareyou) ([]byte, v5wire.Nonce, error)
|
Encode(enode.ID, string, v5wire.Packet, *v5wire.Whoareyou) ([]byte, v5wire.Nonce, error)
|
||||||
|
|
||||||
// decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
|
// Decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
|
||||||
// The *enode.Node return value is non-nil when the input contains a handshake response.
|
// The *enode.Node return value is non-nil when the input contains a handshake response.
|
||||||
Decode([]byte, string) (enode.ID, *enode.Node, v5wire.Packet, error)
|
Decode([]byte, string) (enode.ID, *enode.Node, v5wire.Packet, error)
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) {
|
|||||||
callDoneCh: make(chan *callV5),
|
callDoneCh: make(chan *callV5),
|
||||||
respTimeoutCh: make(chan *callTimeout),
|
respTimeoutCh: make(chan *callTimeout),
|
||||||
// state of dispatch
|
// state of dispatch
|
||||||
codec: v5wire.NewCodec(ln, cfg.PrivateKey, cfg.Clock, cfg.V5Config.ProtocolID),
|
codec: v5wire.NewCodec(ln, cfg.PrivateKey, cfg.Clock, *cfg.V5Config.ProtocolID),
|
||||||
activeCallByNode: make(map[enode.ID]*callV5),
|
activeCallByNode: make(map[enode.ID]*callV5),
|
||||||
activeCallByAuth: make(map[v5wire.Nonce]*callV5),
|
activeCallByAuth: make(map[v5wire.Nonce]*callV5),
|
||||||
callQueue: make(map[enode.ID][]*callV5),
|
callQueue: make(map[enode.ID][]*callV5),
|
||||||
@ -305,7 +305,7 @@ func (t *UDPv5) lookupWorker(destNode *node, target enode.ID) ([]*node, error) {
|
|||||||
)
|
)
|
||||||
var r []*enode.Node
|
var r []*enode.Node
|
||||||
r, err = t.findnode(unwrapNode(destNode), dists)
|
r, err = t.findnode(unwrapNode(destNode), dists)
|
||||||
if err == errClosed {
|
if errors.Is(err, errClosed) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, n := range r {
|
for _, n := range r {
|
||||||
@ -347,7 +347,7 @@ func (t *UDPv5) ping(n *enode.Node) (uint64, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// requestENR requests n's record.
|
// RequestENR requests n's record.
|
||||||
func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) {
|
func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
nodes, err := t.findnode(n, []uint{0})
|
nodes, err := t.findnode(n, []uint{0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -407,6 +407,9 @@ func (t *UDPv5) verifyResponseNode(c *callV5, r *enr.Record, distances []uint, s
|
|||||||
if err := netutil.CheckRelayIP(c.node.IP(), node.IP()); err != nil {
|
if err := netutil.CheckRelayIP(c.node.IP(), node.IP()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if t.netrestrict != nil && !t.netrestrict.Contains(node.IP()) {
|
||||||
|
return nil, errors.New("not contained in netrestrict list")
|
||||||
|
}
|
||||||
if c.node.UDP() <= 1024 {
|
if c.node.UDP() <= 1024 {
|
||||||
return nil, errLowPort
|
return nil, errLowPort
|
||||||
}
|
}
|
||||||
@ -622,8 +625,8 @@ func (t *UDPv5) readLoop() {
|
|||||||
t.log.Debug("Temporary UDP read error", "err", err)
|
t.log.Debug("Temporary UDP read error", "err", err)
|
||||||
continue
|
continue
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
// Shut down the loop for permament errors.
|
// Shut down the loop for permanent errors.
|
||||||
if err != io.EOF {
|
if !errors.Is(err, io.EOF) {
|
||||||
t.log.Debug("UDP read error", "err", err)
|
t.log.Debug("UDP read error", "err", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -90,6 +90,10 @@ const (
|
|||||||
minVersion = 1
|
minVersion = 1
|
||||||
sizeofMaskingIV = 16
|
sizeofMaskingIV = 16
|
||||||
|
|
||||||
|
// The minimum size of any Discovery v5 packet is 63 bytes.
|
||||||
|
// Should reject packets smaller than minPacketSize.
|
||||||
|
minPacketSize = 63
|
||||||
|
|
||||||
minMessageSize = 48 // this refers to data after static headers
|
minMessageSize = 48 // this refers to data after static headers
|
||||||
randomPacketMsgSize = 20
|
randomPacketMsgSize = 20
|
||||||
)
|
)
|
||||||
@ -114,6 +118,7 @@ var (
|
|||||||
|
|
||||||
// Public errors.
|
// Public errors.
|
||||||
var (
|
var (
|
||||||
|
// ErrInvalidReqID represents error when the ID is invalid.
|
||||||
ErrInvalidReqID = errors.New("request ID larger than 8 bytes")
|
ErrInvalidReqID = errors.New("request ID larger than 8 bytes")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,11 +134,10 @@ var (
|
|||||||
// Codec encodes and decodes Discovery v5 packets.
|
// Codec encodes and decodes Discovery v5 packets.
|
||||||
// This type is not safe for concurrent use.
|
// This type is not safe for concurrent use.
|
||||||
type Codec struct {
|
type Codec struct {
|
||||||
sha256 hash.Hash
|
sha256 hash.Hash
|
||||||
localnode *enode.LocalNode
|
localnode *enode.LocalNode
|
||||||
privkey *ecdsa.PrivateKey
|
privkey *ecdsa.PrivateKey
|
||||||
sc *SessionCache
|
sc *SessionCache
|
||||||
|
|
||||||
protocolID [6]byte
|
protocolID [6]byte
|
||||||
|
|
||||||
// encoder buffers
|
// encoder buffers
|
||||||
@ -303,7 +307,7 @@ func (c *Codec) encodeWhoareyou(toID enode.ID, packet *Whoareyou) (Header, error
|
|||||||
return head, nil
|
return head, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeHandshakeMessage encodes the handshake message packet header.
|
// encodeHandshakeHeader encodes the handshake message packet header.
|
||||||
func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Whoareyou) (Header, *session, error) {
|
func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Whoareyou) (Header, *session, error) {
|
||||||
// Ensure calling code sets challenge.node.
|
// Ensure calling code sets challenge.node.
|
||||||
if challenge.Node == nil {
|
if challenge.Node == nil {
|
||||||
@ -340,7 +344,7 @@ func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Who
|
|||||||
return head, session, err
|
return head, session, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeAuthHeader creates the auth header on a request packet following WHOAREYOU.
|
// makeHandshakeAuth creates the auth header on a request packet following WHOAREYOU.
|
||||||
func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoareyou) (*handshakeAuthData, *session, error) {
|
func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoareyou) (*handshakeAuthData, *session, error) {
|
||||||
auth := new(handshakeAuthData)
|
auth := new(handshakeAuthData)
|
||||||
auth.h.SrcID = c.localnode.ID()
|
auth.h.SrcID = c.localnode.ID()
|
||||||
@ -382,7 +386,7 @@ func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoarey
|
|||||||
return auth, sec, err
|
return auth, sec, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeMessage encodes an encrypted message packet.
|
// encodeMessageHeader encodes an encrypted message packet.
|
||||||
func (c *Codec) encodeMessageHeader(toID enode.ID, s *session) (Header, error) {
|
func (c *Codec) encodeMessageHeader(toID enode.ID, s *session) (Header, error) {
|
||||||
head := c.makeHeader(toID, flagMessage, 0)
|
head := c.makeHeader(toID, flagMessage, 0)
|
||||||
|
|
||||||
@ -418,10 +422,10 @@ func (c *Codec) encryptMessage(s *session, p Packet, head *Header, headerData []
|
|||||||
|
|
||||||
// Decode decodes a discovery packet.
|
// Decode decodes a discovery packet.
|
||||||
func (c *Codec) Decode(input []byte, addr string) (src enode.ID, n *enode.Node, p Packet, err error) {
|
func (c *Codec) Decode(input []byte, addr string) (src enode.ID, n *enode.Node, p Packet, err error) {
|
||||||
// Unmask the static header.
|
if len(input) < minPacketSize {
|
||||||
if len(input) < sizeofStaticPacketData {
|
|
||||||
return enode.ID{}, nil, nil, errTooShort
|
return enode.ID{}, nil, nil, errTooShort
|
||||||
}
|
}
|
||||||
|
// Unmask the static header.
|
||||||
var head Header
|
var head Header
|
||||||
copy(head.IV[:], input[:sizeofMaskingIV])
|
copy(head.IV[:], input[:sizeofMaskingIV])
|
||||||
mask := head.mask(c.localnode.ID())
|
mask := head.mask(c.localnode.ID())
|
||||||
@ -599,7 +603,7 @@ func (c *Codec) decodeMessage(fromAddr string, head *Header, headerData, msgData
|
|||||||
// Try decrypting the message.
|
// Try decrypting the message.
|
||||||
key := c.sc.readKey(auth.SrcID, fromAddr)
|
key := c.sc.readKey(auth.SrcID, fromAddr)
|
||||||
msg, err := c.decryptMessage(msgData, head.Nonce[:], headerData, key)
|
msg, err := c.decryptMessage(msgData, head.Nonce[:], headerData, key)
|
||||||
if err == errMessageDecrypt {
|
if errors.Is(err, errMessageDecrypt) {
|
||||||
// It didn't work. Start the handshake since this is an ordinary message packet.
|
// It didn't work. Start the handshake since this is an ordinary message packet.
|
||||||
return &Unknown{Nonce: head.Nonce}, nil
|
return &Unknown{Nonce: head.Nonce}, nil
|
||||||
}
|
}
|
||||||
@ -635,7 +639,7 @@ func (h *StaticHeader) checkValid(packetLen int, protocolID [6]byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// headerMask returns a cipher for 'masking' / 'unmasking' packet headers.
|
// mask returns a cipher for 'masking' / 'unmasking' packet headers.
|
||||||
func (h *Header) mask(destID enode.ID) cipher.Stream {
|
func (h *Header) mask(destID enode.ID) cipher.Stream {
|
||||||
block, err := aes.NewCipher(destID[:16])
|
block, err := aes.NewCipher(destID[:16])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -23,7 +23,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -39,8 +38,7 @@ import (
|
|||||||
|
|
||||||
// To regenerate discv5 test vectors, run
|
// To regenerate discv5 test vectors, run
|
||||||
//
|
//
|
||||||
// go test -run TestVectors -write-test-vectors
|
// go test -run TestVectors -write-test-vectors
|
||||||
//
|
|
||||||
var writeTestVectorsFlag = flag.Bool("write-test-vectors", false, "Overwrite discv5 test vectors in testdata/")
|
var writeTestVectorsFlag = flag.Bool("write-test-vectors", false, "Overwrite discv5 test vectors in testdata/")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -276,7 +274,15 @@ func TestDecodeErrorsV5(t *testing.T) {
|
|||||||
net := newHandshakeTest()
|
net := newHandshakeTest()
|
||||||
defer net.close()
|
defer net.close()
|
||||||
|
|
||||||
net.nodeA.expectDecodeErr(t, errTooShort, []byte{})
|
b := make([]byte, 0)
|
||||||
|
net.nodeA.expectDecodeErr(t, errTooShort, b)
|
||||||
|
|
||||||
|
b = make([]byte, 62)
|
||||||
|
net.nodeA.expectDecodeErr(t, errTooShort, b)
|
||||||
|
|
||||||
|
b = make([]byte, 63)
|
||||||
|
net.nodeA.expectDecodeErr(t, errInvalidHeader, b)
|
||||||
|
|
||||||
// TODO some more tests would be nice :)
|
// TODO some more tests would be nice :)
|
||||||
// - check invalid authdata sizes
|
// - check invalid authdata sizes
|
||||||
// - check invalid handshake data sizes
|
// - check invalid handshake data sizes
|
||||||
@ -498,8 +504,8 @@ type handshakeTestNode struct {
|
|||||||
|
|
||||||
func newHandshakeTest() *handshakeTest {
|
func newHandshakeTest() *handshakeTest {
|
||||||
t := new(handshakeTest)
|
t := new(handshakeTest)
|
||||||
t.nodeA.init(testKeyA, net.IP{127, 0, 0, 1}, &t.clock, [6]byte{'d', 'i', 's', 'c', 'v', '5'})
|
t.nodeA.init(testKeyA, net.IP{127, 0, 0, 1}, &t.clock, DefaultProtocolID)
|
||||||
t.nodeB.init(testKeyB, net.IP{127, 0, 0, 1}, &t.clock, [6]byte{'d', 'i', 's', 'c', 'v', '5'})
|
t.nodeB.init(testKeyB, net.IP{127, 0, 0, 1}, &t.clock, DefaultProtocolID)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,7 +586,7 @@ func (n *handshakeTestNode) id() enode.ID {
|
|||||||
// hexFile reads the given file and decodes the hex data contained in it.
|
// hexFile reads the given file and decodes the hex data contained in it.
|
||||||
// Whitespace and any lines beginning with the # character are ignored.
|
// Whitespace and any lines beginning with the # character are ignored.
|
||||||
func hexFile(file string) []byte {
|
func hexFile(file string) []byte {
|
||||||
fileContent, err := ioutil.ReadFile(file)
|
fileContent, err := os.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2019 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@ -59,7 +59,7 @@ type (
|
|||||||
Nonce Nonce
|
Nonce Nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
// WHOAREYOU contains the handshake challenge.
|
// Whoareyou contains the handshake challenge.
|
||||||
Whoareyou struct {
|
Whoareyou struct {
|
||||||
ChallengeData []byte // Encoded challenge
|
ChallengeData []byte // Encoded challenge
|
||||||
Nonce Nonce // Nonce of request packet
|
Nonce Nonce // Nonce of request packet
|
||||||
@ -73,13 +73,13 @@ type (
|
|||||||
sent mclock.AbsTime // for handshake GC.
|
sent mclock.AbsTime // for handshake GC.
|
||||||
}
|
}
|
||||||
|
|
||||||
// PING is sent during liveness checks.
|
// Ping is sent during liveness checks.
|
||||||
Ping struct {
|
Ping struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
ENRSeq uint64
|
ENRSeq uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// PONG is the reply to PING.
|
// Pong is the reply to Ping.
|
||||||
Pong struct {
|
Pong struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
ENRSeq uint64
|
ENRSeq uint64
|
||||||
@ -87,58 +87,58 @@ type (
|
|||||||
ToPort uint16 // packet, which provides a way to discover the external address (after NAT).
|
ToPort uint16 // packet, which provides a way to discover the external address (after NAT).
|
||||||
}
|
}
|
||||||
|
|
||||||
// FINDNODE is a query for nodes in the given bucket.
|
// Findnode is a query for nodes in the given bucket.
|
||||||
Findnode struct {
|
Findnode struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Distances []uint
|
Distances []uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// NODES is the reply to FINDNODE and TOPICQUERY.
|
// Nodes is the reply to Findnode and Topicquery.
|
||||||
Nodes struct {
|
Nodes struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Total uint8
|
Total uint8
|
||||||
Nodes []*enr.Record
|
Nodes []*enr.Record
|
||||||
}
|
}
|
||||||
|
|
||||||
// TALKREQ is an application-level request.
|
// TalkRequest is an application-level request.
|
||||||
TalkRequest struct {
|
TalkRequest struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Protocol string
|
Protocol string
|
||||||
Message []byte
|
Message []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// TALKRESP is the reply to TALKREQ.
|
// TalkResponse is the reply to TalkRequest.
|
||||||
TalkResponse struct {
|
TalkResponse struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Message []byte
|
Message []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// REQUESTTICKET requests a ticket for a topic queue.
|
// RequestTicket requests a ticket for a topic queue.
|
||||||
RequestTicket struct {
|
RequestTicket struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Topic []byte
|
Topic []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// TICKET is the response to REQUESTTICKET.
|
// Ticket is the response to RequestTicket.
|
||||||
Ticket struct {
|
Ticket struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Ticket []byte
|
Ticket []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// REGTOPIC registers the sender in a topic queue using a ticket.
|
// Regtopic registers the sender in a topic queue using a ticket.
|
||||||
Regtopic struct {
|
Regtopic struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Ticket []byte
|
Ticket []byte
|
||||||
ENR *enr.Record
|
ENR *enr.Record
|
||||||
}
|
}
|
||||||
|
|
||||||
// REGCONFIRMATION is the reply to REGTOPIC.
|
// Regconfirmation is the reply to Regtopic.
|
||||||
Regconfirmation struct {
|
Regconfirmation struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Registered bool
|
Registered bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOPICQUERY asks for nodes with the given topic.
|
// TopicQuery asks for nodes with the given topic.
|
||||||
TopicQuery struct {
|
TopicQuery struct {
|
||||||
ReqID []byte
|
ReqID []byte
|
||||||
Topic []byte
|
Topic []byte
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user