diff --git a/Makefile b/Makefile index bd7d851fd7..d2ae8dcddd 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ test_unit: test_cli: tests/cli/shunit2 # sudo apt-get install jq @./tests/cli/basictx.sh - # @./tests/cli/counter.sh + @./tests/cli/counter.sh @./tests/cli/restart.sh # @./tests/cli/ibc.sh diff --git a/docs/guide/counter/cmd/counter/main.go b/docs/guide/counter/cmd/counter/main.go index 854cd0efe3..85dafc555e 100644 --- a/docs/guide/counter/cmd/counter/main.go +++ b/docs/guide/counter/cmd/counter/main.go @@ -7,10 +7,8 @@ import ( "github.com/tendermint/tmlibs/cli" - "github.com/tendermint/basecoin/app" "github.com/tendermint/basecoin/cmd/basecoin/commands" "github.com/tendermint/basecoin/docs/guide/counter/plugins/counter" - "github.com/tendermint/basecoin/types" ) func main() { @@ -20,7 +18,7 @@ func main() { } // TODO: register the counter here - commands.Handler = app.DefaultHandler() + commands.Handler = counter.NewCounterHandler() RootCmd.AddCommand( commands.InitCmd, @@ -29,7 +27,6 @@ func main() { commands.VersionCmd, ) - commands.RegisterStartPlugin("counter", func() types.Plugin { return counter.New() }) cmd := cli.PrepareMainCmd(RootCmd, "CT", os.ExpandEnv("$HOME/.counter")) cmd.Execute() } diff --git a/docs/guide/counter/cmd/countercli/commands/counter.go b/docs/guide/counter/cmd/countercli/commands/counter.go index 0481e3d065..3c388c8975 100644 --- a/docs/guide/counter/cmd/countercli/commands/counter.go +++ b/docs/guide/counter/cmd/countercli/commands/counter.go @@ -4,11 +4,12 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - wire "github.com/tendermint/go-wire" + "github.com/tendermint/basecoin" + "github.com/tendermint/light-client/commands" txcmd "github.com/tendermint/light-client/commands/txs" - bcmd "github.com/tendermint/basecoin/cmd/basecli/commands" "github.com/tendermint/basecoin/docs/guide/counter/plugins/counter" + "github.com/tendermint/basecoin/txs" btypes "github.com/tendermint/basecoin/types" ) @@ -20,64 +21,59 @@ var CounterTxCmd = &cobra.Command{ Long: `Add a vote to the counter. You must pass --valid for it to count and the countfee will be added to the counter.`, - RunE: counterTxCmd, + RunE: doCounterTx, } const ( - flagCountFee = "countfee" - flagValid = "valid" + FlagCountFee = "countfee" + FlagValid = "valid" + FlagSequence = "sequence" // FIXME: currently not supported... ) func init() { fs := CounterTxCmd.Flags() - bcmd.AddAppTxFlags(fs) - fs.String(flagCountFee, "", "Coins to send in the format ,...") - fs.Bool(flagValid, false, "Is count valid?") + fs.String(FlagCountFee, "", "Coins to send in the format ,...") + fs.Bool(FlagValid, false, "Is count valid?") + fs.Int(FlagSequence, -1, "Sequence number for this transaction") } -func counterTxCmd(cmd *cobra.Command, args []string) error { - // Note: we don't support loading apptx from json currently, so skip that - - // Read the app-specific flags - name, data, err := getAppData() +// TODO: doCounterTx is very similar to the sendtx one, +// maybe we can pull out some common patterns? +func doCounterTx(cmd *cobra.Command, args []string) error { + // load data from json or flags + var tx basecoin.Tx + found, err := txcmd.LoadJSON(&tx) + if err != nil { + return err + } + if !found { + tx, err = readCounterTxFlags() + } if err != nil { return err } - // Read the standard app-tx flags - gas, fee, txInput, err := bcmd.ReadAppTxFlags() - if err != nil { - return err - } + // TODO: make this more flexible for middleware + // add the chain info + tx = txs.NewChain(commands.GetChainID(), tx) + stx := txs.NewSig(tx) - // Create AppTx and broadcast - tx := &btypes.AppTx{ - Gas: gas, - Fee: fee, - Name: name, - Input: txInput, - Data: data, - } - res, err := bcmd.BroadcastAppTx(tx) + // Sign if needed and post. This it the work-horse + bres, err := txcmd.SignAndPostTx(stx) if err != nil { return err } // Output result - return txcmd.OutputTx(res) + return txcmd.OutputTx(bres) } -func getAppData() (name string, data []byte, err error) { - countFee, err := btypes.ParseCoins(viper.GetString(flagCountFee)) +func readCounterTxFlags() (tx basecoin.Tx, err error) { + feeCoins, err := btypes.ParseCoins(viper.GetString(FlagCountFee)) if err != nil { - return - } - ctx := counter.CounterTx{ - Valid: viper.GetBool(flagValid), - Fee: countFee, + return tx, err } - name = counter.New().Name() - data = wire.BinaryBytes(ctx) - return + tx = counter.NewCounterTx(viper.GetBool(FlagValid), feeCoins) + return tx, nil } diff --git a/docs/guide/counter/cmd/countercli/commands/query.go b/docs/guide/counter/cmd/countercli/commands/query.go index 692e04c7b3..0d5febfe9e 100644 --- a/docs/guide/counter/cmd/countercli/commands/query.go +++ b/docs/guide/counter/cmd/countercli/commands/query.go @@ -16,9 +16,9 @@ var CounterQueryCmd = &cobra.Command{ } func counterQueryCmd(cmd *cobra.Command, args []string) error { - key := counter.New().StateKey() + key := counter.StateKey() - var cp counter.CounterPluginState + var cp counter.CounterState proof, err := proofcmd.GetAndParseAppProof(key, &cp) if err != nil { return err diff --git a/docs/guide/counter/plugins/counter/counter.go b/docs/guide/counter/plugins/counter/counter.go index 71050862e2..aec7775b76 100644 --- a/docs/guide/counter/plugins/counter/counter.go +++ b/docs/guide/counter/plugins/counter/counter.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/basecoin" "github.com/tendermint/basecoin/errors" "github.com/tendermint/basecoin/modules/coin" + "github.com/tendermint/basecoin/stack" "github.com/tendermint/basecoin/types" ) @@ -78,6 +79,17 @@ func ErrDecoding() error { // CounterHandler //-------------------------------------------------------------------------------- +func NewCounterHandler() basecoin.Handler { + // use the default stack + coin := coin.NewHandler() + counter := CounterHandler{} + dispatcher := stack.NewDispatcher( + stack.WrapHandler(coin), + stack.WrapHandler(counter), + ) + return stack.NewDefault().Use(dispatcher) +} + type CounterHandler struct { basecoin.NopOption } @@ -107,6 +119,7 @@ func (h CounterHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx } // TODO: handle coin movement.... ugh, need sequence to do this, right? + // like, actually decrement the other account // update the counter state, err := LoadState(store) @@ -135,16 +148,16 @@ func checkTx(ctx basecoin.Context, tx basecoin.Tx) (ctr CounterTx, err error) { // CounterStore //-------------------------------------------------------------------------------- -type CounterPluginState struct { - Counter int - TotalFees types.Coins +type CounterState struct { + Counter int `json:"counter"` + TotalFees types.Coins `json:"total_fees"` } func StateKey() []byte { return []byte(NameCounter + "/state") } -func LoadState(store types.KVStore) (state CounterPluginState, err error) { +func LoadState(store types.KVStore) (state CounterState, err error) { bytes := store.Get(StateKey()) if len(bytes) > 0 { err = wire.ReadBinaryBytes(bytes, &state) @@ -155,7 +168,7 @@ func LoadState(store types.KVStore) (state CounterPluginState, err error) { return state, nil } -func StoreState(store types.KVStore, state CounterPluginState) error { +func StoreState(store types.KVStore, state CounterState) error { bytes := wire.BinaryBytes(state) store.Set(StateKey(), bytes) return nil diff --git a/docs/guide/counter/plugins/counter/counter_test.go b/docs/guide/counter/plugins/counter/counter_test.go index 3fa84849a3..e3e8793da7 100644 --- a/docs/guide/counter/plugins/counter/counter_test.go +++ b/docs/guide/counter/plugins/counter/counter_test.go @@ -7,10 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/abci/types" - "github.com/tendermint/basecoin" "github.com/tendermint/basecoin/app" - "github.com/tendermint/basecoin/modules/coin" - "github.com/tendermint/basecoin/stack" "github.com/tendermint/basecoin/txs" "github.com/tendermint/basecoin/types" "github.com/tendermint/go-wire" @@ -18,18 +15,6 @@ import ( "github.com/tendermint/tmlibs/log" ) -// TODO: actually handle the counter here... -func NewCounterHandler() basecoin.Handler { - // use the default stack - coin := coin.NewHandler() - counter := CounterHandler{} - dispatcher := stack.NewDispatcher( - stack.WrapHandler(coin), - stack.WrapHandler(counter), - ) - return stack.NewDefault().Use(dispatcher) -} - func TestCounterPlugin(t *testing.T) { assert := assert.New(t) diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh index 02b8ac44d6..05a5858dd1 100755 --- a/tests/cli/counter.sh +++ b/tests/cli/counter.sh @@ -55,21 +55,22 @@ test02GetCounter() { checkCounter() { # make sure sender goes down ACCT=$(${CLIENT_EXE} query counter) - assertTrue "count is set" $? - assertEquals "proper count" "$1" $(echo $ACCT | jq .data.Counter) - assertEquals "proper money" "$2" $(echo $ACCT | jq .data.TotalFees[0].amount) + if assertTrue "count is set" $?; then + assertEquals "proper count" "$1" $(echo $ACCT | jq .data.counter) + assertEquals "proper money" "$2" $(echo $ACCT | jq .data.total_fees[0].amount) + fi } test03AddCount() { SENDER=$(getAddr $RICH) - assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --amount=1000mycoin --sequence=2 --name=${RICH} 2>/dev/null" + assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --countfee=100mycoin --sequence=2 --name=${RICH} 2>/dev/null" - TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin) + TX=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --countfee=10mycoin --sequence=2 --name=${RICH} --valid) txSucceeded $? "$TX" "counter" HASH=$(echo $TX | jq .hash | tr -d \") TX_HEIGHT=$(echo $TX | jq .height) - checkCounter "1" "5" + checkCounter "1" "10" # FIXME: cannot load apptx properly. # Look at the stack trace diff --git a/tests/tmsp/tmsp_test.go b/tests/tmsp/tmsp_test.go index 9de055ad65..f08b626008 100644 --- a/tests/tmsp/tmsp_test.go +++ b/tests/tmsp/tmsp_test.go @@ -1,157 +1,159 @@ package tmsp_test -import ( - "encoding/json" - "testing" +// TODO: replace with benchmarker - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tendermint/basecoin/app" - "github.com/tendermint/basecoin/types" - wire "github.com/tendermint/go-wire" - eyescli "github.com/tendermint/merkleeyes/client" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" -) +// import ( +// "encoding/json" +// "testing" -func TestSendTx(t *testing.T) { - eyesCli := eyescli.NewLocalClient("", 0) - chainID := "test_chain_id" - bcApp := app.NewBasecoin(eyesCli, log.TestingLogger().With("module", "app")) - bcApp.SetOption("base/chain_id", chainID) - // t.Log(bcApp.Info()) +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +// "github.com/tendermint/basecoin/app" +// "github.com/tendermint/basecoin/types" +// wire "github.com/tendermint/go-wire" +// eyescli "github.com/tendermint/merkleeyes/client" +// cmn "github.com/tendermint/tmlibs/common" +// "github.com/tendermint/tmlibs/log" +// ) - test1PrivAcc := types.PrivAccountFromSecret("test1") - test2PrivAcc := types.PrivAccountFromSecret("test2") +// func TestSendTx(t *testing.T) { +// eyesCli := eyescli.NewLocalClient("", 0) +// chainID := "test_chain_id" +// bcApp := app.NewBasecoin(eyesCli, log.TestingLogger().With("module", "app")) +// bcApp.SetOption("base/chain_id", chainID) +// // t.Log(bcApp.Info()) - // Seed Basecoin with account - test1Acc := test1PrivAcc.Account - test1Acc.Balance = types.Coins{{"", 1000}} - accOpt, err := json.Marshal(test1Acc) - require.Nil(t, err) - bcApp.SetOption("base/account", string(accOpt)) +// test1PrivAcc := types.PrivAccountFromSecret("test1") +// test2PrivAcc := types.PrivAccountFromSecret("test2") - // Construct a SendTx signature - tx := &types.SendTx{ - Gas: 0, - Fee: types.Coin{"", 0}, - Inputs: []types.TxInput{ - types.NewTxInput(test1PrivAcc.Account.PubKey, types.Coins{{"", 1}}, 1), - }, - Outputs: []types.TxOutput{ - types.TxOutput{ - Address: test2PrivAcc.Account.PubKey.Address(), - Coins: types.Coins{{"", 1}}, - }, - }, - } +// // Seed Basecoin with account +// test1Acc := test1PrivAcc.Account +// test1Acc.Balance = types.Coins{{"", 1000}} +// accOpt, err := json.Marshal(test1Acc) +// require.Nil(t, err) +// bcApp.SetOption("base/account", string(accOpt)) - // Sign request - signBytes := tx.SignBytes(chainID) - // t.Log("Sign bytes: %X\n", signBytes) - sig := test1PrivAcc.Sign(signBytes) - tx.Inputs[0].Signature = sig - // t.Log("Signed TX bytes: %X\n", wire.BinaryBytes(types.TxS{tx})) +// // Construct a SendTx signature +// tx := &types.SendTx{ +// Gas: 0, +// Fee: types.Coin{"", 0}, +// Inputs: []types.TxInput{ +// types.NewTxInput(test1PrivAcc.Account.PubKey, types.Coins{{"", 1}}, 1), +// }, +// Outputs: []types.TxOutput{ +// types.TxOutput{ +// Address: test2PrivAcc.Account.PubKey.Address(), +// Coins: types.Coins{{"", 1}}, +// }, +// }, +// } - // Write request - txBytes := wire.BinaryBytes(types.TxS{tx}) - res := bcApp.DeliverTx(txBytes) - // t.Log(res) - assert.True(t, res.IsOK(), "Failed: %v", res.Error()) -} +// // Sign request +// signBytes := tx.SignBytes(chainID) +// // t.Log("Sign bytes: %X\n", signBytes) +// sig := test1PrivAcc.Sign(signBytes) +// tx.Inputs[0].Signature = sig +// // t.Log("Signed TX bytes: %X\n", wire.BinaryBytes(types.TxS{tx})) -func TestSequence(t *testing.T) { - eyesCli := eyescli.NewLocalClient("", 0) - chainID := "test_chain_id" - bcApp := app.NewBasecoin(eyesCli, log.TestingLogger().With("module", "app")) - bcApp.SetOption("base/chain_id", chainID) - // t.Log(bcApp.Info()) +// // Write request +// txBytes := wire.BinaryBytes(types.TxS{tx}) +// res := bcApp.DeliverTx(txBytes) +// // t.Log(res) +// assert.True(t, res.IsOK(), "Failed: %v", res.Error()) +// } - // Get the test account - test1PrivAcc := types.PrivAccountFromSecret("test1") - test1Acc := test1PrivAcc.Account - test1Acc.Balance = types.Coins{{"", 1 << 53}} - accOpt, err := json.Marshal(test1Acc) - require.Nil(t, err) - bcApp.SetOption("base/account", string(accOpt)) +// func TestSequence(t *testing.T) { +// eyesCli := eyescli.NewLocalClient("", 0) +// chainID := "test_chain_id" +// bcApp := app.NewBasecoin(eyesCli, log.TestingLogger().With("module", "app")) +// bcApp.SetOption("base/chain_id", chainID) +// // t.Log(bcApp.Info()) - sequence := int(1) - // Make a bunch of PrivAccounts - privAccounts := types.RandAccounts(1000, 1000000, 0) - privAccountSequences := make(map[string]int) - // Send coins to each account +// // Get the test account +// test1PrivAcc := types.PrivAccountFromSecret("test1") +// test1Acc := test1PrivAcc.Account +// test1Acc.Balance = types.Coins{{"", 1 << 53}} +// accOpt, err := json.Marshal(test1Acc) +// require.Nil(t, err) +// bcApp.SetOption("base/account", string(accOpt)) - for i := 0; i < len(privAccounts); i++ { - privAccount := privAccounts[i] +// sequence := int(1) +// // Make a bunch of PrivAccounts +// privAccounts := types.RandAccounts(1000, 1000000, 0) +// privAccountSequences := make(map[string]int) +// // Send coins to each account - tx := &types.SendTx{ - Gas: 2, - Fee: types.Coin{"", 2}, - Inputs: []types.TxInput{ - types.NewTxInput(test1Acc.PubKey, types.Coins{{"", 1000002}}, sequence), - }, - Outputs: []types.TxOutput{ - types.TxOutput{ - Address: privAccount.Account.PubKey.Address(), - Coins: types.Coins{{"", 1000000}}, - }, - }, - } - sequence += 1 +// for i := 0; i < len(privAccounts); i++ { +// privAccount := privAccounts[i] - // Sign request - signBytes := tx.SignBytes(chainID) - sig := test1PrivAcc.Sign(signBytes) - tx.Inputs[0].Signature = sig - // t.Log("ADDR: %X -> %X\n", tx.Inputs[0].Address, tx.Outputs[0].Address) +// tx := &types.SendTx{ +// Gas: 2, +// Fee: types.Coin{"", 2}, +// Inputs: []types.TxInput{ +// types.NewTxInput(test1Acc.PubKey, types.Coins{{"", 1000002}}, sequence), +// }, +// Outputs: []types.TxOutput{ +// types.TxOutput{ +// Address: privAccount.Account.PubKey.Address(), +// Coins: types.Coins{{"", 1000000}}, +// }, +// }, +// } +// sequence += 1 - // Write request - txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - res := bcApp.DeliverTx(txBytes) - assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) - } +// // Sign request +// signBytes := tx.SignBytes(chainID) +// sig := test1PrivAcc.Sign(signBytes) +// tx.Inputs[0].Signature = sig +// // t.Log("ADDR: %X -> %X\n", tx.Inputs[0].Address, tx.Outputs[0].Address) - res := bcApp.Commit() - assert.True(t, res.IsOK(), "Failed Commit: %v", res.Error()) +// // Write request +// txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) +// res := bcApp.DeliverTx(txBytes) +// assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) +// } - t.Log("-------------------- RANDOM SENDS --------------------") +// res := bcApp.Commit() +// assert.True(t, res.IsOK(), "Failed Commit: %v", res.Error()) - // Now send coins between these accounts - for i := 0; i < 10000; i++ { - randA := cmn.RandInt() % len(privAccounts) - randB := cmn.RandInt() % len(privAccounts) - if randA == randB { - continue - } +// t.Log("-------------------- RANDOM SENDS --------------------") - privAccountA := privAccounts[randA] - privAccountASequence := privAccountSequences[privAccountA.Account.PubKey.KeyString()] - privAccountSequences[privAccountA.Account.PubKey.KeyString()] = privAccountASequence + 1 - privAccountB := privAccounts[randB] +// // Now send coins between these accounts +// for i := 0; i < 10000; i++ { +// randA := cmn.RandInt() % len(privAccounts) +// randB := cmn.RandInt() % len(privAccounts) +// if randA == randB { +// continue +// } - tx := &types.SendTx{ - Gas: 2, - Fee: types.Coin{"", 2}, - Inputs: []types.TxInput{ - types.NewTxInput(privAccountA.PubKey, types.Coins{{"", 3}}, privAccountASequence+1), - }, - Outputs: []types.TxOutput{ - types.TxOutput{ - Address: privAccountB.PubKey.Address(), - Coins: types.Coins{{"", 1}}, - }, - }, - } +// privAccountA := privAccounts[randA] +// privAccountASequence := privAccountSequences[privAccountA.Account.PubKey.KeyString()] +// privAccountSequences[privAccountA.Account.PubKey.KeyString()] = privAccountASequence + 1 +// privAccountB := privAccounts[randB] - // Sign request - signBytes := tx.SignBytes(chainID) - sig := privAccountA.Sign(signBytes) - tx.Inputs[0].Signature = sig - // t.Log("ADDR: %X -> %X\n", tx.Inputs[0].Address, tx.Outputs[0].Address) +// tx := &types.SendTx{ +// Gas: 2, +// Fee: types.Coin{"", 2}, +// Inputs: []types.TxInput{ +// types.NewTxInput(privAccountA.PubKey, types.Coins{{"", 3}}, privAccountASequence+1), +// }, +// Outputs: []types.TxOutput{ +// types.TxOutput{ +// Address: privAccountB.PubKey.Address(), +// Coins: types.Coins{{"", 1}}, +// }, +// }, +// } - // Write request - txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - res := bcApp.DeliverTx(txBytes) - assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) - } -} +// // Sign request +// signBytes := tx.SignBytes(chainID) +// sig := privAccountA.Sign(signBytes) +// tx.Inputs[0].Signature = sig +// // t.Log("ADDR: %X -> %X\n", tx.Inputs[0].Address, tx.Outputs[0].Address) + +// // Write request +// txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) +// res := bcApp.DeliverTx(txBytes) +// assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) +// } +// }