diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go
index 45b8eaf82c2..13813f97925 100644
--- a/core/chaincode/exectransaction_test.go
+++ b/core/chaincode/exectransaction_test.go
@@ -136,7 +136,7 @@ func endTxSimulationCDS(chainID string, txid string, txsim ledger.TxSimulator, p
 		return err
 	}
 	// get a proposal - we need it to get a transaction
-	prop, err := putils.CreateProposalFromCDS(txid, chainID, cds, ss)
+	prop, err := putils.CreateDeployProposalFromCDS(txid, chainID, cds, ss)
 	if err != nil {
 		return err
 	}
diff --git a/peer/chaincode/chaincode.go b/peer/chaincode/chaincode.go
index 1629eaaedf8..3814b11305b 100755
--- a/peer/chaincode/chaincode.go
+++ b/peer/chaincode/chaincode.go
@@ -31,9 +31,8 @@ const (
 
 var logger = logging.MustGetLogger("chaincodeCmd")
 
-// Cmd returns the cobra command for Chaincode
-func Cmd() *cobra.Command {
-	flags := chaincodeCmd.PersistentFlags()
+func AddFlags(cmd *cobra.Command) {
+	flags := cmd.PersistentFlags()
 
 	flags.StringVarP(&chaincodeLang, "lang", "l", "golang",
 		fmt.Sprintf("Language the %s is written in", chainFuncName))
@@ -51,10 +50,16 @@ func Cmd() *cobra.Command {
 		fmt.Sprint("Name of a custom ID generation algorithm (hashing and decoding) e.g. sha256base64"))
 	flags.StringVarP(&chainID, "chainID", "C", util.GetTestChainID(),
 		fmt.Sprint("The chain on which this command should be executed"))
+}
+
+// Cmd returns the cobra command for Chaincode
+func Cmd(cf *ChaincodeCmdFactory) *cobra.Command {
+	AddFlags(chaincodeCmd)
 
-	chaincodeCmd.AddCommand(deployCmd())
-	chaincodeCmd.AddCommand(invokeCmd())
-	chaincodeCmd.AddCommand(queryCmd())
+	chaincodeCmd.AddCommand(deployCmd(cf))
+	chaincodeCmd.AddCommand(invokeCmd(cf))
+	chaincodeCmd.AddCommand(queryCmd(cf))
+	chaincodeCmd.AddCommand(upgradeCmd(cf))
 
 	return chaincodeCmd
 }
diff --git a/peer/chaincode/common.go b/peer/chaincode/common.go
index 0ae36772156..08c0ed008e3 100755
--- a/peer/chaincode/common.go
+++ b/peer/chaincode/common.go
@@ -32,7 +32,6 @@ import (
 	"github.com/hyperledger/fabric/msp"
 	"github.com/hyperledger/fabric/peer/common"
 	"github.com/hyperledger/fabric/peer/util"
-	protcommon "github.com/hyperledger/fabric/protos/common"
 	pb "github.com/hyperledger/fabric/protos/peer"
 	putils "github.com/hyperledger/fabric/protos/utils"
 	"github.com/spf13/cobra"
@@ -155,7 +154,7 @@ func getChaincodeSpecification(cmd *cobra.Command) (*pb.ChaincodeSpec, error) {
 //
 // NOTE - Query will likely go away as all interactions with the endorser are
 // Proposal and ProposalResponses
-func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err error) {
+func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool, cf *ChaincodeCmdFactory) (err error) {
 	spec, err := getChaincodeSpecification(cmd)
 	if err != nil {
 		return err
@@ -167,19 +166,9 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
 		invocation.IdGenerationAlg = customIDGenAlg
 	}
 
-	endorserClient, err := common.GetEndorserClient(cmd)
+	creator, err := cf.Signer.Serialize()
 	if err != nil {
-		return fmt.Errorf("Error getting endorser client %s: %s", chainFuncName, err)
-	}
-
-	signer, err := msp.GetLocalMSP().GetDefaultSigningIdentity()
-	if err != nil {
-		return fmt.Errorf("Error obtaining the default signing identity, err %s", err)
-	}
-
-	creator, err := signer.Serialize()
-	if err != nil {
-		return fmt.Errorf("Error serializing the default signing identity, err %s", err)
+		return fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.Identifier(), err)
 	}
 
 	uuid := cutil.GenerateUUID()
@@ -191,13 +180,13 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
 	}
 
 	var signedProp *pb.SignedProposal
-	signedProp, err = putils.GetSignedProposal(prop, signer)
+	signedProp, err = putils.GetSignedProposal(prop, cf.Signer)
 	if err != nil {
 		return fmt.Errorf("Error creating signed proposal  %s: %s\n", chainFuncName, err)
 	}
 
 	var proposalResp *pb.ProposalResponse
-	proposalResp, err = endorserClient.ProcessProposal(context.Background(), signedProp)
+	proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
 	if err != nil {
 		return fmt.Errorf("Error endorsing %s: %s\n", chainFuncName, err)
 	}
@@ -205,13 +194,13 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
 	if invoke {
 		if proposalResp != nil {
 			// assemble a signed transaction (it's an Envelope message)
-			env, err := putils.CreateSignedTx(prop, signer, proposalResp)
+			env, err := putils.CreateSignedTx(prop, cf.Signer, proposalResp)
 			if err != nil {
 				return fmt.Errorf("Could not assemble transaction, err %s", err)
 			}
 
 			// send the envelope for ordering
-			if err = sendTransaction(env); err != nil {
+			if err = cf.BroadcastClient.Send(env); err != nil {
 				return fmt.Errorf("Error sending transaction %s: %s\n", chainFuncName, err)
 			}
 		}
@@ -241,7 +230,6 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
 }
 
 func checkChaincodeCmdParams(cmd *cobra.Command) error {
-
 	//we need chaincode name for everything, including deploy
 	if chaincodeName == common.UndefinedParamValue {
 		return fmt.Errorf("Must supply value for %s name parameter.\n", chainFuncName)
@@ -283,16 +271,33 @@ func checkChaincodeCmdParams(cmd *cobra.Command) error {
 	return nil
 }
 
-//sendTransactions sends a serialize Envelop to the orderer
-func sendTransaction(env *protcommon.Envelope) error {
-	var orderer string
-	if viper.GetBool("peer.committer.enabled") {
-		orderer = viper.GetString("peer.committer.ledger.orderer")
+// ChaincodeCmdFactory holds the clients used by ChaincodeCmd
+type ChaincodeCmdFactory struct {
+	EndorserClient  pb.EndorserClient
+	Signer          msp.SigningIdentity
+	BroadcastClient common.BroadcastClient
+}
+
+// InitCmdFactory init the ChaincodeCmdFactory with default clients
+func InitCmdFactory() (*ChaincodeCmdFactory, error) {
+	endorserClient, err := common.GetEndorserClient()
+	if err != nil {
+		return nil, fmt.Errorf("Error getting endorser client %s: %s", chainFuncName, err)
 	}
 
-	if orderer == "" {
-		return nil
+	signer, err := common.GetDefaultSigner()
+	if err != nil {
+		return nil, fmt.Errorf("Error getting default signer: %s", err)
+	}
+
+	broadcastClient, err := common.GetBroadcastClient()
+	if err != nil {
+		return nil, fmt.Errorf("Error getting broadcast client: %s", err)
 	}
 
-	return Send(orderer, env)
+	return &ChaincodeCmdFactory{
+		EndorserClient:  endorserClient,
+		Signer:          signer,
+		BroadcastClient: broadcastClient,
+	}, nil
 }
diff --git a/peer/chaincode/deploy.go b/peer/chaincode/deploy.go
index ff30af96e60..124931461ba 100755
--- a/peer/chaincode/deploy.go
+++ b/peer/chaincode/deploy.go
@@ -22,31 +22,31 @@ import (
 	"golang.org/x/net/context"
 
 	"github.com/hyperledger/fabric/core/util"
-	"github.com/hyperledger/fabric/msp"
-	"github.com/hyperledger/fabric/peer/common"
 	protcommon "github.com/hyperledger/fabric/protos/common"
 	pb "github.com/hyperledger/fabric/protos/peer"
 	"github.com/hyperledger/fabric/protos/utils"
 	"github.com/spf13/cobra"
 )
 
-// Cmd returns the cobra command for Chaincode Deploy
-func deployCmd() *cobra.Command {
-	return chaincodeDeployCmd
-}
+var chaincodeDeployCmd *cobra.Command
+
+// deployCmd returns the cobra command for Chaincode Deploy
+func deployCmd(cf *ChaincodeCmdFactory) *cobra.Command {
+	chaincodeDeployCmd = &cobra.Command{
+		Use:       "deploy",
+		Short:     fmt.Sprintf("Deploy the specified chaincode to the network."),
+		Long:      fmt.Sprintf(`Deploy the specified chaincode to the network.`),
+		ValidArgs: []string{"1"},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return chaincodeDeploy(cmd, args, cf)
+		},
+	}
 
-var chaincodeDeployCmd = &cobra.Command{
-	Use:       "deploy",
-	Short:     fmt.Sprintf("Deploy the specified chaincode to the network."),
-	Long:      fmt.Sprintf(`Deploy the specified chaincode to the network.`),
-	ValidArgs: []string{"1"},
-	RunE: func(cmd *cobra.Command, args []string) error {
-		return chaincodeDeploy(cmd, args)
-	},
+	return chaincodeDeployCmd
 }
 
 //deploy the command via Endorser
-func deploy(cmd *cobra.Command) (*protcommon.Envelope, error) {
+func deploy(cmd *cobra.Command, cf *ChaincodeCmdFactory) (*protcommon.Envelope, error) {
 	spec, err := getChaincodeSpecification(cmd)
 	if err != nil {
 		return nil, err
@@ -57,41 +57,32 @@ func deploy(cmd *cobra.Command) (*protcommon.Envelope, error) {
 		return nil, fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err)
 	}
 
-	endorserClient, err := common.GetEndorserClient(cmd)
-	if err != nil {
-		return nil, fmt.Errorf("Error getting endorser client %s: %s", chainFuncName, err)
-	}
-	signer, err := msp.GetLocalMSP().GetDefaultSigningIdentity()
-	if err != nil {
-		return nil, fmt.Errorf("Error obtaining the default signing identity, err %s", err)
-	}
-
-	creator, err := signer.Serialize()
+	creator, err := cf.Signer.Serialize()
 	if err != nil {
-		return nil, fmt.Errorf("Error serializing the default signing identity, err %s", err)
+		return nil, fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.Identifier(), err)
 	}
 
 	uuid := util.GenerateUUID()
 
-	prop, err := utils.CreateProposalFromCDS(uuid, chainID, cds, creator)
+	prop, err := utils.CreateDeployProposalFromCDS(uuid, chainID, cds, creator)
 	if err != nil {
 		return nil, fmt.Errorf("Error creating proposal  %s: %s\n", chainFuncName, err)
 	}
 
 	var signedProp *pb.SignedProposal
-	signedProp, err = utils.GetSignedProposal(prop, signer)
+	signedProp, err = utils.GetSignedProposal(prop, cf.Signer)
 	if err != nil {
 		return nil, fmt.Errorf("Error creating signed proposal  %s: %s\n", chainFuncName, err)
 	}
 
-	proposalResponse, err := endorserClient.ProcessProposal(context.Background(), signedProp)
+	proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
 	if err != nil {
 		return nil, fmt.Errorf("Error endorsing %s: %s\n", chainFuncName, err)
 	}
 
 	if proposalResponse != nil {
 		// assemble a signed transaction (it's an Envelope message)
-		env, err := utils.CreateSignedTx(prop, signer, proposalResponse)
+		env, err := utils.CreateSignedTx(prop, cf.Signer, proposalResponse)
 		if err != nil {
 			return nil, fmt.Errorf("Could not assemble transaction, err %s", err)
 		}
@@ -105,14 +96,22 @@ func deploy(cmd *cobra.Command) (*protcommon.Envelope, error) {
 // chaincodeDeploy deploys the chaincode. On success, the chaincode name
 // (hash) is printed to STDOUT for use by subsequent chaincode-related CLI
 // commands.
-func chaincodeDeploy(cmd *cobra.Command, args []string) error {
-	env, err := deploy(cmd)
+func chaincodeDeploy(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
+	var err error
+	if cf == nil {
+		cf, err = InitCmdFactory()
+		if err != nil {
+			return err
+		}
+	}
+	defer cf.BroadcastClient.Close()
+	env, err := deploy(cmd, cf)
 	if err != nil {
 		return err
 	}
 
 	if env != nil {
-		err = sendTransaction(env)
+		err = cf.BroadcastClient.Send(env)
 	}
 
 	return err
diff --git a/peer/chaincode/invoke.go b/peer/chaincode/invoke.go
index 7334a40e28b..1e2c6ad0d5e 100755
--- a/peer/chaincode/invoke.go
+++ b/peer/chaincode/invoke.go
@@ -22,20 +22,32 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func invokeCmd() *cobra.Command {
-	return chaincodeInvokeCmd
-}
+var chaincodeInvokeCmd *cobra.Command
+
+// invokeCmd returns the cobra command for Chaincode Invoke
+func invokeCmd(cf *ChaincodeCmdFactory) *cobra.Command {
+	chaincodeInvokeCmd = &cobra.Command{
+		Use:       "invoke",
+		Short:     fmt.Sprintf("Invoke the specified %s.", chainFuncName),
+		Long:      fmt.Sprintf(`Invoke the specified %s.`, chainFuncName),
+		ValidArgs: []string{"1"},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return chaincodeInvoke(cmd, args, cf)
+		},
+	}
 
-var chaincodeInvokeCmd = &cobra.Command{
-	Use:       "invoke",
-	Short:     fmt.Sprintf("Invoke the specified %s.", chainFuncName),
-	Long:      fmt.Sprintf(`Invoke the specified %s.`, chainFuncName),
-	ValidArgs: []string{"1"},
-	RunE: func(cmd *cobra.Command, args []string) error {
-		return chaincodeInvoke(cmd, args)
-	},
+	return chaincodeInvokeCmd
 }
 
-func chaincodeInvoke(cmd *cobra.Command, args []string) error {
-	return chaincodeInvokeOrQuery(cmd, args, true)
+func chaincodeInvoke(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
+	var err error
+	if cf == nil {
+		cf, err = InitCmdFactory()
+		if err != nil {
+			return err
+		}
+	}
+	defer cf.BroadcastClient.Close()
+
+	return chaincodeInvokeOrQuery(cmd, args, true, cf)
 }
diff --git a/peer/chaincode/query.go b/peer/chaincode/query.go
index 4bcb9db08b1..47ab272d329 100755
--- a/peer/chaincode/query.go
+++ b/peer/chaincode/query.go
@@ -22,7 +22,20 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func queryCmd() *cobra.Command {
+var chaincodeQueryCmd *cobra.Command
+
+// queryCmd returns the cobra command for Chaincode Query
+func queryCmd(cf *ChaincodeCmdFactory) *cobra.Command {
+	chaincodeQueryCmd = &cobra.Command{
+		Use:       "query",
+		Short:     fmt.Sprintf("Query using the specified %s.", chainFuncName),
+		Long:      fmt.Sprintf(`Query using the specified %s.`, chainFuncName),
+		ValidArgs: []string{"1"},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return chaincodeQuery(cmd, args, cf)
+		},
+	}
+
 	chaincodeQueryCmd.Flags().BoolVarP(&chaincodeQueryRaw, "raw", "r", false,
 		"If true, output the query value as raw bytes, otherwise format as a printable string")
 	chaincodeQueryCmd.Flags().BoolVarP(&chaincodeQueryHex, "hex", "x", false,
@@ -31,16 +44,15 @@ func queryCmd() *cobra.Command {
 	return chaincodeQueryCmd
 }
 
-var chaincodeQueryCmd = &cobra.Command{
-	Use:       "query",
-	Short:     fmt.Sprintf("Query using the specified %s.", chainFuncName),
-	Long:      fmt.Sprintf(`Query using the specified %s.`, chainFuncName),
-	ValidArgs: []string{"1"},
-	RunE: func(cmd *cobra.Command, args []string) error {
-		return chaincodeQuery(cmd, args)
-	},
-}
-
-func chaincodeQuery(cmd *cobra.Command, args []string) error {
-	return chaincodeInvokeOrQuery(cmd, args, false)
+func chaincodeQuery(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
+	var err error
+	if cf == nil {
+		cf, err = InitCmdFactory()
+		if err != nil {
+			return err
+		}
+	}
+	defer cf.BroadcastClient.Close()
+
+	return chaincodeInvokeOrQuery(cmd, args, false, cf)
 }
diff --git a/peer/chaincode/upgrade.go b/peer/chaincode/upgrade.go
new file mode 100644
index 00000000000..9b213e7576f
--- /dev/null
+++ b/peer/chaincode/upgrade.go
@@ -0,0 +1,122 @@
+/*
+Copyright IBM Corp. 2016 All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package chaincode
+
+import (
+	"fmt"
+
+	"golang.org/x/net/context"
+
+	"github.com/hyperledger/fabric/core/util"
+	protcommon "github.com/hyperledger/fabric/protos/common"
+	pb "github.com/hyperledger/fabric/protos/peer"
+	"github.com/hyperledger/fabric/protos/utils"
+	"github.com/spf13/cobra"
+)
+
+var chaincodeUpgradeCmd *cobra.Command
+
+// upgradeCmd returns the cobra command for Chaincode Upgrade
+func upgradeCmd(cf *ChaincodeCmdFactory) *cobra.Command {
+	chaincodeUpgradeCmd = &cobra.Command{
+		Use:       "upgrade",
+		Short:     fmt.Sprintf("Upgrade chaincode."),
+		Long:      fmt.Sprintf(`Upgrade an existing chaincode with the specified one. The new chaincode will immediately replace the existing chaincode upon the transaction committed.`),
+		ValidArgs: []string{"1"},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return chaincodeUpgrade(cmd, args, cf)
+		},
+	}
+
+	return chaincodeUpgradeCmd
+}
+
+//upgrade the command via Endorser
+func upgrade(cmd *cobra.Command, cf *ChaincodeCmdFactory) (*protcommon.Envelope, error) {
+	spec, err := getChaincodeSpecification(cmd)
+	if err != nil {
+		return nil, err
+	}
+
+	cds, err := getChaincodeBytes(spec)
+	if err != nil {
+		return nil, fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err)
+	}
+
+	creator, err := cf.Signer.Serialize()
+	if err != nil {
+		return nil, fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.Identifier(), err)
+	}
+
+	uuid := util.GenerateUUID()
+
+	prop, err := utils.CreateUpgradeProposalFromCDS(uuid, chainID, cds, creator)
+	if err != nil {
+		return nil, fmt.Errorf("Error creating proposal %s: %s\n", chainFuncName, err)
+	}
+	logger.Debugf("Get upgrade proposal for chaincode <%v>", spec.ChaincodeID)
+
+	var signedProp *pb.SignedProposal
+	signedProp, err = utils.GetSignedProposal(prop, cf.Signer)
+	if err != nil {
+		return nil, fmt.Errorf("Error creating signed proposal  %s: %s\n", chainFuncName, err)
+	}
+
+	proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
+	if err != nil {
+		return nil, fmt.Errorf("Error endorsing %s: %s\n", chainFuncName, err)
+	}
+	logger.Debugf("endorse upgrade proposal, get response <%v>", proposalResponse.Response)
+
+	if proposalResponse != nil {
+		// assemble a signed transaction (it's an Envelope message)
+		env, err := utils.CreateSignedTx(prop, cf.Signer, proposalResponse)
+		if err != nil {
+			return nil, fmt.Errorf("Could not assemble transaction, err %s", err)
+		}
+		logger.Debug("Get Signed envelope")
+		return env, nil
+	}
+
+	return nil, nil
+}
+
+// chaincodeUpgrade upgrades the chaincode. On success, the new chaincode
+// version is printed to STDOUT
+func chaincodeUpgrade(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
+	var err error
+	if cf == nil {
+		cf, err = InitCmdFactory()
+		if err != nil {
+			return err
+		}
+	}
+	defer cf.BroadcastClient.Close()
+
+	env, err := upgrade(cmd, cf)
+	if err != nil {
+		return err
+	}
+
+	if env != nil {
+		logger.Debug("Send signed envelope to orderer")
+		err = cf.BroadcastClient.Send(env)
+		return err
+	}
+
+	return nil
+}
diff --git a/peer/chaincode/upgrade_test.go b/peer/chaincode/upgrade_test.go
new file mode 100644
index 00000000000..6883fd70af6
--- /dev/null
+++ b/peer/chaincode/upgrade_test.go
@@ -0,0 +1,170 @@
+/*
+ Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package chaincode
+
+import (
+	"fmt"
+	"os"
+	"sync"
+	"testing"
+
+	"github.com/hyperledger/fabric/core/config"
+	"github.com/hyperledger/fabric/peer/common"
+	pb "github.com/hyperledger/fabric/protos/peer"
+	//	"github.com/hyperledger/fabric/protos/utils"
+	"github.com/hyperledger/fabric/core/crypto/primitives"
+)
+
+var once sync.Once
+
+// InitMSP init MSP
+func InitMSP() {
+	once.Do(initMSP)
+}
+
+func initMSP() {
+	// TODO: determine the location of this config file
+	var alternativeCfgPath = os.Getenv("PEER_CFG_PATH")
+	var mspMgrConfigFile string
+	if alternativeCfgPath != "" {
+		mspMgrConfigFile = alternativeCfgPath + "/msp/peer-config.json"
+	} else if _, err := os.Stat("./peer-config.json"); err == nil {
+		mspMgrConfigFile = "./peer-config.json"
+	} else {
+		mspMgrConfigFile = os.Getenv("GOPATH") + "/src/github.com/hyperledger/fabric/msp/peer-config.json"
+	}
+
+	err := config.SetupFakeMSPInfrastructureForTests(mspMgrConfigFile)
+	if err != nil {
+		panic(fmt.Errorf("Fatal error when reading MSP config file %s: err %s\n", mspMgrConfigFile, err))
+	}
+}
+
+func TestUpgradeCmd(t *testing.T) {
+	primitives.SetSecurityLevel("SHA2", 256)
+	InitMSP()
+
+	signer, err := common.GetDefaultSigner()
+	if err != nil {
+		t.Fatalf("Get default signer error: %v", err)
+	}
+
+	mockResponse := &pb.ProposalResponse{
+		Response:    &pb.Response{Status: 200},
+		Endorsement: &pb.Endorsement{},
+	}
+
+	mockEndorerClient := common.GetMockEndorserClient(mockResponse, nil)
+
+	mockBroadcastClient := common.GetMockBroadcastClient(nil)
+
+	mockCF := &ChaincodeCmdFactory{
+		EndorserClient:  mockEndorerClient,
+		Signer:          signer,
+		BroadcastClient: mockBroadcastClient,
+	}
+
+	cmd := upgradeCmd(mockCF)
+	AddFlags(cmd)
+
+	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}"}
+	cmd.SetArgs(args)
+
+	if err := cmd.Execute(); err != nil {
+		t.Errorf("Run chaincode upgrade cmd error:%v", err)
+	}
+}
+
+func TestUpgradeCmdEndorseFail(t *testing.T) {
+	primitives.SetSecurityLevel("SHA2", 256)
+	InitMSP()
+
+	signer, err := common.GetDefaultSigner()
+	if err != nil {
+		t.Fatalf("Get default signer error: %v", err)
+	}
+
+	errCode := int32(500)
+	errMsg := "upgrade error"
+	mockResponse := &pb.ProposalResponse{Response: &pb.Response{Status: errCode, Message: errMsg}}
+
+	mockEndorerClient := common.GetMockEndorserClient(mockResponse, nil)
+
+	mockBroadcastClient := common.GetMockBroadcastClient(nil)
+
+	mockCF := &ChaincodeCmdFactory{
+		EndorserClient:  mockEndorerClient,
+		Signer:          signer,
+		BroadcastClient: mockBroadcastClient,
+	}
+
+	cmd := upgradeCmd(mockCF)
+	AddFlags(cmd)
+
+	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}"}
+	cmd.SetArgs(args)
+
+	expectErrMsg := fmt.Sprintf("Could not assemble transaction, err Proposal response was not successful, error code %d, msg %s", errCode, errMsg)
+	if err := cmd.Execute(); err == nil {
+		t.Errorf("Run chaincode upgrade cmd error:%v", err)
+	} else {
+		if err.Error() != expectErrMsg {
+			t.Errorf("Run chaincode upgrade cmd get unexpected error: %s", err.Error())
+		}
+	}
+}
+
+func TestUpgradeCmdSendTXFail(t *testing.T) {
+	primitives.SetSecurityLevel("SHA2", 256)
+	InitMSP()
+
+	signer, err := common.GetDefaultSigner()
+	if err != nil {
+		t.Fatalf("Get default signer error: %v", err)
+	}
+
+	mockResponse := &pb.ProposalResponse{
+		Response:    &pb.Response{Status: 200},
+		Endorsement: &pb.Endorsement{},
+	}
+
+	mockEndorerClient := common.GetMockEndorserClient(mockResponse, nil)
+
+	sendErr := fmt.Errorf("send tx failed")
+	mockBroadcastClient := common.GetMockBroadcastClient(sendErr)
+
+	mockCF := &ChaincodeCmdFactory{
+		EndorserClient:  mockEndorerClient,
+		Signer:          signer,
+		BroadcastClient: mockBroadcastClient,
+	}
+
+	cmd := upgradeCmd(mockCF)
+	AddFlags(cmd)
+
+	args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-c", "{\"Function\":\"init\",\"Args\": [\"param\",\"1\"]}"}
+	cmd.SetArgs(args)
+
+	expectErrMsg := sendErr.Error()
+	if err := cmd.Execute(); err == nil {
+		t.Errorf("Run chaincode upgrade cmd error:%v", err)
+	} else {
+		if err.Error() != expectErrMsg {
+			t.Errorf("Run chaincode upgrade cmd get unexpected error: %s", err.Error())
+		}
+	}
+}
diff --git a/peer/common/common.go b/peer/common/common.go
index c799d95075e..6d830f6eb3a 100755
--- a/peer/common/common.go
+++ b/peer/common/common.go
@@ -17,11 +17,13 @@ limitations under the License.
 package common
 
 import (
+	"fmt"
+
 	"github.com/hyperledger/fabric/core/errors"
 	"github.com/hyperledger/fabric/core/peer"
 	"github.com/hyperledger/fabric/flogging"
+	"github.com/hyperledger/fabric/msp"
 	pb "github.com/hyperledger/fabric/protos/peer"
-	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 )
 
@@ -29,7 +31,7 @@ import (
 const UndefinedParamValue = ""
 
 // GetEndorserClient returns a new endorser client connection for this peer
-func GetEndorserClient(cmd *cobra.Command) (pb.EndorserClient, error) {
+func GetEndorserClient() (pb.EndorserClient, error) {
 	clientConn, err := peer.NewPeerClientConnection()
 	if err != nil {
 		err = errors.ErrorWithCallstack(errors.Peer, errors.PeerConnectionError, err.Error())
@@ -58,3 +60,13 @@ func SetErrorLoggingLevel() error {
 
 	return err
 }
+
+// GetDefaultSigner return a default Signer(Default/PERR) for cli
+func GetDefaultSigner() (msp.SigningIdentity, error) {
+	signer, err := msp.GetLocalMSP().GetDefaultSigningIdentity()
+	if err != nil {
+		return nil, fmt.Errorf("Error obtaining the default signing identity, err %s", err)
+	}
+
+	return signer, err
+}
diff --git a/peer/common/mockclient.go b/peer/common/mockclient.go
new file mode 100644
index 00000000000..992f440c469
--- /dev/null
+++ b/peer/common/mockclient.go
@@ -0,0 +1,58 @@
+/*
+Copyright IBM Corp. 2016 All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+		 http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+	cb "github.com/hyperledger/fabric/protos/common"
+	pb "github.com/hyperledger/fabric/protos/peer"
+	context "golang.org/x/net/context"
+	grpc "google.golang.org/grpc"
+)
+
+// GetMockEndorserClient return a endorser client return specified ProposalResponse and err(nil or error)
+func GetMockEndorserClient(repponse *pb.ProposalResponse, err error) pb.EndorserClient {
+	return &mockEndorserClient{
+		repponse: repponse,
+		err:      err,
+	}
+}
+
+type mockEndorserClient struct {
+	repponse *pb.ProposalResponse
+	err      error
+}
+
+func (m *mockEndorserClient) ProcessProposal(ctx context.Context, in *pb.SignedProposal, opts ...grpc.CallOption) (*pb.ProposalResponse, error) {
+	return m.repponse, m.err
+}
+
+func GetMockBroadcastClient(err error) BroadcastClient {
+	return &mockBroadcastClient{err: err}
+}
+
+// mockBroadcastClient return success immediately
+type mockBroadcastClient struct {
+	err error
+}
+
+func (m *mockBroadcastClient) Send(env *cb.Envelope) error {
+	return m.err
+}
+
+func (m *mockBroadcastClient) Close() error {
+	return nil
+}
diff --git a/peer/chaincode/noopsordererclient.go b/peer/common/ordererclient.go
similarity index 60%
rename from peer/chaincode/noopsordererclient.go
rename to peer/common/ordererclient.go
index a976b80c9b2..fb941e3491c 100644
--- a/peer/chaincode/noopsordererclient.go
+++ b/peer/common/ordererclient.go
@@ -14,67 +14,81 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package chaincode
-
-//--------!!!IMPORTANT!!-!!IMPORTANT!!-!!IMPORTANT!!---------
-// This Orderer client is based off fabric/orderer/sample_clients/
-// broadcast_timestamp/client.go
-// It is temporary and will go away from CLI when SDK implements
-// interactions for the V1 architecture
-//-------------------------------------------------------------
+package common
+
 import (
 	"fmt"
 	"time"
 
 	cb "github.com/hyperledger/fabric/protos/common"
 	ab "github.com/hyperledger/fabric/protos/orderer"
+	"github.com/spf13/viper"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 )
 
-type broadcastClient struct {
-	client ab.AtomicBroadcast_BroadcastClient
+type BroadcastClient interface {
+	//Send data to orderer
+	Send(env *cb.Envelope) error
+	Close() error
 }
 
-// newBroadcastClient creates a simple instance of the broadcastClient interface
-func newBroadcastClient(client ab.AtomicBroadcast_BroadcastClient) *broadcastClient {
-	return &broadcastClient{client: client}
+type broadcastClient struct {
+	conn   *grpc.ClientConn
+	client ab.AtomicBroadcast_BroadcastClient
 }
 
-func (s *broadcastClient) getAck() error {
-	msg, err := s.client.Recv()
-	if err != nil {
-		return err
+// GetBroadcastClient creates a simple instance of the BroadcastClient interface
+func GetBroadcastClient() (BroadcastClient, error) {
+	var orderer string
+	if viper.GetBool("peer.committer.enabled") {
+		orderer = viper.GetString("peer.committer.ledger.orderer")
 	}
-	if msg.Status != cb.Status_SUCCESS {
-		return fmt.Errorf("Got unexpected status: %v", msg.Status)
+
+	if orderer == "" {
+		return nil, fmt.Errorf("Can't get orderer address")
 	}
-	return nil
-}
 
-//Send data to solo orderer
-func Send(serverAddr string, env *cb.Envelope) error {
 	var opts []grpc.DialOption
 	opts = append(opts, grpc.WithInsecure())
 	opts = append(opts, grpc.WithTimeout(3*time.Second))
 	opts = append(opts, grpc.WithBlock())
 
-	conn, err := grpc.Dial(serverAddr, opts...)
-	defer conn.Close()
+	conn, err := grpc.Dial(orderer, opts...)
 	if err != nil {
-		return fmt.Errorf("Error connecting: %s", err)
+		return nil, fmt.Errorf("Error connecting: %s", err)
 	}
 	client, err := ab.NewAtomicBroadcastClient(conn).Broadcast(context.TODO())
 	if err != nil {
-		return fmt.Errorf("Error connecting: %s", err)
+		conn.Close()
+		return nil, fmt.Errorf("Error connecting: %s", err)
 	}
 
-	s := newBroadcastClient(client)
-	if err = s.client.Send(env); err != nil {
+	return &broadcastClient{conn: conn, client: client}, nil
+}
+
+func (s *broadcastClient) getAck() error {
+	msg, err := s.client.Recv()
+	if err != nil {
+		return err
+	}
+	if msg.Status != cb.Status_SUCCESS {
+		return fmt.Errorf("Got unexpected status: %v", msg.Status)
+	}
+	return nil
+}
+
+//Send data to orderer
+func (s *broadcastClient) Send(env *cb.Envelope) error {
+	if err := s.client.Send(env); err != nil {
 		return fmt.Errorf("Could not send :%s)", err)
 	}
 
-	err = s.getAck()
+	err := s.getAck()
 
 	return err
 }
+
+func (s *broadcastClient) Close() error {
+	return s.conn.Close()
+}
diff --git a/peer/main.go b/peer/main.go
index 079c693faa1..a46010ee0ac 100644
--- a/peer/main.go
+++ b/peer/main.go
@@ -108,7 +108,7 @@ func main() {
 
 	mainCmd.AddCommand(version.Cmd())
 	mainCmd.AddCommand(node.Cmd())
-	mainCmd.AddCommand(chaincode.Cmd())
+	mainCmd.AddCommand(chaincode.Cmd(nil))
 	mainCmd.AddCommand(clilogging.Cmd())
 
 	runtime.GOMAXPROCS(viper.GetInt("peer.gomaxprocs"))
diff --git a/protos/utils/proputils.go b/protos/utils/proputils.go
index afc95f1fdac..5819f0c18fb 100644
--- a/protos/utils/proputils.go
+++ b/protos/utils/proputils.go
@@ -377,19 +377,35 @@ func CreateProposalFromCIS(txid string, chainID string, cis *peer.ChaincodeInvoc
 	return CreateChaincodeProposal(txid, chainID, cis, creator)
 }
 
-// CreateProposalFromCDS returns a proposal given a serialized identity and a ChaincodeDeploymentSpec
-func CreateProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte) (*peer.Proposal, error) {
+// CreateDeployProposalFromCDS returns a deploy proposal given a serialized identity and a ChaincodeDeploymentSpec
+func CreateDeployProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte) (*peer.Proposal, error) {
+	return createProposalFromCDS(txid, chainID, cds, creator, true)
+}
+
+// CreateUpgradeProposalFromCDS returns a upgrade proposal given a serialized identity and a ChaincodeDeploymentSpec
+func CreateUpgradeProposalFromCDS(txid string, chainID string, cds *peer.ChaincodeDeploymentSpec, creator []byte) (*peer.Proposal, error) {
+	return createProposalFromCDS(txid, chainID, cds, creator, false)
+}
+
+// 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, deploy bool) (*peer.Proposal, error) {
 	b, err := proto.Marshal(cds)
 	if err != nil {
 		return nil, err
 	}
 
+	var propType string
+	if deploy {
+		propType = "deploy"
+	} else {
+		propType = "upgrade"
+	}
 	//wrap the deployment in an invocation spec to lccc...
 	lcccSpec := &peer.ChaincodeInvocationSpec{
 		ChaincodeSpec: &peer.ChaincodeSpec{
 			Type:        peer.ChaincodeSpec_GOLANG,
 			ChaincodeID: &peer.ChaincodeID{Name: "lccc"},
-			CtorMsg:     &peer.ChaincodeInput{Args: [][]byte{[]byte("deploy"), []byte(chainID), b}}}}
+			CtorMsg:     &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), []byte(chainID), b}}}}
 
 	//...and get the proposal for it
 	return CreateProposalFromCIS(txid, chainID, lcccSpec, creator)