github.com/status-im/status-go@v1.1.0/waku/waku_version_test.go (about)

     1  // Copyright 2019 The Waku Library Authors.
     2  //
     3  // The Waku library is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Lesser General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // (at your option) any later version.
     7  //
     8  // The Waku library is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty off
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    11  // GNU Lesser General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Lesser General Public License
    14  // along with the Waku library. If not, see <http://www.gnu.org/licenses/>.
    15  //
    16  // This software uses the go-ethereum library, which is licensed
    17  // under the GNU Lesser General Public Library, version 3 or any later.
    18  
    19  package waku
    20  
    21  import (
    22  	mrand "math/rand"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/suite"
    27  
    28  	"github.com/status-im/status-go/waku/common"
    29  	v0 "github.com/status-im/status-go/waku/v0"
    30  	v1 "github.com/status-im/status-go/waku/v1"
    31  
    32  	"go.uber.org/zap"
    33  
    34  	gethcommon "github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/crypto"
    36  	"github.com/ethereum/go-ethereum/p2p"
    37  	"github.com/ethereum/go-ethereum/p2p/enode"
    38  )
    39  
    40  func TestWakuV0(t *testing.T) {
    41  	ws := new(WakuTestSuite)
    42  	ws.newPeer = v0.NewPeer
    43  
    44  	suite.Run(t, ws)
    45  }
    46  
    47  func TestWakuV1(t *testing.T) {
    48  	ws := new(WakuTestSuite)
    49  	ws.newPeer = v1.NewPeer
    50  
    51  	suite.Run(t, ws)
    52  }
    53  
    54  type WakuTestSuite struct {
    55  	suite.Suite
    56  	seed    int64
    57  	stats   *common.StatsTracker
    58  	newPeer func(common.WakuHost, *p2p.Peer, p2p.MsgReadWriter, *zap.Logger, *common.StatsTracker) common.Peer
    59  }
    60  
    61  // Set up random seed
    62  func (s *WakuTestSuite) SetupTest() {
    63  	s.seed = time.Now().Unix()
    64  	s.stats = &common.StatsTracker{}
    65  	mrand.Seed(s.seed)
    66  }
    67  
    68  func (s *WakuTestSuite) TestHandleP2PMessageCode() {
    69  
    70  	w1 := New(nil, nil)
    71  	s.Require().NoError(w1.SetMinimumPoW(0.0000001, false))
    72  	s.Require().NoError(w1.Start())
    73  
    74  	go func() { handleError(s.T(), w1.Stop()) }()
    75  
    76  	w2 := New(nil, nil)
    77  	s.Require().NoError(w2.SetMinimumPoW(0.0000001, false))
    78  	s.Require().NoError(w2.Start())
    79  	go func() { handleError(s.T(), w2.Stop()) }()
    80  
    81  	envelopeEvents := make(chan common.EnvelopeEvent, 10)
    82  	sub := w1.SubscribeEnvelopeEvents(envelopeEvents)
    83  	defer sub.Unsubscribe()
    84  
    85  	params, err := generateMessageParams()
    86  	s.Require().NoError(err, "failed generateMessageParams with seed", s.seed)
    87  
    88  	params.TTL = 1
    89  
    90  	msg, err := common.NewSentMessage(params)
    91  	s.Require().NoError(err, "failed to create new message with seed", seed)
    92  
    93  	env, err := msg.Wrap(params, time.Now())
    94  	s.Require().NoError(err, "failed Wrap with seed", seed)
    95  
    96  	rw1, rw2 := p2p.MsgPipe()
    97  
    98  	go func() {
    99  		s.Require().Error(w1.HandlePeer(s.newPeer(w1, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), rw1, nil, s.stats), rw1))
   100  	}()
   101  
   102  	timer := time.AfterFunc(time.Second*5, func() {
   103  		handleError(s.T(), rw1.Close())
   104  		handleError(s.T(), rw2.Close())
   105  	})
   106  
   107  	peer1 := s.newPeer(w2, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), rw2, nil, s.stats)
   108  	peer1.SetPeerTrusted(true)
   109  
   110  	err = peer1.Start()
   111  	s.Require().NoError(err, "failed run message loop")
   112  
   113  	// Simulate receiving the new envelope
   114  	_, err = w2.add(env, true)
   115  	s.Require().NoError(err)
   116  
   117  	e := <-envelopeEvents
   118  	s.Require().Equal(e.Hash, env.Hash(), "envelopes not equal")
   119  	peer1.Stop()
   120  	s.Require().NoError(rw1.Close())
   121  	s.Require().NoError(rw2.Close())
   122  	timer.Stop()
   123  }
   124  
   125  func (s *WakuTestSuite) testConfirmationsHandshake(expectConfirmations bool) {
   126  	conf := &Config{
   127  		MinimumAcceptedPoW:  0,
   128  		EnableConfirmations: expectConfirmations,
   129  	}
   130  	w1 := New(nil, nil)
   131  	w2 := New(conf, nil)
   132  	rw1, rw2 := p2p.MsgPipe()
   133  
   134  	// so that actual read won't hang forever
   135  	timer := time.AfterFunc(5*time.Second, func() {
   136  		handleError(s.T(), rw1.Close())
   137  		handleError(s.T(), rw2.Close())
   138  	})
   139  
   140  	p1 := s.newPeer(w1, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{Name: "waku", Version: 1}}), rw1, nil, s.stats)
   141  
   142  	go func() {
   143  		// This will always fail eventually as we close the channels
   144  		s.Require().Error(w1.HandlePeer(p1, rw1))
   145  	}()
   146  
   147  	p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{}, "test-2", []p2p.Cap{}), rw2, nil, s.stats)
   148  	err := p2.Start()
   149  	s.Require().NoError(err)
   150  	peers := w1.getPeers()
   151  	s.Require().Len(peers, 1)
   152  	// We need to let the loop run, not very elegant, but otherwise is
   153  	// flaky
   154  	time.Sleep(10 * time.Millisecond)
   155  	s.Require().Equal(expectConfirmations, peers[0].ConfirmationsEnabled())
   156  	timer.Stop()
   157  	s.Require().NoError(rw1.Close())
   158  	s.Require().NoError(rw2.Close())
   159  }
   160  
   161  func (s *WakuTestSuite) TestConfirmationHandshakeExtension() {
   162  	s.testConfirmationsHandshake(true)
   163  }
   164  
   165  func (s *WakuTestSuite) TestHandshakeWithConfirmationsDisabled() {
   166  	s.testConfirmationsHandshake(false)
   167  }
   168  
   169  func (s *WakuTestSuite) TestMessagesResponseWithError() {
   170  	conf := &Config{
   171  		MinimumAcceptedPoW:  0,
   172  		MaxMessageSize:      10 << 20,
   173  		EnableConfirmations: true,
   174  	}
   175  	w1 := New(conf, nil)
   176  	w2 := New(conf, nil)
   177  
   178  	rw1, rw2 := p2p.MsgPipe()
   179  	defer func() {
   180  		if err := rw1.Close(); err != nil {
   181  			s.T().Errorf("error closing MsgPipe 1, '%s'", err)
   182  		}
   183  		if err := rw2.Close(); err != nil {
   184  			s.T().Errorf("error closing MsgPipe 2, '%s'", err)
   185  		}
   186  	}()
   187  	p1 := s.newPeer(w1, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{Name: "waku", Version: 0}}), rw2, nil, s.stats)
   188  	p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{2}, "2", []p2p.Cap{{Name: "waku", Version: 0}}), rw1, nil, s.stats)
   189  
   190  	errorc := make(chan error, 1)
   191  	go func() { errorc <- w1.HandlePeer(p1, rw2) }()
   192  	s.Require().NoError(p2.Start())
   193  
   194  	failed := common.Envelope{
   195  		Expiry: uint32(time.Now().Add(time.Hour).Unix()),
   196  		TTL:    10,
   197  		Topic:  common.TopicType{1},
   198  		Data:   make([]byte, 1<<10),
   199  		Nonce:  1,
   200  	}
   201  	normal := common.Envelope{
   202  		Expiry: uint32(time.Now().Unix()) + 5,
   203  		TTL:    10,
   204  		Topic:  common.TopicType{1},
   205  		Data:   make([]byte, 1<<10),
   206  		Nonce:  1,
   207  	}
   208  
   209  	events := make(chan common.EnvelopeEvent, 2)
   210  	sub := w1.SubscribeEnvelopeEvents(events)
   211  	defer sub.Unsubscribe()
   212  
   213  	w2.addEnvelope(&failed)
   214  	w2.addEnvelope(&normal)
   215  	count := 0
   216  	// Wait for the two envelopes to be received
   217  	for count < 2 {
   218  		select {
   219  		case <-time.After(5 * time.Second):
   220  			s.Require().FailNow("didnt receive events")
   221  
   222  		case ev := <-events:
   223  			switch ev.Event {
   224  			case common.EventEnvelopeReceived:
   225  				count++
   226  			default:
   227  				s.Require().FailNow("invalid event message", ev.Event)
   228  
   229  			}
   230  		}
   231  	}
   232  	// Make sure only one envelope is saved and one is discarded
   233  	s.Require().Len(w1.Envelopes(), 1)
   234  }
   235  
   236  func (s *WakuTestSuite) TestEventsWithoutConfirmation() {
   237  	conf := &Config{
   238  		MinimumAcceptedPoW: 0,
   239  		MaxMessageSize:     10 << 20,
   240  	}
   241  	w1 := New(conf, nil)
   242  	w2 := New(conf, nil)
   243  	events := make(chan common.EnvelopeEvent, 2)
   244  	sub := w1.SubscribeEnvelopeEvents(events)
   245  	defer sub.Unsubscribe()
   246  
   247  	rw1, rw2 := p2p.MsgPipe()
   248  	p1 := s.newPeer(w1, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{Name: "waku", Version: 0}}), rw2, nil, s.stats)
   249  
   250  	go func() { handleError(s.T(), w1.HandlePeer(p1, rw2)) }()
   251  
   252  	timer := time.AfterFunc(5*time.Second, func() {
   253  		handleError(s.T(), rw1.Close())
   254  	})
   255  	peer2 := s.newPeer(w2, p2p.NewPeer(enode.ID{1}, "1", nil), rw1, nil, s.stats)
   256  	s.Require().NoError(peer2.Start())
   257  
   258  	go func() { handleError(s.T(), peer2.Run()) }()
   259  
   260  	e := common.Envelope{
   261  		Expiry: uint32(time.Now().Add(10 * time.Second).Unix()),
   262  		TTL:    10,
   263  		Topic:  common.TopicType{1},
   264  		Data:   make([]byte, 1<<10),
   265  		Nonce:  1,
   266  	}
   267  	s.Require().NoError(w1.Send(&e))
   268  
   269  	select {
   270  	case ev := <-events:
   271  		s.Require().Equal(common.EventEnvelopeSent, ev.Event)
   272  		s.Require().Equal(p1.EnodeID(), ev.Peer)
   273  		s.Require().Equal(gethcommon.Hash{}, ev.Batch)
   274  	case <-time.After(5 * time.Second):
   275  		s.Require().FailNow("timed out waiting for an envelope.sent event")
   276  	}
   277  	s.Require().NoError(rw1.Close())
   278  	timer.Stop()
   279  }
   280  
   281  func (s *WakuTestSuite) TestWakuTimeDesyncEnvelopeIgnored() {
   282  	c := &Config{
   283  		MaxMessageSize:     common.DefaultMaxMessageSize,
   284  		MinimumAcceptedPoW: 0,
   285  	}
   286  	rw1, rw2 := p2p.MsgPipe()
   287  	defer func() {
   288  		if err := rw1.Close(); err != nil {
   289  			s.T().Errorf("error closing MsgPipe, '%s'", err)
   290  		}
   291  		if err := rw2.Close(); err != nil {
   292  			s.T().Errorf("error closing MsgPipe, '%s'", err)
   293  		}
   294  	}()
   295  	w1, w2 := New(c, nil), New(c, nil)
   296  	p1 := s.newPeer(w2, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{Name: "waku", Version: 1}}), rw1, nil, s.stats)
   297  	p2 := s.newPeer(w1, p2p.NewPeer(enode.ID{2}, "2", []p2p.Cap{{Name: "waku", Version: 1}}), rw2, nil, s.stats)
   298  
   299  	errc := make(chan error)
   300  	go func() { errc <- w1.HandlePeer(p2, rw2) }()
   301  	go func() { errc <- w2.HandlePeer(p1, rw1) }()
   302  	w1.SetTimeSource(func() time.Time {
   303  		return time.Now().Add(time.Hour)
   304  	})
   305  	env := &common.Envelope{
   306  		Expiry: uint32(time.Now().Add(time.Hour).Unix()),
   307  		TTL:    30,
   308  		Topic:  common.TopicType{1},
   309  		Data:   []byte{1, 1, 1},
   310  	}
   311  	s.Require().NoError(w1.Send(env))
   312  	select {
   313  	case err := <-errc:
   314  		s.Require().NoError(err)
   315  	case <-time.After(time.Second):
   316  	}
   317  	s.Require().NoError(rw2.Close())
   318  	select {
   319  	case err := <-errc:
   320  		s.Require().Error(err, "p2p: read or write on closed message pipe")
   321  	case <-time.After(time.Second):
   322  		s.Require().FailNow("connection wasn't closed in expected time")
   323  	}
   324  }
   325  
   326  type MockMailserver struct {
   327  	deliverMail func([]byte, *common.Envelope)
   328  }
   329  
   330  func (*MockMailserver) Archive(e *common.Envelope) {
   331  }
   332  
   333  func (*MockMailserver) Deliver(peerID []byte, r common.MessagesRequest) {
   334  }
   335  
   336  func (m *MockMailserver) DeliverMail(peerID []byte, e *common.Envelope) {
   337  
   338  	if m.deliverMail != nil {
   339  		m.deliverMail(peerID, e)
   340  	}
   341  }
   342  
   343  func (s *WakuTestSuite) TestRateLimiterIntegration() {
   344  	conf := &Config{
   345  		MinimumAcceptedPoW: 0,
   346  		MaxMessageSize:     10 << 20,
   347  	}
   348  	w := New(conf, nil)
   349  	w.RegisterRateLimiter(common.NewPeerRateLimiter(nil, &common.MetricsRateLimiterHandler{}))
   350  	rw1, rw2 := p2p.MsgPipe()
   351  	defer func() {
   352  		if err := rw1.Close(); err != nil {
   353  			s.T().Errorf("error closing MsgPipe, '%s'", err)
   354  		}
   355  		if err := rw2.Close(); err != nil {
   356  			s.T().Errorf("error closing MsgPipe, '%s'", err)
   357  		}
   358  	}()
   359  	p := s.newPeer(w, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{Name: "waku", Version: 0}}), rw2, nil, s.stats)
   360  	errorc := make(chan error, 1)
   361  	go func() { errorc <- w.HandlePeer(p, rw2) }()
   362  
   363  	_, err := rw1.ReadMsg()
   364  	s.Require().NoError(err)
   365  
   366  	select {
   367  	case err := <-errorc:
   368  		s.Require().NoError(err)
   369  	default:
   370  	}
   371  }
   372  
   373  func (s *WakuTestSuite) TestMailserverCompletionEvent() {
   374  	w1 := New(nil, nil)
   375  	s.Require().NoError(w1.Start())
   376  	defer func() { handleError(s.T(), w1.Stop()) }()
   377  
   378  	rw1, rw2 := p2p.MsgPipe()
   379  	errorc := make(chan error, 1)
   380  	go func() {
   381  		err := w1.HandlePeer(s.newPeer(w1, p2p.NewPeer(enode.ID{}, "1", []p2p.Cap{}), rw1, nil, s.stats), rw1)
   382  		errorc <- err
   383  	}()
   384  
   385  	w2 := New(nil, nil)
   386  	s.Require().NoError(w2.Start())
   387  	defer func() { handleError(s.T(), w2.Stop()) }()
   388  
   389  	peer2 := s.newPeer(w2, p2p.NewPeer(enode.ID{1}, "1", nil), rw2, nil, s.stats)
   390  	peer2.SetPeerTrusted(true)
   391  
   392  	events := make(chan common.EnvelopeEvent)
   393  	sub := w1.SubscribeEnvelopeEvents(events)
   394  	defer sub.Unsubscribe()
   395  
   396  	envelopes := []*common.Envelope{{Data: []byte{1}}, {Data: []byte{2}}}
   397  	s.Require().NoError(peer2.Start())
   398  	// Set peer trusted, we know the peer has been added as handshake was successful
   399  	w1.getPeers()[0].SetPeerTrusted(true)
   400  
   401  	s.Require().NoError(peer2.SendP2PMessages(envelopes))
   402  	s.Require().NoError(peer2.SendHistoricMessageResponse(make([]byte, 100)))
   403  	s.Require().NoError(rw2.Close())
   404  
   405  	// Wait for all messages to be read
   406  	err := <-errorc
   407  	s.Require().EqualError(err, "p2p: read or write on closed message pipe")
   408  
   409  	after := time.After(2 * time.Second)
   410  	count := 0
   411  	for {
   412  		select {
   413  		case <-after:
   414  			s.Require().FailNow("timed out waiting for all events")
   415  		case ev := <-events:
   416  			switch ev.Event {
   417  			case common.EventEnvelopeAvailable:
   418  				count++
   419  			case common.EventMailServerRequestCompleted:
   420  				s.Require().Equal(count, len(envelopes),
   421  					"all envelope.avaiable events mut be recevied before request is compelted")
   422  				return
   423  			}
   424  		}
   425  	}
   426  }
   427  
   428  // two generic waku node handshake
   429  func (s *WakuTestSuite) TestPeerHandshakeWithTwoFullNode() {
   430  	rw1, rw2 := p2p.MsgPipe()
   431  	defer func() { handleError(s.T(), rw1.Close()) }()
   432  	defer func() { handleError(s.T(), rw2.Close()) }()
   433  
   434  	w1 := New(nil, nil)
   435  	var pow = 0.1
   436  	err := w1.SetMinimumPoW(pow, true)
   437  	s.Require().NoError(err)
   438  
   439  	w2 := New(nil, nil)
   440  
   441  	go func() {
   442  		handleError(s.T(), w1.HandlePeer(s.newPeer(w1, p2p.NewPeer(enode.ID{}, "test-1", []p2p.Cap{}), rw1, nil, s.stats), rw1))
   443  	}()
   444  
   445  	p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{}, "test-2", []p2p.Cap{}), rw2, nil, s.stats)
   446  	err = p2.Start()
   447  	s.Require().NoError(err)
   448  
   449  	s.Require().Equal(pow, p2.PoWRequirement())
   450  }
   451  
   452  // two generic waku node handshake. one don't send light flag
   453  func (s *WakuTestSuite) TestHandshakeWithOldVersionWithoutLightModeFlag() {
   454  	rw1, rw2 := p2p.MsgPipe()
   455  	defer func() { handleError(s.T(), rw1.Close()) }()
   456  	defer func() { handleError(s.T(), rw2.Close()) }()
   457  
   458  	w1 := New(nil, nil)
   459  	w1.SetLightClientMode(true)
   460  
   461  	w2 := New(nil, nil)
   462  
   463  	go func() {
   464  		handleError(s.T(), w1.HandlePeer(s.newPeer(w1, p2p.NewPeer(enode.ID{}, "test-1", []p2p.Cap{}), rw1, nil, s.stats), rw1))
   465  	}()
   466  
   467  	p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{}, "test-2", []p2p.Cap{}), rw2, nil, s.stats)
   468  	err := p2.Start()
   469  	s.Require().NoError(err)
   470  }
   471  
   472  // two light nodes handshake. restriction enable
   473  func (s *WakuTestSuite) TestTwoLightPeerHandshakeRestrictionOff() {
   474  	rw1, rw2 := p2p.MsgPipe()
   475  	defer func() { handleError(s.T(), rw1.Close()) }()
   476  	defer func() { handleError(s.T(), rw2.Close()) }()
   477  
   478  	w1 := New(nil, nil)
   479  	w1.SetLightClientMode(true)
   480  	w1.settings.RestrictLightClientsConn = false
   481  
   482  	w2 := New(nil, nil)
   483  	w2.SetLightClientMode(true)
   484  	w2.settings.RestrictLightClientsConn = false
   485  
   486  	go func() {
   487  		handleError(s.T(), w1.HandlePeer(s.newPeer(w1, p2p.NewPeer(enode.ID{}, "test-1", []p2p.Cap{}), rw1, nil, s.stats), rw1))
   488  	}()
   489  
   490  	p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{}, "test-2", []p2p.Cap{}), rw2, nil, s.stats)
   491  	s.Require().NoError(p2.Start())
   492  }
   493  
   494  // two light nodes handshake. restriction enabled
   495  func (s *WakuTestSuite) TestTwoLightPeerHandshakeError() {
   496  	rw1, rw2 := p2p.MsgPipe()
   497  	defer func() { handleError(s.T(), rw1.Close()) }()
   498  	defer func() { handleError(s.T(), rw2.Close()) }()
   499  
   500  	w1 := New(nil, nil)
   501  	w1.SetLightClientMode(true)
   502  	w1.settings.RestrictLightClientsConn = true
   503  
   504  	w2 := New(nil, nil)
   505  	w2.SetLightClientMode(true)
   506  	w2.settings.RestrictLightClientsConn = true
   507  
   508  	go func() {
   509  		handleError(s.T(), w1.HandlePeer(s.newPeer(w1, p2p.NewPeer(enode.ID{}, "test-1", []p2p.Cap{}), rw1, nil, s.stats), rw1))
   510  	}()
   511  
   512  	p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{}, "test-2", []p2p.Cap{}), rw2, nil, s.stats)
   513  	s.Require().Error(p2.Start())
   514  }
   515  
   516  func generateMessageParams() (*common.MessageParams, error) {
   517  	// set all the parameters except p.Dst and p.Padding
   518  
   519  	buf := make([]byte, 4)
   520  	mrand.Read(buf)       // nolint: gosec
   521  	sz := mrand.Intn(400) // nolint: gosec
   522  
   523  	var p common.MessageParams
   524  	p.PoW = 0.01
   525  	p.WorkTime = 1
   526  	p.TTL = uint32(mrand.Intn(1024)) // nolint: gosec
   527  	p.Payload = make([]byte, sz)
   528  	p.KeySym = make([]byte, common.AESKeyLength)
   529  	mrand.Read(p.Payload) // nolint: gosec
   530  	mrand.Read(p.KeySym)  // nolint: gosec
   531  	p.Topic = common.BytesToTopic(buf)
   532  
   533  	var err error
   534  	p.Src, err = crypto.GenerateKey()
   535  	if err != nil {
   536  		return nil, err
   537  	}
   538  
   539  	return &p, nil
   540  }