Skip to content

Commit 2df3402

Browse files
Jason Yellicksykesm
Jason Yellick
authored andcommitted
FAB-16353 Replace ChaincodeDefinition API
This CR should be the penultimate in this stack. It finally switches away from using the ccprovider.ChaincodeDefinition interface and finally simply uses a literal as returned by lifecycle. Change-Id: I0634597fede1638717fa57e31395b8584b8d07c1 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent e016ff9 commit 2df3402

18 files changed

+385
-581
lines changed

Diff for: core/chaincode/chaincode_ginkgo_support_test.go

+65-130
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
var _ = Describe("CheckInvocation", func() {
2424
var (
2525
chaincodeSupport *chaincode.ChaincodeSupport
26+
invokeInfo *lifecycle.ChaincodeEndorsementInfo
2627

2728
fakeLifecycle *mock.Lifecycle
2829
fakeSimulator *mock.TxSimulator
@@ -36,6 +37,13 @@ var _ = Describe("CheckInvocation", func() {
3637
fakeSimulator = &mock.TxSimulator{}
3738
fakeSimulator.GetStateReturns([]byte("old-cc-version"), nil)
3839

40+
invokeInfo = &lifecycle.ChaincodeEndorsementInfo{
41+
Version: "definition-version",
42+
ChaincodeID: "definition-ccid",
43+
}
44+
45+
fakeLifecycle.ChaincodeEndorsementInfoReturns(invokeInfo, nil)
46+
3947
txParams = &ccprovider.TransactionParams{
4048
ChannelID: "channel-id",
4149
TXSimulator: fakeSimulator,
@@ -48,168 +56,95 @@ var _ = Describe("CheckInvocation", func() {
4856
}
4957
})
5058

51-
Describe("CheckInvocation for a non-legacy (_lifecycle) chaincode definition", func() {
52-
var (
53-
chaincodeDefinition *lifecycle.LegacyDefinition
54-
)
59+
It("fetches the info and returns the ccid and type", func() {
60+
ccid, cctype, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
61+
Expect(err).NotTo(HaveOccurred())
62+
Expect(ccid).To(Equal("definition-ccid"))
63+
Expect(cctype).To(Equal(pb.ChaincodeMessage_TRANSACTION))
64+
})
5565

66+
Context("when the invocation is an init", func() {
5667
BeforeEach(func() {
57-
chaincodeDefinition = &lifecycle.LegacyDefinition{
58-
Version: "definition-version",
59-
ChaincodeIDField: "definition-ccid",
60-
}
61-
62-
fakeLifecycle.ChaincodeDefinitionReturns(chaincodeDefinition, nil)
68+
input.IsInit = true
6369
})
6470

65-
It("fetches the definition and skips the legacy security checks", func() {
66-
ccid, cctype, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
67-
Expect(err).NotTo(HaveOccurred())
68-
Expect(ccid).To(Equal("definition-ccid"))
69-
Expect(cctype).To(Equal(pb.ChaincodeMessage_TRANSACTION))
70-
71-
Expect(fakeLifecycle.ChaincodeDefinitionCallCount()).To(Equal(1))
72-
channelID, chaincodeName, txSim := fakeLifecycle.ChaincodeDefinitionArgsForCall(0)
73-
Expect(channelID).To(Equal("channel-id"))
74-
Expect(chaincodeName).To(Equal("test-chaincode-name"))
75-
Expect(txSim).To(Equal(fakeSimulator))
71+
It("returns an error for chaincodes which do not require init", func() {
72+
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
73+
Expect(err).To(MatchError("chaincode 'test-chaincode-name' does not require initialization but called as init"))
7674
})
7775

78-
Context("when the invocation is an init", func() {
76+
Context("when the chaincode requires init be enforced", func() {
7977
BeforeEach(func() {
80-
input.IsInit = true
78+
invokeInfo.EnforceInit = true
8179
})
8280

83-
It("returns an error for chaincodes which do not require init", func() {
84-
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
85-
Expect(err).To(MatchError("chaincode 'test-chaincode-name' does not require initialization but called as init"))
81+
It("enforces init exactly once semantics", func() {
82+
ccid, cctype, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
83+
Expect(err).NotTo(HaveOccurred())
84+
Expect(ccid).To(Equal("definition-ccid"))
85+
Expect(cctype).To(Equal(pb.ChaincodeMessage_INIT))
86+
87+
Expect(fakeSimulator.GetStateCallCount()).To(Equal(1))
88+
namespace, key := fakeSimulator.GetStateArgsForCall(0)
89+
Expect(namespace).To(Equal("test-chaincode-name"))
90+
Expect(key).To(Equal("\x00" + string(utf8.MaxRune) + "initialized"))
91+
92+
Expect(fakeSimulator.SetStateCallCount()).To(Equal(1))
93+
namespace, key, value := fakeSimulator.SetStateArgsForCall(0)
94+
Expect(namespace).To(Equal("test-chaincode-name"))
95+
Expect(key).To(Equal("\x00" + string(utf8.MaxRune) + "initialized"))
96+
Expect(value).To(Equal([]byte("definition-version")))
8697
})
8798

88-
Context("when the chaincode requires init", func() {
99+
Context("when the invocation is not an init", func() {
89100
BeforeEach(func() {
90-
chaincodeDefinition.RequiresInitField = true
101+
input.IsInit = false
91102
})
92103

93-
It("enforces init exactly once semantics", func() {
94-
ccid, cctype, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
95-
Expect(err).NotTo(HaveOccurred())
96-
Expect(ccid).To(Equal("definition-ccid"))
97-
Expect(cctype).To(Equal(pb.ChaincodeMessage_INIT))
98-
99-
Expect(fakeSimulator.GetStateCallCount()).To(Equal(1))
100-
namespace, key := fakeSimulator.GetStateArgsForCall(0)
101-
Expect(namespace).To(Equal("test-chaincode-name"))
102-
Expect(key).To(Equal("\x00" + string(utf8.MaxRune) + "initialized"))
103-
104-
Expect(fakeSimulator.SetStateCallCount()).To(Equal(1))
105-
namespace, key, value := fakeSimulator.SetStateArgsForCall(0)
106-
Expect(namespace).To(Equal("test-chaincode-name"))
107-
Expect(key).To(Equal("\x00" + string(utf8.MaxRune) + "initialized"))
108-
Expect(value).To(Equal([]byte("definition-version")))
104+
It("returns an error", func() {
105+
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
106+
Expect(err).To(MatchError("chaincode 'test-chaincode-name' has not been initialized for this version, must call as init first"))
109107
})
108+
})
110109

111-
Context("when the invocation is not an init", func() {
112-
BeforeEach(func() {
113-
input.IsInit = false
114-
})
115-
116-
It("returns an error", func() {
117-
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
118-
Expect(err).To(MatchError("chaincode 'test-chaincode-name' has not been initialized for this version, must call as init first"))
119-
})
110+
Context("when the chaincode is already initialized", func() {
111+
BeforeEach(func() {
112+
fakeSimulator.GetStateReturns([]byte("definition-version"), nil)
120113
})
121114

122-
Context("when the chaincode is already initialized", func() {
123-
BeforeEach(func() {
124-
fakeSimulator.GetStateReturns([]byte("definition-version"), nil)
125-
})
126-
127-
It("returns an error", func() {
128-
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
129-
Expect(err).To(MatchError("chaincode 'test-chaincode-name' is already initialized but called as init"))
130-
})
115+
It("returns an error", func() {
116+
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
117+
Expect(err).To(MatchError("chaincode 'test-chaincode-name' is already initialized but called as init"))
131118
})
119+
})
132120

133-
Context("when the txsimulator cannot get state", func() {
134-
BeforeEach(func() {
135-
fakeSimulator.GetStateReturns(nil, fmt.Errorf("get-state-error"))
136-
})
137-
138-
It("wraps and returns the error", func() {
139-
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
140-
Expect(err).To(MatchError("could not get 'initialized' key: get-state-error"))
141-
})
121+
Context("when the txsimulator cannot get state", func() {
122+
BeforeEach(func() {
123+
fakeSimulator.GetStateReturns(nil, fmt.Errorf("get-state-error"))
142124
})
143125

144-
Context("when the txsimulator cannot set state", func() {
145-
BeforeEach(func() {
146-
fakeSimulator.SetStateReturns(fmt.Errorf("set-state-error"))
147-
})
148-
149-
It("wraps and returns the error", func() {
150-
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
151-
Expect(err).To(MatchError("could not set 'initialized' key: set-state-error"))
152-
})
126+
It("wraps and returns the error", func() {
127+
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
128+
Expect(err).To(MatchError("could not get 'initialized' key: get-state-error"))
153129
})
154130
})
155131

156-
})
157-
})
158-
159-
Describe("CheckInvocation for a legacy (lscc) chaincode definition", func() {
160-
var (
161-
fakeLegacyDefinition *mock.LegacyChaincodeDefinition
162-
)
163-
164-
BeforeEach(func() {
165-
input.IsInit = false
166-
fakeLegacyDefinition = &mock.LegacyChaincodeDefinition{}
167-
168-
ccDef := struct {
169-
*ccprovider.ChaincodeData
170-
*mock.LegacyChaincodeDefinition
171-
}{
172-
ChaincodeData: &ccprovider.ChaincodeData{
173-
Name: "definition-name",
174-
Version: "cc-version",
175-
Id: []byte("id"),
176-
},
177-
LegacyChaincodeDefinition: fakeLegacyDefinition,
178-
}
179-
180-
fakeLifecycle.ChaincodeDefinitionReturns(ccDef, nil)
181-
})
182-
183-
It("fetches the definition, performs security checks, and skips the init checks", func() {
184-
ccid, cctype, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
185-
Expect(err).NotTo(HaveOccurred())
186-
Expect(ccid).To(Equal("definition-name:cc-version"))
187-
Expect(cctype).To(Equal(pb.ChaincodeMessage_TRANSACTION))
188-
189-
Expect(fakeLifecycle.ChaincodeDefinitionCallCount()).To(Equal(1))
190-
channelID, chaincodeName, txSim := fakeLifecycle.ChaincodeDefinitionArgsForCall(0)
191-
Expect(channelID).To(Equal("channel-id"))
192-
Expect(chaincodeName).To(Equal("test-chaincode-name"))
193-
Expect(txSim).To(Equal(fakeSimulator))
194-
195-
Expect(fakeLegacyDefinition.ExecuteLegacySecurityChecksCallCount()).To(Equal(1))
196-
})
197-
198-
Context("when the legacy security check fails", func() {
199-
BeforeEach(func() {
200-
fakeLegacyDefinition.ExecuteLegacySecurityChecksReturns(fmt.Errorf("fake-security-error"))
201-
})
132+
Context("when the txsimulator cannot set state", func() {
133+
BeforeEach(func() {
134+
fakeSimulator.SetStateReturns(fmt.Errorf("set-state-error"))
135+
})
202136

203-
It("wraps and returns the error", func() {
204-
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
205-
Expect(err).To(MatchError("[channel channel-id] failed the chaincode security checks for test-chaincode-name: fake-security-error"))
137+
It("wraps and returns the error", func() {
138+
_, _, err := chaincodeSupport.CheckInvocation(txParams, "test-chaincode-name", input)
139+
Expect(err).To(MatchError("could not set 'initialized' key: set-state-error"))
140+
})
206141
})
207142
})
208143
})
209144

210145
Context("when lifecycle returns an error", func() {
211146
BeforeEach(func() {
212-
fakeLifecycle.ChaincodeDefinitionReturns(nil, fmt.Errorf("fake-lifecycle-error"))
147+
fakeLifecycle.ChaincodeEndorsementInfoReturns(nil, fmt.Errorf("fake-lifecycle-error"))
213148
})
214149

215150
It("wraps and returns the error", func() {

Diff for: core/chaincode/chaincode_suite_test.go

-5
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ type lifecycle_ interface {
6464
chaincode.Lifecycle
6565
}
6666

67-
//go:generate counterfeiter -o mock/legacy_chaincode_definition.go --fake-name LegacyChaincodeDefinition . legacyChaincodeDefinition
68-
type legacyChaincodeDefinition interface {
69-
chaincode.LegacyChaincodeDefinition
70-
}
71-
7267
//go:generate counterfeiter -o mock/chaincode_stream.go --fake-name ChaincodeStream . chaincodeStream
7368
type chaincodeStream interface {
7469
ccintf.ChaincodeStream

Diff for: core/chaincode/chaincode_support.go

+11-24
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/golang/protobuf/proto"
1515
pb "github.com/hyperledger/fabric-protos-go/peer"
1616
"github.com/hyperledger/fabric/common/util"
17+
"github.com/hyperledger/fabric/core/chaincode/lifecycle"
1718
"github.com/hyperledger/fabric/core/common/ccprovider"
1819
"github.com/hyperledger/fabric/core/container/ccintf"
1920
"github.com/hyperledger/fabric/core/ledger"
@@ -45,16 +46,9 @@ type Launcher interface {
4546

4647
// Lifecycle provides a way to retrieve chaincode definitions and the packages necessary to run them
4748
type Lifecycle interface {
48-
// ChaincodeDefinition returns the details for a chaincode by name
49-
ChaincodeDefinition(channelID, chaincodeName string, qe ledger.SimpleQueryExecutor) (ccprovider.ChaincodeDefinition, error)
50-
}
51-
52-
// LegacyChaincodeDefinitions need to perform security checks whenever a chaincode definition
53-
// is looked up. These security checks include checking the instantiation policy, as well
54-
// as performing the chaincode fingerprint matching, and other checks implemented in the legacy
55-
// packaging.
56-
type LegacyChaincodeDefinition interface {
57-
ExecuteLegacySecurityChecks() error
49+
// ChaincodeEndorsementInfo looks up the chaincode info in the given channel. It is the responsibility
50+
// of the implementation to add appropriate read dependencies for the information returned.
51+
ChaincodeEndorsementInfo(channelID, chaincodeName string, qe ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error)
5852
}
5953

6054
// ChaincodeSupport responsible for providing interfacing with chaincodes from the Peer.
@@ -210,21 +204,14 @@ func (cs *ChaincodeSupport) Invoke(txParams *ccprovider.TransactionParams, chain
210204
// Finally, it returns the chaincode ID to route to and the message type of the request (normal transation, or init).
211205
func (cs *ChaincodeSupport) CheckInvocation(txParams *ccprovider.TransactionParams, chaincodeName string, input *pb.ChaincodeInput) (ccid string, cctype pb.ChaincodeMessage_Type, err error) {
212206
chaincodeLogger.Debugf("[%s] getting chaincode data for %s on channel %s", shorttxid(txParams.TxID), chaincodeName, txParams.ChannelID)
213-
cd, err := cs.Lifecycle.ChaincodeDefinition(txParams.ChannelID, chaincodeName, txParams.TXSimulator)
207+
cii, err := cs.Lifecycle.ChaincodeEndorsementInfo(txParams.ChannelID, chaincodeName, txParams.TXSimulator)
214208
if err != nil {
215209
logDevModeError(cs.UserRunsCC)
216210
return "", 0, errors.Wrapf(err, "[channel %s] failed to get chaincode container info for %s", txParams.ChannelID, chaincodeName)
217211
}
218212

219-
if legacyDefinition, ok := cd.(LegacyChaincodeDefinition); ok {
220-
err = legacyDefinition.ExecuteLegacySecurityChecks()
221-
if err != nil {
222-
return "", 0, errors.WithMessagef(err, "[channel %s] failed the chaincode security checks for %s", txParams.ChannelID, chaincodeName)
223-
}
224-
}
225-
226213
needsInitialization := false
227-
if cd.RequiresInit() {
214+
if cii.EnforceInit {
228215
// Note, RequiresInit() is only ever true for non-legacy definitions, and is always false for system chaincodes
229216
// so performing this txSimulator read is safe.
230217

@@ -233,34 +220,34 @@ func (cs *ChaincodeSupport) CheckInvocation(txParams *ccprovider.TransactionPara
233220
return "", 0, errors.WithMessage(err, "could not get 'initialized' key")
234221
}
235222

236-
needsInitialization = !bytes.Equal(value, []byte(cd.CCVersion()))
223+
needsInitialization = !bytes.Equal(value, []byte(cii.Version))
237224
}
238225

239226
// Note, IsInit is a new field for v2.0 and should only be set for invocations of non-legacy chaincodes.
240227
// Any invocation of a legacy chaincode with IsInit set will fail. This is desirable, as the old
241228
// InstantiationPolicy contract enforces which users may call init.
242229
if input.IsInit {
243-
if !cd.RequiresInit() {
230+
if !cii.EnforceInit {
244231
return "", 0, errors.Errorf("chaincode '%s' does not require initialization but called as init", chaincodeName)
245232
}
246233

247234
if !needsInitialization {
248235
return "", 0, errors.Errorf("chaincode '%s' is already initialized but called as init", chaincodeName)
249236
}
250237

251-
err = txParams.TXSimulator.SetState(chaincodeName, InitializedKeyName, []byte(cd.CCVersion()))
238+
err = txParams.TXSimulator.SetState(chaincodeName, InitializedKeyName, []byte(cii.Version))
252239
if err != nil {
253240
return "", 0, errors.WithMessage(err, "could not set 'initialized' key")
254241
}
255242

256-
return cd.ChaincodeID(), pb.ChaincodeMessage_INIT, nil
243+
return cii.ChaincodeID, pb.ChaincodeMessage_INIT, nil
257244
}
258245

259246
if needsInitialization {
260247
return "", 0, errors.Errorf("chaincode '%s' has not been initialized for this version, must call as init first", chaincodeName)
261248
}
262249

263-
return cd.ChaincodeID(), pb.ChaincodeMessage_TRANSACTION, nil
250+
return cii.ChaincodeID, pb.ChaincodeMessage_TRANSACTION, nil
264251
}
265252

266253
// execute executes a transaction and waits for it to complete until a timeout value.

Diff for: core/chaincode/chaincode_support_test.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,15 @@ func initMockPeer(chainIDs ...string) (*peer.Peer, *ChaincodeSupport, func(), er
181181
globalConfig.ExecuteTimeout = 1 * time.Second
182182
lsccImpl := lscc.New(map[string]struct{}{"lscc": {}}, &lscc.PeerShim{Peer: peerInstance}, mockAclProvider, peerInstance.GetMSPIDs, newPolicyChecker(peerInstance))
183183
ml := &mock.Lifecycle{}
184-
ml.ChaincodeDefinitionStub = func(_, name string, _ ledger.SimpleQueryExecutor) (ccprovider.ChaincodeDefinition, error) {
184+
ml.ChaincodeEndorsementInfoStub = func(_, name string, _ ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) {
185185
switch name {
186186
case "shimTestCC", "calledCC":
187-
return &ccprovider.ChaincodeData{
188-
Name: name,
189-
Version: "0",
187+
return &lifecycle.ChaincodeEndorsementInfo{
188+
ChaincodeID: name + ":0",
190189
}, nil
191190
case "lscc":
192-
return &lifecycle.LegacyDefinition{
193-
Version: "syscc",
194-
ChaincodeIDField: "lscc.syscc",
191+
return &lifecycle.ChaincodeEndorsementInfo{
192+
ChaincodeID: "lscc.syscc",
195193
}, nil
196194
default:
197195
return nil, errors.New("oh-bother-no-chaincode-info")

0 commit comments

Comments
 (0)