From 72c95893e22ceada4f2cf4633e0962712c5ea7c7 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 22 Nov 2018 01:23:44 +0000 Subject: [PATCH] Don't call gaiacli tx sign. Use utils.SignStdTx() instead. This is to avoid command redirection and reduce the use of viper's global variables. Closes: #2875 --- PENDING.md | 1 + cmd/gaia/cli_test/cli_test.go | 13 +++++-- cmd/gaia/init/gentx.go | 69 +++++++++++++++++++++++++---------- x/auth/client/cli/sign.go | 2 +- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/PENDING.md b/PENDING.md index 47c6ab60e5ff..5622bf40576c 100644 --- a/PENDING.md +++ b/PENDING.md @@ -11,6 +11,7 @@ BREAKING CHANGES * [cli] [\#2829](https://github.com/cosmos/cosmos-sdk/pull/2829) add-genesis-account command now validates state when adding accounts * [cli] [\#2804](https://github.com/cosmos/cosmos-sdk/issues/2804) Check whether key exists before passing it on to `tx create-validator`. * [cli] [\#2874](https://github.com/cosmos/cosmos-sdk/pull/2874) `gaiacli tx sign` takes an optional `--output-document` flag to support output redirection. + * [cli] [\#2875](https://github.com/cosmos/cosmos-sdk/pull/2875) Refactor `gaiad gentx` and avoid redirection to `gaiacli tx sign` for tx signing. * Gaia diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 8ad32870f497..f2c2e4ba1f88 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -606,10 +606,11 @@ func getTestingHomeDirs() (string, string) { func initializeFixtures(t *testing.T) (chainID, servAddr, port string) { tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "") + os.RemoveAll(filepath.Join(gaiadHome, "config", "gentx")) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass) executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s foo", gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) + executeWriteCheckErr(t, fmt.Sprintf("gaiacli keys add --home=%s foo", gaiacliHome), app.DefaultKeyPass) + executeWriteCheckErr(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass) fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf( "gaiacli keys show foo --output=json --home=%s", gaiacliHome)) chainID = executeInit(t, fmt.Sprintf("gaiad init -o --moniker=foo --home=%s", gaiadHome)) @@ -623,10 +624,10 @@ func initializeFixtures(t *testing.T) (chainID, servAddr, port string) { require.NoError(t, err) genDoc.AppState = appStateJSON genDoc.SaveAs(genFile) - executeWrite(t, fmt.Sprintf( + executeWriteCheckErr(t, fmt.Sprintf( "gaiad gentx --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome), app.DefaultKeyPass) - executeWrite(t, fmt.Sprintf("gaiad collect-gentxs --home=%s", gaiadHome), app.DefaultKeyPass) + executeWriteCheckErr(t, fmt.Sprintf("gaiad collect-gentxs --home=%s", gaiadHome), app.DefaultKeyPass) // get a free port, also setup some common flags servAddr, port, err = server.FreeTCPAddr() require.NoError(t, err) @@ -662,6 +663,10 @@ func readGenesisFile(t *testing.T, genFile string) types.GenesisDoc { //___________________________________________________________________________________ // executors +func executeWriteCheckErr(t *testing.T, cmdStr string, writes ...string) { + require.True(t, executeWrite(t, cmdStr, writes...)) +} + func executeWrite(t *testing.T, cmdStr string, writes ...string) (exitSuccess bool) { exitSuccess, _, _ = executeWriteRetStdStreams(t, cmdStr, writes...) return diff --git a/cmd/gaia/init/gentx.go b/cmd/gaia/init/gentx.go index 91dfbd2e1648..b8392d3bd27d 100644 --- a/cmd/gaia/init/gentx.go +++ b/cmd/gaia/init/gentx.go @@ -1,7 +1,9 @@ package init import ( + "bytes" "fmt" + "io" "io/ioutil" "os" "path/filepath" @@ -17,7 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" - authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + "github.com/cosmos/cosmos-sdk/x/auth" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" "github.com/cosmos/cosmos-sdk/x/stake/client/cli" stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types" @@ -71,7 +73,9 @@ following delegation and commission default parameters: if err != nil { return err } - if _, err = kb.Get(viper.GetString(client.FlagName)); err != nil { + + name := viper.GetString(client.FlagName) + if _, err := kb.Get(name); err != nil { return err } @@ -84,34 +88,40 @@ following delegation and commission default parameters: } // Run gaiad tx create-validator prepareFlagsForTxCreateValidator(config, nodeID, ip, genDoc.ChainID, valPubKey) - cliCtx, txBldr, msg, err := cli.BuildCreateValidatorMsg( - context.NewCLIContext().WithCodec(cdc), - authtxb.NewTxBuilderFromCLI().WithCodec(cdc), - ) + txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc) + cliCtx := context.NewCLIContext().WithCodec(cdc) + cliCtx, txBldr, msg, err := cli.BuildCreateValidatorMsg(cliCtx, txBldr) if err != nil { return err } - w, err := ioutil.TempFile("", "gentx") - if err != nil { + // write the unsigned transaction to the buffer + w := bytes.NewBuffer([]byte{}) + if err := utils.PrintUnsignedStdTx(w, txBldr, cliCtx, []sdk.Msg{msg}, true); err != nil { return err } - unsignedGenTxFilename := w.Name() - defer os.Remove(unsignedGenTxFilename) - if err := utils.PrintUnsignedStdTx(w, txBldr, cliCtx, []sdk.Msg{msg}, true); err != nil { + // read the transaction + stdTx, err := readUnsignedGenTxFile(cdc, w) + if err != nil { return err } - prepareFlagsForTxSign() - signCmd := authcmd.GetSignCommand(cdc) + // sign the transaction and write it to the output file + signedTx, err := utils.SignStdTx(txBldr, cliCtx, name, stdTx, false, true) + if err != nil { + return err + } outputDocument, err := makeOutputFilepath(config.RootDir, nodeID) if err != nil { return err } - viper.Set("output-document", outputDocument) - return signCmd.RunE(nil, []string{unsignedGenTxFilename}) + if err := writeSignedGenTx(cdc, outputDocument, signedTx); err != nil { + return err + } + fmt.Fprintf(os.Stderr, "Genesis transaction written to %q\n", outputDocument) + return nil }, } @@ -152,10 +162,6 @@ func prepareFlagsForTxCreateValidator(config *cfg.Config, nodeID, ip, chainID st } } -func prepareFlagsForTxSign() { - viper.Set("offline", true) -} - func makeOutputFilepath(rootDir, nodeID string) (string, error) { writePath := filepath.Join(rootDir, "config", "gentx") if err := common.EnsureDir(writePath, 0700); err != nil { @@ -163,3 +169,28 @@ func makeOutputFilepath(rootDir, nodeID string) (string, error) { } return filepath.Join(writePath, fmt.Sprintf("gentx-%v.json", nodeID)), nil } + +func readUnsignedGenTxFile(cdc *codec.Codec, r io.Reader) (auth.StdTx, error) { + var stdTx auth.StdTx + bytes, err := ioutil.ReadAll(r) + if err != nil { + return stdTx, err + } + err = cdc.UnmarshalJSON(bytes, &stdTx) + return stdTx, err +} + +// nolint: errcheck +func writeSignedGenTx(cdc *codec.Codec, outputDocument string, tx auth.StdTx) error { + outputFile, err := os.OpenFile(outputDocument, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer outputFile.Close() + json, err := cdc.MarshalJSON(tx) + if err != nil { + return err + } + _, err = fmt.Fprintf(outputFile, "%s\n", json) + return err +} diff --git a/x/auth/client/cli/sign.go b/x/auth/client/cli/sign.go index 6fc57ac16634..73facdfd9357 100644 --- a/x/auth/client/cli/sign.go +++ b/x/auth/client/cli/sign.go @@ -118,7 +118,7 @@ func makeSignCmd(cdc *amino.Codec) func(cmd *cobra.Command, args []string) error fp, err := os.OpenFile( viper.GetString(flagOutfile), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644, - ) + ) if err != nil { return err }