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 }