Skip to content

Commit

Permalink
[FAB-10650] retrieve collections configurations
Browse files Browse the repository at this point in the history
Ability to query for a chaincode's collection configuration.

Change-Id: I467eb1adcf249999f2c93a856e6a909eb5de1418
Signed-off-by: zhaochy <[email protected]>
  • Loading branch information
zhaochy1990 committed Jul 31, 2018
1 parent 1218853 commit d8e27eb
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions core/aclmgmt/defaultaclprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func (d *defaultACLProvider) initialize() {
d.cResourcePolicyMap[resources.Lscc_GetDeploymentSpec] = CHANNELREADERS
d.cResourcePolicyMap[resources.Lscc_GetChaincodeData] = CHANNELREADERS
d.cResourcePolicyMap[resources.Lscc_GetInstantiatedChaincodes] = CHANNELREADERS
d.cResourcePolicyMap[resources.Lscc_GetCollectionsConfig] = CHANNELREADERS

//-------------- QSCC --------------
//p resources (none)
Expand Down
1 change: 1 addition & 0 deletions core/aclmgmt/resources/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
Lscc_GetChaincodeData = "lscc/GetChaincodeData"
Lscc_GetInstantiatedChaincodes = "lscc/GetInstantiatedChaincodes"
Lscc_GetInstalledChaincodes = "lscc/GetInstalledChaincodes"
Lscc_GetCollectionsConfig = "lscc/GetCollectionsConfig"

//Qscc resources
Qscc_GetChainInfo = "qscc/GetChainInfo"
Expand Down
33 changes: 33 additions & 0 deletions core/scc/lscc/lscc.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ const (
// GETINSTALLEDCHAINCODESALIAS gets the installed chaincodes on a peer
GETINSTALLEDCHAINCODESALIAS = "GetInstalledChaincodes"

// GETCOLLECTIONSCONFIG gets the collections config for a chaincode
GETCOLLECTIONSCONFIG = "GetCollectionsConfig"

// GETCOLLECTIONSCONFIGALIAS gets the collections config for a chaincode
GETCOLLECTIONSCONFIGALIAS = "getcollectionsconfig"

allowedChaincodeName = "^[a-zA-Z0-9]+([-_][a-zA-Z0-9]+)*$"
allowedCharsVersion = "[A-Za-z0-9_.+-]+"
)
Expand Down Expand Up @@ -336,6 +342,19 @@ func (lscc *LifeCycleSysCC) putChaincodeCollectionData(stub shim.ChaincodeStubIn
return nil
}

// getChaincodeCollectionData retrieve collections config.
func (lscc *LifeCycleSysCC) getChaincodeCollectionData(stub shim.ChaincodeStubInterface, chaincodeName string) pb.Response {
key := privdata.BuildCollectionKVSKey(chaincodeName)
collectionsConfigBytes, err := stub.GetState(key)
if err != nil {
return shim.Error(err.Error())
}
if len(collectionsConfigBytes) == 0 {
return shim.Error(fmt.Sprintf("collections config not defined for chaincode %s", chaincodeName))
}
return shim.Success(collectionsConfigBytes)
}

//checks for existence of chaincode on the given channel
func (lscc *LifeCycleSysCC) getCCInstance(stub shim.ChaincodeStubInterface, ccname string) ([]byte, error) {
cdbytes, err := stub.GetState(ccname)
Expand Down Expand Up @@ -960,6 +979,20 @@ func (lscc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response
}

return lscc.getInstalledChaincodes()
case GETCOLLECTIONSCONFIG, GETCOLLECTIONSCONFIGALIAS:
if len(args) != 2 {
return shim.Error(InvalidArgsLenErr(len(args)).Error())
}

chaincodeName := string(args[1])

logger.Debugf("GetCollectionsConfig, chaincodeName:%s, start to check ACL for current identity policy", chaincodeName)
if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetCollectionsConfig, stub.GetChannelID(), sp); err != nil {
logger.Debugf("ACL Check Failed for channel:%s, chaincode:%s", stub.GetChannelID(), chaincodeName)
return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
}

return lscc.getChaincodeCollectionData(stub, chaincodeName)
}

return shim.Error(InvalidFunctionErr(function).Error())
Expand Down
55 changes: 55 additions & 0 deletions core/scc/lscc/lscc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,61 @@ func TestPutChaincodeCollectionData(t *testing.T) {
stub.MockTransactionEnd("foo")
}

func TestGetChaincodeCollectionData(t *testing.T) {
scc := New(NewMockProvider(), mockAclProvider, platforms.NewRegistry(&golang.Platform{}))
stub := shim.NewMockStub("lscc", scc)
stub.ChannelID = "test"
scc.Support = &lscc.MockSupport{}

cd := &ccprovider.ChaincodeData{Name: "foo"}

collName1 := "mycollection1"
policyEnvelope := &common.SignaturePolicyEnvelope{}
coll1 := createCollectionConfig(collName1, policyEnvelope, 1, 2)
ccp := &common.CollectionConfigPackage{Config: []*common.CollectionConfig{coll1}}
ccpBytes, err := proto.Marshal(ccp)
assert.NoError(t, err)
assert.NotNil(t, ccpBytes)

stub.MockTransactionStart("foo")
err = scc.putChaincodeCollectionData(stub, cd, ccpBytes)
assert.NoError(t, err)
stub.MockTransactionEnd("foo")

res := stub.MockInit("1", nil)
assert.Equal(t, int32(shim.OK), res.Status, res.Message)

for _, function := range []string{"GetCollectionsConfig", "getcollectionsconfig"} {
sProp, _ := utils.MockSignedEndorserProposalOrPanic("test", &pb.ChaincodeSpec{}, []byte("Bob"), []byte("msg1"))
sProp.Signature = sProp.ProposalBytes

t.Run("invalid number of arguments", func(t *testing.T) {
res = stub.MockInvokeWithSignedProposal("1", util.ToChaincodeArgs(function, "foo", "bar"), nil)
assert.NotEqual(t, int32(shim.OK), res.Status)
assert.Equal(t, "invalid number of arguments to lscc: 3", res.Message)
})
t.Run("invalid identity", func(t *testing.T) {
mockAclProvider.Reset()
mockAclProvider.On("CheckACL", resources.Lscc_GetCollectionsConfig, "test", sProp).Return(errors.New("acl check failed"))
res = stub.MockInvokeWithSignedProposal("1", util.ToChaincodeArgs(function, "foo"), sProp)
assert.NotEqual(t, int32(shim.OK), res.Status)
assert.Contains(t, res.Message, "access denied for ["+function+"]")
})
t.Run("non-exists collections config", func(t *testing.T) {
mockAclProvider.Reset()
mockAclProvider.On("CheckACL", resources.Lscc_GetCollectionsConfig, "test", sProp).Return(nil)
res = stub.MockInvokeWithSignedProposal("1", util.ToChaincodeArgs(function, "bar"), sProp)
assert.NotEqual(t, int32(shim.OK), res.Status)
assert.Equal(t, res.Message, "collections config not defined for chaincode bar")
})
t.Run("Success", func(t *testing.T) {
res = stub.MockInvokeWithSignedProposal("1", util.ToChaincodeArgs(function, "foo"), sProp)
assert.Equal(t, int32(shim.OK), res.Status)
assert.NotNil(t, res.Payload)
})
}
}

func TestCheckCollectionMemberPolicy(t *testing.T) {
// error case: no msp manager set, no collection config set
err := checkCollectionMemberPolicy(nil, nil)
Expand Down

0 comments on commit d8e27eb

Please sign in to comment.