v5_udp_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. // Copyright 2019 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package discover
  17. import (
  18. "bytes"
  19. "crypto/ecdsa"
  20. "encoding/binary"
  21. "fmt"
  22. "math/rand"
  23. "net"
  24. "reflect"
  25. "sort"
  26. "testing"
  27. "time"
  28. "github.com/ethereum/go-ethereum/internal/testlog"
  29. "github.com/ethereum/go-ethereum/log"
  30. "github.com/ethereum/go-ethereum/p2p/discover/v5wire"
  31. "github.com/ethereum/go-ethereum/p2p/enode"
  32. "github.com/ethereum/go-ethereum/p2p/enr"
  33. "github.com/ethereum/go-ethereum/rlp"
  34. )
  35. // Real sockets, real crypto: this test checks end-to-end connectivity for UDPv5.
  36. func TestUDPv5_lookupE2E(t *testing.T) {
  37. t.Parallel()
  38. const N = 5
  39. var nodes []*UDPv5
  40. for i := 0; i < N; i++ {
  41. var cfg Config
  42. if len(nodes) > 0 {
  43. bn := nodes[0].Self()
  44. cfg.Bootnodes = []*enode.Node{bn}
  45. }
  46. node := startLocalhostV5(t, cfg)
  47. nodes = append(nodes, node)
  48. defer node.Close()
  49. }
  50. last := nodes[N-1]
  51. target := nodes[rand.Intn(N-2)].Self()
  52. // It is expected that all nodes can be found.
  53. expectedResult := make([]*enode.Node, len(nodes))
  54. for i := range nodes {
  55. expectedResult[i] = nodes[i].Self()
  56. }
  57. sort.Slice(expectedResult, func(i, j int) bool {
  58. return enode.DistCmp(target.ID(), expectedResult[i].ID(), expectedResult[j].ID()) < 0
  59. })
  60. // Do the lookup.
  61. results := last.Lookup(target.ID())
  62. if err := checkNodesEqual(results, expectedResult); err != nil {
  63. t.Fatalf("lookup returned wrong results: %v", err)
  64. }
  65. }
  66. func startLocalhostV5(t *testing.T, cfg Config) *UDPv5 {
  67. cfg.PrivateKey = newkey()
  68. db, _ := enode.OpenDB("")
  69. ln := enode.NewLocalNode(db, cfg.PrivateKey)
  70. // Prefix logs with node ID.
  71. lprefix := fmt.Sprintf("(%s)", ln.ID().TerminalString())
  72. lfmt := log.TerminalFormat(false)
  73. cfg.Log = testlog.Logger(t, log.LvlTrace)
  74. cfg.Log.SetHandler(log.FuncHandler(func(r *log.Record) error {
  75. t.Logf("%s %s", lprefix, lfmt.Format(r))
  76. return nil
  77. }))
  78. // Listen.
  79. socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}})
  80. if err != nil {
  81. t.Fatal(err)
  82. }
  83. realaddr := socket.LocalAddr().(*net.UDPAddr)
  84. ln.SetStaticIP(realaddr.IP)
  85. ln.Set(enr.UDP(realaddr.Port))
  86. udp, err := ListenV5(socket, ln, cfg)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. return udp
  91. }
  92. // This test checks that incoming PING calls are handled correctly.
  93. func TestUDPv5_pingHandling(t *testing.T) {
  94. t.Parallel()
  95. test := newUDPV5Test(t)
  96. defer test.close()
  97. test.packetIn(&v5wire.Ping{ReqID: []byte("foo")})
  98. test.waitPacketOut(func(p *v5wire.Pong, addr *net.UDPAddr, _ v5wire.Nonce) {
  99. if !bytes.Equal(p.ReqID, []byte("foo")) {
  100. t.Error("wrong request ID in response:", p.ReqID)
  101. }
  102. if p.ENRSeq != test.table.self().Seq() {
  103. t.Error("wrong ENR sequence number in response:", p.ENRSeq)
  104. }
  105. })
  106. }
  107. // This test checks that incoming 'unknown' packets trigger the handshake.
  108. func TestUDPv5_unknownPacket(t *testing.T) {
  109. t.Parallel()
  110. test := newUDPV5Test(t)
  111. defer test.close()
  112. nonce := v5wire.Nonce{1, 2, 3}
  113. check := func(p *v5wire.Whoareyou, wantSeq uint64) {
  114. t.Helper()
  115. if p.Nonce != nonce {
  116. t.Error("wrong nonce in WHOAREYOU:", p.Nonce, nonce)
  117. }
  118. if p.IDNonce == ([16]byte{}) {
  119. t.Error("all zero ID nonce")
  120. }
  121. if p.RecordSeq != wantSeq {
  122. t.Errorf("wrong record seq %d in WHOAREYOU, want %d", p.RecordSeq, wantSeq)
  123. }
  124. }
  125. // Unknown packet from unknown node.
  126. test.packetIn(&v5wire.Unknown{Nonce: nonce})
  127. test.waitPacketOut(func(p *v5wire.Whoareyou, addr *net.UDPAddr, _ v5wire.Nonce) {
  128. check(p, 0)
  129. })
  130. // Make node known.
  131. n := test.getNode(test.remotekey, test.remoteaddr).Node()
  132. test.table.addSeenNode(wrapNode(n))
  133. test.packetIn(&v5wire.Unknown{Nonce: nonce})
  134. test.waitPacketOut(func(p *v5wire.Whoareyou, addr *net.UDPAddr, _ v5wire.Nonce) {
  135. check(p, n.Seq())
  136. })
  137. }
  138. // This test checks that incoming FINDNODE calls are handled correctly.
  139. func TestUDPv5_findnodeHandling(t *testing.T) {
  140. t.Parallel()
  141. test := newUDPV5Test(t)
  142. defer test.close()
  143. // Create test nodes and insert them into the table.
  144. nodes253 := nodesAtDistance(test.table.self().ID(), 253, 10)
  145. nodes249 := nodesAtDistance(test.table.self().ID(), 249, 4)
  146. nodes248 := nodesAtDistance(test.table.self().ID(), 248, 10)
  147. fillTable(test.table, wrapNodes(nodes253))
  148. fillTable(test.table, wrapNodes(nodes249))
  149. fillTable(test.table, wrapNodes(nodes248))
  150. // Requesting with distance zero should return the node's own record.
  151. test.packetIn(&v5wire.Findnode{ReqID: []byte{0}, Distances: []uint{0}})
  152. test.expectNodes([]byte{0}, 1, []*enode.Node{test.udp.Self()})
  153. // Requesting with distance > 256 shouldn't crash.
  154. test.packetIn(&v5wire.Findnode{ReqID: []byte{1}, Distances: []uint{4234098}})
  155. test.expectNodes([]byte{1}, 1, nil)
  156. // Requesting with empty distance list shouldn't crash either.
  157. test.packetIn(&v5wire.Findnode{ReqID: []byte{2}, Distances: []uint{}})
  158. test.expectNodes([]byte{2}, 1, nil)
  159. // This request gets no nodes because the corresponding bucket is empty.
  160. test.packetIn(&v5wire.Findnode{ReqID: []byte{3}, Distances: []uint{254}})
  161. test.expectNodes([]byte{3}, 1, nil)
  162. // This request gets all the distance-253 nodes.
  163. test.packetIn(&v5wire.Findnode{ReqID: []byte{4}, Distances: []uint{253}})
  164. test.expectNodes([]byte{4}, 4, nodes253)
  165. // This request gets all the distance-249 nodes and some more at 248 because
  166. // the bucket at 249 is not full.
  167. test.packetIn(&v5wire.Findnode{ReqID: []byte{5}, Distances: []uint{249, 248}})
  168. var nodes []*enode.Node
  169. nodes = append(nodes, nodes249...)
  170. nodes = append(nodes, nodes248[:10]...)
  171. test.expectNodes([]byte{5}, 5, nodes)
  172. }
  173. func (test *udpV5Test) expectNodes(wantReqID []byte, wantTotal uint8, wantNodes []*enode.Node) {
  174. nodeSet := make(map[enode.ID]*enr.Record)
  175. for _, n := range wantNodes {
  176. nodeSet[n.ID()] = n.Record()
  177. }
  178. for {
  179. test.waitPacketOut(func(p *v5wire.Nodes, addr *net.UDPAddr, _ v5wire.Nonce) {
  180. if !bytes.Equal(p.ReqID, wantReqID) {
  181. test.t.Fatalf("wrong request ID %v in response, want %v", p.ReqID, wantReqID)
  182. }
  183. if len(p.Nodes) > 3 {
  184. test.t.Fatalf("too many nodes in response")
  185. }
  186. if p.Total != wantTotal {
  187. test.t.Fatalf("wrong total response count %d, want %d", p.Total, wantTotal)
  188. }
  189. for _, record := range p.Nodes {
  190. n, _ := enode.New(enode.ValidSchemesForTesting, record)
  191. want := nodeSet[n.ID()]
  192. if want == nil {
  193. test.t.Fatalf("unexpected node in response: %v", n)
  194. }
  195. if !reflect.DeepEqual(record, want) {
  196. test.t.Fatalf("wrong record in response: %v", n)
  197. }
  198. delete(nodeSet, n.ID())
  199. }
  200. })
  201. if len(nodeSet) == 0 {
  202. return
  203. }
  204. }
  205. }
  206. // This test checks that outgoing PING calls work.
  207. func TestUDPv5_pingCall(t *testing.T) {
  208. t.Parallel()
  209. test := newUDPV5Test(t)
  210. defer test.close()
  211. remote := test.getNode(test.remotekey, test.remoteaddr).Node()
  212. done := make(chan error, 1)
  213. // This ping times out.
  214. go func() {
  215. _, err := test.udp.ping(remote)
  216. done <- err
  217. }()
  218. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {})
  219. if err := <-done; err != errTimeout {
  220. t.Fatalf("want errTimeout, got %q", err)
  221. }
  222. // This ping works.
  223. go func() {
  224. _, err := test.udp.ping(remote)
  225. done <- err
  226. }()
  227. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
  228. test.packetInFrom(test.remotekey, test.remoteaddr, &v5wire.Pong{ReqID: p.ReqID})
  229. })
  230. if err := <-done; err != nil {
  231. t.Fatal(err)
  232. }
  233. // This ping gets a reply from the wrong endpoint.
  234. go func() {
  235. _, err := test.udp.ping(remote)
  236. done <- err
  237. }()
  238. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
  239. wrongAddr := &net.UDPAddr{IP: net.IP{33, 44, 55, 22}, Port: 10101}
  240. test.packetInFrom(test.remotekey, wrongAddr, &v5wire.Pong{ReqID: p.ReqID})
  241. })
  242. if err := <-done; err != errTimeout {
  243. t.Fatalf("want errTimeout for reply from wrong IP, got %q", err)
  244. }
  245. }
  246. // This test checks that outgoing FINDNODE calls work and multiple NODES
  247. // replies are aggregated.
  248. func TestUDPv5_findnodeCall(t *testing.T) {
  249. t.Parallel()
  250. test := newUDPV5Test(t)
  251. defer test.close()
  252. // Launch the request:
  253. var (
  254. distances = []uint{230}
  255. remote = test.getNode(test.remotekey, test.remoteaddr).Node()
  256. nodes = nodesAtDistance(remote.ID(), int(distances[0]), 8)
  257. done = make(chan error, 1)
  258. response []*enode.Node
  259. )
  260. go func() {
  261. var err error
  262. response, err = test.udp.findnode(remote, distances)
  263. done <- err
  264. }()
  265. // Serve the responses:
  266. test.waitPacketOut(func(p *v5wire.Findnode, addr *net.UDPAddr, _ v5wire.Nonce) {
  267. if !reflect.DeepEqual(p.Distances, distances) {
  268. t.Fatalf("wrong distances in request: %v", p.Distances)
  269. }
  270. test.packetIn(&v5wire.Nodes{
  271. ReqID: p.ReqID,
  272. Total: 2,
  273. Nodes: nodesToRecords(nodes[:4]),
  274. })
  275. test.packetIn(&v5wire.Nodes{
  276. ReqID: p.ReqID,
  277. Total: 2,
  278. Nodes: nodesToRecords(nodes[4:]),
  279. })
  280. })
  281. // Check results:
  282. if err := <-done; err != nil {
  283. t.Fatalf("unexpected error: %v", err)
  284. }
  285. if !reflect.DeepEqual(response, nodes) {
  286. t.Fatalf("wrong nodes in response")
  287. }
  288. // TODO: check invalid IPs
  289. // TODO: check invalid/unsigned record
  290. }
  291. // This test checks that pending calls are re-sent when a handshake happens.
  292. func TestUDPv5_callResend(t *testing.T) {
  293. t.Parallel()
  294. test := newUDPV5Test(t)
  295. defer test.close()
  296. remote := test.getNode(test.remotekey, test.remoteaddr).Node()
  297. done := make(chan error, 2)
  298. go func() {
  299. _, err := test.udp.ping(remote)
  300. done <- err
  301. }()
  302. go func() {
  303. _, err := test.udp.ping(remote)
  304. done <- err
  305. }()
  306. // Ping answered by WHOAREYOU.
  307. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, nonce v5wire.Nonce) {
  308. test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
  309. })
  310. // Ping should be re-sent.
  311. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
  312. test.packetIn(&v5wire.Pong{ReqID: p.ReqID})
  313. })
  314. // Answer the other ping.
  315. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
  316. test.packetIn(&v5wire.Pong{ReqID: p.ReqID})
  317. })
  318. if err := <-done; err != nil {
  319. t.Fatalf("unexpected ping error: %v", err)
  320. }
  321. if err := <-done; err != nil {
  322. t.Fatalf("unexpected ping error: %v", err)
  323. }
  324. }
  325. // This test ensures we don't allow multiple rounds of WHOAREYOU for a single call.
  326. func TestUDPv5_multipleHandshakeRounds(t *testing.T) {
  327. t.Parallel()
  328. test := newUDPV5Test(t)
  329. defer test.close()
  330. remote := test.getNode(test.remotekey, test.remoteaddr).Node()
  331. done := make(chan error, 1)
  332. go func() {
  333. _, err := test.udp.ping(remote)
  334. done <- err
  335. }()
  336. // Ping answered by WHOAREYOU.
  337. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, nonce v5wire.Nonce) {
  338. test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
  339. })
  340. // Ping answered by WHOAREYOU again.
  341. test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, nonce v5wire.Nonce) {
  342. test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
  343. })
  344. if err := <-done; err != errTimeout {
  345. t.Fatalf("unexpected ping error: %q", err)
  346. }
  347. }
  348. // This test checks that calls with n replies may take up to n * respTimeout.
  349. func TestUDPv5_callTimeoutReset(t *testing.T) {
  350. t.Parallel()
  351. test := newUDPV5Test(t)
  352. defer test.close()
  353. // Launch the request:
  354. var (
  355. distance = uint(230)
  356. remote = test.getNode(test.remotekey, test.remoteaddr).Node()
  357. nodes = nodesAtDistance(remote.ID(), int(distance), 8)
  358. done = make(chan error, 1)
  359. )
  360. go func() {
  361. _, err := test.udp.findnode(remote, []uint{distance})
  362. done <- err
  363. }()
  364. // Serve two responses, slowly.
  365. test.waitPacketOut(func(p *v5wire.Findnode, addr *net.UDPAddr, _ v5wire.Nonce) {
  366. time.Sleep(respTimeout - 50*time.Millisecond)
  367. test.packetIn(&v5wire.Nodes{
  368. ReqID: p.ReqID,
  369. Total: 2,
  370. Nodes: nodesToRecords(nodes[:4]),
  371. })
  372. time.Sleep(respTimeout - 50*time.Millisecond)
  373. test.packetIn(&v5wire.Nodes{
  374. ReqID: p.ReqID,
  375. Total: 2,
  376. Nodes: nodesToRecords(nodes[4:]),
  377. })
  378. })
  379. if err := <-done; err != nil {
  380. t.Fatalf("unexpected error: %q", err)
  381. }
  382. }
  383. // This test checks that TALKREQ calls the registered handler function.
  384. func TestUDPv5_talkHandling(t *testing.T) {
  385. t.Parallel()
  386. test := newUDPV5Test(t)
  387. defer test.close()
  388. var recvMessage []byte
  389. test.udp.RegisterTalkHandler("test", func(id enode.ID, addr *net.UDPAddr, message []byte) []byte {
  390. recvMessage = message
  391. return []byte("test response")
  392. })
  393. // Successful case:
  394. test.packetIn(&v5wire.TalkRequest{
  395. ReqID: []byte("foo"),
  396. Protocol: "test",
  397. Message: []byte("test request"),
  398. })
  399. test.waitPacketOut(func(p *v5wire.TalkResponse, addr *net.UDPAddr, _ v5wire.Nonce) {
  400. if !bytes.Equal(p.ReqID, []byte("foo")) {
  401. t.Error("wrong request ID in response:", p.ReqID)
  402. }
  403. if string(p.Message) != "test response" {
  404. t.Errorf("wrong talk response message: %q", p.Message)
  405. }
  406. if string(recvMessage) != "test request" {
  407. t.Errorf("wrong message received in handler: %q", recvMessage)
  408. }
  409. })
  410. // Check that empty response is returned for unregistered protocols.
  411. recvMessage = nil
  412. test.packetIn(&v5wire.TalkRequest{
  413. ReqID: []byte("2"),
  414. Protocol: "wrong",
  415. Message: []byte("test request"),
  416. })
  417. test.waitPacketOut(func(p *v5wire.TalkResponse, addr *net.UDPAddr, _ v5wire.Nonce) {
  418. if !bytes.Equal(p.ReqID, []byte("2")) {
  419. t.Error("wrong request ID in response:", p.ReqID)
  420. }
  421. if string(p.Message) != "" {
  422. t.Errorf("wrong talk response message: %q", p.Message)
  423. }
  424. if recvMessage != nil {
  425. t.Errorf("handler was called for wrong protocol: %q", recvMessage)
  426. }
  427. })
  428. }
  429. // This test checks that outgoing TALKREQ calls work.
  430. func TestUDPv5_talkRequest(t *testing.T) {
  431. t.Parallel()
  432. test := newUDPV5Test(t)
  433. defer test.close()
  434. remote := test.getNode(test.remotekey, test.remoteaddr).Node()
  435. done := make(chan error, 1)
  436. // This request times out.
  437. go func() {
  438. _, err := test.udp.TalkRequest(remote, "test", []byte("test request"))
  439. done <- err
  440. }()
  441. test.waitPacketOut(func(p *v5wire.TalkRequest, addr *net.UDPAddr, _ v5wire.Nonce) {})
  442. if err := <-done; err != errTimeout {
  443. t.Fatalf("want errTimeout, got %q", err)
  444. }
  445. // This request works.
  446. go func() {
  447. _, err := test.udp.TalkRequest(remote, "test", []byte("test request"))
  448. done <- err
  449. }()
  450. test.waitPacketOut(func(p *v5wire.TalkRequest, addr *net.UDPAddr, _ v5wire.Nonce) {
  451. if p.Protocol != "test" {
  452. t.Errorf("wrong protocol ID in talk request: %q", p.Protocol)
  453. }
  454. if string(p.Message) != "test request" {
  455. t.Errorf("wrong message talk request: %q", p.Message)
  456. }
  457. test.packetInFrom(test.remotekey, test.remoteaddr, &v5wire.TalkResponse{
  458. ReqID: p.ReqID,
  459. Message: []byte("test response"),
  460. })
  461. })
  462. if err := <-done; err != nil {
  463. t.Fatal(err)
  464. }
  465. }
  466. // This test checks that lookup works.
  467. func TestUDPv5_lookup(t *testing.T) {
  468. t.Parallel()
  469. test := newUDPV5Test(t)
  470. // Lookup on empty table returns no nodes.
  471. if results := test.udp.Lookup(lookupTestnet.target.id()); len(results) > 0 {
  472. t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
  473. }
  474. // Ensure the tester knows all nodes in lookupTestnet by IP.
  475. for d, nn := range lookupTestnet.dists {
  476. for i, key := range nn {
  477. n := lookupTestnet.node(d, i)
  478. test.getNode(key, &net.UDPAddr{IP: n.IP(), Port: n.UDP()})
  479. }
  480. }
  481. // Seed table with initial node.
  482. initialNode := lookupTestnet.node(256, 0)
  483. fillTable(test.table, []*node{wrapNode(initialNode)})
  484. // Start the lookup.
  485. resultC := make(chan []*enode.Node, 1)
  486. go func() {
  487. resultC <- test.udp.Lookup(lookupTestnet.target.id())
  488. test.close()
  489. }()
  490. // Answer lookup packets.
  491. asked := make(map[enode.ID]bool)
  492. for done := false; !done; {
  493. done = test.waitPacketOut(func(p v5wire.Packet, to *net.UDPAddr, _ v5wire.Nonce) {
  494. recipient, key := lookupTestnet.nodeByAddr(to)
  495. switch p := p.(type) {
  496. case *v5wire.Ping:
  497. test.packetInFrom(key, to, &v5wire.Pong{ReqID: p.ReqID})
  498. case *v5wire.Findnode:
  499. if asked[recipient.ID()] {
  500. t.Error("Asked node", recipient.ID(), "twice")
  501. }
  502. asked[recipient.ID()] = true
  503. nodes := lookupTestnet.neighborsAtDistances(recipient, p.Distances, 16)
  504. t.Logf("Got FINDNODE for %v, returning %d nodes", p.Distances, len(nodes))
  505. for _, resp := range packNodes(p.ReqID, nodes) {
  506. test.packetInFrom(key, to, resp)
  507. }
  508. }
  509. })
  510. }
  511. // Verify result nodes.
  512. results := <-resultC
  513. checkLookupResults(t, lookupTestnet, results)
  514. }
  515. // This test checks the local node can be utilised to set key-values.
  516. func TestUDPv5_LocalNode(t *testing.T) {
  517. t.Parallel()
  518. var cfg Config
  519. node := startLocalhostV5(t, cfg)
  520. defer node.Close()
  521. localNd := node.LocalNode()
  522. // set value in node's local record
  523. testVal := [4]byte{'A', 'B', 'C', 'D'}
  524. localNd.Set(enr.WithEntry("testing", &testVal))
  525. // retrieve the value from self to make sure it matches.
  526. outputVal := [4]byte{}
  527. if err := node.Self().Load(enr.WithEntry("testing", &outputVal)); err != nil {
  528. t.Errorf("Could not load value from record: %v", err)
  529. }
  530. if testVal != outputVal {
  531. t.Errorf("Wanted %#x to be retrieved from the record but instead got %#x", testVal, outputVal)
  532. }
  533. }
  534. func TestUDPv5_PingWithIPV4MappedAddress(t *testing.T) {
  535. t.Parallel()
  536. test := newUDPV5Test(t)
  537. defer test.close()
  538. rawIP := net.IPv4(0xFF, 0x12, 0x33, 0xE5)
  539. test.remoteaddr = &net.UDPAddr{
  540. IP: rawIP.To16(),
  541. Port: 0,
  542. }
  543. remote := test.getNode(test.remotekey, test.remoteaddr).Node()
  544. done := make(chan struct{}, 1)
  545. // This handler will truncate the ipv4-mapped in ipv6 address.
  546. go func() {
  547. test.udp.handlePing(&v5wire.Ping{ENRSeq: 1}, remote.ID(), test.remoteaddr)
  548. done <- struct{}{}
  549. }()
  550. test.waitPacketOut(func(p *v5wire.Pong, addr *net.UDPAddr, _ v5wire.Nonce) {
  551. if len(p.ToIP) == net.IPv6len {
  552. t.Error("Received untruncated ip address")
  553. }
  554. if len(p.ToIP) != net.IPv4len {
  555. t.Errorf("Received ip address with incorrect length: %d", len(p.ToIP))
  556. }
  557. if !p.ToIP.Equal(rawIP) {
  558. t.Errorf("Received incorrect ip address: wanted %s but received %s", rawIP.String(), p.ToIP.String())
  559. }
  560. })
  561. <-done
  562. }
  563. // udpV5Test is the framework for all tests above.
  564. // It runs the UDPv5 transport on a virtual socket and allows testing outgoing packets.
  565. type udpV5Test struct {
  566. t *testing.T
  567. pipe *dgramPipe
  568. table *Table
  569. db *enode.DB
  570. udp *UDPv5
  571. localkey, remotekey *ecdsa.PrivateKey
  572. remoteaddr *net.UDPAddr
  573. nodesByID map[enode.ID]*enode.LocalNode
  574. nodesByIP map[string]*enode.LocalNode
  575. }
  576. // testCodec is the packet encoding used by protocol tests. This codec does not perform encryption.
  577. type testCodec struct {
  578. test *udpV5Test
  579. id enode.ID
  580. ctr uint64
  581. }
  582. type testCodecFrame struct {
  583. NodeID enode.ID
  584. AuthTag v5wire.Nonce
  585. Ptype byte
  586. Packet rlp.RawValue
  587. }
  588. func (c *testCodec) Encode(toID enode.ID, addr string, p v5wire.Packet, _ *v5wire.Whoareyou) ([]byte, v5wire.Nonce, error) {
  589. c.ctr++
  590. var authTag v5wire.Nonce
  591. binary.BigEndian.PutUint64(authTag[:], c.ctr)
  592. penc, _ := rlp.EncodeToBytes(p)
  593. frame, err := rlp.EncodeToBytes(testCodecFrame{c.id, authTag, p.Kind(), penc})
  594. return frame, authTag, err
  595. }
  596. func (c *testCodec) Decode(input []byte, addr string) (enode.ID, *enode.Node, v5wire.Packet, error) {
  597. frame, p, err := c.decodeFrame(input)
  598. if err != nil {
  599. return enode.ID{}, nil, nil, err
  600. }
  601. return frame.NodeID, nil, p, nil
  602. }
  603. func (c *testCodec) decodeFrame(input []byte) (frame testCodecFrame, p v5wire.Packet, err error) {
  604. if err = rlp.DecodeBytes(input, &frame); err != nil {
  605. return frame, nil, fmt.Errorf("invalid frame: %v", err)
  606. }
  607. switch frame.Ptype {
  608. case v5wire.UnknownPacket:
  609. dec := new(v5wire.Unknown)
  610. err = rlp.DecodeBytes(frame.Packet, &dec)
  611. p = dec
  612. case v5wire.WhoareyouPacket:
  613. dec := new(v5wire.Whoareyou)
  614. err = rlp.DecodeBytes(frame.Packet, &dec)
  615. p = dec
  616. default:
  617. p, err = v5wire.DecodeMessage(frame.Ptype, frame.Packet)
  618. }
  619. return frame, p, err
  620. }
  621. func newUDPV5Test(t *testing.T) *udpV5Test {
  622. test := &udpV5Test{
  623. t: t,
  624. pipe: newpipe(),
  625. localkey: newkey(),
  626. remotekey: newkey(),
  627. remoteaddr: &net.UDPAddr{IP: net.IP{10, 0, 1, 99}, Port: 30303},
  628. nodesByID: make(map[enode.ID]*enode.LocalNode),
  629. nodesByIP: make(map[string]*enode.LocalNode),
  630. }
  631. test.db, _ = enode.OpenDB("")
  632. ln := enode.NewLocalNode(test.db, test.localkey)
  633. ln.SetStaticIP(net.IP{10, 0, 0, 1})
  634. ln.Set(enr.UDP(30303))
  635. test.udp, _ = ListenV5(test.pipe, ln, Config{
  636. PrivateKey: test.localkey,
  637. Log: testlog.Logger(t, log.LvlTrace),
  638. ValidSchemes: enode.ValidSchemesForTesting,
  639. })
  640. test.udp.codec = &testCodec{test: test, id: ln.ID()}
  641. test.table = test.udp.tab
  642. test.nodesByID[ln.ID()] = ln
  643. // Wait for initial refresh so the table doesn't send unexpected findnode.
  644. <-test.table.initDone
  645. return test
  646. }
  647. // handles a packet as if it had been sent to the transport.
  648. func (test *udpV5Test) packetIn(packet v5wire.Packet) {
  649. test.t.Helper()
  650. test.packetInFrom(test.remotekey, test.remoteaddr, packet)
  651. }
  652. // handles a packet as if it had been sent to the transport by the key/endpoint.
  653. func (test *udpV5Test) packetInFrom(key *ecdsa.PrivateKey, addr *net.UDPAddr, packet v5wire.Packet) {
  654. test.t.Helper()
  655. ln := test.getNode(key, addr)
  656. codec := &testCodec{test: test, id: ln.ID()}
  657. enc, _, err := codec.Encode(test.udp.Self().ID(), addr.String(), packet, nil)
  658. if err != nil {
  659. test.t.Errorf("%s encode error: %v", packet.Name(), err)
  660. }
  661. if test.udp.dispatchReadPacket(addr, enc) {
  662. <-test.udp.readNextCh // unblock UDPv5.dispatch
  663. }
  664. }
  665. // getNode ensures the test knows about a node at the given endpoint.
  666. func (test *udpV5Test) getNode(key *ecdsa.PrivateKey, addr *net.UDPAddr) *enode.LocalNode {
  667. id := encodePubkey(&key.PublicKey).id()
  668. ln := test.nodesByID[id]
  669. if ln == nil {
  670. db, _ := enode.OpenDB("")
  671. ln = enode.NewLocalNode(db, key)
  672. ln.SetStaticIP(addr.IP)
  673. ln.Set(enr.UDP(addr.Port))
  674. test.nodesByID[id] = ln
  675. }
  676. test.nodesByIP[string(addr.IP)] = ln
  677. return ln
  678. }
  679. // waitPacketOut waits for the next output packet and handles it using the given 'validate'
  680. // function. The function must be of type func (X, *net.UDPAddr, v5wire.Nonce) where X is
  681. // assignable to packetV5.
  682. func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) {
  683. test.t.Helper()
  684. fn := reflect.ValueOf(validate)
  685. exptype := fn.Type().In(0)
  686. dgram, err := test.pipe.receive()
  687. if err == errClosed {
  688. return true
  689. }
  690. if err == errTimeout {
  691. test.t.Fatalf("timed out waiting for %v", exptype)
  692. return false
  693. }
  694. ln := test.nodesByIP[string(dgram.to.IP)]
  695. if ln == nil {
  696. test.t.Fatalf("attempt to send to non-existing node %v", &dgram.to)
  697. return false
  698. }
  699. codec := &testCodec{test: test, id: ln.ID()}
  700. frame, p, err := codec.decodeFrame(dgram.data)
  701. if err != nil {
  702. test.t.Errorf("sent packet decode error: %v", err)
  703. return false
  704. }
  705. if !reflect.TypeOf(p).AssignableTo(exptype) {
  706. test.t.Errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
  707. return false
  708. }
  709. fn.Call([]reflect.Value{reflect.ValueOf(p), reflect.ValueOf(&dgram.to), reflect.ValueOf(frame.AuthTag)})
  710. return false
  711. }
  712. func (test *udpV5Test) close() {
  713. test.t.Helper()
  714. test.udp.Close()
  715. test.db.Close()
  716. for id, n := range test.nodesByID {
  717. if id != test.udp.Self().ID() {
  718. n.Database().Close()
  719. }
  720. }
  721. if len(test.pipe.queue) != 0 {
  722. test.t.Fatalf("%d unmatched UDP packets in queue", len(test.pipe.queue))
  723. }
  724. }