diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index 83a2e859ba9..0995e080e8b 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -283,9 +283,8 @@ func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeployme } }() - if err = ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec); err != nil { - return nil, err - } + //ignore existence errors + ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec) sysCCVers := util.GetSysCCVersion() lcccid := ccprovider.NewCCContext(cccid.ChainID, cis.ChaincodeSpec.ChaincodeId.Name, sysCCVers, uuid, true, nil) diff --git a/core/common/ccprovider/ccprovider.go b/core/common/ccprovider/ccprovider.go index db341a8e244..14e944bc618 100644 --- a/core/common/ccprovider/ccprovider.go +++ b/core/common/ccprovider/ccprovider.go @@ -89,12 +89,17 @@ func PutChaincodeIntoFS(depSpec *pb.ChaincodeDeploymentSpec) error { ccname := depSpec.ChaincodeSpec.ChaincodeId.Name ccversion := depSpec.ChaincodeSpec.ChaincodeId.Version + //return error if chaincode exists + path := fmt.Sprintf("%s/%s.%s", chaincodeInstallPath, ccname, ccversion) + if _, err := os.Stat(path); err == nil { + return fmt.Errorf("chaincode %s exits", path) + } + b, err := proto.Marshal(depSpec) if err != nil { return fmt.Errorf("failed to marshal fs deployment spec for %s, %s", ccname, ccversion) } - path := fmt.Sprintf("%s/%s.%s", chaincodeInstallPath, ccname, ccversion) if err = ioutil.WriteFile(path, b, 0644); err != nil { return err } diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index cbd2e3d837e..7a4870bef67 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -320,7 +320,7 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro //TODO till we implement global ESCC, CSCC for system chaincodes //chainless proposals (such as CSCC) don't have to be endorsed if ischainless { - pResp = &pb.ProposalResponse{Response: &pb.Response{}} + pResp = &pb.ProposalResponse{Response: res} } else { pResp, err = e.endorseProposal(ctx, chainID, txid, prop, res, simulationResult, ccevent, hdrExt.PayloadVisibility, hdrExt.ChaincodeId, txsim, cd) if err != nil { diff --git a/core/endorser/endorser_test.go b/core/endorser/endorser_test.go index 712dc10ebbe..37deee86b5c 100644 --- a/core/endorser/endorser_test.go +++ b/core/endorser/endorser_test.go @@ -264,6 +264,8 @@ 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", Version: "0"}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}}} + defer os.RemoveAll("/tmp/hyperledger/production/chaincodes/ex01.0") + cccid := ccprovider.NewCCContext(chainID, "ex01", "0", "", false, nil) _, _, err := deploy(endorserServer, chainID, spec, nil) @@ -283,6 +285,8 @@ 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", Version: "0"}, Input: &pb.ChaincodeInput{Args: [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}}} + defer os.RemoveAll("/tmp/hyperledger/production/chaincodes/ex02.0") + cccid := ccprovider.NewCCContext(chainID, "ex02", "0", "", false, nil) _, _, err := deploy(endorserServer, chainID, spec, nil) @@ -293,6 +297,8 @@ func TestRedeploy(t *testing.T) { return } + os.RemoveAll("/tmp/hyperledger/production/chaincodes/ex02.0") + //second time should not fail as we are just simulating _, _, err = deploy(endorserServer, chainID, spec, nil) if err != nil { @@ -312,6 +318,8 @@ func TestDeployAndInvoke(t *testing.T) { url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01" chaincodeID := &pb.ChaincodeID{Path: url, Name: "ex01", Version: "0"} + defer os.RemoveAll("/tmp/hyperledger/production/chaincodes/ex01.0") + args := []string{"10"} f := "init" @@ -364,6 +372,9 @@ func TestDeployAndUpgrade(t *testing.T) { chaincodeID1 := &pb.ChaincodeID{Path: url1, Name: "upgradeex01", Version: "0"} chaincodeID2 := &pb.ChaincodeID{Path: url2, Name: "upgradeex01", Version: "1"} + defer os.RemoveAll("/tmp/hyperledger/production/chaincodes/upgradeex01.0") + defer os.RemoveAll("/tmp/hyperledger/production/chaincodes/upgradeex01.1") + f := "init" argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200") spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID1, Input: &pb.ChaincodeInput{Args: argsDeploy}} diff --git a/core/scc/lccc/lccc.go b/core/scc/lccc/lccc.go index 2ed87491c33..e58963ddbcf 100644 --- a/core/scc/lccc/lccc.go +++ b/core/scc/lccc/lccc.go @@ -46,6 +46,9 @@ const ( //chaincode lifecyle commands + //INSTALL install command + INSTALL = "install" + //DEPLOY deploy command DEPLOY = "deploy" @@ -284,6 +287,29 @@ func (lccc *LifeCycleSysCC) isValidChaincodeName(chaincodename string) bool { return true } +//this implements "install" Invoke transaction +func (lccc *LifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, depSpec []byte) error { + cds, err := lccc.getChaincodeDeploymentSpec(depSpec) + + if err != nil { + return err + } + + if !lccc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name) { + return InvalidChaincodeNameErr(cds.ChaincodeSpec.ChaincodeId.Name) + } + + if cds.ChaincodeSpec.ChaincodeId.Version == "" { + return EmptyVersionErr(cds.ChaincodeSpec.ChaincodeId.Name) + } + + if err = ccprovider.PutChaincodeIntoFS(cds); err != nil { + return fmt.Errorf("Error installing chaincode code %s:%s(%s)", cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, err) + } + + return err +} + //this implements "deploy" Invoke transaction func (lccc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chainname string, depSpec []byte, policy []byte, escc []byte, vscc []byte) error { cds, err := lccc.getChaincodeDeploymentSpec(depSpec) @@ -395,6 +421,18 @@ func (lccc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response function := string(args[0]) switch function { + case INSTALL: + if len(args) < 2 { + return shim.Error(InvalidArgsLenErr(len(args)).Error()) + } + + depSpec := args[1] + + err := lccc.executeInstall(stub, depSpec) + if err != nil { + return shim.Error(err.Error()) + } + return shim.Success([]byte("OK")) case DEPLOY: if len(args) < 3 || len(args) > 6 { return shim.Error(InvalidArgsLenErr(len(args)).Error()) diff --git a/core/scc/lccc/lccc_test.go b/core/scc/lccc/lccc_test.go index 8494cc91c97..265dc9dec76 100644 --- a/core/scc/lccc/lccc_test.go +++ b/core/scc/lccc/lccc_test.go @@ -53,16 +53,18 @@ func register(stub *shim.MockStub, ccname string) error { return nil } -func constructDeploymentSpec(name string, path string, version string, initArgs [][]byte) (*pb.ChaincodeDeploymentSpec, error) { +func constructDeploymentSpec(name string, path string, version string, initArgs [][]byte, createFS bool) (*pb.ChaincodeDeploymentSpec, error) { spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: &pb.ChaincodeID{Name: name, Path: path, Version: version}, Input: &pb.ChaincodeInput{Args: initArgs}} codePackageBytes := []byte(name + path + version) chaincodeDeploymentSpec := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes} - err := ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec) - if err != nil { - return nil, err + if createFS { + err := ccprovider.PutChaincodeIntoFS(chaincodeDeploymentSpec) + if err != nil { + return nil, err + } } return chaincodeDeploymentSpec, nil @@ -78,8 +80,8 @@ func TestDeploy(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { t.FailNow() @@ -91,6 +93,55 @@ func TestDeploy(t *testing.T) { } } +//TestInstall tests the install function +func TestInstall(t *testing.T) { + scc := new(LifeCycleSysCC) + stub := shim.NewMockStub("lccc", scc) + + if res := stub.MockInit("1", nil); res.Status != shim.OK { + fmt.Println("Init failed", string(res.Message)) + t.FailNow() + } + + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, false) + var b []byte + if b, err = proto.Marshal(cds); err != nil || b == nil { + t.FailNow() + } + + //constructDeploymentSpec puts the depspec on the FS. This should fail + args := [][]byte{[]byte(INSTALL), b} + defer os.Remove(lccctestpath + "/example02.0") + if res := stub.MockInvoke("1", args); res.Status != shim.OK { + t.FailNow() + } +} + +//TestReinstall tests the install function +func TestReinstall(t *testing.T) { + scc := new(LifeCycleSysCC) + stub := shim.NewMockStub("lccc", scc) + + if res := stub.MockInit("1", nil); res.Status != shim.OK { + fmt.Println("Init failed", string(res.Message)) + t.FailNow() + } + + //note that this puts the code on the filesyste.... + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") + var b []byte + if b, err = proto.Marshal(cds); err != nil || b == nil { + t.FailNow() + } + + //constructDeploymentSpec puts the depspec on the FS. This should fail + args := [][]byte{[]byte(INSTALL), b} + if res := stub.MockInvoke("1", args); res.Status == shim.OK { + t.FailNow() + } +} + //TestInvalidCodeDeploy tests the deploy function with invalid code package func TestInvalidCodeDeploy(t *testing.T) { scc := new(LifeCycleSysCC) @@ -121,8 +172,11 @@ func TestInvalidChaincodeName(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") + if err != nil { + t.FailNow() + } //change name to empty cds.ChaincodeSpec.ChaincodeId.Name = "" @@ -150,8 +204,11 @@ func TestEmptyChaincodeVersion(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") + if err != nil { + t.FailNow() + } //change version to empty cds.ChaincodeSpec.ChaincodeId.Version = "" @@ -179,8 +236,8 @@ func TestRedeploy(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { t.FailNow() @@ -209,8 +266,8 @@ func TestCheckCC(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { @@ -228,7 +285,7 @@ func TestCheckCC(t *testing.T) { } } -//TestMultipleDeploy tests deploying multiple chaincodes +//TestMultipleDeploy tests deploying multiple chaincodeschaincodes func TestMultipleDeploy(t *testing.T) { scc := new(LifeCycleSysCC) stub := shim.NewMockStub("lccc", scc) @@ -239,8 +296,8 @@ func TestMultipleDeploy(t *testing.T) { } //deploy 02 - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { t.FailNow() @@ -257,8 +314,8 @@ func TestMultipleDeploy(t *testing.T) { } //deploy 01 - cds, err = constructDeploymentSpec("example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example01.0") + cds, err = constructDeploymentSpec("example01", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example01", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example01.0") if b, err = proto.Marshal(cds); err != nil || b == nil { t.FailNow() } @@ -285,8 +342,8 @@ func TestRetryFailedDeploy(t *testing.T) { } //deploy 02 - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { t.FailNow() @@ -328,8 +385,8 @@ func TestUpgrade(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { t.Fatalf("Marshal DeploymentSpec failed") @@ -340,8 +397,8 @@ func TestUpgrade(t *testing.T) { t.Fatalf("Deploy chaincode error: %v", err) } - newCds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "1", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.1") + newCds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "1", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.1") var newb []byte if newb, err = proto.Marshal(newCds); err != nil || newb == nil { t.Fatalf("Marshal DeploymentSpec failed") @@ -370,8 +427,8 @@ func TestUpgradeNonExistChaincode(t *testing.T) { t.FailNow() } - cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example02.0") + cds, err := constructDeploymentSpec("example02", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example02.0") var b []byte if b, err = proto.Marshal(cds); err != nil || b == nil { t.Fatalf("Marshal DeploymentSpec failed") @@ -382,8 +439,8 @@ func TestUpgradeNonExistChaincode(t *testing.T) { t.Fatalf("Deploy chaincode error: %s", res.Message) } - newCds, err := constructDeploymentSpec("example03", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "1", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}) - defer os.Remove(lccctestpath + "/chaincodes/example03.1") + newCds, err := constructDeploymentSpec("example03", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "1", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, true) + defer os.Remove(lccctestpath + "/example03.1") var newb []byte if newb, err = proto.Marshal(newCds); err != nil || newb == nil { t.Fatalf("Marshal DeploymentSpec failed") diff --git a/core/scc/sysccapi.go b/core/scc/sysccapi.go index efbba3acb5e..685712e0189 100644 --- a/core/scc/sysccapi.go +++ b/core/scc/sysccapi.go @@ -84,17 +84,12 @@ func deploySysCC(chainID string, syscc *SystemChaincode) error { return nil } - chainless := false - if chainID == "" { - chainless = true - } - var err error ccprov := ccprovider.GetChaincodeProvider() ctxt := context.Background() - if !chainless { + if chainID != "" { lgr := peer.GetLedger(chainID) if lgr == nil { panic(fmt.Sprintf("syschain %s start up failure - unexpected nil ledger for channel %s", syscc.Name, chainID)) diff --git a/peer/chaincode/install.go b/peer/chaincode/install.go index 7bf14c65483..ddb14b0e154 100644 --- a/peer/chaincode/install.go +++ b/peer/chaincode/install.go @@ -19,11 +19,15 @@ package chaincode import ( "fmt" + "golang.org/x/net/context" + + "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/peer/common" + pb "github.com/hyperledger/fabric/protos/peer" + "github.com/hyperledger/fabric/protos/utils" "github.com/spf13/cobra" - "github.com/spf13/viper" ) var chaincodeInstallCmd *cobra.Command @@ -45,21 +49,52 @@ func installCmd(cf *ChaincodeCmdFactory) *cobra.Command { return chaincodeInstallCmd } -// chaincodeInstall deploys the chaincode. On success, the chaincode name -// (hash) is printed to STDOUT for use by subsequent chaincode-related CLI -// commands. +//install the depspec to "peer.address" +func install(chaincodeName string, chaincodeVersion string, cds *pb.ChaincodeDeploymentSpec, cf *ChaincodeCmdFactory) error { + creator, err := cf.Signer.Serialize() + if err != nil { + return fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.GetIdentifier(), err) + } + + uuid := util.GenerateUUID() + + prop, err := utils.CreateInstallProposalFromCDS(uuid, cds, creator) + if err != nil { + return fmt.Errorf("Error creating proposal %s: %s\n", chainFuncName, err) + } + + var signedProp *pb.SignedProposal + signedProp, err = utils.GetSignedProposal(prop, cf.Signer) + if err != nil { + return fmt.Errorf("Error creating signed proposal %s: %s\n", chainFuncName, err) + } + + proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp) + if err != nil { + return fmt.Errorf("Error endorsing %s: %s\n", chainFuncName, err) + } + + if proposalResponse != nil { + fmt.Printf("Installed remotely %v\n", proposalResponse) + } + + return nil +} + +// chaincodeInstall installs the chaincode. If remoteinstall, does it via a lccc call func chaincodeInstall(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error { if chaincodePath == common.UndefinedParamValue || chaincodeVersion == common.UndefinedParamValue { return fmt.Errorf("Must supply value for %s path and version parameters.\n", chainFuncName) } - peerPath := viper.GetString("peer.fileSystemPath") - if peerPath == "" { - return fmt.Errorf("Peer's environment \"peer.fileSystemPath\" is not set") + var err error + if cf == nil { + cf, err = InitCmdFactory() + if err != nil { + return err + } } - ccprovider.SetChaincodesPath(peerPath + "/chaincodes") - tmppkg, _ := ccprovider.GetChaincodePackage(chaincodeName, chaincodeVersion) if tmppkg != nil { return fmt.Errorf("chaincode %s:%s exists", chaincodeName, chaincodeVersion) @@ -75,11 +110,7 @@ func chaincodeInstall(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory return fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err) } - if err = ccprovider.PutChaincodeIntoFS(cds); err != nil { - return fmt.Errorf("Error installing chaincode code %s:%s(%s)", chaincodeName, chaincodeVersion, err) - } - - logger.Debugf("Installed chaincode %s:%s", chaincodeName, chaincodeVersion) + err = install(chaincodeName, chaincodeVersion, cds, cf) return err } diff --git a/peer/chaincode/install_test.go b/peer/chaincode/install_test.go index fd37efe3688..1e82d491ba1 100644 --- a/peer/chaincode/install_test.go +++ b/peer/chaincode/install_test.go @@ -17,10 +17,12 @@ package chaincode import ( + "fmt" "os" "testing" "github.com/hyperledger/fabric/peer/common" + pb "github.com/hyperledger/fabric/protos/peer" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -56,25 +58,6 @@ func finitInstallTest(fsPath string) { os.RemoveAll(fsPath) } -// TestInstallCmd tests generation of install command -func TestInstallCmd(t *testing.T) { - fsPath := "/tmp/installtest" - - cmd := initInstallTest(fsPath, t) - defer finitInstallTest(fsPath) - - args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-v", "testversion"} - cmd.SetArgs(args) - - if err := cmd.Execute(); err != nil { - t.Fatalf("Error executing install command %s", err) - } - - if _, err := os.Stat(fsPath + "/chaincodes/example02.testversion"); err != nil { - t.Fatalf("chaincode example02.testversion does not exist %s", err) - } -} - // TestBadVersion tests generation of install command func TestBadVersion(t *testing.T) { fsPath := "/tmp/installtest" @@ -109,25 +92,41 @@ func TestNonExistentCC(t *testing.T) { } } -// TestCCExists should fail second time -func TestCCExists(t *testing.T) { - fsPath := "/tmp/installtest" +func installEx02() error { - cmd := initInstallTest(fsPath, t) - defer finitInstallTest(fsPath) + signer, err := common.GetDefaultSigner() + if err != nil { + return fmt.Errorf("Get default signer error: %v", err) + } + + mockResponse := &pb.ProposalResponse{ + Response: &pb.Response{Status: 200}, + Endorsement: &pb.Endorsement{}, + } + + mockEndorerClient := common.GetMockEndorserClient(mockResponse, nil) + + mockCF := &ChaincodeCmdFactory{ + EndorserClient: mockEndorerClient, + Signer: signer, + } + + cmd := installCmd(mockCF) + AddFlags(cmd) - args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-v", "testversion"} + args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-v", "anotherversion"} cmd.SetArgs(args) if err := cmd.Execute(); err != nil { - t.Fatalf("Error executing install command %s", err) + return fmt.Errorf("Run chaincode upgrade cmd error:%v", err) } - if _, err := os.Stat(fsPath + "/chaincodes/example02.testversion"); err != nil { - t.Fatalf("chaincode example02.testversion does not exist %s", err) - } + return nil +} - if err := cmd.Execute(); err == nil { - t.Fatalf("Expected error reinstall but succeeded") +func TestInstall(t *testing.T) { + InitMSP() + if err := installEx02(); err != nil { + t.Fatalf("Install failed with error: %v", err) } } diff --git a/protos/utils/proputils.go b/protos/utils/proputils.go index cc39c881c4e..cff387b740c 100644 --- a/protos/utils/proputils.go +++ b/protos/utils/proputils.go @@ -437,35 +437,40 @@ func CreateProposalFromCIS(txid string, typ common.HeaderType, chainID string, c return CreateChaincodeProposal(txid, typ, chainID, cis, creator) } +// CreateInstallProposalFromCDS returns a install proposal given a serialized identity and a ChaincodeDeploymentSpec +func CreateInstallProposalFromCDS(txid string, cds *peer.ChaincodeDeploymentSpec, creator []byte) (*peer.Proposal, error) { + return createProposalFromCDS(txid, "", cds, creator, nil, nil, nil, "install") +} + // CreateDeployProposalFromCDS returns a deploy proposal given a serialized identity and a ChaincodeDeploymentSpec func CreateDeployProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, error) { - return createProposalFromCDS(txid, chainID, cds, creator, policy, escc, vscc, true) + return createProposalFromCDS(txid, chainID, cds, creator, policy, escc, vscc, "deploy") } // CreateUpgradeProposalFromCDS returns a upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec func CreateUpgradeProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte) (*peer.Proposal, error) { - return createProposalFromCDS(txid, chainID, cds, creator, policy, escc, vscc, false) + return createProposalFromCDS(txid, chainID, cds, creator, policy, escc, vscc, "upgrade") } // createProposalFromCDS returns a deploy or upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec -func createProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte, deploy bool) (*peer.Proposal, error) { - var propType string - if deploy { - propType = "deploy" - } else { - propType = "upgrade" - } - +func createProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte, policy []byte, escc []byte, vscc []byte, propType string) (*peer.Proposal, error) { //in the new mode, cds will be nil, "deploy" and "upgrade" are instantiates. var ccinp *peer.ChaincodeInput + var b []byte + var err error if cds != nil { - b, err := proto.Marshal(cds) + b, err = proto.Marshal(cds) if err != nil { return nil, err } + } + switch propType { + case "deploy": + fallthrough + case "upgrade": ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), []byte(chainID), b, policy, escc, vscc}} - } else { - ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), []byte(chainID), nil, policy, escc, vscc}} + case "install": + ccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), b}} } //wrap the deployment in an invocation spec to lccc...