Skip to content

Commit ab4b7f7

Browse files
author
Srinivasan Muralidharan
committed
FAB-1783 - use installed CC from file system
https://jira.hyperledger.org/browse/FAB-1783. In particular, "newdeploy.pptx" there. Move off per channel "on-ledger" deploy model to "on-peer" install model. This affects version, launch and per channel ledger instatiation. Now that chaincode is not on ledger but is on-peer, there is no need to create a container per instance of the chaincode deployed on different channels. These are the tightly related changes . user has to specify version (see, version option in CLI commands) . load off file system and not on ledger (see ccprovider.go) . chaincode launch separated from chaincode instantiation (see chaincode_support.go) . chaincode "init" is no longer tied to deploy (install) (see handler.go) Note 1 -a minor side effect is that the chaincode container is not killed after instantiate like it was after the old deploy. It need not be as the chaincode is not bound to a channel. Note 2 - the "--peer-chaincodedev=true" has to be treated differently for the new model. A JIRA https://jira.hyperledger.org/browse/FAB-2128 has been opened for this Change-Id: I34b417d119c16bf296130f8740cddd5af9a8b582 Signed-off-by: Srinivasan Muralidharan <[email protected]>
1 parent 32ae559 commit ab4b7f7

22 files changed

+381
-453
lines changed

core/chaincode/chaincode_support.go

+27-56
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package chaincode
1919
import (
2020
"fmt"
2121
"io"
22+
"path/filepath"
2223
"strconv"
2324
"sync"
2425
"time"
@@ -105,6 +106,8 @@ func (chaincodeSupport *ChaincodeSupport) chaincodeHasBeenLaunched(chaincode str
105106

106107
// NewChaincodeSupport creates a new ChaincodeSupport instance
107108
func NewChaincodeSupport(getPeerEndpoint func() (*pb.PeerEndpoint, error), userrunsCC bool, ccstartuptimeout time.Duration) *ChaincodeSupport {
109+
ccprovider.SetChaincodesPath(viper.GetString("peer.fileSystemPath") + string(filepath.Separator) + "chaincodes")
110+
108111
pnid := viper.GetString("peer.networkId")
109112
pid := viper.GetString("peer.id")
110113

@@ -265,8 +268,8 @@ func (chaincodeSupport *ChaincodeSupport) deregisterHandler(chaincodehandler *Ha
265268
return nil
266269
}
267270

268-
// Based on state of chaincode send either init or ready to move to ready state
269-
func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Context, cccid *ccprovider.CCContext, initArgs [][]byte, timeout time.Duration) error {
271+
// send ready to move to ready state
272+
func (chaincodeSupport *ChaincodeSupport) sendReady(context context.Context, cccid *ccprovider.CCContext, timeout time.Duration) error {
270273
canName := cccid.GetCanonicalName()
271274
chaincodeSupport.runningChaincodes.Lock()
272275
//if its in the map, there must be a connected stream...nothing to do
@@ -281,7 +284,7 @@ func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Contex
281284

282285
var notfy chan *pb.ChaincodeMessage
283286
var err error
284-
if notfy, err = chrte.handler.initOrReady(context, cccid.ChainID, cccid.TxID, cccid.Proposal, initArgs); err != nil {
287+
if notfy, err = chrte.handler.ready(context, cccid.ChainID, cccid.TxID, cccid.Proposal); err != nil {
285288
return fmt.Errorf("Error sending %s: %s", pb.ChaincodeMessage_INIT, err)
286289
}
287290
if notfy != nil {
@@ -394,7 +397,7 @@ func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context.
394397

395398
vmtype, _ := chaincodeSupport.getVMType(cds)
396399

397-
sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Builder: builder, Args: args, Env: env}
400+
sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, Version: cccid.Version}, Builder: builder, Args: args, Env: env}
398401

399402
ipcCtxt := context.WithValue(ctxt, ccintf.GetCCHandlerKey(), chaincodeSupport)
400403

@@ -437,7 +440,7 @@ func (chaincodeSupport *ChaincodeSupport) Stop(context context.Context, cccid *c
437440
}
438441

439442
//stop the chaincode
440-
sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Timeout: 0}
443+
sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, Version: cccid.Version}, Timeout: 0}
441444
// The line below is left for debugging. It replaces the line above to keep
442445
// the chaincode container around to give you a chance to get data
443446
//sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Timeout: 0, Dontremove: true}
@@ -470,7 +473,6 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
470473
var cID *pb.ChaincodeID
471474
var cMsg *pb.ChaincodeInput
472475
var cLang pb.ChaincodeSpec_Type
473-
var initargs [][]byte
474476

