github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/gossip/state/state_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package state
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"fmt"
    13  	"math/rand"
    14  	"net"
    15  	"sync"
    16  	"sync/atomic"
    17  	"testing"
    18  	"time"
    19  
    20  	pb "github.com/golang/protobuf/proto"
    21  	pcomm "github.com/hyperledger/fabric-protos-go/common"
    22  	proto "github.com/hyperledger/fabric-protos-go/gossip"
    23  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    24  	tspb "github.com/hyperledger/fabric-protos-go/transientstore"
    25  	"github.com/osdi23p228/fabric/bccsp/factory"
    26  	"github.com/osdi23p228/fabric/common/configtx/test"
    27  	errors2 "github.com/osdi23p228/fabric/common/errors"
    28  	"github.com/osdi23p228/fabric/common/flogging"
    29  	"github.com/osdi23p228/fabric/common/metrics/disabled"
    30  	"github.com/osdi23p228/fabric/core/committer"
    31  	"github.com/osdi23p228/fabric/core/committer/txvalidator"
    32  	"github.com/osdi23p228/fabric/core/ledger"
    33  	"github.com/osdi23p228/fabric/core/mocks/validator"
    34  	"github.com/osdi23p228/fabric/core/transientstore"
    35  	"github.com/osdi23p228/fabric/gossip/api"
    36  	"github.com/osdi23p228/fabric/gossip/comm"
    37  	"github.com/osdi23p228/fabric/gossip/common"
    38  	"github.com/osdi23p228/fabric/gossip/discovery"
    39  	"github.com/osdi23p228/fabric/gossip/gossip"
    40  	"github.com/osdi23p228/fabric/gossip/gossip/algo"
    41  	"github.com/osdi23p228/fabric/gossip/gossip/channel"
    42  	"github.com/osdi23p228/fabric/gossip/metrics"
    43  	"github.com/osdi23p228/fabric/gossip/privdata"
    44  	capabilitymock "github.com/osdi23p228/fabric/gossip/privdata/mocks"
    45  	"github.com/osdi23p228/fabric/gossip/protoext"
    46  	"github.com/osdi23p228/fabric/gossip/state/mocks"
    47  	gossiputil "github.com/osdi23p228/fabric/gossip/util"
    48  	gutil "github.com/osdi23p228/fabric/gossip/util"
    49  	corecomm "github.com/osdi23p228/fabric/internal/pkg/comm"
    50  	"github.com/osdi23p228/fabric/protoutil"
    51  	"github.com/onsi/gomega"
    52  	"github.com/onsi/gomega/gbytes"
    53  	"github.com/stretchr/testify/assert"
    54  	"github.com/stretchr/testify/mock"
    55  	"go.uber.org/zap"
    56  	"go.uber.org/zap/zapcore"
    57  )
    58  
    59  var (
    60  	orgID = []byte("ORG1")
    61  
    62  	noopPeerIdentityAcceptor = func(identity api.PeerIdentityType) error {
    63  		return nil
    64  	}
    65  )
    66  
    67  type peerIdentityAcceptor func(identity api.PeerIdentityType) error
    68  
    69  type joinChanMsg struct {
    70  }
    71  
    72  func init() {
    73  	gutil.SetupTestLogging()
    74  	factory.InitFactories(nil)
    75  }
    76  
    77  // SequenceNumber returns the sequence number of the block that the message
    78  // is derived from
    79  func (*joinChanMsg) SequenceNumber() uint64 {
    80  	return uint64(time.Now().UnixNano())
    81  }
    82  
    83  // Members returns the organizations of the channel
    84  func (jcm *joinChanMsg) Members() []api.OrgIdentityType {
    85  	return []api.OrgIdentityType{orgID}
    86  }
    87  
    88  // AnchorPeersOf returns the anchor peers of the given organization
    89  func (jcm *joinChanMsg) AnchorPeersOf(org api.OrgIdentityType) []api.AnchorPeer {
    90  	return []api.AnchorPeer{}
    91  }
    92  
    93  type orgCryptoService struct {
    94  }
    95  
    96  // OrgByPeerIdentity returns the OrgIdentityType
    97  // of a given peer identity
    98  func (*orgCryptoService) OrgByPeerIdentity(identity api.PeerIdentityType) api.OrgIdentityType {
    99  	return orgID
   100  }
   101  
   102  // Verify verifies a JoinChannelMessage, returns nil on success,
   103  // and an error on failure
   104  func (*orgCryptoService) Verify(joinChanMsg api.JoinChannelMessage) error {
   105  	return nil
   106  }
   107  
   108  type cryptoServiceMock struct {
   109  	acceptor peerIdentityAcceptor
   110  }
   111  
   112  func (cryptoServiceMock) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
   113  	return time.Now().Add(time.Hour), nil
   114  }
   115  
   116  // GetPKIidOfCert returns the PKI-ID of a peer's identity
   117  func (*cryptoServiceMock) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
   118  	return common.PKIidType(peerIdentity)
   119  }
   120  
   121  // VerifyBlock returns nil if the block is properly signed,
   122  // else returns error
   123  func (*cryptoServiceMock) VerifyBlock(channelID common.ChannelID, seqNum uint64, signedBlock *pcomm.Block) error {
   124  	return nil
   125  }
   126  
   127  // Sign signs msg with this peer's signing key and outputs
   128  // the signature if no error occurred.
   129  func (*cryptoServiceMock) Sign(msg []byte) ([]byte, error) {
   130  	clone := make([]byte, len(msg))
   131  	copy(clone, msg)
   132  	return clone, nil
   133  }
   134  
   135  // Verify checks that signature is a valid signature of message under a peer's verification key.
   136  // If the verification succeeded, Verify returns nil meaning no error occurred.
   137  // If peerCert is nil, then the signature is verified against this peer's verification key.
   138  func (*cryptoServiceMock) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
   139  	equal := bytes.Equal(signature, message)
   140  	if !equal {
   141  		return fmt.Errorf("Wrong signature:%v, %v", signature, message)
   142  	}
   143  	return nil
   144  }
   145  
   146  // VerifyByChannel checks that signature is a valid signature of message
   147  // under a peer's verification key, but also in the context of a specific channel.
   148  // If the verification succeeded, Verify returns nil meaning no error occurred.
   149  // If peerIdentity is nil, then the signature is verified against this peer's verification key.
   150  func (cs *cryptoServiceMock) VerifyByChannel(channelID common.ChannelID, peerIdentity api.PeerIdentityType, signature, message []byte) error {
   151  	return cs.acceptor(peerIdentity)
   152  }
   153  
   154  func (*cryptoServiceMock) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
   155  	return nil
   156  }
   157  
   158  func bootPeersWithPorts(ports ...int) []string {
   159  	var peers []string
   160  	for _, port := range ports {
   161  		peers = append(peers, fmt.Sprintf("127.0.0.1:%d", port))
   162  	}
   163  	return peers
   164  }
   165  
   166  type peerNodeGossipSupport interface {
   167  	GossipAdapter
   168  	Stop()
   169  	JoinChan(joinMsg api.JoinChannelMessage, channelID common.ChannelID)
   170  }
   171  
   172  // Simple presentation of peer which includes only
   173  // communication module, gossip and state transfer
   174  type peerNode struct {
   175  	port   int
   176  	g      peerNodeGossipSupport
   177  	s      *GossipStateProviderImpl
   178  	cs     *cryptoServiceMock
   179  	commit committer.Committer
   180  	grpc   *corecomm.GRPCServer
   181  }
   182  
   183  // Shutting down all modules used
   184  func (node *peerNode) shutdown() {
   185  	node.s.Stop()
   186  	node.g.Stop()
   187  	node.grpc.Stop()
   188  }
   189  
   190  type mockCommitter struct {
   191  	*mock.Mock
   192  	sync.Mutex
   193  }
   194  
   195  func (mc *mockCommitter) GetConfigHistoryRetriever() (ledger.ConfigHistoryRetriever, error) {
   196  	args := mc.Called()
   197  	return args.Get(0).(ledger.ConfigHistoryRetriever), args.Error(1)
   198  }
   199  
   200  func (mc *mockCommitter) GetPvtDataByNum(blockNum uint64, filter ledger.PvtNsCollFilter) ([]*ledger.TxPvtData, error) {
   201  	args := mc.Called(blockNum, filter)
   202  	return args.Get(0).([]*ledger.TxPvtData), args.Error(1)
   203  }
   204  
   205  func (mc *mockCommitter) CommitLegacy(blockAndPvtData *ledger.BlockAndPvtData, commitOpts *ledger.CommitOptions) error {
   206  	mc.Lock()
   207  	m := mc.Mock
   208  	mc.Unlock()
   209  	m.Called(blockAndPvtData.Block)
   210  	return nil
   211  }
   212  
   213  func (mc *mockCommitter) GetPvtDataAndBlockByNum(seqNum uint64) (*ledger.BlockAndPvtData, error) {
   214  	mc.Lock()
   215  	m := mc.Mock
   216  	mc.Unlock()
   217  
   218  	args := m.Called(seqNum)
   219  	return args.Get(0).(*ledger.BlockAndPvtData), args.Error(1)
   220  }
   221  
   222  func (mc *mockCommitter) LedgerHeight() (uint64, error) {
   223  	mc.Lock()
   224  	m := mc.Mock
   225  	mc.Unlock()
   226  	args := m.Called()
   227  	if args.Get(1) == nil {
   228  		return args.Get(0).(uint64), nil
   229  	}
   230  	return args.Get(0).(uint64), args.Get(1).(error)
   231  }
   232  
   233  func (mc *mockCommitter) DoesPvtDataInfoExistInLedger(blkNum uint64) (bool, error) {
   234  	mc.Lock()
   235  	m := mc.Mock
   236  	mc.Unlock()
   237  	args := m.Called(blkNum)
   238  	return args.Get(0).(bool), args.Error(1)
   239  }
   240  
   241  func (mc *mockCommitter) GetBlocks(blockSeqs []uint64) []*pcomm.Block {
   242  	mc.Lock()
   243  	m := mc.Mock
   244  	mc.Unlock()
   245  
   246  	if m.Called(blockSeqs).Get(0) == nil {
   247  		return nil
   248  	}
   249  	return m.Called(blockSeqs).Get(0).([]*pcomm.Block)
   250  }
   251  
   252  func (*mockCommitter) GetMissingPvtDataTracker() (ledger.MissingPvtDataTracker, error) {
   253  	panic("implement me")
   254  }
   255  
   256  func (*mockCommitter) CommitPvtDataOfOldBlocks(
   257  	reconciledPvtdata []*ledger.ReconciledPvtdata,
   258  	unreconciled ledger.MissingPvtDataInfo,
   259  ) ([]*ledger.PvtdataHashMismatch, error) {
   260  	panic("implement me")
   261  }
   262  
   263  func (*mockCommitter) Close() {
   264  }
   265  
   266  type ramLedger struct {
   267  	ledger map[uint64]*ledger.BlockAndPvtData
   268  	sync.RWMutex
   269  }
   270  
   271  func (mock *ramLedger) GetMissingPvtDataTracker() (ledger.MissingPvtDataTracker, error) {
   272  	panic("implement me")
   273  }
   274  
   275  func (mock *ramLedger) CommitPvtDataOfOldBlocks(
   276  	reconciledPvtdata []*ledger.ReconciledPvtdata,
   277  	unreconciled ledger.MissingPvtDataInfo,
   278  ) ([]*ledger.PvtdataHashMismatch, error) {
   279  	panic("implement me")
   280  }
   281  
   282  func (mock *ramLedger) GetConfigHistoryRetriever() (ledger.ConfigHistoryRetriever, error) {
   283  	panic("implement me")
   284  }
   285  
   286  func (mock *ramLedger) GetPvtDataAndBlockByNum(blockNum uint64, filter ledger.PvtNsCollFilter) (*ledger.BlockAndPvtData, error) {
   287  	mock.RLock()
   288  	defer mock.RUnlock()
   289  
   290  	if block, ok := mock.ledger[blockNum]; !ok {
   291  		return nil, fmt.Errorf("no block with seq = %d found", blockNum)
   292  	} else {
   293  		return block, nil
   294  	}
   295  }
   296  
   297  func (mock *ramLedger) GetPvtDataByNum(blockNum uint64, filter ledger.PvtNsCollFilter) ([]*ledger.TxPvtData, error) {
   298  	panic("implement me")
   299  }
   300  
   301  func (mock *ramLedger) CommitLegacy(blockAndPvtdata *ledger.BlockAndPvtData, commitOpts *ledger.CommitOptions) error {
   302  	mock.Lock()
   303  	defer mock.Unlock()
   304  
   305  	if blockAndPvtdata != nil && blockAndPvtdata.Block != nil {
   306  		mock.ledger[blockAndPvtdata.Block.Header.Number] = blockAndPvtdata
   307  		return nil
   308  	}
   309  	return errors.New("invalid input parameters for block and private data param")
   310  }
   311  
   312  func (mock *ramLedger) GetBlockchainInfo() (*pcomm.BlockchainInfo, error) {
   313  	mock.RLock()
   314  	defer mock.RUnlock()
   315  
   316  	currentBlock := mock.ledger[uint64(len(mock.ledger)-1)].Block
   317  	return &pcomm.BlockchainInfo{
   318  		Height:            currentBlock.Header.Number + 1,
   319  		CurrentBlockHash:  protoutil.BlockHeaderHash(currentBlock.Header),
   320  		PreviousBlockHash: currentBlock.Header.PreviousHash,
   321  	}, nil
   322  }
   323  
   324  func (mock *ramLedger) DoesPvtDataInfoExist(blkNum uint64) (bool, error) {
   325  	return false, nil
   326  }
   327  
   328  func (mock *ramLedger) GetBlockByNumber(blockNumber uint64) (*pcomm.Block, error) {
   329  	mock.RLock()
   330  	defer mock.RUnlock()
   331  
   332  	if blockAndPvtData, ok := mock.ledger[blockNumber]; !ok {
   333  		return nil, fmt.Errorf("no block with seq = %d found", blockNumber)
   334  	} else {
   335  		return blockAndPvtData.Block, nil
   336  	}
   337  }
   338  
   339  func (mock *ramLedger) Close() {
   340  
   341  }
   342  
   343  // Create new instance of KVLedger to be used for testing
   344  func newCommitter() committer.Committer {
   345  	cb, _ := test.MakeGenesisBlock("testChain")
   346  	ldgr := &ramLedger{
   347  		ledger: make(map[uint64]*ledger.BlockAndPvtData),
   348  	}
   349  	ldgr.CommitLegacy(&ledger.BlockAndPvtData{Block: cb}, &ledger.CommitOptions{})
   350  	return committer.NewLedgerCommitter(ldgr)
   351  }
   352  
   353  func newPeerNodeWithGossip(id int, committer committer.Committer,
   354  	acceptor peerIdentityAcceptor, g peerNodeGossipSupport, bootPorts ...int) *peerNode {
   355  	logger := flogging.MustGetLogger(gutil.StateLogger)
   356  	return newPeerNodeWithGossipWithValidator(logger, id, committer, acceptor, g, &validator.MockValidator{}, bootPorts...)
   357  }
   358  
   359  // Constructing pseudo peer node, simulating only gossip and state transfer part
   360  func newPeerNodeWithGossipWithValidatorWithMetrics(logger gutil.Logger, id int, committer committer.Committer,
   361  	acceptor peerIdentityAcceptor, g peerNodeGossipSupport, v txvalidator.Validator,
   362  	gossipMetrics *metrics.GossipMetrics, bootPorts ...int) (node *peerNode, port int) {
   363  	cs := &cryptoServiceMock{acceptor: acceptor}
   364  	port, gRPCServer, certs, secureDialOpts, _ := gossiputil.CreateGRPCLayer()
   365  
   366  	if g == nil {
   367  		config := &gossip.Config{
   368  			BindPort:                     port,
   369  			BootstrapPeers:               bootPeersWithPorts(bootPorts...),
   370  			ID:                           fmt.Sprintf("p%d", id),
   371  			MaxBlockCountToStore:         0,
   372  			MaxPropagationBurstLatency:   time.Duration(10) * time.Millisecond,
   373  			MaxPropagationBurstSize:      10,
   374  			PropagateIterations:          1,
   375  			PropagatePeerNum:             3,
   376  			PullInterval:                 time.Duration(4) * time.Second,
   377  			PullPeerNum:                  5,
   378  			InternalEndpoint:             fmt.Sprintf("127.0.0.1:%d", port),
   379  			PublishCertPeriod:            10 * time.Second,
   380  			RequestStateInfoInterval:     4 * time.Second,
   381  			PublishStateInfoInterval:     4 * time.Second,
   382  			TimeForMembershipTracker:     5 * time.Second,
   383  			TLSCerts:                     certs,
   384  			DigestWaitTime:               algo.DefDigestWaitTime,
   385  			RequestWaitTime:              algo.DefRequestWaitTime,
   386  			ResponseWaitTime:             algo.DefResponseWaitTime,
   387  			DialTimeout:                  comm.DefDialTimeout,
   388  			ConnTimeout:                  comm.DefConnTimeout,
   389  			RecvBuffSize:                 comm.DefRecvBuffSize,
   390  			SendBuffSize:                 comm.DefSendBuffSize,
   391  			MsgExpirationTimeout:         channel.DefMsgExpirationTimeout,
   392  			AliveTimeInterval:            discovery.DefAliveTimeInterval,
   393  			AliveExpirationTimeout:       discovery.DefAliveExpirationTimeout,
   394  			AliveExpirationCheckInterval: discovery.DefAliveExpirationCheckInterval,
   395  			ReconnectInterval:            discovery.DefReconnectInterval,
   396  			MaxConnectionAttempts:        discovery.DefMaxConnectionAttempts,
   397  			MsgExpirationFactor:          discovery.DefMsgExpirationFactor,
   398  		}
   399  
   400  		selfID := api.PeerIdentityType(config.InternalEndpoint)
   401  		mcs := &cryptoServiceMock{acceptor: noopPeerIdentityAcceptor}
   402  		g = gossip.New(config, gRPCServer.Server(), &orgCryptoService{}, mcs, selfID, secureDialOpts, gossipMetrics, nil)
   403  	}
   404  
   405  	g.JoinChan(&joinChanMsg{}, common.ChannelID("testchannelid"))
   406  
   407  	go func() {
   408  		gRPCServer.Start()
   409  	}()
   410  
   411  	// Initialize pseudo peer simulator, which has only three
   412  	// basic parts
   413  
   414  	servicesAdapater := &ServicesMediator{GossipAdapter: g, MCSAdapter: cs}
   415  	coordConfig := privdata.CoordinatorConfig{
   416  		PullRetryThreshold:             0,
   417  		TransientBlockRetention:        1000,
   418  		SkipPullingInvalidTransactions: false,
   419  	}
   420  
   421  	mspID := "Org1MSP"
   422  	capabilityProvider := &capabilitymock.CapabilityProvider{}
   423  	appCapability := &capabilitymock.AppCapabilities{}
   424  	capabilityProvider.On("Capabilities").Return(appCapability)
   425  	appCapability.On("StorePvtDataOfInvalidTx").Return(true)
   426  	coord := privdata.NewCoordinator(mspID, privdata.Support{
   427  		Validator:          v,
   428  		Committer:          committer,
   429  		CapabilityProvider: capabilityProvider,
   430  	}, &transientstore.Store{}, protoutil.SignedData{}, gossipMetrics.PrivdataMetrics, coordConfig, nil)
   431  	stateConfig := &StateConfig{
   432  		StateCheckInterval:   DefStateCheckInterval,
   433  		StateResponseTimeout: DefStateResponseTimeout,
   434  		StateBatchSize:       DefStateBatchSize,
   435  		StateMaxRetries:      DefStateMaxRetries,
   436  		StateBlockBufferSize: DefStateBlockBufferSize,
   437  		StateChannelSize:     DefStateChannelSize,
   438  		StateEnabled:         true,
   439  	}
   440  	sp := NewGossipStateProvider(logger, "testchannelid", servicesAdapater, coord, gossipMetrics.StateMetrics, blocking, stateConfig)
   441  	if sp == nil {
   442  		gRPCServer.Stop()
   443  		return nil, port
   444  	}
   445  
   446  	return &peerNode{
   447  		port:   port,
   448  		g:      g,
   449  		s:      sp.(*GossipStateProviderImpl),
   450  		commit: committer,
   451  		cs:     cs,
   452  		grpc:   gRPCServer,
   453  	}, port
   454  
   455  }
   456  
   457  // add metrics provider for metrics testing
   458  func newPeerNodeWithGossipWithMetrics(id int, committer committer.Committer,
   459  	acceptor peerIdentityAcceptor, g peerNodeGossipSupport, gossipMetrics *metrics.GossipMetrics) *peerNode {
   460  	logger := flogging.MustGetLogger(gutil.StateLogger)
   461  	node, _ := newPeerNodeWithGossipWithValidatorWithMetrics(logger, id, committer, acceptor, g,
   462  		&validator.MockValidator{}, gossipMetrics)
   463  	return node
   464  }
   465  
   466  // Constructing pseudo peer node, simulating only gossip and state transfer part
   467  func newPeerNodeWithGossipWithValidator(logger gutil.Logger, id int, committer committer.Committer,
   468  	acceptor peerIdentityAcceptor, g peerNodeGossipSupport, v txvalidator.Validator, bootPorts ...int) *peerNode {
   469  	gossipMetrics := metrics.NewGossipMetrics(&disabled.Provider{})
   470  	node, _ := newPeerNodeWithGossipWithValidatorWithMetrics(logger, id, committer, acceptor, g, v, gossipMetrics, bootPorts...)
   471  	return node
   472  }
   473  
   474  // Constructing pseudo peer node, simulating only gossip and state transfer part
   475  func newPeerNode(id int, committer committer.Committer, acceptor peerIdentityAcceptor, bootPorts ...int) *peerNode {
   476  	return newPeerNodeWithGossip(id, committer, acceptor, nil, bootPorts...)
   477  }
   478  
   479  // Constructing pseudo boot node, simulating only gossip and state transfer part, return port
   480  func newBootNode(id int, committer committer.Committer, acceptor peerIdentityAcceptor) (node *peerNode, port int) {
   481  	v := &validator.MockValidator{}
   482  	gossipMetrics := metrics.NewGossipMetrics(&disabled.Provider{})
   483  	logger := flogging.MustGetLogger(gutil.StateLogger)
   484  	return newPeerNodeWithGossipWithValidatorWithMetrics(logger, id, committer, acceptor, nil, v, gossipMetrics)
   485  }
   486  
   487  func TestStraggler(t *testing.T) {
   488  	for _, testCase := range []struct {
   489  		stateEnabled   bool
   490  		orgLeader      bool
   491  		leaderElection bool
   492  		height         uint64
   493  		receivedSeq    uint64
   494  		expected       bool
   495  	}{
   496  		{
   497  			height:         100,
   498  			receivedSeq:    300,
   499  			leaderElection: true,
   500  			expected:       true,
   501  		},
   502  		{
   503  			height:      100,
   504  			receivedSeq: 300,
   505  			expected:    true,
   506  		},
   507  		{
   508  			height:      100,
   509  			receivedSeq: 300,
   510  			orgLeader:   true,
   511  		},
   512  		{
   513  			height:         100,
   514  			receivedSeq:    105,
   515  			leaderElection: true,
   516  		},
   517  		{
   518  			height:         100,
   519  			receivedSeq:    300,
   520  			leaderElection: true,
   521  			stateEnabled:   true,
   522  		},
   523  	} {
   524  		description := fmt.Sprintf("%+v", testCase)
   525  		t.Run(description, func(t *testing.T) {
   526  			s := &GossipStateProviderImpl{
   527  				config: &StateConfig{
   528  					StateEnabled:      testCase.stateEnabled,
   529  					OrgLeader:         testCase.orgLeader,
   530  					UseLeaderElection: testCase.leaderElection,
   531  				},
   532  			}
   533  
   534  			s.straggler(testCase.height, &proto.Payload{
   535  				SeqNum: testCase.receivedSeq,
   536  			})
   537  		})
   538  	}
   539  
   540  }
   541  
   542  func TestNilDirectMsg(t *testing.T) {
   543  	mc := &mockCommitter{Mock: &mock.Mock{}}
   544  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   545  	g := &mocks.GossipMock{}
   546  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   547  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   548  	p := newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   549  	defer p.shutdown()
   550  	p.s.handleStateRequest(nil)
   551  	p.s.directMessage(nil)
   552  	sMsg, _ := protoext.NoopSign(p.s.stateRequestMessage(uint64(10), uint64(8)))
   553  	req := &comm.ReceivedMessageImpl{
   554  		SignedGossipMessage: sMsg,
   555  	}
   556  	p.s.directMessage(req)
   557  }
   558  
   559  func TestNilAddPayload(t *testing.T) {
   560  	mc := &mockCommitter{Mock: &mock.Mock{}}
   561  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   562  	g := &mocks.GossipMock{}
   563  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   564  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   565  	p := newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   566  	defer p.shutdown()
   567  	err := p.s.AddPayload(nil)
   568  	assert.Error(t, err)
   569  	assert.Contains(t, err.Error(), "nil")
   570  }
   571  
   572  func TestAddPayloadLedgerUnavailable(t *testing.T) {
   573  	mc := &mockCommitter{Mock: &mock.Mock{}}
   574  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   575  	g := &mocks.GossipMock{}
   576  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   577  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   578  	p := newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   579  	defer p.shutdown()
   580  	// Simulate a problem in the ledger
   581  	failedLedger := mock.Mock{}
   582  	failedLedger.On("LedgerHeight", mock.Anything).Return(uint64(0), errors.New("cannot query ledger"))
   583  	mc.Lock()
   584  	mc.Mock = &failedLedger
   585  	mc.Unlock()
   586  
   587  	rawblock := protoutil.NewBlock(uint64(1), []byte{})
   588  	b, _ := pb.Marshal(rawblock)
   589  	err := p.s.AddPayload(&proto.Payload{
   590  		SeqNum: uint64(1),
   591  		Data:   b,
   592  	})
   593  	assert.Error(t, err)
   594  	assert.Contains(t, err.Error(), "Failed obtaining ledger height")
   595  	assert.Contains(t, err.Error(), "cannot query ledger")
   596  }
   597  
   598  func TestLargeBlockGap(t *testing.T) {
   599  	// Scenario: the peer knows of a peer who has a ledger height much higher
   600  	// than itself (500 blocks higher).
   601  	// The peer needs to ask blocks in a way such that the size of the payload buffer
   602  	// never rises above a certain threshold.
   603  	mc := &mockCommitter{Mock: &mock.Mock{}}
   604  	blocksPassedToLedger := make(chan uint64, 200)
   605  	mc.On("CommitLegacy", mock.Anything).Run(func(arg mock.Arguments) {
   606  		blocksPassedToLedger <- arg.Get(0).(*pcomm.Block).Header.Number
   607  	})
   608  	msgsFromPeer := make(chan protoext.ReceivedMessage)
   609  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   610  	mc.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
   611  	g := &mocks.GossipMock{}
   612  	membership := []discovery.NetworkMember{
   613  		{
   614  			PKIid:    common.PKIidType("a"),
   615  			Endpoint: "a",
   616  			Properties: &proto.Properties{
   617  				LedgerHeight: 500,
   618  			},
   619  		}}
   620  	g.On("PeersOfChannel", mock.Anything).Return(membership)
   621  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   622  	g.On("Accept", mock.Anything, true).Return(nil, msgsFromPeer)
   623  	g.On("Send", mock.Anything, mock.Anything).Run(func(arguments mock.Arguments) {
   624  		msg := arguments.Get(0).(*proto.GossipMessage)
   625  		// The peer requested a state request
   626  		req := msg.GetStateRequest()
   627  		// Construct a skeleton for the response
   628  		res := &proto.GossipMessage{
   629  			Nonce:   msg.Nonce,
   630  			Channel: []byte("testchannelid"),
   631  			Content: &proto.GossipMessage_StateResponse{
   632  				StateResponse: &proto.RemoteStateResponse{},
   633  			},
   634  		}
   635  		// Populate the response with payloads according to what the peer asked
   636  		for seq := req.StartSeqNum; seq <= req.EndSeqNum; seq++ {
   637  			rawblock := protoutil.NewBlock(seq, []byte{})
   638  			b, _ := pb.Marshal(rawblock)
   639  			payload := &proto.Payload{
   640  				SeqNum: seq,
   641  				Data:   b,
   642  			}
   643  			res.GetStateResponse().Payloads = append(res.GetStateResponse().Payloads, payload)
   644  		}
   645  		// Finally, send the response down the channel the peer expects to receive it from
   646  		sMsg, _ := protoext.NoopSign(res)
   647  		msgsFromPeer <- &comm.ReceivedMessageImpl{
   648  			SignedGossipMessage: sMsg,
   649  		}
   650  	})
   651  	p := newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   652  	defer p.shutdown()
   653  
   654  	// Process blocks at a speed of 20 Millisecond for each block.
   655  	// The imaginative peer that responds to state
   656  	// If the payload buffer expands above defMaxBlockDistance*2 + defAntiEntropyBatchSize blocks, fail the test
   657  	blockProcessingTime := 20 * time.Millisecond // 10 seconds for total 500 blocks
   658  	expectedSequence := 1
   659  	for expectedSequence < 500 {
   660  		blockSeq := <-blocksPassedToLedger
   661  		assert.Equal(t, expectedSequence, int(blockSeq))
   662  		// Ensure payload buffer isn't over-populated
   663  		assert.True(t, p.s.payloads.Size() <= defMaxBlockDistance*2+defAntiEntropyBatchSize, "payload buffer size is %d", p.s.payloads.Size())
   664  		expectedSequence++
   665  		time.Sleep(blockProcessingTime)
   666  	}
   667  }
   668  
   669  func TestOverPopulation(t *testing.T) {
   670  	// Scenario: Add to the state provider blocks
   671  	// with a gap in between, and ensure that the payload buffer
   672  	// rejects blocks starting if the distance between the ledger height to the latest
   673  	// block it contains is bigger than defMaxBlockDistance.
   674  	mc := &mockCommitter{Mock: &mock.Mock{}}
   675  	blocksPassedToLedger := make(chan uint64, 10)
   676  	mc.On("CommitLegacy", mock.Anything).Run(func(arg mock.Arguments) {
   677  		blocksPassedToLedger <- arg.Get(0).(*pcomm.Block).Header.Number
   678  	})
   679  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   680  	mc.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
   681  	g := &mocks.GossipMock{}
   682  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   683  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   684  	p := newPeerNode(0, mc, noopPeerIdentityAcceptor)
   685  	defer p.shutdown()
   686  
   687  	// Add some blocks in a sequential manner and make sure it works
   688  	for i := 1; i <= 4; i++ {
   689  		rawblock := protoutil.NewBlock(uint64(i), []byte{})
   690  		b, _ := pb.Marshal(rawblock)
   691  		assert.NoError(t, p.s.addPayload(&proto.Payload{
   692  			SeqNum: uint64(i),
   693  			Data:   b,
   694  		}, nonBlocking))
   695  	}
   696  
   697  	// Add payloads from 10 to defMaxBlockDistance, while we're missing blocks [5,9]
   698  	// Should succeed
   699  	for i := 10; i <= defMaxBlockDistance; i++ {
   700  		rawblock := protoutil.NewBlock(uint64(i), []byte{})
   701  		b, _ := pb.Marshal(rawblock)
   702  		assert.NoError(t, p.s.addPayload(&proto.Payload{
   703  			SeqNum: uint64(i),
   704  			Data:   b,
   705  		}, nonBlocking))
   706  	}
   707  
   708  	// Add payloads from defMaxBlockDistance + 2 to defMaxBlockDistance * 10
   709  	// Should fail.
   710  	for i := defMaxBlockDistance + 1; i <= defMaxBlockDistance*10; i++ {
   711  		rawblock := protoutil.NewBlock(uint64(i), []byte{})
   712  		b, _ := pb.Marshal(rawblock)
   713  		assert.Error(t, p.s.addPayload(&proto.Payload{
   714  			SeqNum: uint64(i),
   715  			Data:   b,
   716  		}, nonBlocking))
   717  	}
   718  
   719  	// Ensure only blocks 1-4 were passed to the ledger
   720  	close(blocksPassedToLedger)
   721  	i := 1
   722  	for seq := range blocksPassedToLedger {
   723  		assert.Equal(t, uint64(i), seq)
   724  		i++
   725  	}
   726  	assert.Equal(t, 5, i)
   727  
   728  	// Ensure we don't store too many blocks in memory
   729  	sp := p.s
   730  	assert.True(t, sp.payloads.Size() < defMaxBlockDistance)
   731  }
   732  
   733  func TestBlockingEnqueue(t *testing.T) {
   734  	// Scenario: In parallel, get blocks from gossip and from the orderer.
   735  	// The blocks from the orderer we get are X2 times the amount of blocks from gossip.
   736  	// The blocks we get from gossip are random indices, to maximize disruption.
   737  	mc := &mockCommitter{Mock: &mock.Mock{}}
   738  	blocksPassedToLedger := make(chan uint64, 10)
   739  	mc.On("CommitLegacy", mock.Anything).Run(func(arg mock.Arguments) {
   740  		blocksPassedToLedger <- arg.Get(0).(*pcomm.Block).Header.Number
   741  	})
   742  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   743  	mc.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
   744  	g := &mocks.GossipMock{}
   745  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   746  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   747  	p := newPeerNode(0, mc, noopPeerIdentityAcceptor)
   748  	defer p.shutdown()
   749  
   750  	numBlocksReceived := 500
   751  	receivedBlockCount := 0
   752  	// Get a block from the orderer every 1ms
   753  	go func() {
   754  		for i := 1; i <= numBlocksReceived; i++ {
   755  			rawblock := protoutil.NewBlock(uint64(i), []byte{})
   756  			b, _ := pb.Marshal(rawblock)
   757  			block := &proto.Payload{
   758  				SeqNum: uint64(i),
   759  				Data:   b,
   760  			}
   761  			p.s.AddPayload(block)
   762  			time.Sleep(time.Millisecond)
   763  		}
   764  	}()
   765  
   766  	// Get a block from gossip every 1ms too
   767  	go func() {
   768  		rand.Seed(time.Now().UnixNano())
   769  		for i := 1; i <= numBlocksReceived/2; i++ {
   770  			blockSeq := rand.Intn(numBlocksReceived)
   771  			rawblock := protoutil.NewBlock(uint64(blockSeq), []byte{})
   772  			b, _ := pb.Marshal(rawblock)
   773  			block := &proto.Payload{
   774  				SeqNum: uint64(blockSeq),
   775  				Data:   b,
   776  			}
   777  			p.s.addPayload(block, nonBlocking)
   778  			time.Sleep(time.Millisecond)
   779  		}
   780  	}()
   781  
   782  	for {
   783  		receivedBlock := <-blocksPassedToLedger
   784  		receivedBlockCount++
   785  		m := &mock.Mock{}
   786  		m.On("LedgerHeight", mock.Anything).Return(receivedBlock, nil)
   787  		m.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
   788  		m.On("CommitLegacy", mock.Anything).Run(func(arg mock.Arguments) {
   789  			blocksPassedToLedger <- arg.Get(0).(*pcomm.Block).Header.Number
   790  		})
   791  		mc.Lock()
   792  		mc.Mock = m
   793  		mc.Unlock()
   794  		assert.Equal(t, receivedBlock, uint64(receivedBlockCount))
   795  		if int(receivedBlockCount) == numBlocksReceived {
   796  			break
   797  		}
   798  		time.Sleep(time.Millisecond * 10)
   799  	}
   800  }
   801  
   802  func TestHaltChainProcessing(t *testing.T) {
   803  	gossipChannel := func(c chan *proto.GossipMessage) <-chan *proto.GossipMessage {
   804  		return c
   805  	}
   806  	makeBlock := func(seq int) []byte {
   807  		b := &pcomm.Block{
   808  			Header: &pcomm.BlockHeader{
   809  				Number: uint64(seq),
   810  			},
   811  			Data: &pcomm.BlockData{
   812  				Data: [][]byte{},
   813  			},
   814  			Metadata: &pcomm.BlockMetadata{
   815  				Metadata: [][]byte{
   816  					{}, {}, {}, {},
   817  				},
   818  			},
   819  		}
   820  		data, _ := pb.Marshal(b)
   821  		return data
   822  	}
   823  	newBlockMsg := func(i int) *proto.GossipMessage {
   824  		return &proto.GossipMessage{
   825  			Channel: []byte("testchannelid"),
   826  			Content: &proto.GossipMessage_DataMsg{
   827  				DataMsg: &proto.DataMessage{
   828  					Payload: &proto.Payload{
   829  						SeqNum: uint64(i),
   830  						Data:   makeBlock(i),
   831  					},
   832  				},
   833  			},
   834  		}
   835  	}
   836  
   837  	mc := &mockCommitter{Mock: &mock.Mock{}}
   838  	mc.On("CommitLegacy", mock.Anything)
   839  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   840  	g := &mocks.GossipMock{}
   841  	gossipMsgs := make(chan *proto.GossipMessage)
   842  
   843  	g.On("Accept", mock.Anything, false).Return(gossipChannel(gossipMsgs), nil)
   844  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   845  	g.On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{})
   846  
   847  	v := &validator.MockValidator{}
   848  	v.On("Validate").Return(&errors2.VSCCExecutionFailureError{
   849  		Err: errors.New("foobar"),
   850  	}).Once()
   851  
   852  	buf := gbytes.NewBuffer()
   853  
   854  	logger := flogging.MustGetLogger(gutil.StateLogger).WithOptions(zap.Hooks(func(entry zapcore.Entry) error {
   855  		buf.Write([]byte(entry.Message))
   856  		buf.Write([]byte("\n"))
   857  		return nil
   858  	}))
   859  	peerNode := newPeerNodeWithGossipWithValidator(logger, 0, mc, noopPeerIdentityAcceptor, g, v)
   860  	defer peerNode.shutdown()
   861  	gossipMsgs <- newBlockMsg(1)
   862  
   863  	gom := gomega.NewGomegaWithT(t)
   864  	gom.Eventually(buf, time.Minute).Should(gbytes.Say("Failed executing VSCC due to foobar"))
   865  	gom.Eventually(buf, time.Minute).Should(gbytes.Say("Aborting chain processing"))
   866  }
   867  
   868  func TestFailures(t *testing.T) {
   869  	mc := &mockCommitter{Mock: &mock.Mock{}}
   870  	mc.On("LedgerHeight", mock.Anything).Return(uint64(0), nil)
   871  	g := &mocks.GossipMock{}
   872  	g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   873  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   874  	g.On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{})
   875  	assert.Panics(t, func() {
   876  		newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   877  	})
   878  	// Reprogram mock
   879  	mc.Mock = &mock.Mock{}
   880  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), errors.New("Failed accessing ledger"))
   881  	assert.Nil(t, newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g))
   882  }
   883  
   884  func TestGossipReception(t *testing.T) {
   885  	signalChan := make(chan struct{})
   886  	rawblock := &pcomm.Block{
   887  		Header: &pcomm.BlockHeader{
   888  			Number: uint64(1),
   889  		},
   890  		Data: &pcomm.BlockData{
   891  			Data: [][]byte{},
   892  		},
   893  		Metadata: &pcomm.BlockMetadata{
   894  			Metadata: [][]byte{
   895  				{}, {}, {}, {},
   896  			},
   897  		},
   898  	}
   899  	b, _ := pb.Marshal(rawblock)
   900  
   901  	newMsg := func(channel string) *proto.GossipMessage {
   902  		{
   903  			return &proto.GossipMessage{
   904  				Channel: []byte(channel),
   905  				Content: &proto.GossipMessage_DataMsg{
   906  					DataMsg: &proto.DataMessage{
   907  						Payload: &proto.Payload{
   908  							SeqNum: 1,
   909  							Data:   b,
   910  						},
   911  					},
   912  				},
   913  			}
   914  		}
   915  	}
   916  
   917  	createChan := func(signalChan chan struct{}) <-chan *proto.GossipMessage {
   918  		c := make(chan *proto.GossipMessage)
   919  
   920  		go func(c chan *proto.GossipMessage) {
   921  			// Wait for Accept() to be called
   922  			<-signalChan
   923  			// Simulate a message reception from the gossip component with an invalid channel
   924  			c <- newMsg("AAA")
   925  			// Simulate a message reception from the gossip component
   926  			c <- newMsg("testchannelid")
   927  		}(c)
   928  		return c
   929  	}
   930  
   931  	g := &mocks.GossipMock{}
   932  	rmc := createChan(signalChan)
   933  	g.On("Accept", mock.Anything, false).Return(rmc, nil).Run(func(_ mock.Arguments) {
   934  		signalChan <- struct{}{}
   935  	})
   936  	g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   937  	g.On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{})
   938  	mc := &mockCommitter{Mock: &mock.Mock{}}
   939  	receivedChan := make(chan struct{})
   940  	mc.On("CommitLegacy", mock.Anything).Run(func(arguments mock.Arguments) {
   941  		block := arguments.Get(0).(*pcomm.Block)
   942  		assert.Equal(t, uint64(1), block.Header.Number)
   943  		receivedChan <- struct{}{}
   944  	})
   945  	mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   946  	mc.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
   947  	p := newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   948  	defer p.shutdown()
   949  	select {
   950  	case <-receivedChan:
   951  	case <-time.After(time.Second * 15):
   952  		assert.Fail(t, "Didn't commit a block within a timely manner")
   953  	}
   954  }
   955  
   956  func TestLedgerHeightFromProperties(t *testing.T) {
   957  	// Scenario: For each test, spawn a peer and supply it
   958  	// with a specific mock of PeersOfChannel from peers that
   959  	// either set both metadata properly, or only the properties, or none, or both.
   960  	// Ensure the logic handles all of the 4 possible cases as needed
   961  
   962  	// Returns whether the given networkMember was selected or not
   963  	wasNetworkMemberSelected := func(t *testing.T, networkMember discovery.NetworkMember) bool {
   964  		var wasGivenNetworkMemberSelected int32
   965  		finChan := make(chan struct{})
   966  		g := &mocks.GossipMock{}
   967  		g.On("Send", mock.Anything, mock.Anything).Run(func(arguments mock.Arguments) {
   968  			msg := arguments.Get(0).(*proto.GossipMessage)
   969  			assert.NotNil(t, msg.GetStateRequest())
   970  			peer := arguments.Get(1).([]*comm.RemotePeer)[0]
   971  			if bytes.Equal(networkMember.PKIid, peer.PKIID) {
   972  				atomic.StoreInt32(&wasGivenNetworkMemberSelected, 1)
   973  			}
   974  			finChan <- struct{}{}
   975  		})
   976  		g.On("Accept", mock.Anything, false).Return(make(<-chan *proto.GossipMessage), nil)
   977  		g.On("Accept", mock.Anything, true).Return(nil, make(chan protoext.ReceivedMessage))
   978  		defaultPeer := discovery.NetworkMember{
   979  			InternalEndpoint: "b",
   980  			PKIid:            common.PKIidType("b"),
   981  			Properties: &proto.Properties{
   982  				LedgerHeight: 5,
   983  			},
   984  		}
   985  		g.On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{
   986  			defaultPeer,
   987  			networkMember,
   988  		})
   989  		mc := &mockCommitter{Mock: &mock.Mock{}}
   990  		mc.On("LedgerHeight", mock.Anything).Return(uint64(1), nil)
   991  		p := newPeerNodeWithGossip(0, mc, noopPeerIdentityAcceptor, g)
   992  		defer p.shutdown()
   993  		select {
   994  		case <-time.After(time.Second * 20):
   995  			t.Fatal("Didn't send a request within a timely manner")
   996  		case <-finChan:
   997  		}
   998  		return atomic.LoadInt32(&wasGivenNetworkMemberSelected) == 1
   999  	}
  1000  
  1001  	peerWithProperties := discovery.NetworkMember{
  1002  		PKIid: common.PKIidType("peerWithoutMetadata"),
  1003  		Properties: &proto.Properties{
  1004  			LedgerHeight: 10,
  1005  		},
  1006  		InternalEndpoint: "peerWithoutMetadata",
  1007  	}
  1008  
  1009  	peerWithoutProperties := discovery.NetworkMember{
  1010  		PKIid:            common.PKIidType("peerWithoutProperties"),
  1011  		InternalEndpoint: "peerWithoutProperties",
  1012  	}
  1013  
  1014  	tests := []struct {
  1015  		shouldGivenBeSelected bool
  1016  		member                discovery.NetworkMember
  1017  	}{
  1018  		{member: peerWithProperties, shouldGivenBeSelected: true},
  1019  		{member: peerWithoutProperties, shouldGivenBeSelected: false},
  1020  	}
  1021  
  1022  	for _, tst := range tests {
  1023  		assert.Equal(t, tst.shouldGivenBeSelected, wasNetworkMemberSelected(t, tst.member))
  1024  	}
  1025  }
  1026  
  1027  func TestAccessControl(t *testing.T) {
  1028  	bootstrapSetSize := 5
  1029  	bootstrapSet := make([]*peerNode, 0)
  1030  
  1031  	authorizedPeersSize := 4
  1032  	var listeners []net.Listener
  1033  	var endpoints []string
  1034  
  1035  	for i := 0; i < authorizedPeersSize; i++ {
  1036  		ll, err := net.Listen("tcp", "127.0.0.1:0")
  1037  		assert.NoError(t, err)
  1038  		listeners = append(listeners, ll)
  1039  		endpoint := ll.Addr().String()
  1040  		endpoints = append(endpoints, endpoint)
  1041  	}
  1042  
  1043  	defer func() {
  1044  		for _, ll := range listeners {
  1045  			ll.Close()
  1046  		}
  1047  	}()
  1048  
  1049  	authorizedPeers := map[string]struct{}{
  1050  		endpoints[0]: {},
  1051  		endpoints[1]: {},
  1052  		endpoints[2]: {},
  1053  		endpoints[3]: {},
  1054  	}
  1055  
  1056  	blockPullPolicy := func(identity api.PeerIdentityType) error {
  1057  		if _, isAuthorized := authorizedPeers[string(identity)]; isAuthorized {
  1058  			return nil
  1059  		}
  1060  		return errors.New("Not authorized")
  1061  	}
  1062  
  1063  	var bootPorts []int
  1064  
  1065  	for i := 0; i < bootstrapSetSize; i++ {
  1066  		commit := newCommitter()
  1067  		bootPeer, bootPort := newBootNode(i, commit, blockPullPolicy)
  1068  		bootstrapSet = append(bootstrapSet, bootPeer)
  1069  		bootPorts = append(bootPorts, bootPort)
  1070  	}
  1071  
  1072  	defer func() {
  1073  		for _, p := range bootstrapSet {
  1074  			p.shutdown()
  1075  		}
  1076  	}()
  1077  
  1078  	msgCount := 5
  1079  
  1080  	for i := 1; i <= msgCount; i++ {
  1081  		rawblock := protoutil.NewBlock(uint64(i), []byte{})
  1082  		if b, err := pb.Marshal(rawblock); err == nil {
  1083  			payload := &proto.Payload{
  1084  				SeqNum: uint64(i),
  1085  				Data:   b,
  1086  			}
  1087  			bootstrapSet[0].s.AddPayload(payload)
  1088  		} else {
  1089  			t.Fail()
  1090  		}
  1091  	}
  1092  
  1093  	standardPeerSetSize := 10
  1094  	peersSet := make([]*peerNode, 0)
  1095  
  1096  	for i := 0; i < standardPeerSetSize; i++ {
  1097  		commit := newCommitter()
  1098  		peersSet = append(peersSet, newPeerNode(bootstrapSetSize+i, commit, blockPullPolicy, bootPorts...))
  1099  	}
  1100  
  1101  	defer func() {
  1102  		for _, p := range peersSet {
  1103  			p.shutdown()
  1104  		}
  1105  	}()
  1106  
  1107  	waitUntilTrueOrTimeout(t, func() bool {
  1108  		for _, p := range peersSet {
  1109  			if len(p.g.PeersOfChannel(common.ChannelID("testchannelid"))) != bootstrapSetSize+standardPeerSetSize-1 {
  1110  				t.Log("Peer discovery has not finished yet")
  1111  				return false
  1112  			}
  1113  		}
  1114  		t.Log("All peer discovered each other!!!")
  1115  		return true
  1116  	}, 30*time.Second)
  1117  
  1118  	t.Log("Waiting for all blocks to arrive.")
  1119  	waitUntilTrueOrTimeout(t, func() bool {
  1120  		t.Log("Trying to see all authorized peers get all blocks, and all non-authorized didn't")
  1121  		for _, p := range peersSet {
  1122  			height, err := p.commit.LedgerHeight()
  1123  			id := fmt.Sprintf("127.0.0.1:%d", p.port)
  1124  			if _, isAuthorized := authorizedPeers[id]; isAuthorized {
  1125  				if height != uint64(msgCount+1) || err != nil {
  1126  					return false
  1127  				}
  1128  			} else {
  1129  				if err == nil && height > 1 {
  1130  					assert.Fail(t, "Peer", id, "got message but isn't authorized! Height:", height)
  1131  				}
  1132  			}
  1133  		}
  1134  		t.Log("All peers have same ledger height!!!")
  1135  		return true
  1136  	}, 60*time.Second)
  1137  }
  1138  
  1139  func TestNewGossipStateProvider_SendingManyMessages(t *testing.T) {
  1140  	bootstrapSetSize := 5
  1141  	bootstrapSet := make([]*peerNode, 0)
  1142  
  1143  	var bootPorts []int
  1144  
  1145  	for i := 0; i < bootstrapSetSize; i++ {
  1146  		commit := newCommitter()
  1147  		bootPeer, bootPort := newBootNode(i, commit, noopPeerIdentityAcceptor)
  1148  		bootstrapSet = append(bootstrapSet, bootPeer)
  1149  		bootPorts = append(bootPorts, bootPort)
  1150  	}
  1151  
  1152  	defer func() {
  1153  		for _, p := range bootstrapSet {
  1154  			p.shutdown()
  1155  		}
  1156  	}()
  1157  
  1158  	msgCount := 10
  1159  
  1160  	for i := 1; i <= msgCount; i++ {
  1161  		rawblock := protoutil.NewBlock(uint64(i), []byte{})
  1162  		if b, err := pb.Marshal(rawblock); err == nil {
  1163  			payload := &proto.Payload{
  1164  				SeqNum: uint64(i),
  1165  				Data:   b,
  1166  			}
  1167  			bootstrapSet[0].s.AddPayload(payload)
  1168  		} else {
  1169  			t.Fail()
  1170  		}
  1171  	}
  1172  
  1173  	standartPeersSize := 10
  1174  	peersSet := make([]*peerNode, 0)
  1175  
  1176  	for i := 0; i < standartPeersSize; i++ {
  1177  		commit := newCommitter()
  1178  		peersSet = append(peersSet, newPeerNode(bootstrapSetSize+i, commit, noopPeerIdentityAcceptor, bootPorts...))
  1179  	}
  1180  
  1181  	defer func() {
  1182  		for _, p := range peersSet {
  1183  			p.shutdown()
  1184  		}
  1185  	}()
  1186  
  1187  	waitUntilTrueOrTimeout(t, func() bool {
  1188  		for _, p := range peersSet {
  1189  			if len(p.g.PeersOfChannel(common.ChannelID("testchannelid"))) != bootstrapSetSize+standartPeersSize-1 {
  1190  				t.Log("Peer discovery has not finished yet")
  1191  				return false
  1192  			}
  1193  		}
  1194  		t.Log("All peer discovered each other!!!")
  1195  		return true
  1196  	}, 30*time.Second)
  1197  
  1198  	t.Log("Waiting for all blocks to arrive.")
  1199  	waitUntilTrueOrTimeout(t, func() bool {
  1200  		t.Log("Trying to see all peers get all blocks")
  1201  		for _, p := range peersSet {
  1202  			height, err := p.commit.LedgerHeight()
  1203  			if height != uint64(msgCount+1) || err != nil {
  1204  				return false
  1205  			}
  1206  		}
  1207  		t.Log("All peers have same ledger height!!!")
  1208  		return true
  1209  	}, 60*time.Second)
  1210  }
  1211  
  1212  // Start one bootstrap peer and submit defAntiEntropyBatchSize + 5 messages into
  1213  // local ledger, next spawning a new peer waiting for anti-entropy procedure to
  1214  // complete missing blocks. Since state transfer messages now batched, it is expected
  1215  // to see _exactly_ two messages with state transfer response.
  1216  func TestNewGossipStateProvider_BatchingOfStateRequest(t *testing.T) {
  1217  	bootPeer, bootPort := newBootNode(0, newCommitter(), noopPeerIdentityAcceptor)
  1218  	defer bootPeer.shutdown()
  1219  
  1220  	msgCount := defAntiEntropyBatchSize + 5
  1221  	expectedMessagesCnt := 2
  1222  
  1223  	for i := 1; i <= msgCount; i++ {
  1224  		rawblock := protoutil.NewBlock(uint64(i), []byte{})
  1225  		if b, err := pb.Marshal(rawblock); err == nil {
  1226  			payload := &proto.Payload{
  1227  				SeqNum: uint64(i),
  1228  				Data:   b,
  1229  			}
  1230  			bootPeer.s.AddPayload(payload)
  1231  		} else {
  1232  			t.Fail()
  1233  		}
  1234  	}
  1235  
  1236  	peer := newPeerNode(1, newCommitter(), noopPeerIdentityAcceptor, bootPort)
  1237  	defer peer.shutdown()
  1238  
  1239  	naiveStateMsgPredicate := func(message interface{}) bool {
  1240  		return protoext.IsRemoteStateMessage(message.(protoext.ReceivedMessage).GetGossipMessage().GossipMessage)
  1241  	}
  1242  	_, peerCh := peer.g.Accept(naiveStateMsgPredicate, true)
  1243  
  1244  	wg := sync.WaitGroup{}
  1245  	wg.Add(expectedMessagesCnt)
  1246  
  1247  	// Number of submitted messages is defAntiEntropyBatchSize + 5, therefore
  1248  	// expected number of batches is expectedMessagesCnt = 2. Following go routine
  1249  	// makes sure it receives expected amount of messages and sends signal of success
  1250  	// to continue the test
  1251  	go func() {
  1252  		for count := 0; count < expectedMessagesCnt; count++ {
  1253  			<-peerCh
  1254  			wg.Done()
  1255  		}
  1256  	}()
  1257  
  1258  	// Once we got message which indicate of two batches being received,
  1259  	// making sure messages indeed committed.
  1260  	waitUntilTrueOrTimeout(t, func() bool {
  1261  		if len(peer.g.PeersOfChannel(common.ChannelID("testchannelid"))) != 1 {
  1262  			t.Log("Peer discovery has not finished yet")
  1263  			return false
  1264  		}
  1265  		t.Log("All peer discovered each other!!!")
  1266  		return true
  1267  	}, 30*time.Second)
  1268  
  1269  	// Waits for message which indicates that expected number of message batches received
  1270  	// otherwise timeouts after 2 * defAntiEntropyInterval + 1 seconds
  1271  	wg.Wait()
  1272  
  1273  	t.Log("Waiting for all blocks to arrive.")
  1274  	waitUntilTrueOrTimeout(t, func() bool {
  1275  		t.Log("Trying to see all peers get all blocks")
  1276  		height, err := peer.commit.LedgerHeight()
  1277  		if height != uint64(msgCount+1) || err != nil {
  1278  			return false
  1279  		}
  1280  		t.Log("All peers have same ledger height!!!")
  1281  		return true
  1282  	}, 60*time.Second)
  1283  }
  1284  
  1285  // coordinatorMock mocking structure to capture mock interface for
  1286  // coord to simulate coord flow during the test
  1287  type coordinatorMock struct {
  1288  	committer.Committer
  1289  	mock.Mock
  1290  }
  1291  
  1292  func (mock *coordinatorMock) GetPvtDataAndBlockByNum(seqNum uint64, _ protoutil.SignedData) (*pcomm.Block, gutil.PvtDataCollections, error) {
  1293  	args := mock.Called(seqNum)
  1294  	return args.Get(0).(*pcomm.Block), args.Get(1).(gutil.PvtDataCollections), args.Error(2)
  1295  }
  1296  
  1297  func (mock *coordinatorMock) GetBlockByNum(seqNum uint64) (*pcomm.Block, error) {
  1298  	args := mock.Called(seqNum)
  1299  	return args.Get(0).(*pcomm.Block), args.Error(1)
  1300  }
  1301  
  1302  func (mock *coordinatorMock) StoreBlock(block *pcomm.Block, data gutil.PvtDataCollections) error {
  1303  	args := mock.Called(block, data)
  1304  	return args.Error(1)
  1305  }
  1306  
  1307  func (mock *coordinatorMock) LedgerHeight() (uint64, error) {
  1308  	args := mock.Called()
  1309  	return args.Get(0).(uint64), args.Error(1)
  1310  }
  1311  
  1312  func (mock *coordinatorMock) Close() {
  1313  	mock.Called()
  1314  }
  1315  
  1316  // StorePvtData used to persist private date into transient store
  1317  func (mock *coordinatorMock) StorePvtData(txid string, privData *tspb.TxPvtReadWriteSetWithConfigInfo, blkHeight uint64) error {
  1318  	return mock.Called().Error(0)
  1319  }
  1320  
  1321  type receivedMessageMock struct {
  1322  	mock.Mock
  1323  }
  1324  
  1325  // Ack returns to the sender an acknowledgement for the message
  1326  func (mock *receivedMessageMock) Ack(err error) {
  1327  
  1328  }
  1329  
  1330  func (mock *receivedMessageMock) Respond(msg *proto.GossipMessage) {
  1331  	mock.Called(msg)
  1332  }
  1333  
  1334  func (mock *receivedMessageMock) GetGossipMessage() *protoext.SignedGossipMessage {
  1335  	args := mock.Called()
  1336  	return args.Get(0).(*protoext.SignedGossipMessage)
  1337  }
  1338  
  1339  func (mock *receivedMessageMock) GetSourceEnvelope() *proto.Envelope {
  1340  	args := mock.Called()
  1341  	return args.Get(0).(*proto.Envelope)
  1342  }
  1343  
  1344  func (mock *receivedMessageMock) GetConnectionInfo() *protoext.ConnectionInfo {
  1345  	args := mock.Called()
  1346  	return args.Get(0).(*protoext.ConnectionInfo)
  1347  }
  1348  
  1349  type testData struct {
  1350  	block   *pcomm.Block
  1351  	pvtData gutil.PvtDataCollections
  1352  }
  1353  
  1354  func TestTransferOfPrivateRWSet(t *testing.T) {
  1355  	chainID := "testChainID"
  1356  
  1357  	// First gossip instance
  1358  	g := &mocks.GossipMock{}
  1359  	coord1 := new(coordinatorMock)
  1360  
  1361  	gossipChannel := make(chan *proto.GossipMessage)
  1362  	commChannel := make(chan protoext.ReceivedMessage)
  1363  
  1364  	gossipChannelFactory := func(ch chan *proto.GossipMessage) <-chan *proto.GossipMessage {
  1365  		return ch
  1366  	}
  1367  
  1368  	g.On("Accept", mock.Anything, false).Return(gossipChannelFactory(gossipChannel), nil)
  1369  	g.On("Accept", mock.Anything, true).Return(nil, commChannel)
  1370  
  1371  	g.On("UpdateChannelMetadata", mock.Anything, mock.Anything)
  1372  	g.On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{})
  1373  	g.On("Close")
  1374  
  1375  	coord1.On("LedgerHeight", mock.Anything).Return(uint64(5), nil)
  1376  
  1377  	var data = map[uint64]*testData{
  1378  		uint64(2): {
  1379  			block: &pcomm.Block{
  1380  				Header: &pcomm.BlockHeader{
  1381  					Number:       2,
  1382  					DataHash:     []byte{0, 1, 1, 1},
  1383  					PreviousHash: []byte{0, 0, 0, 1},
  1384  				},
  1385  				Data: &pcomm.BlockData{
  1386  					Data: [][]byte{{1}, {2}, {3}},
  1387  				},
  1388  			},
  1389  			pvtData: gutil.PvtDataCollections{
  1390  				{
  1391  					SeqInBlock: uint64(0),
  1392  					WriteSet: &rwset.TxPvtReadWriteSet{
  1393  						DataModel: rwset.TxReadWriteSet_KV,
  1394  						NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1395  							{
  1396  								Namespace: "myCC:v1",
  1397  								CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
  1398  									{
  1399  										CollectionName: "mysecrectCollection",
  1400  										Rwset:          []byte{1, 2, 3, 4, 5},
  1401  									},
  1402  								},
  1403  							},
  1404  						},
  1405  					},
  1406  				},
  1407  			},
  1408  		},
  1409  
  1410  		uint64(3): {
  1411  			block: &pcomm.Block{
  1412  				Header: &pcomm.BlockHeader{
  1413  					Number:       3,
  1414  					DataHash:     []byte{1, 1, 1, 1},
  1415  					PreviousHash: []byte{0, 1, 1, 1},
  1416  				},
  1417  				Data: &pcomm.BlockData{
  1418  					Data: [][]byte{{4}, {5}, {6}},
  1419  				},
  1420  			},
  1421  			pvtData: gutil.PvtDataCollections{
  1422  				{
  1423  					SeqInBlock: uint64(2),
  1424  					WriteSet: &rwset.TxPvtReadWriteSet{
  1425  						DataModel: rwset.TxReadWriteSet_KV,
  1426  						NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1427  							{
  1428  								Namespace: "otherCC:v1",
  1429  								CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
  1430  									{
  1431  										CollectionName: "topClassified",
  1432  										Rwset:          []byte{0, 0, 0, 4, 2},
  1433  									},
  1434  								},
  1435  							},
  1436  						},
  1437  					},
  1438  				},
  1439  			},
  1440  		},
  1441  	}
  1442  
  1443  	for seqNum, each := range data {
  1444  		coord1.On("GetPvtDataAndBlockByNum", seqNum).Return(each.block, each.pvtData, nil /* no error*/)
  1445  	}
  1446  
  1447  	coord1.On("Close")
  1448  
  1449  	servicesAdapater := &ServicesMediator{GossipAdapter: g, MCSAdapter: &cryptoServiceMock{acceptor: noopPeerIdentityAcceptor}}
  1450  	stateMetrics := metrics.NewGossipMetrics(&disabled.Provider{}).StateMetrics
  1451  	stateConfig := &StateConfig{
  1452  		StateCheckInterval:   DefStateCheckInterval,
  1453  		StateResponseTimeout: DefStateResponseTimeout,
  1454  		StateBatchSize:       DefStateBatchSize,
  1455  		StateMaxRetries:      DefStateMaxRetries,
  1456  		StateBlockBufferSize: DefStateBlockBufferSize,
  1457  		StateChannelSize:     DefStateChannelSize,
  1458  		StateEnabled:         true,
  1459  	}
  1460  	logger := flogging.MustGetLogger(gutil.StateLogger)
  1461  	st := NewGossipStateProvider(logger, chainID, servicesAdapater, coord1, stateMetrics, blocking, stateConfig)
  1462  	defer st.Stop()
  1463  
  1464  	// Mocked state request message
  1465  	requestMsg := new(receivedMessageMock)
  1466  
  1467  	// Get state request message, blocks [2...3]
  1468  	requestGossipMsg := &proto.GossipMessage{
  1469  		// Copy nonce field from the request, so it will be possible to match response
  1470  		Nonce:   1,
  1471  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
  1472  		Channel: []byte(chainID),
  1473  		Content: &proto.GossipMessage_StateRequest{StateRequest: &proto.RemoteStateRequest{
  1474  			StartSeqNum: 2,
  1475  			EndSeqNum:   3,
  1476  		}},
  1477  	}
  1478  
  1479  	msg, _ := protoext.NoopSign(requestGossipMsg)
  1480  
  1481  	requestMsg.On("GetGossipMessage").Return(msg)
  1482  	requestMsg.On("GetConnectionInfo").Return(&protoext.ConnectionInfo{
  1483  		Auth: &protoext.AuthInfo{},
  1484  	})
  1485  
  1486  	// Channel to send responses back
  1487  	responseChannel := make(chan protoext.ReceivedMessage)
  1488  	defer close(responseChannel)
  1489  
  1490  	requestMsg.On("Respond", mock.Anything).Run(func(args mock.Arguments) {
  1491  		// Get gossip response to respond back on state request
  1492  		response := args.Get(0).(*proto.GossipMessage)
  1493  		// Wrap it up into received response
  1494  		receivedMsg := new(receivedMessageMock)
  1495  		// Create sign response
  1496  		msg, _ := protoext.NoopSign(response)
  1497  		// Mock to respond
  1498  		receivedMsg.On("GetGossipMessage").Return(msg)
  1499  		// Send response
  1500  		responseChannel <- receivedMsg
  1501  	})
  1502  
  1503  	// Send request message via communication channel into state transfer
  1504  	commChannel <- requestMsg
  1505  
  1506  	// State transfer request should result in state response back
  1507  	response := <-responseChannel
  1508  
  1509  	// Start the assertion section
  1510  	stateResponse := response.GetGossipMessage().GetStateResponse()
  1511  
  1512  	assertion := assert.New(t)
  1513  	// Nonce should be equal to Nonce of the request
  1514  	assertion.Equal(response.GetGossipMessage().Nonce, uint64(1))
  1515  	// Payload should not need be nil
  1516  	assertion.NotNil(stateResponse)
  1517  	assertion.NotNil(stateResponse.Payloads)
  1518  	// Exactly two messages expected
  1519  	assertion.Equal(len(stateResponse.Payloads), 2)
  1520  
  1521  	// Assert we have all data and it's same as we expected it
  1522  	for _, each := range stateResponse.Payloads {
  1523  		block := &pcomm.Block{}
  1524  		err := pb.Unmarshal(each.Data, block)
  1525  		assertion.NoError(err)
  1526  
  1527  		assertion.NotNil(block.Header)
  1528  
  1529  		testBlock, ok := data[block.Header.Number]
  1530  		assertion.True(ok)
  1531  
  1532  		for i, d := range testBlock.block.Data.Data {
  1533  			assertion.True(bytes.Equal(d, block.Data.Data[i]))
  1534  		}
  1535  
  1536  		for i, p := range testBlock.pvtData {
  1537  			pvtDataPayload := &proto.PvtDataPayload{}
  1538  			err := pb.Unmarshal(each.PrivateData[i], pvtDataPayload)
  1539  			assertion.NoError(err)
  1540  			pvtRWSet := &rwset.TxPvtReadWriteSet{}
  1541  			err = pb.Unmarshal(pvtDataPayload.Payload, pvtRWSet)
  1542  			assertion.NoError(err)
  1543  			assertion.True(pb.Equal(p.WriteSet, pvtRWSet))
  1544  		}
  1545  	}
  1546  }
  1547  
  1548  type testPeer struct {
  1549  	*mocks.GossipMock
  1550  	id            string
  1551  	gossipChannel chan *proto.GossipMessage
  1552  	commChannel   chan protoext.ReceivedMessage
  1553  	coord         *coordinatorMock
  1554  }
  1555  
  1556  func (t testPeer) Gossip() <-chan *proto.GossipMessage {
  1557  	return t.gossipChannel
  1558  }
  1559  
  1560  func (t testPeer) Comm() chan protoext.ReceivedMessage {
  1561  	return t.commChannel
  1562  }
  1563  
  1564  var peers = map[string]testPeer{
  1565  	"peer1": {
  1566  		id:            "peer1",
  1567  		gossipChannel: make(chan *proto.GossipMessage),
  1568  		commChannel:   make(chan protoext.ReceivedMessage),
  1569  		GossipMock:    &mocks.GossipMock{},
  1570  		coord:         new(coordinatorMock),
  1571  	},
  1572  	"peer2": {
  1573  		id:            "peer2",
  1574  		gossipChannel: make(chan *proto.GossipMessage),
  1575  		commChannel:   make(chan protoext.ReceivedMessage),
  1576  		GossipMock:    &mocks.GossipMock{},
  1577  		coord:         new(coordinatorMock),
  1578  	},
  1579  }
  1580  
  1581  func TestTransferOfPvtDataBetweenPeers(t *testing.T) {
  1582  	/*
  1583  	   This test covers pretty basic scenario, there are two peers: "peer1" and "peer2",
  1584  	   while peer2 missing a few blocks in the ledger therefore asking to replicate those
  1585  	   blocks from the first peers.
  1586  
  1587  	   Test going to check that block from one peer will be replicated into second one and
  1588  	   have identical content.
  1589  	*/
  1590  	chainID := "testChainID"
  1591  
  1592  	// Initialize peer
  1593  	for _, peer := range peers {
  1594  		peer.On("Accept", mock.Anything, false).Return(peer.Gossip(), nil)
  1595  
  1596  		peer.On("Accept", mock.Anything, true).
  1597  			Return(nil, peer.Comm()).
  1598  			Once().
  1599  			On("Accept", mock.Anything, true).
  1600  			Return(nil, make(chan protoext.ReceivedMessage))
  1601  
  1602  		peer.On("UpdateChannelMetadata", mock.Anything, mock.Anything)
  1603  		peer.coord.On("Close")
  1604  		peer.On("Close")
  1605  	}
  1606  
  1607  	// First peer going to have more advanced ledger
  1608  	peers["peer1"].coord.On("LedgerHeight", mock.Anything).Return(uint64(3), nil)
  1609  
  1610  	// Second peer has a gap of one block, hence it will have to replicate it from previous
  1611  	peers["peer2"].coord.On("LedgerHeight", mock.Anything).Return(uint64(2), nil)
  1612  
  1613  	peers["peer1"].coord.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
  1614  	peers["peer2"].coord.On("DoesPvtDataInfoExistInLedger", mock.Anything).Return(false, nil)
  1615  
  1616  	peers["peer1"].coord.On("GetPvtDataAndBlockByNum", uint64(2)).Return(&pcomm.Block{
  1617  		Header: &pcomm.BlockHeader{
  1618  			Number:       2,
  1619  			DataHash:     []byte{0, 0, 0, 1},
  1620  			PreviousHash: []byte{0, 1, 1, 1},
  1621  		},
  1622  		Data: &pcomm.BlockData{
  1623  			Data: [][]byte{{4}, {5}, {6}},
  1624  		},
  1625  	}, gutil.PvtDataCollections{&ledger.TxPvtData{
  1626  		SeqInBlock: uint64(1),
  1627  		WriteSet: &rwset.TxPvtReadWriteSet{
  1628  			DataModel: rwset.TxReadWriteSet_KV,
  1629  			NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1630  				{
  1631  					Namespace: "myCC:v1",
  1632  					CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
  1633  						{
  1634  							CollectionName: "mysecrectCollection",
  1635  							Rwset:          []byte{1, 2, 3, 4, 5},
  1636  						},
  1637  					},
  1638  				},
  1639  			},
  1640  		},
  1641  	}}, nil)
  1642  
  1643  	// Return membership of the peers
  1644  	member2 := discovery.NetworkMember{
  1645  		PKIid:            common.PKIidType([]byte{2}),
  1646  		Endpoint:         "peer2:7051",
  1647  		InternalEndpoint: "peer2:7051",
  1648  		Properties: &proto.Properties{
  1649  			LedgerHeight: 2,
  1650  		},
  1651  	}
  1652  
  1653  	member1 := discovery.NetworkMember{
  1654  		PKIid:            common.PKIidType([]byte{1}),
  1655  		Endpoint:         "peer1:7051",
  1656  		InternalEndpoint: "peer1:7051",
  1657  		Properties: &proto.Properties{
  1658  			LedgerHeight: 3,
  1659  		},
  1660  	}
  1661  
  1662  	peers["peer1"].On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{member2})
  1663  	peers["peer2"].On("PeersOfChannel", mock.Anything).Return([]discovery.NetworkMember{member1})
  1664  
  1665  	peers["peer2"].On("Send", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
  1666  		request := args.Get(0).(*proto.GossipMessage)
  1667  		requestMsg := new(receivedMessageMock)
  1668  		msg, _ := protoext.NoopSign(request)
  1669  		requestMsg.On("GetGossipMessage").Return(msg)
  1670  		requestMsg.On("GetConnectionInfo").Return(&protoext.ConnectionInfo{
  1671  			Auth: &protoext.AuthInfo{},
  1672  		})
  1673  
  1674  		requestMsg.On("Respond", mock.Anything).Run(func(args mock.Arguments) {
  1675  			response := args.Get(0).(*proto.GossipMessage)
  1676  			receivedMsg := new(receivedMessageMock)
  1677  			msg, _ := protoext.NoopSign(response)
  1678  			receivedMsg.On("GetGossipMessage").Return(msg)
  1679  			// Send response back to the peer
  1680  			peers["peer2"].commChannel <- receivedMsg
  1681  		})
  1682  
  1683  		peers["peer1"].commChannel <- requestMsg
  1684  	})
  1685  
  1686  	wg := sync.WaitGroup{}
  1687  	wg.Add(1)
  1688  	peers["peer2"].coord.On("StoreBlock", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
  1689  		wg.Done() // Done once second peer hits commit of the block
  1690  	}).Return([]string{}, nil) // No pvt data to complete and no error
  1691  
  1692  	cryptoService := &cryptoServiceMock{acceptor: noopPeerIdentityAcceptor}
  1693  
  1694  	stateMetrics := metrics.NewGossipMetrics(&disabled.Provider{}).StateMetrics
  1695  
  1696  	mediator := &ServicesMediator{GossipAdapter: peers["peer1"], MCSAdapter: cryptoService}
  1697  	stateConfig := &StateConfig{
  1698  		StateCheckInterval:   DefStateCheckInterval,
  1699  		StateResponseTimeout: DefStateResponseTimeout,
  1700  		StateBatchSize:       DefStateBatchSize,
  1701  		StateMaxRetries:      DefStateMaxRetries,
  1702  		StateBlockBufferSize: DefStateBlockBufferSize,
  1703  		StateChannelSize:     DefStateChannelSize,
  1704  		StateEnabled:         true,
  1705  	}
  1706  	logger := flogging.MustGetLogger(gutil.StateLogger)
  1707  	peer1State := NewGossipStateProvider(logger, chainID, mediator, peers["peer1"].coord, stateMetrics, blocking, stateConfig)
  1708  	defer peer1State.Stop()
  1709  
  1710  	mediator = &ServicesMediator{GossipAdapter: peers["peer2"], MCSAdapter: cryptoService}
  1711  	logger = flogging.MustGetLogger(gutil.StateLogger)
  1712  	peer2State := NewGossipStateProvider(logger, chainID, mediator, peers["peer2"].coord, stateMetrics, blocking, stateConfig)
  1713  	defer peer2State.Stop()
  1714  
  1715  	// Make sure state was replicated
  1716  	done := make(chan struct{})
  1717  	go func() {
  1718  		wg.Wait()
  1719  		done <- struct{}{}
  1720  	}()
  1721  
  1722  	select {
  1723  	case <-done:
  1724  		break
  1725  	case <-time.After(30 * time.Second):
  1726  		t.Fail()
  1727  	}
  1728  }
  1729  
  1730  func TestStateRequestValidator(t *testing.T) {
  1731  	validator := &stateRequestValidator{}
  1732  	err := validator.validate(&proto.RemoteStateRequest{
  1733  		StartSeqNum: 10,
  1734  		EndSeqNum:   5,
  1735  	}, defAntiEntropyBatchSize)
  1736  	assert.Contains(t, err.Error(), "Invalid sequence interval [10...5).")
  1737  	assert.Error(t, err)
  1738  
  1739  	err = validator.validate(&proto.RemoteStateRequest{
  1740  		StartSeqNum: 10,
  1741  		EndSeqNum:   30,
  1742  	}, defAntiEntropyBatchSize)
  1743  	assert.Contains(t, err.Error(), "Requesting blocks range [10-30) greater than configured")
  1744  	assert.Error(t, err)
  1745  
  1746  	err = validator.validate(&proto.RemoteStateRequest{
  1747  		StartSeqNum: 10,
  1748  		EndSeqNum:   20,
  1749  	}, defAntiEntropyBatchSize)
  1750  	assert.NoError(t, err)
  1751  }
  1752  
  1753  func waitUntilTrueOrTimeout(t *testing.T, predicate func() bool, timeout time.Duration) {
  1754  	ch := make(chan struct{})
  1755  	t.Log("Started to spin off, until predicate will be satisfied.")
  1756  
  1757  	go func() {
  1758  		t := time.NewTicker(time.Second)
  1759  		for !predicate() {
  1760  			select {
  1761  			case <-ch:
  1762  				t.Stop()
  1763  				return
  1764  			case <-t.C:
  1765  			}
  1766  		}
  1767  		t.Stop()
  1768  		close(ch)
  1769  	}()
  1770  
  1771  	select {
  1772  	case <-ch:
  1773  		t.Log("Done.")
  1774  		break
  1775  	case <-time.After(timeout):
  1776  		t.Fatal("Timeout has expired")
  1777  		close(ch)
  1778  		break
  1779  	}
  1780  	t.Log("Stop waiting until timeout or true")
  1781  }