|
|
|
@ -49,79 +49,30 @@ func NewSuite(dest *enode.Node, chainfile string, genesisfile string) (*Suite, e |
|
|
|
|
}, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Suite) AllEthTests() []utesting.Test { |
|
|
|
|
func (s *Suite) EthTests() []utesting.Test { |
|
|
|
|
return []utesting.Test{ |
|
|
|
|
// status
|
|
|
|
|
{Name: "TestStatus65", Fn: s.TestStatus65}, |
|
|
|
|
{Name: "TestStatus66", Fn: s.TestStatus66}, |
|
|
|
|
{Name: "TestStatus", Fn: s.TestStatus}, |
|
|
|
|
// get block headers
|
|
|
|
|
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65}, |
|
|
|
|
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66}, |
|
|
|
|
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66}, |
|
|
|
|
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66}, |
|
|
|
|
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66}, |
|
|
|
|
{Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders}, |
|
|
|
|
{Name: "TestSimultaneousRequests", Fn: s.TestSimultaneousRequests}, |
|
|
|
|
{Name: "TestSameRequestID", Fn: s.TestSameRequestID}, |
|
|
|
|
{Name: "TestZeroRequestID", Fn: s.TestZeroRequestID}, |
|
|
|
|
// get block bodies
|
|
|
|
|
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65}, |
|
|
|
|
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66}, |
|
|
|
|
{Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies}, |
|
|
|
|
// broadcast
|
|
|
|
|
{Name: "TestBroadcast65", Fn: s.TestBroadcast65}, |
|
|
|
|
{Name: "TestBroadcast66", Fn: s.TestBroadcast66}, |
|
|
|
|
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65}, |
|
|
|
|
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66}, |
|
|
|
|
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65}, |
|
|
|
|
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66}, |
|
|
|
|
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65}, |
|
|
|
|
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66}, |
|
|
|
|
{Name: "TestBroadcast", Fn: s.TestBroadcast}, |
|
|
|
|
{Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce}, |
|
|
|
|
{Name: "TestOldAnnounce", Fn: s.TestOldAnnounce}, |
|
|
|
|
{Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce}, |
|
|
|
|
// malicious handshakes + status
|
|
|
|
|
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65}, |
|
|
|
|
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65}, |
|
|
|
|
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66}, |
|
|
|
|
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66}, |
|
|
|
|
{Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake}, |
|
|
|
|
{Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus}, |
|
|
|
|
// test transactions
|
|
|
|
|
{Name: "TestTransaction65", Fn: s.TestTransaction65}, |
|
|
|
|
{Name: "TestTransaction66", Fn: s.TestTransaction66}, |
|
|
|
|
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65}, |
|
|
|
|
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66}, |
|
|
|
|
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66}, |
|
|
|
|
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Suite) EthTests() []utesting.Test { |
|
|
|
|
return []utesting.Test{ |
|
|
|
|
{Name: "TestStatus65", Fn: s.TestStatus65}, |
|
|
|
|
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65}, |
|
|
|
|
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65}, |
|
|
|
|
{Name: "TestBroadcast65", Fn: s.TestBroadcast65}, |
|
|
|
|
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65}, |
|
|
|
|
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65}, |
|
|
|
|
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65}, |
|
|
|
|
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65}, |
|
|
|
|
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65}, |
|
|
|
|
{Name: "TestTransaction65", Fn: s.TestTransaction65}, |
|
|
|
|
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (s *Suite) Eth66Tests() []utesting.Test { |
|
|
|
|
return []utesting.Test{ |
|
|
|
|
// only proceed with eth66 test suite if node supports eth 66 protocol
|
|
|
|
|
{Name: "TestStatus66", Fn: s.TestStatus66}, |
|
|
|
|
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66}, |
|
|
|
|
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66}, |
|
|
|
|
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66}, |
|
|
|
|
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66}, |
|
|
|
|
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66}, |
|
|
|
|
{Name: "TestBroadcast66", Fn: s.TestBroadcast66}, |
|
|
|
|
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66}, |
|
|
|
|
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66}, |
|
|
|
|
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66}, |
|
|
|
|
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66}, |
|
|
|
|
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66}, |
|
|
|
|
{Name: "TestTransaction66", Fn: s.TestTransaction66}, |
|
|
|
|
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66}, |
|
|
|
|
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66}, |
|
|
|
|
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66}, |
|
|
|
|
{Name: "TestTransaction", Fn: s.TestTransaction}, |
|
|
|
|
{Name: "TestMaliciousTx", Fn: s.TestMaliciousTx}, |
|
|
|
|
{Name: "TestLargeTxRequest", Fn: s.TestLargeTxRequest}, |
|
|
|
|
{Name: "TestNewPooledTxs", Fn: s.TestNewPooledTxs}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -135,14 +86,9 @@ func (s *Suite) SnapTests() []utesting.Test { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
eth66 = true // indicates whether suite should negotiate eth66 connection
|
|
|
|
|
eth65 = false // indicates whether suite should negotiate eth65 connection or below.
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// TestStatus65 attempts to connect to the given node and exchange
|
|
|
|
|
// a status message with it.
|
|
|
|
|
func (s *Suite) TestStatus65(t *utesting.T) { |
|
|
|
|
// TestStatus attempts to connect to the given node and exchange
|
|
|
|
|
// a status message with it on the eth protocol.
|
|
|
|
|
func (s *Suite) TestStatus(t *utesting.T) { |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
@ -153,79 +99,32 @@ func (s *Suite) TestStatus65(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestStatus66 attempts to connect to the given node and exchange
|
|
|
|
|
// a status message with it on the eth66 protocol.
|
|
|
|
|
func (s *Suite) TestStatus66(t *utesting.T) { |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
|
defer conn.Close() |
|
|
|
|
if err := conn.peer(s.chain, nil); err != nil { |
|
|
|
|
t.Fatalf("peering failed: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestGetBlockHeaders65 tests whether the given node can respond to
|
|
|
|
|
// a `GetBlockHeaders` request accurately.
|
|
|
|
|
func (s *Suite) TestGetBlockHeaders65(t *utesting.T) { |
|
|
|
|
// TestGetBlockHeaders tests whether the given node can respond to
|
|
|
|
|
// an eth `GetBlockHeaders` request and that the response is accurate.
|
|
|
|
|
func (s *Suite) TestGetBlockHeaders(t *utesting.T) { |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
|
defer conn.Close() |
|
|
|
|
if err := conn.peer(s.chain, nil); err != nil { |
|
|
|
|
t.Fatalf("handshake(s) failed: %v", err) |
|
|
|
|
} |
|
|
|
|
// write request
|
|
|
|
|
req := &GetBlockHeaders{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
|
Hash: s.chain.blocks[1].Hash(), |
|
|
|
|
}, |
|
|
|
|
Amount: 2, |
|
|
|
|
Skip: 1, |
|
|
|
|
Reverse: false, |
|
|
|
|
} |
|
|
|
|
headers, err := conn.headersRequest(req, s.chain, eth65, 0) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("GetBlockHeaders request failed: %v", err) |
|
|
|
|
} |
|
|
|
|
// check for correct headers
|
|
|
|
|
expected, err := s.chain.GetHeaders(*req) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get headers for given request: %v", err) |
|
|
|
|
} |
|
|
|
|
if !headersMatch(expected, headers) { |
|
|
|
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestGetBlockHeaders66 tests whether the given node can respond to
|
|
|
|
|
// an eth66 `GetBlockHeaders` request and that the response is accurate.
|
|
|
|
|
func (s *Suite) TestGetBlockHeaders66(t *utesting.T) { |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
|
defer conn.Close() |
|
|
|
|
if err = conn.peer(s.chain, nil); err != nil { |
|
|
|
|
t.Fatalf("peering failed: %v", err) |
|
|
|
|
} |
|
|
|
|
// write request
|
|
|
|
|
req := &GetBlockHeaders{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
|
Hash: s.chain.blocks[1].Hash(), |
|
|
|
|
}, |
|
|
|
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ |
|
|
|
|
Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()}, |
|
|
|
|
Amount: 2, |
|
|
|
|
Skip: 1, |
|
|
|
|
Reverse: false, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
headers, err := conn.headersRequest(req, s.chain, eth66, 33) |
|
|
|
|
headers, err := conn.headersRequest(req, s.chain, 33) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("could not get block headers: %v", err) |
|
|
|
|
} |
|
|
|
|
// check for correct headers
|
|
|
|
|
expected, err := s.chain.GetHeaders(*req) |
|
|
|
|
expected, err := s.chain.GetHeaders(req) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get headers for given request: %v", err) |
|
|
|
|
} |
|
|
|
@ -234,12 +133,12 @@ func (s *Suite) TestGetBlockHeaders66(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestSimultaneousRequests66 sends two simultaneous `GetBlockHeader` requests from
|
|
|
|
|
// TestSimultaneousRequests sends two simultaneous `GetBlockHeader` requests from
|
|
|
|
|
// the same connection with different request IDs and checks to make sure the node
|
|
|
|
|
// responds with the correct headers per request.
|
|
|
|
|
func (s *Suite) TestSimultaneousRequests66(t *utesting.T) { |
|
|
|
|
func (s *Suite) TestSimultaneousRequests(t *utesting.T) { |
|
|
|
|
// create a connection
|
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
@ -247,8 +146,9 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) { |
|
|
|
|
if err := conn.peer(s.chain, nil); err != nil { |
|
|
|
|
t.Fatalf("peering failed: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// create two requests
|
|
|
|
|
req1 := ð.GetBlockHeadersPacket66{ |
|
|
|
|
req1 := &GetBlockHeaders{ |
|
|
|
|
RequestId: uint64(111), |
|
|
|
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
@ -259,7 +159,7 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) { |
|
|
|
|
Reverse: false, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
req2 := ð.GetBlockHeadersPacket66{ |
|
|
|
|
req2 := &GetBlockHeaders{ |
|
|
|
|
RequestId: uint64(222), |
|
|
|
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
@ -270,46 +170,49 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) { |
|
|
|
|
Reverse: false, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// write the first request
|
|
|
|
|
if err := conn.Write66(req1, GetBlockHeaders{}.Code()); err != nil { |
|
|
|
|
if err := conn.Write(req1); err != nil { |
|
|
|
|
t.Fatalf("failed to write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
// write the second request
|
|
|
|
|
if err := conn.Write66(req2, GetBlockHeaders{}.Code()); err != nil { |
|
|
|
|
if err := conn.Write(req2); err != nil { |
|
|
|
|
t.Fatalf("failed to write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// wait for responses
|
|
|
|
|
msg := conn.waitForResponse(s.chain, timeout, req1.RequestId) |
|
|
|
|
headers1, ok := msg.(BlockHeaders) |
|
|
|
|
headers1, ok := msg.(*BlockHeaders) |
|
|
|
|
if !ok { |
|
|
|
|
t.Fatalf("unexpected %s", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
msg = conn.waitForResponse(s.chain, timeout, req2.RequestId) |
|
|
|
|
headers2, ok := msg.(BlockHeaders) |
|
|
|
|
headers2, ok := msg.(*BlockHeaders) |
|
|
|
|
if !ok { |
|
|
|
|
t.Fatalf("unexpected %s", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// check received headers for accuracy
|
|
|
|
|
expected1, err := s.chain.GetHeaders(GetBlockHeaders(*req1.GetBlockHeadersPacket)) |
|
|
|
|
expected1, err := s.chain.GetHeaders(req1) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get expected headers for request 1: %v", err) |
|
|
|
|
} |
|
|
|
|
expected2, err := s.chain.GetHeaders(GetBlockHeaders(*req2.GetBlockHeadersPacket)) |
|
|
|
|
expected2, err := s.chain.GetHeaders(req2) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get expected headers for request 2: %v", err) |
|
|
|
|
} |
|
|
|
|
if !headersMatch(expected1, headers1) { |
|
|
|
|
if !headersMatch(expected1, headers1.BlockHeadersPacket) { |
|
|
|
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) |
|
|
|
|
} |
|
|
|
|
if !headersMatch(expected2, headers2) { |
|
|
|
|
if !headersMatch(expected2, headers2.BlockHeadersPacket) { |
|
|
|
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestSameRequestID66 sends two requests with the same request ID to a
|
|
|
|
|
// TestSameRequestID sends two requests with the same request ID to a
|
|
|
|
|
// single node.
|
|
|
|
|
func (s *Suite) TestSameRequestID66(t *utesting.T) { |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
func (s *Suite) TestSameRequestID(t *utesting.T) { |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
@ -319,7 +222,7 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
// create requests
|
|
|
|
|
reqID := uint64(1234) |
|
|
|
|
request1 := ð.GetBlockHeadersPacket66{ |
|
|
|
|
request1 := &GetBlockHeaders{ |
|
|
|
|
RequestId: reqID, |
|
|
|
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
@ -328,7 +231,7 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) { |
|
|
|
|
Amount: 2, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
request2 := ð.GetBlockHeadersPacket66{ |
|
|
|
|
request2 := &GetBlockHeaders{ |
|
|
|
|
RequestId: reqID, |
|
|
|
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
@ -337,45 +240,48 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) { |
|
|
|
|
Amount: 2, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// write the requests
|
|
|
|
|
if err = conn.Write66(request1, GetBlockHeaders{}.Code()); err != nil { |
|
|
|
|
if err = conn.Write(request1); err != nil { |
|
|
|
|
t.Fatalf("failed to write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
if err = conn.Write66(request2, GetBlockHeaders{}.Code()); err != nil { |
|
|
|
|
if err = conn.Write(request2); err != nil { |
|
|
|
|
t.Fatalf("failed to write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// wait for responses
|
|
|
|
|
msg := conn.waitForResponse(s.chain, timeout, reqID) |
|
|
|
|
headers1, ok := msg.(BlockHeaders) |
|
|
|
|
headers1, ok := msg.(*BlockHeaders) |
|
|
|
|
if !ok { |
|
|
|
|
t.Fatalf("unexpected %s", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
msg = conn.waitForResponse(s.chain, timeout, reqID) |
|
|
|
|
headers2, ok := msg.(BlockHeaders) |
|
|
|
|
headers2, ok := msg.(*BlockHeaders) |
|
|
|
|
if !ok { |
|
|
|
|
t.Fatalf("unexpected %s", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// check if headers match
|
|
|
|
|
expected1, err := s.chain.GetHeaders(GetBlockHeaders(*request1.GetBlockHeadersPacket)) |
|
|
|
|
expected1, err := s.chain.GetHeaders(request1) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get expected block headers: %v", err) |
|
|
|
|
} |
|
|
|
|
expected2, err := s.chain.GetHeaders(GetBlockHeaders(*request2.GetBlockHeadersPacket)) |
|
|
|
|
expected2, err := s.chain.GetHeaders(request2) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get expected block headers: %v", err) |
|
|
|
|
} |
|
|
|
|
if !headersMatch(expected1, headers1) { |
|
|
|
|
if !headersMatch(expected1, headers1.BlockHeadersPacket) { |
|
|
|
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) |
|
|
|
|
} |
|
|
|
|
if !headersMatch(expected2, headers2) { |
|
|
|
|
if !headersMatch(expected2, headers2.BlockHeadersPacket) { |
|
|
|
|
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestZeroRequestID_66 checks that a message with a request ID of zero is still handled
|
|
|
|
|
// TestZeroRequestID checks that a message with a request ID of zero is still handled
|
|
|
|
|
// by the node.
|
|
|
|
|
func (s *Suite) TestZeroRequestID66(t *utesting.T) { |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
func (s *Suite) TestZeroRequestID(t *utesting.T) { |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
@ -384,16 +290,16 @@ func (s *Suite) TestZeroRequestID66(t *utesting.T) { |
|
|
|
|
t.Fatalf("peering failed: %v", err) |
|
|
|
|
} |
|
|
|
|
req := &GetBlockHeaders{ |
|
|
|
|
Origin: eth.HashOrNumber{ |
|
|
|
|
Number: 0, |
|
|
|
|
}, |
|
|
|
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ |
|
|
|
|
Origin: eth.HashOrNumber{Number: 0}, |
|
|
|
|
Amount: 2, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
headers, err := conn.headersRequest(req, s.chain, eth66, 0) |
|
|
|
|
headers, err := conn.headersRequest(req, s.chain, 0) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get block headers: %v", err) |
|
|
|
|
} |
|
|
|
|
expected, err := s.chain.GetHeaders(*req) |
|
|
|
|
expected, err := s.chain.GetHeaders(req) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to get expected block headers: %v", err) |
|
|
|
|
} |
|
|
|
@ -402,9 +308,9 @@ func (s *Suite) TestZeroRequestID66(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestGetBlockBodies65 tests whether the given node can respond to
|
|
|
|
|
// TestGetBlockBodies tests whether the given node can respond to
|
|
|
|
|
// a `GetBlockBodies` request and that the response is accurate.
|
|
|
|
|
func (s *Suite) TestGetBlockBodies65(t *utesting.T) { |
|
|
|
|
func (s *Suite) TestGetBlockBodies(t *utesting.T) { |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
@ -415,126 +321,39 @@ func (s *Suite) TestGetBlockBodies65(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
// create block bodies request
|
|
|
|
|
req := &GetBlockBodies{ |
|
|
|
|
s.chain.blocks[54].Hash(), |
|
|
|
|
s.chain.blocks[75].Hash(), |
|
|
|
|
} |
|
|
|
|
if err := conn.Write(req); err != nil { |
|
|
|
|
t.Fatalf("could not write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
// wait for response
|
|
|
|
|
switch msg := conn.readAndServe(s.chain, timeout).(type) { |
|
|
|
|
case *BlockBodies: |
|
|
|
|
t.Logf("received %d block bodies", len(*msg)) |
|
|
|
|
if len(*msg) != len(*req) { |
|
|
|
|
t.Fatalf("wrong bodies in response: expected %d bodies, "+ |
|
|
|
|
"got %d", len(*req), len(*msg)) |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
|
t.Fatalf("unexpected: %s", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestGetBlockBodies66 tests whether the given node can respond to
|
|
|
|
|
// a `GetBlockBodies` request and that the response is accurate over
|
|
|
|
|
// the eth66 protocol.
|
|
|
|
|
func (s *Suite) TestGetBlockBodies66(t *utesting.T) { |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
|
defer conn.Close() |
|
|
|
|
if err := conn.peer(s.chain, nil); err != nil { |
|
|
|
|
t.Fatalf("peering failed: %v", err) |
|
|
|
|
} |
|
|
|
|
// create block bodies request
|
|
|
|
|
req := ð.GetBlockBodiesPacket66{ |
|
|
|
|
RequestId: uint64(55), |
|
|
|
|
GetBlockBodiesPacket: eth.GetBlockBodiesPacket{ |
|
|
|
|
s.chain.blocks[54].Hash(), |
|
|
|
|
s.chain.blocks[75].Hash(), |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
if err := conn.Write66(req, GetBlockBodies{}.Code()); err != nil { |
|
|
|
|
if err := conn.Write(req); err != nil { |
|
|
|
|
t.Fatalf("could not write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
// wait for block bodies response
|
|
|
|
|
msg := conn.waitForResponse(s.chain, timeout, req.RequestId) |
|
|
|
|
blockBodies, ok := msg.(BlockBodies) |
|
|
|
|
resp, ok := msg.(*BlockBodies) |
|
|
|
|
if !ok { |
|
|
|
|
t.Fatalf("unexpected: %s", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
t.Logf("received %d block bodies", len(blockBodies)) |
|
|
|
|
if len(blockBodies) != len(req.GetBlockBodiesPacket) { |
|
|
|
|
bodies := resp.BlockBodiesPacket |
|
|
|
|
t.Logf("received %d block bodies", len(bodies)) |
|
|
|
|
if len(bodies) != len(req.GetBlockBodiesPacket) { |
|
|
|
|
t.Fatalf("wrong bodies in response: expected %d bodies, "+ |
|
|
|
|
"got %d", len(req.GetBlockBodiesPacket), len(blockBodies)) |
|
|
|
|
"got %d", len(req.GetBlockBodiesPacket), len(bodies)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestBroadcast65 tests whether a block announcement is correctly
|
|
|
|
|
// propagated to the given node's peer(s).
|
|
|
|
|
func (s *Suite) TestBroadcast65(t *utesting.T) { |
|
|
|
|
if err := s.sendNextBlock(eth65); err != nil { |
|
|
|
|
// TestBroadcast tests whether a block announcement is correctly
|
|
|
|
|
// propagated to the node's peers.
|
|
|
|
|
func (s *Suite) TestBroadcast(t *utesting.T) { |
|
|
|
|
if err := s.sendNextBlock(); err != nil { |
|
|
|
|
t.Fatalf("block broadcast failed: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestBroadcast66 tests whether a block announcement is correctly
|
|
|
|
|
// propagated to the given node's peer(s) on the eth66 protocol.
|
|
|
|
|
func (s *Suite) TestBroadcast66(t *utesting.T) { |
|
|
|
|
if err := s.sendNextBlock(eth66); err != nil { |
|
|
|
|
t.Fatalf("block broadcast failed: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestLargeAnnounce65 tests the announcement mechanism with a large block.
|
|
|
|
|
func (s *Suite) TestLargeAnnounce65(t *utesting.T) { |
|
|
|
|
nextBlock := len(s.chain.blocks) |
|
|
|
|
blocks := []*NewBlock{ |
|
|
|
|
{ |
|
|
|
|
Block: largeBlock(), |
|
|
|
|
TD: s.fullChain.TotalDifficultyAt(nextBlock), |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Block: s.fullChain.blocks[nextBlock], |
|
|
|
|
TD: largeNumber(2), |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Block: largeBlock(), |
|
|
|
|
TD: largeNumber(2), |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for i, blockAnnouncement := range blocks { |
|
|
|
|
t.Logf("Testing malicious announcement: %v\n", i) |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err = conn.peer(s.chain, nil); err != nil { |
|
|
|
|
t.Fatalf("peering failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err = conn.Write(blockAnnouncement); err != nil { |
|
|
|
|
t.Fatalf("could not write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
// Invalid announcement, check that peer disconnected
|
|
|
|
|
switch msg := conn.readAndServe(s.chain, time.Second*8).(type) { |
|
|
|
|
case *Disconnect: |
|
|
|
|
case *Error: |
|
|
|
|
break |
|
|
|
|
default: |
|
|
|
|
t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg)) |
|
|
|
|
} |
|
|
|
|
conn.Close() |
|
|
|
|
} |
|
|
|
|
// Test the last block as a valid block
|
|
|
|
|
if err := s.sendNextBlock(eth65); err != nil { |
|
|
|
|
t.Fatalf("failed to broadcast next block: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestLargeAnnounce66 tests the announcement mechanism with a large
|
|
|
|
|
// block over the eth66 protocol.
|
|
|
|
|
func (s *Suite) TestLargeAnnounce66(t *utesting.T) { |
|
|
|
|
// TestLargeAnnounce tests the announcement mechanism with a large block.
|
|
|
|
|
func (s *Suite) TestLargeAnnounce(t *utesting.T) { |
|
|
|
|
nextBlock := len(s.chain.blocks) |
|
|
|
|
blocks := []*NewBlock{ |
|
|
|
|
{ |
|
|
|
@ -553,7 +372,7 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) { |
|
|
|
|
|
|
|
|
|
for i, blockAnnouncement := range blocks[0:3] { |
|
|
|
|
t.Logf("Testing malicious announcement: %v\n", i) |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
@ -564,7 +383,7 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) { |
|
|
|
|
t.Fatalf("could not write to connection: %v", err) |
|
|
|
|
} |
|
|
|
|
// Invalid announcement, check that peer disconnected
|
|
|
|
|
switch msg := conn.readAndServe(s.chain, time.Second*8).(type) { |
|
|
|
|
switch msg := conn.readAndServe(s.chain, 8*time.Second).(type) { |
|
|
|
|
case *Disconnect: |
|
|
|
|
case *Error: |
|
|
|
|
break |
|
|
|
@ -574,58 +393,35 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) { |
|
|
|
|
conn.Close() |
|
|
|
|
} |
|
|
|
|
// Test the last block as a valid block
|
|
|
|
|
if err := s.sendNextBlock(eth66); err != nil { |
|
|
|
|
if err := s.sendNextBlock(); err != nil { |
|
|
|
|
t.Fatalf("failed to broadcast next block: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestOldAnnounce65 tests the announcement mechanism with an old block.
|
|
|
|
|
func (s *Suite) TestOldAnnounce65(t *utesting.T) { |
|
|
|
|
if err := s.oldAnnounce(eth65); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestOldAnnounce66 tests the announcement mechanism with an old block,
|
|
|
|
|
// over the eth66 protocol.
|
|
|
|
|
func (s *Suite) TestOldAnnounce66(t *utesting.T) { |
|
|
|
|
if err := s.oldAnnounce(eth66); err != nil { |
|
|
|
|
// TestOldAnnounce tests the announcement mechanism with an old block.
|
|
|
|
|
func (s *Suite) TestOldAnnounce(t *utesting.T) { |
|
|
|
|
if err := s.oldAnnounce(); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestBlockHashAnnounce65 sends a new block hash announcement and expects
|
|
|
|
|
// TestBlockHashAnnounce sends a new block hash announcement and expects
|
|
|
|
|
// the node to perform a `GetBlockHeaders` request.
|
|
|
|
|
func (s *Suite) TestBlockHashAnnounce65(t *utesting.T) { |
|
|
|
|
if err := s.hashAnnounce(eth65); err != nil { |
|
|
|
|
func (s *Suite) TestBlockHashAnnounce(t *utesting.T) { |
|
|
|
|
if err := s.hashAnnounce(); err != nil { |
|
|
|
|
t.Fatalf("block hash announcement failed: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestBlockHashAnnounce66 sends a new block hash announcement and expects
|
|
|
|
|
// the node to perform a `GetBlockHeaders` request.
|
|
|
|
|
func (s *Suite) TestBlockHashAnnounce66(t *utesting.T) { |
|
|
|
|
if err := s.hashAnnounce(eth66); err != nil { |
|
|
|
|
t.Fatalf("block hash announcement failed: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestMaliciousHandshake65 tries to send malicious data during the handshake.
|
|
|
|
|
func (s *Suite) TestMaliciousHandshake65(t *utesting.T) { |
|
|
|
|
if err := s.maliciousHandshakes(t, eth65); err != nil { |
|
|
|
|
// TestMaliciousHandshake tries to send malicious data during the handshake.
|
|
|
|
|
func (s *Suite) TestMaliciousHandshake(t *utesting.T) { |
|
|
|
|
if err := s.maliciousHandshakes(t); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestMaliciousHandshake66 tries to send malicious data during the handshake.
|
|
|
|
|
func (s *Suite) TestMaliciousHandshake66(t *utesting.T) { |
|
|
|
|
if err := s.maliciousHandshakes(t, eth66); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestMaliciousStatus65 sends a status package with a large total difficulty.
|
|
|
|
|
func (s *Suite) TestMaliciousStatus65(t *utesting.T) { |
|
|
|
|
// TestMaliciousStatus sends a status package with a large total difficulty.
|
|
|
|
|
func (s *Suite) TestMaliciousStatus(t *utesting.T) { |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
@ -637,58 +433,28 @@ func (s *Suite) TestMaliciousStatus65(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestMaliciousStatus66 sends a status package with a large total
|
|
|
|
|
// difficulty over the eth66 protocol.
|
|
|
|
|
func (s *Suite) TestMaliciousStatus66(t *utesting.T) { |
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
|
defer conn.Close() |
|
|
|
|
|
|
|
|
|
if err := s.maliciousStatus(conn); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestTransaction65 sends a valid transaction to the node and
|
|
|
|
|
// TestTransaction sends a valid transaction to the node and
|
|
|
|
|
// checks if the transaction gets propagated.
|
|
|
|
|
func (s *Suite) TestTransaction65(t *utesting.T) { |
|
|
|
|
if err := s.sendSuccessfulTxs(t, eth65); err != nil { |
|
|
|
|
func (s *Suite) TestTransaction(t *utesting.T) { |
|
|
|
|
if err := s.sendSuccessfulTxs(t); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestTransaction66 sends a valid transaction to the node and
|
|
|
|
|
// checks if the transaction gets propagated.
|
|
|
|
|
func (s *Suite) TestTransaction66(t *utesting.T) { |
|
|
|
|
if err := s.sendSuccessfulTxs(t, eth66); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestMaliciousTx65 sends several invalid transactions and tests whether
|
|
|
|
|
// the node will propagate them.
|
|
|
|
|
func (s *Suite) TestMaliciousTx65(t *utesting.T) { |
|
|
|
|
if err := s.sendMaliciousTxs(t, eth65); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestMaliciousTx66 sends several invalid transactions and tests whether
|
|
|
|
|
// TestMaliciousTx sends several invalid transactions and tests whether
|
|
|
|
|
// the node will propagate them.
|
|
|
|
|
func (s *Suite) TestMaliciousTx66(t *utesting.T) { |
|
|
|
|
if err := s.sendMaliciousTxs(t, eth66); err != nil { |
|
|
|
|
func (s *Suite) TestMaliciousTx(t *utesting.T) { |
|
|
|
|
if err := s.sendMaliciousTxs(t); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestLargeTxRequest66 tests whether a node can fulfill a large GetPooledTransactions
|
|
|
|
|
// TestLargeTxRequest tests whether a node can fulfill a large GetPooledTransactions
|
|
|
|
|
// request.
|
|
|
|
|
func (s *Suite) TestLargeTxRequest66(t *utesting.T) { |
|
|
|
|
func (s *Suite) TestLargeTxRequest(t *utesting.T) { |
|
|
|
|
// send the next block to ensure the node is no longer syncing and
|
|
|
|
|
// is able to accept txs
|
|
|
|
|
if err := s.sendNextBlock(eth66); err != nil { |
|
|
|
|
if err := s.sendNextBlock(); err != nil { |
|
|
|
|
t.Fatalf("failed to send next block: %v", err) |
|
|
|
|
} |
|
|
|
|
// send 2000 transactions to the node
|
|
|
|
@ -701,7 +467,7 @@ func (s *Suite) TestLargeTxRequest66(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
// set up connection to receive to ensure node is peered with the receiving connection
|
|
|
|
|
// before tx request is sent
|
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
@ -714,17 +480,17 @@ func (s *Suite) TestLargeTxRequest66(t *utesting.T) { |
|
|
|
|
for _, hash := range hashMap { |
|
|
|
|
hashes = append(hashes, hash) |
|
|
|
|
} |
|
|
|
|
getTxReq := ð.GetPooledTransactionsPacket66{ |
|
|
|
|
getTxReq := &GetPooledTransactions{ |
|
|
|
|
RequestId: 1234, |
|
|
|
|
GetPooledTransactionsPacket: hashes, |
|
|
|
|
} |
|
|
|
|
if err = conn.Write66(getTxReq, GetPooledTransactions{}.Code()); err != nil { |
|
|
|
|
if err = conn.Write(getTxReq); 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 := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) { |
|
|
|
|
case PooledTransactions: |
|
|
|
|
for _, gotTx := range msg { |
|
|
|
|
case *PooledTransactions: |
|
|
|
|
for _, gotTx := range msg.PooledTransactionsPacket { |
|
|
|
|
if _, exists := hashMap[gotTx.Hash()]; !exists { |
|
|
|
|
t.Fatalf("unexpected tx received: %v", gotTx.Hash()) |
|
|
|
|
} |
|
|
|
@ -734,12 +500,12 @@ func (s *Suite) TestLargeTxRequest66(t *utesting.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestNewPooledTxs_66 tests whether a node will do a GetPooledTransactions
|
|
|
|
|
// TestNewPooledTxs tests whether a node will do a GetPooledTransactions
|
|
|
|
|
// request upon receiving a NewPooledTransactionHashes announcement.
|
|
|
|
|
func (s *Suite) TestNewPooledTxs66(t *utesting.T) { |
|
|
|
|
func (s *Suite) TestNewPooledTxs(t *utesting.T) { |
|
|
|
|
// send the next block to ensure the node is no longer syncing and
|
|
|
|
|
// is able to accept txs
|
|
|
|
|
if err := s.sendNextBlock(eth66); err != nil { |
|
|
|
|
if err := s.sendNextBlock(); err != nil { |
|
|
|
|
t.Fatalf("failed to send next block: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -757,7 +523,7 @@ func (s *Suite) TestNewPooledTxs66(t *utesting.T) { |
|
|
|
|
announce := NewPooledTransactionHashes(hashes) |
|
|
|
|
|
|
|
|
|
// send announcement
|
|
|
|
|
conn, err := s.dial66() |
|
|
|
|
conn, err := s.dial() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("dial failed: %v", err) |
|
|
|
|
} |
|
|
|
@ -771,11 +537,11 @@ func (s *Suite) TestNewPooledTxs66(t *utesting.T) { |
|
|
|
|
|
|
|
|
|
// wait for GetPooledTxs request
|
|
|
|
|
for { |
|
|
|
|
_, msg := conn.readAndServe66(s.chain, timeout) |
|
|
|
|
msg := conn.readAndServe(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)) |
|
|
|
|
case *GetPooledTransactions: |
|
|
|
|
if len(msg.GetPooledTransactionsPacket) != len(hashes) { |
|
|
|
|
t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsPacket)) |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
// ignore propagated txs from previous tests
|
|
|
|
|