Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FAB-18527] Discovery supports DisregardNamespacePolicy hint from client #2768

Merged
merged 1 commit into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions discovery/endorsement/endorsement.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,23 @@ func (ea *endorsementAnalyzer) computePrincipalSets(channelID common.ChannelID,
sessionLogger.Debug("Policy for chaincode '", chaincode, "'doesn't exist")
return nil, errors.New("policy not found")
}
if chaincode.DisregardNamespacePolicy && len(chaincode.KeyPolicies) == 0 && len(policies) == 1 {
sessionLogger.Warnf("Client requested to disregard chaincode %s's policy, but it did not specify any "+
"collection policies or key policies. This is probably a bug in the client side code, as the client should"+
"either not specify DisregardNamespacePolicy, or specify at least one key policy or at least one collection policy", chaincode.Name)
return nil, errors.Errorf("requested to disregard chaincode %s's policy but key and collection policies are missing, either "+
"disable DisregardNamespacePolicy or specify at least one key policy or at least one collection policy", chaincode.Name)
}
if chaincode.DisregardNamespacePolicy {
if len(policies) == 1 {
sessionLogger.Debugf("Client requested to disregard the namespace policy for chaincode %s,"+
" and no collection policies are present", chaincode.Name)
continue
}
sessionLogger.Debugf("Client requested to disregard the namespace policy for chaincode %s,"+
" however there exist %d collection policies taken into account", chaincode.Name, len(policies)-1)
policies = policies[1:]
}
inquireablePoliciesForChaincodeAndCollections = append(inquireablePoliciesForChaincodeAndCollections, policies...)
}

Expand Down
157 changes: 157 additions & 0 deletions discovery/endorsement/endorsement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,163 @@ func TestPeersForEndorsement(t *testing.T) {
peerIdentityString("p6"): {},
}, intersection)
})

t.Run("Chaincode call with DisregardNamespacePolicy set but no key policies or collection policies present", func(t *testing.T) {
// Scenario XVI: A chaincode call with DisregardNamespacePolicy set
// Total organizations are 0, 2, 4, 6, 10, 12
// and there is a collection specified by the client but no collection policies exist
// We expect an error because since DisregardNamespacePolicy is specified, and no collection policies are defined,
// there is not a single endorsement policy to compute.

chanPeers := peerSet{}
for _, id := range []int{0, 2, 4, 6, 10, 12} {
peer := newPeer(id).withChaincode("cc1", "1.0")
chanPeers = append(chanPeers, peer)
}

g.On("PeersOfChannel").Return(chanPeers.toMembers()).Once()

mf := &metadataFetcher{}
mf.On("Metadata").Return(&chaincode.Metadata{
Name: "cc1",
Version: "1.0",
}).Once()

pb := principalBuilder{}
cc1policy := pb.newSet().addPrincipal(peerRole("p0")).addPrincipal(peerRole("p2")).
newSet().addPrincipal(peerRole("p6")).addPrincipal(peerRole("p10")).buildPolicy()

pf.On("PoliciesByChaincode", "cc1").Return(cc1policy).Once()

analyzer := NewEndorsementAnalyzer(g, pf, &principalEvaluatorMock{}, mf)
desc, err := analyzer.PeersForEndorsement(channel, &peer.ChaincodeInterest{
Chaincodes: []*peer.ChaincodeCall{
{
Name: "cc1",
DisregardNamespacePolicy: true,
},
},
})
require.EqualError(t, err, "requested to disregard chaincode cc1's policy but key and collection policies are missing,"+
" either disable DisregardNamespacePolicy or specify at least one key policy or at least one collection policy")
require.Nil(t, desc)
})

t.Run("Chaincode call with state based endorsement policy and no chaincode namespace policy", func(t *testing.T) {
// Scenario XVII: A chaincode call with a state based endorsement policy and DisregardNamespacePolicy set
// Total organizations are 0, 2, 4, 6, 10, 12
// and the endorsement policies of the chaincode is:
// cc1: OR(AND(0, 2), AND(6, 10))
// However the chaincode call is accompanied with a hint
// for a state based endorsement policy for both organizations 2 and 6
// Therefore, the result should be: {2, 6}

chanPeers := peerSet{}
for _, id := range []int{0, 2, 4, 6, 10, 12} {
peer := newPeer(id).withChaincode("cc1", "1.0")
chanPeers = append(chanPeers, peer)
}

g.On("PeersOfChannel").Return(chanPeers.toMembers()).Once()

mf := &metadataFetcher{}
mf.On("Metadata").Return(&chaincode.Metadata{
Name: "cc1",
Version: "1.0",
}).Once()

pb := principalBuilder{}
cc1policy := pb.newSet().addPrincipal(peerRole("p0")).addPrincipal(peerRole("p2")).
newSet().addPrincipal(peerRole("p6")).addPrincipal(peerRole("p10")).buildPolicy()

pf.On("PoliciesByChaincode", "cc1").Return(cc1policy).Once()

analyzer := NewEndorsementAnalyzer(g, pf, &principalEvaluatorMock{}, mf)
desc, err := analyzer.PeersForEndorsement(channel, &peer.ChaincodeInterest{
Chaincodes: []*peer.ChaincodeCall{
{
Name: "cc1",
DisregardNamespacePolicy: true,
KeyPolicies: []*common2.SignaturePolicyEnvelope{
{
Identities: []*msp.MSPPrincipal{peerRole("p2")},
Rule: policydsl.SignedBy(0),
},
{
Identities: []*msp.MSPPrincipal{peerRole("p6")},
Rule: policydsl.SignedBy(0),
},
},
},
},
})
require.NoError(t, err)
require.NotNil(t, desc)
require.Len(t, desc.Layouts, 1)
require.Len(t, desc.Layouts[0].QuantitiesByGroup, 2)
require.Equal(t, map[string]struct{}{
peerIdentityString("p2"): {},
peerIdentityString("p6"): {},
}, extractPeers(desc))
})

