Skip to content

Commit

Permalink
[FAB-17303] Set RequiredPeerCount and MaxPeerCount defaults for implicit
Browse files Browse the repository at this point in the history
and explicit collections

Signed-off-by: Danny Cao <dcao@us.ibm.com>
  • Loading branch information
caod123 authored and denyeart committed Jan 28, 2020
1 parent 9bd0a95 commit e7fb9c7
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 80 deletions.
4 changes: 2 additions & 2 deletions Gopkg.lock

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

2 changes: 2 additions & 0 deletions core/chaincode/lifecycle/deployedcc_infoprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ func GenerateImplicitCollectionForOrg(mspid string) *pb.StaticCollectionConfig {
SignaturePolicy: cauthdsl.SignedByMspMember(mspid),
},
},
RequiredPeerCount: 0,
MaximumPeerCount: 1,
}
}

Expand Down
4 changes: 4 additions & 0 deletions core/chaincode/lifecycle/deployedcc_infoprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,11 @@ var _ = Describe("ValidatorCommitter", func() {
}
}
Expect(firstOrg).NotTo(BeNil())
Expect(firstOrg.RequiredPeerCount).To(Equal(int32(0)))
Expect(firstOrg.MaximumPeerCount).To(Equal(int32(1)))
Expect(secondOrg).NotTo(BeNil())
Expect(secondOrg.RequiredPeerCount).To(Equal(int32(0)))
Expect(secondOrg.MaximumPeerCount).To(Equal(int32(1)))
})

