Commit 9e65f859 authored by Yacov Manevich's avatar Yacov Manevich Committed by Gerrit Code Review
Browse files

Merge "[FAB-10742] Batch retrive of pvt data from ledger"

parents b5ee20f7 24078dff
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"time" "time"
pb "github.com/golang/protobuf/proto" pb "github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/bccsp/factory"
util2 "github.com/hyperledger/fabric/common/util" util2 "github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/common/privdata" "github.com/hyperledger/fabric/core/common/privdata"
"github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger"
...@@ -35,6 +36,7 @@ import ( ...@@ -35,6 +36,7 @@ import (
func init() { func init() {
viper.Set("peer.gossip.pvtData.pullRetryThreshold", time.Second*3) viper.Set("peer.gossip.pvtData.pullRetryThreshold", time.Second*3)
factory.InitFactories(nil)
} }
type persistCall struct { type persistCall struct {
......
...@@ -22,9 +22,13 @@ import ( ...@@ -22,9 +22,13 @@ import (
type StorageDataRetriever interface { type StorageDataRetriever interface {
// CollectionRWSet retrieves for give digest relevant private data if // CollectionRWSet retrieves for give digest relevant private data if
// available otherwise returns nil // available otherwise returns nil
CollectionRWSet(dig *gossip2.PvtDataDigest) (*util.PrivateRWSetWithConfig, error) CollectionRWSet(dig []*gossip2.PvtDataDigest, blockNum uint64) (Dig2PvtRWSetWithConfig, error)
} }
//go:generate mockery -dir . -name DataStore -case underscore -output mocks/
//go:generate mockery -dir ../../core/transientstore/ -name RWSetScanner -case underscore -output mocks/
//go:generate mockery -dir ../../core/ledger/ -name ConfigHistoryRetriever -case underscore -output mocks/
// DataStore defines set of APIs need to get private data // DataStore defines set of APIs need to get private data
// from underlined data store // from underlined data store
type DataStore interface { type DataStore interface {
...@@ -56,70 +60,110 @@ func NewDataRetriever(store DataStore) StorageDataRetriever { ...@@ -56,70 +60,110 @@ func NewDataRetriever(store DataStore) StorageDataRetriever {
// CollectionRWSet retrieves for give digest relevant private data if // CollectionRWSet retrieves for give digest relevant private data if
// available otherwise returns nil // available otherwise returns nil
func (dr *dataRetriever) CollectionRWSet(dig *gossip2.PvtDataDigest) (*util.PrivateRWSetWithConfig, error) { func (dr *dataRetriever) CollectionRWSet(digests []*gossip2.PvtDataDigest, blockNum uint64) (Dig2PvtRWSetWithConfig, error) {
filter := map[string]ledger.PvtCollFilter{
dig.Namespace: map[string]bool{
dig.Collection: true,
},
}
height, err := dr.store.LedgerHeight() height, err := dr.store.LedgerHeight()
if err != nil { if err != nil {
// if there is an error getting info from the ledger, we need to try to read from transient store // if there is an error getting info from the ledger, we need to try to read from transient store
return nil, errors.New(fmt.Sprint("Wasn't able to read ledger height, due to", err, "trying to lookup "+ return nil, fmt.Errorf("wasn't able to read ledger height, due to %s", err)
"private data from transient store, namespace", dig.Namespace, "collection name", dig.Collection, "txID", dig.TxId))
} }
if height <= dig.BlockSeq { if height <= blockNum {
logger.Debug("Current ledger height ", height, "is below requested block sequence number", 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", blockNum, "retrieving private data from transient store")
dig.Collection, "txID", dig.TxId)
} }
if height <= dig.BlockSeq { // Check whenever current ledger height is equal or above block sequence num. results := make(Dig2PvtRWSetWithConfig)
return dr.fromTransientStore(dig, filter) if height <= blockNum { // Check whenever current ledger height is equal or below block sequence num.
for _, dig := range digests {
filter := map[string]ledger.PvtCollFilter{
dig.Namespace: map[string]bool{
dig.Collection: true,
},
}
pvtRWSet, err := dr.fromTransientStore(dig, filter)
if err != nil {
logger.Errorf("couldn't read from transient store private read-write set, "+
"digest %+v, because of %s", dig, err)
continue
}
results[DigKey{
Namespace: dig.Namespace,
Collection: dig.Collection,
TxId: dig.TxId,
BlockSeq: dig.BlockSeq,
SeqInBlock: dig.SeqInBlock,
}] = pvtRWSet
}
return results, nil
} }
// Since ledger height is above block sequence number private data is might be available in the ledger // Since ledger height is above block sequence number private data is might be available in the ledger
return dr.fromLedger(dig, filter) return dr.fromLedger(digests, blockNum)
} }
func (dr *dataRetriever) fromLedger(dig *gossip2.PvtDataDigest, filter map[string]ledger.PvtCollFilter) (*util.PrivateRWSetWithConfig, error) { func (dr *dataRetriever) fromLedger(digests []*gossip2.PvtDataDigest, blockNum uint64) (Dig2PvtRWSetWithConfig, error) {
results := &util.PrivateRWSetWithConfig{} filter := make(map[string]ledger.PvtCollFilter)
pvtData, err := dr.store.GetPvtDataByNum(dig.BlockSeq, filter) for _, dig := range digests {
if err != nil { if _, ok := filter[dig.Namespace]; !ok {
return nil, errors.New(fmt.Sprint("wasn't able to obtain private data for collection", dig.Collection, filter[dig.Namespace] = make(ledger.PvtCollFilter)
"txID", dig.TxId, "block sequence number", dig.BlockSeq, "due to", err))
}
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) filter[dig.Namespace][dig.Collection] = true
results.RWSet = append(results.RWSet, pvtRWSet...)
} }
confHistoryRetriever, err := dr.store.GetConfigHistoryRetriever() pvtData, err := dr.store.GetPvtDataByNum(blockNum, filter)
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprint("cannot obtain configuration history retriever, for collection,", dig.Collection, return nil, errors.New(fmt.Sprint("wasn't able to obtain private data, block sequence number", blockNum, "due to", err))
"txID", dig.TxId, "block sequence number", dig.BlockSeq, "due to", err))
} }
configInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace) results := make(Dig2PvtRWSetWithConfig)
if err != nil { for _, dig := range digests {
return nil, errors.New(fmt.Sprint("cannot find recent collection config update below block sequence = ", dig.BlockSeq, dig := dig
"collection name =", dig.Collection, "for chaincode", dig.Namespace)) pvtRWSetWithConfig := &util.PrivateRWSetWithConfig{}
} for _, data := range pvtData {
if data.WriteSet == nil {
logger.Warning("Received nil write set for collection tx in block", data.SeqInBlock, "block number", blockNum)
continue
}
if configInfo == nil { // private data doesn't hold rwsets for namespace and collection or
return nil, errors.New(fmt.Sprint("no collection config update below block sequence = ", dig.BlockSeq, // belongs to different transaction
"collection name =", dig.Collection, "for chaincode", dig.Namespace, "is available")) if !data.Has(dig.Namespace, dig.Collection) || data.SeqInBlock != dig.SeqInBlock {
} continue
configs := dr.extractCollectionConfigs(configInfo.CollectionConfig, dig) }
if configs == nil {
return nil, errors.New(fmt.Sprint("no collection config was found for collection", dig.Collection, pvtRWSet := dr.extractPvtRWsets(data.WriteSet.NsPvtRwset, dig.Namespace, dig.Collection)
"namespace", dig.Namespace, "txID", dig.TxId)) pvtRWSetWithConfig.RWSet = append(pvtRWSetWithConfig.RWSet, pvtRWSet...)
}
confHistoryRetriever, err := dr.store.GetConfigHistoryRetriever()
if err != nil {
return nil, errors.New(fmt.Sprint("cannot obtain configuration history retriever, for collection,", dig.Collection,
"txID", dig.TxId, "block sequence number", dig.BlockSeq, "due to", err))
}
configInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)
if err != nil {
return nil, errors.New(fmt.Sprint("cannot find recent collection config update below block sequence = ", dig.BlockSeq,
"collection name =", dig.Collection, "for chaincode", dig.Namespace))
}
if configInfo == nil {
return nil, errors.New(fmt.Sprint("no collection config update below block sequence = ", dig.BlockSeq,
"collection name =", dig.Collection, "for chaincode", dig.Namespace, "is available"))
}
configs := dr.extractCollectionConfigs(configInfo.CollectionConfig, dig)
if configs == nil {
return nil, errors.New(fmt.Sprint("no collection config was found for collection ", dig.Collection,
" namespace ", dig.Namespace, " txID ", dig.TxId))
}
pvtRWSetWithConfig.CollectionConfig = configs
results[DigKey{
Namespace: dig.Namespace,
Collection: dig.Collection,
TxId: dig.TxId,
BlockSeq: dig.BlockSeq,
SeqInBlock: dig.SeqInBlock,
}] = pvtRWSetWithConfig
} }
results.CollectionConfig = configs
return results, nil return results, nil
} }
...@@ -182,13 +226,13 @@ func (dr *dataRetriever) extractPvtRWsets(pvtRWSets []*rwset.NsPvtReadWriteSet, ...@@ -182,13 +226,13 @@ func (dr *dataRetriever) extractPvtRWsets(pvtRWSets []*rwset.NsPvtReadWriteSet,
for _, nsws := range pvtRWSets { for _, nsws := range pvtRWSets {
// and in each namespace - iterate over all collections // and in each namespace - iterate over all collections
if nsws.Namespace != namespace { if nsws.Namespace != namespace {
logger.Warning("Received private data namespace", nsws.Namespace, "instead of", namespace, "skipping...") logger.Warning("Received private data namespace ", nsws.Namespace, " instead of ", namespace, " skipping...")
continue continue
} }
for _, col := range nsws.CollectionPvtRwset { for _, col := range nsws.CollectionPvtRwset {
// This isn't the collection we're looking for // This isn't the collection we're looking for
if col.CollectionName != collectionName { if col.CollectionName != collectionName {
logger.Warning("Received private data collection", col.CollectionName, "instead of", collectionName, "skipping...") logger.Warning("Received private data collection ", col.CollectionName, " instead of ", collectionName, " skipping...")
continue continue
} }
// Add the collection pRWset to the accumulated set // Add the collection pRWset to the accumulated set
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/transientstore" "github.com/hyperledger/fabric/core/transientstore"
"github.com/hyperledger/fabric/gossip/privdata/mocks"
"github.com/hyperledger/fabric/protos/common" "github.com/hyperledger/fabric/protos/common"
gossip2 "github.com/hyperledger/fabric/protos/gossip" gossip2 "github.com/hyperledger/fabric/protos/gossip"
"github.com/hyperledger/fabric/protos/ledger/rwset" "github.com/hyperledger/fabric/protos/ledger/rwset"
...@@ -20,71 +21,6 @@ import ( ...@@ -20,71 +21,6 @@ import (
"github.com/stretchr/testify/mock" "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
}
func (ds *mockedDataStore) GetConfigHistoryRetriever() (ledger.ConfigHistoryRetriever, error) {
args := ds.Called()
return args.Get(0).(ledger.ConfigHistoryRetriever), args.Error(1)
}
func (ds *mockedDataStore) GetTxPvtRWSetByTxid(txid string, filter ledger.PvtNsCollFilter) (transientstore.RWSetScanner, error) {
args := ds.Called(txid, filter)
return args.Get(0).(transientstore.RWSetScanner), args.Error(1)
}
func (ds *mockedDataStore) GetPvtDataByNum(blockNum uint64, filter ledger.PvtNsCollFilter) ([]*ledger.TxPvtData, error) {
args := ds.Called(blockNum, filter)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).([]*ledger.TxPvtData), args.Error(1)
}
func (ds *mockedDataStore) LedgerHeight() (uint64, error) {
args := ds.Called()
return args.Get(0).(uint64), args.Error(1)
}
type mockedRWSetScanner struct {
mock.Mock
}
func (mock *mockedRWSetScanner) Close() {
}
func (mock *mockedRWSetScanner) Next() (*transientstore.EndorserPvtSimulationResults, error) {
args := mock.Called()
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*transientstore.EndorserPvtSimulationResults), args.Error(1)
}
func (mock *mockedRWSetScanner) NextWithConfig() (*transientstore.EndorserPvtSimulationResultsWithConfig, error) {
args := mock.Called()
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*transientstore.EndorserPvtSimulationResultsWithConfig), args.Error(1)
}
/* /*
Test checks following scenario, it tries to obtain private data for Test checks following scenario, it tries to obtain private data for
given block sequence which is greater than available ledger height, given block sequence which is greater than available ledger height,
...@@ -92,12 +28,13 @@ func (mock *mockedRWSetScanner) NextWithConfig() (*transientstore.EndorserPvtSim ...@@ -92,12 +28,13 @@ func (mock *mockedRWSetScanner) NextWithConfig() (*transientstore.EndorserPvtSim
*/ */
func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) { func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
t.Parallel() t.Parallel()
dataStore := &mockedDataStore{} dataStore := &mocks.DataStore{}
rwSetScanner := &mockedRWSetScanner{} rwSetScanner := &mocks.RWSetScanner{}
namespace := "testChaincodeName1" namespace := "testChaincodeName1"
collectionName := "testCollectionName" collectionName := "testCollectionName"
rwSetScanner.On("Close")
rwSetScanner.On("NextWithConfig").Return(&transientstore.EndorserPvtSimulationResultsWithConfig{ rwSetScanner.On("NextWithConfig").Return(&transientstore.EndorserPvtSimulationResultsWithConfig{
ReceivedAtBlockHeight: 2, ReceivedAtBlockHeight: 2,
PvtSimulationResultsWithConfig: nil, PvtSimulationResultsWithConfig: nil,
...@@ -107,24 +44,8 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) { ...@@ -107,24 +44,8 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
PvtRwset: &rwset.TxPvtReadWriteSet{ PvtRwset: &rwset.TxPvtReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV, DataModel: rwset.TxReadWriteSet_KV,
NsPvtRwset: []*rwset.NsPvtReadWriteSet{ NsPvtRwset: []*rwset.NsPvtReadWriteSet{
{ pvtReadWriteSet(namespace, collectionName, []byte{1, 2}),
Namespace: namespace, pvtReadWriteSet(namespace, collectionName, []byte{3, 4}),
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
{
CollectionName: collectionName,
Rwset: []byte{1, 2},
},
},
},
{
Namespace: namespace,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
{
CollectionName: collectionName,
Rwset: []byte{3, 4},
},
},
},
}, },
}, },
CollectionConfigs: map[string]*common.CollectionConfigPackage{ CollectionConfigs: map[string]*common.CollectionConfigPackage{
...@@ -152,22 +73,30 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) { ...@@ -152,22 +73,30 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
// Request digest for private data which is greater than current ledger height // Request digest for private data which is greater than current ledger height
// to make it query transient store for missed private data // to make it query transient store for missed private data
rwSets, err := retriever.CollectionRWSet(&gossip2.PvtDataDigest{ rwSets, err := retriever.CollectionRWSet([]*gossip2.PvtDataDigest{{
Namespace: namespace, Namespace: namespace,
Collection: collectionName, Collection: collectionName,
BlockSeq: 2, BlockSeq: 2,
TxId: "testTxID", TxId: "testTxID",
SeqInBlock: 1, SeqInBlock: 1,
}) }}, 2)
assertion := assert.New(t) assertion := assert.New(t)
assertion.NoError(err) assertion.NoError(err)
assertion.NotNil(rwSets) assertion.NotEmpty(rwSets)
assertion.NotEmpty(rwSets.RWSet) dig2pvtRWSet := rwSets[DigKey{
assertion.Equal(2, len(rwSets.RWSet)) Namespace: namespace,
Collection: collectionName,
BlockSeq: 2,
TxId: "testTxID",
SeqInBlock: 1,
}]
assertion.NotNil(dig2pvtRWSet)
pvtRWSets := dig2pvtRWSet.RWSet
assertion.Equal(2, len(pvtRWSets))
var mergedRWSet []byte var mergedRWSet []byte
for _, rws := range rwSets.RWSet { for _, rws := range pvtRWSets {
mergedRWSet = append(mergedRWSet, rws...) mergedRWSet = append(mergedRWSet, rws...)
} }
...@@ -181,7 +110,7 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) { ...@@ -181,7 +110,7 @@ func TestNewDataRetriever_GetDataFromTransientStore(t *testing.T) {
*/ */
func TestNewDataRetriever_GetDataFromLedger(t *testing.T) { func TestNewDataRetriever_GetDataFromLedger(t *testing.T) {
t.Parallel() t.Parallel()
dataStore := &mockedDataStore{} dataStore := &mocks.DataStore{}
namespace := "testChaincodeName1" namespace := "testChaincodeName1"
collectionName := "testCollectionName" collectionName := "testCollectionName"
...@@ -190,20 +119,8 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) { ...@@ -190,20 +119,8 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) {
WriteSet: &rwset.TxPvtReadWriteSet{ WriteSet: &rwset.TxPvtReadWriteSet{
DataModel: rwset.TxReadWriteSet_KV, DataModel: rwset.TxReadWriteSet_KV,
NsPvtRwset: []*rwset.NsPvtReadWriteSet{ NsPvtRwset: []*rwset.NsPvtReadWriteSet{
{ pvtReadWriteSet(namespace, collectionName, []byte{1, 2}),
Namespace: namespace, pvtReadWriteSet(namespace, collectionName, []byte{3, 4}),
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{{
CollectionName: collectionName,
Rwset: []byte{1, 2},
}},
},
{
Namespace: namespace,
CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{{
CollectionName: collectionName,
Rwset: []byte{3, 4},
}},
},
}, },
}, },
SeqInBlock: 1, SeqInBlock: 1,
...@@ -212,42 +129,37 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) { ...@@ -212,42 +129,37 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) {
dataStore.On("LedgerHeight").Return(uint64(10), nil) dataStore.On("LedgerHeight").Return(uint64(10), nil)
dataStore.On("GetPvtDataByNum", uint64(5), mock.Anything).Return(result, nil) dataStore.On("GetPvtDataByNum", uint64(5), mock.Anything).Return(result, nil)
historyRetreiver := &mockedHistoryRetreiver{} historyRetreiver := &mocks.ConfigHistoryRetriever{}
historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, namespace).Return(&ledger.CollectionConfigInfo{ historyRetreiver.On("MostRecentCollectionConfigBelow", mock.Anything, namespace).Return(newCollectionConfig(collectionName), nil)
CollectionConfig: &common.CollectionConfigPackage{
Config: []*common.CollectionConfig{
{
Payload: &common.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &common.StaticCollectionConfig{
Name: collectionName,
},
},
},
},
},
}, nil)
dataStore.On("GetConfigHistoryRetriever").Return(historyRetreiver, nil) dataStore.On("GetConfigHistoryRetriever").Return(historyRetreiver, nil)
retriever := NewDataRetriever(dataStore) retriever := NewDataRetriever(dataStore)
// Request digest for private data which is greater than current ledger height // Request digest for private data which is greater than current ledger height
// to make it query ledger for missed private data // to make it query ledger for missed private data
rwSets, err := retriever.CollectionRWSet(&gossip2.PvtDataDigest{ rwSets, err := retriever.CollectionRWSet([]*gossip2.PvtDataDigest{{
Namespace: namespace, Namespace: namespace,
Collection: collectionName, Collection: collectionName,
BlockSeq: uint64(5), BlockSeq: uint64(5),
TxId: "testTxID", TxId: "testTxID",
SeqInBlock: 1, SeqInBlock: 1,
}) }}, uint64(5))
assertion := assert.New(t) assertion := assert.New(t)
assertion.NoError(err) assertion.NoError(err)
assertion.NotNil(rwSets)
assertion.NotEmpty(rwSets) assertion.NotEmpty(rwSets)
assertion.Equal(2, len(rwSets.RWSet)) pvtRWSet := rwSets[DigKey{
Namespace: namespace,
Collection: collectionName,
BlockSeq: 5,
TxId: "testTxID",
SeqInBlock: 1,
}]
assertion.NotEmpty(pvtRWSet)
assertion.Equal(2, len(pvtRWSet.RWSet))
var mergedRWSet []byte var mergedRWSet []byte
for _, rws := range rwSets.RWSet { for _, rws := range pvtRWSet.RWSet {
mergedRWSet = append(mergedRWSet, rws...) mergedRWSet = append(mergedRWSet, rws...)
} }
...@@ -256,7 +168,7 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) { ...@@ -256,7 +168,7 @@ func TestNewDataRetriever_GetDataFromLedger(t *testing.T) {
func TestNewDataRetriever_FailGetPvtDataFromLedger(t *testing.T) { func TestNewDataRetriever_FailGetPvtDataFromLedger(t *testing.T) {
t.Parallel() t.Parallel()
dataStore := &mockedDataStore{} dataStore := &mocks.DataStore{}
namespace := "testChaincodeName1" namespace := "testChaincodeName1"
collectionName := "testCollectionName" collectionName := "testCollectionName"
...@@ -269,22 +181,22 @@ func TestNewDataRetriever_FailGetPvtDataFromLedger(t *testing.T) { ...@@ -269,22 +181,22 @@ func TestNewDataRetriever_FailGetPvtDataFromLedger(t *testing.T) {
// Request digest for private data which is greater than current ledger height // Request digest for private data which is greater than current ledger height
// to make it query transient store for missed private data // to make it query transient store for missed private data
rwSets, err := retriever.CollectionRWSet(&gossip2.PvtDataDigest{ rwSets, err := retriever.CollectionRWSet([]*gossip2.PvtDataDigest{{
Namespace: namespace, Namespace: namespace,
Collection: collectionName, Collection: collectionName,
BlockSeq: uint64(5), BlockSeq: uint64(5),
TxId: "testTxID", TxId: "testTxID",
SeqInBlock: 1, SeqInBlock: 1,
}) }}, uint64(5))
assertion := assert.New(t) assertion := assert.New(t)
assertion.Error(err) assertion.Error(err)
assertion.Nil(rwSets) assertion.Empty(rwSets)
} }
func TestNewDataRetriever_GetOnlyRelevantPvtData(t *testing.T) { func TestNewDataRetriever_GetOnlyRelevantPvtData(t *testing.T) {
t.Parallel() t.Parallel()
dataStore := &mockedDataStore{} dataStore := &mocks.DataStore{}
namespace := "testChaincodeName1"