github.com/lzy4123/fabric@v2.1.1+incompatible/gossip/privdata/pull_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package privdata
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/rand"
    12  	"io/ioutil"
    13  	"os"
    14  	"sync"
    15  	"testing"
    16  
    17  	pb "github.com/golang/protobuf/proto"
    18  	proto "github.com/hyperledger/fabric-protos-go/gossip"
    19  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    20  	"github.com/hyperledger/fabric-protos-go/peer"
    21  	"github.com/hyperledger/fabric/common/metrics/disabled"
    22  	"github.com/hyperledger/fabric/core/common/privdata"
    23  	"github.com/hyperledger/fabric/core/ledger"
    24  	"github.com/hyperledger/fabric/core/transientstore"
    25  	"github.com/hyperledger/fabric/gossip/api"
    26  	"github.com/hyperledger/fabric/gossip/comm"
    27  	"github.com/hyperledger/fabric/gossip/common"
    28  	"github.com/hyperledger/fabric/gossip/discovery"
    29  	"github.com/hyperledger/fabric/gossip/filter"
    30  	"github.com/hyperledger/fabric/gossip/metrics"
    31  	gmetricsmocks "github.com/hyperledger/fabric/gossip/metrics/mocks"
    32  	privdatacommon "github.com/hyperledger/fabric/gossip/privdata/common"
    33  	"github.com/hyperledger/fabric/gossip/privdata/mocks"
    34  	"github.com/hyperledger/fabric/gossip/protoext"
    35  	"github.com/hyperledger/fabric/gossip/util"
    36  	"github.com/hyperledger/fabric/protoutil"
    37  	"github.com/pkg/errors"
    38  	"github.com/stretchr/testify/assert"
    39  	"github.com/stretchr/testify/mock"
    40  )
    41  
    42  func init() {
    43  	policy2Filter = make(map[privdata.CollectionAccessPolicy]privdata.Filter)
    44  }
    45  
    46  // protoMatcher is used to test that a slice of protos equals another slice of protos.
    47  // This is needed because in general reflect.Equal(proto1, proto1) may not be true.
    48  func protoMatcher(pvds ...*proto.PvtDataDigest) func([]*proto.PvtDataDigest) bool {
    49  	return func(ipvds []*proto.PvtDataDigest) bool {
    50  		if len(pvds) != len(ipvds) {
    51  			return false
    52  		}
    53  
    54  		for i, pvd := range pvds {
    55  			if !pb.Equal(pvd, ipvds[i]) {
    56  				return false
    57  			}
    58  		}
    59  
    60  		return true
    61  	}
    62  }
    63  
    64  var policyLock sync.Mutex
    65  var policy2Filter map[privdata.CollectionAccessPolicy]privdata.Filter
    66  
    67  type mockCollectionStore struct {
    68  	m            map[string]*mockCollectionAccess
    69  	accessFilter privdata.Filter
    70  }
    71  
    72  func newCollectionStore() *mockCollectionStore {
    73  	return &mockCollectionStore{
    74  		m:            make(map[string]*mockCollectionAccess),
    75  		accessFilter: nil,
    76  	}
    77  }
    78  
    79  func (cs *mockCollectionStore) withPolicy(collection string, btl uint64) *mockCollectionAccess {
    80  	coll := &mockCollectionAccess{cs: cs, btl: btl}
    81  	cs.m[collection] = coll
    82  	return coll
    83  }
    84  
    85  func (cs *mockCollectionStore) withAccessFilter(filter privdata.Filter) *mockCollectionStore {
    86  	cs.accessFilter = filter
    87  	return cs
    88  }
    89  
    90  func (cs mockCollectionStore) RetrieveCollectionAccessPolicy(cc privdata.CollectionCriteria) (privdata.CollectionAccessPolicy, error) {
    91  	return cs.m[cc.Collection], nil
    92  }
    93  
    94  func (cs mockCollectionStore) RetrieveCollection(privdata.CollectionCriteria) (privdata.Collection, error) {
    95  	panic("implement me")
    96  }
    97  
    98  func (cs mockCollectionStore) RetrieveCollectionConfig(privdata.CollectionCriteria) (*peer.StaticCollectionConfig, error) {
    99  	panic("implement me")
   100  }
   101  
   102  func (cs mockCollectionStore) RetrieveCollectionConfigPackage(privdata.CollectionCriteria) (*peer.CollectionConfigPackage, error) {
   103  	panic("implement me")
   104  }
   105  
   106  func (cs mockCollectionStore) RetrieveCollectionPersistenceConfigs(cc privdata.CollectionCriteria) (privdata.CollectionPersistenceConfigs, error) {
   107  	return cs.m[cc.Collection], nil
   108  }
   109  
   110  func (cs mockCollectionStore) RetrieveReadWritePermission(cc privdata.CollectionCriteria, sp *peer.SignedProposal, qe ledger.QueryExecutor) (bool, bool, error) {
   111  	panic("implement me")
   112  }
   113  
   114  func (cs mockCollectionStore) AccessFilter(channelName string, collectionPolicyConfig *peer.CollectionPolicyConfig) (privdata.Filter, error) {
   115  	if cs.accessFilter != nil {
   116  		return cs.accessFilter, nil
   117  	}
   118  	panic("implement me")
   119  }
   120  
   121  type mockCollectionAccess struct {
   122  	cs  *mockCollectionStore
   123  	btl uint64
   124  }
   125  
   126  func (mc *mockCollectionAccess) BlockToLive() uint64 {
   127  	return mc.btl
   128  }
   129  
   130  func (mc *mockCollectionAccess) thatMapsTo(peers ...string) *mockCollectionStore {
   131  	policyLock.Lock()
   132  	defer policyLock.Unlock()
   133  	policy2Filter[mc] = func(sd protoutil.SignedData) bool {
   134  		for _, peer := range peers {
   135  			if bytes.Equal(sd.Identity, []byte(peer)) {
   136  				return true
   137  			}
   138  		}
   139  		return false
   140  	}
   141  	return mc.cs
   142  }
   143  
   144  func (mc *mockCollectionAccess) MemberOrgs() map[string]struct{} {
   145  	return nil
   146  }
   147  
   148  func (mc *mockCollectionAccess) AccessFilter() privdata.Filter {
   149  	policyLock.Lock()
   150  	defer policyLock.Unlock()
   151  	return policy2Filter[mc]
   152  }
   153  
   154  func (mc *mockCollectionAccess) RequiredPeerCount() int {
   155  	return 0
   156  }
   157  
   158  func (mc *mockCollectionAccess) MaximumPeerCount() int {
   159  	return 0
   160  }
   161  
   162  func (mc *mockCollectionAccess) IsMemberOnlyRead() bool {
   163  	return false
   164  }
   165  
   166  func (mc *mockCollectionAccess) IsMemberOnlyWrite() bool {
   167  	return false
   168  }
   169  
   170  type dataRetrieverMock struct {
   171  	mock.Mock
   172  }
   173  
   174  func (dr *dataRetrieverMock) CollectionRWSet(dig []*proto.PvtDataDigest, blockNum uint64) (Dig2PvtRWSetWithConfig, bool, error) {
   175  	args := dr.Called(dig, blockNum)
   176  	return args.Get(0).(Dig2PvtRWSetWithConfig), args.Bool(1), args.Error(2)
   177  }
   178  
   179  type receivedMsg struct {
   180  	responseChan chan protoext.ReceivedMessage
   181  	*comm.RemotePeer
   182  	*protoext.SignedGossipMessage
   183  }
   184  
   185  func (msg *receivedMsg) Ack(_ error) {
   186  
   187  }
   188  
   189  func (msg *receivedMsg) Respond(message *proto.GossipMessage) {
   190  	m, _ := protoext.NoopSign(message)
   191  	msg.responseChan <- &receivedMsg{SignedGossipMessage: m, RemotePeer: &comm.RemotePeer{}}
   192  }
   193  
   194  func (msg *receivedMsg) GetGossipMessage() *protoext.SignedGossipMessage {
   195  	return msg.SignedGossipMessage
   196  }
   197  
   198  func (msg *receivedMsg) GetSourceEnvelope() *proto.Envelope {
   199  	panic("implement me")
   200  }
   201  
   202  func (msg *receivedMsg) GetConnectionInfo() *protoext.ConnectionInfo {
   203  	return &protoext.ConnectionInfo{
   204  		Identity: api.PeerIdentityType(msg.RemotePeer.PKIID),
   205  		Auth: &protoext.AuthInfo{
   206  			SignedData: []byte{},
   207  			Signature:  []byte{},
   208  		},
   209  	}
   210  }
   211  
   212  type mockGossip struct {
   213  	mock.Mock
   214  	msgChan chan protoext.ReceivedMessage
   215  	id      *comm.RemotePeer
   216  	network *gossipNetwork
   217  }
   218  
   219  func newMockGossip(id *comm.RemotePeer) *mockGossip {
   220  	return &mockGossip{
   221  		msgChan: make(chan protoext.ReceivedMessage),
   222  		id:      id,
   223  	}
   224  }
   225  
   226  func (g *mockGossip) PeerFilter(channel common.ChannelID, messagePredicate api.SubChannelSelectionCriteria) (filter.RoutingFilter, error) {
   227  	for _, call := range g.Mock.ExpectedCalls {
   228  		if call.Method == "PeerFilter" {
   229  			args := g.Called(channel, messagePredicate)
   230  			if args.Get(1) != nil {
   231  				return nil, args.Get(1).(error)
   232  			}
   233  			return args.Get(0).(filter.RoutingFilter), nil
   234  		}
   235  	}
   236  	return func(member discovery.NetworkMember) bool {
   237  		return messagePredicate(api.PeerSignature{
   238  			PeerIdentity: api.PeerIdentityType(member.PKIid),
   239  		})
   240  	}, nil
   241  }
   242  
   243  func (g *mockGossip) Send(msg *proto.GossipMessage, peers ...*comm.RemotePeer) {
   244  	sMsg, _ := protoext.NoopSign(msg)
   245  	for _, peer := range g.network.peers {
   246  		if bytes.Equal(peer.id.PKIID, peers[0].PKIID) {
   247  			peer.msgChan <- &receivedMsg{
   248  				RemotePeer:          g.id,
   249  				SignedGossipMessage: sMsg,
   250  				responseChan:        g.msgChan,
   251  			}
   252  			return
   253  		}
   254  	}
   255  }
   256  
   257  func (g *mockGossip) PeersOfChannel(common.ChannelID) []discovery.NetworkMember {
   258  	return g.Called().Get(0).([]discovery.NetworkMember)
   259  }
   260  
   261  func (g *mockGossip) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan protoext.ReceivedMessage) {
   262  	return nil, g.msgChan
   263  }
   264  
   265  type peerData struct {
   266  	id           string
   267  	ledgerHeight uint64
   268  }
   269  
   270  func membership(knownPeers ...peerData) []discovery.NetworkMember {
   271  	var peers []discovery.NetworkMember
   272  	for _, peer := range knownPeers {
   273  		peers = append(peers, discovery.NetworkMember{
   274  			Endpoint: peer.id,
   275  			PKIid:    common.PKIidType(peer.id),
   276  			Properties: &proto.Properties{
   277  				LedgerHeight: peer.ledgerHeight,
   278  			},
   279  		})
   280  	}
   281  	return peers
   282  }
   283  
   284  type gossipNetwork struct {
   285  	peers []*mockGossip
   286  }
   287  
   288  func (gn *gossipNetwork) newPullerWithMetrics(metrics *metrics.PrivdataMetrics, id string, ps privdata.CollectionStore,
   289  	factory CollectionAccessFactory, knownMembers ...discovery.NetworkMember) *puller {
   290  	g := newMockGossip(&comm.RemotePeer{PKIID: common.PKIidType(id), Endpoint: id})
   291  	g.network = gn
   292  	g.On("PeersOfChannel", mock.Anything).Return(knownMembers)
   293  
   294  	p := NewPuller(metrics, ps, g, &dataRetrieverMock{}, factory, "A", 10)
   295  	gn.peers = append(gn.peers, g)
   296  	return p
   297  }
   298  
   299  func (gn *gossipNetwork) newPuller(id string, ps privdata.CollectionStore, factory CollectionAccessFactory,
   300  	knownMembers ...discovery.NetworkMember) *puller {
   301  	metrics := metrics.NewGossipMetrics(&disabled.Provider{}).PrivdataMetrics
   302  	return gn.newPullerWithMetrics(metrics, id, ps, factory, knownMembers...)
   303  }
   304  
   305  func newPRWSet() []util.PrivateRWSet {
   306  	b1 := make([]byte, 10)
   307  	b2 := make([]byte, 10)
   308  	rand.Read(b1)
   309  	rand.Read(b2)
   310  	return []util.PrivateRWSet{util.PrivateRWSet(b1), util.PrivateRWSet(b2)}
   311  }
   312  
   313  func TestPullerFromOnly1Peer(t *testing.T) {
   314  	t.Parallel()
   315  	// Scenario: p1 pulls from p2 and not from p3
   316  	// and succeeds - p1 asks from p2 (and not from p3!) for the
   317  	// expected digest
   318  	gn := &gossipNetwork{}
   319  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   320  	factoryMock1 := &mocks.CollectionAccessFactory{}
   321  	policyMock1 := &mocks.CollectionAccessPolicy{}
   322  	Setup(policyMock1, 1, 2, func(data protoutil.SignedData) bool {
   323  		return bytes.Equal(data.Identity, []byte("p2"))
   324  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   325  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock1, nil)
   326  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   327  
   328  	p2TransientStore := &util.PrivateRWSetWithConfig{
   329  		RWSet: newPRWSet(),
   330  		CollectionConfig: &peer.CollectionConfig{
   331  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   332  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   333  					Name: "col1",
   334  				},
   335  			},
   336  		},
   337  	}
   338  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
   339  	factoryMock2 := &mocks.CollectionAccessFactory{}
   340  	policyMock2 := &mocks.CollectionAccessPolicy{}
   341  	Setup(policyMock2, 1, 2, func(data protoutil.SignedData) bool {
   342  		return bytes.Equal(data.Identity, []byte("p1"))
   343  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   344  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock2, nil)
   345  
   346  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   347  	dig := &proto.PvtDataDigest{
   348  		TxId:       "txID1",
   349  		Collection: "col1",
   350  		Namespace:  "ns1",
   351  	}
   352  
   353  	store := Dig2PvtRWSetWithConfig{
   354  		privdatacommon.DigKey{
   355  			TxId:       "txID1",
   356  			Collection: "col1",
   357  			Namespace:  "ns1",
   358  		}: p2TransientStore,
   359  	}
   360  
   361  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   362  
   363  	factoryMock3 := &mocks.CollectionAccessFactory{}
   364  	policyMock3 := &mocks.CollectionAccessPolicy{}
   365  	Setup(policyMock3, 1, 2, func(data protoutil.SignedData) bool {
   366  		return false
   367  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   368  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock3, nil)
   369  
   370  	p3 := gn.newPuller("p3", newCollectionStore(), factoryMock3)
   371  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Run(func(_ mock.Arguments) {
   372  		t.Fatal("p3 shouldn't have been selected for pull")
   373  	})
   374  
   375  	dasf := &digestsAndSourceFactory{}
   376  
   377  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
   378  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   379  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   380  	fetched := []util.PrivateRWSet{rws1, rws2}
   381  	assert.NoError(t, err)
   382  	assert.Equal(t, p2TransientStore.RWSet, fetched)
   383  }
   384  
   385  func TestPullerDataNotAvailable(t *testing.T) {
   386  	t.Parallel()
   387  	// Scenario: p1 pulls from p2 and not from p3
   388  	// but the data in p2 doesn't exist
   389  	gn := &gossipNetwork{}
   390  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   391  	factoryMock := &mocks.CollectionAccessFactory{}
   392  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(&mocks.CollectionAccessPolicy{}, nil)
   393  
   394  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   395  
   396  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
   397  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   398  	dig := &proto.PvtDataDigest{
   399  		TxId:       "txID1",
   400  		Collection: "col1",
   401  		Namespace:  "ns1",
   402  	}
   403  
   404  	store := Dig2PvtRWSetWithConfig{
   405  		privdatacommon.DigKey{
   406  			TxId:       "txID1",
   407  			Collection: "col1",
   408  			Namespace:  "ns1",
   409  		}: &util.PrivateRWSetWithConfig{
   410  			RWSet: []util.PrivateRWSet{},
   411  		},
   412  	}
   413  
   414  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Return(store, true, nil)
   415  
   416  	p3 := gn.newPuller("p3", newCollectionStore(), factoryMock)
   417  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Run(func(_ mock.Arguments) {
   418  		t.Fatal("p3 shouldn't have been selected for pull")
   419  	})
   420  
   421  	dasf := &digestsAndSourceFactory{}
   422  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
   423  	assert.Empty(t, fetchedMessages.AvailableElements)
   424  	assert.NoError(t, err)
   425  }
   426  
   427  func TestPullerNoPeersKnown(t *testing.T) {
   428  	t.Parallel()
   429  	// Scenario: p1 doesn't know any peer and therefore fails fetching
   430  	gn := &gossipNetwork{}
   431  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2", "p3")
   432  	factoryMock := &mocks.CollectionAccessFactory{}
   433  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(&mocks.CollectionAccessPolicy{}, nil)
   434  
   435  	p1 := gn.newPuller("p1", policyStore, factoryMock)
   436  	dasf := &digestsAndSourceFactory{}
   437  	d2s := dasf.mapDigest(&privdatacommon.DigKey{Collection: "col1", TxId: "txID1", Namespace: "ns1"}).toSources().create()
   438  	fetchedMessages, err := p1.fetch(d2s)
   439  	assert.Empty(t, fetchedMessages)
   440  	assert.Error(t, err)
   441  	assert.Contains(t, err.Error(), "Empty membership")
   442  }
   443  
   444  func TestPullPeerFilterError(t *testing.T) {
   445  	t.Parallel()
   446  	// Scenario: p1 attempts to fetch for the wrong channel
   447  	gn := &gossipNetwork{}
   448  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   449  	factoryMock := &mocks.CollectionAccessFactory{}
   450  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(&mocks.CollectionAccessPolicy{}, nil)
   451  
   452  	p1 := gn.newPuller("p1", policyStore, factoryMock)
   453  	gn.peers[0].On("PeerFilter", mock.Anything, mock.Anything).Return(nil, errors.New("Failed obtaining filter"))
   454  	dasf := &digestsAndSourceFactory{}
   455  	d2s := dasf.mapDigest(&privdatacommon.DigKey{Collection: "col1", TxId: "txID1", Namespace: "ns1"}).toSources().create()
   456  	fetchedMessages, err := p1.fetch(d2s)
   457  	assert.Error(t, err)
   458  	assert.Contains(t, err.Error(), "Failed obtaining filter")
   459  	assert.Empty(t, fetchedMessages)
   460  }
   461  
   462  func TestPullerPeerNotEligible(t *testing.T) {
   463  	t.Parallel()
   464  	// Scenario: p1 pulls from p2 or from p3
   465  	// but it's not eligible for pulling data from p2 or from p3
   466  	gn := &gossipNetwork{}
   467  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2", "p3")
   468  	factoryMock1 := &mocks.CollectionAccessFactory{}
   469  	accessPolicyMock1 := &mocks.CollectionAccessPolicy{}
   470  	Setup(accessPolicyMock1, 1, 2, func(data protoutil.SignedData) bool {
   471  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p3"))
   472  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   473  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   474  
   475  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   476  
   477  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   478  	factoryMock2 := &mocks.CollectionAccessFactory{}
   479  	accessPolicyMock2 := &mocks.CollectionAccessPolicy{}
   480  	Setup(accessPolicyMock2, 1, 2, func(data protoutil.SignedData) bool {
   481  		return bytes.Equal(data.Identity, []byte("p2"))
   482  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   483  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock2, nil)
   484  
   485  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   486  
   487  	dig := &proto.PvtDataDigest{
   488  		TxId:       "txID1",
   489  		Collection: "col1",
   490  		Namespace:  "ns1",
   491  	}
   492  
   493  	store := Dig2PvtRWSetWithConfig{
   494  		privdatacommon.DigKey{
   495  			TxId:       "txID1",
   496  			Collection: "col1",
   497  			Namespace:  "ns1",
   498  		}: &util.PrivateRWSetWithConfig{
   499  			RWSet: newPRWSet(),
   500  			CollectionConfig: &peer.CollectionConfig{
   501  				Payload: &peer.CollectionConfig_StaticCollectionConfig{
   502  					StaticCollectionConfig: &peer.StaticCollectionConfig{
   503  						Name: "col1",
   504  					},
   505  				},
   506  			},
   507  		},
   508  	}
   509  
   510  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Return(store, true, nil)
   511  
   512  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p3")
   513  	factoryMock3 := &mocks.CollectionAccessFactory{}
   514  	accessPolicyMock3 := &mocks.CollectionAccessPolicy{}
   515  	Setup(accessPolicyMock3, 1, 2, func(data protoutil.SignedData) bool {
   516  		return bytes.Equal(data.Identity, []byte("p3"))
   517  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   518  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   519  
   520  	p3 := gn.newPuller("p3", policyStore, factoryMock3)
   521  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Return(store, true, nil)
   522  	dasf := &digestsAndSourceFactory{}
   523  	d2s := dasf.mapDigest(&privdatacommon.DigKey{Collection: "col1", TxId: "txID1", Namespace: "ns1"}).toSources().create()
   524  	fetchedMessages, err := p1.fetch(d2s)
   525  	assert.Empty(t, fetchedMessages.AvailableElements)
   526  	assert.NoError(t, err)
   527  }
   528  
   529  func TestPullerDifferentPeersDifferentCollections(t *testing.T) {
   530  	t.Parallel()
   531  	// Scenario: p1 pulls from p2 and from p3
   532  	// and each has different collections
   533  	gn := &gossipNetwork{}
   534  	factoryMock1 := &mocks.CollectionAccessFactory{}
   535  	accessPolicyMock1 := &mocks.CollectionAccessPolicy{}
   536  	Setup(accessPolicyMock1, 1, 2, func(data protoutil.SignedData) bool {
   537  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p3"))
   538  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   539  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   540  
   541  	policyStore := newCollectionStore().withPolicy("col2", uint64(100)).thatMapsTo("p2").withPolicy("col3", uint64(100)).thatMapsTo("p3")
   542  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   543  
   544  	p2TransientStore := &util.PrivateRWSetWithConfig{
   545  		RWSet: newPRWSet(),
   546  		CollectionConfig: &peer.CollectionConfig{
   547  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   548  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   549  					Name: "col2",
   550  				},
   551  			},
   552  		},
   553  	}
   554  
   555  	policyStore = newCollectionStore().withPolicy("col2", uint64(100)).thatMapsTo("p1")
   556  	factoryMock2 := &mocks.CollectionAccessFactory{}
   557  	accessPolicyMock2 := &mocks.CollectionAccessPolicy{}
   558  	Setup(accessPolicyMock2, 1, 2, func(data protoutil.SignedData) bool {
   559  		return bytes.Equal(data.Identity, []byte("p1"))
   560  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   561  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock2, nil)
   562  
   563  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   564  	dig1 := &proto.PvtDataDigest{
   565  		TxId:       "txID1",
   566  		Collection: "col2",
   567  		Namespace:  "ns1",
   568  	}
   569  
   570  	store1 := Dig2PvtRWSetWithConfig{
   571  		privdatacommon.DigKey{
   572  			TxId:       "txID1",
   573  			Collection: "col2",
   574  			Namespace:  "ns1",
   575  		}: p2TransientStore,
   576  	}
   577  
   578  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), mock.Anything).Return(store1, true, nil)
   579  
   580  	p3TransientStore := &util.PrivateRWSetWithConfig{
   581  		RWSet: newPRWSet(),
   582  		CollectionConfig: &peer.CollectionConfig{
   583  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   584  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   585  					Name: "col3",
   586  				},
   587  			},
   588  		},
   589  	}
   590  
   591  	store2 := Dig2PvtRWSetWithConfig{
   592  		privdatacommon.DigKey{
   593  			TxId:       "txID1",
   594  			Collection: "col3",
   595  			Namespace:  "ns1",
   596  		}: p3TransientStore,
   597  	}
   598  	policyStore = newCollectionStore().withPolicy("col3", uint64(100)).thatMapsTo("p1")
   599  	factoryMock3 := &mocks.CollectionAccessFactory{}
   600  	accessPolicyMock3 := &mocks.CollectionAccessPolicy{}
   601  	Setup(accessPolicyMock3, 1, 2, func(data protoutil.SignedData) bool {
   602  		return bytes.Equal(data.Identity, []byte("p1"))
   603  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   604  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock3, nil)
   605  
   606  	p3 := gn.newPuller("p3", policyStore, factoryMock3)
   607  	dig2 := &proto.PvtDataDigest{
   608  		TxId:       "txID1",
   609  		Collection: "col3",
   610  		Namespace:  "ns1",
   611  	}
   612  
   613  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), mock.Anything).Return(store2, true, nil)
   614  
   615  	dasf := &digestsAndSourceFactory{}
   616  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig1)).toSources().mapDigest(toDigKey(dig2)).toSources().create())
   617  	assert.NoError(t, err)
   618  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   619  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   620  	rws3 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[0])
   621  	rws4 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[1])
   622  	fetched := []util.PrivateRWSet{rws1, rws2, rws3, rws4}
   623  	assert.Contains(t, fetched, p2TransientStore.RWSet[0])
   624  	assert.Contains(t, fetched, p2TransientStore.RWSet[1])
   625  	assert.Contains(t, fetched, p3TransientStore.RWSet[0])
   626  	assert.Contains(t, fetched, p3TransientStore.RWSet[1])
   627  }
   628  
   629  func TestPullerRetries(t *testing.T) {
   630  	t.Parallel()
   631  	// Scenario: p1 pulls from p2, p3, p4 and p5.
   632  	// Only p3 considers p1 to be eligible to receive the data.
   633  	// The rest consider p1 as not eligible.
   634  	gn := &gossipNetwork{}
   635  	factoryMock1 := &mocks.CollectionAccessFactory{}
   636  	accessPolicyMock1 := &mocks.CollectionAccessPolicy{}
   637  	Setup(accessPolicyMock1, 1, 2, func(data protoutil.SignedData) bool {
   638  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p3")) ||
   639  			bytes.Equal(data.Identity, []byte("p4")) ||
   640  			bytes.Equal(data.Identity, []byte("p5"))
   641  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   642  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   643  
   644  	// p1
   645  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2", "p3", "p4", "p5")
   646  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)},
   647  		peerData{"p3", uint64(1)}, peerData{"p4", uint64(1)}, peerData{"p5", uint64(1)})...)
   648  
   649  	// p2, p3, p4, and p5 have the same transient store
   650  	transientStore := &util.PrivateRWSetWithConfig{
   651  		RWSet: newPRWSet(),
   652  		CollectionConfig: &peer.CollectionConfig{
   653  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   654  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   655  					Name: "col1",
   656  				},
   657  			},
   658  		},
   659  	}
   660  
   661  	dig := &proto.PvtDataDigest{
   662  		TxId:       "txID1",
   663  		Collection: "col1",
   664  		Namespace:  "ns1",
   665  	}
   666  
   667  	store := Dig2PvtRWSetWithConfig{
   668  		privdatacommon.DigKey{
   669  			TxId:       "txID1",
   670  			Collection: "col1",
   671  			Namespace:  "ns1",
   672  		}: transientStore,
   673  	}
   674  
   675  	// p2
   676  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   677  	factoryMock2 := &mocks.CollectionAccessFactory{}
   678  	accessPolicyMock2 := &mocks.CollectionAccessPolicy{}
   679  	Setup(accessPolicyMock2, 1, 2, func(data protoutil.SignedData) bool {
   680  		return bytes.Equal(data.Identity, []byte("p2"))
   681  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   682  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock2, nil)
   683  
   684  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   685  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   686  
   687  	// p3
   688  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
   689  	factoryMock3 := &mocks.CollectionAccessFactory{}
   690  	accessPolicyMock3 := &mocks.CollectionAccessPolicy{}
   691  	Setup(accessPolicyMock3, 1, 2, func(data protoutil.SignedData) bool {
   692  		return bytes.Equal(data.Identity, []byte("p1"))
   693  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   694  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock3, nil)
   695  
   696  	p3 := gn.newPuller("p3", policyStore, factoryMock3)
   697  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   698  
   699  	// p4
   700  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p4")
   701  	factoryMock4 := &mocks.CollectionAccessFactory{}
   702  	accessPolicyMock4 := &mocks.CollectionAccessPolicy{}
   703  	Setup(accessPolicyMock4, 1, 2, func(data protoutil.SignedData) bool {
   704  		return bytes.Equal(data.Identity, []byte("p4"))
   705  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   706  	factoryMock4.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock4, nil)
   707  
   708  	p4 := gn.newPuller("p4", policyStore, factoryMock4)
   709  	p4.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   710  
   711  	// p5
   712  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p5")
   713  	factoryMock5 := &mocks.CollectionAccessFactory{}
   714  	accessPolicyMock5 := &mocks.CollectionAccessPolicy{}
   715  	Setup(accessPolicyMock5, 1, 2, func(data protoutil.SignedData) bool {
   716  		return bytes.Equal(data.Identity, []byte("p5"))
   717  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   718  	factoryMock5.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock5, nil)
   719  
   720  	p5 := gn.newPuller("p5", policyStore, factoryMock5)
   721  	p5.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   722  
   723  	// Fetch from someone
   724  	dasf := &digestsAndSourceFactory{}
   725  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
   726  	assert.NoError(t, err)
   727  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   728  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   729  	fetched := []util.PrivateRWSet{rws1, rws2}
   730  	assert.NoError(t, err)
   731  	assert.Equal(t, transientStore.RWSet, fetched)
   732  }
   733  
   734  func TestPullerPreferEndorsers(t *testing.T) {
   735  	t.Parallel()
   736  	// Scenario: p1 pulls from p2, p3, p4, p5
   737  	// and the only endorser for col1 is p3, so it should be selected
   738  	// at the top priority for col1.
   739  	// for col2, only p2 should have the data, but its not an endorser of the data.
   740  	gn := &gossipNetwork{}
   741  	factoryMock := &mocks.CollectionAccessFactory{}
   742  	accessPolicyMock := &mocks.CollectionAccessPolicy{}
   743  	Setup(accessPolicyMock, 1, 2, func(data protoutil.SignedData) bool {
   744  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p1"))
   745  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   746  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock, nil)
   747  
   748  	policyStore := newCollectionStore().
   749  		withPolicy("col1", uint64(100)).
   750  		thatMapsTo("p1", "p2", "p3", "p4", "p5").
   751  		withPolicy("col2", uint64(100)).
   752  		thatMapsTo("p1", "p2")
   753  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)},
   754  		peerData{"p3", uint64(1)}, peerData{"p4", uint64(1)}, peerData{"p5", uint64(1)})...)
   755  
   756  	p3TransientStore := &util.PrivateRWSetWithConfig{
   757  		RWSet: newPRWSet(),
   758  		CollectionConfig: &peer.CollectionConfig{
   759  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   760  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   761  					Name: "col2",
   762  				},
   763  			},
   764  		},
   765  	}
   766  
   767  	p2TransientStore := &util.PrivateRWSetWithConfig{
   768  		RWSet: newPRWSet(),
   769  		CollectionConfig: &peer.CollectionConfig{
   770  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   771  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   772  					Name: "col2",
   773  				},
   774  			},
   775  		},
   776  	}
   777  
   778  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   779  	p3 := gn.newPuller("p3", policyStore, factoryMock)
   780  	gn.newPuller("p4", policyStore, factoryMock)
   781  	gn.newPuller("p5", policyStore, factoryMock)
   782  
   783  	dig1 := &proto.PvtDataDigest{
   784  		TxId:       "txID1",
   785  		Collection: "col1",
   786  		Namespace:  "ns1",
   787  	}
   788  
   789  	dig2 := &proto.PvtDataDigest{
   790  		TxId:       "txID1",
   791  		Collection: "col2",
   792  		Namespace:  "ns1",
   793  	}
   794  
   795  	store := Dig2PvtRWSetWithConfig{
   796  		privdatacommon.DigKey{
   797  			TxId:       "txID1",
   798  			Collection: "col1",
   799  			Namespace:  "ns1",
   800  		}: p3TransientStore,
   801  		privdatacommon.DigKey{
   802  			TxId:       "txID1",
   803  			Collection: "col2",
   804  			Namespace:  "ns1",
   805  		}: p2TransientStore,
   806  	}
   807  
   808  	// We only define an action for dig2 on p2, and the test would fail with panic if any other peer is asked for
   809  	// a private RWSet on dig2
   810  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil)
   811  
   812  	// We only define an action for dig1 on p3, and the test would fail with panic if any other peer is asked for
   813  	// a private RWSet on dig1
   814  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), uint64(0)).Return(store, true, nil)
   815  
   816  	dasf := &digestsAndSourceFactory{}
   817  	d2s := dasf.mapDigest(toDigKey(dig1)).toSources("p3").mapDigest(toDigKey(dig2)).toSources().create()
   818  	fetchedMessages, err := p1.fetch(d2s)
   819  	assert.NoError(t, err)
   820  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   821  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   822  	rws3 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[0])
   823  	rws4 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[1])
   824  	fetched := []util.PrivateRWSet{rws1, rws2, rws3, rws4}
   825  	assert.Contains(t, fetched, p3TransientStore.RWSet[0])
   826  	assert.Contains(t, fetched, p3TransientStore.RWSet[1])
   827  	assert.Contains(t, fetched, p2TransientStore.RWSet[0])
   828  	assert.Contains(t, fetched, p2TransientStore.RWSet[1])
   829  }
   830  
   831  func TestPullerFetchReconciledItemsPreferPeersFromOriginalConfig(t *testing.T) {
   832  	t.Parallel()
   833  	// Scenario: p1 pulls from p2, p3, p4, p5
   834  	// the only peer that was in the collection config while data was created for col1 is p3, so it should be selected
   835  	// at the top priority for col1.
   836  	// for col2, p3 was in the collection config while the data was created but was removed from collection and now only p2 should have the data.
   837  	// so obviously p2 should be selected for col2.
   838  	gn := &gossipNetwork{}
   839  	factoryMock := &mocks.CollectionAccessFactory{}
   840  	accessPolicyMock := &mocks.CollectionAccessPolicy{}
   841  	Setup(accessPolicyMock, 1, 2, func(data protoutil.SignedData) bool {
   842  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p1"))
   843  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   844  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock, nil)
   845  
   846  	policyStore := newCollectionStore().
   847  		withPolicy("col1", uint64(100)).
   848  		thatMapsTo("p1", "p2", "p3", "p4", "p5").
   849  		withPolicy("col2", uint64(100)).
   850  		thatMapsTo("p1", "p2").
   851  		withAccessFilter(func(data protoutil.SignedData) bool {
   852  			return bytes.Equal(data.Identity, []byte("p3"))
   853  		})
   854  
   855  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)},
   856  		peerData{"p3", uint64(1)}, peerData{"p4", uint64(1)}, peerData{"p5", uint64(1)})...)
   857  
   858  	p3TransientStore := &util.PrivateRWSetWithConfig{
   859  		RWSet: newPRWSet(),
   860  		CollectionConfig: &peer.CollectionConfig{
   861  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   862  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   863  					Name: "col2",
   864  				},
   865  			},
   866  		},
   867  	}
   868  
   869  	p2TransientStore := &util.PrivateRWSetWithConfig{
   870  		RWSet: newPRWSet(),
   871  		CollectionConfig: &peer.CollectionConfig{
   872  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   873  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   874  					Name: "col2",
   875  				},
   876  			},
   877  		},
   878  	}
   879  
   880  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   881  	p3 := gn.newPuller("p3", policyStore, factoryMock)
   882  	gn.newPuller("p4", policyStore, factoryMock)
   883  	gn.newPuller("p5", policyStore, factoryMock)
   884  
   885  	dig1 := &proto.PvtDataDigest{
   886  		TxId:       "txID1",
   887  		Collection: "col1",
   888  		Namespace:  "ns1",
   889  	}
   890  
   891  	dig2 := &proto.PvtDataDigest{
   892  		TxId:       "txID1",
   893  		Collection: "col2",
   894  		Namespace:  "ns1",
   895  	}
   896  
   897  	store := Dig2PvtRWSetWithConfig{
   898  		privdatacommon.DigKey{
   899  			TxId:       "txID1",
   900  			Collection: "col1",
   901  			Namespace:  "ns1",
   902  		}: p3TransientStore,
   903  		privdatacommon.DigKey{
   904  			TxId:       "txID1",
   905  			Collection: "col2",
   906  			Namespace:  "ns1",
   907  		}: p2TransientStore,
   908  	}
   909  
   910  	// We only define an action for dig2 on p2, and the test would fail with panic if any other peer is asked for
   911  	// a private RWSet on dig2
   912  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil)
   913  
   914  	// We only define an action for dig1 on p3, and the test would fail with panic if any other peer is asked for
   915  	// a private RWSet on dig1
   916  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), uint64(0)).Return(store, true, nil)
   917  
   918  	d2cc := privdatacommon.Dig2CollectionConfig{
   919  		privdatacommon.DigKey{
   920  			TxId:       "txID1",
   921  			Collection: "col1",
   922  			Namespace:  "ns1",
   923  		}: &peer.StaticCollectionConfig{
   924  			Name: "col1",
   925  		},
   926  		privdatacommon.DigKey{
   927  			TxId:       "txID1",
   928  			Collection: "col2",
   929  			Namespace:  "ns1",
   930  		}: &peer.StaticCollectionConfig{
   931  			Name: "col2",
   932  		},
   933  	}
   934  
   935  	fetchedMessages, err := p1.FetchReconciledItems(d2cc)
   936  	assert.NoError(t, err)
   937  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   938  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   939  	rws3 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[0])
   940  	rws4 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[1])
   941  	fetched := []util.PrivateRWSet{rws1, rws2, rws3, rws4}
   942  	assert.Contains(t, fetched, p3TransientStore.RWSet[0])
   943  	assert.Contains(t, fetched, p3TransientStore.RWSet[1])
   944  	assert.Contains(t, fetched, p2TransientStore.RWSet[0])
   945  	assert.Contains(t, fetched, p2TransientStore.RWSet[1])
   946  }
   947  
   948  func TestPullerAvoidPullingPurgedData(t *testing.T) {
   949  	// Scenario: p1 missing private data for col1
   950  	// p2 and p3 is suppose to have it, while p3 has more advanced
   951  	// ledger and based on BTL already purged data for, so p1
   952  	// suppose to fetch data only from p2
   953  
   954  	t.Parallel()
   955  	gn := &gossipNetwork{}
   956  	factoryMock := &mocks.CollectionAccessFactory{}
   957  	accessPolicyMock := &mocks.CollectionAccessPolicy{}
   958  	Setup(accessPolicyMock, 1, 2, func(data protoutil.SignedData) bool {
   959  		return bytes.Equal(data.Identity, []byte("p1"))
   960  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   961  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock, nil)
   962  
   963  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1", "p2", "p3").
   964  		withPolicy("col2", uint64(1000)).thatMapsTo("p1", "p2", "p3")
   965  
   966  	// p2 is at ledger height 1, while p2 is at 111 which is beyond BTL defined for col1 (100)
   967  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)},
   968  		peerData{"p3", uint64(111)})...)
   969  
   970  	privateData1 := &util.PrivateRWSetWithConfig{
   971  		RWSet: newPRWSet(),
   972  		CollectionConfig: &peer.CollectionConfig{
   973  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   974  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   975  					Name: "col1",
   976  				},
   977  			},
   978  		},
   979  	}
   980  	privateData2 := &util.PrivateRWSetWithConfig{
   981  		RWSet: newPRWSet(),
   982  		CollectionConfig: &peer.CollectionConfig{
   983  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   984  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   985  					Name: "col2",
   986  				},
   987  			},
   988  		},
   989  	}
   990  
   991  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   992  	p3 := gn.newPuller("p3", policyStore, factoryMock)
   993  
   994  	dig1 := &proto.PvtDataDigest{
   995  		TxId:       "txID1",
   996  		Collection: "col1",
   997  		Namespace:  "ns1",
   998  	}
   999  
  1000  	dig2 := &proto.PvtDataDigest{
  1001  		TxId:       "txID1",
  1002  		Collection: "col2",
  1003  		Namespace:  "ns1",
  1004  	}
  1005  
  1006  	store := Dig2PvtRWSetWithConfig{
  1007  		privdatacommon.DigKey{
  1008  			TxId:       "txID1",
  1009  			Collection: "col1",
  1010  			Namespace:  "ns1",
  1011  		}: privateData1,
  1012  		privdatacommon.DigKey{
  1013  			TxId:       "txID1",
  1014  			Collection: "col2",
  1015  			Namespace:  "ns1",
  1016  		}: privateData2,
  1017  	}
  1018  
  1019  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), 0).Return(store, true, nil)
  1020  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), 0).Return(store, true, nil).
  1021  		Run(
  1022  			func(arg mock.Arguments) {
  1023  				assert.Fail(t, "we should not fetch private data from peers where it was purged")
  1024  			},
  1025  		)
  1026  
  1027  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil)
  1028  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil).
  1029  		Run(
  1030  			func(mock.Arguments) {
  1031  				assert.Fail(t, "we should not fetch private data of collection2 from peer 2")
  1032  
  1033  			},
  1034  		)
  1035  
  1036  	dasf := &digestsAndSourceFactory{}
  1037  	d2s := dasf.mapDigest(toDigKey(dig1)).toSources("p3", "p2").mapDigest(toDigKey(dig2)).toSources("p3").create()
  1038  	// trying to fetch missing pvt data for block seq 1
  1039  	fetchedMessages, err := p1.fetch(d2s)
  1040  
  1041  	assert.NoError(t, err)
  1042  	assert.Equal(t, 1, len(fetchedMessages.PurgedElements))
  1043  	assert.Equal(t, dig1, fetchedMessages.PurgedElements[0])
  1044  	p3.PrivateDataRetriever.(*dataRetrieverMock).AssertNumberOfCalls(t, "CollectionRWSet", 1)
  1045  
  1046  }
  1047  
  1048  type counterDataRetreiver struct {
  1049  	numberOfCalls int
  1050  	PrivateDataRetriever
  1051  }
  1052  
  1053  func (c *counterDataRetreiver) CollectionRWSet(dig []*proto.PvtDataDigest, blockNum uint64) (Dig2PvtRWSetWithConfig, bool, error) {
  1054  	c.numberOfCalls += 1
  1055  	return c.PrivateDataRetriever.CollectionRWSet(dig, blockNum)
  1056  }
  1057  
  1058  func (c *counterDataRetreiver) getNumberOfCalls() int {
  1059  	return c.numberOfCalls
  1060  }
  1061  
  1062  func TestPullerIntegratedWithDataRetreiver(t *testing.T) {
  1063  	t.Parallel()
  1064  	gn := &gossipNetwork{}
  1065  
  1066  	ns1, ns2 := "testChaincodeName1", "testChaincodeName2"
  1067  	col1, col2 := "testCollectionName1", "testCollectionName2"
  1068  
  1069  	ap := &mocks.CollectionAccessPolicy{}
  1070  	Setup(ap, 1, 2, func(data protoutil.SignedData) bool {
  1071  		return bytes.Equal(data.Identity, []byte("p1"))
  1072  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
  1073  
  1074  	factoryMock := &mocks.CollectionAccessFactory{}
  1075  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(ap, nil)
  1076  
  1077  	policyStore := newCollectionStore().withPolicy(col1, uint64(1000)).thatMapsTo("p1", "p2").
  1078  		withPolicy(col2, uint64(1000)).thatMapsTo("p1", "p2")
  1079  
  1080  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(10)})...)
  1081  	p2 := gn.newPuller("p2", policyStore, factoryMock, membership(peerData{"p1", uint64(1)})...)
  1082  
  1083  	committer := &mocks.Committer{}
  1084  	tempdir, err := ioutil.TempDir("", "ts")
  1085  	if err != nil {
  1086  		t.Fatalf("Failed to create test directory, got err %s", err)
  1087  		return
  1088  	}
  1089  	storeProvider, err := transientstore.NewStoreProvider(tempdir)
  1090  	if err != nil {
  1091  		t.Fatalf("Failed to open store, got err %s", err)
  1092  		return
  1093  	}
  1094  	store, err := storeProvider.OpenStore("test")
  1095  	if err != nil {
  1096  		t.Fatalf("Failed to open store, got err %s", err)
  1097  		return
  1098  	}
  1099  	defer storeProvider.Close()
  1100  	defer os.RemoveAll(tempdir)
  1101  	result := []*ledger.TxPvtData{
  1102  		{
  1103  			WriteSet: &rwset.TxPvtReadWriteSet{
  1104  				DataModel: rwset.TxReadWriteSet_KV,
  1105  				NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1106  					pvtReadWriteSet(ns1, col1, []byte{1}),
  1107  					pvtReadWriteSet(ns1, col1, []byte{2}),
  1108  				},
  1109  			},
  1110  			SeqInBlock: 1,
  1111  		},
  1112  		{
  1113  			WriteSet: &rwset.TxPvtReadWriteSet{
  1114  				DataModel: rwset.TxReadWriteSet_KV,
  1115  				NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1116  					pvtReadWriteSet(ns2, col2, []byte{3}),
  1117  					pvtReadWriteSet(ns2, col2, []byte{4}),
  1118  				},
  1119  			},
  1120  			SeqInBlock: 2,
  1121  		},
  1122  	}
  1123  
  1124  	committer.On("LedgerHeight").Return(uint64(10), nil)
  1125  	committer.On("GetPvtDataByNum", uint64(5), mock.Anything).Return(result, nil)
  1126  	historyRetreiver := &mocks.ConfigHistoryRetriever{}
  1127  	historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, ns1).Return(newCollectionConfig(col1), nil)
  1128  	historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, ns2).Return(newCollectionConfig(col2), nil)
  1129  	committer.On("GetConfigHistoryRetriever").Return(historyRetreiver, nil)
  1130  
  1131  	dataRetreiver := &counterDataRetreiver{PrivateDataRetriever: NewDataRetriever(store, committer), numberOfCalls: 0}
  1132  	p2.PrivateDataRetriever = dataRetreiver
  1133  
  1134  	dig1 := &privdatacommon.DigKey{
  1135  		TxId:       "txID1",
  1136  		Collection: col1,
  1137  		Namespace:  ns1,
  1138  		BlockSeq:   5,
  1139  		SeqInBlock: 1,
  1140  	}
  1141  
  1142  	dig2 := &privdatacommon.DigKey{
  1143  		TxId:       "txID1",
  1144  		Collection: col2,
  1145  		Namespace:  ns2,
  1146  		BlockSeq:   5,
  1147  		SeqInBlock: 2,
  1148  	}
  1149  
  1150  	dasf := &digestsAndSourceFactory{}
  1151  	d2s := dasf.mapDigest(dig1).toSources("p2").mapDigest(dig2).toSources("p2").create()
  1152  	fetchedMessages, err := p1.fetch(d2s)
  1153  	assert.NoError(t, err)
  1154  	assert.Equal(t, 2, len(fetchedMessages.AvailableElements))
  1155  	assert.Equal(t, 1, dataRetreiver.getNumberOfCalls())
  1156  	assert.Equal(t, 2, len(fetchedMessages.AvailableElements[0].Payload))
  1157  	assert.Equal(t, 2, len(fetchedMessages.AvailableElements[1].Payload))
  1158  }
  1159  
  1160  func toDigKey(dig *proto.PvtDataDigest) *privdatacommon.DigKey {
  1161  	return &privdatacommon.DigKey{
  1162  		TxId:       dig.TxId,
  1163  		BlockSeq:   dig.BlockSeq,
  1164  		SeqInBlock: dig.SeqInBlock,
  1165  		Namespace:  dig.Namespace,
  1166  		Collection: dig.Collection,
  1167  	}
  1168  }
  1169  
  1170  func TestPullerMetrics(t *testing.T) {
  1171  	t.Parallel()
  1172  	// Scenario: p1 pulls from p2 and sends metric reports
  1173  	gn := &gossipNetwork{}
  1174  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
  1175  	factoryMock1 := &mocks.CollectionAccessFactory{}
  1176  	policyMock1 := &mocks.CollectionAccessPolicy{}
  1177  	Setup(policyMock1, 1, 2, func(data protoutil.SignedData) bool {
  1178  		return bytes.Equal(data.Identity, []byte("p2"))
  1179  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
  1180  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock1, nil)
  1181  
  1182  	testMetricProvider := gmetricsmocks.TestUtilConstructMetricProvider()
  1183  	metrics := metrics.NewGossipMetrics(testMetricProvider.FakeProvider).PrivdataMetrics
  1184  
  1185  	p1 := gn.newPullerWithMetrics(metrics, "p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)})...)
  1186  
  1187  	p2TransientStore := &util.PrivateRWSetWithConfig{
  1188  		RWSet: newPRWSet(),
  1189  		CollectionConfig: &peer.CollectionConfig{
  1190  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
  1191  				StaticCollectionConfig: &peer.StaticCollectionConfig{
  1192  					Name: "col1",
  1193  				},
  1194  			},
  1195  		},
  1196  	}
  1197  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
  1198  	factoryMock2 := &mocks.CollectionAccessFactory{}
  1199  	policyMock2 := &mocks.CollectionAccessPolicy{}
  1200  	Setup(policyMock2, 1, 2, func(data protoutil.SignedData) bool {
  1201  		return bytes.Equal(data.Identity, []byte("p1"))
  1202  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
  1203  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock2, nil)
  1204  
  1205  	p2 := gn.newPullerWithMetrics(metrics, "p2", policyStore, factoryMock2)
  1206  
  1207  	dig := &proto.PvtDataDigest{
  1208  		TxId:       "txID1",
  1209  		Collection: "col1",
  1210  		Namespace:  "ns1",
  1211  	}
  1212  
  1213  	store := Dig2PvtRWSetWithConfig{
  1214  		privdatacommon.DigKey{
  1215  			TxId:       "txID1",
  1216  			Collection: "col1",
  1217  			Namespace:  "ns1",
  1218  		}: p2TransientStore,
  1219  	}
  1220  
  1221  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)),
  1222  		uint64(0)).Return(store, true, nil)
  1223  
  1224  	dasf := &digestsAndSourceFactory{}
  1225  
  1226  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
  1227  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
  1228  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
  1229  	fetched := []util.PrivateRWSet{rws1, rws2}
  1230  	assert.NoError(t, err)
  1231  	assert.Equal(t, p2TransientStore.RWSet, fetched)
  1232  
  1233  	assert.Equal(t,
  1234  		[]string{"channel", "A"},
  1235  		testMetricProvider.FakePullDuration.WithArgsForCall(0),
  1236  	)
  1237  	assert.True(t, testMetricProvider.FakePullDuration.ObserveArgsForCall(0) > 0)
  1238  	assert.Equal(t,
  1239  		[]string{"channel", "A"},
  1240  		testMetricProvider.FakeRetrieveDuration.WithArgsForCall(0),
  1241  	)
  1242  	assert.True(t, testMetricProvider.FakeRetrieveDuration.ObserveArgsForCall(0) > 0)
  1243  }