github.com/daragao/go-ethereum@v1.8.14-0.20180809141559-45eaef243198/swarm/pss/pss_test.go (about) 1 // Copyright 2018 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 pss 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/ecdsa" 23 "encoding/binary" 24 "encoding/hex" 25 "encoding/json" 26 "flag" 27 "fmt" 28 "io/ioutil" 29 "math/rand" 30 "os" 31 "strconv" 32 "strings" 33 "sync" 34 "testing" 35 "time" 36 37 "github.com/ethereum/go-ethereum/common" 38 "github.com/ethereum/go-ethereum/common/hexutil" 39 "github.com/ethereum/go-ethereum/crypto" 40 "github.com/ethereum/go-ethereum/log" 41 "github.com/ethereum/go-ethereum/metrics" 42 "github.com/ethereum/go-ethereum/metrics/influxdb" 43 "github.com/ethereum/go-ethereum/node" 44 "github.com/ethereum/go-ethereum/p2p" 45 "github.com/ethereum/go-ethereum/p2p/discover" 46 "github.com/ethereum/go-ethereum/p2p/protocols" 47 "github.com/ethereum/go-ethereum/p2p/simulations" 48 "github.com/ethereum/go-ethereum/p2p/simulations/adapters" 49 "github.com/ethereum/go-ethereum/rpc" 50 "github.com/ethereum/go-ethereum/swarm/network" 51 "github.com/ethereum/go-ethereum/swarm/state" 52 whisper "github.com/ethereum/go-ethereum/whisper/whisperv5" 53 ) 54 55 var ( 56 initOnce = sync.Once{} 57 debugdebugflag = flag.Bool("vv", false, "veryverbose") 58 debugflag = flag.Bool("v", false, "verbose") 59 longrunning = flag.Bool("longrunning", false, "do run long-running tests") 60 w *whisper.Whisper 61 wapi *whisper.PublicWhisperAPI 62 psslogmain log.Logger 63 pssprotocols map[string]*protoCtrl 64 useHandshake bool 65 ) 66 67 func init() { 68 flag.Parse() 69 rand.Seed(time.Now().Unix()) 70 71 adapters.RegisterServices(newServices(false)) 72 initTest() 73 } 74 75 func initTest() { 76 initOnce.Do( 77 func() { 78 loglevel := log.LvlInfo 79 if *debugflag { 80 loglevel = log.LvlDebug 81 } else if *debugdebugflag { 82 loglevel = log.LvlTrace 83 } 84 85 psslogmain = log.New("psslog", "*") 86 hs := log.StreamHandler(os.Stderr, log.TerminalFormat(true)) 87 hf := log.LvlFilterHandler(loglevel, hs) 88 h := log.CallerFileHandler(hf) 89 log.Root().SetHandler(h) 90 91 w = whisper.New(&whisper.DefaultConfig) 92 wapi = whisper.NewPublicWhisperAPI(w) 93 94 pssprotocols = make(map[string]*protoCtrl) 95 }, 96 ) 97 } 98 99 // test that topic conversion functions give predictable results 100 func TestTopic(t *testing.T) { 101 102 api := &API{} 103 104 topicstr := strings.Join([]string{PingProtocol.Name, strconv.Itoa(int(PingProtocol.Version))}, ":") 105 106 // bytestotopic is the authoritative topic conversion source 107 topicobj := BytesToTopic([]byte(topicstr)) 108 109 // string to topic and bytes to topic must match 110 topicapiobj, _ := api.StringToTopic(topicstr) 111 if topicobj != topicapiobj { 112 t.Fatalf("bytes and string topic conversion mismatch; %s != %s", topicobj, topicapiobj) 113 } 114 115 // string representation of topichex 116 topichex := topicobj.String() 117 118 // protocoltopic wrapper on pingtopic should be same as topicstring 119 // check that it matches 120 pingtopichex := PingTopic.String() 121 if topichex != pingtopichex { 122 t.Fatalf("protocol topic conversion mismatch; %s != %s", topichex, pingtopichex) 123 } 124 125 // json marshal of topic 126 topicjsonout, err := topicobj.MarshalJSON() 127 if err != nil { 128 t.Fatal(err) 129 } 130 if string(topicjsonout)[1:len(topicjsonout)-1] != topichex { 131 t.Fatalf("topic json marshal mismatch; %s != \"%s\"", topicjsonout, topichex) 132 } 133 134 // json unmarshal of topic 135 var topicjsonin Topic 136 topicjsonin.UnmarshalJSON(topicjsonout) 137 if topicjsonin != topicobj { 138 t.Fatalf("topic json unmarshal mismatch: %x != %x", topicjsonin, topicobj) 139 } 140 } 141 142 // test bit packing of message control flags 143 func TestMsgParams(t *testing.T) { 144 var ctrl byte 145 ctrl |= pssControlRaw 146 p := newMsgParamsFromBytes([]byte{ctrl}) 147 m := newPssMsg(p) 148 if !m.isRaw() || m.isSym() { 149 t.Fatal("expected raw=true and sym=false") 150 } 151 ctrl |= pssControlSym 152 p = newMsgParamsFromBytes([]byte{ctrl}) 153 m = newPssMsg(p) 154 if !m.isRaw() || !m.isSym() { 155 t.Fatal("expected raw=true and sym=true") 156 } 157 ctrl &= 0xff &^ pssControlRaw 158 p = newMsgParamsFromBytes([]byte{ctrl}) 159 m = newPssMsg(p) 160 if m.isRaw() || !m.isSym() { 161 t.Fatal("expected raw=false and sym=true") 162 } 163 } 164 165 // test if we can insert into cache, match items with cache and cache expiry 166 func TestCache(t *testing.T) { 167 var err error 168 to, _ := hex.DecodeString("08090a0b0c0d0e0f1011121314150001020304050607161718191a1b1c1d1e1f") 169 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 170 defer cancel() 171 keys, err := wapi.NewKeyPair(ctx) 172 privkey, err := w.GetPrivateKey(keys) 173 if err != nil { 174 t.Fatal(err) 175 } 176 ps := newTestPss(privkey, nil, nil) 177 pp := NewPssParams().WithPrivateKey(privkey) 178 data := []byte("foo") 179 datatwo := []byte("bar") 180 datathree := []byte("baz") 181 wparams := &whisper.MessageParams{ 182 TTL: defaultWhisperTTL, 183 Src: privkey, 184 Dst: &privkey.PublicKey, 185 Topic: whisper.TopicType(PingTopic), 186 WorkTime: defaultWhisperWorkTime, 187 PoW: defaultWhisperPoW, 188 Payload: data, 189 } 190 woutmsg, err := whisper.NewSentMessage(wparams) 191 env, err := woutmsg.Wrap(wparams) 192 msg := &PssMsg{ 193 Payload: env, 194 To: to, 195 } 196 wparams.Payload = datatwo 197 woutmsg, err = whisper.NewSentMessage(wparams) 198 envtwo, err := woutmsg.Wrap(wparams) 199 msgtwo := &PssMsg{ 200 Payload: envtwo, 201 To: to, 202 } 203 wparams.Payload = datathree 204 woutmsg, err = whisper.NewSentMessage(wparams) 205 envthree, err := woutmsg.Wrap(wparams) 206 msgthree := &PssMsg{ 207 Payload: envthree, 208 To: to, 209 } 210 211 digest := ps.digest(msg) 212 if err != nil { 213 t.Fatalf("could not store cache msgone: %v", err) 214 } 215 digesttwo := ps.digest(msgtwo) 216 if err != nil { 217 t.Fatalf("could not store cache msgtwo: %v", err) 218 } 219 digestthree := ps.digest(msgthree) 220 if err != nil { 221 t.Fatalf("could not store cache msgthree: %v", err) 222 } 223 224 if digest == digesttwo { 225 t.Fatalf("different msgs return same hash: %d", digesttwo) 226 } 227 228 // check the cache 229 err = ps.addFwdCache(msg) 230 if err != nil { 231 t.Fatalf("write to pss expire cache failed: %v", err) 232 } 233 234 if !ps.checkFwdCache(msg) { 235 t.Fatalf("message %v should have EXPIRE record in cache but checkCache returned false", msg) 236 } 237 238 if ps.checkFwdCache(msgtwo) { 239 t.Fatalf("message %v should NOT have EXPIRE record in cache but checkCache returned true", msgtwo) 240 } 241 242 time.Sleep(pp.CacheTTL + 1*time.Second) 243 err = ps.addFwdCache(msgthree) 244 if err != nil { 245 t.Fatalf("write to pss expire cache failed: %v", err) 246 } 247 248 if ps.checkFwdCache(msg) { 249 t.Fatalf("message %v should have expired from cache but checkCache returned true", msg) 250 } 251 252 if _, ok := ps.fwdCache[digestthree]; !ok { 253 t.Fatalf("unexpired message should be in the cache: %v", digestthree) 254 } 255 256 if _, ok := ps.fwdCache[digesttwo]; ok { 257 t.Fatalf("expired message should have been cleared from the cache: %v", digesttwo) 258 } 259 } 260 261 // matching of address hints; whether a message could be or is for the node 262 func TestAddressMatch(t *testing.T) { 263 264 localaddr := network.RandomAddr().Over() 265 copy(localaddr[:8], []byte("deadbeef")) 266 remoteaddr := []byte("feedbeef") 267 kadparams := network.NewKadParams() 268 kad := network.NewKademlia(localaddr, kadparams) 269 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 270 defer cancel() 271 keys, err := wapi.NewKeyPair(ctx) 272 if err != nil { 273 t.Fatalf("Could not generate private key: %v", err) 274 } 275 privkey, err := w.GetPrivateKey(keys) 276 pssp := NewPssParams().WithPrivateKey(privkey) 277 ps, err := NewPss(kad, pssp) 278 if err != nil { 279 t.Fatal(err.Error()) 280 } 281 282 pssmsg := &PssMsg{ 283 To: remoteaddr, 284 Payload: &whisper.Envelope{}, 285 } 286 287 // differ from first byte 288 if ps.isSelfRecipient(pssmsg) { 289 t.Fatalf("isSelfRecipient true but %x != %x", remoteaddr, localaddr) 290 } 291 if ps.isSelfPossibleRecipient(pssmsg) { 292 t.Fatalf("isSelfPossibleRecipient true but %x != %x", remoteaddr[:8], localaddr[:8]) 293 } 294 295 // 8 first bytes same 296 copy(remoteaddr[:4], localaddr[:4]) 297 if ps.isSelfRecipient(pssmsg) { 298 t.Fatalf("isSelfRecipient true but %x != %x", remoteaddr, localaddr) 299 } 300 if !ps.isSelfPossibleRecipient(pssmsg) { 301 t.Fatalf("isSelfPossibleRecipient false but %x == %x", remoteaddr[:8], localaddr[:8]) 302 } 303 304 // all bytes same 305 pssmsg.To = localaddr 306 if !ps.isSelfRecipient(pssmsg) { 307 t.Fatalf("isSelfRecipient false but %x == %x", remoteaddr, localaddr) 308 } 309 if !ps.isSelfPossibleRecipient(pssmsg) { 310 t.Fatalf("isSelfPossibleRecipient false but %x == %x", remoteaddr[:8], localaddr[:8]) 311 } 312 } 313 314 // 315 func TestHandlerConditions(t *testing.T) { 316 317 t.Skip("Disabled due to probable faulty logic for outbox expectations") 318 // setup 319 privkey, err := crypto.GenerateKey() 320 if err != nil { 321 t.Fatal(err.Error()) 322 } 323 324 addr := make([]byte, 32) 325 addr[0] = 0x01 326 ps := newTestPss(privkey, network.NewKademlia(addr, network.NewKadParams()), NewPssParams()) 327 328 // message should pass 329 msg := &PssMsg{ 330 To: addr, 331 Expire: uint32(time.Now().Add(time.Second * 60).Unix()), 332 Payload: &whisper.Envelope{ 333 Topic: [4]byte{}, 334 Data: []byte{0x66, 0x6f, 0x6f}, 335 }, 336 } 337 if err := ps.handlePssMsg(context.TODO(), msg); err != nil { 338 t.Fatal(err.Error()) 339 } 340 tmr := time.NewTimer(time.Millisecond * 100) 341 var outmsg *PssMsg 342 select { 343 case outmsg = <-ps.outbox: 344 case <-tmr.C: 345 default: 346 } 347 if outmsg != nil { 348 t.Fatalf("expected outbox empty after full address on msg, but had message %s", msg) 349 } 350 351 // message should pass and queue due to partial length 352 msg.To = addr[0:1] 353 msg.Payload.Data = []byte{0x78, 0x79, 0x80, 0x80, 0x79} 354 if err := ps.handlePssMsg(context.TODO(), msg); err != nil { 355 t.Fatal(err.Error()) 356 } 357 tmr.Reset(time.Millisecond * 100) 358 outmsg = nil 359 select { 360 case outmsg = <-ps.outbox: 361 case <-tmr.C: 362 } 363 if outmsg == nil { 364 t.Fatal("expected message in outbox on encrypt fail, but empty") 365 } 366 outmsg = nil 367 select { 368 case outmsg = <-ps.outbox: 369 default: 370 } 371 if outmsg != nil { 372 t.Fatalf("expected only one queued message but also had message %v", msg) 373 } 374 375 // full address mismatch should put message in queue 376 msg.To[0] = 0xff 377 if err := ps.handlePssMsg(context.TODO(), msg); err != nil { 378 t.Fatal(err.Error()) 379 } 380 tmr.Reset(time.Millisecond * 10) 381 outmsg = nil 382 select { 383 case outmsg = <-ps.outbox: 384 case <-tmr.C: 385 } 386 if outmsg == nil { 387 t.Fatal("expected message in outbox on address mismatch, but empty") 388 } 389 outmsg = nil 390 select { 391 case outmsg = <-ps.outbox: 392 default: 393 } 394 if outmsg != nil { 395 t.Fatalf("expected only one queued message but also had message %v", msg) 396 } 397 398 // expired message should be dropped 399 msg.Expire = uint32(time.Now().Add(-time.Second).Unix()) 400 if err := ps.handlePssMsg(context.TODO(), msg); err != nil { 401 t.Fatal(err.Error()) 402 } 403 tmr.Reset(time.Millisecond * 10) 404 outmsg = nil 405 select { 406 case outmsg = <-ps.outbox: 407 case <-tmr.C: 408 default: 409 } 410 if outmsg != nil { 411 t.Fatalf("expected empty queue but have message %v", msg) 412 } 413 414 // invalid message should return error 415 fckedupmsg := &struct { 416 pssMsg *PssMsg 417 }{ 418 pssMsg: &PssMsg{}, 419 } 420 if err := ps.handlePssMsg(context.TODO(), fckedupmsg); err == nil { 421 t.Fatalf("expected error from processMsg but error nil") 422 } 423 424 // outbox full should return error 425 msg.Expire = uint32(time.Now().Add(time.Second * 60).Unix()) 426 for i := 0; i < defaultOutboxCapacity; i++ { 427 ps.outbox <- msg 428 } 429 msg.Payload.Data = []byte{0x62, 0x61, 0x72} 430 err = ps.handlePssMsg(context.TODO(), msg) 431 if err == nil { 432 t.Fatal("expected error when mailbox full, but was nil") 433 } 434 } 435 436 // set and generate pubkeys and symkeys 437 func TestKeys(t *testing.T) { 438 // make our key and init pss with it 439 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 440 defer cancel() 441 ourkeys, err := wapi.NewKeyPair(ctx) 442 if err != nil { 443 t.Fatalf("create 'our' key fail") 444 } 445 ctx, cancel2 := context.WithTimeout(context.Background(), time.Second) 446 defer cancel2() 447 theirkeys, err := wapi.NewKeyPair(ctx) 448 if err != nil { 449 t.Fatalf("create 'their' key fail") 450 } 451 ourprivkey, err := w.GetPrivateKey(ourkeys) 452 if err != nil { 453 t.Fatalf("failed to retrieve 'our' private key") 454 } 455 theirprivkey, err := w.GetPrivateKey(theirkeys) 456 if err != nil { 457 t.Fatalf("failed to retrieve 'their' private key") 458 } 459 ps := newTestPss(ourprivkey, nil, nil) 460 461 // set up peer with mock address, mapped to mocked publicaddress and with mocked symkey 462 addr := make(PssAddress, 32) 463 copy(addr, network.RandomAddr().Over()) 464 outkey := network.RandomAddr().Over() 465 topicobj := BytesToTopic([]byte("foo:42")) 466 ps.SetPeerPublicKey(&theirprivkey.PublicKey, topicobj, &addr) 467 outkeyid, err := ps.SetSymmetricKey(outkey, topicobj, &addr, false) 468 if err != nil { 469 t.Fatalf("failed to set 'our' outgoing symmetric key") 470 } 471 472 // make a symmetric key that we will send to peer for encrypting messages to us 473 inkeyid, err := ps.GenerateSymmetricKey(topicobj, &addr, true) 474 if err != nil { 475 t.Fatalf("failed to set 'our' incoming symmetric key") 476 } 477 478 // get the key back from whisper, check that it's still the same 479 outkeyback, err := ps.w.GetSymKey(outkeyid) 480 if err != nil { 481 t.Fatalf(err.Error()) 482 } 483 inkey, err := ps.w.GetSymKey(inkeyid) 484 if err != nil { 485 t.Fatalf(err.Error()) 486 } 487 if !bytes.Equal(outkeyback, outkey) { 488 t.Fatalf("passed outgoing symkey doesnt equal stored: %x / %x", outkey, outkeyback) 489 } 490 491 t.Logf("symout: %v", outkeyback) 492 t.Logf("symin: %v", inkey) 493 494 // check that the key is stored in the peerpool 495 psp := ps.symKeyPool[inkeyid][topicobj] 496 if psp.address != &addr { 497 t.Fatalf("inkey address does not match; %p != %p", psp.address, &addr) 498 } 499 } 500 501 func TestGetPublickeyEntries(t *testing.T) { 502 503 privkey, err := crypto.GenerateKey() 504 if err != nil { 505 t.Fatal(err) 506 } 507 ps := newTestPss(privkey, nil, nil) 508 509 peeraddr := network.RandomAddr().Over() 510 topicaddr := make(map[Topic]PssAddress) 511 topicaddr[Topic{0x13}] = peeraddr 512 topicaddr[Topic{0x2a}] = peeraddr[:16] 513 topicaddr[Topic{0x02, 0x9a}] = []byte{} 514 515 remoteprivkey, err := crypto.GenerateKey() 516 if err != nil { 517 t.Fatal(err) 518 } 519 remotepubkeybytes := crypto.FromECDSAPub(&remoteprivkey.PublicKey) 520 remotepubkeyhex := common.ToHex(remotepubkeybytes) 521 522 pssapi := NewAPI(ps) 523 524 for to, a := range topicaddr { 525 err = pssapi.SetPeerPublicKey(remotepubkeybytes, to, a) 526 if err != nil { 527 t.Fatal(err) 528 } 529 } 530 531 intopic, err := pssapi.GetPeerTopics(remotepubkeyhex) 532 if err != nil { 533 t.Fatal(err) 534 } 535 536 OUTER: 537 for _, tnew := range intopic { 538 for torig, addr := range topicaddr { 539 if bytes.Equal(torig[:], tnew[:]) { 540 inaddr, err := pssapi.GetPeerAddress(remotepubkeyhex, torig) 541 if err != nil { 542 t.Fatal(err) 543 } 544 if !bytes.Equal(addr, inaddr) { 545 t.Fatalf("Address mismatch for topic %x; got %x, expected %x", torig, inaddr, addr) 546 } 547 delete(topicaddr, torig) 548 continue OUTER 549 } 550 } 551 t.Fatalf("received topic %x did not match any existing topics", tnew) 552 } 553 554 if len(topicaddr) != 0 { 555 t.Fatalf("%d topics were not matched", len(topicaddr)) 556 } 557 } 558 559 type pssTestPeer struct { 560 *protocols.Peer 561 addr []byte 562 } 563 564 func (t *pssTestPeer) Address() []byte { 565 return t.addr 566 } 567 568 func (t *pssTestPeer) Update(addr network.OverlayAddr) network.OverlayAddr { 569 return addr 570 } 571 572 func (t *pssTestPeer) Off() network.OverlayAddr { 573 return &pssTestPeer{} 574 } 575 576 // forwarding should skip peers that do not have matching pss capabilities 577 func TestMismatch(t *testing.T) { 578 579 // create privkey for forwarder node 580 privkey, err := crypto.GenerateKey() 581 if err != nil { 582 t.Fatal(err) 583 } 584 585 // initialize overlay 586 baseaddr := network.RandomAddr() 587 kad := network.NewKademlia((baseaddr).Over(), network.NewKadParams()) 588 rw := &p2p.MsgPipeRW{} 589 590 // one peer has a mismatching version of pss 591 wrongpssaddr := network.RandomAddr() 592 wrongpsscap := p2p.Cap{ 593 Name: pssProtocolName, 594 Version: 0, 595 } 596 nid, _ := discover.HexID("0x01") 597 wrongpsspeer := &pssTestPeer{ 598 Peer: protocols.NewPeer(p2p.NewPeer(nid, common.ToHex(wrongpssaddr.Over()), []p2p.Cap{wrongpsscap}), rw, nil), 599 addr: wrongpssaddr.Over(), 600 } 601 602 // one peer doesn't even have pss (boo!) 603 nopssaddr := network.RandomAddr() 604 nopsscap := p2p.Cap{ 605 Name: "nopss", 606 Version: 1, 607 } 608 nid, _ = discover.HexID("0x02") 609 nopsspeer := &pssTestPeer{ 610 Peer: protocols.NewPeer(p2p.NewPeer(nid, common.ToHex(nopssaddr.Over()), []p2p.Cap{nopsscap}), rw, nil), 611 addr: nopssaddr.Over(), 612 } 613 614 // add peers to kademlia and activate them 615 // it's safe so don't check errors 616 kad.Register([]network.OverlayAddr{wrongpsspeer}) 617 kad.On(wrongpsspeer) 618 kad.Register([]network.OverlayAddr{nopsspeer}) 619 kad.On(nopsspeer) 620 621 // create pss 622 pssmsg := &PssMsg{ 623 To: []byte{}, 624 Expire: uint32(time.Now().Add(time.Second).Unix()), 625 Payload: &whisper.Envelope{}, 626 } 627 ps := newTestPss(privkey, kad, nil) 628 629 // run the forward 630 // it is enough that it completes; trying to send to incapable peers would create segfault 631 ps.forward(pssmsg) 632 633 } 634 635 func TestSendRaw(t *testing.T) { 636 t.Run("32", testSendRaw) 637 t.Run("8", testSendRaw) 638 t.Run("0", testSendRaw) 639 } 640 641 func testSendRaw(t *testing.T) { 642 643 var addrsize int64 644 var err error 645 646 paramstring := strings.Split(t.Name(), "/") 647 648 addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) 649 log.Info("raw send test", "addrsize", addrsize) 650 651 clients, err := setupNetwork(2, true) 652 if err != nil { 653 t.Fatal(err) 654 } 655 656 topic := "0xdeadbeef" 657 658 var loaddrhex string 659 err = clients[0].Call(&loaddrhex, "pss_baseAddr") 660 if err != nil { 661 t.Fatalf("rpc get node 1 baseaddr fail: %v", err) 662 } 663 loaddrhex = loaddrhex[:2+(addrsize*2)] 664 var roaddrhex string 665 err = clients[1].Call(&roaddrhex, "pss_baseAddr") 666 if err != nil { 667 t.Fatalf("rpc get node 2 baseaddr fail: %v", err) 668 } 669 roaddrhex = roaddrhex[:2+(addrsize*2)] 670 671 time.Sleep(time.Millisecond * 500) 672 673 // at this point we've verified that symkeys are saved and match on each peer 674 // now try sending symmetrically encrypted message, both directions 675 lmsgC := make(chan APIMsg) 676 lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10) 677 defer lcancel() 678 lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) 679 log.Trace("lsub", "id", lsub) 680 defer lsub.Unsubscribe() 681 rmsgC := make(chan APIMsg) 682 rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10) 683 defer rcancel() 684 rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) 685 log.Trace("rsub", "id", rsub) 686 defer rsub.Unsubscribe() 687 688 // send and verify delivery 689 lmsg := []byte("plugh") 690 err = clients[1].Call(nil, "pss_sendRaw", loaddrhex, topic, lmsg) 691 if err != nil { 692 t.Fatal(err) 693 } 694 select { 695 case recvmsg := <-lmsgC: 696 if !bytes.Equal(recvmsg.Msg, lmsg) { 697 t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg) 698 } 699 case cerr := <-lctx.Done(): 700 t.Fatalf("test message (left) timed out: %v", cerr) 701 } 702 rmsg := []byte("xyzzy") 703 err = clients[0].Call(nil, "pss_sendRaw", roaddrhex, topic, rmsg) 704 if err != nil { 705 t.Fatal(err) 706 } 707 select { 708 case recvmsg := <-rmsgC: 709 if !bytes.Equal(recvmsg.Msg, rmsg) { 710 t.Fatalf("node 2 received payload mismatch: expected %x, got %v", rmsg, recvmsg.Msg) 711 } 712 case cerr := <-rctx.Done(): 713 t.Fatalf("test message (right) timed out: %v", cerr) 714 } 715 } 716 717 // send symmetrically encrypted message between two directly connected peers 718 func TestSendSym(t *testing.T) { 719 t.Run("32", testSendSym) 720 t.Run("8", testSendSym) 721 t.Run("0", testSendSym) 722 } 723 724 func testSendSym(t *testing.T) { 725 726 // address hint size 727 var addrsize int64 728 var err error 729 paramstring := strings.Split(t.Name(), "/") 730 addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) 731 log.Info("sym send test", "addrsize", addrsize) 732 733 clients, err := setupNetwork(2, false) 734 if err != nil { 735 t.Fatal(err) 736 } 737 738 var topic string 739 err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") 740 if err != nil { 741 t.Fatal(err) 742 } 743 744 var loaddrhex string 745 err = clients[0].Call(&loaddrhex, "pss_baseAddr") 746 if err != nil { 747 t.Fatalf("rpc get node 1 baseaddr fail: %v", err) 748 } 749 loaddrhex = loaddrhex[:2+(addrsize*2)] 750 var roaddrhex string 751 err = clients[1].Call(&roaddrhex, "pss_baseAddr") 752 if err != nil { 753 t.Fatalf("rpc get node 2 baseaddr fail: %v", err) 754 } 755 roaddrhex = roaddrhex[:2+(addrsize*2)] 756 757 // retrieve public key from pss instance 758 // set this public key reciprocally 759 var lpubkeyhex string 760 err = clients[0].Call(&lpubkeyhex, "pss_getPublicKey") 761 if err != nil { 762 t.Fatalf("rpc get node 1 pubkey fail: %v", err) 763 } 764 var rpubkeyhex string 765 err = clients[1].Call(&rpubkeyhex, "pss_getPublicKey") 766 if err != nil { 767 t.Fatalf("rpc get node 2 pubkey fail: %v", err) 768 } 769 770 time.Sleep(time.Millisecond * 500) 771 772 // at this point we've verified that symkeys are saved and match on each peer 773 // now try sending symmetrically encrypted message, both directions 774 lmsgC := make(chan APIMsg) 775 lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10) 776 defer lcancel() 777 lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) 778 log.Trace("lsub", "id", lsub) 779 defer lsub.Unsubscribe() 780 rmsgC := make(chan APIMsg) 781 rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10) 782 defer rcancel() 783 rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) 784 log.Trace("rsub", "id", rsub) 785 defer rsub.Unsubscribe() 786 787 lrecvkey := network.RandomAddr().Over() 788 rrecvkey := network.RandomAddr().Over() 789 790 var lkeyids [2]string 791 var rkeyids [2]string 792 793 // manually set reciprocal symkeys 794 err = clients[0].Call(&lkeyids, "psstest_setSymKeys", rpubkeyhex, lrecvkey, rrecvkey, defaultSymKeySendLimit, topic, roaddrhex) 795 if err != nil { 796 t.Fatal(err) 797 } 798 err = clients[1].Call(&rkeyids, "psstest_setSymKeys", lpubkeyhex, rrecvkey, lrecvkey, defaultSymKeySendLimit, topic, loaddrhex) 799 if err != nil { 800 t.Fatal(err) 801 } 802 803 // send and verify delivery 804 lmsg := []byte("plugh") 805 err = clients[1].Call(nil, "pss_sendSym", rkeyids[1], topic, hexutil.Encode(lmsg)) 806 if err != nil { 807 t.Fatal(err) 808 } 809 select { 810 case recvmsg := <-lmsgC: 811 if !bytes.Equal(recvmsg.Msg, lmsg) { 812 t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg) 813 } 814 case cerr := <-lctx.Done(): 815 t.Fatalf("test message timed out: %v", cerr) 816 } 817 rmsg := []byte("xyzzy") 818 err = clients[0].Call(nil, "pss_sendSym", lkeyids[1], topic, hexutil.Encode(rmsg)) 819 if err != nil { 820 t.Fatal(err) 821 } 822 select { 823 case recvmsg := <-rmsgC: 824 if !bytes.Equal(recvmsg.Msg, rmsg) { 825 t.Fatalf("node 2 received payload mismatch: expected %x, got %v", rmsg, recvmsg.Msg) 826 } 827 case cerr := <-rctx.Done(): 828 t.Fatalf("test message timed out: %v", cerr) 829 } 830 } 831 832 // send asymmetrically encrypted message between two directly connected peers 833 func TestSendAsym(t *testing.T) { 834 t.Run("32", testSendAsym) 835 t.Run("8", testSendAsym) 836 t.Run("0", testSendAsym) 837 } 838 839 func testSendAsym(t *testing.T) { 840 841 // address hint size 842 var addrsize int64 843 var err error 844 paramstring := strings.Split(t.Name(), "/") 845 addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0) 846 log.Info("asym send test", "addrsize", addrsize) 847 848 clients, err := setupNetwork(2, false) 849 if err != nil { 850 t.Fatal(err) 851 } 852 853 var topic string 854 err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") 855 if err != nil { 856 t.Fatal(err) 857 } 858 859 time.Sleep(time.Millisecond * 250) 860 861 var loaddrhex string 862 err = clients[0].Call(&loaddrhex, "pss_baseAddr") 863 if err != nil { 864 t.Fatalf("rpc get node 1 baseaddr fail: %v", err) 865 } 866 loaddrhex = loaddrhex[:2+(addrsize*2)] 867 var roaddrhex string 868 err = clients[1].Call(&roaddrhex, "pss_baseAddr") 869 if err != nil { 870 t.Fatalf("rpc get node 2 baseaddr fail: %v", err) 871 } 872 roaddrhex = roaddrhex[:2+(addrsize*2)] 873 874 // retrieve public key from pss instance 875 // set this public key reciprocally 876 var lpubkey string 877 err = clients[0].Call(&lpubkey, "pss_getPublicKey") 878 if err != nil { 879 t.Fatalf("rpc get node 1 pubkey fail: %v", err) 880 } 881 var rpubkey string 882 err = clients[1].Call(&rpubkey, "pss_getPublicKey") 883 if err != nil { 884 t.Fatalf("rpc get node 2 pubkey fail: %v", err) 885 } 886 887 time.Sleep(time.Millisecond * 500) // replace with hive healthy code 888 889 lmsgC := make(chan APIMsg) 890 lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10) 891 defer lcancel() 892 lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic) 893 log.Trace("lsub", "id", lsub) 894 defer lsub.Unsubscribe() 895 rmsgC := make(chan APIMsg) 896 rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10) 897 defer rcancel() 898 rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) 899 log.Trace("rsub", "id", rsub) 900 defer rsub.Unsubscribe() 901 902 // store reciprocal public keys 903 err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, roaddrhex) 904 if err != nil { 905 t.Fatal(err) 906 } 907 err = clients[1].Call(nil, "pss_setPeerPublicKey", lpubkey, topic, loaddrhex) 908 if err != nil { 909 t.Fatal(err) 910 } 911 912 // send and verify delivery 913 rmsg := []byte("xyzzy") 914 err = clients[0].Call(nil, "pss_sendAsym", rpubkey, topic, hexutil.Encode(rmsg)) 915 if err != nil { 916 t.Fatal(err) 917 } 918 select { 919 case recvmsg := <-rmsgC: 920 if !bytes.Equal(recvmsg.Msg, rmsg) { 921 t.Fatalf("node 2 received payload mismatch: expected %v, got %v", rmsg, recvmsg.Msg) 922 } 923 case cerr := <-rctx.Done(): 924 t.Fatalf("test message timed out: %v", cerr) 925 } 926 lmsg := []byte("plugh") 927 err = clients[1].Call(nil, "pss_sendAsym", lpubkey, topic, hexutil.Encode(lmsg)) 928 if err != nil { 929 t.Fatal(err) 930 } 931 select { 932 case recvmsg := <-lmsgC: 933 if !bytes.Equal(recvmsg.Msg, lmsg) { 934 t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg.Msg) 935 } 936 case cerr := <-lctx.Done(): 937 t.Fatalf("test message timed out: %v", cerr) 938 } 939 } 940 941 type Job struct { 942 Msg []byte 943 SendNode discover.NodeID 944 RecvNode discover.NodeID 945 } 946 947 func worker(id int, jobs <-chan Job, rpcs map[discover.NodeID]*rpc.Client, pubkeys map[discover.NodeID]string, topic string) { 948 for j := range jobs { 949 rpcs[j.SendNode].Call(nil, "pss_sendAsym", pubkeys[j.RecvNode], topic, hexutil.Encode(j.Msg)) 950 } 951 } 952 953 func TestNetwork(t *testing.T) { 954 t.Run("16/1000/4/sim", testNetwork) 955 } 956 957 // params in run name: 958 // nodes/msgs/addrbytes/adaptertype 959 // if adaptertype is exec uses execadapter, simadapter otherwise 960 func TestNetwork2000(t *testing.T) { 961 //enableMetrics() 962 963 if !*longrunning { 964 t.Skip("run with --longrunning flag to run extensive network tests") 965 } 966 t.Run("3/2000/4/sim", testNetwork) 967 t.Run("4/2000/4/sim", testNetwork) 968 t.Run("8/2000/4/sim", testNetwork) 969 t.Run("16/2000/4/sim", testNetwork) 970 } 971 972 func TestNetwork5000(t *testing.T) { 973 //enableMetrics() 974 975 if !*longrunning { 976 t.Skip("run with --longrunning flag to run extensive network tests") 977 } 978 t.Run("3/5000/4/sim", testNetwork) 979 t.Run("4/5000/4/sim", testNetwork) 980 t.Run("8/5000/4/sim", testNetwork) 981 t.Run("16/5000/4/sim", testNetwork) 982 } 983 984 func TestNetwork10000(t *testing.T) { 985 //enableMetrics() 986 987 if !*longrunning { 988 t.Skip("run with --longrunning flag to run extensive network tests") 989 } 990 t.Run("3/10000/4/sim", testNetwork) 991 t.Run("4/10000/4/sim", testNetwork) 992 t.Run("8/10000/4/sim", testNetwork) 993 } 994 995 func testNetwork(t *testing.T) { 996 type msgnotifyC struct { 997 id discover.NodeID 998 msgIdx int 999 } 1000 1001 paramstring := strings.Split(t.Name(), "/") 1002 nodecount, _ := strconv.ParseInt(paramstring[1], 10, 0) 1003 msgcount, _ := strconv.ParseInt(paramstring[2], 10, 0) 1004 addrsize, _ := strconv.ParseInt(paramstring[3], 10, 0) 1005 adapter := paramstring[4] 1006 1007 log.Info("network test", "nodecount", nodecount, "msgcount", msgcount, "addrhintsize", addrsize) 1008 1009 nodes := make([]discover.NodeID, nodecount) 1010 bzzaddrs := make(map[discover.NodeID]string, nodecount) 1011 rpcs := make(map[discover.NodeID]*rpc.Client, nodecount) 1012 pubkeys := make(map[discover.NodeID]string, nodecount) 1013 1014 sentmsgs := make([][]byte, msgcount) 1015 recvmsgs := make([]bool, msgcount) 1016 nodemsgcount := make(map[discover.NodeID]int, nodecount) 1017 1018 trigger := make(chan discover.NodeID) 1019 1020 var a adapters.NodeAdapter 1021 if adapter == "exec" { 1022 dirname, err := ioutil.TempDir(".", "") 1023 if err != nil { 1024 t.Fatal(err) 1025 } 1026 a = adapters.NewExecAdapter(dirname) 1027 } else if adapter == "tcp" { 1028 a = adapters.NewTCPAdapter(newServices(false)) 1029 } else if adapter == "sim" { 1030 a = adapters.NewSimAdapter(newServices(false)) 1031 } 1032 net := simulations.NewNetwork(a, &simulations.NetworkConfig{ 1033 ID: "0", 1034 }) 1035 defer net.Shutdown() 1036 1037 f, err := os.Open(fmt.Sprintf("testdata/snapshot_%d.json", nodecount)) 1038 if err != nil { 1039 t.Fatal(err) 1040 } 1041 jsonbyte, err := ioutil.ReadAll(f) 1042 if err != nil { 1043 t.Fatal(err) 1044 } 1045 var snap simulations.Snapshot 1046 err = json.Unmarshal(jsonbyte, &snap) 1047 if err != nil { 1048 t.Fatal(err) 1049 } 1050 err = net.Load(&snap) 1051 if err != nil { 1052 //TODO: Fix p2p simulation framework to not crash when loading 32-nodes 1053 //t.Fatal(err) 1054 } 1055 1056 time.Sleep(1 * time.Second) 1057 1058 triggerChecks := func(trigger chan discover.NodeID, id discover.NodeID, rpcclient *rpc.Client, topic string) error { 1059 msgC := make(chan APIMsg) 1060 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 1061 defer cancel() 1062 sub, err := rpcclient.Subscribe(ctx, "pss", msgC, "receive", topic) 1063 if err != nil { 1064 t.Fatal(err) 1065 } 1066 go func() { 1067 defer sub.Unsubscribe() 1068 for { 1069 select { 1070 case recvmsg := <-msgC: 1071 idx, _ := binary.Uvarint(recvmsg.Msg) 1072 if !recvmsgs[idx] { 1073 log.Debug("msg recv", "idx", idx, "id", id) 1074 recvmsgs[idx] = true 1075 trigger <- id 1076 } 1077 case <-sub.Err(): 1078 return 1079 } 1080 } 1081 }() 1082 return nil 1083 } 1084 1085 var topic string 1086 for i, nod := range net.GetNodes() { 1087 nodes[i] = nod.ID() 1088 rpcs[nodes[i]], err = nod.Client() 1089 if err != nil { 1090 t.Fatal(err) 1091 } 1092 if topic == "" { 1093 err = rpcs[nodes[i]].Call(&topic, "pss_stringToTopic", "foo:42") 1094 if err != nil { 1095 t.Fatal(err) 1096 } 1097 } 1098 var pubkey string 1099 err = rpcs[nodes[i]].Call(&pubkey, "pss_getPublicKey") 1100 if err != nil { 1101 t.Fatal(err) 1102 } 1103 pubkeys[nod.ID()] = pubkey 1104 var addrhex string 1105 err = rpcs[nodes[i]].Call(&addrhex, "pss_baseAddr") 1106 if err != nil { 1107 t.Fatal(err) 1108 } 1109 bzzaddrs[nodes[i]] = addrhex 1110 err = triggerChecks(trigger, nodes[i], rpcs[nodes[i]], topic) 1111 if err != nil { 1112 t.Fatal(err) 1113 } 1114 } 1115 1116 time.Sleep(1 * time.Second) 1117 1118 // setup workers 1119 jobs := make(chan Job, 10) 1120 for w := 1; w <= 10; w++ { 1121 go worker(w, jobs, rpcs, pubkeys, topic) 1122 } 1123 1124 time.Sleep(1 * time.Second) 1125 1126 for i := 0; i < int(msgcount); i++ { 1127 sendnodeidx := rand.Intn(int(nodecount)) 1128 recvnodeidx := rand.Intn(int(nodecount - 1)) 1129 if recvnodeidx >= sendnodeidx { 1130 recvnodeidx++ 1131 } 1132 nodemsgcount[nodes[recvnodeidx]]++ 1133 sentmsgs[i] = make([]byte, 8) 1134 c := binary.PutUvarint(sentmsgs[i], uint64(i)) 1135 if c == 0 { 1136 t.Fatal("0 byte message") 1137 } 1138 if err != nil { 1139 t.Fatal(err) 1140 } 1141 err = rpcs[nodes[sendnodeidx]].Call(nil, "pss_setPeerPublicKey", pubkeys[nodes[recvnodeidx]], topic, bzzaddrs[nodes[recvnodeidx]]) 1142 if err != nil { 1143 t.Fatal(err) 1144 } 1145 1146 jobs <- Job{ 1147 Msg: sentmsgs[i], 1148 SendNode: nodes[sendnodeidx], 1149 RecvNode: nodes[recvnodeidx], 1150 } 1151 } 1152 1153 finalmsgcount := 0 1154 ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) 1155 defer cancel() 1156 outer: 1157 for i := 0; i < int(msgcount); i++ { 1158 select { 1159 case id := <-trigger: 1160 nodemsgcount[id]-- 1161 finalmsgcount++ 1162 case <-ctx.Done(): 1163 log.Warn("timeout") 1164 break outer 1165 } 1166 } 1167 1168 for i, msg := range recvmsgs { 1169 if !msg { 1170 log.Debug("missing message", "idx", i) 1171 } 1172 } 1173 t.Logf("%d of %d messages received", finalmsgcount, msgcount) 1174 1175 if finalmsgcount != int(msgcount) { 1176 t.Fatalf("%d messages were not received", int(msgcount)-finalmsgcount) 1177 } 1178 1179 } 1180 1181 // check that in a network of a -> b -> c -> a 1182 // a doesn't receive a sent message twice 1183 func TestDeduplication(t *testing.T) { 1184 var err error 1185 1186 clients, err := setupNetwork(3, false) 1187 if err != nil { 1188 t.Fatal(err) 1189 } 1190 1191 var addrsize = 32 1192 var loaddrhex string 1193 err = clients[0].Call(&loaddrhex, "pss_baseAddr") 1194 if err != nil { 1195 t.Fatalf("rpc get node 1 baseaddr fail: %v", err) 1196 } 1197 loaddrhex = loaddrhex[:2+(addrsize*2)] 1198 var roaddrhex string 1199 err = clients[1].Call(&roaddrhex, "pss_baseAddr") 1200 if err != nil { 1201 t.Fatalf("rpc get node 2 baseaddr fail: %v", err) 1202 } 1203 roaddrhex = roaddrhex[:2+(addrsize*2)] 1204 var xoaddrhex string 1205 err = clients[2].Call(&xoaddrhex, "pss_baseAddr") 1206 if err != nil { 1207 t.Fatalf("rpc get node 3 baseaddr fail: %v", err) 1208 } 1209 xoaddrhex = xoaddrhex[:2+(addrsize*2)] 1210 1211 log.Info("peer", "l", loaddrhex, "r", roaddrhex, "x", xoaddrhex) 1212 1213 var topic string 1214 err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42") 1215 if err != nil { 1216 t.Fatal(err) 1217 } 1218 1219 time.Sleep(time.Millisecond * 250) 1220 1221 // retrieve public key from pss instance 1222 // set this public key reciprocally 1223 var rpubkey string 1224 err = clients[1].Call(&rpubkey, "pss_getPublicKey") 1225 if err != nil { 1226 t.Fatalf("rpc get receivenode pubkey fail: %v", err) 1227 } 1228 1229 time.Sleep(time.Millisecond * 500) // replace with hive healthy code 1230 1231 rmsgC := make(chan APIMsg) 1232 rctx, cancel := context.WithTimeout(context.Background(), time.Second*1) 1233 defer cancel() 1234 rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic) 1235 log.Trace("rsub", "id", rsub) 1236 defer rsub.Unsubscribe() 1237 1238 // store public key for recipient 1239 // zero-length address means forward to all 1240 // we have just two peers, they will be in proxbin, and will both receive 1241 err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, "0x") 1242 if err != nil { 1243 t.Fatal(err) 1244 } 1245 1246 // send and verify delivery 1247 rmsg := []byte("xyzzy") 1248 err = clients[0].Call(nil, "pss_sendAsym", rpubkey, topic, hexutil.Encode(rmsg)) 1249 if err != nil { 1250 t.Fatal(err) 1251 } 1252 1253 var receivedok bool 1254 OUTER: 1255 for { 1256 select { 1257 case <-rmsgC: 1258 if receivedok { 1259 t.Fatalf("duplicate message received") 1260 } 1261 receivedok = true 1262 case <-rctx.Done(): 1263 break OUTER 1264 } 1265 } 1266 if !receivedok { 1267 t.Fatalf("message did not arrive") 1268 } 1269 } 1270 1271 // symmetric send performance with varying message sizes 1272 func BenchmarkSymkeySend(b *testing.B) { 1273 b.Run(fmt.Sprintf("%d", 256), benchmarkSymKeySend) 1274 b.Run(fmt.Sprintf("%d", 1024), benchmarkSymKeySend) 1275 b.Run(fmt.Sprintf("%d", 1024*1024), benchmarkSymKeySend) 1276 b.Run(fmt.Sprintf("%d", 1024*1024*10), benchmarkSymKeySend) 1277 b.Run(fmt.Sprintf("%d", 1024*1024*100), benchmarkSymKeySend) 1278 } 1279 1280 func benchmarkSymKeySend(b *testing.B) { 1281 msgsizestring := strings.Split(b.Name(), "/") 1282 if len(msgsizestring) != 2 { 1283 b.Fatalf("benchmark called without msgsize param") 1284 } 1285 msgsize, err := strconv.ParseInt(msgsizestring[1], 10, 0) 1286 if err != nil { 1287 b.Fatalf("benchmark called with invalid msgsize param '%s': %v", msgsizestring[1], err) 1288 } 1289 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 1290 defer cancel() 1291 keys, err := wapi.NewKeyPair(ctx) 1292 privkey, err := w.GetPrivateKey(keys) 1293 ps := newTestPss(privkey, nil, nil) 1294 msg := make([]byte, msgsize) 1295 rand.Read(msg) 1296 topic := BytesToTopic([]byte("foo")) 1297 to := make(PssAddress, 32) 1298 copy(to[:], network.RandomAddr().Over()) 1299 symkeyid, err := ps.GenerateSymmetricKey(topic, &to, true) 1300 if err != nil { 1301 b.Fatalf("could not generate symkey: %v", err) 1302 } 1303 symkey, err := ps.w.GetSymKey(symkeyid) 1304 if err != nil { 1305 b.Fatalf("could not retrieve symkey: %v", err) 1306 } 1307 ps.SetSymmetricKey(symkey, topic, &to, false) 1308 1309 b.ResetTimer() 1310 for i := 0; i < b.N; i++ { 1311 ps.SendSym(symkeyid, topic, msg) 1312 } 1313 } 1314 1315 // asymmetric send performance with varying message sizes 1316 func BenchmarkAsymkeySend(b *testing.B) { 1317 b.Run(fmt.Sprintf("%d", 256), benchmarkAsymKeySend) 1318 b.Run(fmt.Sprintf("%d", 1024), benchmarkAsymKeySend) 1319 b.Run(fmt.Sprintf("%d", 1024*1024), benchmarkAsymKeySend) 1320 b.Run(fmt.Sprintf("%d", 1024*1024*10), benchmarkAsymKeySend) 1321 b.Run(fmt.Sprintf("%d", 1024*1024*100), benchmarkAsymKeySend) 1322 } 1323 1324 func benchmarkAsymKeySend(b *testing.B) { 1325 msgsizestring := strings.Split(b.Name(), "/") 1326 if len(msgsizestring) != 2 { 1327 b.Fatalf("benchmark called without msgsize param") 1328 } 1329 msgsize, err := strconv.ParseInt(msgsizestring[1], 10, 0) 1330 if err != nil { 1331 b.Fatalf("benchmark called with invalid msgsize param '%s': %v", msgsizestring[1], err) 1332 } 1333 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 1334 defer cancel() 1335 keys, err := wapi.NewKeyPair(ctx) 1336 privkey, err := w.GetPrivateKey(keys) 1337 ps := newTestPss(privkey, nil, nil) 1338 msg := make([]byte, msgsize) 1339 rand.Read(msg) 1340 topic := BytesToTopic([]byte("foo")) 1341 to := make(PssAddress, 32) 1342 copy(to[:], network.RandomAddr().Over()) 1343 ps.SetPeerPublicKey(&privkey.PublicKey, topic, &to) 1344 b.ResetTimer() 1345 for i := 0; i < b.N; i++ { 1346 ps.SendAsym(common.ToHex(crypto.FromECDSAPub(&privkey.PublicKey)), topic, msg) 1347 } 1348 } 1349 func BenchmarkSymkeyBruteforceChangeaddr(b *testing.B) { 1350 for i := 100; i < 100000; i = i * 10 { 1351 for j := 32; j < 10000; j = j * 8 { 1352 b.Run(fmt.Sprintf("%d/%d", i, j), benchmarkSymkeyBruteforceChangeaddr) 1353 } 1354 //b.Run(fmt.Sprintf("%d", i), benchmarkSymkeyBruteforceChangeaddr) 1355 } 1356 } 1357 1358 // decrypt performance using symkey cache, worst case 1359 // (decrypt key always last in cache) 1360 func benchmarkSymkeyBruteforceChangeaddr(b *testing.B) { 1361 keycountstring := strings.Split(b.Name(), "/") 1362 cachesize := int64(0) 1363 var ps *Pss 1364 if len(keycountstring) < 2 { 1365 b.Fatalf("benchmark called without count param") 1366 } 1367 keycount, err := strconv.ParseInt(keycountstring[1], 10, 0) 1368 if err != nil { 1369 b.Fatalf("benchmark called with invalid count param '%s': %v", keycountstring[1], err) 1370 } 1371 if len(keycountstring) == 3 { 1372 cachesize, err = strconv.ParseInt(keycountstring[2], 10, 0) 1373 if err != nil { 1374 b.Fatalf("benchmark called with invalid cachesize '%s': %v", keycountstring[2], err) 1375 } 1376 } 1377 pssmsgs := make([]*PssMsg, 0, keycount) 1378 var keyid string 1379 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 1380 defer cancel() 1381 keys, err := wapi.NewKeyPair(ctx) 1382 privkey, err := w.GetPrivateKey(keys) 1383 if cachesize > 0 { 1384 ps = newTestPss(privkey, nil, &PssParams{SymKeyCacheCapacity: int(cachesize)}) 1385 } else { 1386 ps = newTestPss(privkey, nil, nil) 1387 } 1388 topic := BytesToTopic([]byte("foo")) 1389 for i := 0; i < int(keycount); i++ { 1390 to := make(PssAddress, 32) 1391 copy(to[:], network.RandomAddr().Over()) 1392 keyid, err = ps.GenerateSymmetricKey(topic, &to, true) 1393 if err != nil { 1394 b.Fatalf("cant generate symkey #%d: %v", i, err) 1395 } 1396 symkey, err := ps.w.GetSymKey(keyid) 1397 if err != nil { 1398 b.Fatalf("could not retrieve symkey %s: %v", keyid, err) 1399 } 1400 wparams := &whisper.MessageParams{ 1401 TTL: defaultWhisperTTL, 1402 KeySym: symkey, 1403 Topic: whisper.TopicType(topic), 1404 WorkTime: defaultWhisperWorkTime, 1405 PoW: defaultWhisperPoW, 1406 Payload: []byte("xyzzy"), 1407 Padding: []byte("1234567890abcdef"), 1408 } 1409 woutmsg, err := whisper.NewSentMessage(wparams) 1410 if err != nil { 1411 b.Fatalf("could not create whisper message: %v", err) 1412 } 1413 env, err := woutmsg.Wrap(wparams) 1414 if err != nil { 1415 b.Fatalf("could not generate whisper envelope: %v", err) 1416 } 1417 ps.Register(&topic, func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error { 1418 return nil 1419 }) 1420 pssmsgs = append(pssmsgs, &PssMsg{ 1421 To: to, 1422 Payload: env, 1423 }) 1424 } 1425 b.ResetTimer() 1426 for i := 0; i < b.N; i++ { 1427 if err := ps.process(pssmsgs[len(pssmsgs)-(i%len(pssmsgs))-1]); err != nil { 1428 b.Fatalf("pss processing failed: %v", err) 1429 } 1430 } 1431 } 1432 1433 func BenchmarkSymkeyBruteforceSameaddr(b *testing.B) { 1434 for i := 100; i < 100000; i = i * 10 { 1435 for j := 32; j < 10000; j = j * 8 { 1436 b.Run(fmt.Sprintf("%d/%d", i, j), benchmarkSymkeyBruteforceSameaddr) 1437 } 1438 } 1439 } 1440 1441 // decrypt performance using symkey cache, best case 1442 // (decrypt key always first in cache) 1443 func benchmarkSymkeyBruteforceSameaddr(b *testing.B) { 1444 var keyid string 1445 var ps *Pss 1446 cachesize := int64(0) 1447 keycountstring := strings.Split(b.Name(), "/") 1448 if len(keycountstring) < 2 { 1449 b.Fatalf("benchmark called without count param") 1450 } 1451 keycount, err := strconv.ParseInt(keycountstring[1], 10, 0) 1452 if err != nil { 1453 b.Fatalf("benchmark called with invalid count param '%s': %v", keycountstring[1], err) 1454 } 1455 if len(keycountstring) == 3 { 1456 cachesize, err = strconv.ParseInt(keycountstring[2], 10, 0) 1457 if err != nil { 1458 b.Fatalf("benchmark called with invalid cachesize '%s': %v", keycountstring[2], err) 1459 } 1460 } 1461 addr := make([]PssAddress, keycount) 1462 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 1463 defer cancel() 1464 keys, err := wapi.NewKeyPair(ctx) 1465 privkey, err := w.GetPrivateKey(keys) 1466 if cachesize > 0 { 1467 ps = newTestPss(privkey, nil, &PssParams{SymKeyCacheCapacity: int(cachesize)}) 1468 } else { 1469 ps = newTestPss(privkey, nil, nil) 1470 } 1471 topic := BytesToTopic([]byte("foo")) 1472 for i := 0; i < int(keycount); i++ { 1473 copy(addr[i], network.RandomAddr().Over()) 1474 keyid, err = ps.GenerateSymmetricKey(topic, &addr[i], true) 1475 if err != nil { 1476 b.Fatalf("cant generate symkey #%d: %v", i, err) 1477 } 1478 1479 } 1480 symkey, err := ps.w.GetSymKey(keyid) 1481 if err != nil { 1482 b.Fatalf("could not retrieve symkey %s: %v", keyid, err) 1483 } 1484 wparams := &whisper.MessageParams{ 1485 TTL: defaultWhisperTTL, 1486 KeySym: symkey, 1487 Topic: whisper.TopicType(topic), 1488 WorkTime: defaultWhisperWorkTime, 1489 PoW: defaultWhisperPoW, 1490 Payload: []byte("xyzzy"), 1491 Padding: []byte("1234567890abcdef"), 1492 } 1493 woutmsg, err := whisper.NewSentMessage(wparams) 1494 if err != nil { 1495 b.Fatalf("could not create whisper message: %v", err) 1496 } 1497 env, err := woutmsg.Wrap(wparams) 1498 if err != nil { 1499 b.Fatalf("could not generate whisper envelope: %v", err) 1500 } 1501 ps.Register(&topic, func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error { 1502 return nil 1503 }) 1504 pssmsg := &PssMsg{ 1505 To: addr[len(addr)-1][:], 1506 Payload: env, 1507 } 1508 for i := 0; i < b.N; i++ { 1509 if err := ps.process(pssmsg); err != nil { 1510 b.Fatalf("pss processing failed: %v", err) 1511 } 1512 } 1513 } 1514 1515 // setup simulated network with bzz/discovery and pss services. 1516 // connects nodes in a circle 1517 // if allowRaw is set, omission of builtin pss encryption is enabled (see PssParams) 1518 func setupNetwork(numnodes int, allowRaw bool) (clients []*rpc.Client, err error) { 1519 nodes := make([]*simulations.Node, numnodes) 1520 clients = make([]*rpc.Client, numnodes) 1521 if numnodes < 2 { 1522 return nil, fmt.Errorf("Minimum two nodes in network") 1523 } 1524 adapter := adapters.NewSimAdapter(newServices(allowRaw)) 1525 net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{ 1526 ID: "0", 1527 DefaultService: "bzz", 1528 }) 1529 for i := 0; i < numnodes; i++ { 1530 nodeconf := adapters.RandomNodeConfig() 1531 nodeconf.Services = []string{"bzz", pssProtocolName} 1532 nodes[i], err = net.NewNodeWithConfig(nodeconf) 1533 if err != nil { 1534 return nil, fmt.Errorf("error creating node 1: %v", err) 1535 } 1536 err = net.Start(nodes[i].ID()) 1537 if err != nil { 1538 return nil, fmt.Errorf("error starting node 1: %v", err) 1539 } 1540 if i > 0 { 1541 err = net.Connect(nodes[i].ID(), nodes[i-1].ID()) 1542 if err != nil { 1543 return nil, fmt.Errorf("error connecting nodes: %v", err) 1544 } 1545 } 1546 clients[i], err = nodes[i].Client() 1547 if err != nil { 1548 return nil, fmt.Errorf("create node 1 rpc client fail: %v", err) 1549 } 1550 } 1551 if numnodes > 2 { 1552 err = net.Connect(nodes[0].ID(), nodes[len(nodes)-1].ID()) 1553 if err != nil { 1554 return nil, fmt.Errorf("error connecting first and last nodes") 1555 } 1556 } 1557 return clients, nil 1558 } 1559 1560 func newServices(allowRaw bool) adapters.Services { 1561 stateStore := state.NewInmemoryStore() 1562 kademlias := make(map[discover.NodeID]*network.Kademlia) 1563 kademlia := func(id discover.NodeID) *network.Kademlia { 1564 if k, ok := kademlias[id]; ok { 1565 return k 1566 } 1567 addr := network.NewAddrFromNodeID(id) 1568 params := network.NewKadParams() 1569 params.MinProxBinSize = 2 1570 params.MaxBinSize = 3 1571 params.MinBinSize = 1 1572 params.MaxRetries = 1000 1573 params.RetryExponent = 2 1574 params.RetryInterval = 1000000 1575 kademlias[id] = network.NewKademlia(addr.Over(), params) 1576 return kademlias[id] 1577 } 1578 return adapters.Services{ 1579 pssProtocolName: func(ctx *adapters.ServiceContext) (node.Service, error) { 1580 // execadapter does not exec init() 1581 initTest() 1582 1583 ctxlocal, cancel := context.WithTimeout(context.Background(), time.Second) 1584 defer cancel() 1585 keys, err := wapi.NewKeyPair(ctxlocal) 1586 privkey, err := w.GetPrivateKey(keys) 1587 pssp := NewPssParams().WithPrivateKey(privkey) 1588 pssp.AllowRaw = allowRaw 1589 pskad := kademlia(ctx.Config.ID) 1590 ps, err := NewPss(pskad, pssp) 1591 if err != nil { 1592 return nil, err 1593 } 1594 1595 ping := &Ping{ 1596 OutC: make(chan bool), 1597 Pong: true, 1598 } 1599 p2pp := NewPingProtocol(ping) 1600 pp, err := RegisterProtocol(ps, &PingTopic, PingProtocol, p2pp, &ProtocolParams{Asymmetric: true}) 1601 if err != nil { 1602 return nil, err 1603 } 1604 if useHandshake { 1605 SetHandshakeController(ps, NewHandshakeParams()) 1606 } 1607 ps.Register(&PingTopic, pp.Handle) 1608 ps.addAPI(rpc.API{ 1609 Namespace: "psstest", 1610 Version: "0.3", 1611 Service: NewAPITest(ps), 1612 Public: false, 1613 }) 1614 if err != nil { 1615 log.Error("Couldnt register pss protocol", "err", err) 1616 os.Exit(1) 1617 } 1618 pssprotocols[ctx.Config.ID.String()] = &protoCtrl{ 1619 C: ping.OutC, 1620 protocol: pp, 1621 run: p2pp.Run, 1622 } 1623 return ps, nil 1624 }, 1625 "bzz": func(ctx *adapters.ServiceContext) (node.Service, error) { 1626 addr := network.NewAddrFromNodeID(ctx.Config.ID) 1627 hp := network.NewHiveParams() 1628 hp.Discovery = false 1629 config := &network.BzzConfig{ 1630 OverlayAddr: addr.Over(), 1631 UnderlayAddr: addr.Under(), 1632 HiveParams: hp, 1633 } 1634 return network.NewBzz(config, kademlia(ctx.Config.ID), stateStore, nil, nil), nil 1635 }, 1636 } 1637 } 1638 1639 func newTestPss(privkey *ecdsa.PrivateKey, overlay network.Overlay, ppextra *PssParams) *Pss { 1640 1641 var nid discover.NodeID 1642 copy(nid[:], crypto.FromECDSAPub(&privkey.PublicKey)) 1643 addr := network.NewAddrFromNodeID(nid) 1644 1645 // set up routing if kademlia is not passed to us 1646 if overlay == nil { 1647 kp := network.NewKadParams() 1648 kp.MinProxBinSize = 3 1649 overlay = network.NewKademlia(addr.Over(), kp) 1650 } 1651 1652 // create pss 1653 pp := NewPssParams().WithPrivateKey(privkey) 1654 if ppextra != nil { 1655 pp.SymKeyCacheCapacity = ppextra.SymKeyCacheCapacity 1656 } 1657 ps, err := NewPss(overlay, pp) 1658 if err != nil { 1659 return nil 1660 } 1661 ps.Start(nil) 1662 1663 return ps 1664 } 1665 1666 // API calls for test/development use 1667 type APITest struct { 1668 *Pss 1669 } 1670 1671 func NewAPITest(ps *Pss) *APITest { 1672 return &APITest{Pss: ps} 1673 } 1674 1675 func (apitest *APITest) SetSymKeys(pubkeyid string, recvsymkey []byte, sendsymkey []byte, limit uint16, topic Topic, to PssAddress) ([2]string, error) { 1676 recvsymkeyid, err := apitest.SetSymmetricKey(recvsymkey, topic, &to, true) 1677 if err != nil { 1678 return [2]string{}, err 1679 } 1680 sendsymkeyid, err := apitest.SetSymmetricKey(sendsymkey, topic, &to, false) 1681 if err != nil { 1682 return [2]string{}, err 1683 } 1684 return [2]string{recvsymkeyid, sendsymkeyid}, nil 1685 } 1686 1687 func (apitest *APITest) Clean() (int, error) { 1688 return apitest.Pss.cleanKeys(), nil 1689 } 1690 1691 // enableMetrics is starting InfluxDB reporter so that we collect stats when running tests locally 1692 func enableMetrics() { 1693 metrics.Enabled = true 1694 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 1*time.Second, "http://localhost:8086", "metrics", "admin", "admin", "swarm.", map[string]string{ 1695 "host": "test", 1696 }) 1697 }