Skip to content

Commit 5918252

Browse files
author
Jason Yellick
committed
FAB-10975 Split Execute into Execute/ExecuteInit
Presently, the Execute function can either take a 'ChaincodeInvocationSpec' or a 'ChaincodeDeploymentSpec', and the path switches in a few different places depending on which it is. This makes the code complicated and difficult to understand, and in the interest of removing the chaincode deployment spec entirely, this code path should be isolated. Change-Id: I1f54684dba5877b5c629a59d344803f6423cc3da Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent 881fc85 commit 5918252

23 files changed

+254
-144
lines changed

core/chaincode/ccproviderimpl.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,15 @@ func (c *CCProviderImpl) ExecuteChaincode(ctxt context.Context, cccid *ccprovide
5757
}
5858

5959
// Execute executes the chaincode given context and spec (invocation or deploy)
60-
func (c *CCProviderImpl) Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) (*pb.Response, *pb.ChaincodeEvent, error) {
60+
func (c *CCProviderImpl) Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
6161
return c.cs.Execute(ctxt, cccid, spec)
6262
}
6363

64+
// ExecuteInit executes the chaincode given context and spec (invocation or deploy)
65+
func (c *CCProviderImpl) ExecuteInit(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
66+
return c.cs.ExecuteInit(ctxt, cccid, spec)
67+
}
68+
6469
// Stop stops the chaincode given context and spec
6570
func (c *CCProviderImpl) Stop(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) error {
6671
return c.cs.Stop(ctxt, cccid, spec)

core/chaincode/chaincode_support.go

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ type Runtime interface {
3030

3131
// Launcher is used to launch chaincode runtimes.
3232
type Launcher interface {
33-
Launch(context context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) error
33+
Launch(context context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) error
34+
LaunchInit(context context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) error
3435
}
3536

3637
// ChaincodeSupport responsible for providing interfacing with chaincodes from the Peer.
@@ -96,10 +97,24 @@ func NewChaincodeSupport(
9697
return cs
9798
}
9899

100+
// LaunchForInit bypasses getting the chaincode spec from the LSCC table
101+
// as in the case of v1.0-v1.2 lifecycle, the chaincode will not yet be
102+
// defined in the LSCC table
103+
func (cs *ChaincodeSupport) LaunchInit(ctx context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) error {
104+
cname := cccid.GetCanonicalName()
105+
if cs.HandlerRegistry.Handler(cname) != nil {
106+
return nil
107+
}
108+
109+
ctx = context.WithValue(ctx, ccintf.GetCCHandlerKey(), cs)
110+
111+
return cs.Launcher.LaunchInit(ctx, cccid, spec)
112+
}
113+
99114
// Launch starts executing chaincode if it is not already running. This method
100115
// blocks until the peer side handler gets into ready state or encounters a fatal
101116
// error. If the chaincode is already running, it simply returns.
102-
func (cs *ChaincodeSupport) Launch(ctx context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) error {
117+
func (cs *ChaincodeSupport) Launch(ctx context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) error {
103118
cname := cccid.GetCanonicalName()
104119
if cs.HandlerRegistry.Handler(cname) != nil {
105120
return nil
@@ -177,9 +192,19 @@ func createCCMessage(messageType pb.ChaincodeMessage_Type, cid string, txid stri
177192
return ccmsg, nil
178193
}
179194

195+
// Execute init invokes chaincode and returns the original response.
196+
func (cs *ChaincodeSupport) ExecuteInit(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
197+
resp, err := cs.InvokeInit(ctxt, cccid, spec)
198+
return processChaincodeExecutionResult(cccid, resp, err)
199+
}
200+
180201
// Execute invokes chaincode and returns the original response.
181-
func (cs *ChaincodeSupport) Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) (*pb.Response, *pb.ChaincodeEvent, error) {
202+
func (cs *ChaincodeSupport) Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.Response, *pb.ChaincodeEvent, error) {
182203
resp, err := cs.Invoke(ctxt, cccid, spec)
204+
return processChaincodeExecutionResult(cccid, resp, err)
205+
}
206+
207+
func processChaincodeExecutionResult(cccid *ccprovider.CCContext, resp *pb.ChaincodeMessage, err error) (*pb.Response, *pb.ChaincodeEvent, error) {
183208
if err != nil {
184209
return nil, nil, errors.Wrapf(err, "failed to execute transaction %s", cccid.TxID)
185210
}
@@ -209,18 +234,33 @@ func (cs *ChaincodeSupport) Execute(ctxt context.Context, cccid *ccprovider.CCCo
209234
}
210235
}
211236

237+
func (cs *ChaincodeSupport) InvokeInit(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeMessage, error) {
238+
cctyp := pb.ChaincodeMessage_INIT
239+
240+
err := cs.LaunchInit(ctxt, cccid, spec)
241+
if err != nil {
242+
return nil, err
243+
}
244+
245+
chaincodeSpec := spec.GetChaincodeSpec()
246+
if chaincodeSpec == nil {
247+
return nil, errors.New("chaincode spec is nil")
248+
}
249+
250+
input := chaincodeSpec.Input
251+
input.Decorations = cccid.ProposalDecorations
252+
ccMsg, err := createCCMessage(cctyp, cccid.ChainID, cccid.TxID, input)
253+
if err != nil {
254+
return nil, errors.WithMessage(err, "failed to create chaincode message")
255+
}
256+
257+
return cs.execute(ctxt, cccid, ccMsg)
258+
}
259+
212260
// Invoke will invoke chaincode and return the message containing the response.
213261
// The chaincode will be launched if it is not already running.
214-
func (cs *ChaincodeSupport) Invoke(ctxt context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) (*pb.ChaincodeMessage, error) {
215-
var cctyp pb.ChaincodeMessage_Type
216-
switch spec.(type) {
217-
case *pb.ChaincodeDeploymentSpec:
218-
cctyp = pb.ChaincodeMessage_INIT
219-
case *pb.ChaincodeInvocationSpec:
220-
cctyp = pb.ChaincodeMessage_TRANSACTION
221-
default:
222-
return nil, errors.New("a deployment or invocation spec is required")
223-
}
262+
func (cs *ChaincodeSupport) Invoke(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.ChaincodeMessage, error) {
263+
cctyp := pb.ChaincodeMessage_TRANSACTION
224264

225265
chaincodeSpec := spec.GetChaincodeSpec()
226266
if chaincodeSpec == nil {

core/chaincode/exectransaction_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeployme
459459
}
460460

461461
var resp *pb.Response
462-
if resp, _, err = chaincodeSupport.Execute(ctx, cccid, chaincodeDeploymentSpec); err != nil {
462+
if resp, _, err = chaincodeSupport.ExecuteInit(ctx, cccid, chaincodeDeploymentSpec); err != nil {
463463
return nil, fmt.Errorf("Error deploying chaincode(2): %s", err)
464464
}
465465

@@ -742,6 +742,7 @@ func runChaincodeInvokeChaincode(t *testing.T, channel1 string, channel2 string,
742742
nextBlockNumber2,
743743
chaincodeSupport,
744744
)
745+
745746
if err != nil {
746747
stopChaincode(ctxt, cccid1, chaincodeSupport)
747748
stopChaincode(ctxt, cccid2, chaincodeSupport)

core/chaincode/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type Registry interface {
4444

4545
// An Invoker invokes chaincode.
4646
type Invoker interface {
47-
Invoke(ctxt context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) (*pb.ChaincodeMessage, error)
47+
Invoke(ctxt context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) (*pb.ChaincodeMessage, error)
4848
}
4949

5050
// SystemCCProvider provides system chaincode metadata.

core/chaincode/handler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@ var _ = Describe("Handler", func() {
15061506
})
15071507

15081508
It("marks the new transaction simulator as done after execute", func() {
1509-
fakeInvoker.InvokeStub = func(context.Context, *ccprovider.CCContext, ccprovider.ChaincodeSpecGetter) (*pb.ChaincodeMessage, error) {
1509+
fakeInvoker.InvokeStub = func(context.Context, *ccprovider.CCContext, *pb.ChaincodeInvocationSpec) (*pb.ChaincodeMessage, error) {
15101510
Expect(newTxSimulator.DoneCallCount()).To(Equal(0))
15111511
return responseMessage, nil
15121512
}

core/chaincode/lifecycle.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818

1919
// Executor is used to invoke chaincode.
2020
type Executor interface {
21-
Execute(ctxt context.Context, cccid *ccprovider.CCContext, cis ccprovider.ChaincodeSpecGetter) (*pb.Response, *pb.ChaincodeEvent, error)
21+
Execute(ctxt context.Context, cccid *ccprovider.CCContext, cis *pb.ChaincodeInvocationSpec) (*pb.Response, *pb.ChaincodeEvent, error)
2222
}
2323

2424
// Lifecycle provides methods to invoke the lifecycle system chaincode.

core/chaincode/mock/executor.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/chaincode/mock/invoker.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/chaincode/runtime_launcher.go

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,29 @@ type RuntimeLauncher struct {
3535
StartupTimeout time.Duration
3636
}
3737

38-
// Launch chaincode with the appropriate runtime.
39-
func (r *RuntimeLauncher) Launch(ctx context.Context, cccid *ccprovider.CCContext, spec ccprovider.ChaincodeSpecGetter) error {
40-
chaincodeID := spec.GetChaincodeSpec().ChaincodeId
41-
cds, _ := spec.(*pb.ChaincodeDeploymentSpec)
42-
if cds == nil {
43-
var err error
44-
cds, err = r.getDeploymentSpec(ctx, cccid, chaincodeID)
45-
if err != nil {
46-
return err
47-
}
38+
// LaunchInit launches a container which is not yet defined in the LSCC table
39+
// This is only necessary for the pre v1.3 lifecycle
40+
func (r *RuntimeLauncher) LaunchInit(ctx context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeDeploymentSpec) error {
41+
err := r.start(ctx, cccid, spec)
42+
if err != nil {
43+
chaincodeLogger.Errorf("start failed: %+v", err)
44+
return err
4845
}
4946

50-
if cds.CodePackage == nil && cds.ExecEnv != pb.ChaincodeDeploymentSpec_SYSTEM {
51-
ccpack, err := r.PackageProvider.GetChaincode(chaincodeID.Name, chaincodeID.Version)
52-
if err != nil {
53-
return errors.Wrap(err, "failed to get chaincode package")
54-
}
55-
cds = ccpack.GetDepSpec()
47+
chaincodeLogger.Debug("launch complete")
48+
49+
return nil
50+
}
51+
52+
// Launch chaincode with the appropriate runtime.
53+
func (r *RuntimeLauncher) Launch(ctx context.Context, cccid *ccprovider.CCContext, spec *pb.ChaincodeInvocationSpec) error {
54+
chaincodeID := spec.GetChaincodeSpec().ChaincodeId
55+
cds, err := r.getDeploymentSpec(ctx, cccid, chaincodeID)
56+
if err != nil {
57+
return err
5658
}
5759

58-
err := r.start(ctx, cccid, cds)
60+
err = r.start(ctx, cccid, cds)
5961
if err != nil {
6062
chaincodeLogger.Errorf("start failed: %+v", err)
6163
return err
@@ -81,6 +83,16 @@ func (r *RuntimeLauncher) getDeploymentSpec(ctx context.Context, cccid *ccprovid
8183
}
8284

8385
func (r *RuntimeLauncher) start(ctx context.Context, cccid *ccprovider.CCContext, cds *pb.ChaincodeDeploymentSpec) error {
86+
// Note, it is not actually possible for cds.CodePackage to be non-nil in the real world
87+
// But some of the tests rely on the idea that it might be set.
88+
if cds.CodePackage == nil && cds.ExecEnv != pb.ChaincodeDeploymentSpec_SYSTEM {
89+
ccpack, err := r.PackageProvider.GetChaincode(cds.Name(), cds.Version())
90+
if err != nil {
91+
return errors.Wrap(err, "failed to get chaincode package")
92+
}
93+
cds = ccpack.GetDepSpec()
94+
}
95+
8496
cname := cccid.GetCanonicalName()
8597
launchState, err := r.Registry.Launching(cname)
8698
if err != nil {

0 commit comments

Comments
 (0)