github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/p2p/discover/v5wire/encoding_test.go (about)

     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  
    17  package v5wire
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/ecdsa"
    22  	"encoding/hex"
    23  	"errors"
    24  	"flag"
    25  	"fmt"
    26  	"io/ioutil"
    27  	"net"
    28  	"os"
    29  	"path/filepath"
    30  	"strings"
    31  	"testing"
    32  
    33  	"github.com/davecgh/go-spew/spew"
    34  
    35  	"github.com/scroll-tech/go-ethereum/common/hexutil"
    36  	"github.com/scroll-tech/go-ethereum/common/mclock"
    37  	"github.com/scroll-tech/go-ethereum/crypto"
    38  	"github.com/scroll-tech/go-ethereum/p2p/enode"
    39  )
    40  
    41  // To regenerate discv5 test vectors, run
    42  //
    43  //     go test -run TestVectors -write-test-vectors
    44  //
    45  var writeTestVectorsFlag = flag.Bool("write-test-vectors", false, "Overwrite discv5 test vectors in testdata/")
    46  
    47  var (
    48  	testKeyA, _   = crypto.HexToECDSA("eef77acb6c6a6eebc5b363a475ac583ec7eccdb42b6481424c60f59aa326547f")
    49  	testKeyB, _   = crypto.HexToECDSA("66fb62bfbd66b9177a138c1e5cddbe4f7c30c343e94e68df8769459cb1cde628")
    50  	testEphKey, _ = crypto.HexToECDSA("0288ef00023598499cb6c940146d050d2b1fb914198c327f76aad590bead68b6")
    51  	testIDnonce   = [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
    52  )
    53  
    54  // This test checks that the minPacketSize and randomPacketMsgSize constants are well-defined.
    55  func TestMinSizes(t *testing.T) {
    56  	var (
    57  		gcmTagSize = 16
    58  		emptyMsg   = sizeofMessageAuthData + gcmTagSize
    59  	)
    60  	t.Log("static header size", sizeofStaticPacketData)
    61  	t.Log("whoareyou size", sizeofStaticPacketData+sizeofWhoareyouAuthData)
    62  	t.Log("empty msg size", sizeofStaticPacketData+emptyMsg)
    63  	if want := emptyMsg; minMessageSize != want {
    64  		t.Fatalf("wrong minMessageSize %d, want %d", minMessageSize, want)
    65  	}
    66  	if sizeofMessageAuthData+randomPacketMsgSize < minMessageSize {
    67  		t.Fatalf("randomPacketMsgSize %d too small", randomPacketMsgSize)
    68  	}
    69  }
    70  
    71  // This test checks the basic handshake flow where A talks to B and A has no secrets.
    72  func TestHandshake(t *testing.T) {
    73  	t.Parallel()
    74  	net := newHandshakeTest()
    75  	defer net.close()
    76  
    77  	// A -> B   RANDOM PACKET
    78  	packet, _ := net.nodeA.encode(t, net.nodeB, &Findnode{})
    79  	resp := net.nodeB.expectDecode(t, UnknownPacket, packet)
    80  
    81  	// A <- B   WHOAREYOU
    82  	challenge := &Whoareyou{
    83  		Nonce:     resp.(*Unknown).Nonce,
    84  		IDNonce:   testIDnonce,
    85  		RecordSeq: 0,
    86  	}
    87  	whoareyou, _ := net.nodeB.encode(t, net.nodeA, challenge)
    88  	net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
    89  
    90  	// A -> B   FINDNODE (handshake packet)
    91  	findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})
    92  	net.nodeB.expectDecode(t, FindnodeMsg, findnode)
    93  	if len(net.nodeB.c.sc.handshakes) > 0 {
    94  		t.Fatalf("node B didn't remove handshake from challenge map")
    95  	}
    96  
    97  	// A <- B   NODES
    98  	nodes, _ := net.nodeB.encode(t, net.nodeA, &Nodes{Total: 1})
    99  	net.nodeA.expectDecode(t, NodesMsg, nodes)
   100  }
   101  
   102  // This test checks that handshake attempts are removed within the timeout.
   103  func TestHandshake_timeout(t *testing.T) {
   104  	t.Parallel()
   105  	net := newHandshakeTest()
   106  	defer net.close()
   107  
   108  	// A -> B   RANDOM PACKET
   109  	packet, _ := net.nodeA.encode(t, net.nodeB, &Findnode{})
   110  	resp := net.nodeB.expectDecode(t, UnknownPacket, packet)
   111  
   112  	// A <- B   WHOAREYOU
   113  	challenge := &Whoareyou{
   114  		Nonce:     resp.(*Unknown).Nonce,
   115  		IDNonce:   testIDnonce,
   116  		RecordSeq: 0,
   117  	}
   118  	whoareyou, _ := net.nodeB.encode(t, net.nodeA, challenge)
   119  	net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
   120  
   121  	// A -> B   FINDNODE (handshake packet) after timeout
   122  	net.clock.Run(handshakeTimeout + 1)
   123  	findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})
   124  	net.nodeB.expectDecodeErr(t, errUnexpectedHandshake, findnode)
   125  }
   126  
   127  // This test checks handshake behavior when no record is sent in the auth response.
   128  func TestHandshake_norecord(t *testing.T) {
   129  	t.Parallel()
   130  	net := newHandshakeTest()
   131  	defer net.close()
   132  
   133  	// A -> B   RANDOM PACKET
   134  	packet, _ := net.nodeA.encode(t, net.nodeB, &Findnode{})
   135  	resp := net.nodeB.expectDecode(t, UnknownPacket, packet)
   136  
   137  	// A <- B   WHOAREYOU
   138  	nodeA := net.nodeA.n()
   139  	if nodeA.Seq() == 0 {
   140  		t.Fatal("need non-zero sequence number")
   141  	}
   142  	challenge := &Whoareyou{
   143  		Nonce:     resp.(*Unknown).Nonce,
   144  		IDNonce:   testIDnonce,
   145  		RecordSeq: nodeA.Seq(),
   146  		Node:      nodeA,
   147  	}
   148  	whoareyou, _ := net.nodeB.encode(t, net.nodeA, challenge)
   149  	net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
   150  
   151  	// A -> B   FINDNODE
   152  	findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})
   153  	net.nodeB.expectDecode(t, FindnodeMsg, findnode)
   154  
   155  	// A <- B   NODES
   156  	nodes, _ := net.nodeB.encode(t, net.nodeA, &Nodes{Total: 1})
   157  	net.nodeA.expectDecode(t, NodesMsg, nodes)
   158  }
   159  
   160  // In this test, A tries to send FINDNODE with existing secrets but B doesn't know
   161  // anything about A.
   162  func TestHandshake_rekey(t *testing.T) {
   163  	t.Parallel()
   164  	net := newHandshakeTest()
   165  	defer net.close()
   166  
   167  	session := &session{
   168  		readKey:  []byte("BBBBBBBBBBBBBBBB"),
   169  		writeKey: []byte("AAAAAAAAAAAAAAAA"),
   170  	}
   171  	net.nodeA.c.sc.storeNewSession(net.nodeB.id(), net.nodeB.addr(), session)
   172  
   173  	// A -> B   FINDNODE (encrypted with zero keys)
   174  	findnode, authTag := net.nodeA.encode(t, net.nodeB, &Findnode{})
   175  	net.nodeB.expectDecode(t, UnknownPacket, findnode)
   176  
   177  	// A <- B   WHOAREYOU
   178  	challenge := &Whoareyou{Nonce: authTag, IDNonce: testIDnonce}
   179  	whoareyou, _ := net.nodeB.encode(t, net.nodeA, challenge)
   180  	net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
   181  
   182  	// Check that new keys haven't been stored yet.
   183  	sa := net.nodeA.c.sc.session(net.nodeB.id(), net.nodeB.addr())
   184  	if !bytes.Equal(sa.writeKey, session.writeKey) || !bytes.Equal(sa.readKey, session.readKey) {
   185  		t.Fatal("node A stored keys too early")
   186  	}
   187  	if s := net.nodeB.c.sc.session(net.nodeA.id(), net.nodeA.addr()); s != nil {
   188  		t.Fatal("node B stored keys too early")
   189  	}
   190  
   191  	// A -> B   FINDNODE encrypted with new keys
   192  	findnode, _ = net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})
   193  	net.nodeB.expectDecode(t, FindnodeMsg, findnode)
   194  
   195  	// A <- B   NODES
   196  	nodes, _ := net.nodeB.encode(t, net.nodeA, &Nodes{Total: 1})
   197  	net.nodeA.expectDecode(t, NodesMsg, nodes)
   198  }
   199  
   200  // In this test A and B have different keys before the handshake.
   201  func TestHandshake_rekey2(t *testing.T) {
   202  	t.Parallel()
   203  	net := newHandshakeTest()
   204  	defer net.close()
   205  
   206  	initKeysA := &session{
   207  		readKey:  []byte("BBBBBBBBBBBBBBBB"),
   208  		writeKey: []byte("AAAAAAAAAAAAAAAA"),
   209  	}
   210  	initKeysB := &session{
   211  		readKey:  []byte("CCCCCCCCCCCCCCCC"),
   212  		writeKey: []byte("DDDDDDDDDDDDDDDD"),
   213  	}
   214  	net.nodeA.c.sc.storeNewSession(net.nodeB.id(), net.nodeB.addr(), initKeysA)
   215  	net.nodeB.c.sc.storeNewSession(net.nodeA.id(), net.nodeA.addr(), initKeysB)
   216  
   217  	// A -> B   FINDNODE encrypted with initKeysA
   218  	findnode, authTag := net.nodeA.encode(t, net.nodeB, &Findnode{Distances: []uint{3}})
   219  	net.nodeB.expectDecode(t, UnknownPacket, findnode)
   220  
   221  	// A <- B   WHOAREYOU
   222  	challenge := &Whoareyou{Nonce: authTag, IDNonce: testIDnonce}
   223  	whoareyou, _ := net.nodeB.encode(t, net.nodeA, challenge)
   224  	net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
   225  
   226  	// A -> B   FINDNODE (handshake packet)
   227  	findnode, _ = net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})
   228  	net.nodeB.expectDecode(t, FindnodeMsg, findnode)
   229  
   230  	// A <- B   NODES
   231  	nodes, _ := net.nodeB.encode(t, net.nodeA, &Nodes{Total: 1})
   232  	net.nodeA.expectDecode(t, NodesMsg, nodes)
   233  }
   234  
   235  func TestHandshake_BadHandshakeAttack(t *testing.T) {
   236  	t.Parallel()
   237  	net := newHandshakeTest()
   238  	defer net.close()
   239  
   240  	// A -> B   RANDOM PACKET
   241  	packet, _ := net.nodeA.encode(t, net.nodeB, &Findnode{})
   242  	resp := net.nodeB.expectDecode(t, UnknownPacket, packet)
   243  
   244  	// A <- B   WHOAREYOU
   245  	challenge := &Whoareyou{
   246  		Nonce:     resp.(*Unknown).Nonce,
   247  		IDNonce:   testIDnonce,
   248  		RecordSeq: 0,
   249  	}
   250  	whoareyou, _ := net.nodeB.encode(t, net.nodeA, challenge)
   251  	net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou)
   252  
   253  	// A -> B   FINDNODE
   254  	incorrect_challenge := &Whoareyou{
   255  		IDNonce:   [16]byte{5, 6, 7, 8, 9, 6, 11, 12},
   256  		RecordSeq: challenge.RecordSeq,
   257  		Node:      challenge.Node,
   258  		sent:      challenge.sent,
   259  	}
   260  	incorrect_findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, incorrect_challenge, &Findnode{})
   261  	incorrect_findnode2 := make([]byte, len(incorrect_findnode))
   262  	copy(incorrect_findnode2, incorrect_findnode)
   263  
   264  	net.nodeB.expectDecodeErr(t, errInvalidNonceSig, incorrect_findnode)
   265  
   266  	// Reject new findnode as previous handshake is now deleted.
   267  	net.nodeB.expectDecodeErr(t, errUnexpectedHandshake, incorrect_findnode2)
   268  
   269  	// The findnode packet is again rejected even with a valid challenge this time.
   270  	findnode, _ := net.nodeA.encodeWithChallenge(t, net.nodeB, challenge, &Findnode{})
   271  	net.nodeB.expectDecodeErr(t, errUnexpectedHandshake, findnode)
   272  }
   273  
   274  // This test checks some malformed packets.
   275  func TestDecodeErrorsV5(t *testing.T) {
   276  	t.Parallel()
   277  	net := newHandshakeTest()
   278  	defer net.close()
   279  
   280  	net.nodeA.expectDecodeErr(t, errTooShort, []byte{})
   281  	// TODO some more tests would be nice :)
   282  	// - check invalid authdata sizes
   283  	// - check invalid handshake data sizes
   284  }
   285  
   286  // This test checks that all test vectors can be decoded.
   287  func TestTestVectorsV5(t *testing.T) {
   288  	var (
   289  		idA     = enode.PubkeyToIDV4(&testKeyA.PublicKey)
   290  		idB     = enode.PubkeyToIDV4(&testKeyB.PublicKey)
   291  		addr    = "127.0.0.1"
   292  		session = &session{
   293  			writeKey: hexutil.MustDecode("0x00000000000000000000000000000000"),
   294  			readKey:  hexutil.MustDecode("0x01010101010101010101010101010101"),
   295  		}
   296  		challenge0A, challenge1A, challenge0B Whoareyou
   297  	)
   298  
   299  	// Create challenge packets.
   300  	c := Whoareyou{
   301  		Nonce:   Nonce{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
   302  		IDNonce: testIDnonce,
   303  	}
   304  	challenge0A, challenge1A, challenge0B = c, c, c
   305  	challenge1A.RecordSeq = 1
   306  	net := newHandshakeTest()
   307  	challenge0A.Node = net.nodeA.n()
   308  	challenge0B.Node = net.nodeB.n()
   309  	challenge1A.Node = net.nodeA.n()
   310  	net.close()
   311  
   312  	type testVectorTest struct {
   313  		name      string               // test vector name
   314  		packet    Packet               // the packet to be encoded
   315  		challenge *Whoareyou           // handshake challenge passed to encoder
   316  		prep      func(*handshakeTest) // called before encode/decode
   317  	}
   318  	tests := []testVectorTest{
   319  		{
   320  			name:   "v5.1-whoareyou",
   321  			packet: &challenge0B,
   322  		},
   323  		{
   324  			name: "v5.1-ping-message",
   325  			packet: &Ping{
   326  				ReqID:  []byte{0, 0, 0, 1},
   327  				ENRSeq: 2,
   328  			},
   329  			prep: func(net *handshakeTest) {
   330  				net.nodeA.c.sc.storeNewSession(idB, addr, session)
   331  				net.nodeB.c.sc.storeNewSession(idA, addr, session.keysFlipped())
   332  			},
   333  		},
   334  		{
   335  			name: "v5.1-ping-handshake-enr",
   336  			packet: &Ping{
   337  				ReqID:  []byte{0, 0, 0, 1},
   338  				ENRSeq: 1,
   339  			},
   340  			challenge: &challenge0A,
   341  			prep: func(net *handshakeTest) {
   342  				// Update challenge.Header.AuthData.
   343  				net.nodeA.c.Encode(idB, "", &challenge0A, nil)
   344  				net.nodeB.c.sc.storeSentHandshake(idA, addr, &challenge0A)
   345  			},
   346  		},
   347  		{
   348  			name: "v5.1-ping-handshake",
   349  			packet: &Ping{
   350  				ReqID:  []byte{0, 0, 0, 1},
   351  				ENRSeq: 1,
   352  			},
   353  			challenge: &challenge1A,
   354  			prep: func(net *handshakeTest) {
   355  				// Update challenge data.
   356  				net.nodeA.c.Encode(idB, "", &challenge1A, nil)
   357  				net.nodeB.c.sc.storeSentHandshake(idA, addr, &challenge1A)
   358  			},
   359  		},
   360  	}
   361  
   362  	for _, test := range tests {
   363  		test := test
   364  		t.Run(test.name, func(t *testing.T) {
   365  			net := newHandshakeTest()
   366  			defer net.close()
   367  
   368  			// Override all random inputs.
   369  			net.nodeA.c.sc.nonceGen = func(counter uint32) (Nonce, error) {
   370  				return Nonce{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, nil
   371  			}
   372  			net.nodeA.c.sc.maskingIVGen = func(buf []byte) error {
   373  				return nil // all zero
   374  			}
   375  			net.nodeA.c.sc.ephemeralKeyGen = func() (*ecdsa.PrivateKey, error) {
   376  				return testEphKey, nil
   377  			}
   378  
   379  			// Prime the codec for encoding/decoding.
   380  			if test.prep != nil {
   381  				test.prep(net)
   382  			}
   383  
   384  			file := filepath.Join("testdata", test.name+".txt")
   385  			if *writeTestVectorsFlag {
   386  				// Encode the packet.
   387  				d, nonce := net.nodeA.encodeWithChallenge(t, net.nodeB, test.challenge, test.packet)
   388  				comment := testVectorComment(net, test.packet, test.challenge, nonce)
   389  				writeTestVector(file, comment, d)
   390  			}
   391  			enc := hexFile(file)
   392  			net.nodeB.expectDecode(t, test.packet.Kind(), enc)
   393  		})
   394  	}
   395  }
   396  
   397  // testVectorComment creates the commentary for discv5 test vector files.
   398  func testVectorComment(net *handshakeTest, p Packet, challenge *Whoareyou, nonce Nonce) string {
   399  	o := new(strings.Builder)
   400  	printWhoareyou := func(p *Whoareyou) {
   401  		fmt.Fprintf(o, "whoareyou.challenge-data = %#x\n", p.ChallengeData)
   402  		fmt.Fprintf(o, "whoareyou.request-nonce = %#x\n", p.Nonce[:])
   403  		fmt.Fprintf(o, "whoareyou.id-nonce = %#x\n", p.IDNonce[:])
   404  		fmt.Fprintf(o, "whoareyou.enr-seq = %d\n", p.RecordSeq)
   405  	}
   406  
   407  	fmt.Fprintf(o, "src-node-id = %#x\n", net.nodeA.id().Bytes())
   408  	fmt.Fprintf(o, "dest-node-id = %#x\n", net.nodeB.id().Bytes())
   409  	switch p := p.(type) {
   410  	case *Whoareyou:
   411  		// WHOAREYOU packet.
   412  		printWhoareyou(p)
   413  	case *Ping:
   414  		fmt.Fprintf(o, "nonce = %#x\n", nonce[:])
   415  		fmt.Fprintf(o, "read-key = %#x\n", net.nodeA.c.sc.session(net.nodeB.id(), net.nodeB.addr()).writeKey)
   416  		fmt.Fprintf(o, "ping.req-id = %#x\n", p.ReqID)
   417  		fmt.Fprintf(o, "ping.enr-seq = %d\n", p.ENRSeq)
   418  		if challenge != nil {
   419  			// Handshake message packet.
   420  			fmt.Fprint(o, "\nhandshake inputs:\n\n")
   421  			printWhoareyou(challenge)
   422  			fmt.Fprintf(o, "ephemeral-key = %#x\n", testEphKey.D.Bytes())
   423  			fmt.Fprintf(o, "ephemeral-pubkey = %#x\n", crypto.CompressPubkey(&testEphKey.PublicKey))
   424  		}
   425  	default:
   426  		panic(fmt.Errorf("unhandled packet type %T", p))
   427  	}
   428  	return o.String()
   429  }
   430  
   431  // This benchmark checks performance of handshake packet decoding.
   432  func BenchmarkV5_DecodeHandshakePingSecp256k1(b *testing.B) {
   433  	net := newHandshakeTest()
   434  	defer net.close()
   435  
   436  	var (
   437  		idA       = net.nodeA.id()
   438  		challenge = &Whoareyou{Node: net.nodeB.n()}
   439  		message   = &Ping{ReqID: []byte("reqid")}
   440  	)
   441  	enc, _, err := net.nodeA.c.Encode(net.nodeB.id(), "", message, challenge)
   442  	if err != nil {
   443  		b.Fatal("can't encode handshake packet")
   444  	}
   445  	challenge.Node = nil // force ENR signature verification in decoder
   446  	b.ResetTimer()
   447  
   448  	input := make([]byte, len(enc))
   449  	for i := 0; i < b.N; i++ {
   450  		copy(input, enc)
   451  		net.nodeB.c.sc.storeSentHandshake(idA, "", challenge)
   452  		_, _, _, err := net.nodeB.c.Decode(input, "")
   453  		if err != nil {
   454  			b.Fatal(err)
   455  		}
   456  	}
   457  }
   458  
   459  // This benchmark checks how long it takes to decode an encrypted ping packet.
   460  func BenchmarkV5_DecodePing(b *testing.B) {
   461  	net := newHandshakeTest()
   462  	defer net.close()
   463  
   464  	session := &session{
   465  		readKey:  []byte{233, 203, 93, 195, 86, 47, 177, 186, 227, 43, 2, 141, 244, 230, 120, 17},
   466  		writeKey: []byte{79, 145, 252, 171, 167, 216, 252, 161, 208, 190, 176, 106, 214, 39, 178, 134},
   467  	}
   468  	net.nodeA.c.sc.storeNewSession(net.nodeB.id(), net.nodeB.addr(), session)
   469  	net.nodeB.c.sc.storeNewSession(net.nodeA.id(), net.nodeA.addr(), session.keysFlipped())
   470  	addrB := net.nodeA.addr()
   471  	ping := &Ping{ReqID: []byte("reqid"), ENRSeq: 5}
   472  	enc, _, err := net.nodeA.c.Encode(net.nodeB.id(), addrB, ping, nil)
   473  	if err != nil {
   474  		b.Fatalf("can't encode: %v", err)
   475  	}
   476  	b.ResetTimer()
   477  
   478  	input := make([]byte, len(enc))
   479  	for i := 0; i < b.N; i++ {
   480  		copy(input, enc)
   481  		_, _, packet, _ := net.nodeB.c.Decode(input, addrB)
   482  		if _, ok := packet.(*Ping); !ok {
   483  			b.Fatalf("wrong packet type %T", packet)
   484  		}
   485  	}
   486  }
   487  
   488  var pp = spew.NewDefaultConfig()
   489  
   490  type handshakeTest struct {
   491  	nodeA, nodeB handshakeTestNode
   492  	clock        mclock.Simulated
   493  }
   494  
   495  type handshakeTestNode struct {
   496  	ln *enode.LocalNode
   497  	c  *Codec
   498  }
   499  
   500  func newHandshakeTest() *handshakeTest {
   501  	t := new(handshakeTest)
   502  	t.nodeA.init(testKeyA, net.IP{127, 0, 0, 1}, &t.clock)
   503  	t.nodeB.init(testKeyB, net.IP{127, 0, 0, 1}, &t.clock)
   504  	return t
   505  }
   506  
   507  func (t *handshakeTest) close() {
   508  	t.nodeA.ln.Database().Close()
   509  	t.nodeB.ln.Database().Close()
   510  }
   511  
   512  func (n *handshakeTestNode) init(key *ecdsa.PrivateKey, ip net.IP, clock mclock.Clock) {
   513  	db, _ := enode.OpenDB("")
   514  	n.ln = enode.NewLocalNode(db, key)
   515  	n.ln.SetStaticIP(ip)
   516  	n.c = NewCodec(n.ln, key, clock)
   517  }
   518  
   519  func (n *handshakeTestNode) encode(t testing.TB, to handshakeTestNode, p Packet) ([]byte, Nonce) {
   520  	t.Helper()
   521  	return n.encodeWithChallenge(t, to, nil, p)
   522  }
   523  
   524  func (n *handshakeTestNode) encodeWithChallenge(t testing.TB, to handshakeTestNode, c *Whoareyou, p Packet) ([]byte, Nonce) {
   525  	t.Helper()
   526  
   527  	// Copy challenge and add destination node. This avoids sharing 'c' among the two codecs.
   528  	var challenge *Whoareyou
   529  	if c != nil {
   530  		challengeCopy := *c
   531  		challenge = &challengeCopy
   532  		challenge.Node = to.n()
   533  	}
   534  	// Encode to destination.
   535  	enc, nonce, err := n.c.Encode(to.id(), to.addr(), p, challenge)
   536  	if err != nil {
   537  		t.Fatal(fmt.Errorf("(%s) %v", n.ln.ID().TerminalString(), err))
   538  	}
   539  	t.Logf("(%s) -> (%s)   %s\n%s", n.ln.ID().TerminalString(), to.id().TerminalString(), p.Name(), hex.Dump(enc))
   540  	return enc, nonce
   541  }
   542  
   543  func (n *handshakeTestNode) expectDecode(t *testing.T, ptype byte, p []byte) Packet {
   544  	t.Helper()
   545  
   546  	dec, err := n.decode(p)
   547  	if err != nil {
   548  		t.Fatal(fmt.Errorf("(%s) %v", n.ln.ID().TerminalString(), err))
   549  	}
   550  	t.Logf("(%s) %#v", n.ln.ID().TerminalString(), pp.NewFormatter(dec))
   551  	if dec.Kind() != ptype {
   552  		t.Fatalf("expected packet type %d, got %d", ptype, dec.Kind())
   553  	}
   554  	return dec
   555  }
   556  
   557  func (n *handshakeTestNode) expectDecodeErr(t *testing.T, wantErr error, p []byte) {
   558  	t.Helper()
   559  	if _, err := n.decode(p); !errors.Is(err, wantErr) {
   560  		t.Fatal(fmt.Errorf("(%s) got err %q, want %q", n.ln.ID().TerminalString(), err, wantErr))
   561  	}
   562  }
   563  
   564  func (n *handshakeTestNode) decode(input []byte) (Packet, error) {
   565  	_, _, p, err := n.c.Decode(input, "127.0.0.1")
   566  	return p, err
   567  }
   568  
   569  func (n *handshakeTestNode) n() *enode.Node {
   570  	return n.ln.Node()
   571  }
   572  
   573  func (n *handshakeTestNode) addr() string {
   574  	return n.ln.Node().IP().String()
   575  }
   576  
   577  func (n *handshakeTestNode) id() enode.ID {
   578  	return n.ln.ID()
   579  }
   580  
   581  // hexFile reads the given file and decodes the hex data contained in it.
   582  // Whitespace and any lines beginning with the # character are ignored.
   583  func hexFile(file string) []byte {
   584  	fileContent, err := ioutil.ReadFile(file)
   585  	if err != nil {
   586  		panic(err)
   587  	}
   588  
   589  	// Gather hex data, ignore comments.
   590  	var text []byte
   591  	for _, line := range bytes.Split(fileContent, []byte("\n")) {
   592  		line = bytes.TrimSpace(line)
   593  		if len(line) > 0 && line[0] == '#' {
   594  			continue
   595  		}
   596  		text = append(text, line...)
   597  	}
   598  
   599  	// Parse the hex.
   600  	if bytes.HasPrefix(text, []byte("0x")) {
   601  		text = text[2:]
   602  	}
   603  	data := make([]byte, hex.DecodedLen(len(text)))
   604  	if _, err := hex.Decode(data, text); err != nil {
   605  		panic("invalid hex in " + file)
   606  	}
   607  	return data
   608  }
   609  
   610  // writeTestVector writes a test vector file with the given commentary and binary data.
   611  func writeTestVector(file, comment string, data []byte) {
   612  	fd, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
   613  	if err != nil {
   614  		panic(err)
   615  	}
   616  	defer fd.Close()
   617  
   618  	if len(comment) > 0 {
   619  		for _, line := range strings.Split(strings.TrimSpace(comment), "\n") {
   620  			fmt.Fprintf(fd, "# %s\n", line)
   621  		}
   622  		fmt.Fprintln(fd)
   623  	}
   624  	for len(data) > 0 {
   625  		var chunk []byte
   626  		if len(data) < 32 {
   627  			chunk = data
   628  		} else {
   629  			chunk = data[:32]
   630  		}
   631  		data = data[len(chunk):]
   632  		fmt.Fprintf(fd, "%x\n", chunk)
   633  	}
   634  }