Context("when the chaincode does not exist", func() {
Expand Down
106 changes: 105 additions & 1 deletion integration/pvtdata/pvtdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ var _ bool = Describe("PrivateData", func() {
})

Describe("Dissemination when pulling is disabled", func() {
It("disseminates private data per collections_config1", func() {
BeforeEach(func() {
By("setting up the network")
network = initThreeOrgsSetup()

Expand All @@ -78,7 +78,9 @@ var _ bool = Describe("PrivateData", func() {

By("starting the network")
process, orderer = startNetwork(network)
})

It("disseminates private data per collections_config1", func() {
By("deploying legacy chaincode and adding marble1")
testChaincode := chaincode{
Chaincode: nwo.Chaincode{
Expand All @@ -102,6 +104,34 @@ var _ bool = Describe("PrivateData", func() {

assertPvtdataPresencePerCollectionConfig1(network, testChaincode.Name, "marble1")
})

When("collection config does not have maxPeerCount or requiredPeerCount", func() {
It("disseminates private data per collections_config7 with default maxPeerCount and requiredPeerCount", func() {
By("deploying legacy chaincode and adding marble1")
testChaincode := chaincode{
Chaincode: nwo.Chaincode{
Name: "marblesp",
Version: "1.0",
Path: "github.com/hyperledger/fabric/integration/chaincode/marbles_private/cmd",
Ctor: `{"Args":["init"]}`,
Policy: `OR ('Org1MSP.member','Org2MSP.member', 'Org3MSP.member')`,
// collections_config1.json defines the access as follows:
// 1. collectionMarbles - Org1, Org2 have access to this collection
// 2. collectionMarblePrivateDetails - Org2 and Org3 have access to this collection
CollectionsConfig: collectionConfig("collections_config7.json"),
},
isLegacy: true,
}
deployChaincode(network, orderer, testChaincode)
peer := network.Peer("Org1", "peer0")
addMarble(network, orderer, testChaincode.Name,
`{"name":"marble1", "color":"blue", "size":35, "owner":"tom", "price":99}`,
peer,
)

assertPvtdataPresencePerCollectionConfig7(network, testChaincode.Name, "marble1", peer)
})
})
})

Describe("Pvtdata behavior with untouched peer configs", func() {
Expand Down Expand Up @@ -971,6 +1001,36 @@ func assertPvtdataPresencePerCollectionConfig2(n *nwo.Network, chaincodeName, ma
}
}

func assertPvtdataPresencePerCollectionConfig7(n *nwo.Network, chaincodeName, marbleName string, excludedPeer *nwo.Peer, peers ...*nwo.Peer) {
if len(peers) == 0 {
peers = n.Peers
}
collectionMPresence := 0
collectionMPDPresence := 0
for _, peer := range peers {
// exclude the peer that invoked originally and count number of peers disseminated to
if peer != excludedPeer {
switch peer.Organization {

case "Org1":
collectionMPresence += checkPresentInCollectionM(n, chaincodeName, marbleName, peer)
assertNotPresentInCollectionMPD(n, chaincodeName, marbleName, peer)

case "Org2":
collectionMPresence += checkPresentInCollectionM(n, chaincodeName, marbleName, peer)
collectionMPDPresence += checkPresentInCollectionMPD(n, chaincodeName, marbleName, peer)

case "Org3":
assertNotPresentInCollectionM(n, chaincodeName, marbleName, peer)
collectionMPDPresence += checkPresentInCollectionMPD(n, chaincodeName, marbleName, peer)
}
}
}
Expect(collectionMPresence).To(Equal(1))
Expect(collectionMPDPresence).To(Equal(1))

}

// assertGetMarblesByRange asserts that
func assertGetMarblesByRange(n *nwo.Network, chaincodeName, marbleRange string, peer *nwo.Peer) {
query := fmt.Sprintf(`{"Args":["getMarblesByRange", %s]}`, marbleRange)
Expand All @@ -994,6 +1054,50 @@ func assertPresentInCollectionMPD(n *nwo.Network, chaincodeName, marbleName stri
queryChaincodePerPeer(n, query, chaincodeName, expectedMsg, true, peerList...)
}

// checkPresentInCollectionM checks then number of peers that have the private data for given marble
// in collection 'readMarble'
func checkPresentInCollectionM(n *nwo.Network, chaincodeName, marbleName string, peerList ...*nwo.Peer) int {
query := fmt.Sprintf(`{"Args":["readMarble","%s"]}`, marbleName)
expectedMsg := fmt.Sprintf(`{"docType":"marble","name":"%s"`, marbleName)
command := commands.ChaincodeQuery{
ChannelID: channelID,
Name: chaincodeName,
Ctor: query,
}
present := 0
for _, peer := range peerList {
sess, err := n.PeerUserSession(peer, "User1", command)
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit())
if bytes.Contains(sess.Buffer().Contents(), []byte(expectedMsg)) {
present++
}
}
return present
}

// checkPresentInCollectionMPD checks the number of peers that have the private data for given marble
// in collection 'readMarblePrivateDetails'
func checkPresentInCollectionMPD(n *nwo.Network, chaincodeName, marbleName string, peerList ...*nwo.Peer) int {
query := fmt.Sprintf(`{"Args":["readMarblePrivateDetails","%s"]}`, marbleName)
expectedMsg := fmt.Sprintf(`{"docType":"marblePrivateDetails","name":"%s"`, marbleName)
command := commands.ChaincodeQuery{
ChannelID: channelID,
Name: chaincodeName,
Ctor: query,
}
present := 0
for _, peer := range peerList {
sess, err := n.PeerUserSession(peer, "User1", command)
Expect(err).NotTo(HaveOccurred())
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit())
if bytes.Contains(sess.Buffer().Contents(), []byte(expectedMsg)) {
present++
}
}
return present
}

// assertNotPresentInCollectionM asserts that the private data for given marble is NOT present
// in collection 'readMarble' at the given peers
func assertNotPresentInCollectionM(n *nwo.Network, chaincodeName, marbleName string, peerList ...*nwo.Peer) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"name": "collectionMarbles",
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
"blockToLive":1000000,
"memberOnlyRead": false
},
{
"name": "collectionMarblePrivateDetails",
"policy": "OR('Org2MSP.member', 'Org3MSP.member')",
"blockToLive":1000000,
"memberOnlyRead": false
}
]
18 changes: 14 additions & 4 deletions internal/peer/chaincode/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ type endorsementPolicy struct {
type collectionConfigJson struct {
Name string `json:"name"`
Policy string `json:"policy"`
RequiredPeerCount int32 `json:"requiredPeerCount"`
MaxPeerCount int32 `json:"maxPeerCount"`
RequiredPeerCount *int32 `json:"requiredPeerCount"`
MaxPeerCount *int32 `json:"maxPeerCount"`
BlockToLive uint64 `json:"blockToLive"`
MemberOnlyRead bool `json:"memberOnlyRead"`
MemberOnlyWrite bool `json:"memberOnlyWrite"`
Expand Down Expand Up @@ -243,13 +243,23 @@ func getCollectionConfigFromBytes(cconfBytes []byte) (*pb.CollectionConfigPackag
}
}

// Set default requiredPeerCount and MaxPeerCount if not specified in json
requiredPeerCount := int32(0)
maxPeerCount := int32(1)
if cconfitem.RequiredPeerCount != nil {
requiredPeerCount = *cconfitem.RequiredPeerCount
}
if cconfitem.MaxPeerCount != nil {
maxPeerCount = *cconfitem.MaxPeerCount
}

cc := &pb.CollectionConfig{
Payload: &pb.CollectionConfig_StaticCollectionConfig{
StaticCollectionConfig: &pb.StaticCollectionConfig{
Name: cconfitem.Name,
MemberOrgsPolicy: cpc,
RequiredPeerCount: cconfitem.RequiredPeerCount,
MaximumPeerCount: cconfitem.MaxPeerCount,
RequiredPeerCount: requiredPeerCount,
MaximumPeerCount: maxPeerCount,
BlockToLive: cconfitem.BlockToLive,
MemberOnlyRead: cconfitem.MemberOnlyRead,
MemberOnlyWrite: cconfitem.MemberOnlyWrite,
Expand Down
26 changes: 26 additions & 0 deletions internal/peer/chaincode/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ const sampleCollectionConfigGood = `[
}
]`

const sampleCollectionConfigGoodNoMaxPeerCountOrRequiredPeerCount = `[
{
"name": "foo",
"policy": "OR('A.member', 'B.member')",
"blockToLive":10,
"memberOnlyRead": true,
"memberOnlyWrite": true
}
]`

const sampleCollectionConfigGoodWithSignaturePolicy = `[
{
"name": "foo",
Expand Down Expand Up @@ -296,6 +306,22 @@ func TestCollectionParsing(t *testing.T) {
assert.Nil(t, conf.EndorsementPolicy)
t.Logf("conf=%s", conf)

// Test default values for RequiredPeerCount and MaxPeerCount
ccp, ccpBytes, err = getCollectionConfigFromBytes([]byte(sampleCollectionConfigGoodNoMaxPeerCountOrRequiredPeerCount))
assert.NoError(t, err)
assert.NotNil(t, ccp)
assert.NotNil(t, ccpBytes)
conf = ccp.Config[0].GetStaticCollectionConfig()
pol, _ = cauthdsl.FromString("OR('A.member', 'B.member')")
assert.Equal(t, 0, int(conf.RequiredPeerCount))
assert.Equal(t, 1, int(conf.MaximumPeerCount))
assert.Equal(t, "foo", conf.Name)
assert.True(t, proto.Equal(pol, conf.MemberOrgsPolicy.GetSignaturePolicy()))
assert.Equal(t, 10, int(conf.BlockToLive))
assert.Equal(t, true, conf.MemberOnlyRead)
assert.Nil(t, conf.EndorsementPolicy)
t.Logf("conf=%s", conf)

ccp, ccpBytes, err = getCollectionConfigFromBytes([]byte(sampleCollectionConfigGoodWithSignaturePolicy))
assert.NoError(t, err)
assert.NotNil(t, ccp)
Expand Down
Loading

0 comments on commit e7fb9c7

Please sign in to comment.