github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/gossip/privdata/pull_test.go (about)

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