| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | // Copyright 2021 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package ethtest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 18:14:39 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/eth/protocols/eth" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/internal/utesting" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-19 14:15:39 +00:00
										 |  |  | // Is_66 checks if the node supports the eth66 protocol version, | 
					
						
							|  |  |  | // and if not, exists the test suite | 
					
						
							|  |  |  | func (s *Suite) Is_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.dial66(t) | 
					
						
							|  |  |  | 	conn.handshake(t) | 
					
						
							|  |  |  | 	if conn.negotiatedProtoVersion < 66 { | 
					
						
							|  |  |  | 		t.Fail() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | // TestStatus_66 attempts to connect to the given node and exchange | 
					
						
							|  |  |  | // a status message with it on the eth66 protocol, and then check to | 
					
						
							|  |  |  | // make sure the chain head is correct. | 
					
						
							|  |  |  | func (s *Suite) TestStatus_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.dial66(t) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// get protoHandshake | 
					
						
							|  |  |  | 	conn.handshake(t) | 
					
						
							|  |  |  | 	// get status | 
					
						
							|  |  |  | 	switch msg := conn.statusExchange66(t, s.chain).(type) { | 
					
						
							|  |  |  | 	case *Status: | 
					
						
							|  |  |  | 		status := *msg | 
					
						
							|  |  |  | 		if status.ProtocolVersion != uint32(66) { | 
					
						
							|  |  |  | 			t.Fatalf("mismatch in version: wanted 66, got %d", status.ProtocolVersion) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		t.Logf("got status message: %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t.Fatalf("unexpected: %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestGetBlockHeaders_66 tests whether the given node can respond to | 
					
						
							|  |  |  | // an eth66 `GetBlockHeaders` request and that the response is accurate. | 
					
						
							|  |  |  | func (s *Suite) TestGetBlockHeaders_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.setupConnection66(t) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// get block headers | 
					
						
							|  |  |  | 	req := ð.GetBlockHeadersPacket66{ | 
					
						
							|  |  |  | 		RequestId: 3, | 
					
						
							|  |  |  | 		GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ | 
					
						
							|  |  |  | 			Origin: eth.HashOrNumber{ | 
					
						
							|  |  |  | 				Hash: s.chain.blocks[1].Hash(), | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Amount:  2, | 
					
						
							|  |  |  | 			Skip:    1, | 
					
						
							|  |  |  | 			Reverse: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// write message | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	headers, err := s.getBlockHeaders66(conn, req, req.RequestId) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not get block headers: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// check for correct headers | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	if !headersMatch(t, s.chain, headers) { | 
					
						
							|  |  |  | 		t.Fatal("received wrong header(s)") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestSimultaneousRequests_66 sends two simultaneous `GetBlockHeader` requests | 
					
						
							|  |  |  | // with different request IDs and checks to make sure the node responds with the correct | 
					
						
							|  |  |  | // headers per request. | 
					
						
							|  |  |  | func (s *Suite) TestSimultaneousRequests_66(t *utesting.T) { | 
					
						
							|  |  |  | 	// create two connections | 
					
						
							| 
									
										
										
										
											2021-05-05 12:27:27 +02:00
										 |  |  | 	conn := s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// create two requests | 
					
						
							|  |  |  | 	req1 := ð.GetBlockHeadersPacket66{ | 
					
						
							|  |  |  | 		RequestId: 111, | 
					
						
							|  |  |  | 		GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ | 
					
						
							|  |  |  | 			Origin: eth.HashOrNumber{ | 
					
						
							|  |  |  | 				Hash: s.chain.blocks[1].Hash(), | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Amount:  2, | 
					
						
							|  |  |  | 			Skip:    1, | 
					
						
							|  |  |  | 			Reverse: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	req2 := ð.GetBlockHeadersPacket66{ | 
					
						
							|  |  |  | 		RequestId: 222, | 
					
						
							|  |  |  | 		GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ | 
					
						
							|  |  |  | 			Origin: eth.HashOrNumber{ | 
					
						
							|  |  |  | 				Hash: s.chain.blocks[1].Hash(), | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Amount:  4, | 
					
						
							|  |  |  | 			Skip:    1, | 
					
						
							|  |  |  | 			Reverse: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-05 12:27:27 +02:00
										 |  |  | 	// write first request | 
					
						
							|  |  |  | 	if err := conn.write66(req1, GetBlockHeaders{}.Code()); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to write to connection: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// write second request | 
					
						
							|  |  |  | 	if err := conn.write66(req2, GetBlockHeaders{}.Code()); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to write to connection: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// wait for responses | 
					
						
							|  |  |  | 	headers1, err := s.waitForBlockHeadersResponse66(conn, req1.RequestId) | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:27:27 +02:00
										 |  |  | 		t.Fatalf("error while waiting for block headers: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	headers2, err := s.waitForBlockHeadersResponse66(conn, req2.RequestId) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("error while waiting for block headers: %v", err) | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-05 12:27:27 +02:00
										 |  |  | 	// check headers of both responses | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	if !headersMatch(t, s.chain, headers1) { | 
					
						
							| 
									
										
										
										
											2021-05-05 12:27:27 +02:00
										 |  |  | 		t.Fatalf("wrong header(s) in response to req1: got %v", headers1) | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-05 12:27:27 +02:00
										 |  |  | 	if !headersMatch(t, s.chain, headers2) { | 
					
						
							|  |  |  | 		t.Fatalf("wrong header(s) in response to req2: got %v", headers2) | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestBroadcast_66 tests whether a block announcement is correctly | 
					
						
							|  |  |  | // propagated to the given node's peer(s) on the eth66 protocol. | 
					
						
							|  |  |  | func (s *Suite) TestBroadcast_66(t *utesting.T) { | 
					
						
							| 
									
										
										
										
											2021-04-23 18:14:39 +02:00
										 |  |  | 	s.sendNextBlock66(t) | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestGetBlockBodies_66 tests whether the given node can respond to | 
					
						
							|  |  |  | // a `GetBlockBodies` request and that the response is accurate over | 
					
						
							|  |  |  | // the eth66 protocol. | 
					
						
							|  |  |  | func (s *Suite) TestGetBlockBodies_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.setupConnection66(t) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// create block bodies request | 
					
						
							|  |  |  | 	id := uint64(55) | 
					
						
							|  |  |  | 	req := ð.GetBlockBodiesPacket66{ | 
					
						
							|  |  |  | 		RequestId: id, | 
					
						
							|  |  |  | 		GetBlockBodiesPacket: eth.GetBlockBodiesPacket{ | 
					
						
							|  |  |  | 			s.chain.blocks[54].Hash(), | 
					
						
							|  |  |  | 			s.chain.blocks[75].Hash(), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := conn.write66(req, GetBlockBodies{}.Code()); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not write to connection: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	reqID, msg := conn.readAndServe66(s.chain, timeout) | 
					
						
							|  |  |  | 	switch msg := msg.(type) { | 
					
						
							|  |  |  | 	case BlockBodies: | 
					
						
							|  |  |  | 		if reqID != req.RequestId { | 
					
						
							|  |  |  | 			t.Fatalf("request ID mismatch: wanted %d, got %d", req.RequestId, reqID) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		t.Logf("received %d block bodies", len(msg)) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t.Fatalf("unexpected: %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestLargeAnnounce_66 tests the announcement mechanism with a large block. | 
					
						
							|  |  |  | func (s *Suite) TestLargeAnnounce_66(t *utesting.T) { | 
					
						
							|  |  |  | 	nextBlock := len(s.chain.blocks) | 
					
						
							|  |  |  | 	blocks := []*NewBlock{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Block: largeBlock(), | 
					
						
							|  |  |  | 			TD:    s.fullChain.TD(nextBlock + 1), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Block: s.fullChain.blocks[nextBlock], | 
					
						
							|  |  |  | 			TD:    largeNumber(2), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Block: largeBlock(), | 
					
						
							|  |  |  | 			TD:    largeNumber(2), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Block: s.fullChain.blocks[nextBlock], | 
					
						
							|  |  |  | 			TD:    s.fullChain.TD(nextBlock + 1), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, blockAnnouncement := range blocks[0:3] { | 
					
						
							|  |  |  | 		t.Logf("Testing malicious announcement: %v\n", i) | 
					
						
							|  |  |  | 		sendConn := s.setupConnection66(t) | 
					
						
							|  |  |  | 		if err := sendConn.Write(blockAnnouncement); err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("could not write to connection: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Invalid announcement, check that peer disconnected | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 		switch msg := sendConn.ReadAndServe(s.chain, time.Second*8).(type) { | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 		case *Disconnect: | 
					
						
							|  |  |  | 		case *Error: | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 		sendConn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Test the last block as a valid block | 
					
						
							| 
									
										
										
										
											2021-04-30 22:47:36 +02:00
										 |  |  | 	s.sendNextBlock66(t) | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 18:50:44 +00:00
										 |  |  | func (s *Suite) TestOldAnnounce_66(t *utesting.T) { | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	sendConn, recvConn := s.setupConnection66(t), s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer sendConn.Close() | 
					
						
							|  |  |  | 	defer recvConn.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s.oldAnnounce(t, sendConn, recvConn) | 
					
						
							| 
									
										
										
										
											2021-03-20 18:50:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | // TestMaliciousHandshake_66 tries to send malicious data during the handshake. | 
					
						
							|  |  |  | func (s *Suite) TestMaliciousHandshake_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.dial66(t) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// write hello to client | 
					
						
							|  |  |  | 	pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:] | 
					
						
							|  |  |  | 	handshakes := []*Hello{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Version: 5, | 
					
						
							|  |  |  | 			Caps: []p2p.Cap{ | 
					
						
							|  |  |  | 				{Name: largeString(2), Version: 66}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ID: pub0, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Version: 5, | 
					
						
							|  |  |  | 			Caps: []p2p.Cap{ | 
					
						
							|  |  |  | 				{Name: "eth", Version: 64}, | 
					
						
							|  |  |  | 				{Name: "eth", Version: 65}, | 
					
						
							|  |  |  | 				{Name: "eth", Version: 66}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ID: append(pub0, byte(0)), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Version: 5, | 
					
						
							|  |  |  | 			Caps: []p2p.Cap{ | 
					
						
							|  |  |  | 				{Name: "eth", Version: 64}, | 
					
						
							|  |  |  | 				{Name: "eth", Version: 65}, | 
					
						
							|  |  |  | 				{Name: "eth", Version: 66}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ID: append(pub0, pub0...), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Version: 5, | 
					
						
							|  |  |  | 			Caps: []p2p.Cap{ | 
					
						
							|  |  |  | 				{Name: "eth", Version: 64}, | 
					
						
							|  |  |  | 				{Name: "eth", Version: 65}, | 
					
						
							|  |  |  | 				{Name: "eth", Version: 66}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ID: largeBuffer(2), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Version: 5, | 
					
						
							|  |  |  | 			Caps: []p2p.Cap{ | 
					
						
							|  |  |  | 				{Name: largeString(2), Version: 66}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ID: largeBuffer(2), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for i, handshake := range handshakes { | 
					
						
							|  |  |  | 		t.Logf("Testing malicious handshake %v\n", i) | 
					
						
							|  |  |  | 		// Init the handshake | 
					
						
							|  |  |  | 		if err := conn.Write(handshake); err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("could not write to connection: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// check that the peer disconnected | 
					
						
							|  |  |  | 		timeout := 20 * time.Second | 
					
						
							|  |  |  | 		// Discard one hello | 
					
						
							|  |  |  | 		for i := 0; i < 2; i++ { | 
					
						
							|  |  |  | 			switch msg := conn.ReadAndServe(s.chain, timeout).(type) { | 
					
						
							|  |  |  | 			case *Disconnect: | 
					
						
							|  |  |  | 			case *Error: | 
					
						
							|  |  |  | 			case *Hello: | 
					
						
							|  |  |  | 				// Hello's are sent concurrently, so ignore them | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				t.Fatalf("unexpected: %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Dial for the next round | 
					
						
							|  |  |  | 		conn = s.dial66(t) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestMaliciousStatus_66 sends a status package with a large total difficulty. | 
					
						
							|  |  |  | func (s *Suite) TestMaliciousStatus_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.dial66(t) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	defer conn.Close() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	// get protoHandshake | 
					
						
							|  |  |  | 	conn.handshake(t) | 
					
						
							|  |  |  | 	status := &Status{ | 
					
						
							|  |  |  | 		ProtocolVersion: uint32(66), | 
					
						
							|  |  |  | 		NetworkID:       s.chain.chainConfig.ChainID.Uint64(), | 
					
						
							|  |  |  | 		TD:              largeNumber(2), | 
					
						
							|  |  |  | 		Head:            s.chain.blocks[s.chain.Len()-1].Hash(), | 
					
						
							|  |  |  | 		Genesis:         s.chain.blocks[0].Hash(), | 
					
						
							|  |  |  | 		ForkID:          s.chain.ForkID(), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// get status | 
					
						
							|  |  |  | 	switch msg := conn.statusExchange(t, s.chain, status).(type) { | 
					
						
							|  |  |  | 	case *Status: | 
					
						
							|  |  |  | 		t.Logf("%+v\n", msg) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t.Fatalf("expected status, got: %#v ", msg) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// wait for disconnect | 
					
						
							|  |  |  | 	switch msg := conn.ReadAndServe(s.chain, timeout).(type) { | 
					
						
							|  |  |  | 	case *Disconnect: | 
					
						
							|  |  |  | 	case *Error: | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t.Fatalf("expected disconnect, got: %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *Suite) TestTransaction_66(t *utesting.T) { | 
					
						
							|  |  |  | 	tests := []*types.Transaction{ | 
					
						
							|  |  |  | 		getNextTxFromChain(t, s), | 
					
						
							|  |  |  | 		unknownTx(t, s), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for i, tx := range tests { | 
					
						
							|  |  |  | 		t.Logf("Testing tx propagation: %v\n", i) | 
					
						
							|  |  |  | 		sendSuccessfulTx66(t, s, tx) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *Suite) TestMaliciousTx_66(t *utesting.T) { | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	badTxs := []*types.Transaction{ | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 		getOldTxFromChain(t, s), | 
					
						
							|  |  |  | 		invalidNonceTx(t, s), | 
					
						
							|  |  |  | 		hugeAmount(t, s), | 
					
						
							|  |  |  | 		hugeGasPrice(t, s), | 
					
						
							|  |  |  | 		hugeData(t, s), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	sendConn := s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer sendConn.Close() | 
					
						
							|  |  |  | 	// set up receiving connection before sending txs to make sure | 
					
						
							|  |  |  | 	// no announcements are missed | 
					
						
							|  |  |  | 	recvConn := s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer recvConn.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, tx := range badTxs { | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 		t.Logf("Testing malicious tx propagation: %v\n", i) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 		if err := sendConn.Write(&Transactions{tx}); err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("could not write to connection: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	// check to make sure bad txs aren't propagated | 
					
						
							|  |  |  | 	waitForTxPropagation(t, s, badTxs, recvConn) | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestZeroRequestID_66 checks that a request ID of zero is still handled | 
					
						
							|  |  |  | // by the node. | 
					
						
							|  |  |  | func (s *Suite) TestZeroRequestID_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.setupConnection66(t) | 
					
						
							| 
									
										
										
										
											2021-04-23 11:15:42 +02:00
										 |  |  | 	defer conn.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	req := ð.GetBlockHeadersPacket66{ | 
					
						
							|  |  |  | 		RequestId: 0, | 
					
						
							|  |  |  | 		GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ | 
					
						
							|  |  |  | 			Origin: eth.HashOrNumber{ | 
					
						
							|  |  |  | 				Number: 0, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Amount: 2, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	headers, err := s.getBlockHeaders66(conn, req, req.RequestId) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not get block headers: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !headersMatch(t, s.chain, headers) { | 
					
						
							|  |  |  | 		t.Fatal("received wrong header(s)") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestSameRequestID_66 sends two requests with the same request ID | 
					
						
							|  |  |  | // concurrently to a single node. | 
					
						
							|  |  |  | func (s *Suite) TestSameRequestID_66(t *utesting.T) { | 
					
						
							|  |  |  | 	conn := s.setupConnection66(t) | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	// create two requests with the same request ID | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 	reqID := uint64(1234) | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	request1 := ð.GetBlockHeadersPacket66{ | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 		RequestId: reqID, | 
					
						
							|  |  |  | 		GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ | 
					
						
							|  |  |  | 			Origin: eth.HashOrNumber{ | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 				Number: 1, | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			Amount: 2, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	request2 := ð.GetBlockHeadersPacket66{ | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | 		RequestId: reqID, | 
					
						
							|  |  |  | 		GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ | 
					
						
							|  |  |  | 			Origin: eth.HashOrNumber{ | 
					
						
							|  |  |  | 				Number: 33, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Amount: 2, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-28 21:38:38 +02:00
										 |  |  | 	// write the first request | 
					
						
							|  |  |  | 	err := conn.write66(request1, GetBlockHeaders{}.Code()) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not write to connection: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// perform second request | 
					
						
							|  |  |  | 	headers2, err := s.getBlockHeaders66(conn, request2, reqID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not get block headers: %v", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// wait for response to first request | 
					
						
							|  |  |  | 	headers1, err := s.waitForBlockHeadersResponse66(conn, reqID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not get BlockHeaders response: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// check if headers match | 
					
						
							|  |  |  | 	if !headersMatch(t, s.chain, headers1) || !headersMatch(t, s.chain, headers2) { | 
					
						
							|  |  |  | 		t.Fatal("received wrong header(s)") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-25 18:36:01 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-04-23 18:14:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // TestLargeTxRequest_66 tests whether a node can fulfill a large GetPooledTransactions | 
					
						
							|  |  |  | // request. | 
					
						
							|  |  |  | func (s *Suite) TestLargeTxRequest_66(t *utesting.T) { | 
					
						
							|  |  |  | 	// send the next block to ensure the node is no longer syncing and is able to accept | 
					
						
							|  |  |  | 	// txs | 
					
						
							|  |  |  | 	s.sendNextBlock66(t) | 
					
						
							|  |  |  | 	// send 2000 transactions to the node | 
					
						
							|  |  |  | 	hashMap, txs := generateTxs(t, s, 2000) | 
					
						
							|  |  |  | 	sendConn := s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer sendConn.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sendMultipleSuccessfulTxs(t, s, sendConn, txs) | 
					
						
							|  |  |  | 	// set up connection to receive to ensure node is peered with the receiving connection | 
					
						
							|  |  |  | 	// before tx request is sent | 
					
						
							|  |  |  | 	recvConn := s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer recvConn.Close() | 
					
						
							|  |  |  | 	// create and send pooled tx request | 
					
						
							|  |  |  | 	hashes := make([]common.Hash, 0) | 
					
						
							|  |  |  | 	for _, hash := range hashMap { | 
					
						
							|  |  |  | 		hashes = append(hashes, hash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	getTxReq := ð.GetPooledTransactionsPacket66{ | 
					
						
							|  |  |  | 		RequestId:                   1234, | 
					
						
							|  |  |  | 		GetPooledTransactionsPacket: hashes, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := recvConn.write66(getTxReq, GetPooledTransactions{}.Code()); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not write to conn: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// check that all received transactions match those that were sent to node | 
					
						
							|  |  |  | 	switch msg := recvConn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) { | 
					
						
							|  |  |  | 	case PooledTransactions: | 
					
						
							|  |  |  | 		for _, gotTx := range msg { | 
					
						
							|  |  |  | 			if _, exists := hashMap[gotTx.Hash()]; !exists { | 
					
						
							|  |  |  | 				t.Fatalf("unexpected tx received: %v", gotTx.Hash()) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t.Fatalf("unexpected %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TestNewPooledTxs_66 tests whether a node will do a GetPooledTransactions | 
					
						
							|  |  |  | // request upon receiving a NewPooledTransactionHashes announcement. | 
					
						
							|  |  |  | func (s *Suite) TestNewPooledTxs_66(t *utesting.T) { | 
					
						
							|  |  |  | 	// send the next block to ensure the node is no longer syncing and is able to accept | 
					
						
							|  |  |  | 	// txs | 
					
						
							|  |  |  | 	s.sendNextBlock66(t) | 
					
						
							|  |  |  | 	// generate 50 txs | 
					
						
							|  |  |  | 	hashMap, _ := generateTxs(t, s, 50) | 
					
						
							|  |  |  | 	// create new pooled tx hashes announcement | 
					
						
							|  |  |  | 	hashes := make([]common.Hash, 0) | 
					
						
							|  |  |  | 	for _, hash := range hashMap { | 
					
						
							|  |  |  | 		hashes = append(hashes, hash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	announce := NewPooledTransactionHashes(hashes) | 
					
						
							|  |  |  | 	// send announcement | 
					
						
							|  |  |  | 	conn := s.setupConnection66(t) | 
					
						
							|  |  |  | 	defer conn.Close() | 
					
						
							|  |  |  | 	if err := conn.Write(announce); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("could not write to connection: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// wait for GetPooledTxs request | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		_, msg := conn.readAndServe66(s.chain, timeout) | 
					
						
							|  |  |  | 		switch msg := msg.(type) { | 
					
						
							|  |  |  | 		case GetPooledTransactions: | 
					
						
							|  |  |  | 			if len(msg) != len(hashes) { | 
					
						
							|  |  |  | 				t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return | 
					
						
							| 
									
										
										
										
											2021-04-28 08:48:07 +02:00
										 |  |  | 		case *NewPooledTransactionHashes, *NewBlock, *NewBlockHashes: | 
					
						
							|  |  |  | 			// ignore propagated txs and blocks from old tests | 
					
						
							| 
									
										
										
										
											2021-04-23 18:14:39 +02:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			t.Fatalf("unexpected %s", pretty.Sdump(msg)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |