Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit bda01c9

Browse files
author
Baha Shaaban
committed
[FABG-822] test pvt data reconciliation
Change-Id: I71a0310d28db101a82f68aa15352c42c9a584247 Signed-off-by: Baha Shaaban <baha.shaaban@securekey.com>
1 parent 7df511b commit bda01c9

File tree

5 files changed

+264
-2
lines changed

5 files changed

+264
-2
lines changed

test/fixtures/dockerenv/docker-compose.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ services:
128128
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/tls/peer/ca.crt
129129
- CORE_PEER_TLS_CLIENTAUTHREQUIRED
130130
- CORE_PEER_TLS_CLIENTROOTCAS_FILES
131+
- CORE_PEER_GOSSIP_PVTDATA_RECONCILESLEEPINTERVAL=1s
131132
# # the following setting starts chaincode containers on the same
132133
# # bridge network as the peers
133134
# # https://docs.docker.com/compose/networking/
@@ -186,6 +187,7 @@ services:
186187
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/tls/peer/ca.crt
187188
- CORE_PEER_TLS_CLIENTAUTHREQUIRED
188189
- CORE_PEER_TLS_CLIENTROOTCAS_FILES
190+
- CORE_PEER_GOSSIP_PVTDATA_RECONCILESLEEPINTERVAL=1s
189191
# # the following setting starts chaincode containers on the same
190192
# # bridge network as the peers
191193
# # https://docs.docker.com/compose/networking/
@@ -246,6 +248,7 @@ services:
246248
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/tls/peer/ca.crt
247249
- CORE_PEER_TLS_CLIENTAUTHREQUIRED
248250
- CORE_PEER_TLS_CLIENTROOTCAS_FILES
251+
- CORE_PEER_GOSSIP_PVTDATA_RECONCILESLEEPINTERVAL=1s
249252
# # the following setting starts chaincode containers on the same
250253
# # bridge network as the peers
251254
# # https://docs.docker.com/compose/networking/
@@ -305,6 +308,7 @@ services:
305308
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/tls/peer/ca.crt
306309
- CORE_PEER_TLS_CLIENTAUTHREQUIRED
307310
- CORE_PEER_TLS_CLIENTROOTCAS_FILES
311+
- CORE_PEER_GOSSIP_PVTDATA_RECONCILESLEEPINTERVAL=1s
308312
# # the following setting starts chaincode containers on the same
309313
# # bridge network as the peers
310314
# # https://docs.docker.com/compose/networking/

test/integration/base_test_setup.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,27 @@ func InstantiateChaincode(resMgmt *resmgmt.Client, channelID, ccName, ccPath, cc
325325
)
326326
}
327327

328+
// UpgradeChaincode upgrades the given chaincode on the given channel
329+
func UpgradeChaincode(resMgmt *resmgmt.Client, channelID, ccName, ccPath, ccVersion string, ccPolicyStr string, args [][]byte, collConfigs ...*cb.CollectionConfig) (resmgmt.UpgradeCCResponse, error) {
330+
ccPolicy, err := cauthdsl.FromString(ccPolicyStr)
331+
if err != nil {
332+
return resmgmt.UpgradeCCResponse{}, errors.Wrapf(err, "error creating CC policy [%s]", ccPolicyStr)
333+
}
334+
335+
return resMgmt.UpgradeCC(
336+
channelID,
337+
resmgmt.UpgradeCCRequest{
338+
Name: ccName,
339+
Path: ccPath,
340+
Version: ccVersion,
341+
Args: args,
342+
Policy: ccPolicy,
343+
CollConfig: collConfigs,
344+
},
345+
resmgmt.WithRetry(retry.DefaultResMgmtOpts),
346+
)
347+
}
348+
328349
// DiscoverLocalPeers queries the local peers for the given MSP context and returns all of the peers. If
329350
// the number of peers does not match the expected number then an error is returned.
330351
func DiscoverLocalPeers(ctxProvider contextAPI.ClientProvider, expectedPeers int) ([]fabAPI.Peer, error) {

test/integration/e2e/configless/metricconfig_override_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ var (
3838

3939
type exampleOperation struct{}
4040

41-
//OperationCfg overrides MetricsConfig's OperationConfig function which returns the operations config
41+
//OperationCfg overrides MetricsConfig's OperationConfig function which returns the operations system config
4242
func (m *exampleOperation) OperationCfg() cfg.OperationConfig {
4343
return operationConfig
4444
}
4545

4646
type exampleMetric struct{}
4747

48-
//MetricCfg overrides MetricsConfig's OperationConfig function which returns the operations config
48+
//MetricCfg overrides MetricsConfig's MetricConfig function which returns the metrics specific config
4949
func (m *exampleMetric) MetricCfg() cfg.MetricConfig {
5050
return metricConfig
5151
}

test/integration/pkg/client/channel/channel_client_pvt_test.go

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"strings"
1515
"sync"
1616
"testing"
17+
"time"
1718

1819
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
1920
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status"
@@ -366,3 +367,221 @@ func newCollectionConfig(colName, policy string, reqPeerCount, maxPeerCount int3
366367
},
367368
}, nil
368369
}
370+
371+
// TestPrivateDataReconcilePutAndGet tests put and get for private data with reconciliation of missing eligible data on some peers (org2's peers)
372+
// the idea to test private data reconciliation is to set a test collection with a policy of 1 member org, put/get private data
373+
// then update the collection config with a new policy of 2 member orgs, private data should be reconciled on peers of the newly added org
374+
func TestPrivateDataReconcilePutAndGet(t *testing.T) {
375+
sdk := mainSDK
376+
singleOrgPolicy := "AND('Org1MSP.member')"
377+
multiOrgsPolicy := "OR('Org1MSP.member','Org2MSP.member')"
378+
coll1 := "collectionx"
379+
ccID := integration.GenerateExamplePvtID(true)
380+
orgsContext := setupMultiOrgContext(t, sdk)
381+
382+
// instantiate and install CC on all peers using collection policy for org1 only then put/get some pvt data
383+
runPvtDataPreReconcilePutAndGet(t, sdk, orgsContext, singleOrgPolicy, ccID, coll1)
384+
// now verify pvt data is not available on org2 peers
385+
verifyPvtDataPreReconcileGet(t, sdk, ccID, coll1)
386+
// upgrade CC to include org2 in collection policy then verify pvt data is available on org2's peers
387+
runPvtDataPostReconcileGet(t, sdk, orgsContext, multiOrgsPolicy, ccID, coll1)
388+
}
389+
390+
func runPvtDataPreReconcilePutAndGet(t *testing.T, sdk *fabsdk.FabricSDK, orgsContext []*integration.OrgContext, policy, ccID, coll1 string) {
391+
err := integration.EnsureChannelCreatedAndPeersJoined(t, sdk, orgChannelID, "orgchannel.tx", orgsContext)
392+
require.NoError(t, err)
393+
394+
collConfig, err := newCollectionConfig(coll1, policy, 0, 2, 1000)
395+
require.NoError(t, err)
396+
397+
err = integration.InstallExamplePvtChaincode(orgsContext, ccID)
398+
require.NoError(t, err)
399+
err = integration.InstantiateExamplePvtChaincode(orgsContext, orgChannelID, ccID, policy, collConfig)
400+
require.NoError(t, err)
401+
402+
ctxProvider := sdk.ChannelContext(orgChannelID, fabsdk.WithUser(org1User), fabsdk.WithOrg(org1Name))
403+
404+
chClient, err := channel.New(ctxProvider)
405+
require.NoError(t, err)
406+
407+
key1 := "key1"
408+
key2 := "key2"
409+
key3 := "key3"
410+
value1 := "pvtValue1"
411+
value2 := "pvtValue2"
412+
value3 := "pvtValue3"
413+
414+
response, err := chClient.Query(
415+
channel.Request{
416+
ChaincodeID: ccID,
417+
Fcn: "getprivate",
418+
Args: [][]byte{[]byte(coll1), []byte(key1)},
419+
},
420+
channel.WithRetry(retry.DefaultChannelOpts),
421+
)
422+
require.NoError(t, err)
423+
t.Logf("Got response payload: [%s]", string(response.Payload))
424+
require.Nil(t, response.Payload)
425+
426+
response, err = chClient.Query(
427+
channel.Request{
428+
ChaincodeID: ccID,
429+
Fcn: "getprivatebyrange",
430+
Args: [][]byte{[]byte(coll1), []byte(key1), []byte(key3)},
431+
},
432+
channel.WithRetry(retry.DefaultChannelOpts),
433+
)
434+
require.NoError(t, err)
435+
t.Logf("Got response payload: [%s]", string(response.Payload))
436+
require.Empty(t, string(response.Payload))
437+
438+
response, err = chClient.Execute(
439+
channel.Request{
440+
ChaincodeID: ccID,
441+
Fcn: "putprivate",
442+
Args: [][]byte{[]byte(coll1), []byte(key1), []byte(value1)},
443+
},
444+
channel.WithRetry(retry.DefaultChannelOpts),
445+
)
446+
require.NoError(t, err)
447+
require.NotEmptyf(t, response.Responses, "expecting at least one response")
448+
449+
response, err = chClient.Execute(
450+
channel.Request{
451+
ChaincodeID: ccID,
452+
Fcn: "putprivate",
453+
Args: [][]byte{[]byte(coll1), []byte(key2), []byte(value2)},
454+
},
455+
channel.WithRetry(retry.DefaultChannelOpts),
456+
)
457+
require.NoError(t, err)
458+
require.NotEmptyf(t, response.Responses, "expecting at least one response")
459+
460+
response, err = chClient.Execute(
461+
channel.Request{
462+
ChaincodeID: ccID,
463+
Fcn: "putprivate",
464+
Args: [][]byte{[]byte(coll1), []byte(key3), []byte(value3)},
465+
},
466+
channel.WithRetry(retry.TestRetryOpts),
467+
)
468+
require.NoError(t, err)
469+
require.NotEmptyf(t, response.Responses, "expecting at least one response")
470+
471+
response, err = chClient.Query(
472+
channel.Request{
473+
ChaincodeID: ccID,
474+
Fcn: "getprivate",
475+
Args: [][]byte{[]byte(coll1), []byte(key1)},
476+
},
477+
channel.WithRetry(retry.TestRetryOpts),
478+
)
479+
require.NoError(t, err)
480+
t.Logf("Got response payload for getprivate: %s", string(response.Payload))
481+
require.Equal(t, value1, string(response.Payload))
482+
483+
response, err = chClient.Query(
484+
channel.Request{
485+
ChaincodeID: ccID,
486+
Fcn: "getprivatebyrange",
487+
Args: [][]byte{[]byte(coll1), []byte(key1), []byte(key3)},
488+
},
489+
channel.WithRetry(retry.DefaultChannelOpts),
490+
)
491+
require.NoError(t, err)
492+
t.Logf("Got response payload for getprivatebyrange: [%s]", string(response.Payload))
493+
require.NotEmpty(t, string(response.Payload))
494+
}
495+
496+
func verifyPvtDataPreReconcileGet(t *testing.T, sdk *fabsdk.FabricSDK, ccID, coll1 string) {
497+
// create ctxProvider for org2 to query org2 peers for pvt data (should be empty)
498+
ctxProvider := sdk.ChannelContext(orgChannelID, fabsdk.WithUser(org1User), fabsdk.WithOrg(org2Name))
499+
500+
// org2 peers are the only targets to test pre reconciliation as they should not have the pvt data as per the collection policy (singleOrgPolicy)
501+
org2TargetOpts := channel.WithTargetEndpoints("peer0.org2.example.com", "peer1.org2.example.com")
502+
chClient, err := channel.New(ctxProvider)
503+
require.NoError(t, err)
504+
505+
key1 := "key1"
506+
key3 := "key3"
507+
508+
response, err := chClient.Query(
509+
channel.Request{
510+
ChaincodeID: ccID,
511+
Fcn: "getprivate",
512+
Args: [][]byte{[]byte(coll1), []byte(key1)},
513+
},
514+
channel.WithRetry(retry.TestRetryOpts),
515+
org2TargetOpts, // query org2 peers to ensure they don't have pvt data
516+
)
517+
require.Error(t, err)
518+
t.Logf("Got response payload for getprivate: %s", string(response.Payload))
519+
require.Empty(t, response.Payload)
520+
521+
response, err = chClient.Query(
522+
channel.Request{
523+
ChaincodeID: ccID,
524+
Fcn: "getprivatebyrange",
525+
Args: [][]byte{[]byte(coll1), []byte(key1), []byte(key3)},
526+
},
527+
channel.WithRetry(retry.DefaultChannelOpts),
528+
org2TargetOpts, // query org2 peers to ensure they don't have pvt data
529+
)
530+
531+
// for some reason, the peer throws an error for getprivate cc invoke(Failed to handle GET_STATE. error: private data matching public hash version is not available.),
532+
// but not for getprivatebyrange cc invoke (it only returns empty payload)
533+
require.NoError(t, err)
534+
t.Logf("Got response payload for getprivatebyrange: [%s]", string(response.Payload))
535+
require.Empty(t, string(response.Payload))
536+
537+
}
538+
539+
func runPvtDataPostReconcileGet(t *testing.T, sdk *fabsdk.FabricSDK, orgsContext []*integration.OrgContext, policy, ccID, coll1 string) {
540+
collConfig, err := newCollectionConfig(coll1, policy, 0, 2, 1000)
541+
require.NoError(t, err)
542+
543+
// org2 peers are the only targets to test post reconciliation as they should have the pvt data after cc upgrade as per the new collection policy (multiOrgsPolicy)
544+
org2TargetOpts := channel.WithTargetEndpoints("peer0.org2.example.com", "peer1.org2.example.com")
545+
546+
err = integration.UpgradeExamplePvtChaincode(orgsContext, orgChannelID, ccID, policy, collConfig)
547+
require.NoError(t, err)
548+
549+
// wait for pvt data reconciliation occurs on peers of org2
550+
time.Sleep(2 * time.Second)
551+
552+
// create ctxProvider for org2 to query org2 peers for pvt data (should be not empty/reconciled)
553+
ctxProvider := sdk.ChannelContext(orgChannelID, fabsdk.WithUser(org1User), fabsdk.WithOrg(org2Name))
554+
555+
chClient, err := channel.New(ctxProvider)
556+
require.NoError(t, err)
557+
558+
key1 := "key1"
559+
key3 := "key3"
560+
value1 := "pvtValue1"
561+
562+
response, err := chClient.Query(
563+
channel.Request{
564+
ChaincodeID: ccID,
565+
Fcn: "getprivate",
566+
Args: [][]byte{[]byte(coll1), []byte(key1)},
567+
},
568+
channel.WithRetry(retry.TestRetryOpts),
569+
org2TargetOpts,
570+
)
571+
require.NoError(t, err)
572+
t.Logf("Got response payload for getprivate: %s", string(response.Payload))
573+
require.Equal(t, value1, string(response.Payload))
574+
575+
response, err = chClient.Query(
576+
channel.Request{
577+
ChaincodeID: ccID,
578+
Fcn: "getprivatebyrange",
579+
Args: [][]byte{[]byte(coll1), []byte(key1), []byte(key3)},
580+
},
581+
channel.WithRetry(retry.DefaultChannelOpts),
582+
org2TargetOpts,
583+
)
584+
require.NoError(t, err)
585+
t.Logf("Got response payload for getprivatebyrange: [%s]", string(response.Payload))
586+
require.NotEmpty(t, string(response.Payload))
587+
}

test/integration/prepare.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const (
3636
examplePvtCCName = "example_pvt_cc"
3737
examplePvtCCPath = "github.com/example_pvt_cc"
3838
examplePvtCCVersion = "v0"
39+
exampleUpgdPvtCCVer = "v1"
3940
)
4041

4142
// GenerateExamplePvtID supplies a chaincode name for example_pvt_cc
@@ -149,6 +150,23 @@ func InstantiateExamplePvtChaincode(orgs []*OrgContext, channelID, ccID, ccPolic
149150
return err
150151
}
151152

153+
// UpgradeExamplePvtChaincode upgrades the instantiated example pvt CC on the given channel
154+
func UpgradeExamplePvtChaincode(orgs []*OrgContext, channelID, ccID, ccPolicy string, collConfigs ...*cb.CollectionConfig) error {
155+
// first install the CC with the upgraded cc version
156+
ccPkg, err := packager.NewCCPackage(examplePvtCCPath, GetDeployPath())
157+
if err != nil {
158+
return errors.WithMessage(err, "creating chaincode package failed")
159+
}
160+
err = InstallChaincodeWithOrgContexts(orgs, ccPkg, examplePvtCCPath, ccID, exampleUpgdPvtCCVer)
161+
if err != nil {
162+
return errors.WithMessage(err, "installing example chaincode failed")
163+
}
164+
165+
// now upgrade cc
166+
_, err = UpgradeChaincode(orgs[0].ResMgmt, channelID, ccID, examplePvtCCPath, exampleUpgdPvtCCVer, ccPolicy, ExampleCCInitArgs(), collConfigs...)
167+
return err
168+
}
169+
152170
func resetExampleCC(sdk *fabsdk.FabricSDK, user fabsdk.ContextOption, orgName string, channelID string, chainCodeID string, args [][]byte) error {
153171
clientContext := sdk.ChannelContext(channelID, user, fabsdk.WithOrg(orgName))
154172

0 commit comments

Comments
 (0)