github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/whisper/whisperv5/filter_test.go (about) 1 // Copyright 2016 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 whisperv5 18 19 import ( 20 "math/big" 21 "math/rand" 22 "testing" 23 "time" 24 25 "github.com/atheioschain/go-atheios/common" 26 "github.com/atheioschain/go-atheios/crypto" 27 ) 28 29 var seed int64 30 31 // InitSingleTest should be called in the beginning of every 32 // test, which uses RNG, in order to make the tests 33 // reproduciblity independent of their sequence. 34 func InitSingleTest() { 35 seed = time.Now().Unix() 36 rand.Seed(seed) 37 } 38 39 func InitDebugTest(i int64) { 40 seed = i 41 rand.Seed(seed) 42 } 43 44 type FilterTestCase struct { 45 f *Filter 46 id uint32 47 alive bool 48 msgCnt int 49 } 50 51 func generateFilter(t *testing.T, symmetric bool) (*Filter, error) { 52 var f Filter 53 f.Messages = make(map[common.Hash]*ReceivedMessage) 54 55 const topicNum = 8 56 f.Topics = make([]TopicType, topicNum) 57 for i := 0; i < topicNum; i++ { 58 randomize(f.Topics[i][:]) 59 f.Topics[i][0] = 0x01 60 } 61 62 key, err := crypto.GenerateKey() 63 if err != nil { 64 t.Fatalf("generateFilter 1 failed with seed %d.", seed) 65 return nil, err 66 } 67 f.Src = &key.PublicKey 68 69 if symmetric { 70 f.KeySym = make([]byte, 12) 71 randomize(f.KeySym) 72 f.SymKeyHash = crypto.Keccak256Hash(f.KeySym) 73 } else { 74 f.KeyAsym, err = crypto.GenerateKey() 75 if err != nil { 76 t.Fatalf("generateFilter 2 failed with seed %d.", seed) 77 return nil, err 78 } 79 } 80 81 // AcceptP2P & PoW are not set 82 return &f, nil 83 } 84 85 func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase { 86 cases := make([]FilterTestCase, SizeTestFilters) 87 for i := 0; i < SizeTestFilters; i++ { 88 f, _ := generateFilter(t, true) 89 cases[i].f = f 90 cases[i].alive = (rand.Int()&int(1) == 0) 91 } 92 return cases 93 } 94 95 func TestInstallFilters(t *testing.T) { 96 InitSingleTest() 97 98 const SizeTestFilters = 256 99 w := NewWhisper(nil) 100 filters := NewFilters(w) 101 tst := generateTestCases(t, SizeTestFilters) 102 103 var j uint32 104 for i := 0; i < SizeTestFilters; i++ { 105 j = filters.Install(tst[i].f) 106 tst[i].id = j 107 } 108 109 if j < SizeTestFilters-1 { 110 t.Fatalf("seed %d: wrong index %d", seed, j) 111 } 112 113 for _, testCase := range tst { 114 if !testCase.alive { 115 filters.Uninstall(testCase.id) 116 } 117 } 118 119 for i, testCase := range tst { 120 fil := filters.Get(testCase.id) 121 exist := (fil != nil) 122 if exist != testCase.alive { 123 t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive) 124 } 125 if exist && fil.PoW != testCase.f.PoW { 126 t.Fatalf("seed %d: failed Get: %d, %v, %v", seed, i, exist, testCase.alive) 127 } 128 } 129 } 130 131 func TestComparePubKey(t *testing.T) { 132 InitSingleTest() 133 134 key1, err := crypto.GenerateKey() 135 if err != nil { 136 t.Fatalf("failed to generate first key with seed %d: %s.", seed, err) 137 } 138 key2, err := crypto.GenerateKey() 139 if err != nil { 140 t.Fatalf("failed to generate second key with seed %d: %s.", seed, err) 141 } 142 if IsPubKeyEqual(&key1.PublicKey, &key2.PublicKey) { 143 t.Fatalf("public keys are equal, seed %d.", seed) 144 } 145 146 // generate key3 == key1 147 rand.Seed(seed) 148 key3, err := crypto.GenerateKey() 149 if err != nil { 150 t.Fatalf("failed to generate third key with seed %d: %s.", seed, err) 151 } 152 if IsPubKeyEqual(&key1.PublicKey, &key3.PublicKey) { 153 t.Fatalf("key1 == key3, seed %d.", seed) 154 } 155 } 156 157 func TestMatchEnvelope(t *testing.T) { 158 InitSingleTest() 159 160 fsym, err := generateFilter(t, true) 161 if err != nil { 162 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 163 } 164 165 fasym, err := generateFilter(t, false) 166 if err != nil { 167 t.Fatalf("failed generateFilter() with seed %d: %s.", seed, err) 168 } 169 170 params, err := generateMessageParams() 171 if err != nil { 172 t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) 173 } 174 175 params.Topic[0] = 0xFF // ensure mismatch 176 177 // mismatch with pseudo-random data 178 msg := NewSentMessage(params) 179 env, err := msg.Wrap(params) 180 if err != nil { 181 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 182 } 183 match := fsym.MatchEnvelope(env) 184 if match { 185 t.Fatalf("failed MatchEnvelope symmetric with seed %d.", seed) 186 } 187 match = fasym.MatchEnvelope(env) 188 if match { 189 t.Fatalf("failed MatchEnvelope asymmetric with seed %d.", seed) 190 } 191 192 // encrypt symmetrically 193 i := rand.Int() % 4 194 fsym.Topics[i] = params.Topic 195 fasym.Topics[i] = params.Topic 196 msg = NewSentMessage(params) 197 env, err = msg.Wrap(params) 198 if err != nil { 199 t.Fatalf("failed Wrap() with seed %d: %s.", seed, err) 200 } 201 202 // symmetric + matching topic: match 203 match = fsym.MatchEnvelope(env) 204 if !match { 205 t.Fatalf("failed MatchEnvelope() symmetric with seed %d.", seed) 206 } 207 208 // asymmetric + matching topic: mismatch 209 match = fasym.MatchEnvelope(env) 210 if match { 211 t.Fatalf("failed MatchEnvelope() asymmetric with seed %d.", seed) 212 } 213 214 // symmetric + matching topic + insufficient PoW: mismatch 215 fsym.PoW = env.PoW() + 1.0 216 match = fsym.MatchEnvelope(env) 217 if match { 218 t.Fatalf("failed MatchEnvelope(symmetric + matching topic + insufficient PoW) asymmetric with seed %d.", seed) 219 } 220 221 // symmetric + matching topic + sufficient PoW: match 222 fsym.PoW = env.PoW() / 2 223 match = fsym.MatchEnvelope(env) 224 if !match { 225 t.Fatalf("failed MatchEnvelope(symmetric + matching topic + sufficient PoW) with seed %d.", seed) 226 } 227 228 // symmetric + topics are nil (wildcard): match 229 prevTopics := fsym.Topics 230 fsym.Topics = nil 231 match = fsym.MatchEnvelope(env) 232 if !match { 233 t.Fatalf("failed MatchEnvelope(symmetric + topics are nil) with seed %d.", seed) 234 } 235 fsym.Topics = prevTopics 236 237 // encrypt asymmetrically 238 key, err := crypto.GenerateKey() 239 if err != nil { 240 t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err) 241 } 242 params.KeySym = nil 243 params.Dst = &key.PublicKey 244 msg = NewSentMessage(params) 245 env, err = msg.Wrap(params) 246 if err != nil { 247 t.Fatalf("failed Wrap() with seed %d: %s.", seed, err) 248 } 249 250 // encryption method mismatch 251 match = fsym.MatchEnvelope(env) 252 if match { 253 t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed) 254 } 255 256 // asymmetric + mismatching topic: mismatch 257 match = fasym.MatchEnvelope(env) 258 if !match { 259 t.Fatalf("failed MatchEnvelope(asymmetric + mismatching topic) with seed %d.", seed) 260 } 261 262 // asymmetric + matching topic: match 263 fasym.Topics[i] = fasym.Topics[i+1] 264 match = fasym.MatchEnvelope(env) 265 if match { 266 t.Fatalf("failed MatchEnvelope(asymmetric + matching topic) with seed %d.", seed) 267 } 268 269 // asymmetric + filter without topic (wildcard): match 270 fasym.Topics = nil 271 match = fasym.MatchEnvelope(env) 272 if !match { 273 t.Fatalf("failed MatchEnvelope(asymmetric + filter without topic) with seed %d.", seed) 274 } 275 276 // asymmetric + insufficient PoW: mismatch 277 fasym.PoW = env.PoW() + 1.0 278 match = fasym.MatchEnvelope(env) 279 if match { 280 t.Fatalf("failed MatchEnvelope(asymmetric + insufficient PoW) with seed %d.", seed) 281 } 282 283 // asymmetric + sufficient PoW: match 284 fasym.PoW = env.PoW() / 2 285 match = fasym.MatchEnvelope(env) 286 if !match { 287 t.Fatalf("failed MatchEnvelope(asymmetric + sufficient PoW) with seed %d.", seed) 288 } 289 290 // filter without topic + envelope without topic: match 291 env.Topic = TopicType{} 292 match = fasym.MatchEnvelope(env) 293 if !match { 294 t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed) 295 } 296 297 // filter with topic + envelope without topic: mismatch 298 fasym.Topics = fsym.Topics 299 match = fasym.MatchEnvelope(env) 300 if match { 301 t.Fatalf("failed MatchEnvelope(filter without topic + envelope without topic) with seed %d.", seed) 302 } 303 } 304 305 func TestMatchMessageSym(t *testing.T) { 306 InitSingleTest() 307 308 params, err := generateMessageParams() 309 if err != nil { 310 t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) 311 } 312 313 f, err := generateFilter(t, true) 314 if err != nil { 315 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 316 } 317 318 const index = 1 319 params.KeySym = f.KeySym 320 params.Topic = f.Topics[index] 321 322 sentMessage := NewSentMessage(params) 323 env, err := sentMessage.Wrap(params) 324 if err != nil { 325 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 326 } 327 328 msg := env.Open(f) 329 if msg == nil { 330 t.Fatalf("failed Open with seed %d.", seed) 331 } 332 333 // Src mismatch 334 if f.MatchMessage(msg) { 335 t.Fatalf("failed MatchMessage(src mismatch) with seed %d.", seed) 336 } 337 338 // Src: match 339 *f.Src.X = *params.Src.PublicKey.X 340 *f.Src.Y = *params.Src.PublicKey.Y 341 if !f.MatchMessage(msg) { 342 t.Fatalf("failed MatchEnvelope(src match) with seed %d.", seed) 343 } 344 345 // insufficient PoW: mismatch 346 f.PoW = msg.PoW + 1.0 347 if f.MatchMessage(msg) { 348 t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed) 349 } 350 351 // sufficient PoW: match 352 f.PoW = msg.PoW / 2 353 if !f.MatchMessage(msg) { 354 t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed) 355 } 356 357 // topic mismatch 358 f.Topics[index][0]++ 359 if f.MatchMessage(msg) { 360 t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed) 361 } 362 f.Topics[index][0]-- 363 364 // key mismatch 365 f.SymKeyHash[0]++ 366 if f.MatchMessage(msg) { 367 t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed) 368 } 369 f.SymKeyHash[0]-- 370 371 // Src absent: match 372 f.Src = nil 373 if !f.MatchMessage(msg) { 374 t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed) 375 } 376 377 // key hash mismatch 378 h := f.SymKeyHash 379 f.SymKeyHash = common.Hash{} 380 if f.MatchMessage(msg) { 381 t.Fatalf("failed MatchEnvelope(key hash mismatch) with seed %d.", seed) 382 } 383 f.SymKeyHash = h 384 if !f.MatchMessage(msg) { 385 t.Fatalf("failed MatchEnvelope(key hash match) with seed %d.", seed) 386 } 387 388 // encryption method mismatch 389 f.KeySym = nil 390 f.KeyAsym, err = crypto.GenerateKey() 391 if err != nil { 392 t.Fatalf("failed GenerateKey with seed %d: %s.", seed, err) 393 } 394 if f.MatchMessage(msg) { 395 t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed) 396 } 397 } 398 399 func TestMatchMessageAsym(t *testing.T) { 400 InitSingleTest() 401 402 f, err := generateFilter(t, false) 403 if err != nil { 404 t.Fatalf("failed generateFilter with seed %d: %s.", seed, err) 405 } 406 407 params, err := generateMessageParams() 408 if err != nil { 409 t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) 410 } 411 412 const index = 1 413 params.Topic = f.Topics[index] 414 params.Dst = &f.KeyAsym.PublicKey 415 keySymOrig := params.KeySym 416 params.KeySym = nil 417 418 sentMessage := NewSentMessage(params) 419 env, err := sentMessage.Wrap(params) 420 if err != nil { 421 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 422 } 423 424 msg := env.Open(f) 425 if msg == nil { 426 t.Fatalf("failed to open with seed %d.", seed) 427 } 428 429 // Src mismatch 430 if f.MatchMessage(msg) { 431 t.Fatalf("failed MatchMessage(src mismatch) with seed %d.", seed) 432 } 433 434 // Src: match 435 *f.Src.X = *params.Src.PublicKey.X 436 *f.Src.Y = *params.Src.PublicKey.Y 437 if !f.MatchMessage(msg) { 438 t.Fatalf("failed MatchMessage(src match) with seed %d.", seed) 439 } 440 441 // insufficient PoW: mismatch 442 f.PoW = msg.PoW + 1.0 443 if f.MatchMessage(msg) { 444 t.Fatalf("failed MatchEnvelope(insufficient PoW) with seed %d.", seed) 445 } 446 447 // sufficient PoW: match 448 f.PoW = msg.PoW / 2 449 if !f.MatchMessage(msg) { 450 t.Fatalf("failed MatchEnvelope(sufficient PoW) with seed %d.", seed) 451 } 452 453 // topic mismatch 454 f.Topics[index][0]++ 455 if f.MatchMessage(msg) { 456 t.Fatalf("failed MatchEnvelope(topic mismatch) with seed %d.", seed) 457 } 458 f.Topics[index][0]-- 459 460 // key mismatch 461 prev := *f.KeyAsym.PublicKey.X 462 zero := *big.NewInt(0) 463 *f.KeyAsym.PublicKey.X = zero 464 if f.MatchMessage(msg) { 465 t.Fatalf("failed MatchEnvelope(key mismatch) with seed %d.", seed) 466 } 467 *f.KeyAsym.PublicKey.X = prev 468 469 // Src absent: match 470 f.Src = nil 471 if !f.MatchMessage(msg) { 472 t.Fatalf("failed MatchEnvelope(src absent) with seed %d.", seed) 473 } 474 475 // encryption method mismatch 476 f.KeySym = keySymOrig 477 f.KeyAsym = nil 478 if f.MatchMessage(msg) { 479 t.Fatalf("failed MatchEnvelope(encryption method mismatch) with seed %d.", seed) 480 } 481 } 482 483 func cloneFilter(orig *Filter) *Filter { 484 var clone Filter 485 clone.Messages = make(map[common.Hash]*ReceivedMessage) 486 clone.Src = orig.Src 487 clone.KeyAsym = orig.KeyAsym 488 clone.KeySym = orig.KeySym 489 clone.Topics = orig.Topics 490 clone.PoW = orig.PoW 491 clone.AcceptP2P = orig.AcceptP2P 492 clone.SymKeyHash = orig.SymKeyHash 493 return &clone 494 } 495 496 func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope { 497 params, err := generateMessageParams() 498 if err != nil { 499 t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) 500 return nil 501 } 502 503 params.KeySym = f.KeySym 504 params.Topic = f.Topics[2] 505 sentMessage := NewSentMessage(params) 506 env, err := sentMessage.Wrap(params) 507 if err != nil { 508 t.Fatalf("failed Wrap with seed %d: %s.", seed, err) 509 return nil 510 } 511 return env 512 } 513 514 func TestWatchers(t *testing.T) { 515 InitSingleTest() 516 517 const NumFilters = 16 518 const NumMessages = 256 519 var i int 520 var j uint32 521 var e *Envelope 522 523 w := NewWhisper(nil) 524 filters := NewFilters(w) 525 tst := generateTestCases(t, NumFilters) 526 for i = 0; i < NumFilters; i++ { 527 tst[i].f.Src = nil 528 j = filters.Install(tst[i].f) 529 tst[i].id = j 530 } 531 532 last := j 533 534 var envelopes [NumMessages]*Envelope 535 for i = 0; i < NumMessages; i++ { 536 j = rand.Uint32() % NumFilters 537 e = generateCompatibeEnvelope(t, tst[j].f) 538 envelopes[i] = e 539 tst[j].msgCnt++ 540 } 541 542 for i = 0; i < NumMessages; i++ { 543 filters.NotifyWatchers(envelopes[i], false) 544 } 545 546 var total int 547 var mail []*ReceivedMessage 548 var count [NumFilters]int 549 550 for i = 0; i < NumFilters; i++ { 551 mail = tst[i].f.Retrieve() 552 count[i] = len(mail) 553 total += len(mail) 554 } 555 556 if total != NumMessages { 557 t.Fatalf("failed with seed %d: total = %d, want: %d.", seed, total, NumMessages) 558 } 559 560 for i = 0; i < NumFilters; i++ { 561 mail = tst[i].f.Retrieve() 562 if len(mail) != 0 { 563 t.Fatalf("failed with seed %d: i = %d.", seed, i) 564 } 565 566 if tst[i].msgCnt != count[i] { 567 t.Fatalf("failed with seed %d: count[%d]: get %d, want %d.", seed, i, tst[i].msgCnt, count[i]) 568 } 569 } 570 571 // another round with a cloned filter 572 573 clone := cloneFilter(tst[0].f) 574 filters.Uninstall(last) 575 total = 0 576 last = NumFilters - 1 577 tst[last].f = clone 578 filters.Install(clone) 579 for i = 0; i < NumFilters; i++ { 580 tst[i].msgCnt = 0 581 count[i] = 0 582 } 583 584 // make sure that the first watcher receives at least one message 585 e = generateCompatibeEnvelope(t, tst[0].f) 586 envelopes[0] = e 587 tst[0].msgCnt++ 588 for i = 1; i < NumMessages; i++ { 589 j = rand.Uint32() % NumFilters 590 e = generateCompatibeEnvelope(t, tst[j].f) 591 envelopes[i] = e 592 tst[j].msgCnt++ 593 } 594 595 for i = 0; i < NumMessages; i++ { 596 filters.NotifyWatchers(envelopes[i], false) 597 } 598 599 for i = 0; i < NumFilters; i++ { 600 mail = tst[i].f.Retrieve() 601 count[i] = len(mail) 602 total += len(mail) 603 } 604 605 combined := tst[0].msgCnt + tst[last].msgCnt 606 if total != NumMessages+count[0] { 607 t.Fatalf("failed with seed %d: total = %d, count[0] = %d.", seed, total, count[0]) 608 } 609 610 if combined != count[0] { 611 t.Fatalf("failed with seed %d: combined = %d, count[0] = %d.", seed, combined, count[0]) 612 } 613 614 if combined != count[last] { 615 t.Fatalf("failed with seed %d: combined = %d, count[last] = %d.", seed, combined, count[last]) 616 } 617 618 for i = 1; i < NumFilters-1; i++ { 619 mail = tst[i].f.Retrieve() 620 if len(mail) != 0 { 621 t.Fatalf("failed with seed %d: i = %d.", seed, i) 622 } 623 624 if tst[i].msgCnt != count[i] { 625 t.Fatalf("failed with seed %d: i = %d, get %d, want %d.", seed, i, tst[i].msgCnt, count[i]) 626 } 627 } 628 629 // test AcceptP2P 630 631 total = 0 632 filters.NotifyWatchers(envelopes[0], true) 633 634 for i = 0; i < NumFilters; i++ { 635 mail = tst[i].f.Retrieve() 636 total += len(mail) 637 } 638 639 if total != 0 { 640 t.Fatalf("failed with seed %d: total: got %d, want 0.", seed, total) 641 } 642 643 f := filters.Get(1) 644 if f == nil { 645 t.Fatalf("failed to get the filter with seed %d.", seed) 646 } 647 f.AcceptP2P = true 648 total = 0 649 filters.NotifyWatchers(envelopes[0], true) 650 651 for i = 0; i < NumFilters; i++ { 652 mail = tst[i].f.Retrieve() 653 total += len(mail) 654 } 655 656 if total != 1 { 657 t.Fatalf("failed with seed %d: total: got %d, want 1.", seed, total) 658 } 659 }