// Copyright 2019 The Waku Library Authors. // // The Waku library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The Waku library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty off // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the Waku library. If not, see . // // This software uses the go-ethereum library, which is licensed // under the GNU Lesser General Public Library, version 3 or any later. package waku import ( "bytes" "crypto/ecdsa" "crypto/sha256" mrand "math/rand" "testing" "time" "golang.org/x/crypto/pbkdf2" "github.com/ethereum/go-ethereum/crypto" "github.com/status-im/status-go/waku/common" v0 "github.com/status-im/status-go/waku/v0" ) var seed int64 // InitSingleTest should be called in the beginning of every // test, which uses RNG, in order to make the tests // reproducibility independent of their sequence. func InitSingleTest() { seed = time.Now().Unix() mrand.Seed(seed) } func TestBasic(t *testing.T) { w := New(nil, nil) p := w.Protocols() waku := p[0] if waku.Name != v0.Name { t.Fatalf("failed Peer Name: %v.", waku.Name) } if uint64(waku.Version) != v0.Version { t.Fatalf("failed Peer Version: %v.", waku.Version) } if waku.Length != v0.NumberOfMessageCodes { t.Fatalf("failed Peer Length: %v.", waku.Length) } if waku.Run == nil { t.Fatalf("failed waku.Run.") } if w.GetFilter("non-existent") != nil { t.Fatalf("failed GetFilter.") } peerID := make([]byte, 64) mrand.Read(peerID) // nolint: gosec peer, _ := w.getPeer(peerID) if peer != nil { t.Fatal("found peer for random key.") } if err := w.AllowP2PMessagesFromPeer(peerID); err == nil { t.Fatalf("failed MarkPeerTrusted.") } exist := w.HasSymKey("non-existing") if exist { t.Fatalf("failed HasSymKey.") } key, err := w.GetSymKey("non-existing") if err == nil { t.Fatalf("failed GetSymKey(non-existing): false positive.") } if key != nil { t.Fatalf("failed GetSymKey: false positive.") } mail := w.Envelopes() if len(mail) != 0 { t.Fatalf("failed w.Envelopes().") } derived := pbkdf2.Key(peerID, nil, 65356, common.AESKeyLength, sha256.New) if !common.ValidateDataIntegrity(derived, common.AESKeyLength) { t.Fatalf("failed validateSymmetricKey with param = %v.", derived) } if common.ContainsOnlyZeros(derived) { t.Fatalf("failed containsOnlyZeros with param = %v.", derived) } buf := []byte{0xFF, 0xE5, 0x80, 0x2, 0} le := common.BytesToUintLittleEndian(buf) be := common.BytesToUintBigEndian(buf) if le != uint64(0x280e5ff) { t.Fatalf("failed bytesToIntLittleEndian: %d.", le) } if be != uint64(0xffe5800200) { t.Fatalf("failed BytesToIntBigEndian: %d.", be) } id, err := w.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair: %s.", err) } pk, err := w.GetPrivateKey(id) if err != nil { t.Fatalf("failed to retrieve new key pair: %s.", err) } if !validatePrivateKey(pk) { t.Fatalf("failed validatePrivateKey: %v.", pk) } if !common.ValidatePublicKey(&pk.PublicKey) { t.Fatalf("failed ValidatePublicKey: %v.", pk) } } func TestAsymmetricKeyImport(t *testing.T) { var ( w = New(nil, nil) privateKeys []*ecdsa.PrivateKey ) for i := 0; i < 50; i++ { id, err := w.NewKeyPair() if err != nil { t.Fatalf("could not generate key: %v", err) } pk, err := w.GetPrivateKey(id) if err != nil { t.Fatalf("could not export private key: %v", err) } privateKeys = append(privateKeys, pk) if !w.DeleteKeyPair(id) { t.Fatalf("could not delete private key") } } for _, pk := range privateKeys { if _, err := w.AddKeyPair(pk); err != nil { t.Fatalf("could not import private key: %v", err) } } } func TestWakuIdentityManagement(t *testing.T) { w := New(nil, nil) id1, err := w.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair: %s.", err) } id2, err := w.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair: %s.", err) } pk1, err := w.GetPrivateKey(id1) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } pk2, err := w.GetPrivateKey(id2) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } if !w.HasKeyPair(id1) { t.Fatalf("failed HasIdentity(pk1).") } if !w.HasKeyPair(id2) { t.Fatalf("failed HasIdentity(pk2).") } if pk1 == nil { t.Fatalf("failed GetIdentity(pk1).") } if pk2 == nil { t.Fatalf("failed GetIdentity(pk2).") } if !validatePrivateKey(pk1) { t.Fatalf("pk1 is invalid.") } if !validatePrivateKey(pk2) { t.Fatalf("pk2 is invalid.") } // Delete one identity done := w.DeleteKeyPair(id1) if !done { t.Fatalf("failed to delete id1.") } pk1, err = w.GetPrivateKey(id1) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } pk2, err = w.GetPrivateKey(id2) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } if w.HasKeyPair(id1) { t.Fatalf("failed DeleteIdentity(pub1): still exist.") } if !w.HasKeyPair(id2) { t.Fatalf("failed DeleteIdentity(pub1): pub2 does not exist.") } if pk1 != nil { t.Fatalf("failed DeleteIdentity(pub1): first key still exist.") } if pk2 == nil { t.Fatalf("failed DeleteIdentity(pub1): second key does not exist.") } // Delete again non-existing identity done = w.DeleteKeyPair(id1) if done { t.Fatalf("delete id1: false positive.") } pk1, err = w.GetPrivateKey(id1) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } pk2, err = w.GetPrivateKey(id2) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } if w.HasKeyPair(id1) { t.Fatalf("failed delete non-existing identity: exist.") } if !w.HasKeyPair(id2) { t.Fatalf("failed delete non-existing identity: pub2 does not exist.") } if pk1 != nil { t.Fatalf("failed delete non-existing identity: first key exist.") } if pk2 == nil { t.Fatalf("failed delete non-existing identity: second key does not exist.") } // Delete second identity done = w.DeleteKeyPair(id2) if !done { t.Fatalf("failed to delete id2.") } pk1, err = w.GetPrivateKey(id1) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } pk2, err = w.GetPrivateKey(id2) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } if w.HasKeyPair(id1) { t.Fatalf("failed delete second identity: first identity exist.") } if w.HasKeyPair(id2) { t.Fatalf("failed delete second identity: still exist.") } if pk1 != nil { t.Fatalf("failed delete second identity: first key exist.") } if pk2 != nil { t.Fatalf("failed delete second identity: second key exist.") } } func TestSymKeyManagement(t *testing.T) { InitSingleTest() var err error var k1, k2 []byte w := New(nil, nil) id2 := "arbitrary-string-2" id1, err := w.GenerateSymKey() if err != nil { t.Fatalf("failed GenerateSymKey with seed %d: %s.", seed, err) } k1, err = w.GetSymKey(id1) if err != nil { t.Fatalf("failed GetSymKey(id1).") } k2, err = w.GetSymKey(id2) if err == nil { t.Fatalf("failed GetSymKey(id2): false positive.") } if !w.HasSymKey(id1) { t.Fatalf("failed HasSymKey(id1).") } if w.HasSymKey(id2) { t.Fatalf("failed HasSymKey(id2): false positive.") } if k1 == nil { t.Fatalf("first key does not exist.") } if k2 != nil { t.Fatalf("second key still exist.") } // add existing id, nothing should change randomKey := make([]byte, common.AESKeyLength) mrand.Read(randomKey) // nolint: gosec id1, err = w.AddSymKeyDirect(randomKey) if err != nil { t.Fatalf("failed AddSymKey with seed %d: %s.", seed, err) } k1, err = w.GetSymKey(id1) if err != nil { t.Fatalf("failed w.GetSymKey(id1).") } k2, err = w.GetSymKey(id2) if err == nil { t.Fatalf("failed w.GetSymKey(id2): false positive.") } if !w.HasSymKey(id1) { t.Fatalf("failed w.HasSymKey(id1).") } if w.HasSymKey(id2) { t.Fatalf("failed w.HasSymKey(id2): false positive.") } if k1 == nil { t.Fatalf("first key does not exist.") } if !bytes.Equal(k1, randomKey) { t.Fatalf("k1 != randomKey.") } if k2 != nil { t.Fatalf("second key already exist.") } id2, err = w.AddSymKeyDirect(randomKey) if err != nil { t.Fatalf("failed AddSymKey(id2) with seed %d: %s.", seed, err) } k1, err = w.GetSymKey(id1) if err != nil { t.Fatalf("failed w.GetSymKey(id1).") } k2, err = w.GetSymKey(id2) if err != nil { t.Fatalf("failed w.GetSymKey(id2).") } if !w.HasSymKey(id1) { t.Fatalf("HasSymKey(id1) failed.") } if !w.HasSymKey(id2) { t.Fatalf("HasSymKey(id2) failed.") } if k1 == nil { t.Fatalf("k1 does not exist.") } if k2 == nil { t.Fatalf("k2 does not exist.") } if !bytes.Equal(k1, k2) { t.Fatalf("k1 != k2.") } if !bytes.Equal(k1, randomKey) { t.Fatalf("k1 != randomKey.") } if len(k1) != common.AESKeyLength { t.Fatalf("wrong length of k1.") } if len(k2) != common.AESKeyLength { t.Fatalf("wrong length of k2.") } w.DeleteSymKey(id1) k1, err = w.GetSymKey(id1) if err == nil { t.Fatalf("failed w.GetSymKey(id1): false positive.") } if k1 != nil { t.Fatalf("failed GetSymKey(id1): false positive.") } k2, err = w.GetSymKey(id2) if err != nil { t.Fatalf("failed w.GetSymKey(id2).") } if w.HasSymKey(id1) { t.Fatalf("failed to delete first key: still exist.") } if !w.HasSymKey(id2) { t.Fatalf("failed to delete first key: second key does not exist.") } if k2 == nil { t.Fatalf("failed to delete first key: second key is nil.") } w.DeleteSymKey(id1) w.DeleteSymKey(id2) k1, err = w.GetSymKey(id1) if err == nil { t.Fatalf("failed w.GetSymKey(id1): false positive.") } k2, err = w.GetSymKey(id2) if err == nil { t.Fatalf("failed w.GetSymKey(id2): false positive.") } if k1 != nil || k2 != nil { t.Fatalf("k1 or k2 is not nil") } if w.HasSymKey(id1) { t.Fatalf("failed to delete second key: first key exist.") } if w.HasSymKey(id2) { t.Fatalf("failed to delete second key: still exist.") } randomKey = make([]byte, common.AESKeyLength+1) mrand.Read(randomKey) // nolint: gosec _, err = w.AddSymKeyDirect(randomKey) if err == nil { t.Fatalf("added the key with wrong size, seed %d.", seed) } const password = "arbitrary data here" id1, err = w.AddSymKeyFromPassword(password) if err != nil { t.Fatalf("failed AddSymKeyFromPassword(id1) with seed %d: %s.", seed, err) } id2, err = w.AddSymKeyFromPassword(password) if err != nil { t.Fatalf("failed AddSymKeyFromPassword(id2) with seed %d: %s.", seed, err) } k1, err = w.GetSymKey(id1) if err != nil { t.Fatalf("failed w.GetSymKey(id1).") } k2, err = w.GetSymKey(id2) if err != nil { t.Fatalf("failed w.GetSymKey(id2).") } if !w.HasSymKey(id1) { t.Fatalf("HasSymKey(id1) failed.") } if !w.HasSymKey(id2) { t.Fatalf("HasSymKey(id2) failed.") } if !common.ValidateDataIntegrity(k2, common.AESKeyLength) { t.Fatalf("key validation failed.") } if !bytes.Equal(k1, k2) { t.Fatalf("k1 != k2.") } } func TestExpiry(t *testing.T) { InitSingleTest() w := New(nil, nil) if err := w.SetMinimumPoW(0.0000001, false); err != nil { t.Fatal("failed to set min pow") } defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }() if err := w.Start(nil); err != nil { t.Fatal("failed to start waku") } defer func() { handleError(t, w.Stop()) }() params, err := generateMessageParams() if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } params.TTL = 1 messagesCount := 5 // Send a few messages one after another. Due to low PoW and expiration buckets // with one second resolution, it covers a case when there are multiple items // in a single expiration bucket. for i := 0; i < messagesCount; i++ { msg, err := common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err := msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } err = w.Send(env) if err != nil { t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) } } // wait till received or timeout var received, expired bool for j := 0; j < 20; j++ { time.Sleep(100 * time.Millisecond) if len(w.Envelopes()) == messagesCount { received = true break } } if !received { t.Fatalf("did not receive the sent envelope, seed: %d.", seed) } // wait till expired or timeout for j := 0; j < 20; j++ { time.Sleep(100 * time.Millisecond) if len(w.Envelopes()) == 0 { expired = true break } } if !expired { t.Fatalf("expire failed, seed: %d.", seed) } } func TestCustomization(t *testing.T) { InitSingleTest() w := New(nil, nil) defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }() defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }() if err := w.Start(nil); err != nil { t.Fatal("failed to start node") } defer func() { handleError(t, w.Stop()) }() const smallPoW = 0.00001 f, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } params, err := generateMessageParams() if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } params.KeySym = f.KeySym params.Topic = common.BytesToTopic(f.Topics[2]) params.PoW = smallPoW params.TTL = 3600 * 24 // one day msg, err := common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err := msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } err = w.Send(env) if err == nil { t.Fatalf("successfully sent envelope with PoW %.06f, false positive (seed %d).", env.PoW(), seed) } _ = w.SetMinimumPoW(smallPoW/2, true) err = w.Send(env) if err != nil { t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) } params.TTL++ msg, err = common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err = msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } _ = w.SetMaxMessageSize(uint32(env.Size() - 1)) err = w.Send(env) if err == nil { t.Fatalf("successfully sent oversized envelope (seed %d): false positive.", seed) } _ = w.SetMaxMessageSize(common.DefaultMaxMessageSize) err = w.Send(env) if err != nil { t.Fatalf("failed to send second envelope with seed %d: %s.", seed, err) } // wait till received or timeout var received bool for j := 0; j < 20; j++ { time.Sleep(100 * time.Millisecond) if len(w.Envelopes()) > 1 { received = true break } } if !received { t.Fatalf("did not receive the sent envelope, seed: %d.", seed) } // check w.messages() _, err = w.Subscribe(f) if err != nil { t.Fatalf("failed subscribe with seed %d: %s.", seed, err) } time.Sleep(5 * time.Millisecond) mail := f.Retrieve() if len(mail) > 0 { t.Fatalf("received premature mail") } } func TestSymmetricSendCycle(t *testing.T) { InitSingleTest() w := New(nil, nil) defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }() defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }() if err := w.Start(nil); err != nil { t.Fatal("failed to start node") } defer func() { handleError(t, w.Stop()) }() filter1, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter1.PoW = common.DefaultMinimumPoW // Copy the first filter since some of its fields // are randomly generated. filter2 := &common.Filter{ KeySym: filter1.KeySym, Topics: filter1.Topics, PoW: filter1.PoW, AllowP2P: filter1.AllowP2P, Messages: common.NewMemoryMessageStore(), } params, err := generateMessageParams() if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter1.Src = ¶ms.Src.PublicKey filter2.Src = ¶ms.Src.PublicKey params.KeySym = filter1.KeySym params.Topic = common.BytesToTopic(filter1.Topics[2]) params.PoW = filter1.PoW params.WorkTime = 10 params.TTL = 50 msg, err := common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err := msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter1) if err != nil { t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter2) if err != nil { t.Fatalf("failed subscribe 2 with seed %d: %s.", seed, err) } err = w.Send(env) if err != nil { t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err) } // wait till received or timeout var received bool for j := 0; j < 200; j++ { time.Sleep(10 * time.Millisecond) if len(w.Envelopes()) > 0 { received = true break } } if !received { t.Fatalf("did not receive the sent envelope, seed: %d.", seed) } // check w.messages() time.Sleep(5 * time.Millisecond) mail1 := filter1.Retrieve() mail2 := filter2.Retrieve() if len(mail2) == 0 { t.Fatalf("did not receive any email for filter 2") } if len(mail1) == 0 { t.Fatalf("did not receive any email for filter 1") } } func TestSymmetricSendCycleWithTopicInterest(t *testing.T) { InitSingleTest() w := New(nil, nil) defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }() defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }() if err := w.Start(nil); err != nil { t.Fatal("could not start node") } defer func() { handleError(t, w.Stop()) }() filter1, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter1.PoW = common.DefaultMinimumPoW // Copy the first filter since some of its fields // are randomly generated. filter2 := &common.Filter{ KeySym: filter1.KeySym, Topics: filter1.Topics, PoW: filter1.PoW, AllowP2P: filter1.AllowP2P, Messages: common.NewMemoryMessageStore(), } params, err := generateMessageParams() if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter1.Src = ¶ms.Src.PublicKey filter2.Src = ¶ms.Src.PublicKey params.KeySym = filter1.KeySym params.Topic = common.BytesToTopic(filter1.Topics[2]) params.PoW = filter1.PoW params.WorkTime = 10 params.TTL = 50 msg, err := common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err := msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter1) if err != nil { t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter2) if err != nil { t.Fatalf("failed subscribe 2 with seed %d: %s.", seed, err) } err = w.Send(env) if err != nil { t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err) } // wait till received or timeout var received bool for j := 0; j < 200; j++ { time.Sleep(10 * time.Millisecond) if len(w.Envelopes()) > 0 { received = true break } } if !received { t.Fatalf("did not receive the sent envelope, seed: %d.", seed) } // check w.messages() time.Sleep(5 * time.Millisecond) mail1 := filter1.Retrieve() mail2 := filter2.Retrieve() if len(mail2) == 0 { t.Fatalf("did not receive any email for filter 2") } if len(mail1) == 0 { t.Fatalf("did not receive any email for filter 1") } } func TestSymmetricSendWithoutAKey(t *testing.T) { InitSingleTest() w := New(nil, nil) if err := w.Start(nil); err != nil { t.Errorf("failed to start waku: '%s'", err) } defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }() defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }() defer func() { handleError(t, w.Stop()) }() filter, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter.PoW = common.DefaultMinimumPoW params, err := generateMessageParams() if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter.Src = nil params.KeySym = filter.KeySym params.Topic = common.BytesToTopic(filter.Topics[2]) params.PoW = filter.PoW params.WorkTime = 10 params.TTL = 50 msg, err := common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err := msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter) if err != nil { t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err) } err = w.Send(env) if err != nil { t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err) } // wait till received or timeout var received bool for j := 0; j < 200; j++ { time.Sleep(10 * time.Millisecond) if len(w.Envelopes()) > 0 { received = true break } } if !received { t.Fatalf("did not receive the sent envelope, seed: %d.", seed) } // check w.messages() time.Sleep(5 * time.Millisecond) mail := filter.Retrieve() if len(mail) == 0 { t.Fatalf("did not receive message in spite of not setting a public key") } } func TestSymmetricSendKeyMismatch(t *testing.T) { InitSingleTest() w := New(nil, nil) if err := w.Start(nil); err != nil { t.Errorf("failed to start waku: '%s'", err) } defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }() defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }() defer func() { handleError(t, w.Stop()) }() filter, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } filter.PoW = common.DefaultMinimumPoW params, err := generateMessageParams() if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } params.KeySym = filter.KeySym params.Topic = common.BytesToTopic(filter.Topics[2]) params.PoW = filter.PoW params.WorkTime = 10 params.TTL = 50 msg, err := common.NewSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } env, err := msg.Wrap(params, time.Now()) if err != nil { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter) if err != nil { t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err) } err = w.Send(env) if err != nil { t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err) } // wait till received or timeout var received bool for j := 0; j < 200; j++ { time.Sleep(10 * time.Millisecond) if len(w.Envelopes()) > 0 { received = true break } } if !received { t.Fatalf("did not receive the sent envelope, seed: %d.", seed) } // check w.messages() time.Sleep(5 * time.Millisecond) mail := filter.Retrieve() if len(mail) > 0 { t.Fatalf("received a message when keys weren't matching") } } func TestBloom(t *testing.T) { topic := common.TopicType{0, 0, 255, 6} b := topic.ToBloom() x := make([]byte, common.BloomFilterSize) x[0] = byte(1) x[32] = byte(1) x[common.BloomFilterSize-1] = byte(128) if !common.BloomFilterMatch(x, b) || !common.BloomFilterMatch(b, x) { t.Fatalf("bloom filter does not match the mask") } _, err := mrand.Read(b) // nolint: gosec if err != nil { t.Fatalf("math rand error") } _, err = mrand.Read(x) // nolint: gosec if err != nil { t.Fatalf("math rand error") } if !common.BloomFilterMatch(b, b) { t.Fatalf("bloom filter does not match self") } x = addBloom(x, b) if !common.BloomFilterMatch(x, b) { t.Fatalf("bloom filter does not match combined bloom") } if !common.IsFullNode(nil) { t.Fatalf("common.IsFullNode did not recognize nil as full node") } x[17] = 254 if common.IsFullNode(x) { t.Fatalf("common.IsFullNode false positive") } for i := 0; i < common.BloomFilterSize; i++ { b[i] = byte(255) } if !common.IsFullNode(b) { t.Fatalf("common.IsFullNode false negative") } if common.BloomFilterMatch(x, b) { t.Fatalf("bloomFilterMatch false positive") } if !common.BloomFilterMatch(b, x) { t.Fatalf("bloomFilterMatch false negative") } w := New(nil, nil) f := w.BloomFilter() if f != nil { t.Fatalf("wrong bloom on creation") } err = w.SetBloomFilter(x) if err != nil { t.Fatalf("failed to set bloom filter: %s", err) } f = w.BloomFilter() if !common.BloomFilterMatch(f, x) || !common.BloomFilterMatch(x, f) { t.Fatalf("retireved wrong bloom filter") } } func TestTopicInterest(t *testing.T) { w := New(nil, nil) topicInterest := w.TopicInterest() if topicInterest != nil { t.Fatalf("wrong topic on creation") } filter1, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter1) if err != nil { t.Fatalf("failed subscribe with seed %d: %s.", seed, err) } topicInterest = w.TopicInterest() if len(topicInterest) != len(filter1.Topics) { t.Fatalf("wrong number of topics created") } filter2, err := generateFilter(t, true) if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } _, err = w.Subscribe(filter2) if err != nil { t.Fatalf("failed subscribe with seed %d: %s.", seed, err) } topicInterest = w.TopicInterest() if len(topicInterest) != len(filter1.Topics)+len(filter2.Topics) { t.Fatalf("wrong number of topics created") } } func handleError(t *testing.T, err error) { if err != nil { t.Logf("deferred function error: '%s'", err) } } func generateFilter(t *testing.T, symmetric bool) (*common.Filter, error) { var f common.Filter f.Messages = common.NewMemoryMessageStore() const topicNum = 8 f.Topics = make([][]byte, topicNum) for i := 0; i < topicNum; i++ { f.Topics[i] = make([]byte, 4) mrand.Read(f.Topics[i]) // nolint: gosec f.Topics[i][0] = 0x01 } key, err := crypto.GenerateKey() if err != nil { t.Fatalf("generateFilter 1 failed with seed %d.", seed) return nil, err } f.Src = &key.PublicKey if symmetric { f.KeySym = make([]byte, common.AESKeyLength) mrand.Read(f.KeySym) // nolint: gosec f.SymKeyHash = crypto.Keccak256Hash(f.KeySym) } else { f.KeyAsym, err = crypto.GenerateKey() if err != nil { t.Fatalf("generateFilter 2 failed with seed %d.", seed) return nil, err } } // AcceptP2P & PoW are not set return &f, nil }