Skip to content

Commit 2415875

Browse files
author
Jason Yellick
committed
FAB-14370 Factor out chaincode parameter Equal
Presently, the only place in the code that compares the equality of the chaincode parameters for a definition and approval is in the ApproveChaincodeForOrg function. However, we need this ability to check if chaincode parameters match before execution. This CR factors the code out into a common function where it can be re-used. Change-Id: I4453e5aac06e1214777bfaa460620fd792d33e3a Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent b4dc9fc commit 2415875

File tree

3 files changed

+118
-84
lines changed

3 files changed

+118
-84
lines changed

core/chaincode/lifecycle/lifecycle.go

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const (
6868
// namespaces/fields/mycc#2/Collections {<collection info>}
6969

7070
// ChaincodeParameters are the parts of the chaincode definition which are serialized
71-
// as values in the statedb.
71+
// as values in the statedb. It is expected that any instance will have no nil fields once initialized.
7272
// WARNING: This structure is serialized/deserialized from the DB, re-ordering or adding fields
7373
// will cause opaque checks to fail.
7474
type ChaincodeParameters struct {
@@ -77,8 +77,28 @@ type ChaincodeParameters struct {
7777
Collections *cb.CollectionConfigPackage
7878
}
7979

80+
func (cp *ChaincodeParameters) Equal(ocp *ChaincodeParameters) error {
81+
switch {
82+
case cp.EndorsementInfo.Version != ocp.EndorsementInfo.Version:
83+
return errors.Errorf("Version '%s' != '%s'", cp.EndorsementInfo.Version, ocp.EndorsementInfo.Version)
84+
case cp.EndorsementInfo.EndorsementPlugin != ocp.EndorsementInfo.EndorsementPlugin:
85+
return errors.Errorf("EndorsementPlugin '%s' != '%s'", cp.EndorsementInfo.EndorsementPlugin, ocp.EndorsementInfo.EndorsementPlugin)
86+
case cp.ValidationInfo.ValidationPlugin != ocp.ValidationInfo.ValidationPlugin:
87+
return errors.Errorf("ValidationPlugin '%s' != '%s'", cp.ValidationInfo.ValidationPlugin, ocp.ValidationInfo.ValidationPlugin)
88+
case !bytes.Equal(cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter):
89+
return errors.Errorf("ValidationParameter '%x' != '%x'", cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter)
90+
case !bytes.Equal(cp.EndorsementInfo.Id, ocp.EndorsementInfo.Id):
91+
return errors.Errorf("Hash '%x' != '%x'", cp.EndorsementInfo.Id, ocp.EndorsementInfo.Id)
92+
case !proto.Equal(cp.Collections, ocp.Collections):
93+
return errors.Errorf("Collections do not match")
94+
default:
95+
}
96+
return nil
97+
}
98+
8099
// ChaincodeDefinition contains the chaincode parameters, as well as the sequence number of the definition.
81-
// Note, it does not embed ChaincodeParameters so as not to complicate the serialization.
100+
// Note, it does not embed ChaincodeParameters so as not to complicate the serialization. It is expected
101+
// that any instance will have no nil fields once initialized.
82102
// WARNING: This structure is serialized/deserialized from the DB, re-ordering or adding fields
83103
// will cause opaque checks to fail.
84104
type ChaincodeDefinition struct {
@@ -196,23 +216,8 @@ func (l *Lifecycle) ApproveChaincodeDefinitionForOrg(name string, cd *ChaincodeD
196216
return errors.WithMessage(err, fmt.Sprintf("could not deserialize namespace %s as chaincode", name))
197217
}
198218

199-
switch {
200-
case definedChaincode.EndorsementInfo.Version != cd.EndorsementInfo.Version:
201-
return errors.Errorf("attempted to define the current sequence (%d) for namespace %s, but Version '%s' != '%s'", currentSequence, name, definedChaincode.EndorsementInfo.Version, cd.EndorsementInfo.Version)
202-
case definedChaincode.EndorsementInfo.EndorsementPlugin != cd.EndorsementInfo.EndorsementPlugin:
203-
return errors.Errorf("attempted to define the current sequence (%d) for namespace %s, but EndorsementPlugin '%s' != '%s'", currentSequence, name, definedChaincode.EndorsementInfo.EndorsementPlugin, cd.EndorsementInfo.EndorsementPlugin)
204-
case definedChaincode.ValidationInfo.ValidationPlugin != cd.ValidationInfo.ValidationPlugin:
205-
return errors.Errorf("attempted to define the current sequence (%d) for namespace %s, but ValidationPlugin '%s' != '%s'", currentSequence, name, definedChaincode.ValidationInfo.ValidationPlugin, cd.ValidationInfo.ValidationPlugin)
206-
case !bytes.Equal(definedChaincode.ValidationInfo.ValidationParameter, cd.ValidationInfo.ValidationParameter):
207-
return errors.Errorf("attempted to define the current sequence (%d) for namespace %s, but ValidationParameter '%x' != '%x'", currentSequence, name, definedChaincode.ValidationInfo.ValidationParameter, cd.ValidationInfo.ValidationParameter)
208-
case !bytes.Equal(definedChaincode.EndorsementInfo.Id, cd.EndorsementInfo.Id):
209-
return errors.Errorf("attempted to define the current sequence (%d) for namespace %s, but Hash '%x' != '%x'", currentSequence, name, definedChaincode.EndorsementInfo.Id, cd.EndorsementInfo.Id)
210-
case !proto.Equal(definedChaincode.Collections, cd.Collections):
211-
if proto.Equal(definedChaincode.Collections, &cb.CollectionConfigPackage{}) && cd.Collections == nil {
212-
break
213-
}
214-
return errors.Errorf("attempted to define the current sequence (%d) for namespace %s, but Collections do not match", currentSequence, name)
215-
default:
219+
if err := definedChaincode.Parameters().Equal(cd.Parameters()); err != nil {
220+
return errors.WithMessage(err, "attempted to define the current sequence (%d) for namespace %s, but")
216221
}
217222
}
218223

core/chaincode/lifecycle/lifecycle_test.go

Lines changed: 86 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,90 @@ import (
2121
"github.com/golang/protobuf/proto"
2222
)
2323

24+
var _ = Describe("ChaincodeParameters", func() {
25+
var (
26+
lhs, rhs *lifecycle.ChaincodeParameters
27+
)
28+
29+
BeforeEach(func() {
30+
lhs = &lifecycle.ChaincodeParameters{
31+
EndorsementInfo: &lb.ChaincodeEndorsementInfo{},
32+
ValidationInfo: &lb.ChaincodeValidationInfo{},
33+
Collections: &cb.CollectionConfigPackage{},
34+
}
35+
36+
rhs = &lifecycle.ChaincodeParameters{
37+
EndorsementInfo: &lb.ChaincodeEndorsementInfo{},
38+
ValidationInfo: &lb.ChaincodeValidationInfo{},
39+
Collections: &cb.CollectionConfigPackage{},
40+
}
41+
})
42+
43+
Describe("Equal", func() {
44+
It("returns nil when the parameters match", func() {
45+
Expect(lhs.Equal(rhs)).NotTo(HaveOccurred())
46+
})
47+
48+
Context("when the EndorsementPlugin differs from the current definition", func() {
49+
BeforeEach(func() {
50+
rhs.EndorsementInfo.EndorsementPlugin = "different"
51+
})
52+
53+
It("returns an error", func() {
54+
Expect(lhs.Equal(rhs)).To(MatchError("EndorsementPlugin '' != 'different'"))
55+
})
56+
})
57+
58+
Context("when the ValidationPlugin differs from the current definition", func() {
59+
BeforeEach(func() {
60+
rhs.ValidationInfo.ValidationPlugin = "different"
61+
})
62+
63+
It("returns an error", func() {
64+
Expect(lhs.Equal(rhs)).To(MatchError("ValidationPlugin '' != 'different'"))
65+
})
66+
})
67+
68+
Context("when the ValidationParameter differs from the current definition", func() {
69+
BeforeEach(func() {
70+
rhs.ValidationInfo.ValidationParameter = []byte("different")
71+
})
72+
73+
It("returns an error", func() {
74+
Expect(lhs.Equal(rhs)).To(MatchError("ValidationParameter '' != '646966666572656e74'"))
75+
})
76+
})
77+
78+
Context("when the Hash differs from the current definition", func() {
79+
BeforeEach(func() {
80+
rhs.EndorsementInfo.Id = []byte("different")
81+
})
82+
83+
It("returns an error", func() {
84+
Expect(lhs.Equal(rhs)).To(MatchError("Hash '' != '646966666572656e74'"))
85+
})
86+
})
87+
88+
Context("when the Collections differ from the current definition", func() {
89+
BeforeEach(func() {
90+
rhs.Collections = &cb.CollectionConfigPackage{
91+
Config: []*cb.CollectionConfig{
92+
{
93+
Payload: &cb.CollectionConfig_StaticCollectionConfig{
94+
StaticCollectionConfig: &cb.StaticCollectionConfig{Name: "foo"},
95+
},
96+
},
97+
},
98+
}
99+
})
100+
101+
It("returns an error", func() {
102+
Expect(lhs.Equal(rhs)).To(MatchError("Collections do not match"))
103+
})
104+
})
105+
})
106+
})
107+
24108
var _ = Describe("Lifecycle", func() {
25109
var (
26110
l *lifecycle.Lifecycle
@@ -156,6 +240,7 @@ var _ = Describe("Lifecycle", func() {
156240
Version: "version",
157241
},
158242
ValidationInfo: &lb.ChaincodeValidationInfo{},
243+
Collections: &cb.CollectionConfigPackage{},
159244
}
160245

161246
fakePublicState = &mock.ReadWritableState{}
@@ -273,70 +358,7 @@ var _ = Describe("Lifecycle", func() {
273358

274359
It("returns an error", func() {
275360
err := l.ApproveChaincodeDefinitionForOrg("cc-name", testDefinition, fakePublicState, fakeOrgState)
276-
Expect(err).To(MatchError("attempted to define the current sequence (5) for namespace cc-name, but Version 'other-version' != 'version'"))
277-
})
278-
})
279-
280-
Context("when the EndorsementPlugin differs from the current definition", func() {
281-
BeforeEach(func() {
282-
testDefinition.EndorsementInfo.EndorsementPlugin = "different"
283-
})
284-
285-
It("returns an error", func() {
286-
err := l.ApproveChaincodeDefinitionForOrg("cc-name", testDefinition, fakePublicState, fakeOrgState)
287-
Expect(err).To(MatchError("attempted to define the current sequence (5) for namespace cc-name, but EndorsementPlugin '' != 'different'"))
288-
})
289-
})
290-
291-
Context("when the ValidationPlugin differs from the current definition", func() {
292-
BeforeEach(func() {
293-
testDefinition.ValidationInfo.ValidationPlugin = "different"
294-
})
295-
296-
It("returns an error", func() {
297-
err := l.ApproveChaincodeDefinitionForOrg("cc-name", testDefinition, fakePublicState, fakeOrgState)
298-
Expect(err).To(MatchError("attempted to define the current sequence (5) for namespace cc-name, but ValidationPlugin '' != 'different'"))
299-
})
300-
})
301-
302-
Context("when the ValidationParameter differs from the current definition", func() {
303-
BeforeEach(func() {
304-
testDefinition.ValidationInfo.ValidationParameter = []byte("different")
305-
})
306-
307-
It("returns an error", func() {
308-
err := l.ApproveChaincodeDefinitionForOrg("cc-name", testDefinition, fakePublicState, fakeOrgState)
309-
Expect(err).To(MatchError("attempted to define the current sequence (5) for namespace cc-name, but ValidationParameter '' != '646966666572656e74'"))
310-
})
311-
})
312-
313-
Context("when the Hash differs from the current definition", func() {
314-
BeforeEach(func() {
315-
testDefinition.EndorsementInfo.Id = []byte("different")
316-
})
317-
318-
It("returns an error", func() {
319-
err := l.ApproveChaincodeDefinitionForOrg("cc-name", testDefinition, fakePublicState, fakeOrgState)
320-
Expect(err).To(MatchError("attempted to define the current sequence (5) for namespace cc-name, but Hash '' != '646966666572656e74'"))
321-
})
322-
})
323-
324-
Context("when the Collections differ from the current definition", func() {
325-
BeforeEach(func() {
326-
testDefinition.Collections = &cb.CollectionConfigPackage{
327-
Config: []*cb.CollectionConfig{
328-
{
329-
Payload: &cb.CollectionConfig_StaticCollectionConfig{
330-
StaticCollectionConfig: &cb.StaticCollectionConfig{Name: "foo"},
331-
},
332-
},
333-
},
334-
}
335-
})
336-
337-
It("returns an error", func() {
338-
err := l.ApproveChaincodeDefinitionForOrg("cc-name", testDefinition, fakePublicState, fakeOrgState)
339-
Expect(err).To(MatchError("attempted to define the current sequence (5) for namespace cc-name, but Collections do not match"))
361+
Expect(err).To(MatchError("attempted to define the current sequence (%d) for namespace %s, but: Version 'other-version' != 'version'"))
340362
})
341363
})
342364
})

core/chaincode/lifecycle/scc.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/hyperledger/fabric/core/aclmgmt"
1515
"github.com/hyperledger/fabric/core/chaincode/shim"
1616
"github.com/hyperledger/fabric/core/dispatcher"
17+
cb "github.com/hyperledger/fabric/protos/common"
1718
pb "github.com/hyperledger/fabric/protos/peer"
1819
lb "github.com/hyperledger/fabric/protos/peer/lifecycle"
1920

@@ -257,6 +258,10 @@ func (i *Invocation) QueryInstalledChaincodes(input *lb.QueryInstalledChaincodes
257258
// lifecycle implementation
258259
func (i *Invocation) ApproveChaincodeDefinitionForMyOrg(input *lb.ApproveChaincodeDefinitionForMyOrgArgs) (proto.Message, error) {
259260
collectionName := ImplicitCollectionNameForOrg(i.SCC.OrgMSPID)
261+
var collectionConfig []*cb.CollectionConfig
262+
if input.Collections != nil {
263+
collectionConfig = input.Collections.Config
264+
}
260265
if err := i.SCC.Functions.ApproveChaincodeDefinitionForOrg(
261266
input.Name,
262267
&ChaincodeDefinition{
@@ -271,7 +276,9 @@ func (i *Invocation) ApproveChaincodeDefinitionForMyOrg(input *lb.ApproveChainco
271276
ValidationPlugin: input.ValidationPlugin,
272277
ValidationParameter: input.ValidationParameter,
273278
},
274-
Collections: input.Collections,
279+
Collections: &cb.CollectionConfigPackage{
280+
Config: collectionConfig,
281+
},
275282
},
276283
i.Stub,
277284
&ChaincodePrivateLedgerShim{

0 commit comments

Comments
 (0)