added cli cobra

rebaseFixes

int

removed ExitOnErr

int

int

int

int

int

added uint64 to RegisterFlags
This commit is contained in:
rigelrozanski
2017-04-21 12:34:11 -04:00
committed by Ethan Buchman
parent c6e348e01b
commit fb3fd1b425
20 changed files with 716 additions and 726 deletions
+12 -10
View File
@@ -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)
}
-119
View File
@@ -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 <amt><coin>,<amt2><coin2>,... (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 <amt><coin>",
}
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: "",
}
)
+123 -178
View File
@@ -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
+39 -23
View File
@@ -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 = `{
+20 -18
View File
@@ -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
}
+41
View File
@@ -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)
},
}
}
+85 -90
View File
@@ -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: "<key>",
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: "<address>",
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: "<height>",
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
}
+8 -31
View File
@@ -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)
}
+44 -49
View File
@@ -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
}
+103 -100
View File
@@ -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 <amt><coin>,<amt2><coin2>,... (eg: 1btc,2gold,5silver},"},
{&gasFlag, "gas", 0, "The amount of gas for the transaction"},
{&feeFlag, "fee", "", "Coins for the transaction fee of the format <amt><coin>"},
{&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,
}
}
+64 -10
View File
@@ -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
+17
View File
@@ -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)
},
}
+26 -25
View File
@@ -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 <amt><coin>")
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)
}
+19 -8
View File
@@ -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)
}