From 86778297c068b2855036eb1284d180a5ac5caecb Mon Sep 17 00:00:00 2001 From: H Copperm Date: Thu, 23 Mar 2017 16:39:23 -0700 Subject: [PATCH 01/33] Update install.md to include git pull --- docs/guide/install.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/guide/install.md b/docs/guide/install.md index ef0ef28a61..9c5738a773 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -13,6 +13,7 @@ the correct way to install is: ``` cd $GOPATH/src/github.com/tendermint/basecoin +git pull origin master make get_vendor_deps make install ``` From 146ca88f2c9c27089263a7a0749428520b6c4e87 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 3 Apr 2017 13:28:14 +0200 Subject: [PATCH 02/33] cast bytes to string before printing --- cmd/commands/key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/commands/key.go b/cmd/commands/key.go index b492eb94bc..124f390ddf 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -38,7 +38,7 @@ func cmdNewKey(c *cli.Context) error { if err != nil { return err } - fmt.Println(keyJSON) + fmt.Println(string(keyJSON)) return nil } From e19fb0328d66c6580533b7fba1abc5f0fa2809e9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 12 Apr 2017 14:58:31 +0200 Subject: [PATCH 03/33] Added info on working with branches to the go basics guide --- docs/go_basics.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/go_basics.md b/docs/go_basics.md index fd753da90c..1364bcb052 100644 --- a/docs/go_basics.md +++ b/docs/go_basics.md @@ -11,6 +11,8 @@ learn a new project quickly as they all have the same enforced layout, programming following these conventions allows for interoperability with much of the go tooling, and a much more fluid development experience. +## Setup + First of all, you should read through [Effective Go](https://golang.org/doc/effective_go.html) to get a feel for the language and the constructs. And maybe pick up a book, read a tutorial, or do what you @@ -36,6 +38,8 @@ github repos. If you put your code outside of GOPATH/src or have a path other than the url of the repo, you can expect errors. There are ways to do this, but quite complex and not worth the bother. +## Compiling from source + Third, every repo in `$GOPATH/src` is checkout out of a version control system (commonly git), and you can go into those directories and manipulate them like any git repo (`git checkout develop`, `git pull`, `git remote set-url origin @@ -44,7 +48,7 @@ master branch and recompile if needed. If you work on develop, get used to using the git commands directly in these repos. [Here](https://tendermint.com/docs/guides/contributing) are some more tips on using git with open source go projects with absolute dependencies such as -Tendermint. +Tendermint. Fourth, installing a go program is rather easy if you know what to do. First to note is all programs compiles with `go install` and end up in `$GOPATH/bin`. @@ -56,6 +60,8 @@ something like `go install github.com/tendermint/basecoin/cmd/basecoin` or to compile all the commands `go install github.com/tendermint/basecoin/cmd/...` (... is a go tooling shortcut for all subdirs, like `*`). +## Dependencies + Fifth, there isn't good dependency management built into go. By default, when compiling a go program which imports another repo, go will compile using the latest master branch, or whichever version you have checked out and located. @@ -80,6 +86,47 @@ install` will compile all commands. `make test` is good to run the test suite and make sure things are working with your environment... failing tests are much easier to debug than a malfunctioning program. +## Custom versions. + +Sometimes compiling the master branch isn't enough. Let's say you just heard the new `develop` branch of tendermint has an awesome new feature and you want to try it out before it makes it into master (in a few weeks). That is pretty simple. Simply go into the `tendermint`, `basecoin`, etc. repo and compile as above. (Note in tendermint and basecoin, make install automatically gets the newest vendor deps, so you can skip that step) + +``` +git checkout develop # or other branch +git pull +make get_vendor_deps +make install +make test +``` + +Great! Now when I run `tendermint` I have the newest of the new, the develop branch! But please not that this branch is not considered production ready and may have issues. This should only be done if you want to develop code for the future and run locally. + +But wait, I want to mix and match. There is a bugfix in `go-p2p:persistent_peer` that I want to use with tendermint. How to compile this. I will show with a simple example, please update the repo and commit numbers for your usecase. Also, make sure these branches are compatible, so if `persistent_peer` is close to `master` it should work. But if it is 15 commits ahead, you will probably need the `develop` branch of tendermint to compile with it. But I assume you know your way around git and can figure that out. + +In the dependent repo: +``` +cd $GOPATH/src/github.com/tendermint/go-p2p +git checkout persistent_peer +git pull +# double-check this makes sense or if it is too far off +git log --oneline --decorate --graph +# get the full commit number here +git log | head -1 +``` + +In the main repo (tendermint, basecoin, ...) where the binary will be built: +``` +cd $GOPATH/src/github.com/tendermint/tendermin +git checkout master +git pull +# -> edit glide.lock, set the version of go-p2p (for example) +# to the commit number you got above (the 40 char version) +make get_vendor_deps +make install +make test +``` + +Great, now you just compiled the master branch of tendermint along with the bugfix for one of the dependencies! Maybe you don't have to wait until the next bugfix release after all. + Okay, that's it, with this info you should be able to follow along and trouble-shoot any issues you have with the rest of the guide. From 52353433a319b7352c36349c67e47d6db25b0d8e Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 13 Apr 2017 14:25:06 +0200 Subject: [PATCH 04/33] Update all dependencies to develop, fix method names --- cmd/commands/tx.go | 2 +- cmd/commands/utils.go | 4 ++-- glide.lock | 20 ++++++++++---------- glide.yaml | 18 +++++++++--------- tests/tendermint/main.go | 4 ++-- types/tx.go | 4 ++-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 66c5acc0a7..8595e57d64 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -189,7 +189,7 @@ func AppTx(c *cli.Context, name string, data []byte) error { func broadcastTx(c *cli.Context, tx types.Tx) ([]byte, string, error) { tmResult := new(ctypes.TMResult) tmAddr := c.String("node") - clientURI := client.NewClientURI(tmAddr) + clientURI := client.NewURIClient(tmAddr) // Don't you hate having to do this? // How many times have I lost an hour over this trick?! diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 56c1480780..8e29949812 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -89,7 +89,7 @@ func ParseCoins(str string) (types.Coins, error) { } func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { - clientURI := client.NewClientURI(tmAddr) + clientURI := client.NewURIClient(tmAddr) tmResult := new(ctypes.TMResult) params := map[string]interface{}{ @@ -136,7 +136,7 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) { func getHeaderAndCommit(c *cli.Context, height int) (*tmtypes.Header, *tmtypes.Commit, error) { tmResult := new(ctypes.TMResult) tmAddr := c.String("node") - clientURI := client.NewClientURI(tmAddr) + clientURI := client.NewURIClient(tmAddr) method := "commit" _, err := clientURI.Call(method, map[string]interface{}{"height": height}, tmResult) diff --git a/glide.lock b/glide.lock index d53e80837b..198a8712a5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c71c0d6c409bfddb4c4b471d8445f59cebd2cd41e1635a90d6facd81bd09a5e0 -updated: 2017-03-14T17:02:44.512359631-04:00 +hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348 +updated: 2017-04-13T14:20:12.625211087+02:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -43,7 +43,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: af792eac777de757cd496349a5f6b5313738fcbc + version: 31eafe8f8eba6b8817edd74df399f508540da528 subpackages: - client - example/dummy @@ -59,13 +59,13 @@ imports: - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: dcb015dff6c7af21e65c8e2f3b450df19d38c777 + version: 6af2364fa91ef2f3afc8ba0db33b66d9d3ae006c - name: github.com/tendermint/go-config version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 3f47cfac5fcd9e0f1727c7db980b3559913b3e3a + version: 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 - name: github.com/tendermint/go-data - version: 32271140e8fd5abdbb22e268d7a02421fa382f0b + version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db version: eac3f2bc147023957c8bf69432a4e6c4dc5c3f72 - name: github.com/tendermint/go-events @@ -79,17 +79,17 @@ imports: - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: 97a5ed2d1a17eaee8717b8a32cfaf7a9a82a273d + version: c39e001a957caf768f06c85c840debb8282c3aaa subpackages: - upnp - name: github.com/tendermint/go-rpc - version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7 + version: 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: f530b7af7a8b06e612c2063bff6ace49060a085e + version: 50889e2b4a9ba65b67be86a486f25853d514b937 - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -100,7 +100,7 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: d4f625455109d88e7f55a999fdb25e208f174802 + version: 585ce45a5e253743da7b72d9a2385c01059fc6d5 subpackages: - blockchain - config/tendermint diff --git a/glide.yaml b/glide.yaml index d607c41cb4..ecf4f151b4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,22 +1,22 @@ package: github.com/tendermint/basecoin import: - package: github.com/tendermint/go-common - version: master + version: develop - package: github.com/tendermint/go-crypto - version: master + version: develop - package: github.com/tendermint/go-events - version: master + version: develop - package: github.com/tendermint/go-logger - version: master + version: develop - package: github.com/tendermint/go-rpc - version: master + version: develop - package: github.com/tendermint/go-wire - version: master + version: develop - package: github.com/tendermint/merkleeyes - version: master + version: develop - package: github.com/tendermint/tendermint - version: master + version: develop - package: github.com/tendermint/abci - version: master + version: develop - package: github.com/gorilla/websocket version: v1.1.0 diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index 5481bfd3a8..504fa88d9e 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -72,7 +72,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes) @@ -122,7 +122,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes) diff --git a/types/tx.go b/types/tx.go index 285902db6f..d4925bbb65 100644 --- a/types/tx.go +++ b/types/tx.go @@ -40,8 +40,8 @@ var txMapper data.Mapper // register both private key types with go-data (and thus go-wire) func init() { txMapper = data.NewMapper(TxS{}). - RegisterInterface(&SendTx{}, TxNameSend, TxTypeSend). - RegisterInterface(&AppTx{}, TxNameApp, TxTypeApp) + RegisterImplementation(&SendTx{}, TxNameSend, TxTypeSend). + RegisterImplementation(&AppTx{}, TxNameApp, TxTypeApp) } // TxS add json serialization to Tx From 4fff8821a32012fd6b3d94be6cd10824ee5c24a1 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 16 Mar 2017 11:43:46 +0400 Subject: [PATCH 05/33] replace fullpath with a dot in Makefile --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 32ec678624..28b99b6c6a 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,22 @@ all: test install -NOVENDOR = go list github.com/tendermint/basecoin/... | grep -v /vendor/ +NOVENDOR = go list ./... | grep -v /vendor/ build: - go build github.com/tendermint/basecoin/cmd/... + go build ./cmd/... install: - go install github.com/tendermint/basecoin/cmd/... + go install ./cmd/... test: go test `${NOVENDOR}` #go run tests/tendermint/*.go get_deps: - go get -d github.com/tendermint/basecoin/... + go get -d ./... update_deps: - go get -d -u github.com/tendermint/basecoin/... + go get -d -u ./... get_vendor_deps: go get github.com/Masterminds/glide From 924d11397edaba37fa882470d628126642aa6f87 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 16 Mar 2017 12:01:29 +0400 Subject: [PATCH 06/33] update go-rpc rpc clients were renamed --- cmd/commands/tx.go | 6 +++--- cmd/commands/utils.go | 10 +++++----- tests/tendermint/main.go | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 8595e57d64..b8e4bcf041 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -12,7 +12,7 @@ import ( cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" ) @@ -189,14 +189,14 @@ func AppTx(c *cli.Context, name string, data []byte) error { func broadcastTx(c *cli.Context, tx types.Tx) ([]byte, string, error) { tmResult := new(ctypes.TMResult) tmAddr := c.String("node") - clientURI := client.NewURIClient(tmAddr) + uriClient := client.NewURIClient(tmAddr) // 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 := clientURI.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult) + _, 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)) } diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 8e29949812..6348ef3cd7 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -16,7 +16,7 @@ import ( abci "github.com/tendermint/abci/types" cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" tmtypes "github.com/tendermint/tendermint/types" ) @@ -89,7 +89,7 @@ func ParseCoins(str string) (types.Coins, error) { } func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { - clientURI := client.NewURIClient(tmAddr) + uriClient := client.NewURIClient(tmAddr) tmResult := new(ctypes.TMResult) params := map[string]interface{}{ @@ -97,7 +97,7 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { "data": key, "prove": true, } - _, err := clientURI.Call("abci_query", params, tmResult) + _, err := uriClient.Call("abci_query", params, tmResult) if err != nil { return nil, errors.New(cmn.Fmt("Error calling /abci_query: %v", err)) } @@ -136,10 +136,10 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) { func getHeaderAndCommit(c *cli.Context, height int) (*tmtypes.Header, *tmtypes.Commit, error) { tmResult := new(ctypes.TMResult) tmAddr := c.String("node") - clientURI := client.NewURIClient(tmAddr) + uriClient := client.NewURIClient(tmAddr) method := "commit" - _, err := clientURI.Call(method, map[string]interface{}{"height": height}, tmResult) + _, 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)) } diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index 504fa88d9e..605de6823c 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -8,9 +8,9 @@ import ( "github.com/tendermint/basecoin/types" cmn "github.com/tendermint/go-common" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-rpc/client" + rpcclient "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-rpc/types" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" _ "github.com/tendermint/tendermint/rpc/core/types" // Register RPCResponse > Result types ) From 0b983fbe37c48c1598c9739b026bf932b9639ae1 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 13 Apr 2017 21:50:18 -0400 Subject: [PATCH 07/33] update glide --- glide.lock | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/glide.lock b/glide.lock index 198a8712a5..ccb7c25322 100644 --- a/glide.lock +++ b/glide.lock @@ -1,18 +1,18 @@ hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348 -updated: 2017-04-13T14:20:12.625211087+02:00 +updated: 2017-04-13T21:40:19.30156119-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 subpackages: - btcec - name: github.com/BurntSushi/toml - version: e643e9ef00b049d75de26e61109c5ea01885cd21 + version: 99064174e013895bbd9b025c31100bd1d9b590ca - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317 + version: 69b215d01a5606c843240eab4937eab3acee6530 subpackages: - proto - name: github.com/golang/snappy @@ -22,11 +22,11 @@ imports: - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable - version: a392f450ea64cee2b268dfaacdc2502b50a22b18 + version: acb9493f2794fd0f820de7a27a217dafbb1b65ea - name: github.com/mattn/go-isatty - version: 57fdcb988a5c543893cc61bce354a6e24ab70022 + version: 9622e0cc9d8f9be434ca605520ff9a16808fee47 - name: github.com/pkg/errors - version: bfd5150e4e41705ded2129ec33379de1cb90b513 + version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/syndtr/goleveldb version: 3c5717caf1475fd25964109a0fc640bd150fce43 subpackages: @@ -83,13 +83,13 @@ imports: subpackages: - upnp - name: github.com/tendermint/go-rpc - version: 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6 + version: c3295f4878019ff3fdfcac37a4c0e4bcf4bb02a7 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: 50889e2b4a9ba65b67be86a486f25853d514b937 + version: ad797c70affa2c81fccc5edaed63ac25144397c6 - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -115,9 +115,9 @@ imports: - types - version - name: github.com/urfave/cli - version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 + version: 8ef3805c9de2519805c3f060524b695bba2cd715 - name: golang.org/x/crypto - version: 728b753d0135da6801d45a38e6f43ff55779c5c2 + version: 40541ccb1c6e64c947ed6f606b8a6cb4b67d7436 subpackages: - curve25519 - nacl/box @@ -128,7 +128,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: a6577fac2d73be281a500b310739095313165611 + version: d379faa25cbdc04d653984913a2ceb43b0bc46d7 subpackages: - context - http2 @@ -138,17 +138,16 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: 99f16d856c9836c42d24e7ab64ea72916925fa97 + version: e48874b42435b4347fc52bdee0424a52abc974d7 subpackages: - unix - name: google.golang.org/grpc - version: 0713829b980f4ddd276689a36235c5fcc82a21bf + version: 7b399ed358736bc5522021cdc7d79a8ee9ac6f98 subpackages: - codes - credentials - grpclog - internal - - keepalive - metadata - naming - peer From 4bf37baf0bbcb994bc41b6e5b2f318639d5f131c Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Wed, 1 Mar 2017 13:07:12 -0500 Subject: [PATCH 08/33] Additional Unit Tests int int int int, got it working! int --- app/app.go | 2 +- glide.lock | 4 +- state/execution.go | 6 + state/execution_test.go | 333 ++++++++++++++++++++++++++++++++++++++++ types/coin.go | 8 + 5 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 state/execution_test.go diff --git a/app/app.go b/app/app.go index 5aafff04ce..c20e220b76 100644 --- a/app/app.go +++ b/app/app.go @@ -37,7 +37,7 @@ func NewBasecoin(eyesCli *eyes.Client) *Basecoin { } } -// For testing, not thread safe! +// XXX For testing, not thread safe! func (app *Basecoin) GetState() *sm.State { return app.state.CacheWrap() } diff --git a/glide.lock b/glide.lock index ccb7c25322..6d411f59ae 100644 --- a/glide.lock +++ b/glide.lock @@ -156,11 +156,11 @@ imports: - transport testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 346938d642f2ec3594ed81d874461961cd0faa76 subpackages: - spew - name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + version: 792786c7400a136282c1664665ae0a8db921c6c2 subpackages: - difflib - name: github.com/stretchr/testify diff --git a/state/execution.go b/state/execution.go index eb7f3c6906..1cd5365337 100644 --- a/state/execution.go +++ b/state/execution.go @@ -1,6 +1,8 @@ package state import ( + "fmt" + abci "github.com/tendermint/abci/types" "github.com/tendermint/basecoin/types" cmn "github.com/tendermint/go-common" @@ -219,6 +221,7 @@ func validateInputsBasic(ins []types.TxInput) (res abci.Result) { // Validate inputs and compute total amount of coins func validateInputsAdvanced(accounts map[string]*types.Account, signBytes []byte, ins []types.TxInput) (total types.Coins, res abci.Result) { for _, in := range ins { + fmt.Println("IN", in) acc := accounts[string(in.Address)] if acc == nil { cmn.PanicSanity("validateInputsAdvanced() expects account in accounts") @@ -244,6 +247,9 @@ func validateInputAdvanced(acc *types.Account, signBytes []byte, in types.TxInpu return abci.ErrBaseInsufficientFunds.AppendLog(cmn.Fmt("balance is %v, tried to send %v", balance, in.Coins)) } // Check signatures + fmt.Printf("signbytes %X\n", signBytes) + fmt.Println("PUBKEY", acc.PubKey) + fmt.Println("") if !acc.PubKey.VerifyBytes(signBytes, in.Signature.Signature) { return abci.ErrBaseInvalidSignature.AppendLog(cmn.Fmt("SignBytes: %X", signBytes)) } diff --git a/state/execution_test.go b/state/execution_test.go new file mode 100644 index 0000000000..a0afbaa65f --- /dev/null +++ b/state/execution_test.go @@ -0,0 +1,333 @@ +package state + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/tendermint/basecoin/types" + "github.com/tendermint/go-crypto" +) + +func TestExecution(t *testing.T) { + + //States and Stores for tests + var store types.KVStore + var state *State + var accsFoo, accsBar, accsFooBar, accsDup []types.PrivAccount + chainID := "test_chain_id" + + makeAccs := func(secrets []string) (accs []types.PrivAccount) { + + for _, secret := range secrets { + privAcc := types.PrivAccountFromSecret(secret) + privAcc.Account.Balance = types.Coins{{"mycoin", 1000}} + accs = append(accs, privAcc) + } + return accs + } + + acc2State := func(accs []types.PrivAccount) { + for _, acc := range accs { + state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) + } + } + + //each tx input signs the tx bytes + signSend := func(tx *types.SendTx, accs []types.PrivAccount) { + signBytes := tx.SignBytes(chainID) + for i, _ := range tx.Inputs { + tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} + } + } + + //turn a list of accounts into basic list of transaction inputs + accs2TxInputs := func(accs []types.PrivAccount) []types.TxInput { + var txs []types.TxInput + for _, acc := range accs { + tx := types.NewTxInput( + acc.Account.PubKey, + types.Coins{{"mycoin", 10}}, + 1) + txs = append(txs, tx) + } + return txs + } + + //turn a list of accounts into basic list of transaction outputs + accs2TxOutputs := func(accs []types.PrivAccount) []types.TxOutput { + var txs []types.TxOutput + for _, acc := range accs { + tx := types.TxOutput{ + acc.Account.PubKey.Address(), + types.Coins{{"mycoin", 9}}} + txs = append(txs, tx) + } + return txs + } + + //reset the store/state/Inputs + reset := func() { + accsFoo = makeAccs([]string{"foo"}) + accsBar = makeAccs([]string{"bar"}) + accsFooBar = makeAccs([]string{"foo", "bar"}) + accsDup = makeAccs([]string{"foo", "foo", "foo"}) + + store = types.NewMemKVStore() + state = NewState(store) + state.SetChainID(chainID) + } + + type er struct { + exp bool //assert true + msg string //msg is assert fails + } + + //define the test list + testList := []struct { + tester func() []er + }{ + /////////////// + //getInputs + + //nil submissions + {func() []er { + acc, res := getInputs(nil, nil) + return []er{ + {!res.IsErr(), "getInputs: error on nil submission"}, + {len(acc) == 0, "getInputs: accounts returned on nil submission"}, + } + }}, + + //test getInputs for registered, non-registered account + {func() []er { + txs := accs2TxInputs(accsFoo) + _, res1 := getInputs(state, txs) + acc2State(accsFoo) + _, res2 := getInputs(state, txs) + return []er{ + {res1.IsErr(), "getInputs: expected to getInput from registered Input"}, + {!res2.IsErr(), "getInputs: expected to getInput from registered Input"}, + } + }}, + + //test sending duplicate accounts + {func() []er { + acc2State(accsDup) + txs := accs2TxInputs(accsDup) + _, res := getInputs(state, txs) + return []er{{res.IsErr(), "getInputs: expected error when sending duplicate accounts"}} + }}, + + /////////////////// + //getOrMakeOutputs + + //nil submissions + {func() []er { + acc, res := getOrMakeOutputs(nil, nil, nil) + return []er{ + {!res.IsErr(), "getOrMakeOutputs: error on nil submission"}, + {len(acc) == 0, "getOrMakeOutputs: accounts returned on nil submission"}, + } + }}, + + //test sending duplicate accounts + {func() []er { + txs := accs2TxOutputs(accsDup) + _, res := getOrMakeOutputs(state, nil, txs) + return []er{{res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts"}} + }}, + + //test sending to existing/new account account + {func() []er { + txs1 := accs2TxOutputs(accsFoo) + txs2 := accs2TxOutputs(accsBar) + + acc2State(accsFoo) + _, res1 := getOrMakeOutputs(state, nil, txs1) + mapRes2, res2 := getOrMakeOutputs(state, nil, txs2) + + //TODO Fix this commented out test + //test the map results + //acc2, map2ok := mapRes2[string(txs2[0].Address)] + _, map2ok := mapRes2[string(txs2[0].Address)] + + return []er{ + {!res1.IsErr(), "getOrMakeOutputs: error when sending to existing account"}, + {!res2.IsErr(), "getOrMakeOutputs: error when sending to new account"}, + {map2ok, "getOrMakeOutputs: account output does not contain new account map item"}, + } + //{accs2[0].PubKey.Equals(acc2.PubKey), "getOrMakeOutputs: account output does not contain new account pointer"}} + }}, + + //validate input basic + {func() []er { + txs := accs2TxInputs(accsFoo) + res1 := validateInputsBasic(txs) + txs[0].Coins[0].Amount = 0 + res2 := validateInputsBasic(txs) + return []er{ + {!res1.IsErr(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res1.Error())}, + {res2.IsErr(), "validateInputsBasic: expected error on bad tx input"}, + } + }}, + + //validate inputs advanced + {func() []er { + txs := types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFooBar), + Outputs: accs2TxOutputs(accsBar), + } + + acc2State(accsFooBar) + accMap, res1 := getInputs(state, txs.Inputs) + signBytes := txs.SignBytes(chainID) + + //test bad case, unsigned + totalCoins, res2 := validateInputsAdvanced(accMap, signBytes, txs.Inputs) + + //test good case sgined + signSend(&txs, accsFooBar) + totalCoins, res3 := validateInputsAdvanced(accMap, signBytes, txs.Inputs) + + return []er{ + {!res1.IsErr(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res1.Error())}, + {res2.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input"}, + {!res3.IsErr(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res3.Error())}, + {totalCoins.IsEqual(txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins)), "ValidateInputsAdvanced: transaction total coins are not equal"}, + } + }}, + + //validate input advanced + {func() []er { + txs := types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFooBar), + Outputs: accs2TxOutputs(accsBar), + } + + acc2State(accsFooBar) + signBytes := txs.SignBytes(chainID) + + //unsigned case + res1 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + + //good signed case + signSend(&txs, accsFooBar) + res2 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + + //bad sequence case + accsFooBar[0].Sequence = 2 + signSend(&txs, accsFooBar) + res3 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + accsFooBar[0].Account.Sequence = 1 //restore sequence + + //bad balance case + accsFooBar[1].Balance = types.Coins{{"mycoin", 2}} + signSend(&txs, accsFooBar) + res4 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + + return []er{ + {res1.IsErr(), "validateInputAdvanced: expected error on tx input without signature"}, + {!res2.IsErr(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res1.Error())}, + {res3.IsErr(), "validateInputAdvanced: expected error on tx input with bad sequence"}, + {res4.IsErr(), "validateInputAdvanced: expected error on tx input with insufficient funds"}, + } + }}, + + //validateOutputsBasic + {func() []er { + txs := accs2TxOutputs(accsFoo) + res1 := validateOutputsBasic(txs) + txs[0].Coins[0].Amount = 0 + res2 := validateOutputsBasic(txs) + return []er{{!res1.IsErr(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res1.Error())}, + {res2.IsErr(), fmt.Sprintf("validateInputBasic: expected error on bad tx inputi. Error: %v", res2.Error())}} + }}, + + //SumOutput + {func() []er { + txs := accs2TxOutputs(accsFooBar) + total := sumOutputs(txs) + return []er{{total.IsEqual(txs[0].Coins.Plus(txs[1].Coins)), "sumOutputs: total coins are not equal"}} + }}, + + //adjustByInputs/adjustByOutputs + //sending transaction from Foo to Bar + {func() []er { + + initBalFoo := accsFooBar[0].Account.Balance + initBalBar := accsFooBar[1].Account.Balance + acc2State(accsFooBar) + + txIn := accs2TxInputs(accsFoo) + txOut := accs2TxOutputs(accsBar) + accMap, _ := getInputs(state, txIn) + accMap, _ = getOrMakeOutputs(state, accMap, txOut) + + adjustByInputs(state, accMap, txIn) + adjustByOutputs(state, accMap, txOut, false) + + endBalFoo := accMap[string(accsFooBar[0].Account.PubKey.Address())].Balance + endBalBar := accMap[string(accsFooBar[1].Account.PubKey.Address())].Balance + decrBalFoo := initBalFoo.Minus(endBalFoo) + incrBalBar := endBalBar.Minus(initBalBar) + + return []er{ + {decrBalFoo.IsEqual(txIn[0].Coins), + fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalFoo.String(), txIn[0].Coins.String())}, + {incrBalBar.IsEqual(txOut[0].Coins), + fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalBar.String(), txOut[0].Coins.String())}, + } + }}, + + //ExecTx + {func() []er { + txs := &types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFoo), + Outputs: accs2TxOutputs(accsBar), + } + + initBalFoo := accsFooBar[0].Account.Balance + initBalBar := accsFooBar[1].Account.Balance + acc2State(accsFooBar) + + //sign that puppy + signBytes := txs.SignBytes(chainID) + sig := accsFoo[0].Sign(signBytes) + txs.Inputs[0].Signature = crypto.SignatureS{sig} + + //TODO tests for CheckTx, some bad transactions + err := ExecTx(state, nil, txs, false, nil) + fmt.Println("ERR", err) + + endBalFoo := state.GetAccount(accsFooBar[0].Account.PubKey.Address()).Balance + endBalBar := state.GetAccount(accsFooBar[1].Account.PubKey.Address()).Balance + decrBalFoo := initBalFoo.Minus(endBalFoo) + decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) + incrBalBar := endBalBar.Minus(initBalBar) + + return []er{ + {decrBalFoo.IsEqual(decrBalFooExp), + fmt.Sprintf("ExecTx(sendTx): unexpected change in input coins. exp: %v, change: %v", decrBalFooExp.String(), decrBalFoo.String())}, + {incrBalBar.IsEqual(txs.Outputs[0].Coins), + fmt.Sprintf("ExecTx(sendTx): unexpected change in output coins. exp: %v, change: %v", incrBalBar.String(), txs.Outputs[0].Coins.String())}, + } + }}, + } + + //execute the tests + for _, tl := range testList { + reset() + for _, tr := range tl.tester() { //loop through all outputs of a test + assert.True(t, tr.exp, tr.msg) + } + } + +} diff --git a/types/coin.go b/types/coin.go index 90b2f30c0f..51c33ebc4a 100644 --- a/types/coin.go +++ b/types/coin.go @@ -19,6 +19,14 @@ func (coin Coin) String() string { type Coins []Coin +func (coins Coins) String() string { + out := "" + for _, coin := range coins { + out += fmt.Sprintf("(%v %v) ", coin.Denom, coin.Amount) + } + return out +} + // Must be sorted, and not have 0 amounts func (coins Coins) IsValid() bool { switch len(coins) { From 16ff0ccf4f801aad2bf0ef243048e835ded6cedd Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 21 Mar 2017 17:16:40 -0400 Subject: [PATCH 09/33] finished execution test int interim, tests finalized --- app/app.go | 2 +- app/app_test.go | 226 ++++++++++++++++++++++++++++++++++++++++ state/execution.go | 6 -- state/execution_test.go | 64 +++++++----- 4 files changed, 267 insertions(+), 31 deletions(-) create mode 100644 app/app_test.go diff --git a/app/app.go b/app/app.go index c20e220b76..f8cc5b739e 100644 --- a/app/app.go +++ b/app/app.go @@ -136,7 +136,7 @@ func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu // handle special path for account info if reqQuery.Path == "/account" { reqQuery.Path = "/key" - reqQuery.Data = append([]byte("base/a/"), reqQuery.Data...) + reqQuery.Data = sm.AccountKey(reqQuery.Data) } resQuery, err := app.eyesCli.QuerySync(reqQuery) diff --git a/app/app_test.go b/app/app_test.go new file mode 100644 index 0000000000..7bb63b21ed --- /dev/null +++ b/app/app_test.go @@ -0,0 +1,226 @@ +package app + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + abci "github.com/tendermint/abci/types" + "github.com/tendermint/basecoin/types" + "github.com/tendermint/go-crypto" + "github.com/tendermint/go-wire" + eyes "github.com/tendermint/merkleeyes/client" +) + +//TODO: + +//Query - +//Commit - see if commit works before and after + +///////////////////// +// Testing functions + +func makeAccs(secrets []string) (accs []types.PrivAccount) { + for _, secret := range secrets { + privAcc := types.PrivAccountFromSecret(secret) + privAcc.Account.Balance = types.Coins{{"mycoin", 7}} + accs = append(accs, privAcc) + } + return +} + +const chainID = "testChain" + +func TestSplitKey(t *testing.T) { + assert := assert.New(t) + prefix, suffix := splitKey("foo/bar") + assert.EqualValues("foo", prefix) + assert.EqualValues("bar", suffix) + + prefix, suffix = splitKey("foobar") + assert.EqualValues("foobar", prefix) + assert.EqualValues("", suffix) +} + +func TestSetOption(t *testing.T) { + assert := assert.New(t) + + eyesCli := eyes.NewLocalClient("", 0) + app := NewBasecoin(eyesCli) + + //testing ChainID + res := app.SetOption("base/chain_id", chainID) + assert.EqualValues(app.GetState().GetChainID(), chainID) + assert.EqualValues(res, "Success") + + accsFoo := makeAccs([]string{"foo"}) + accsFooBytes, err := json.Marshal(accsFoo[0].Account) + assert.Nil(err) + res = app.SetOption("base/account", string(accsFooBytes)) + assert.EqualValues(res, "Success") + + res = app.SetOption("base/dslfkgjdas", "") + assert.NotEqual(res, "Success") + + res = app.SetOption("dslfkgjdas", "") + assert.NotEqual(res, "Success") + + res = app.SetOption("dslfkgjdas/szfdjzs", "") + assert.NotEqual(res, "Success") +} + +//CheckTx - bad bytes, bad tx, good tx. +//DeliverTx - bad bytes, bad tx, good tx. +func TestTx(t *testing.T) { + assert := assert.New(t) + + var accsFoo, accsBar []types.PrivAccount + + var app *Basecoin + + acc2app := func(acc types.Account) { + accBytes, err := json.Marshal(acc) + assert.Nil(err) + res := app.SetOption("base/account", string(accBytes)) + assert.EqualValues(res, "Success") + } + + reset := func() { + accsFoo = makeAccs([]string{"foo"}) + accsBar = makeAccs([]string{"bar"}) + + eyesCli := eyes.NewLocalClient("", 0) + app = NewBasecoin(eyesCli) + + res := app.SetOption("base/chain_id", chainID) + assert.EqualValues(res, "Success") + + acc2app(accsFoo[0].Account) + acc2app(accsBar[0].Account) + + resabci := app.Commit() + assert.True(resabci.IsOK(), resabci) + } + reset() + + accs2TxInputs := func(accs []types.PrivAccount, seq int) []types.TxInput { + var txs []types.TxInput + for _, acc := range accs { + tx := types.NewTxInput( + acc.Account.PubKey, + types.Coins{{"mycoin", 5}}, + seq) + txs = append(txs, tx) + } + return txs + } + + //turn a list of accounts into basic list of transaction outputs + accs2TxOutputs := func(accs []types.PrivAccount) []types.TxOutput { + var txs []types.TxOutput + for _, acc := range accs { + tx := types.TxOutput{ + acc.Account.PubKey.Address(), + types.Coins{{"mycoin", 4}}} + txs = append(txs, tx) + } + return txs + } + + getTx := func(seq int) *types.SendTx { + txs := &types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFoo, seq), + Outputs: accs2TxOutputs(accsBar), + } + signBytes := txs.SignBytes(chainID) + for i, _ := range txs.Inputs { + txs.Inputs[i].Signature = crypto.SignatureS{accsFoo[i].Sign(signBytes)} + } + + return txs + } + txs := getTx(1) + + exec := func(checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { + + initBalFoo := app.GetState().GetAccount(accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := app.GetState().GetAccount(accsBar[0].Account.PubKey.Address()).Balance + + txBytes := []byte(wire.BinaryBytes(struct { + types.Tx `json:"unwrap"` + }{txs})) + + if checkTx { + res = app.CheckTx(txBytes) + } else { + res = app.DeliverTx(txBytes) + } + + endBalFoo := app.GetState().GetAccount(accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := app.GetState().GetAccount(accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(txs.Outputs[0].Coins) + } + + //Bad Balance + accsFoo[0].Balance = types.Coins{{"mycoin", 2}} + acc2app(accsFoo[0].Account) + res, _, _, _, _ := exec(true) + assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) + res, foo, fooexp, bar, barexp := exec(false) + assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) + assert.True(!foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) + assert.True(!bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) + + //Regular CheckTx + reset() + res, _, _, _, _ = exec(true) + assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) + + //Regular DeliverTx + reset() + res, foo, fooexp, bar, barexp = exec(false) + assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) + assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) + assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) + + /////////////////////// + //test Commit/Query + //After Delivered TX foo should have no more coins to send, + // but because the state hasn't yet been committed, checkTx should still + // pass but after a commit it shouldn't + + reset() + + txs = getTx(1) + res, _, _, _, _ = exec(false) + assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) + + txs = getTx(2) + res, _, _, _, _ = exec(true) + assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) + + resQueryPreCommit := app.Query(abci.RequestQuery{ + Path: "/account", + Data: accsFoo[0].Account.PubKey.Address(), + }) + + res = app.Commit() + assert.True(res.IsOK(), res) + + resQueryPostCommit := app.Query(abci.RequestQuery{ + Path: "/account", + Data: accsFoo[0].Account.PubKey.Address(), + }) + fmt.Println(resQueryPreCommit) + fmt.Println(resQueryPostCommit) + + assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") + txs = getTx(3) + res, _, _, _, _ = exec(true) + assert.True(res.IsErr(), fmt.Sprintf("Commit, CheckTx: Expected error return from CheckTx, returned: %v", res)) + +} diff --git a/state/execution.go b/state/execution.go index 1cd5365337..eb7f3c6906 100644 --- a/state/execution.go +++ b/state/execution.go @@ -1,8 +1,6 @@ package state import ( - "fmt" - abci "github.com/tendermint/abci/types" "github.com/tendermint/basecoin/types" cmn "github.com/tendermint/go-common" @@ -221,7 +219,6 @@ func validateInputsBasic(ins []types.TxInput) (res abci.Result) { // Validate inputs and compute total amount of coins func validateInputsAdvanced(accounts map[string]*types.Account, signBytes []byte, ins []types.TxInput) (total types.Coins, res abci.Result) { for _, in := range ins { - fmt.Println("IN", in) acc := accounts[string(in.Address)] if acc == nil { cmn.PanicSanity("validateInputsAdvanced() expects account in accounts") @@ -247,9 +244,6 @@ func validateInputAdvanced(acc *types.Account, signBytes []byte, in types.TxInpu return abci.ErrBaseInsufficientFunds.AppendLog(cmn.Fmt("balance is %v, tried to send %v", balance, in.Coins)) } // Check signatures - fmt.Printf("signbytes %X\n", signBytes) - fmt.Println("PUBKEY", acc.PubKey) - fmt.Println("") if !acc.PubKey.VerifyBytes(signBytes, in.Signature.Signature) { return abci.ErrBaseInvalidSignature.AppendLog(cmn.Fmt("SignBytes: %X", signBytes)) } diff --git a/state/execution_test.go b/state/execution_test.go index a0afbaa65f..98d5848f20 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" + abci "github.com/tendermint/abci/types" "github.com/tendermint/basecoin/types" "github.com/tendermint/go-crypto" ) @@ -48,7 +49,7 @@ func TestExecution(t *testing.T) { for _, acc := range accs { tx := types.NewTxInput( acc.Account.PubKey, - types.Coins{{"mycoin", 10}}, + types.Coins{{"mycoin", 5}}, 1) txs = append(txs, tx) } @@ -61,7 +62,7 @@ func TestExecution(t *testing.T) { for _, acc := range accs { tx := types.TxOutput{ acc.Account.PubKey.Address(), - types.Coins{{"mycoin", 9}}} + types.Coins{{"mycoin", 4}}} txs = append(txs, tx) } return txs @@ -148,9 +149,7 @@ func TestExecution(t *testing.T) { _, res1 := getOrMakeOutputs(state, nil, txs1) mapRes2, res2 := getOrMakeOutputs(state, nil, txs2) - //TODO Fix this commented out test //test the map results - //acc2, map2ok := mapRes2[string(txs2[0].Address)] _, map2ok := mapRes2[string(txs2[0].Address)] return []er{ @@ -158,7 +157,6 @@ func TestExecution(t *testing.T) { {!res2.IsErr(), "getOrMakeOutputs: error when sending to new account"}, {map2ok, "getOrMakeOutputs: account output does not contain new account map item"}, } - //{accs2[0].PubKey.Equals(acc2.PubKey), "getOrMakeOutputs: account output does not contain new account pointer"}} }}, //validate input basic @@ -294,30 +292,48 @@ func TestExecution(t *testing.T) { Outputs: accs2TxOutputs(accsBar), } - initBalFoo := accsFooBar[0].Account.Balance - initBalBar := accsFooBar[1].Account.Balance - acc2State(accsFooBar) + acc2State(accsFoo) + acc2State(accsBar) + signSend(txs, accsFoo) - //sign that puppy - signBytes := txs.SignBytes(chainID) - sig := accsFoo[0].Sign(signBytes) - txs.Inputs[0].Signature = crypto.SignatureS{sig} + exec := func(checkTx bool) (ExecTxRes abci.Result, foo, fooExp, bar, barExp types.Coins) { - //TODO tests for CheckTx, some bad transactions - err := ExecTx(state, nil, txs, false, nil) - fmt.Println("ERR", err) + initBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance + res := ExecTx(state, nil, txs, checkTx, nil) + endBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(txs.Outputs[0].Coins) + } - endBalFoo := state.GetAccount(accsFooBar[0].Account.PubKey.Address()).Balance - endBalBar := state.GetAccount(accsFooBar[1].Account.PubKey.Address()).Balance - decrBalFoo := initBalFoo.Minus(endBalFoo) - decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) - incrBalBar := endBalBar.Minus(initBalBar) + //Bad Balance + accsFoo[0].Balance = types.Coins{{"mycoin", 2}} + acc2State(accsFoo) + res1, _, _, _, _ := exec(true) + res2, foo2, fooexp2, bar2, barexp2 := exec(false) + + //Regular CheckTx + reset() + acc2State(accsFoo) + acc2State(accsBar) + res3, _, _, _, _ := exec(true) + + //Regular DeliverTx + reset() + acc2State(accsFoo) + acc2State(accsBar) + res4, foo4, fooexp4, bar4, barexp4 := exec(false) return []er{ - {decrBalFoo.IsEqual(decrBalFooExp), - fmt.Sprintf("ExecTx(sendTx): unexpected change in input coins. exp: %v, change: %v", decrBalFooExp.String(), decrBalFoo.String())}, - {incrBalBar.IsEqual(txs.Outputs[0].Coins), - fmt.Sprintf("ExecTx(sendTx): unexpected change in output coins. exp: %v, change: %v", incrBalBar.String(), txs.Outputs[0].Coins.String())}, + {res1.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res1)}, + {res2.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res2)}, + {!foo2.IsEqual(fooexp2), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo2, fooexp2)}, + {!bar2.IsEqual(barexp2), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar2, barexp2)}, + {res3.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res3)}, + {res4.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res4)}, + {foo4.IsEqual(fooexp4), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo4, fooexp4)}, + {bar4.IsEqual(barexp4), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar4, barexp4)}, } }}, } From 0720a03daebfeb18983a3ccf7111d276139a6415 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 23 Mar 2017 20:51:50 -0400 Subject: [PATCH 10/33] tests cleanup cleanup --- app/app_test.go | 262 +++++++------- cmd/commands/utils_test.go | 56 +-- plugins/counter/counter_test.go | 22 +- plugins/ibc/ibc_test.go | 37 +- scripts/print_test_account.go | 6 +- state/execution_test.go | 598 +++++++++++++++----------------- state/state_test.go | 60 ++-- types/account_test.go | 6 +- types/coin_test.go | 32 +- types/kvstore_test.go | 53 ++- types/plugin_test.go | 25 +- types/tx_test.go | 38 +- 12 files changed, 566 insertions(+), 629 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 7bb63b21ed..e5fb3b3f28 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -6,6 +6,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/abci/types" "github.com/tendermint/basecoin/types" "github.com/tendermint/go-crypto" @@ -13,11 +15,6 @@ import ( eyes "github.com/tendermint/merkleeyes/client" ) -//TODO: - -//Query - -//Commit - see if commit works before and after - ///////////////////// // Testing functions @@ -70,157 +67,172 @@ func TestSetOption(t *testing.T) { assert.NotEqual(res, "Success") } +//////////////////////// TxTest + +type testValues struct { + t *testing.T + app *Basecoin + accsFoo []types.PrivAccount + accsBar []types.PrivAccount +} + +func (tv *testValues) acc2app(acc types.Account) { + accBytes, err := json.Marshal(acc) + require.Nil(tv.t, err) + res := tv.app.SetOption("base/account", string(accBytes)) + require.EqualValues(tv.t, res, "Success") +} + +func (tv *testValues) appInit() { + tv.accsFoo = makeAccs([]string{"foo"}) + tv.accsBar = makeAccs([]string{"bar"}) + + eyesCli := eyes.NewLocalClient("", 0) + tv.app = NewBasecoin(eyesCli) + + res := tv.app.SetOption("base/chain_id", chainID) + require.EqualValues(tv.t, res, "Success") + + tv.acc2app(tv.accsFoo[0].Account) + tv.acc2app(tv.accsBar[0].Account) + + resabci := tv.app.Commit() + require.True(tv.t, resabci.IsOK(), resabci) +} + +func accs2TxInputs(accs []types.PrivAccount, seq int) []types.TxInput { + var txs []types.TxInput + for _, acc := range accs { + tx := types.NewTxInput( + acc.Account.PubKey, + types.Coins{{"mycoin", 5}}, + seq) + txs = append(txs, tx) + } + return txs +} + +//turn a list of accounts into basic list of transaction outputs +func accs2TxOutputs(accs []types.PrivAccount) []types.TxOutput { + var txs []types.TxOutput + for _, acc := range accs { + tx := types.TxOutput{ + acc.Account.PubKey.Address(), + types.Coins{{"mycoin", 4}}} + txs = append(txs, tx) + } + return txs +} + +func (tv testValues) getTx(seq int) *types.SendTx { + txs := &types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(tv.accsFoo, seq), + Outputs: accs2TxOutputs(tv.accsBar), + } + signBytes := txs.SignBytes(chainID) + for i, _ := range txs.Inputs { + txs.Inputs[i].Signature = crypto.SignatureS{tv.accsFoo[i].Sign(signBytes)} + } + + return txs +} + +func (tv testValues) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { + + initBalFoo := tv.app.GetState().GetAccount(tv.accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := tv.app.GetState().GetAccount(tv.accsBar[0].Account.PubKey.Address()).Balance + + txBytes := []byte(wire.BinaryBytes(struct { + types.Tx `json:"unwrap"` + }{tx})) + + if checkTx { + res = tv.app.CheckTx(txBytes) + } else { + res = tv.app.DeliverTx(txBytes) + } + + endBalFoo := tv.app.GetState().GetAccount(tv.accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := tv.app.GetState().GetAccount(tv.accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) +} + //CheckTx - bad bytes, bad tx, good tx. //DeliverTx - bad bytes, bad tx, good tx. func TestTx(t *testing.T) { assert := assert.New(t) - var accsFoo, accsBar []types.PrivAccount - - var app *Basecoin - - acc2app := func(acc types.Account) { - accBytes, err := json.Marshal(acc) - assert.Nil(err) - res := app.SetOption("base/account", string(accBytes)) - assert.EqualValues(res, "Success") - } - - reset := func() { - accsFoo = makeAccs([]string{"foo"}) - accsBar = makeAccs([]string{"bar"}) - - eyesCli := eyes.NewLocalClient("", 0) - app = NewBasecoin(eyesCli) - - res := app.SetOption("base/chain_id", chainID) - assert.EqualValues(res, "Success") - - acc2app(accsFoo[0].Account) - acc2app(accsBar[0].Account) - - resabci := app.Commit() - assert.True(resabci.IsOK(), resabci) - } - reset() - - accs2TxInputs := func(accs []types.PrivAccount, seq int) []types.TxInput { - var txs []types.TxInput - for _, acc := range accs { - tx := types.NewTxInput( - acc.Account.PubKey, - types.Coins{{"mycoin", 5}}, - seq) - txs = append(txs, tx) - } - return txs - } - - //turn a list of accounts into basic list of transaction outputs - accs2TxOutputs := func(accs []types.PrivAccount) []types.TxOutput { - var txs []types.TxOutput - for _, acc := range accs { - tx := types.TxOutput{ - acc.Account.PubKey.Address(), - types.Coins{{"mycoin", 4}}} - txs = append(txs, tx) - } - return txs - } - - getTx := func(seq int) *types.SendTx { - txs := &types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFoo, seq), - Outputs: accs2TxOutputs(accsBar), - } - signBytes := txs.SignBytes(chainID) - for i, _ := range txs.Inputs { - txs.Inputs[i].Signature = crypto.SignatureS{accsFoo[i].Sign(signBytes)} - } - - return txs - } - txs := getTx(1) - - exec := func(checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { - - initBalFoo := app.GetState().GetAccount(accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := app.GetState().GetAccount(accsBar[0].Account.PubKey.Address()).Balance - - txBytes := []byte(wire.BinaryBytes(struct { - types.Tx `json:"unwrap"` - }{txs})) - - if checkTx { - res = app.CheckTx(txBytes) - } else { - res = app.DeliverTx(txBytes) - } - - endBalFoo := app.GetState().GetAccount(accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := app.GetState().GetAccount(accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(txs.Outputs[0].Coins) - } + tv := testValues{t: t} + tv.appInit() //Bad Balance - accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - acc2app(accsFoo[0].Account) - res, _, _, _, _ := exec(true) + tv.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} + tv.acc2app(tv.accsFoo[0].Account) + res, _, _, _, _ := tv.exec(tv.getTx(1), true) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) - res, foo, fooexp, bar, barexp := exec(false) + res, foo, fooexp, bar, barexp := tv.exec(tv.getTx(1), false) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) assert.True(!foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) assert.True(!bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) //Regular CheckTx - reset() - res, _, _, _, _ = exec(true) + tv.appInit() + res, _, _, _, _ = tv.exec(tv.getTx(1), true) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) //Regular DeliverTx - reset() - res, foo, fooexp, bar, barexp = exec(false) + tv.appInit() + res, foo, fooexp, bar, barexp = tv.exec(tv.getTx(1), false) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) +} - /////////////////////// - //test Commit/Query - //After Delivered TX foo should have no more coins to send, - // but because the state hasn't yet been committed, checkTx should still - // pass but after a commit it shouldn't +func TestQuery(t *testing.T) { + assert := assert.New(t) + tv := testValues{t: t} + tv.appInit() - reset() - - txs = getTx(1) - res, _, _, _, _ = exec(false) + res, _, _, _, _ := tv.exec(tv.getTx(1), false) assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) - txs = getTx(2) - res, _, _, _, _ = exec(true) - assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) - - resQueryPreCommit := app.Query(abci.RequestQuery{ + resQueryPreCommit := tv.app.Query(abci.RequestQuery{ Path: "/account", - Data: accsFoo[0].Account.PubKey.Address(), + Data: tv.accsFoo[0].Account.PubKey.Address(), }) - res = app.Commit() + res = tv.app.Commit() assert.True(res.IsOK(), res) - resQueryPostCommit := app.Query(abci.RequestQuery{ + resQueryPostCommit := tv.app.Query(abci.RequestQuery{ Path: "/account", - Data: accsFoo[0].Account.PubKey.Address(), + Data: tv.accsFoo[0].Account.PubKey.Address(), }) fmt.Println(resQueryPreCommit) fmt.Println(resQueryPostCommit) - assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") - txs = getTx(3) - res, _, _, _, _ = exec(true) - assert.True(res.IsErr(), fmt.Sprintf("Commit, CheckTx: Expected error return from CheckTx, returned: %v", res)) - +} + +func TestCommit(t *testing.T) { + assert := assert.New(t) + tv := testValues{t: t} + tv.appInit() + + //After Delivered TX foo should have no more coins to send, + // but because the state hasn't yet been committed, checkTx should still + // pass but after a commit it shouldn't + res, _, _, _, _ := tv.exec(tv.getTx(1), false) + assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) + + res, _, _, _, _ = tv.exec(tv.getTx(2), true) + assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) + + res = tv.app.Commit() + assert.True(res.IsOK(), res) + + res, _, _, _, _ = tv.exec(tv.getTx(3), true) + assert.True(res.IsErr(), fmt.Sprintf("Commit, CheckTx: Expected error return from CheckTx, returned: %v", res)) } diff --git a/cmd/commands/utils_test.go b/cmd/commands/utils_test.go index f16927d486..138afac53f 100644 --- a/cmd/commands/utils_test.go +++ b/cmd/commands/utils_test.go @@ -9,6 +9,7 @@ import ( ) func TestHex(t *testing.T) { + assert := assert.New(t) //test isHex hexNoPrefix := hex.EncodeToString([]byte("foobar")) @@ -16,27 +17,17 @@ func TestHex(t *testing.T) { str := "foobar" strWPrefix := "0xfoobar" - //define the list of coin tests - var testList = []struct { - testPass bool - errMsg string - }{ - {isHex(hexWPrefix), "isHex not identifying hex with 0x prefix"}, - {!isHex(hexNoPrefix), "isHex shouldn't identify hex without 0x prefix"}, - {!isHex(str), "isHex shouldn't identify non-hex string"}, - {!isHex(strWPrefix), "isHex shouldn't identify non-hex string with 0x prefix"}, - {StripHex(hexWPrefix) == hexNoPrefix, "StripHex doesn't remove first two characters"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass, tl.errMsg) - } + assert.True(isHex(hexWPrefix), "isHex not identifying hex with 0x prefix") + assert.False(isHex(hexNoPrefix), "isHex shouldn't identify hex without 0x prefix") + assert.False(isHex(str), "isHex shouldn't identify non-hex string") + assert.False(isHex(strWPrefix), "isHex shouldn't identify non-hex string with 0x prefix") + assert.True(StripHex(hexWPrefix) == hexNoPrefix, "StripHex doesn't remove first two characters") } //Test the parse coin and parse coins functionality func TestParse(t *testing.T) { + assert := assert.New(t) makeCoin := func(str string) types.Coin { coin, err := ParseCoin(str) @@ -54,27 +45,16 @@ func TestParse(t *testing.T) { return coin } - //define the list of coin tests - var testList = []struct { - testPass bool - errMsg string - }{ - //testing ParseCoin Function - {types.Coin{} == makeCoin(""), "parseCoin makes bad empty coin"}, - {types.Coin{"fooCoin", 1} == makeCoin("1fooCoin"), "parseCoin makes bad coins"}, - {types.Coin{"barCoin", 10} == makeCoin("10 barCoin"), "parseCoin makes bad coins"}, + //testing ParseCoin Function + assert.Equal(types.Coin{}, makeCoin(""), "parseCoin makes bad empty coin") + assert.Equal(types.Coin{"fooCoin", 1}, makeCoin("1fooCoin"), "parseCoin makes bad coins") + assert.Equal(types.Coin{"barCoin", 10}, makeCoin("10 barCoin"), "parseCoin makes bad coins") - //testing ParseCoins Function - {types.Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), - "parseCoins doesn't parse a single coin"}, - {types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")), - "parseCoins doesn't properly parse two coins"}, - {types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")), - "parseCoins doesn't properly parse two coins which use spaces"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass, tl.errMsg) - } + //testing ParseCoins Function + assert.True(types.Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), + "parseCoins doesn't parse a single coin") + assert.True(types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")), + "parseCoins doesn't properly parse two coins") + assert.True(types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")), + "parseCoins doesn't properly parse two coins which use spaces") } diff --git a/plugins/counter/counter_test.go b/plugins/counter/counter_test.go index 9c76544bc5..f7c658a9af 100644 --- a/plugins/counter/counter_test.go +++ b/plugins/counter/counter_test.go @@ -15,6 +15,7 @@ import ( ) func TestCounterPlugin(t *testing.T) { + assert := assert.New(t) // Basecoin initialization eyesCli := eyescli.NewLocalClient("", 0) @@ -64,39 +65,40 @@ func TestCounterPlugin(t *testing.T) { // Test a basic send, no fee res := DeliverCounterTx(0, types.Coin{}, types.Coins{{"", 1}}, 1, types.Coins{}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test fee prevented transaction res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 1}}, 2, types.Coins{}) - assert.True(t, res.IsErr(), res.String()) + assert.True(res.IsErr(), res.String()) // Test input equals fee res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 2}}, 2, types.Coins{}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test more input than fee res = DeliverCounterTx(0, types.Coin{"", 2}, types.Coins{{"", 3}}, 3, types.Coins{}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test input equals fee+appFee res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 1}}, 4, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test fee+appFee prevented transaction, not enough "" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 2}, {"gold", 1}}, 5, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsErr(), res.String()) + assert.True(res.IsErr(), res.String()) // Test fee+appFee prevented transaction, not enough "gold" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 1}}, 5, types.Coins{{"", 2}, {"gold", 2}}) - assert.True(t, res.IsErr(), res.String()) + assert.True(res.IsErr(), res.String()) // Test more input than fee, more "" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 4}, {"gold", 1}}, 6, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) // Test more input than fee, more "gold" res = DeliverCounterTx(0, types.Coin{"", 1}, types.Coins{{"", 3}, {"gold", 2}}, 7, types.Coins{{"", 2}, {"gold", 1}}) - assert.True(t, res.IsOK(), res.String()) + assert.True(res.IsOK(), res.String()) + + // REF: DeliverCounterTx(gas, fee, inputCoins, inputSequence, appFee) {w - // REF: DeliverCounterTx(gas, fee, inputCoins, inputSequence, appFee) { } diff --git a/plugins/ibc/ibc_test.go b/plugins/ibc/ibc_test.go index 0f2ab88540..9439f43784 100644 --- a/plugins/ibc/ibc_test.go +++ b/plugins/ibc/ibc_test.go @@ -65,6 +65,7 @@ func (pas PrivAccountsByAddress) Swap(i, j int) { //-------------------------------------------------------------------------------- func TestIBCPlugin(t *testing.T) { + assert := assert.New(t) eyesClient := eyes.NewLocalClient("", 0) store := types.NewKVCache(eyesClient) @@ -88,7 +89,7 @@ func TestIBCPlugin(t *testing.T) { Genesis: "", }, }})) - assert.Equal(t, IBCCodeEncodingError, res.Code) + assert.Equal(IBCCodeEncodingError, res.Code) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -99,7 +100,7 @@ func TestIBCPlugin(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.True(t, res.IsOK(), res.Log) + assert.True(res.IsOK(), res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -110,7 +111,7 @@ func TestIBCPlugin(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.Equal(t, IBCCodeChainAlreadyExists, res.Code, res.Log) + assert.Equal(IBCCodeChainAlreadyExists, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -125,7 +126,7 @@ func TestIBCPlugin(t *testing.T) { res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{ Packet: packet, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -133,7 +134,7 @@ func TestIBCPlugin(t *testing.T) { res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{ Packet: packet, }})) - assert.Equal(t, IBCCodePacketAlreadyExists, res.Code, res.Log) + assert.Equal(IBCCodePacketAlreadyExists, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -175,7 +176,7 @@ func TestIBCPlugin(t *testing.T) { Header: header, Commit: commit, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -190,10 +191,10 @@ func TestIBCPlugin(t *testing.T) { Data: packetKey, Prove: true, }) - assert.Nil(t, err) + assert.Nil(err) var proof *merkle.IAVLProof err = wire.ReadBinaryBytes(resQuery.Proof, &proof) - assert.Nil(t, err) + assert.Nil(err) // Post a packet res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketPostTx{ @@ -202,12 +203,13 @@ func TestIBCPlugin(t *testing.T) { Packet: packet, Proof: proof, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() } func TestIBCPluginBadCommit(t *testing.T) { + assert := assert.New(t) eyesClient := eyes.NewLocalClient("", 0) store := types.NewKVCache(eyesClient) @@ -231,7 +233,7 @@ func TestIBCPluginBadCommit(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.True(t, res.IsOK(), res.Log) + assert.True(res.IsOK(), res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -273,13 +275,14 @@ func TestIBCPluginBadCommit(t *testing.T) { Header: header, Commit: commit, }})) - assert.Equal(t, IBCCodeInvalidCommit, res.Code, res.Log) + assert.Equal(IBCCodeInvalidCommit, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() } func TestIBCPluginBadProof(t *testing.T) { + assert := assert.New(t) eyesClient := eyes.NewLocalClient("", 0) store := types.NewKVCache(eyesClient) @@ -303,7 +306,7 @@ func TestIBCPluginBadProof(t *testing.T) { Genesis: string(genDocJSON_1), }, }})) - assert.True(t, res.IsOK(), res.Log) + assert.True(res.IsOK(), res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -318,7 +321,7 @@ func TestIBCPluginBadProof(t *testing.T) { res = ibcPlugin.RunTx(store, ctx, wire.BinaryBytes(struct{ IBCTx }{IBCPacketCreateTx{ Packet: packet, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -360,7 +363,7 @@ func TestIBCPluginBadProof(t *testing.T) { Header: header, Commit: commit, }})) - assert.Equal(t, abci.CodeType_OK, res.Code, res.Log) + assert.Equal(abci.CodeType_OK, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() @@ -375,10 +378,10 @@ func TestIBCPluginBadProof(t *testing.T) { Data: packetKey, Prove: true, }) - assert.Nil(t, err) + assert.Nil(err) var proof *merkle.IAVLProof err = wire.ReadBinaryBytes(resQuery.Proof, &proof) - assert.Nil(t, err) + assert.Nil(err) // Mutate the proof proof.InnerNodes[0].Height += 1 @@ -390,7 +393,7 @@ func TestIBCPluginBadProof(t *testing.T) { Packet: packet, Proof: proof, }})) - assert.Equal(t, IBCCodeInvalidProof, res.Code, res.Log) + assert.Equal(IBCCodeInvalidProof, res.Code, res.Log) t.Log(">>", strings.Join(store.GetLogLines(), "\n")) store.ClearLogLines() } diff --git a/scripts/print_test_account.go b/scripts/print_test_account.go index 11998c6639..12e4bd005f 100644 --- a/scripts/print_test_account.go +++ b/scripts/print_test_account.go @@ -15,8 +15,8 @@ Address: D9B727742AA29FA638DC63D70813C976014C4CE0 */ func main() { tAcc := tests.PrivAccountFromSecret("test") - fmt.Println("PrivKey:", fmt.Sprintf("%X", tAcc.PrivKey.Bytes())) - fmt.Println("PubKey:", fmt.Sprintf("%X", tAcc.Account.PubKey.Bytes())) - fmt.Println("Address:", fmt.Sprintf("%X", tAcc.Account.PubKey.Address())) + fmt.Printf("PrivKey:%X\n", tAcc.PrivKey.Bytes()) + fmt.Printf("PubKey:%X\n", tAcc.Account.PubKey.Bytes()) + fmt.Printf("Address:%X\n", tAcc.Account.PubKey.Address()) fmt.Println(string(wire.JSONBytesPretty(tAcc))) } diff --git a/state/execution_test.go b/state/execution_test.go index 98d5848f20..b6e09d3799 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -11,339 +11,319 @@ import ( "github.com/tendermint/go-crypto" ) -func TestExecution(t *testing.T) { +//States and Stores for tests +var ( + store types.KVStore + state *State + accsFoo, accsBar, accsFooBar, accsDup []types.PrivAccount + chainID string = "test_chain_id" +) - //States and Stores for tests - var store types.KVStore - var state *State - var accsFoo, accsBar, accsFooBar, accsDup []types.PrivAccount - chainID := "test_chain_id" +func makeAccs(secrets []string) (accs []types.PrivAccount) { - makeAccs := func(secrets []string) (accs []types.PrivAccount) { - - for _, secret := range secrets { - privAcc := types.PrivAccountFromSecret(secret) - privAcc.Account.Balance = types.Coins{{"mycoin", 1000}} - accs = append(accs, privAcc) - } - return accs + for _, secret := range secrets { + privAcc := types.PrivAccountFromSecret(secret) + privAcc.Account.Balance = types.Coins{{"mycoin", 1000}} + accs = append(accs, privAcc) } + return accs +} - acc2State := func(accs []types.PrivAccount) { - for _, acc := range accs { - state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) - } +func acc2State(accs []types.PrivAccount) { + for _, acc := range accs { + state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) } +} - //each tx input signs the tx bytes - signSend := func(tx *types.SendTx, accs []types.PrivAccount) { - signBytes := tx.SignBytes(chainID) - for i, _ := range tx.Inputs { - tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} - } +//each tx input signs the tx bytes +func signSend(tx *types.SendTx, accs []types.PrivAccount) { + signBytes := tx.SignBytes(chainID) + for i, _ := range tx.Inputs { + tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} } +} - //turn a list of accounts into basic list of transaction inputs - accs2TxInputs := func(accs []types.PrivAccount) []types.TxInput { - var txs []types.TxInput - for _, acc := range accs { - tx := types.NewTxInput( - acc.Account.PubKey, - types.Coins{{"mycoin", 5}}, - 1) - txs = append(txs, tx) - } - return txs +//turn a list of accounts into basic list of transaction inputs +func accs2TxInputs(accs []types.PrivAccount) []types.TxInput { + var txs []types.TxInput + for _, acc := range accs { + tx := types.NewTxInput( + acc.Account.PubKey, + types.Coins{{"mycoin", 5}}, + 1) + txs = append(txs, tx) } + return txs +} - //turn a list of accounts into basic list of transaction outputs - accs2TxOutputs := func(accs []types.PrivAccount) []types.TxOutput { - var txs []types.TxOutput - for _, acc := range accs { - tx := types.TxOutput{ - acc.Account.PubKey.Address(), - types.Coins{{"mycoin", 4}}} - txs = append(txs, tx) - } - return txs +//turn a list of accounts into basic list of transaction outputs +func accs2TxOutputs(accs []types.PrivAccount) []types.TxOutput { + var txs []types.TxOutput + for _, acc := range accs { + tx := types.TxOutput{ + acc.Account.PubKey.Address(), + types.Coins{{"mycoin", 4}}} + txs = append(txs, tx) } + return txs +} - //reset the store/state/Inputs - reset := func() { - accsFoo = makeAccs([]string{"foo"}) - accsBar = makeAccs([]string{"bar"}) - accsFooBar = makeAccs([]string{"foo", "bar"}) - accsDup = makeAccs([]string{"foo", "foo", "foo"}) +//reset the store/state/Inputs +func reset() { + accsFoo = makeAccs([]string{"foo"}) + accsBar = makeAccs([]string{"bar"}) + accsFooBar = makeAccs([]string{"foo", "bar"}) + accsDup = makeAccs([]string{"foo", "foo", "foo"}) - store = types.NewMemKVStore() - state = NewState(store) - state.SetChainID(chainID) - } + store = types.NewMemKVStore() + state = NewState(store) + state.SetChainID(chainID) +} - type er struct { - exp bool //assert true - msg string //msg is assert fails - } +func TestGetInputs(t *testing.T) { + assert := assert.New(t) - //define the test list - testList := []struct { - tester func() []er - }{ - /////////////// - //getInputs + //nil submissions + reset() + acc, res := getInputs(nil, nil) + assert.False(res.IsErr(), "getInputs: error on nil submission") + assert.Zero(len(acc), "getInputs: accounts returned on nil submission") - //nil submissions - {func() []er { - acc, res := getInputs(nil, nil) - return []er{ - {!res.IsErr(), "getInputs: error on nil submission"}, - {len(acc) == 0, "getInputs: accounts returned on nil submission"}, - } - }}, + //test getInputs for registered, non-registered account + reset() + txs := accs2TxInputs(accsFoo) + _, res = getInputs(state, txs) + assert.True(res.IsErr(), "getInputs: expected to getInput from registered Input") - //test getInputs for registered, non-registered account - {func() []er { - txs := accs2TxInputs(accsFoo) - _, res1 := getInputs(state, txs) - acc2State(accsFoo) - _, res2 := getInputs(state, txs) - return []er{ - {res1.IsErr(), "getInputs: expected to getInput from registered Input"}, - {!res2.IsErr(), "getInputs: expected to getInput from registered Input"}, - } - }}, + acc2State(accsFoo) + _, res = getInputs(state, txs) + assert.False(res.IsErr(), "getInputs: expected to getInput from registered Input") - //test sending duplicate accounts - {func() []er { - acc2State(accsDup) - txs := accs2TxInputs(accsDup) - _, res := getInputs(state, txs) - return []er{{res.IsErr(), "getInputs: expected error when sending duplicate accounts"}} - }}, + //test sending duplicate accounts + reset() + acc2State(accsDup) + txs = accs2TxInputs(accsDup) + _, res = getInputs(state, txs) + assert.True(res.IsErr(), "getInputs: expected error when sending duplicate accounts") +} - /////////////////// - //getOrMakeOutputs +func TestGetOrMakeOutputs(t *testing.T) { + assert := assert.New(t) - //nil submissions - {func() []er { - acc, res := getOrMakeOutputs(nil, nil, nil) - return []er{ - {!res.IsErr(), "getOrMakeOutputs: error on nil submission"}, - {len(acc) == 0, "getOrMakeOutputs: accounts returned on nil submission"}, - } - }}, + //nil submissions + reset() + acc, res := getOrMakeOutputs(nil, nil, nil) + assert.False(res.IsErr(), "getOrMakeOutputs: error on nil submission") + assert.Zero(len(acc), "getOrMakeOutputs: accounts returned on nil submission") - //test sending duplicate accounts - {func() []er { - txs := accs2TxOutputs(accsDup) - _, res := getOrMakeOutputs(state, nil, txs) - return []er{{res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts"}} - }}, + //test sending duplicate accounts + reset() + txs := accs2TxOutputs(accsDup) + _, res = getOrMakeOutputs(state, nil, txs) + assert.True(res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts") - //test sending to existing/new account account - {func() []er { - txs1 := accs2TxOutputs(accsFoo) - txs2 := accs2TxOutputs(accsBar) + //test sending to existing/new account account + reset() + txs1 := accs2TxOutputs(accsFoo) + txs2 := accs2TxOutputs(accsBar) - acc2State(accsFoo) - _, res1 := getOrMakeOutputs(state, nil, txs1) - mapRes2, res2 := getOrMakeOutputs(state, nil, txs2) + acc2State(accsFoo) + _, res = getOrMakeOutputs(state, nil, txs1) + assert.False(res.IsErr(), "getOrMakeOutputs: error when sending to existing account") - //test the map results - _, map2ok := mapRes2[string(txs2[0].Address)] + mapRes2, res := getOrMakeOutputs(state, nil, txs2) + assert.False(res.IsErr(), "getOrMakeOutputs: error when sending to new account") - return []er{ - {!res1.IsErr(), "getOrMakeOutputs: error when sending to existing account"}, - {!res2.IsErr(), "getOrMakeOutputs: error when sending to new account"}, - {map2ok, "getOrMakeOutputs: account output does not contain new account map item"}, - } - }}, - - //validate input basic - {func() []er { - txs := accs2TxInputs(accsFoo) - res1 := validateInputsBasic(txs) - txs[0].Coins[0].Amount = 0 - res2 := validateInputsBasic(txs) - return []er{ - {!res1.IsErr(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res1.Error())}, - {res2.IsErr(), "validateInputsBasic: expected error on bad tx input"}, - } - }}, - - //validate inputs advanced - {func() []er { - txs := types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFooBar), - Outputs: accs2TxOutputs(accsBar), - } - - acc2State(accsFooBar) - accMap, res1 := getInputs(state, txs.Inputs) - signBytes := txs.SignBytes(chainID) - - //test bad case, unsigned - totalCoins, res2 := validateInputsAdvanced(accMap, signBytes, txs.Inputs) - - //test good case sgined - signSend(&txs, accsFooBar) - totalCoins, res3 := validateInputsAdvanced(accMap, signBytes, txs.Inputs) - - return []er{ - {!res1.IsErr(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res1.Error())}, - {res2.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input"}, - {!res3.IsErr(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res3.Error())}, - {totalCoins.IsEqual(txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins)), "ValidateInputsAdvanced: transaction total coins are not equal"}, - } - }}, - - //validate input advanced - {func() []er { - txs := types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFooBar), - Outputs: accs2TxOutputs(accsBar), - } - - acc2State(accsFooBar) - signBytes := txs.SignBytes(chainID) - - //unsigned case - res1 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) - - //good signed case - signSend(&txs, accsFooBar) - res2 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) - - //bad sequence case - accsFooBar[0].Sequence = 2 - signSend(&txs, accsFooBar) - res3 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) - accsFooBar[0].Account.Sequence = 1 //restore sequence - - //bad balance case - accsFooBar[1].Balance = types.Coins{{"mycoin", 2}} - signSend(&txs, accsFooBar) - res4 := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) - - return []er{ - {res1.IsErr(), "validateInputAdvanced: expected error on tx input without signature"}, - {!res2.IsErr(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res1.Error())}, - {res3.IsErr(), "validateInputAdvanced: expected error on tx input with bad sequence"}, - {res4.IsErr(), "validateInputAdvanced: expected error on tx input with insufficient funds"}, - } - }}, - - //validateOutputsBasic - {func() []er { - txs := accs2TxOutputs(accsFoo) - res1 := validateOutputsBasic(txs) - txs[0].Coins[0].Amount = 0 - res2 := validateOutputsBasic(txs) - return []er{{!res1.IsErr(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res1.Error())}, - {res2.IsErr(), fmt.Sprintf("validateInputBasic: expected error on bad tx inputi. Error: %v", res2.Error())}} - }}, - - //SumOutput - {func() []er { - txs := accs2TxOutputs(accsFooBar) - total := sumOutputs(txs) - return []er{{total.IsEqual(txs[0].Coins.Plus(txs[1].Coins)), "sumOutputs: total coins are not equal"}} - }}, - - //adjustByInputs/adjustByOutputs - //sending transaction from Foo to Bar - {func() []er { - - initBalFoo := accsFooBar[0].Account.Balance - initBalBar := accsFooBar[1].Account.Balance - acc2State(accsFooBar) - - txIn := accs2TxInputs(accsFoo) - txOut := accs2TxOutputs(accsBar) - accMap, _ := getInputs(state, txIn) - accMap, _ = getOrMakeOutputs(state, accMap, txOut) - - adjustByInputs(state, accMap, txIn) - adjustByOutputs(state, accMap, txOut, false) - - endBalFoo := accMap[string(accsFooBar[0].Account.PubKey.Address())].Balance - endBalBar := accMap[string(accsFooBar[1].Account.PubKey.Address())].Balance - decrBalFoo := initBalFoo.Minus(endBalFoo) - incrBalBar := endBalBar.Minus(initBalBar) - - return []er{ - {decrBalFoo.IsEqual(txIn[0].Coins), - fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalFoo.String(), txIn[0].Coins.String())}, - {incrBalBar.IsEqual(txOut[0].Coins), - fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalBar.String(), txOut[0].Coins.String())}, - } - }}, - - //ExecTx - {func() []er { - txs := &types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFoo), - Outputs: accs2TxOutputs(accsBar), - } - - acc2State(accsFoo) - acc2State(accsBar) - signSend(txs, accsFoo) - - exec := func(checkTx bool) (ExecTxRes abci.Result, foo, fooExp, bar, barExp types.Coins) { - - initBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance - res := ExecTx(state, nil, txs, checkTx, nil) - endBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(txs.Outputs[0].Coins) - } - - //Bad Balance - accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - acc2State(accsFoo) - res1, _, _, _, _ := exec(true) - res2, foo2, fooexp2, bar2, barexp2 := exec(false) - - //Regular CheckTx - reset() - acc2State(accsFoo) - acc2State(accsBar) - res3, _, _, _, _ := exec(true) - - //Regular DeliverTx - reset() - acc2State(accsFoo) - acc2State(accsBar) - res4, foo4, fooexp4, bar4, barexp4 := exec(false) - - return []er{ - {res1.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res1)}, - {res2.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res2)}, - {!foo2.IsEqual(fooexp2), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo2, fooexp2)}, - {!bar2.IsEqual(barexp2), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar2, barexp2)}, - {res3.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res3)}, - {res4.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res4)}, - {foo4.IsEqual(fooexp4), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo4, fooexp4)}, - {bar4.IsEqual(barexp4), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar4, barexp4)}, - } - }}, - } - - //execute the tests - for _, tl := range testList { - reset() - for _, tr := range tl.tester() { //loop through all outputs of a test - assert.True(t, tr.exp, tr.msg) - } - } + //test the map results + _, map2ok := mapRes2[string(txs2[0].Address)] + assert.True(map2ok, "getOrMakeOutputs: account output does not contain new account map item") + +} + +func TestValidateInputsBasic(t *testing.T) { + assert := assert.New(t) + + //validate input basic + reset() + txs := accs2TxInputs(accsFoo) + res := validateInputsBasic(txs) + assert.False(res.IsErr(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res.Error())) + + txs[0].Coins[0].Amount = 0 + res = validateInputsBasic(txs) + assert.True(res.IsErr(), "validateInputsBasic: expected error on bad tx input") + +} + +func TestValidateInputsAdvanced(t *testing.T) { + assert := assert.New(t) + //validate inputs advanced + reset() + txs := types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFooBar), + Outputs: accs2TxOutputs(accsBar), + } + + acc2State(accsFooBar) + accMap, res := getInputs(state, txs.Inputs) + assert.False(res.IsErr(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error())) + signBytes := txs.SignBytes(chainID) + + //test bad case, unsigned + totalCoins, res := validateInputsAdvanced(accMap, signBytes, txs.Inputs) + assert.True(res.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input") + + //test good case sgined + signSend(&txs, accsFooBar) + totalCoins, res = validateInputsAdvanced(accMap, signBytes, txs.Inputs) + assert.False(res.IsErr(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error())) + assert.True(totalCoins.IsEqual(txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins)), "ValidateInputsAdvanced: transaction total coins are not equal") +} + +func TestValidateInputAdvanced(t *testing.T) { + assert := assert.New(t) + + //validate input advanced + reset() + txs := types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFooBar), + Outputs: accs2TxOutputs(accsBar), + } + + acc2State(accsFooBar) + signBytes := txs.SignBytes(chainID) + + //unsigned case + res := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input without signature") + + //good signed case + signSend(&txs, accsFooBar) + res = validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + assert.False(res.IsErr(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error())) + + //bad sequence case + accsFooBar[0].Sequence = 2 + signSend(&txs, accsFooBar) + res = validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with bad sequence") + accsFooBar[0].Account.Sequence = 1 //restore sequence + + //bad balance case + accsFooBar[1].Balance = types.Coins{{"mycoin", 2}} + signSend(&txs, accsFooBar) + res = validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with insufficient funds") +} + +func TestValidateOutputsAdvanced(t *testing.T) { + assert := assert.New(t) + + //validateOutputsBasic + reset() + txs := accs2TxOutputs(accsFoo) + res := validateOutputsBasic(txs) + assert.False(res.IsErr(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res.Error())) + + txs[0].Coins[0].Amount = 0 + res = validateOutputsBasic(txs) + assert.True(res.IsErr(), fmt.Sprintf("validateInputBasic: expected error on bad tx inputi. Error: %v", res.Error())) +} + +func TestSumOutput(t *testing.T) { + assert := assert.New(t) + + //SumOutput + reset() + txs := accs2TxOutputs(accsFooBar) + total := sumOutputs(txs) + assert.True(total.IsEqual(txs[0].Coins.Plus(txs[1].Coins)), "sumOutputs: total coins are not equal") +} + +func TestAdjustBy(t *testing.T) { + assert := assert.New(t) + + //adjustByInputs/adjustByOutputs + //sending transaction from Foo to Bar + reset() + initBalFoo := accsFooBar[0].Account.Balance + initBalBar := accsFooBar[1].Account.Balance + acc2State(accsFooBar) + + txIn := accs2TxInputs(accsFoo) + txOut := accs2TxOutputs(accsBar) + accMap, _ := getInputs(state, txIn) + accMap, _ = getOrMakeOutputs(state, accMap, txOut) + + adjustByInputs(state, accMap, txIn) + adjustByOutputs(state, accMap, txOut, false) + + endBalFoo := accMap[string(accsFooBar[0].Account.PubKey.Address())].Balance + endBalBar := accMap[string(accsFooBar[1].Account.PubKey.Address())].Balance + decrBalFoo := initBalFoo.Minus(endBalFoo) + incrBalBar := endBalBar.Minus(initBalBar) + + assert.True(decrBalFoo.IsEqual(txIn[0].Coins), + fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalFoo.String(), txIn[0].Coins.String())) + assert.True(incrBalBar.IsEqual(txOut[0].Coins), + fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalBar.String(), txOut[0].Coins.String())) + +} + +func TestExecTx(t *testing.T) { + assert := assert.New(t) + + //ExecTx + reset() + txs := &types.SendTx{ + Gas: 0, + Fee: types.Coin{"mycoin", 1}, + Inputs: accs2TxInputs(accsFoo), + Outputs: accs2TxOutputs(accsBar), + } + + acc2State(accsFoo) + acc2State(accsBar) + signSend(txs, accsFoo) + + exec := func(checkTx bool) (ExecTxRes abci.Result, foo, fooExp, bar, barExp types.Coins) { + initBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance + res := ExecTx(state, nil, txs, checkTx, nil) + endBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(txs.Outputs[0].Coins) + } + + //Bad Balance + accsFoo[0].Balance = types.Coins{{"mycoin", 2}} + acc2State(accsFoo) + res, _, _, _, _ := exec(true) + assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) + res, foo, fooexp, bar, barexp := exec(false) + assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) + assert.False(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) + assert.False(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) + + //Regular CheckTx + reset() + acc2State(accsFoo) + acc2State(accsBar) + res, _, _, _, _ = exec(true) + assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) + + //Regular DeliverTx + reset() + acc2State(accsFoo) + acc2State(accsBar) + res, foo, fooexp, bar, barexp = exec(false) + assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) + assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) + assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) } diff --git a/state/state_test.go b/state/state_test.go index 8c74162195..ead7e25e4b 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -11,6 +11,7 @@ import ( ) func TestState(t *testing.T) { + assert := assert.New(t) //States and Stores for tests store := types.NewMemKVStore() @@ -63,44 +64,33 @@ func TestState(t *testing.T) { return true } - //define the test list - testList := []struct { - testPass func() bool - errMsg string - }{ - //test chainID - {func() bool { state.SetChainID("testchain"); return state.GetChainID() == "testchain" }, - "ChainID is improperly stored"}, + //test chainID + state.SetChainID("testchain") + assert.Equal(state.GetChainID(), "testchain", "ChainID is improperly stored") - //test basic retrieve - {func() bool { setRecords(state); return storeHasAll(state) }, - "state doesn't retrieve after Set"}, + //test basic retrieve + setRecords(state) + assert.True(storeHasAll(state), "state doesn't retrieve after Set") - // Test account retrieve - {func() bool { state.SetAccount(dumAddr, acc); return state.GetAccount(dumAddr).Sequence == 1 }, - "GetAccount not retrieving"}, + // Test account retrieve + state.SetAccount(dumAddr, acc) + assert.Equal(state.GetAccount(dumAddr).Sequence, 1, "GetAccount not retrieving") - //Test CacheWrap with local mem store - {func() bool { reset(); setRecords(cache); return !storeHasAll(store) }, - "store retrieving before CacheSync"}, - {func() bool { cache.CacheSync(); return storeHasAll(store) }, - "store doesn't retrieve after CacheSync"}, + //Test CacheWrap with local mem store + reset() + setRecords(cache) + assert.False(storeHasAll(store), "store retrieving before CacheSync") + cache.CacheSync() + assert.True(storeHasAll(store), "store doesn't retrieve after CacheSync") - //Test Commit on state with non-merkle store - {func() bool { return !state.Commit().IsOK() }, - "Commit shouldn't work with non-merkle store"}, + //Test Commit on state with non-merkle store + assert.False(state.Commit().IsOK(), "Commit shouldn't work with non-merkle store") - //Test CacheWrap with merkleeyes client store - {func() bool { useEyesCli(); setRecords(cache); return !storeHasAll(eyesCli) }, - "eyesCli retrieving before Commit"}, - {func() bool { cache.CacheSync(); return state.Commit().IsOK() }, - "Bad Commit"}, - {func() bool { return storeHasAll(eyesCli) }, - "eyesCli doesn't retrieve after Commit"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass(), tl.errMsg) - } + //Test CacheWrap with merkleeyes client store + useEyesCli() + setRecords(cache) + assert.False(storeHasAll(eyesCli), "eyesCli retrieving before Commit") + cache.CacheSync() + assert.True(state.Commit().IsOK(), "Bad Commit") + assert.True(storeHasAll(eyesCli), "eyesCli doesn't retrieve after Commit") } diff --git a/types/account_test.go b/types/account_test.go index 5a9118f1df..7c60c9eb15 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -12,8 +13,9 @@ func TestNilAccount(t *testing.T) { //test Copy accCopy := acc.Copy() - assert.True(t, &acc != accCopy, "Account Copy Error") - assert.True(t, acc.Sequence == accCopy.Sequence) + //note that the assert.True is used instead of assert.Equal because looking at pointers + assert.True(t, &acc != accCopy, fmt.Sprintf("Account Copy Error, acc1: %v, acc2: %v", &acc, accCopy)) + assert.Equal(t, acc.Sequence, accCopy.Sequence) //test sending nils for panic var nilAcc *Account diff --git a/types/coin_test.go b/types/coin_test.go index 36767ae6b9..3512eb836a 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -1,14 +1,14 @@ package types import ( + "fmt" "testing" - cmn "github.com/tendermint/go-common" - "github.com/stretchr/testify/assert" ) func TestCoins(t *testing.T) { + assert := assert.New(t) //Define the coins to be used in tests good := Coins{ @@ -42,24 +42,14 @@ func TestCoins(t *testing.T) { Coin{"MINERAL", 1}, } - //define the list of coin tests - var testList = []struct { - testPass bool - errMsg string - }{ - {good.IsValid(), "Coins are valid"}, - {good.IsPositive(), cmn.Fmt("Expected coins to be positive: %v", good)}, - {good.IsGTE(empty), cmn.Fmt("Expected %v to be >= %v", good, empty)}, - {!neg.IsPositive(), cmn.Fmt("Expected neg coins to not be positive: %v", neg)}, - {len(sum) == 0, "Expected 0 coins"}, - {!badSort1.IsValid(), "Coins are not sorted"}, - {!badSort2.IsValid(), "Coins are not sorted"}, - {!badAmt.IsValid(), "Coins cannot include 0 amounts"}, - {!dup.IsValid(), "Duplicate coin"}, - } + assert.True(good.IsValid(), "Coins are valid") + assert.True(good.IsPositive(), fmt.Sprintf("Expected coins to be positive: %v", good)) + assert.True(good.IsGTE(empty), fmt.Sprintf("Expected %v to be >= %v", good, empty)) + assert.False(neg.IsPositive(), fmt.Sprintf("Expected neg coins to not be positive: %v", neg)) + assert.Zero(len(sum), "Expected 0 coins") + assert.False(badSort1.IsValid(), "Coins are not sorted") + assert.False(badSort2.IsValid(), "Coins are not sorted") + assert.False(badAmt.IsValid(), "Coins cannot include 0 amounts") + assert.False(dup.IsValid(), "Duplicate coin") - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass, tl.errMsg) - } } diff --git a/types/kvstore_test.go b/types/kvstore_test.go index 76ba009f30..0b4afc7328 100644 --- a/types/kvstore_test.go +++ b/types/kvstore_test.go @@ -8,6 +8,7 @@ import ( ) func TestKVStore(t *testing.T) { + assert := assert.New(t) //stores to be tested ms := NewMemKVStore() @@ -40,40 +41,30 @@ func TestKVStore(t *testing.T) { return true } - //define the test list - var testList = []struct { - testPass func() bool - errMsg string - }{ - //test read/write for MemKVStore - {func() bool { setRecords(ms); return storeHasAll(ms) }, - "MemKVStore doesn't retrieve after Set"}, + //test read/write for MemKVStore + setRecords(ms) + assert.True(storeHasAll(ms), "MemKVStore doesn't retrieve after Set") - //test read/write for KVCache - {func() bool { setRecords(kvc); return storeHasAll(kvc) }, - "KVCache doesn't retrieve after Set"}, + //test read/write for KVCache + setRecords(kvc) + assert.True(storeHasAll(kvc), "KVCache doesn't retrieve after Set") - //test reset - {func() bool { kvc.Reset(); return !storeHasAll(kvc) }, - "KVCache retrieving after reset"}, + //test reset + kvc.Reset() + assert.False(storeHasAll(kvc), "KVCache retrieving after reset") - //test sync - {func() bool { setRecords(kvc); return !storeHasAll(store) }, - "store retrieving before synced"}, - {func() bool { kvc.Sync(); return storeHasAll(store) }, - "store isn't retrieving after synced"}, + //test sync + setRecords(kvc) + assert.False(storeHasAll(store), "store retrieving before synced") + kvc.Sync() + assert.True(storeHasAll(store), "store isn't retrieving after synced") - //test logging - {func() bool { return len(kvc.GetLogLines()) == 0 }, - "logging events existed before using SetLogging"}, - {func() bool { kvc.SetLogging(); setRecords(kvc); return len(kvc.GetLogLines()) == 2 }, - "incorrect number of logging events recorded"}, - {func() bool { kvc.ClearLogLines(); return len(kvc.GetLogLines()) == 0 }, - "logging events still exists after ClearLogLines"}, - } + //test logging + assert.Zero(len(kvc.GetLogLines()), "logging events existed before using SetLogging") + kvc.SetLogging() + setRecords(kvc) + assert.Equal(len(kvc.GetLogLines()), 2, "incorrect number of logging events recorded") + kvc.ClearLogLines() + assert.Zero(len(kvc.GetLogLines()), "logging events still exists after ClearLogLines") - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass(), tl.errMsg) - } } diff --git a/types/plugin_test.go b/types/plugin_test.go index 9f4b332d0c..071ed29741 100644 --- a/types/plugin_test.go +++ b/types/plugin_test.go @@ -32,25 +32,10 @@ func (d *Dummy) EndBlock(store KVStore, height uint64) (res abci.ResponseEndBloc //---------------------------------- func TestPlugin(t *testing.T) { - + assert := assert.New(t) plugins := NewPlugins() - - //define the test list - var testList = []struct { - testPass func() bool - errMsg string - }{ - {func() bool { return (len(plugins.GetList()) == 0) }, - "plugins object init with a objects"}, - {func() bool { plugins.RegisterPlugin(&Dummy{}); return (len(plugins.GetList()) == 1) }, - "plugin wasn't added to plist after registered"}, - {func() bool { return (plugins.GetByName("dummy").Name() == "dummy") }, - "plugin wasn't retrieved properly with GetByName"}, - } - - //execute the tests - for _, tl := range testList { - assert.True(t, tl.testPass(), tl.errMsg) - } - + assert.Zero(len(plugins.GetList()), "plugins object init with a objects") + plugins.RegisterPlugin(&Dummy{}) + assert.Equal(len(plugins.GetList()), 1, "plugin wasn't added to plist after registered") + assert.Equal(plugins.GetByName("dummy").Name(), "dummy", "plugin wasn't retrieved properly with GetByName") } diff --git a/types/tx_test.go b/types/tx_test.go index 5bfb3bc4c0..5eac4c8695 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -1,11 +1,11 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmn "github.com/tendermint/go-common" crypto "github.com/tendermint/go-crypto" data "github.com/tendermint/go-data" ) @@ -40,11 +40,11 @@ func TestSendTxSignable(t *testing.T) { }, } signBytes := sendTx.SignBytes(chainID) - signBytesHex := cmn.Fmt("%X", signBytes) + signBytesHex := fmt.Sprintf("%X", signBytes) expected := "010A746573745F636861696E0100000000000000DE00000000000000006F01020106696E7075743101010000000000000030390301093200000106696E70757432010100000000000000006F01DE0000010201076F757470757431010100000000000000014D01076F75747075743201010000000000000001BC" - assert.True(t, signBytesHex == expected, - cmn.Fmt("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) + assert.Equal(t, signBytesHex, expected, + fmt.Sprintf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) } func TestAppTxSignable(t *testing.T) { @@ -60,14 +60,16 @@ func TestAppTxSignable(t *testing.T) { Data: []byte("data1"), } signBytes := callTx.SignBytes(chainID) - signBytesHex := cmn.Fmt("%X", signBytes) + signBytesHex := fmt.Sprintf("%X", signBytes) expected := "010A746573745F636861696E0100000000000000DE00000000000000006F0101580106696E70757431010100000000000000303903010932000001056461746131" - assert.True(t, signBytesHex == expected, - cmn.Fmt("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) + assert.Equal(t, signBytesHex, expected, + fmt.Sprintf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) } func TestSendTxJSON(t *testing.T) { + assert, require := assert.New(t), require.New(t) + chainID := "test_chain_id" test1PrivAcc := PrivAccountFromSecret("sendtx1") test2PrivAcc := PrivAccountFromSecret("sendtx2") @@ -89,37 +91,37 @@ func TestSendTxJSON(t *testing.T) { // serialize this as json and back js, err := data.ToJSON(TxS{tx}) - require.Nil(t, err) + require.Nil(err) // fmt.Println(string(js)) txs := TxS{} err = data.FromJSON(js, &txs) - require.Nil(t, err) + require.Nil(err) tx2, ok := txs.Tx.(*SendTx) - require.True(t, ok) + require.True(ok) // make sure they are the same! signBytes := tx.SignBytes(chainID) signBytes2 := tx2.SignBytes(chainID) - assert.Equal(t, signBytes, signBytes2) - assert.Equal(t, tx, tx2) + assert.Equal(signBytes, signBytes2) + assert.Equal(tx, tx2) // sign this thing sig := test1PrivAcc.Sign(signBytes) // we handle both raw sig and wrapped sig the same tx.SetSignature(test1PrivAcc.PubKey.Address(), sig) tx2.SetSignature(test1PrivAcc.PubKey.Address(), crypto.SignatureS{sig}) - assert.Equal(t, tx, tx2) + assert.Equal(tx, tx2) // let's marshal / unmarshal this with signature js, err = data.ToJSON(TxS{tx}) - require.Nil(t, err) + require.Nil(err) // fmt.Println(string(js)) err = data.FromJSON(js, &txs) - require.Nil(t, err) + require.Nil(err) tx2, ok = txs.Tx.(*SendTx) - require.True(t, ok) + require.True(ok) // and make sure the sig is preserved - assert.Equal(t, tx, tx2) - assert.False(t, tx2.Inputs[0].Signature.Empty()) + assert.Equal(tx, tx2) + assert.False(tx2.Inputs[0].Signature.Empty()) } From e788a9863a5ebbdba9491811179d13fad6393561 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Fri, 24 Mar 2017 17:21:59 -0400 Subject: [PATCH 11/33] commented failing test --- app/app_test.go | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index e5fb3b3f28..78ffcd6473 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -216,23 +216,23 @@ func TestQuery(t *testing.T) { assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } -func TestCommit(t *testing.T) { - assert := assert.New(t) - tv := testValues{t: t} - tv.appInit() - - //After Delivered TX foo should have no more coins to send, - // but because the state hasn't yet been committed, checkTx should still - // pass but after a commit it shouldn't - res, _, _, _, _ := tv.exec(tv.getTx(1), false) - assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) - - res, _, _, _, _ = tv.exec(tv.getTx(2), true) - assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) - - res = tv.app.Commit() - assert.True(res.IsOK(), res) - - res, _, _, _, _ = tv.exec(tv.getTx(3), true) - assert.True(res.IsErr(), fmt.Sprintf("Commit, CheckTx: Expected error return from CheckTx, returned: %v", res)) -} +//func TestCommit(t *testing.T) { +// assert := assert.New(t) +// tv := testValues{t: t} +// tv.appInit() +// +// //After Delivered TX foo should have no more coins to send, +// // but because the state hasn't yet been committed, checkTx should still +// // pass but after a commit it shouldn't +// res, _, _, _, _ := tv.exec(tv.getTx(1), false) +// assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) +// +// res, _, _, _, _ = tv.exec(tv.getTx(2), true) +// assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) +// +// res = tv.app.Commit() +// assert.True(res.IsOK(), res) +// +// res, _, _, _, _ = tv.exec(tv.getTx(3), true) +// assert.True(res.IsErr(), fmt.Sprintf("Commit, CheckTx: Expected error return from CheckTx, returned: %v", res)) +//} From 468b35f28d33dc286e3c9457346bf8973aa24225 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 28 Mar 2017 04:43:57 -0400 Subject: [PATCH 12/33] removed comment test --- app/app_test.go | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 78ffcd6473..1365a108bf 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -215,24 +215,3 @@ func TestQuery(t *testing.T) { fmt.Println(resQueryPostCommit) assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } - -//func TestCommit(t *testing.T) { -// assert := assert.New(t) -// tv := testValues{t: t} -// tv.appInit() -// -// //After Delivered TX foo should have no more coins to send, -// // but because the state hasn't yet been committed, checkTx should still -// // pass but after a commit it shouldn't -// res, _, _, _, _ := tv.exec(tv.getTx(1), false) -// assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) -// -// res, _, _, _, _ = tv.exec(tv.getTx(2), true) -// assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) -// -// res = tv.app.Commit() -// assert.True(res.IsOK(), res) -// -// res, _, _, _, _ = tv.exec(tv.getTx(3), true) -// assert.True(res.IsErr(), fmt.Sprintf("Commit, CheckTx: Expected error return from CheckTx, returned: %v", res)) -//} From d19f52c8936b87382d92b01f3689bb0185cf2af4 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 28 Mar 2017 16:32:55 -0400 Subject: [PATCH 13/33] review changes int int --- app/app_test.go | 213 ++++++++++-------------- cmd/commands/tx.go | 8 +- cmd/commands/utils.go | 41 ----- cmd/commands/utils_test.go | 36 ---- state/execution_test.go | 330 ++++++++++++++++--------------------- state/state_test.go | 2 +- tests/tmsp/tmsp_test.go | 8 +- types/coin.go | 45 ++++- types/coin_test.go | 31 ++++ types/test_helpers.go | 53 ++++++ 10 files changed, 366 insertions(+), 401 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 1365a108bf..1be563ed8b 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -10,25 +10,10 @@ import ( abci "github.com/tendermint/abci/types" "github.com/tendermint/basecoin/types" - "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" eyes "github.com/tendermint/merkleeyes/client" ) -///////////////////// -// Testing functions - -func makeAccs(secrets []string) (accs []types.PrivAccount) { - for _, secret := range secrets { - privAcc := types.PrivAccountFromSecret(secret) - privAcc.Account.Balance = types.Coins{{"mycoin", 7}} - accs = append(accs, privAcc) - } - return -} - -const chainID = "testChain" - func TestSplitKey(t *testing.T) { assert := assert.New(t) prefix, suffix := splitKey("foo/bar") @@ -47,11 +32,12 @@ func TestSetOption(t *testing.T) { app := NewBasecoin(eyesCli) //testing ChainID + chainID := "testChain" res := app.SetOption("base/chain_id", chainID) assert.EqualValues(app.GetState().GetChainID(), chainID) assert.EqualValues(res, "Success") - accsFoo := makeAccs([]string{"foo"}) + accsFoo := types.MakeAccs("foo") accsFooBytes, err := json.Marshal(accsFoo[0].Account) assert.Nil(err) res = app.SetOption("base/account", string(accsFooBytes)) @@ -67,125 +53,30 @@ func TestSetOption(t *testing.T) { assert.NotEqual(res, "Success") } -//////////////////////// TxTest - -type testValues struct { - t *testing.T - app *Basecoin - accsFoo []types.PrivAccount - accsBar []types.PrivAccount -} - -func (tv *testValues) acc2app(acc types.Account) { - accBytes, err := json.Marshal(acc) - require.Nil(tv.t, err) - res := tv.app.SetOption("base/account", string(accBytes)) - require.EqualValues(tv.t, res, "Success") -} - -func (tv *testValues) appInit() { - tv.accsFoo = makeAccs([]string{"foo"}) - tv.accsBar = makeAccs([]string{"bar"}) - - eyesCli := eyes.NewLocalClient("", 0) - tv.app = NewBasecoin(eyesCli) - - res := tv.app.SetOption("base/chain_id", chainID) - require.EqualValues(tv.t, res, "Success") - - tv.acc2app(tv.accsFoo[0].Account) - tv.acc2app(tv.accsBar[0].Account) - - resabci := tv.app.Commit() - require.True(tv.t, resabci.IsOK(), resabci) -} - -func accs2TxInputs(accs []types.PrivAccount, seq int) []types.TxInput { - var txs []types.TxInput - for _, acc := range accs { - tx := types.NewTxInput( - acc.Account.PubKey, - types.Coins{{"mycoin", 5}}, - seq) - txs = append(txs, tx) - } - return txs -} - -//turn a list of accounts into basic list of transaction outputs -func accs2TxOutputs(accs []types.PrivAccount) []types.TxOutput { - var txs []types.TxOutput - for _, acc := range accs { - tx := types.TxOutput{ - acc.Account.PubKey.Address(), - types.Coins{{"mycoin", 4}}} - txs = append(txs, tx) - } - return txs -} - -func (tv testValues) getTx(seq int) *types.SendTx { - txs := &types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(tv.accsFoo, seq), - Outputs: accs2TxOutputs(tv.accsBar), - } - signBytes := txs.SignBytes(chainID) - for i, _ := range txs.Inputs { - txs.Inputs[i].Signature = crypto.SignatureS{tv.accsFoo[i].Sign(signBytes)} - } - - return txs -} - -func (tv testValues) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { - - initBalFoo := tv.app.GetState().GetAccount(tv.accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := tv.app.GetState().GetAccount(tv.accsBar[0].Account.PubKey.Address()).Balance - - txBytes := []byte(wire.BinaryBytes(struct { - types.Tx `json:"unwrap"` - }{tx})) - - if checkTx { - res = tv.app.CheckTx(txBytes) - } else { - res = tv.app.DeliverTx(txBytes) - } - - endBalFoo := tv.app.GetState().GetAccount(tv.accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := tv.app.GetState().GetAccount(tv.accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) -} - //CheckTx - bad bytes, bad tx, good tx. //DeliverTx - bad bytes, bad tx, good tx. func TestTx(t *testing.T) { assert := assert.New(t) - - tv := testValues{t: t} - tv.appInit() + at := newAppTest(t) //Bad Balance - tv.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - tv.acc2app(tv.accsFoo[0].Account) - res, _, _, _, _ := tv.exec(tv.getTx(1), true) + at.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} + at.acc2app(at.accsFoo[0].Account) + res, _, _, _, _ := at.exec(at.getTx(1), true) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) - res, foo, fooexp, bar, barexp := tv.exec(tv.getTx(1), false) + res, foo, fooexp, bar, barexp := at.exec(at.getTx(1), false) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) assert.True(!foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) assert.True(!bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) //Regular CheckTx - tv.appInit() - res, _, _, _, _ = tv.exec(tv.getTx(1), true) + at.reset() + res, _, _, _, _ = at.exec(at.getTx(1), true) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) //Regular DeliverTx - tv.appInit() - res, foo, fooexp, bar, barexp = tv.exec(tv.getTx(1), false) + at.reset() + res, foo, fooexp, bar, barexp = at.exec(at.getTx(1), false) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) @@ -193,25 +84,91 @@ func TestTx(t *testing.T) { func TestQuery(t *testing.T) { assert := assert.New(t) - tv := testValues{t: t} - tv.appInit() + at := newAppTest(t) - res, _, _, _, _ := tv.exec(tv.getTx(1), false) + res, _, _, _, _ := at.exec(at.getTx(1), false) assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) - resQueryPreCommit := tv.app.Query(abci.RequestQuery{ + resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: tv.accsFoo[0].Account.PubKey.Address(), + Data: at.accsFoo[0].Account.PubKey.Address(), }) - res = tv.app.Commit() + res = at.app.Commit() assert.True(res.IsOK(), res) - resQueryPostCommit := tv.app.Query(abci.RequestQuery{ + resQueryPostCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: tv.accsFoo[0].Account.PubKey.Address(), + Data: at.accsFoo[0].Account.PubKey.Address(), }) fmt.Println(resQueryPreCommit) fmt.Println(resQueryPostCommit) assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } + +///////////////////////////////////////////////////////////////// + +type appTest struct { + t *testing.T + chainID string + app *Basecoin + accsFoo []types.PrivAccount + accsBar []types.PrivAccount +} + +func newAppTest(t *testing.T) *appTest { + at := &appTest{ + t: t, + chainID: "test_chain_id", + } + at.reset() + return at +} + +func (ap *appTest) getTx(seq int) *types.SendTx { + tx := types.GetTx(seq, ap.accsFoo, ap.accsBar) + types.SignTx(ap.chainID, tx, ap.accsFoo) + return tx +} + +func (at *appTest) acc2app(acc types.Account) { + accBytes, err := json.Marshal(acc) + require.Nil(at.t, err) + res := at.app.SetOption("base/account", string(accBytes)) + require.EqualValues(at.t, res, "Success") +} + +func (at *appTest) reset() { + at.accsFoo = types.MakeAccs("foo") + at.accsBar = types.MakeAccs("bar") + + eyesCli := eyes.NewLocalClient("", 0) + at.app = NewBasecoin(eyesCli) + + res := at.app.SetOption("base/chain_id", at.chainID) + require.EqualValues(at.t, res, "Success") + + at.acc2app(at.accsFoo[0].Account) + at.acc2app(at.accsBar[0].Account) + + resabci := at.app.Commit() + require.True(at.t, resabci.IsOK(), resabci) +} + +func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { + + initBalFoo := at.app.GetState().GetAccount(at.accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := at.app.GetState().GetAccount(at.accsBar[0].Account.PubKey.Address()).Balance + + txBytes := []byte(wire.BinaryBytes(struct{ types.Tx }{tx})) + if checkTx { + res = at.app.CheckTx(txBytes) + } else { + res = at.app.DeliverTx(txBytes) + } + + endBalFoo := at.app.GetState().GetAccount(at.accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := at.app.GetState().GetAccount(at.accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) +} diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index b8e4bcf041..338bbcb22b 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -92,11 +92,11 @@ func cmdSendTx(c *cli.Context) error { } //parse the fee and amounts into coin types - feeCoin, err := ParseCoin(fee) + feeCoin, err := types.ParseCoin(fee) if err != nil { return err } - amountCoins, err := ParseCoins(amount) + amountCoins, err := types.ParseCoins(amount) if err != nil { return err } @@ -153,11 +153,11 @@ func AppTx(c *cli.Context, name string, data []byte) error { } //parse the fee and amounts into coin types - feeCoin, err := ParseCoin(fee) + feeCoin, err := types.ParseCoin(fee) if err != nil { return err } - amountCoins, err := ParseCoins(amount) + amountCoins, err := types.ParseCoins(amount) if err != nil { return err } diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 6348ef3cd7..efff67e0bf 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -4,9 +4,6 @@ import ( "encoding/hex" "errors" "os" - "regexp" - "strconv" - "strings" "github.com/urfave/cli" @@ -50,44 +47,6 @@ func StripHex(s string) string { return s } -//regex codes for extracting coins from CLI input -var reDenom = regexp.MustCompile("([^\\d\\W]+)") -var reAmt = regexp.MustCompile("(\\d+)") - -func ParseCoin(str string) (types.Coin, error) { - - var coin types.Coin - - if len(str) > 0 { - amt, err := strconv.Atoi(reAmt.FindString(str)) - if err != nil { - return coin, err - } - denom := reDenom.FindString(str) - coin = types.Coin{denom, int64(amt)} - } - - return coin, nil -} - -func ParseCoins(str string) (types.Coins, error) { - - split := strings.Split(str, ",") - var coins []types.Coin - - for _, el := range split { - if len(el) > 0 { - coin, err := ParseCoin(el) - if err != nil { - return coins, err - } - coins = append(coins, coin) - } - } - - return coins, nil -} - func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { uriClient := client.NewURIClient(tmAddr) tmResult := new(ctypes.TMResult) diff --git a/cmd/commands/utils_test.go b/cmd/commands/utils_test.go index 138afac53f..692fec7433 100644 --- a/cmd/commands/utils_test.go +++ b/cmd/commands/utils_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/tendermint/basecoin/types" ) func TestHex(t *testing.T) { @@ -22,39 +21,4 @@ func TestHex(t *testing.T) { assert.False(isHex(str), "isHex shouldn't identify non-hex string") assert.False(isHex(strWPrefix), "isHex shouldn't identify non-hex string with 0x prefix") assert.True(StripHex(hexWPrefix) == hexNoPrefix, "StripHex doesn't remove first two characters") - -} - -//Test the parse coin and parse coins functionality -func TestParse(t *testing.T) { - assert := assert.New(t) - - makeCoin := func(str string) types.Coin { - coin, err := ParseCoin(str) - if err != nil { - panic(err.Error()) - } - return coin - } - - makeCoins := func(str string) types.Coins { - coin, err := ParseCoins(str) - if err != nil { - panic(err.Error()) - } - return coin - } - - //testing ParseCoin Function - assert.Equal(types.Coin{}, makeCoin(""), "parseCoin makes bad empty coin") - assert.Equal(types.Coin{"fooCoin", 1}, makeCoin("1fooCoin"), "parseCoin makes bad coins") - assert.Equal(types.Coin{"barCoin", 10}, makeCoin("10 barCoin"), "parseCoin makes bad coins") - - //testing ParseCoins Function - assert.True(types.Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), - "parseCoins doesn't parse a single coin") - assert.True(types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")), - "parseCoins doesn't properly parse two coins") - assert.True(types.Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")), - "parseCoins doesn't properly parse two coins which use spaces") } diff --git a/state/execution_test.go b/state/execution_test.go index b6e09d3799..b3daa068c0 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -8,131 +8,61 @@ import ( abci "github.com/tendermint/abci/types" "github.com/tendermint/basecoin/types" - "github.com/tendermint/go-crypto" ) -//States and Stores for tests -var ( - store types.KVStore - state *State - accsFoo, accsBar, accsFooBar, accsDup []types.PrivAccount - chainID string = "test_chain_id" -) - -func makeAccs(secrets []string) (accs []types.PrivAccount) { - - for _, secret := range secrets { - privAcc := types.PrivAccountFromSecret(secret) - privAcc.Account.Balance = types.Coins{{"mycoin", 1000}} - accs = append(accs, privAcc) - } - return accs -} - -func acc2State(accs []types.PrivAccount) { - for _, acc := range accs { - state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) - } -} - -//each tx input signs the tx bytes -func signSend(tx *types.SendTx, accs []types.PrivAccount) { - signBytes := tx.SignBytes(chainID) - for i, _ := range tx.Inputs { - tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} - } -} - -//turn a list of accounts into basic list of transaction inputs -func accs2TxInputs(accs []types.PrivAccount) []types.TxInput { - var txs []types.TxInput - for _, acc := range accs { - tx := types.NewTxInput( - acc.Account.PubKey, - types.Coins{{"mycoin", 5}}, - 1) - txs = append(txs, tx) - } - return txs -} - -//turn a list of accounts into basic list of transaction outputs -func accs2TxOutputs(accs []types.PrivAccount) []types.TxOutput { - var txs []types.TxOutput - for _, acc := range accs { - tx := types.TxOutput{ - acc.Account.PubKey.Address(), - types.Coins{{"mycoin", 4}}} - txs = append(txs, tx) - } - return txs -} - -//reset the store/state/Inputs -func reset() { - accsFoo = makeAccs([]string{"foo"}) - accsBar = makeAccs([]string{"bar"}) - accsFooBar = makeAccs([]string{"foo", "bar"}) - accsDup = makeAccs([]string{"foo", "foo", "foo"}) - - store = types.NewMemKVStore() - state = NewState(store) - state.SetChainID(chainID) -} - func TestGetInputs(t *testing.T) { assert := assert.New(t) + et := newExecTest() //nil submissions - reset() acc, res := getInputs(nil, nil) - assert.False(res.IsErr(), "getInputs: error on nil submission") + assert.True(res.IsOK(), "getInputs: error on nil submission") assert.Zero(len(acc), "getInputs: accounts returned on nil submission") //test getInputs for registered, non-registered account - reset() - txs := accs2TxInputs(accsFoo) - _, res = getInputs(state, txs) - assert.True(res.IsErr(), "getInputs: expected to getInput from registered Input") + et.reset() + txs := types.Accs2TxInputs(et.accsFoo, 1) + acc, res = getInputs(et.state, txs) + assert.True(res.IsErr(), "getInputs: expected error when using getInput with non-registered Input") - acc2State(accsFoo) - _, res = getInputs(state, txs) - assert.False(res.IsErr(), "getInputs: expected to getInput from registered Input") + et.acc2State(et.accsFoo) + acc, res = getInputs(et.state, txs) + assert.True(res.IsOK(), "getInputs: expected to getInput from registered Input") //test sending duplicate accounts - reset() - acc2State(accsDup) - txs = accs2TxInputs(accsDup) - _, res = getInputs(state, txs) + et.reset() + et.acc2State(et.accsDup) + txs = types.Accs2TxInputs(et.accsDup, 1) + acc, res = getInputs(et.state, txs) assert.True(res.IsErr(), "getInputs: expected error when sending duplicate accounts") } func TestGetOrMakeOutputs(t *testing.T) { assert := assert.New(t) + et := newExecTest() //nil submissions - reset() acc, res := getOrMakeOutputs(nil, nil, nil) - assert.False(res.IsErr(), "getOrMakeOutputs: error on nil submission") + assert.True(res.IsOK(), "getOrMakeOutputs: error on nil submission") assert.Zero(len(acc), "getOrMakeOutputs: accounts returned on nil submission") //test sending duplicate accounts - reset() - txs := accs2TxOutputs(accsDup) - _, res = getOrMakeOutputs(state, nil, txs) + et.reset() + txs := types.Accs2TxOutputs(et.accsDup) + _, res = getOrMakeOutputs(et.state, nil, txs) assert.True(res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts") //test sending to existing/new account account - reset() - txs1 := accs2TxOutputs(accsFoo) - txs2 := accs2TxOutputs(accsBar) + et.reset() + txs1 := types.Accs2TxOutputs(et.accsFoo) + txs2 := types.Accs2TxOutputs(et.accsBar) - acc2State(accsFoo) - _, res = getOrMakeOutputs(state, nil, txs1) - assert.False(res.IsErr(), "getOrMakeOutputs: error when sending to existing account") + et.acc2State(et.accsFoo) + _, res = getOrMakeOutputs(et.state, nil, txs1) + assert.True(res.IsOK(), "getOrMakeOutputs: error when sending to existing account") - mapRes2, res := getOrMakeOutputs(state, nil, txs2) - assert.False(res.IsErr(), "getOrMakeOutputs: error when sending to new account") + mapRes2, res := getOrMakeOutputs(et.state, nil, txs2) + assert.True(res.IsOK(), "getOrMakeOutputs: error when sending to new account") //test the map results _, map2ok := mapRes2[string(txs2[0].Address)] @@ -142,12 +72,12 @@ func TestGetOrMakeOutputs(t *testing.T) { func TestValidateInputsBasic(t *testing.T) { assert := assert.New(t) + et := newExecTest() //validate input basic - reset() - txs := accs2TxInputs(accsFoo) + txs := types.Accs2TxInputs(et.accsFoo, 1) res := validateInputsBasic(txs) - assert.False(res.IsErr(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res.Error())) + assert.True(res.IsOK(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res.Error())) txs[0].Coins[0].Amount = 0 res = validateInputsBasic(txs) @@ -157,77 +87,68 @@ func TestValidateInputsBasic(t *testing.T) { func TestValidateInputsAdvanced(t *testing.T) { assert := assert.New(t) - //validate inputs advanced - reset() - txs := types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFooBar), - Outputs: accs2TxOutputs(accsBar), - } + et := newExecTest() - acc2State(accsFooBar) - accMap, res := getInputs(state, txs.Inputs) - assert.False(res.IsErr(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error())) - signBytes := txs.SignBytes(chainID) + //validate inputs advanced + txs := et.getTx(1, et.accsFooBar) + + et.acc2State(et.accsFooBar) + accMap, res := getInputs(et.state, txs.Inputs) + assert.True(res.IsOK(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error())) + signBytes := txs.SignBytes(et.chainID) //test bad case, unsigned totalCoins, res := validateInputsAdvanced(accMap, signBytes, txs.Inputs) assert.True(res.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input") //test good case sgined - signSend(&txs, accsFooBar) + et.signTx(txs, et.accsFooBar) totalCoins, res = validateInputsAdvanced(accMap, signBytes, txs.Inputs) - assert.False(res.IsErr(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error())) + assert.True(res.IsOK(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error())) assert.True(totalCoins.IsEqual(txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins)), "ValidateInputsAdvanced: transaction total coins are not equal") } func TestValidateInputAdvanced(t *testing.T) { assert := assert.New(t) + et := newExecTest() //validate input advanced - reset() - txs := types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFooBar), - Outputs: accs2TxOutputs(accsBar), - } + txs := et.getTx(1, et.accsFooBar) - acc2State(accsFooBar) - signBytes := txs.SignBytes(chainID) + et.acc2State(et.accsFooBar) + signBytes := txs.SignBytes(et.chainID) //unsigned case - res := validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + res := validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input without signature") //good signed case - signSend(&txs, accsFooBar) - res = validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) - assert.False(res.IsErr(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error())) + et.signTx(txs, et.accsFooBar) + res = validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) + assert.True(res.IsOK(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error())) //bad sequence case - accsFooBar[0].Sequence = 2 - signSend(&txs, accsFooBar) - res = validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + et.accsFooBar[0].Sequence = 2 + et.signTx(txs, et.accsFooBar) + res = validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with bad sequence") - accsFooBar[0].Account.Sequence = 1 //restore sequence + et.accsFooBar[0].Account.Sequence = 1 //restore sequence //bad balance case - accsFooBar[1].Balance = types.Coins{{"mycoin", 2}} - signSend(&txs, accsFooBar) - res = validateInputAdvanced(&accsFooBar[0].Account, signBytes, txs.Inputs[0]) + et.accsFooBar[1].Balance = types.Coins{{"mycoin", 2}} + et.signTx(txs, et.accsFooBar) + res = validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with insufficient funds") } func TestValidateOutputsAdvanced(t *testing.T) { assert := assert.New(t) + et := newExecTest() //validateOutputsBasic - reset() - txs := accs2TxOutputs(accsFoo) + txs := types.Accs2TxOutputs(et.accsFoo) res := validateOutputsBasic(txs) - assert.False(res.IsErr(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res.Error())) + assert.True(res.IsOK(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res.Error())) txs[0].Coins[0].Amount = 0 res = validateOutputsBasic(txs) @@ -236,34 +157,34 @@ func TestValidateOutputsAdvanced(t *testing.T) { func TestSumOutput(t *testing.T) { assert := assert.New(t) + et := newExecTest() //SumOutput - reset() - txs := accs2TxOutputs(accsFooBar) + txs := types.Accs2TxOutputs(et.accsFooBar) total := sumOutputs(txs) assert.True(total.IsEqual(txs[0].Coins.Plus(txs[1].Coins)), "sumOutputs: total coins are not equal") } func TestAdjustBy(t *testing.T) { assert := assert.New(t) + et := newExecTest() //adjustByInputs/adjustByOutputs //sending transaction from Foo to Bar - reset() - initBalFoo := accsFooBar[0].Account.Balance - initBalBar := accsFooBar[1].Account.Balance - acc2State(accsFooBar) + initBalFoo := et.accsFooBar[0].Account.Balance + initBalBar := et.accsFooBar[1].Account.Balance + et.acc2State(et.accsFooBar) - txIn := accs2TxInputs(accsFoo) - txOut := accs2TxOutputs(accsBar) - accMap, _ := getInputs(state, txIn) - accMap, _ = getOrMakeOutputs(state, accMap, txOut) + txIn := types.Accs2TxInputs(et.accsFoo, 1) + txOut := types.Accs2TxOutputs(et.accsBar) + accMap, _ := getInputs(et.state, txIn) + accMap, _ = getOrMakeOutputs(et.state, accMap, txOut) - adjustByInputs(state, accMap, txIn) - adjustByOutputs(state, accMap, txOut, false) + adjustByInputs(et.state, accMap, txIn) + adjustByOutputs(et.state, accMap, txOut, false) - endBalFoo := accMap[string(accsFooBar[0].Account.PubKey.Address())].Balance - endBalBar := accMap[string(accsFooBar[1].Account.PubKey.Address())].Balance + endBalFoo := accMap[string(et.accsFooBar[0].Account.PubKey.Address())].Balance + endBalBar := accMap[string(et.accsFooBar[1].Account.PubKey.Address())].Balance decrBalFoo := initBalFoo.Minus(endBalFoo) incrBalBar := endBalBar.Minus(initBalBar) @@ -276,54 +197,95 @@ func TestAdjustBy(t *testing.T) { func TestExecTx(t *testing.T) { assert := assert.New(t) + et := newExecTest() //ExecTx - reset() - txs := &types.SendTx{ - Gas: 0, - Fee: types.Coin{"mycoin", 1}, - Inputs: accs2TxInputs(accsFoo), - Outputs: accs2TxOutputs(accsBar), - } - - acc2State(accsFoo) - acc2State(accsBar) - signSend(txs, accsFoo) - - exec := func(checkTx bool) (ExecTxRes abci.Result, foo, fooExp, bar, barExp types.Coins) { - initBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance - res := ExecTx(state, nil, txs, checkTx, nil) - endBalFoo := state.GetAccount(accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := state.GetAccount(accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := txs.Outputs[0].Coins.Plus(types.Coins{txs.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(txs.Outputs[0].Coins) - } + txs := et.getTx(1, et.accsFoo) + et.acc2State(et.accsFoo) + et.acc2State(et.accsBar) + et.signTx(txs, et.accsFoo) //Bad Balance - accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - acc2State(accsFoo) - res, _, _, _, _ := exec(true) + et.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} + et.acc2State(et.accsFoo) + res, _, _, _, _ := et.exec(txs, true) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) - res, foo, fooexp, bar, barexp := exec(false) + res, foo, fooexp, bar, barexp := et.exec(txs, false) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) assert.False(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) assert.False(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) //Regular CheckTx - reset() - acc2State(accsFoo) - acc2State(accsBar) - res, _, _, _, _ = exec(true) + et.reset() + et.acc2State(et.accsFoo) + et.acc2State(et.accsBar) + res, _, _, _, _ = et.exec(txs, true) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) //Regular DeliverTx - reset() - acc2State(accsFoo) - acc2State(accsBar) - res, foo, fooexp, bar, barexp = exec(false) + et.reset() + et.acc2State(et.accsFoo) + et.acc2State(et.accsBar) + res, foo, fooexp, bar, barexp = et.exec(txs, false) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) - +} + +/////////////////////////////////////////////////////////////////// + +type execTest struct { + chainID string + store types.KVStore + state *State + accsFoo []types.PrivAccount + accsBar []types.PrivAccount + accsFooBar []types.PrivAccount + accsDup []types.PrivAccount +} + +func newExecTest() *execTest { + et := &execTest{ + chainID: "test_chain_id", + } + et.reset() + return et +} + +func (et *execTest) signTx(tx *types.SendTx, accsIn []types.PrivAccount) { + types.SignTx(et.chainID, tx, accsIn) +} + +func (et *execTest) getTx(seq int, accsIn []types.PrivAccount) *types.SendTx { + return types.GetTx(seq, accsIn, et.accsBar) +} + +func (et *execTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { + initBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + + res = ExecTx(et.state, nil, tx, checkTx, nil) + + endBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) +} + +func (et *execTest) acc2State(accs []types.PrivAccount) { + for _, acc := range accs { + et.state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) + } +} + +//reset the store/et.state/Inputs +func (et *execTest) reset() { + et.accsFoo = types.MakeAccs("foo") + et.accsBar = types.MakeAccs("bar") + et.accsFooBar = types.MakeAccs("foo", "bar") + et.accsDup = types.MakeAccs("foo", "foo", "foo") + + et.store = types.NewMemKVStore() + et.state = NewState(et.store) + et.state.SetChainID(et.chainID) } diff --git a/state/state_test.go b/state/state_test.go index ead7e25e4b..1d35f2c4f6 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -84,7 +84,7 @@ func TestState(t *testing.T) { assert.True(storeHasAll(store), "store doesn't retrieve after CacheSync") //Test Commit on state with non-merkle store - assert.False(state.Commit().IsOK(), "Commit shouldn't work with non-merkle store") + assert.True(state.Commit().IsErr(), "Commit shouldn't work with non-merkle store") //Test CacheWrap with merkleeyes client store useEyesCli() diff --git a/tests/tmsp/tmsp_test.go b/tests/tmsp/tmsp_test.go index eec105deda..86b4bfbf24 100644 --- a/tests/tmsp/tmsp_test.go +++ b/tests/tmsp/tmsp_test.go @@ -57,7 +57,7 @@ func TestSendTx(t *testing.T) { txBytes := wire.BinaryBytes(types.TxS{tx}) res := bcApp.DeliverTx(txBytes) // t.Log(res) - assert.False(t, res.IsErr(), "Failed: %v", res.Error()) + assert.True(t, res.IsOK(), "Failed: %v", res.Error()) } func TestSequence(t *testing.T) { @@ -108,11 +108,11 @@ func TestSequence(t *testing.T) { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) res := bcApp.DeliverTx(txBytes) - assert.False(t, res.IsErr(), "DeliverTx error: %v", res.Error()) + assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) } res := bcApp.Commit() - assert.False(t, res.IsErr(), "Failed Commit: %v", res.Error()) + assert.True(t, res.IsOK(), "Failed Commit: %v", res.Error()) t.Log("-------------------- RANDOM SENDS --------------------") @@ -152,6 +152,6 @@ func TestSequence(t *testing.T) { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) res := bcApp.DeliverTx(txBytes) - assert.False(t, res.IsErr(), "DeliverTx error: %v", res.Error()) + assert.True(t, res.IsOK(), "DeliverTx error: %v", res.Error()) } } diff --git a/types/coin.go b/types/coin.go index 51c33ebc4a..1af65edcac 100644 --- a/types/coin.go +++ b/types/coin.go @@ -2,6 +2,8 @@ package types import ( "fmt" + "regexp" + "strconv" "strings" ) @@ -11,8 +13,27 @@ type Coin struct { } func (coin Coin) String() string { - return fmt.Sprintf("(%v %v)", - coin.Denom, coin.Amount) + return fmt.Sprintf("%v%v", coin.Amount, coin.Denom) +} + +//regex codes for extracting coins from string +var reDenom = regexp.MustCompile("([^\\d\\W]+)") +var reAmt = regexp.MustCompile("(\\d+)") + +func ParseCoin(str string) (Coin, error) { + + var coin Coin + + if len(str) > 0 { + amt, err := strconv.Atoi(reAmt.FindString(str)) + if err != nil { + return coin, err + } + denom := reDenom.FindString(str) + coin = Coin{denom, int64(amt)} + } + + return coin, nil } //---------------------------------------- @@ -22,11 +43,29 @@ type Coins []Coin func (coins Coins) String() string { out := "" for _, coin := range coins { - out += fmt.Sprintf("(%v %v) ", coin.Denom, coin.Amount) + out += fmt.Sprintf("%v,", coin.String()) } return out } +func ParseCoins(str string) (Coins, error) { + + split := strings.Split(str, ",") + var coins []Coin + + for _, el := range split { + if len(el) > 0 { + coin, err := ParseCoin(el) + if err != nil { + return coins, err + } + coins = append(coins, coin) + } + } + + return coins, nil +} + // Must be sorted, and not have 0 amounts func (coins Coins) IsValid() bool { switch len(coins) { diff --git a/types/coin_test.go b/types/coin_test.go index 3512eb836a..5de483a321 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCoins(t *testing.T) { @@ -53,3 +54,33 @@ func TestCoins(t *testing.T) { assert.False(dup.IsValid(), "Duplicate coin") } + +//Test the parse coin and parse coins functionality +func TestParse(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + makeCoin := func(str string) Coin { + coin, err := ParseCoin(str) + require.Nil(err) + return coin + } + + makeCoins := func(str string) Coins { + coin, err := ParseCoins(str) + require.Nil(err) + return coin + } + + //testing ParseCoin Function + assert.Equal(Coin{}, makeCoin(""), "ParseCoin makes bad empty coin") + assert.Equal(Coin{"fooCoin", 1}, makeCoin("1fooCoin"), "ParseCoin makes bad coins") + assert.Equal(Coin{"barCoin", 10}, makeCoin("10 barCoin"), "ParseCoin makes bad coins") + + //testing ParseCoins Function + assert.True(Coins{{"fooCoin", 1}}.IsEqual(makeCoins("1fooCoin")), + "ParseCoins doesn't parse a single coin") + assert.True(Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99barCoin,1fooCoin")), + "ParseCoins doesn't properly parse two coins") + assert.True(Coins{{"barCoin", 99}, {"fooCoin", 1}}.IsEqual(makeCoins("99 barCoin, 1 fooCoin")), + "ParseCoins doesn't properly parse two coins which use spaces") +} diff --git a/types/test_helpers.go b/types/test_helpers.go index c7ce21ff0f..070c4b739d 100644 --- a/types/test_helpers.go +++ b/types/test_helpers.go @@ -43,3 +43,56 @@ func RandAccounts(num int, minAmount int64, maxAmount int64) []PrivAccount { return privAccs } + +///////////////////////////////////////////////////////////////// + +func MakeAccs(secrets ...string) (accs []PrivAccount) { + for _, secret := range secrets { + privAcc := PrivAccountFromSecret(secret) + privAcc.Account.Balance = Coins{{"mycoin", 7}} + accs = append(accs, privAcc) + } + return +} + +func Accs2TxInputs(accs []PrivAccount, seq int) []TxInput { + var txs []TxInput + for _, acc := range accs { + tx := NewTxInput( + acc.Account.PubKey, + Coins{{"mycoin", 5}}, + seq) + txs = append(txs, tx) + } + return txs +} + +//turn a list of accounts into basic list of transaction outputs +func Accs2TxOutputs(accs []PrivAccount) []TxOutput { + var txs []TxOutput + for _, acc := range accs { + tx := TxOutput{ + acc.Account.PubKey.Address(), + Coins{{"mycoin", 4}}} + txs = append(txs, tx) + } + return txs +} + +func GetTx(seq int, accsIn, accsOut []PrivAccount) *SendTx { + txs := &SendTx{ + Gas: 0, + Fee: Coin{"mycoin", 1}, + Inputs: Accs2TxInputs(accsIn, seq), + Outputs: Accs2TxOutputs(accsOut), + } + + return txs +} + +func SignTx(chainID string, tx *SendTx, accs []PrivAccount) { + signBytes := tx.SignBytes(chainID) + for i, _ := range tx.Inputs { + tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} + } +} From 750859f1e8d6c9148e916f9bfd5994175674f738 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 13 Apr 2017 21:33:39 -0400 Subject: [PATCH 14/33] some renames and comments --- app/app_test.go | 172 +++++++++++++++++++++------------------- state/execution_test.go | 121 ++++++++++++++-------------- types/coin.go | 2 +- 3 files changed, 153 insertions(+), 142 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 1be563ed8b..31c300b6e6 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -14,6 +14,80 @@ import ( eyes "github.com/tendermint/merkleeyes/client" ) +//-------------------------------------------------------- +// test environment is a list of input and output accounts + +type appTest struct { + t *testing.T + chainID string + app *Basecoin + accsIn []types.PrivAccount + accsOut []types.PrivAccount +} + +func newAppTest(t *testing.T) *appTest { + at := &appTest{ + t: t, + chainID: "test_chain_id", + } + at.reset() + return at +} + +// make a tx sending 5mycoin from each accsIn to accsOut +func (ap *appTest) getTx(seq int) *types.SendTx { + tx := types.GetTx(seq, ap.accsIn, ap.accsOut) + types.SignTx(ap.chainID, tx, ap.accsIn) + return tx +} + +// set the account on the app through SetOption +func (at *appTest) acc2app(acc types.Account) { + accBytes, err := json.Marshal(acc) + require.Nil(at.t, err) + res := at.app.SetOption("base/account", string(accBytes)) + require.EqualValues(at.t, res, "Success") +} + +// reset the in and out accs to be one account each with 7mycoin +func (at *appTest) reset() { + at.accsIn = types.MakeAccs("input0") + at.accsOut = types.MakeAccs("output0") + + eyesCli := eyes.NewLocalClient("", 0) + at.app = NewBasecoin(eyesCli) + + res := at.app.SetOption("base/chain_id", at.chainID) + require.EqualValues(at.t, res, "Success") + + at.acc2app(at.accsIn[0].Account) + at.acc2app(at.accsOut[0].Account) + + resabci := at.app.Commit() + require.True(at.t, resabci.IsOK(), resabci) +} + +// returns the final balance and expected balance for input and output accounts +func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inputGot, inputExp, outputGot, outputExpected types.Coins) { + + initBalFoo := at.app.GetState().GetAccount(at.accsIn[0].Account.PubKey.Address()).Balance + initBalBar := at.app.GetState().GetAccount(at.accsOut[0].Account.PubKey.Address()).Balance + + txBytes := []byte(wire.BinaryBytes(struct{ types.Tx }{tx})) + if checkTx { + res = at.app.CheckTx(txBytes) + } else { + res = at.app.DeliverTx(txBytes) + } + + endBalFoo := at.app.GetState().GetAccount(at.accsIn[0].Account.PubKey.Address()).Balance + endBalBar := at.app.GetState().GetAccount(at.accsOut[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) +} + +//-------------------------------------------------------- + func TestSplitKey(t *testing.T) { assert := assert.New(t) prefix, suffix := splitKey("foo/bar") @@ -37,10 +111,10 @@ func TestSetOption(t *testing.T) { assert.EqualValues(app.GetState().GetChainID(), chainID) assert.EqualValues(res, "Success") - accsFoo := types.MakeAccs("foo") - accsFooBytes, err := json.Marshal(accsFoo[0].Account) + accsIn := types.MakeAccs("input0") + accsInBytes, err := json.Marshal(accsIn[0].Account) assert.Nil(err) - res = app.SetOption("base/account", string(accsFooBytes)) + res = app.SetOption("base/account", string(accsInBytes)) assert.EqualValues(res, "Success") res = app.SetOption("base/dslfkgjdas", "") @@ -53,21 +127,20 @@ func TestSetOption(t *testing.T) { assert.NotEqual(res, "Success") } -//CheckTx - bad bytes, bad tx, good tx. -//DeliverTx - bad bytes, bad tx, good tx. +// Test CheckTx and DeliverTx with insufficient and sufficient balance func TestTx(t *testing.T) { assert := assert.New(t) at := newAppTest(t) //Bad Balance - at.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - at.acc2app(at.accsFoo[0].Account) + at.accsIn[0].Balance = types.Coins{{"mycoin", 2}} + at.acc2app(at.accsIn[0].Account) res, _, _, _, _ := at.exec(at.getTx(1), true) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) - res, foo, fooexp, bar, barexp := at.exec(at.getTx(1), false) + res, inGot, inExp, outGot, outExp := at.exec(at.getTx(1), false) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) - assert.True(!foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) - assert.True(!bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) + assert.False(inGot.IsEqual(inExp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, inGot: %v, inExp: %v", inGot, inExp)) + assert.False(outGot.IsEqual(outExp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, outGot: %v, outExp: %v", outGot, outExp)) //Regular CheckTx at.reset() @@ -76,10 +149,10 @@ func TestTx(t *testing.T) { //Regular DeliverTx at.reset() - res, foo, fooexp, bar, barexp = at.exec(at.getTx(1), false) + res, inGot, inExp, outGot, outExp = at.exec(at.getTx(1), false) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) - assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) - assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) + assert.True(inGot.IsEqual(inExp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, inGot: %v, inExp: %v", inGot, inExp)) + assert.True(outGot.IsEqual(outExp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, outGot: %v, outExp: %v", outGot, outExp)) } func TestQuery(t *testing.T) { @@ -87,11 +160,11 @@ func TestQuery(t *testing.T) { at := newAppTest(t) res, _, _, _, _ := at.exec(at.getTx(1), false) - assert.True(res.IsOK(), fmt.Sprintf("Commit, CheckTx: Expected OK return from CheckTx, Error: %v", res)) + assert.True(res.IsOK(), fmt.Sprintf("Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", res)) resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: at.accsFoo[0].Account.PubKey.Address(), + Data: at.accsIn[0].Account.PubKey.Address(), }) res = at.app.Commit() @@ -99,76 +172,9 @@ func TestQuery(t *testing.T) { resQueryPostCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: at.accsFoo[0].Account.PubKey.Address(), + Data: at.accsIn[0].Account.PubKey.Address(), }) fmt.Println(resQueryPreCommit) fmt.Println(resQueryPostCommit) assert.NotEqual(resQueryPreCommit, resQueryPostCommit, "Query should change before/after commit") } - -///////////////////////////////////////////////////////////////// - -type appTest struct { - t *testing.T - chainID string - app *Basecoin - accsFoo []types.PrivAccount - accsBar []types.PrivAccount -} - -func newAppTest(t *testing.T) *appTest { - at := &appTest{ - t: t, - chainID: "test_chain_id", - } - at.reset() - return at -} - -func (ap *appTest) getTx(seq int) *types.SendTx { - tx := types.GetTx(seq, ap.accsFoo, ap.accsBar) - types.SignTx(ap.chainID, tx, ap.accsFoo) - return tx -} - -func (at *appTest) acc2app(acc types.Account) { - accBytes, err := json.Marshal(acc) - require.Nil(at.t, err) - res := at.app.SetOption("base/account", string(accBytes)) - require.EqualValues(at.t, res, "Success") -} - -func (at *appTest) reset() { - at.accsFoo = types.MakeAccs("foo") - at.accsBar = types.MakeAccs("bar") - - eyesCli := eyes.NewLocalClient("", 0) - at.app = NewBasecoin(eyesCli) - - res := at.app.SetOption("base/chain_id", at.chainID) - require.EqualValues(at.t, res, "Success") - - at.acc2app(at.accsFoo[0].Account) - at.acc2app(at.accsBar[0].Account) - - resabci := at.app.Commit() - require.True(at.t, resabci.IsOK(), resabci) -} - -func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { - - initBalFoo := at.app.GetState().GetAccount(at.accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := at.app.GetState().GetAccount(at.accsBar[0].Account.PubKey.Address()).Balance - - txBytes := []byte(wire.BinaryBytes(struct{ types.Tx }{tx})) - if checkTx { - res = at.app.CheckTx(txBytes) - } else { - res = at.app.DeliverTx(txBytes) - } - - endBalFoo := at.app.GetState().GetAccount(at.accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := at.app.GetState().GetAccount(at.accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) -} diff --git a/state/execution_test.go b/state/execution_test.go index b3daa068c0..210ff4e2b5 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -10,6 +10,69 @@ import ( "github.com/tendermint/basecoin/types" ) +//-------------------------------------------------------- +// test environment is a bunch of lists of accountns + +type execTest struct { + chainID string + store types.KVStore + state *State + accsFoo []types.PrivAccount + accsBar []types.PrivAccount + accsFooBar []types.PrivAccount + accsDup []types.PrivAccount +} + +func newExecTest() *execTest { + et := &execTest{ + chainID: "test_chain_id", + } + et.reset() + return et +} + +func (et *execTest) signTx(tx *types.SendTx, accsIn []types.PrivAccount) { + types.SignTx(et.chainID, tx, accsIn) +} + +// make tx from accsIn to et.accsBar +func (et *execTest) getTx(seq int, accsIn []types.PrivAccount) *types.SendTx { + return types.GetTx(seq, accsIn, et.accsBar) +} + +// returns the final balance and expected balance for input and output accounts +func (et *execTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inGot, inExp, outGot, outExp types.Coins) { + initBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance + initBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + + res = ExecTx(et.state, nil, tx, checkTx, nil) + + endBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance + endBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) +} + +func (et *execTest) acc2State(accs []types.PrivAccount) { + for _, acc := range accs { + et.state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) + } +} + +//reset everything. state is empty +func (et *execTest) reset() { + et.accsFoo = types.MakeAccs("foo") + et.accsBar = types.MakeAccs("bar") + et.accsFooBar = types.MakeAccs("foo", "bar") + et.accsDup = types.MakeAccs("foo", "foo", "foo") + + et.store = types.NewMemKVStore() + et.state = NewState(et.store) + et.state.SetChainID(et.chainID) +} + +//-------------------------------------------------------- + func TestGetInputs(t *testing.T) { assert := assert.New(t) et := newExecTest() @@ -231,61 +294,3 @@ func TestExecTx(t *testing.T) { assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) } - -/////////////////////////////////////////////////////////////////// - -type execTest struct { - chainID string - store types.KVStore - state *State - accsFoo []types.PrivAccount - accsBar []types.PrivAccount - accsFooBar []types.PrivAccount - accsDup []types.PrivAccount -} - -func newExecTest() *execTest { - et := &execTest{ - chainID: "test_chain_id", - } - et.reset() - return et -} - -func (et *execTest) signTx(tx *types.SendTx, accsIn []types.PrivAccount) { - types.SignTx(et.chainID, tx, accsIn) -} - -func (et *execTest) getTx(seq int, accsIn []types.PrivAccount) *types.SendTx { - return types.GetTx(seq, accsIn, et.accsBar) -} - -func (et *execTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, foo, fooExp, bar, barExp types.Coins) { - initBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance - - res = ExecTx(et.state, nil, tx, checkTx, nil) - - endBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) -} - -func (et *execTest) acc2State(accs []types.PrivAccount) { - for _, acc := range accs { - et.state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) - } -} - -//reset the store/et.state/Inputs -func (et *execTest) reset() { - et.accsFoo = types.MakeAccs("foo") - et.accsBar = types.MakeAccs("bar") - et.accsFooBar = types.MakeAccs("foo", "bar") - et.accsDup = types.MakeAccs("foo", "foo", "foo") - - et.store = types.NewMemKVStore() - et.state = NewState(et.store) - et.state.SetChainID(et.chainID) -} diff --git a/types/coin.go b/types/coin.go index 1af65edcac..05c3111aa6 100644 --- a/types/coin.go +++ b/types/coin.go @@ -45,7 +45,7 @@ func (coins Coins) String() string { for _, coin := range coins { out += fmt.Sprintf("%v,", coin.String()) } - return out + return out[:len(out)-1] } func ParseCoins(str string) (Coins, error) { From f857f6218b7313bb6cc413a429f6672a259749b5 Mon Sep 17 00:00:00 2001 From: Rigel Rozanski Date: Thu, 13 Apr 2017 23:28:14 -0400 Subject: [PATCH 15/33] foo->in bar->out, use of variadic variables --- app/app_test.go | 40 +++++----- state/execution_test.go | 168 ++++++++++++++++++++-------------------- types/coin.go | 4 + types/test_helpers.go | 32 ++++---- 4 files changed, 129 insertions(+), 115 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 31c300b6e6..b4e1200228 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -21,8 +21,8 @@ type appTest struct { t *testing.T chainID string app *Basecoin - accsIn []types.PrivAccount - accsOut []types.PrivAccount + accIn types.PrivAccount + accOut types.PrivAccount } func newAppTest(t *testing.T) *appTest { @@ -34,10 +34,10 @@ func newAppTest(t *testing.T) *appTest { return at } -// make a tx sending 5mycoin from each accsIn to accsOut -func (ap *appTest) getTx(seq int) *types.SendTx { - tx := types.GetTx(seq, ap.accsIn, ap.accsOut) - types.SignTx(ap.chainID, tx, ap.accsIn) +// make a tx sending 5mycoin from each accIn to accOut +func (at *appTest) getTx(seq int) *types.SendTx { + tx := types.GetTx(seq, at.accOut, at.accIn) + types.SignTx(at.chainID, tx, at.accIn) return tx } @@ -51,8 +51,8 @@ func (at *appTest) acc2app(acc types.Account) { // reset the in and out accs to be one account each with 7mycoin func (at *appTest) reset() { - at.accsIn = types.MakeAccs("input0") - at.accsOut = types.MakeAccs("output0") + at.accIn = types.MakeAcc("input0") + at.accOut = types.MakeAcc("output0") eyesCli := eyes.NewLocalClient("", 0) at.app = NewBasecoin(eyesCli) @@ -60,8 +60,8 @@ func (at *appTest) reset() { res := at.app.SetOption("base/chain_id", at.chainID) require.EqualValues(at.t, res, "Success") - at.acc2app(at.accsIn[0].Account) - at.acc2app(at.accsOut[0].Account) + at.acc2app(at.accIn.Account) + at.acc2app(at.accOut.Account) resabci := at.app.Commit() require.True(at.t, resabci.IsOK(), resabci) @@ -70,8 +70,8 @@ func (at *appTest) reset() { // returns the final balance and expected balance for input and output accounts func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inputGot, inputExp, outputGot, outputExpected types.Coins) { - initBalFoo := at.app.GetState().GetAccount(at.accsIn[0].Account.PubKey.Address()).Balance - initBalBar := at.app.GetState().GetAccount(at.accsOut[0].Account.PubKey.Address()).Balance + initBalFoo := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance + initBalBar := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance txBytes := []byte(wire.BinaryBytes(struct{ types.Tx }{tx})) if checkTx { @@ -80,8 +80,8 @@ func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inputG res = at.app.DeliverTx(txBytes) } - endBalFoo := at.app.GetState().GetAccount(at.accsIn[0].Account.PubKey.Address()).Balance - endBalBar := at.app.GetState().GetAccount(at.accsOut[0].Account.PubKey.Address()).Balance + endBalFoo := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance + endBalBar := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) } @@ -111,8 +111,8 @@ func TestSetOption(t *testing.T) { assert.EqualValues(app.GetState().GetChainID(), chainID) assert.EqualValues(res, "Success") - accsIn := types.MakeAccs("input0") - accsInBytes, err := json.Marshal(accsIn[0].Account) + accIn := types.MakeAcc("input0") + accsInBytes, err := json.Marshal(accIn.Account) assert.Nil(err) res = app.SetOption("base/account", string(accsInBytes)) assert.EqualValues(res, "Success") @@ -133,8 +133,8 @@ func TestTx(t *testing.T) { at := newAppTest(t) //Bad Balance - at.accsIn[0].Balance = types.Coins{{"mycoin", 2}} - at.acc2app(at.accsIn[0].Account) + at.accIn.Balance = types.Coins{{"mycoin", 2}} + at.acc2app(at.accIn.Account) res, _, _, _, _ := at.exec(at.getTx(1), true) assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) res, inGot, inExp, outGot, outExp := at.exec(at.getTx(1), false) @@ -164,7 +164,7 @@ func TestQuery(t *testing.T) { resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: at.accsIn[0].Account.PubKey.Address(), + Data: at.accIn.Account.PubKey.Address(), }) res = at.app.Commit() @@ -172,7 +172,7 @@ func TestQuery(t *testing.T) { resQueryPostCommit := at.app.Query(abci.RequestQuery{ Path: "/account", - Data: at.accsIn[0].Account.PubKey.Address(), + Data: at.accIn.Account.PubKey.Address(), }) fmt.Println(resQueryPreCommit) fmt.Println(resQueryPostCommit) diff --git a/state/execution_test.go b/state/execution_test.go index 210ff4e2b5..f2a0073956 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -14,13 +14,11 @@ import ( // test environment is a bunch of lists of accountns type execTest struct { - chainID string - store types.KVStore - state *State - accsFoo []types.PrivAccount - accsBar []types.PrivAccount - accsFooBar []types.PrivAccount - accsDup []types.PrivAccount + chainID string + store types.KVStore + state *State + accIn types.PrivAccount + accOut types.PrivAccount } func newExecTest() *execTest { @@ -31,29 +29,29 @@ func newExecTest() *execTest { return et } -func (et *execTest) signTx(tx *types.SendTx, accsIn []types.PrivAccount) { - types.SignTx(et.chainID, tx, accsIn) +func (et *execTest) signTx(tx *types.SendTx, accsIn ...types.PrivAccount) { + types.SignTx(et.chainID, tx, accsIn...) } -// make tx from accsIn to et.accsBar -func (et *execTest) getTx(seq int, accsIn []types.PrivAccount) *types.SendTx { - return types.GetTx(seq, accsIn, et.accsBar) +// make tx from accsIn to et.accOut +func (et *execTest) getTx(seq int, accsIn ...types.PrivAccount) *types.SendTx { + return types.GetTx(seq, et.accOut, accsIn...) } // returns the final balance and expected balance for input and output accounts func (et *execTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inGot, inExp, outGot, outExp types.Coins) { - initBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance - initBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance + initBalIn := et.state.GetAccount(et.accIn.Account.PubKey.Address()).Balance + initBalOut := et.state.GetAccount(et.accOut.Account.PubKey.Address()).Balance res = ExecTx(et.state, nil, tx, checkTx, nil) - endBalFoo := et.state.GetAccount(et.accsFoo[0].Account.PubKey.Address()).Balance - endBalBar := et.state.GetAccount(et.accsBar[0].Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) + endBalIn := et.state.GetAccount(et.accIn.Account.PubKey.Address()).Balance + endBalOut := et.state.GetAccount(et.accOut.Account.PubKey.Address()).Balance + decrBalInExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) //expected decrease in balance In + return res, endBalIn, initBalIn.Minus(decrBalInExp), endBalOut, initBalOut.Plus(tx.Outputs[0].Coins) } -func (et *execTest) acc2State(accs []types.PrivAccount) { +func (et *execTest) acc2State(accs ...types.PrivAccount) { for _, acc := range accs { et.state.SetAccount(acc.Account.PubKey.Address(), &acc.Account) } @@ -61,10 +59,8 @@ func (et *execTest) acc2State(accs []types.PrivAccount) { //reset everything. state is empty func (et *execTest) reset() { - et.accsFoo = types.MakeAccs("foo") - et.accsBar = types.MakeAccs("bar") - et.accsFooBar = types.MakeAccs("foo", "bar") - et.accsDup = types.MakeAccs("foo", "foo", "foo") + et.accIn = types.MakeAcc("foo") + et.accOut = types.MakeAcc("bar") et.store = types.NewMemKVStore() et.state = NewState(et.store) @@ -84,18 +80,18 @@ func TestGetInputs(t *testing.T) { //test getInputs for registered, non-registered account et.reset() - txs := types.Accs2TxInputs(et.accsFoo, 1) + txs := types.Accs2TxInputs(1, et.accIn) acc, res = getInputs(et.state, txs) assert.True(res.IsErr(), "getInputs: expected error when using getInput with non-registered Input") - et.acc2State(et.accsFoo) + et.acc2State(et.accIn) acc, res = getInputs(et.state, txs) assert.True(res.IsOK(), "getInputs: expected to getInput from registered Input") //test sending duplicate accounts et.reset() - et.acc2State(et.accsDup) - txs = types.Accs2TxInputs(et.accsDup, 1) + et.acc2State(et.accIn, et.accIn, et.accIn) + txs = types.Accs2TxInputs(1, et.accIn, et.accIn, et.accIn) acc, res = getInputs(et.state, txs) assert.True(res.IsErr(), "getInputs: expected error when sending duplicate accounts") } @@ -111,16 +107,16 @@ func TestGetOrMakeOutputs(t *testing.T) { //test sending duplicate accounts et.reset() - txs := types.Accs2TxOutputs(et.accsDup) + txs := types.Accs2TxOutputs(et.accIn, et.accIn, et.accIn) _, res = getOrMakeOutputs(et.state, nil, txs) assert.True(res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts") //test sending to existing/new account account et.reset() - txs1 := types.Accs2TxOutputs(et.accsFoo) - txs2 := types.Accs2TxOutputs(et.accsBar) + txs1 := types.Accs2TxOutputs(et.accIn) + txs2 := types.Accs2TxOutputs(et.accOut) - et.acc2State(et.accsFoo) + et.acc2State(et.accIn) _, res = getOrMakeOutputs(et.state, nil, txs1) assert.True(res.IsOK(), "getOrMakeOutputs: error when sending to existing account") @@ -138,7 +134,7 @@ func TestValidateInputsBasic(t *testing.T) { et := newExecTest() //validate input basic - txs := types.Accs2TxInputs(et.accsFoo, 1) + txs := types.Accs2TxInputs(1, et.accIn) res := validateInputsBasic(txs) assert.True(res.IsOK(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res.Error())) @@ -153,9 +149,9 @@ func TestValidateInputsAdvanced(t *testing.T) { et := newExecTest() //validate inputs advanced - txs := et.getTx(1, et.accsFooBar) + txs := et.getTx(1, et.accIn, et.accOut) - et.acc2State(et.accsFooBar) + et.acc2State(et.accIn, et.accOut) accMap, res := getInputs(et.state, txs.Inputs) assert.True(res.IsOK(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error())) signBytes := txs.SignBytes(et.chainID) @@ -165,7 +161,7 @@ func TestValidateInputsAdvanced(t *testing.T) { assert.True(res.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input") //test good case sgined - et.signTx(txs, et.accsFooBar) + et.signTx(txs, et.accIn, et.accOut) totalCoins, res = validateInputsAdvanced(accMap, signBytes, txs.Inputs) assert.True(res.IsOK(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error())) assert.True(totalCoins.IsEqual(txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins)), "ValidateInputsAdvanced: transaction total coins are not equal") @@ -176,31 +172,31 @@ func TestValidateInputAdvanced(t *testing.T) { et := newExecTest() //validate input advanced - txs := et.getTx(1, et.accsFooBar) + txs := et.getTx(1, et.accIn, et.accOut) - et.acc2State(et.accsFooBar) + et.acc2State(et.accIn, et.accOut) signBytes := txs.SignBytes(et.chainID) //unsigned case - res := validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) + res := validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input without signature") //good signed case - et.signTx(txs, et.accsFooBar) - res = validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) + et.signTx(txs, et.accIn, et.accOut) + res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) assert.True(res.IsOK(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error())) //bad sequence case - et.accsFooBar[0].Sequence = 2 - et.signTx(txs, et.accsFooBar) - res = validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) + et.accIn.Sequence = 2 + et.signTx(txs, et.accIn, et.accOut) + res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with bad sequence") - et.accsFooBar[0].Account.Sequence = 1 //restore sequence + et.accIn.Sequence = 1 //restore sequence //bad balance case - et.accsFooBar[1].Balance = types.Coins{{"mycoin", 2}} - et.signTx(txs, et.accsFooBar) - res = validateInputAdvanced(&et.accsFooBar[0].Account, signBytes, txs.Inputs[0]) + et.accOut.Balance = types.Coins{{"mycoin", 2}} + et.signTx(txs, et.accIn, et.accOut) + res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with insufficient funds") } @@ -209,7 +205,7 @@ func TestValidateOutputsAdvanced(t *testing.T) { et := newExecTest() //validateOutputsBasic - txs := types.Accs2TxOutputs(et.accsFoo) + txs := types.Accs2TxOutputs(et.accIn) res := validateOutputsBasic(txs) assert.True(res.IsOK(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res.Error())) @@ -223,7 +219,7 @@ func TestSumOutput(t *testing.T) { et := newExecTest() //SumOutput - txs := types.Accs2TxOutputs(et.accsFooBar) + txs := types.Accs2TxOutputs(et.accIn, et.accOut) total := sumOutputs(txs) assert.True(total.IsEqual(txs[0].Coins.Plus(txs[1].Coins)), "sumOutputs: total coins are not equal") } @@ -233,28 +229,28 @@ func TestAdjustBy(t *testing.T) { et := newExecTest() //adjustByInputs/adjustByOutputs - //sending transaction from Foo to Bar - initBalFoo := et.accsFooBar[0].Account.Balance - initBalBar := et.accsFooBar[1].Account.Balance - et.acc2State(et.accsFooBar) + //sending transaction from accIn to accOut + initBalIn := et.accIn.Account.Balance + initBalOut := et.accOut.Account.Balance + et.acc2State(et.accIn, et.accOut) - txIn := types.Accs2TxInputs(et.accsFoo, 1) - txOut := types.Accs2TxOutputs(et.accsBar) + txIn := types.Accs2TxInputs(1, et.accIn) + txOut := types.Accs2TxOutputs(et.accOut) accMap, _ := getInputs(et.state, txIn) accMap, _ = getOrMakeOutputs(et.state, accMap, txOut) adjustByInputs(et.state, accMap, txIn) adjustByOutputs(et.state, accMap, txOut, false) - endBalFoo := accMap[string(et.accsFooBar[0].Account.PubKey.Address())].Balance - endBalBar := accMap[string(et.accsFooBar[1].Account.PubKey.Address())].Balance - decrBalFoo := initBalFoo.Minus(endBalFoo) - incrBalBar := endBalBar.Minus(initBalBar) + endBalIn := accMap[string(et.accIn.Account.PubKey.Address())].Balance + endBalOut := accMap[string(et.accOut.Account.PubKey.Address())].Balance + decrBalIn := initBalIn.Minus(endBalIn) + incrBalOut := endBalOut.Minus(initBalOut) - assert.True(decrBalFoo.IsEqual(txIn[0].Coins), - fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalFoo.String(), txIn[0].Coins.String())) - assert.True(incrBalBar.IsEqual(txOut[0].Coins), - fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalBar.String(), txOut[0].Coins.String())) + assert.True(decrBalIn.IsEqual(txIn[0].Coins), + fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalIn.String(), txIn[0].Coins.String())) + assert.True(incrBalOut.IsEqual(txOut[0].Coins), + fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalOut.String(), txOut[0].Coins.String())) } @@ -263,34 +259,42 @@ func TestExecTx(t *testing.T) { et := newExecTest() //ExecTx - txs := et.getTx(1, et.accsFoo) - et.acc2State(et.accsFoo) - et.acc2State(et.accsBar) - et.signTx(txs, et.accsFoo) + txs := et.getTx(1, et.accIn) + et.acc2State(et.accIn) + et.acc2State(et.accOut) + et.signTx(txs, et.accIn) //Bad Balance - et.accsFoo[0].Balance = types.Coins{{"mycoin", 2}} - et.acc2State(et.accsFoo) + et.accIn.Balance = types.Coins{{"mycoin", 2}} + et.acc2State(et.accIn) res, _, _, _, _ := et.exec(txs, true) - assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) - res, foo, fooexp, bar, barexp := et.exec(txs, false) - assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) - assert.False(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, foo: %v, fooExp: %v", foo, fooexp)) - assert.False(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, bar: %v, barExp: %v", bar, barexp)) + assert.True(res.IsErr(), + fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) + + res, balIn, balInExp, balOut, balOutExp := et.exec(txs, false) + assert.True(res.IsErr(), + fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) + assert.False(balIn.IsEqual(balInExp), + fmt.Sprintf("ExecTx/Bad DeliverTx: balance shouldn't be equal for accIn: got %v, expected: %v", balIn, balInExp)) + assert.False(balOut.IsEqual(balOutExp), + fmt.Sprintf("ExecTx/Bad DeliverTx: balance shouldn't be equal for accOut: got %v, expected: %v", balOut, balOutExp)) //Regular CheckTx et.reset() - et.acc2State(et.accsFoo) - et.acc2State(et.accsBar) + et.acc2State(et.accIn) + et.acc2State(et.accOut) res, _, _, _, _ = et.exec(txs, true) assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) //Regular DeliverTx et.reset() - et.acc2State(et.accsFoo) - et.acc2State(et.accsBar) - res, foo, fooexp, bar, barexp = et.exec(txs, false) - assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) - assert.True(foo.IsEqual(fooexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, foo: %v, fooExp: %v", foo, fooexp)) - assert.True(bar.IsEqual(barexp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, bar: %v, barExp: %v", bar, barexp)) + et.acc2State(et.accIn) + et.acc2State(et.accOut) + res, balIn, balInExp, balOut, balOutExp = et.exec(txs, false) + assert.True(res.IsOK(), + fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) + assert.True(balIn.IsEqual(balInExp), + fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input balance, got: %v, expected: %v", balIn, balInExp)) + assert.True(balOut.IsEqual(balOutExp), + fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output balance, got: %v, expected: %v", balOut, balOutExp)) } diff --git a/types/coin.go b/types/coin.go index 05c3111aa6..e34f7d1bdb 100644 --- a/types/coin.go +++ b/types/coin.go @@ -41,6 +41,10 @@ func ParseCoin(str string) (Coin, error) { type Coins []Coin func (coins Coins) String() string { + if len(coins) == 0 { + return "" + } + out := "" for _, coin := range coins { out += fmt.Sprintf("%v,", coin.String()) diff --git a/types/test_helpers.go b/types/test_helpers.go index 070c4b739d..81e639ee10 100644 --- a/types/test_helpers.go +++ b/types/test_helpers.go @@ -46,16 +46,22 @@ func RandAccounts(num int, minAmount int64, maxAmount int64) []PrivAccount { ///////////////////////////////////////////////////////////////// -func MakeAccs(secrets ...string) (accs []PrivAccount) { - for _, secret := range secrets { - privAcc := PrivAccountFromSecret(secret) - privAcc.Account.Balance = Coins{{"mycoin", 7}} - accs = append(accs, privAcc) - } - return +//func MakeAccs(secrets ...string) (accs []PrivAccount) { +// for _, secret := range secrets { +// privAcc := PrivAccountFromSecret(secret) +// privAcc.Account.Balance = Coins{{"mycoin", 7}} +// accs = append(accs, privAcc) +// } +// return +//} + +func MakeAcc(secret string) PrivAccount { + privAcc := PrivAccountFromSecret(secret) + privAcc.Account.Balance = Coins{{"mycoin", 7}} + return privAcc } -func Accs2TxInputs(accs []PrivAccount, seq int) []TxInput { +func Accs2TxInputs(seq int, accs ...PrivAccount) []TxInput { var txs []TxInput for _, acc := range accs { tx := NewTxInput( @@ -68,7 +74,7 @@ func Accs2TxInputs(accs []PrivAccount, seq int) []TxInput { } //turn a list of accounts into basic list of transaction outputs -func Accs2TxOutputs(accs []PrivAccount) []TxOutput { +func Accs2TxOutputs(accs ...PrivAccount) []TxOutput { var txs []TxOutput for _, acc := range accs { tx := TxOutput{ @@ -79,18 +85,18 @@ func Accs2TxOutputs(accs []PrivAccount) []TxOutput { return txs } -func GetTx(seq int, accsIn, accsOut []PrivAccount) *SendTx { +func GetTx(seq int, accOut PrivAccount, accsIn ...PrivAccount) *SendTx { txs := &SendTx{ Gas: 0, Fee: Coin{"mycoin", 1}, - Inputs: Accs2TxInputs(accsIn, seq), - Outputs: Accs2TxOutputs(accsOut), + Inputs: Accs2TxInputs(seq, accsIn...), + Outputs: Accs2TxOutputs(accOut), } return txs } -func SignTx(chainID string, tx *SendTx, accs []PrivAccount) { +func SignTx(chainID string, tx *SendTx, accs ...PrivAccount) { signBytes := tx.SignBytes(chainID) for i, _ := range tx.Inputs { tx.Inputs[i].Signature = crypto.SignatureS{accs[i].Sign(signBytes)} From e6ec782f0c7c0536d748e7e9dc9453b771d6210c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 17 Apr 2017 17:47:00 -0400 Subject: [PATCH 16/33] minor cleanup --- app/app_test.go | 12 ++++++------ state/execution_test.go | 10 +++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index b4e1200228..4ce7210534 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -70,8 +70,8 @@ func (at *appTest) reset() { // returns the final balance and expected balance for input and output accounts func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inputGot, inputExp, outputGot, outputExpected types.Coins) { - initBalFoo := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance - initBalBar := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance + initBalIn := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance + initBalOut := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance txBytes := []byte(wire.BinaryBytes(struct{ types.Tx }{tx})) if checkTx { @@ -80,10 +80,10 @@ func (at *appTest) exec(tx *types.SendTx, checkTx bool) (res abci.Result, inputG res = at.app.DeliverTx(txBytes) } - endBalFoo := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance - endBalBar := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance - decrBalFooExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) - return res, endBalFoo, initBalFoo.Minus(decrBalFooExp), endBalBar, initBalBar.Plus(tx.Outputs[0].Coins) + endBalIn := at.app.GetState().GetAccount(at.accIn.Account.PubKey.Address()).Balance + endBalOut := at.app.GetState().GetAccount(at.accOut.Account.PubKey.Address()).Balance + decrBalInExp := tx.Outputs[0].Coins.Plus(types.Coins{tx.Fee}) + return res, endBalIn, initBalIn.Minus(decrBalInExp), endBalOut, initBalOut.Plus(tx.Outputs[0].Coins) } //-------------------------------------------------------- diff --git a/state/execution_test.go b/state/execution_test.go index f2a0073956..a6648e90b6 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -65,6 +65,10 @@ func (et *execTest) reset() { et.store = types.NewMemKVStore() et.state = NewState(et.store) et.state.SetChainID(et.chainID) + + // NOTE we dont run acc2State here + // so we can test non-existing accounts + } //-------------------------------------------------------- @@ -111,7 +115,7 @@ func TestGetOrMakeOutputs(t *testing.T) { _, res = getOrMakeOutputs(et.state, nil, txs) assert.True(res.IsErr(), "getOrMakeOutputs: expected error when sending duplicate accounts") - //test sending to existing/new account account + //test sending to existing/new account et.reset() txs1 := types.Accs2TxOutputs(et.accIn) txs2 := types.Accs2TxOutputs(et.accOut) @@ -207,11 +211,11 @@ func TestValidateOutputsAdvanced(t *testing.T) { //validateOutputsBasic txs := types.Accs2TxOutputs(et.accIn) res := validateOutputsBasic(txs) - assert.True(res.IsOK(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx input. Error: %v", res.Error())) + assert.True(res.IsOK(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx output. Error: %v", res.Error())) txs[0].Coins[0].Amount = 0 res = validateOutputsBasic(txs) - assert.True(res.IsErr(), fmt.Sprintf("validateInputBasic: expected error on bad tx inputi. Error: %v", res.Error())) + assert.True(res.IsErr(), fmt.Sprintf("validateInputBasic: expected error on bad tx output. Error: %v", res.Error())) } func TestSumOutput(t *testing.T) { From e36a40c6034d8738144c330f8afaa2f070a85e3d Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Mon, 17 Apr 2017 19:53:06 -0400 Subject: [PATCH 17/33] fixes, remove assert with Sprintf --- app/app_test.go | 20 ++++++----- state/execution_test.go | 75 ++++++++++++++++++++++------------------- types/account_test.go | 3 +- types/coin_test.go | 7 ++-- types/tx_test.go | 4 +-- 5 files changed, 58 insertions(+), 51 deletions(-) diff --git a/app/app_test.go b/app/app_test.go index 4ce7210534..011d9d7561 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -136,23 +136,25 @@ func TestTx(t *testing.T) { at.accIn.Balance = types.Coins{{"mycoin", 2}} at.acc2app(at.accIn.Account) res, _, _, _, _ := at.exec(at.getTx(1), true) - assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) + assert.True(res.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res) res, inGot, inExp, outGot, outExp := at.exec(at.getTx(1), false) - assert.True(res.IsErr(), fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) - assert.False(inGot.IsEqual(inExp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, inGot: %v, inExp: %v", inGot, inExp)) - assert.False(outGot.IsEqual(outExp), fmt.Sprintf("ExecTx/Bad DeliverTx: shouldn't be equal, outGot: %v, outExp: %v", outGot, outExp)) + assert.True(res.IsErr(), "ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res) + assert.False(inGot.IsEqual(inExp), "ExecTx/Bad DeliverTx: shouldn't be equal, inGot: %v, inExp: %v", inGot, inExp) + assert.False(outGot.IsEqual(outExp), "ExecTx/Bad DeliverTx: shouldn't be equal, outGot: %v, outExp: %v", outGot, outExp) //Regular CheckTx at.reset() res, _, _, _, _ = at.exec(at.getTx(1), true) - assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) + assert.True(res.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res) //Regular DeliverTx at.reset() res, inGot, inExp, outGot, outExp = at.exec(at.getTx(1), false) - assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) - assert.True(inGot.IsEqual(inExp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input coins, inGot: %v, inExp: %v", inGot, inExp)) - assert.True(outGot.IsEqual(outExp), fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output coins, outGot: %v, outExp: %v", outGot, outExp)) + assert.True(res.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res) + assert.True(inGot.IsEqual(inExp), + "ExecTx/good DeliverTx: unexpected change in input coins, inGot: %v, inExp: %v", inGot, inExp) + assert.True(outGot.IsEqual(outExp), + "ExecTx/good DeliverTx: unexpected change in output coins, outGot: %v, outExp: %v", outGot, outExp) } func TestQuery(t *testing.T) { @@ -160,7 +162,7 @@ func TestQuery(t *testing.T) { at := newAppTest(t) res, _, _, _, _ := at.exec(at.getTx(1), false) - assert.True(res.IsOK(), fmt.Sprintf("Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", res)) + assert.True(res.IsOK(), "Commit, DeliverTx: Expected OK return from DeliverTx, Error: %v", res) resQueryPreCommit := at.app.Query(abci.RequestQuery{ Path: "/account", diff --git a/state/execution_test.go b/state/execution_test.go index a6648e90b6..f6f1d9e95d 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -1,7 +1,6 @@ package state import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -34,8 +33,8 @@ func (et *execTest) signTx(tx *types.SendTx, accsIn ...types.PrivAccount) { } // make tx from accsIn to et.accOut -func (et *execTest) getTx(seq int, accsIn ...types.PrivAccount) *types.SendTx { - return types.GetTx(seq, et.accOut, accsIn...) +func (et *execTest) getTx(seq int, accOut types.PrivAccount, accsIn ...types.PrivAccount) *types.SendTx { + return types.GetTx(seq, accOut, accsIn...) } // returns the final balance and expected balance for input and output accounts @@ -140,7 +139,7 @@ func TestValidateInputsBasic(t *testing.T) { //validate input basic txs := types.Accs2TxInputs(1, et.accIn) res := validateInputsBasic(txs) - assert.True(res.IsOK(), fmt.Sprintf("validateInputsBasic: expected no error on good tx input. Error: %v", res.Error())) + assert.True(res.IsOK(), "validateInputsBasic: expected no error on good tx input. Error: %v", res.Error()) txs[0].Coins[0].Amount = 0 res = validateInputsBasic(txs) @@ -152,12 +151,17 @@ func TestValidateInputsAdvanced(t *testing.T) { assert := assert.New(t) et := newExecTest() - //validate inputs advanced - txs := et.getTx(1, et.accIn, et.accOut) + //create three temp accounts for the test + accIn1 := types.MakeAcc("foox") + accIn2 := types.MakeAcc("fooy") + accIn3 := types.MakeAcc("fooz") - et.acc2State(et.accIn, et.accOut) + //validate inputs advanced + txs := et.getTx(1, et.accOut, accIn1, accIn2, accIn3) + + et.acc2State(accIn1, accIn2, accIn3, et.accOut) accMap, res := getInputs(et.state, txs.Inputs) - assert.True(res.IsOK(), fmt.Sprintf("validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error())) + assert.True(res.IsOK(), "validateInputsAdvanced: error retrieving accMap. Error: %v", res.Error()) signBytes := txs.SignBytes(et.chainID) //test bad case, unsigned @@ -165,10 +169,15 @@ func TestValidateInputsAdvanced(t *testing.T) { assert.True(res.IsErr(), "validateInputsAdvanced: expected an error on an unsigned tx input") //test good case sgined - et.signTx(txs, et.accIn, et.accOut) + et.signTx(txs, accIn1, accIn2, accIn3, et.accOut) totalCoins, res = validateInputsAdvanced(accMap, signBytes, txs.Inputs) - assert.True(res.IsOK(), fmt.Sprintf("validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error())) - assert.True(totalCoins.IsEqual(txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins)), "ValidateInputsAdvanced: transaction total coins are not equal") + assert.True(res.IsOK(), "validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error()) + + txsTotalCoins := txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins) + txsTotalCoins = txsTotalCoins.Plus(txs.Inputs[2].Coins) + + assert.True(totalCoins.IsEqual(txsTotalCoins), + "ValidateInputsAdvanced: transaction total coins are not equal: got %v, expected %v", txsTotalCoins, totalCoins) } func TestValidateInputAdvanced(t *testing.T) { @@ -176,7 +185,7 @@ func TestValidateInputAdvanced(t *testing.T) { et := newExecTest() //validate input advanced - txs := et.getTx(1, et.accIn, et.accOut) + txs := et.getTx(1, et.accOut, et.accIn) et.acc2State(et.accIn, et.accOut) signBytes := txs.SignBytes(et.chainID) @@ -188,20 +197,21 @@ func TestValidateInputAdvanced(t *testing.T) { //good signed case et.signTx(txs, et.accIn, et.accOut) res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) - assert.True(res.IsOK(), fmt.Sprintf("validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error())) + assert.True(res.IsOK(), "validateInputAdvanced: expected no error on good tx input. Error: %v", res.Error()) //bad sequence case - et.accIn.Sequence = 2 + et.accIn.Sequence = 1 et.signTx(txs, et.accIn, et.accOut) res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) - assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with bad sequence") - et.accIn.Sequence = 1 //restore sequence + assert.Equal(abci.CodeType_BaseInvalidSequence, res.Code, "validateInputAdvanced: expected error on tx input with bad sequence") + et.accIn.Sequence = 0 //restore sequence //bad balance case - et.accOut.Balance = types.Coins{{"mycoin", 2}} + et.accIn.Balance = types.Coins{{"mycoin", 2}} et.signTx(txs, et.accIn, et.accOut) res = validateInputAdvanced(&et.accIn.Account, signBytes, txs.Inputs[0]) - assert.True(res.IsErr(), "validateInputAdvanced: expected error on tx input with insufficient funds") + assert.Equal(abci.CodeType_BaseInsufficientFunds, res.Code, + "validateInputAdvanced: expected error on tx input with insufficient funds %v", et.accIn.Sequence) } func TestValidateOutputsAdvanced(t *testing.T) { @@ -211,11 +221,11 @@ func TestValidateOutputsAdvanced(t *testing.T) { //validateOutputsBasic txs := types.Accs2TxOutputs(et.accIn) res := validateOutputsBasic(txs) - assert.True(res.IsOK(), fmt.Sprintf("validateOutputsBasic: expected no error on good tx output. Error: %v", res.Error())) + assert.True(res.IsOK(), "validateOutputsBasic: expected no error on good tx output. Error: %v", res.Error()) txs[0].Coins[0].Amount = 0 res = validateOutputsBasic(txs) - assert.True(res.IsErr(), fmt.Sprintf("validateInputBasic: expected error on bad tx output. Error: %v", res.Error())) + assert.True(res.IsErr(), "validateInputBasic: expected error on bad tx output. Error: %v", res.Error()) } func TestSumOutput(t *testing.T) { @@ -252,9 +262,9 @@ func TestAdjustBy(t *testing.T) { incrBalOut := endBalOut.Minus(initBalOut) assert.True(decrBalIn.IsEqual(txIn[0].Coins), - fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalIn.String(), txIn[0].Coins.String())) + "adjustByInputs: total coins are not equal. diff: %v, tx: %v", decrBalIn.String(), txIn[0].Coins.String()) assert.True(incrBalOut.IsEqual(txOut[0].Coins), - fmt.Sprintf("adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalOut.String(), txOut[0].Coins.String())) + "adjustByInputs: total coins are not equal. diff: %v, tx: %v", incrBalOut.String(), txOut[0].Coins.String()) } @@ -263,7 +273,7 @@ func TestExecTx(t *testing.T) { et := newExecTest() //ExecTx - txs := et.getTx(1, et.accIn) + txs := et.getTx(1, et.accOut, et.accIn) et.acc2State(et.accIn) et.acc2State(et.accOut) et.signTx(txs, et.accIn) @@ -272,33 +282,30 @@ func TestExecTx(t *testing.T) { et.accIn.Balance = types.Coins{{"mycoin", 2}} et.acc2State(et.accIn) res, _, _, _, _ := et.exec(txs, true) - assert.True(res.IsErr(), - fmt.Sprintf("ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res)) + assert.True(res.IsErr(), "ExecTx/Bad CheckTx: Expected error return from ExecTx, returned: %v", res) res, balIn, balInExp, balOut, balOutExp := et.exec(txs, false) - assert.True(res.IsErr(), - fmt.Sprintf("ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res)) + assert.True(res.IsErr(), "ExecTx/Bad DeliverTx: Expected error return from ExecTx, returned: %v", res) assert.False(balIn.IsEqual(balInExp), - fmt.Sprintf("ExecTx/Bad DeliverTx: balance shouldn't be equal for accIn: got %v, expected: %v", balIn, balInExp)) + "ExecTx/Bad DeliverTx: balance shouldn't be equal for accIn: got %v, expected: %v", balIn, balInExp) assert.False(balOut.IsEqual(balOutExp), - fmt.Sprintf("ExecTx/Bad DeliverTx: balance shouldn't be equal for accOut: got %v, expected: %v", balOut, balOutExp)) + "ExecTx/Bad DeliverTx: balance shouldn't be equal for accOut: got %v, expected: %v", balOut, balOutExp) //Regular CheckTx et.reset() et.acc2State(et.accIn) et.acc2State(et.accOut) res, _, _, _, _ = et.exec(txs, true) - assert.True(res.IsOK(), fmt.Sprintf("ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res)) + assert.True(res.IsOK(), "ExecTx/Good CheckTx: Expected OK return from ExecTx, Error: %v", res) //Regular DeliverTx et.reset() et.acc2State(et.accIn) et.acc2State(et.accOut) res, balIn, balInExp, balOut, balOutExp = et.exec(txs, false) - assert.True(res.IsOK(), - fmt.Sprintf("ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res)) + assert.True(res.IsOK(), "ExecTx/Good DeliverTx: Expected OK return from ExecTx, Error: %v", res) assert.True(balIn.IsEqual(balInExp), - fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in input balance, got: %v, expected: %v", balIn, balInExp)) + "ExecTx/good DeliverTx: unexpected change in input balance, got: %v, expected: %v", balIn, balInExp) assert.True(balOut.IsEqual(balOutExp), - fmt.Sprintf("ExecTx/good DeliverTx: unexpected change in output balance, got: %v, expected: %v", balOut, balOutExp)) + "ExecTx/good DeliverTx: unexpected change in output balance, got: %v, expected: %v", balOut, balOutExp) } diff --git a/types/account_test.go b/types/account_test.go index 7c60c9eb15..6bcb997d87 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -1,7 +1,6 @@ package types import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -14,7 +13,7 @@ func TestNilAccount(t *testing.T) { //test Copy accCopy := acc.Copy() //note that the assert.True is used instead of assert.Equal because looking at pointers - assert.True(t, &acc != accCopy, fmt.Sprintf("Account Copy Error, acc1: %v, acc2: %v", &acc, accCopy)) + assert.True(t, &acc != accCopy, "Account Copy Error, acc1: %v, acc2: %v", &acc, accCopy) assert.Equal(t, acc.Sequence, accCopy.Sequence) //test sending nils for panic diff --git a/types/coin_test.go b/types/coin_test.go index 5de483a321..8cbc708a49 100644 --- a/types/coin_test.go +++ b/types/coin_test.go @@ -1,7 +1,6 @@ package types import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -44,9 +43,9 @@ func TestCoins(t *testing.T) { } assert.True(good.IsValid(), "Coins are valid") - assert.True(good.IsPositive(), fmt.Sprintf("Expected coins to be positive: %v", good)) - assert.True(good.IsGTE(empty), fmt.Sprintf("Expected %v to be >= %v", good, empty)) - assert.False(neg.IsPositive(), fmt.Sprintf("Expected neg coins to not be positive: %v", neg)) + assert.True(good.IsPositive(), "Expected coins to be positive: %v", good) + assert.True(good.IsGTE(empty), "Expected %v to be >= %v", good, empty) + assert.False(neg.IsPositive(), "Expected neg coins to not be positive: %v", neg) assert.Zero(len(sum), "Expected 0 coins") assert.False(badSort1.IsValid(), "Coins are not sorted") assert.False(badSort2.IsValid(), "Coins are not sorted") diff --git a/types/tx_test.go b/types/tx_test.go index 5eac4c8695..71033cc9e7 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -44,7 +44,7 @@ func TestSendTxSignable(t *testing.T) { expected := "010A746573745F636861696E0100000000000000DE00000000000000006F01020106696E7075743101010000000000000030390301093200000106696E70757432010100000000000000006F01DE0000010201076F757470757431010100000000000000014D01076F75747075743201010000000000000001BC" assert.Equal(t, signBytesHex, expected, - fmt.Sprintf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) + "Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex) } func TestAppTxSignable(t *testing.T) { @@ -64,7 +64,7 @@ func TestAppTxSignable(t *testing.T) { expected := "010A746573745F636861696E0100000000000000DE00000000000000006F0101580106696E70757431010100000000000000303903010932000001056461746131" assert.Equal(t, signBytesHex, expected, - fmt.Sprintf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex)) + "Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signBytesHex) } func TestSendTxJSON(t *testing.T) { From eae5dc18610b73614de6677f53da05910db4ba3b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 17 Apr 2017 20:10:31 -0400 Subject: [PATCH 18/33] tiny cleanup --- state/execution_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/state/execution_test.go b/state/execution_test.go index f6f1d9e95d..249380b9fe 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -173,8 +173,9 @@ func TestValidateInputsAdvanced(t *testing.T) { totalCoins, res = validateInputsAdvanced(accMap, signBytes, txs.Inputs) assert.True(res.IsOK(), "validateInputsAdvanced: expected no error on good tx input. Error: %v", res.Error()) - txsTotalCoins := txs.Inputs[0].Coins.Plus(txs.Inputs[1].Coins) - txsTotalCoins = txsTotalCoins.Plus(txs.Inputs[2].Coins) + txsTotalCoins := txs.Inputs[0].Coins. + Plus(txs.Inputs[1].Coins). + Plus(txs.Inputs[2].Coins) assert.True(totalCoins.IsEqual(txsTotalCoins), "ValidateInputsAdvanced: transaction total coins are not equal: got %v, expected %v", txsTotalCoins, totalCoins) From c6e348e01b552b7e1433409fb80961f3245d3681 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 21 Apr 2017 17:41:42 +0200 Subject: [PATCH 19/33] Update to tendermint 0.9.1 --- glide.lock | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/glide.lock b/glide.lock index 6d411f59ae..38755f1a6a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,18 +1,18 @@ -hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348 -updated: 2017-04-13T21:40:19.30156119-04:00 +hash: c023dbd97e1ea0a525e33738f03afd6be61f997f1c2592a5d9928fdcecc71361 +updated: 2017-04-21T17:38:13.194966906+02:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 subpackages: - btcec - name: github.com/BurntSushi/toml - version: 99064174e013895bbd9b025c31100bd1d9b590ca + version: e643e9ef00b049d75de26e61109c5ea01885cd21 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 69b215d01a5606c843240eab4937eab3acee6530 + version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317 subpackages: - proto - name: github.com/golang/snappy @@ -22,11 +22,11 @@ imports: - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable - version: acb9493f2794fd0f820de7a27a217dafbb1b65ea + version: a392f450ea64cee2b268dfaacdc2502b50a22b18 - name: github.com/mattn/go-isatty - version: 9622e0cc9d8f9be434ca605520ff9a16808fee47 + version: 57fdcb988a5c543893cc61bce354a6e24ab70022 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: bfd5150e4e41705ded2129ec33379de1cb90b513 - name: github.com/syndtr/goleveldb version: 3c5717caf1475fd25964109a0fc640bd150fce43 subpackages: @@ -43,7 +43,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 31eafe8f8eba6b8817edd74df399f508540da528 + version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998 subpackages: - client - example/dummy @@ -59,15 +59,15 @@ imports: - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: 6af2364fa91ef2f3afc8ba0db33b66d9d3ae006c + version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-config version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 + version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db - version: eac3f2bc147023957c8bf69432a4e6c4dc5c3f72 + version: 9643f60bc2578693844aacf380a7c32e4c029fee - name: github.com/tendermint/go-events version: f8ffbfb2be3483e9e7927495590a727f51c0c11f - name: github.com/tendermint/go-flowrate @@ -79,17 +79,17 @@ imports: - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: c39e001a957caf768f06c85c840debb8282c3aaa + version: 17124989a93774833df33107fbf17157a7f8ef31 subpackages: - upnp - name: github.com/tendermint/go-rpc - version: c3295f4878019ff3fdfcac37a4c0e4bcf4bb02a7 + version: 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: ad797c70affa2c81fccc5edaed63ac25144397c6 + version: c1c9a57ab8038448ddea1714c0698f8051e5748c - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -100,7 +100,7 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: 585ce45a5e253743da7b72d9a2385c01059fc6d5 + version: 7cf773e2d37b2b5a08bc94fb125cfd346b834824 subpackages: - blockchain - config/tendermint @@ -112,12 +112,15 @@ imports: - rpc/core/types - rpc/grpc - state + - state/txindex + - state/txindex/kv + - state/txindex/null - types - version - name: github.com/urfave/cli - version: 8ef3805c9de2519805c3f060524b695bba2cd715 + version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/crypto - version: 40541ccb1c6e64c947ed6f606b8a6cb4b67d7436 + version: 728b753d0135da6801d45a38e6f43ff55779c5c2 subpackages: - curve25519 - nacl/box @@ -128,7 +131,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: d379faa25cbdc04d653984913a2ceb43b0bc46d7 + version: a6577fac2d73be281a500b310739095313165611 subpackages: - context - http2 @@ -138,16 +141,17 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: e48874b42435b4347fc52bdee0424a52abc974d7 + version: 99f16d856c9836c42d24e7ab64ea72916925fa97 subpackages: - unix - name: google.golang.org/grpc - version: 7b399ed358736bc5522021cdc7d79a8ee9ac6f98 + version: 0713829b980f4ddd276689a36235c5fcc82a21bf subpackages: - codes - credentials - grpclog - internal + - keepalive - metadata - naming - peer @@ -156,11 +160,11 @@ imports: - transport testImports: - name: github.com/davecgh/go-spew - version: 346938d642f2ec3594ed81d874461961cd0faa76 + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/pmezard/go-difflib - version: 792786c7400a136282c1664665ae0a8db921c6c2 + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: - difflib - name: github.com/stretchr/testify From fb3fd1b425636c7be1721bcd4905772c57dfe078 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 9 Mar 2017 02:19:07 -0500 Subject: [PATCH 20/33] added cli cobra rebaseFixes int removed ExitOnErr int int int int int added uint64 to RegisterFlags --- cmd/basecoin/main.go | 22 +- cmd/commands/flags.go | 119 ---------- cmd/commands/ibc.go | 301 +++++++++++--------------- cmd/commands/init.go | 62 ++++-- cmd/commands/key.go | 38 ++-- cmd/commands/plugin_util.go | 41 ++++ cmd/commands/query.go | 175 ++++++++------- cmd/commands/reset.go | 39 +--- cmd/commands/start.go | 93 ++++---- cmd/commands/tx.go | 203 ++++++++--------- cmd/commands/utils.go | 74 ++++++- cmd/commands/version.go | 17 ++ cmd/counter/cmd.go | 51 ++--- cmd/counter/main.go | 27 ++- demo/start.sh | 6 +- docs/guide/example-plugin.md | 51 ++++- docs/guide/src/example-plugin/cmd.go | 44 ++-- docs/guide/src/example-plugin/main.go | 32 ++- glide.lock | 27 ++- glide.yaml | 20 +- 20 files changed, 716 insertions(+), 726 deletions(-) delete mode 100644 cmd/commands/flags.go create mode 100644 cmd/commands/plugin_util.go create mode 100644 cmd/commands/version.go diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index 4eb4c944c5..bcb5493010 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -4,17 +4,18 @@ import ( "fmt" "os" + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/cmd/commands" - "github.com/tendermint/basecoin/version" - "github.com/urfave/cli" ) func main() { - app := cli.NewApp() - app.Name = "basecoin" - app.Usage = "basecoin [command] [args...]" - app.Version = version.Version - app.Commands = []cli.Command{ + var RootCmd = &cobra.Command{ + Use: "basecoin", + Short: "A cryptocurrency framework in Golang based on Tendermint-Core", + } + + RootCmd.AddCommand( commands.InitCmd, commands.StartCmd, commands.TxCmd, @@ -24,9 +25,10 @@ func main() { commands.BlockCmd, commands.AccountCmd, commands.UnsafeResetAllCmd, - } - err := app.Run(os.Args) - if err != nil { + commands.VersionCmd, + ) + + if err := RootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } diff --git a/cmd/commands/flags.go b/cmd/commands/flags.go deleted file mode 100644 index ccf95769d3..0000000000 --- a/cmd/commands/flags.go +++ /dev/null @@ -1,119 +0,0 @@ -package commands - -import ( - "github.com/urfave/cli" -) - -// start flags -var ( - AddrFlag = cli.StringFlag{ - Name: "address", - Value: "tcp://0.0.0.0:46658", - Usage: "Listen address", - } - - EyesFlag = cli.StringFlag{ - Name: "eyes", - Value: "local", - Usage: "MerkleEyes address, or 'local' for embedded", - } - - // TODO: move to config file - // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") - - WithoutTendermintFlag = cli.BoolFlag{ - Name: "without-tendermint", - Usage: "Run the Basecoin app without Tendermint", - } -) - -// tx flags - -var ( - NodeFlag = cli.StringFlag{ - Name: "node", - Value: "tcp://localhost:46657", - Usage: "Tendermint RPC address", - } - - ToFlag = cli.StringFlag{ - Name: "to", - Value: "", - Usage: "Destination address for the transaction", - } - - AmountFlag = cli.StringFlag{ - Name: "amount", - Value: "", - Usage: "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver)", - } - - FromFlag = cli.StringFlag{ - Name: "from", - Value: "key.json", - Usage: "Path to a private key to sign the transaction", - } - - SeqFlag = cli.IntFlag{ - Name: "sequence", - Value: 0, - Usage: "Sequence number for the account", - } - - GasFlag = cli.IntFlag{ - Name: "gas", - Value: 0, - Usage: "The amount of gas for the transaction", - } - - FeeFlag = cli.StringFlag{ - Name: "fee", - Value: "", - Usage: "Coins for the transaction fee of the format ", - } - - DataFlag = cli.StringFlag{ - Name: "data", - Value: "", - Usage: "Data to send with the transaction", - } - - NameFlag = cli.StringFlag{ - Name: "name", - Value: "", - Usage: "Plugin to send the transaction to", - } - - ChainIDFlag = cli.StringFlag{ - Name: "chain_id", - Value: "test_chain_id", - Usage: "ID of the chain for replay protection", - } -) - -// proof flags -var ( - ProofFlag = cli.StringFlag{ - Name: "proof", - Usage: "hex-encoded IAVL proof", - Value: "", - } - - KeyFlag = cli.StringFlag{ - Name: "key", - Usage: "key to the IAVL tree", - Value: "", - } - - ValueFlag = cli.StringFlag{ - Name: "value", - Usage: "value in the IAVL tree", - Value: "", - } - - RootFlag = cli.StringFlag{ - Name: "root", - Usage: "root hash of the IAVL tree", - Value: "", - } -) diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 34f4b7923d..48fd4d6c2b 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -2,11 +2,10 @@ package commands import ( "encoding/hex" - "errors" "fmt" "io/ioutil" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/tendermint/basecoin/plugins/ibc" @@ -21,172 +20,110 @@ func NewIBCPlugin() *ibc.IBCPlugin { return ibc.New() } -//--------------------------------------------------------------------- -// ibc flags - +//commands var ( - IbcChainIDFlag = cli.StringFlag{ - Name: "chain_id", - Usage: "ChainID for the new blockchain", - Value: "", + IBCTxCmd = &cobra.Command{ + Use: "ibc", + Short: "An IBC transaction, for InterBlockchain Communication", } - IbcGenesisFlag = cli.StringFlag{ - Name: "genesis", - Usage: "Genesis file for the new blockchain", - Value: "", + IBCRegisterTxCmd = &cobra.Command{ + Use: "register", + Short: "Register a blockchain via IBC", + Run: ibcRegisterTxCmd, } - IbcHeaderFlag = cli.StringFlag{ - Name: "header", - Usage: "Block header for an ibc update", - Value: "", + IBCUpdateTxCmd = &cobra.Command{ + Use: "update", + Short: "Update the latest state of a blockchain via IBC", + Run: ibcUpdateTxCmd, } - IbcCommitFlag = cli.StringFlag{ - Name: "commit", - Usage: "Block commit for an ibc update", - Value: "", + IBCPacketTxCmd = &cobra.Command{ + Use: "packet", + Short: "Send a new packet via IBC", } - IbcFromFlag = cli.StringFlag{ - Name: "from", - Usage: "Source ChainID", - Value: "", + IBCPacketCreateTxCmd = &cobra.Command{ + Use: "create", + Short: "Create an egress IBC packet", + Run: ibcPacketCreateTxCmd, } - IbcToFlag = cli.StringFlag{ - Name: "to", - Usage: "Destination ChainID", - Value: "", - } - - IbcTypeFlag = cli.StringFlag{ - Name: "type", - Usage: "IBC packet type (eg. coin)", - Value: "", - } - - IbcPayloadFlag = cli.StringFlag{ - Name: "payload", - Usage: "IBC packet payload", - Value: "", - } - - IbcPacketFlag = cli.StringFlag{ - Name: "packet", - Usage: "hex-encoded IBC packet", - Value: "", - } - - IbcProofFlag = cli.StringFlag{ - Name: "proof", - Usage: "hex-encoded proof of IBC packet from source chain", - Value: "", - } - - IbcSequenceFlag = cli.IntFlag{ - Name: "sequence", - Usage: "sequence number for IBC packet", - Value: 0, - } - - IbcHeightFlag = cli.IntFlag{ - Name: "height", - Usage: "Height the packet became egress in source chain", - Value: 0, + IBCPacketPostTxCmd = &cobra.Command{ + Use: "post", + Short: "Deliver an IBC packet to another chain", + Run: ibcPacketPostTxCmd, } ) -//--------------------------------------------------------------------- -// ibc commands - +//flags var ( - IbcTxCmd = cli.Command{ - Name: "ibc", - Usage: "an IBC transaction, for InterBlockchain Communication", - Flags: TxFlags, - Subcommands: []cli.Command{ - IbcRegisterTxCmd, - IbcUpdateTxCmd, - IbcPacketTxCmd, - }, - } - - IbcRegisterTxCmd = cli.Command{ - Name: "register", - Usage: "Register a blockchain via IBC", - Action: func(c *cli.Context) error { - return cmdIBCRegisterTx(c) - }, - Flags: []cli.Flag{ - IbcChainIDFlag, - IbcGenesisFlag, - }, - } - - IbcUpdateTxCmd = cli.Command{ - Name: "update", - Usage: "Update the latest state of a blockchain via IBC", - Action: func(c *cli.Context) error { - return cmdIBCUpdateTx(c) - }, - Flags: []cli.Flag{ - IbcHeaderFlag, - IbcCommitFlag, - }, - } - - IbcPacketTxCmd = cli.Command{ - Name: "packet", - Usage: "Send a new packet via IBC", - Subcommands: []cli.Command{ - IbcPacketCreateTx, - IbcPacketPostTx, - }, - } - - IbcPacketCreateTx = cli.Command{ - Name: "create", - Usage: "Create an egress IBC packet", - Action: func(c *cli.Context) error { - return cmdIBCPacketCreateTx(c) - }, - Flags: []cli.Flag{ - IbcFromFlag, - IbcToFlag, - IbcTypeFlag, - IbcPayloadFlag, - IbcSequenceFlag, - }, - } - - IbcPacketPostTx = cli.Command{ - Name: "post", - Usage: "Deliver an IBC packet to another chain", - Action: func(c *cli.Context) error { - return cmdIBCPacketPostTx(c) - }, - Flags: []cli.Flag{ - IbcFromFlag, - IbcHeightFlag, - IbcPacketFlag, - IbcProofFlag, - }, - } + ibcChainIDFlag string + ibcGenesisFlag string + ibcHeaderFlag string + ibcCommitFlag string + ibcFromFlag string + ibcToFlag string + ibcTypeFlag string + ibcPayloadFlag string + ibcPacketFlag string + ibcProofFlag string + ibcSequenceFlag int + ibcHeightFlag int ) +func init() { + + // register flags + registerFlags := []Flag2Register{ + {&ibcChainIDFlag, "ibc_chain_id", "", "ChainID for the new blockchain"}, + {&ibcGenesisFlag, "genesis", "", "Genesis file for the new blockchain"}, + } + + updateFlags := []Flag2Register{ + {&ibcHeaderFlag, "header", "", "Block header for an ibc update"}, + {&ibcCommitFlag, "commit", "", "Block commit for an ibc update"}, + } + + fromFlagReg := Flag2Register{&ibcFromFlag, "ibc_from", "", "Source ChainID"} + + packetCreateFlags := []Flag2Register{ + fromFlagReg, + {&ibcToFlag, "to", "", "Destination ChainID"}, + {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin},"}, + {&ibcPayloadFlag, "payload", "", "IBC packet payload"}, + {&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"}, + } + + packetPostFlags := []Flag2Register{ + fromFlagReg, + {&ibcHeightFlag, "height", 0, "Height the packet became egress in source chain"}, + {&ibcPacketFlag, "packet", "", "hex-encoded IBC packet"}, + {&ibcProofFlag, "proof", "", "hex-encoded proof of IBC packet from source chain"}, + } + + RegisterFlags(IBCRegisterTxCmd, registerFlags) + RegisterFlags(IBCUpdateTxCmd, updateFlags) + RegisterFlags(IBCPacketCreateTxCmd, packetCreateFlags) + RegisterFlags(IBCPacketPostTxCmd, packetPostFlags) + + //register commands + IBCTxCmd.AddCommand(IBCRegisterTxCmd, IBCUpdateTxCmd, IBCPacketTxCmd) + IBCPacketTxCmd.AddCommand(IBCPacketCreateTxCmd, IBCPacketPostTxCmd) + RegisterTxSubcommand(IBCTxCmd) +} + //--------------------------------------------------------------------- // ibc command implementations -func cmdIBCRegisterTx(c *cli.Context) error { - chainID := c.String("chain_id") - genesisFile := c.String("genesis") - parent := c.Parent() +func ibcRegisterTxCmd(cmd *cobra.Command, args []string) { + chainID := ibcChainIDFlag + genesisFile := ibcGenesisFlag genesisBytes, err := ioutil.ReadFile(genesisFile) if err != nil { - return errors.New(cmn.Fmt("Error reading genesis file %v: %v", genesisFile, err)) + cmn.Exit(fmt.Sprintf("Error reading genesis file %v: %+v\n", genesisFile, err)) } ibcTx := ibc.IBCRegisterChainTx{ @@ -203,27 +140,31 @@ func cmdIBCRegisterTx(c *cli.Context) error { }{ibcTx})) name := "IBC" - return AppTx(parent, name, data) + AppTx(name, data) } -func cmdIBCUpdateTx(c *cli.Context) error { - headerBytes, err := hex.DecodeString(StripHex(c.String("header"))) +func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { + headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag)) if err != nil { - return errors.New(cmn.Fmt("Header (%v) is invalid hex: %v", c.String("header"), err)) + cmn.Exit(fmt.Sprintf("Header (%v) is invalid hex: %+v\n", ibcHeaderFlag, err)) } - commitBytes, err := hex.DecodeString(StripHex(c.String("commit"))) + + commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag)) if err != nil { - return errors.New(cmn.Fmt("Commit (%v) is invalid hex: %v", c.String("commit"), err)) + cmn.Exit(fmt.Sprintf("Commit (%v) is invalid hex: %+v\n", ibcCommitFlag, err)) } header := new(tmtypes.Header) commit := new(tmtypes.Commit) - if err := wire.ReadBinaryBytes(headerBytes, &header); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling header: %v", err)) + err = wire.ReadBinaryBytes(headerBytes, &header) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling header: %+v\n", err)) } - if err := wire.ReadBinaryBytes(commitBytes, &commit); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling commit: %v", err)) + + err = wire.ReadBinaryBytes(commitBytes, &commit) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling commit: %+v\n", err)) } ibcTx := ibc.IBCUpdateChainTx{ @@ -238,21 +179,21 @@ func cmdIBCUpdateTx(c *cli.Context) error { }{ibcTx})) name := "IBC" - return AppTx(c.Parent(), name, data) + AppTx(name, data) } -func cmdIBCPacketCreateTx(c *cli.Context) error { - fromChain, toChain := c.String("from"), c.String("to") - packetType := c.String("type") +func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) { + fromChain, toChain := ibcFromFlag, ibcToFlag + packetType := ibcTypeFlag - payloadBytes, err := hex.DecodeString(StripHex(c.String("payload"))) + payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag)) if err != nil { - return errors.New(cmn.Fmt("Payload (%v) is invalid hex: %v", c.String("payload"), err)) + cmn.Exit(fmt.Sprintf("Payload (%v) is invalid hex: %+v\n", ibcPayloadFlag, err)) } - sequence, err := getIBCSequence(c) + sequence, err := ibcSequenceCmd() if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } ibcTx := ibc.IBCPacketCreateTx{ @@ -271,29 +212,33 @@ func cmdIBCPacketCreateTx(c *cli.Context) error { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - return AppTx(c.Parent().Parent(), "IBC", data) + AppTx("IBC", data) } -func cmdIBCPacketPostTx(c *cli.Context) error { - fromChain, fromHeight := c.String("from"), c.Int("height") +func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { + fromChain, fromHeight := ibcFromFlag, ibcHeightFlag - packetBytes, err := hex.DecodeString(StripHex(c.String("packet"))) + packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag)) if err != nil { - return errors.New(cmn.Fmt("Packet (%v) is invalid hex: %v", c.String("packet"), err)) + cmn.Exit(fmt.Sprintf("Packet (%v) is invalid hex: %+v\n", ibcPacketFlag, err)) } - proofBytes, err := hex.DecodeString(StripHex(c.String("proof"))) + + proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag)) if err != nil { - return errors.New(cmn.Fmt("Proof (%v) is invalid hex: %v", c.String("proof"), err)) + cmn.Exit(fmt.Sprintf("Proof (%v) is invalid hex: %+v\n", ibcProofFlag, err)) } var packet ibc.Packet proof := new(merkle.IAVLProof) - if err := wire.ReadBinaryBytes(packetBytes, &packet); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling packet: %v", err)) + err = wire.ReadBinaryBytes(packetBytes, &packet) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling packet: %+v\n", err)) } - if err := wire.ReadBinaryBytes(proofBytes, &proof); err != nil { - return errors.New(cmn.Fmt("Error unmarshalling proof: %v", err)) + + err = wire.ReadBinaryBytes(proofBytes, &proof) + if err != nil { + cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) } ibcTx := ibc.IBCPacketPostTx{ @@ -309,12 +254,12 @@ func cmdIBCPacketPostTx(c *cli.Context) error { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - return AppTx(c.Parent().Parent(), "IBC", data) + AppTx("IBC", data) } -func getIBCSequence(c *cli.Context) (uint64, error) { - if c.IsSet("sequence") { - return uint64(c.Int("sequence")), nil +func ibcSequenceCmd() (uint64, error) { + if ibcSequenceFlag >= 0 { + return uint64(ibcSequenceFlag), nil } // TODO: get sequence diff --git a/cmd/commands/init.go b/cmd/commands/init.go index e60e7d1306..99bff657c8 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -1,27 +1,38 @@ package commands import ( + "fmt" "io/ioutil" "path" - "github.com/urfave/cli" + "github.com/spf13/cobra" cmn "github.com/tendermint/go-common" ) -var InitCmd = cli.Command{ - Name: "init", - Usage: "Initialize a basecoin blockchain", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdInit(c) - }, - Flags: []cli.Flag{ - ChainIDFlag, - }, -} +//commands +var ( + InitCmd = &cobra.Command{ + Use: "init", + Short: "Initialize a basecoin blockchain", + Run: initCmd, + } +) -func cmdInit(c *cli.Context) error { +//flags +//var chainIDFlag string + +//func init() { +// +// //register flags +// flags := []Flag2Register{ +// {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, +// } +// RegisterFlags(InitCmd, flags) +// +//} + +func initCmd(cmd *cobra.Command, args []string) { rootDir := BasecoinRoot("") cmn.EnsureDir(rootDir, 0777) @@ -32,22 +43,27 @@ func cmdInit(c *cli.Context) error { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - if err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644); err != nil { - return err + err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - if err := ioutil.WriteFile(privValFile, []byte(privValJSON), 0400); err != nil { - return err + + err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - if err := ioutil.WriteFile(key1File, []byte(key1JSON), 0400); err != nil { - return err + + err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - if err := ioutil.WriteFile(key2File, []byte(key2JSON), 0400); err != nil { - return err + + err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) - - return nil } const privValJSON = `{ diff --git a/cmd/commands/key.go b/cmd/commands/key.go index 124f390ddf..a79ca92f16 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -8,38 +8,38 @@ import ( "path" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" ) +//commands var ( - KeyCmd = cli.Command{ - Name: "key", - Usage: "Manage keys", - ArgsUsage: "", - Subcommands: []cli.Command{NewKeyCmd}, + KeyCmd = &cobra.Command{ + Use: "key", + Short: "Manage keys", } - NewKeyCmd = cli.Command{ - Name: "new", - Usage: "Create a new private key", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdNewKey(c) - }, + NewKeyCmd = &cobra.Command{ + Use: "new", + Short: "Create a new private key", + Run: newKeyCmd, } ) -func cmdNewKey(c *cli.Context) error { +func newKeyCmd(cmd *cobra.Command, args []string) { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Println(string(keyJSON)) - return nil +} + +func init() { + //register commands + KeyCmd.AddCommand(NewKeyCmd) } //--------------------------------------------- @@ -88,12 +88,14 @@ func LoadKey(keyFile string) *Key { filePath := path.Join(BasecoinRoot(""), keyFile) keyJSONBytes, err := ioutil.ReadFile(filePath) if err != nil { - cmn.Exit(err.Error()) + cmn.Exit(fmt.Sprintf("%+v\n", err)) } + key := new(Key) err = json.Unmarshal(keyJSONBytes, key) if err != nil { - cmn.Exit(cmn.Fmt("Error reading key from %v: %v\n", filePath, err)) + cmn.Exit(fmt.Sprintf("Error reading key from %v: %v\n", filePath, err)) } + return key } diff --git a/cmd/commands/plugin_util.go b/cmd/commands/plugin_util.go new file mode 100644 index 0000000000..082ff2669f --- /dev/null +++ b/cmd/commands/plugin_util.go @@ -0,0 +1,41 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/types" +) + +type plugin struct { + name string + newPlugin func() types.Plugin +} + +var plugins = []plugin{} + +// RegisterStartPlugin is used to enable a plugin +func RegisterStartPlugin(name string, newPlugin func() types.Plugin) { + plugins = append(plugins, plugin{name: name, newPlugin: newPlugin}) +} + +// Register a subcommand of QueryCmd for plugin specific query functionality +func RegisterQuerySubcommand(cmd *cobra.Command) { + QueryCmd.AddCommand(cmd) +} + +// Register a subcommand of TxCmd to craft transactions for plugins +func RegisterTxSubcommand(cmd *cobra.Command) { + TxCmd.AddCommand(cmd) +} + +//Returns a version command based on version input +func QuickVersionCmd(version string) *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "Show version info", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version) + }, + } +} diff --git a/cmd/commands/query.go b/cmd/commands/query.go index 231d32f9fb..7e6e8de285 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -2,11 +2,10 @@ package commands import ( "encoding/hex" - "errors" "fmt" "strconv" - "github.com/urfave/cli" + "github.com/spf13/cobra" cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" @@ -14,85 +13,85 @@ import ( tmtypes "github.com/tendermint/tendermint/types" ) +//commands var ( - QueryCmd = cli.Command{ - Name: "query", - Usage: "Query the merkle tree", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdQuery(c) - }, - Flags: []cli.Flag{ - NodeFlag, - }, + QueryCmd = &cobra.Command{ + Use: "query [key]", + Short: "Query the merkle tree", + Run: queryCmd, } - AccountCmd = cli.Command{ - Name: "account", - Usage: "Get details of an account", - ArgsUsage: "
", - Action: func(c *cli.Context) error { - return cmdAccount(c) - }, - Flags: []cli.Flag{ - NodeFlag, - }, + AccountCmd = &cobra.Command{ + Use: "account [address]", + Short: "Get details of an account", + Run: accountCmd, } - BlockCmd = cli.Command{ - Name: "block", - Usage: "Get the header and commit of a block", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdBlock(c) - }, - Flags: []cli.Flag{ - NodeFlag, - }, + BlockCmd = &cobra.Command{ + Use: "block [height]", + Short: "Get the header and commit of a block", + Run: blockCmd, } - VerifyCmd = cli.Command{ - Name: "verify", - Usage: "Verify the IAVL proof", - Action: func(c *cli.Context) error { - return cmdVerify(c) - }, - Flags: []cli.Flag{ - ProofFlag, - KeyFlag, - ValueFlag, - RootFlag, - }, + VerifyCmd = &cobra.Command{ + Use: "verify", + Short: "Verify the IAVL proof", + Run: verifyCmd, } ) -// Register a subcommand of QueryCmd for plugin specific query functionality -func RegisterQuerySubcommand(cmd cli.Command) { - QueryCmd.Subcommands = append(QueryCmd.Subcommands, cmd) +//flags +var ( + nodeFlag string + proofFlag string + keyFlag string + valueFlag string + rootFlag string +) + +func init() { + + commonFlags := []Flag2Register{ + {&nodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, + } + + verifyFlags := []Flag2Register{ + {&proofFlag, "proof", "", "hex-encoded IAVL proof"}, + {&keyFlag, "key", "", "key to the IAVL tree"}, + {&valueFlag, "value", "", "value in the IAVL tree"}, + {&rootFlag, "root", "", "root hash of the IAVL tree"}, + } + + RegisterFlags(QueryCmd, commonFlags) + RegisterFlags(AccountCmd, commonFlags) + RegisterFlags(BlockCmd, commonFlags) + RegisterFlags(VerifyCmd, verifyFlags) } -func cmdQuery(c *cli.Context) error { - if len(c.Args()) != 1 { - return errors.New("query command requires an argument ([key])") +func queryCmd(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + cmn.Exit("query command requires an argument ([key])") } - keyString := c.Args()[0] + + keyString := args[0] key := []byte(keyString) if isHex(keyString) { // convert key to bytes var err error key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - return errors.New(cmn.Fmt("Query key (%v) is invalid hex: %v", keyString, err)) + cmn.Exit(fmt.Sprintf("Query key (%v) is invalid hex: %+v\n", keyString, err)) } } - resp, err := Query(c.String("node"), key) + resp, err := Query(nodeFlag, key) if err != nil { - return err + cmn.Exit(fmt.Sprintf("Query returns error: %+v\n", err)) } if !resp.Code.IsOK() { - return errors.New(cmn.Fmt("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log)) + cmn.Exit(fmt.Sprintf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log)) } val := resp.Value @@ -104,43 +103,44 @@ func cmdQuery(c *cli.Context) error { Proof []byte `json:"proof"` Height uint64 `json:"height"` }{val, proof, height}))) - - return nil } -func cmdAccount(c *cli.Context) error { - if len(c.Args()) != 1 { - return errors.New("account command requires an argument ([address])") +func accountCmd(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + cmn.Exit("account command requires an argument ([address])") } - addrHex := StripHex(c.Args()[0]) + + addrHex := StripHex(args[0]) // convert destination address to bytes addr, err := hex.DecodeString(addrHex) if err != nil { - return errors.New(cmn.Fmt("Account address (%v) is invalid hex: %v", addrHex, err)) + cmn.Exit(fmt.Sprintf("Account address (%v) is invalid hex: %+v\n", addrHex, err)) } - acc, err := getAcc(c.String("node"), addr) + acc, err := getAcc(nodeFlag, addr) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Println(string(wire.JSONBytes(acc))) - return nil } -func cmdBlock(c *cli.Context) error { - if len(c.Args()) != 1 { - return errors.New("block command requires an argument ([height])") - } - heightString := c.Args()[0] - height, err := strconv.Atoi(heightString) - if err != nil { - return errors.New(cmn.Fmt("Height must be an int, got %v: %v", heightString, err)) +func blockCmd(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + cmn.Exit("block command requires an argument ([height])") } - header, commit, err := getHeaderAndCommit(c, height) + heightString := args[0] + height, err := strconv.Atoi(heightString) if err != nil { - return err + cmn.Exit(fmt.Sprintf("Height must be an int, got %v: %+v\n", heightString, err)) + } + + header, commit, err := getHeaderAndCommit(nodeFlag, height) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Println(string(wire.JSONBytes(struct { @@ -156,8 +156,6 @@ func cmdBlock(c *cli.Context) error { Commit: commit, }, }))) - - return nil } type BlockHex struct { @@ -170,15 +168,16 @@ type BlockJSON struct { Commit *tmtypes.Commit `json:"commit"` } -func cmdVerify(c *cli.Context) error { - keyString, valueString := c.String("key"), c.String("value") +func verifyCmd(cmd *cobra.Command, args []string) { + + keyString, valueString := keyFlag, valueFlag var err error key := []byte(keyString) if isHex(keyString) { key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - return errors.New(cmn.Fmt("Key (%v) is invalid hex: %v", keyString, err)) + cmn.Exit(fmt.Sprintf("Key (%v) is invalid hex: %+v\n", keyString, err)) } } @@ -186,29 +185,25 @@ func cmdVerify(c *cli.Context) error { if isHex(valueString) { value, err = hex.DecodeString(StripHex(valueString)) if err != nil { - return errors.New(cmn.Fmt("Value (%v) is invalid hex: %v", valueString, err)) + cmn.Exit(fmt.Sprintf("Value (%v) is invalid hex: %+v\n", valueString, err)) } } - root, err := hex.DecodeString(StripHex(c.String("root"))) + root, err := hex.DecodeString(StripHex(rootFlag)) if err != nil { - return errors.New(cmn.Fmt("Root (%v) is invalid hex: %v", c.String("root"), err)) + cmn.Exit(fmt.Sprintf("Root (%v) is invalid hex: %+v\n", rootFlag, err)) } - proofBytes, err := hex.DecodeString(StripHex(c.String("proof"))) - if err != nil { - return errors.New(cmn.Fmt("Proof (%v) is invalid hex: %v", c.String("proof"), err)) - } + proofBytes, err := hex.DecodeString(StripHex(proofFlag)) proof, err := merkle.ReadProof(proofBytes) if err != nil { - return errors.New(cmn.Fmt("Error unmarshalling proof: %v", err)) + cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) } if proof.Verify(key, value, root) { fmt.Println("OK") } else { - return errors.New("Proof does not verify") + cmn.Exit(fmt.Sprintf("Proof does not verify")) } - return nil } diff --git a/cmd/commands/reset.go b/cmd/commands/reset.go index d9688fd859..f2841ea801 100644 --- a/cmd/commands/reset.go +++ b/cmd/commands/reset.go @@ -1,47 +1,24 @@ package commands import ( - "os" "path" - "github.com/urfave/cli" + "github.com/spf13/cobra" + "github.com/tendermint/tendermint/cmd/tendermint/commands" tmcfg "github.com/tendermint/tendermint/config/tendermint" - types "github.com/tendermint/tendermint/types" ) -var UnsafeResetAllCmd = cli.Command{ - Name: "unsafe_reset_all", - Usage: "Reset all blockchain data", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdUnsafeResetAll(c) - }, +var UnsafeResetAllCmd = &cobra.Command{ + Use: "unsafe_reset_all", + Short: "Reset all blockchain data", + Run: unsafeResetAllCmd, } -func cmdUnsafeResetAll(c *cli.Context) error { +func unsafeResetAllCmd(cmd *cobra.Command, args []string) { basecoinDir := BasecoinRoot("") tmDir := path.Join(basecoinDir) tmConfig := tmcfg.GetConfig(tmDir) - // Get and Reset PrivValidator - var privValidator *types.PrivValidator - privValidatorFile := tmConfig.GetString("priv_validator_file") - if _, err := os.Stat(privValidatorFile); err == nil { - privValidator = types.LoadPrivValidator(privValidatorFile) - privValidator.Reset() - log.Notice("Reset PrivValidator", "file", privValidatorFile) - } else { - privValidator = types.GenPrivValidator() - privValidator.SetFile(privValidatorFile) - privValidator.Save() - log.Notice("Generated PrivValidator", "file", privValidatorFile) - } - - // Remove all tendermint data - tmDataDir := tmConfig.GetString("db_dir") - os.RemoveAll(tmDataDir) - log.Notice("Removed all data", "dir", tmDataDir) - - return nil + commands.ResetAll(tmConfig, log) } diff --git a/cmd/commands/start.go b/cmd/commands/start.go index 1e6861ac06..d14f663d12 100644 --- a/cmd/commands/start.go +++ b/cmd/commands/start.go @@ -1,12 +1,11 @@ package commands import ( - "errors" "fmt" "os" "path" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/tendermint/abci/server" cmn "github.com/tendermint/go-common" @@ -18,50 +17,51 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/tendermint/basecoin/app" - "github.com/tendermint/basecoin/types" ) +var StartCmd = &cobra.Command{ + Use: "start", + Short: "Start basecoin", + Run: startCmd, +} + +//flags +var ( + addrFlag string + eyesFlag string + dirFlag string + withoutTendermintFlag bool +) + +// TODO: move to config file const EyesCacheSize = 10000 -var StartCmd = cli.Command{ - Name: "start", - Usage: "Start basecoin", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdStart(c) - }, - Flags: []cli.Flag{ - AddrFlag, - EyesFlag, - WithoutTendermintFlag, - ChainIDFlag, - }, +func init() { + + flags := []Flag2Register{ + {&addrFlag, "address", "tcp://0.0.0.0:46658", "Listen address"}, + {&eyesFlag, "eyes", "local", "MerkleEyes address, or 'local' for embedded"}, + {&dirFlag, "dir", ".", "Root directory"}, + {&withoutTendermintFlag, "without-tendermint", false, "Run Tendermint in-process with the App"}, + } + RegisterFlags(StartCmd, flags) + + // TODO: move to config file + // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") } -type plugin struct { - name string - newPlugin func() types.Plugin -} - -var plugins = []plugin{} - -// RegisterStartPlugin is used to enable a plugin -func RegisterStartPlugin(name string, newPlugin func() types.Plugin) { - plugins = append(plugins, plugin{name: name, newPlugin: newPlugin}) -} - -func cmdStart(c *cli.Context) error { +func startCmd(cmd *cobra.Command, args []string) { basecoinDir := BasecoinRoot("") // Connect to MerkleEyes var eyesCli *eyes.Client - if c.String("eyes") == "local" { + if eyesFlag == "local" { eyesCli = eyes.NewLocalClient(path.Join(basecoinDir, "data", "merkleeyes.db"), EyesCacheSize) } else { var err error - eyesCli, err = eyes.NewClient(c.String("eyes")) + eyesCli, err = eyes.NewClient(eyesFlag) if err != nil { - return errors.New("connect to MerkleEyes: " + err.Error()) + cmn.Exit(fmt.Sprintf("Error connecting to MerkleEyes: %+v\n", err)) } } @@ -84,7 +84,7 @@ func cmdStart(c *cli.Context) error { if _, err := os.Stat(genesisFile); err == nil { err := basecoinApp.LoadGenesis(genesisFile) if err != nil { - return errors.New(cmn.Fmt("%+v", err)) + cmn.Exit(fmt.Sprintf("Error in LoadGenesis: %+v\n", err)) } } else { fmt.Printf("No genesis file at %s, skipping...\n", genesisFile) @@ -92,40 +92,37 @@ func cmdStart(c *cli.Context) error { } chainID := basecoinApp.GetState().GetChainID() - if c.Bool("without-tendermint") { + if withoutTendermintFlag { log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID) // run just the abci app/server - return startBasecoinABCI(c, basecoinApp) + startBasecoinABCI(basecoinApp) } else { log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID) // start the app with tendermint in-process - return startTendermint(basecoinDir, basecoinApp) + startTendermint(basecoinDir, basecoinApp) } - - return nil } -func startBasecoinABCI(c *cli.Context, basecoinApp *app.Basecoin) error { +func startBasecoinABCI(basecoinApp *app.Basecoin) { + // Start the ABCI listener - svr, err := server.NewServer(c.String("address"), "socket", basecoinApp) + svr, err := server.NewServer(addrFlag, "socket", basecoinApp) if err != nil { - return errors.New("create listener: " + err.Error()) + cmn.Exit(fmt.Sprintf("Error creating listener: %+v\n", err)) } + // Wait forever cmn.TrapSignal(func() { // Cleanup svr.Stop() }) - return nil - } -func startTendermint(dir string, basecoinApp *app.Basecoin) error { +func startTendermint(dir string, basecoinApp *app.Basecoin) { + // Get configuration tmConfig := tmcfg.GetConfig(dir) - // logger.SetLogLevel("notice") //config.GetString("log_level")) - // parseFlags(config, args[1:]) // Command line overrides // Create & start tendermint node @@ -135,7 +132,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error { _, err := n.Start() if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } // Wait forever @@ -143,6 +140,4 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error { // Cleanup n.Stop() }) - - return nil } diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 338bbcb22b..95358221f4 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -2,10 +2,10 @@ package commands import ( "encoding/hex" - "errors" "fmt" - "github.com/urfave/cli" + "github.com/pkg/errors" + "github.com/spf13/cobra" "github.com/tendermint/basecoin/types" crypto "github.com/tendermint/go-crypto" @@ -16,211 +16,215 @@ import ( ctypes "github.com/tendermint/tendermint/rpc/core/types" ) -var TxFlags = []cli.Flag{ - NodeFlag, - ChainIDFlag, - - FromFlag, - - AmountFlag, - GasFlag, - FeeFlag, - SeqFlag, -} - +//commands var ( - TxCmd = cli.Command{ - Name: "tx", - Usage: "Create, sign, and broadcast a transaction", - ArgsUsage: "", - Subcommands: []cli.Command{ - SendTxCmd, - AppTxCmd, - IbcTxCmd, - }, + TxCmd = &cobra.Command{ + Use: "tx", + Short: "Create, sign, and broadcast a transaction", } - SendTxCmd = cli.Command{ - Name: "send", - Usage: "a SendTx transaction, for sending tokens around", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdSendTx(c) - }, - Flags: append(TxFlags, ToFlag), + SendTxCmd = &cobra.Command{ + Use: "send", + Short: "A SendTx transaction, for sending tokens around", + Run: sendTxCmd, } - AppTxCmd = cli.Command{ - Name: "app", - Usage: "an AppTx transaction, for sending raw data to plugins", - ArgsUsage: "", - Action: func(c *cli.Context) error { - return cmdAppTx(c) - }, - Flags: append(TxFlags, NameFlag, DataFlag), - // Subcommands are dynamically registered with plugins as needed - Subcommands: []cli.Command{}, + AppTxCmd = &cobra.Command{ + Use: "app", + Short: "An AppTx transaction, for sending raw data to plugins", + Run: appTxCmd, } ) -// Register a subcommand of TxCmd to craft transactions for plugins -func RegisterTxSubcommand(cmd cli.Command) { - TxCmd.Subcommands = append(TxCmd.Subcommands, cmd) +//flags +var ( + txNodeFlag string + toFlag string + amountFlag string + fromFlag string + seqFlag int + gasFlag int + feeFlag string + dataFlag string + nameFlag string + chainIDFlag string +) + +func init() { + + // register flags + cmdTxFlags := []Flag2Register{ + {&txNodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, + {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, + {&fromFlag, "from", "key.json", "Path to a private key to sign the transaction"}, + {&amountFlag, "amount", "", "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver},"}, + {&gasFlag, "gas", 0, "The amount of gas for the transaction"}, + {&feeFlag, "fee", "", "Coins for the transaction fee of the format "}, + {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate},"}, + } + + sendTxFlags := []Flag2Register{ + {&toFlag, "to", "", "Destination address for the transaction"}, + } + + appTxFlags := []Flag2Register{ + {&nameFlag, "name", "", "Plugin to send the transaction to"}, + {&dataFlag, "data", "", "Data to send with the transaction"}, + } + + RegisterPersistentFlags(TxCmd, cmdTxFlags) + RegisterFlags(SendTxCmd, sendTxFlags) + RegisterFlags(AppTxCmd, appTxFlags) + + //register commands + TxCmd.AddCommand(SendTxCmd, AppTxCmd) } -func cmdSendTx(c *cli.Context) error { - toHex := c.String("to") - fromFile := c.String("from") - amount := c.String("amount") - gas := int64(c.Int("gas")) - fee := c.String("fee") - chainID := c.String("chain_id") +func sendTxCmd(cmd *cobra.Command, args []string) { // convert destination address to bytes - to, err := hex.DecodeString(StripHex(toHex)) + to, err := hex.DecodeString(StripHex(toFlag)) if err != nil { - return errors.New("To address is invalid hex: " + err.Error()) + cmn.Exit(fmt.Sprintf("To address is invalid hex: %+v\n", err)) } // load the priv key - privKey := LoadKey(fromFile) + privKey := LoadKey(fromFlag) // get the sequence number for the tx - sequence, err := getSeq(c, privKey.Address[:]) + sequence, err := getSeq(privKey.Address[:]) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } //parse the fee and amounts into coin types - feeCoin, err := types.ParseCoin(fee) + feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - amountCoins, err := types.ParseCoins(amount) + amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } // craft the tx input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) output := newOutput(to, amountCoins) tx := &types.SendTx{ - Gas: gas, + Gas: int64(gasFlag), Fee: feeCoin, Inputs: []types.TxInput{input}, Outputs: []types.TxOutput{output}, } // sign that puppy - signBytes := tx.SignBytes(chainID) + signBytes := tx.SignBytes(chainIDFlag) tx.Inputs[0].Signature = crypto.SignatureS{privKey.Sign(signBytes)} fmt.Println("Signed SendTx:") fmt.Println(string(wire.JSONBytes(tx))) // broadcast the transaction to tendermint - data, log, err := broadcastTx(c, tx) + data, log, err := broadcastTx(tx) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Printf("Response: %X ; %s\n", data, log) - return nil } -func cmdAppTx(c *cli.Context) error { +func appTxCmd(cmd *cobra.Command, args []string) { // convert data to bytes - dataString := c.String("data") - data := []byte(dataString) - if isHex(dataString) { - data, _ = hex.DecodeString(dataString) + data := []byte(dataFlag) + if isHex(dataFlag) { + data, _ = hex.DecodeString(dataFlag) } - name := c.String("name") - return AppTx(c, name, data) + name := nameFlag + AppTx(name, data) } -func AppTx(c *cli.Context, name string, data []byte) error { - fromFile := c.String("from") - amount := c.String("amount") - fee := c.String("fee") - gas := int64(c.Int("gas")) - chainID := c.String("chain_id") +func AppTx(name string, data []byte) { - privKey := LoadKey(fromFile) + privKey := LoadKey(fromFlag) - sequence, err := getSeq(c, privKey.Address[:]) + sequence, err := getSeq(privKey.Address[:]) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } //parse the fee and amounts into coin types - feeCoin, err := types.ParseCoin(fee) + feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } - amountCoins, err := types.ParseCoins(amount) + + amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) tx := &types.AppTx{ - Gas: gas, + Gas: int64(gasFlag), Fee: feeCoin, Name: name, Input: input, Data: data, } - tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainID))} + tx.Input.Signature = crypto.SignatureS{privKey.Sign(tx.SignBytes(chainIDFlag))} fmt.Println("Signed AppTx:") fmt.Println(string(wire.JSONBytes(tx))) - data, log, err := broadcastTx(c, tx) + data, log, err := broadcastTx(tx) if err != nil { - return err + cmn.Exit(fmt.Sprintf("%+v\n", err)) } fmt.Printf("Response: %X ; %s\n", data, log) - - return nil } // broadcast the transaction to tendermint -func broadcastTx(c *cli.Context, tx types.Tx) ([]byte, string, error) { +func broadcastTx(tx types.Tx) ([]byte, string, error) { + tmResult := new(ctypes.TMResult) - tmAddr := c.String("node") - uriClient := client.NewURIClient(tmAddr) + uriClient := client.NewURIClient(txNodeFlag) // Don't you hate having to do this? // How many times have I lost an hour over this trick?! txBytes := []byte(wire.BinaryBytes(struct { types.Tx `json:"unwrap"` }{tx})) + _, err := uriClient.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult) if err != nil { return nil, "", errors.New(cmn.Fmt("Error on broadcast tx: %v", err)) } + res := (*tmResult).(*ctypes.ResultBroadcastTxCommit) + // if it fails check, we don't even get a delivertx back! if !res.CheckTx.Code.IsOK() { r := res.CheckTx return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log)) } + if !res.DeliverTx.Code.IsOK() { r := res.DeliverTx return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log)) } + return res.DeliverTx.Data, res.DeliverTx.Log, nil } // if the sequence flag is set, return it; // else, fetch the account by querying the app and return the sequence number -func getSeq(c *cli.Context, address []byte) (int, error) { - if c.IsSet("sequence") { - return c.Int("sequence"), nil +func getSeq(address []byte) (int, error) { + + if seqFlag >= 0 { + return seqFlag, nil } - tmAddr := c.String("node") - acc, err := getAcc(tmAddr, address) + + acc, err := getAcc(txNodeFlag, address) if err != nil { return 0, err } @@ -232,5 +236,4 @@ func newOutput(to []byte, amount types.Coins) types.TxOutput { Address: to, Coins: amount, } - } diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index efff67e0bf..f49bfe162d 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -2,16 +2,17 @@ package commands import ( "encoding/hex" - "errors" + "fmt" "os" - "github.com/urfave/cli" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/tendermint/basecoin/state" "github.com/tendermint/basecoin/types" abci "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -28,6 +29,60 @@ func BasecoinRoot(rootDir string) string { return rootDir } +type Flag2Register struct { + Pointer interface{} + Use string + Value interface{} + Desc string +} + +//register flag utils +func RegisterFlags(c *cobra.Command, flags []Flag2Register) { + registerFlags(c, flags, false) +} + +func RegisterPersistentFlags(c *cobra.Command, flags []Flag2Register) { + registerFlags(c, flags, true) +} + +func registerFlags(c *cobra.Command, flags []Flag2Register, persistent bool) { + + var flagset *pflag.FlagSet + if persistent { + flagset = c.PersistentFlags() + } else { + flagset = c.Flags() + } + + for _, f := range flags { + + ok := false + + switch f.Value.(type) { + case string: + if _, ok = f.Pointer.(*string); ok { + flagset.StringVar(f.Pointer.(*string), f.Use, f.Value.(string), f.Desc) + } + case int: + if _, ok = f.Pointer.(*int); ok { + flagset.IntVar(f.Pointer.(*int), f.Use, f.Value.(int), f.Desc) + } + case uint64: + if _, ok = f.Pointer.(*uint64); ok { + flagset.Uint64Var(f.Pointer.(*uint64), f.Use, f.Value.(uint64), f.Desc) + } + case bool: + if _, ok = f.Pointer.(*bool); ok { + flagset.BoolVar(f.Pointer.(*bool), f.Use, f.Value.(bool), f.Desc) + } + } + + if !ok { + panic("improper use of RegisterFlags") + } + } +} + // Returns true for non-empty hex-string prefixed with "0x" func isHex(s string) bool { if len(s) > 2 && s[:2] == "0x" { @@ -58,11 +113,11 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { } _, err := uriClient.Call("abci_query", params, tmResult) if err != nil { - return nil, errors.New(cmn.Fmt("Error calling /abci_query: %v", err)) + return nil, errors.New(fmt.Sprintf("Error calling /abci_query: %v", err)) } res := (*tmResult).(*ctypes.ResultABCIQuery) if !res.Response.Code.IsOK() { - return nil, errors.New(cmn.Fmt("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)) + return nil, errors.New(fmt.Sprintf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)) } return &res.Response, nil } @@ -79,28 +134,27 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) { accountBytes := response.Value if len(accountBytes) == 0 { - return nil, errors.New(cmn.Fmt("Account bytes are empty for address: %X ", address)) + return nil, errors.New(fmt.Sprintf("Account bytes are empty for address: %X ", address)) } var acc *types.Account err = wire.ReadBinaryBytes(accountBytes, &acc) if err != nil { - return nil, errors.New(cmn.Fmt("Error reading account %X error: %v", + return nil, errors.New(fmt.Sprintf("Error reading account %X error: %v", accountBytes, err.Error())) } return acc, nil } -func getHeaderAndCommit(c *cli.Context, height int) (*tmtypes.Header, *tmtypes.Commit, error) { +func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Commit, error) { tmResult := new(ctypes.TMResult) - tmAddr := c.String("node") uriClient := client.NewURIClient(tmAddr) method := "commit" _, err := uriClient.Call(method, map[string]interface{}{"height": height}, tmResult) if err != nil { - return nil, nil, errors.New(cmn.Fmt("Error on %s: %v", method, err)) + return nil, nil, errors.New(fmt.Sprintf("Error on %s: %v", method, err)) } resCommit := (*tmResult).(*ctypes.ResultCommit) header := resCommit.Header diff --git a/cmd/commands/version.go b/cmd/commands/version.go new file mode 100644 index 0000000000..1cbf891e43 --- /dev/null +++ b/cmd/commands/version.go @@ -0,0 +1,17 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/tendermint/basecoin/version" +) + +var VersionCmd = &cobra.Command{ + Use: "version", + Short: "Show version info", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version.Version) + }, +} diff --git a/cmd/counter/cmd.go b/cmd/counter/cmd.go index c125feb4f6..6b31e3fc61 100644 --- a/cmd/counter/cmd.go +++ b/cmd/counter/cmd.go @@ -3,46 +3,47 @@ package main import ( "fmt" + "github.com/spf13/cobra" wire "github.com/tendermint/go-wire" - "github.com/urfave/cli" "github.com/tendermint/basecoin/cmd/commands" "github.com/tendermint/basecoin/plugins/counter" "github.com/tendermint/basecoin/types" + cmn "github.com/tendermint/go-common" +) + +//commands +var CounterTxCmd = &cobra.Command{ + Use: "counter", + Short: "Create, sign, and broadcast a transaction to the counter plugin", + Run: counterTxCmd, +} + +//flags +var ( + validFlag bool + countFeeFlag string ) func init() { + + CounterTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set valid field in CounterTx") + CounterTxCmd.Flags().StringVar(&countFeeFlag, "countfee", "", "Coins for the counter fee of the format ") + commands.RegisterTxSubcommand(CounterTxCmd) commands.RegisterStartPlugin("counter", func() types.Plugin { return counter.New() }) } -var ( - ValidFlag = cli.BoolFlag{ - Name: "valid", - Usage: "Set valid field in CounterTx", - } +func counterTxCmd(cmd *cobra.Command, args []string) { - CounterTxCmd = cli.Command{ - Name: "counter", - Usage: "Create, sign, and broadcast a transaction to the counter plugin", - Action: func(c *cli.Context) error { - return cmdCounterTx(c) - }, - Flags: append(commands.TxFlags, ValidFlag), + countFee, err := commands.ParseCoins(countFeeFlag) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) } -) - -func cmdCounterTx(c *cli.Context) error { - valid := c.Bool("valid") counterTx := counter.CounterTx{ - Valid: valid, - Fee: types.Coins{ - { - Denom: c.String("coin"), - Amount: int64(c.Int("fee")), - }, - }, + Valid: validFlag, + Fee: countFee, } fmt.Println("CounterTx:", string(wire.JSONBytes(counterTx))) @@ -50,5 +51,5 @@ func cmdCounterTx(c *cli.Context) error { data := wire.BinaryBytes(counterTx) name := "counter" - return commands.AppTx(c, name, data) + commands.AppTx(name, data) } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 72395a9b07..fc5ad6b02a 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -1,23 +1,34 @@ package main import ( + "fmt" "os" + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/cmd/commands" - "github.com/urfave/cli" ) func main() { - app := cli.NewApp() - app.Name = "counter" - app.Usage = "counter [command] [args...]" - app.Version = "0.1.0" - app.Commands = []cli.Command{ + + var RootCmd = &cobra.Command{ + Use: "counter", + Short: "demo plugin for basecoin", + } + + RootCmd.AddCommand( commands.StartCmd, commands.TxCmd, - commands.KeyCmd, commands.QueryCmd, + commands.KeyCmd, + commands.VerifyCmd, + commands.BlockCmd, commands.AccountCmd, + commands.QuickVersionCmd("0.1.0"), + ) + + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - app.Run(os.Args) } diff --git a/demo/start.sh b/demo/start.sh index af91db2a07..d7d9659dc4 100644 --- a/demo/start.sh +++ b/demo/start.sh @@ -103,14 +103,14 @@ sleep 3 echo "... registering chain1 on chain2" echo "" # register chain1 on chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json +basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --ibc_chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json echo "" echo "... creating egress packet on chain1" echo "" # create a packet on chain1 destined for chain2 PAYLOAD="DEADBEEF" #TODO -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --sequence 1 +basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --ibc_from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --ibc_sequence 1 echo "" echo "... querying for packet data" @@ -162,7 +162,7 @@ echo "" echo "... posting packet from chain1 on chain2" echo "" # post the packet from chain1 to chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF +basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --ibc_from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF echo "" echo "... checking if the packet is present on chain2" diff --git a/docs/guide/example-plugin.md b/docs/guide/example-plugin.md index 31aa3479c2..312f3ac23d 100644 --- a/docs/guide/example-plugin.md +++ b/docs/guide/example-plugin.md @@ -25,18 +25,30 @@ The `main.go` is very simple and does not need to be changed: ```golang func main() { - app := cli.NewApp() - app.Name = "example-plugin" - app.Usage = "example-plugin [command] [args...]" - app.Version = "0.1.0" - app.Commands = []cli.Command{ + //Initialize example-plugin root command + var RootCmd = &cobra.Command{ + Use: "example-plugin", + Short: "example-plugin usage description", + } + + //Add the default basecoin commands to the root command + RootCmd.AddCommand( + commands.InitCmd, commands.StartCmd, commands.TxCmd, - commands.KeyCmd, commands.QueryCmd, + commands.KeyCmd, + commands.VerifyCmd, + commands.BlockCmd, commands.AccountCmd, + commands.UnsafeResetAllCmd, + ) + + //Run the root command + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - app.Run(os.Args) } ``` @@ -49,19 +61,40 @@ This is where the `cmd.go` comes in. ### cmd.go -First, we register the plugin: +First we define the new command and associated flag variables +```golang +var ( + //CLI Flags + validFlag bool + + //CLI Plugin Commands + ExamplePluginTxCmd = &cobra.Command{ + Use: "example", + Short: "Create, sign, and broadcast a transaction to the example plugin", + Run: examplePluginTxCmd, + } +) +``` + +Next we register the plugin: ```golang func init() { + + //Set the Plugin Flags + ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid") + + //Register a plugin specific CLI command as a subcommand of the tx command commands.RegisterTxSubcommand(ExamplePluginTxCmd) + + //Register the example with basecoin at start commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() }) } ``` This creates a new subcommand under `tx` (defined below), and ensures the plugin is activated when we start the app. -Now we actually define the new command: ```golang var ( diff --git a/docs/guide/src/example-plugin/cmd.go b/docs/guide/src/example-plugin/cmd.go index 6d7c29a799..51077d06f5 100644 --- a/docs/guide/src/example-plugin/cmd.go +++ b/docs/guide/src/example-plugin/cmd.go @@ -1,16 +1,32 @@ package main import ( + "github.com/spf13/cobra" + wire "github.com/tendermint/go-wire" - "github.com/urfave/cli" "github.com/tendermint/basecoin/cmd/commands" "github.com/tendermint/basecoin/types" ) +var ( + //CLI Flags + validFlag bool + + //CLI Plugin Commands + ExamplePluginTxCmd = &cobra.Command{ + Use: "example", + Short: "Create, sign, and broadcast a transaction to the example plugin", + Run: examplePluginTxCmd, + } +) + //Called during CLI initialization func init() { + //Set the Plugin Flags + ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid") + //Register a plugin specific CLI command as a subcommand of the tx command commands.RegisterTxSubcommand(ExamplePluginTxCmd) @@ -18,32 +34,12 @@ func init() { commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() }) } -var ( - //CLI Flags - ExampleFlag = cli.BoolFlag{ - Name: "valid", - Usage: "Set this to make the transaction valid", - } - - //CLI Plugin Commands - ExamplePluginTxCmd = cli.Command{ - Name: "example", - Usage: "Create, sign, and broadcast a transaction to the example plugin", - Action: func(c *cli.Context) error { - return cmdExamplePluginTx(c) - }, - Flags: append(commands.TxFlags, ExampleFlag), - } -) - //Send a transaction -func cmdExamplePluginTx(c *cli.Context) error { - //Retrieve any flag results - exampleFlag := c.Bool("valid") +func examplePluginTxCmd(cmd *cobra.Command, args []string) { // Create a transaction using the flag. // The tx passes on custom information to the plugin - exampleTx := ExamplePluginTx{exampleFlag} + exampleTx := ExamplePluginTx{validFlag} // The tx is passed to the plugin in the form of // a byte array. This is achieved by serializing the object using go-wire. @@ -62,5 +58,5 @@ func cmdExamplePluginTx(c *cli.Context) error { // - Once deserialized, the tx is passed to `state.ExecTx` (state/execution.go) // - If the tx passes various checks, the `tx.Data` is forwarded as `txBytes` to `plugin.RunTx` (docs/guide/src/example-plugin/plugin.go) // - Finally, it deserialized back to the ExamplePluginTx - return commands.AppTx(c, "example-plugin", exampleTxBytes) + commands.AppTx("example-plugin", exampleTxBytes) } diff --git a/docs/guide/src/example-plugin/main.go b/docs/guide/src/example-plugin/main.go index d8cc38a958..3a2984b60d 100644 --- a/docs/guide/src/example-plugin/main.go +++ b/docs/guide/src/example-plugin/main.go @@ -1,24 +1,38 @@ package main import ( + "fmt" "os" + "github.com/spf13/cobra" + "github.com/tendermint/basecoin/cmd/commands" - "github.com/urfave/cli" ) func main() { - //Initialize an instance of basecoin with default basecoin commands - app := cli.NewApp() - app.Name = "example-plugin" - app.Usage = "example-plugin [command] [args...]" - app.Version = "0.1.0" - app.Commands = []cli.Command{ + + //Initialize example-plugin root command + var RootCmd = &cobra.Command{ + Use: "example-plugin", + Short: "example-plugin usage description", + } + + //Add the default basecoin commands to the root command + RootCmd.AddCommand( + commands.InitCmd, commands.StartCmd, commands.TxCmd, - commands.KeyCmd, commands.QueryCmd, + commands.KeyCmd, + commands.VerifyCmd, + commands.BlockCmd, commands.AccountCmd, + commands.UnsafeResetAllCmd, + ) + + //Run the root command + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) } - app.Run(os.Args) } diff --git a/glide.lock b/glide.lock index 38755f1a6a..eedcffdccc 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c023dbd97e1ea0a525e33738f03afd6be61f997f1c2592a5d9928fdcecc71361 -updated: 2017-04-21T17:38:13.194966906+02:00 +hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600 +updated: 2017-04-13T18:07:44.07521907-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -19,6 +19,8 @@ imports: version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 +- name: github.com/inconshreveable/mousetrap + version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable @@ -26,7 +28,11 @@ imports: - name: github.com/mattn/go-isatty version: 57fdcb988a5c543893cc61bce354a6e24ab70022 - name: github.com/pkg/errors - version: bfd5150e4e41705ded2129ec33379de1cb90b513 + version: 645ef00459ed84a119197bfb8d8205042c6df63d +- name: github.com/spf13/cobra + version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c +- name: github.com/spf13/pflag + version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 - name: github.com/syndtr/goleveldb version: 3c5717caf1475fd25964109a0fc640bd150fce43 subpackages: @@ -43,7 +49,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998 + version: af792eac777de757cd496349a5f6b5313738fcbc subpackages: - client - example/dummy @@ -59,11 +65,11 @@ imports: - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: f9e3db037330c8a8d61d3966de8473eaf01154fa + version: dcb015dff6c7af21e65c8e2f3b450df19d38c777 - name: github.com/tendermint/go-config version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da + version: 3f47cfac5fcd9e0f1727c7db980b3559913b3e3a - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db @@ -83,13 +89,13 @@ imports: subpackages: - upnp - name: github.com/tendermint/go-rpc - version: 9d18cbe74e66f875afa36d2fa3be280e4a2dc9e6 + version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: c1c9a57ab8038448ddea1714c0698f8051e5748c + version: f530b7af7a8b06e612c2063bff6ace49060a085e - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -100,9 +106,10 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: 7cf773e2d37b2b5a08bc94fb125cfd346b834824 + version: 022a5509181a19f78995a3dd9bba470333fe2d63 subpackages: - blockchain + - cmd/tendermint/commands - config/tendermint - consensus - mempool @@ -117,8 +124,6 @@ imports: - state/txindex/null - types - version -- name: github.com/urfave/cli - version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/crypto version: 728b753d0135da6801d45a38e6f43ff55779c5c2 subpackages: diff --git a/glide.yaml b/glide.yaml index ecf4f151b4..420cc1ceba 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,22 +1,24 @@ package: github.com/tendermint/basecoin import: - package: github.com/tendermint/go-common - version: develop + version: master - package: github.com/tendermint/go-crypto - version: develop + version: master - package: github.com/tendermint/go-events - version: develop + version: master - package: github.com/tendermint/go-logger - version: develop + version: master +- package: github.com/tendermint/go-data + version: master - package: github.com/tendermint/go-rpc - version: develop + version: master - package: github.com/tendermint/go-wire - version: develop + version: master - package: github.com/tendermint/merkleeyes - version: develop + version: master - package: github.com/tendermint/tendermint - version: develop + version: cli_change - package: github.com/tendermint/abci - version: develop + version: master - package: github.com/gorilla/websocket version: v1.1.0 From 6eb511670f7251c201357fc6e68b0c3b60f74274 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 30 Mar 2017 01:30:55 -0400 Subject: [PATCH 21/33] cmd init cleanup --- cmd/commands/init.go | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 99bff657c8..7b89b6b798 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -3,6 +3,7 @@ package commands import ( "fmt" "io/ioutil" + "os" "path" "github.com/spf13/cobra" @@ -43,27 +44,31 @@ func initCmd(cmd *cobra.Command, args []string) { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + if _, err := os.Stat(privValFile); os.IsNotExist(err) { + err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } - log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) + log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) + } else { + log.Notice("Already initialized", "priv_validator", privValFile) + } } const privValJSON = `{ From 18f1142d4ca7b077c07ae83864f539a4a79debac Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 30 Mar 2017 01:59:46 -0400 Subject: [PATCH 22/33] v0.4.0 int --- CHANGELOG.md | 10 ++++++++++ cmd/commands/init.go | 13 ------------- version/version.go | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 927c2f688f..1d01ce65e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.4.0 (March 30, 2017) + +BREAKING CHANGES: + +- CLI now uses Cobra + +IMPROVEMENTS: + +- `basecoin init` doesn't generate error if already initialized + ## 0.3.1 (March 23, 2017) IMPROVEMENTS: diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 7b89b6b798..e938ccb2c5 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -20,19 +20,6 @@ var ( } ) -//flags -//var chainIDFlag string - -//func init() { -// -// //register flags -// flags := []Flag2Register{ -// {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, -// } -// RegisterFlags(InitCmd, flags) -// -//} - func initCmd(cmd *cobra.Command, args []string) { rootDir := BasecoinRoot("") diff --git a/version/version.go b/version/version.go index 7708867588..ae549d0832 100644 --- a/version/version.go +++ b/version/version.go @@ -1,7 +1,7 @@ package version const Maj = "0" -const Min = "3" -const Fix = "1" +const Min = "4" +const Fix = "0" const Version = Maj + "." + Min + "." + Fix From 02b4fd5f1768cce1c4d527a9a1ee2373576c1f71 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 1 Apr 2017 15:49:56 -0400 Subject: [PATCH 23/33] doc update --- cmd/commands/key.go | 1 + cmd/commands/tx.go | 10 +- docs/guide/example-plugin.md | 194 ++++++++++++++++------------------- docs/guide/plugin-design.md | 4 +- 4 files changed, 99 insertions(+), 110 deletions(-) diff --git a/cmd/commands/key.go b/cmd/commands/key.go index a79ca92f16..a1cec50d1b 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -31,6 +31,7 @@ var ( func newKeyCmd(cmd *cobra.Command, args []string) { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") + fmt.Println(&key) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 95358221f4..e7381b0874 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -36,18 +36,20 @@ var ( } ) -//flags var ( + //persistent flags txNodeFlag string - toFlag string amountFlag string fromFlag string seqFlag int gasFlag int feeFlag string - dataFlag string - nameFlag string chainIDFlag string + + //non-persistent flags + toFlag string + dataFlag string + nameFlag string ) func init() { diff --git a/docs/guide/example-plugin.md b/docs/guide/example-plugin.md index 312f3ac23d..d9e3a3255b 100644 --- a/docs/guide/example-plugin.md +++ b/docs/guide/example-plugin.md @@ -6,10 +6,11 @@ Here, we will demonstrate how to extend the blockchain and CLI to support a simp ## Overview -Creating a new plugin and CLI to support it requires a little bit of boilerplate, but not much. -For convenience, we've implemented an extremely simple example plugin that can be easily modified. -The example is under `docs/guide/src/example-plugin`. -To build your own plugin, copy this folder to a new location and start modifying it there. +Creating a new plugin and CLI to support it requires a little bit of +boilerplate, but not much. For convenience, we've implemented an extremely +simple example plugin that can be easily modified. The example is under +`docs/guide/src/example-plugin`. To build your own plugin, copy this folder to +a new location and start modifying it there. Let's take a look at the files in `docs/guide/src/example-plugin`: @@ -52,16 +53,14 @@ func main() { } ``` -It creates the CLI, exactly like the `basecoin` one. -However, if we want our plugin to be active, -we need to make sure it is registered with the application. -In addition, if we want to send transactions to our plugin, -we need to add a new command to the CLI. -This is where the `cmd.go` comes in. +It creates the CLI, exactly like the `basecoin` one. However, if we want our +plugin to be active, we need to make sure it is registered with the +application. In addition, if we want to send transactions to our plugin, we +need to add a new command to the CLI. This is where the `cmd.go` comes in. ### cmd.go -First we define the new command and associated flag variables +First we define the new CLI command and associated flag variables. ```golang var ( @@ -77,7 +76,10 @@ var ( ) ``` -Next we register the plugin: +Next within the `init` function we register our plugin's flags and register our +custom plugin command with the root command. This creates a new subcommand +under `tx` (defined below), and ensures the plugin is activated when we start +the app. ```golang func init() { @@ -93,59 +95,38 @@ func init() { } ``` -This creates a new subcommand under `tx` (defined below), -and ensures the plugin is activated when we start the app. +We now define the actual function which is called by our CLI command. + +```golang +func examplePluginTxCmd(cmd *cobra.Command, args []string) { + exampleTx := ExamplePluginTx{validFlag} + exampleTxBytes := wire.BinaryBytes(exampleTx) + commands.AppTx("example-plugin", exampleTxBytes) +} +``` + +Our function is a simple command with one boolean flag. However, it actually +inherits the persistent flags from the Basecoin framework. These persistent +flags use pointers to these variables stored in `cmd/commands/tx.go`: ```golang var ( - ExampleFlag = cli.BoolFlag{ - Name: "valid", - Usage: "Set this to make the transaction valid", - } - - ExamplePluginTxCmd = cli.Command{ - Name: "example", - Usage: "Create, sign, and broadcast a transaction to the example plugin", - Action: func(c *cli.Context) error { - return cmdExamplePluginTx(c) - }, - Flags: append(commands.TxFlags, ExampleFlag), - } + //persistent flags + txNodeFlag string + amountFlag string + fromFlag string + seqFlag int + gasFlag int + feeFlag string + chainIDFlag string + + //non-persistent flags + toFlag string + dataFlag string + nameFlag string ) - -func cmdExamplePluginTx(c *cli.Context) error { - exampleFlag := c.Bool("valid") - exampleTx := ExamplePluginTx{exampleFlag} - return commands.AppTx(c, "example-plugin", wire.BinaryBytes(exampleTx)) -} ``` -It's a simple command with one flag, which is just a boolean. -However, it actually inherits more flags from the Basecoin framework: - -```golang -Flags: append(commands.TxFlags, ExampleFlag), -``` - -The `commands.TxFlags` is defined in `cmd/commands/tx.go`: - -```golang -var TxFlags = []cli.Flag{ - NodeFlag, - ChainIDFlag, - - FromFlag, - - AmountFlag, - CoinFlag, - GasFlag, - FeeFlag, - SeqFlag, -} -``` - -It adds all the default flags for a Basecoin transaction. - If we now compile and run our program, we can see all the options: ``` @@ -157,48 +138,51 @@ example-plugin tx example --help The output: ``` -NAME: - example-plugin tx example - Create, sign, and broadcast a transaction to the example plugin +Create, sign, and broadcast a transaction to the example plugin -USAGE: - example-plugin tx example [command options] [arguments...] +Usage: + example-plugin tx example [flags] -OPTIONS: - --node value Tendermint RPC address (default: "tcp://localhost:46657") - --chain_id value ID of the chain for replay protection (default: "test_chain_id") - --from value Path to a private key to sign the transaction (default: "key.json") - --amount value Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver) - --gas value The amount of gas for the transaction (default: 0) - --fee value Coins for the transaction fee of the format - --sequence value Sequence number for the account (default: 0) - --valid Set this to make the transaction valid +Flags: + --valid Set this to make transaction valid + +Global Flags: + --amount string Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver}, + --chain_id string ID of the chain for replay protection (default "test_chain_id") + --fee string Coins for the transaction fee of the format + --from string Path to a private key to sign the transaction (default "key.json") + --gas int The amount of gas for the transaction + --node string Tendermint RPC address (default "tcp://localhost:46657") + --sequence int Sequence number for the account (-1 to autocalculate}, (default -1) ``` Cool, eh? -Before we move on to `plugin.go`, let's look at the `cmdExamplePluginTx` function in `cmd.go`: +Before we move on to `plugin.go`, let's look at the `examplePluginTxCmd` +function in `cmd.go`: ```golang -func cmdExamplePluginTx(c *cli.Context) error { - exampleFlag := c.Bool("valid") - exampleTx := ExamplePluginTx{exampleFlag} - return commands.AppTx(c, "example-plugin", wire.BinaryBytes(exampleTx)) +func examplePluginTxCmd(cmd *cobra.Command, args []string) { + exampleTx := ExamplePluginTx{validFlag} + exampleTxBytes := wire.BinaryBytes(exampleTx) + commands.AppTx("example-plugin", exampleTxBytes) } ``` We read the flag from the CLI library, and then create the example transaction. -Remember that Basecoin itself only knows about two transaction types, `SendTx` and `AppTx`. -All plugin data must be serialized (ie. encoded as a byte-array) -and sent as data in an `AppTx`. The `commands.AppTx` function does this for us - -it creates an `AppTx` with the corresponding data, signs it, and sends it on to the blockchain. +Remember that Basecoin itself only knows about two transaction types, `SendTx` +and `AppTx`. All plugin data must be serialized (ie. encoded as a byte-array) +and sent as data in an `AppTx`. The `commands.AppTx` function does this for us +- it creates an `AppTx` with the corresponding data, signs it, and sends it on +to the blockchain. ### plugin.go -Ok, now we're ready to actually look at the implementation of the plugin in `plugin.go`. -Note I'll leave out some of the methods as they don't serve any purpose for this example, -but are necessary boilerplate. -Your plugin may have additional requirements that utilize these other methods. -Here's what's relevant for us: +Ok, now we're ready to actually look at the implementation of the plugin in +`plugin.go`. Note I'll leave out some of the methods as they don't serve any +purpose for this example, but are necessary boilerplate. Your plugin may have +additional requirements that utilize these other methods. Here's what's +relevant for us: ```golang type ExamplePluginState struct { @@ -232,15 +216,17 @@ func (ep *ExamplePlugin) SetOption(store types.KVStore, key string, value string } func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txBytes []byte) (res abci.Result) { - - // Decode tx + + // Decode txBytes using go-wire. Attempt to write the txBytes to the variable + // tx, if the txBytes have not been properly encoded from a ExamplePluginTx + // struct wire will produce an error. var tx ExamplePluginTx err := wire.ReadBinaryBytes(txBytes, &tx) if err != nil { return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error()) } - // Validate tx + // Perform Transaction Validation if !tx.Valid { return abci.ErrInternalError.AppendLog("Valid must be true") } @@ -248,8 +234,10 @@ func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txByt // Load PluginState var pluginState ExamplePluginState stateBytes := store.Get(ep.StateKey()) + // If the state does not exist, stateBytes will be initialized + // as an empty byte array with length of zero if len(stateBytes) > 0 { - err = wire.ReadBinaryBytes(stateBytes, &pluginState) + err = wire.ReadBinaryBytes(stateBytes, &pluginState) //decode using go-wire if err != nil { return abci.ErrInternalError.AppendLog("Error decoding state: " + err.Error()) } @@ -266,12 +254,11 @@ func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txByt ``` All we're doing here is defining a state and transaction type for our plugin, -and then using the `RunTx` method to define how the transaction updates the state. -Let's break down `RunTx` in parts. First, we deserialize the transaction: - +and then using the `RunTx` method to define how the transaction updates the +state. Let's break down `RunTx` in parts. First, we deserialize the +transaction: ```golang -// Decode tx var tx ExamplePluginTx err := wire.ReadBinaryBytes(txBytes, &tx) if err != nil { @@ -279,27 +266,26 @@ if err != nil { } ``` -The transaction is expected to be serialized according to Tendermint's "wire" format, -as defined in the `github.com/tendermint/go-wire` package. -If it's not encoded properly, we return an error. +The transaction is expected to be serialized according to Tendermint's "wire" +format, as defined in the `github.com/tendermint/go-wire` package. If it's not +encoded properly, we return an error. If the transaction deserializes correctly, we can now check if it's valid: ```golang -// Validate tx if !tx.Valid { return abci.ErrInternalError.AppendLog("Valid must be true") } ``` -The transaction is valid if the `Valid` field is set, otherwise it's not - simple as that. -Finally, we can update the state. In this example, the state simply counts how many valid transactions -we've processed. But the state itself is serialized and kept in some `store`, which is typically a Merkle tree. -So first we have to load the state from the store and deserialize it: +The transaction is valid if the `Valid` field is set, otherwise it's not - +simple as that. Finally, we can update the state. In this example, the state +simply counts how many valid transactions we've processed. But the state itself +is serialized and kept in some `store`, which is typically a Merkle tree. So +first we have to load the state from the store and deserialize it: ```golang -// Load PluginState var pluginState ExamplePluginState stateBytes := store.Get(ep.StateKey()) if len(stateBytes) > 0 { @@ -402,5 +388,5 @@ basecoin CLI to activate the plugin on the blockchain and to send transactions t Hopefully by now you have some ideas for your own plugin, and feel comfortable implementing them. In the [next tutorial](more-examples.md), we tour through some other plugin examples, -adding features for minting new coins, voting, and changing the Tendermint validator set. +addin mple-plugin query ExamplePlugin.Statefeatures for minting new coins, voting, and changing the Tendermint validator set. But first, you may want to learn a bit more about [the design of the plugin system](plugin-design.md) diff --git a/docs/guide/plugin-design.md b/docs/guide/plugin-design.md index f59ce736c6..e8e7dc92f5 100644 --- a/docs/guide/plugin-design.md +++ b/docs/guide/plugin-design.md @@ -43,8 +43,8 @@ type Plugin interface { // Other ABCI message handlers SetOption(store KVStore, key string, value string) (log string) InitChain(store KVStore, vals []*abci.Validator) - BeginBlock(store KVStore, height uint64) - EndBlock(store KVStore, height uint64) []*abci.Validator + BeginBlock(store KVStore, hash []byte, header *abci.Header) + EndBlock(store KVStore, height uint64) (res abci.ResponseEndBlock) } type CallContext struct { From b60845c81812be8307960eb994f7128012db7a86 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 1 Apr 2017 17:31:44 -0400 Subject: [PATCH 24/33] BCHOME default dir change int int int int --- app/app.go | 12 ++++++------ app/genesis_test.go | 27 ++++++++++++++++++++++++++- cmd/commands/init.go | 16 ++++++++-------- cmd/commands/utils.go | 6 +++++- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/app/app.go b/app/app.go index f8cc5b739e..fe17736697 100644 --- a/app/app.go +++ b/app/app.go @@ -5,17 +5,17 @@ import ( "strings" abci "github.com/tendermint/abci/types" - sm "github.com/tendermint/basecoin/state" - "github.com/tendermint/basecoin/types" . "github.com/tendermint/go-common" "github.com/tendermint/go-wire" eyes "github.com/tendermint/merkleeyes/client" + + sm "github.com/tendermint/basecoin/state" + "github.com/tendermint/basecoin/types" + "github.com/tendermint/basecoin/version" ) const ( - version = "0.1" - maxTxSize = 10240 - + maxTxSize = 10240 PluginNameBase = "base" ) @@ -44,7 +44,7 @@ func (app *Basecoin) GetState() *sm.State { // ABCI::Info func (app *Basecoin) Info() abci.ResponseInfo { - return abci.ResponseInfo{Data: Fmt("Basecoin v%v", version)} + return abci.ResponseInfo{Data: Fmt("Basecoin v%v", version.Version)} } func (app *Basecoin) RegisterPlugin(plugin types.Plugin) { diff --git a/app/genesis_test.go b/app/genesis_test.go index 90f61e152c..74ca22e61b 100644 --- a/app/genesis_test.go +++ b/app/genesis_test.go @@ -2,20 +2,24 @@ package app import ( "encoding/hex" + "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" eyescli "github.com/tendermint/merkleeyes/client" ) +const genesisFilepath = "./testdata/genesis.json" + func TestLoadGenesis(t *testing.T) { assert, require := assert.New(t), require.New(t) eyesCli := eyescli.NewLocalClient("", 0) app := NewBasecoin(eyesCli) - err := app.LoadGenesis("./testdata/genesis.json") + err := app.LoadGenesis(genesisFilepath) require.Nil(err, "%+v", err) // check the chain id @@ -41,3 +45,24 @@ func TestLoadGenesis(t *testing.T) { assert.EqualValues(pkbyte, epk[:]) } } + +func TestParseGenesisList(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + bytes, err := cmn.ReadFile(genesisFilepath) + require.Nil(err, "loading genesis file %+v", err) + + // the basecoin genesis go-data :) + genDoc := new(FullGenesisDoc) + err = json.Unmarshal(bytes, genDoc) + require.Nil(err, "unmarshaling genesis file %+v", err) + + pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions) + require.Nil(err, "%+v", err) + genDoc.AppOptions.pluginOptions = pluginOpts + + assert.Equal(genDoc.AppOptions.pluginOptions[0].Key, "plugin1/key1") + assert.Equal(genDoc.AppOptions.pluginOptions[1].Key, "plugin1/key2") + assert.Equal(genDoc.AppOptions.pluginOptions[0].Value, "value1") + assert.Equal(genDoc.AppOptions.pluginOptions[1].Value, "value2") +} diff --git a/cmd/commands/init.go b/cmd/commands/init.go index e938ccb2c5..05a76ef8a1 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -32,22 +32,22 @@ func initCmd(cmd *cobra.Command, args []string) { key2File := path.Join(rootDir, "key2.json") if _, err := os.Stat(privValFile); os.IsNotExist(err) { - err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644) + err := ioutil.WriteFile(genesisFile, []byte(GenesisJSON), 0644) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } - err = ioutil.WriteFile(privValFile, []byte(privValJSON), 0400) + err = ioutil.WriteFile(privValFile, []byte(PrivValJSON), 0400) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } - err = ioutil.WriteFile(key1File, []byte(key1JSON), 0400) + err = ioutil.WriteFile(key1File, []byte(Key1JSON), 0400) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } - err = ioutil.WriteFile(key2File, []byte(key2JSON), 0400) + err = ioutil.WriteFile(key2File, []byte(Key2JSON), 0400) if err != nil { cmn.Exit(fmt.Sprintf("%+v\n", err)) } @@ -58,7 +58,7 @@ func initCmd(cmd *cobra.Command, args []string) { } } -const privValJSON = `{ +var PrivValJSON = `{ "address": "7A956FADD20D3A5B2375042B2959F8AB172A058F", "last_height": 0, "last_round": 0, @@ -75,7 +75,7 @@ const privValJSON = `{ ] }` -const genesisJSON = `{ +var GenesisJSON = `{ "app_hash": "", "chain_id": "test_chain_id", "genesis_time": "0001-01-01T00:00:00.000Z", @@ -105,7 +105,7 @@ const genesisJSON = `{ } }` -const key1JSON = `{ +var Key1JSON = `{ "address": "1B1BE55F969F54064628A63B9559E7C21C925165", "priv_key": { "type": "ed25519", @@ -117,7 +117,7 @@ const key1JSON = `{ } }` -const key2JSON = `{ +var Key2JSON = `{ "address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090", "priv_key": { "type": "ed25519", diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index f49bfe162d..7f21be9515 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -19,12 +19,16 @@ import ( tmtypes "github.com/tendermint/tendermint/types" ) +//This variable can be overwritten by plugin applications +// if they require a different working directory +var DefaultHome = "basecoin" + func BasecoinRoot(rootDir string) string { if rootDir == "" { rootDir = os.Getenv("BCHOME") } if rootDir == "" { - rootDir = os.Getenv("HOME") + "/.basecoin" + rootDir = os.Getenv("HOME") + "/." + DefaultHome } return rootDir } From 587461afa4a9d7d097b8421bea1deff77600eef5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 3 Apr 2017 10:44:30 +0200 Subject: [PATCH 25/33] Make initializing files more robust to some files existing --- cmd/commands/init.go | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 05a76ef8a1..233a39087d 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -20,6 +20,20 @@ var ( } ) +// setupFile aborts on error... or should we return it?? +// returns 1 iff it set a file, otherwise 0 (so we can add them) +func setupFile(path, data string, perm os.FileMode) int { + _, err := os.Stat(path) + if !os.IsNotExist(err) { + return 0 + } + err = ioutil.WriteFile(path, []byte(data), perm) + if err != nil { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } + return 1 +} + func initCmd(cmd *cobra.Command, args []string) { rootDir := BasecoinRoot("") @@ -31,27 +45,12 @@ func initCmd(cmd *cobra.Command, args []string) { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - if _, err := os.Stat(privValFile); os.IsNotExist(err) { - err := ioutil.WriteFile(genesisFile, []byte(GenesisJSON), 0644) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } - - err = ioutil.WriteFile(privValFile, []byte(PrivValJSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } - - err = ioutil.WriteFile(key1File, []byte(Key1JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } - - err = ioutil.WriteFile(key2File, []byte(Key2JSON), 0400) - if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) - } + mod := setupFile(genesisFile, GenesisJSON, 0644) + + setupFile(privValFile, PrivValJSON, 0400) + + setupFile(key1File, Key1JSON, 0400) + + setupFile(key2File, Key2JSON, 0400) + if mod > 0 { log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) } else { log.Notice("Already initialized", "priv_validator", privValFile) From 5ebdd964c5dda6c53376d3506bc4d19458be6206 Mon Sep 17 00:00:00 2001 From: Rigel Rozanski Date: Thu, 13 Apr 2017 19:04:56 -0400 Subject: [PATCH 26/33] rebase updates/ rpc updates --- glide.lock | 4 ++-- tests/tendermint/main.go | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index eedcffdccc..0476397fef 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600 -updated: 2017-04-13T18:07:44.07521907-04:00 +updated: 2017-04-13T18:53:31.406195807-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -69,7 +69,7 @@ imports: - name: github.com/tendermint/go-config version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto - version: 3f47cfac5fcd9e0f1727c7db980b3559913b3e3a + version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index 605de6823c..c486c64ab3 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -72,7 +72,8 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + //request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes) @@ -122,7 +123,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes) From c292d54e47c5d9164778e1c62f2931b0e21f7397 Mon Sep 17 00:00:00 2001 From: Rigel Rozanski Date: Sat, 15 Apr 2017 12:07:27 -0400 Subject: [PATCH 27/33] Debug Flag, Run -> RunE --- cmd/basecoin/main.go | 8 +---- cmd/commands/ibc.go | 48 ++++++++++++------------- cmd/commands/init.go | 37 ++++++++++++------- cmd/commands/key.go | 17 ++++----- cmd/commands/query.go | 52 ++++++++++++++------------- cmd/commands/reset.go | 9 ++--- cmd/commands/start.go | 25 +++++++------ cmd/commands/tx.go | 49 ++++++++++++++----------- cmd/commands/utils.go | 26 ++++++++++---- cmd/counter/cmd.go | 9 +++-- cmd/counter/main.go | 8 +---- docs/guide/example-plugin.md | 11 +++--- docs/guide/ibc.md | 6 ++-- docs/guide/src/example-plugin/cmd.go | 6 ++-- docs/guide/src/example-plugin/main.go | 8 +---- glide.lock | 2 +- glide.yaml | 2 +- scripts/print_txs.go | 6 ++-- tests/tendermint/main.go | 4 +-- 19 files changed, 178 insertions(+), 155 deletions(-) diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index bcb5493010..5b37ab7fef 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/tendermint/basecoin/cmd/commands" @@ -28,8 +25,5 @@ func main() { commands.VersionCmd, ) - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 48fd4d6c2b..1c817d5bdb 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -5,11 +5,11 @@ import ( "fmt" "io/ioutil" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tendermint/basecoin/plugins/ibc" - cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" tmtypes "github.com/tendermint/tendermint/types" @@ -30,13 +30,13 @@ var ( IBCRegisterTxCmd = &cobra.Command{ Use: "register", Short: "Register a blockchain via IBC", - Run: ibcRegisterTxCmd, + RunE: ibcRegisterTxCmd, } IBCUpdateTxCmd = &cobra.Command{ Use: "update", Short: "Update the latest state of a blockchain via IBC", - Run: ibcUpdateTxCmd, + RunE: ibcUpdateTxCmd, } IBCPacketTxCmd = &cobra.Command{ @@ -47,13 +47,13 @@ var ( IBCPacketCreateTxCmd = &cobra.Command{ Use: "create", Short: "Create an egress IBC packet", - Run: ibcPacketCreateTxCmd, + RunE: ibcPacketCreateTxCmd, } IBCPacketPostTxCmd = &cobra.Command{ Use: "post", Short: "Deliver an IBC packet to another chain", - Run: ibcPacketPostTxCmd, + RunE: ibcPacketPostTxCmd, } ) @@ -117,13 +117,13 @@ func init() { //--------------------------------------------------------------------- // ibc command implementations -func ibcRegisterTxCmd(cmd *cobra.Command, args []string) { +func ibcRegisterTxCmd(cmd *cobra.Command, args []string) error { chainID := ibcChainIDFlag genesisFile := ibcGenesisFlag genesisBytes, err := ioutil.ReadFile(genesisFile) if err != nil { - cmn.Exit(fmt.Sprintf("Error reading genesis file %v: %+v\n", genesisFile, err)) + return errors.Errorf("Error reading genesis file %v: %v\n", genesisFile, err) } ibcTx := ibc.IBCRegisterChainTx{ @@ -140,18 +140,18 @@ func ibcRegisterTxCmd(cmd *cobra.Command, args []string) { }{ibcTx})) name := "IBC" - AppTx(name, data) + return AppTx(name, data) } -func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { +func ibcUpdateTxCmd(cmd *cobra.Command, args []string) error { headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Header (%v) is invalid hex: %+v\n", ibcHeaderFlag, err)) + return errors.Errorf("Header (%v) is invalid hex: %v\n", ibcHeaderFlag, err) } commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Commit (%v) is invalid hex: %+v\n", ibcCommitFlag, err)) + return errors.Errorf("Commit (%v) is invalid hex: %v\n", ibcCommitFlag, err) } header := new(tmtypes.Header) @@ -159,12 +159,12 @@ func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { err = wire.ReadBinaryBytes(headerBytes, &header) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling header: %+v\n", err)) + return errors.Errorf("Error unmarshalling header: %v\n", err) } err = wire.ReadBinaryBytes(commitBytes, &commit) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling commit: %+v\n", err)) + return errors.Errorf("Error unmarshalling commit: %v\n", err) } ibcTx := ibc.IBCUpdateChainTx{ @@ -179,21 +179,21 @@ func ibcUpdateTxCmd(cmd *cobra.Command, args []string) { }{ibcTx})) name := "IBC" - AppTx(name, data) + return AppTx(name, data) } -func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) { +func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) error { fromChain, toChain := ibcFromFlag, ibcToFlag packetType := ibcTypeFlag payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Payload (%v) is invalid hex: %+v\n", ibcPayloadFlag, err)) + return errors.Errorf("Payload (%v) is invalid hex: %v\n", ibcPayloadFlag, err) } sequence, err := ibcSequenceCmd() if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } ibcTx := ibc.IBCPacketCreateTx{ @@ -212,20 +212,20 @@ func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - AppTx("IBC", data) + return AppTx("IBC", data) } -func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { +func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) error { fromChain, fromHeight := ibcFromFlag, ibcHeightFlag packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Packet (%v) is invalid hex: %+v\n", ibcPacketFlag, err)) + return errors.Errorf("Packet (%v) is invalid hex: %v\n", ibcPacketFlag, err) } proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Proof (%v) is invalid hex: %+v\n", ibcProofFlag, err)) + return errors.Errorf("Proof (%v) is invalid hex: %v\n", ibcProofFlag, err) } var packet ibc.Packet @@ -233,12 +233,12 @@ func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { err = wire.ReadBinaryBytes(packetBytes, &packet) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling packet: %+v\n", err)) + return errors.Errorf("Error unmarshalling packet: %v\n", err) } err = wire.ReadBinaryBytes(proofBytes, &proof) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) + return errors.Errorf("Error unmarshalling proof: %v\n", err) } ibcTx := ibc.IBCPacketPostTx{ @@ -254,7 +254,7 @@ func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) { ibc.IBCTx `json:"unwrap"` }{ibcTx})) - AppTx("IBC", data) + return AppTx("IBC", data) } func ibcSequenceCmd() (uint64, error) { diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 233a39087d..7308c7961c 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -1,7 +1,6 @@ package commands import ( - "fmt" "io/ioutil" "os" "path" @@ -16,25 +15,25 @@ var ( InitCmd = &cobra.Command{ Use: "init", Short: "Initialize a basecoin blockchain", - Run: initCmd, + RunE: initCmd, } ) // setupFile aborts on error... or should we return it?? // returns 1 iff it set a file, otherwise 0 (so we can add them) -func setupFile(path, data string, perm os.FileMode) int { +func setupFile(path, data string, perm os.FileMode) (int, error) { _, err := os.Stat(path) if !os.IsNotExist(err) { - return 0 + return 0, nil } err = ioutil.WriteFile(path, []byte(data), perm) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return 0, err } - return 1 + return 1, nil } -func initCmd(cmd *cobra.Command, args []string) { +func initCmd(cmd *cobra.Command, args []string) error { rootDir := BasecoinRoot("") cmn.EnsureDir(rootDir, 0777) @@ -45,16 +44,30 @@ func initCmd(cmd *cobra.Command, args []string) { key1File := path.Join(rootDir, "key.json") key2File := path.Join(rootDir, "key2.json") - mod := setupFile(genesisFile, GenesisJSON, 0644) + - setupFile(privValFile, PrivValJSON, 0400) + - setupFile(key1File, Key1JSON, 0400) + - setupFile(key2File, Key2JSON, 0400) + mod1, err := setupFile(genesisFile, GenesisJSON, 0644) + if err != nil { + return err + } + mod2, err := setupFile(privValFile, PrivValJSON, 0400) + if err != nil { + return err + } + mod3, err := setupFile(key1File, Key1JSON, 0400) + if err != nil { + return err + } + mod4, err := setupFile(key2File, Key2JSON, 0400) + if err != nil { + return err + } - if mod > 0 { + if (mod1 + mod2 + mod3 + mod4) > 0 { log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File) } else { log.Notice("Already initialized", "priv_validator", privValFile) } + + return nil } var PrivValJSON = `{ diff --git a/cmd/commands/key.go b/cmd/commands/key.go index a1cec50d1b..62be3c1d36 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -8,9 +8,9 @@ import ( "path" "strings" + //"github.com/pkg/errors" "github.com/spf13/cobra" - cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" ) @@ -24,18 +24,19 @@ var ( NewKeyCmd = &cobra.Command{ Use: "new", Short: "Create a new private key", - Run: newKeyCmd, + RunE: newKeyCmd, } ) -func newKeyCmd(cmd *cobra.Command, args []string) { +func newKeyCmd(cmd *cobra.Command, args []string) error { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") fmt.Println(&key) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Println(string(keyJSON)) + return nil } func init() { @@ -85,18 +86,18 @@ func genKey() *Key { } } -func LoadKey(keyFile string) *Key { +func LoadKey(keyFile string) (*Key, error) { filePath := path.Join(BasecoinRoot(""), keyFile) keyJSONBytes, err := ioutil.ReadFile(filePath) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return nil, err } key := new(Key) err = json.Unmarshal(keyJSONBytes, key) if err != nil { - cmn.Exit(fmt.Sprintf("Error reading key from %v: %v\n", filePath, err)) + return nil, fmt.Errorf("Error reading key from %v: %v\n", filePath, err) //never stack trace } - return key + return key, nil } diff --git a/cmd/commands/query.go b/cmd/commands/query.go index 7e6e8de285..56ec683a16 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -5,9 +5,9 @@ import ( "fmt" "strconv" + "github.com/pkg/errors" "github.com/spf13/cobra" - cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" tmtypes "github.com/tendermint/tendermint/types" @@ -18,25 +18,25 @@ var ( QueryCmd = &cobra.Command{ Use: "query [key]", Short: "Query the merkle tree", - Run: queryCmd, + RunE: queryCmd, } AccountCmd = &cobra.Command{ Use: "account [address]", Short: "Get details of an account", - Run: accountCmd, + RunE: accountCmd, } BlockCmd = &cobra.Command{ Use: "block [height]", Short: "Get the header and commit of a block", - Run: blockCmd, + RunE: blockCmd, } VerifyCmd = &cobra.Command{ Use: "verify", Short: "Verify the IAVL proof", - Run: verifyCmd, + RunE: verifyCmd, } ) @@ -68,10 +68,10 @@ func init() { RegisterFlags(VerifyCmd, verifyFlags) } -func queryCmd(cmd *cobra.Command, args []string) { +func queryCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 { - cmn.Exit("query command requires an argument ([key])") + return fmt.Errorf("query command requires an argument ([key])") //never stack trace } keyString := args[0] @@ -81,17 +81,17 @@ func queryCmd(cmd *cobra.Command, args []string) { var err error key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - cmn.Exit(fmt.Sprintf("Query key (%v) is invalid hex: %+v\n", keyString, err)) + return errors.Errorf("Query key (%v) is invalid hex: %v\n", keyString, err) } } resp, err := Query(nodeFlag, key) if err != nil { - cmn.Exit(fmt.Sprintf("Query returns error: %+v\n", err)) + return errors.Errorf("Query returns error: %v\n", err) } if !resp.Code.IsOK() { - cmn.Exit(fmt.Sprintf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log)) + return errors.Errorf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log) } val := resp.Value @@ -103,12 +103,13 @@ func queryCmd(cmd *cobra.Command, args []string) { Proof []byte `json:"proof"` Height uint64 `json:"height"` }{val, proof, height}))) + return nil } -func accountCmd(cmd *cobra.Command, args []string) { +func accountCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 { - cmn.Exit("account command requires an argument ([address])") + return fmt.Errorf("account command requires an argument ([address])") //never stack trace } addrHex := StripHex(args[0]) @@ -116,31 +117,32 @@ func accountCmd(cmd *cobra.Command, args []string) { // convert destination address to bytes addr, err := hex.DecodeString(addrHex) if err != nil { - cmn.Exit(fmt.Sprintf("Account address (%v) is invalid hex: %+v\n", addrHex, err)) + return errors.Errorf("Account address (%v) is invalid hex: %v\n", addrHex, err) } acc, err := getAcc(nodeFlag, addr) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Println(string(wire.JSONBytes(acc))) + return nil } -func blockCmd(cmd *cobra.Command, args []string) { +func blockCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 { - cmn.Exit("block command requires an argument ([height])") + return fmt.Errorf("block command requires an argument ([height])") //never stack trace } heightString := args[0] height, err := strconv.Atoi(heightString) if err != nil { - cmn.Exit(fmt.Sprintf("Height must be an int, got %v: %+v\n", heightString, err)) + return errors.Errorf("Height must be an int, got %v: %v\n", heightString, err) } header, commit, err := getHeaderAndCommit(nodeFlag, height) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Println(string(wire.JSONBytes(struct { @@ -156,6 +158,7 @@ func blockCmd(cmd *cobra.Command, args []string) { Commit: commit, }, }))) + return nil } type BlockHex struct { @@ -168,7 +171,7 @@ type BlockJSON struct { Commit *tmtypes.Commit `json:"commit"` } -func verifyCmd(cmd *cobra.Command, args []string) { +func verifyCmd(cmd *cobra.Command, args []string) error { keyString, valueString := keyFlag, valueFlag @@ -177,7 +180,7 @@ func verifyCmd(cmd *cobra.Command, args []string) { if isHex(keyString) { key, err = hex.DecodeString(StripHex(keyString)) if err != nil { - cmn.Exit(fmt.Sprintf("Key (%v) is invalid hex: %+v\n", keyString, err)) + return errors.Errorf("Key (%v) is invalid hex: %v\n", keyString, err) } } @@ -185,25 +188,26 @@ func verifyCmd(cmd *cobra.Command, args []string) { if isHex(valueString) { value, err = hex.DecodeString(StripHex(valueString)) if err != nil { - cmn.Exit(fmt.Sprintf("Value (%v) is invalid hex: %+v\n", valueString, err)) + return errors.Errorf("Value (%v) is invalid hex: %v\n", valueString, err) } } root, err := hex.DecodeString(StripHex(rootFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("Root (%v) is invalid hex: %+v\n", rootFlag, err)) + return errors.Errorf("Root (%v) is invalid hex: %v\n", rootFlag, err) } proofBytes, err := hex.DecodeString(StripHex(proofFlag)) proof, err := merkle.ReadProof(proofBytes) if err != nil { - cmn.Exit(fmt.Sprintf("Error unmarshalling proof: %+v\n", err)) + return errors.Errorf("Error unmarshalling proof: %v\n", err) } if proof.Verify(key, value, root) { fmt.Println("OK") } else { - cmn.Exit(fmt.Sprintf("Proof does not verify")) + return errors.New("Proof does not verify") } + return nil } diff --git a/cmd/commands/reset.go b/cmd/commands/reset.go index f2841ea801..d1b4dfbbc8 100644 --- a/cmd/commands/reset.go +++ b/cmd/commands/reset.go @@ -5,20 +5,21 @@ import ( "github.com/spf13/cobra" - "github.com/tendermint/tendermint/cmd/tendermint/commands" + tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tmcfg "github.com/tendermint/tendermint/config/tendermint" ) var UnsafeResetAllCmd = &cobra.Command{ Use: "unsafe_reset_all", Short: "Reset all blockchain data", - Run: unsafeResetAllCmd, + RunE: unsafeResetAllCmd, } -func unsafeResetAllCmd(cmd *cobra.Command, args []string) { +func unsafeResetAllCmd(cmd *cobra.Command, args []string) error { basecoinDir := BasecoinRoot("") tmDir := path.Join(basecoinDir) tmConfig := tmcfg.GetConfig(tmDir) - commands.ResetAll(tmConfig, log) + tmcmd.ResetAll(tmConfig, log) + return nil } diff --git a/cmd/commands/start.go b/cmd/commands/start.go index d14f663d12..e4fd5560cd 100644 --- a/cmd/commands/start.go +++ b/cmd/commands/start.go @@ -5,6 +5,7 @@ import ( "os" "path" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tendermint/abci/server" @@ -22,7 +23,7 @@ import ( var StartCmd = &cobra.Command{ Use: "start", Short: "Start basecoin", - Run: startCmd, + RunE: startCmd, } //flags @@ -42,7 +43,7 @@ func init() { {&addrFlag, "address", "tcp://0.0.0.0:46658", "Listen address"}, {&eyesFlag, "eyes", "local", "MerkleEyes address, or 'local' for embedded"}, {&dirFlag, "dir", ".", "Root directory"}, - {&withoutTendermintFlag, "without-tendermint", false, "Run Tendermint in-process with the App"}, + {&withoutTendermintFlag, "without-tendermint", false, "RunE Tendermint in-process with the App"}, } RegisterFlags(StartCmd, flags) @@ -50,7 +51,7 @@ func init() { // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") } -func startCmd(cmd *cobra.Command, args []string) { +func startCmd(cmd *cobra.Command, args []string) error { basecoinDir := BasecoinRoot("") // Connect to MerkleEyes @@ -61,7 +62,7 @@ func startCmd(cmd *cobra.Command, args []string) { var err error eyesCli, err = eyes.NewClient(eyesFlag) if err != nil { - cmn.Exit(fmt.Sprintf("Error connecting to MerkleEyes: %+v\n", err)) + return errors.Errorf("Error connecting to MerkleEyes: %v\n", err) } } @@ -84,7 +85,7 @@ func startCmd(cmd *cobra.Command, args []string) { if _, err := os.Stat(genesisFile); err == nil { err := basecoinApp.LoadGenesis(genesisFile) if err != nil { - cmn.Exit(fmt.Sprintf("Error in LoadGenesis: %+v\n", err)) + return errors.Errorf("Error in LoadGenesis: %v\n", err) } } else { fmt.Printf("No genesis file at %s, skipping...\n", genesisFile) @@ -95,20 +96,20 @@ func startCmd(cmd *cobra.Command, args []string) { if withoutTendermintFlag { log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID) // run just the abci app/server - startBasecoinABCI(basecoinApp) + return startBasecoinABCI(basecoinApp) } else { log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID) // start the app with tendermint in-process - startTendermint(basecoinDir, basecoinApp) + return startTendermint(basecoinDir, basecoinApp) } } -func startBasecoinABCI(basecoinApp *app.Basecoin) { +func startBasecoinABCI(basecoinApp *app.Basecoin) error { // Start the ABCI listener svr, err := server.NewServer(addrFlag, "socket", basecoinApp) if err != nil { - cmn.Exit(fmt.Sprintf("Error creating listener: %+v\n", err)) + return errors.Errorf("Error creating listener: %v\n", err) } // Wait forever @@ -116,9 +117,10 @@ func startBasecoinABCI(basecoinApp *app.Basecoin) { // Cleanup svr.Stop() }) + return nil } -func startTendermint(dir string, basecoinApp *app.Basecoin) { +func startTendermint(dir string, basecoinApp *app.Basecoin) error { // Get configuration tmConfig := tmcfg.GetConfig(dir) @@ -132,7 +134,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) { _, err := n.Start() if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return errors.Errorf("%v\n", err) } // Wait forever @@ -140,4 +142,5 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) { // Cleanup n.Stop() }) + return nil } diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index e7381b0874..1fd6be11cd 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -10,7 +10,6 @@ import ( "github.com/tendermint/basecoin/types" crypto "github.com/tendermint/go-crypto" - cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -26,13 +25,13 @@ var ( SendTxCmd = &cobra.Command{ Use: "send", Short: "A SendTx transaction, for sending tokens around", - Run: sendTxCmd, + RunE: sendTxCmd, } AppTxCmd = &cobra.Command{ Use: "app", Short: "An AppTx transaction, for sending raw data to plugins", - Run: appTxCmd, + RunE: appTxCmd, } ) @@ -82,31 +81,34 @@ func init() { TxCmd.AddCommand(SendTxCmd, AppTxCmd) } -func sendTxCmd(cmd *cobra.Command, args []string) { +func sendTxCmd(cmd *cobra.Command, args []string) error { // convert destination address to bytes to, err := hex.DecodeString(StripHex(toFlag)) if err != nil { - cmn.Exit(fmt.Sprintf("To address is invalid hex: %+v\n", err)) + return errors.Errorf("To address is invalid hex: %v\n", err) } // load the priv key - privKey := LoadKey(fromFlag) + privKey, err := LoadKey(fromFlag) + if err != nil { + return err + } // get the sequence number for the tx sequence, err := getSeq(privKey.Address[:]) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } //parse the fee and amounts into coin types feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } // craft the tx @@ -129,39 +131,43 @@ func sendTxCmd(cmd *cobra.Command, args []string) { // broadcast the transaction to tendermint data, log, err := broadcastTx(tx) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Printf("Response: %X ; %s\n", data, log) + return nil } -func appTxCmd(cmd *cobra.Command, args []string) { +func appTxCmd(cmd *cobra.Command, args []string) error { // convert data to bytes data := []byte(dataFlag) if isHex(dataFlag) { data, _ = hex.DecodeString(dataFlag) } name := nameFlag - AppTx(name, data) + return AppTx(name, data) } -func AppTx(name string, data []byte) { +func AppTx(name string, data []byte) error { - privKey := LoadKey(fromFlag) + privKey, err := LoadKey(fromFlag) + if err != nil { + return err + } sequence, err := getSeq(privKey.Address[:]) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } //parse the fee and amounts into coin types feeCoin, err := types.ParseCoin(feeFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } amountCoins, err := types.ParseCoins(amountFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) @@ -180,9 +186,10 @@ func AppTx(name string, data []byte) { data, log, err := broadcastTx(tx) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } fmt.Printf("Response: %X ; %s\n", data, log) + return nil } // broadcast the transaction to tendermint @@ -199,7 +206,7 @@ func broadcastTx(tx types.Tx) ([]byte, string, error) { _, err := uriClient.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult) if err != nil { - return nil, "", errors.New(cmn.Fmt("Error on broadcast tx: %v", err)) + return nil, "", errors.Errorf("Error on broadcast tx: %v", err) } res := (*tmResult).(*ctypes.ResultBroadcastTxCommit) @@ -207,12 +214,12 @@ func broadcastTx(tx types.Tx) ([]byte, string, error) { // if it fails check, we don't even get a delivertx back! if !res.CheckTx.Code.IsOK() { r := res.CheckTx - return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log)) + return nil, "", errors.Errorf("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log) } if !res.DeliverTx.Code.IsOK() { r := res.DeliverTx - return nil, "", errors.New(cmn.Fmt("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log)) + return nil, "", errors.Errorf("BroadcastTxCommit got non-zero exit code: %v. %X; %s", r.Code, r.Data, r.Log) } return res.DeliverTx.Data, res.DeliverTx.Log, nil diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 7f21be9515..18b856f4d7 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -13,6 +13,7 @@ import ( "github.com/tendermint/basecoin/types" abci "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" client "github.com/tendermint/go-rpc/client" wire "github.com/tendermint/go-wire" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -33,6 +34,19 @@ func BasecoinRoot(rootDir string) string { return rootDir } +//Add debugging flag and execute the root command +func ExecuteWithDebug(RootCmd *cobra.Command) { + + var debug bool + RootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enables stack trace error messages") + + //note that Execute() prints the error if encountered, so no need to reprint the error, + // only if we want the full stack trace + if err := RootCmd.Execute(); err != nil && debug { + cmn.Exit(fmt.Sprintf("%+v\n", err)) + } +} + type Flag2Register struct { Pointer interface{} Use string @@ -117,11 +131,11 @@ func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) { } _, err := uriClient.Call("abci_query", params, tmResult) if err != nil { - return nil, errors.New(fmt.Sprintf("Error calling /abci_query: %v", err)) + return nil, errors.Errorf("Error calling /abci_query: %v", err) } res := (*tmResult).(*ctypes.ResultABCIQuery) if !res.Response.Code.IsOK() { - return nil, errors.New(fmt.Sprintf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)) + return nil, errors.Errorf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log) } return &res.Response, nil } @@ -138,14 +152,14 @@ func getAcc(tmAddr string, address []byte) (*types.Account, error) { accountBytes := response.Value if len(accountBytes) == 0 { - return nil, errors.New(fmt.Sprintf("Account bytes are empty for address: %X ", address)) + return nil, fmt.Errorf("Account bytes are empty for address: %X ", address) //never stack trace } var acc *types.Account err = wire.ReadBinaryBytes(accountBytes, &acc) if err != nil { - return nil, errors.New(fmt.Sprintf("Error reading account %X error: %v", - accountBytes, err.Error())) + return nil, errors.Errorf("Error reading account %X error: %v", + accountBytes, err.Error()) } return acc, nil @@ -158,7 +172,7 @@ func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Co method := "commit" _, err := uriClient.Call(method, map[string]interface{}{"height": height}, tmResult) if err != nil { - return nil, nil, errors.New(fmt.Sprintf("Error on %s: %v", method, err)) + return nil, nil, errors.Errorf("Error on %s: %v", method, err) } resCommit := (*tmResult).(*ctypes.ResultCommit) header := resCommit.Header diff --git a/cmd/counter/cmd.go b/cmd/counter/cmd.go index 6b31e3fc61..cde1f0fd00 100644 --- a/cmd/counter/cmd.go +++ b/cmd/counter/cmd.go @@ -9,14 +9,13 @@ import ( "github.com/tendermint/basecoin/cmd/commands" "github.com/tendermint/basecoin/plugins/counter" "github.com/tendermint/basecoin/types" - cmn "github.com/tendermint/go-common" ) //commands var CounterTxCmd = &cobra.Command{ Use: "counter", Short: "Create, sign, and broadcast a transaction to the counter plugin", - Run: counterTxCmd, + RunE: counterTxCmd, } //flags @@ -34,11 +33,11 @@ func init() { commands.RegisterStartPlugin("counter", func() types.Plugin { return counter.New() }) } -func counterTxCmd(cmd *cobra.Command, args []string) { +func counterTxCmd(cmd *cobra.Command, args []string) error { countFee, err := commands.ParseCoins(countFeeFlag) if err != nil { - cmn.Exit(fmt.Sprintf("%+v\n", err)) + return err } counterTx := counter.CounterTx{ @@ -51,5 +50,5 @@ func counterTxCmd(cmd *cobra.Command, args []string) { data := wire.BinaryBytes(counterTx) name := "counter" - commands.AppTx(name, data) + return commands.AppTx(name, data) } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index fc5ad6b02a..8a96b50ed7 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/tendermint/basecoin/cmd/commands" @@ -27,8 +24,5 @@ func main() { commands.QuickVersionCmd("0.1.0"), ) - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } diff --git a/docs/guide/example-plugin.md b/docs/guide/example-plugin.md index d9e3a3255b..a4592b355a 100644 --- a/docs/guide/example-plugin.md +++ b/docs/guide/example-plugin.md @@ -46,10 +46,7 @@ func main() { ) //Run the root command - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } ``` @@ -71,7 +68,7 @@ var ( ExamplePluginTxCmd = &cobra.Command{ Use: "example", Short: "Create, sign, and broadcast a transaction to the example plugin", - Run: examplePluginTxCmd, + RunE: examplePluginTxCmd, } ) ``` @@ -98,10 +95,10 @@ func init() { We now define the actual function which is called by our CLI command. ```golang -func examplePluginTxCmd(cmd *cobra.Command, args []string) { +func examplePluginTxCmd(cmd *cobra.Command, args []string) error { exampleTx := ExamplePluginTx{validFlag} exampleTxBytes := wire.BinaryBytes(exampleTx) - commands.AppTx("example-plugin", exampleTxBytes) + return commands.AppTx("example-plugin", exampleTxBytes) } ``` diff --git a/docs/guide/ibc.md b/docs/guide/ibc.md index 9b88c416ba..abbf0908fc 100644 --- a/docs/guide/ibc.md +++ b/docs/guide/ibc.md @@ -13,7 +13,8 @@ You may also want to see the tutorials on [a simple example plugin](example-plug and the list of [more advanced plugins](more-examples.md). The IBC plugin defines a new set of transactions as subtypes of the `AppTx`. -The plugin's functionality is accessed by setting the `AppTx.Name` field to `"IBC"`, and setting the `Data` field to the serialized IBC transaction type. +The plugin's functionality is accessed by setting the `AppTx.Name` field to `"IBC"`, +and setting the `Data` field to the serialized IBC transaction type. We'll demonstrate exactly how this works below. @@ -33,7 +34,8 @@ contains the votes responsible for committing the previous block, and a field in the block header called `AppHash`, which refers to the Merkle root hash of the application after processing the transactions from the previous block. So, if we want to verify the `AppHash` from height H, we need the signatures from `LastCommit` -at height H+1. (And remember that this `AppHash` only contains the results from all transactions up to and including block H-1) +at height H+1. (And remember that this `AppHash` only contains the results from all +transactions up to and including block H-1) Unlike Proof-of-Work, the light-client protocol does not need to download and check all the headers in the blockchain - the client can always jump straight diff --git a/docs/guide/src/example-plugin/cmd.go b/docs/guide/src/example-plugin/cmd.go index 51077d06f5..b439176266 100644 --- a/docs/guide/src/example-plugin/cmd.go +++ b/docs/guide/src/example-plugin/cmd.go @@ -17,7 +17,7 @@ var ( ExamplePluginTxCmd = &cobra.Command{ Use: "example", Short: "Create, sign, and broadcast a transaction to the example plugin", - Run: examplePluginTxCmd, + RunE: examplePluginTxCmd, } ) @@ -35,7 +35,7 @@ func init() { } //Send a transaction -func examplePluginTxCmd(cmd *cobra.Command, args []string) { +func examplePluginTxCmd(cmd *cobra.Command, args []string) error { // Create a transaction using the flag. // The tx passes on custom information to the plugin @@ -58,5 +58,5 @@ func examplePluginTxCmd(cmd *cobra.Command, args []string) { // - Once deserialized, the tx is passed to `state.ExecTx` (state/execution.go) // - If the tx passes various checks, the `tx.Data` is forwarded as `txBytes` to `plugin.RunTx` (docs/guide/src/example-plugin/plugin.go) // - Finally, it deserialized back to the ExamplePluginTx - commands.AppTx("example-plugin", exampleTxBytes) + return commands.AppTx("example-plugin", exampleTxBytes) } diff --git a/docs/guide/src/example-plugin/main.go b/docs/guide/src/example-plugin/main.go index 3a2984b60d..e2892bd7d8 100644 --- a/docs/guide/src/example-plugin/main.go +++ b/docs/guide/src/example-plugin/main.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "os" - "github.com/spf13/cobra" "github.com/tendermint/basecoin/cmd/commands" @@ -31,8 +28,5 @@ func main() { ) //Run the root command - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + commands.ExecuteWithDebug(RootCmd) } diff --git a/glide.lock b/glide.lock index 0476397fef..e8ed38ebdd 100644 --- a/glide.lock +++ b/glide.lock @@ -89,7 +89,7 @@ imports: subpackages: - upnp - name: github.com/tendermint/go-rpc - version: fcea0cda21f64889be00a0f4b6d13266b1a76ee7 + version: c3295f4878019ff3fdfcac37a4c0e4bcf4bb02a7 subpackages: - client - server diff --git a/glide.yaml b/glide.yaml index 420cc1ceba..9d74f5a6b9 100644 --- a/glide.yaml +++ b/glide.yaml @@ -11,7 +11,7 @@ import: - package: github.com/tendermint/go-data version: master - package: github.com/tendermint/go-rpc - version: master + version: develop - package: github.com/tendermint/go-wire version: master - package: github.com/tendermint/merkleeyes diff --git a/scripts/print_txs.go b/scripts/print_txs.go index d7570a0bd6..689173a907 100644 --- a/scripts/print_txs.go +++ b/scripts/print_txs.go @@ -9,7 +9,7 @@ import ( "time" "github.com/gorilla/websocket" - . "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-rpc/types" "github.com/tendermint/go-wire" @@ -21,7 +21,7 @@ func main() { _, err := ws.Start() if err != nil { - Exit(err.Error()) + cmn.Exit(err.Error()) } // Read a bunch of responses @@ -50,7 +50,7 @@ func main() { reqBytes := wire.JSONBytes(request) err = ws.WriteMessage(websocket.TextMessage, reqBytes) if err != nil { - Exit("writing websocket request: " + err.Error()) + cmn.Exit("writing websocket request: " + err.Error()) } } diff --git a/tests/tendermint/main.go b/tests/tendermint/main.go index c486c64ab3..73ace4ef88 100644 --- a/tests/tendermint/main.go +++ b/tests/tendermint/main.go @@ -72,7 +72,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) //request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") @@ -123,7 +123,7 @@ func main() { // Write request txBytes := wire.BinaryBytes(struct{ types.Tx }{tx}) - request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", cmn.Arr(txBytes)) + request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx_sync", map[string]interface{}{"tx": txBytes}) reqBytes := wire.JSONBytes(request) //fmt.Print(".") err := ws.WriteMessage(websocket.TextMessage, reqBytes) From 04f79f3ad2b4aa82f6dafe2a69b6fdf0246d606a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 17 Apr 2017 19:59:22 -0400 Subject: [PATCH 28/33] cmd.SilenceUsage --- CHANGELOG.md | 4 ++-- cmd/commands/utils.go | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d01ce65e3..b8014dd06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,10 @@ # Changelog -## 0.4.0 (March 30, 2017) +## 0.4.0 (TBD) BREAKING CHANGES: -- CLI now uses Cobra +- CLI now uses Cobra, which forced changes to some of the flag names and orderings IMPROVEMENTS: diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 18b856f4d7..5dd9635fa4 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -38,6 +38,7 @@ func BasecoinRoot(rootDir string) string { func ExecuteWithDebug(RootCmd *cobra.Command) { var debug bool + RootCmd.SilenceUsage = true RootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enables stack trace error messages") //note that Execute() prints the error if encountered, so no need to reprint the error, From 6da5f72de93d5b407bc2c4966b2f42b8b8abd419 Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Mon, 17 Apr 2017 21:28:03 -0400 Subject: [PATCH 29/33] tiny fixes --- cmd/commands/ibc.go | 2 +- cmd/commands/init.go | 3 +-- cmd/commands/key.go | 1 - cmd/commands/query.go | 3 +++ cmd/commands/start.go | 7 ++----- cmd/commands/tx.go | 4 ++-- cmd/commands/utils.go | 16 ++++++++++++++-- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 1c817d5bdb..8b0938826b 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -91,7 +91,7 @@ func init() { packetCreateFlags := []Flag2Register{ fromFlagReg, {&ibcToFlag, "to", "", "Destination ChainID"}, - {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin},"}, + {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin)"}, {&ibcPayloadFlag, "payload", "", "IBC packet payload"}, {&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"}, } diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 7308c7961c..68b2ab3899 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -19,11 +19,10 @@ var ( } ) -// setupFile aborts on error... or should we return it?? // returns 1 iff it set a file, otherwise 0 (so we can add them) func setupFile(path, data string, perm os.FileMode) (int, error) { _, err := os.Stat(path) - if !os.IsNotExist(err) { + if !os.IsNotExist(err) { //permission errors generated if use os.IsExist return 0, nil } err = ioutil.WriteFile(path, []byte(data), perm) diff --git a/cmd/commands/key.go b/cmd/commands/key.go index 62be3c1d36..91678f625f 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -31,7 +31,6 @@ var ( func newKeyCmd(cmd *cobra.Command, args []string) error { key := genKey() keyJSON, err := json.MarshalIndent(key, "", "\t") - fmt.Println(&key) if err != nil { return err } diff --git a/cmd/commands/query.go b/cmd/commands/query.go index 56ec683a16..f73ed0ada0 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -198,6 +198,9 @@ func verifyCmd(cmd *cobra.Command, args []string) error { } proofBytes, err := hex.DecodeString(StripHex(proofFlag)) + if err != nil { + return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofBytes, err) + } proof, err := merkle.ReadProof(proofBytes) if err != nil { diff --git a/cmd/commands/start.go b/cmd/commands/start.go index e4fd5560cd..4578738ceb 100644 --- a/cmd/commands/start.go +++ b/cmd/commands/start.go @@ -43,12 +43,9 @@ func init() { {&addrFlag, "address", "tcp://0.0.0.0:46658", "Listen address"}, {&eyesFlag, "eyes", "local", "MerkleEyes address, or 'local' for embedded"}, {&dirFlag, "dir", ".", "Root directory"}, - {&withoutTendermintFlag, "without-tendermint", false, "RunE Tendermint in-process with the App"}, + {&withoutTendermintFlag, "without-tendermint", false, "Run Tendermint in-process with the App"}, } RegisterFlags(StartCmd, flags) - - // TODO: move to config file - // eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded") } func startCmd(cmd *cobra.Command, args []string) error { @@ -134,7 +131,7 @@ func startTendermint(dir string, basecoinApp *app.Basecoin) error { _, err := n.Start() if err != nil { - return errors.Errorf("%v\n", err) + return err } // Wait forever diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 1fd6be11cd..2e12be06ec 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -58,10 +58,10 @@ func init() { {&txNodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, {&chainIDFlag, "chain_id", "test_chain_id", "ID of the chain for replay protection"}, {&fromFlag, "from", "key.json", "Path to a private key to sign the transaction"}, - {&amountFlag, "amount", "", "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver},"}, + {&amountFlag, "amount", "", "Coins to send in transaction of the format ,,... (eg: 1btc,2gold,5silver)"}, {&gasFlag, "gas", 0, "The amount of gas for the transaction"}, {&feeFlag, "fee", "", "Coins for the transaction fee of the format "}, - {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate},"}, + {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate)"}, } sendTxFlags := []Flag2Register{ diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 5dd9635fa4..7eea8cdebd 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -4,6 +4,10 @@ import ( "encoding/hex" "fmt" "os" + "path" + "regexp" + "strconv" + "strings" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -22,14 +26,14 @@ import ( //This variable can be overwritten by plugin applications // if they require a different working directory -var DefaultHome = "basecoin" +var DefaultHome = ".basecoin" func BasecoinRoot(rootDir string) string { if rootDir == "" { rootDir = os.Getenv("BCHOME") } if rootDir == "" { - rootDir = os.Getenv("HOME") + "/." + DefaultHome + rootDir = path.Join(os.Getenv("HOME"), DefaultHome) } return rootDir } @@ -48,6 +52,14 @@ func ExecuteWithDebug(RootCmd *cobra.Command) { } } +//Quickly registering flags can be quickly achieved through using the utility functions +//RegisterFlags, and RegisterPersistentFlags. Ex: +// flags := []Flag2Register{ +// {&myStringFlag, "mystringflag", "foobar", "description of what this flag does"}, +// {&myBoolFlag, "myboolflag", false, "description of what this flag does"}, +// {&myInt64Flag, "myintflag", 333, "description of what this flag does"}, +// } +// RegisterFlags(MyCobraCmd, flags) type Flag2Register struct { Pointer interface{} Use string From 55e4cf17fd5692e4c612f8da0dbdcf435a2cf482 Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Tue, 18 Apr 2017 02:50:23 -0400 Subject: [PATCH 30/33] minor fix x2 --- cmd/commands/init.go | 2 +- cmd/commands/query.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/commands/init.go b/cmd/commands/init.go index 68b2ab3899..f7fae72e6c 100644 --- a/cmd/commands/init.go +++ b/cmd/commands/init.go @@ -22,7 +22,7 @@ var ( // returns 1 iff it set a file, otherwise 0 (so we can add them) func setupFile(path, data string, perm os.FileMode) (int, error) { _, err := os.Stat(path) - if !os.IsNotExist(err) { //permission errors generated if use os.IsExist + if !os.IsNotExist(err) { //note, os.IsExist(err) != !os.IsNotExist(err) return 0, nil } err = ioutil.WriteFile(path, []byte(data), perm) diff --git a/cmd/commands/query.go b/cmd/commands/query.go index f73ed0ada0..7d79c2f1f2 100644 --- a/cmd/commands/query.go +++ b/cmd/commands/query.go @@ -199,7 +199,7 @@ func verifyCmd(cmd *cobra.Command, args []string) error { proofBytes, err := hex.DecodeString(StripHex(proofFlag)) if err != nil { - return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofBytes, err) + return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofFlag, err) } proof, err := merkle.ReadProof(proofBytes) From 34fc383aef6a2510a45d1a09ac09362d8245cbed Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Tue, 18 Apr 2017 23:04:50 -0400 Subject: [PATCH 31/33] tendermint dep branch: cli_change -> viper --- glide.lock | 90 ++++++++++++++++++++++++++++++++++++++++-------------- glide.yaml | 2 +- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/glide.lock b/glide.lock index e8ed38ebdd..366aee42ac 100644 --- a/glide.lock +++ b/glide.lock @@ -1,40 +1,72 @@ -hash: 57732245af8acdb6bc7f20b36e2e0329b60570797ac47353edee108129b1b600 -updated: 2017-04-13T18:53:31.406195807-04:00 +hash: a248393a241987824fbc93210d0d4c9202df819b2b015e9392d652393540cb19 +updated: 2017-04-18T23:03:02.314286469-04:00 imports: - name: github.com/btcsuite/btcd - version: 583684b21bfbde9b5fc4403916fd7c807feb0289 + version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - name: github.com/BurntSushi/toml version: e643e9ef00b049d75de26e61109c5ea01885cd21 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 +- name: github.com/fsnotify/fsnotify + version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317 + version: 2bba0603135d7d7f5cb73b2125beeda19c09f4ef subpackages: - proto + - ptypes/any - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 +- name: github.com/hashicorp/hcl + version: 630949a3c5fa3c613328e1b8256052cbc2327c9b + subpackages: + - hcl/ast + - hcl/parser + - hcl/scanner + - hcl/strconv + - hcl/token + - json/parser + - json/scanner + - json/token - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 +- name: github.com/magiconair/properties + version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable - version: a392f450ea64cee2b268dfaacdc2502b50a22b18 + version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty - version: 57fdcb988a5c543893cc61bce354a6e24ab70022 + version: fc9e8d8ef48496124e79ae0df75490096eccf6fe +- name: github.com/mitchellh/mapstructure + version: 53818660ed4955e899c0bcafa97299a388bd7c8e +- name: github.com/pelletier/go-buffruneio + version: c37440a7cf42ac63b919c752ca73a85067e05992 +- name: github.com/pelletier/go-toml + version: fe206efb84b2bc8e8cfafe6b4c1826622be969e3 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: ff09b135c25aae272398c51a07235b90a75aa4f0 +- name: github.com/spf13/afero + version: 9be650865eab0c12963d8753212f4f9c66cdcf12 + subpackages: + - mem +- name: github.com/spf13/cast + version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c + version: b6cb3958937245a12d4d7728be080a6c758f4136 +- name: github.com/spf13/jwalterweatherman + version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 - name: github.com/spf13/pflag - version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 + version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51 +- name: github.com/spf13/viper + version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/syndtr/goleveldb - version: 3c5717caf1475fd25964109a0fc640bd150fce43 + version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: - leveldb - leveldb/cache @@ -65,9 +97,7 @@ imports: - name: github.com/tendermint/go-clist version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common - version: dcb015dff6c7af21e65c8e2f3b450df19d38c777 -- name: github.com/tendermint/go-config - version: 620dcbbd7d587cf3599dedbf329b64311b0c307a + version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data @@ -85,17 +115,17 @@ imports: - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: 17124989a93774833df33107fbf17157a7f8ef31 + version: 4e802b363bdd843a40b0905e9791663bda4b1284 subpackages: - upnp - name: github.com/tendermint/go-rpc - version: c3295f4878019ff3fdfcac37a4c0e4bcf4bb02a7 + version: 4671c44b2d124f7f6f6243dbfbf4ae2bf42ee809 subpackages: - client - server - types - name: github.com/tendermint/go-wire - version: f530b7af7a8b06e612c2063bff6ace49060a085e + version: c1c9a57ab8038448ddea1714c0698f8051e5748c - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: @@ -106,7 +136,7 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: 022a5509181a19f78995a3dd9bba470333fe2d63 + version: de8952dd2ba7fd4697658f1a0ffc50e8cb690f9a subpackages: - blockchain - cmd/tendermint/commands @@ -125,7 +155,7 @@ imports: - types - version - name: golang.org/x/crypto - version: 728b753d0135da6801d45a38e6f43ff55779c5c2 + version: 12c985af8526c1f6f0c463bbfd9d69623d13b323 subpackages: - curve25519 - nacl/box @@ -136,7 +166,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: a6577fac2d73be281a500b310739095313165611 + version: 5602c733f70afc6dcec6766be0d5034d4c4f14de subpackages: - context - http2 @@ -146,11 +176,22 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: 99f16d856c9836c42d24e7ab64ea72916925fa97 + version: f3918c30c5c2cb527c0b071a27c35120a6c0719a subpackages: - unix +- name: golang.org/x/text + version: f4b4367115ec2de254587813edaa901bc1c723a8 + subpackages: + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm +- name: google.golang.org/genproto + version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + subpackages: + - googleapis/rpc/status - name: google.golang.org/grpc - version: 0713829b980f4ddd276689a36235c5fcc82a21bf + version: 6914ab1e338c92da4218a23d27fcd03d0ad78d46 subpackages: - codes - credentials @@ -161,11 +202,14 @@ imports: - naming - peer - stats + - status - tap - transport +- name: gopkg.in/yaml.v2 + version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -173,7 +217,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 4d4bfba8f1d1027c4fdbe371823030df51419987 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index 9d74f5a6b9..4396e8526d 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,7 +17,7 @@ import: - package: github.com/tendermint/merkleeyes version: master - package: github.com/tendermint/tendermint - version: cli_change + version: viper - package: github.com/tendermint/abci version: master - package: github.com/gorilla/websocket From 9d620e449b84b08de935144610bab8b28e69785c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 12:56:50 -0400 Subject: [PATCH 32/33] glide update and rebase fixes --- cmd/commands/utils.go | 3 --- cmd/counter/cmd.go | 2 +- glide.lock | 63 +++++++++++-------------------------------- glide.yaml | 18 ++++++------- 4 files changed, 26 insertions(+), 60 deletions(-) diff --git a/cmd/commands/utils.go b/cmd/commands/utils.go index 7eea8cdebd..0f263d82a8 100644 --- a/cmd/commands/utils.go +++ b/cmd/commands/utils.go @@ -5,9 +5,6 @@ import ( "fmt" "os" "path" - "regexp" - "strconv" - "strings" "github.com/pkg/errors" "github.com/spf13/cobra" diff --git a/cmd/counter/cmd.go b/cmd/counter/cmd.go index cde1f0fd00..451f42a482 100644 --- a/cmd/counter/cmd.go +++ b/cmd/counter/cmd.go @@ -35,7 +35,7 @@ func init() { func counterTxCmd(cmd *cobra.Command, args []string) error { - countFee, err := commands.ParseCoins(countFeeFlag) + countFee, err := types.ParseCoins(countFeeFlag) if err != nil { return err } diff --git a/glide.lock b/glide.lock index 366aee42ac..bc150cd7de 100644 --- a/glide.lock +++ b/glide.lock @@ -1,16 +1,14 @@ -hash: a248393a241987824fbc93210d0d4c9202df819b2b015e9392d652393540cb19 -updated: 2017-04-18T23:03:02.314286469-04:00 +hash: c6e5febc35b5fd1003066820defb8a089db048b407239dad9faf44553fdc15e8 +updated: 2017-04-21T12:55:42.7004558-04:00 imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - name: github.com/BurntSushi/toml - version: e643e9ef00b049d75de26e61109c5ea01885cd21 + version: b26d9c308763d68093482582cea63d69be07a0f0 - name: github.com/ebuchman/fail-test version: 95f809107225be108efcf10a3509e4ea6ceef3c4 -- name: github.com/fsnotify/fsnotify - version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf @@ -22,49 +20,20 @@ imports: version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/gorilla/websocket version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13 -- name: github.com/hashicorp/hcl - version: 630949a3c5fa3c613328e1b8256052cbc2327c9b - subpackages: - - hcl/ast - - hcl/parser - - hcl/scanner - - hcl/strconv - - hcl/token - - json/parser - - json/scanner - - json/token - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/magiconair/properties - version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty version: fc9e8d8ef48496124e79ae0df75490096eccf6fe -- name: github.com/mitchellh/mapstructure - version: 53818660ed4955e899c0bcafa97299a388bd7c8e -- name: github.com/pelletier/go-buffruneio - version: c37440a7cf42ac63b919c752ca73a85067e05992 -- name: github.com/pelletier/go-toml - version: fe206efb84b2bc8e8cfafe6b4c1826622be969e3 - name: github.com/pkg/errors version: ff09b135c25aae272398c51a07235b90a75aa4f0 -- name: github.com/spf13/afero - version: 9be650865eab0c12963d8753212f4f9c66cdcf12 - subpackages: - - mem -- name: github.com/spf13/cast - version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: b6cb3958937245a12d4d7728be080a6c758f4136 -- name: github.com/spf13/jwalterweatherman - version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 + version: 10f6b9d7e1631a54ad07c5c0fb71c28a1abfd3c2 - name: github.com/spf13/pflag version: 2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51 -- name: github.com/spf13/viper - version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -81,7 +50,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/abci - version: af792eac777de757cd496349a5f6b5313738fcbc + version: 56e13d87f4e3ec1ea756957d6b23caa6ebcf0998 subpackages: - client - example/dummy @@ -98,6 +67,8 @@ imports: version: 3baa390bbaf7634251c42ad69a8682e7e3990552 - name: github.com/tendermint/go-common version: f9e3db037330c8a8d61d3966de8473eaf01154fa +- name: github.com/tendermint/go-config + version: 620dcbbd7d587cf3599dedbf329b64311b0c307a - name: github.com/tendermint/go-crypto version: 0ca2c6fdb0706001ca4c4b9b80c9f428e8cf39da - name: github.com/tendermint/go-data @@ -115,11 +86,11 @@ imports: - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-p2p - version: 4e802b363bdd843a40b0905e9791663bda4b1284 + version: 17124989a93774833df33107fbf17157a7f8ef31 subpackages: - upnp - name: github.com/tendermint/go-rpc - version: 4671c44b2d124f7f6f6243dbfbf4ae2bf42ee809 + version: 559613689d56eaa423b19a3a4158546beb4857de subpackages: - client - server @@ -136,7 +107,7 @@ imports: - app - client - name: github.com/tendermint/tendermint - version: de8952dd2ba7fd4697658f1a0ffc50e8cb690f9a + version: e8cad948e366cd1d0a9ebef642073f4ade9899e9 subpackages: - blockchain - cmd/tendermint/commands @@ -155,7 +126,7 @@ imports: - types - version - name: golang.org/x/crypto - version: 12c985af8526c1f6f0c463bbfd9d69623d13b323 + version: 96846453c37f0876340a66a47f3f75b1f3a6cd2d subpackages: - curve25519 - nacl/box @@ -166,7 +137,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 5602c733f70afc6dcec6766be0d5034d4c4f14de + version: c8c74377599bd978aee1cf3b9b63a8634051cec2 subpackages: - context - http2 @@ -176,11 +147,11 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: f3918c30c5c2cb527c0b071a27c35120a6c0719a + version: ea9bcade75cb975a0b9738936568ab388b845617 subpackages: - unix - name: golang.org/x/text - version: f4b4367115ec2de254587813edaa901bc1c723a8 + version: 19e3104b43db45fca0303f489a9536087b184802 subpackages: - secure/bidirule - transform @@ -205,11 +176,9 @@ imports: - status - tap - transport -- name: gopkg.in/yaml.v2 - version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: - name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -217,7 +186,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 4d4bfba8f1d1027c4fdbe371823030df51419987 + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index 4396e8526d..87735c19c9 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,24 +1,24 @@ package: github.com/tendermint/basecoin import: - package: github.com/tendermint/go-common - version: master + version: develop - package: github.com/tendermint/go-crypto - version: master + version: develop - package: github.com/tendermint/go-events - version: master + version: develop - package: github.com/tendermint/go-logger - version: master + version: develop - package: github.com/tendermint/go-data - version: master + version: develop - package: github.com/tendermint/go-rpc version: develop - package: github.com/tendermint/go-wire - version: master + version: develop - package: github.com/tendermint/merkleeyes - version: master + version: develop - package: github.com/tendermint/tendermint - version: viper + version: develop - package: github.com/tendermint/abci - version: master + version: develop - package: github.com/gorilla/websocket version: v1.1.0 From 7914661eda664b2e769c117667b462edde6b749f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 13:00:45 -0400 Subject: [PATCH 33/33] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8014dd06c..6ddfaf3434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ BREAKING CHANGES: IMPROVEMENTS: - `basecoin init` doesn't generate error if already initialized +- Much more testing ## 0.3.1 (March 23, 2017)