github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/gossip/comm/comm_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package comm
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/tls"
    22  	"fmt"
    23  	"math/rand"
    24  	"os"
    25  	"strings"
    26  	"sync"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/hyperledger/fabric/gossip/api"
    31  	"github.com/hyperledger/fabric/gossip/common"
    32  	"github.com/hyperledger/fabric/gossip/identity"
    33  	"github.com/hyperledger/fabric/gossip/util"
    34  	proto "github.com/hyperledger/fabric/protos/gossip"
    35  	"github.com/spf13/viper"
    36  	"github.com/stretchr/testify/assert"
    37  	"golang.org/x/net/context"
    38  	"google.golang.org/grpc"
    39  	"google.golang.org/grpc/credentials"
    40  )
    41  
    42  func init() {
    43  	rand.Seed(42)
    44  }
    45  
    46  func acceptAll(msg interface{}) bool {
    47  	return true
    48  }
    49  
    50  var naiveSec = &naiveSecProvider{}
    51  
    52  type naiveSecProvider struct {
    53  }
    54  
    55  func (*naiveSecProvider) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
    56  	return nil
    57  }
    58  
    59  // GetPKIidOfCert returns the PKI-ID of a peer's identity
    60  func (*naiveSecProvider) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
    61  	return common.PKIidType(peerIdentity)
    62  }
    63  
    64  // VerifyBlock returns nil if the block is properly signed,
    65  // else returns error
    66  func (*naiveSecProvider) VerifyBlock(chainID common.ChainID, signedBlock api.SignedBlock) error {
    67  	return nil
    68  }
    69  
    70  // Sign signs msg with this peer's signing key and outputs
    71  // the signature if no error occurred.
    72  func (*naiveSecProvider) Sign(msg []byte) ([]byte, error) {
    73  	return msg, nil
    74  }
    75  
    76  // Verify checks that signature is a valid signature of message under a peer's verification key.
    77  // If the verification succeeded, Verify returns nil meaning no error occurred.
    78  // If peerCert is nil, then the signature is verified against this peer's verification key.
    79  func (*naiveSecProvider) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
    80  	equal := bytes.Equal(signature, message)
    81  	if !equal {
    82  		return fmt.Errorf("Wrong certificate:%v, %v", signature, message)
    83  	}
    84  	return nil
    85  }
    86  
    87  // VerifyByChannel verifies a peer's signature on a message in the context
    88  // of a specific channel
    89  func (*naiveSecProvider) VerifyByChannel(_ common.ChainID, _ api.PeerIdentityType, _, _ []byte) error {
    90  	return nil
    91  }
    92  
    93  func newCommInstance(port int, sec api.MessageCryptoService) (Comm, error) {
    94  	endpoint := fmt.Sprintf("localhost:%d", port)
    95  	inst, err := NewCommInstanceWithServer(port, identity.NewIdentityMapper(sec), []byte(endpoint))
    96  	return inst, err
    97  }
    98  
    99  func handshaker(endpoint string, comm Comm, t *testing.T, sigMutator func([]byte) []byte, pkiIDmutator func([]byte) []byte) <-chan proto.ReceivedMessage {
   100  	c := &commImpl{}
   101  	err := generateCertificates("key.pem", "cert.pem")
   102  	defer os.Remove("cert.pem")
   103  	defer os.Remove("key.pem")
   104  	cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
   105  	ta := credentials.NewTLS(&tls.Config{
   106  		InsecureSkipVerify: true,
   107  		Certificates:       []tls.Certificate{cert},
   108  	})
   109  	acceptChan := comm.Accept(acceptAll)
   110  	conn, err := grpc.Dial("localhost:9611", grpc.WithTransportCredentials(&authCreds{tlsCreds: ta}), grpc.WithBlock(), grpc.WithTimeout(time.Second))
   111  	assert.NoError(t, err, "%v", err)
   112  	if err != nil {
   113  		return nil
   114  	}
   115  	cl := proto.NewGossipClient(conn)
   116  	stream, err := cl.GossipStream(context.Background())
   117  	assert.NoError(t, err, "%v", err)
   118  	if err != nil {
   119  		return nil
   120  	}
   121  	clientCertHash := certHashFromRawCert(cert.Certificate[0])
   122  
   123  	pkiID := common.PKIidType(endpoint)
   124  	if pkiIDmutator != nil {
   125  		pkiID = common.PKIidType(pkiIDmutator([]byte(endpoint)))
   126  	}
   127  	assert.NoError(t, err, "%v", err)
   128  	msg := c.createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) {
   129  		return msg, nil
   130  	})
   131  
   132  	if sigMutator != nil {
   133  		msg.Envelope.Signature = sigMutator(msg.Envelope.Signature)
   134  	}
   135  
   136  	stream.Send(msg.Envelope)
   137  	envelope, err := stream.Recv()
   138  	assert.NoError(t, err, "%v", err)
   139  	msg, err = envelope.ToGossipMessage()
   140  	assert.NoError(t, err, "%v", err)
   141  	if sigMutator == nil {
   142  		hash := extractCertificateHashFromContext(stream.Context())
   143  		expectedMsg := c.createConnectionMsg(common.PKIidType("localhost:9611"), hash, []byte("localhost:9611"), func(msg []byte) ([]byte, error) {
   144  			return msg, nil
   145  		})
   146  		assert.Equal(t, expectedMsg.Envelope.Signature, msg.Envelope.Signature)
   147  	}
   148  	assert.Equal(t, []byte("localhost:9611"), msg.GetConn().PkiID)
   149  	msg2Send := createGossipMsg()
   150  	nonce := uint64(rand.Int())
   151  	msg2Send.Nonce = nonce
   152  	go stream.Send(msg2Send.Envelope)
   153  	return acceptChan
   154  }
   155  
   156  func TestViperConfig(t *testing.T) {
   157  	viper.SetConfigName("core")
   158  	viper.SetEnvPrefix("CORE")
   159  	viper.AddConfigPath("./../../peer")
   160  	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
   161  	viper.AutomaticEnv()
   162  	err := viper.ReadInConfig()
   163  	if err != nil { // Handle errors reading the config file
   164  		panic(fmt.Errorf("Fatal error config file: %s \n", err))
   165  	}
   166  
   167  	assert.Equal(t, time.Duration(2)*time.Second, util.GetDurationOrDefault("peer.gossip.connTimeout", 0))
   168  	assert.Equal(t, time.Duration(300)*time.Millisecond, util.GetDurationOrDefault("peer.gossip.dialTimeout", 0))
   169  	assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.recvBuffSize", 0))
   170  	assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.sendBuffSize", 0))
   171  }
   172  
   173  func TestHandshake(t *testing.T) {
   174  	t.Parallel()
   175  	comm, _ := newCommInstance(9611, naiveSec)
   176  	defer comm.Stop()
   177  
   178  	acceptChan := handshaker("localhost:9610", comm, t, nil, nil)
   179  	time.Sleep(2 * time.Second)
   180  	assert.Equal(t, 1, len(acceptChan))
   181  
   182  	// negative path, nothing should be read from the channel because the signature is wrong
   183  	mutateSig := func(b []byte) []byte {
   184  		if b[0] == 0 {
   185  			b[0] = 1
   186  		} else {
   187  			b[0] = 0
   188  		}
   189  		return b
   190  	}
   191  	acceptChan = handshaker("localhost:9612", comm, t, mutateSig, nil)
   192  	time.Sleep(time.Second)
   193  	assert.Equal(t, 0, len(acceptChan))
   194  
   195  	// negative path, nothing should be read from the channel because the PKIid doesn't match the identity
   196  	mutatePKIID := func(b []byte) []byte {
   197  		return []byte("localhost:9650")
   198  	}
   199  	acceptChan = handshaker("localhost:9613", comm, t, nil, mutatePKIID)
   200  	time.Sleep(time.Second)
   201  	assert.Equal(t, 0, len(acceptChan))
   202  }
   203  
   204  func TestBasic(t *testing.T) {
   205  	t.Parallel()
   206  	comm1, _ := newCommInstance(2000, naiveSec)
   207  	comm2, _ := newCommInstance(3000, naiveSec)
   208  	defer comm1.Stop()
   209  	defer comm2.Stop()
   210  	m1 := comm1.Accept(acceptAll)
   211  	m2 := comm2.Accept(acceptAll)
   212  	out := make(chan uint64, 2)
   213  	reader := func(ch <-chan proto.ReceivedMessage) {
   214  		m := <-ch
   215  		out <- m.GetGossipMessage().Nonce
   216  	}
   217  	go reader(m1)
   218  	go reader(m2)
   219  	comm1.Send(createGossipMsg(), remotePeer(3000))
   220  	time.Sleep(time.Second)
   221  	comm2.Send(createGossipMsg(), remotePeer(2000))
   222  	waitForMessages(t, out, 2, "Didn't receive 2 messages")
   223  }
   224  
   225  func TestGetPKIID(t *testing.T) {
   226  	t.Parallel()
   227  	comm1, _ := newCommInstance(6000, naiveSec)
   228  	comm2, _ := newCommInstance(7000, naiveSec)
   229  	defer comm1.Stop()
   230  	defer comm2.Stop()
   231  	m1 := comm1.Accept(acceptAll)
   232  	comm2.Send(createGossipMsg(), remotePeer(6000))
   233  	select {
   234  	case <-time.After(time.Second * 10):
   235  		t.Fatal("Didn't receive a message in time")
   236  	case msg := <-m1:
   237  		assert.Equal(t, comm2.GetPKIid(), msg.GetPKIID())
   238  	}
   239  }
   240  
   241  func TestBlackListPKIid(t *testing.T) {
   242  	t.Parallel()
   243  	comm1, _ := newCommInstance(1611, naiveSec)
   244  	comm2, _ := newCommInstance(1612, naiveSec)
   245  	comm3, _ := newCommInstance(1613, naiveSec)
   246  	comm4, _ := newCommInstance(1614, naiveSec)
   247  	defer comm1.Stop()
   248  	defer comm2.Stop()
   249  	defer comm3.Stop()
   250  	defer comm4.Stop()
   251  
   252  	reader := func(instance string, out chan uint64, in <-chan proto.ReceivedMessage) {
   253  		for {
   254  			msg := <-in
   255  			if msg == nil {
   256  				return
   257  			}
   258  			out <- msg.GetGossipMessage().Nonce
   259  		}
   260  	}
   261  
   262  	out1 := make(chan uint64, 4)
   263  	out2 := make(chan uint64, 4)
   264  	out3 := make(chan uint64, 4)
   265  	out4 := make(chan uint64, 4)
   266  
   267  	go reader("comm1", out1, comm1.Accept(acceptAll))
   268  	go reader("comm2", out2, comm2.Accept(acceptAll))
   269  	go reader("comm3", out3, comm3.Accept(acceptAll))
   270  	go reader("comm4", out4, comm4.Accept(acceptAll))
   271  
   272  	// have comm1 BL comm3
   273  	comm1.BlackListPKIid([]byte("localhost:1613"))
   274  
   275  	// make comm3 send to 1 and 2
   276  	comm3.Send(createGossipMsg(), remotePeer(1612)) // out2++
   277  	comm3.Send(createGossipMsg(), remotePeer(1611))
   278  
   279  	waitForMessages(t, out2, 1, "comm2 should have received 1 message")
   280  
   281  	// make comm1 and comm2 send to comm3
   282  	comm1.Send(createGossipMsg(), remotePeer(1613))
   283  	comm2.Send(createGossipMsg(), remotePeer(1613)) // out3++
   284  	waitForMessages(t, out3, 1, "comm3 should have received 1 message")
   285  
   286  	// make comm1 and comm2 send to comm4 which is not blacklisted		// out4 += 4
   287  	comm1.Send(createGossipMsg(), remotePeer(1614))
   288  	comm2.Send(createGossipMsg(), remotePeer(1614))
   289  	comm1.Send(createGossipMsg(), remotePeer(1614))
   290  	comm2.Send(createGossipMsg(), remotePeer(1614))
   291  
   292  	// blacklist comm3 by comm2
   293  	comm2.BlackListPKIid([]byte("localhost:1613"))
   294  
   295  	// send from comm1 and comm2 to comm3 again
   296  	comm1.Send(createGossipMsg(), remotePeer(1613)) // shouldn't have an effect
   297  	comm2.Send(createGossipMsg(), remotePeer(1613)) // shouldn't have an effect
   298  
   299  	waitForMessages(t, out4, 4, "comm1 should have received 4 messages")
   300  }
   301  
   302  func TestParallelSend(t *testing.T) {
   303  	t.Parallel()
   304  	comm1, _ := newCommInstance(5411, naiveSec)
   305  	comm2, _ := newCommInstance(5412, naiveSec)
   306  	defer comm1.Stop()
   307  	defer comm2.Stop()
   308  
   309  	messages2Send := util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize)
   310  
   311  	wg := sync.WaitGroup{}
   312  	go func() {
   313  		for i := 0; i < messages2Send; i++ {
   314  			wg.Add(1)
   315  			emptyMsg := createGossipMsg()
   316  			go func() {
   317  				defer wg.Done()
   318  				comm1.Send(emptyMsg, remotePeer(5412))
   319  			}()
   320  		}
   321  		wg.Wait()
   322  	}()
   323  
   324  	c := 0
   325  	waiting := true
   326  	ticker := time.NewTicker(time.Duration(5) * time.Second)
   327  	ch := comm2.Accept(acceptAll)
   328  	for waiting {
   329  		select {
   330  		case <-ch:
   331  			c++
   332  			if c == messages2Send {
   333  				waiting = false
   334  			}
   335  			break
   336  		case <-ticker.C:
   337  			waiting = false
   338  			break
   339  		}
   340  	}
   341  	assert.Equal(t, messages2Send, c)
   342  }
   343  
   344  func TestResponses(t *testing.T) {
   345  	t.Parallel()
   346  	comm1, _ := newCommInstance(8611, naiveSec)
   347  	comm2, _ := newCommInstance(8612, naiveSec)
   348  
   349  	defer comm1.Stop()
   350  	defer comm2.Stop()
   351  
   352  	msg := createGossipMsg()
   353  	go func() {
   354  		inChan := comm1.Accept(acceptAll)
   355  		for m := range inChan {
   356  			reply := createGossipMsg()
   357  			reply.Nonce = m.GetGossipMessage().Nonce + 1
   358  			m.Respond(reply.GossipMessage)
   359  		}
   360  	}()
   361  	expectedNOnce := uint64(msg.Nonce + 1)
   362  	responsesFromComm1 := comm2.Accept(acceptAll)
   363  
   364  	ticker := time.NewTicker(time.Duration(6000) * time.Millisecond)
   365  	comm2.Send(msg, remotePeer(8611))
   366  	time.Sleep(time.Duration(100) * time.Millisecond)
   367  
   368  	select {
   369  	case <-ticker.C:
   370  		assert.Fail(t, "Haven't got response from comm1 within a timely manner")
   371  		break
   372  	case resp := <-responsesFromComm1:
   373  		ticker.Stop()
   374  		assert.Equal(t, expectedNOnce, resp.GetGossipMessage().Nonce)
   375  		break
   376  	}
   377  }
   378  
   379  func TestAccept(t *testing.T) {
   380  	t.Parallel()
   381  	comm1, _ := newCommInstance(7611, naiveSec)
   382  	comm2, _ := newCommInstance(7612, naiveSec)
   383  
   384  	evenNONCESelector := func(m interface{}) bool {
   385  		return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 == 0
   386  	}
   387  
   388  	oddNONCESelector := func(m interface{}) bool {
   389  		return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 != 0
   390  	}
   391  
   392  	evenNONCES := comm1.Accept(evenNONCESelector)
   393  	oddNONCES := comm1.Accept(oddNONCESelector)
   394  
   395  	var evenResults []uint64
   396  	var oddResults []uint64
   397  
   398  	out := make(chan uint64, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize))
   399  	sem := make(chan struct{}, 0)
   400  
   401  	readIntoSlice := func(a *[]uint64, ch <-chan proto.ReceivedMessage) {
   402  		for m := range ch {
   403  			*a = append(*a, m.GetGossipMessage().Nonce)
   404  			out <- m.GetGossipMessage().Nonce
   405  		}
   406  		sem <- struct{}{}
   407  	}
   408  
   409  	go readIntoSlice(&evenResults, evenNONCES)
   410  	go readIntoSlice(&oddResults, oddNONCES)
   411  
   412  	for i := 0; i < util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize); i++ {
   413  		comm2.Send(createGossipMsg(), remotePeer(7611))
   414  	}
   415  
   416  	waitForMessages(t, out, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize), "Didn't receive all messages sent")
   417  
   418  	comm1.Stop()
   419  	comm2.Stop()
   420  
   421  	<-sem
   422  	<-sem
   423  
   424  	assert.NotEmpty(t, evenResults)
   425  	assert.NotEmpty(t, oddResults)
   426  
   427  	remainderPredicate := func(a []uint64, rem uint64) {
   428  		for _, n := range a {
   429  			assert.Equal(t, n%2, rem)
   430  		}
   431  	}
   432  
   433  	remainderPredicate(evenResults, 0)
   434  	remainderPredicate(oddResults, 1)
   435  }
   436  
   437  func TestReConnections(t *testing.T) {
   438  	t.Parallel()
   439  	comm1, _ := newCommInstance(3611, naiveSec)
   440  	comm2, _ := newCommInstance(3612, naiveSec)
   441  
   442  	reader := func(out chan uint64, in <-chan proto.ReceivedMessage) {
   443  		for {
   444  			msg := <-in
   445  			if msg == nil {
   446  				return
   447  			}
   448  			out <- msg.GetGossipMessage().Nonce
   449  		}
   450  	}
   451  
   452  	out1 := make(chan uint64, 10)
   453  	out2 := make(chan uint64, 10)
   454  
   455  	go reader(out1, comm1.Accept(acceptAll))
   456  	go reader(out2, comm2.Accept(acceptAll))
   457  
   458  	// comm1 connects to comm2
   459  	comm1.Send(createGossipMsg(), remotePeer(3612))
   460  	waitForMessages(t, out2, 1, "Comm2 didn't receive a message from comm1 in a timely manner")
   461  	time.Sleep(time.Second)
   462  	// comm2 sends to comm1
   463  	comm2.Send(createGossipMsg(), remotePeer(3611))
   464  	waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner")
   465  
   466  	comm1.Stop()
   467  	comm1, _ = newCommInstance(3611, naiveSec)
   468  	time.Sleep(time.Second)
   469  	out1 = make(chan uint64, 1)
   470  	go reader(out1, comm1.Accept(acceptAll))
   471  	comm2.Send(createGossipMsg(), remotePeer(3611))
   472  	waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner")
   473  }
   474  
   475  func TestProbe(t *testing.T) {
   476  	t.Parallel()
   477  	comm1, _ := newCommInstance(6611, naiveSec)
   478  	defer comm1.Stop()
   479  	comm2, _ := newCommInstance(6612, naiveSec)
   480  	time.Sleep(time.Duration(1) * time.Second)
   481  	assert.NoError(t, comm1.Probe(remotePeer(6612)))
   482  	assert.Error(t, comm1.Probe(remotePeer(9012)))
   483  	comm2.Stop()
   484  	time.Sleep(time.Second)
   485  	assert.Error(t, comm1.Probe(remotePeer(6612)))
   486  	comm2, _ = newCommInstance(6612, naiveSec)
   487  	defer comm2.Stop()
   488  	time.Sleep(time.Duration(1) * time.Second)
   489  	assert.NoError(t, comm2.Probe(remotePeer(6611)))
   490  	assert.NoError(t, comm1.Probe(remotePeer(6612)))
   491  }
   492  
   493  func TestPresumedDead(t *testing.T) {
   494  	t.Parallel()
   495  	comm1, _ := newCommInstance(4611, naiveSec)
   496  	comm2, _ := newCommInstance(4612, naiveSec)
   497  	go comm1.Send(createGossipMsg(), remotePeer(4612))
   498  	<-comm2.Accept(acceptAll)
   499  	comm2.Stop()
   500  	go func() {
   501  		for i := 0; i < 5; i++ {
   502  			comm1.Send(createGossipMsg(), remotePeer(4612))
   503  			time.Sleep(time.Millisecond * 200)
   504  		}
   505  	}()
   506  
   507  	ticker := time.NewTicker(time.Second * time.Duration(3))
   508  	select {
   509  	case <-ticker.C:
   510  		assert.Fail(t, "Didn't get a presumed dead message within a timely manner")
   511  		break
   512  	case <-comm1.PresumedDead():
   513  		ticker.Stop()
   514  		break
   515  	}
   516  }
   517  
   518  func createGossipMsg() *proto.SignedGossipMessage {
   519  	return (&proto.GossipMessage{
   520  		Tag:   proto.GossipMessage_EMPTY,
   521  		Nonce: uint64(rand.Int()),
   522  		Content: &proto.GossipMessage_DataMsg{
   523  			DataMsg: &proto.DataMessage{},
   524  		},
   525  	}).NoopSign()
   526  }
   527  
   528  func remotePeer(port int) *RemotePeer {
   529  	endpoint := fmt.Sprintf("localhost:%d", port)
   530  	return &RemotePeer{Endpoint: endpoint, PKIID: []byte(endpoint)}
   531  }
   532  
   533  func waitForMessages(t *testing.T, msgChan chan uint64, count int, errMsg string) {
   534  	c := 0
   535  	waiting := true
   536  	ticker := time.NewTicker(time.Duration(10) * time.Second)
   537  	for waiting {
   538  		select {
   539  		case <-msgChan:
   540  			c++
   541  			if c == count {
   542  				waiting = false
   543  			}
   544  			break
   545  		case <-ticker.C:
   546  			waiting = false
   547  			break
   548  		}
   549  	}
   550  	assert.Equal(t, count, c, errMsg)
   551  }
   552  
   553  func TestMain(m *testing.M) {
   554  	SetDialTimeout(time.Duration(300) * time.Millisecond)
   555  
   556  	ret := m.Run()
   557  	os.Exit(ret)
   558  }