t.Run("Chaincode call with collection endorsement policy and no namespace endorsement policy", func(t *testing.T) {
// Scenario XVIII: A chaincode call with collection endorsement policy and DisregardNamespacePolicy set
// The chaincode EP is OR(AND(0, 2), AND(6, 10))
// The collection endorsement policy is p0 and p2.
// Additionally, the client sets DisregardNamespacePolicy which makes
// discovery only use the collection policy and not the namespace policy.

chanPeers := peerSet{}
for _, id := range []int{0, 2, 4, 6, 10, 12} {
peer := newPeer(id).withChaincode("cc1", "1.0")
chanPeers = append(chanPeers, peer)
}

g.On("PeersOfChannel").Return(chanPeers.toMembers()).Once()

collectionOrgs := []*msp.MSPPrincipal{
peerRole("p0"),
peerRole("p2"),
}
col2principals := map[string][]*msp.MSPPrincipal{
"collection": collectionOrgs,
}
mf := &metadataFetcher{}
mf.On("Metadata").Return(&chaincode.Metadata{
Name: "cc1",
Version: "1.0",
CollectionsConfig: buildCollectionConfig(col2principals),
}).Once()

pb := principalBuilder{}
cc1policy := pb.newSet().addPrincipal(peerRole("p0")).addPrincipal(peerRole("p2")).
newSet().addPrincipal(peerRole("p6")).addPrincipal(peerRole("p10")).buildPolicy()

collectionEP := pb.newSet().addPrincipal(peerRole("p0")). // p0 and p6
addPrincipal(peerRole("p2")).buildPolicy()

pf.On("PoliciesByChaincode", "cc1").Return([]policies.InquireablePolicy{cc1policy, collectionEP}).Once()

analyzer := NewEndorsementAnalyzer(g, pf, &principalEvaluatorMock{}, mf)
desc, err := analyzer.PeersForEndorsement(channel, &peer.ChaincodeInterest{
Chaincodes: []*peer.ChaincodeCall{
{
Name: "cc1",
DisregardNamespacePolicy: true,
CollectionNames: []string{"collection"},
},
},
})
require.NoError(t, err)
require.NotNil(t, desc)
require.Len(t, desc.Layouts, 1)
require.Len(t, desc.Layouts[0].QuantitiesByGroup, 2)
require.Equal(t, map[string]struct{}{
peerIdentityString("p0"): {},
peerIdentityString("p2"): {},
}, extractPeers(desc))
})
}

func TestPeersAuthorizedByCriteria(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ require (
github.com/hyperledger/fabric-chaincode-go v0.0.0-20201119163726-f8ef75b17719
github.com/hyperledger/fabric-config v0.1.0
github.com/hyperledger/fabric-lib-go v1.0.0
github.com/hyperledger/fabric-protos-go v0.0.0-20210717172449-368ac8b7bc5b
github.com/hyperledger/fabric-protos-go v0.0.0-20210720123151-f0dc3e2a0871
github.com/kr/pretty v0.2.1
github.com/magiconair/properties v1.8.1 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ github.com/hyperledger/fabric-lib-go v1.0.0 h1:UL1w7c9LvHZUSkIvHTDGklxFv2kTeva1Q
github.com/hyperledger/fabric-lib-go v1.0.0/go.mod h1:H362nMlunurmHwkYqR5uHL2UDWbQdbfz74n8kbCFsqc=
github.com/hyperledger/fabric-protos-go v0.0.0-20190919234611-2a87503ac7c9/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-protos-go v0.0.0-20210717172449-368ac8b7bc5b h1:F3UmdNp9Hl6OCw3NwmEjrkJzG08X0+Xmt3NhmPnueE8=
github.com/hyperledger/fabric-protos-go v0.0.0-20210717172449-368ac8b7bc5b/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-protos-go v0.0.0-20210720123151-f0dc3e2a0871 h1:d7do07Q4LaOFAEWceRwUwVDdcfx3BdLeZYyUGtbHfRk=
github.com/hyperledger/fabric-protos-go v0.0.0-20210720123151-f0dc3e2a0871/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ github.com/hyperledger/fabric-config/protolator/protoext/peerext
# github.com/hyperledger/fabric-lib-go v1.0.0
## explicit
github.com/hyperledger/fabric-lib-go/healthz
# github.com/hyperledger/fabric-protos-go v0.0.0-20210717172449-368ac8b7bc5b
# github.com/hyperledger/fabric-protos-go v0.0.0-20210720123151-f0dc3e2a0871
## explicit
github.com/hyperledger/fabric-protos-go/common
github.com/hyperledger/fabric-protos-go/discovery
Expand Down