From 9fe2f6b365b891bfaf064fdbb22e0c1bf08955ff Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sun, 6 Aug 2017 21:21:52 +0200 Subject: [PATCH 1/8] Setup first tx, error code --- modules/etc/errors.go | 23 +++++++++++++++++++++++ modules/etc/handler.go | 6 ++++++ modules/etc/store.go | 1 + modules/etc/tx.go | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 modules/etc/errors.go create mode 100644 modules/etc/handler.go create mode 100644 modules/etc/store.go create mode 100644 modules/etc/tx.go diff --git a/modules/etc/errors.go b/modules/etc/errors.go new file mode 100644 index 000000000..9eab3cf57 --- /dev/null +++ b/modules/etc/errors.go @@ -0,0 +1,23 @@ +package etc + +import ( + "fmt" + + abci "github.com/tendermint/abci/types" + + "github.com/tendermint/basecoin/errors" +) + +var ( + errMissingData = fmt.Errorf("All tx fields must be filled") + + malformed = abci.CodeType_EncodingError +) + +//nolint +func ErrMissingData() errors.TMError { + return errors.WithCode(errMissingData, malformed) +} +func IsMissingDataErr(err error) bool { + return errors.IsSameError(errMissingData, err) +} diff --git a/modules/etc/handler.go b/modules/etc/handler.go new file mode 100644 index 000000000..e9c06620d --- /dev/null +++ b/modules/etc/handler.go @@ -0,0 +1,6 @@ +package etc + +const ( + // Name of the module for registering it + Name = "etc" +) diff --git a/modules/etc/store.go b/modules/etc/store.go new file mode 100644 index 000000000..825503c2e --- /dev/null +++ b/modules/etc/store.go @@ -0,0 +1 @@ +package etc diff --git a/modules/etc/tx.go b/modules/etc/tx.go new file mode 100644 index 000000000..80dbf4da0 --- /dev/null +++ b/modules/etc/tx.go @@ -0,0 +1,41 @@ +package etc + +import ( + "github.com/tendermint/basecoin" + "github.com/tendermint/go-wire/data" +) + +// nolint +const ( + TypeSet = Name + "/set" + TypeGet = Name + "/get" + TypeRemove = Name + "/remove" + + ByteSet = 0xF0 + ByteGet = 0xF1 + ByteRemove = 0xF2 +) + +func init() { + basecoin.TxMapper. + RegisterImplementation(SetTx{}, TypeSet, ByteSet) +} + +// SetTx sets a key-value pair +type SetTx struct { + Key data.Bytes `json:"key"` + Value data.Bytes `json:"value"` +} + +// Wrap - fulfills TxInner interface +func (t SetTx) Wrap() basecoin.Tx { + return basecoin.Tx{t} +} + +// ValidateBasic makes sure it is valid +func (t SetTx) ValidateBasic() error { + if len(t.Key) == 0 || len(t.Value) == 0 { + return ErrMissingData() + } + return nil +} From 4c663d5551476794fff8a1f4300f07bf26b3b079 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sun, 6 Aug 2017 22:23:17 +0200 Subject: [PATCH 2/8] Add handler and store Notice that everything has json tags and that we check price in CheckTx, while we run real code in DeliverTx. Return values are meant for the client. --- modules/etc/handler.go | 85 ++++++++++++++++++++++++++++++++++++++++++ modules/etc/store.go | 19 ++++++++++ modules/etc/tx.go | 23 ++++++++++-- 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/modules/etc/handler.go b/modules/etc/handler.go index e9c06620d..ba338d5fb 100644 --- a/modules/etc/handler.go +++ b/modules/etc/handler.go @@ -1,6 +1,91 @@ package etc +import ( + "github.com/tendermint/basecoin" + "github.com/tendermint/basecoin/errors" + "github.com/tendermint/basecoin/state" + wire "github.com/tendermint/go-wire" +) + const ( // Name of the module for registering it Name = "etc" + + // CostSet is the gas needed for the set operation + CostSet uint64 = 10 + // CostRemove is the gas needed for the remove operation + CostRemove = 10 ) + +// Handler allows us to set and remove data +type Handler struct { + basecoin.NopInitState + basecoin.NopInitValidate +} + +var _ basecoin.Handler = Handler{} + +// NewHandler makes a role handler to modify data +func NewHandler() Handler { + return Handler{} +} + +// Name - return name space +func (Handler) Name() string { + return Name +} + +// CheckTx verifies if the transaction is properly formated +func (h Handler) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx) (res basecoin.CheckResult, err error) { + err = tx.ValidateBasic() + if err != nil { + return + } + + switch tx.Unwrap().(type) { + case SetTx: + res = basecoin.NewCheck(CostSet, "") + case RemoveTx: + res = basecoin.NewCheck(CostRemove, "") + default: + err = errors.ErrUnknownTxType(tx) + } + return +} + +// DeliverTx tries to create a new role. +// +// Returns an error if the role already exists +func (h Handler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx) (res basecoin.DeliverResult, err error) { + err = tx.ValidateBasic() + if err != nil { + return + } + + switch t := tx.Unwrap().(type) { + case SetTx: + res, err = h.doSetTx(ctx, store, t) + case RemoveTx: + res, err = h.doRemoveTx(ctx, store, t) + default: + err = errors.ErrUnknownTxType(tx) + } + return +} + +// doSetTx write to the store, overwriting any previous value +func (h Handler) doSetTx(ctx basecoin.Context, store state.SimpleDB, tx SetTx) (res basecoin.DeliverResult, err error) { + data := NewData(tx.Value, ctx.BlockHeight()) + store.Set(tx.Key, wire.BinaryBytes(data)) + return +} + +// doRemoveTx deletes the value from the store and returns the last value +func (h Handler) doRemoveTx(ctx basecoin.Context, store state.SimpleDB, tx RemoveTx) (res basecoin.DeliverResult, err error) { + // we set res.Data so it gets returned to the client over the abci interface + res.Data = store.Get(tx.Key) + if len(res.Data) != 0 { + store.Remove(tx.Key) + } + return +} diff --git a/modules/etc/store.go b/modules/etc/store.go index 825503c2e..4ec45d251 100644 --- a/modules/etc/store.go +++ b/modules/etc/store.go @@ -1 +1,20 @@ package etc + +import "github.com/tendermint/go-wire/data" + +// Data is the struct we use to store in the merkle tree +type Data struct { + // SetAt is the block height this was set at + SetAt uint64 `json:"created_at"` + // Value is the data that was stored. + // data.Bytes is like []byte but json encodes as hex not base64 + Value data.Bytes `json:"value"` +} + +// NewData creates a new Data item +func NewData(value []byte, setAt uint64) Data { + return Data{ + SetAt: setAt, + Value: value, + } +} diff --git a/modules/etc/tx.go b/modules/etc/tx.go index 80dbf4da0..cae743591 100644 --- a/modules/etc/tx.go +++ b/modules/etc/tx.go @@ -8,17 +8,16 @@ import ( // nolint const ( TypeSet = Name + "/set" - TypeGet = Name + "/get" TypeRemove = Name + "/remove" ByteSet = 0xF0 - ByteGet = 0xF1 ByteRemove = 0xF2 ) func init() { basecoin.TxMapper. - RegisterImplementation(SetTx{}, TypeSet, ByteSet) + RegisterImplementation(SetTx{}, TypeSet, ByteSet). + RegisterImplementation(RemoveTx{}, TypeRemove, ByteRemove) } // SetTx sets a key-value pair @@ -39,3 +38,21 @@ func (t SetTx) ValidateBasic() error { } return nil } + +// RemoveTx deletes the value at this key, returns old value +type RemoveTx struct { + Key data.Bytes `json:"key"` +} + +// Wrap - fulfills TxInner interface +func (t RemoveTx) Wrap() basecoin.Tx { + return basecoin.Tx{t} +} + +// ValidateBasic makes sure it is valid +func (t RemoveTx) ValidateBasic() error { + if len(t.Key) == 0 { + return ErrMissingData() + } + return nil +} From 464ea226f5604a6bb648c77b8f76e737d90f6c95 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sun, 6 Aug 2017 22:34:27 +0200 Subject: [PATCH 3/8] Test the handlers and fix type byte for no conflicts --- modules/etc/handler_test.go | 61 +++++++++++++++++++++++++++++++++++++ modules/etc/tx.go | 4 +-- 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 modules/etc/handler_test.go diff --git a/modules/etc/handler_test.go b/modules/etc/handler_test.go new file mode 100644 index 000000000..28827dc9b --- /dev/null +++ b/modules/etc/handler_test.go @@ -0,0 +1,61 @@ +package etc + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/basecoin/stack" + "github.com/tendermint/basecoin/state" + wire "github.com/tendermint/go-wire" +) + +func TestHandler(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + key := []byte("one") + val := []byte("foo") + var height uint64 = 123 + + h := NewHandler() + ctx := stack.MockContext("role-chain", height) + store := state.NewMemKVStore() + + set := SetTx{Key: key, Value: val}.Wrap() + remove := RemoveTx{Key: key}.Wrap() + invalid := SetTx{}.Wrap() + + // make sure pricing makes sense + cres, err := h.CheckTx(ctx, store, set) + require.Nil(err, "%+v", err) + require.True(cres.GasAllocated > 5, "%#v", cres) + + // set the value, no error + dres, err := h.DeliverTx(ctx, store, set) + require.Nil(err, "%+v", err) + + // get the data + var data Data + bs := store.Get(key) + require.NotEmpty(bs) + err = wire.ReadBinaryBytes(bs, &data) + require.Nil(err, "%+v", err) + assert.Equal(height, data.SetAt) + assert.EqualValues(val, data.Value) + + // make sure pricing makes sense + cres, err = h.CheckTx(ctx, store, remove) + require.Nil(err, "%+v", err) + require.True(cres.GasAllocated > 5, "%#v", cres) + + // remove the data returns the same as the above query + dres, err = h.DeliverTx(ctx, store, remove) + require.Nil(err, "%+v", err) + require.EqualValues(bs, dres.Data) + + // make sure invalid fails both ways + _, err = h.CheckTx(ctx, store, invalid) + require.NotNil(err) + _, err = h.DeliverTx(ctx, store, invalid) + require.NotNil(err) +} diff --git a/modules/etc/tx.go b/modules/etc/tx.go index cae743591..706fcf181 100644 --- a/modules/etc/tx.go +++ b/modules/etc/tx.go @@ -10,8 +10,8 @@ const ( TypeSet = Name + "/set" TypeRemove = Name + "/remove" - ByteSet = 0xF0 - ByteRemove = 0xF2 + ByteSet = 0xF4 + ByteRemove = 0xF5 ) func init() { From 6e38609e3fccc9892927b8b24f5fd854080c5d2f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sun, 6 Aug 2017 22:51:07 +0200 Subject: [PATCH 4/8] Add CLI commands as sub-package --- modules/etc/commands/query.go | 44 +++++++++++++++++++++++++ modules/etc/commands/tx.go | 62 +++++++++++++++++++++++++++++++++++ modules/etc/tx.go | 8 +++++ 3 files changed, 114 insertions(+) create mode 100644 modules/etc/commands/query.go create mode 100644 modules/etc/commands/tx.go diff --git a/modules/etc/commands/query.go b/modules/etc/commands/query.go new file mode 100644 index 000000000..4d0a3cfee --- /dev/null +++ b/modules/etc/commands/query.go @@ -0,0 +1,44 @@ +package commands + +import ( + "encoding/hex" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + cmn "github.com/tendermint/tmlibs/common" + + "github.com/tendermint/basecoin/client/commands" + "github.com/tendermint/basecoin/client/commands/query" + "github.com/tendermint/basecoin/modules/etc" + "github.com/tendermint/basecoin/stack" +) + +// EtcQueryCmd - command to query raw data +var EtcQueryCmd = &cobra.Command{ + Use: "etc [key]", + Short: "Get data stored under key in etc", + RunE: commands.RequireInit(etcQueryCmd), +} + +func etcQueryCmd(cmd *cobra.Command, args []string) error { + var res etc.Data + + arg, err := commands.GetOneArg(args, "key") + if err != nil { + return err + } + key, err := hex.DecodeString(cmn.StripHex(arg)) + if err != nil { + return err + } + + key = stack.PrefixedKey(etc.Name, key) + prove := !viper.GetBool(commands.FlagTrustNode) + height, err := query.GetParsed(key, &res, prove) + if err != nil { + return err + } + + return query.OutputProof(res, height) +} diff --git a/modules/etc/commands/tx.go b/modules/etc/commands/tx.go new file mode 100644 index 000000000..92a444fa9 --- /dev/null +++ b/modules/etc/commands/tx.go @@ -0,0 +1,62 @@ +package commands + +import ( + "github.com/spf13/cobra" + + "github.com/tendermint/basecoin/client/commands" + "github.com/tendermint/basecoin/client/commands/txs" + "github.com/tendermint/basecoin/modules/etc" +) + +// SetTxCmd is CLI command to set data +var SetTxCmd = &cobra.Command{ + Use: "set", + Short: "Sets a key value pair", + RunE: commands.RequireInit(setTxCmd), +} + +// RemoveTxCmd is CLI command to remove data +var RemoveTxCmd = &cobra.Command{ + Use: "Remove", + Short: "Removes a key value pair", + RunE: commands.RequireInit(removeTxCmd), +} + +//nolint +const ( + FlagKey = "key" + FlagValue = "value" +) + +func init() { + SetTxCmd.Flags().String(FlagKey, "", "Key to store data under (hex)") + SetTxCmd.Flags().String(FlagValue, "", "Data to store (hex)") + + RemoveTxCmd.Flags().String(FlagKey, "", "Key under which to remove data (hex)") +} + +// setTxCmd creates a SetTx, wraps, signs, and delivers it +func setTxCmd(cmd *cobra.Command, args []string) error { + key, err := commands.ParseHexFlag(FlagKey) + if err != nil { + return err + } + value, err := commands.ParseHexFlag(FlagValue) + if err != nil { + return err + } + + tx := etc.NewSetTx(key, value) + return txs.DoTx(tx) +} + +// removeTxCmd creates a RemoveTx, wraps, signs, and delivers it +func removeTxCmd(cmd *cobra.Command, args []string) error { + key, err := commands.ParseHexFlag(FlagKey) + if err != nil { + return err + } + + tx := etc.NewRemoveTx(key) + return txs.DoTx(tx) +} diff --git a/modules/etc/tx.go b/modules/etc/tx.go index 706fcf181..12921443d 100644 --- a/modules/etc/tx.go +++ b/modules/etc/tx.go @@ -26,6 +26,10 @@ type SetTx struct { Value data.Bytes `json:"value"` } +func NewSetTx(key, value []byte) basecoin.Tx { + return SetTx{Key: key, Value: value}.Wrap() +} + // Wrap - fulfills TxInner interface func (t SetTx) Wrap() basecoin.Tx { return basecoin.Tx{t} @@ -44,6 +48,10 @@ type RemoveTx struct { Key data.Bytes `json:"key"` } +func NewRemoveTx(key []byte) basecoin.Tx { + return RemoveTx{Key: key}.Wrap() +} + // Wrap - fulfills TxInner interface func (t RemoveTx) Wrap() basecoin.Tx { return basecoin.Tx{t} From 6bc5fa387635f965dbeab6ee22bae696d66e6c11 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 7 Aug 2017 00:00:34 +0200 Subject: [PATCH 5/8] Add eyes and eyescli main commands Note how the all framework commands can be reused with a bit of configurations. And one can add the custom query and tx commands. --- cmd/eyes/init.go | 58 +++++++++++++++++++++++++++++++++ cmd/eyes/main.go | 45 +++++++++++++++++++++++++ cmd/eyescli/main.go | 67 ++++++++++++++++++++++++++++++++++++++ modules/etc/commands/tx.go | 2 +- 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 cmd/eyes/init.go create mode 100644 cmd/eyes/main.go create mode 100644 cmd/eyescli/main.go diff --git a/cmd/eyes/init.go b/cmd/eyes/init.go new file mode 100644 index 000000000..54f424293 --- /dev/null +++ b/cmd/eyes/init.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + + "github.com/tendermint/basecoin/cmd/basecoin/commands" +) + +// InitCmd - node initialization command +var InitCmd = &cobra.Command{ + Use: "init", + Short: "Initialize eyes abci server", + RunE: initCmd, +} + +//nolint - flags +var ( + FlagChainID = "chain-id" //TODO group with other flags or remove? is this already a flag here? +) + +func init() { + InitCmd.Flags().String(FlagChainID, "eyes_test_id", "Chain ID") +} + +func initCmd(cmd *cobra.Command, args []string) error { + // this will ensure that config.toml is there if not yet created, and create dir + cfg, err := tcmd.ParseConfig() + if err != nil { + return err + } + + genesis := getGenesisJSON(viper.GetString(commands.FlagChainID)) + return commands.CreateGenesisValidatorFiles(cfg, genesis, cmd.Root().Name()) +} + +// TODO: better, auto-generate validator... +func getGenesisJSON(chainID string) string { + return fmt.Sprintf(`{ + "app_hash": "", + "chain_id": "%s", + "genesis_time": "0001-01-01T00:00:00.000Z", + "validators": [ + { + "amount": 10, + "name": "", + "pub_key": { + "type": "ed25519", + "data": "7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30" + } + } + ] +}`, chainID) +} diff --git a/cmd/eyes/main.go b/cmd/eyes/main.go new file mode 100644 index 000000000..2c92dd487 --- /dev/null +++ b/cmd/eyes/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "os" + + "github.com/tendermint/tmlibs/cli" + + "github.com/tendermint/basecoin" + "github.com/tendermint/basecoin/cmd/basecoin/commands" + "github.com/tendermint/basecoin/modules/base" + "github.com/tendermint/basecoin/modules/etc" + "github.com/tendermint/basecoin/stack" +) + +// BuildApp constructs the stack we want to use for this app +func BuildApp() basecoin.Handler { + return stack.New( + base.Logger{}, + stack.Recovery{}, + ). + // We do this to demo real usage, also embeds it under it's own namespace + Dispatch( + stack.WrapHandler(etc.NewHandler()), + ) +} + +func main() { + rt := commands.RootCmd + rt.Short = "eyes" + rt.Long = "A demo app to show key-value store with proofs over abci" + + commands.Handler = BuildApp() + + rt.AddCommand( + // out own init command to not require argument + InitCmd, + commands.StartCmd, + //commands.RelayCmd, + commands.UnsafeResetAllCmd, + commands.VersionCmd, + ) + + cmd := cli.PrepareMainCmd(rt, "EYE", os.ExpandEnv("$HOME/.eyes")) + cmd.Execute() +} diff --git a/cmd/eyescli/main.go b/cmd/eyescli/main.go new file mode 100644 index 000000000..1efa6bfc4 --- /dev/null +++ b/cmd/eyescli/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "os" + + "github.com/spf13/cobra" + + keycmd "github.com/tendermint/go-crypto/cmd" + "github.com/tendermint/tmlibs/cli" + + "github.com/tendermint/basecoin/client/commands" + "github.com/tendermint/basecoin/client/commands/auto" + "github.com/tendermint/basecoin/client/commands/proxy" + "github.com/tendermint/basecoin/client/commands/query" + rpccmd "github.com/tendermint/basecoin/client/commands/rpc" + "github.com/tendermint/basecoin/client/commands/seeds" + txcmd "github.com/tendermint/basecoin/client/commands/txs" + etccmd "github.com/tendermint/basecoin/modules/etc/commands" +) + +// EyesCli - main basecoin client command +var EyesCli = &cobra.Command{ + Use: "eyescli", + Short: "Light client for tendermint", + Long: `EyesCli is the light client for a merkle key-value store (eyes)`, +} + +func main() { + commands.AddBasicFlags(EyesCli) + + // Prepare queries + query.RootCmd.AddCommand( + // These are default parsers, but optional in your app (you can remove key) + query.TxQueryCmd, + query.KeyQueryCmd, + // this is out custom parser + etccmd.EtcQueryCmd, + ) + + // no middleware wrapers + txcmd.Middleware = txcmd.Wrappers{} + // txcmd.Middleware.Register(txcmd.RootCmd.PersistentFlags()) + + // just the etc commands + txcmd.RootCmd.AddCommand( + etccmd.SetTxCmd, + etccmd.RemoveTxCmd, + ) + + // Set up the various commands to use + EyesCli.AddCommand( + // we use out own init command to not require address arg + commands.InitCmd, + commands.ResetCmd, + keycmd.RootCmd, + seeds.RootCmd, + rpccmd.RootCmd, + query.RootCmd, + txcmd.RootCmd, + proxy.RootCmd, + commands.VersionCmd, + auto.AutoCompleteCmd, + ) + + cmd := cli.PrepareMainCmd(EyesCli, "EYE", os.ExpandEnv("$HOME/.eyescli")) + cmd.Execute() +} diff --git a/modules/etc/commands/tx.go b/modules/etc/commands/tx.go index 92a444fa9..492067b24 100644 --- a/modules/etc/commands/tx.go +++ b/modules/etc/commands/tx.go @@ -17,7 +17,7 @@ var SetTxCmd = &cobra.Command{ // RemoveTxCmd is CLI command to remove data var RemoveTxCmd = &cobra.Command{ - Use: "Remove", + Use: "remove", Short: "Removes a key value pair", RunE: commands.RequireInit(removeTxCmd), } From 483ed6d87a815d0fe3789a6375e1fa40bf53f68f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 7 Aug 2017 00:23:21 +0200 Subject: [PATCH 6/8] Add cli tests for eyes query and add to Makefile --- Makefile | 1 + tests/cli/eyes.sh | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100755 tests/cli/eyes.sh diff --git a/Makefile b/Makefile index 089ee47c4..d272fcdc2 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ test_cli: tests/cli/shunit2 ./tests/cli/rpc.sh ./tests/cli/init.sh ./tests/cli/basictx.sh + ./tests/cli/eyes.sh ./tests/cli/roles.sh ./tests/cli/counter.sh ./tests/cli/restart.sh diff --git a/tests/cli/eyes.sh b/tests/cli/eyes.sh new file mode 100755 index 000000000..800335970 --- /dev/null +++ b/tests/cli/eyes.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# These global variables are required for common.sh +SERVER_EXE=eyes +CLIENT_EXE=eyescli + +oneTimeSetUp() { + # These are passed in as args + BASE_DIR=$HOME/.test_eyes + CHAIN_ID="eyes-cli-test" + + rm -rf $BASE_DIR 2>/dev/null + mkdir -p $BASE_DIR + + echo "Setting up genesis..." + SERVE_DIR=${BASE_DIR}/server + SERVER_LOG=${BASE_DIR}/${SERVER_EXE}.log + + echo "Starting ${SERVER_EXE} server..." + export EYE_HOME=${SERVE_DIR} + ${SERVER_EXE} init --chain-id=$CHAIN_ID >>$SERVER_LOG + startServer $SERVE_DIR $SERVER_LOG + if [ $? != 0 ]; then return 1; fi + + # Set up client - make sure you use the proper prefix if you set + # a custom CLIENT_EXE + export EYE_HOME=${BASE_DIR}/client + + initClient $CHAIN_ID + if [ $? != 0 ]; then return 1; fi + + printf "...Testing may begin!\n\n\n" +} + +oneTimeTearDown() { + quickTearDown +} + +test00SetGetRemove() { + KEY="CAFE6000" + VALUE="F00D4200" + + assertFalse "line=${LINENO} data present" "${CLIENT_EXE} query etc ${KEY}" + + # set data + TXRES=$(${CLIENT_EXE} tx set --key=${KEY} --value=${VALUE}) + txSucceeded $? "$TXRES" "set cafe" + HASH=$(echo $TXRES | jq .hash | tr -d \") + TX_HEIGHT=$(echo $TXRES | jq .height) + + # make sure it is set + DATA=$(${CLIENT_EXE} query etc ${KEY}) + assertTrue "line=${LINENO} data not set" $? + assertEquals "line=${LINENO}" "\"${VALUE}\"" $(echo $DATA | jq .data.value) + + # query the tx + TX=$(${CLIENT_EXE} query tx $HASH) + assertTrue "line=${LINENO}, found tx" $? + if [ -n "$DEBUG" ]; then echo $TX; echo; fi + + assertEquals "line=${LINENO}, proper type" "\"etc/set\"" $(echo $TX | jq .data.type) + assertEquals "line=${LINENO}, proper key" "\"${KEY}\"" $(echo $TX | jq .data.data.key) + assertEquals "line=${LINENO}, proper value" "\"${VALUE}\"" $(echo $TX | jq .data.data.value) +} + + +# Load common then run these tests with shunit2! +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory +. $DIR/common.sh +. $DIR/shunit2 + From 0133723acaaefbbe6e8a5213e1a6770b9c93f7e4 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 7 Aug 2017 18:47:22 +0200 Subject: [PATCH 7/8] Clean up comments --- cmd/basecli/main.go | 11 +++++------ cmd/eyes/main.go | 1 - cmd/eyescli/main.go | 4 ++-- modules/etc/commands/tx.go | 5 +++-- modules/etc/handler.go | 4 +++- modules/etc/store.go | 2 +- tests/cli/eyes.sh | 4 ++-- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cmd/basecli/main.go b/cmd/basecli/main.go index 0239c5ada..54df8eac5 100644 --- a/cmd/basecli/main.go +++ b/cmd/basecli/main.go @@ -27,13 +27,12 @@ import ( // BaseCli - main basecoin client command var BaseCli = &cobra.Command{ Use: "basecli", - Short: "Light client for tendermint", - Long: `Basecli is an version of tmcli including custom logic to -present a nice (not raw hex) interface to the basecoin blockchain structure. + Short: "Light client for Tendermint", + Long: `Basecli is a certifying light client for the basecoin abci app. -This is a useful tool, but also serves to demonstrate how one can configure -tmcli to work for any custom abci app. -`, +It leverages the power of the tendermint consensus algorithm get full +cryptographic proof of all queries while only syncing a fraction of the +block headers.`, } func main() { diff --git a/cmd/eyes/main.go b/cmd/eyes/main.go index 2c92dd487..59d750695 100644 --- a/cmd/eyes/main.go +++ b/cmd/eyes/main.go @@ -35,7 +35,6 @@ func main() { // out own init command to not require argument InitCmd, commands.StartCmd, - //commands.RelayCmd, commands.UnsafeResetAllCmd, commands.VersionCmd, ) diff --git a/cmd/eyescli/main.go b/cmd/eyescli/main.go index 1efa6bfc4..e65a7083a 100644 --- a/cmd/eyescli/main.go +++ b/cmd/eyescli/main.go @@ -21,7 +21,7 @@ import ( // EyesCli - main basecoin client command var EyesCli = &cobra.Command{ Use: "eyescli", - Short: "Light client for tendermint", + Short: "Light client for Tendermint", Long: `EyesCli is the light client for a merkle key-value store (eyes)`, } @@ -33,7 +33,7 @@ func main() { // These are default parsers, but optional in your app (you can remove key) query.TxQueryCmd, query.KeyQueryCmd, - // this is out custom parser + // this is our custom parser etccmd.EtcQueryCmd, ) diff --git a/modules/etc/commands/tx.go b/modules/etc/commands/tx.go index 492067b24..d60b790d8 100644 --- a/modules/etc/commands/tx.go +++ b/modules/etc/commands/tx.go @@ -22,9 +22,10 @@ var RemoveTxCmd = &cobra.Command{ RunE: commands.RequireInit(removeTxCmd), } -//nolint const ( - FlagKey = "key" + // FlagKey is the cli flag to set the key + FlagKey = "key" + // FlagValue is the cli flag to set the value FlagValue = "value" ) diff --git a/modules/etc/handler.go b/modules/etc/handler.go index ba338d5fb..c979813e7 100644 --- a/modules/etc/handler.go +++ b/modules/etc/handler.go @@ -73,7 +73,8 @@ func (h Handler) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx baseco return } -// doSetTx write to the store, overwriting any previous value +// doSetTx writes to the store, overwriting any previous value +// note that an empty response in DeliverTx is OK with no log or data returned func (h Handler) doSetTx(ctx basecoin.Context, store state.SimpleDB, tx SetTx) (res basecoin.DeliverResult, err error) { data := NewData(tx.Value, ctx.BlockHeight()) store.Set(tx.Key, wire.BinaryBytes(data)) @@ -81,6 +82,7 @@ func (h Handler) doSetTx(ctx basecoin.Context, store state.SimpleDB, tx SetTx) ( } // doRemoveTx deletes the value from the store and returns the last value +// here we let res.Data to return the value over abci func (h Handler) doRemoveTx(ctx basecoin.Context, store state.SimpleDB, tx RemoveTx) (res basecoin.DeliverResult, err error) { // we set res.Data so it gets returned to the client over the abci interface res.Data = store.Get(tx.Key) diff --git a/modules/etc/store.go b/modules/etc/store.go index 4ec45d251..458b1d3ab 100644 --- a/modules/etc/store.go +++ b/modules/etc/store.go @@ -5,7 +5,7 @@ import "github.com/tendermint/go-wire/data" // Data is the struct we use to store in the merkle tree type Data struct { // SetAt is the block height this was set at - SetAt uint64 `json:"created_at"` + SetAt uint64 `json:"set_at"` // Value is the data that was stored. // data.Bytes is like []byte but json encodes as hex not base64 Value data.Bytes `json:"value"` diff --git a/tests/cli/eyes.sh b/tests/cli/eyes.sh index 800335970..5ca993507 100755 --- a/tests/cli/eyes.sh +++ b/tests/cli/eyes.sh @@ -20,14 +20,14 @@ oneTimeSetUp() { export EYE_HOME=${SERVE_DIR} ${SERVER_EXE} init --chain-id=$CHAIN_ID >>$SERVER_LOG startServer $SERVE_DIR $SERVER_LOG - if [ $? != 0 ]; then return 1; fi + [ $? = 0 ] || return 1 # Set up client - make sure you use the proper prefix if you set # a custom CLIENT_EXE export EYE_HOME=${BASE_DIR}/client initClient $CHAIN_ID - if [ $? != 0 ]; then return 1; fi + [ $? = 0 ] || return 1 printf "...Testing may begin!\n\n\n" } From ade9d4527bb381913b5182b5eb04b05c44912b8f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 7 Aug 2017 18:49:03 +0200 Subject: [PATCH 8/8] Rename module/etc to eyes as well --- cmd/eyes/main.go | 2 +- cmd/eyescli/main.go | 2 +- modules/{etc => eyes}/commands/query.go | 2 +- modules/{etc => eyes}/commands/tx.go | 2 +- modules/{etc => eyes}/errors.go | 0 modules/{etc => eyes}/handler.go | 0 modules/{etc => eyes}/handler_test.go | 0 modules/{etc => eyes}/store.go | 0 modules/{etc => eyes}/tx.go | 0 9 files changed, 4 insertions(+), 4 deletions(-) rename modules/{etc => eyes}/commands/query.go (95%) rename modules/{etc => eyes}/commands/tx.go (96%) rename modules/{etc => eyes}/errors.go (100%) rename modules/{etc => eyes}/handler.go (100%) rename modules/{etc => eyes}/handler_test.go (100%) rename modules/{etc => eyes}/store.go (100%) rename modules/{etc => eyes}/tx.go (100%) diff --git a/cmd/eyes/main.go b/cmd/eyes/main.go index 59d750695..8253ecd2c 100644 --- a/cmd/eyes/main.go +++ b/cmd/eyes/main.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/basecoin" "github.com/tendermint/basecoin/cmd/basecoin/commands" "github.com/tendermint/basecoin/modules/base" - "github.com/tendermint/basecoin/modules/etc" + "github.com/tendermint/basecoin/modules/eyes" "github.com/tendermint/basecoin/stack" ) diff --git a/cmd/eyescli/main.go b/cmd/eyescli/main.go index e65a7083a..86bc156a3 100644 --- a/cmd/eyescli/main.go +++ b/cmd/eyescli/main.go @@ -15,7 +15,7 @@ import ( rpccmd "github.com/tendermint/basecoin/client/commands/rpc" "github.com/tendermint/basecoin/client/commands/seeds" txcmd "github.com/tendermint/basecoin/client/commands/txs" - etccmd "github.com/tendermint/basecoin/modules/etc/commands" + etccmd "github.com/tendermint/basecoin/modules/eyes/commands" ) // EyesCli - main basecoin client command diff --git a/modules/etc/commands/query.go b/modules/eyes/commands/query.go similarity index 95% rename from modules/etc/commands/query.go rename to modules/eyes/commands/query.go index 4d0a3cfee..eea6c3d11 100644 --- a/modules/etc/commands/query.go +++ b/modules/eyes/commands/query.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/basecoin/client/commands" "github.com/tendermint/basecoin/client/commands/query" - "github.com/tendermint/basecoin/modules/etc" + "github.com/tendermint/basecoin/modules/eyes" "github.com/tendermint/basecoin/stack" ) diff --git a/modules/etc/commands/tx.go b/modules/eyes/commands/tx.go similarity index 96% rename from modules/etc/commands/tx.go rename to modules/eyes/commands/tx.go index d60b790d8..612ed1c5f 100644 --- a/modules/etc/commands/tx.go +++ b/modules/eyes/commands/tx.go @@ -5,7 +5,7 @@ import ( "github.com/tendermint/basecoin/client/commands" "github.com/tendermint/basecoin/client/commands/txs" - "github.com/tendermint/basecoin/modules/etc" + "github.com/tendermint/basecoin/modules/eyes" ) // SetTxCmd is CLI command to set data diff --git a/modules/etc/errors.go b/modules/eyes/errors.go similarity index 100% rename from modules/etc/errors.go rename to modules/eyes/errors.go diff --git a/modules/etc/handler.go b/modules/eyes/handler.go similarity index 100% rename from modules/etc/handler.go rename to modules/eyes/handler.go diff --git a/modules/etc/handler_test.go b/modules/eyes/handler_test.go similarity index 100% rename from modules/etc/handler_test.go rename to modules/eyes/handler_test.go diff --git a/modules/etc/store.go b/modules/eyes/store.go similarity index 100% rename from modules/etc/store.go rename to modules/eyes/store.go diff --git a/modules/etc/tx.go b/modules/eyes/tx.go similarity index 100% rename from modules/etc/tx.go rename to modules/eyes/tx.go