From 7f5184037fe522784303e620334edd8991e713fb Mon Sep 17 00:00:00 2001 From: Srinivasan Muralidharan Date: Mon, 12 Dec 2016 00:36:54 -0500 Subject: [PATCH] FAB-1357 simpl. cc API param passing using a ctxt obj https://jira.hyperledger.org/browse/FAB-1357 List of parameters to many of the chaincode APIs is growing . chaincode name . chain ID . version (needed for upgrade) . Proposal . txid Before getting into the meat of upgrade, simplify the APIs using a CCContext structure. In addition to cleaning and simplifying APIs, this will make the upgrade CR easier to follow Change-Id: Ic7ea5f4e082d347cda3072fc2e39077006d866c1 Signed-off-by: Srinivasan Muralidharan --- core/chaincode/chaincode_support.go | 123 ++++++++---- core/chaincode/chaincodeexec.go | 9 +- core/chaincode/exectransaction.go | 20 +- core/chaincode/exectransaction_test.go | 218 +++++++++++++--------- core/chaincode/handler.go | 7 +- core/chaincode/importsysccs.go | 11 ++ core/chaincode/lccc.go | 23 ++- core/chaincode/lccc_test.go | 2 +- core/chaincode/multichains_test.go | 5 +- core/chaincode/sysccapi.go | 11 +- core/chaincode/systemchaincode_test.go | 7 +- core/committer/noopssinglechain/client.go | 4 +- core/endorser/endorser.go | 26 ++- core/endorser/endorser_test.go | 48 +++-- 14 files changed, 334 insertions(+), 180 deletions(-) diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index 6306c0f52c3..7463bd9801a 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -64,6 +64,57 @@ func getTxSimulator(context context.Context) ledger.TxSimulator { panic("!!!---Not Using ledgernext---!!!") } +//CCContext pass this around instead of string of args +type CCContext struct { + //ChainID chain id + ChainID string + + //Name chaincode name + Name string + + //Version used to construct the chaincode image and register + Version string + + //TxID is the transaction id for the proposal (if any) + TxID string + + //Syscc is this a system chaincode + Syscc bool + + //Proposal for this invoke (if any) + //this is kept here just in case we need to pass something + //from this to the chaincode + Proposal *pb.Proposal + + //this is not set but computed (note that this is not exported. use GetCanonicalName) + canName string +} + +//NewCCContext just construct a new struct with whatever args +func NewCCContext(cid, name, version, txid string, syscc bool, prop *pb.Proposal) *CCContext { + var canName string + if version != "" { + canName = name + ":" + version + "/" + cid + } else { + canName = name + "/" + cid + } + + cccid := &CCContext{cid, name, version, txid, syscc, prop, canName} + + chaincodeLogger.Infof("NewCCCC (chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t,proposal=%p,canname=%s", cid, name, version, txid, syscc, prop, cccid.canName) + + return cccid +} + +//GetCanonicalName returns the canonical name associated with the proposal context +func (cccid *CCContext) GetCanonicalName() string { + if cccid.canName == "" { + panic(fmt.Sprintf("cccid not constructed using NewCCContext(chain=%s,chaincode=%s,version=%s,txid=%s,syscc=%t)", cccid.ChainID, cccid.Name, cccid.Version, cccid.TxID, cccid.Syscc)) + } + + return cccid.canName +} + // //chaincode runtime environment encapsulates handler and container environment //This is where the VM that's running the chaincode would hook in @@ -78,6 +129,7 @@ type runningChaincodes struct { chaincodeMap map[string]*chaincodeRTEnv } +//GetChain returns the chaincode framework support object func GetChain() *ChaincodeSupport { return theChaincodeSupport } @@ -193,10 +245,6 @@ type ChaincodeSupport struct { chaincodeLogLevel string } -func (*ChaincodeSupport) getCanonicalCCName(chainID string, name string) string { - return name + "/" + chainID -} - // DuplicateChaincodeHandlerError returned if attempt to register same chaincodeID while a stream already exists. type DuplicateChaincodeHandlerError struct { ChaincodeID *pb.ChaincodeID @@ -265,8 +313,8 @@ func (chaincodeSupport *ChaincodeSupport) deregisterHandler(chaincodehandler *Ha } // Based on state of chaincode send either init or ready to move to ready state -func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Context, chainID string, txid string, prop *pb.Proposal, chaincode string, initArgs [][]byte, timeout time.Duration) error { - canName := chaincodeSupport.getCanonicalCCName(chainID, chaincode) +func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Context, cccid *CCContext, initArgs [][]byte, timeout time.Duration) error { + canName := cccid.GetCanonicalName() chaincodeSupport.runningChaincodes.Lock() //if its in the map, there must be a connected stream...nothing to do var chrte *chaincodeRTEnv @@ -280,7 +328,7 @@ func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Contex var notfy chan *pb.ChaincodeMessage var err error - if notfy, err = chrte.handler.initOrReady(context, chainID, txid, prop, initArgs); err != nil { + if notfy, err = chrte.handler.initOrReady(context, cccid.ChainID, cccid.TxID, cccid.Proposal, initArgs); err != nil { return fmt.Errorf("Error sending %s: %s", pb.ChaincodeMessage_INIT, err) } if notfy != nil { @@ -295,14 +343,14 @@ func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Contex } //if initOrReady succeeded, our responsibility to delete the context - chrte.handler.deleteTxContext(txid) + chrte.handler.deleteTxContext(cccid.TxID) return err } //get args and env given chaincodeID -func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(chainID string, cID *pb.ChaincodeID, cLang pb.ChaincodeSpec_Type) (args []string, envs []string, err error) { - canName := chaincodeSupport.getCanonicalCCName(chainID, cID.Name) +func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cccid *CCContext, cLang pb.ChaincodeSpec_Type) (args []string, envs []string, err error) { + canName := cccid.GetCanonicalName() envs = []string{"CORE_CHAINCODE_ID_NAME=" + canName} //if TLS is enabled, pass TLS material to chaincode if chaincodeSupport.peerTLS { @@ -322,13 +370,13 @@ func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(chainID string, cID *pb. switch cLang { case pb.ChaincodeSpec_GOLANG, pb.ChaincodeSpec_CAR: //chaincode executable will be same as the name of the chaincode - args = []string{chaincodeSupport.chaincodeInstallPath + cID.Name, fmt.Sprintf("-peer.address=%s", chaincodeSupport.peerAddress)} + args = []string{chaincodeSupport.chaincodeInstallPath + cccid.Name, fmt.Sprintf("-peer.address=%s", chaincodeSupport.peerAddress)} chaincodeLogger.Debugf("Executable is %s", args[0]) case pb.ChaincodeSpec_JAVA: //TODO add security args args = strings.Split( fmt.Sprintf("/root/Chaincode/bin/runChaincode -a %s -i %s", - chaincodeSupport.peerAddress, cID.Name), + chaincodeSupport.peerAddress, cccid.Name), " ") if chaincodeSupport.peerTLS { args = append(args, " -s") @@ -341,8 +389,8 @@ func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(chainID string, cID *pb. } // launchAndWaitForRegister will launch container if not already running. Use the targz to create the image if not found -func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context.Context, cds *pb.ChaincodeDeploymentSpec, chainID string, cID *pb.ChaincodeID, txid string, cLang pb.ChaincodeSpec_Type, targz io.Reader) (bool, error) { - canName := chaincodeSupport.getCanonicalCCName(chainID, cID.Name) +func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context.Context, cccid *CCContext, cds *pb.ChaincodeDeploymentSpec, cLang pb.ChaincodeSpec_Type, targz io.Reader) (bool, error) { + canName := cccid.GetCanonicalName() if canName == "" { return false, fmt.Errorf("chaincode name not set") } @@ -362,7 +410,7 @@ func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context. //launch the chaincode - args, env, err := chaincodeSupport.getArgsAndEnv(chainID, cID, cLang) + args, env, err := chaincodeSupport.getArgsAndEnv(cccid, cLang) if err != nil { return alreadyRunning, err } @@ -371,7 +419,7 @@ func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context. vmtype, _ := chaincodeSupport.getVMType(cds) - sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: chainID}, Reader: targz, Args: args, Env: env} + sir := container.StartImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID}, Reader: targz, Args: args, Env: env} ipcCtxt := context.WithValue(ctxt, ccintf.GetCCHandlerKey(), chaincodeSupport) @@ -391,14 +439,14 @@ func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context. select { case ok := <-notfy: if !ok { - err = fmt.Errorf("registration failed for %s(networkid:%s,peerid:%s,tx:%s)", canName, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID, txid) + err = fmt.Errorf("registration failed for %s(networkid:%s,peerid:%s,tx:%s)", canName, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID, cccid.TxID) } case <-time.After(chaincodeSupport.ccStartupTimeout): - err = fmt.Errorf("Timeout expired while starting chaincode %s(networkid:%s,peerid:%s,tx:%s)", canName, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID, txid) + err = fmt.Errorf("Timeout expired while starting chaincode %s(networkid:%s,peerid:%s,tx:%s)", canName, chaincodeSupport.peerNetworkID, chaincodeSupport.peerID, cccid.TxID) } if err != nil { chaincodeLogger.Debugf("stopping due to error while launching %s", err) - errIgnore := chaincodeSupport.Stop(ctxt, chainID, cds) + errIgnore := chaincodeSupport.Stop(ctxt, cccid, cds) if errIgnore != nil { chaincodeLogger.Debugf("error on stop %s(%s)", errIgnore, err) } @@ -407,14 +455,14 @@ func (chaincodeSupport *ChaincodeSupport) launchAndWaitForRegister(ctxt context. } //Stop stops a chaincode if running -func (chaincodeSupport *ChaincodeSupport) Stop(context context.Context, chainID string, cds *pb.ChaincodeDeploymentSpec) error { - canName := chaincodeSupport.getCanonicalCCName(chainID, cds.ChaincodeSpec.ChaincodeID.Name) +func (chaincodeSupport *ChaincodeSupport) Stop(context context.Context, cccid *CCContext, cds *pb.ChaincodeDeploymentSpec) error { + canName := cccid.GetCanonicalName() if canName == "" { return fmt.Errorf("chaincode name not set") } //stop the chaincode - sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: chainID}, Timeout: 0} + sir := container.StopImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID}, Timeout: 0} vmtype, _ := chaincodeSupport.getVMType(cds) @@ -439,7 +487,7 @@ func (chaincodeSupport *ChaincodeSupport) Stop(context context.Context, chainID } // Launch will launch the chaincode if not running (if running return nil) and will wait for handler of the chaincode to get into FSM ready state. -func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, chainID string, txid string, prop *pb.Proposal, spec interface{}) (*pb.ChaincodeID, *pb.ChaincodeInput, error) { +func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, cccid *CCContext, spec interface{}) (*pb.ChaincodeID, *pb.ChaincodeInput, error) { //build the chaincode var cID *pb.ChaincodeID var cMsg *pb.ChaincodeInput @@ -463,7 +511,7 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, chainI cMsg = ci.ChaincodeSpec.CtorMsg } - canName := chaincodeSupport.getCanonicalCCName(chainID, cID.Name) + canName := cccid.GetCanonicalName() chaincodeSupport.runningChaincodes.Lock() var chrte *chaincodeRTEnv var ok bool @@ -486,6 +534,10 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, chainI chaincodeSupport.runningChaincodes.Unlock() if cds == nil { + if cccid.Syscc { + return cID, cMsg, fmt.Errorf("a syscc should be running (it cannot be launched) %s", canName) + } + if chaincodeSupport.userRunsCC { chaincodeLogger.Error("You are attempting to perform an action other than Deploy on Chaincode that is not ready and you are in developer mode. Did you forget to Deploy your chaincode?") } @@ -496,7 +548,7 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, chainI var depPayload []byte //hopefully we are restarting from existing image and the deployed transaction exists - depPayload, err = GetCDSFromLCCC(context, txid, prop, chainID, cID.Name) + depPayload, err = GetCDSFromLCCC(context, cccid.TxID, cccid.Proposal, cccid.ChainID, cID.Name) if err != nil { return cID, cMsg, fmt.Errorf("Could not get deployment transaction from LCCC for %s - %s", canName, err) } @@ -518,7 +570,7 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, chainI //launch container if it is a System container or not in dev mode if (!chaincodeSupport.userRunsCC || cds.ExecEnv == pb.ChaincodeDeploymentSpec_SYSTEM) && (chrte == nil || chrte.handler == nil) { var targz io.Reader = bytes.NewBuffer(cds.CodePackage) - _, err = chaincodeSupport.launchAndWaitForRegister(context, cds, chainID, cID, txid, cLang, targz) + _, err = chaincodeSupport.launchAndWaitForRegister(context, cccid, cds, cLang, targz) if err != nil { chaincodeLogger.Errorf("launchAndWaitForRegister failed %s", err) return cID, cMsg, err @@ -527,11 +579,11 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, chainI if err == nil { //send init (if (args)) and wait for ready state - err = chaincodeSupport.sendInitOrReady(context, chainID, txid, prop, cID.Name, initargs, chaincodeSupport.ccStartupTimeout) + err = chaincodeSupport.sendInitOrReady(context, cccid, initargs, chaincodeSupport.ccStartupTimeout) if err != nil { chaincodeLogger.Errorf("sending init failed(%s)", err) err = fmt.Errorf("Failed to init chaincode(%s)", err) - errIgnore := chaincodeSupport.Stop(context, chainID, cds) + errIgnore := chaincodeSupport.Stop(context, cccid, cds) if errIgnore != nil { chaincodeLogger.Errorf("stop failed %s(%s)", errIgnore, err) } @@ -554,10 +606,9 @@ func (chaincodeSupport *ChaincodeSupport) getVMType(cds *pb.ChaincodeDeploymentS } // Deploy deploys the chaincode if not in development mode where user is running the chaincode. -func (chaincodeSupport *ChaincodeSupport) Deploy(context context.Context, chainID string, cds *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeDeploymentSpec, error) { - cID := cds.ChaincodeSpec.ChaincodeID +func (chaincodeSupport *ChaincodeSupport) Deploy(context context.Context, cccid *CCContext, cds *pb.ChaincodeDeploymentSpec) (*pb.ChaincodeDeploymentSpec, error) { cLang := cds.ChaincodeSpec.Type - canName := chaincodeSupport.getCanonicalCCName(chainID, cID.Name) + canName := cccid.GetCanonicalName() if chaincodeSupport.userRunsCC { chaincodeLogger.Debug("user runs chaincode, not deploying chaincode") @@ -573,13 +624,13 @@ func (chaincodeSupport *ChaincodeSupport) Deploy(context context.Context, chainI } chaincodeSupport.runningChaincodes.Unlock() - args, envs, err := chaincodeSupport.getArgsAndEnv(chainID, cID, cLang) + args, envs, err := chaincodeSupport.getArgsAndEnv(cccid, cLang) if err != nil { return cds, fmt.Errorf("error getting args for chaincode %s", err) } var targz io.Reader = bytes.NewBuffer(cds.CodePackage) - cir := &container.CreateImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: chainID}, Args: args, Reader: targz, Env: envs} + cir := &container.CreateImageReq{CCID: ccintf.CCID{ChaincodeSpec: cds.ChaincodeSpec, NetworkID: chaincodeSupport.peerNetworkID, PeerID: chaincodeSupport.peerID, ChainID: cccid.ChainID}, Args: args, Reader: targz, Env: envs} vmtype, _ := chaincodeSupport.getVMType(cds) @@ -615,8 +666,8 @@ func createTransactionMessage(txid string, cMsg *pb.ChaincodeInput) (*pb.Chainco } // Execute executes a transaction and waits for it to complete until a timeout value. -func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, chainID string, chaincode string, msg *pb.ChaincodeMessage, timeout time.Duration, prop *pb.Proposal) (*pb.ChaincodeMessage, error) { - canName := chaincodeSupport.getCanonicalCCName(chainID, chaincode) +func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, cccid *CCContext, msg *pb.ChaincodeMessage, timeout time.Duration) (*pb.ChaincodeMessage, error) { + canName := cccid.GetCanonicalName() chaincodeSupport.runningChaincodes.Lock() //we expect the chaincode to be running... sanity check chrte, ok := chaincodeSupport.chaincodeHasBeenLaunched(canName) @@ -629,7 +680,7 @@ func (chaincodeSupport *ChaincodeSupport) Execute(ctxt context.Context, chainID var notfy chan *pb.ChaincodeMessage var err error - if notfy, err = chrte.handler.sendExecuteMessage(ctxt, chainID, msg, prop); err != nil { + if notfy, err = chrte.handler.sendExecuteMessage(ctxt, cccid.ChainID, msg, cccid.Proposal); err != nil { return nil, fmt.Errorf("Error sending %s: %s", msg.Type.String(), err) } var ccresp *pb.ChaincodeMessage diff --git a/core/chaincode/chaincodeexec.go b/core/chaincode/chaincodeexec.go index dbc9dd5f521..7ab9ac56949 100644 --- a/core/chaincode/chaincodeexec.go +++ b/core/chaincode/chaincodeexec.go @@ -36,19 +36,20 @@ func createCIS(ccname string, args [][]byte) (*pb.ChaincodeInvocationSpec, error // GetCDSFromLCCC gets chaincode deployment spec from LCCC func GetCDSFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) ([]byte, error) { - payload, _, err := ExecuteChaincode(ctxt, chainID, txid, prop, "lccc", [][]byte{[]byte("getdepspec"), []byte(chainID), []byte(chaincodeID)}) + cccid := NewCCContext(chainID, "lccc", "", txid, true, prop) + payload, _, err := ExecuteChaincode(ctxt, cccid, [][]byte{[]byte("getdepspec"), []byte(chainID), []byte(chaincodeID)}) return payload, err } // ExecuteChaincode executes a given chaincode given chaincode name and arguments -func ExecuteChaincode(ctxt context.Context, chainID string, txid string, prop *pb.Proposal, ccname string, args [][]byte) ([]byte, *pb.ChaincodeEvent, error) { +func ExecuteChaincode(ctxt context.Context, cccid *CCContext, args [][]byte) ([]byte, *pb.ChaincodeEvent, error) { var spec *pb.ChaincodeInvocationSpec var err error var b []byte var ccevent *pb.ChaincodeEvent - spec, err = createCIS(ccname, args) - b, ccevent, err = Execute(ctxt, chainID, txid, prop, spec) + spec, err = createCIS(cccid.Name, args) + b, ccevent, err = Execute(ctxt, cccid, spec) if err != nil { return nil, nil, fmt.Errorf("Error deploying chaincode: %s", err) } diff --git a/core/chaincode/exectransaction.go b/core/chaincode/exectransaction.go index 0d24ea9e58d..eec74c55726 100644 --- a/core/chaincode/exectransaction.go +++ b/core/chaincode/exectransaction.go @@ -28,7 +28,7 @@ import ( ) //Execute - execute proposal -func Execute(ctxt context.Context, chainID string, txid string, prop *pb.Proposal, spec interface{}) ([]byte, *pb.ChaincodeEvent, error) { +func Execute(ctxt context.Context, cccid *CCContext, spec interface{}) ([]byte, *pb.ChaincodeEvent, error) { var err error var cds *pb.ChaincodeDeploymentSpec var ci *pb.ChaincodeInvocationSpec @@ -39,18 +39,18 @@ func Execute(ctxt context.Context, chainID string, txid string, prop *pb.Proposa } if cds != nil { - _, err := theChaincodeSupport.Deploy(ctxt, chainID, cds) + _, err := theChaincodeSupport.Deploy(ctxt, cccid, cds) if err != nil { return nil, nil, fmt.Errorf("Failed to deploy chaincode spec(%s)", err) } - _, _, err = theChaincodeSupport.Launch(ctxt, chainID, txid, prop, cds) + _, _, err = theChaincodeSupport.Launch(ctxt, cccid, cds) if err != nil { return nil, nil, fmt.Errorf("%s", err) } } else { //will launch if necessary (and wait for ready) - cID, cMsg, err := theChaincodeSupport.Launch(ctxt, chainID, txid, prop, ci) + cID, cMsg, err := theChaincodeSupport.Launch(ctxt, cccid, ci) if err != nil { return nil, nil, fmt.Errorf("Failed to launch chaincode spec(%s)", err) } @@ -70,22 +70,22 @@ func Execute(ctxt context.Context, chainID string, txid string, prop *pb.Proposa } var ccMsg *pb.ChaincodeMessage - ccMsg, err = createTransactionMessage(txid, cMsg) + ccMsg, err = createTransactionMessage(cccid.TxID, cMsg) if err != nil { return nil, nil, fmt.Errorf("Failed to transaction message(%s)", err) } - resp, err := theChaincodeSupport.Execute(ctxt, chainID, chaincode, ccMsg, timeout, prop) + resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout) if err != nil { // Rollback transaction return nil, nil, fmt.Errorf("Failed to execute transaction (%s)", err) } else if resp == nil { // Rollback transaction - return nil, nil, fmt.Errorf("Failed to receive a response for (%s)", txid) + return nil, nil, fmt.Errorf("Failed to receive a response for (%s)", cccid.TxID) } else { if resp.ChaincodeEvent != nil { - resp.ChaincodeEvent.ChaincodeID = chaincode - resp.ChaincodeEvent.TxID = txid + resp.ChaincodeEvent.ChaincodeID = cccid.Name + resp.ChaincodeEvent.TxID = cccid.TxID } if resp.Type == pb.ChaincodeMessage_COMPLETED { @@ -95,7 +95,7 @@ func Execute(ctxt context.Context, chainID string, txid string, prop *pb.Proposa // Rollback transaction return nil, resp.ChaincodeEvent, fmt.Errorf("Transaction returned with failure: %s", string(resp.Payload)) } - return resp.Payload, nil, fmt.Errorf("receive a response for (%s) but in invalid state(%d)", txid, resp.Type) + return resp.Payload, nil, fmt.Errorf("receive a response for (%s) but in invalid state(%d)", cccid.TxID, resp.Type) } } diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index 401817dad5d..f42a562f5a1 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -229,48 +229,50 @@ func getDeployLCCCSpec(chainID string, cds *pb.ChaincodeDeploymentSpec) (*pb.Cha } // Deploy a chaincode - i.e., build and initialize. -func deploy(ctx context.Context, chainID string, spec *pb.ChaincodeSpec) (b []byte, err error) { +func deploy(ctx context.Context, cccid *CCContext, spec *pb.ChaincodeSpec) (b []byte, err error) { // First build and get the deployment spec chaincodeDeploymentSpec, err := getDeploymentSpec(ctx, spec) if err != nil { return nil, err } - return deploy2(ctx, chainID, chaincodeDeploymentSpec) + return deploy2(ctx, cccid, chaincodeDeploymentSpec) } -func deploy2(ctx context.Context, chainID string, chaincodeDeploymentSpec *pb.ChaincodeDeploymentSpec) (b []byte, err error) { - cis, err := getDeployLCCCSpec(chainID, chaincodeDeploymentSpec) +func deploy2(ctx context.Context, cccid *CCContext, chaincodeDeploymentSpec *pb.ChaincodeDeploymentSpec) (b []byte, err error) { + cis, err := getDeployLCCCSpec(cccid.ChainID, chaincodeDeploymentSpec) if err != nil { return nil, fmt.Errorf("Error creating lccc spec : %s\n", err) } - tid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name - - ctx, txsim, err := startTxSimulation(ctx, chainID) + ctx, txsim, err := startTxSimulation(ctx, cccid.ChainID) if err != nil { return nil, fmt.Errorf("Failed to get handle to simulator: %s ", err) } uuid := util.GenerateUUID() + cccid.TxID = uuid + defer func() { //no error, lets try commit if err == nil { //capture returned error from commit - err = endTxSimulationCDS(chainID, uuid, txsim, []byte("deployed"), true, chaincodeDeploymentSpec) + err = endTxSimulationCDS(cccid.ChainID, uuid, txsim, []byte("deployed"), true, chaincodeDeploymentSpec) } else { //there was an error, just close simulation and return that - endTxSimulationCDS(chainID, uuid, txsim, []byte("deployed"), false, chaincodeDeploymentSpec) + endTxSimulationCDS(cccid.ChainID, uuid, txsim, []byte("deployed"), false, chaincodeDeploymentSpec) } }() + lcccid := NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeID.Name, "", uuid, true, nil) + //write to lccc - if _, _, err = Execute(ctx, chainID, uuid, nil, cis); err != nil { + if _, _, err = Execute(ctx, lcccid, cis); err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s", err) } - if b, _, err = Execute(ctx, chainID, tid, nil, chaincodeDeploymentSpec); err != nil { + if b, _, err = Execute(ctx, cccid, chaincodeDeploymentSpec); err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s", err) } @@ -301,7 +303,8 @@ func invoke(ctx context.Context, chainID string, spec *pb.ChaincodeSpec) (ccevt } }() - retval, ccevt, err = Execute(ctx, chainID, uuid, nil, chaincodeInvocationSpec) + cccid := NewCCContext(chainID, chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name, "", uuid, false, nil) + retval, ccevt, err = Execute(ctx, cccid, chaincodeInvocationSpec) if err != nil { return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s ", err) } @@ -330,16 +333,20 @@ func executeDeployTransaction(t *testing.T, chainID string, name string, url str f := "init" args := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: name, Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}} - _, err = deploy(ctxt, chainID, spec) + + cccid := NewCCContext(chainID, name, "", "", false, nil) + + _, err = deploy(ctxt, cccid, spec) + chaincodeID := spec.ChaincodeID.Name if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) t.Fail() t.Logf("Error deploying <%s>: %s", chaincodeID, err) return } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } func chaincodeQueryChaincode(chainID string, user string) error { @@ -354,10 +361,13 @@ func chaincodeQueryChaincode(chainID string, user string) error { spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user} - _, err := deploy(ctxt, chainID, spec1) + cccid1 := NewCCContext(chainID, "example02", "", "", false, nil) + + _, err := deploy(ctxt, cccid1, spec1) + chaincodeID1 := spec1.ChaincodeID.Name if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) return fmt.Errorf("Error initializing chaincode %s(%s)", chaincodeID1, err) } @@ -372,11 +382,13 @@ func chaincodeQueryChaincode(chainID string, user string) error { spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user} - _, err = deploy(ctxt, chainID, spec2) + cccid2 := NewCCContext(chainID, "example05", "", "", false, nil) + + _, err = deploy(ctxt, cccid2, spec2) chaincodeID2 := spec2.ChaincodeID.Name if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return fmt.Errorf("Error initializing chaincode %s(%s)", chaincodeID2, err) } @@ -392,16 +404,16 @@ func chaincodeQueryChaincode(chainID string, user string) error { _, _, retVal, err = invoke(ctxt, chainID, spec2) if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return fmt.Errorf("Error invoking <%s>: %s", chaincodeID2, err) } // Check the return value result, err := strconv.Atoi(string(retVal)) if err != nil || result != 300 { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return fmt.Errorf("Incorrect final state after transaction for <%s>: %s", chaincodeID1, err) } @@ -414,21 +426,21 @@ func chaincodeQueryChaincode(chainID string, user string) error { _, _, retVal, err = invoke(ctxt, chainID, spec2) if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return fmt.Errorf("Error querying <%s>: %s", chaincodeID2, err) } // Check the return value result, err = strconv.Atoi(string(retVal)) if err != nil || result != 300 { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return fmt.Errorf("Incorrect final value after query for <%s>: %s", chaincodeID1, err) } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return nil } @@ -461,15 +473,15 @@ func TestHTTPExecuteDeployTransaction(t *testing.T) { } // Check the correctness of the final state after transaction execution. -func checkFinalState(uuid string, chainID string, chaincodeID string) error { - _, txsim, err := startTxSimulation(context.Background(), chainID) +func checkFinalState(cccid *CCContext) error { + _, txsim, err := startTxSimulation(context.Background(), cccid.ChainID) if err != nil { return fmt.Errorf("Failed to get handle to simulator: %s ", err) } defer txsim.Done() - canName := GetChain().getCanonicalCCName(chainID, chaincodeID) + canName := cccid.GetCanonicalName() // Invoke ledger to get state var Aval, Bval int resbytes, resErr := txsim.GetState(canName, "a") @@ -503,12 +515,12 @@ func checkFinalState(uuid string, chainID string, chaincodeID string) error { } // Invoke chaincode_example02 -func invokeExample02Transaction(ctxt context.Context, chainID string, cID *pb.ChaincodeID, args []string, destroyImage bool) error { +func invokeExample02Transaction(ctxt context.Context, cccid *CCContext, cID *pb.ChaincodeID, args []string, destroyImage bool) error { f := "init" argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: argsDeploy}} - _, err := deploy(ctxt, chainID, spec) + _, err := deploy(ctxt, cccid, spec) chaincodeID := spec.ChaincodeID.Name if err != nil { return fmt.Errorf("Error deploying <%s>: %s", chaincodeID, err) @@ -517,8 +529,8 @@ func invokeExample02Transaction(ctxt context.Context, chainID string, cID *pb.Ch time.Sleep(time.Second) if destroyImage { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) - dir := container.DestroyImageReq{CCID: ccintf.CCID{ChaincodeSpec: spec, NetworkID: theChaincodeSupport.peerNetworkID, PeerID: theChaincodeSupport.peerID, ChainID: chainID}, Force: true, NoPrune: true} + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + dir := container.DestroyImageReq{CCID: ccintf.CCID{ChaincodeSpec: spec, NetworkID: theChaincodeSupport.peerNetworkID, PeerID: theChaincodeSupport.peerID, ChainID: cccid.ChainID}, Force: true, NoPrune: true} _, err = container.VMCProcess(ctxt, container.DOCKER, dir) if err != nil { @@ -530,12 +542,13 @@ func invokeExample02Transaction(ctxt context.Context, chainID string, cID *pb.Ch f = "invoke" invokeArgs := append([]string{f}, args...) spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(invokeArgs...)}} - _, uuid, _, err := invoke(ctxt, chainID, spec) + _, uuid, _, err := invoke(ctxt, cccid.ChainID, spec) if err != nil { - return fmt.Errorf("Error invoking <%s>: %s", chaincodeID, err) + return fmt.Errorf("Error invoking <%s>: %s", cccid.Name, err) } - err = checkFinalState(uuid, chainID, chaincodeID) + cccid.TxID = uuid + err = checkFinalState(cccid) if err != nil { return fmt.Errorf("Incorrect final state after transaction for <%s>: %s", chaincodeID, err) } @@ -544,9 +557,9 @@ func invokeExample02Transaction(ctxt context.Context, chainID string, cID *pb.Ch f = "delete" delArgs := util.ToChaincodeArgs(f, "a") spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: delArgs}} - _, uuid, _, err = invoke(ctxt, chainID, spec) + _, uuid, _, err = invoke(ctxt, cccid.ChainID, spec) if err != nil { - return fmt.Errorf("Error deleting state in <%s>: %s", chaincodeID, err) + return fmt.Errorf("Error deleting state in <%s>: %s", cccid.Name, err) } return nil @@ -565,11 +578,12 @@ func TestExecuteInvokeTransaction(t *testing.T) { var ctxt = context.Background() + cccid := NewCCContext(chainID, "example02", "", "", false, nil) url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url} args := []string{"a", "b", "10"} - err = invokeExample02Transaction(ctxt, chainID, chaincodeID, args, true) + err = invokeExample02Transaction(ctxt, cccid, chaincodeID, args, true) if err != nil { t.Fail() t.Logf("Error invoking transaction: %s", err) @@ -578,7 +592,7 @@ func TestExecuteInvokeTransaction(t *testing.T) { t.Logf("Invoke test passed") } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) } // Execute multiple transactions and queries. @@ -630,16 +644,18 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) { url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" chaincodeID := &pb.ChaincodeID{Name: "example02", Path: url} + cccid := NewCCContext(chainID, "example02", "", "", false, nil) + //FAIL, FAIL! args := []string{"x", "-1"} - err = invokeExample02Transaction(ctxt, chainID, chaincodeID, args, false) + err = invokeExample02Transaction(ctxt, cccid, chaincodeID, args, false) //this HAS to fail with expectedDeltaStringPrefix if err != nil { errStr := err.Error() t.Logf("Got error %s\n", errStr) t.Logf("InvalidInvoke test passed") - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) return } @@ -647,7 +663,7 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) { t.Fail() t.Logf("Error invoking transaction %s", err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) } // Test the execution of a chaincode that invokes another chaincode. @@ -685,12 +701,14 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user} - _, err = deploy(ctxt, chainID, spec1) + cccid1 := NewCCContext(chainID, "example02", "", "", false, nil) + + _, err = deploy(ctxt, cccid1, spec1) chaincodeID1 := spec1.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID1, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) return } @@ -707,13 +725,15 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user} - _, err = deploy(ctxt, chainID, spec2) + cccid2 := NewCCContext(chainID, "example04", "", "", false, nil) + + _, err = deploy(ctxt, cccid2, spec2) chaincodeID2 := spec2.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID2, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } @@ -733,23 +753,25 @@ func chaincodeInvokeChaincode(t *testing.T, chainID string, user string) (err er if err != nil { t.Fail() t.Logf("Error invoking <%s>: %s", chaincodeID2, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } + cccid1.TxID = uuid + // Check the state in the ledger - err = checkFinalState(uuid, chainID, chaincodeID1) + err = checkFinalState(cccid1) if err != nil { t.Fail() t.Logf("Incorrect final state after transaction for <%s>: %s", chaincodeID1, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } @@ -778,12 +800,14 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}} - _, err = deploy(ctxt, chainID, spec1) + cccid1 := NewCCContext(chainID, "example02", "", "", false, nil) + + _, err = deploy(ctxt, cccid1, spec1) chaincodeID1 := spec1.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID1, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) return } @@ -798,13 +822,15 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}} - _, err = deploy(ctxt, chainID, spec2) + cccid2 := NewCCContext(chainID, "pthru", "", "", false, nil) + + _, err = deploy(ctxt, cccid2, spec2) chaincodeID2 := spec2.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID2, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } @@ -821,21 +847,21 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { if err == nil { t.Fail() t.Logf("Error invoking <%s>: %s", chaincodeID2, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } if strings.Index(err.Error(), "Incorrect number of arguments. Expecting 3") < 0 { t.Fail() t.Logf("Unexpected error %s", err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) return } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) } // Test the invocation of a transaction. @@ -863,12 +889,14 @@ func TestRangeQuery(t *testing.T) { spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}} - _, err = deploy(ctxt, chainID, spec) + cccid := NewCCContext(chainID, "tmap", "", "", false, nil) + + _, err = deploy(ctxt, cccid, spec) chaincodeID := spec.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } @@ -882,10 +910,10 @@ func TestRangeQuery(t *testing.T) { if err != nil { t.Fail() t.Logf("Error invoking <%s>: %s", chaincodeID, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } func TestGetEvent(t *testing.T) { @@ -907,12 +935,14 @@ func TestGetEvent(t *testing.T) { f := "init" spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(f)}} - _, err = deploy(ctxt, chainID, spec) + cccid := NewCCContext(chainID, "esender", "", "", false, nil) + + _, err = deploy(ctxt, cccid, spec) chaincodeID := spec.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID, err) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } @@ -945,7 +975,7 @@ func TestGetEvent(t *testing.T) { t.Fail() } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } // Test the execution of a chaincode that queries another chaincode @@ -974,10 +1004,12 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}} - _, err = deploy(ctxt, chainID, spec1) + cccid1 := NewCCContext(chainID, "example02", "", "", false, nil) + + _, err = deploy(ctxt, cccid1, spec1) chaincodeID1 := spec1.ChaincodeID.Name if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID1, err) return @@ -994,11 +1026,13 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}} - _, err = deploy(ctxt, chainID, spec2) + cccid2 := NewCCContext(chainID, "example05", "", "", false, nil) + + _, err = deploy(ctxt, cccid2, spec2) chaincodeID2 := spec2.ChaincodeID.Name if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) t.Fail() t.Logf("Error initializing chaincode %s(%s)", chaincodeID2, err) return @@ -1016,8 +1050,8 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { _, _, retVal, err = invoke(ctxt, chainID, spec2) if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) t.Fail() t.Logf("Error invoking <%s>: %s", chaincodeID2, err) return @@ -1026,8 +1060,8 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { // Check the return value result, err := strconv.Atoi(string(retVal)) if err != nil || result != 300 { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) t.Fail() t.Logf("Incorrect final state after transaction for <%s>: %s", chaincodeID1, err) return @@ -1042,8 +1076,8 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { _, _, retVal, err = invoke(ctxt, chainID, spec2) if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) t.Fail() t.Logf("Error querying <%s>: %s", chaincodeID2, err) return @@ -1052,15 +1086,15 @@ func TestChaincodeQueryChaincodeUsingInvoke(t *testing.T) { // Check the return value result, err = strconv.Atoi(string(retVal)) if err != nil || result != 300 { - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) t.Fail() t.Logf("Incorrect final value after query for <%s>: %s", chaincodeID1, err) return } - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) - theChaincodeSupport.Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) + theChaincodeSupport.Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec1}) + theChaincodeSupport.Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec2}) } var signer msp.SigningIdentity diff --git a/core/chaincode/handler.go b/core/chaincode/handler.go index 16584b18a0c..8be4816056b 100644 --- a/core/chaincode/handler.go +++ b/core/chaincode/handler.go @@ -909,8 +909,11 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { // Create the invocation spec chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: chaincodeSpec} + //Get the latest version of newChaincodeID + cccid := NewCCContext(txContext.chainID, newChaincodeID, "", msg.Txid, false, txContext.proposal) + // Launch the new chaincode if not already running - _, chaincodeInput, launchErr := handler.chaincodeSupport.Launch(ctxt, txContext.chainID, msg.Txid, txContext.proposal, chaincodeInvocationSpec) + _, chaincodeInput, launchErr := handler.chaincodeSupport.Launch(ctxt, cccid, chaincodeInvocationSpec) if launchErr != nil { payload := []byte(launchErr.Error()) chaincodeLogger.Debugf("[%s]Failed to launch invoked chaincode. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) @@ -924,7 +927,7 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { ccMsg, _ := createTransactionMessage(msg.Txid, chaincodeInput) // Execute the chaincode - response, execErr := handler.chaincodeSupport.Execute(ctxt, txContext.chainID, newChaincodeID, ccMsg, timeout, txContext.proposal) + response, execErr := handler.chaincodeSupport.Execute(ctxt, cccid, ccMsg, timeout) //payload is marshalled and send to the calling chaincode's shim which unmarshals and //sends it to chaincode diff --git a/core/chaincode/importsysccs.go b/core/chaincode/importsysccs.go index b21101052e8..93e3a157750 100644 --- a/core/chaincode/importsysccs.go +++ b/core/chaincode/importsysccs.go @@ -70,3 +70,14 @@ func deRegisterSysCCs(chainID string) { deregisterSysCC(chainID, sysCC) } } + +//IsSysCC returns true if the name matches a system chaincode's +//system chaincode names are system, chain wide +func IsSysCC(name string) bool { + for _, sysCC := range systemChaincodes { + if sysCC.Name == name { + return true + } + } + return false +} diff --git a/core/chaincode/lccc.go b/core/chaincode/lccc.go index 1e4c46b908d..99ec9792998 100644 --- a/core/chaincode/lccc.go +++ b/core/chaincode/lccc.go @@ -143,9 +143,10 @@ func (t ExistsErr) Error() string { return fmt.Sprintf("Chaincode exists %s", string(t)) } -type ChaincodeNotFoundErr string +//NotFoundErr chaincode not registered with LCCC error +type NotFoundErr string -func (t ChaincodeNotFoundErr) Error() string { +func (t NotFoundErr) Error() string { return fmt.Sprintf("chaincode not found %s", string(t)) } @@ -287,22 +288,26 @@ func (lccc *LifeCycleSysCC) deploy(stub shim.ChaincodeStubInterface, chainname s ctxt = context.WithValue(ctxt, TXSimulatorKey, dummytxsim) - _, err = theChaincodeSupport.Deploy(ctxt, chainname, cds) + //TODO-if/when we use this deploy() func make sure to use the + //TXID of the calling proposal + txid := util.GenerateUUID() + + //deploy does not need a version + cccid := NewCCContext(chainname, cds.ChaincodeSpec.ChaincodeID.Name, "", txid, false, nil) + + _, err = theChaincodeSupport.Deploy(ctxt, cccid, cds) if err != nil { return fmt.Errorf("Failed to deploy chaincode spec(%s)", err) } - //we don't need the original txid (in fact we need a new one) - txid := util.GenerateUUID() - //launch and wait for ready - _, _, err = theChaincodeSupport.Launch(ctxt, chainname, txid, nil, cds) + _, _, err = theChaincodeSupport.Launch(ctxt, cccid, cds) if err != nil { return fmt.Errorf("%s", err) } //stop now that we are done - theChaincodeSupport.Stop(ctxt, chainname, cds) + theChaincodeSupport.Stop(ctxt, cccid, cds) return nil } @@ -356,7 +361,7 @@ func (lccc *LifeCycleSysCC) executeUpgrade(stub shim.ChaincodeStubInterface, cha // check for existence of chaincode cd, err := lccc.getChaincode(stub, chainName, chaincodeName) if cd == nil { - return nil, ChaincodeNotFoundErr(chainName) + return nil, NotFoundErr(chainName) } if err = lccc.acl(stub, chainName, cds); err != nil { diff --git a/core/chaincode/lccc_test.go b/core/chaincode/lccc_test.go index 3d44c82c5ab..4a2126df507 100644 --- a/core/chaincode/lccc_test.go +++ b/core/chaincode/lccc_test.go @@ -312,7 +312,7 @@ func TestUpgradeNonExistChaincode(t *testing.T) { args = [][]byte{[]byte(UPGRADE), []byte("test"), newb} _, err = stub.MockInvoke("1", args) - if _, ok := err.(ChaincodeNotFoundErr); !ok { + if _, ok := err.(NotFoundErr); !ok { t.FailNow() } } diff --git a/core/chaincode/multichains_test.go b/core/chaincode/multichains_test.go index 2d783c1ccda..48ade3d30fc 100644 --- a/core/chaincode/multichains_test.go +++ b/core/chaincode/multichains_test.go @@ -41,14 +41,15 @@ func TestExecuteInvokeOnManyChains(t *testing.T) { args := []string{"a", "b", "10"} for _, c := range chains { - err = invokeExample02Transaction(ctxt, c, chaincodeID, args, true) + cccid := NewCCContext(c, "example02", "", "", false, nil) + err = invokeExample02Transaction(ctxt, cccid, chaincodeID, args, false) if err != nil { t.Fail() t.Logf("Error invoking transaction: %s", err) } else { t.Logf("Invoke test passed for chain %s", c) } - theChaincodeSupport.Stop(ctxt, c, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) } } diff --git a/core/chaincode/sysccapi.go b/core/chaincode/sysccapi.go index c48ebf54103..8a6244640c6 100644 --- a/core/chaincode/sysccapi.go +++ b/core/chaincode/sysccapi.go @@ -25,6 +25,7 @@ import ( "github.com/hyperledger/fabric/core/container/inproccontroller" "github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger/kvledger" + "github.com/hyperledger/fabric/core/util" "github.com/op/go-logging" "github.com/spf13/viper" @@ -105,8 +106,11 @@ func DeploySysCC(chainID string, syscc *SystemChaincode) error { return err } - txid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name - _, _, err = Execute(ctxt, chainID, txid, nil, chaincodeDeploymentSpec) + txid := util.GenerateUUID() + + cccid := NewCCContext(chainID, chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name, "", txid, true, nil) + + _, _, err = Execute(ctxt, cccid, chaincodeDeploymentSpec) sysccLogger.Infof("system chaincode %s/%s(%s) deployed", syscc.Name, chainID, syscc.Path) @@ -129,7 +133,8 @@ func deregisterSysCC(chainID string, syscc *SystemChaincode) error { chaincodeSupport := GetChain() if chaincodeSupport != nil { - err = chaincodeSupport.Stop(ctx, chainID, chaincodeDeploymentSpec) + cccid := NewCCContext(chainID, syscc.Name, "", "", true, nil) + err = chaincodeSupport.Stop(ctx, cccid, chaincodeDeploymentSpec) } return err diff --git a/core/chaincode/systemchaincode_test.go b/core/chaincode/systemchaincode_test.go index 63c546a12b6..93de7e9a902 100644 --- a/core/chaincode/systemchaincode_test.go +++ b/core/chaincode/systemchaincode_test.go @@ -43,8 +43,9 @@ func deploySampleSysCC(t *testing.T, ctxt context.Context, chainID string) error spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}} _, _, _, err := invoke(ctxt, chainID, spec) + cccid := NewCCContext(chainID, "sample_syscc", "", "", true, nil) if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, cdsforStop) + theChaincodeSupport.Stop(ctxt, cccid, cdsforStop) t.Logf("Error invoking sample_syscc: %s", err) return err } @@ -54,12 +55,12 @@ func deploySampleSysCC(t *testing.T, ctxt context.Context, chainID string) error spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "sample_syscc", Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}} _, _, _, err = invoke(ctxt, chainID, spec) if err != nil { - theChaincodeSupport.Stop(ctxt, chainID, cdsforStop) + theChaincodeSupport.Stop(ctxt, cccid, cdsforStop) t.Logf("Error invoking sample_syscc: %s", err) return err } - theChaincodeSupport.Stop(ctxt, chainID, cdsforStop) + theChaincodeSupport.Stop(ctxt, cccid, cdsforStop) return nil } diff --git a/core/committer/noopssinglechain/client.go b/core/committer/noopssinglechain/client.go index d715d33ee98..3b50c1ee7b4 100644 --- a/core/committer/noopssinglechain/client.go +++ b/core/committer/noopssinglechain/client.go @@ -248,8 +248,10 @@ func isTxValidForVscc(payload *common.Payload, envBytes []byte) error { defer txsim.Done() ctxt := context.WithValue(context.Background(), chaincode.TXSimulatorKey, txsim) + cccid := chaincode.NewCCContext(chainName, vscc, "", txid, true, prop) + // invoke VSCC - _, _, err = chaincode.ExecuteChaincode(ctxt, chainName, txid, prop, vscc, args) + _, _, err = chaincode.ExecuteChaincode(ctxt, cccid, args) if err != nil { logger.Errorf("VSCC check failed for transaction, error %s", err) return err diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index a7390dd46c7..6ede68b9f39 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -64,22 +64,22 @@ func (*Endorser) getTxSimulator(ledgername string) (ledger.TxSimulator, error) { } //deploy the chaincode after call to the system chaincode is successful -func (e *Endorser) deploy(ctxt context.Context, txid string, proposal *pb.Proposal, chainname string, cds *pb.ChaincodeDeploymentSpec, cid *pb.ChaincodeID) error { +func (e *Endorser) deploy(ctxt context.Context, cccid *chaincode.CCContext, cds *pb.ChaincodeDeploymentSpec) error { chaincodeSupport := chaincode.GetChain() - _, err := chaincodeSupport.Deploy(ctxt, chainname, cds) + _, err := chaincodeSupport.Deploy(ctxt, cccid, cds) if err != nil { return fmt.Errorf("Failed to deploy chaincode spec(%s)", err) } //launch and wait for ready - _, _, err = chaincodeSupport.Launch(ctxt, chainname, txid, proposal, cds) + _, _, err = chaincodeSupport.Launch(ctxt, cccid, cds) if err != nil { return fmt.Errorf("%s", err) } //stop now that we are done - chaincodeSupport.Stop(ctxt, chainname, cds) + chaincodeSupport.Stop(ctxt, cccid, cds) return nil } @@ -91,7 +91,13 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, txid stri var ccevent *pb.ChaincodeEvent ctxt = context.WithValue(ctxt, chaincode.TXSimulatorKey, txsim) - b, ccevent, err = chaincode.ExecuteChaincode(ctxt, chainID, txid, prop, cid.Name, cis.ChaincodeSpec.CtorMsg.Args) + + //is this a system chaincode + syscc := chaincode.IsSysCC(cid.Name) + + cccid := chaincode.NewCCContext(chainID, cid.Name, "", txid, syscc, prop) + + b, ccevent, err = chaincode.ExecuteChaincode(ctxt, cccid, cis.ChaincodeSpec.CtorMsg.Args) if err != nil { return nil, nil, err @@ -111,7 +117,15 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, txid stri if err != nil { return nil, nil, err } - err = e.deploy(ctxt, txid, prop, chainID, cds, cid) + + //this should not be a system chaincode + if chaincode.IsSysCC(cds.ChaincodeSpec.ChaincodeID.Name) { + return nil, nil, fmt.Errorf("attempting to deploy a system chaincode %s/%s", cds.ChaincodeSpec.ChaincodeID.Name, chainID) + } + + cccid = chaincode.NewCCContext(chainID, cds.ChaincodeSpec.ChaincodeID.Name, "", txid, false, prop) + + err = e.deploy(ctxt, cccid, cds) if err != nil { return nil, nil, err } diff --git a/core/endorser/endorser_test.go b/core/endorser/endorser_test.go index 5564f0a338f..df8b0f20225 100644 --- a/core/endorser/endorser_test.go +++ b/core/endorser/endorser_test.go @@ -263,14 +263,16 @@ func TestDeploy(t *testing.T) { chainID := util.GetTestChainID() spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "ex01", Path: "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01"}, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}}} + cccid := chaincode.NewCCContext(chainID, "ex01", "", "", false, nil) + _, _, err := deploy(endorserServer, chainID, spec, nil) if err != nil { t.Fail() t.Logf("Deploy-error in deploy %s", err) - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } //TestDeployBadArgs sets bad args on deploy. It should fail, and example02 should not be deployed @@ -279,14 +281,16 @@ func TestDeployBadArgs(t *testing.T) { //invalid arguments spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "ex02", Path: "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"}, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b")}}} + cccid := chaincode.NewCCContext(chainID, "ex02", "", "", false, nil) + _, _, err := deploy(endorserServer, chainID, spec, nil) if err == nil { t.Fail() t.Log("DeployBadArgs-expected error in deploy but succeeded") - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } //TestDeployBadPayload set payload to nil and do a deploy. It should fail and example02 should not be deployed @@ -295,6 +299,8 @@ func TestDeployBadPayload(t *testing.T) { //invalid arguments spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "ex02", Path: "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"}, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}}} + cccid := chaincode.NewCCContext(chainID, "ex02", "", "", false, nil) + f := func(cds *pb.ChaincodeDeploymentSpec) { cds.CodePackage = nil } @@ -302,10 +308,10 @@ func TestDeployBadPayload(t *testing.T) { if err == nil { t.Fail() t.Log("DeployBadPayload-expected error in deploy but succeeded") - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } //TestRedeploy - deploy two times, second time should fail but example02 should remain deployed @@ -315,11 +321,13 @@ func TestRedeploy(t *testing.T) { //invalid arguments spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "ex02", Path: "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"}, CtorMsg: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}}} + cccid := chaincode.NewCCContext(chainID, "ex02", "", "", false, nil) + _, _, err := deploy(endorserServer, chainID, spec, nil) if err != nil { t.Fail() t.Logf("error in endorserServer.ProcessProposal %s", err) - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } @@ -328,10 +336,10 @@ func TestRedeploy(t *testing.T) { if err != nil { t.Fail() t.Logf("error in endorserServer.ProcessProposal %s", err) - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } - chaincode.GetChain().Stop(context.Background(), chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + chaincode.GetChain().Stop(context.Background(), cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } // TestDeployAndInvoke deploys and invokes chaincode_example01 @@ -347,11 +355,15 @@ func TestDeployAndInvoke(t *testing.T) { f := "init" argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: chaincodeID, CtorMsg: &pb.ChaincodeInput{Args: argsDeploy}} + + cccid := chaincode.NewCCContext(chainID, "ex01", "", "", false, nil) + resp, prop, err := deploy(endorserServer, chainID, spec, nil) chaincodeID1 := spec.ChaincodeID.Name if err != nil { t.Fail() t.Logf("Error deploying <%s>: %s", chaincodeID1, err) + chaincode.GetChain().Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) return } @@ -359,6 +371,7 @@ func TestDeployAndInvoke(t *testing.T) { if err != nil { t.Fail() t.Logf("Error committing <%s>: %s", chaincodeID1, err) + chaincode.GetChain().Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) return } @@ -369,13 +382,14 @@ func TestDeployAndInvoke(t *testing.T) { if err != nil { t.Fail() t.Logf("Error invoking transaction: %s", err) + chaincode.GetChain().Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) return } fmt.Printf("Invoke test passed\n") t.Logf("Invoke test passed") - chaincode.GetChain().Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) + chaincode.GetChain().Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID}}) } // TestUpgradeAndInvoke deploys chaincode_example01, upgrade it with chaincode_example02, then invoke it @@ -391,10 +405,17 @@ func TestDeployAndUpgrade(t *testing.T) { f := "init" argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: chaincodeID1, CtorMsg: &pb.ChaincodeInput{Args: argsDeploy}} + + cccid1 := chaincode.NewCCContext(chainID, "upgradeex01", "", "", false, nil) + cccid2 := chaincode.NewCCContext(chainID, "upgradeex02", "", "", false, nil) + resp, prop, err := deploy(endorserServer, chainID, spec, nil) + chaincodeName := spec.ChaincodeID.Name if err != nil { t.Fail() + chaincode.GetChain().Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID1}}) + chaincode.GetChain().Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID2}}) t.Logf("Error deploying <%s>: %s", chaincodeName, err) return } @@ -402,6 +423,8 @@ func TestDeployAndUpgrade(t *testing.T) { err = endorserServer.(*Endorser).commitTxSimulation(prop, chainID, signer, resp) if err != nil { t.Fail() + chaincode.GetChain().Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID1}}) + chaincode.GetChain().Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID2}}) t.Logf("Error committing <%s>: %s", chaincodeName, err) return } @@ -411,6 +434,8 @@ func TestDeployAndUpgrade(t *testing.T) { resp, prop, err = upgrade(endorserServer, chainID, spec, nil) if err != nil { t.Fail() + chaincode.GetChain().Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID1}}) + chaincode.GetChain().Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID2}}) t.Logf("Error upgrading <%s>: %s", chaincodeName, err) return } @@ -418,7 +443,8 @@ func TestDeployAndUpgrade(t *testing.T) { fmt.Printf("Upgrade test passed\n") t.Logf("Upgrade test passed") - chaincode.GetChain().Stop(ctxt, chainID, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID2}}) + chaincode.GetChain().Stop(ctxt, cccid1, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID1}}) + chaincode.GetChain().Stop(ctxt, cccid2, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeID: chaincodeID2}}) } func TestMain(m *testing.M) {