github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/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/FusionFoundation/efsn/common"
    38  	"github.com/FusionFoundation/efsn/common/hexutil"
    39  	"github.com/FusionFoundation/efsn/crypto"
    40  	"github.com/FusionFoundation/efsn/log"
    41  	"github.com/FusionFoundation/efsn/metrics"
    42  	"github.com/FusionFoundation/efsn/metrics/influxdb"
    43  	"github.com/FusionFoundation/efsn/node"
    44  	"github.com/FusionFoundation/efsn/p2p"
    45  	"github.com/FusionFoundation/efsn/p2p/discover"
    46  	"github.com/FusionFoundation/efsn/p2p/protocols"
    47  	"github.com/FusionFoundation/efsn/p2p/simulations"
    48  	"github.com/FusionFoundation/efsn/p2p/simulations/adapters"
    49  	"github.com/FusionFoundation/efsn/rpc"
    50  	"github.com/FusionFoundation/efsn/swarm/network"
    51  	"github.com/FusionFoundation/efsn/swarm/state"
    52  	whisper "github.com/FusionFoundation/efsn/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  // forwarding should skip peers that do not have matching pss capabilities
   560  func TestMismatch(t *testing.T) {
   561  
   562  	// create privkey for forwarder node
   563  	privkey, err := crypto.GenerateKey()
   564  	if err != nil {
   565  		t.Fatal(err)
   566  	}
   567  
   568  	// initialize kad
   569  	baseaddr := network.RandomAddr()
   570  	kad := network.NewKademlia((baseaddr).Over(), network.NewKadParams())
   571  	rw := &p2p.MsgPipeRW{}
   572  
   573  	// one peer has a mismatching version of pss
   574  	wrongpssaddr := network.RandomAddr()
   575  	wrongpsscap := p2p.Cap{
   576  		Name:    pssProtocolName,
   577  		Version: 0,
   578  	}
   579  	nid, _ := discover.HexID("0x01")
   580  	wrongpsspeer := network.NewPeer(&network.BzzPeer{
   581  		Peer:    protocols.NewPeer(p2p.NewPeer(nid, common.ToHex(wrongpssaddr.Over()), []p2p.Cap{wrongpsscap}), rw, nil),
   582  		BzzAddr: &network.BzzAddr{OAddr: wrongpssaddr.Over(), UAddr: nil},
   583  	}, kad)
   584  
   585  	// one peer doesn't even have pss (boo!)
   586  	nopssaddr := network.RandomAddr()
   587  	nopsscap := p2p.Cap{
   588  		Name:    "nopss",
   589  		Version: 1,
   590  	}
   591  	nid, _ = discover.HexID("0x02")
   592  	nopsspeer := network.NewPeer(&network.BzzPeer{
   593  		Peer:    protocols.NewPeer(p2p.NewPeer(nid, common.ToHex(nopssaddr.Over()), []p2p.Cap{nopsscap}), rw, nil),
   594  		BzzAddr: &network.BzzAddr{OAddr: nopssaddr.Over(), UAddr: nil},
   595  	}, kad)
   596  
   597  	// add peers to kademlia and activate them
   598  	// it's safe so don't check errors
   599  	kad.Register(wrongpsspeer.BzzAddr)
   600  	kad.On(wrongpsspeer)
   601  	kad.Register(nopsspeer.BzzAddr)
   602  	kad.On(nopsspeer)
   603  
   604  	// create pss
   605  	pssmsg := &PssMsg{
   606  		To:      []byte{},
   607  		Expire:  uint32(time.Now().Add(time.Second).Unix()),
   608  		Payload: &whisper.Envelope{},
   609  	}
   610  	ps := newTestPss(privkey, kad, nil)
   611  
   612  	// run the forward
   613  	// it is enough that it completes; trying to send to incapable peers would create segfault
   614  	ps.forward(pssmsg)
   615  
   616  }
   617  
   618  func TestSendRaw(t *testing.T) {
   619  	t.Run("32", testSendRaw)
   620  	t.Run("8", testSendRaw)
   621  	t.Run("0", testSendRaw)
   622  }
   623  
   624  func testSendRaw(t *testing.T) {
   625  
   626  	var addrsize int64
   627  	var err error
   628  
   629  	paramstring := strings.Split(t.Name(), "/")
   630  
   631  	addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
   632  	log.Info("raw send test", "addrsize", addrsize)
   633  
   634  	clients, err := setupNetwork(2, true)
   635  	if err != nil {
   636  		t.Fatal(err)
   637  	}
   638  
   639  	topic := "0xdeadbeef"
   640  
   641  	var loaddrhex string
   642  	err = clients[0].Call(&loaddrhex, "pss_baseAddr")
   643  	if err != nil {
   644  		t.Fatalf("rpc get node 1 baseaddr fail: %v", err)
   645  	}
   646  	loaddrhex = loaddrhex[:2+(addrsize*2)]
   647  	var roaddrhex string
   648  	err = clients[1].Call(&roaddrhex, "pss_baseAddr")
   649  	if err != nil {
   650  		t.Fatalf("rpc get node 2 baseaddr fail: %v", err)
   651  	}
   652  	roaddrhex = roaddrhex[:2+(addrsize*2)]
   653  
   654  	time.Sleep(time.Millisecond * 500)
   655  
   656  	// at this point we've verified that symkeys are saved and match on each peer
   657  	// now try sending symmetrically encrypted message, both directions
   658  	lmsgC := make(chan APIMsg)
   659  	lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10)
   660  	defer lcancel()
   661  	lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic)
   662  	log.Trace("lsub", "id", lsub)
   663  	defer lsub.Unsubscribe()
   664  	rmsgC := make(chan APIMsg)
   665  	rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10)
   666  	defer rcancel()
   667  	rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic)
   668  	log.Trace("rsub", "id", rsub)
   669  	defer rsub.Unsubscribe()
   670  
   671  	// send and verify delivery
   672  	lmsg := []byte("plugh")
   673  	err = clients[1].Call(nil, "pss_sendRaw", loaddrhex, topic, lmsg)
   674  	if err != nil {
   675  		t.Fatal(err)
   676  	}
   677  	select {
   678  	case recvmsg := <-lmsgC:
   679  		if !bytes.Equal(recvmsg.Msg, lmsg) {
   680  			t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg)
   681  		}
   682  	case cerr := <-lctx.Done():
   683  		t.Fatalf("test message (left) timed out: %v", cerr)
   684  	}
   685  	rmsg := []byte("xyzzy")
   686  	err = clients[0].Call(nil, "pss_sendRaw", roaddrhex, topic, rmsg)
   687  	if err != nil {
   688  		t.Fatal(err)
   689  	}
   690  	select {
   691  	case recvmsg := <-rmsgC:
   692  		if !bytes.Equal(recvmsg.Msg, rmsg) {
   693  			t.Fatalf("node 2 received payload mismatch: expected %x, got %v", rmsg, recvmsg.Msg)
   694  		}
   695  	case cerr := <-rctx.Done():
   696  		t.Fatalf("test message (right) timed out: %v", cerr)
   697  	}
   698  }
   699  
   700  // send symmetrically encrypted message between two directly connected peers
   701  func TestSendSym(t *testing.T) {
   702  	t.Run("32", testSendSym)
   703  	t.Run("8", testSendSym)
   704  	t.Run("0", testSendSym)
   705  }
   706  
   707  func testSendSym(t *testing.T) {
   708  
   709  	// address hint size
   710  	var addrsize int64
   711  	var err error
   712  	paramstring := strings.Split(t.Name(), "/")
   713  	addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
   714  	log.Info("sym send test", "addrsize", addrsize)
   715  
   716  	clients, err := setupNetwork(2, false)
   717  	if err != nil {
   718  		t.Fatal(err)
   719  	}
   720  
   721  	var topic string
   722  	err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42")
   723  	if err != nil {
   724  		t.Fatal(err)
   725  	}
   726  
   727  	var loaddrhex string
   728  	err = clients[0].Call(&loaddrhex, "pss_baseAddr")
   729  	if err != nil {
   730  		t.Fatalf("rpc get node 1 baseaddr fail: %v", err)
   731  	}
   732  	loaddrhex = loaddrhex[:2+(addrsize*2)]
   733  	var roaddrhex string
   734  	err = clients[1].Call(&roaddrhex, "pss_baseAddr")
   735  	if err != nil {
   736  		t.Fatalf("rpc get node 2 baseaddr fail: %v", err)
   737  	}
   738  	roaddrhex = roaddrhex[:2+(addrsize*2)]
   739  
   740  	// retrieve public key from pss instance
   741  	// set this public key reciprocally
   742  	var lpubkeyhex string
   743  	err = clients[0].Call(&lpubkeyhex, "pss_getPublicKey")
   744  	if err != nil {
   745  		t.Fatalf("rpc get node 1 pubkey fail: %v", err)
   746  	}
   747  	var rpubkeyhex string
   748  	err = clients[1].Call(&rpubkeyhex, "pss_getPublicKey")
   749  	if err != nil {
   750  		t.Fatalf("rpc get node 2 pubkey fail: %v", err)
   751  	}
   752  
   753  	time.Sleep(time.Millisecond * 500)
   754  
   755  	// at this point we've verified that symkeys are saved and match on each peer
   756  	// now try sending symmetrically encrypted message, both directions
   757  	lmsgC := make(chan APIMsg)
   758  	lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10)
   759  	defer lcancel()
   760  	lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic)
   761  	log.Trace("lsub", "id", lsub)
   762  	defer lsub.Unsubscribe()
   763  	rmsgC := make(chan APIMsg)
   764  	rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10)
   765  	defer rcancel()
   766  	rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic)
   767  	log.Trace("rsub", "id", rsub)
   768  	defer rsub.Unsubscribe()
   769  
   770  	lrecvkey := network.RandomAddr().Over()
   771  	rrecvkey := network.RandomAddr().Over()
   772  
   773  	var lkeyids [2]string
   774  	var rkeyids [2]string
   775  
   776  	// manually set reciprocal symkeys
   777  	err = clients[0].Call(&lkeyids, "psstest_setSymKeys", rpubkeyhex, lrecvkey, rrecvkey, defaultSymKeySendLimit, topic, roaddrhex)
   778  	if err != nil {
   779  		t.Fatal(err)
   780  	}
   781  	err = clients[1].Call(&rkeyids, "psstest_setSymKeys", lpubkeyhex, rrecvkey, lrecvkey, defaultSymKeySendLimit, topic, loaddrhex)
   782  	if err != nil {
   783  		t.Fatal(err)
   784  	}
   785  
   786  	// send and verify delivery
   787  	lmsg := []byte("plugh")
   788  	err = clients[1].Call(nil, "pss_sendSym", rkeyids[1], topic, hexutil.Encode(lmsg))
   789  	if err != nil {
   790  		t.Fatal(err)
   791  	}
   792  	select {
   793  	case recvmsg := <-lmsgC:
   794  		if !bytes.Equal(recvmsg.Msg, lmsg) {
   795  			t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg)
   796  		}
   797  	case cerr := <-lctx.Done():
   798  		t.Fatalf("test message timed out: %v", cerr)
   799  	}
   800  	rmsg := []byte("xyzzy")
   801  	err = clients[0].Call(nil, "pss_sendSym", lkeyids[1], topic, hexutil.Encode(rmsg))
   802  	if err != nil {
   803  		t.Fatal(err)
   804  	}
   805  	select {
   806  	case recvmsg := <-rmsgC:
   807  		if !bytes.Equal(recvmsg.Msg, rmsg) {
   808  			t.Fatalf("node 2 received payload mismatch: expected %x, got %v", rmsg, recvmsg.Msg)
   809  		}
   810  	case cerr := <-rctx.Done():
   811  		t.Fatalf("test message timed out: %v", cerr)
   812  	}
   813  }
   814  
   815  // send asymmetrically encrypted message between two directly connected peers
   816  func TestSendAsym(t *testing.T) {
   817  	t.Run("32", testSendAsym)
   818  	t.Run("8", testSendAsym)
   819  	t.Run("0", testSendAsym)
   820  }
   821  
   822  func testSendAsym(t *testing.T) {
   823  
   824  	// address hint size
   825  	var addrsize int64
   826  	var err error
   827  	paramstring := strings.Split(t.Name(), "/")
   828  	addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
   829  	log.Info("asym send test", "addrsize", addrsize)
   830  
   831  	clients, err := setupNetwork(2, false)
   832  	if err != nil {
   833  		t.Fatal(err)
   834  	}
   835  
   836  	var topic string
   837  	err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42")
   838  	if err != nil {
   839  		t.Fatal(err)
   840  	}
   841  
   842  	time.Sleep(time.Millisecond * 250)
   843  
   844  	var loaddrhex string
   845  	err = clients[0].Call(&loaddrhex, "pss_baseAddr")
   846  	if err != nil {
   847  		t.Fatalf("rpc get node 1 baseaddr fail: %v", err)
   848  	}
   849  	loaddrhex = loaddrhex[:2+(addrsize*2)]
   850  	var roaddrhex string
   851  	err = clients[1].Call(&roaddrhex, "pss_baseAddr")
   852  	if err != nil {
   853  		t.Fatalf("rpc get node 2 baseaddr fail: %v", err)
   854  	}
   855  	roaddrhex = roaddrhex[:2+(addrsize*2)]
   856  
   857  	// retrieve public key from pss instance
   858  	// set this public key reciprocally
   859  	var lpubkey string
   860  	err = clients[0].Call(&lpubkey, "pss_getPublicKey")
   861  	if err != nil {
   862  		t.Fatalf("rpc get node 1 pubkey fail: %v", err)
   863  	}
   864  	var rpubkey string
   865  	err = clients[1].Call(&rpubkey, "pss_getPublicKey")
   866  	if err != nil {
   867  		t.Fatalf("rpc get node 2 pubkey fail: %v", err)
   868  	}
   869  
   870  	time.Sleep(time.Millisecond * 500) // replace with hive healthy code
   871  
   872  	lmsgC := make(chan APIMsg)
   873  	lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10)
   874  	defer lcancel()
   875  	lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic)
   876  	log.Trace("lsub", "id", lsub)
   877  	defer lsub.Unsubscribe()
   878  	rmsgC := make(chan APIMsg)
   879  	rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10)
   880  	defer rcancel()
   881  	rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic)
   882  	log.Trace("rsub", "id", rsub)
   883  	defer rsub.Unsubscribe()
   884  
   885  	// store reciprocal public keys
   886  	err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, roaddrhex)
   887  	if err != nil {
   888  		t.Fatal(err)
   889  	}
   890  	err = clients[1].Call(nil, "pss_setPeerPublicKey", lpubkey, topic, loaddrhex)
   891  	if err != nil {
   892  		t.Fatal(err)
   893  	}
   894  
   895  	// send and verify delivery
   896  	rmsg := []byte("xyzzy")
   897  	err = clients[0].Call(nil, "pss_sendAsym", rpubkey, topic, hexutil.Encode(rmsg))
   898  	if err != nil {
   899  		t.Fatal(err)
   900  	}
   901  	select {
   902  	case recvmsg := <-rmsgC:
   903  		if !bytes.Equal(recvmsg.Msg, rmsg) {
   904  			t.Fatalf("node 2 received payload mismatch: expected %v, got %v", rmsg, recvmsg.Msg)
   905  		}
   906  	case cerr := <-rctx.Done():
   907  		t.Fatalf("test message timed out: %v", cerr)
   908  	}
   909  	lmsg := []byte("plugh")
   910  	err = clients[1].Call(nil, "pss_sendAsym", lpubkey, topic, hexutil.Encode(lmsg))
   911  	if err != nil {
   912  		t.Fatal(err)
   913  	}
   914  	select {
   915  	case recvmsg := <-lmsgC:
   916  		if !bytes.Equal(recvmsg.Msg, lmsg) {
   917  			t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg.Msg)
   918  		}
   919  	case cerr := <-lctx.Done():
   920  		t.Fatalf("test message timed out: %v", cerr)
   921  	}
   922  }
   923  
   924  type Job struct {
   925  	Msg      []byte
   926  	SendNode discover.NodeID
   927  	RecvNode discover.NodeID
   928  }
   929  
   930  func worker(id int, jobs <-chan Job, rpcs map[discover.NodeID]*rpc.Client, pubkeys map[discover.NodeID]string, topic string) {
   931  	for j := range jobs {
   932  		rpcs[j.SendNode].Call(nil, "pss_sendAsym", pubkeys[j.RecvNode], topic, hexutil.Encode(j.Msg))
   933  	}
   934  }
   935  
   936  func TestNetwork(t *testing.T) {
   937  	t.Run("16/1000/4/sim", testNetwork)
   938  }
   939  
   940  // params in run name:
   941  // nodes/msgs/addrbytes/adaptertype
   942  // if adaptertype is exec uses execadapter, simadapter otherwise
   943  func TestNetwork2000(t *testing.T) {
   944  	//enableMetrics()
   945  
   946  	if !*longrunning {
   947  		t.Skip("run with --longrunning flag to run extensive network tests")
   948  	}
   949  	t.Run("3/2000/4/sim", testNetwork)
   950  	t.Run("4/2000/4/sim", testNetwork)
   951  	t.Run("8/2000/4/sim", testNetwork)
   952  	t.Run("16/2000/4/sim", testNetwork)
   953  }
   954  
   955  func TestNetwork5000(t *testing.T) {
   956  	//enableMetrics()
   957  
   958  	if !*longrunning {
   959  		t.Skip("run with --longrunning flag to run extensive network tests")
   960  	}
   961  	t.Run("3/5000/4/sim", testNetwork)
   962  	t.Run("4/5000/4/sim", testNetwork)
   963  	t.Run("8/5000/4/sim", testNetwork)
   964  	t.Run("16/5000/4/sim", testNetwork)
   965  }
   966  
   967  func TestNetwork10000(t *testing.T) {
   968  	//enableMetrics()
   969  
   970  	if !*longrunning {
   971  		t.Skip("run with --longrunning flag to run extensive network tests")
   972  	}
   973  	t.Run("3/10000/4/sim", testNetwork)
   974  	t.Run("4/10000/4/sim", testNetwork)
   975  	t.Run("8/10000/4/sim", testNetwork)
   976  }
   977  
   978  func testNetwork(t *testing.T) {
   979  	type msgnotifyC struct {
   980  		id     discover.NodeID
   981  		msgIdx int
   982  	}
   983  
   984  	paramstring := strings.Split(t.Name(), "/")
   985  	nodecount, _ := strconv.ParseInt(paramstring[1], 10, 0)
   986  	msgcount, _ := strconv.ParseInt(paramstring[2], 10, 0)
   987  	addrsize, _ := strconv.ParseInt(paramstring[3], 10, 0)
   988  	adapter := paramstring[4]
   989  
   990  	log.Info("network test", "nodecount", nodecount, "msgcount", msgcount, "addrhintsize", addrsize)
   991  
   992  	nodes := make([]discover.NodeID, nodecount)
   993  	bzzaddrs := make(map[discover.NodeID]string, nodecount)
   994  	rpcs := make(map[discover.NodeID]*rpc.Client, nodecount)
   995  	pubkeys := make(map[discover.NodeID]string, nodecount)
   996  
   997  	sentmsgs := make([][]byte, msgcount)
   998  	recvmsgs := make([]bool, msgcount)
   999  	nodemsgcount := make(map[discover.NodeID]int, nodecount)
  1000  
  1001  	trigger := make(chan discover.NodeID)
  1002  
  1003  	var a adapters.NodeAdapter
  1004  	if adapter == "exec" {
  1005  		dirname, err := ioutil.TempDir(".", "")
  1006  		if err != nil {
  1007  			t.Fatal(err)
  1008  		}
  1009  		a = adapters.NewExecAdapter(dirname)
  1010  	} else if adapter == "tcp" {
  1011  		a = adapters.NewTCPAdapter(newServices(false))
  1012  	} else if adapter == "sim" {
  1013  		a = adapters.NewSimAdapter(newServices(false))
  1014  	}
  1015  	net := simulations.NewNetwork(a, &simulations.NetworkConfig{
  1016  		ID: "0",
  1017  	})
  1018  	defer net.Shutdown()
  1019  
  1020  	f, err := os.Open(fmt.Sprintf("testdata/snapshot_%d.json", nodecount))
  1021  	if err != nil {
  1022  		t.Fatal(err)
  1023  	}
  1024  	jsonbyte, err := ioutil.ReadAll(f)
  1025  	if err != nil {
  1026  		t.Fatal(err)
  1027  	}
  1028  	var snap simulations.Snapshot
  1029  	err = json.Unmarshal(jsonbyte, &snap)
  1030  	if err != nil {
  1031  		t.Fatal(err)
  1032  	}
  1033  	err = net.Load(&snap)
  1034  	if err != nil {
  1035  		//TODO: Fix p2p simulation framework to not crash when loading 32-nodes
  1036  		//t.Fatal(err)
  1037  	}
  1038  
  1039  	time.Sleep(1 * time.Second)
  1040  
  1041  	triggerChecks := func(trigger chan discover.NodeID, id discover.NodeID, rpcclient *rpc.Client, topic string) error {
  1042  		msgC := make(chan APIMsg)
  1043  		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  1044  		defer cancel()
  1045  		sub, err := rpcclient.Subscribe(ctx, "pss", msgC, "receive", topic)
  1046  		if err != nil {
  1047  			t.Fatal(err)
  1048  		}
  1049  		go func() {
  1050  			defer sub.Unsubscribe()
  1051  			for {
  1052  				select {
  1053  				case recvmsg := <-msgC:
  1054  					idx, _ := binary.Uvarint(recvmsg.Msg)
  1055  					if !recvmsgs[idx] {
  1056  						log.Debug("msg recv", "idx", idx, "id", id)
  1057  						recvmsgs[idx] = true
  1058  						trigger <- id
  1059  					}
  1060  				case <-sub.Err():
  1061  					return
  1062  				}
  1063  			}
  1064  		}()
  1065  		return nil
  1066  	}
  1067  
  1068  	var topic string
  1069  	for i, nod := range net.GetNodes() {
  1070  		nodes[i] = nod.ID()
  1071  		rpcs[nodes[i]], err = nod.Client()
  1072  		if err != nil {
  1073  			t.Fatal(err)
  1074  		}
  1075  		if topic == "" {
  1076  			err = rpcs[nodes[i]].Call(&topic, "pss_stringToTopic", "foo:42")
  1077  			if err != nil {
  1078  				t.Fatal(err)
  1079  			}
  1080  		}
  1081  		var pubkey string
  1082  		err = rpcs[nodes[i]].Call(&pubkey, "pss_getPublicKey")
  1083  		if err != nil {
  1084  			t.Fatal(err)
  1085  		}
  1086  		pubkeys[nod.ID()] = pubkey
  1087  		var addrhex string
  1088  		err = rpcs[nodes[i]].Call(&addrhex, "pss_baseAddr")
  1089  		if err != nil {
  1090  			t.Fatal(err)
  1091  		}
  1092  		bzzaddrs[nodes[i]] = addrhex
  1093  		err = triggerChecks(trigger, nodes[i], rpcs[nodes[i]], topic)
  1094  		if err != nil {
  1095  			t.Fatal(err)
  1096  		}
  1097  	}
  1098  
  1099  	time.Sleep(1 * time.Second)
  1100  
  1101  	// setup workers
  1102  	jobs := make(chan Job, 10)
  1103  	for w := 1; w <= 10; w++ {
  1104  		go worker(w, jobs, rpcs, pubkeys, topic)
  1105  	}
  1106  
  1107  	time.Sleep(1 * time.Second)
  1108  
  1109  	for i := 0; i < int(msgcount); i++ {
  1110  		sendnodeidx := rand.Intn(int(nodecount))
  1111  		recvnodeidx := rand.Intn(int(nodecount - 1))
  1112  		if recvnodeidx >= sendnodeidx {
  1113  			recvnodeidx++
  1114  		}
  1115  		nodemsgcount[nodes[recvnodeidx]]++
  1116  		sentmsgs[i] = make([]byte, 8)
  1117  		c := binary.PutUvarint(sentmsgs[i], uint64(i))
  1118  		if c == 0 {
  1119  			t.Fatal("0 byte message")
  1120  		}
  1121  		if err != nil {
  1122  			t.Fatal(err)
  1123  		}
  1124  		err = rpcs[nodes[sendnodeidx]].Call(nil, "pss_setPeerPublicKey", pubkeys[nodes[recvnodeidx]], topic, bzzaddrs[nodes[recvnodeidx]])
  1125  		if err != nil {
  1126  			t.Fatal(err)
  1127  		}
  1128  
  1129  		jobs <- Job{
  1130  			Msg:      sentmsgs[i],
  1131  			SendNode: nodes[sendnodeidx],
  1132  			RecvNode: nodes[recvnodeidx],
  1133  		}
  1134  	}
  1135  
  1136  	finalmsgcount := 0
  1137  	ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
  1138  	defer cancel()
  1139  outer:
  1140  	for i := 0; i < int(msgcount); i++ {
  1141  		select {
  1142  		case id := <-trigger:
  1143  			nodemsgcount[id]--
  1144  			finalmsgcount++
  1145  		case <-ctx.Done():
  1146  			log.Warn("timeout")
  1147  			break outer
  1148  		}
  1149  	}
  1150  
  1151  	for i, msg := range recvmsgs {
  1152  		if !msg {
  1153  			log.Debug("missing message", "idx", i)
  1154  		}
  1155  	}
  1156  	t.Logf("%d of %d messages received", finalmsgcount, msgcount)
  1157  
  1158  	if finalmsgcount != int(msgcount) {
  1159  		t.Fatalf("%d messages were not received", int(msgcount)-finalmsgcount)
  1160  	}
  1161  
  1162  }
  1163  
  1164  // check that in a network of a -> b -> c -> a
  1165  // a doesn't receive a sent message twice
  1166  func TestDeduplication(t *testing.T) {
  1167  	var err error
  1168  
  1169  	clients, err := setupNetwork(3, false)
  1170  	if err != nil {
  1171  		t.Fatal(err)
  1172  	}
  1173  
  1174  	var addrsize = 32
  1175  	var loaddrhex string
  1176  	err = clients[0].Call(&loaddrhex, "pss_baseAddr")
  1177  	if err != nil {
  1178  		t.Fatalf("rpc get node 1 baseaddr fail: %v", err)
  1179  	}
  1180  	loaddrhex = loaddrhex[:2+(addrsize*2)]
  1181  	var roaddrhex string
  1182  	err = clients[1].Call(&roaddrhex, "pss_baseAddr")
  1183  	if err != nil {
  1184  		t.Fatalf("rpc get node 2 baseaddr fail: %v", err)
  1185  	}
  1186  	roaddrhex = roaddrhex[:2+(addrsize*2)]
  1187  	var xoaddrhex string
  1188  	err = clients[2].Call(&xoaddrhex, "pss_baseAddr")
  1189  	if err != nil {
  1190  		t.Fatalf("rpc get node 3 baseaddr fail: %v", err)
  1191  	}
  1192  	xoaddrhex = xoaddrhex[:2+(addrsize*2)]
  1193  
  1194  	log.Info("peer", "l", loaddrhex, "r", roaddrhex, "x", xoaddrhex)
  1195  
  1196  	var topic string
  1197  	err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42")
  1198  	if err != nil {
  1199  		t.Fatal(err)
  1200  	}
  1201  
  1202  	time.Sleep(time.Millisecond * 250)
  1203  
  1204  	// retrieve public key from pss instance
  1205  	// set this public key reciprocally
  1206  	var rpubkey string
  1207  	err = clients[1].Call(&rpubkey, "pss_getPublicKey")
  1208  	if err != nil {
  1209  		t.Fatalf("rpc get receivenode pubkey fail: %v", err)
  1210  	}
  1211  
  1212  	time.Sleep(time.Millisecond * 500) // replace with hive healthy code
  1213  
  1214  	rmsgC := make(chan APIMsg)
  1215  	rctx, cancel := context.WithTimeout(context.Background(), time.Second*1)
  1216  	defer cancel()
  1217  	rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic)
  1218  	log.Trace("rsub", "id", rsub)
  1219  	defer rsub.Unsubscribe()
  1220  
  1221  	// store public key for recipient
  1222  	// zero-length address means forward to all
  1223  	// we have just two peers, they will be in proxbin, and will both receive
  1224  	err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, "0x")
  1225  	if err != nil {
  1226  		t.Fatal(err)
  1227  	}
  1228  
  1229  	// send and verify delivery
  1230  	rmsg := []byte("xyzzy")
  1231  	err = clients[0].Call(nil, "pss_sendAsym", rpubkey, topic, hexutil.Encode(rmsg))
  1232  	if err != nil {
  1233  		t.Fatal(err)
  1234  	}
  1235  
  1236  	var receivedok bool
  1237  OUTER:
  1238  	for {
  1239  		select {
  1240  		case <-rmsgC:
  1241  			if receivedok {
  1242  				t.Fatalf("duplicate message received")
  1243  			}
  1244  			receivedok = true
  1245  		case <-rctx.Done():
  1246  			break OUTER
  1247  		}
  1248  	}
  1249  	if !receivedok {
  1250  		t.Fatalf("message did not arrive")
  1251  	}
  1252  }
  1253  
  1254  // symmetric send performance with varying message sizes
  1255  func BenchmarkSymkeySend(b *testing.B) {
  1256  	b.Run(fmt.Sprintf("%d", 256), benchmarkSymKeySend)
  1257  	b.Run(fmt.Sprintf("%d", 1024), benchmarkSymKeySend)
  1258  	b.Run(fmt.Sprintf("%d", 1024*1024), benchmarkSymKeySend)
  1259  	b.Run(fmt.Sprintf("%d", 1024*1024*10), benchmarkSymKeySend)
  1260  	b.Run(fmt.Sprintf("%d", 1024*1024*100), benchmarkSymKeySend)
  1261  }
  1262  
  1263  func benchmarkSymKeySend(b *testing.B) {
  1264  	msgsizestring := strings.Split(b.Name(), "/")
  1265  	if len(msgsizestring) != 2 {
  1266  		b.Fatalf("benchmark called without msgsize param")
  1267  	}
  1268  	msgsize, err := strconv.ParseInt(msgsizestring[1], 10, 0)
  1269  	if err != nil {
  1270  		b.Fatalf("benchmark called with invalid msgsize param '%s': %v", msgsizestring[1], err)
  1271  	}
  1272  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  1273  	defer cancel()
  1274  	keys, err := wapi.NewKeyPair(ctx)
  1275  	privkey, err := w.GetPrivateKey(keys)
  1276  	ps := newTestPss(privkey, nil, nil)
  1277  	msg := make([]byte, msgsize)
  1278  	rand.Read(msg)
  1279  	topic := BytesToTopic([]byte("foo"))
  1280  	to := make(PssAddress, 32)
  1281  	copy(to[:], network.RandomAddr().Over())
  1282  	symkeyid, err := ps.GenerateSymmetricKey(topic, &to, true)
  1283  	if err != nil {
  1284  		b.Fatalf("could not generate symkey: %v", err)
  1285  	}
  1286  	symkey, err := ps.w.GetSymKey(symkeyid)
  1287  	if err != nil {
  1288  		b.Fatalf("could not retrieve symkey: %v", err)
  1289  	}
  1290  	ps.SetSymmetricKey(symkey, topic, &to, false)
  1291  
  1292  	b.ResetTimer()
  1293  	for i := 0; i < b.N; i++ {
  1294  		ps.SendSym(symkeyid, topic, msg)
  1295  	}
  1296  }
  1297  
  1298  // asymmetric send performance with varying message sizes
  1299  func BenchmarkAsymkeySend(b *testing.B) {
  1300  	b.Run(fmt.Sprintf("%d", 256), benchmarkAsymKeySend)
  1301  	b.Run(fmt.Sprintf("%d", 1024), benchmarkAsymKeySend)
  1302  	b.Run(fmt.Sprintf("%d", 1024*1024), benchmarkAsymKeySend)
  1303  	b.Run(fmt.Sprintf("%d", 1024*1024*10), benchmarkAsymKeySend)
  1304  	b.Run(fmt.Sprintf("%d", 1024*1024*100), benchmarkAsymKeySend)
  1305  }
  1306  
  1307  func benchmarkAsymKeySend(b *testing.B) {
  1308  	msgsizestring := strings.Split(b.Name(), "/")
  1309  	if len(msgsizestring) != 2 {
  1310  		b.Fatalf("benchmark called without msgsize param")
  1311  	}
  1312  	msgsize, err := strconv.ParseInt(msgsizestring[1], 10, 0)
  1313  	if err != nil {
  1314  		b.Fatalf("benchmark called with invalid msgsize param '%s': %v", msgsizestring[1], err)
  1315  	}
  1316  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  1317  	defer cancel()
  1318  	keys, err := wapi.NewKeyPair(ctx)
  1319  	privkey, err := w.GetPrivateKey(keys)
  1320  	ps := newTestPss(privkey, nil, nil)
  1321  	msg := make([]byte, msgsize)
  1322  	rand.Read(msg)
  1323  	topic := BytesToTopic([]byte("foo"))
  1324  	to := make(PssAddress, 32)
  1325  	copy(to[:], network.RandomAddr().Over())
  1326  	ps.SetPeerPublicKey(&privkey.PublicKey, topic, &to)
  1327  	b.ResetTimer()
  1328  	for i := 0; i < b.N; i++ {
  1329  		ps.SendAsym(common.ToHex(crypto.FromECDSAPub(&privkey.PublicKey)), topic, msg)
  1330  	}
  1331  }
  1332  func BenchmarkSymkeyBruteforceChangeaddr(b *testing.B) {
  1333  	for i := 100; i < 100000; i = i * 10 {
  1334  		for j := 32; j < 10000; j = j * 8 {
  1335  			b.Run(fmt.Sprintf("%d/%d", i, j), benchmarkSymkeyBruteforceChangeaddr)
  1336  		}
  1337  		//b.Run(fmt.Sprintf("%d", i), benchmarkSymkeyBruteforceChangeaddr)
  1338  	}
  1339  }
  1340  
  1341  // decrypt performance using symkey cache, worst case
  1342  // (decrypt key always last in cache)
  1343  func benchmarkSymkeyBruteforceChangeaddr(b *testing.B) {
  1344  	keycountstring := strings.Split(b.Name(), "/")
  1345  	cachesize := int64(0)
  1346  	var ps *Pss
  1347  	if len(keycountstring) < 2 {
  1348  		b.Fatalf("benchmark called without count param")
  1349  	}
  1350  	keycount, err := strconv.ParseInt(keycountstring[1], 10, 0)
  1351  	if err != nil {
  1352  		b.Fatalf("benchmark called with invalid count param '%s': %v", keycountstring[1], err)
  1353  	}
  1354  	if len(keycountstring) == 3 {
  1355  		cachesize, err = strconv.ParseInt(keycountstring[2], 10, 0)
  1356  		if err != nil {
  1357  			b.Fatalf("benchmark called with invalid cachesize '%s': %v", keycountstring[2], err)
  1358  		}
  1359  	}
  1360  	pssmsgs := make([]*PssMsg, 0, keycount)
  1361  	var keyid string
  1362  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  1363  	defer cancel()
  1364  	keys, err := wapi.NewKeyPair(ctx)
  1365  	privkey, err := w.GetPrivateKey(keys)
  1366  	if cachesize > 0 {
  1367  		ps = newTestPss(privkey, nil, &PssParams{SymKeyCacheCapacity: int(cachesize)})
  1368  	} else {
  1369  		ps = newTestPss(privkey, nil, nil)
  1370  	}
  1371  	topic := BytesToTopic([]byte("foo"))
  1372  	for i := 0; i < int(keycount); i++ {
  1373  		to := make(PssAddress, 32)
  1374  		copy(to[:], network.RandomAddr().Over())
  1375  		keyid, err = ps.GenerateSymmetricKey(topic, &to, true)
  1376  		if err != nil {
  1377  			b.Fatalf("cant generate symkey #%d: %v", i, err)
  1378  		}
  1379  		symkey, err := ps.w.GetSymKey(keyid)
  1380  		if err != nil {
  1381  			b.Fatalf("could not retrieve symkey %s: %v", keyid, err)
  1382  		}
  1383  		wparams := &whisper.MessageParams{
  1384  			TTL:      defaultWhisperTTL,
  1385  			KeySym:   symkey,
  1386  			Topic:    whisper.TopicType(topic),
  1387  			WorkTime: defaultWhisperWorkTime,
  1388  			PoW:      defaultWhisperPoW,
  1389  			Payload:  []byte("xyzzy"),
  1390  			Padding:  []byte("1234567890abcdef"),
  1391  		}
  1392  		woutmsg, err := whisper.NewSentMessage(wparams)
  1393  		if err != nil {
  1394  			b.Fatalf("could not create whisper message: %v", err)
  1395  		}
  1396  		env, err := woutmsg.Wrap(wparams)
  1397  		if err != nil {
  1398  			b.Fatalf("could not generate whisper envelope: %v", err)
  1399  		}
  1400  		ps.Register(&topic, func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
  1401  			return nil
  1402  		})
  1403  		pssmsgs = append(pssmsgs, &PssMsg{
  1404  			To:      to,
  1405  			Payload: env,
  1406  		})
  1407  	}
  1408  	b.ResetTimer()
  1409  	for i := 0; i < b.N; i++ {
  1410  		if err := ps.process(pssmsgs[len(pssmsgs)-(i%len(pssmsgs))-1]); err != nil {
  1411  			b.Fatalf("pss processing failed: %v", err)
  1412  		}
  1413  	}
  1414  }
  1415  
  1416  func BenchmarkSymkeyBruteforceSameaddr(b *testing.B) {
  1417  	for i := 100; i < 100000; i = i * 10 {
  1418  		for j := 32; j < 10000; j = j * 8 {
  1419  			b.Run(fmt.Sprintf("%d/%d", i, j), benchmarkSymkeyBruteforceSameaddr)
  1420  		}
  1421  	}
  1422  }
  1423  
  1424  // decrypt performance using symkey cache, best case
  1425  // (decrypt key always first in cache)
  1426  func benchmarkSymkeyBruteforceSameaddr(b *testing.B) {
  1427  	var keyid string
  1428  	var ps *Pss
  1429  	cachesize := int64(0)
  1430  	keycountstring := strings.Split(b.Name(), "/")
  1431  	if len(keycountstring) < 2 {
  1432  		b.Fatalf("benchmark called without count param")
  1433  	}
  1434  	keycount, err := strconv.ParseInt(keycountstring[1], 10, 0)
  1435  	if err != nil {
  1436  		b.Fatalf("benchmark called with invalid count param '%s': %v", keycountstring[1], err)
  1437  	}
  1438  	if len(keycountstring) == 3 {
  1439  		cachesize, err = strconv.ParseInt(keycountstring[2], 10, 0)
  1440  		if err != nil {
  1441  			b.Fatalf("benchmark called with invalid cachesize '%s': %v", keycountstring[2], err)
  1442  		}
  1443  	}
  1444  	addr := make([]PssAddress, keycount)
  1445  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  1446  	defer cancel()
  1447  	keys, err := wapi.NewKeyPair(ctx)
  1448  	privkey, err := w.GetPrivateKey(keys)
  1449  	if cachesize > 0 {
  1450  		ps = newTestPss(privkey, nil, &PssParams{SymKeyCacheCapacity: int(cachesize)})
  1451  	} else {
  1452  		ps = newTestPss(privkey, nil, nil)
  1453  	}
  1454  	topic := BytesToTopic([]byte("foo"))
  1455  	for i := 0; i < int(keycount); i++ {
  1456  		copy(addr[i], network.RandomAddr().Over())
  1457  		keyid, err = ps.GenerateSymmetricKey(topic, &addr[i], true)
  1458  		if err != nil {
  1459  			b.Fatalf("cant generate symkey #%d: %v", i, err)
  1460  		}
  1461  
  1462  	}
  1463  	symkey, err := ps.w.GetSymKey(keyid)
  1464  	if err != nil {
  1465  		b.Fatalf("could not retrieve symkey %s: %v", keyid, err)
  1466  	}
  1467  	wparams := &whisper.MessageParams{
  1468  		TTL:      defaultWhisperTTL,
  1469  		KeySym:   symkey,
  1470  		Topic:    whisper.TopicType(topic),
  1471  		WorkTime: defaultWhisperWorkTime,
  1472  		PoW:      defaultWhisperPoW,
  1473  		Payload:  []byte("xyzzy"),
  1474  		Padding:  []byte("1234567890abcdef"),
  1475  	}
  1476  	woutmsg, err := whisper.NewSentMessage(wparams)
  1477  	if err != nil {
  1478  		b.Fatalf("could not create whisper message: %v", err)
  1479  	}
  1480  	env, err := woutmsg.Wrap(wparams)
  1481  	if err != nil {
  1482  		b.Fatalf("could not generate whisper envelope: %v", err)
  1483  	}
  1484  	ps.Register(&topic, func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
  1485  		return nil
  1486  	})
  1487  	pssmsg := &PssMsg{
  1488  		To:      addr[len(addr)-1][:],
  1489  		Payload: env,
  1490  	}
  1491  	for i := 0; i < b.N; i++ {
  1492  		if err := ps.process(pssmsg); err != nil {
  1493  			b.Fatalf("pss processing failed: %v", err)
  1494  		}
  1495  	}
  1496  }
  1497  
  1498  // setup simulated network with bzz/discovery and pss services.
  1499  // connects nodes in a circle
  1500  // if allowRaw is set, omission of builtin pss encryption is enabled (see PssParams)
  1501  func setupNetwork(numnodes int, allowRaw bool) (clients []*rpc.Client, err error) {
  1502  	nodes := make([]*simulations.Node, numnodes)
  1503  	clients = make([]*rpc.Client, numnodes)
  1504  	if numnodes < 2 {
  1505  		return nil, fmt.Errorf("Minimum two nodes in network")
  1506  	}
  1507  	adapter := adapters.NewSimAdapter(newServices(allowRaw))
  1508  	net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{
  1509  		ID:             "0",
  1510  		DefaultService: "bzz",
  1511  	})
  1512  	for i := 0; i < numnodes; i++ {
  1513  		nodeconf := adapters.RandomNodeConfig()
  1514  		nodeconf.Services = []string{"bzz", pssProtocolName}
  1515  		nodes[i], err = net.NewNodeWithConfig(nodeconf)
  1516  		if err != nil {
  1517  			return nil, fmt.Errorf("error creating node 1: %v", err)
  1518  		}
  1519  		err = net.Start(nodes[i].ID())
  1520  		if err != nil {
  1521  			return nil, fmt.Errorf("error starting node 1: %v", err)
  1522  		}
  1523  		if i > 0 {
  1524  			err = net.Connect(nodes[i].ID(), nodes[i-1].ID())
  1525  			if err != nil {
  1526  				return nil, fmt.Errorf("error connecting nodes: %v", err)
  1527  			}
  1528  		}
  1529  		clients[i], err = nodes[i].Client()
  1530  		if err != nil {
  1531  			return nil, fmt.Errorf("create node 1 rpc client fail: %v", err)
  1532  		}
  1533  	}
  1534  	if numnodes > 2 {
  1535  		err = net.Connect(nodes[0].ID(), nodes[len(nodes)-1].ID())
  1536  		if err != nil {
  1537  			return nil, fmt.Errorf("error connecting first and last nodes")
  1538  		}
  1539  	}
  1540  	return clients, nil
  1541  }
  1542  
  1543  func newServices(allowRaw bool) adapters.Services {
  1544  	stateStore := state.NewInmemoryStore()
  1545  	kademlias := make(map[discover.NodeID]*network.Kademlia)
  1546  	kademlia := func(id discover.NodeID) *network.Kademlia {
  1547  		if k, ok := kademlias[id]; ok {
  1548  			return k
  1549  		}
  1550  		addr := network.NewAddrFromNodeID(id)
  1551  		params := network.NewKadParams()
  1552  		params.MinProxBinSize = 2
  1553  		params.MaxBinSize = 3
  1554  		params.MinBinSize = 1
  1555  		params.MaxRetries = 1000
  1556  		params.RetryExponent = 2
  1557  		params.RetryInterval = 1000000
  1558  		kademlias[id] = network.NewKademlia(addr.Over(), params)
  1559  		return kademlias[id]
  1560  	}
  1561  	return adapters.Services{
  1562  		pssProtocolName: func(ctx *adapters.ServiceContext) (node.Service, error) {
  1563  			// execadapter does not exec init()
  1564  			initTest()
  1565  
  1566  			ctxlocal, cancel := context.WithTimeout(context.Background(), time.Second)
  1567  			defer cancel()
  1568  			keys, err := wapi.NewKeyPair(ctxlocal)
  1569  			privkey, err := w.GetPrivateKey(keys)
  1570  			pssp := NewPssParams().WithPrivateKey(privkey)
  1571  			pssp.AllowRaw = allowRaw
  1572  			pskad := kademlia(ctx.Config.ID)
  1573  			ps, err := NewPss(pskad, pssp)
  1574  			if err != nil {
  1575  				return nil, err
  1576  			}
  1577  
  1578  			ping := &Ping{
  1579  				OutC: make(chan bool),
  1580  				Pong: true,
  1581  			}
  1582  			p2pp := NewPingProtocol(ping)
  1583  			pp, err := RegisterProtocol(ps, &PingTopic, PingProtocol, p2pp, &ProtocolParams{Asymmetric: true})
  1584  			if err != nil {
  1585  				return nil, err
  1586  			}
  1587  			if useHandshake {
  1588  				SetHandshakeController(ps, NewHandshakeParams())
  1589  			}
  1590  			ps.Register(&PingTopic, pp.Handle)
  1591  			ps.addAPI(rpc.API{
  1592  				Namespace: "psstest",
  1593  				Version:   "0.3",
  1594  				Service:   NewAPITest(ps),
  1595  				Public:    false,
  1596  			})
  1597  			if err != nil {
  1598  				log.Error("Couldnt register pss protocol", "err", err)
  1599  				os.Exit(1)
  1600  			}
  1601  			pssprotocols[ctx.Config.ID.String()] = &protoCtrl{
  1602  				C:        ping.OutC,
  1603  				protocol: pp,
  1604  				run:      p2pp.Run,
  1605  			}
  1606  			return ps, nil
  1607  		},
  1608  		"bzz": func(ctx *adapters.ServiceContext) (node.Service, error) {
  1609  			addr := network.NewAddrFromNodeID(ctx.Config.ID)
  1610  			hp := network.NewHiveParams()
  1611  			hp.Discovery = false
  1612  			config := &network.BzzConfig{
  1613  				OverlayAddr:  addr.Over(),
  1614  				UnderlayAddr: addr.Under(),
  1615  				HiveParams:   hp,
  1616  			}
  1617  			return network.NewBzz(config, kademlia(ctx.Config.ID), stateStore, nil, nil), nil
  1618  		},
  1619  	}
  1620  }
  1621  
  1622  func newTestPss(privkey *ecdsa.PrivateKey, kad *network.Kademlia, ppextra *PssParams) *Pss {
  1623  
  1624  	var nid discover.NodeID
  1625  	copy(nid[:], crypto.FromECDSAPub(&privkey.PublicKey))
  1626  	addr := network.NewAddrFromNodeID(nid)
  1627  
  1628  	// set up routing if kademlia is not passed to us
  1629  	if kad == nil {
  1630  		kp := network.NewKadParams()
  1631  		kp.MinProxBinSize = 3
  1632  		kad = network.NewKademlia(addr.Over(), kp)
  1633  	}
  1634  
  1635  	// create pss
  1636  	pp := NewPssParams().WithPrivateKey(privkey)
  1637  	if ppextra != nil {
  1638  		pp.SymKeyCacheCapacity = ppextra.SymKeyCacheCapacity
  1639  	}
  1640  	ps, err := NewPss(kad, pp)
  1641  	if err != nil {
  1642  		return nil
  1643  	}
  1644  	ps.Start(nil)
  1645  
  1646  	return ps
  1647  }
  1648  
  1649  // API calls for test/development use
  1650  type APITest struct {
  1651  	*Pss
  1652  }
  1653  
  1654  func NewAPITest(ps *Pss) *APITest {
  1655  	return &APITest{Pss: ps}
  1656  }
  1657  
  1658  func (apitest *APITest) SetSymKeys(pubkeyid string, recvsymkey []byte, sendsymkey []byte, limit uint16, topic Topic, to PssAddress) ([2]string, error) {
  1659  	recvsymkeyid, err := apitest.SetSymmetricKey(recvsymkey, topic, &to, true)
  1660  	if err != nil {
  1661  		return [2]string{}, err
  1662  	}
  1663  	sendsymkeyid, err := apitest.SetSymmetricKey(sendsymkey, topic, &to, false)
  1664  	if err != nil {
  1665  		return [2]string{}, err
  1666  	}
  1667  	return [2]string{recvsymkeyid, sendsymkeyid}, nil
  1668  }
  1669  
  1670  func (apitest *APITest) Clean() (int, error) {
  1671  	return apitest.Pss.cleanKeys(), nil
  1672  }
  1673  
  1674  // enableMetrics is starting InfluxDB reporter so that we collect stats when running tests locally
  1675  func enableMetrics() {
  1676  	metrics.Enabled = true
  1677  	go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 1*time.Second, "http://localhost:8086", "metrics", "admin", "admin", "swarm.", map[string]string{
  1678  		"host": "test",
  1679  	})
  1680  }