github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/gossip/state/state_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 state
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"strconv"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  
    28  	pb "github.com/golang/protobuf/proto"
    29  	"github.com/hyperledger/fabric/common/configtx/test"
    30  	"github.com/hyperledger/fabric/common/util"
    31  	"github.com/hyperledger/fabric/core/committer"
    32  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
    33  	"github.com/hyperledger/fabric/core/mocks/validator"
    34  	"github.com/hyperledger/fabric/gossip/api"
    35  	"github.com/hyperledger/fabric/gossip/comm"
    36  	"github.com/hyperledger/fabric/gossip/common"
    37  	"github.com/hyperledger/fabric/gossip/gossip"
    38  	"github.com/hyperledger/fabric/gossip/identity"
    39  	"github.com/hyperledger/fabric/gossip/state/mocks"
    40  	gutil "github.com/hyperledger/fabric/gossip/util"
    41  	pcomm "github.com/hyperledger/fabric/protos/common"
    42  	proto "github.com/hyperledger/fabric/protos/gossip"
    43  	"github.com/spf13/viper"
    44  	"github.com/stretchr/testify/assert"
    45  	"github.com/stretchr/testify/mock"
    46  )
    47  
    48  var (
    49  	portPrefix = 5610
    50  )
    51  
    52  var orgID = []byte("ORG1")
    53  
    54  type peerIdentityAcceptor func(identity api.PeerIdentityType) error
    55  
    56  var noopPeerIdentityAcceptor = func(identity api.PeerIdentityType) error {
    57  	return nil
    58  }
    59  
    60  type joinChanMsg struct {
    61  }
    62  
    63  func init() {
    64  	gutil.SetupTestLogging()
    65  }
    66  
    67  // SequenceNumber returns the sequence number of the block that the message
    68  // is derived from
    69  func (*joinChanMsg) SequenceNumber() uint64 {
    70  	return uint64(time.Now().UnixNano())
    71  }
    72  
    73  // Members returns the organizations of the channel
    74  func (jcm *joinChanMsg) Members() []api.OrgIdentityType {
    75  	return []api.OrgIdentityType{orgID}
    76  }
    77  
    78  // AnchorPeersOf returns the anchor peers of the given organization
    79  func (jcm *joinChanMsg) AnchorPeersOf(org api.OrgIdentityType) []api.AnchorPeer {
    80  	return []api.AnchorPeer{}
    81  }
    82  
    83  type orgCryptoService struct {
    84  }
    85  
    86  // OrgByPeerIdentity returns the OrgIdentityType
    87  // of a given peer identity
    88  func (*orgCryptoService) OrgByPeerIdentity(identity api.PeerIdentityType) api.OrgIdentityType {
    89  	return orgID
    90  }
    91  
    92  // Verify verifies a JoinChannelMessage, returns nil on success,
    93  // and an error on failure
    94  func (*orgCryptoService) Verify(joinChanMsg api.JoinChannelMessage) error {
    95  	return nil
    96  }
    97  
    98  type cryptoServiceMock struct {
    99  	acceptor peerIdentityAcceptor
   100  }
   101  
   102  // GetPKIidOfCert returns the PKI-ID of a peer's identity
   103  func (*cryptoServiceMock) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
   104  	return common.PKIidType(peerIdentity)
   105  }
   106  
   107  // VerifyBlock returns nil if the block is properly signed,
   108  // else returns error
   109  func (*cryptoServiceMock) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
   110  	return nil
   111  }
   112  
   113  // Sign signs msg with this peer's signing key and outputs
   114  // the signature if no error occurred.
   115  func (*cryptoServiceMock) Sign(msg []byte) ([]byte, error) {
   116  	clone := make([]byte, len(msg))
   117  	copy(clone, msg)
   118  	return clone, nil
   119  }
   120  
   121  // Verify checks that signature is a valid signature of message under a peer's verification key.
   122  // If the verification succeeded, Verify returns nil meaning no error occurred.
   123  // If peerCert is nil, then the signature is verified against this peer's verification key.
   124  func (*cryptoServiceMock) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
   125  	equal := bytes.Equal(signature, message)
   126  	if !equal {
   127  		return fmt.Errorf("Wrong signature:%v, %v", signature, message)
   128  	}
   129  	return nil
   130  }
   131  
   132  // VerifyByChannel checks that signature is a valid signature of message
   133  // under a peer's verification key, but also in the context of a specific channel.
   134  // If the verification succeeded, Verify returns nil meaning no error occurred.
   135  // If peerIdentity is nil, then the signature is verified against this peer's verification key.
   136  func (cs *cryptoServiceMock) VerifyByChannel(chainID common.ChainID, peerIdentity api.PeerIdentityType, signature, message []byte) error {
   137  	return cs.acceptor(peerIdentity)
   138  }
   139  
   140  func (*cryptoServiceMock) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
   141  	return nil
   142  }
   143  
   144  func bootPeers(ids ...int) []string {
   145  	peers := []string{}
   146  	for _, id := range ids {
   147  		peers = append(peers, fmt.Sprintf("localhost:%d", id+portPrefix))
   148  	}
   149  	return peers
   150  }
   151  
   152  // Simple presentation of peer which includes only
   153  // communication module, gossip and state transfer
   154  type peerNode struct {
   155  	port   int
   156  	g      gossip.Gossip
   157  	s      GossipStateProvider
   158  	cs     *cryptoServiceMock
   159  	commit committer.Committer
   160  }
   161  
   162  // Shutting down all modules used
   163  func (node *peerNode) shutdown() {
   164  	node.s.Stop()
   165  	node.g.Stop()
   166  }
   167  
   168  type mockCommitter struct {
   169  	mock.Mock
   170  }
   171  
   172  func (mc *mockCommitter) Commit(block *pcomm.Block) error {
   173  	mc.Called(block)
   174  	return nil
   175  }
   176  
   177  func (mc *mockCommitter) LedgerHeight() (uint64, error) {
   178  	if mc.Called().Get(1) == nil {
   179  		return mc.Called().Get(0).(uint64), nil
   180  	}
   181  	return mc.Called().Get(0).(uint64), mc.Called().Get(1).(error)
   182  }
   183  
   184  func (mc *mockCommitter) GetBlocks(blockSeqs []uint64) []*pcomm.Block {
   185  	if mc.Called(blockSeqs).Get(0) == nil {
   186  		return nil
   187  	}
   188  	return mc.Called(blockSeqs).Get(0).([]*pcomm.Block)
   189  }
   190  
   191  func (*mockCommitter) Close() {
   192  }
   193  
   194  // Default configuration to be used for gossip and communication modules
   195  func newGossipConfig(id int, boot ...int) *gossip.Config {
   196  	port := id + portPrefix
   197  	return &gossip.Config{
   198  		BindPort:                   port,
   199  		BootstrapPeers:             bootPeers(boot...),
   200  		ID:                         fmt.Sprintf("p%d", id),
   201  		MaxBlockCountToStore:       0,
   202  		MaxPropagationBurstLatency: time.Duration(10) * time.Millisecond,
   203  		MaxPropagationBurstSize:    10,
   204  		PropagateIterations:        1,
   205  		PropagatePeerNum:           3,
   206  		PullInterval:               time.Duration(4) * time.Second,
   207  		PullPeerNum:                5,
   208  		InternalEndpoint:           fmt.Sprintf("localhost:%d", port),
   209  		PublishCertPeriod:          10 * time.Second,
   210  		RequestStateInfoInterval:   4 * time.Second,
   211  		PublishStateInfoInterval:   4 * time.Second,
   212  	}
   213  }
   214  
   215  // Create gossip instance
   216  func newGossipInstance(config *gossip.Config, mcs api.MessageCryptoService) gossip.Gossip {
   217  	idMapper := identity.NewIdentityMapper(mcs)
   218  
   219  	return gossip.NewGossipServiceWithServer(config, &orgCryptoService{}, mcs, idMapper, []byte(config.InternalEndpoint))
   220  }
   221  
   222  // Create new instance of KVLedger to be used for testing
   223  func newCommitter(id int) committer.Committer {
   224  	cb, _ := test.MakeGenesisBlock(strconv.Itoa(id))
   225  	ledger, _ := ledgermgmt.CreateLedger(cb)
   226  	return committer.NewLedgerCommitter(ledger, &validator.MockValidator{})
   227  }
   228  
   229  // Constructing pseudo peer node, simulating only gossip and state transfer part
   230  func newPeerNodeWithGossip(config *gossip.Config, committer committer.Committer, acceptor peerIdentityAcceptor, g gossip.Gossip) *peerNode {
   231  	cs := &cryptoServiceMock{acceptor: acceptor}
   232  	// Gossip component based on configuration provided and communication module
   233  	if g == nil {
   234  		g = newGossipInstance(config, &cryptoServiceMock{acceptor: noopPeerIdentityAcceptor})
   235  	}
   236  
   237  	logger.Debug("Joinning channel", util.GetTestChainID())
   238  	g.JoinChan(&joinChanMsg{}, common.ChainID(util.GetTestChainID()))
   239  
   240  	// Initialize pseudo peer simulator, which has only three
   241  	// basic parts
   242  
   243  	sp := NewGossipStateProvider(util.GetTestChainID(), g, committer, cs)
   244  	if sp == nil {
   245  		return nil
   246  	}
   247  
   248  	return &peerNode{
   249  		port:   config.BindPort,
   250  		g:      g,
   251  		s:      sp,
   252  		commit: committer,
   253  		cs:     cs,
   254  	}
   255  }
   256  
   257  // Constructing pseudo peer node, simulating only gossip and state transfer part
   258  func newPeerNode(config *gossip.Config, committer committer.Committer, acceptor peerIdentityAcceptor) *peerNode {
   259  	return newPeerNodeWithGossip(config, committer, acceptor, nil)
   260  }
   261  
   262  func TestNilDirectMsg(t *testing.T) {
   263  	mc := &mockCommitter{}
   264  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   265  	g := &mocks.GossipMock{}
   266  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   267  	g.On("Accept", mock.Anything, true).Return(nil, make(<-chan proto.ReceivedMessage))
   268  	p := newPeerNodeWithGossip(newGossipConfig(0), mc, noopPeerIdentityAcceptor, g)
   269  	defer p.shutdown()
   270  	p.s.(*GossipStateProviderImpl).handleStateRequest(nil)
   271  	p.s.(*GossipStateProviderImpl).directMessage(nil)
   272  	req := &comm.ReceivedMessageImpl{
   273  		SignedGossipMessage: p.s.(*GossipStateProviderImpl).stateRequestMessage(uint64(10), uint64(8)).NoopSign(),
   274  	}
   275  	p.s.(*GossipStateProviderImpl).directMessage(req)
   276  }
   277  
   278  func TestFailures(t *testing.T) {
   279  	mc := &mockCommitter{}
   280  	mc.On("LedgerHeight", mock.Anything).Return(uint64(0), nil)
   281  	g := &mocks.GossipMock{}
   282  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   283  	g.On("Accept", mock.Anything, true).Return(nil, make(<-chan proto.ReceivedMessage))
   284  	assert.Panics(t, func() {
   285  		newPeerNodeWithGossip(newGossipConfig(0), mc, noopPeerIdentityAcceptor, g)
   286  	})
   287  	// Reprogram mock
   288  	mc.Mock = mock.Mock{}
   289  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), errors.New("Failed accessing ledger"))
   290  	assert.Nil(t, newPeerNodeWithGossip(newGossipConfig(0), mc, noopPeerIdentityAcceptor, g))
   291  	// Reprogram mock
   292  	mc.Mock = mock.Mock{}
   293  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   294  	mc.On("GetBlocks", mock.Anything).Return(nil)
   295  	p := newPeerNodeWithGossip(newGossipConfig(0), mc, noopPeerIdentityAcceptor, g)
   296  	assert.Nil(t, p.s.GetBlock(uint64(1)))
   297  }
   298  
   299  func TestGossipReception(t *testing.T) {
   300  	signalChan := make(chan struct{})
   301  	rawblock := &pcomm.Block{
   302  		Header: &pcomm.BlockHeader{
   303  			Number: uint64(1),
   304  		},
   305  		Data: &pcomm.BlockData{
   306  			Data: [][]byte{},
   307  		},
   308  	}
   309  	b, _ := pb.Marshal(rawblock)
   310  
   311  	createChan := func(signalChan chan struct{}) <-chan *proto.GossipMessage {
   312  		c := make(chan *proto.GossipMessage)
   313  		gMsg := &proto.GossipMessage{
   314  			Channel: []byte("AAA"),
   315  			Content: &proto.GossipMessage_DataMsg{
   316  				DataMsg: &proto.DataMessage{
   317  					Payload: &proto.Payload{
   318  						SeqNum: 1,
   319  						Data:   b,
   320  					},
   321  				},
   322  			},
   323  		}
   324  		go func(c chan *proto.GossipMessage) {
   325  			// Wait for Accept() to be called
   326  			<-signalChan
   327  			// Simulate a message reception from the gossip component with an invalid channel
   328  			c <- gMsg
   329  			gMsg.Channel = []byte(util.GetTestChainID())
   330  			// Simulate a message reception from the gossip component
   331  			c <- gMsg
   332  		}(c)
   333  		return c
   334  	}
   335  
   336  	g := &mocks.GossipMock{}
   337  	rmc := createChan(signalChan)
   338  	g.On("Accept", mock.Anything, false).Return(rmc, nil).Run(func(_ mock.Arguments) {
   339  		signalChan <- struct{}{}
   340  	})
   341  	g.On("Accept", mock.Anything, true).Return(nil, make(<-chan proto.ReceivedMessage))
   342  	mc := &mockCommitter{}
   343  	receivedChan := make(chan struct{})
   344  	mc.On("Commit", mock.Anything).Run(func(arguments mock.Arguments) {
   345  		block := arguments.Get(0).(*pcomm.Block)
   346  		assert.Equal(t, uint64(1), block.Header.Number)
   347  		receivedChan <- struct{}{}
   348  	})
   349  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   350  	p := newPeerNodeWithGossip(newGossipConfig(0), mc, noopPeerIdentityAcceptor, g)
   351  	defer p.shutdown()
   352  	select {
   353  	case <-receivedChan:
   354  	case <-time.After(time.Second * 15):
   355  		assert.Fail(t, "Didn't commit a block within a timely manner")
   356  	}
   357  }
   358  
   359  func TestAccessControl(t *testing.T) {
   360  	viper.Set("peer.fileSystemPath", "/tmp/tests/ledger/node")
   361  	ledgermgmt.InitializeTestEnv()
   362  	defer ledgermgmt.CleanupTestEnv()
   363  
   364  	bootstrapSetSize := 5
   365  	bootstrapSet := make([]*peerNode, 0)
   366  
   367  	authorizedPeers := map[string]struct{}{
   368  		"localhost:5610": {},
   369  		"localhost:5615": {},
   370  		"localhost:5618": {},
   371  		"localhost:5621": {},
   372  	}
   373  
   374  	blockPullPolicy := func(identity api.PeerIdentityType) error {
   375  		if _, isAuthorized := authorizedPeers[string(identity)]; isAuthorized {
   376  			return nil
   377  		}
   378  		return errors.New("Not authorized")
   379  	}
   380  
   381  	for i := 0; i < bootstrapSetSize; i++ {
   382  		commit := newCommitter(i)
   383  		bootstrapSet = append(bootstrapSet, newPeerNode(newGossipConfig(i), commit, blockPullPolicy))
   384  	}
   385  
   386  	defer func() {
   387  		for _, p := range bootstrapSet {
   388  			p.shutdown()
   389  		}
   390  	}()
   391  
   392  	msgCount := 5
   393  
   394  	for i := 1; i <= msgCount; i++ {
   395  		rawblock := pcomm.NewBlock(uint64(i), []byte{})
   396  		if b, err := pb.Marshal(rawblock); err == nil {
   397  			payload := &proto.Payload{uint64(i), "", b}
   398  			bootstrapSet[0].s.AddPayload(payload)
   399  		} else {
   400  			t.Fail()
   401  		}
   402  	}
   403  
   404  	standardPeerSetSize := 10
   405  	peersSet := make([]*peerNode, 0)
   406  
   407  	for i := 0; i < standardPeerSetSize; i++ {
   408  		commit := newCommitter(bootstrapSetSize + i)
   409  		peersSet = append(peersSet, newPeerNode(newGossipConfig(bootstrapSetSize+i, 0, 1, 2, 3, 4), commit, blockPullPolicy))
   410  	}
   411  
   412  	defer func() {
   413  		for _, p := range peersSet {
   414  			p.shutdown()
   415  		}
   416  	}()
   417  
   418  	waitUntilTrueOrTimeout(t, func() bool {
   419  		for _, p := range peersSet {
   420  			if len(p.g.PeersOfChannel(common.ChainID(util.GetTestChainID()))) != bootstrapSetSize+standardPeerSetSize-1 {
   421  				logger.Debug("Peer discovery has not finished yet")
   422  				return false
   423  			}
   424  		}
   425  		logger.Debug("All peer discovered each other!!!")
   426  		return true
   427  	}, 30*time.Second)
   428  
   429  	logger.Debug("Waiting for all blocks to arrive.")
   430  	waitUntilTrueOrTimeout(t, func() bool {
   431  		logger.Debug("Trying to see all authorized peers get all blocks, and all non-authorized didn't")
   432  		for _, p := range peersSet {
   433  			height, err := p.commit.LedgerHeight()
   434  			id := fmt.Sprintf("localhost:%d", p.port)
   435  			if _, isAuthorized := authorizedPeers[id]; isAuthorized {
   436  				if height != uint64(msgCount+1) || err != nil {
   437  					return false
   438  				}
   439  			} else {
   440  				if err == nil && height > 1 {
   441  					assert.Fail(t, "Peer", id, "got message but isn't authorized! Height:", height)
   442  				}
   443  			}
   444  		}
   445  		logger.Debug("All peers have same ledger height!!!")
   446  		return true
   447  	}, 60*time.Second)
   448  }
   449  
   450  /*// Simple scenario to start first booting node, gossip a message
   451  // then start second node and verify second node also receives it
   452  func TestNewGossipStateProvider_GossipingOneMessage(t *testing.T) {
   453  	bootId := 0
   454  	ledgerPath := "/tmp/tests/ledger/"
   455  	defer os.RemoveAll(ledgerPath)
   456  
   457  	bootNodeCommitter := newCommitter(bootId, ledgerPath + "node/")
   458  	defer bootNodeCommitter.Close()
   459  
   460  	bootNode := newPeerNode(newGossipConfig(bootId, 100), bootNodeCommitter)
   461  	defer bootNode.shutdown()
   462  
   463  	rawblock := &peer.Block2{}
   464  	if err := pb.Unmarshal([]byte{}, rawblock); err != nil {
   465  		t.Fail()
   466  	}
   467  
   468  	if bytes, err := pb.Marshal(rawblock); err == nil {
   469  		payload := &proto.Payload{1, "", bytes}
   470  		bootNode.s.AddPayload(payload)
   471  	} else {
   472  		t.Fail()
   473  	}
   474  
   475  	waitUntilTrueOrTimeout(t, func() bool {
   476  		if block := bootNode.s.GetBlock(uint64(1)); block != nil {
   477  			return true
   478  		}
   479  		return false
   480  	}, 5 * time.Second)
   481  
   482  	bootNode.g.Gossip(createDataMsg(uint64(1), []byte{}, ""))
   483  
   484  	peerCommitter := newCommitter(1, ledgerPath + "node/")
   485  	defer peerCommitter.Close()
   486  
   487  	peer := newPeerNode(newGossipConfig(1, 100, bootId), peerCommitter)
   488  	defer peer.shutdown()
   489  
   490  	ready := make(chan interface{})
   491  
   492  	go func(p *peerNode) {
   493  		for len(p.g.GetPeers()) != 1 {
   494  			time.Sleep(100 * time.Millisecond)
   495  		}
   496  		ready <- struct{}{}
   497  	}(peer)
   498  
   499  	select {
   500  	case <-ready:
   501  		{
   502  			break
   503  		}
   504  	case <-time.After(1 * time.Second):
   505  		{
   506  			t.Fail()
   507  		}
   508  	}
   509  
   510  	// Let sure anti-entropy will have a chance to bring missing block
   511  	waitUntilTrueOrTimeout(t, func() bool {
   512  		if block := peer.s.GetBlock(uint64(1)); block != nil {
   513  			return true
   514  		}
   515  		return false
   516  	}, 2 * defAntiEntropyInterval + 1 * time.Second)
   517  
   518  	block := peer.s.GetBlock(uint64(1))
   519  
   520  	assert.NotNil(t, block)
   521  }
   522  
   523  func TestNewGossipStateProvider_RepeatGossipingOneMessage(t *testing.T) {
   524  	for i := 0; i < 10; i++ {
   525  		TestNewGossipStateProvider_GossipingOneMessage(t)
   526  	}
   527  }*/
   528  
   529  func TestNewGossipStateProvider_SendingManyMessages(t *testing.T) {
   530  	viper.Set("peer.fileSystemPath", "/tmp/tests/ledger/node")
   531  	ledgermgmt.InitializeTestEnv()
   532  	defer ledgermgmt.CleanupTestEnv()
   533  
   534  	bootstrapSetSize := 5
   535  	bootstrapSet := make([]*peerNode, 0)
   536  
   537  	for i := 0; i < bootstrapSetSize; i++ {
   538  		commit := newCommitter(i)
   539  		bootstrapSet = append(bootstrapSet, newPeerNode(newGossipConfig(i), commit, noopPeerIdentityAcceptor))
   540  	}
   541  
   542  	defer func() {
   543  		for _, p := range bootstrapSet {
   544  			p.shutdown()
   545  		}
   546  	}()
   547  
   548  	msgCount := 10
   549  
   550  	for i := 1; i <= msgCount; i++ {
   551  		rawblock := pcomm.NewBlock(uint64(i), []byte{})
   552  		if b, err := pb.Marshal(rawblock); err == nil {
   553  			payload := &proto.Payload{uint64(i), "", b}
   554  			bootstrapSet[0].s.AddPayload(payload)
   555  		} else {
   556  			t.Fail()
   557  		}
   558  	}
   559  
   560  	standartPeersSize := 10
   561  	peersSet := make([]*peerNode, 0)
   562  
   563  	for i := 0; i < standartPeersSize; i++ {
   564  		commit := newCommitter(bootstrapSetSize + i)
   565  		peersSet = append(peersSet, newPeerNode(newGossipConfig(bootstrapSetSize+i, 0, 1, 2, 3, 4), commit, noopPeerIdentityAcceptor))
   566  	}
   567  
   568  	defer func() {
   569  		for _, p := range peersSet {
   570  			p.shutdown()
   571  		}
   572  	}()
   573  
   574  	waitUntilTrueOrTimeout(t, func() bool {
   575  		for _, p := range peersSet {
   576  			if len(p.g.PeersOfChannel(common.ChainID(util.GetTestChainID()))) != bootstrapSetSize+standartPeersSize-1 {
   577  				logger.Debug("Peer discovery has not finished yet")
   578  				return false
   579  			}
   580  		}
   581  		logger.Debug("All peer discovered each other!!!")
   582  		return true
   583  	}, 30*time.Second)
   584  
   585  	logger.Debug("Waiting for all blocks to arrive.")
   586  	waitUntilTrueOrTimeout(t, func() bool {
   587  		logger.Debug("Trying to see all peers get all blocks")
   588  		for _, p := range peersSet {
   589  			height, err := p.commit.LedgerHeight()
   590  			if height != uint64(msgCount+1) || err != nil {
   591  				return false
   592  			}
   593  		}
   594  		logger.Debug("All peers have same ledger height!!!")
   595  		return true
   596  	}, 60*time.Second)
   597  }
   598  
   599  func TestGossipStateProvider_TestStateMessages(t *testing.T) {
   600  	viper.Set("peer.fileSystemPath", "/tmp/tests/ledger/node")
   601  	ledgermgmt.InitializeTestEnv()
   602  	defer ledgermgmt.CleanupTestEnv()
   603  
   604  	bootPeer := newPeerNode(newGossipConfig(0), newCommitter(0), noopPeerIdentityAcceptor)
   605  	defer bootPeer.shutdown()
   606  
   607  	peer := newPeerNode(newGossipConfig(1, 0), newCommitter(1), noopPeerIdentityAcceptor)
   608  	defer peer.shutdown()
   609  
   610  	naiveStateMsgPredicate := func(message interface{}) bool {
   611  		return message.(proto.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage()
   612  	}
   613  
   614  	_, bootCh := bootPeer.g.Accept(naiveStateMsgPredicate, true)
   615  	_, peerCh := peer.g.Accept(naiveStateMsgPredicate, true)
   616  
   617  	wg := sync.WaitGroup{}
   618  	wg.Add(2)
   619  
   620  	go func() {
   621  		msg := <-bootCh
   622  		logger.Info("Bootstrap node got message, ", msg)
   623  		assert.True(t, msg.GetGossipMessage().GetStateRequest() != nil)
   624  		msg.Respond(&proto.GossipMessage{
   625  			Content: &proto.GossipMessage_StateResponse{&proto.RemoteStateResponse{nil}},
   626  		})
   627  		wg.Done()
   628  	}()
   629  
   630  	go func() {
   631  		msg := <-peerCh
   632  		logger.Info("Peer node got an answer, ", msg)
   633  		assert.True(t, msg.GetGossipMessage().GetStateResponse() != nil)
   634  		wg.Done()
   635  
   636  	}()
   637  
   638  	readyCh := make(chan struct{})
   639  	go func() {
   640  		wg.Wait()
   641  		readyCh <- struct{}{}
   642  	}()
   643  
   644  	time.Sleep(time.Duration(5) * time.Second)
   645  	logger.Info("Sending gossip message with remote state request")
   646  
   647  	chainID := common.ChainID(util.GetTestChainID())
   648  
   649  	peer.g.Send(&proto.GossipMessage{
   650  		Content: &proto.GossipMessage_StateRequest{&proto.RemoteStateRequest{0, 1}},
   651  	}, &comm.RemotePeer{peer.g.PeersOfChannel(chainID)[0].Endpoint, peer.g.PeersOfChannel(chainID)[0].PKIid})
   652  	logger.Info("Waiting until peers exchange messages")
   653  
   654  	select {
   655  	case <-readyCh:
   656  		{
   657  			logger.Info("Done!!!")
   658  
   659  		}
   660  	case <-time.After(time.Duration(10) * time.Second):
   661  		{
   662  			t.Fail()
   663  		}
   664  	}
   665  }
   666  
   667  // Start one bootstrap peer and submit defAntiEntropyBatchSize + 5 messages into
   668  // local ledger, next spawning a new peer waiting for anti-entropy procedure to
   669  // complete missing blocks. Since state transfer messages now batched, it is expected
   670  // to see _exactly_ two messages with state transfer response.
   671  func TestNewGossipStateProvider_BatchingOfStateRequest(t *testing.T) {
   672  	viper.Set("peer.fileSystemPath", "/tmp/tests/ledger/node")
   673  	ledgermgmt.InitializeTestEnv()
   674  	defer ledgermgmt.CleanupTestEnv()
   675  
   676  	bootPeer := newPeerNode(newGossipConfig(0), newCommitter(0), noopPeerIdentityAcceptor)
   677  	defer bootPeer.shutdown()
   678  
   679  	msgCount := defAntiEntropyBatchSize + 5
   680  	expectedMessagesCnt := 2
   681  
   682  	for i := 1; i <= msgCount; i++ {
   683  		rawblock := pcomm.NewBlock(uint64(i), []byte{})
   684  		if b, err := pb.Marshal(rawblock); err == nil {
   685  			payload := &proto.Payload{uint64(i), "", b}
   686  			bootPeer.s.AddPayload(payload)
   687  		} else {
   688  			t.Fail()
   689  		}
   690  	}
   691  
   692  	peer := newPeerNode(newGossipConfig(1, 0), newCommitter(1), noopPeerIdentityAcceptor)
   693  	defer peer.shutdown()
   694  
   695  	naiveStateMsgPredicate := func(message interface{}) bool {
   696  		return message.(proto.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage()
   697  	}
   698  	_, peerCh := peer.g.Accept(naiveStateMsgPredicate, true)
   699  
   700  	messageCh := make(chan struct{})
   701  	stopWaiting := make(chan struct{})
   702  
   703  	// Number of submitted messages is defAntiEntropyBatchSize + 5, therefore
   704  	// expected number of batches is expectedMessagesCnt = 2. Following go routine
   705  	// makes sure it receives expected amount of messages and sends signal of success
   706  	// to continue the test
   707  	go func(expected int) {
   708  		cnt := 0
   709  		for cnt < expected {
   710  			select {
   711  			case <-peerCh:
   712  				{
   713  					cnt++
   714  				}
   715  
   716  			case <-stopWaiting:
   717  				{
   718  					return
   719  				}
   720  			}
   721  		}
   722  
   723  		messageCh <- struct{}{}
   724  	}(expectedMessagesCnt)
   725  
   726  	// Waits for message which indicates that expected number of message batches received
   727  	// otherwise timeouts after 2 * defAntiEntropyInterval + 1 seconds
   728  	select {
   729  	case <-messageCh:
   730  		{
   731  			// Once we got message which indicate of two batches being received,
   732  			// making sure messages indeed committed.
   733  			waitUntilTrueOrTimeout(t, func() bool {
   734  				if len(peer.g.PeersOfChannel(common.ChainID(util.GetTestChainID()))) != 1 {
   735  					logger.Debug("Peer discovery has not finished yet")
   736  					return false
   737  				}
   738  				logger.Debug("All peer discovered each other!!!")
   739  				return true
   740  			}, 30*time.Second)
   741  
   742  			logger.Debug("Waiting for all blocks to arrive.")
   743  			waitUntilTrueOrTimeout(t, func() bool {
   744  				logger.Debug("Trying to see all peers get all blocks")
   745  				height, err := peer.commit.LedgerHeight()
   746  				if height != uint64(msgCount+1) || err != nil {
   747  					return false
   748  				}
   749  				logger.Debug("All peers have same ledger height!!!")
   750  				return true
   751  			}, 60*time.Second)
   752  		}
   753  	case <-time.After(defAntiEntropyInterval*2 + time.Second*1):
   754  		{
   755  			close(stopWaiting)
   756  			t.Fatal("Expected to receive two batches with missing payloads")
   757  		}
   758  	}
   759  }
   760  
   761  func waitUntilTrueOrTimeout(t *testing.T, predicate func() bool, timeout time.Duration) {
   762  	ch := make(chan struct{})
   763  	go func() {
   764  		logger.Debug("Started to spin off, until predicate will be satisfied.")
   765  		for !predicate() {
   766  			time.Sleep(1 * time.Second)
   767  		}
   768  		ch <- struct{}{}
   769  		logger.Debug("Done.")
   770  	}()
   771  
   772  	select {
   773  	case <-ch:
   774  		break
   775  	case <-time.After(timeout):
   776  		t.Fatal("Timeout has expired")
   777  		break
   778  	}
   779  	logger.Debug("Stop waiting until timeout or true")
   780  }