github.com/googgoog/go-ethereum@v1.9.7/whisper/mailserver/server_test.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package mailserver 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "encoding/binary" 23 "io/ioutil" 24 "math/rand" 25 "testing" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/crypto" 30 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 31 ) 32 33 const powRequirement = 0.00001 34 35 var keyID string 36 var shh *whisper.Whisper 37 var seed = time.Now().Unix() 38 39 type ServerTestParams struct { 40 topic whisper.TopicType 41 low uint32 42 upp uint32 43 key *ecdsa.PrivateKey 44 } 45 46 func assert(statement bool, text string, t *testing.T) { 47 if !statement { 48 t.Fatal(text) 49 } 50 } 51 52 func TestDBKey(t *testing.T) { 53 var h common.Hash 54 i := uint32(time.Now().Unix()) 55 k := NewDbKey(i, h) 56 assert(len(k.raw) == common.HashLength+4, "wrong DB key length", t) 57 assert(byte(i%0x100) == k.raw[3], "raw representation should be big endian", t) 58 assert(byte(i/0x1000000) == k.raw[0], "big endian expected", t) 59 } 60 61 func generateEnvelope(t *testing.T) *whisper.Envelope { 62 h := crypto.Keccak256Hash([]byte("test sample data")) 63 params := &whisper.MessageParams{ 64 KeySym: h[:], 65 Topic: whisper.TopicType{0x1F, 0x7E, 0xA1, 0x7F}, 66 Payload: []byte("test payload"), 67 PoW: powRequirement, 68 WorkTime: 2, 69 } 70 71 msg, err := whisper.NewSentMessage(params) 72 if err != nil { 73 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 74 } 75 env, err := msg.Wrap(params) 76 if err != nil { 77 t.Fatalf("failed to wrap with seed %d: %s.", seed, err) 78 } 79 return env 80 } 81 82 func TestMailServer(t *testing.T) { 83 const password = "password_for_this_test" 84 const dbPath = "whisper-server-test" 85 86 dir, err := ioutil.TempDir("", dbPath) 87 if err != nil { 88 t.Fatal(err) 89 } 90 91 var server WMailServer 92 shh = whisper.New(&whisper.DefaultConfig) 93 shh.RegisterServer(&server) 94 95 err = server.Init(shh, dir, password, powRequirement) 96 if err != nil { 97 t.Fatal(err) 98 } 99 defer server.Close() 100 101 keyID, err = shh.AddSymKeyFromPassword(password) 102 if err != nil { 103 t.Fatalf("Failed to create symmetric key for mail request: %s", err) 104 } 105 106 rand.Seed(seed) 107 env := generateEnvelope(t) 108 server.Archive(env) 109 deliverTest(t, &server, env) 110 } 111 112 func deliverTest(t *testing.T, server *WMailServer, env *whisper.Envelope) { 113 id, err := shh.NewKeyPair() 114 if err != nil { 115 t.Fatalf("failed to generate new key pair with seed %d: %s.", seed, err) 116 } 117 testPeerID, err := shh.GetPrivateKey(id) 118 if err != nil { 119 t.Fatalf("failed to retrieve new key pair with seed %d: %s.", seed, err) 120 } 121 birth := env.Expiry - env.TTL 122 p := &ServerTestParams{ 123 topic: env.Topic, 124 low: birth - 1, 125 upp: birth + 1, 126 key: testPeerID, 127 } 128 129 singleRequest(t, server, env, p, true) 130 131 p.low, p.upp = birth+1, 0xffffffff 132 singleRequest(t, server, env, p, false) 133 134 p.low, p.upp = 0, birth-1 135 singleRequest(t, server, env, p, false) 136 137 p.low = birth - 1 138 p.upp = birth + 1 139 p.topic[0] = 0xFF 140 singleRequest(t, server, env, p, false) 141 } 142 143 func singleRequest(t *testing.T, server *WMailServer, env *whisper.Envelope, p *ServerTestParams, expect bool) { 144 request := createRequest(t, p) 145 src := crypto.FromECDSAPub(&p.key.PublicKey) 146 ok, lower, upper, bloom := server.validateRequest(src, request) 147 if !ok { 148 t.Fatalf("request validation failed, seed: %d.", seed) 149 } 150 if lower != p.low { 151 t.Fatalf("request validation failed (lower bound), seed: %d.", seed) 152 } 153 if upper != p.upp { 154 t.Fatalf("request validation failed (upper bound), seed: %d.", seed) 155 } 156 expectedBloom := whisper.TopicToBloom(p.topic) 157 if !bytes.Equal(bloom, expectedBloom) { 158 t.Fatalf("request validation failed (topic), seed: %d.", seed) 159 } 160 161 var exist bool 162 mail := server.processRequest(nil, p.low, p.upp, bloom) 163 for _, msg := range mail { 164 if msg.Hash() == env.Hash() { 165 exist = true 166 break 167 } 168 } 169 170 if exist != expect { 171 t.Fatalf("error: exist = %v, seed: %d.", exist, seed) 172 } 173 174 src[0]++ 175 ok, lower, upper, _ = server.validateRequest(src, request) 176 if !ok { 177 // request should be valid regardless of signature 178 t.Fatalf("request validation false negative, seed: %d (lower: %d, upper: %d).", seed, lower, upper) 179 } 180 } 181 182 func createRequest(t *testing.T, p *ServerTestParams) *whisper.Envelope { 183 bloom := whisper.TopicToBloom(p.topic) 184 data := make([]byte, 8) 185 binary.BigEndian.PutUint32(data, p.low) 186 binary.BigEndian.PutUint32(data[4:], p.upp) 187 data = append(data, bloom...) 188 189 key, err := shh.GetSymKey(keyID) 190 if err != nil { 191 t.Fatalf("failed to retrieve sym key with seed %d: %s.", seed, err) 192 } 193 194 params := &whisper.MessageParams{ 195 KeySym: key, 196 Topic: p.topic, 197 Payload: data, 198 PoW: powRequirement * 2, 199 WorkTime: 2, 200 Src: p.key, 201 } 202 203 msg, err := whisper.NewSentMessage(params) 204 if err != nil { 205 t.Fatalf("failed to create new message with seed %d: %s.", seed, err) 206 } 207 env, err := msg.Wrap(params) 208 if err != nil { 209 t.Fatalf("failed to wrap with seed %d: %s.", seed, err) 210 } 211 return env 212 }