From fb3fd1b425636c7be1721bcd4905772c57dfe078 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 9 Mar 2017 02:19:07 -0500 Subject: [PATCH 01/13] added cli cobra rebaseFixes int removed ExitOnErr int int int int int added uint64 to RegisterFlags --- cmd/basecoin/main.go | 22 +- cmd/commands/flags.go | 119 ---------- cmd/commands/ibc.go | 301 +++++++++++--------------- cmd/commands/init.go | 62 ++++-- cmd/commands/key.go | 38 ++-- cmd/commands/plugin_util.go | 41 ++++ cmd/commands/query.go | 175 ++++++++------- cmd/commands/reset.go | 39 +--- cmd/commands/start.go | 93 ++++---- cmd/commands/tx.go | 203 ++++++++--------- cmd/commands/utils.go | 74 ++++++- cmd/commands/version.go | 17 ++ cmd/counter/cmd.go | 51 ++--- cmd/counter/main.go | 27 ++- demo/start.sh | 6 +- docs/guide/example-plugin.md | 51 ++++- docs/guide/src/example-plugin/cmd.go | 44 ++-- docs/guide/src/example-plugin/main.go | 32 ++- glide.lock | 27 ++- glide.yaml | 20 +- 20 files changed, 716 insertions(+), 726 deletions(-) delete mode 100644 cmd/commands/flags.go create mode 100644 cmd/commands/plugin_util.go create mode 100644 cmd/commands/version.go diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index 4eb4c944c..bcb549301 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -4,17 +4,18 @@ import ( "fmt" "os" + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/cmd/commands" - "github.com/tendermint/basecoin/version" - "github.com/urfave/cli" ) func main() { - app := cli.NewApp() - app.Name = "basecoin" - app.Usage = "basecoin [command] [args...]" - app.Version = version.Version - app.Commands = []cli.Command{ + var RootCmd = &cobra.Command{ + Use: "basecoin", + Short: "A cryptocurrency framework in Golang based on Tendermint-Core", + } + + RootCmd.AddCommand( commands.InitCmd, commands.StartCmd, commands.TxCmd, @@ -24,9 +25,10 @@ func main() { commands.BlockCmd, commands.AccountCmd, commands.UnsafeResetAllCmd, - } - err := app.Run(os.Args) - if err != nil { + commands.VersionCmd, + ) + + if err := RootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } diff --git a/cmd/commands/flags.go b/cmd/commands/flags.go deleted file mode 100644 index ccf95769d..000000000 --- a/cmd/commands/flags.go +++ /dev/null @@ -1,119 +0,0 @@ -package commands - -import ( - "github.com/urfave/cli" -) - -// start flags -var ( - AddrFlag = cli.StringFlag{ - Name: "address", - Value: "tcp://0.0.0.0:46658", - Usage: "Listen address", - } - - EyesFlag = cli.StringFlag{ - Name: "eyes", - Value: "local", - Usage: "MerkleEyes address, or 'local' for embedded", - } - - // TODO: move to config file - // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") - - WithoutTendermintFlag = cli.BoolFlag{ - Name: "without-tendermint", - Usage: "Run the Basecoin app without Tendermint", - } -) - -// tx flags - -var ( - NodeFlag = cli.StringFlag{ - Name: "node", - Value: "tcp://localhost:46657", - Usage: "Tendermint RPC address", - } - - ToFlag = cli.StringFlag{ - Name: "to", - Value: "", - Usage: "Destination address for the transaction", - } - - AmountFlag = cli.StringFlag{ - Name: "amount", - Value: "", - Usage: "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver)", - } - - FromFlag = cli.StringFlag{ - Name: "from", - Value: "key.json", - Usage: "Path to a private key to sign the transaction", - } - - SeqFlag = cli.IntFlag{ - Name: "sequence", - Value: 0, - Usage: "Sequence number for the account", - } - - GasFlag = cli.IntFlag{ - Name: "gas", - Value: 0, - Usage: "The amount of gas for the transaction", - } - - FeeFlag = cli.StringFlag{ - Name: "fee", - Value: "", - Usage: "Coins for the transaction fee of the format ", - } - - DataFlag = cli.StringFlag{ - Name: "data", - Value: "", - Usage: "Data to send with the transaction", - } - - NameFlag = cli.StringFlag{ - Name: "name", - Value: "", - Usage: "Plugin to send the transaction to", - } - - ChainIDFlag = cli.StringFlag{ - Name: "chain_id", - Value: "test_chain_id", - Usage: "ID of the chain for replay protection", - } -) - -// proof flags -var ( - ProofFlag = cli.StringFlag{ - Name: "proof", - Usage: "hex-encoded IAVL proof", - Value: "", - } - - KeyFlag = cli.StringFlag{ - Name: "key", - Usage: "key to the IAVL tree", - Value: "", - } - - ValueFlag = cli.StringFlag{ - Name: "value", - Usage: "value in the IAVL tree", - Value: "", - } - - RootFlag = cli.StringFlag{ - Name: "root", - Usage: "root hash of the IAVL tree", - Value: "", - } -) diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 34f4b7923..48fd4d6c2 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -2,11 +2,10 @@ package commands import ( "encoding/hex" - "errors" "fmt" "io/ioutil" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/tendermint/basecoin/plugins/ibc" @@ -21,172 +20,110 @@ func NewIBCPlugin() *ibc.IBCPlugin { return ibc.New() } -//--------------------------------------------------------------------- -// ibc flags - +//commands var ( - IbcChainIDFlag = cli.StringFlag{ - Name: "chain_id", - Usage: "ChainID for the new blockchain", - Value: "", + IBCTxCmd = &cobra.Command{ + Use: "ibc", + Short: "An IBC transaction, for InterBlockchain Communication", } - IbcGenesisFlag = cli.StringFlag{ - Name: "genesis", - Usage: "Genesis file for the new blockchain", - Value: "", + IBCRegisterTxCmd = &cobra.Command{ + Use: "register", + Short: "Register a blockchain via IBC", + Run: ibcRegisterTxCmd, } - IbcHeaderFlag = cli.StringFlag{ - Name: "header", - Usage: "Block header for an ibc update", - Value: "", + IBCUpdateTxCmd = &cobra.Command{ + Use: "update", + Short: "Update the latest state of a blockchain via IBC", + Run: ibcUpdateTxCmd, } - IbcCommitFlag = cli.StringFlag{ - Name: "commit", - Usage: "Block commit for an ibc update", - Value: "", + IBCPacketTxCmd = &cobra.Command{ + Use: "packet", + Short: "Send a new packet via IBC", } - IbcFromFlag = cli.StringFlag{ - Name: "from", - Usage: "Source ChainID", - Value: "", + IBCPacketCreateTxCmd = &cobra.Command{ + Use: "create", + Short: "Create an egress IBC packet", + Run: ibcPacketCreateTxCmd, } - IbcToFlag = cli.StringFlag{ - Name: "to", - Usage: "Destination ChainID", - Value: "", - } - - IbcTypeFlag = cli.StringFlag{ - Name: "type", - Usage: "IBC packet type (eg. coin)", - Value: "", - } - - IbcPayloadFlag = cli.StringFlag{ - Name: "payload", - Usage: "IBC packet payload", - Value: "", - } - - IbcPacketFlag = cli.StringFlag{ - Name: "packet", - Usage: "hex-encoded IBC packet", - Value: "", - } - - IbcProofFlag = cli.StringFlag{ - Name: "proof", - Usage: "hex-encoded proof of IBC packet from source chain", - Value: "", - } - - IbcSequenceFlag = cli.IntFlag{ - Name: "sequence", - Usage: "sequence number for IBC packet", - Value: 0, - } - - IbcHeightFlag = cli.IntFlag{ - Name: "height", - Usage: "Height the packet became egress in source chain", - Value: 0, + IBCPacketPostTxCmd = &cobra.Command{ + Use: "post", + Short: "Deliver an IBC packet to another chain", + Run: ibcPacketPostTxCmd, } ) -//--------------------------------------------------------------------- -// ibc commands - +//flags var ( - IbcTxCmd = cli.Command{ - Name: "ibc", - Usage: "an IBC transaction, for InterBlockchain Communication", - Flags: TxFlags, - Subcommands: []cli.Command{ - IbcRegisterTxCmd, - IbcUpdateTxCmd, - IbcPacketTxCmd, - }, - } - - IbcRegisterTxCmd = cli.Command{ - Name: "register", - Usage: "Register a blockchain via IBC", - Action: func(c *cli.Context) error { - return cmdIBCRegisterTx(c) - }, - Flags: []cli.Flag{ - IbcChainIDFlag, - IbcGenesisFlag, - }, - } - - IbcUpdateTxCmd = cli.Command{ - Name: "update", - Usage: "Update the latest state of a blockchain via IBC", - Action: func(c *cli.Context) error { - return cmdIBCUpdateTx(c) - }, - Flags: []cli.Flag{ - IbcHeaderFlag, - IbcCommitFlag, - }, - } - - IbcPacketTxCmd = cli.Command{ - Name: "packet", - Usage: "Send a new packet via IBC", - Subcommands: []cli.Command{ - IbcPacketCreateTx, - IbcPacketPostTx, - }, - } - - IbcPacketCreateTx = cli.Command{ - Name: "create", - Usage: "Create an egress IBC packet", - Action: func(c *cli.Context) error { - return cmdIBCPacketCreateTx(c) - }, - Flags: []cli.Flag{ - IbcFromFlag, - IbcToFlag, - IbcTypeFlag, - IbcPayloadFlag, - IbcSequenceFlag, - }, - } - - IbcPacketPostTx = cli.Command{ - Name: "post", - Usage: "Deliver an IBC packet to another chain", - Action: func(c *cli.Context) error { - return cmdIBCPacketPostTx(c) - }, - Flags: []cli.Flag{ - IbcFromFlag, - IbcHeightFlag, - IbcPacketFlag, - IbcProofFlag, - }, - } + ibcChainIDFlag string + ibcGenesisFlag string + ibcHeaderFlag string + ibcCommitFlag string + ibcFromFlag string + ibcToFlag string + ibcTypeFlag string + ibcPayloadFlag string + ibcPacketFlag string + ibcProofFlag string + ibcSequenceFlag int + ibcHeightFlag int ) +func init() { + + // register flags + registerFlags := []Flag2Register{ + {&ibcChainIDFlag, "ibc_chain_id", "", "ChainID for the new blockchain"}, + {&ibcGenesisFlag, "genesis", "", "Genesis file for the new blockchain"}, + } + + updateFlags := []Flag2Register{ + {&ibcHeaderFlag, "header", "", "Block header for an ibc update"}, + {&ibcCommitFlag, "commit", "", "Block commit for an ibc update"}, + } + + fromFlagReg := Flag2Register{&ibcFromFlag, "ibc_from", "", "Source ChainID"} + + packetCreateFlags := []Flag2Register{ + fromFlagReg, + {&ibcToFlag, "to", "", "Destination ChainID"}, + {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin},"}, + {&ibcPayloadFlag, "payload", "", "IBC packet payload"}, + {&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"}, + } + + packetPostFlags := []Flag2Register{ + fromFlagReg, + {&ibcHeightFlag, "height", 0, "Height the packet became egress in source chain"}, + {&ibcPacketFlag, "packet", "", "hex-encoded IBC packet"}, + {&ibcProofFlag, "proof", "", "hex-encoded proof of IBC packet from source chain"}, + } + + RegisterFlags(IBCRegisterTxCmd, registerFlags) + RegisterFlags(IBCUpdateTxCmd, updateFlags) + RegisterFlags(IBCPacketCreateTxCmd, packetCreateFlags) + RegisterFlags(IBCPacketPostTxCmd, packetPostFlags) + + //register commands + IBCTxCmd.AddCommand(IBCRegisterTxCmd, IBCUpdateTxCmd, IBCPacketTxCmd) + IBCPacketTxCmd.AddCommand(IBCPacketCreateTxCmd, IBCPacketPostTxCmd) + RegisterTxSubcommand(IBCTxCmd) +} + //--------------------------------------------------------------------- // ibc command implementations -func cmdIBCRegisterTx(c *cli.Context) error { - chainID := c.String("chain_id") - genesisFile := c.String("genesis") - parent := c.Parent() +func ibcRegisterTxCmd(cmd *cobra.Command, args []string) { + chainID := ibcChainIDFlag + genesisFile := ibcGenesisFlag genesisBytes, err := ioutil.ReadFile(genesisFile) if err != nil { - return errors.New(cmn.Fmt("Error reading genesis file %v: %v", genesisFile, err)) + cmn.Exit(fmt.Sprintf("Error reading genesis file %v: %+v\n", genesisFile, err)) } ibcTx := ibc.IBCRegisterChainTx{ @@ -203,27 +140,31 @@ func cmdIBCRegisterTx(c *cli.Context) error { }{ibcTx})) name := "IBC" - return AppTx(parent, name, data) + AppTx(name, data) } -func cmdIBCUpdateTx(c *cli.Context) error { - headerBytes, err := hex.DecodeString(StripHex(c.String("header"))) +func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { + headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag)) if err != nil { - return errors.New(cmn.Fmt("Header (%v) is invalid hex: %v", c.String("header"), err)) + cmn.Exit(fmt.Sprintf("Header (%v) is invalid hex: %+v\n", ibcHeaderFlag, err)) } - commitBytes, err := hex.DecodeString(StripHex(c.String("commit"))) + + commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag)) if err != nil { - return errors.New(cmn.Fmt("Commit (%v) is invalid hex: %v", c.String("commit"), err)) + cmn.Exit(fmt.Sprintf("Commit (%v) is invalid hex: %+v\n", ibcCommitFlag, err)) } header := new(tmtypes.Header) commit := new(tmtypes.Commit) - if err := wire.ReadBinaryBytes(headerBytes, &header); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling header: %v", err)) + err = wire.ReadBinaryBytes(headerBytes, &header) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling header: %+v\n", err)) } - if err := wire.ReadBinaryBytes(commitBytes, &commit); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling commit: %v", err)) + + err = wire.ReadBinaryBytes(commitBytes, &commit) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling commit: %+v\n", err)) } ibcTx := ibc.IBCUpdateChainTx{ @@ -238,21 +179,21 @@ func cmdIBCUpdateTx(c *cli.Context) error { }{ibcTx})) name := "IBC" - return AppTx(c.Parent(), name, data) + AppTx(name, data) } -func cmdIBCPacketCreateTx(c *cli.Context) error { - fromChain, toChain := c.String("from"), c.String("to") - packetType := c.String("type") +func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) { + fromChain, toChain := ibcFromFlag, ibcToFlag + packetType := ibcTypeFlag - payloadBytes, err := hex.DecodeString(StripHex(c.String("payload"))) + payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag)) if err != nil { - return errors.New(cmn.Fmt("Payload (%v) is invalid hex: %v", c.String("payload"), err)) + cmn.Exit(fmt.Sprintf("Payload (%v) is invalid hex: %+v\n", ibcPayloadFlag, err)) } - sequence, err := getIBCSequence(c) + sequence, err := ibcSequenceCmd() if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } ibcTx := ibc.IBCPacketCreateTx{ @@ -271,29 +212,33 @@ func cmdIBCPacketCreateTx(c *cli.Context) error { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - return AppTx(c.Parent().Parent(), "IBC", data) + AppTx("IBC", data) } -func cmdIBCPacketPostTx(c *cli.Context) error { - fromChain, fromHeight := c.String("from"), c.Int("height") +func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { + fromChain, fromHeight := ibcFromFlag, ibcHeightFlag - packetBytes, err := hex.DecodeString(StripHex(c.String("packet"))) + packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag)) if err != nil { - return errors.New(cmn.Fmt("Packet (%v) is invalid hex: %v", c.String("packet"), err)) + cmn.Exit(fmt.Sprintf("Packet (%v) is invalid hex: %+v\n", ibcPacketFlag, err)) } - proofBytes, err := hex.DecodeString(StripHex(c.String("proof"))) + + proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag)) if err != nil { - return errors.New(cmn.Fmt("Proof (%v) is invalid hex: %v", c.String("proof"), err)) + cmn.Exit(fmt.Sprintf("Proof (%v) is invalid hex: %+v\n", ibcProofFlag, err)) } var packet ibc.Packet proof := new(merkle.IAVLProof) - if err := wire.ReadBinaryBytes(packetBytes, &packet); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling packet: %v", err)) + err = wire.ReadBinaryBytes(packetBytes, &packet) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling packet: %+v\n", err)) } - if err := wire.ReadBinaryBytes(proofBytes, &proof); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling proof: %v", err)) + + err = wire.ReadBinaryBytes(proofBytes, &proof) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) } ibcTx := ibc.IBCPacketPostTx{ @@ -309,12 +254,12 @@ func cmdIBCPacketPostTx(c *cli.Context) error { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - return AppTx(c.Parent().Parent(), "IBC", data) + AppTx("IBC", data) } -func getIBCSequence(c *cli.Context) (uint64, error) { - if c.IsSet("sequence") { - return uint64(c.Int("sequence")), nil +func ibcSequenceCmd() (uint64, error) { + if ibcSequenceFlag >= 0 { + return uint64(ibcSequenceFlag), nil } // TODO: get sequence diff --git a/cmd/commands/init.go b/cmd/commands/init.go index e60e7d130..99bff657c 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -1,27 +1,38 @@ package commands import ( + "fmt" "io/ioutil" "path" - "github.com/urfave/cli" + "github.com/spf13/cobra" cmn "github.com/tendermint/go-common" ) -var InitCmd = cli.Command{ - Name: "init", - Usage: "Initialize a basecoin blockchain", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdInit(c) - }, - Flags: []cli.Flag{ - ChainIDFlag, - }, -} +//commands +var ( + InitCmd = &cobra.Command{ + Use: "init", + Short: "Initialize a basecoin blockchain", + Run: initCmd, + } +) -func cmdInit(c *cli.Context) error { +//flags +//var chainIDFlag string + +//func init() { +// +// //register flags +// flags := []Flag2Register{ +// {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, +// } +// RegisterFlags(InitCmd, flags) +// +//} + +func initCmd(cmd *cobra.Command, args []string) { rootDir := BasecoinRoot("") cmn.EnsureDir(rootDir, 0777) @@ -32,22 +43,27 @@ func cmdInit(c *cli.Context) error { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - if err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644); err != nil { - return err + err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - if err := ioutil.WriteFile(privValFile, []byte(privValJSON), 0400); err != nil { - return err + + err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - if err := ioutil.WriteFile(key1File, []byte(key1JSON), 0400); err != nil { - return err + + err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - if err := ioutil.WriteFile(key2File, []byte(key2JSON), 0400); err != nil { - return err + + err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) - - return nil } const privValJSON = `{ diff --git a/cmd/commands/key.go b/cmd/commands/key.go index 124f390dd..a79ca92f1 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -8,38 +8,38 @@ import ( "path" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" ) +//commands var ( - KeyCmd = cli.Command{ - Name: "key", - Usage: "Manage keys", - ArgsUsage: "", - Subcommands: []cli.Command{NewKeyCmd}, + KeyCmd = &cobra.Command{ + Use: "key", + Short: "Manage keys", } - NewKeyCmd = cli.Command{ - Name: "new", - Usage: "Create a new private key", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdNewKey(c) - }, + NewKeyCmd = &cobra.Command{ + Use: "new", + Short: "Create a new private key", + Run: newKeyCmd, } ) -func cmdNewKey(c *cli.Context) error { +func newKeyCmd(cmd *cobra.Command, args []string) { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Println(string(keyJSON)) - return nil +} + +func init() { + //register commands + KeyCmd.AddCommand(NewKeyCmd) } //--------------------------------------------- @@ -88,12 +88,14 @@ func LoadKey(keyFile string) *Key { filePath := path.Join(BasecoinRoot(""), keyFile) keyJSONBytes, err := ioutil.ReadFile(filePath) if err != nil { - cmn.Exit(err.Error()) + cmn.Exit(fmt.Sprintf("%+v\n", err)) } + key := new(Key) err = json.Unmarshal(keyJSONBytes, key) if err != nil { - cmn.Exit(cmn.Fmt("Error reading key from %v: %v\n", filePath, err)) + cmn.Exit(fmt.Sprintf("Error reading key from %v: %v\n", filePath, err)) } + return key } diff --git a/cmd/commands/plugin_util.go b/cmd/commands/plugin_util.go new file mode 100644 index 000000000..082ff2669 --- /dev/null +++ b/cmd/commands/plugin_util.go @@ -0,0 +1,41 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/types" +) + +type plugin struct { + name string + newPlugin func() types.Plugin +} + +var plugins = []plugin{} + +// RegisterStartPlugin is used to enable a plugin +func RegisterStartPlugin(name string, newPlugin func() types.Plugin) { + plugins = append(plugins, plugin{name: name, newPlugin: newPlugin}) +} + +// Register a subcommand of QueryCmd for plugin specific query functionality +func RegisterQuerySubcommand(cmd *cobra.Command) { + QueryCmd.AddCommand(cmd) +} + +// Register a subcommand of TxCmd to craft transactions for plugins +func RegisterTxSubcommand(cmd *cobra.Command) { + TxCmd.AddCommand(cmd) +} + +//Returns a version command based on version input +func QuickVersionCmd(version string) *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "Show version info", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version) + }, + } +} diff --git a/cmd/commands/query.go b/cmd/commands/query.go index 231d32f9f..7e6e8de28 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -2,11 +2,10 @@ package commands import ( "encoding/hex" - "errors" "fmt" "strconv" - "github.com/urfave/cli" + "github.com/spf13/cobra" cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" @@ -14,85 +13,85 @@ import ( tmtypes "github.com/tendermint/tendermint/types" ) +//commands var ( - QueryCmd = cli.Command{ - Name: "query", - Usage: "Query the merkle tree", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdQuery(c) - }, - Flags: []cli.Flag{ - NodeFlag, - }, + QueryCmd = &cobra.Command{ + Use: "query [key]", + Short: "Query the merkle tree", + Run: queryCmd, } - AccountCmd = cli.Command{ - Name: "account", - Usage: "Get details of an account", - ArgsUsage: "
", - Action: func(c *cli.Context) error { - return cmdAccount(c) - }, - Flags: []cli.Flag{ - NodeFlag, - }, + AccountCmd = &cobra.Command{ + Use: "account [address]", + Short: "Get details of an account", + Run: accountCmd, } - BlockCmd = cli.Command{ - Name: "block", - Usage: "Get the header and commit of a block", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdBlock(c) - }, - Flags: []cli.Flag{ - NodeFlag, - }, + BlockCmd = &cobra.Command{ + Use: "block [height]", + Short: "Get the header and commit of a block", + Run: blockCmd, } - VerifyCmd = cli.Command{ - Name: "verify", - Usage: "Verify the IAVL proof", - Action: func(c *cli.Context) error { - return cmdVerify(c) - }, - Flags: []cli.Flag{ - ProofFlag, - KeyFlag, - ValueFlag, - RootFlag, - }, + VerifyCmd = &cobra.Command{ + Use: "verify", + Short: "Verify the IAVL proof", + Run: verifyCmd, } ) -// Register a subcommand of QueryCmd for plugin specific query functionality -func RegisterQuerySubcommand(cmd cli.Command) { - QueryCmd.Subcommands = append(QueryCmd.Subcommands, cmd) +//flags +var ( + nodeFlag string + proofFlag string + keyFlag string + valueFlag string + rootFlag string +) + +func init() { + + commonFlags := []Flag2Register{ + {&nodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, + } + + verifyFlags := []Flag2Register{ + {&proofFlag, "proof", "", "hex-encoded IAVL proof"}, + {&keyFlag, "key", "", "key to the IAVL tree"}, + {&valueFlag, "value", "", "value in the IAVL tree"}, + {&rootFlag, "root", "", "root hash of the IAVL tree"}, + } + + RegisterFlags(QueryCmd, commonFlags) + RegisterFlags(AccountCmd, commonFlags) + RegisterFlags(BlockCmd, commonFlags) + RegisterFlags(VerifyCmd, verifyFlags) } -func cmdQuery(c *cli.Context) error { - if len(c.Args()) != 1 { - return errors.New("query command requires an argument ([key])") +func queryCmd(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + cmn.Exit("query command requires an argument ([key])") } - keyString := c.Args()[0] + + keyString := args[0] key := []byte(keyString) if isHex(keyString) { // convert key to bytes var err error key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - return errors.New(cmn.Fmt("Query key (%v) is invalid hex: %v", keyString, err)) + cmn.Exit(fmt.Sprintf("Query key (%v) is invalid hex: %+v\n", keyString, err)) } } - resp, err := Query(c.String("node"), key) + resp, err := Query(nodeFlag, key) if err != nil { - return err + cmn.Exit(fmt.Sprintf("Query returns error: %+v\n", err)) } if !resp.Code.IsOK() { - return errors.New(cmn.Fmt("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log)) + cmn.Exit(fmt.Sprintf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log)) } val := resp.Value @@ -104,43 +103,44 @@ func cmdQuery(c *cli.Context) error { Proof []byte `json:"proof"` Height uint64 `json:"height"` }{val, proof, height}))) - - return nil } -func cmdAccount(c *cli.Context) error { - if len(c.Args()) != 1 { - return errors.New("account command requires an argument ([address])") +func accountCmd(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + cmn.Exit("account command requires an argument ([address])") } - addrHex := StripHex(c.Args()[0]) + + addrHex := StripHex(args[0]) // convert destination address to bytes addr, err := hex.DecodeString(addrHex) if err != nil { - return errors.New(cmn.Fmt("Account address (%v) is invalid hex: %v", addrHex, err)) + cmn.Exit(fmt.Sprintf("Account address (%v) is invalid hex: %+v\n", addrHex, err)) } - acc, err := getAcc(c.String("node"), addr) + acc, err := getAcc(nodeFlag, addr) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Println(string(wire.JSONBytes(acc))) - return nil } -func cmdBlock(c *cli.Context) error { - if len(c.Args()) != 1 { - return errors.New("block command requires an argument ([height])") - } - heightString := c.Args()[0] - height, err := strconv.Atoi(heightString) - if err != nil { - return errors.New(cmn.Fmt("Height must be an int, got %v: %v", heightString, err)) +func blockCmd(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + cmn.Exit("block command requires an argument ([height])") } - header, commit, err := getHeaderAndCommit(c, height) + heightString := args[0] + height, err := strconv.Atoi(heightString) if err != nil { - return err + cmn.Exit(fmt.Sprintf("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)) } fmt.Println(string(wire.JSONBytes(struct { @@ -156,8 +156,6 @@ func cmdBlock(c *cli.Context) error { Commit: commit, }, }))) - - return nil } type BlockHex struct { @@ -170,15 +168,16 @@ type BlockJSON struct { Commit *tmtypes.Commit `json:"commit"` } -func cmdVerify(c *cli.Context) error { - keyString, valueString := c.String("key"), c.String("value") +func verifyCmd(cmd *cobra.Command, args []string) { + + keyString, valueString := keyFlag, valueFlag var err error key := []byte(keyString) if isHex(keyString) { key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - return errors.New(cmn.Fmt("Key (%v) is invalid hex: %v", keyString, err)) + cmn.Exit(fmt.Sprintf("Key (%v) is invalid hex: %+v\n", keyString, err)) } } @@ -186,29 +185,25 @@ func cmdVerify(c *cli.Context) error { if isHex(valueString) { value, err = hex.DecodeString(StripHex(valueString)) if err != nil { - return errors.New(cmn.Fmt("Value (%v) is invalid hex: %v", valueString, err)) + cmn.Exit(fmt.Sprintf("Value (%v) is invalid hex: %+v\n", valueString, err)) } } - root, err := hex.DecodeString(StripHex(c.String("root"))) + root, err := hex.DecodeString(StripHex(rootFlag)) if err != nil { - return errors.New(cmn.Fmt("Root (%v) is invalid hex: %v", c.String("root"), err)) + cmn.Exit(fmt.Sprintf("Root (%v) is invalid hex: %+v\n", rootFlag, err)) } - proofBytes, err := hex.DecodeString(StripHex(c.String("proof"))) - if err != nil { - return errors.New(cmn.Fmt("Proof (%v) is invalid hex: %v", c.String("proof"), err)) - } + proofBytes, err := hex.DecodeString(StripHex(proofFlag)) proof, err := merkle.ReadProof(proofBytes) if err != nil { - return errors.New(cmn.Fmt("Error unmarshalling proof: %v", err)) + cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) } if proof.Verify(key, value, root) { fmt.Println("OK") } else { - return errors.New("Proof does not verify") + cmn.Exit(fmt.Sprintf("Proof does not verify")) } - return nil } diff --git a/cmd/commands/reset.go b/cmd/commands/reset.go index d9688fd85..f2841ea80 100644 --- a/cmd/commands/reset.go +++ b/cmd/commands/reset.go @@ -1,47 +1,24 @@ package commands import ( - "os" "path" - "github.com/urfave/cli" + "github.com/spf13/cobra" + "github.com/tendermint/tendermint/cmd/tendermint/commands" tmcfg "github.com/tendermint/tendermint/config/tendermint" - types "github.com/tendermint/tendermint/types" ) -var UnsafeResetAllCmd = cli.Command{ - Name: "unsafe_reset_all", - Usage: "Reset all blockchain data", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdUnsafeResetAll(c) - }, +var UnsafeResetAllCmd = &cobra.Command{ + Use: "unsafe_reset_all", + Short: "Reset all blockchain data", + Run: unsafeResetAllCmd, } -func cmdUnsafeResetAll(c *cli.Context) error { +func unsafeResetAllCmd(cmd *cobra.Command, args []string) { basecoinDir := BasecoinRoot("") tmDir := path.Join(basecoinDir) tmConfig := tmcfg.GetConfig(tmDir) - // Get and Reset PrivValidator - var privValidator *types.PrivValidator - privValidatorFile := tmConfig.GetString("priv_validator_file") - if _, err := os.Stat(privValidatorFile); err == nil { - privValidator = types.LoadPrivValidator(privValidatorFile) - privValidator.Reset() - log.Notice("Reset PrivValidator", "file", privValidatorFile) - } else { - privValidator = types.GenPrivValidator() - privValidator.SetFile(privValidatorFile) - privValidator.Save() - log.Notice("Generated PrivValidator", "file", privValidatorFile) - } - - // Remove all tendermint data - tmDataDir := tmConfig.GetString("db_dir") - os.RemoveAll(tmDataDir) - log.Notice("Removed all data", "dir", tmDataDir) - - return nil + commands.ResetAll(tmConfig, log) } diff --git a/cmd/commands/start.go b/cmd/commands/start.go index 1e6861ac0..d14f663d1 100644 --- a/cmd/commands/start.go +++ b/cmd/commands/start.go @@ -1,12 +1,11 @@ package commands import ( - "errors" "fmt" "os" "path" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/tendermint/abci/server" cmn "github.com/tendermint/go-common" @@ -18,50 +17,51 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/tendermint/basecoin/app" - "github.com/tendermint/basecoin/types" ) +var StartCmd = &cobra.Command{ + Use: "start", + Short: "Start basecoin", + Run: startCmd, +} + +//flags +var ( + addrFlag string + eyesFlag string + dirFlag string + withoutTendermintFlag bool +) + +// TODO: move to config file const EyesCacheSize = 10000 -var StartCmd = cli.Command{ - Name: "start", - Usage: "Start basecoin", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdStart(c) - }, - Flags: []cli.Flag{ - AddrFlag, - EyesFlag, - WithoutTendermintFlag, - ChainIDFlag, - }, +func init() { + + flags := []Flag2Register{ + {&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"}, + } + RegisterFlags(StartCmd, flags) + + // TODO: move to config file + // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") } -type plugin struct { - name string - newPlugin func() types.Plugin -} - -var plugins = []plugin{} - -// RegisterStartPlugin is used to enable a plugin -func RegisterStartPlugin(name string, newPlugin func() types.Plugin) { - plugins = append(plugins, plugin{name: name, newPlugin: newPlugin}) -} - -func cmdStart(c *cli.Context) error { +func startCmd(cmd *cobra.Command, args []string) { basecoinDir := BasecoinRoot("") // Connect to MerkleEyes var eyesCli *eyes.Client - if c.String("eyes") == "local" { + if eyesFlag == "local" { eyesCli = eyes.NewLocalClient(path.Join(basecoinDir, "data", "merkleeyes.db"), EyesCacheSize) } else { var err error - eyesCli, err = eyes.NewClient(c.String("eyes")) + eyesCli, err = eyes.NewClient(eyesFlag) if err != nil { - return errors.New("connect to MerkleEyes: " + err.Error()) + cmn.Exit(fmt.Sprintf("Error connecting to MerkleEyes: %+v\n", err)) } } @@ -84,7 +84,7 @@ func cmdStart(c *cli.Context) error { if _, err := os.Stat(genesisFile); err == nil { err := basecoinApp.LoadGenesis(genesisFile) if err != nil { - return errors.New(cmn.Fmt("%+v", err)) + cmn.Exit(fmt.Sprintf("Error in LoadGenesis: %+v\n", err)) } } else { fmt.Printf("No genesis file at %s, skipping...\n", genesisFile) @@ -92,40 +92,37 @@ func cmdStart(c *cli.Context) error { } chainID := basecoinApp.GetState().GetChainID() - if c.Bool("without-tendermint") { + if withoutTendermintFlag { log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID) // run just the abci app/server - return startBasecoinABCI(c, basecoinApp) + startBasecoinABCI(basecoinApp) } else { log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID) // start the app with tendermint in-process - return startTendermint(basecoinDir, basecoinApp) + startTendermint(basecoinDir, basecoinApp) } - - return nil } -func startBasecoinABCI(c *cli.Context, basecoinApp *app.Basecoin) error { +func startBasecoinABCI(basecoinApp *app.Basecoin) { + // Start the ABCI listener - svr, err := server.NewServer(c.String("address"), "socket", basecoinApp) + svr, err := server.NewServer(addrFlag, "socket", basecoinApp) if err != nil { - return errors.New("create listener: " + err.Error()) + cmn.Exit(fmt.Sprintf("Error creating listener: %+v\n", err)) } + // Wait forever cmn.TrapSignal(func() { // Cleanup svr.Stop() }) - return nil - } -func startTendermint(dir string, basecoinApp *app.Basecoin) error { +func startTendermint(dir string, basecoinApp *app.Basecoin) { + // Get configuration tmConfig := tmcfg.GetConfig(dir) - // logger.SetLogLevel("notice") //config.GetString("log_level")) - // parseFlags(config, args[1:]) // Command line overrides // Create & start tendermint node @@ -135,7 +132,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error { _, err := n.Start() if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } // Wait forever @@ -143,6 +140,4 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error { // Cleanup n.Stop() }) - - return nil } diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 338bbcb22..95358221f 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -2,10 +2,10 @@ package commands import ( "encoding/hex" - "errors" "fmt" - "github.com/urfave/cli" + "github.com/pkg/errors" + "github.com/spf13/cobra" "github.com/tendermint/basecoin/types" crypto "github.com/tendermint/go-crypto" @@ -16,211 +16,215 @@ import ( ctypes "github.com/tendermint/tendermint/rpc/core/types" ) -var TxFlags = []cli.Flag{ - NodeFlag, - ChainIDFlag, - - FromFlag, - - AmountFlag, - GasFlag, - FeeFlag, - SeqFlag, -} - +//commands var ( - TxCmd = cli.Command{ - Name: "tx", - Usage: "Create, sign, and broadcast a transaction", - ArgsUsage: "", - Subcommands: []cli.Command{ - SendTxCmd, - AppTxCmd, - IbcTxCmd, - }, + TxCmd = &cobra.Command{ + Use: "tx", + Short: "Create, sign, and broadcast a transaction", } - SendTxCmd = cli.Command{ - Name: "send", - Usage: "a SendTx transaction, for sending tokens around", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdSendTx(c) - }, - Flags: append(TxFlags, ToFlag), + SendTxCmd = &cobra.Command{ + Use: "send", + Short: "A SendTx transaction, for sending tokens around", + Run: sendTxCmd, } - AppTxCmd = cli.Command{ - Name: "app", - Usage: "an AppTx transaction, for sending raw data to plugins", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdAppTx(c) - }, - Flags: append(TxFlags, NameFlag, DataFlag), - // Subcommands are dynamically registered with plugins as needed - Subcommands: []cli.Command{}, + AppTxCmd = &cobra.Command{ + Use: "app", + Short: "An AppTx transaction, for sending raw data to plugins", + Run: appTxCmd, } ) -// Register a subcommand of TxCmd to craft transactions for plugins -func RegisterTxSubcommand(cmd cli.Command) { - TxCmd.Subcommands = append(TxCmd.Subcommands, cmd) +//flags +var ( + txNodeFlag string + toFlag string + amountFlag string + fromFlag string + seqFlag int + gasFlag int + feeFlag string + dataFlag string + nameFlag string + chainIDFlag string +) + +func init() { + + // register flags + cmdTxFlags := []Flag2Register{ + {&txNodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, + {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, + {&fromFlag, "from", "key.json", "Path to a private key to sign the transaction"}, + {&amountFlag, "amount", "", "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver},"}, + {&gasFlag, "gas", 0, "The amount of gas for the transaction"}, + {&feeFlag, "fee", "", "Coins for the transaction fee of the format "}, + {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate},"}, + } + + sendTxFlags := []Flag2Register{ + {&toFlag, "to", "", "Destination address for the transaction"}, + } + + appTxFlags := []Flag2Register{ + {&nameFlag, "name", "", "Plugin to send the transaction to"}, + {&dataFlag, "data", "", "Data to send with the transaction"}, + } + + RegisterPersistentFlags(TxCmd, cmdTxFlags) + RegisterFlags(SendTxCmd, sendTxFlags) + RegisterFlags(AppTxCmd, appTxFlags) + + //register commands + TxCmd.AddCommand(SendTxCmd, AppTxCmd) } -func cmdSendTx(c *cli.Context) error { - toHex := c.String("to") - fromFile := c.String("from") - amount := c.String("amount") - gas := int64(c.Int("gas")) - fee := c.String("fee") - chainID := c.String("chain_id") +func sendTxCmd(cmd *cobra.Command, args []string) { // convert destination address to bytes - to, err := hex.DecodeString(StripHex(toHex)) + to, err := hex.DecodeString(StripHex(toFlag)) if err != nil { - return errors.New("To address is invalid hex: " + err.Error()) + cmn.Exit(fmt.Sprintf("To address is invalid hex: %+v\n", err)) } // load the priv key - privKey := LoadKey(fromFile) + privKey := LoadKey(fromFlag) // get the sequence number for the tx - sequence, err := getSeq(c, privKey.Address[:]) + sequence, err := getSeq(privKey.Address[:]) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } //parse the fee and amounts into coin types - feeCoin, err := types.ParseCoin(fee) + feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - amountCoins, err := types.ParseCoins(amount) + amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } // craft the tx input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) output := newOutput(to, amountCoins) tx := &types.SendTx{ - Gas: gas, + Gas: int64(gasFlag), Fee: feeCoin, Inputs: []types.TxInput{input}, Outputs: []types.TxOutput{output}, } // sign that puppy - signBytes := tx.SignBytes(chainID) + signBytes := tx.SignBytes(chainIDFlag) tx.Inputs[0].Signature = crypto.SignatureS{privKey.Sign(signBytes)} fmt.Println("Signed SendTx:") fmt.Println(string(wire.JSONBytes(tx))) // broadcast the transaction to tendermint - data, log, err := broadcastTx(c, tx) + data, log, err := broadcastTx(tx) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Printf("Response: %X ; %s\n", data, log) - return nil } -func cmdAppTx(c *cli.Context) error { +func appTxCmd(cmd *cobra.Command, args []string) { // convert data to bytes - dataString := c.String("data") - data := []byte(dataString) - if isHex(dataString) { - data, _ = hex.DecodeString(dataString) + data := []byte(dataFlag) + if isHex(dataFlag) { + data, _ = hex.DecodeString(dataFlag) } - name := c.String("name") - return AppTx(c, name, data) + name := nameFlag + AppTx(name, data) } -func AppTx(c *cli.Context, name string, data []byte) error { - fromFile := c.String("from") - amount := c.String("amount") - fee := c.String("fee") - gas := int64(c.Int("gas")) - chainID := c.String("chain_id") +func AppTx(name string, data []byte) { - privKey := LoadKey(fromFile) + privKey := LoadKey(fromFlag) - sequence, err := getSeq(c, privKey.Address[:]) + sequence, err := getSeq(privKey.Address[:]) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } //parse the fee and amounts into coin types - feeCoin, err := types.ParseCoin(fee) + feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - amountCoins, err := types.ParseCoins(amount) + + amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) tx := &types.AppTx{ - Gas: gas, + Gas: int64(gasFlag), Fee: feeCoin, Name: name, Input: input, Data: data, } - tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainID))} + tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainIDFlag))} fmt.Println("Signed AppTx:") fmt.Println(string(wire.JSONBytes(tx))) - data, log, err := broadcastTx(c, tx) + data, log, err := broadcastTx(tx) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Printf("Response: %X ; %s\n", data, log) - - return nil } // broadcast the transaction to tendermint -func broadcastTx(c *cli.Context, tx types.Tx) ([]byte, string, error) { +func broadcastTx(tx types.Tx) ([]byte, string, error) { + tmResult := new(ctypes.TMResult) - tmAddr := c.String("node") - uriClient := client.NewURIClient(tmAddr) + uriClient := client.NewURIClient(txNodeFlag) // Don't you hate having to do this? // How many times have I lost an hour over this trick?! txBytes := []byte(wire.BinaryBytes(struct { types.Tx `json:"unwrap"` }{tx})) + _, 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)) } + res := (*tmResult).(*ctypes.ResultBroadcastTxCommit) + // 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)) } + 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 res.DeliverTx.Data, res.DeliverTx.Log, nil } // if the sequence flag is set, return it; // else, fetch the account by querying the app and return the sequence number -func getSeq(c *cli.Context, address []byte) (int, error) { - if c.IsSet("sequence") { - return c.Int("sequence"), nil +func getSeq(address []byte) (int, error) { + + if seqFlag >= 0 { + return seqFlag, nil } - tmAddr := c.String("node") - acc, err := getAcc(tmAddr, address) + + acc, err := getAcc(txNodeFlag, address) if err != nil { return 0, err } @@ -232,5 +236,4 @@ func newOutput(to []byte, amount types.Coins) types.TxOutput { Address: to, Coins: amount, } - } diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index efff67e0b..f49bfe162 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -2,16 +2,17 @@ package commands import ( "encoding/hex" - "errors" + "fmt" "os" - "github.com/urfave/cli" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/tendermint/basecoin/state" "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" @@ -28,6 +29,60 @@ func BasecoinRoot(rootDir string) string { return rootDir } +type Flag2Register struct { + Pointer interface{} + Use string + Value interface{} + Desc string +} + +//register flag utils +func RegisterFlags(c *cobra.Command, flags []Flag2Register) { + registerFlags(c, flags, false) +} + +func RegisterPersistentFlags(c *cobra.Command, flags []Flag2Register) { + registerFlags(c, flags, true) +} + +func registerFlags(c *cobra.Command, flags []Flag2Register, persistent bool) { + + var flagset *pflag.FlagSet + if persistent { + flagset = c.PersistentFlags() + } else { + flagset = c.Flags() + } + + for _, f := range flags { + + ok := false + + switch f.Value.(type) { + case string: + if _, ok = f.Pointer.(*string); ok { + flagset.StringVar(f.Pointer.(*string), f.Use, f.Value.(string), f.Desc) + } + case int: + if _, ok = f.Pointer.(*int); ok { + flagset.IntVar(f.Pointer.(*int), f.Use, f.Value.(int), f.Desc) + } + case uint64: + if _, ok = f.Pointer.(*uint64); ok { + flagset.Uint64Var(f.Pointer.(*uint64), f.Use, f.Value.(uint64), f.Desc) + } + case bool: + if _, ok = f.Pointer.(*bool); ok { + flagset.BoolVar(f.Pointer.(*bool), f.Use, f.Value.(bool), f.Desc) + } + } + + if !ok { + panic("improper use of RegisterFlags") + } + } +} + // Returns true for non-empty hex-string prefixed with "0x" func isHex(s string) bool { if len(s) > 2 && s[:2] == "0x" { @@ -58,11 +113,11 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { } _, err := uriClient.Call("abci_query", params, tmResult) if err != nil { - return nil, errors.New(cmn.Fmt("Error calling /abci_query: %v", err)) + return nil, errors.New(fmt.Sprintf("Error calling /abci_query: %v", err)) } res := (*tmResult).(*ctypes.ResultABCIQuery) if !res.Response.Code.IsOK() { - return nil, errors.New(cmn.Fmt("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)) + return nil, errors.New(fmt.Sprintf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)) } return &res.Response, nil } @@ -79,28 +134,27 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) { accountBytes := response.Value if len(accountBytes) == 0 { - return nil, errors.New(cmn.Fmt("Account bytes are empty for address: %X ", address)) + return nil, errors.New(fmt.Sprintf("Account bytes are empty for address: %X ", address)) } var acc *types.Account err = wire.ReadBinaryBytes(accountBytes, &acc) if err != nil { - return nil, errors.New(cmn.Fmt("Error reading account %X error: %v", + return nil, errors.New(fmt.Sprintf("Error reading account %X error: %v", accountBytes, err.Error())) } return acc, nil } -func getHeaderAndCommit(c *cli.Context, height int) (*tmtypes.Header, *tmtypes.Commit, error) { +func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Commit, error) { tmResult := new(ctypes.TMResult) - tmAddr := c.String("node") uriClient := client.NewURIClient(tmAddr) method := "commit" _, err := uriClient.Call(method, map[string]interface{}{"height": height}, tmResult) if err != nil { - return nil, nil, errors.New(cmn.Fmt("Error on %s: %v", method, err)) + return nil, nil, errors.New(fmt.Sprintf("Error on %s: %v", method, err)) } resCommit := (*tmResult).(*ctypes.ResultCommit) header := resCommit.Header diff --git a/cmd/commands/version.go b/cmd/commands/version.go new file mode 100644 index 000000000..1cbf891e4 --- /dev/null +++ b/cmd/commands/version.go @@ -0,0 +1,17 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/tendermint/basecoin/version" +) + +var VersionCmd = &cobra.Command{ + Use: "version", + Short: "Show version info", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version.Version) + }, +} diff --git a/cmd/counter/cmd.go b/cmd/counter/cmd.go index c125feb4f..6b31e3fc6 100644 --- a/cmd/counter/cmd.go +++ b/cmd/counter/cmd.go @@ -3,46 +3,47 @@ package main import ( "fmt" + "github.com/spf13/cobra" wire "github.com/tendermint/go-wire" - "github.com/urfave/cli" "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, +} + +//flags +var ( + validFlag bool + countFeeFlag string ) func init() { + + CounterTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set valid field in CounterTx") + CounterTxCmd.Flags().StringVar(&countFeeFlag, "countfee", "", "Coins for the counter fee of the format ") + commands.RegisterTxSubcommand(CounterTxCmd) commands.RegisterStartPlugin("counter", func() types.Plugin { return counter.New() }) } -var ( - ValidFlag = cli.BoolFlag{ - Name: "valid", - Usage: "Set valid field in CounterTx", - } +func counterTxCmd(cmd *cobra.Command, args []string) { - CounterTxCmd = cli.Command{ - Name: "counter", - Usage: "Create, sign, and broadcast a transaction to the counter plugin", - Action: func(c *cli.Context) error { - return cmdCounterTx(c) - }, - Flags: append(commands.TxFlags, ValidFlag), + countFee, err := commands.ParseCoins(countFeeFlag) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } -) - -func cmdCounterTx(c *cli.Context) error { - valid := c.Bool("valid") counterTx := counter.CounterTx{ - Valid: valid, - Fee: types.Coins{ - { - Denom: c.String("coin"), - Amount: int64(c.Int("fee")), - }, - }, + Valid: validFlag, + Fee: countFee, } fmt.Println("CounterTx:", string(wire.JSONBytes(counterTx))) @@ -50,5 +51,5 @@ func cmdCounterTx(c *cli.Context) error { data := wire.BinaryBytes(counterTx) name := "counter" - return commands.AppTx(c, name, data) + commands.AppTx(name, data) } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 72395a9b0..fc5ad6b02 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -1,23 +1,34 @@ package main import ( + "fmt" "os" + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/cmd/commands" - "github.com/urfave/cli" ) func main() { - app := cli.NewApp() - app.Name = "counter" - app.Usage = "counter [command] [args...]" - app.Version = "0.1.0" - app.Commands = []cli.Command{ + + var RootCmd = &cobra.Command{ + Use: "counter", + Short: "demo plugin for basecoin", + } + + RootCmd.AddCommand( commands.StartCmd, commands.TxCmd, - commands.KeyCmd, commands.QueryCmd, + commands.KeyCmd, + commands.VerifyCmd, + commands.BlockCmd, commands.AccountCmd, + commands.QuickVersionCmd("0.1.0"), + ) + + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - app.Run(os.Args) } diff --git a/demo/start.sh b/demo/start.sh index af91db2a0..d7d9659dc 100644 --- a/demo/start.sh +++ b/demo/start.sh @@ -103,14 +103,14 @@ sleep 3 echo "... registering chain1 on chain2" echo "" # register chain1 on chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json +basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --ibc_chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json echo "" echo "... creating egress packet on chain1" echo "" # create a packet on chain1 destined for chain2 PAYLOAD="DEADBEEF" #TODO -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --sequence 1 +basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --ibc_from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --ibc_sequence 1 echo "" echo "... querying for packet data" @@ -162,7 +162,7 @@ echo "" echo "... posting packet from chain1 on chain2" echo "" # post the packet from chain1 to chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF +basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --ibc_from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF echo "" echo "... checking if the packet is present on chain2" diff --git a/docs/guide/example-plugin.md b/docs/guide/example-plugin.md index 31aa3479c..312f3ac23 100644 --- a/docs/guide/example-plugin.md +++ b/docs/guide/example-plugin.md @@ -25,18 +25,30 @@ The `main.go` is very simple and does not need to be changed: ```golang func main() { - app := cli.NewApp() - app.Name = "example-plugin" - app.Usage = "example-plugin [command] [args...]" - app.Version = "0.1.0" - app.Commands = []cli.Command{ + //Initialize example-plugin root command + var RootCmd = &cobra.Command{ + Use: "example-plugin", + Short: "example-plugin usage description", + } + + //Add the default basecoin commands to the root command + RootCmd.AddCommand( + commands.InitCmd, commands.StartCmd, commands.TxCmd, - commands.KeyCmd, commands.QueryCmd, + commands.KeyCmd, + commands.VerifyCmd, + commands.BlockCmd, commands.AccountCmd, + commands.UnsafeResetAllCmd, + ) + + //Run the root command + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - app.Run(os.Args) } ``` @@ -49,19 +61,40 @@ This is where the `cmd.go` comes in. ### cmd.go -First, we register the plugin: +First we define the new command and associated flag variables +```golang +var ( + //CLI Flags + validFlag bool + + //CLI Plugin Commands + ExamplePluginTxCmd = &cobra.Command{ + Use: "example", + Short: "Create, sign, and broadcast a transaction to the example plugin", + Run: examplePluginTxCmd, + } +) +``` + +Next we register the plugin: ```golang func init() { + + //Set the Plugin Flags + ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid") + + //Register a plugin specific CLI command as a subcommand of the tx command commands.RegisterTxSubcommand(ExamplePluginTxCmd) + + //Register the example with basecoin at start commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() }) } ``` This creates a new subcommand under `tx` (defined below), and ensures the plugin is activated when we start the app. -Now we actually define the new command: ```golang var ( diff --git a/docs/guide/src/example-plugin/cmd.go b/docs/guide/src/example-plugin/cmd.go index 6d7c29a79..51077d06f 100644 --- a/docs/guide/src/example-plugin/cmd.go +++ b/docs/guide/src/example-plugin/cmd.go @@ -1,16 +1,32 @@ package main import ( + "github.com/spf13/cobra" + wire "github.com/tendermint/go-wire" - "github.com/urfave/cli" "github.com/tendermint/basecoin/cmd/commands" "github.com/tendermint/basecoin/types" ) +var ( + //CLI Flags + validFlag bool + + //CLI Plugin Commands + ExamplePluginTxCmd = &cobra.Command{ + Use: "example", + Short: "Create, sign, and broadcast a transaction to the example plugin", + Run: examplePluginTxCmd, + } +) + //Called during CLI initialization func init() { + //Set the Plugin Flags + ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid") + //Register a plugin specific CLI command as a subcommand of the tx command commands.RegisterTxSubcommand(ExamplePluginTxCmd) @@ -18,32 +34,12 @@ func init() { commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() }) } -var ( - //CLI Flags - ExampleFlag = cli.BoolFlag{ - Name: "valid", - Usage: "Set this to make the transaction valid", - } - - //CLI Plugin Commands - ExamplePluginTxCmd = cli.Command{ - Name: "example", - Usage: "Create, sign, and broadcast a transaction to the example plugin", - Action: func(c *cli.Context) error { - return cmdExamplePluginTx(c) - }, - Flags: append(commands.TxFlags, ExampleFlag), - } -) - //Send a transaction -func cmdExamplePluginTx(c *cli.Context) error { - //Retrieve any flag results - exampleFlag := c.Bool("valid") +func examplePluginTxCmd(cmd *cobra.Command, args []string) { // Create a transaction using the flag. // The tx passes on custom information to the plugin - exampleTx := ExamplePluginTx{exampleFlag} + exampleTx := ExamplePluginTx{validFlag} // The tx is passed to the plugin in the form of // a byte array. This is achieved by serializing the object using go-wire. @@ -62,5 +58,5 @@ func cmdExamplePluginTx(c *cli.Context) error { // - 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 - return commands.AppTx(c, "example-plugin", exampleTxBytes) + commands.AppTx("example-plugin", exampleTxBytes) } diff --git a/docs/guide/src/example-plugin/main.go b/docs/guide/src/example-plugin/main.go index d8cc38a95..3a2984b60 100644 --- a/docs/guide/src/example-plugin/main.go +++ b/docs/guide/src/example-plugin/main.go @@ -1,24 +1,38 @@ package main import ( + "fmt" "os" + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/cmd/commands" - "github.com/urfave/cli" ) func main() { - //Initialize an instance of basecoin with default basecoin commands - app := cli.NewApp() - app.Name = "example-plugin" - app.Usage = "example-plugin [command] [args...]" - app.Version = "0.1.0" - app.Commands = []cli.Command{ + + //Initialize example-plugin root command + var RootCmd = &cobra.Command{ + Use: "example-plugin", + Short: "example-plugin usage description", + } + + //Add the default basecoin commands to the root command + RootCmd.AddCommand( + commands.InitCmd, commands.StartCmd, commands.TxCmd, - commands.KeyCmd, commands.QueryCmd, + commands.KeyCmd, + commands.VerifyCmd, + commands.BlockCmd, commands.AccountCmd, + commands.UnsafeResetAllCmd, + ) + + //Run the root command + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - app.Run(os.Args) } diff --git a/glide.lock b/glide.lock index 38755f1a6..eedcffdcc 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c023dbd97e1ea0a525e33738f03afd6be61f997f1c2592a5d9928fdcecc71361 -updated: 2017-04-21T17:38:13.194966906+02:00 +hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600 +updated: 2017-04-13T18:07:44.07521907-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -19,6 +19,8 @@ imports: version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 +- name: github.com/inconshreveable/mousetrap + version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable @@ -26,7 +28,11 @@ imports: - name: github.com/mattn/go-isatty version: 57fdcb988a5c543893cc61bce354a6e24ab70022 - name: github.com/pkg/errors - version: bfd5150e4e41705ded2129ec33379de1cb90b513 + version: 645ef00459ed84a119197bfb8d8205042c6df63d +- name: github.com/spf13/cobra + version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c +- name: github.com/spf13/pflag + version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 - name: github.com/syndtr/goleveldb version: 3c5717caf1475fd25964109a0fc640bd150fce43 subpackages: @@ -43,7 +49,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998 + version: af792eac777de757cd496349a5f6b5313738fcbc subpackages: - client - example/dummy @@ -59,11 +65,11 @@ imports: - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: f9e3db037330c8a8d61d3966de8473eaf01154fa + version: dcb015dff6c7af21e65c8e2f3b450df19d38c777 - name: github.com/tendermint/go-config version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da + version: 3f47cfac5fcd9e0f1727c7db980b3559913b3e3a - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db @@ -83,13 +89,13 @@ imports: subpackages: - upnp - name: github.com/tendermint/go-rpc - version: 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6 + version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: c1c9a57ab8038448ddea1714c0698f8051e5748c + version: f530b7af7a8b06e612c2063bff6ace49060a085e - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -100,9 +106,10 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: 7cf773e2d37b2b5a08bc94fb125cfd346b834824 + version: 022a5509181a19f78995a3dd9bba470333fe2d63 subpackages: - blockchain + - cmd/tendermint/commands - config/tendermint - consensus - mempool @@ -117,8 +124,6 @@ imports: - state/txindex/null - types - version -- name: github.com/urfave/cli - version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/crypto version: 728b753d0135da6801d45a38e6f43ff55779c5c2 subpackages: diff --git a/glide.yaml b/glide.yaml index ecf4f151b..420cc1ceb 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,22 +1,24 @@ package: github.com/tendermint/basecoin import: - package: github.com/tendermint/go-common - version: develop + version: master - package: github.com/tendermint/go-crypto - version: develop + version: master - package: github.com/tendermint/go-events - version: develop + version: master - package: github.com/tendermint/go-logger - version: develop + version: master +- package: github.com/tendermint/go-data + version: master - package: github.com/tendermint/go-rpc - version: develop + version: master - package: github.com/tendermint/go-wire - version: develop + version: master - package: github.com/tendermint/merkleeyes - version: develop + version: master - package: github.com/tendermint/tendermint - version: develop + version: cli_change - package: github.com/tendermint/abci - version: develop + version: master - package: github.com/gorilla/websocket version: v1.1.0 From 6eb511670f7251c201357fc6e68b0c3b60f74274 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 30 Mar 2017 01:30:55 -0400 Subject: [PATCH 02/13] cmd init cleanup --- cmd/commands/init.go | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 99bff657c..7b89b6b79 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -3,6 +3,7 @@ package commands import ( "fmt" "io/ioutil" + "os" "path" "github.com/spf13/cobra" @@ -43,27 +44,31 @@ func initCmd(cmd *cobra.Command, args []string) { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + if _, err := os.Stat(privValFile); os.IsNotExist(err) { + err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) + log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) + } else { + log.Notice("Already initialized", "priv_validator", privValFile) + } } const privValJSON = `{ From 18f1142d4ca7b077c07ae83864f539a4a79debac Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 30 Mar 2017 01:59:46 -0400 Subject: [PATCH 03/13] v0.4.0 int --- CHANGELOG.md | 10 ++++++++++ cmd/commands/init.go | 13 ------------- version/version.go | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 927c2f688..1d01ce65e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.4.0 (March 30, 2017) + +BREAKING CHANGES: + +- CLI now uses Cobra + +IMPROVEMENTS: + +- `basecoin init` doesn't generate error if already initialized + ## 0.3.1 (March 23, 2017) IMPROVEMENTS: diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 7b89b6b79..e938ccb2c 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -20,19 +20,6 @@ var ( } ) -//flags -//var chainIDFlag string - -//func init() { -// -// //register flags -// flags := []Flag2Register{ -// {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, -// } -// RegisterFlags(InitCmd, flags) -// -//} - func initCmd(cmd *cobra.Command, args []string) { rootDir := BasecoinRoot("") diff --git a/version/version.go b/version/version.go index 770886758..ae549d083 100644 --- a/version/version.go +++ b/version/version.go @@ -1,7 +1,7 @@ package version const Maj = "0" -const Min = "3" -const Fix = "1" +const Min = "4" +const Fix = "0" const Version = Maj + "." + Min + "." + Fix From 02b4fd5f1768cce1c4d527a9a1ee2373576c1f71 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 1 Apr 2017 15:49:56 -0400 Subject: [PATCH 04/13] doc update --- cmd/commands/key.go | 1 + cmd/commands/tx.go | 10 +- docs/guide/example-plugin.md | 194 ++++++++++++++++------------------- docs/guide/plugin-design.md | 4 +- 4 files changed, 99 insertions(+), 110 deletions(-) diff --git a/cmd/commands/key.go b/cmd/commands/key.go index a79ca92f1..a1cec50d1 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -31,6 +31,7 @@ var ( func newKeyCmd(cmd *cobra.Command, args []string) { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") + fmt.Println(&key) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 95358221f..e7381b087 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -36,18 +36,20 @@ var ( } ) -//flags var ( + //persistent flags txNodeFlag string - toFlag string amountFlag string fromFlag string seqFlag int gasFlag int feeFlag string - dataFlag string - nameFlag string chainIDFlag string + + //non-persistent flags + toFlag string + dataFlag string + nameFlag string ) func init() { diff --git a/docs/guide/example-plugin.md b/docs/guide/example-plugin.md index 312f3ac23..d9e3a3255 100644 --- a/docs/guide/example-plugin.md +++ b/docs/guide/example-plugin.md @@ -6,10 +6,11 @@ Here, we will demonstrate how to extend the blockchain and CLI to support a simp ## Overview -Creating a new plugin and CLI to support it requires a little bit of boilerplate, but not much. -For convenience, we've implemented an extremely simple example plugin that can be easily modified. -The example is under `docs/guide/src/example-plugin`. -To build your own plugin, copy this folder to a new location and start modifying it there. +Creating a new plugin and CLI to support it requires a little bit of +boilerplate, but not much. For convenience, we've implemented an extremely +simple example plugin that can be easily modified. The example is under +`docs/guide/src/example-plugin`. To build your own plugin, copy this folder to +a new location and start modifying it there. Let's take a look at the files in `docs/guide/src/example-plugin`: @@ -52,16 +53,14 @@ func main() { } ``` -It creates the CLI, exactly like the `basecoin` one. -However, if we want our plugin to be active, -we need to make sure it is registered with the application. -In addition, if we want to send transactions to our plugin, -we need to add a new command to the CLI. -This is where the `cmd.go` comes in. +It creates the CLI, exactly like the `basecoin` one. However, if we want our +plugin to be active, we need to make sure it is registered with the +application. In addition, if we want to send transactions to our plugin, we +need to add a new command to the CLI. This is where the `cmd.go` comes in. ### cmd.go -First we define the new command and associated flag variables +First we define the new CLI command and associated flag variables. ```golang var ( @@ -77,7 +76,10 @@ var ( ) ``` -Next we register the plugin: +Next within the `init` function we register our plugin's flags and register our +custom plugin command with the root command. This creates a new subcommand +under `tx` (defined below), and ensures the plugin is activated when we start +the app. ```golang func init() { @@ -93,59 +95,38 @@ func init() { } ``` -This creates a new subcommand under `tx` (defined below), -and ensures the plugin is activated when we start the app. +We now define the actual function which is called by our CLI command. + +```golang +func examplePluginTxCmd(cmd *cobra.Command, args []string) { + exampleTx := ExamplePluginTx{validFlag} + exampleTxBytes := wire.BinaryBytes(exampleTx) + commands.AppTx("example-plugin", exampleTxBytes) +} +``` + +Our function is a simple command with one boolean flag. However, it actually +inherits the persistent flags from the Basecoin framework. These persistent +flags use pointers to these variables stored in `cmd/commands/tx.go`: ```golang var ( - ExampleFlag = cli.BoolFlag{ - Name: "valid", - Usage: "Set this to make the transaction valid", - } - - ExamplePluginTxCmd = cli.Command{ - Name: "example", - Usage: "Create, sign, and broadcast a transaction to the example plugin", - Action: func(c *cli.Context) error { - return cmdExamplePluginTx(c) - }, - Flags: append(commands.TxFlags, ExampleFlag), - } + //persistent flags + txNodeFlag string + amountFlag string + fromFlag string + seqFlag int + gasFlag int + feeFlag string + chainIDFlag string + + //non-persistent flags + toFlag string + dataFlag string + nameFlag string ) - -func cmdExamplePluginTx(c *cli.Context) error { - exampleFlag := c.Bool("valid") - exampleTx := ExamplePluginTx{exampleFlag} - return commands.AppTx(c, "example-plugin", wire.BinaryBytes(exampleTx)) -} ``` -It's a simple command with one flag, which is just a boolean. -However, it actually inherits more flags from the Basecoin framework: - -```golang -Flags: append(commands.TxFlags, ExampleFlag), -``` - -The `commands.TxFlags` is defined in `cmd/commands/tx.go`: - -```golang -var TxFlags = []cli.Flag{ - NodeFlag, - ChainIDFlag, - - FromFlag, - - AmountFlag, - CoinFlag, - GasFlag, - FeeFlag, - SeqFlag, -} -``` - -It adds all the default flags for a Basecoin transaction. - If we now compile and run our program, we can see all the options: ``` @@ -157,48 +138,51 @@ example-plugin tx example --help The output: ``` -NAME: - example-plugin tx example - Create, sign, and broadcast a transaction to the example plugin +Create, sign, and broadcast a transaction to the example plugin -USAGE: - example-plugin tx example [command options] [arguments...] +Usage: + example-plugin tx example [flags] -OPTIONS: - --node value Tendermint RPC address (default: "tcp://localhost:46657") - --chain_id value ID of the chain for replay protection (default: "test_chain_id") - --from value Path to a private key to sign the transaction (default: "key.json") - --amount value Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver) - --gas value The amount of gas for the transaction (default: 0) - --fee value Coins for the transaction fee of the format - --sequence value Sequence number for the account (default: 0) - --valid Set this to make the transaction valid +Flags: + --valid Set this to make transaction valid + +Global Flags: + --amount string Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver}, + --chain_id string ID of the chain for replay protection (default "test_chain_id") + --fee string Coins for the transaction fee of the format + --from string Path to a private key to sign the transaction (default "key.json") + --gas int The amount of gas for the transaction + --node string Tendermint RPC address (default "tcp://localhost:46657") + --sequence int Sequence number for the account (-1 to autocalculate}, (default -1) ``` Cool, eh? -Before we move on to `plugin.go`, let's look at the `cmdExamplePluginTx` function in `cmd.go`: +Before we move on to `plugin.go`, let's look at the `examplePluginTxCmd` +function in `cmd.go`: ```golang -func cmdExamplePluginTx(c *cli.Context) error { - exampleFlag := c.Bool("valid") - exampleTx := ExamplePluginTx{exampleFlag} - return commands.AppTx(c, "example-plugin", wire.BinaryBytes(exampleTx)) +func examplePluginTxCmd(cmd *cobra.Command, args []string) { + exampleTx := ExamplePluginTx{validFlag} + exampleTxBytes := wire.BinaryBytes(exampleTx) + commands.AppTx("example-plugin", exampleTxBytes) } ``` We read the flag from the CLI library, and then create the example transaction. -Remember that Basecoin itself only knows about two transaction types, `SendTx` and `AppTx`. -All plugin data must be serialized (ie. encoded as a byte-array) -and sent as data in an `AppTx`. The `commands.AppTx` function does this for us - -it creates an `AppTx` with the corresponding data, signs it, and sends it on to the blockchain. +Remember that Basecoin itself only knows about two transaction types, `SendTx` +and `AppTx`. All plugin data must be serialized (ie. encoded as a byte-array) +and sent as data in an `AppTx`. The `commands.AppTx` function does this for us +- it creates an `AppTx` with the corresponding data, signs it, and sends it on +to the blockchain. ### plugin.go -Ok, now we're ready to actually look at the implementation of the plugin in `plugin.go`. -Note I'll leave out some of the methods as they don't serve any purpose for this example, -but are necessary boilerplate. -Your plugin may have additional requirements that utilize these other methods. -Here's what's relevant for us: +Ok, now we're ready to actually look at the implementation of the plugin in +`plugin.go`. Note I'll leave out some of the methods as they don't serve any +purpose for this example, but are necessary boilerplate. Your plugin may have +additional requirements that utilize these other methods. Here's what's +relevant for us: ```golang type ExamplePluginState struct { @@ -232,15 +216,17 @@ func (ep *ExamplePlugin) SetOption(store types.KVStore, key string, value string } func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txBytes []byte) (res abci.Result) { - - // Decode tx + + // Decode txBytes using go-wire. Attempt to write the txBytes to the variable + // tx, if the txBytes have not been properly encoded from a ExamplePluginTx + // struct wire will produce an error. var tx ExamplePluginTx err := wire.ReadBinaryBytes(txBytes, &tx) if err != nil { return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error()) } - // Validate tx + // Perform Transaction Validation if !tx.Valid { return abci.ErrInternalError.AppendLog("Valid must be true") } @@ -248,8 +234,10 @@ func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txByt // Load PluginState var pluginState ExamplePluginState stateBytes := store.Get(ep.StateKey()) + // If the state does not exist, stateBytes will be initialized + // as an empty byte array with length of zero if len(stateBytes) > 0 { - err = wire.ReadBinaryBytes(stateBytes, &pluginState) + err = wire.ReadBinaryBytes(stateBytes, &pluginState) //decode using go-wire if err != nil { return abci.ErrInternalError.AppendLog("Error decoding state: " + err.Error()) } @@ -266,12 +254,11 @@ func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txByt ``` All we're doing here is defining a state and transaction type for our plugin, -and then using the `RunTx` method to define how the transaction updates the state. -Let's break down `RunTx` in parts. First, we deserialize the transaction: - +and then using the `RunTx` method to define how the transaction updates the +state. Let's break down `RunTx` in parts. First, we deserialize the +transaction: ```golang -// Decode tx var tx ExamplePluginTx err := wire.ReadBinaryBytes(txBytes, &tx) if err != nil { @@ -279,27 +266,26 @@ if err != nil { } ``` -The transaction is expected to be serialized according to Tendermint's "wire" format, -as defined in the `github.com/tendermint/go-wire` package. -If it's not encoded properly, we return an error. +The transaction is expected to be serialized according to Tendermint's "wire" +format, as defined in the `github.com/tendermint/go-wire` package. If it's not +encoded properly, we return an error. If the transaction deserializes correctly, we can now check if it's valid: ```golang -// Validate tx if !tx.Valid { return abci.ErrInternalError.AppendLog("Valid must be true") } ``` -The transaction is valid if the `Valid` field is set, otherwise it's not - simple as that. -Finally, we can update the state. In this example, the state simply counts how many valid transactions -we've processed. But the state itself is serialized and kept in some `store`, which is typically a Merkle tree. -So first we have to load the state from the store and deserialize it: +The transaction is valid if the `Valid` field is set, otherwise it's not - +simple as that. Finally, we can update the state. In this example, the state +simply counts how many valid transactions we've processed. But the state itself +is serialized and kept in some `store`, which is typically a Merkle tree. So +first we have to load the state from the store and deserialize it: ```golang -// Load PluginState var pluginState ExamplePluginState stateBytes := store.Get(ep.StateKey()) if len(stateBytes) > 0 { @@ -402,5 +388,5 @@ basecoin CLI to activate the plugin on the blockchain and to send transactions t Hopefully by now you have some ideas for your own plugin, and feel comfortable implementing them. In the [next tutorial](more-examples.md), we tour through some other plugin examples, -adding features for minting new coins, voting, and changing the Tendermint validator set. +addin mple-plugin query ExamplePlugin.Statefeatures for minting new coins, voting, and changing the Tendermint validator set. But first, you may want to learn a bit more about [the design of the plugin system](plugin-design.md) diff --git a/docs/guide/plugin-design.md b/docs/guide/plugin-design.md index f59ce736c..e8e7dc92f 100644 --- a/docs/guide/plugin-design.md +++ b/docs/guide/plugin-design.md @@ -43,8 +43,8 @@ type Plugin interface { // Other ABCI message handlers SetOption(store KVStore, key string, value string) (log string) InitChain(store KVStore, vals []*abci.Validator) - BeginBlock(store KVStore, height uint64) - EndBlock(store KVStore, height uint64) []*abci.Validator + BeginBlock(store KVStore, hash []byte, header *abci.Header) + EndBlock(store KVStore, height uint64) (res abci.ResponseEndBlock) } type CallContext struct { From b60845c81812be8307960eb994f7128012db7a86 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 1 Apr 2017 17:31:44 -0400 Subject: [PATCH 05/13] BCHOME default dir change int int int int --- app/app.go | 12 ++++++------ app/genesis_test.go | 27 ++++++++++++++++++++++++++- cmd/commands/init.go | 16 ++++++++-------- cmd/commands/utils.go | 6 +++++- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/app/app.go b/app/app.go index f8cc5b739..fe1773669 100644 --- a/app/app.go +++ b/app/app.go @@ -5,17 +5,17 @@ import ( "strings" abci "github.com/tendermint/abci/types" - sm "github.com/tendermint/basecoin/state" - "github.com/tendermint/basecoin/types" . "github.com/tendermint/go-common" "github.com/tendermint/go-wire" eyes "github.com/tendermint/merkleeyes/client" + + sm "github.com/tendermint/basecoin/state" + "github.com/tendermint/basecoin/types" + "github.com/tendermint/basecoin/version" ) const ( - version = "0.1" - maxTxSize = 10240 - + maxTxSize = 10240 PluginNameBase = "base" ) @@ -44,7 +44,7 @@ func (app *Basecoin) GetState() *sm.State { // ABCI::Info func (app *Basecoin) Info() abci.ResponseInfo { - return abci.ResponseInfo{Data: Fmt("Basecoin v%v", version)} + return abci.ResponseInfo{Data: Fmt("Basecoin v%v", version.Version)} } func (app *Basecoin) RegisterPlugin(plugin types.Plugin) { diff --git a/app/genesis_test.go b/app/genesis_test.go index 90f61e152..74ca22e61 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -2,20 +2,24 @@ package app import ( "encoding/hex" + "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" eyescli "github.com/tendermint/merkleeyes/client" ) +const genesisFilepath = "./testdata/genesis.json" + func TestLoadGenesis(t *testing.T) { assert, require := assert.New(t), require.New(t) eyesCli := eyescli.NewLocalClient("", 0) app := NewBasecoin(eyesCli) - err := app.LoadGenesis("./testdata/genesis.json") + err := app.LoadGenesis(genesisFilepath) require.Nil(err, "%+v", err) // check the chain id @@ -41,3 +45,24 @@ func TestLoadGenesis(t *testing.T) { assert.EqualValues(pkbyte, epk[:]) } } + +func TestParseGenesisList(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + bytes, err := cmn.ReadFile(genesisFilepath) + require.Nil(err, "loading genesis file %+v", err) + + // the basecoin genesis go-data :) + genDoc := new(FullGenesisDoc) + err = json.Unmarshal(bytes, genDoc) + require.Nil(err, "unmarshaling genesis file %+v", err) + + pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions) + require.Nil(err, "%+v", err) + genDoc.AppOptions.pluginOptions = pluginOpts + + assert.Equal(genDoc.AppOptions.pluginOptions[0].Key, "plugin1/key1") + assert.Equal(genDoc.AppOptions.pluginOptions[1].Key, "plugin1/key2") + assert.Equal(genDoc.AppOptions.pluginOptions[0].Value, "value1") + assert.Equal(genDoc.AppOptions.pluginOptions[1].Value, "value2") +} diff --git a/cmd/commands/init.go b/cmd/commands/init.go index e938ccb2c..05a76ef8a 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -32,22 +32,22 @@ func initCmd(cmd *cobra.Command, args []string) { key2File := path.Join(rootDir, "key2.json") if _, err := os.Stat(privValFile); os.IsNotExist(err) { - err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) + err := ioutil.WriteFile(genesisFile, []byte(GenesisJSON), 0644) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } - err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) + err = ioutil.WriteFile(privValFile, []byte(PrivValJSON), 0400) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } - err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) + err = ioutil.WriteFile(key1File, []byte(Key1JSON), 0400) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } - err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) + err = ioutil.WriteFile(key2File, []byte(Key2JSON), 0400) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } @@ -58,7 +58,7 @@ func initCmd(cmd *cobra.Command, args []string) { } } -const privValJSON = `{ +var PrivValJSON = `{ "address": "7A956FADD20D3A5B2375042B2959F8AB172A058F", "last_height": 0, "last_round": 0, @@ -75,7 +75,7 @@ const privValJSON = `{ ] }` -const genesisJSON = `{ +var GenesisJSON = `{ "app_hash": "", "chain_id": "test_chain_id", "genesis_time": "0001-01-01T00:00:00.000Z", @@ -105,7 +105,7 @@ const genesisJSON = `{ } }` -const key1JSON = `{ +var Key1JSON = `{ "address": "1B1BE55F969F54064628A63B9559E7C21C925165", "priv_key": { "type": "ed25519", @@ -117,7 +117,7 @@ const key1JSON = `{ } }` -const key2JSON = `{ +var Key2JSON = `{ "address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090", "priv_key": { "type": "ed25519", diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index f49bfe162..7f21be951 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -19,12 +19,16 @@ import ( tmtypes "github.com/tendermint/tendermint/types" ) +//This variable can be overwritten by plugin applications +// if they require a different working directory +var DefaultHome = "basecoin" + func BasecoinRoot(rootDir string) string { if rootDir == "" { rootDir = os.Getenv("BCHOME") } if rootDir == "" { - rootDir = os.Getenv("HOME") + "/.basecoin" + rootDir = os.Getenv("HOME") + "/." + DefaultHome } return rootDir } From 587461afa4a9d7d097b8421bea1deff77600eef5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 3 Apr 2017 10:44:30 +0200 Subject: [PATCH 06/13] Make initializing files more robust to some files existing --- cmd/commands/init.go | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 05a76ef8a..233a39087 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -20,6 +20,20 @@ var ( } ) +// 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 { + _, err := os.Stat(path) + if !os.IsNotExist(err) { + return 0 + } + err = ioutil.WriteFile(path, []byte(data), perm) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } + return 1 +} + func initCmd(cmd *cobra.Command, args []string) { rootDir := BasecoinRoot("") @@ -31,27 +45,12 @@ func initCmd(cmd *cobra.Command, args []string) { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - if _, err := os.Stat(privValFile); os.IsNotExist(err) { - err := ioutil.WriteFile(genesisFile, []byte(GenesisJSON), 0644) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } - - err = ioutil.WriteFile(privValFile, []byte(PrivValJSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } - - err = ioutil.WriteFile(key1File, []byte(Key1JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } - - err = ioutil.WriteFile(key2File, []byte(Key2JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + mod := setupFile(genesisFile, GenesisJSON, 0644) + + setupFile(privValFile, PrivValJSON, 0400) + + setupFile(key1File, Key1JSON, 0400) + + setupFile(key2File, Key2JSON, 0400) + if mod > 0 { log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) } else { log.Notice("Already initialized", "priv_validator", privValFile) From 5ebdd964c5dda6c53376d3506bc4d19458be6206 Mon Sep 17 00:00:00 2001 From: Rigel Rozanski Date: Thu, 13 Apr 2017 19:04:56 -0400 Subject: [PATCH 07/13] rebase updates/ rpc updates --- glide.lock | 4 ++-- tests/tendermint/main.go | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index eedcffdcc..0476397fe 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600 -updated: 2017-04-13T18:07:44.07521907-04:00 +updated: 2017-04-13T18:53:31.406195807-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -69,7 +69,7 @@ imports: - name: github.com/tendermint/go-config version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 3f47cfac5fcd9e0f1727c7db980b3559913b3e3a + version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index 605de6823..c486c64ab 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -72,7 +72,8 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) + 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) @@ -122,7 +123,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes) From c292d54e47c5d9164778e1c62f2931b0e21f7397 Mon Sep 17 00:00:00 2001 From: Rigel Rozanski Date: Sat, 15 Apr 2017 12:07:27 -0400 Subject: [PATCH 08/13] 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 bcb549301..5b37ab7fe 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 48fd4d6c2..1c817d5bd 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 233a39087..7308c7961 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 a1cec50d1..62be3c1d3 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 7e6e8de28..56ec683a1 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 f2841ea80..d1b4dfbbc 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 d14f663d1..e4fd5560c 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 e7381b087..1fd6be11c 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 7f21be951..18b856f4d 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 6b31e3fc6..cde1f0fd0 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 fc5ad6b02..8a96b50ed 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 d9e3a3255..a4592b355 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 9b88c416b..abbf0908f 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 51077d06f..b43917626 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 3a2984b60..e2892bd7d 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 0476397fe..e8ed38ebd 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 420cc1ceb..9d74f5a6b 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 d7570a0bd..689173a90 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 c486c64ab..73ace4ef8 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) From 04f79f3ad2b4aa82f6dafe2a69b6fdf0246d606a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 17 Apr 2017 19:59:22 -0400 Subject: [PATCH 09/13] cmd.SilenceUsage --- CHANGELOG.md | 4 ++-- cmd/commands/utils.go | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d01ce65e..b8014dd06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,10 @@ # Changelog -## 0.4.0 (March 30, 2017) +## 0.4.0 (TBD) BREAKING CHANGES: -- CLI now uses Cobra +- CLI now uses Cobra, which forced changes to some of the flag names and orderings IMPROVEMENTS: diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 18b856f4d..5dd9635fa 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -38,6 +38,7 @@ func BasecoinRoot(rootDir string) string { func ExecuteWithDebug(RootCmd *cobra.Command) { var debug bool + RootCmd.SilenceUsage = true 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, From 6da5f72de93d5b407bc2c4966b2f42b8b8abd419 Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Mon, 17 Apr 2017 21:28:03 -0400 Subject: [PATCH 10/13] tiny fixes --- cmd/commands/ibc.go | 2 +- cmd/commands/init.go | 3 +-- cmd/commands/key.go | 1 - cmd/commands/query.go | 3 +++ cmd/commands/start.go | 7 ++----- cmd/commands/tx.go | 4 ++-- cmd/commands/utils.go | 16 ++++++++++++++-- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 1c817d5bd..8b0938826 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -91,7 +91,7 @@ func init() { packetCreateFlags := []Flag2Register{ fromFlagReg, {&ibcToFlag, "to", "", "Destination ChainID"}, - {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin},"}, + {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin)"}, {&ibcPayloadFlag, "payload", "", "IBC packet payload"}, {&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"}, } diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 7308c7961..68b2ab389 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -19,11 +19,10 @@ var ( } ) -// 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, error) { _, err := os.Stat(path) - if !os.IsNotExist(err) { + if !os.IsNotExist(err) { //permission errors generated if use os.IsExist return 0, nil } err = ioutil.WriteFile(path, []byte(data), perm) diff --git a/cmd/commands/key.go b/cmd/commands/key.go index 62be3c1d3..91678f625 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -31,7 +31,6 @@ var ( func newKeyCmd(cmd *cobra.Command, args []string) error { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") - fmt.Println(&key) if err != nil { return err } diff --git a/cmd/commands/query.go b/cmd/commands/query.go index 56ec683a1..f73ed0ada 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -198,6 +198,9 @@ func verifyCmd(cmd *cobra.Command, args []string) error { } proofBytes, err := hex.DecodeString(StripHex(proofFlag)) + if err != nil { + return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofBytes, err) + } proof, err := merkle.ReadProof(proofBytes) if err != nil { diff --git a/cmd/commands/start.go b/cmd/commands/start.go index e4fd5560c..4578738ce 100644 --- a/cmd/commands/start.go +++ b/cmd/commands/start.go @@ -43,12 +43,9 @@ 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, "RunE Tendermint in-process with the App"}, + {&withoutTendermintFlag, "without-tendermint", false, "Run Tendermint in-process with the App"}, } RegisterFlags(StartCmd, flags) - - // TODO: move to config file - // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") } func startCmd(cmd *cobra.Command, args []string) error { @@ -134,7 +131,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error { _, err := n.Start() if err != nil { - return errors.Errorf("%v\n", err) + return err } // Wait forever diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 1fd6be11c..2e12be06e 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -58,10 +58,10 @@ func init() { {&txNodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, {&fromFlag, "from", "key.json", "Path to a private key to sign the transaction"}, - {&amountFlag, "amount", "", "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver},"}, + {&amountFlag, "amount", "", "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver)"}, {&gasFlag, "gas", 0, "The amount of gas for the transaction"}, {&feeFlag, "fee", "", "Coins for the transaction fee of the format "}, - {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate},"}, + {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate)"}, } sendTxFlags := []Flag2Register{ diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 5dd9635fa..7eea8cdeb 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -4,6 +4,10 @@ import ( "encoding/hex" "fmt" "os" + "path" + "regexp" + "strconv" + "strings" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -22,14 +26,14 @@ import ( //This variable can be overwritten by plugin applications // if they require a different working directory -var DefaultHome = "basecoin" +var DefaultHome = ".basecoin" func BasecoinRoot(rootDir string) string { if rootDir == "" { rootDir = os.Getenv("BCHOME") } if rootDir == "" { - rootDir = os.Getenv("HOME") + "/." + DefaultHome + rootDir = path.Join(os.Getenv("HOME"), DefaultHome) } return rootDir } @@ -48,6 +52,14 @@ func ExecuteWithDebug(RootCmd *cobra.Command) { } } +//Quickly registering flags can be quickly achieved through using the utility functions +//RegisterFlags, and RegisterPersistentFlags. Ex: +// flags := []Flag2Register{ +// {&myStringFlag, "mystringflag", "foobar", "description of what this flag does"}, +// {&myBoolFlag, "myboolflag", false, "description of what this flag does"}, +// {&myInt64Flag, "myintflag", 333, "description of what this flag does"}, +// } +// RegisterFlags(MyCobraCmd, flags) type Flag2Register struct { Pointer interface{} Use string From 55e4cf17fd5692e4c612f8da0dbdcf435a2cf482 Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Tue, 18 Apr 2017 02:50:23 -0400 Subject: [PATCH 11/13] minor fix x2 --- cmd/commands/init.go | 2 +- cmd/commands/query.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 68b2ab389..f7fae72e6 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -22,7 +22,7 @@ var ( // returns 1 iff it set a file, otherwise 0 (so we can add them) func setupFile(path, data string, perm os.FileMode) (int, error) { _, err := os.Stat(path) - if !os.IsNotExist(err) { //permission errors generated if use os.IsExist + if !os.IsNotExist(err) { //note, os.IsExist(err) != !os.IsNotExist(err) return 0, nil } err = ioutil.WriteFile(path, []byte(data), perm) diff --git a/cmd/commands/query.go b/cmd/commands/query.go index f73ed0ada..7d79c2f1f 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -199,7 +199,7 @@ func verifyCmd(cmd *cobra.Command, args []string) error { proofBytes, err := hex.DecodeString(StripHex(proofFlag)) if err != nil { - return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofBytes, err) + return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofFlag, err) } proof, err := merkle.ReadProof(proofBytes) From 34fc383aef6a2510a45d1a09ac09362d8245cbed Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Tue, 18 Apr 2017 23:04:50 -0400 Subject: [PATCH 12/13] tendermint dep branch: cli_change -> viper --- glide.lock | 90 ++++++++++++++++++++++++++++++++++++++++-------------- glide.yaml | 2 +- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/glide.lock b/glide.lock index e8ed38ebd..366aee42a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,40 +1,72 @@ -hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600 -updated: 2017-04-13T18:53:31.406195807-04:00 +hash: a248393a241987824fbc93210d0d4c9202df819b2b015e9392d652393540cb19 +updated: 2017-04-18T23:03:02.314286469-04:00 imports: - name: github.com/btcsuite/btcd - version: 583684b21bfbde9b5fc4403916fd7c807feb0289 + version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - name: github.com/BurntSushi/toml version: e643e9ef00b049d75de26e61109c5ea01885cd21 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 +- name: github.com/fsnotify/fsnotify + version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317 + version: 2bba0603135d7d7f5cb73b2125beeda19c09f4ef subpackages: - proto + - ptypes/any - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 +- name: github.com/hashicorp/hcl + version: 630949a3c5fa3c613328e1b8256052cbc2327c9b + subpackages: + - hcl/ast + - hcl/parser + - hcl/scanner + - hcl/strconv + - hcl/token + - json/parser + - json/scanner + - json/token - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 +- name: github.com/magiconair/properties + version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable - version: a392f450ea64cee2b268dfaacdc2502b50a22b18 + version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty - version: 57fdcb988a5c543893cc61bce354a6e24ab70022 + version: fc9e8d8ef48496124e79ae0df75490096eccf6fe +- name: github.com/mitchellh/mapstructure + version: 53818660ed4955e899c0bcafa97299a388bd7c8e +- name: github.com/pelletier/go-buffruneio + version: c37440a7cf42ac63b919c752ca73a85067e05992 +- name: github.com/pelletier/go-toml + version: fe206efb84b2bc8e8cfafe6b4c1826622be969e3 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: ff09b135c25aae272398c51a07235b90a75aa4f0 +- name: github.com/spf13/afero + version: 9be650865eab0c12963d8753212f4f9c66cdcf12 + subpackages: + - mem +- name: github.com/spf13/cast + version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c + version: b6cb3958937245a12d4d7728be080a6c758f4136 +- name: github.com/spf13/jwalterweatherman + version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 - name: github.com/spf13/pflag - version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 + version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51 +- name: github.com/spf13/viper + version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/syndtr/goleveldb - version: 3c5717caf1475fd25964109a0fc640bd150fce43 + version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: - leveldb - leveldb/cache @@ -65,9 +97,7 @@ imports: - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: dcb015dff6c7af21e65c8e2f3b450df19d38c777 -- name: github.com/tendermint/go-config - version: 620dcbbd7d587cf3599dedbf329b64311b0c307a + version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data @@ -85,17 +115,17 @@ imports: - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: 17124989a93774833df33107fbf17157a7f8ef31 + version: 4e802b363bdd843a40b0905e9791663bda4b1284 subpackages: - upnp - name: github.com/tendermint/go-rpc - version: c3295f4878019ff3fdfcac37a4c0e4bcf4bb02a7 + version: 4671c44b2d124f7f6f6243dbfbf4ae2bf42ee809 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: f530b7af7a8b06e612c2063bff6ace49060a085e + version: c1c9a57ab8038448ddea1714c0698f8051e5748c - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -106,7 +136,7 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: 022a5509181a19f78995a3dd9bba470333fe2d63 + version: de8952dd2ba7fd4697658f1a0ffc50e8cb690f9a subpackages: - blockchain - cmd/tendermint/commands @@ -125,7 +155,7 @@ imports: - types - version - name: golang.org/x/crypto - version: 728b753d0135da6801d45a38e6f43ff55779c5c2 + version: 12c985af8526c1f6f0c463bbfd9d69623d13b323 subpackages: - curve25519 - nacl/box @@ -136,7 +166,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: a6577fac2d73be281a500b310739095313165611 + version: 5602c733f70afc6dcec6766be0d5034d4c4f14de subpackages: - context - http2 @@ -146,11 +176,22 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: 99f16d856c9836c42d24e7ab64ea72916925fa97 + version: f3918c30c5c2cb527c0b071a27c35120a6c0719a subpackages: - unix +- name: golang.org/x/text + version: f4b4367115ec2de254587813edaa901bc1c723a8 + subpackages: + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm +- name: google.golang.org/genproto + version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + subpackages: + - googleapis/rpc/status - name: google.golang.org/grpc - version: 0713829b980f4ddd276689a36235c5fcc82a21bf + version: 6914ab1e338c92da4218a23d27fcd03d0ad78d46 subpackages: - codes - credentials @@ -161,11 +202,14 @@ imports: - naming - peer - stats + - status - tap - transport +- name: gopkg.in/yaml.v2 + version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -173,7 +217,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 4d4bfba8f1d1027c4fdbe371823030df51419987 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index 9d74f5a6b..4396e8526 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,7 +17,7 @@ import: - package: github.com/tendermint/merkleeyes version: master - package: github.com/tendermint/tendermint - version: cli_change + version: viper - package: github.com/tendermint/abci version: master - package: github.com/gorilla/websocket From 9d620e449b84b08de935144610bab8b28e69785c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 12:56:50 -0400 Subject: [PATCH 13/13] glide update and rebase fixes --- cmd/commands/utils.go | 3 --- cmd/counter/cmd.go | 2 +- glide.lock | 63 +++++++++++-------------------------------- glide.yaml | 18 ++++++------- 4 files changed, 26 insertions(+), 60 deletions(-) diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 7eea8cdeb..0f263d82a 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -5,9 +5,6 @@ import ( "fmt" "os" "path" - "regexp" - "strconv" - "strings" "github.com/pkg/errors" "github.com/spf13/cobra" diff --git a/cmd/counter/cmd.go b/cmd/counter/cmd.go index cde1f0fd0..451f42a48 100644 --- a/cmd/counter/cmd.go +++ b/cmd/counter/cmd.go @@ -35,7 +35,7 @@ func init() { func counterTxCmd(cmd *cobra.Command, args []string) error { - countFee, err := commands.ParseCoins(countFeeFlag) + countFee, err := types.ParseCoins(countFeeFlag) if err != nil { return err } diff --git a/glide.lock b/glide.lock index 366aee42a..bc150cd7d 100644 --- a/glide.lock +++ b/glide.lock @@ -1,16 +1,14 @@ -hash: a248393a241987824fbc93210d0d4c9202df819b2b015e9392d652393540cb19 -updated: 2017-04-18T23:03:02.314286469-04:00 +hash: c6e5febc35b5fd1003066820defb8a089db048b407239dad9faf44553fdc15e8 +updated: 2017-04-21T12:55:42.7004558-04:00 imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - name: github.com/BurntSushi/toml - version: e643e9ef00b049d75de26e61109c5ea01885cd21 + version: b26d9c308763d68093482582cea63d69be07a0f0 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 -- name: github.com/fsnotify/fsnotify - version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf @@ -22,49 +20,20 @@ imports: version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 -- name: github.com/hashicorp/hcl - version: 630949a3c5fa3c613328e1b8256052cbc2327c9b - subpackages: - - hcl/ast - - hcl/parser - - hcl/scanner - - hcl/strconv - - hcl/token - - json/parser - - json/scanner - - json/token - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/magiconair/properties - version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty version: fc9e8d8ef48496124e79ae0df75490096eccf6fe -- name: github.com/mitchellh/mapstructure - version: 53818660ed4955e899c0bcafa97299a388bd7c8e -- name: github.com/pelletier/go-buffruneio - version: c37440a7cf42ac63b919c752ca73a85067e05992 -- name: github.com/pelletier/go-toml - version: fe206efb84b2bc8e8cfafe6b4c1826622be969e3 - name: github.com/pkg/errors version: ff09b135c25aae272398c51a07235b90a75aa4f0 -- name: github.com/spf13/afero - version: 9be650865eab0c12963d8753212f4f9c66cdcf12 - subpackages: - - mem -- name: github.com/spf13/cast - version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: b6cb3958937245a12d4d7728be080a6c758f4136 -- name: github.com/spf13/jwalterweatherman - version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 + version: 10f6b9d7e1631a54ad07c5c0fb71c28a1abfd3c2 - name: github.com/spf13/pflag version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51 -- name: github.com/spf13/viper - version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -81,7 +50,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: af792eac777de757cd496349a5f6b5313738fcbc + version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998 subpackages: - client - example/dummy @@ -98,6 +67,8 @@ imports: version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common version: f9e3db037330c8a8d61d3966de8473eaf01154fa +- name: github.com/tendermint/go-config + version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data @@ -115,11 +86,11 @@ imports: - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: 4e802b363bdd843a40b0905e9791663bda4b1284 + version: 17124989a93774833df33107fbf17157a7f8ef31 subpackages: - upnp - name: github.com/tendermint/go-rpc - version: 4671c44b2d124f7f6f6243dbfbf4ae2bf42ee809 + version: 559613689d56eaa423b19a3a4158546beb4857de subpackages: - client - server @@ -136,7 +107,7 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: de8952dd2ba7fd4697658f1a0ffc50e8cb690f9a + version: e8cad948e366cd1d0a9ebef642073f4ade9899e9 subpackages: - blockchain - cmd/tendermint/commands @@ -155,7 +126,7 @@ imports: - types - version - name: golang.org/x/crypto - version: 12c985af8526c1f6f0c463bbfd9d69623d13b323 + version: 96846453c37f0876340a66a47f3f75b1f3a6cd2d subpackages: - curve25519 - nacl/box @@ -166,7 +137,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 5602c733f70afc6dcec6766be0d5034d4c4f14de + version: c8c74377599bd978aee1cf3b9b63a8634051cec2 subpackages: - context - http2 @@ -176,11 +147,11 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: f3918c30c5c2cb527c0b071a27c35120a6c0719a + version: ea9bcade75cb975a0b9738936568ab388b845617 subpackages: - unix - name: golang.org/x/text - version: f4b4367115ec2de254587813edaa901bc1c723a8 + version: 19e3104b43db45fca0303f489a9536087b184802 subpackages: - secure/bidirule - transform @@ -205,11 +176,9 @@ imports: - status - tap - transport -- name: gopkg.in/yaml.v2 - version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: - name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -217,7 +186,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 4d4bfba8f1d1027c4fdbe371823030df51419987 + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index 4396e8526..87735c19c 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,24 +1,24 @@ package: github.com/tendermint/basecoin import: - package: github.com/tendermint/go-common - version: master + version: develop - package: github.com/tendermint/go-crypto - version: master + version: develop - package: github.com/tendermint/go-events - version: master + version: develop - package: github.com/tendermint/go-logger - version: master + version: develop - package: github.com/tendermint/go-data - version: master + version: develop - package: github.com/tendermint/go-rpc version: develop - package: github.com/tendermint/go-wire - version: master + version: develop - package: github.com/tendermint/merkleeyes - version: master + version: develop - package: github.com/tendermint/tendermint - version: viper + version: develop - package: github.com/tendermint/abci - version: master + version: develop - package: github.com/gorilla/websocket version: v1.1.0