From c292d54e47c5d9164778e1c62f2931b0e21f7397 Mon Sep 17 00:00:00 2001 From: Rigel Rozanski Date: Sat, 15 Apr 2017 12:07:27 -0400 Subject: [PATCH] Debug Flag, Run -> RunE --- cmd/basecoin/main.go | 8 +---- cmd/commands/ibc.go | 48 ++++++++++++------------- cmd/commands/init.go | 37 ++++++++++++------- cmd/commands/key.go | 17 ++++----- cmd/commands/query.go | 52 ++++++++++++++------------- cmd/commands/reset.go | 9 ++--- cmd/commands/start.go | 25 +++++++------ cmd/commands/tx.go | 49 ++++++++++++++----------- cmd/commands/utils.go | 26 ++++++++++---- cmd/counter/cmd.go | 9 +++-- cmd/counter/main.go | 8 +---- docs/guide/example-plugin.md | 11 +++--- docs/guide/ibc.md | 6 ++-- docs/guide/src/example-plugin/cmd.go | 6 ++-- docs/guide/src/example-plugin/main.go | 8 +---- glide.lock | 2 +- glide.yaml | 2 +- scripts/print_txs.go | 6 ++-- tests/tendermint/main.go | 4 +-- 19 files changed, 178 insertions(+), 155 deletions(-) diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index bcb5493010..5b37ab7fef 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/tendermint/basecoin/cmd/commands" @@ -28,8 +25,5 @@ func main() { commands.VersionCmd, ) - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 48fd4d6c2b..1c817d5bdb 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -5,11 +5,11 @@ import ( "fmt" "io/ioutil" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tendermint/basecoin/plugins/ibc" - cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" tmtypes "github.com/tendermint/tendermint/types" @@ -30,13 +30,13 @@ var ( IBCRegisterTxCmd = &cobra.Command{ Use: "register", Short: "Register a blockchain via IBC", - Run: ibcRegisterTxCmd, + RunE: ibcRegisterTxCmd, } IBCUpdateTxCmd = &cobra.Command{ Use: "update", Short: "Update the latest state of a blockchain via IBC", - Run: ibcUpdateTxCmd, + RunE: ibcUpdateTxCmd, } IBCPacketTxCmd = &cobra.Command{ @@ -47,13 +47,13 @@ var ( IBCPacketCreateTxCmd = &cobra.Command{ Use: "create", Short: "Create an egress IBC packet", - Run: ibcPacketCreateTxCmd, + RunE: ibcPacketCreateTxCmd, } IBCPacketPostTxCmd = &cobra.Command{ Use: "post", Short: "Deliver an IBC packet to another chain", - Run: ibcPacketPostTxCmd, + RunE: ibcPacketPostTxCmd, } ) @@ -117,13 +117,13 @@ func init() { //--------------------------------------------------------------------- // ibc command implementations -func ibcRegisterTxCmd(cmd *cobra.Command, args []string) { +func ibcRegisterTxCmd(cmd *cobra.Command, args []string) error { chainID := ibcChainIDFlag genesisFile := ibcGenesisFlag genesisBytes, err := ioutil.ReadFile(genesisFile) if err != nil { - cmn.Exit(fmt.Sprintf("Error reading genesis file %v: %+v\n", genesisFile, err)) + return errors.Errorf("Error reading genesis file %v: %v\n", genesisFile, err) } ibcTx := ibc.IBCRegisterChainTx{ @@ -140,18 +140,18 @@ func ibcRegisterTxCmd(cmd *cobra.Command, args []string) { }{ibcTx})) name := "IBC" - AppTx(name, data) + return AppTx(name, data) } -func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { +func ibcUpdateTxCmd(cmd *cobra.Command, args []string) error { headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Header (%v) is invalid hex: %+v\n", ibcHeaderFlag, err)) + return errors.Errorf("Header (%v) is invalid hex: %v\n", ibcHeaderFlag, err) } commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Commit (%v) is invalid hex: %+v\n", ibcCommitFlag, err)) + return errors.Errorf("Commit (%v) is invalid hex: %v\n", ibcCommitFlag, err) } header := new(tmtypes.Header) @@ -159,12 +159,12 @@ func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { err = wire.ReadBinaryBytes(headerBytes, &header) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling header: %+v\n", err)) + return errors.Errorf("Error unmarshalling header: %v\n", err) } err = wire.ReadBinaryBytes(commitBytes, &commit) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling commit: %+v\n", err)) + return errors.Errorf("Error unmarshalling commit: %v\n", err) } ibcTx := ibc.IBCUpdateChainTx{ @@ -179,21 +179,21 @@ func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { }{ibcTx})) name := "IBC" - AppTx(name, data) + return AppTx(name, data) } -func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) { +func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) error { fromChain, toChain := ibcFromFlag, ibcToFlag packetType := ibcTypeFlag payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Payload (%v) is invalid hex: %+v\n", ibcPayloadFlag, err)) + return errors.Errorf("Payload (%v) is invalid hex: %v\n", ibcPayloadFlag, err) } sequence, err := ibcSequenceCmd() if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } ibcTx := ibc.IBCPacketCreateTx{ @@ -212,20 +212,20 @@ func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - AppTx("IBC", data) + return AppTx("IBC", data) } -func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { +func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) error { fromChain, fromHeight := ibcFromFlag, ibcHeightFlag packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Packet (%v) is invalid hex: %+v\n", ibcPacketFlag, err)) + return errors.Errorf("Packet (%v) is invalid hex: %v\n", ibcPacketFlag, err) } proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Proof (%v) is invalid hex: %+v\n", ibcProofFlag, err)) + return errors.Errorf("Proof (%v) is invalid hex: %v\n", ibcProofFlag, err) } var packet ibc.Packet @@ -233,12 +233,12 @@ func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { err = wire.ReadBinaryBytes(packetBytes, &packet) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling packet: %+v\n", err)) + return errors.Errorf("Error unmarshalling packet: %v\n", err) } err = wire.ReadBinaryBytes(proofBytes, &proof) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) + return errors.Errorf("Error unmarshalling proof: %v\n", err) } ibcTx := ibc.IBCPacketPostTx{ @@ -254,7 +254,7 @@ func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - AppTx("IBC", data) + return AppTx("IBC", data) } func ibcSequenceCmd() (uint64, error) { diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 233a39087d..7308c7961c 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -1,7 +1,6 @@ package commands import ( - "fmt" "io/ioutil" "os" "path" @@ -16,25 +15,25 @@ var ( InitCmd = &cobra.Command{ Use: "init", Short: "Initialize a basecoin blockchain", - Run: initCmd, + RunE: initCmd, } ) // setupFile aborts on error... or should we return it?? // returns 1 iff it set a file, otherwise 0 (so we can add them) -func setupFile(path, data string, perm os.FileMode) int { +func setupFile(path, data string, perm os.FileMode) (int, error) { _, err := os.Stat(path) if !os.IsNotExist(err) { - return 0 + return 0, nil } err = ioutil.WriteFile(path, []byte(data), perm) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return 0, err } - return 1 + return 1, nil } -func initCmd(cmd *cobra.Command, args []string) { +func initCmd(cmd *cobra.Command, args []string) error { rootDir := BasecoinRoot("") cmn.EnsureDir(rootDir, 0777) @@ -45,16 +44,30 @@ func initCmd(cmd *cobra.Command, args []string) { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - mod := setupFile(genesisFile, GenesisJSON, 0644) + - setupFile(privValFile, PrivValJSON, 0400) + - setupFile(key1File, Key1JSON, 0400) + - setupFile(key2File, Key2JSON, 0400) + mod1, err := setupFile(genesisFile, GenesisJSON, 0644) + if err != nil { + return err + } + mod2, err := setupFile(privValFile, PrivValJSON, 0400) + if err != nil { + return err + } + mod3, err := setupFile(key1File, Key1JSON, 0400) + if err != nil { + return err + } + mod4, err := setupFile(key2File, Key2JSON, 0400) + if err != nil { + return err + } - if mod > 0 { + if (mod1 + mod2 + mod3 + mod4) > 0 { log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) } else { log.Notice("Already initialized", "priv_validator", privValFile) } + + return nil } var PrivValJSON = `{ diff --git a/cmd/commands/key.go b/cmd/commands/key.go index a1cec50d1b..62be3c1d36 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -8,9 +8,9 @@ import ( "path" "strings" + //"github.com/pkg/errors" "github.com/spf13/cobra" - cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" ) @@ -24,18 +24,19 @@ var ( NewKeyCmd = &cobra.Command{ Use: "new", Short: "Create a new private key", - Run: newKeyCmd, + RunE: newKeyCmd, } ) -func newKeyCmd(cmd *cobra.Command, args []string) { +func newKeyCmd(cmd *cobra.Command, args []string) error { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") fmt.Println(&key) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Println(string(keyJSON)) + return nil } func init() { @@ -85,18 +86,18 @@ func genKey() *Key { } } -func LoadKey(keyFile string) *Key { +func LoadKey(keyFile string) (*Key, error) { filePath := path.Join(BasecoinRoot(""), keyFile) keyJSONBytes, err := ioutil.ReadFile(filePath) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return nil, err } key := new(Key) err = json.Unmarshal(keyJSONBytes, key) if err != nil { - cmn.Exit(fmt.Sprintf("Error reading key from %v: %v\n", filePath, err)) + return nil, fmt.Errorf("Error reading key from %v: %v\n", filePath, err) //never stack trace } - return key + return key, nil } diff --git a/cmd/commands/query.go b/cmd/commands/query.go index 7e6e8de285..56ec683a16 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -5,9 +5,9 @@ import ( "fmt" "strconv" + "github.com/pkg/errors" "github.com/spf13/cobra" - cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" tmtypes "github.com/tendermint/tendermint/types" @@ -18,25 +18,25 @@ var ( QueryCmd = &cobra.Command{ Use: "query [key]", Short: "Query the merkle tree", - Run: queryCmd, + RunE: queryCmd, } AccountCmd = &cobra.Command{ Use: "account [address]", Short: "Get details of an account", - Run: accountCmd, + RunE: accountCmd, } BlockCmd = &cobra.Command{ Use: "block [height]", Short: "Get the header and commit of a block", - Run: blockCmd, + RunE: blockCmd, } VerifyCmd = &cobra.Command{ Use: "verify", Short: "Verify the IAVL proof", - Run: verifyCmd, + RunE: verifyCmd, } ) @@ -68,10 +68,10 @@ func init() { RegisterFlags(VerifyCmd, verifyFlags) } -func queryCmd(cmd *cobra.Command, args []string) { +func queryCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 { - cmn.Exit("query command requires an argument ([key])") + return fmt.Errorf("query command requires an argument ([key])") //never stack trace } keyString := args[0] @@ -81,17 +81,17 @@ func queryCmd(cmd *cobra.Command, args []string) { var err error key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - cmn.Exit(fmt.Sprintf("Query key (%v) is invalid hex: %+v\n", keyString, err)) + return errors.Errorf("Query key (%v) is invalid hex: %v\n", keyString, err) } } resp, err := Query(nodeFlag, key) if err != nil { - cmn.Exit(fmt.Sprintf("Query returns error: %+v\n", err)) + return errors.Errorf("Query returns error: %v\n", err) } if !resp.Code.IsOK() { - cmn.Exit(fmt.Sprintf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log)) + return errors.Errorf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log) } val := resp.Value @@ -103,12 +103,13 @@ func queryCmd(cmd *cobra.Command, args []string) { Proof []byte `json:"proof"` Height uint64 `json:"height"` }{val, proof, height}))) + return nil } -func accountCmd(cmd *cobra.Command, args []string) { +func accountCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 { - cmn.Exit("account command requires an argument ([address])") + return fmt.Errorf("account command requires an argument ([address])") //never stack trace } addrHex := StripHex(args[0]) @@ -116,31 +117,32 @@ func accountCmd(cmd *cobra.Command, args []string) { // convert destination address to bytes addr, err := hex.DecodeString(addrHex) if err != nil { - cmn.Exit(fmt.Sprintf("Account address (%v) is invalid hex: %+v\n", addrHex, err)) + return errors.Errorf("Account address (%v) is invalid hex: %v\n", addrHex, err) } acc, err := getAcc(nodeFlag, addr) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Println(string(wire.JSONBytes(acc))) + return nil } -func blockCmd(cmd *cobra.Command, args []string) { +func blockCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 { - cmn.Exit("block command requires an argument ([height])") + return fmt.Errorf("block command requires an argument ([height])") //never stack trace } heightString := args[0] height, err := strconv.Atoi(heightString) if err != nil { - cmn.Exit(fmt.Sprintf("Height must be an int, got %v: %+v\n", heightString, err)) + return errors.Errorf("Height must be an int, got %v: %v\n", heightString, err) } header, commit, err := getHeaderAndCommit(nodeFlag, height) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Println(string(wire.JSONBytes(struct { @@ -156,6 +158,7 @@ func blockCmd(cmd *cobra.Command, args []string) { Commit: commit, }, }))) + return nil } type BlockHex struct { @@ -168,7 +171,7 @@ type BlockJSON struct { Commit *tmtypes.Commit `json:"commit"` } -func verifyCmd(cmd *cobra.Command, args []string) { +func verifyCmd(cmd *cobra.Command, args []string) error { keyString, valueString := keyFlag, valueFlag @@ -177,7 +180,7 @@ func verifyCmd(cmd *cobra.Command, args []string) { if isHex(keyString) { key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - cmn.Exit(fmt.Sprintf("Key (%v) is invalid hex: %+v\n", keyString, err)) + return errors.Errorf("Key (%v) is invalid hex: %v\n", keyString, err) } } @@ -185,25 +188,26 @@ func verifyCmd(cmd *cobra.Command, args []string) { if isHex(valueString) { value, err = hex.DecodeString(StripHex(valueString)) if err != nil { - cmn.Exit(fmt.Sprintf("Value (%v) is invalid hex: %+v\n", valueString, err)) + return errors.Errorf("Value (%v) is invalid hex: %v\n", valueString, err) } } root, err := hex.DecodeString(StripHex(rootFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Root (%v) is invalid hex: %+v\n", rootFlag, err)) + return errors.Errorf("Root (%v) is invalid hex: %v\n", rootFlag, err) } proofBytes, err := hex.DecodeString(StripHex(proofFlag)) proof, err := merkle.ReadProof(proofBytes) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) + return errors.Errorf("Error unmarshalling proof: %v\n", err) } if proof.Verify(key, value, root) { fmt.Println("OK") } else { - cmn.Exit(fmt.Sprintf("Proof does not verify")) + return errors.New("Proof does not verify") } + return nil } diff --git a/cmd/commands/reset.go b/cmd/commands/reset.go index f2841ea801..d1b4dfbbc8 100644 --- a/cmd/commands/reset.go +++ b/cmd/commands/reset.go @@ -5,20 +5,21 @@ import ( "github.com/spf13/cobra" - "github.com/tendermint/tendermint/cmd/tendermint/commands" + tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tmcfg "github.com/tendermint/tendermint/config/tendermint" ) var UnsafeResetAllCmd = &cobra.Command{ Use: "unsafe_reset_all", Short: "Reset all blockchain data", - Run: unsafeResetAllCmd, + RunE: unsafeResetAllCmd, } -func unsafeResetAllCmd(cmd *cobra.Command, args []string) { +func unsafeResetAllCmd(cmd *cobra.Command, args []string) error { basecoinDir := BasecoinRoot("") tmDir := path.Join(basecoinDir) tmConfig := tmcfg.GetConfig(tmDir) - commands.ResetAll(tmConfig, log) + tmcmd.ResetAll(tmConfig, log) + return nil } diff --git a/cmd/commands/start.go b/cmd/commands/start.go index d14f663d12..e4fd5560cd 100644 --- a/cmd/commands/start.go +++ b/cmd/commands/start.go @@ -5,6 +5,7 @@ import ( "os" "path" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tendermint/abci/server" @@ -22,7 +23,7 @@ import ( var StartCmd = &cobra.Command{ Use: "start", Short: "Start basecoin", - Run: startCmd, + RunE: startCmd, } //flags @@ -42,7 +43,7 @@ func init() { {&addrFlag, "address", "tcp://0.0.0.0:46658", "Listen address"}, {&eyesFlag, "eyes", "local", "MerkleEyes address, or 'local' for embedded"}, {&dirFlag, "dir", ".", "Root directory"}, - {&withoutTendermintFlag, "without-tendermint", false, "Run Tendermint in-process with the App"}, + {&withoutTendermintFlag, "without-tendermint", false, "RunE Tendermint in-process with the App"}, } RegisterFlags(StartCmd, flags) @@ -50,7 +51,7 @@ func init() { // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") } -func startCmd(cmd *cobra.Command, args []string) { +func startCmd(cmd *cobra.Command, args []string) error { basecoinDir := BasecoinRoot("") // Connect to MerkleEyes @@ -61,7 +62,7 @@ func startCmd(cmd *cobra.Command, args []string) { var err error eyesCli, err = eyes.NewClient(eyesFlag) if err != nil { - cmn.Exit(fmt.Sprintf("Error connecting to MerkleEyes: %+v\n", err)) + return errors.Errorf("Error connecting to MerkleEyes: %v\n", err) } } @@ -84,7 +85,7 @@ func startCmd(cmd *cobra.Command, args []string) { if _, err := os.Stat(genesisFile); err == nil { err := basecoinApp.LoadGenesis(genesisFile) if err != nil { - cmn.Exit(fmt.Sprintf("Error in LoadGenesis: %+v\n", err)) + return errors.Errorf("Error in LoadGenesis: %v\n", err) } } else { fmt.Printf("No genesis file at %s, skipping...\n", genesisFile) @@ -95,20 +96,20 @@ func startCmd(cmd *cobra.Command, args []string) { if withoutTendermintFlag { log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID) // run just the abci app/server - startBasecoinABCI(basecoinApp) + return startBasecoinABCI(basecoinApp) } else { log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID) // start the app with tendermint in-process - startTendermint(basecoinDir, basecoinApp) + return startTendermint(basecoinDir, basecoinApp) } } -func startBasecoinABCI(basecoinApp *app.Basecoin) { +func startBasecoinABCI(basecoinApp *app.Basecoin) error { // Start the ABCI listener svr, err := server.NewServer(addrFlag, "socket", basecoinApp) if err != nil { - cmn.Exit(fmt.Sprintf("Error creating listener: %+v\n", err)) + return errors.Errorf("Error creating listener: %v\n", err) } // Wait forever @@ -116,9 +117,10 @@ func startBasecoinABCI(basecoinApp *app.Basecoin) { // Cleanup svr.Stop() }) + return nil } -func startTendermint(dir string, basecoinApp *app.Basecoin) { +func startTendermint(dir string, basecoinApp *app.Basecoin) error { // Get configuration tmConfig := tmcfg.GetConfig(dir) @@ -132,7 +134,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) { _, err := n.Start() if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return errors.Errorf("%v\n", err) } // Wait forever @@ -140,4 +142,5 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) { // Cleanup n.Stop() }) + return nil } diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index e7381b0874..1fd6be11cd 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -10,7 +10,6 @@ import ( "github.com/tendermint/basecoin/types" crypto "github.com/tendermint/go-crypto" - cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -26,13 +25,13 @@ var ( SendTxCmd = &cobra.Command{ Use: "send", Short: "A SendTx transaction, for sending tokens around", - Run: sendTxCmd, + RunE: sendTxCmd, } AppTxCmd = &cobra.Command{ Use: "app", Short: "An AppTx transaction, for sending raw data to plugins", - Run: appTxCmd, + RunE: appTxCmd, } ) @@ -82,31 +81,34 @@ func init() { TxCmd.AddCommand(SendTxCmd, AppTxCmd) } -func sendTxCmd(cmd *cobra.Command, args []string) { +func sendTxCmd(cmd *cobra.Command, args []string) error { // convert destination address to bytes to, err := hex.DecodeString(StripHex(toFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("To address is invalid hex: %+v\n", err)) + return errors.Errorf("To address is invalid hex: %v\n", err) } // load the priv key - privKey := LoadKey(fromFlag) + privKey, err := LoadKey(fromFlag) + if err != nil { + return err + } // get the sequence number for the tx sequence, err := getSeq(privKey.Address[:]) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } //parse the fee and amounts into coin types feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } // craft the tx @@ -129,39 +131,43 @@ func sendTxCmd(cmd *cobra.Command, args []string) { // broadcast the transaction to tendermint data, log, err := broadcastTx(tx) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Printf("Response: %X ; %s\n", data, log) + return nil } -func appTxCmd(cmd *cobra.Command, args []string) { +func appTxCmd(cmd *cobra.Command, args []string) error { // convert data to bytes data := []byte(dataFlag) if isHex(dataFlag) { data, _ = hex.DecodeString(dataFlag) } name := nameFlag - AppTx(name, data) + return AppTx(name, data) } -func AppTx(name string, data []byte) { +func AppTx(name string, data []byte) error { - privKey := LoadKey(fromFlag) + privKey, err := LoadKey(fromFlag) + if err != nil { + return err + } sequence, err := getSeq(privKey.Address[:]) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } //parse the fee and amounts into coin types feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) @@ -180,9 +186,10 @@ func AppTx(name string, data []byte) { data, log, err := broadcastTx(tx) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Printf("Response: %X ; %s\n", data, log) + return nil } // broadcast the transaction to tendermint @@ -199,7 +206,7 @@ func broadcastTx(tx types.Tx) ([]byte, string, error) { _, err := uriClient.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult) if err != nil { - return nil, "", errors.New(cmn.Fmt("Error on broadcast tx: %v", err)) + return nil, "", errors.Errorf("Error on broadcast tx: %v", err) } res := (*tmResult).(*ctypes.ResultBroadcastTxCommit) @@ -207,12 +214,12 @@ func broadcastTx(tx types.Tx) ([]byte, string, error) { // if it fails check, we don't even get a delivertx back! if !res.CheckTx.Code.IsOK() { r := res.CheckTx - return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log)) + return nil, "", errors.Errorf("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log) } if !res.DeliverTx.Code.IsOK() { r := res.DeliverTx - return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log)) + return nil, "", errors.Errorf("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log) } return res.DeliverTx.Data, res.DeliverTx.Log, nil diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 7f21be9515..18b856f4d7 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -13,6 +13,7 @@ import ( "github.com/tendermint/basecoin/types" abci "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -33,6 +34,19 @@ func BasecoinRoot(rootDir string) string { return rootDir } +//Add debugging flag and execute the root command +func ExecuteWithDebug(RootCmd *cobra.Command) { + + var debug bool + RootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enables stack trace error messages") + + //note that Execute() prints the error if encountered, so no need to reprint the error, + // only if we want the full stack trace + if err := RootCmd.Execute(); err != nil && debug { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } +} + type Flag2Register struct { Pointer interface{} Use string @@ -117,11 +131,11 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { } _, err := uriClient.Call("abci_query", params, tmResult) if err != nil { - return nil, errors.New(fmt.Sprintf("Error calling /abci_query: %v", err)) + return nil, errors.Errorf("Error calling /abci_query: %v", err) } res := (*tmResult).(*ctypes.ResultABCIQuery) if !res.Response.Code.IsOK() { - return nil, errors.New(fmt.Sprintf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)) + return nil, errors.Errorf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log) } return &res.Response, nil } @@ -138,14 +152,14 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) { accountBytes := response.Value if len(accountBytes) == 0 { - return nil, errors.New(fmt.Sprintf("Account bytes are empty for address: %X ", address)) + return nil, fmt.Errorf("Account bytes are empty for address: %X ", address) //never stack trace } var acc *types.Account err = wire.ReadBinaryBytes(accountBytes, &acc) if err != nil { - return nil, errors.New(fmt.Sprintf("Error reading account %X error: %v", - accountBytes, err.Error())) + return nil, errors.Errorf("Error reading account %X error: %v", + accountBytes, err.Error()) } return acc, nil @@ -158,7 +172,7 @@ func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Co method := "commit" _, err := uriClient.Call(method, map[string]interface{}{"height": height}, tmResult) if err != nil { - return nil, nil, errors.New(fmt.Sprintf("Error on %s: %v", method, err)) + return nil, nil, errors.Errorf("Error on %s: %v", method, err) } resCommit := (*tmResult).(*ctypes.ResultCommit) header := resCommit.Header diff --git a/cmd/counter/cmd.go b/cmd/counter/cmd.go index 6b31e3fc61..cde1f0fd00 100644 --- a/cmd/counter/cmd.go +++ b/cmd/counter/cmd.go @@ -9,14 +9,13 @@ import ( "github.com/tendermint/basecoin/cmd/commands" "github.com/tendermint/basecoin/plugins/counter" "github.com/tendermint/basecoin/types" - cmn "github.com/tendermint/go-common" ) //commands var CounterTxCmd = &cobra.Command{ Use: "counter", Short: "Create, sign, and broadcast a transaction to the counter plugin", - Run: counterTxCmd, + RunE: counterTxCmd, } //flags @@ -34,11 +33,11 @@ func init() { commands.RegisterStartPlugin("counter", func() types.Plugin { return counter.New() }) } -func counterTxCmd(cmd *cobra.Command, args []string) { +func counterTxCmd(cmd *cobra.Command, args []string) error { countFee, err := commands.ParseCoins(countFeeFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } counterTx := counter.CounterTx{ @@ -51,5 +50,5 @@ func counterTxCmd(cmd *cobra.Command, args []string) { data := wire.BinaryBytes(counterTx) name := "counter" - commands.AppTx(name, data) + return commands.AppTx(name, data) } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index fc5ad6b02a..8a96b50ed7 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/tendermint/basecoin/cmd/commands" @@ -27,8 +24,5 @@ func main() { commands.QuickVersionCmd("0.1.0"), ) - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } diff --git a/docs/guide/example-plugin.md b/docs/guide/example-plugin.md index d9e3a3255b..a4592b355a 100644 --- a/docs/guide/example-plugin.md +++ b/docs/guide/example-plugin.md @@ -46,10 +46,7 @@ func main() { ) //Run the root command - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } ``` @@ -71,7 +68,7 @@ var ( ExamplePluginTxCmd = &cobra.Command{ Use: "example", Short: "Create, sign, and broadcast a transaction to the example plugin", - Run: examplePluginTxCmd, + RunE: examplePluginTxCmd, } ) ``` @@ -98,10 +95,10 @@ func init() { We now define the actual function which is called by our CLI command. ```golang -func examplePluginTxCmd(cmd *cobra.Command, args []string) { +func examplePluginTxCmd(cmd *cobra.Command, args []string) error { exampleTx := ExamplePluginTx{validFlag} exampleTxBytes := wire.BinaryBytes(exampleTx) - commands.AppTx("example-plugin", exampleTxBytes) + return commands.AppTx("example-plugin", exampleTxBytes) } ``` diff --git a/docs/guide/ibc.md b/docs/guide/ibc.md index 9b88c416ba..abbf0908fc 100644 --- a/docs/guide/ibc.md +++ b/docs/guide/ibc.md @@ -13,7 +13,8 @@ You may also want to see the tutorials on [a simple example plugin](example-plug and the list of [more advanced plugins](more-examples.md). The IBC plugin defines a new set of transactions as subtypes of the `AppTx`. -The plugin's functionality is accessed by setting the `AppTx.Name` field to `"IBC"`, and setting the `Data` field to the serialized IBC transaction type. +The plugin's functionality is accessed by setting the `AppTx.Name` field to `"IBC"`, +and setting the `Data` field to the serialized IBC transaction type. We'll demonstrate exactly how this works below. @@ -33,7 +34,8 @@ contains the votes responsible for committing the previous block, and a field in the block header called `AppHash`, which refers to the Merkle root hash of the application after processing the transactions from the previous block. So, if we want to verify the `AppHash` from height H, we need the signatures from `LastCommit` -at height H+1. (And remember that this `AppHash` only contains the results from all transactions up to and including block H-1) +at height H+1. (And remember that this `AppHash` only contains the results from all +transactions up to and including block H-1) Unlike Proof-of-Work, the light-client protocol does not need to download and check all the headers in the blockchain - the client can always jump straight diff --git a/docs/guide/src/example-plugin/cmd.go b/docs/guide/src/example-plugin/cmd.go index 51077d06f5..b439176266 100644 --- a/docs/guide/src/example-plugin/cmd.go +++ b/docs/guide/src/example-plugin/cmd.go @@ -17,7 +17,7 @@ var ( ExamplePluginTxCmd = &cobra.Command{ Use: "example", Short: "Create, sign, and broadcast a transaction to the example plugin", - Run: examplePluginTxCmd, + RunE: examplePluginTxCmd, } ) @@ -35,7 +35,7 @@ func init() { } //Send a transaction -func examplePluginTxCmd(cmd *cobra.Command, args []string) { +func examplePluginTxCmd(cmd *cobra.Command, args []string) error { // Create a transaction using the flag. // The tx passes on custom information to the plugin @@ -58,5 +58,5 @@ func examplePluginTxCmd(cmd *cobra.Command, args []string) { // - Once deserialized, the tx is passed to `state.ExecTx` (state/execution.go) // - If the tx passes various checks, the `tx.Data` is forwarded as `txBytes` to `plugin.RunTx` (docs/guide/src/example-plugin/plugin.go) // - Finally, it deserialized back to the ExamplePluginTx - commands.AppTx("example-plugin", exampleTxBytes) + return commands.AppTx("example-plugin", exampleTxBytes) } diff --git a/docs/guide/src/example-plugin/main.go b/docs/guide/src/example-plugin/main.go index 3a2984b60d..e2892bd7d8 100644 --- a/docs/guide/src/example-plugin/main.go +++ b/docs/guide/src/example-plugin/main.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/tendermint/basecoin/cmd/commands" @@ -31,8 +28,5 @@ func main() { ) //Run the root command - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } diff --git a/glide.lock b/glide.lock index 0476397fef..e8ed38ebdd 100644 --- a/glide.lock +++ b/glide.lock @@ -89,7 +89,7 @@ imports: subpackages: - upnp - name: github.com/tendermint/go-rpc - version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7 + version: c3295f4878019ff3fdfcac37a4c0e4bcf4bb02a7 subpackages: - client - server diff --git a/glide.yaml b/glide.yaml index 420cc1ceba..9d74f5a6b9 100644 --- a/glide.yaml +++ b/glide.yaml @@ -11,7 +11,7 @@ import: - package: github.com/tendermint/go-data version: master - package: github.com/tendermint/go-rpc - version: master + version: develop - package: github.com/tendermint/go-wire version: master - package: github.com/tendermint/merkleeyes diff --git a/scripts/print_txs.go b/scripts/print_txs.go index d7570a0bd6..689173a907 100644 --- a/scripts/print_txs.go +++ b/scripts/print_txs.go @@ -9,7 +9,7 @@ import ( "time" "github.com/gorilla/websocket" - . "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-rpc/types" "github.com/tendermint/go-wire" @@ -21,7 +21,7 @@ func main() { _, err := ws.Start() if err != nil { - Exit(err.Error()) + cmn.Exit(err.Error()) } // Read a bunch of responses @@ -50,7 +50,7 @@ func main() { reqBytes := wire.JSONBytes(request) err = ws.WriteMessage(websocket.TextMessage, reqBytes) if err != nil { - Exit("writing websocket request: " + err.Error()) + cmn.Exit("writing websocket request: " + err.Error()) } } diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index c486c64ab3..73ace4ef88 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -72,7 +72,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) //request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") @@ -123,7 +123,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes)