github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/fabric/common/metrics/disabled"
    22  	"github.com/osdi23p228/fabric/core/common/privdata"
    23  	"github.com/osdi23p228/fabric/core/ledger"
    24  	"github.com/osdi23p228/fabric/core/transientstore"
    25  	"github.com/osdi23p228/fabric/gossip/api"
    26  	"github.com/osdi23p228/fabric/gossip/comm"
    27  	"github.com/osdi23p228/fabric/gossip/common"
    28  	"github.com/osdi23p228/fabric/gossip/discovery"
    29  	"github.com/osdi23p228/fabric/gossip/filter"
    30  	"github.com/osdi23p228/fabric/gossip/metrics"
    31  	gmetricsmocks "github.com/osdi23p228/fabric/gossip/metrics/mocks"
    32  	privdatacommon "github.com/osdi23p228/fabric/gossip/privdata/common"
    33  	"github.com/osdi23p228/fabric/gossip/privdata/mocks"
    34  	"github.com/osdi23p228/fabric/gossip/protoext"
    35  	"github.com/osdi23p228/fabric/gossip/util"
    36  	"github.com/osdi23p228/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  	// Scenario: p1 pulls from p2 and not from p3
   315  	// and succeeds - p1 asks from p2 (and not from p3!) for the
   316  	// expected digest
   317  	gn := &gossipNetwork{}
   318  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   319  	factoryMock1 := &mocks.CollectionAccessFactory{}
   320  	policyMock1 := &mocks.CollectionAccessPolicy{}
   321  	Setup(policyMock1, 1, 2, func(data protoutil.SignedData) bool {
   322  		return bytes.Equal(data.Identity, []byte("p2"))
   323  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   324  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock1, nil)
   325  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   326  
   327  	p2TransientStore := &util.PrivateRWSetWithConfig{
   328  		RWSet: newPRWSet(),
   329  		CollectionConfig: &peer.CollectionConfig{
   330  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   331  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   332  					Name: "col1",
   333  				},
   334  			},
   335  		},
   336  	}
   337  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
   338  	factoryMock2 := &mocks.CollectionAccessFactory{}
   339  	policyMock2 := &mocks.CollectionAccessPolicy{}
   340  	Setup(policyMock2, 1, 2, func(data protoutil.SignedData) bool {
   341  		return bytes.Equal(data.Identity, []byte("p1"))
   342  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   343  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock2, nil)
   344  
   345  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   346  	dig := &proto.PvtDataDigest{
   347  		TxId:       "txID1",
   348  		Collection: "col1",
   349  		Namespace:  "ns1",
   350  	}
   351  
   352  	store := Dig2PvtRWSetWithConfig{
   353  		privdatacommon.DigKey{
   354  			TxId:       "txID1",
   355  			Collection: "col1",
   356  			Namespace:  "ns1",
   357  		}: p2TransientStore,
   358  	}
   359  
   360  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   361  
   362  	factoryMock3 := &mocks.CollectionAccessFactory{}
   363  	policyMock3 := &mocks.CollectionAccessPolicy{}
   364  	Setup(policyMock3, 1, 2, func(data protoutil.SignedData) bool {
   365  		return false
   366  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   367  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock3, nil)
   368  
   369  	p3 := gn.newPuller("p3", newCollectionStore(), factoryMock3)
   370  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Run(func(_ mock.Arguments) {
   371  		t.Fatal("p3 shouldn't have been selected for pull")
   372  	})
   373  
   374  	dasf := &digestsAndSourceFactory{}
   375  
   376  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
   377  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   378  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   379  	fetched := []util.PrivateRWSet{rws1, rws2}
   380  	assert.NoError(t, err)
   381  	assert.Equal(t, p2TransientStore.RWSet, fetched)
   382  }
   383  
   384  func TestPullerDataNotAvailable(t *testing.T) {
   385  	// Scenario: p1 pulls from p2 and not from p3
   386  	// but the data in p2 doesn't exist
   387  	gn := &gossipNetwork{}
   388  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   389  	factoryMock := &mocks.CollectionAccessFactory{}
   390  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(&mocks.CollectionAccessPolicy{}, nil)
   391  
   392  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   393  
   394  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
   395  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   396  	dig := &proto.PvtDataDigest{
   397  		TxId:       "txID1",
   398  		Collection: "col1",
   399  		Namespace:  "ns1",
   400  	}
   401  
   402  	store := Dig2PvtRWSetWithConfig{
   403  		privdatacommon.DigKey{
   404  			TxId:       "txID1",
   405  			Collection: "col1",
   406  			Namespace:  "ns1",
   407  		}: &util.PrivateRWSetWithConfig{
   408  			RWSet: []util.PrivateRWSet{},
   409  		},
   410  	}
   411  
   412  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Return(store, true, nil)
   413  
   414  	p3 := gn.newPuller("p3", newCollectionStore(), factoryMock)
   415  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Run(func(_ mock.Arguments) {
   416  		t.Fatal("p3 shouldn't have been selected for pull")
   417  	})
   418  
   419  	dasf := &digestsAndSourceFactory{}
   420  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
   421  	assert.Empty(t, fetchedMessages.AvailableElements)
   422  	assert.NoError(t, err)
   423  }
   424  
   425  func TestPullerNoPeersKnown(t *testing.T) {
   426  	// Scenario: p1 doesn't know any peer and therefore fails fetching
   427  	gn := &gossipNetwork{}
   428  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2", "p3")
   429  	factoryMock := &mocks.CollectionAccessFactory{}
   430  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(&mocks.CollectionAccessPolicy{}, nil)
   431  
   432  	p1 := gn.newPuller("p1", policyStore, factoryMock)
   433  	dasf := &digestsAndSourceFactory{}
   434  	d2s := dasf.mapDigest(&privdatacommon.DigKey{Collection: "col1", TxId: "txID1", Namespace: "ns1"}).toSources().create()
   435  	fetchedMessages, err := p1.fetch(d2s)
   436  	assert.Empty(t, fetchedMessages)
   437  	assert.Error(t, err)
   438  	assert.Contains(t, err.Error(), "Empty membership")
   439  }
   440  
   441  func TestPullPeerFilterError(t *testing.T) {
   442  	// Scenario: p1 attempts to fetch for the wrong channel
   443  	gn := &gossipNetwork{}
   444  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   445  	factoryMock := &mocks.CollectionAccessFactory{}
   446  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(&mocks.CollectionAccessPolicy{}, nil)
   447  
   448  	p1 := gn.newPuller("p1", policyStore, factoryMock)
   449  	gn.peers[0].On("PeerFilter", mock.Anything, mock.Anything).Return(nil, errors.New("Failed obtaining filter"))
   450  	dasf := &digestsAndSourceFactory{}
   451  	d2s := dasf.mapDigest(&privdatacommon.DigKey{Collection: "col1", TxId: "txID1", Namespace: "ns1"}).toSources().create()
   452  	fetchedMessages, err := p1.fetch(d2s)
   453  	assert.Error(t, err)
   454  	assert.Contains(t, err.Error(), "Failed obtaining filter")
   455  	assert.Empty(t, fetchedMessages)
   456  }
   457  
   458  func TestPullerPeerNotEligible(t *testing.T) {
   459  	// Scenario: p1 pulls from p2 or from p3
   460  	// but it's not eligible for pulling data from p2 or from p3
   461  	gn := &gossipNetwork{}
   462  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2", "p3")
   463  	factoryMock1 := &mocks.CollectionAccessFactory{}
   464  	accessPolicyMock1 := &mocks.CollectionAccessPolicy{}
   465  	Setup(accessPolicyMock1, 1, 2, func(data protoutil.SignedData) bool {
   466  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p3"))
   467  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   468  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   469  
   470  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   471  
   472  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   473  	factoryMock2 := &mocks.CollectionAccessFactory{}
   474  	accessPolicyMock2 := &mocks.CollectionAccessPolicy{}
   475  	Setup(accessPolicyMock2, 1, 2, func(data protoutil.SignedData) bool {
   476  		return bytes.Equal(data.Identity, []byte("p2"))
   477  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   478  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock2, nil)
   479  
   480  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   481  
   482  	dig := &proto.PvtDataDigest{
   483  		TxId:       "txID1",
   484  		Collection: "col1",
   485  		Namespace:  "ns1",
   486  	}
   487  
   488  	store := Dig2PvtRWSetWithConfig{
   489  		privdatacommon.DigKey{
   490  			TxId:       "txID1",
   491  			Collection: "col1",
   492  			Namespace:  "ns1",
   493  		}: &util.PrivateRWSetWithConfig{
   494  			RWSet: newPRWSet(),
   495  			CollectionConfig: &peer.CollectionConfig{
   496  				Payload: &peer.CollectionConfig_StaticCollectionConfig{
   497  					StaticCollectionConfig: &peer.StaticCollectionConfig{
   498  						Name: "col1",
   499  					},
   500  				},
   501  			},
   502  		},
   503  	}
   504  
   505  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Return(store, true, nil)
   506  
   507  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p3")
   508  	factoryMock3 := &mocks.CollectionAccessFactory{}
   509  	accessPolicyMock3 := &mocks.CollectionAccessPolicy{}
   510  	Setup(accessPolicyMock3, 1, 2, func(data protoutil.SignedData) bool {
   511  		return bytes.Equal(data.Identity, []byte("p3"))
   512  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   513  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   514  
   515  	p3 := gn.newPuller("p3", policyStore, factoryMock3)
   516  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), mock.Anything).Return(store, true, nil)
   517  	dasf := &digestsAndSourceFactory{}
   518  	d2s := dasf.mapDigest(&privdatacommon.DigKey{Collection: "col1", TxId: "txID1", Namespace: "ns1"}).toSources().create()
   519  	fetchedMessages, err := p1.fetch(d2s)
   520  	assert.Empty(t, fetchedMessages.AvailableElements)
   521  	assert.NoError(t, err)
   522  }
   523  
   524  func TestPullerDifferentPeersDifferentCollections(t *testing.T) {
   525  	// Scenario: p1 pulls from p2 and from p3
   526  	// and each has different collections
   527  	gn := &gossipNetwork{}
   528  	factoryMock1 := &mocks.CollectionAccessFactory{}
   529  	accessPolicyMock1 := &mocks.CollectionAccessPolicy{}
   530  	Setup(accessPolicyMock1, 1, 2, func(data protoutil.SignedData) bool {
   531  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p3"))
   532  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   533  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   534  
   535  	policyStore := newCollectionStore().withPolicy("col2", uint64(100)).thatMapsTo("p2").withPolicy("col3", uint64(100)).thatMapsTo("p3")
   536  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)}, peerData{"p3", uint64(1)})...)
   537  
   538  	p2TransientStore := &util.PrivateRWSetWithConfig{
   539  		RWSet: newPRWSet(),
   540  		CollectionConfig: &peer.CollectionConfig{
   541  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   542  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   543  					Name: "col2",
   544  				},
   545  			},
   546  		},
   547  	}
   548  
   549  	policyStore = newCollectionStore().withPolicy("col2", uint64(100)).thatMapsTo("p1")
   550  	factoryMock2 := &mocks.CollectionAccessFactory{}
   551  	accessPolicyMock2 := &mocks.CollectionAccessPolicy{}
   552  	Setup(accessPolicyMock2, 1, 2, func(data protoutil.SignedData) bool {
   553  		return bytes.Equal(data.Identity, []byte("p1"))
   554  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   555  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock2, nil)
   556  
   557  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   558  	dig1 := &proto.PvtDataDigest{
   559  		TxId:       "txID1",
   560  		Collection: "col2",
   561  		Namespace:  "ns1",
   562  	}
   563  
   564  	store1 := Dig2PvtRWSetWithConfig{
   565  		privdatacommon.DigKey{
   566  			TxId:       "txID1",
   567  			Collection: "col2",
   568  			Namespace:  "ns1",
   569  		}: p2TransientStore,
   570  	}
   571  
   572  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), mock.Anything).Return(store1, true, nil)
   573  
   574  	p3TransientStore := &util.PrivateRWSetWithConfig{
   575  		RWSet: newPRWSet(),
   576  		CollectionConfig: &peer.CollectionConfig{
   577  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   578  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   579  					Name: "col3",
   580  				},
   581  			},
   582  		},
   583  	}
   584  
   585  	store2 := Dig2PvtRWSetWithConfig{
   586  		privdatacommon.DigKey{
   587  			TxId:       "txID1",
   588  			Collection: "col3",
   589  			Namespace:  "ns1",
   590  		}: p3TransientStore,
   591  	}
   592  	policyStore = newCollectionStore().withPolicy("col3", uint64(100)).thatMapsTo("p1")
   593  	factoryMock3 := &mocks.CollectionAccessFactory{}
   594  	accessPolicyMock3 := &mocks.CollectionAccessPolicy{}
   595  	Setup(accessPolicyMock3, 1, 2, func(data protoutil.SignedData) bool {
   596  		return bytes.Equal(data.Identity, []byte("p1"))
   597  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   598  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock3, nil)
   599  
   600  	p3 := gn.newPuller("p3", policyStore, factoryMock3)
   601  	dig2 := &proto.PvtDataDigest{
   602  		TxId:       "txID1",
   603  		Collection: "col3",
   604  		Namespace:  "ns1",
   605  	}
   606  
   607  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), mock.Anything).Return(store2, true, nil)
   608  
   609  	dasf := &digestsAndSourceFactory{}
   610  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig1)).toSources().mapDigest(toDigKey(dig2)).toSources().create())
   611  	assert.NoError(t, err)
   612  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   613  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   614  	rws3 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[0])
   615  	rws4 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[1])
   616  	fetched := []util.PrivateRWSet{rws1, rws2, rws3, rws4}
   617  	assert.Contains(t, fetched, p2TransientStore.RWSet[0])
   618  	assert.Contains(t, fetched, p2TransientStore.RWSet[1])
   619  	assert.Contains(t, fetched, p3TransientStore.RWSet[0])
   620  	assert.Contains(t, fetched, p3TransientStore.RWSet[1])
   621  }
   622  
   623  func TestPullerRetries(t *testing.T) {
   624  	// Scenario: p1 pulls from p2, p3, p4 and p5.
   625  	// Only p3 considers p1 to be eligible to receive the data.
   626  	// The rest consider p1 as not eligible.
   627  	gn := &gossipNetwork{}
   628  	factoryMock1 := &mocks.CollectionAccessFactory{}
   629  	accessPolicyMock1 := &mocks.CollectionAccessPolicy{}
   630  	Setup(accessPolicyMock1, 1, 2, func(data protoutil.SignedData) bool {
   631  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p3")) ||
   632  			bytes.Equal(data.Identity, []byte("p4")) ||
   633  			bytes.Equal(data.Identity, []byte("p5"))
   634  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   635  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock1, nil)
   636  
   637  	// p1
   638  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2", "p3", "p4", "p5")
   639  	p1 := gn.newPuller("p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)},
   640  		peerData{"p3", uint64(1)}, peerData{"p4", uint64(1)}, peerData{"p5", uint64(1)})...)
   641  
   642  	// p2, p3, p4, and p5 have the same transient store
   643  	transientStore := &util.PrivateRWSetWithConfig{
   644  		RWSet: newPRWSet(),
   645  		CollectionConfig: &peer.CollectionConfig{
   646  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   647  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   648  					Name: "col1",
   649  				},
   650  			},
   651  		},
   652  	}
   653  
   654  	dig := &proto.PvtDataDigest{
   655  		TxId:       "txID1",
   656  		Collection: "col1",
   657  		Namespace:  "ns1",
   658  	}
   659  
   660  	store := Dig2PvtRWSetWithConfig{
   661  		privdatacommon.DigKey{
   662  			TxId:       "txID1",
   663  			Collection: "col1",
   664  			Namespace:  "ns1",
   665  		}: transientStore,
   666  	}
   667  
   668  	// p2
   669  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
   670  	factoryMock2 := &mocks.CollectionAccessFactory{}
   671  	accessPolicyMock2 := &mocks.CollectionAccessPolicy{}
   672  	Setup(accessPolicyMock2, 1, 2, func(data protoutil.SignedData) bool {
   673  		return bytes.Equal(data.Identity, []byte("p2"))
   674  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   675  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock2, nil)
   676  
   677  	p2 := gn.newPuller("p2", policyStore, factoryMock2)
   678  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   679  
   680  	// p3
   681  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
   682  	factoryMock3 := &mocks.CollectionAccessFactory{}
   683  	accessPolicyMock3 := &mocks.CollectionAccessPolicy{}
   684  	Setup(accessPolicyMock3, 1, 2, func(data protoutil.SignedData) bool {
   685  		return bytes.Equal(data.Identity, []byte("p1"))
   686  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   687  	factoryMock3.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock3, nil)
   688  
   689  	p3 := gn.newPuller("p3", policyStore, factoryMock3)
   690  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   691  
   692  	// p4
   693  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p4")
   694  	factoryMock4 := &mocks.CollectionAccessFactory{}
   695  	accessPolicyMock4 := &mocks.CollectionAccessPolicy{}
   696  	Setup(accessPolicyMock4, 1, 2, func(data protoutil.SignedData) bool {
   697  		return bytes.Equal(data.Identity, []byte("p4"))
   698  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   699  	factoryMock4.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock4, nil)
   700  
   701  	p4 := gn.newPuller("p4", policyStore, factoryMock4)
   702  	p4.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   703  
   704  	// p5
   705  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p5")
   706  	factoryMock5 := &mocks.CollectionAccessFactory{}
   707  	accessPolicyMock5 := &mocks.CollectionAccessPolicy{}
   708  	Setup(accessPolicyMock5, 1, 2, func(data protoutil.SignedData) bool {
   709  		return bytes.Equal(data.Identity, []byte("p5"))
   710  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   711  	factoryMock5.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock5, nil)
   712  
   713  	p5 := gn.newPuller("p5", policyStore, factoryMock5)
   714  	p5.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)), uint64(0)).Return(store, true, nil)
   715  
   716  	// Fetch from someone
   717  	dasf := &digestsAndSourceFactory{}
   718  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
   719  	assert.NoError(t, err)
   720  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   721  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   722  	fetched := []util.PrivateRWSet{rws1, rws2}
   723  	assert.NoError(t, err)
   724  	assert.Equal(t, transientStore.RWSet, fetched)
   725  }
   726  
   727  func TestPullerPreferEndorsers(t *testing.T) {
   728  	// Scenario: p1 pulls from p2, p3, p4, p5
   729  	// and the only endorser for col1 is p3, so it should be selected
   730  	// at the top priority for col1.
   731  	// for col2, only p2 should have the data, but its not an endorser of the data.
   732  	gn := &gossipNetwork{}
   733  	factoryMock := &mocks.CollectionAccessFactory{}
   734  	accessPolicyMock := &mocks.CollectionAccessPolicy{}
   735  	Setup(accessPolicyMock, 1, 2, func(data protoutil.SignedData) bool {
   736  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p1"))
   737  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   738  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock, nil)
   739  
   740  	policyStore := newCollectionStore().
   741  		withPolicy("col1", uint64(100)).
   742  		thatMapsTo("p1", "p2", "p3", "p4", "p5").
   743  		withPolicy("col2", uint64(100)).
   744  		thatMapsTo("p1", "p2")
   745  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)},
   746  		peerData{"p3", uint64(1)}, peerData{"p4", uint64(1)}, peerData{"p5", uint64(1)})...)
   747  
   748  	p3TransientStore := &util.PrivateRWSetWithConfig{
   749  		RWSet: newPRWSet(),
   750  		CollectionConfig: &peer.CollectionConfig{
   751  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   752  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   753  					Name: "col2",
   754  				},
   755  			},
   756  		},
   757  	}
   758  
   759  	p2TransientStore := &util.PrivateRWSetWithConfig{
   760  		RWSet: newPRWSet(),
   761  		CollectionConfig: &peer.CollectionConfig{
   762  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   763  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   764  					Name: "col2",
   765  				},
   766  			},
   767  		},
   768  	}
   769  
   770  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   771  	p3 := gn.newPuller("p3", policyStore, factoryMock)
   772  	gn.newPuller("p4", policyStore, factoryMock)
   773  	gn.newPuller("p5", policyStore, factoryMock)
   774  
   775  	dig1 := &proto.PvtDataDigest{
   776  		TxId:       "txID1",
   777  		Collection: "col1",
   778  		Namespace:  "ns1",
   779  	}
   780  
   781  	dig2 := &proto.PvtDataDigest{
   782  		TxId:       "txID1",
   783  		Collection: "col2",
   784  		Namespace:  "ns1",
   785  	}
   786  
   787  	store := Dig2PvtRWSetWithConfig{
   788  		privdatacommon.DigKey{
   789  			TxId:       "txID1",
   790  			Collection: "col1",
   791  			Namespace:  "ns1",
   792  		}: p3TransientStore,
   793  		privdatacommon.DigKey{
   794  			TxId:       "txID1",
   795  			Collection: "col2",
   796  			Namespace:  "ns1",
   797  		}: p2TransientStore,
   798  	}
   799  
   800  	// We only define an action for dig2 on p2, and the test would fail with panic if any other peer is asked for
   801  	// a private RWSet on dig2
   802  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil)
   803  
   804  	// We only define an action for dig1 on p3, and the test would fail with panic if any other peer is asked for
   805  	// a private RWSet on dig1
   806  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), uint64(0)).Return(store, true, nil)
   807  
   808  	dasf := &digestsAndSourceFactory{}
   809  	d2s := dasf.mapDigest(toDigKey(dig1)).toSources("p3").mapDigest(toDigKey(dig2)).toSources().create()
   810  	fetchedMessages, err := p1.fetch(d2s)
   811  	assert.NoError(t, err)
   812  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   813  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   814  	rws3 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[0])
   815  	rws4 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[1])
   816  	fetched := []util.PrivateRWSet{rws1, rws2, rws3, rws4}
   817  	assert.Contains(t, fetched, p3TransientStore.RWSet[0])
   818  	assert.Contains(t, fetched, p3TransientStore.RWSet[1])
   819  	assert.Contains(t, fetched, p2TransientStore.RWSet[0])
   820  	assert.Contains(t, fetched, p2TransientStore.RWSet[1])
   821  }
   822  
   823  func TestPullerFetchReconciledItemsPreferPeersFromOriginalConfig(t *testing.T) {
   824  	// Scenario: p1 pulls from p2, p3, p4, p5
   825  	// the only peer that was in the collection config while data was created for col1 is p3, so it should be selected
   826  	// at the top priority for col1.
   827  	// 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.
   828  	// so obviously p2 should be selected for col2.
   829  	gn := &gossipNetwork{}
   830  	factoryMock := &mocks.CollectionAccessFactory{}
   831  	accessPolicyMock := &mocks.CollectionAccessPolicy{}
   832  	Setup(accessPolicyMock, 1, 2, func(data protoutil.SignedData) bool {
   833  		return bytes.Equal(data.Identity, []byte("p2")) || bytes.Equal(data.Identity, []byte("p1"))
   834  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   835  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock, nil)
   836  
   837  	policyStore := newCollectionStore().
   838  		withPolicy("col1", uint64(100)).
   839  		thatMapsTo("p1", "p2", "p3", "p4", "p5").
   840  		withPolicy("col2", uint64(100)).
   841  		thatMapsTo("p1", "p2").
   842  		withAccessFilter(func(data protoutil.SignedData) bool {
   843  			return bytes.Equal(data.Identity, []byte("p3"))
   844  		})
   845  
   846  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)},
   847  		peerData{"p3", uint64(1)}, peerData{"p4", uint64(1)}, peerData{"p5", uint64(1)})...)
   848  
   849  	p3TransientStore := &util.PrivateRWSetWithConfig{
   850  		RWSet: newPRWSet(),
   851  		CollectionConfig: &peer.CollectionConfig{
   852  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   853  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   854  					Name: "col2",
   855  				},
   856  			},
   857  		},
   858  	}
   859  
   860  	p2TransientStore := &util.PrivateRWSetWithConfig{
   861  		RWSet: newPRWSet(),
   862  		CollectionConfig: &peer.CollectionConfig{
   863  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   864  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   865  					Name: "col2",
   866  				},
   867  			},
   868  		},
   869  	}
   870  
   871  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   872  	p3 := gn.newPuller("p3", policyStore, factoryMock)
   873  	gn.newPuller("p4", policyStore, factoryMock)
   874  	gn.newPuller("p5", policyStore, factoryMock)
   875  
   876  	dig1 := &proto.PvtDataDigest{
   877  		TxId:       "txID1",
   878  		Collection: "col1",
   879  		Namespace:  "ns1",
   880  	}
   881  
   882  	dig2 := &proto.PvtDataDigest{
   883  		TxId:       "txID1",
   884  		Collection: "col2",
   885  		Namespace:  "ns1",
   886  	}
   887  
   888  	store := Dig2PvtRWSetWithConfig{
   889  		privdatacommon.DigKey{
   890  			TxId:       "txID1",
   891  			Collection: "col1",
   892  			Namespace:  "ns1",
   893  		}: p3TransientStore,
   894  		privdatacommon.DigKey{
   895  			TxId:       "txID1",
   896  			Collection: "col2",
   897  			Namespace:  "ns1",
   898  		}: p2TransientStore,
   899  	}
   900  
   901  	// We only define an action for dig2 on p2, and the test would fail with panic if any other peer is asked for
   902  	// a private RWSet on dig2
   903  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil)
   904  
   905  	// We only define an action for dig1 on p3, and the test would fail with panic if any other peer is asked for
   906  	// a private RWSet on dig1
   907  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), uint64(0)).Return(store, true, nil)
   908  
   909  	d2cc := privdatacommon.Dig2CollectionConfig{
   910  		privdatacommon.DigKey{
   911  			TxId:       "txID1",
   912  			Collection: "col1",
   913  			Namespace:  "ns1",
   914  		}: &peer.StaticCollectionConfig{
   915  			Name: "col1",
   916  		},
   917  		privdatacommon.DigKey{
   918  			TxId:       "txID1",
   919  			Collection: "col2",
   920  			Namespace:  "ns1",
   921  		}: &peer.StaticCollectionConfig{
   922  			Name: "col2",
   923  		},
   924  	}
   925  
   926  	fetchedMessages, err := p1.FetchReconciledItems(d2cc)
   927  	assert.NoError(t, err)
   928  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
   929  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
   930  	rws3 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[0])
   931  	rws4 := util.PrivateRWSet(fetchedMessages.AvailableElements[1].Payload[1])
   932  	fetched := []util.PrivateRWSet{rws1, rws2, rws3, rws4}
   933  	assert.Contains(t, fetched, p3TransientStore.RWSet[0])
   934  	assert.Contains(t, fetched, p3TransientStore.RWSet[1])
   935  	assert.Contains(t, fetched, p2TransientStore.RWSet[0])
   936  	assert.Contains(t, fetched, p2TransientStore.RWSet[1])
   937  }
   938  
   939  func TestPullerAvoidPullingPurgedData(t *testing.T) {
   940  	// Scenario: p1 missing private data for col1
   941  	// p2 and p3 is suppose to have it, while p3 has more advanced
   942  	// ledger and based on BTL already purged data for, so p1
   943  	// suppose to fetch data only from p2
   944  	gn := &gossipNetwork{}
   945  	factoryMock := &mocks.CollectionAccessFactory{}
   946  	accessPolicyMock := &mocks.CollectionAccessPolicy{}
   947  	Setup(accessPolicyMock, 1, 2, func(data protoutil.SignedData) bool {
   948  		return bytes.Equal(data.Identity, []byte("p1"))
   949  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
   950  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(accessPolicyMock, nil)
   951  
   952  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1", "p2", "p3").
   953  		withPolicy("col2", uint64(1000)).thatMapsTo("p1", "p2", "p3")
   954  
   955  	// p2 is at ledger height 1, while p2 is at 111 which is beyond BTL defined for col1 (100)
   956  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(1)},
   957  		peerData{"p3", uint64(111)})...)
   958  
   959  	privateData1 := &util.PrivateRWSetWithConfig{
   960  		RWSet: newPRWSet(),
   961  		CollectionConfig: &peer.CollectionConfig{
   962  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   963  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   964  					Name: "col1",
   965  				},
   966  			},
   967  		},
   968  	}
   969  	privateData2 := &util.PrivateRWSetWithConfig{
   970  		RWSet: newPRWSet(),
   971  		CollectionConfig: &peer.CollectionConfig{
   972  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
   973  				StaticCollectionConfig: &peer.StaticCollectionConfig{
   974  					Name: "col2",
   975  				},
   976  			},
   977  		},
   978  	}
   979  
   980  	p2 := gn.newPuller("p2", policyStore, factoryMock)
   981  	p3 := gn.newPuller("p3", policyStore, factoryMock)
   982  
   983  	dig1 := &proto.PvtDataDigest{
   984  		TxId:       "txID1",
   985  		Collection: "col1",
   986  		Namespace:  "ns1",
   987  	}
   988  
   989  	dig2 := &proto.PvtDataDigest{
   990  		TxId:       "txID1",
   991  		Collection: "col2",
   992  		Namespace:  "ns1",
   993  	}
   994  
   995  	store := Dig2PvtRWSetWithConfig{
   996  		privdatacommon.DigKey{
   997  			TxId:       "txID1",
   998  			Collection: "col1",
   999  			Namespace:  "ns1",
  1000  		}: privateData1,
  1001  		privdatacommon.DigKey{
  1002  			TxId:       "txID1",
  1003  			Collection: "col2",
  1004  			Namespace:  "ns1",
  1005  		}: privateData2,
  1006  	}
  1007  
  1008  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), 0).Return(store, true, nil)
  1009  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig1)), 0).Return(store, true, nil).
  1010  		Run(
  1011  			func(arg mock.Arguments) {
  1012  				assert.Fail(t, "we should not fetch private data from peers where it was purged")
  1013  			},
  1014  		)
  1015  
  1016  	p3.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil)
  1017  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig2)), uint64(0)).Return(store, true, nil).
  1018  		Run(
  1019  			func(mock.Arguments) {
  1020  				assert.Fail(t, "we should not fetch private data of collection2 from peer 2")
  1021  
  1022  			},
  1023  		)
  1024  
  1025  	dasf := &digestsAndSourceFactory{}
  1026  	d2s := dasf.mapDigest(toDigKey(dig1)).toSources("p3", "p2").mapDigest(toDigKey(dig2)).toSources("p3").create()
  1027  	// trying to fetch missing pvt data for block seq 1
  1028  	fetchedMessages, err := p1.fetch(d2s)
  1029  
  1030  	assert.NoError(t, err)
  1031  	assert.Equal(t, 1, len(fetchedMessages.PurgedElements))
  1032  	assert.Equal(t, dig1, fetchedMessages.PurgedElements[0])
  1033  	p3.PrivateDataRetriever.(*dataRetrieverMock).AssertNumberOfCalls(t, "CollectionRWSet", 1)
  1034  
  1035  }
  1036  
  1037  type counterDataRetreiver struct {
  1038  	numberOfCalls int
  1039  	PrivateDataRetriever
  1040  }
  1041  
  1042  func (c *counterDataRetreiver) CollectionRWSet(dig []*proto.PvtDataDigest, blockNum uint64) (Dig2PvtRWSetWithConfig, bool, error) {
  1043  	c.numberOfCalls += 1
  1044  	return c.PrivateDataRetriever.CollectionRWSet(dig, blockNum)
  1045  }
  1046  
  1047  func (c *counterDataRetreiver) getNumberOfCalls() int {
  1048  	return c.numberOfCalls
  1049  }
  1050  
  1051  func TestPullerIntegratedWithDataRetreiver(t *testing.T) {
  1052  	gn := &gossipNetwork{}
  1053  
  1054  	ns1, ns2 := "testChaincodeName1", "testChaincodeName2"
  1055  	col1, col2 := "testCollectionName1", "testCollectionName2"
  1056  
  1057  	ap := &mocks.CollectionAccessPolicy{}
  1058  	Setup(ap, 1, 2, func(data protoutil.SignedData) bool {
  1059  		return bytes.Equal(data.Identity, []byte("p1"))
  1060  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
  1061  
  1062  	factoryMock := &mocks.CollectionAccessFactory{}
  1063  	factoryMock.On("AccessPolicy", mock.Anything, mock.Anything).Return(ap, nil)
  1064  
  1065  	policyStore := newCollectionStore().withPolicy(col1, uint64(1000)).thatMapsTo("p1", "p2").
  1066  		withPolicy(col2, uint64(1000)).thatMapsTo("p1", "p2")
  1067  
  1068  	p1 := gn.newPuller("p1", policyStore, factoryMock, membership(peerData{"p2", uint64(10)})...)
  1069  	p2 := gn.newPuller("p2", policyStore, factoryMock, membership(peerData{"p1", uint64(1)})...)
  1070  
  1071  	committer := &mocks.Committer{}
  1072  	tempdir, err := ioutil.TempDir("", "ts")
  1073  	if err != nil {
  1074  		t.Fatalf("Failed to create test directory, got err %s", err)
  1075  		return
  1076  	}
  1077  	storeProvider, err := transientstore.NewStoreProvider(tempdir)
  1078  	if err != nil {
  1079  		t.Fatalf("Failed to open store, got err %s", err)
  1080  		return
  1081  	}
  1082  	store, err := storeProvider.OpenStore("test")
  1083  	if err != nil {
  1084  		t.Fatalf("Failed to open store, got err %s", err)
  1085  		return
  1086  	}
  1087  	defer storeProvider.Close()
  1088  	defer os.RemoveAll(tempdir)
  1089  	result := []*ledger.TxPvtData{
  1090  		{
  1091  			WriteSet: &rwset.TxPvtReadWriteSet{
  1092  				DataModel: rwset.TxReadWriteSet_KV,
  1093  				NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1094  					pvtReadWriteSet(ns1, col1, []byte{1}),
  1095  					pvtReadWriteSet(ns1, col1, []byte{2}),
  1096  				},
  1097  			},
  1098  			SeqInBlock: 1,
  1099  		},
  1100  		{
  1101  			WriteSet: &rwset.TxPvtReadWriteSet{
  1102  				DataModel: rwset.TxReadWriteSet_KV,
  1103  				NsPvtRwset: []*rwset.NsPvtReadWriteSet{
  1104  					pvtReadWriteSet(ns2, col2, []byte{3}),
  1105  					pvtReadWriteSet(ns2, col2, []byte{4}),
  1106  				},
  1107  			},
  1108  			SeqInBlock: 2,
  1109  		},
  1110  	}
  1111  
  1112  	committer.On("LedgerHeight").Return(uint64(10), nil)
  1113  	committer.On("GetPvtDataByNum", uint64(5), mock.Anything).Return(result, nil)
  1114  	historyRetreiver := &mocks.ConfigHistoryRetriever{}
  1115  	historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, ns1).Return(newCollectionConfig(col1), nil)
  1116  	historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, ns2).Return(newCollectionConfig(col2), nil)
  1117  	committer.On("GetConfigHistoryRetriever").Return(historyRetreiver, nil)
  1118  
  1119  	dataRetreiver := &counterDataRetreiver{PrivateDataRetriever: NewDataRetriever("testchannel", store, committer), numberOfCalls: 0}
  1120  	p2.PrivateDataRetriever = dataRetreiver
  1121  
  1122  	dig1 := &privdatacommon.DigKey{
  1123  		TxId:       "txID1",
  1124  		Collection: col1,
  1125  		Namespace:  ns1,
  1126  		BlockSeq:   5,
  1127  		SeqInBlock: 1,
  1128  	}
  1129  
  1130  	dig2 := &privdatacommon.DigKey{
  1131  		TxId:       "txID1",
  1132  		Collection: col2,
  1133  		Namespace:  ns2,
  1134  		BlockSeq:   5,
  1135  		SeqInBlock: 2,
  1136  	}
  1137  
  1138  	dasf := &digestsAndSourceFactory{}
  1139  	d2s := dasf.mapDigest(dig1).toSources("p2").mapDigest(dig2).toSources("p2").create()
  1140  	fetchedMessages, err := p1.fetch(d2s)
  1141  	assert.NoError(t, err)
  1142  	assert.Equal(t, 2, len(fetchedMessages.AvailableElements))
  1143  	assert.Equal(t, 1, dataRetreiver.getNumberOfCalls())
  1144  	assert.Equal(t, 2, len(fetchedMessages.AvailableElements[0].Payload))
  1145  	assert.Equal(t, 2, len(fetchedMessages.AvailableElements[1].Payload))
  1146  }
  1147  
  1148  func toDigKey(dig *proto.PvtDataDigest) *privdatacommon.DigKey {
  1149  	return &privdatacommon.DigKey{
  1150  		TxId:       dig.TxId,
  1151  		BlockSeq:   dig.BlockSeq,
  1152  		SeqInBlock: dig.SeqInBlock,
  1153  		Namespace:  dig.Namespace,
  1154  		Collection: dig.Collection,
  1155  	}
  1156  }
  1157  
  1158  func TestPullerMetrics(t *testing.T) {
  1159  	// Scenario: p1 pulls from p2 and sends metric reports
  1160  	gn := &gossipNetwork{}
  1161  	policyStore := newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p2")
  1162  	factoryMock1 := &mocks.CollectionAccessFactory{}
  1163  	policyMock1 := &mocks.CollectionAccessPolicy{}
  1164  	Setup(policyMock1, 1, 2, func(data protoutil.SignedData) bool {
  1165  		return bytes.Equal(data.Identity, []byte("p2"))
  1166  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
  1167  	factoryMock1.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock1, nil)
  1168  
  1169  	testMetricProvider := gmetricsmocks.TestUtilConstructMetricProvider()
  1170  	metrics := metrics.NewGossipMetrics(testMetricProvider.FakeProvider).PrivdataMetrics
  1171  
  1172  	p1 := gn.newPullerWithMetrics(metrics, "p1", policyStore, factoryMock1, membership(peerData{"p2", uint64(1)})...)
  1173  
  1174  	p2TransientStore := &util.PrivateRWSetWithConfig{
  1175  		RWSet: newPRWSet(),
  1176  		CollectionConfig: &peer.CollectionConfig{
  1177  			Payload: &peer.CollectionConfig_StaticCollectionConfig{
  1178  				StaticCollectionConfig: &peer.StaticCollectionConfig{
  1179  					Name: "col1",
  1180  				},
  1181  			},
  1182  		},
  1183  	}
  1184  	policyStore = newCollectionStore().withPolicy("col1", uint64(100)).thatMapsTo("p1")
  1185  	factoryMock2 := &mocks.CollectionAccessFactory{}
  1186  	policyMock2 := &mocks.CollectionAccessPolicy{}
  1187  	Setup(policyMock2, 1, 2, func(data protoutil.SignedData) bool {
  1188  		return bytes.Equal(data.Identity, []byte("p1"))
  1189  	}, map[string]struct{}{"org1": {}, "org2": {}}, false)
  1190  	factoryMock2.On("AccessPolicy", mock.Anything, mock.Anything).Return(policyMock2, nil)
  1191  
  1192  	p2 := gn.newPullerWithMetrics(metrics, "p2", policyStore, factoryMock2)
  1193  
  1194  	dig := &proto.PvtDataDigest{
  1195  		TxId:       "txID1",
  1196  		Collection: "col1",
  1197  		Namespace:  "ns1",
  1198  	}
  1199  
  1200  	store := Dig2PvtRWSetWithConfig{
  1201  		privdatacommon.DigKey{
  1202  			TxId:       "txID1",
  1203  			Collection: "col1",
  1204  			Namespace:  "ns1",
  1205  		}: p2TransientStore,
  1206  	}
  1207  
  1208  	p2.PrivateDataRetriever.(*dataRetrieverMock).On("CollectionRWSet", mock.MatchedBy(protoMatcher(dig)),
  1209  		uint64(0)).Return(store, true, nil)
  1210  
  1211  	dasf := &digestsAndSourceFactory{}
  1212  
  1213  	fetchedMessages, err := p1.fetch(dasf.mapDigest(toDigKey(dig)).toSources().create())
  1214  	rws1 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[0])
  1215  	rws2 := util.PrivateRWSet(fetchedMessages.AvailableElements[0].Payload[1])
  1216  	fetched := []util.PrivateRWSet{rws1, rws2}
  1217  	assert.NoError(t, err)
  1218  	assert.Equal(t, p2TransientStore.RWSet, fetched)
  1219  
  1220  	assert.Equal(t,
  1221  		[]string{"channel", "A"},
  1222  		testMetricProvider.FakePullDuration.WithArgsForCall(0),
  1223  	)
  1224  	assert.True(t, testMetricProvider.FakePullDuration.ObserveArgsForCall(0) > 0)
  1225  	assert.Equal(t,
  1226  		[]string{"channel", "A"},
  1227  		testMetricProvider.FakeRetrieveDuration.WithArgsForCall(0),
  1228  	)
  1229  	assert.True(t, testMetricProvider.FakeRetrieveDuration.ObserveArgsForCall(0) > 0)
  1230  }