github.com/dim4egster/coreth@v0.10.2/peer/network_test.go (about)

     1  // (c) 2019-2022, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package peer
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"fmt"
    10  	"sync"
    11  	"sync/atomic"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/dim4egster/qmallgo/snow/engine/common"
    16  
    17  	"github.com/dim4egster/coreth/plugin/evm/message"
    18  
    19  	"github.com/dim4egster/qmallgo/codec"
    20  	"github.com/dim4egster/qmallgo/codec/linearcodec"
    21  	"github.com/dim4egster/qmallgo/ids"
    22  	"github.com/dim4egster/qmallgo/version"
    23  	"github.com/stretchr/testify/assert"
    24  )
    25  
    26  var (
    27  	defaultPeerVersion = &version.Application{
    28  		Major: 1,
    29  		Minor: 0,
    30  		Patch: 0,
    31  	}
    32  
    33  	_ message.Request = &HelloRequest{}
    34  	_                 = &HelloResponse{}
    35  	_                 = &GreetingRequest{}
    36  	_                 = &GreetingResponse{}
    37  	_                 = &TestMessage{}
    38  
    39  	_ message.RequestHandler = &HelloGreetingRequestHandler{}
    40  	_ message.RequestHandler = &testRequestHandler{}
    41  
    42  	_ common.AppSender      = testAppSender{}
    43  	_ message.GossipMessage = HelloGossip{}
    44  	_ message.GossipHandler = &testGossipHandler{}
    45  )
    46  
    47  func TestNetworkDoesNotConnectToItself(t *testing.T) {
    48  	selfNodeID := ids.GenerateTestNodeID()
    49  	n := NewNetwork(nil, nil, selfNodeID, 1)
    50  	assert.NoError(t, n.Connected(selfNodeID, defaultPeerVersion))
    51  	assert.EqualValues(t, 0, n.Size())
    52  }
    53  
    54  func TestRequestAnyRequestsRoutingAndResponse(t *testing.T) {
    55  	callNum := uint32(0)
    56  	senderWg := &sync.WaitGroup{}
    57  	var net Network
    58  	sender := testAppSender{
    59  		sendAppRequestFn: func(nodes ids.NodeIDSet, requestID uint32, requestBytes []byte) error {
    60  			nodeID, _ := nodes.Pop()
    61  			senderWg.Add(1)
    62  			go func() {
    63  				defer senderWg.Done()
    64  				if err := net.AppRequest(nodeID, requestID, time.Now().Add(5*time.Second), requestBytes); err != nil {
    65  					panic(err)
    66  				}
    67  			}()
    68  			return nil
    69  		},
    70  		sendAppResponseFn: func(nodeID ids.NodeID, requestID uint32, responseBytes []byte) error {
    71  			senderWg.Add(1)
    72  			go func() {
    73  				defer senderWg.Done()
    74  				if err := net.AppResponse(nodeID, requestID, responseBytes); err != nil {
    75  					panic(err)
    76  				}
    77  				atomic.AddUint32(&callNum, 1)
    78  			}()
    79  			return nil
    80  		},
    81  	}
    82  
    83  	codecManager := buildCodec(t, HelloRequest{}, HelloResponse{})
    84  	net = NewNetwork(sender, codecManager, ids.EmptyNodeID, 16)
    85  	net.SetRequestHandler(&HelloGreetingRequestHandler{codec: codecManager})
    86  	client := NewNetworkClient(net)
    87  	nodeID := ids.GenerateTestNodeID()
    88  	assert.NoError(t, net.Connected(nodeID, defaultPeerVersion))
    89  
    90  	requestMessage := HelloRequest{Message: "this is a request"}
    91  
    92  	defer net.Shutdown()
    93  	assert.NoError(t, net.Connected(nodeID, defaultPeerVersion))
    94  
    95  	totalRequests := 5000
    96  	numCallsPerRequest := 1 // on sending response
    97  	totalCalls := totalRequests * numCallsPerRequest
    98  
    99  	requestWg := &sync.WaitGroup{}
   100  	requestWg.Add(totalCalls)
   101  	for i := 0; i < totalCalls; i++ {
   102  		go func(wg *sync.WaitGroup) {
   103  			defer wg.Done()
   104  			requestBytes, err := message.RequestToBytes(codecManager, requestMessage)
   105  			assert.NoError(t, err)
   106  			responseBytes, _, err := client.RequestAny(defaultPeerVersion, requestBytes)
   107  			assert.NoError(t, err)
   108  			assert.NotNil(t, responseBytes)
   109  
   110  			var response TestMessage
   111  			if _, err = codecManager.Unmarshal(responseBytes, &response); err != nil {
   112  				panic(fmt.Errorf("unexpected error during unmarshal: %w", err))
   113  			}
   114  			assert.Equal(t, "Hi", response.Message)
   115  		}(requestWg)
   116  	}
   117  
   118  	requestWg.Wait()
   119  	senderWg.Wait()
   120  	assert.Equal(t, totalCalls, int(atomic.LoadUint32(&callNum)))
   121  }
   122  
   123  func TestRequestRequestsRoutingAndResponse(t *testing.T) {
   124  	callNum := uint32(0)
   125  	senderWg := &sync.WaitGroup{}
   126  	var net Network
   127  	var lock sync.Mutex
   128  	contactedNodes := make(map[ids.NodeID]struct{})
   129  	sender := testAppSender{
   130  		sendAppRequestFn: func(nodes ids.NodeIDSet, requestID uint32, requestBytes []byte) error {
   131  			nodeID, _ := nodes.Pop()
   132  			lock.Lock()
   133  			contactedNodes[nodeID] = struct{}{}
   134  			lock.Unlock()
   135  			senderWg.Add(1)
   136  			go func() {
   137  				defer senderWg.Done()
   138  				if err := net.AppRequest(nodeID, requestID, time.Now().Add(5*time.Second), requestBytes); err != nil {
   139  					panic(err)
   140  				}
   141  			}()
   142  			return nil
   143  		},
   144  		sendAppResponseFn: func(nodeID ids.NodeID, requestID uint32, responseBytes []byte) error {
   145  			senderWg.Add(1)
   146  			go func() {
   147  				defer senderWg.Done()
   148  				if err := net.AppResponse(nodeID, requestID, responseBytes); err != nil {
   149  					panic(err)
   150  				}
   151  				atomic.AddUint32(&callNum, 1)
   152  			}()
   153  			return nil
   154  		},
   155  	}
   156  
   157  	codecManager := buildCodec(t, HelloRequest{}, HelloResponse{})
   158  	net = NewNetwork(sender, codecManager, ids.EmptyNodeID, 16)
   159  	net.SetRequestHandler(&HelloGreetingRequestHandler{codec: codecManager})
   160  	client := NewNetworkClient(net)
   161  
   162  	nodes := []ids.NodeID{
   163  		ids.GenerateTestNodeID(),
   164  		ids.GenerateTestNodeID(),
   165  		ids.GenerateTestNodeID(),
   166  		ids.GenerateTestNodeID(),
   167  		ids.GenerateTestNodeID(),
   168  	}
   169  	for _, nodeID := range nodes {
   170  		assert.NoError(t, net.Connected(nodeID, defaultPeerVersion))
   171  	}
   172  
   173  	requestMessage := HelloRequest{Message: "this is a request"}
   174  	defer net.Shutdown()
   175  
   176  	totalRequests := 5000
   177  	numCallsPerRequest := 1 // on sending response
   178  	totalCalls := totalRequests * numCallsPerRequest
   179  
   180  	requestWg := &sync.WaitGroup{}
   181  	requestWg.Add(totalCalls)
   182  	nodeIdx := 0
   183  	for i := 0; i < totalCalls; i++ {
   184  		nodeIdx = (nodeIdx + 1) % (len(nodes))
   185  		nodeID := nodes[nodeIdx]
   186  		go func(wg *sync.WaitGroup, nodeID ids.NodeID) {
   187  			defer wg.Done()
   188  			requestBytes, err := message.RequestToBytes(codecManager, requestMessage)
   189  			assert.NoError(t, err)
   190  			responseBytes, err := client.Request(nodeID, requestBytes)
   191  			assert.NoError(t, err)
   192  			assert.NotNil(t, responseBytes)
   193  
   194  			var response TestMessage
   195  			if _, err = codecManager.Unmarshal(responseBytes, &response); err != nil {
   196  				panic(fmt.Errorf("unexpected error during unmarshal: %w", err))
   197  			}
   198  			assert.Equal(t, "Hi", response.Message)
   199  		}(requestWg, nodeID)
   200  	}
   201  
   202  	requestWg.Wait()
   203  	senderWg.Wait()
   204  	assert.Equal(t, totalCalls, int(atomic.LoadUint32(&callNum)))
   205  	for _, nodeID := range nodes {
   206  		if _, exists := contactedNodes[nodeID]; !exists {
   207  			t.Fatalf("expected nodeID %s to be contacted but was not", nodeID)
   208  		}
   209  	}
   210  
   211  	// ensure empty nodeID is not allowed
   212  	_, err := client.Request(ids.EmptyNodeID, []byte("hello there"))
   213  	assert.Error(t, err)
   214  	assert.Contains(t, err.Error(), "cannot send request to empty nodeID")
   215  }
   216  
   217  func TestRequestMinVersion(t *testing.T) {
   218  	callNum := uint32(0)
   219  	nodeID := ids.GenerateTestNodeID()
   220  	codecManager := buildCodec(t, TestMessage{})
   221  
   222  	var net Network
   223  	sender := testAppSender{
   224  		sendAppRequestFn: func(nodes ids.NodeIDSet, reqID uint32, messageBytes []byte) error {
   225  			atomic.AddUint32(&callNum, 1)
   226  			assert.True(t, nodes.Contains(nodeID), "request nodes should contain expected nodeID")
   227  			assert.Len(t, nodes, 1, "request nodes should contain exactly one node")
   228  
   229  			go func() {
   230  				time.Sleep(200 * time.Millisecond)
   231  				atomic.AddUint32(&callNum, 1)
   232  				responseBytes, err := codecManager.Marshal(message.Version, TestMessage{Message: "this is a response"})
   233  				if err != nil {
   234  					panic(err)
   235  				}
   236  				err = net.AppResponse(nodeID, reqID, responseBytes)
   237  				assert.NoError(t, err)
   238  			}()
   239  			return nil
   240  		},
   241  	}
   242  
   243  	// passing nil as codec works because the net.AppRequest is never called
   244  	net = NewNetwork(sender, codecManager, ids.EmptyNodeID, 1)
   245  	client := NewNetworkClient(net)
   246  	requestMessage := TestMessage{Message: "this is a request"}
   247  	requestBytes, err := message.RequestToBytes(codecManager, requestMessage)
   248  	assert.NoError(t, err)
   249  	assert.NoError(t,
   250  		net.Connected(
   251  			nodeID,
   252  			&version.Application{
   253  				Major: 1,
   254  				Minor: 7,
   255  				Patch: 1,
   256  			},
   257  		),
   258  	)
   259  
   260  	// ensure version does not match
   261  	responseBytes, _, err := client.RequestAny(
   262  		&version.Application{
   263  			Major: 2,
   264  			Minor: 0,
   265  			Patch: 0,
   266  		},
   267  		requestBytes,
   268  	)
   269  	assert.Equal(t, err.Error(), "no peers found matching version avalanche/2.0.0 out of 1 peers")
   270  	assert.Nil(t, responseBytes)
   271  
   272  	// ensure version matches and the request goes through
   273  	responseBytes, _, err = client.RequestAny(defaultPeerVersion, requestBytes)
   274  	assert.NoError(t, err)
   275  
   276  	var response TestMessage
   277  	if _, err = codecManager.Unmarshal(responseBytes, &response); err != nil {
   278  		t.Fatal("unexpected error during unmarshal", err)
   279  	}
   280  	assert.Equal(t, "this is a response", response.Message)
   281  }
   282  
   283  func TestOnRequestHonoursDeadline(t *testing.T) {
   284  	var net Network
   285  	responded := false
   286  	sender := testAppSender{
   287  		sendAppRequestFn: func(nodes ids.NodeIDSet, reqID uint32, message []byte) error {
   288  			return nil
   289  		},
   290  		sendAppResponseFn: func(nodeID ids.NodeID, reqID uint32, message []byte) error {
   291  			responded = true
   292  			return nil
   293  		},
   294  	}
   295  
   296  	codecManager := buildCodec(t, TestMessage{})
   297  
   298  	requestBytes, err := marshalStruct(codecManager, TestMessage{Message: "hello there"})
   299  	assert.NoError(t, err)
   300  
   301  	requestHandler := &testRequestHandler{
   302  		processingDuration: 500 * time.Millisecond,
   303  	}
   304  	net = NewNetwork(sender, codecManager, ids.EmptyNodeID, 1)
   305  	net.SetRequestHandler(requestHandler)
   306  	nodeID := ids.GenerateTestNodeID()
   307  
   308  	requestHandler.response, err = marshalStruct(codecManager, TestMessage{Message: "hi there"})
   309  	assert.NoError(t, err)
   310  	err = net.AppRequest(nodeID, 1, time.Now().Add(1*time.Millisecond), requestBytes)
   311  	assert.NoError(t, err)
   312  	// ensure the handler didn't get called (as peer.Network would've dropped the request)
   313  	assert.EqualValues(t, requestHandler.calls, 0)
   314  
   315  	requestHandler.processingDuration = 0
   316  	err = net.AppRequest(nodeID, 2, time.Now().Add(250*time.Millisecond), requestBytes)
   317  	assert.NoError(t, err)
   318  	assert.True(t, responded)
   319  	assert.EqualValues(t, requestHandler.calls, 1)
   320  }
   321  
   322  func TestGossip(t *testing.T) {
   323  	codecManager := buildCodec(t, HelloGossip{})
   324  
   325  	nodeID := ids.GenerateTestNodeID()
   326  	var clientNetwork Network
   327  	wg := &sync.WaitGroup{}
   328  	sentGossip := false
   329  	wg.Add(1)
   330  	sender := testAppSender{
   331  		sendAppGossipFn: func(msg []byte) error {
   332  			go func() {
   333  				defer wg.Done()
   334  				err := clientNetwork.AppGossip(nodeID, msg)
   335  				assert.NoError(t, err)
   336  			}()
   337  			sentGossip = true
   338  			return nil
   339  		},
   340  	}
   341  
   342  	gossipHandler := &testGossipHandler{}
   343  	clientNetwork = NewNetwork(sender, codecManager, ids.EmptyNodeID, 1)
   344  	clientNetwork.SetGossipHandler(gossipHandler)
   345  
   346  	assert.NoError(t, clientNetwork.Connected(nodeID, defaultPeerVersion))
   347  
   348  	client := NewNetworkClient(clientNetwork)
   349  	defer clientNetwork.Shutdown()
   350  
   351  	b, err := buildGossip(codecManager, HelloGossip{Msg: "hello there!"})
   352  	assert.NoError(t, err)
   353  
   354  	err = client.Gossip(b)
   355  	assert.NoError(t, err)
   356  
   357  	wg.Wait()
   358  	assert.True(t, sentGossip)
   359  	assert.True(t, gossipHandler.received)
   360  }
   361  
   362  func TestHandleInvalidMessages(t *testing.T) {
   363  	codecManager := buildCodec(t, HelloGossip{}, TestMessage{})
   364  
   365  	nodeID := ids.GenerateTestNodeID()
   366  	requestID := uint32(1)
   367  	sender := testAppSender{}
   368  
   369  	clientNetwork := NewNetwork(sender, codecManager, ids.EmptyNodeID, 1)
   370  	clientNetwork.SetGossipHandler(message.NoopMempoolGossipHandler{})
   371  	clientNetwork.SetRequestHandler(&testRequestHandler{})
   372  
   373  	assert.NoError(t, clientNetwork.Connected(nodeID, defaultPeerVersion))
   374  
   375  	defer clientNetwork.Shutdown()
   376  
   377  	// Ensure a valid gossip message sent as any App specific message type does not trigger a fatal error
   378  	gossipMsg, err := buildGossip(codecManager, HelloGossip{Msg: "hello there!"})
   379  	assert.NoError(t, err)
   380  
   381  	// Ensure a valid request message sent as any App specific message type does not trigger a fatal error
   382  	requestMessage, err := marshalStruct(codecManager, TestMessage{Message: "Hello"})
   383  	assert.NoError(t, err)
   384  
   385  	// Ensure a random message sent as any App specific message type does not trigger a fatal error
   386  	garbageResponse := make([]byte, 10)
   387  	// Ensure a zero-length message sent as any App specific message type does not trigger a fatal error
   388  	emptyResponse := make([]byte, 0)
   389  	// Ensure a nil byte slice sent as any App specific message type does not trigger a fatal error
   390  	var nilResponse []byte
   391  
   392  	// Check for edge cases
   393  	assert.NoError(t, clientNetwork.AppGossip(nodeID, gossipMsg))
   394  	assert.NoError(t, clientNetwork.AppGossip(nodeID, requestMessage))
   395  	assert.NoError(t, clientNetwork.AppGossip(nodeID, garbageResponse))
   396  	assert.NoError(t, clientNetwork.AppGossip(nodeID, emptyResponse))
   397  	assert.NoError(t, clientNetwork.AppGossip(nodeID, nilResponse))
   398  	assert.NoError(t, clientNetwork.AppRequest(nodeID, requestID, time.Now().Add(time.Second), gossipMsg))
   399  	assert.NoError(t, clientNetwork.AppRequest(nodeID, requestID, time.Now().Add(time.Second), requestMessage))
   400  	assert.NoError(t, clientNetwork.AppRequest(nodeID, requestID, time.Now().Add(time.Second), garbageResponse))
   401  	assert.NoError(t, clientNetwork.AppRequest(nodeID, requestID, time.Now().Add(time.Second), emptyResponse))
   402  	assert.NoError(t, clientNetwork.AppRequest(nodeID, requestID, time.Now().Add(time.Second), nilResponse))
   403  	assert.NoError(t, clientNetwork.AppResponse(nodeID, requestID, gossipMsg))
   404  	assert.NoError(t, clientNetwork.AppResponse(nodeID, requestID, requestMessage))
   405  	assert.NoError(t, clientNetwork.AppResponse(nodeID, requestID, garbageResponse))
   406  	assert.NoError(t, clientNetwork.AppResponse(nodeID, requestID, emptyResponse))
   407  	assert.NoError(t, clientNetwork.AppResponse(nodeID, requestID, nilResponse))
   408  	assert.NoError(t, clientNetwork.AppRequestFailed(nodeID, requestID))
   409  }
   410  
   411  func TestNetworkPropagatesRequestHandlerError(t *testing.T) {
   412  	codecManager := buildCodec(t, TestMessage{})
   413  
   414  	nodeID := ids.GenerateTestNodeID()
   415  	requestID := uint32(1)
   416  	sender := testAppSender{}
   417  
   418  	clientNetwork := NewNetwork(sender, codecManager, ids.EmptyNodeID, 1)
   419  	clientNetwork.SetGossipHandler(message.NoopMempoolGossipHandler{})
   420  	clientNetwork.SetRequestHandler(&testRequestHandler{err: errors.New("fail")}) // Return an error from the request handler
   421  
   422  	assert.NoError(t, clientNetwork.Connected(nodeID, defaultPeerVersion))
   423  
   424  	defer clientNetwork.Shutdown()
   425  
   426  	// Ensure a valid request message sent as any App specific message type does not trigger a fatal error
   427  	requestMessage, err := marshalStruct(codecManager, TestMessage{Message: "Hello"})
   428  	assert.NoError(t, err)
   429  
   430  	// Check that if the request handler returns an error, it is propagated as a fatal error.
   431  	assert.Error(t, clientNetwork.AppRequest(nodeID, requestID, time.Now().Add(time.Second), requestMessage))
   432  }
   433  
   434  func buildCodec(t *testing.T, types ...interface{}) codec.Manager {
   435  	codecManager := codec.NewDefaultManager()
   436  	c := linearcodec.NewDefault()
   437  	for _, typ := range types {
   438  		assert.NoError(t, c.RegisterType(typ))
   439  	}
   440  	assert.NoError(t, codecManager.RegisterCodec(message.Version, c))
   441  	return codecManager
   442  }
   443  
   444  // marshalStruct is a helper method used to marshal an object as `interface{}`
   445  // so that the codec is able to include the TypeID in the resulting bytes
   446  func marshalStruct(codec codec.Manager, obj interface{}) ([]byte, error) {
   447  	return codec.Marshal(message.Version, &obj)
   448  }
   449  
   450  func buildGossip(codec codec.Manager, msg message.GossipMessage) ([]byte, error) {
   451  	return codec.Marshal(message.Version, &msg)
   452  }
   453  
   454  type testAppSender struct {
   455  	sendAppRequestFn  func(ids.NodeIDSet, uint32, []byte) error
   456  	sendAppResponseFn func(ids.NodeID, uint32, []byte) error
   457  	sendAppGossipFn   func([]byte) error
   458  }
   459  
   460  func (t testAppSender) SendAppGossipSpecific(ids.NodeIDSet, []byte) error {
   461  	panic("not implemented")
   462  }
   463  
   464  func (t testAppSender) SendAppRequest(nodeIDs ids.NodeIDSet, requestID uint32, message []byte) error {
   465  	return t.sendAppRequestFn(nodeIDs, requestID, message)
   466  }
   467  
   468  func (t testAppSender) SendAppResponse(nodeID ids.NodeID, requestID uint32, message []byte) error {
   469  	return t.sendAppResponseFn(nodeID, requestID, message)
   470  }
   471  
   472  func (t testAppSender) SendAppGossip(message []byte) error {
   473  	return t.sendAppGossipFn(message)
   474  }
   475  
   476  type HelloRequest struct {
   477  	Message string `serialize:"true"`
   478  }
   479  
   480  func (h HelloRequest) Handle(ctx context.Context, nodeID ids.NodeID, requestID uint32, handler message.RequestHandler) ([]byte, error) {
   481  	// casting is only necessary for test since RequestHandler does not implement anything at the moment
   482  	return handler.(TestRequestHandler).HandleHelloRequest(ctx, nodeID, requestID, &h)
   483  }
   484  
   485  func (h HelloRequest) String() string {
   486  	return fmt.Sprintf("HelloRequest(%s)", h.Message)
   487  }
   488  
   489  type GreetingRequest struct {
   490  	Greeting string `serialize:"true"`
   491  }
   492  
   493  func (g GreetingRequest) Handle(ctx context.Context, nodeID ids.NodeID, requestID uint32, handler message.RequestHandler) ([]byte, error) {
   494  	// casting is only necessary for test since RequestHandler does not implement anything at the moment
   495  	return handler.(TestRequestHandler).HandleGreetingRequest(ctx, nodeID, requestID, &g)
   496  }
   497  
   498  func (g GreetingRequest) String() string {
   499  	return fmt.Sprintf("GreetingRequest(%s)", g.Greeting)
   500  }
   501  
   502  type HelloResponse struct {
   503  	Response string `serialize:"true"`
   504  }
   505  
   506  type GreetingResponse struct {
   507  	Greet string `serialize:"true"`
   508  }
   509  
   510  type TestRequestHandler interface {
   511  	HandleHelloRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request *HelloRequest) ([]byte, error)
   512  	HandleGreetingRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request *GreetingRequest) ([]byte, error)
   513  }
   514  
   515  type HelloGreetingRequestHandler struct {
   516  	message.RequestHandler
   517  	codec codec.Manager
   518  }
   519  
   520  func (h *HelloGreetingRequestHandler) HandleHelloRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request *HelloRequest) ([]byte, error) {
   521  	return h.codec.Marshal(message.Version, HelloResponse{Response: "Hi"})
   522  }
   523  
   524  func (h *HelloGreetingRequestHandler) HandleGreetingRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request *GreetingRequest) ([]byte, error) {
   525  	return h.codec.Marshal(message.Version, GreetingResponse{Greet: "Hey there"})
   526  }
   527  
   528  type TestMessage struct {
   529  	Message string `serialize:"true"`
   530  }
   531  
   532  func (t TestMessage) Handle(ctx context.Context, nodeID ids.NodeID, requestID uint32, handler message.RequestHandler) ([]byte, error) {
   533  	return handler.(*testRequestHandler).handleTestRequest(ctx, nodeID, requestID, &t)
   534  }
   535  
   536  func (t TestMessage) String() string {
   537  	return fmt.Sprintf("TestMessage(%s)", t.Message)
   538  }
   539  
   540  type HelloGossip struct {
   541  	Msg string `serialize:"true"`
   542  }
   543  
   544  func (h HelloGossip) Handle(handler message.GossipHandler, nodeID ids.NodeID) error {
   545  	return handler.HandleEthTxs(nodeID, message.EthTxsGossip{})
   546  }
   547  
   548  func (h HelloGossip) String() string {
   549  	return fmt.Sprintf("HelloGossip(%s)", h.Msg)
   550  }
   551  
   552  func (h HelloGossip) initialize(_ []byte) {
   553  	// no op
   554  }
   555  
   556  func (h HelloGossip) Bytes() []byte {
   557  	// no op
   558  	return nil
   559  }
   560  
   561  type testGossipHandler struct {
   562  	received bool
   563  	nodeID   ids.NodeID
   564  	msg      []byte
   565  }
   566  
   567  func (t *testGossipHandler) HandleAtomicTx(nodeID ids.NodeID, msg message.AtomicTxGossip) error {
   568  	t.received = true
   569  	t.nodeID = nodeID
   570  	return nil
   571  }
   572  
   573  func (t *testGossipHandler) HandleEthTxs(nodeID ids.NodeID, msg message.EthTxsGossip) error {
   574  	t.received = true
   575  	t.nodeID = nodeID
   576  	return nil
   577  }
   578  
   579  type testRequestHandler struct {
   580  	message.RequestHandler
   581  	calls              uint32
   582  	processingDuration time.Duration
   583  	response           []byte
   584  	err                error
   585  }
   586  
   587  func (r *testRequestHandler) handleTestRequest(ctx context.Context, _ ids.NodeID, _ uint32, _ *TestMessage) ([]byte, error) {
   588  	r.calls++
   589  	select {
   590  	case <-time.After(r.processingDuration):
   591  		break
   592  	case <-ctx.Done():
   593  		return nil, ctx.Err()
   594  	}
   595  	return r.response, r.err
   596  }