p2p/discover/v4wire: use optional RLP field for EIP-868 seq (#22842)

This changes the definitions of Ping and Pong, adding an optional field
for the sequence number. This field was previously encoded/decoded using
the "tail" struct tag, but using "optional" is much nicer.
This commit is contained in:
Felix Lange 2021-05-18 11:48:41 +02:00 committed by GitHub
parent 32c1ed8a9c
commit 3e6f46caec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 17 additions and 47 deletions

View File

@ -34,7 +34,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover/v4wire" "github.com/ethereum/go-ethereum/p2p/discover/v4wire"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/rlp"
) )
// Errors // Errors
@ -217,7 +216,7 @@ func (t *UDPv4) Ping(n *enode.Node) error {
func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) { func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
rm := t.sendPing(n.ID(), &net.UDPAddr{IP: n.IP(), Port: n.UDP()}, nil) rm := t.sendPing(n.ID(), &net.UDPAddr{IP: n.IP(), Port: n.UDP()}, nil)
if err = <-rm.errc; err == nil { if err = <-rm.errc; err == nil {
seq = rm.reply.(*v4wire.Pong).ENRSeq() seq = rm.reply.(*v4wire.Pong).ENRSeq
} }
return seq, err return seq, err
} }
@ -248,13 +247,12 @@ func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *r
} }
func (t *UDPv4) makePing(toaddr *net.UDPAddr) *v4wire.Ping { func (t *UDPv4) makePing(toaddr *net.UDPAddr) *v4wire.Ping {
seq, _ := rlp.EncodeToBytes(t.localNode.Node().Seq())
return &v4wire.Ping{ return &v4wire.Ping{
Version: 4, Version: 4,
From: t.ourEndpoint(), From: t.ourEndpoint(),
To: v4wire.NewEndpoint(toaddr, 0), To: v4wire.NewEndpoint(toaddr, 0),
Expiration: uint64(time.Now().Add(expiration).Unix()), Expiration: uint64(time.Now().Add(expiration).Unix()),
Rest: []rlp.RawValue{seq}, ENRSeq: t.localNode.Node().Seq(),
} }
} }
@ -660,12 +658,11 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
req := h.Packet.(*v4wire.Ping) req := h.Packet.(*v4wire.Ping)
// Reply. // Reply.
seq, _ := rlp.EncodeToBytes(t.localNode.Node().Seq())
t.send(from, fromID, &v4wire.Pong{ t.send(from, fromID, &v4wire.Pong{
To: v4wire.NewEndpoint(from, req.From.TCP), To: v4wire.NewEndpoint(from, req.From.TCP),
ReplyTok: mac, ReplyTok: mac,
Expiration: uint64(time.Now().Add(expiration).Unix()), Expiration: uint64(time.Now().Add(expiration).Unix()),
Rest: []rlp.RawValue{seq}, ENRSeq: t.localNode.Node().Seq(),
}) })
// Ping back if our last pong on file is too far in the past. // Ping back if our last pong on file is too far in the past.

View File

