From f8115028266cea72bfc222579662e90a2ff166ca Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 29 Jan 2017 15:32:38 -0800 Subject: [PATCH] cmd: counter tx --- app/app.go | 3 + cmd/basecoin/cmd.go | 98 ++++++++++++++++++++ cmd/basecoin/flags.go | 121 +++++++++++++++++++++++++ cmd/basecoin/main.go | 177 +------------------------------------ cmd/basecoin/start.go | 10 +++ cmd/basecoin/tx.go | 49 +++++++--- cmd/paytovote/main.go | 53 ----------- plugins/counter/counter.go | 2 +- 8 files changed, 275 insertions(+), 238 deletions(-) create mode 100644 cmd/basecoin/cmd.go create mode 100644 cmd/basecoin/flags.go delete mode 100644 cmd/paytovote/main.go diff --git a/app/app.go b/app/app.go index be618ae72..a6ad90424 100644 --- a/app/app.go +++ b/app/app.go @@ -1,6 +1,7 @@ package app import ( + "fmt" "strings" abci "github.com/tendermint/abci/types" @@ -102,6 +103,8 @@ func (app *Basecoin) CheckTx(txBytes []byte) (res abci.Result) { return abci.ErrBaseEncodingError.AppendLog("Tx size exceeds maximum") } + fmt.Printf("%X\n", txBytes) + // Decode tx var tx types.Tx err := wire.ReadBinaryBytes(txBytes, &tx) diff --git a/cmd/basecoin/cmd.go b/cmd/basecoin/cmd.go new file mode 100644 index 000000000..7fe5fb3db --- /dev/null +++ b/cmd/basecoin/cmd.go @@ -0,0 +1,98 @@ +package main + +import ( + "github.com/urfave/cli" +) + +var ( + startCmd = cli.Command{ + Name: "start", + Usage: "Start basecoin", + ArgsUsage: "", + Action: func(c *cli.Context) error { + return cmdStart(c) + }, + Flags: []cli.Flag{ + addrFlag, + eyesFlag, + eyesDBFlag, + genesisFlag, + inProcTMFlag, + chainIDFlag, + pluginFlag, + }, + } + + sendTxCmd = cli.Command{ + Name: "sendtx", + Usage: "Broadcast a basecoin SendTx", + ArgsUsage: "", + Action: func(c *cli.Context) error { + return cmdSendTx(c) + }, + Flags: []cli.Flag{ + tmAddrFlag, + chainIDFlag, + + fromFlag, + + amountFlag, + coinFlag, + gasFlag, + feeFlag, + seqFlag, + + toFlag, + }, + } + + appTxCmd = cli.Command{ + Name: "apptx", + Usage: "Broadcast a basecoin AppTx", + ArgsUsage: "", + Action: func(c *cli.Context) error { + return cmdAppTx(c) + }, + Flags: []cli.Flag{ + tmAddrFlag, + chainIDFlag, + + fromFlag, + + amountFlag, + coinFlag, + gasFlag, + feeFlag, + seqFlag, + + nameFlag, + dataFlag, + }, + Subcommands: []cli.Command{ + counterTxCmd, + }, + } + + counterTxCmd = cli.Command{ + Name: "counter", + Usage: "Craft a transaction to the counter plugin", + Action: func(c *cli.Context) error { + return cmdCounterTx(c) + }, + Flags: []cli.Flag{ + validFlag, + }, + } + + 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{ + tmAddrFlag, + }, + } +) diff --git a/cmd/basecoin/flags.go b/cmd/basecoin/flags.go new file mode 100644 index 000000000..c4b4c9f62 --- /dev/null +++ b/cmd/basecoin/flags.go @@ -0,0 +1,121 @@ +package main + +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", + } + + eyesDBFlag = cli.StringFlag{ + Name: "eyes-db", + Value: "merkleeyes.db", + Usage: "MerkleEyes db name for embedded", + } + + // TODO: move to config file + // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") + + genesisFlag = cli.StringFlag{ + Name: "genesis", + Value: "", + Usage: "Path to genesis file, if it exists", + } + + inProcTMFlag = cli.BoolFlag{ + Name: "in-proc", + Usage: "Run Tendermint in-process with the App", + } + + pluginFlag = cli.StringFlag{ + Name: "plugin", + Value: "counter", // load the counter by default + Usage: "Plugin to enable", + } +) + +// tx flags + +var ( + tmAddrFlag = cli.StringFlag{ + Name: "tendermint", + Value: "tcp://localhost:46657", + Usage: "Tendermint RPC address", + } + + toFlag = cli.StringFlag{ + Name: "to", + Value: "", + Usage: "Destination address for the transaction", + } + + amountFlag = cli.IntFlag{ + Name: "amount", + Value: 0, + Usage: "Amount of coins to send in the transaction", + } + + fromFlag = cli.StringFlag{ + Name: "from", + Value: "priv_validator.json", + Usage: "Path to a private key to sign the transaction", + } + + seqFlag = cli.IntFlag{ + Name: "sequence", + Value: 0, + Usage: "Sequence number for the account", + } + + coinFlag = cli.StringFlag{ + Name: "coin", + Value: "blank", + Usage: "Specify a coin denomination", + } + + gasFlag = cli.IntFlag{ + Name: "gas", + Value: 0, + Usage: "The amount of gas for the transaction", + } + + feeFlag = cli.IntFlag{ + Name: "fee", + Value: 0, + Usage: "The transaction fee", + } + + 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", + } + + validFlag = cli.BoolFlag{ + Name: "valid", + Usage: "Set valid field in CounterTx", + } +) diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index 741c94f1f..1fd2c79eb 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -6,185 +6,16 @@ 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", - } - - eyesDBFlag = cli.StringFlag{ - Name: "eyes-db", - Value: "merkleeyes.db", - Usage: "MerkleEyes db name for embedded", - } - - // TODO: move to config file - // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") - - genesisFlag = cli.StringFlag{ - Name: "genesis", - Value: "", - Usage: "Path to genesis file, if it exists", - } - - inProcTMFlag = cli.BoolFlag{ - Name: "in-proc", - Usage: "Run Tendermint in-process with the App", - } -) - -// tx flags - -var ( - tmAddrFlag = cli.StringFlag{ - Name: "tendermint", - Value: "tcp://localhost:46657", - Usage: "Tendermint RPC address", - } - - toFlag = cli.StringFlag{ - Name: "to", - Value: "", - Usage: "Destination address for the transaction", - } - - amountFlag = cli.IntFlag{ - Name: "amount", - Value: 0, - Usage: "Amount of coins to send in the transaction", - } - - fromFlag = cli.StringFlag{ - Name: "from", - Value: "priv_validator.json", - Usage: "Path to a private key to sign the transaction", - } - - seqFlag = cli.IntFlag{ - Name: "sequence", - Value: 0, - Usage: "Sequence number for the account", - } - - coinFlag = cli.StringFlag{ - Name: "coin", - Value: "blank", - Usage: "Specify a coin denomination", - } - - gasFlag = cli.IntFlag{ - Name: "gas", - Value: 0, - Usage: "The amount of gas for the transaction", - } - - feeFlag = cli.IntFlag{ - Name: "fee", - Value: 0, - Usage: "The transaction fee", - } - - 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", - } -) - func main() { app := cli.NewApp() app.Name = "basecoin" app.Usage = "basecoin [command] [args...]" app.Version = "0.1.0" app.Commands = []cli.Command{ - { - Name: "start", - Usage: "Start basecoin", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdStart(c) - }, - Flags: []cli.Flag{ - addrFlag, - eyesFlag, - eyesDBFlag, - genesisFlag, - inProcTMFlag, - chainIDFlag, - }, - }, - - { - Name: "sendtx", - Usage: "Broadcast a basecoin SendTx", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdSendTx(c) - }, - Flags: []cli.Flag{ - tmAddrFlag, - toFlag, - fromFlag, - amountFlag, - coinFlag, - gasFlag, - feeFlag, - chainIDFlag, - seqFlag, - }, - }, - - { - Name: "apptx", - Usage: "Broadcast a basecoin AppTx", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdAppTx(c) - }, - Flags: []cli.Flag{ - tmAddrFlag, - nameFlag, - fromFlag, - amountFlag, - coinFlag, - gasFlag, - feeFlag, - dataFlag, - seqFlag, - }, - }, - - { - Name: "account", - Usage: "Get details of an account", - ArgsUsage: "[address]", - Action: func(c *cli.Context) error { - return cmdAccount(c) - }, - Flags: []cli.Flag{ - tmAddrFlag, - }, - }, + startCmd, + sendTxCmd, + appTxCmd, + accountCmd, } app.Run(os.Args) } diff --git a/cmd/basecoin/start.go b/cmd/basecoin/start.go index 5d5c2de54..e483737a4 100644 --- a/cmd/basecoin/start.go +++ b/cmd/basecoin/start.go @@ -17,6 +17,7 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/tendermint/basecoin/app" + "github.com/tendermint/basecoin/plugins/counter" ) var config cfg.Config @@ -40,6 +41,15 @@ func cmdStart(c *cli.Context) error { // Create Basecoin app basecoinApp := app.NewBasecoin(eyesCli) + switch c.String("plugin") { + case "counter": + basecoinApp.RegisterPlugin(counter.New("counter")) + case "": + // no plugins to register + default: + return errors.New(cmn.Fmt("Unknown plugin: %v", c.String("plugin"))) + } + // If genesis file was specified, set key-value options if c.String("genesis") != "" { err := basecoinApp.LoadGenesis(c.String("genesis")) diff --git a/cmd/basecoin/tx.go b/cmd/basecoin/tx.go index 4b0bd8384..e80d1a77a 100644 --- a/cmd/basecoin/tx.go +++ b/cmd/basecoin/tx.go @@ -7,7 +7,9 @@ import ( "github.com/urfave/cli" + "github.com/tendermint/basecoin/plugins/counter" "github.com/tendermint/basecoin/types" + cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-wire" @@ -60,24 +62,26 @@ func cmdSendTx(c *cli.Context) error { if err := broadcastTx(c, tx); err != nil { return err } - return nil } func cmdAppTx(c *cli.Context) error { + // convert data to bytes + dataString := c.String("data") + data := []byte(dataString) + if isHex(dataString) { + data, _ = hex.DecodeString(dataString) + } name := c.String("name") + return appTx(c, name, data) +} + +func appTx(c *cli.Context, name string, data []byte) error { fromFile := c.String("from") amount := int64(c.Int("amount")) coin := c.String("coin") gas, fee := c.Int("gas"), int64(c.Int("fee")) chainID := c.String("chain_id") - dataString := c.String("data") - - // convert data to bytes - data := []byte(dataString) - if isHex(dataString) { - data, _ = hex.DecodeString(dataString) - } privVal := tmtypes.LoadPrivValidator(fromFile) @@ -107,16 +111,39 @@ func cmdAppTx(c *cli.Context) error { return nil } +func cmdCounterTx(c *cli.Context) error { + valid := c.Bool("valid") + parent := c.Parent() + + counterTx := counter.CounterTx{ + Valid: valid, + Fee: types.Coins{ + { + Denom: parent.String("coin"), + Amount: int64(parent.Int("fee")), + }, + }, + } + + fmt.Println("CounterTx:", string(wire.JSONBytes(counterTx))) + + data := wire.BinaryBytes(counterTx) + name := "counter" + + return appTx(parent, name, data) +} + // broadcast the transaction to tendermint func broadcastTx(c *cli.Context, tx types.Tx) error { tmResult := new(ctypes.TMResult) tmAddr := c.String("tendermint") clientURI := client.NewClientURI(tmAddr) - /*txBytes := []byte(wire.JSONBytes(struct { + // 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}))*/ - txBytes := wire.BinaryBytes(tx) + }{tx})) _, err := clientURI.Call("broadcast_tx_sync", map[string]interface{}{"tx": txBytes}, tmResult) if err != nil { return errors.New(cmn.Fmt("Error on broadcast tx: %v", err)) diff --git a/cmd/paytovote/main.go b/cmd/paytovote/main.go deleted file mode 100644 index 7c7715d99..000000000 --- a/cmd/paytovote/main.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "flag" - - "github.com/tendermint/abci/server" - "github.com/tendermint/basecoin/app" - "github.com/tendermint/basecoin/plugins/counter" - cmn "github.com/tendermint/go-common" - eyes "github.com/tendermint/merkleeyes/client" -) - -func main() { - addrPtr := flag.String("address", "tcp://0.0.0.0:46658", "Listen address") - eyesPtr := flag.String("eyes", "local", "MerkleEyes address, or 'local' for embedded") - genFilePath := flag.String("genesis", "", "Genesis file, if any") - flag.Parse() - - // Connect to MerkleEyes - eyesCli, err := eyes.NewClient(*eyesPtr) - if err != nil { - cmn.Exit("connect to MerkleEyes: " + err.Error()) - } - - // Create Basecoin app - app := app.NewBasecoin(eyesCli) - - // add plugins - // TODO: add some more, like the cool voting app - counter := counter.New("counter") - app.RegisterPlugin(counter) - - // If genesis file was specified, set key-value options - if *genFilePath != "" { - err := app.LoadGenesis(*genFilePath) - if err != nil { - cmn.Exit(cmn.Fmt("%+v", err)) - } - } - - // Start the listener - svr, err := server.NewServer(*addrPtr, "socket", app) - if err != nil { - cmn.Exit("create listener: " + err.Error()) - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - svr.Stop() - }) - -} diff --git a/plugins/counter/counter.go b/plugins/counter/counter.go index 8f3526818..9c115089b 100644 --- a/plugins/counter/counter.go +++ b/plugins/counter/counter.go @@ -47,7 +47,7 @@ func (cp *CounterPlugin) RunTx(store types.KVStore, ctx types.CallContext, txByt var tx CounterTx err := wire.ReadBinaryBytes(txBytes, &tx) if err != nil { - return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error()) + return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error()).PrependLog("CounterTx Error: ") } // Validate tx