Skip to content

Commit

Permalink
[FAB-1237] chaincode upgrade cli
Browse files Browse the repository at this point in the history
This commit can be divided into two parts. One implements chaincode
upgrade cli. Another is a refactor of chaincode cmd package. The
main idea is extract endorserClient/broadcastClient/signer to be
holded by ChaincodeCmdFactory, then we can get clients needed from
ChaincodeCmdFactory in cmd implements. Thus in unit-tests, we can
construct mock clients for tests. If this refactor looks good, we
can extend it to other cmd tests.

Change-Id: I1a44e347009fc645b2e97cd6d65efde5fb229257
Signed-off-by: jiangyaoguo <jiangyaoguo@gmail.com>
  • Loading branch information
jiangyaoguo committed Dec 8, 2016
1 parent 62e16f9 commit eb048ef
Show file tree
Hide file tree
Showing 13 changed files with 554 additions and 129 deletions.
2 changes: 1 addition & 1 deletion core/chaincode/exectransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
17 changes: 11 additions & 6 deletions peer/chaincode/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
}
Expand Down
59 changes: 32 additions & 27 deletions peer/chaincode/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -191,27 +180,27 @@ 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)
}

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)
}
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
65 changes: 32 additions & 33 deletions peer/chaincode/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
Expand All @@ -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
Expand Down
38 changes: 25 additions & 13 deletions peer/chaincode/invoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
38 changes: 25 additions & 13 deletions peer/chaincode/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
}

0 comments on commit eb048ef

Please sign in to comment.