@ -470,13 +470,13 @@ func TestUDPv4_EIP868(t *testing.T) {
// Perform endpoint proof and check for sequence number in packet tail. // Perform endpoint proof and check for sequence number in packet tail.
test.packetIn(nil, &v4wire.Ping{Expiration: futureExp}) test.packetIn(nil, &v4wire.Ping{Expiration: futureExp})
test.waitPacketOut(func(p *v4wire.Pong, addr *net.UDPAddr, hash []byte) { test.waitPacketOut(func(p *v4wire.Pong, addr *net.UDPAddr, hash []byte) {
if p.ENRSeq() != wantNode.Seq() { if p.ENRSeq != wantNode.Seq() {
t.Errorf("wrong sequence number in pong: %d, want %d", p.ENRSeq(), wantNode.Seq()) t.Errorf("wrong sequence number in pong: %d, want %d", p.ENRSeq, wantNode.Seq())
} }
}) })
test.waitPacketOut(func(p *v4wire.Ping, addr *net.UDPAddr, hash []byte) { test.waitPacketOut(func(p *v4wire.Ping, addr *net.UDPAddr, hash []byte) {
if p.ENRSeq() != wantNode.Seq() { if p.ENRSeq != wantNode.Seq() {
t.Errorf("wrong sequence number in ping: %d, want %d", p.ENRSeq(), wantNode.Seq()) t.Errorf("wrong sequence number in ping: %d, want %d", p.ENRSeq, wantNode.Seq())
} }
test.packetIn(nil, &v4wire.Pong{Expiration: futureExp, ReplyTok: hash}) test.packetIn(nil, &v4wire.Pong{Expiration: futureExp, ReplyTok: hash})
}) })

View File

@ -50,6 +50,8 @@ type (
Version uint Version uint
From, To Endpoint From, To Endpoint
Expiration uint64 Expiration uint64
ENRSeq uint64 `rlp:"optional"` // Sequence number of local record, added by EIP-868.
// Ignore additional fields (for forward compatibility). // Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"` Rest []rlp.RawValue `rlp:"tail"`
} }
@ -62,6 +64,8 @@ type (
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.
ENRSeq uint64 `rlp:"optional"` // Sequence number of local record, added by EIP-868.
// Ignore additional fields (for forward compatibility). // Ignore additional fields (for forward compatibility).
Rest []rlp.RawValue `rlp:"tail"` Rest []rlp.RawValue `rlp:"tail"`
} }
@ -162,13 +166,11 @@ type Packet interface {
Kind() byte Kind() byte
} }
func (req *Ping) Name() string { return "PING/v4" } func (req *Ping) Name() string { return "PING/v4" }
func (req *Ping) Kind() byte { return PingPacket } func (req *Ping) Kind() byte { return PingPacket }
func (req *Ping) ENRSeq() uint64 { return seqFromTail(req.Rest) }
func (req *Pong) Name() string { return "PONG/v4" } func (req *Pong) Name() string { return "PONG/v4" }
func (req *Pong) Kind() byte { return PongPacket } func (req *Pong) Kind() byte { return PongPacket }
func (req *Pong) ENRSeq() uint64 { return seqFromTail(req.Rest) }
func (req *Findnode) Name() string { return "FINDNODE/v4" } func (req *Findnode) Name() string { return "FINDNODE/v4" }
func (req *Findnode) Kind() byte { return FindnodePacket } func (req *Findnode) Kind() byte { return FindnodePacket }
@ -187,15 +189,6 @@ func Expired(ts uint64) bool {
return time.Unix(int64(ts), 0).Before(time.Now()) return time.Unix(int64(ts), 0).Before(time.Now())
} }
func seqFromTail(tail []rlp.RawValue) uint64 {
if len(tail) == 0 {
return 0
}
var seq uint64
rlp.DecodeBytes(tail[0], &seq)
return seq
}
// Encoder/decoder. // Encoder/decoder.
const ( const (

View File

@ -23,7 +23,6 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -40,7 +39,6 @@ var testPackets = []struct {
From: Endpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544}, From: Endpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
To: Endpoint{net.ParseIP("::1"), 2222, 3333}, To: Endpoint{net.ParseIP("::1"), 2222, 3333},
Expiration: 1136239445, Expiration: 1136239445,
Rest: []rlp.RawValue{},
}, },
}, },
{ {
@ -50,26 +48,8 @@ var testPackets = []struct {
From: Endpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544}, From: Endpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
To: Endpoint{net.ParseIP("::1"), 2222, 3333}, To: Endpoint{net.ParseIP("::1"), 2222, 3333},
Expiration: 1136239445, Expiration: 1136239445,
Rest: []rlp.RawValue{{0x01}, {0x02}}, ENRSeq: 1,
}, Rest: []rlp.RawValue{{0x02}},
},
{
input: "577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3",
wantPacket: &Ping{
Version: 555,
From: Endpoint{net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 3322, 5544},
To: Endpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
Expiration: 1136239445,
Rest: []rlp.RawValue{{0xC5, 0x01, 0x02, 0x03, 0x04, 0x05}},
},
},
{
input: "09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b2069869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e",
wantPacket: &Pong{
To: Endpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
ReplyTok: common.Hex2Bytes("fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954"),
Expiration: 1136239445,
Rest: []rlp.RawValue{{0xC6, 0x01, 0x02, 0x03, 0xC2, 0x04, 0x05}, {0x06}},
}, },
}, },
{ {