Commit d6ba31b6 authored by Artem Barger's avatar Artem Barger Committed by Gari Singh
Browse files

[FAB-9923/FAB-10096] Use stored coll. conf for pull



This commit makes use of the stored collection config which was
available at endorsement time to support pull of the missing private
data.

Change-Id: Ic10f3142f769e6afa7cfff70553fa3093244a08e
Signed-off-by: default avatarArtem Barger <bartem@il.ibm.com>
parent 71983e8b
......@@ -304,20 +304,25 @@ func (c *coordinator) fetchFromTransientStore(txAndSeq txAndSeqInBlock, filter l
}
defer iterator.Close()
for {
res, err := iterator.Next()
res, err := iterator.NextWithConfig()
if err != nil {
logger.Warning("Failed iterating:", err)
logger.Error("Failed iterating:", err)
break
}
if res == nil {
// End of iteration
break
}
if res.PvtSimulationResults == nil {
logger.Warning("Resultset's PvtSimulationResults for", txAndSeq.txID, "is nil, skipping")
if res.PvtSimulationResultsWithConfig == nil {
logger.Warning("Resultset's PvtSimulationResultsWithConfig for", txAndSeq.txID, "is nil, skipping")
continue
}
for _, ns := range res.PvtSimulationResults.NsPvtRwset {
simRes := res.PvtSimulationResultsWithConfig
if simRes.PvtRwset == nil {
logger.Warning("The PvtRwset of PvtSimulationResultsWithConfig for", txAndSeq.txID, "is nil, skipping")
continue
}
for _, ns := range simRes.PvtRwset.NsPvtRwset {
for _, col := range ns.CollectionPvtRwset {
key := rwSetKey{
txID: txAndSeq.txID,
......
......@@ -117,20 +117,35 @@ func (store *mockTransientStore) GetTxPvtRWSetByTxid(txid string, filter ledger.
type mockRWSetScanner struct {
err error
results []*transientstore.EndorserPvtSimulationResults
results []*transientstore.EndorserPvtSimulationResultsWithConfig
}
func (scanner *mockRWSetScanner) withRWSet(ns string, col string) *mockRWSetScanner {
scanner.results = append(scanner.results, &transientstore.EndorserPvtSimulationResults{
PvtSimulationResults: &rwset.TxPvtReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV,
NsPvtRwset: []*rwset.NsPvtReadWriteSet{
{
Namespace: ns,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
scanner.results = append(scanner.results, &transientstore.EndorserPvtSimulationResultsWithConfig{
PvtSimulationResultsWithConfig: &transientstore2.TxPvtReadWriteSetWithConfigInfo{
PvtRwset: &rwset.TxPvtReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV,
NsPvtRwset: []*rwset.NsPvtReadWriteSet{
{
Namespace: ns,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
{
CollectionName: col,
Rwset: []byte("rws-pre-image"),
},
},
},
},
},
CollectionConfigs: map[string]*common.CollectionConfigPackage{
ns: {
Config: []*common.CollectionConfig{
{
CollectionName: col,
Rwset: []byte("rws-pre-image"),
Payload: &common.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &common.StaticCollectionConfig{
Name: col,
},
},
},
},
},
......@@ -141,10 +156,14 @@ func (scanner *mockRWSetScanner) withRWSet(ns string, col string) *mockRWSetScan
}
func (scanner *mockRWSetScanner) Next() (*transientstore.EndorserPvtSimulationResults, error) {
panic("should not be used")
}
func (scanner *mockRWSetScanner) NextWithConfig() (*transientstore.EndorserPvtSimulationResultsWithConfig, error) {
if scanner.err != nil {
return nil, scanner.err
}
var res *transientstore.EndorserPvtSimulationResults
var res *transientstore.EndorserPvtSimulationResultsWithConfig
if len(scanner.results) == 0 {
return nil, nil
}
......@@ -152,10 +171,6 @@ func (scanner *mockRWSetScanner) Next() (*transientstore.EndorserPvtSimulationRe
return res, nil
}
func (scanner *mockRWSetScanner) NextWithConfig() (*transientstore.EndorserPvtSimulationResultsWithConfig, error) {
return nil, nil
}
func (*mockRWSetScanner) Close() {
}
......@@ -279,6 +294,7 @@ func (f *fetcherMock) On(methodName string, arguments ...interface{}) *fetchCall
}
func (f *fetcherMock) fetch(dig2src dig2sources) ([]*proto.PvtDataElement, error) {
fmt.Println("XXX: Expected endorsers", f.expectedEndorsers)
for _, endorsements := range dig2src {
for _, endorsement := range endorsements {
_, exists := f.expectedEndorsers[string(endorsement.Endorser)]
......@@ -882,6 +898,7 @@ func TestCoordinatorStoreBlock(t *testing.T) {
block := bf.AddTxnWithEndorsement("tx1", "ns1", hash, "org1", true, "c1", "c2").
AddTxnWithEndorsement("tx2", "ns2", hash, "org2", true, "c1").create()
fmt.Println("Scenario I")
// Scenario I: Block we got has sufficient private data alongside it.
// If the coordinator tries fetching from the transientstore, or peers it would result in panic,
// because we didn't define yet the "On(...)" invocation of the transient store or other peers.
......@@ -898,6 +915,7 @@ func TestCoordinatorStoreBlock(t *testing.T) {
assertCommitHappened()
assertPurged("tx1", "tx2")
fmt.Println("Scenario II")
// Scenario II: Block we got doesn't have sufficient private data alongside it,
// it is missing ns1: c2, but the data exists in the transient store
store.On("GetTxPvtRWSetByTxid", "tx1", mock.Anything).Return((&mockRWSetScanner{}).withRWSet("ns1", "c2"), nil)
......@@ -914,6 +932,7 @@ func TestCoordinatorStoreBlock(t *testing.T) {
},
}, store.lastReqFilter)
fmt.Println("Scenario III")
// Scenario III: Block doesn't have sufficient private data alongside it,
// it is missing ns1: c2, and the data exists in the transient store,
// but it is also missing ns2: c1, and that data doesn't exist in the transient store - but in a peer.
......@@ -956,6 +975,7 @@ func TestCoordinatorStoreBlock(t *testing.T) {
assert.NoError(t, err)
assertCommitHappened()
fmt.Println("Scenario IV")
// Scenario IV: Block came with more than sufficient private data alongside it, some of it is redundant.
pvtData = pdFactory.addRWSet().addNSRWSet("ns1", "c1", "c2", "c3").
addRWSet().addNSRWSet("ns2", "c1", "c3").addRWSet().addNSRWSet("ns1", "c4").create()
......@@ -964,6 +984,7 @@ func TestCoordinatorStoreBlock(t *testing.T) {
assert.NoError(t, err)
assertCommitHappened()
fmt.Println("Scenario V")
// Scenario V: Block didn't get with any private data alongside it, and the transient store
// has some problem.
// In this case, we should try to fetch data from peers.
......@@ -1010,6 +1031,7 @@ func TestCoordinatorStoreBlock(t *testing.T) {
assert.NoError(t, err)
assertCommitHappened()
fmt.Println("Scenario VI")
// Scenario VI: Block contains 2 transactions, and the peer is eligible for only tx3-ns3-c3.
// Also, the blocks comes with a private data for tx3-ns3-c3 so that the peer won't have to fetch the
// private data from the transient store or peers, and in fact- if it attempts to fetch the data it's not eligible
......
......@@ -10,6 +10,7 @@ import (
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/transientstore"
"github.com/hyperledger/fabric/gossip/util"
"github.com/hyperledger/fabric/protos/common"
gossip2 "github.com/hyperledger/fabric/protos/gossip"
"github.com/hyperledger/fabric/protos/ledger/rwset"
)
......@@ -18,7 +19,7 @@ import (
type StorageDataRetriever interface {
// CollectionRWSet retrieves for give digest relevant private data if
// available otherwise returns nil
CollectionRWSet(dig *gossip2.PvtDataDigest) []util.PrivateRWSet
CollectionRWSet(dig *gossip2.PvtDataDigest) *util.PrivateRWSetWithConfig
}
// DataStore defines set of APIs need to get private data
......@@ -52,69 +53,129 @@ func NewDataRetriever(store DataStore) StorageDataRetriever {
// CollectionRWSet retrieves for give digest relevant private data if
// available otherwise returns nil
func (dr *dataRetriever) CollectionRWSet(dig *gossip2.PvtDataDigest) []util.PrivateRWSet {
func (dr *dataRetriever) CollectionRWSet(dig *gossip2.PvtDataDigest) *util.PrivateRWSetWithConfig {
filter := map[string]ledger.PvtCollFilter{
dig.Namespace: map[string]bool{
dig.Collection: true,
},
}
pRWsets := []util.PrivateRWSet{}
height, err := dr.store.LedgerHeight()
if err != nil {
// if there is an error getting info from the ledger, we need to try to read from transient store
logger.Warning("Wasn't able to read ledger height, due to", err, "trying to lookup "+
logger.Error("Wasn't able to read ledger height, due to", err, "trying to lookup "+
"private data from transient store, namespace", dig.Namespace, "collection name", dig.Collection, "txID", dig.TxId)
return nil
}
if height <= dig.BlockSeq {
logger.Debug("Current ledger height ", height, "is below requested block sequence number",
dig.BlockSeq, "retrieving private data from transient store, namespace", dig.Namespace, "collection name",
dig.Collection, "txID", dig.TxId)
}
if err != nil || height <= dig.BlockSeq { // Check whenever current ledger height is equal or above block sequence num.
if height <= dig.BlockSeq { // Check whenever current ledger height is equal or above block sequence num.
return dr.fromTransientStore(dig, filter)
}
// Since ledger height is above block sequence number private data is might be available in the ledger
return dr.fromLedger(dig, filter)
}
func (dr *dataRetriever) fromLedger(dig *gossip2.PvtDataDigest, filter map[string]ledger.PvtCollFilter) *util.PrivateRWSetWithConfig {
results := &util.PrivateRWSetWithConfig{}
pvtData, err := dr.store.GetPvtDataByNum(dig.BlockSeq, filter)
if err != nil {
logger.Error("Wasn't able to obtain private data for collection", dig.Collection,
"txID", dig.TxId, "block sequence number", dig.BlockSeq, "due to", err)
return nil
}
for _, data := range pvtData {
if data.WriteSet == nil {
logger.Warning("Received nil write set for collection", dig.Collection, "namespace", dig.Namespace)
continue
}
pvtRWSet := dr.extractPvtRWsets(data.WriteSet.NsPvtRwset, dig.Namespace, dig.Collection)
results.RWSet = append(results.RWSet, pvtRWSet...)
}
confHistoryRetriever, err := dr.store.GetConfigHistoryRetriever()
if err != nil {
logger.Error("Cannot obtain configuration history retriever, for collection,", dig.Collection,
"txID", dig.TxId, "block sequence number", dig.BlockSeq, "due to", err)
return nil
}
configInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)
if err != nil {
logger.Error("Cannot find recent collection config update below block sequence = ", dig.BlockSeq,
"collection name =", dig.Collection, "for chaincode", dig.Namespace)
return nil
}
if configInfo == nil {
logger.Error("No collection config update below block sequence = ", dig.BlockSeq,
"collection name =", dig.Collection, "for chaincode", dig.Namespace, "is available")
return nil
}
configs := dr.extractCollectionConfigs(configInfo.CollectionConfig, dig)
if configs == nil {
logger.Error("No collection config was found for collection", dig.Collection,
"namespace", dig.Namespace, "txID", dig.TxId)
return nil
}
results.CollectionConfig = configs
return results
}
func (dr *dataRetriever) fromTransientStore(dig *gossip2.PvtDataDigest, filter map[string]ledger.PvtCollFilter) *util.PrivateRWSetWithConfig {
results := &util.PrivateRWSetWithConfig{}
it, err := dr.store.GetTxPvtRWSetByTxid(dig.TxId, filter)
if err != nil {
logger.Error("Was not able to retrieve private data from transient store, namespace", dig.Namespace,
", collection name", dig.Collection, ", txID", dig.TxId, ", due to", err)
return nil
}
defer it.Close()
it, err := dr.store.GetTxPvtRWSetByTxid(dig.TxId, filter)
for {
res, err := it.NextWithConfig()
if err != nil {
logger.Error("Was not able to retrieve private data from transient store, namespace", dig.Namespace,
logger.Error("Error getting next element out of private data iterator, namespace", dig.Namespace,
", collection name", dig.Collection, ", txID", dig.TxId, ", due to", err)
return nil
}
defer it.Close()
for {
res, err := it.Next()
if err != nil {
logger.Error("Error getting next element out of private data iterator, namespace", dig.Namespace,
", collection name", dig.Collection, ", txID", dig.TxId, ", due to", err)
return nil
}
if res == nil {
return pRWsets
}
rws := res.PvtSimulationResults
if rws == nil {
logger.Debug("Skipping empty PvtSimulationResults received at block height", res.ReceivedAtBlockHeight)
continue
}
pRWsets = append(pRWsets, dr.extractPvtRWsets(rws.NsPvtRwset, dig.Namespace, dig.Collection)...)
if res == nil {
return results
}
} else { // Since ledger height is above block sequence number private data is available in the ledger
pvtData, err := dr.store.GetPvtDataByNum(dig.BlockSeq, filter)
if err != nil {
logger.Error("Wasn't able to obtain private data for collection", dig.Collection,
"txID", dig.TxId, "block sequence number", dig.BlockSeq, "due to", err)
rws := res.PvtSimulationResultsWithConfig
if rws == nil {
logger.Debug("Skipping nil PvtSimulationResultsWithConfig received at block height", res.ReceivedAtBlockHeight)
continue
}
for _, data := range pvtData {
if data.WriteSet == nil {
logger.Warning("Received nil write set for collection", dig.Collection, "namespace", dig.Namespace)
continue
}
pRWsets = append(pRWsets, dr.extractPvtRWsets(data.WriteSet.NsPvtRwset, dig.Namespace, dig.Collection)...)
txPvtRWSet := rws.PvtRwset
if txPvtRWSet == nil {
logger.Debug("Skipping empty PvtRwset of PvtSimulationResultsWithConfig received at block height", res.ReceivedAtBlockHeight)
continue
}
}
return pRWsets
colConfigs, found := rws.CollectionConfigs[dig.Namespace]
if !found {
logger.Error("No collection config was found for chaincode", dig.Namespace, "collection name",
dig.Namespace, "txID", dig.TxId)
continue
}
configs := dr.extractCollectionConfigs(colConfigs, dig)
if configs == nil {
logger.Error("No collection config was found for collection", dig.Collection,
"namespace", dig.Namespace, "txID", dig.TxId)
continue
}
pvtRWSet := dr.extractPvtRWsets(txPvtRWSet.NsPvtRwset, dig.Namespace, dig.Collection)
// TODO: Next CR will extend TxPvtReadWriteSetWithConfigInfo to have ledger height of
// endorsement time to be used here in order to select most updated collection config.
results.CollectionConfig = configs
results.RWSet = append(results.RWSet, pvtRWSet...)
}
}
func (dr *dataRetriever) extractPvtRWsets(pvtRWSets []*rwset.NsPvtReadWriteSet, namespace string, collectionName string) []util.PrivateRWSet {
......@@ -140,3 +201,17 @@ func (dr *dataRetriever) extractPvtRWsets(pvtRWSets []*rwset.NsPvtReadWriteSet,
return pRWsets
}
func (dr *dataRetriever) extractCollectionConfigs(configPackage *common.CollectionConfigPackage, digest *gossip2.PvtDataDigest) *common.CollectionConfig {
for _, config := range configPackage.Config {
switch cconf := config.Payload.(type) {
case *common.CollectionConfig_StaticCollectionConfig:
if cconf.StaticCollectionConfig.Name == digest.Collection {
return config
}
default:
return nil
}
}
return nil
}
......@@ -12,12 +12,28 @@ import (
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/transientstore"
"github.com/hyperledger/fabric/protos/common"
gossip2 "github.com/hyperledger/fabric/protos/gossip"
"github.com/hyperledger/fabric/protos/ledger/rwset"
transientstore2 "github.com/hyperledger/fabric/protos/transientstore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type mockedHistoryRetreiver struct {
mock.Mock
}
func (mock *mockedHistoryRetreiver) CollectionConfigAt(blockNum uint64, chaincodeName string) (*ledger.CollectionConfigInfo, error) {
args := mock.Called(blockNum, chaincodeName)
return args.Get(0).(*ledger.CollectionConfigInfo), args.Error(1)
}
func (mock *mockedHistoryRetreiver) MostRecentCollectionConfigBelow(blockNum uint64, chaincodeName string) (*ledger.CollectionConfigInfo, error) {
args := mock.Called(blockNum, chaincodeName)
return args.Get(0).(*ledger.CollectionConfigInfo), args.Error(1)
}
type mockedDataStore struct {
mock.Mock
}
......@@ -62,7 +78,11 @@ func (mock *mockedRWSetScanner) Next() (*transientstore.EndorserPvtSimulationRes
}
func (mock *mockedRWSetScanner) NextWithConfig() (*transientstore.EndorserPvtSimulationResultsWithConfig, error) {
return nil, nil
args := mock.Called()
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*transientstore.EndorserPvtSimulationResultsWithConfig), args.Error(1)
}
/*
......@@ -78,29 +98,44 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
namespace := "testChaincodeName1"
collectionName := "testCollectionName"
rwSetScanner.On("Next").Return(&transientstore.EndorserPvtSimulationResults{
ReceivedAtBlockHeight: 2,
PvtSimulationResults: nil,
}, nil).Once().On("Next").Return(&transientstore.EndorserPvtSimulationResults{
rwSetScanner.On("NextWithConfig").Return(&transientstore.EndorserPvtSimulationResultsWithConfig{
ReceivedAtBlockHeight: 2,
PvtSimulationResultsWithConfig: nil,
}, nil).Once().On("NextWithConfig").Return(&transientstore.EndorserPvtSimulationResultsWithConfig{
ReceivedAtBlockHeight: 2,
PvtSimulationResults: &rwset.TxPvtReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV,
NsPvtRwset: []*rwset.NsPvtReadWriteSet{
{
Namespace: namespace,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
{
CollectionName: collectionName,
Rwset: []byte{1, 2},
PvtSimulationResultsWithConfig: &transientstore2.TxPvtReadWriteSetWithConfigInfo{
PvtRwset: &rwset.TxPvtReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV,
NsPvtRwset: []*rwset.NsPvtReadWriteSet{
{
Namespace: namespace,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
{
CollectionName: collectionName,
Rwset: []byte{1, 2},
},
},
},
{
Namespace: namespace,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
{
CollectionName: collectionName,
Rwset: []byte{3, 4},
},
},
},
},
{
Namespace: namespace,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
},
CollectionConfigs: map[string]*common.CollectionConfigPackage{
namespace: {
Config: []*common.CollectionConfig{
{
CollectionName: collectionName,
Rwset: []byte{3, 4},
Payload: &common.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &common.StaticCollectionConfig{
Name: collectionName,
},
},
},
},
},
......@@ -108,7 +143,7 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
},
}, nil).
Once(). // return only once results, next call should return and empty result
On("Next").Return(nil, nil)
On("NextWithConfig").Return(nil, nil)
dataStore.On("LedgerHeight").Return(uint64(1), nil)
dataStore.On("GetTxPvtRWSetByTxid", "testTxID", mock.Anything).Return(rwSetScanner, nil)
......@@ -127,14 +162,12 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
assertion := assert.New(t)
assertion.NotNil(rwSets)
assertion.NotEmpty(rwSets)
assertion.Equal(2, len(rwSets))
assertion.NotEmpty(rwSets.RWSet)
assertion.Equal(2, len(rwSets.RWSet))
var mergedRWSet []byte
for _, rws := range rwSets {
for _, rw := range rws {
mergedRWSet = append(mergedRWSet, rw)
}
for _, rws := range rwSets.RWSet {
mergedRWSet = append(mergedRWSet, rws...)
}
assertion.Equal([]byte{1, 2, 3, 4}, mergedRWSet)
......@@ -178,6 +211,22 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) {
dataStore.On("LedgerHeight").Return(uint64(10), nil)
dataStore.On("GetPvtDataByNum", uint64(5), mock.Anything).Return(result, nil)
historyRetreiver := &mockedHistoryRetreiver{}
historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, namespace).Return(&ledger.CollectionConfigInfo{
CollectionConfig: &common.CollectionConfigPackage{
Config: []*common.CollectionConfig{
{
Payload: &common.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &common.StaticCollectionConfig{
Name: collectionName,
},
},
},
},
},
}, nil)
dataStore.On("GetConfigHistoryRetriever").Return(historyRetreiver, nil)
retriever := NewDataRetriever(dataStore)
// Request digest for private data which is greater than current ledger height
......@@ -193,13 +242,11 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) {
assertion := assert.New(t)
assertion.NotNil(rwSets)
assertion.NotEmpty(rwSets)
assertion.Equal(2, len(rwSets))
assertion.Equal(2, len(rwSets.RWSet))
var mergedRWSet []byte
for _, rws := range rwSets {
for _, rw := range rws {
mergedRWSet = append(mergedRWSet, rw)
}
for _, rws := range rwSets.RWSet {
mergedRWSet = append(mergedRWSet, rws...)
}
assertion.Equal([]byte{1, 2, 3, 4}, mergedRWSet)
......@@ -214,7 +261,7 @@ func TestNewDataRetriever_FailGetPvtDataFromLedger(t *testing.T) {
dataStore.On("LedgerHeight").Return(uint64(10), nil)
dataStore.On("GetPvtDataByNum", uint64(5), mock.Anything).
Return(nil, errors.New("failing retreiving private data"))
Return(nil, errors.New("failing retrieving private data"))
retriever := NewDataRetriever(dataStore)
......@@ -229,9 +276,7 @@ func TestNewDataRetriever_FailGetPvtDataFromLedger(t *testing.T) {
})
assertion := assert.New(t)
assertion.NotNil(rwSets)
assertion.Empty(rwSets)
assertion.Nil(rwSets)
}
func TestNewDataRetriever_GetOnlyRelevantPvtData(t *testing.T) {
......@@ -280,6 +325,21 @@ func TestNewDataRetriever_GetOnlyRelevantPvtData(t *testing.T) {
dataStore.On("LedgerHeight").Return(uint64(10), nil)
dataStore.On("GetPvtDataByNum", uint64(5), mock.Anything).Return(result, nil)
historyRetreiver := &mockedHistoryRetreiver{}
historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, namespace).Return(&ledger.CollectionConfigInfo{
CollectionConfig: &common.CollectionConfigPackage{
Config: []*common.CollectionConfig{
{
Payload: &common.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &common.StaticCollectionConfig{
Name: collectionName,
},
},
},
},
},
}, nil)
dataStore.On("GetConfigHistoryRetriever").Return(historyRetreiver, nil)
retriever := NewDataRetriever(dataStore)
......@@ -296,13 +356,11 @@ func TestNewDataRetriever_GetOnlyRelevantPvtData(t *testing.T) {
assertion := assert.New(t)
assertion.NotNil(rwSets)
assertion.NotEmpty(rwSets)
assertion.Equal(2, len(rwSets))
assertion.Equal(2, len(rwSets.RWSet))
var mergedRWSet []byte
for _, rws := range rwSets {
for _, rw := range rws {
mergedRWSet = append(mergedRWSet, rw)
}
for _, rws := range rwSets.RWSet {
mergedRWSet = append(mergedRWSet, rws...)
}
assertion.Equal([]byte{1, 2}, mergedRWSet)
......
......@@ -37,21 +37,31 @@ type collectionAccessPolicyMock struct {
}
func (mock *collectionAccessPolicyMock) AccessFilter() privdata.Filter {
return func(_ common.SignedData) bool {
return true
}
args := mock.Called()
return args.Get(0).(privdata.Filter)
}
func (mock *collectionAccessPolicyMock) RequiredPeerCount() int {
return 1
args := mock