475477
var cds *pb.ChaincodeDeploymentSpec
476478
var ci *pb.ChaincodeInvocationSpec
@@ -483,7 +485,6 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
483485
cID = cds.ChaincodeSpec.ChaincodeID
484486
cMsg = cds.ChaincodeSpec.Input
485487
cLang = cds.ChaincodeSpec.Type
486-
initargs = cMsg.Args
487488
} else {
488489
cID = ci.ChaincodeSpec.ChaincodeID
489490
cMsg = ci.ChaincodeSpec.Input
@@ -548,6 +549,20 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
548549

549550
//launch container if it is a System container or not in dev mode
550551
if (!chaincodeSupport.userRunsCC || cds.ExecEnv == pb.ChaincodeDeploymentSpec_SYSTEM) && (chrte == nil || chrte.handler == nil) {
552+
//whether we deploying, upgrading or launching a chaincode we now have a
553+
//deployment package. If lauching, we got it from LCCC and has gone through
554+
//ccprovider.GetChaincodeFromFS
555+
if cds.CodePackage == nil {
556+
//no code bytes for these situations
557+
if !(chaincodeSupport.userRunsCC || cds.ExecEnv == pb.ChaincodeDeploymentSpec_SYSTEM) {
558+
_, cdsfs, err := ccprovider.GetChaincodeFromFS(cID.Name, cID.Version)
559+
if err != nil {
560+
return cID, cMsg, err
561+
}
562+
cds.CodePackage = cdsfs.CodePackage
563+
chaincodeLogger.Debugf("launchAndWaitForRegister fetched %d from file system", len(cds.CodePackage), err)
564+
}
565+
}
551566

552567
builder := func() (io.Reader, error) { return platforms.GenerateDockerBuild(cds) }
553568
err = chaincodeSupport.launchAndWaitForRegister(context, cccid, cds, cLang, builder)
@@ -558,8 +573,8 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid
558573
}
559574

560575
if err == nil {
561-
//send init (if (args)) and wait for ready state
562-
err = chaincodeSupport.sendInitOrReady(context, cccid, initargs, chaincodeSupport.ccStartupTimeout)
576+
//launch will set the chaincode in Ready state
577+
err = chaincodeSupport.sendReady(context, cccid, chaincodeSupport.ccStartupTimeout)
563578
if err != nil {
564579
chaincodeLogger.Errorf("sending init failed(%s)", err)
565580
err = fmt.Errorf("Failed to init chaincode(%s)", err)
@@ -585,50 +600,6 @@ func (chaincodeSupport *ChaincodeSupport) getVMType(cds *pb.ChaincodeDeploymentS
585600
return container.DOCKER, nil
586601
}
587602

588-
// Deploy deploys the chaincode if not in development mode where user is running the chaincode.
589-
func (chaincodeSupport *ChaincodeSupport) Deploy(context context.Context, cccid *ccprovider.CCContext, cds *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeDeploymentSpec, error) {
590-
cLang := cds.ChaincodeSpec.Type
591-
canName := cccid.GetCanonicalName()
592-
593-
if chaincodeSupport.userRunsCC {
594-
chaincodeLogger.Debug("user runs chaincode, not deploying chaincode")
595-
return nil, nil
596-
}
597-
598-
chaincodeSupport.runningChaincodes.Lock()
599-
//if its in the map, there must be a connected stream...and we are trying to build the code ?!
600-
if _, ok := chaincodeSupport.chaincodeHasBeenLaunched(canName); ok {
601-
chaincodeLogger.Debugf("deploy ?!! there's a chaincode with that name running: %s", canName)
602-
chaincodeSupport.runningChaincodes.Unlock()
603-
return cds, fmt.Errorf("deploy attempted but a chaincode with same name running %s", canName)
604-
}
605-
chaincodeSupport.runningChaincodes.Unlock()
606-
607-
args, envs, err := chaincodeSupport.getArgsAndEnv(cccid, cLang)
608-
if err != nil {
609-
return cds, fmt.Errorf("error getting args for chaincode %s", err)
610-
}
611-
612-
targz, err := platforms.GenerateDockerBuild(cds)
613-
if err != nil {
614-
return cds, fmt.Errorf("error converting CodePackage to Docker: %s", err)
615-
}
616-
617-
cir := &container.CreateImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID, Version: cccid.Version}, Args: args, Reader: targz, Env: envs}
618-
619-
vmtype, _ := chaincodeSupport.getVMType(cds)
620-
621-
chaincodeLogger.Debugf("deploying chaincode %s(networkid:%s,peerid:%s)", canName, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID)
622-
623-
//create image and create container
624-
resp, err2 := container.VMCProcess(context, vmtype, cir)
625-
if err2 != nil || (resp != nil && resp.(container.VMCResp).Err != nil) {
626-
err = fmt.Errorf("Error creating image: %s", err2)
627-
}
628-
629-
return cds, err
630-
}
631-
632603
// HandleChaincodeStream implements ccintf.HandleChaincodeStream for all vms to call with appropriate stream
633604
func (chaincodeSupport *ChaincodeSupport) HandleChaincodeStream(ctxt context.Context, stream ccintf.ChaincodeStream) error {
634605
return HandleChaincodeStream(chaincodeSupport, ctxt, stream)
@@ -639,14 +610,14 @@ func (chaincodeSupport *ChaincodeSupport) Register(stream pb.ChaincodeSupport_Re
639610
return chaincodeSupport.HandleChaincodeStream(stream.Context(), stream)
640611
}
641612

642-
// createTransactionMessage creates a transaction message.
643-
func createTransactionMessage(txid string, cMsg *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
613+
// createCCMessage creates a transaction message.
614+
func createCCMessage(typ pb.ChaincodeMessage_Type, txid string, cMsg *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
644615
payload, err := proto.Marshal(cMsg)
645616
if err != nil {
646617
fmt.Printf(err.Error())
647618
return nil, err
648619
}
649-
return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: txid}, nil
620+
return &pb.ChaincodeMessage{Type: typ, Payload: payload, Txid: txid}, nil
650621
}
651622

652623
// Execute executes a transaction and waits for it to complete until a timeout value.

core/chaincode/concurrency_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func TestExecuteConcurrentInvokes(t *testing.T) {
4848

4949
url := "github.com/hyperledger/fabric/examples/ccchecker/chaincodes/newkeyperinvoke"
5050

51-
chaincodeID := &pb.ChaincodeID{Name: "nkpi", Path: url}
51+
chaincodeID := &pb.ChaincodeID{Name: "nkpi", Path: url, Version: "0"}
5252

5353
args := util.ToChaincodeArgs("init", "")
5454

core/chaincode/exectransaction.go

+48-58
Original file line numberDiff line numberDiff line change
@@ -35,79 +35,69 @@ func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}
3535
var err error
3636
var cds *pb.ChaincodeDeploymentSpec
3737
var ci *pb.ChaincodeInvocationSpec
38+
39+
//init will call the Init method of a on a chain
40+
cctyp := pb.ChaincodeMessage_INIT
3841
if cds, _ = spec.(*pb.ChaincodeDeploymentSpec); cds == nil {
3942
if ci, _ = spec.(*pb.ChaincodeInvocationSpec); ci == nil {
4043
panic("Execute should be called with deployment or invocation spec")
4144
}
45+
cctyp = pb.ChaincodeMessage_TRANSACTION
4246
}
4347

44-
if cds != nil {
45-
_, err := theChaincodeSupport.Deploy(ctxt, cccid, cds)
46-
if err != nil {
47-
return nil, nil, fmt.Errorf("Failed to deploy chaincode spec(%s)", err)
48-
}
48+
cID, cMsg, err := theChaincodeSupport.Launch(ctxt, cccid, spec)
49+
if err != nil {
50+
return nil, nil, fmt.Errorf("%s", err)
51+
}
4952

50-
_, _, err = theChaincodeSupport.Launch(ctxt, cccid, cds)
51-
if err != nil {
52-
return nil, nil, fmt.Errorf("%s", err)
53-
}
54-
} else {
55-
//will launch if necessary (and wait for ready)
56-
cID, cMsg, err := theChaincodeSupport.Launch(ctxt, cccid, ci)
57-
if err != nil {
58-
return nil, nil, fmt.Errorf("Failed to launch chaincode spec(%s)", err)
59-
}
53+
//this should work because it worked above...
54+
chaincode := cID.Name
6055

61-
//this should work because it worked above...
62-
chaincode := cID.Name
56+
if err != nil {
57+
return nil, nil, fmt.Errorf("Failed to stablish stream to container %s", chaincode)
58+
}
6359

64-
if err != nil {
65-
return nil, nil, fmt.Errorf("Failed to stablish stream to container %s", chaincode)
66-
}
60+
// TODO: Need to comment next line and uncomment call to getTimeout, when transaction blocks are being created
61+
timeout := time.Duration(30000) * time.Millisecond
6762

68-
// TODO: Need to comment next line and uncomment call to getTimeout, when transaction blocks are being created
69-
timeout := time.Duration(30000) * time.Millisecond
63+
if err != nil {
64+
return nil, nil, fmt.Errorf("Failed to retrieve chaincode spec(%s)", err)
65+
}
7066

71-
if err != nil {
72-
return nil, nil, fmt.Errorf("Failed to retrieve chaincode spec(%s)", err)
73-
}
67+
var ccMsg *pb.ChaincodeMessage
68+
ccMsg, err = createCCMessage(cctyp, cccid.TxID, cMsg)
69+
if err != nil {
70+
return nil, nil, fmt.Errorf("Failed to transaction message(%s)", err)
71+
}
7472

75-
var ccMsg *pb.ChaincodeMessage
76-
ccMsg, err = createTransactionMessage(cccid.TxID, cMsg)
77-
if err != nil {
78-
return nil, nil, fmt.Errorf("Failed to transaction message(%s)", err)
79-
}
73+
resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout)
74+
if err != nil {
75+
// Rollback transaction
76+
return nil, nil, fmt.Errorf("Failed to execute transaction (%s)", err)
77+
} else if resp == nil {
78+
// Rollback transaction
79+
return nil, nil, fmt.Errorf("Failed to receive a response for (%s)", cccid.TxID)
80+
}
81+
res := &pb.Response{}
82+
unmarshalErr := proto.Unmarshal(resp.Payload, res)
83+
if unmarshalErr != nil {
84+
return nil, nil, fmt.Errorf("Failed to unmarshal response for (%s): %s", cccid.TxID, unmarshalErr)
85+
}
8086

81-
resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout)
82-
if err != nil {
83-
// Rollback transaction
84-
return nil, nil, fmt.Errorf("Failed to execute transaction (%s)", err)
85-
} else if resp == nil {
86-
// Rollback transaction
87-
return nil, nil, fmt.Errorf("Failed to receive a response for (%s)", cccid.TxID)
88-
}
89-
res := &pb.Response{}
90-
unmarshalErr := proto.Unmarshal(resp.Payload, res)
91-
if unmarshalErr != nil {
92-
return nil, nil, fmt.Errorf("Failed to unmarshal response for (%s): %s", cccid.TxID, unmarshalErr)
93-
} else {
94-
if resp.ChaincodeEvent != nil {
95-
resp.ChaincodeEvent.ChaincodeID = cccid.Name
96-
resp.ChaincodeEvent.TxID = cccid.TxID
97-
}
98-
99-
if resp.Type == pb.ChaincodeMessage_COMPLETED {
100-
// Success
101-
return res, resp.ChaincodeEvent, nil
102-
} else if resp.Type == pb.ChaincodeMessage_ERROR {
103-
// Rollback transaction
104-
return nil, resp.ChaincodeEvent, fmt.Errorf("Transaction returned with failure: %s", string(resp.Payload))
105-
}
106-
return res, nil, fmt.Errorf("receive a response for (%s) but in invalid state(%d)", cccid.TxID, resp.Type)
107-
}
87+
if resp.ChaincodeEvent != nil {
88+
resp.ChaincodeEvent.ChaincodeID = cccid.Name
89+
resp.ChaincodeEvent.TxID = cccid.TxID
90+
}
10891

92+
if resp.Type == pb.ChaincodeMessage_COMPLETED {
93+
// Success
94+
return res, resp.ChaincodeEvent, nil
95+
} else if resp.Type == pb.ChaincodeMessage_ERROR {
96+
// Rollback transaction
97+
return nil, resp.ChaincodeEvent, fmt.Errorf("Transaction returned with failure: %s", string(resp.Payload))
10998
}
110-
return &pb.Response{Status: shim.OK, Payload: nil}, nil, err
99+
100+
return res, nil, fmt.Errorf("receive a response for (%s) but in invalid state(%d)", cccid.TxID, resp.Type)
111101
}
112102

113103
// ExecuteWithErrorFilter is similar to Execute, but filters error contained in chaincode response and returns Payload of response only.

0 commit comments

Comments
 (0)