diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2fea153..adba0d2e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.10.1 (March 22, 2018) + +FEATURES: + +- [types] ResponseCheckTx and ResponseDeliverTx are now the same. +- [example] `dummy` is duplicated as `kvstore`. + +IMPROVEMENTS: + +- glide -> Godep +- remove pkg/errors +- improve specification.rst + ## 0.10.0 (February 20, 2018) BREAKING CHANGES: diff --git a/Dockerfile.develop b/Dockerfile.develop index d4643155a..c6ec05f69 100644 --- a/Dockerfile.develop +++ b/Dockerfile.develop @@ -6,16 +6,18 @@ WORKDIR /go/src/github.com/tendermint/abci COPY Makefile /go/src/github.com/tendermint/abci/ # see make protoc for details on ldconfig -RUN make install_protoc && ldconfig +RUN make get_protoc && ldconfig # killall is used in tests RUN apt-get update && apt-get install -y \ psmisc \ && rm -rf /var/lib/apt/lists/* -COPY glide.yaml /go/src/github.com/tendermint/abci/ -COPY glide.lock /go/src/github.com/tendermint/abci/ +COPY Gopkg.toml /go/src/github.com/tendermint/abci/ +COPY Gopkg.lock /go/src/github.com/tendermint/abci/ +RUN make get_tools -RUN make get_vendor_deps +# see https://github.com/golang/dep/issues/1312 +RUN dep ensure -vendor-only COPY . /go/src/github.com/tendermint/abci diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 000000000..66b293f8d --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,213 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/go-kit/kit" + packages = [ + "log", + "log/level", + "log/term" + ] + revision = "4dc7be5d2d12881735283bcab7352178e190fc71" + version = "v0.6.0" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" + version = "v1.7.0" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "jsonpb", + "proto", + "protoc-gen-gogo/descriptor", + "sortkeys", + "types" + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + +[[projects]] + branch = "master" + name = "github.com/jmhodges/levigo" + packages = ["."] + revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/spf13/cobra" + packages = ["."] + revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" + version = "v0.0.1" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + branch = "master" + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util" + ] + revision = "169b1b37be738edb2813dab48c97a549bcf99bb5" + +[[projects]] + name = "github.com/tendermint/tmlibs" + packages = [ + "common", + "db", + "log" + ] + revision = "24da7009c3d8c019b40ba4287495749e3160caca" + version = "v0.7.1" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "lex/httplex", + "trace" + ] + revision = "6078986fec03a1dcc236c34816c71b0e05018fda" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + branch = "master" + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "f8c8703595236ae70fdf8789ecb656ea0bcdcf46" + +[[projects]] + name = "google.golang.org/grpc" + packages = [ + ".", + "balancer", + "codes", + "connectivity", + "credentials", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "stats", + "status", + "tap", + "transport" + ] + revision = "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" + version = "v1.7.5" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "e0c31538af2916be2aed38bae72f9040d93aa9a4b86a1839df7a83545a2442f1" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 000000000..7e52deced --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,56 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + +# NOTE if not specified, dep automatically adds `^` to each version, +# meaning it will accept up to the next version for the first non-zero +# element in the version. +# +# So `version = "1.3.2"` means `1.3.2 <= version < 2.0.0`. +# Use `~` for only minor version bumps. + +[[constraint]] + name = "github.com/gogo/protobuf" + version = "~1.0.0" + +[[constraint]] + name = "github.com/spf13/cobra" + version = "~0.0.1" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "~1.2.1" + +[[constraint]] + version = "~0.7.1" + name = "github.com/tendermint/tmlibs" + +[[constraint]] + name = "google.golang.org/grpc" + version = "~1.7.3" + +[prune] + go-tests = true + unused-packages = true diff --git a/Makefile b/Makefile index afdfb0f7b..64a989a87 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ GOTOOLS = \ github.com/mitchellh/gox \ - github.com/Masterminds/glide \ + github.com/golang/dep/cmd/dep \ gopkg.in/alecthomas/gometalinter.v2 \ github.com/gogo/protobuf/protoc-gen-gogo \ github.com/gogo/protobuf/gogoproto -GOTOOLS_CHECK = gox glide gometalinter.v2 protoc protoc-gen-gogo +GOTOOLS_CHECK = gox dep gometalinter.v2 protoc protoc-gen-gogo PACKAGES=$(shell go list ./... | grep -v '/vendor/') INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf @@ -65,8 +65,8 @@ update_tools: get_vendor_deps: @rm -rf vendor/ - @echo "--> Running glide install" - @glide install + @echo "--> Running dep ensure" + @dep ensure ######################################## diff --git a/README.md b/README.md index d5d2551f4..e6051cc34 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ See [the documentation](http://tendermint.readthedocs.io/en/master/) for more de ### Examples Check out the variety of example applications in the [example directory](example/). -It also contains the code refered to by the `counter` and `dummy` apps; these apps come +It also contains the code refered to by the `counter` and `kvstore` apps; these apps come built into the `abci-cli` binary. #### Counter @@ -125,21 +125,21 @@ func cmdCounter(cmd *cobra.Command, args []string) error { and can be found in [this file](cmd/abci-cli/abci-cli.go). -#### Dummy +#### kvstore -The `abci-cli dummy` application, which illustrates a simple key-value Merkle tree +The `abci-cli kvstore` application, which illustrates a simple key-value Merkle tree ```golang -func cmdDummy(cmd *cobra.Command, args []string) error { +func cmdKVStore(cmd *cobra.Command, args []string) error { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Create the application - in memory or persisted to disk var app types.Application if flagPersist == "" { - app = dummy.NewDummyApplication() + app = kvstore.NewKVStoreApplication() } else { - app = dummy.NewPersistentDummyApplication(flagPersist) - app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) + app = kvstore.NewPersistentKVStoreApplication(flagPersist) + app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) } // Start the listener @@ -160,4 +160,3 @@ func cmdDummy(cmd *cobra.Command, args []string) error { return nil } ``` - diff --git a/client/grpc_client.go b/client/grpc_client.go index f277e1d77..0f405a9c4 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -6,7 +6,6 @@ import ( "sync" "time" - "github.com/pkg/errors" context "golang.org/x/net/context" grpc "google.golang.org/grpc" @@ -105,7 +104,7 @@ func (cli *grpcClient) StopForError(err error) { func (cli *grpcClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return errors.Wrap(cli.err, "grpc client error") + return cli.err } // Set listener for all responses diff --git a/client/socket_client.go b/client/socket_client.go index 3030bb571..5c0101685 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -3,13 +3,13 @@ package abcicli import ( "bufio" "container/list" + "errors" "fmt" "net" "reflect" "sync" "time" - "github.com/pkg/errors" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -111,7 +111,7 @@ func (cli *socketClient) StopForError(err error) { func (cli *socketClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return errors.Wrap(cli.err, "socket client error") + return cli.err } // Set listener for all responses diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index faaea5020..4dc5e96e3 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -17,7 +17,7 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/example/counter" - "github.com/tendermint/abci/example/dummy" + "github.com/tendermint/abci/example/kvstore" "github.com/tendermint/abci/server" servertest "github.com/tendermint/abci/tests/server" "github.com/tendermint/abci/types" @@ -47,7 +47,7 @@ var ( flagAddrC string flagSerial bool - // dummy + // kvstore flagAddrD string flagPersist string ) @@ -59,7 +59,7 @@ var RootCmd = &cobra.Command{ PersistentPreRunE: func(cmd *cobra.Command, args []string) error { switch cmd.Use { - case "counter", "dummy": // for the examples apps, don't pre-run + case "counter", "kvstore", "dummy": // for the examples apps, don't pre-run return nil case "version": // skip running for version command return nil @@ -133,6 +133,12 @@ func addDummyFlags() { dummyCmd.PersistentFlags().StringVarP(&flagAddrD, "addr", "", "tcp://0.0.0.0:46658", "listen address") dummyCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database") } + +func addKVStoreFlags() { + kvstoreCmd.PersistentFlags().StringVarP(&flagAddrD, "addr", "", "tcp://0.0.0.0:46658", "listen address") + kvstoreCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database") +} + func addCommands() { RootCmd.AddCommand(batchCmd) RootCmd.AddCommand(consoleCmd) @@ -150,8 +156,12 @@ func addCommands() { // examples addCounterFlags() RootCmd.AddCommand(counterCmd) + // deprecated, left for backwards compatibility addDummyFlags() RootCmd.AddCommand(dummyCmd) + // replaces dummy, see issue #196 + addKVStoreFlags() + RootCmd.AddCommand(kvstoreCmd) } var batchCmd = &cobra.Command{ @@ -285,13 +295,25 @@ var counterCmd = &cobra.Command{ }, } +// deprecated, left for backwards compatibility var dummyCmd = &cobra.Command{ - Use: "dummy", + Use: "dummy", + Deprecated: "use: [abci-cli kvstore] instead", + Short: "ABCI demo example", + Long: "ABCI demo example", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + return cmdKVStore(cmd, args) + }, +} + +var kvstoreCmd = &cobra.Command{ + Use: "kvstore", Short: "ABCI demo example", Long: "ABCI demo example", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - return cmdDummy(cmd, args) + return cmdKVStore(cmd, args) }, } @@ -654,16 +676,16 @@ func cmdCounter(cmd *cobra.Command, args []string) error { return nil } -func cmdDummy(cmd *cobra.Command, args []string) error { +func cmdKVStore(cmd *cobra.Command, args []string) error { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Create the application - in memory or persisted to disk var app types.Application if flagPersist == "" { - app = dummy.NewDummyApplication() + app = kvstore.NewKVStoreApplication() } else { - app = dummy.NewPersistentDummyApplication(flagPersist) - app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) + app = kvstore.NewPersistentKVStoreApplication(flagPersist) + app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) } // Start the listener diff --git a/example/dummy/README.md b/example/dummy/README.md index 8c1f0f042..fe9d1c2db 100644 --- a/example/dummy/README.md +++ b/example/dummy/README.md @@ -1,31 +1,4 @@ # Dummy -There are two app's here: the DummyApplication and the PersistentDummyApplication. - -## DummyApplication - -The DummyApplication is a simple merkle key-value store. -Transactions of the form `key=value` are stored as key-value pairs in the tree. -Transactions without an `=` sign set the value to the key. -The app has no replay protection (other than what the mempool provides). - -## PersistentDummyApplication - -The PersistentDummyApplication wraps the DummyApplication -and provides two additional features: - -1) persistence of state across app restarts (using Tendermint's ABCI-Handshake mechanism) -2) validator set changes - -The state is persisted in leveldb along with the last block committed, -and the Handshake allows any necessary blocks to be replayed. -Validator set changes are effected using the following transaction format: - -``` -val:pubkey1/power1,addr2/power2,addr3/power3" -``` - -where `power1` is the new voting power for the validator with `pubkey1` (possibly a new one). -There is no sybil protection against new validators joining. -Validators can be removed by setting their power to `0`. +DEPRECATED. See KVStore diff --git a/example/dummy/dummy.go b/example/dummy/kvstore.go similarity index 100% rename from example/dummy/dummy.go rename to example/dummy/kvstore.go diff --git a/example/dummy/dummy_test.go b/example/dummy/kvstore_test.go similarity index 100% rename from example/dummy/dummy_test.go rename to example/dummy/kvstore_test.go diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_kvstore.go similarity index 100% rename from example/dummy/persistent_dummy.go rename to example/dummy/persistent_kvstore.go diff --git a/example/example_test.go b/example/example_test.go index dfa38a398..3fc38f492 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -16,14 +16,14 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/code" - "github.com/tendermint/abci/example/dummy" + "github.com/tendermint/abci/example/kvstore" abciserver "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" ) -func TestDummy(t *testing.T) { - fmt.Println("### Testing Dummy") - testStream(t, dummy.NewDummyApplication()) +func TestKVStore(t *testing.T) { + fmt.Println("### Testing KVStore") + testStream(t, kvstore.NewKVStoreApplication()) } func TestBaseApp(t *testing.T) { diff --git a/example/kvstore/README.md b/example/kvstore/README.md new file mode 100644 index 000000000..e988eadb0 --- /dev/null +++ b/example/kvstore/README.md @@ -0,0 +1,31 @@ +# KVStore + +There are two app's here: the KVStoreApplication and the PersistentKVStoreApplication. + +## KVStoreApplication + +The KVStoreApplication is a simple merkle key-value store. +Transactions of the form `key=value` are stored as key-value pairs in the tree. +Transactions without an `=` sign set the value to the key. +The app has no replay protection (other than what the mempool provides). + +## PersistentKVStoreApplication + +The PersistentKVStoreApplication wraps the KVStoreApplication +and provides two additional features: + +1) persistence of state across app restarts (using Tendermint's ABCI-Handshake mechanism) +2) validator set changes + +The state is persisted in leveldb along with the last block committed, +and the Handshake allows any necessary blocks to be replayed. +Validator set changes are effected using the following transaction format: + +``` +val:pubkey1/power1,addr2/power2,addr3/power3" +``` + +where `power1` is the new voting power for the validator with `pubkey1` (possibly a new one). +There is no sybil protection against new validators joining. +Validators can be removed by setting their power to `0`. + diff --git a/example/kvstore/helpers.go b/example/kvstore/helpers.go new file mode 100644 index 000000000..c71e371a9 --- /dev/null +++ b/example/kvstore/helpers.go @@ -0,0 +1,36 @@ +package kvstore + +import ( + "github.com/tendermint/abci/types" + cmn "github.com/tendermint/tmlibs/common" +) + +// RandVal creates one random validator, with a key derived +// from the input value +func RandVal(i int) types.Validator { + pubkey := cmn.RandBytes(33) + power := cmn.RandUint16() + 1 + return types.Validator{pubkey, int64(power)} +} + +// RandVals returns a list of cnt validators for initializing +// the application. Note that the keys are deterministically +// derived from the index in the array, while the power is +// random (Change this if not desired) +func RandVals(cnt int) []types.Validator { + res := make([]types.Validator, cnt) + for i := 0; i < cnt; i++ { + res[i] = RandVal(i) + } + return res +} + +// InitKVStore initializes the kvstore app with some data, +// which allows tests to pass and is fine as long as you +// don't make any tx that modify the validator state +func InitKVStore(app *PersistentKVStoreApplication) { + app.InitChain(types.RequestInitChain{ + Validators: RandVals(1), + AppStateBytes: []byte("[]"), + }) +} diff --git a/example/kvstore/kvstore.go b/example/kvstore/kvstore.go new file mode 100644 index 000000000..4ccbc56b0 --- /dev/null +++ b/example/kvstore/kvstore.go @@ -0,0 +1,126 @@ +package kvstore + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + + "github.com/tendermint/abci/example/code" + "github.com/tendermint/abci/types" + cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" +) + +var ( + stateKey = []byte("stateKey") + kvPairPrefixKey = []byte("kvPairKey:") +) + +type State struct { + db dbm.DB + Size int64 `json:"size"` + Height int64 `json:"height"` + AppHash []byte `json:"app_hash"` +} + +func loadState(db dbm.DB) State { + stateBytes := db.Get(stateKey) + var state State + if len(stateBytes) != 0 { + err := json.Unmarshal(stateBytes, &state) + if err != nil { + panic(err) + } + } + state.db = db + return state +} + +func saveState(state State) { + stateBytes, err := json.Marshal(state) + if err != nil { + panic(err) + } + state.db.Set(stateKey, stateBytes) +} + +func prefixKey(key []byte) []byte { + return append(kvPairPrefixKey, key...) +} + +//--------------------------------------------------- + +var _ types.Application = (*KVStoreApplication)(nil) + +type KVStoreApplication struct { + types.BaseApplication + + state State +} + +func NewKVStoreApplication() *KVStoreApplication { + state := loadState(dbm.NewMemDB()) + return &KVStoreApplication{state: state} +} + +func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { + return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size)} +} + +// tx is either "key=value" or just arbitrary bytes +func (app *KVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { + var key, value []byte + parts := bytes.Split(tx, []byte("=")) + if len(parts) == 2 { + key, value = parts[0], parts[1] + } else { + key, value = tx, tx + } + app.state.db.Set(prefixKey(key), value) + app.state.Size += 1 + + tags := []cmn.KVPair{ + {[]byte("app.creator"), []byte("jae")}, + {[]byte("app.key"), key}, + } + return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags} +} + +func (app *KVStoreApplication) CheckTx(tx []byte) types.ResponseCheckTx { + return types.ResponseCheckTx{Code: code.CodeTypeOK} +} + +func (app *KVStoreApplication) Commit() types.ResponseCommit { + // Using a memdb - just return the big endian size of the db + appHash := make([]byte, 8) + binary.PutVarint(appHash, app.state.Size) + app.state.AppHash = appHash + app.state.Height += 1 + saveState(app.state) + return types.ResponseCommit{Data: appHash} +} + +func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { + if reqQuery.Prove { + value := app.state.db.Get(prefixKey(reqQuery.Data)) + resQuery.Index = -1 // TODO make Proof return index + resQuery.Key = reqQuery.Data + resQuery.Value = value + if value != nil { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } else { + value := app.state.db.Get(prefixKey(reqQuery.Data)) + resQuery.Value = value + if value != nil { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } +} diff --git a/example/kvstore/kvstore_test.go b/example/kvstore/kvstore_test.go new file mode 100644 index 000000000..b3d29ffb0 --- /dev/null +++ b/example/kvstore/kvstore_test.go @@ -0,0 +1,310 @@ +package kvstore + +import ( + "bytes" + "io/ioutil" + "sort" + "testing" + + "github.com/stretchr/testify/require" + + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" + + abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/example/code" + abciserver "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" +) + +func testKVStore(t *testing.T, app types.Application, tx []byte, key, value string) { + ar := app.DeliverTx(tx) + require.False(t, ar.IsErr(), ar) + // repeating tx doesn't raise error + ar = app.DeliverTx(tx) + require.False(t, ar.IsErr(), ar) + + // make sure query is fine + resQuery := app.Query(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + }) + require.Equal(t, code.CodeTypeOK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) + + // make sure proof is fine + resQuery = app.Query(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + Prove: true, + }) + require.EqualValues(t, code.CodeTypeOK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) +} + +func TestKVStoreKV(t *testing.T) { + kvstore := NewKVStoreApplication() + key := "abc" + value := key + tx := []byte(key) + testKVStore(t, kvstore, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testKVStore(t, kvstore, tx, key, value) +} + +func TestPersistentKVStoreKV(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO + if err != nil { + t.Fatal(err) + } + kvstore := NewPersistentKVStoreApplication(dir) + key := "abc" + value := key + tx := []byte(key) + testKVStore(t, kvstore, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testKVStore(t, kvstore, tx, key, value) +} + +func TestPersistentKVStoreInfo(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO + if err != nil { + t.Fatal(err) + } + kvstore := NewPersistentKVStoreApplication(dir) + InitKVStore(kvstore) + height := int64(0) + + resInfo := kvstore.Info(types.RequestInfo{}) + if resInfo.LastBlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) + } + + // make and apply block + height = int64(1) + hash := []byte("foo") + header := types.Header{ + Height: int64(height), + } + kvstore.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil}) + kvstore.EndBlock(types.RequestEndBlock{header.Height}) + kvstore.Commit() + + resInfo = kvstore.Info(types.RequestInfo{}) + if resInfo.LastBlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) + } + +} + +// add a validator, remove a validator, update a validator +func TestValUpdates(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO + if err != nil { + t.Fatal(err) + } + kvstore := NewPersistentKVStoreApplication(dir) + + // init with some validators + total := 10 + nInit := 5 + vals := RandVals(total) + // iniitalize with the first nInit + kvstore.InitChain(types.RequestInitChain{ + Validators: vals[:nInit], + }) + + vals1, vals2 := vals[:nInit], kvstore.Validators() + valsEqual(t, vals1, vals2) + + var v1, v2, v3 types.Validator + + // add some validators + v1, v2 = vals[nInit], vals[nInit+1] + diff := []types.Validator{v1, v2} + tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power) + tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power) + + makeApplyBlock(t, kvstore, 1, diff, tx1, tx2) + + vals1, vals2 = vals[:nInit+2], kvstore.Validators() + valsEqual(t, vals1, vals2) + + // remove some validators + v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit] + v1.Power = 0 + v2.Power = 0 + v3.Power = 0 + diff = []types.Validator{v1, v2, v3} + tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) + tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power) + tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power) + + makeApplyBlock(t, kvstore, 2, diff, tx1, tx2, tx3) + + vals1 = append(vals[:nInit-2], vals[nInit+1]) + vals2 = kvstore.Validators() + valsEqual(t, vals1, vals2) + + // update some validators + v1 = vals[0] + if v1.Power == 5 { + v1.Power = 6 + } else { + v1.Power = 5 + } + diff = []types.Validator{v1} + tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) + + makeApplyBlock(t, kvstore, 3, diff, tx1) + + vals1 = append([]types.Validator{v1}, vals1[1:]...) + vals2 = kvstore.Validators() + valsEqual(t, vals1, vals2) + +} + +func makeApplyBlock(t *testing.T, kvstore types.Application, heightInt int, diff []types.Validator, txs ...[]byte) { + // make and apply block + height := int64(heightInt) + hash := []byte("foo") + header := types.Header{ + Height: height, + } + + kvstore.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil}) + for _, tx := range txs { + if r := kvstore.DeliverTx(tx); r.IsErr() { + t.Fatal(r) + } + } + resEndBlock := kvstore.EndBlock(types.RequestEndBlock{header.Height}) + kvstore.Commit() + + valsEqual(t, diff, resEndBlock.ValidatorUpdates) + +} + +// order doesn't matter +func valsEqual(t *testing.T, vals1, vals2 []types.Validator) { + if len(vals1) != len(vals2) { + t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1)) + } + sort.Sort(types.Validators(vals1)) + sort.Sort(types.Validators(vals2)) + for i, v1 := range vals1 { + v2 := vals2[i] + if !bytes.Equal(v1.PubKey, v2.PubKey) || + v1.Power != v2.Power { + t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power) + } + } +} + +func makeSocketClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { + // Start the listener + socket := cmn.Fmt("unix://%s.sock", name) + logger := log.TestingLogger() + + server := abciserver.NewSocketServer(socket, app) + server.SetLogger(logger.With("module", "abci-server")) + if err := server.Start(); err != nil { + return nil, nil, err + } + + // Connect to the socket + client := abcicli.NewSocketClient(socket, false) + client.SetLogger(logger.With("module", "abci-client")) + if err := client.Start(); err != nil { + server.Stop() + return nil, nil, err + } + + return client, server, nil +} + +func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { + // Start the listener + socket := cmn.Fmt("unix://%s.sock", name) + logger := log.TestingLogger() + + gapp := types.NewGRPCApplication(app) + server := abciserver.NewGRPCServer(socket, gapp) + server.SetLogger(logger.With("module", "abci-server")) + if err := server.Start(); err != nil { + return nil, nil, err + } + + client := abcicli.NewGRPCClient(socket, true) + client.SetLogger(logger.With("module", "abci-client")) + if err := client.Start(); err != nil { + server.Stop() + return nil, nil, err + } + return client, server, nil +} + +func TestClientServer(t *testing.T) { + // set up socket app + kvstore := NewKVStoreApplication() + client, server, err := makeSocketClientServer(kvstore, "kvstore-socket") + require.Nil(t, err) + defer server.Stop() + defer client.Stop() + + runClientTests(t, client) + + // set up grpc app + kvstore = NewKVStoreApplication() + gclient, gserver, err := makeGRPCClientServer(kvstore, "kvstore-grpc") + require.Nil(t, err) + defer gserver.Stop() + defer gclient.Stop() + + runClientTests(t, gclient) +} + +func runClientTests(t *testing.T, client abcicli.Client) { + // run some tests.... + key := "abc" + value := key + tx := []byte(key) + testClient(t, client, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testClient(t, client, tx, key, value) +} + +func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) { + ar, err := app.DeliverTxSync(tx) + require.NoError(t, err) + require.False(t, ar.IsErr(), ar) + // repeating tx doesn't raise error + ar, err = app.DeliverTxSync(tx) + require.NoError(t, err) + require.False(t, ar.IsErr(), ar) + + // make sure query is fine + resQuery, err := app.QuerySync(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + }) + require.Nil(t, err) + require.Equal(t, code.CodeTypeOK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) + + // make sure proof is fine + resQuery, err = app.QuerySync(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + Prove: true, + }) + require.Nil(t, err) + require.Equal(t, code.CodeTypeOK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) +} diff --git a/example/kvstore/persistent_kvstore.go b/example/kvstore/persistent_kvstore.go new file mode 100644 index 000000000..888258ff5 --- /dev/null +++ b/example/kvstore/persistent_kvstore.go @@ -0,0 +1,205 @@ +package kvstore + +import ( + "bytes" + "encoding/hex" + "fmt" + "strconv" + "strings" + + "github.com/tendermint/abci/example/code" + "github.com/tendermint/abci/types" + cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" +) + +const ( + ValidatorSetChangePrefix string = "val:" +) + +//----------------------------------------- + +var _ types.Application = (*PersistentKVStoreApplication)(nil) + +type PersistentKVStoreApplication struct { + app *KVStoreApplication + + // validator set + ValUpdates []types.Validator + + logger log.Logger +} + +func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication { + name := "kvstore" + db, err := dbm.NewGoLevelDB(name, dbDir) + if err != nil { + panic(err) + } + + state := loadState(db) + + return &PersistentKVStoreApplication{ + app: &KVStoreApplication{state: state}, + logger: log.NewNopLogger(), + } +} + +func (app *PersistentKVStoreApplication) SetLogger(l log.Logger) { + app.logger = l +} + +func (app *PersistentKVStoreApplication) Info(req types.RequestInfo) types.ResponseInfo { + res := app.app.Info(req) + res.LastBlockHeight = app.app.state.Height + res.LastBlockAppHash = app.app.state.AppHash + return res +} + +func (app *PersistentKVStoreApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption { + return app.app.SetOption(req) +} + +// tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes +func (app *PersistentKVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { + // if it starts with "val:", update the validator set + // format is "val:pubkey/power" + if isValidatorTx(tx) { + // update validators in the merkle tree + // and in app.ValUpdates + return app.execValidatorTx(tx) + } + + // otherwise, update the key-value store + return app.app.DeliverTx(tx) +} + +func (app *PersistentKVStoreApplication) CheckTx(tx []byte) types.ResponseCheckTx { + return app.app.CheckTx(tx) +} + +// Commit will panic if InitChain was not called +func (app *PersistentKVStoreApplication) Commit() types.ResponseCommit { + return app.app.Commit() +} + +func (app *PersistentKVStoreApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { + return app.app.Query(reqQuery) +} + +// Save the validators in the merkle tree +func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain { + for _, v := range req.Validators { + r := app.updateValidator(v) + if r.IsErr() { + app.logger.Error("Error updating validators", "r", r) + } + } + return types.ResponseInitChain{} +} + +// Track the block hash and header information +func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { + // reset valset changes + app.ValUpdates = make([]types.Validator, 0) + return types.ResponseBeginBlock{} +} + +// Update the validator set +func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { + return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates} +} + +//--------------------------------------------- +// update validators + +func (app *PersistentKVStoreApplication) Validators() (validators []types.Validator) { + itr := app.app.state.db.Iterator(nil, nil) + for ; itr.Valid(); itr.Next() { + if isValidatorTx(itr.Key()) { + validator := new(types.Validator) + err := types.ReadMessage(bytes.NewBuffer(itr.Value()), validator) + if err != nil { + panic(err) + } + validators = append(validators, *validator) + } + } + return +} + +func MakeValSetChangeTx(pubkey []byte, power int64) []byte { + return []byte(cmn.Fmt("val:%X/%d", pubkey, power)) +} + +func isValidatorTx(tx []byte) bool { + return strings.HasPrefix(string(tx), ValidatorSetChangePrefix) +} + +// format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx +func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx { + tx = tx[len(ValidatorSetChangePrefix):] + + //get the pubkey and power + pubKeyAndPower := strings.Split(string(tx), "/") + if len(pubKeyAndPower) != 2 { + return types.ResponseDeliverTx{ + Code: code.CodeTypeEncodingError, + Log: fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)} + } + pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] + + // decode the pubkey, ensuring its go-crypto encoded + pubkey, err := hex.DecodeString(pubkeyS) + if err != nil { + return types.ResponseDeliverTx{ + Code: code.CodeTypeEncodingError, + Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)} + } + /*_, err = crypto.PubKeyFromBytes(pubkey) + if err != nil { + return types.ResponseDeliverTx{ + Code: code.CodeTypeEncodingError, + Log: fmt.Sprintf("Pubkey (%X) is invalid go-crypto encoded", pubkey)} + }*/ + + // decode the power + power, err := strconv.ParseInt(powerS, 10, 64) + if err != nil { + return types.ResponseDeliverTx{ + Code: code.CodeTypeEncodingError, + Log: fmt.Sprintf("Power (%s) is not an int", powerS)} + } + + // update + return app.updateValidator(types.Validator{pubkey, power}) +} + +// add, update, or remove a validator +func (app *PersistentKVStoreApplication) updateValidator(v types.Validator) types.ResponseDeliverTx { + key := []byte("val:" + string(v.PubKey)) + if v.Power == 0 { + // remove validator + if !app.app.state.db.Has(key) { + return types.ResponseDeliverTx{ + Code: code.CodeTypeUnauthorized, + Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)} + } + app.app.state.db.Delete(key) + } else { + // add or update validator + value := bytes.NewBuffer(make([]byte, 0)) + if err := types.WriteMessage(&v, value); err != nil { + return types.ResponseDeliverTx{ + Code: code.CodeTypeEncodingError, + Log: fmt.Sprintf("Error encoding validator: %v", err)} + } + app.app.state.db.Set(key, value.Bytes()) + } + + // we only update the changes array if we successfully updated the tree + app.ValUpdates = append(app.ValUpdates, v) + + return types.ResponseDeliverTx{Code: code.CodeTypeOK} +} diff --git a/glide.lock b/glide.lock deleted file mode 100644 index e99f5e2e6..000000000 --- a/glide.lock +++ /dev/null @@ -1,120 +0,0 @@ -hash: cff2757779ef879f0c625c42af37fb3e486afd93ab9a91175c2458a719faac66 -updated: 2018-02-20T22:02:37.638875125-05:00 -imports: -- name: github.com/go-kit/kit - version: 4dc7be5d2d12881735283bcab7352178e190fc71 - subpackages: - - log - - log/level - - log/term -- name: github.com/go-logfmt/logfmt - version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 -- name: github.com/go-stack/stack - version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc -- name: github.com/gogo/protobuf - version: 1adfc126b41513cc696b209667c8656ea7aac67c - subpackages: - - gogoproto - - jsonpb - - proto - - protoc-gen-gogo/descriptor - - sortkeys - - types -- name: github.com/golang/protobuf - version: 925541529c1fa6821df4e44ce2723319eb2be768 - subpackages: - - proto - - ptypes - - ptypes/any - - ptypes/duration - - ptypes/timestamp -- name: github.com/golang/snappy - version: 553a641470496b2327abcac10b36396bd98e45c9 -- name: github.com/inconshreveable/mousetrap - version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 -- name: github.com/jmhodges/levigo - version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/kr/logfmt - version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 -- name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/spf13/cobra - version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b -- name: github.com/spf13/pflag - version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea -- name: github.com/syndtr/goleveldb - version: 211f780988068502fe874c44dae530528ebd840f - subpackages: - - leveldb - - leveldb/cache - - leveldb/comparer - - leveldb/errors - - leveldb/filter - - leveldb/iterator - - leveldb/journal - - leveldb/memdb - - leveldb/opt - - leveldb/storage - - leveldb/table - - leveldb/util -- name: github.com/tendermint/tmlibs - version: 1b9b5652a199ab0be2e781393fb275b66377309d - subpackages: - - common - - db - - log - - process -- name: golang.org/x/net - version: 2fb46b16b8dda405028c50f7c7f0f9dd1fa6bfb1 - subpackages: - - context - - http2 - - http2/hpack - - idna - - internal/timeseries - - lex/httplex - - trace -- name: golang.org/x/text - version: e19ae1496984b1c655b8044a65c0300a3c878dd3 - subpackages: - - secure/bidirule - - transform - - unicode/bidi - - unicode/norm -- name: google.golang.org/genproto - version: 4eb30f4778eed4c258ba66527a0d4f9ec8a36c45 - subpackages: - - googleapis/rpc/status -- name: google.golang.org/grpc - version: 401e0e00e4bb830a10496d64cd95e068c5bf50de - subpackages: - - balancer - - codes - - connectivity - - credentials - - grpclb/grpc_lb_v1/messages - - grpclog - - internal - - keepalive - - metadata - - naming - - peer - - resolver - - stats - - status - - tap - - transport -testImports: -- name: github.com/davecgh/go-spew - version: 346938d642f2ec3594ed81d874461961cd0faa76 - subpackages: - - spew -- name: github.com/pmezard/go-difflib - version: 792786c7400a136282c1664665ae0a8db921c6c2 - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 12b6f73e6084dad08a7c6e575284b177ecafbc71 - subpackages: - - assert - - require diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index bab5d17f0..000000000 --- a/glide.yaml +++ /dev/null @@ -1,28 +0,0 @@ -package: github.com/tendermint/abci -import: -- package: github.com/gogo/protobuf - version: ^1.0.0 - subpackages: - - proto -- package: github.com/pkg/errors - version: v0.8.0 -- package: github.com/spf13/cobra - version: v0.0.1 -- package: github.com/tendermint/tmlibs - version: v0.7.0 - subpackages: - - common - - db - - log - - process -- package: golang.org/x/net - subpackages: - - context -- package: google.golang.org/grpc - version: v1.7.3 -testImport: -- package: github.com/stretchr/testify - version: v1.2.1 - subpackages: - - assert - - require diff --git a/specification.rst b/specification.rst index 0c8994944..4b2704637 100644 --- a/specification.rst +++ b/specification.rst @@ -8,8 +8,51 @@ ABCI requests/responses are defined as simple Protobuf messages in `this schema file `__. TendermintCore sends the requests, and the ABCI application sends the -responses. Here, we describe the requests and responses as function -arguments and return values, and make some notes about usage: +responses. Here, we provide an overview of the messages types and how they +are used by Tendermint. Then we describe each request-response pair as a +function with arguments and return values, and add some notes on usage. + +Some messages (``Echo, Info, InitChain, BeginBlock, EndBlock, Commit``), don't +return errors because an error would indicate a critical failure in the +application and there's nothing Tendermint can do. The problem should be +addressed and both Tendermint and the application restarted. All other +messages (``SetOption, Query, CheckTx, DeliverTx``) return an +application-specific response ``Code uint32``, where only ``0`` is reserved for +``OK``. + +Some messages (``SetOption, Query, CheckTx, DeliverTx``) return +non-deterministic data in the form of ``Info`` and ``Log``. The ``Log`` is +intended for the literal output from the application's logger, while the +``Info`` is any additional info that should be returned. + +The first time a new blockchain is started, Tendermint calls ``InitChain``. +From then on, the Block Execution Sequence that causes the committed state to +be updated is as follows: + +``BeginBlock, [DeliverTx], EndBlock, Commit`` + +where one ``DeliverTx`` is called for each transaction in the block. +Cryptographic commitments to the results of DeliverTx, EndBlock, and +Commit are included in the header of the next block. + +Tendermint opens three connections to the application to handle the different message +types: + +- ``Consensus Connection - InitChain, BeginBlock, DeliverTx, EndBlock, Commit`` + +- ``Mempool Connection - CheckTx`` + +- ``Info Connection - Info, SetOption, Query`` + +The ``Flush`` message is used on every connection, and the ``Echo`` message +is only used for debugging. + +Note that messages may be sent concurrently across all connections - +a typical application will thus maintain a distinct state for each +connection. They may be referred to as the ``DeliverTx state``, the +``CheckTx state``, and the ``Commit state`` respectively. + +See below for more details on the message types and how they are used. Echo ^^^^ @@ -55,7 +98,11 @@ Info - **Usage**: - Return information about the application state. - - Used to sync the app with Tendermint on crash/restart. + - Used to sync Tendermint with the application during a handshake that + happens on startup. + - Tendermint expects ``LastBlockAppHash`` and ``LastBlockHeight`` to be + updated during ``Commit``, ensuring that ``Commit`` is never called twice + for the same block height. SetOption ^^^^^^^^^ @@ -87,7 +134,7 @@ InitChain - **Usage**: - - Called once upon genesis + - Called once upon genesis. Query ^^^^^ @@ -161,26 +208,26 @@ CheckTx - ``Data ([]byte)``: Result bytes, if any. - ``Log (string)``: The output of the application's logger. May be non-deterministic. - ``Info (string)``: Additional information. May be non-deterministic. - - ``GasWanted (int64)``: Amount of gas consumed by transaction. + - ``GasWanted (int64)``: Amount of gas request for transaction. + - ``GasUsed (int64)``: Amount of gas consumed by transaction. - ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account). - - ``Fee ([]cmn.KI64Pair)``: Fee paid for the transaction. + - ``Fee (cmn.KI64Pair)``: Fee paid for the transaction. - **Usage**: Validate a mempool transaction, prior to broadcasting or - proposing. This message should not mutate the main state, but - application developers may want to keep a separate CheckTx state that - gets reset upon Commit. - - CheckTx can happen interspersed with DeliverTx, but they happen on - different ABCI connections - CheckTx from the mempool connection, and - DeliverTx from the consensus connection. During Commit, the mempool - is locked, so you can reset the mempool state to the latest state - after running all those DeliverTxs, and then the mempool will re-run - whatever txs it has against that latest mempool state. - - Transactions are first run through CheckTx before broadcast to peers - in the mempool layer. You can make CheckTx semi-stateful and clear - the state upon ``Commit``, to allow for dependent sequences of transactions - in the same block. + proposing. CheckTx should perform stateful but light-weight checks + of the validity of the transaction (like checking signatures and account balances), + but need not execute in full (like running a smart contract). + + Tendermint runs CheckTx and DeliverTx concurrently with eachother, + though on distinct ABCI connections - the mempool connection and the consensus + connection, respectively. + + The application should maintain a separate state to support CheckTx. + This state can be reset to the latest committed state during ``Commit``, + where Tendermint ensures the mempool is locked and not sending new ``CheckTx``. + After ``Commit``, the mempool will rerun CheckTx on all remaining + transactions, throwing out any that are no longer valid. + DeliverTx ^^^^^^^^^ @@ -195,11 +242,13 @@ DeliverTx - ``Data ([]byte)``: Result bytes, if any. - ``Log (string)``: The output of the application's logger. May be non-deterministic. - ``Info (string)``: Additional information. May be non-deterministic. - - ``GasWanted (int64)``: Amount of gas predicted to be consumed by transaction. + - ``GasWanted (int64)``: Amount of gas requested for transaction. - ``GasUsed (int64)``: Amount of gas consumed by transaction. - ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account). + - ``Fee (cmn.KI64Pair)``: Fee paid for the transaction. - **Usage**: + - Deliver a transaction to be executed in full by the application. If the transaction is valid, returns CodeType.OK. @@ -222,6 +271,7 @@ EndBlock - Signals the end of a block. - Called prior to each Commit, after all transactions. - Validator set and consensus params are updated with the result. + - Validator pubkeys are expected to be go-wire encoded. Commit ^^^^^^ diff --git a/tests/client_server_test.go b/tests/client_server_test.go index 3d74478bc..3e1e3e1cd 100644 --- a/tests/client_server_test.go +++ b/tests/client_server_test.go @@ -6,14 +6,14 @@ import ( "github.com/stretchr/testify/assert" abciclient "github.com/tendermint/abci/client" - "github.com/tendermint/abci/example/dummy" + "github.com/tendermint/abci/example/kvstore" abciserver "github.com/tendermint/abci/server" ) func TestClientServerNoAddrPrefix(t *testing.T) { addr := "localhost:46658" transport := "socket" - app := dummy.NewDummyApplication() + app := kvstore.NewKVStoreApplication() server, err := abciserver.NewServer(addr, transport, app) assert.NoError(t, err, "expected no error on NewServer") diff --git a/tests/server/client.go b/tests/server/client.go index ee312c1a8..e7bcbc931 100644 --- a/tests/server/client.go +++ b/tests/server/client.go @@ -34,7 +34,7 @@ func SetOption(client abcicli.Client, key, value string) error { _, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: value}) if err != nil { fmt.Println("Failed test: SetOption") - fmt.Printf("error while setting %v=%v: \nerror: %v\n", key, value) + fmt.Printf("error while setting %v=%v: \nerror: %v\n", key, value, err) return err } fmt.Println("Passed test: SetOption") diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index ccbb313c5..ce074f513 100755 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -35,7 +35,7 @@ function testExample() { rm "${INPUT}".out.new } -testExample 1 tests/test_cli/ex1.abci abci-cli dummy +testExample 1 tests/test_cli/ex1.abci abci-cli kvstore testExample 2 tests/test_cli/ex2.abci abci-cli counter echo "" diff --git a/types/messages_test.go b/types/messages_test.go index 53e1a0cac..21d3595f0 100644 --- a/types/messages_test.go +++ b/types/messages_test.go @@ -21,7 +21,9 @@ func TestMarshalJSON(t *testing.T) { Code: 1, Data: []byte("hello"), GasWanted: 43, - Fee: cmn.KI64Pair{[]byte("pho"), 12}, + Tags: []cmn.KVPair{ + {[]byte("pho"), []byte("bo")}, + }, } b, err = json.Marshal(&r1) assert.Nil(t, err) diff --git a/types/types.pb.go b/types/types.pb.go index fda9b752c..b4ef05bbb 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1327,14 +1327,14 @@ func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} } type ResponseCheckTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` - // int64 gas_used = 6; - Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"` - Fee common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` + Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"` + Fee *common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1377,6 +1377,13 @@ func (m *ResponseCheckTx) GetGasWanted() int64 { return 0 } +func (m *ResponseCheckTx) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + func (m *ResponseCheckTx) GetTags() []common.KVPair { if m != nil { return m.Tags @@ -1384,21 +1391,22 @@ func (m *ResponseCheckTx) GetTags() []common.KVPair { return nil } -func (m *ResponseCheckTx) GetFee() common.KI64Pair { +func (m *ResponseCheckTx) GetFee() *common.KI64Pair { if m != nil { return m.Fee } - return common.KI64Pair{} + return nil } type ResponseDeliverTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` - GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` - Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` + Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"` + Fee *common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee,omitempty"` } func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } @@ -1455,6 +1463,13 @@ func (m *ResponseDeliverTx) GetTags() []common.KVPair { return nil } +func (m *ResponseDeliverTx) GetFee() *common.KI64Pair { + if m != nil { + return m.Fee + } + return nil +} + type ResponseEndBlock struct { ValidatorUpdates []Validator `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates"` ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"` @@ -2225,115 +2240,115 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1759 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xdd, 0x6e, 0x1b, 0xb9, - 0x15, 0xb6, 0xfe, 0x35, 0x47, 0xb6, 0x64, 0xd3, 0x4e, 0xa2, 0x68, 0x51, 0xc4, 0x18, 0x14, 0x59, - 0xa5, 0xc9, 0x5a, 0xad, 0xb7, 0x09, 0x92, 0x6c, 0xb1, 0x68, 0x64, 0xa7, 0x91, 0xb0, 0x6d, 0x37, - 0x9d, 0x64, 0x53, 0xa0, 0x37, 0x02, 0xa5, 0xa1, 0xa5, 0x41, 0x34, 0x3f, 0x3b, 0xa4, 0xbc, 0x72, - 0x9e, 0x61, 0xef, 0x7b, 0xdd, 0xab, 0x3e, 0x41, 0x5f, 0xa1, 0x68, 0xd1, 0x07, 0xe8, 0x9d, 0x2f, - 0x16, 0xbd, 0xea, 0x53, 0x14, 0x87, 0xe4, 0xfc, 0x7a, 0x66, 0xb1, 0x68, 0x81, 0xde, 0x48, 0x3c, - 0x3c, 0xdf, 0x21, 0x79, 0xc8, 0xc3, 0xef, 0x9c, 0x21, 0x1c, 0x88, 0xab, 0x80, 0xf1, 0x91, 0xfc, - 0x3d, 0x09, 0x42, 0x5f, 0xf8, 0xa4, 0x21, 0x85, 0xc1, 0x27, 0x4b, 0x47, 0xac, 0x36, 0xf3, 0x93, - 0x85, 0xef, 0x8e, 0x96, 0xfe, 0xd2, 0x1f, 0x49, 0xed, 0x7c, 0x73, 0x21, 0x25, 0x29, 0xc8, 0x96, - 0xb2, 0x1a, 0x8c, 0x52, 0x70, 0xc1, 0x3c, 0x9b, 0x85, 0xae, 0xe3, 0x89, 0x91, 0x70, 0xd7, 0xce, - 0x9c, 0x8f, 0x16, 0xbe, 0xeb, 0xfa, 0x5e, 0x7a, 0x1a, 0xf3, 0xaf, 0x75, 0x68, 0x59, 0xec, 0xeb, - 0x0d, 0xe3, 0x82, 0x0c, 0xa1, 0xce, 0x16, 0x2b, 0xbf, 0x5f, 0x3d, 0xae, 0x0c, 0x3b, 0xa7, 0xe4, - 0x44, 0xe1, 0xb4, 0xf6, 0xe5, 0x62, 0xe5, 0x4f, 0x76, 0x2c, 0x89, 0x20, 0x0f, 0xa1, 0x71, 0xb1, - 0xde, 0xf0, 0x55, 0xbf, 0x26, 0xa1, 0x87, 0x59, 0xe8, 0xaf, 0x50, 0x35, 0xd9, 0xb1, 0x14, 0x06, - 0x87, 0x75, 0xbc, 0x0b, 0xbf, 0x5f, 0x2f, 0x1a, 0x76, 0xea, 0x5d, 0xc8, 0x61, 0x11, 0x41, 0x9e, - 0x02, 0x70, 0x26, 0x66, 0x7e, 0x20, 0x1c, 0xdf, 0xeb, 0x37, 0x24, 0xfe, 0x4e, 0x16, 0xff, 0x86, - 0x89, 0x2f, 0xa5, 0x7a, 0xb2, 0x63, 0x19, 0x3c, 0x12, 0xd0, 0xd2, 0xf1, 0x1c, 0x31, 0x5b, 0xac, - 0xa8, 0xe3, 0xf5, 0x9b, 0x45, 0x96, 0x53, 0xcf, 0x11, 0x67, 0xa8, 0x46, 0x4b, 0x27, 0x12, 0xd0, - 0x95, 0xaf, 0x37, 0x2c, 0xbc, 0xea, 0xb7, 0x8a, 0x5c, 0xf9, 0x1d, 0xaa, 0xd0, 0x15, 0x89, 0x21, - 0x9f, 0x41, 0x67, 0xce, 0x96, 0x8e, 0x37, 0x9b, 0xaf, 0xfd, 0xc5, 0xfb, 0x7e, 0x5b, 0x9a, 0xf4, - 0xb3, 0x26, 0x63, 0x04, 0x8c, 0x51, 0x3f, 0xd9, 0xb1, 0x60, 0x1e, 0x4b, 0xe4, 0x14, 0xda, 0x8b, - 0x15, 0x5b, 0xbc, 0x9f, 0x89, 0x6d, 0xdf, 0x90, 0x96, 0xb7, 0xb2, 0x96, 0x67, 0xa8, 0x7d, 0xbb, - 0x9d, 0xec, 0x58, 0xad, 0x85, 0x6a, 0xa2, 0x5f, 0x36, 0x5b, 0x3b, 0x97, 0x2c, 0x44, 0xab, 0xc3, - 0x22, 0xbf, 0xce, 0x95, 0x5e, 0xda, 0x19, 0x76, 0x24, 0x90, 0xc7, 0x60, 0x30, 0xcf, 0xd6, 0x0b, - 0xed, 0x48, 0xc3, 0xdb, 0xb9, 0x13, 0xf5, 0xec, 0x68, 0x99, 0x6d, 0xa6, 0xdb, 0xe4, 0x04, 0x9a, - 0x18, 0x25, 0x8e, 0xe8, 0xef, 0x4a, 0x9b, 0xa3, 0xdc, 0x12, 0xa5, 0x6e, 0xb2, 0x63, 0x69, 0xd4, - 0xb8, 0x05, 0x8d, 0x4b, 0xba, 0xde, 0x30, 0xf3, 0x63, 0xe8, 0xa4, 0x22, 0x85, 0xf4, 0xa1, 0xe5, - 0x32, 0xce, 0xe9, 0x92, 0xf5, 0x2b, 0xc7, 0x95, 0xa1, 0x61, 0x45, 0xa2, 0xd9, 0x85, 0xdd, 0x74, - 0x9c, 0xa4, 0x0c, 0x31, 0x16, 0xd0, 0xf0, 0x92, 0x85, 0x1c, 0x03, 0x40, 0x1b, 0x6a, 0xd1, 0x7c, - 0x0e, 0xfb, 0xf9, 0x20, 0x20, 0xfb, 0x50, 0x7b, 0xcf, 0xae, 0x34, 0x12, 0x9b, 0xe4, 0x48, 0x2f, - 0x48, 0x46, 0xb1, 0x61, 0xe9, 0xd5, 0x85, 0xb1, 0x6d, 0x1c, 0x06, 0xe4, 0x09, 0xc0, 0x25, 0x5d, - 0x3b, 0x36, 0x15, 0x7e, 0xc8, 0xfb, 0x95, 0xe3, 0xda, 0xb0, 0x73, 0xba, 0xaf, 0xdd, 0x7d, 0x17, - 0x29, 0xc6, 0xf5, 0xbf, 0x5d, 0xdf, 0xdb, 0xb1, 0x52, 0x48, 0x72, 0x1f, 0x7a, 0x34, 0x08, 0x66, - 0x5c, 0x50, 0xc1, 0x66, 0xf3, 0x2b, 0xc1, 0xb8, 0x9c, 0x6b, 0xd7, 0xda, 0xa3, 0x41, 0xf0, 0x06, - 0x7b, 0xc7, 0xd8, 0x69, 0xda, 0xb1, 0xa3, 0x32, 0x8a, 0x08, 0x81, 0xba, 0x4d, 0x05, 0x95, 0x8b, - 0xdd, 0xb5, 0x64, 0x1b, 0xfb, 0x02, 0x2a, 0x56, 0x7a, 0xb1, 0xb2, 0x4d, 0x6e, 0x43, 0x73, 0xc5, - 0x9c, 0xe5, 0x4a, 0xc8, 0xdb, 0x55, 0xb3, 0xb4, 0x84, 0x9e, 0x05, 0xa1, 0x7f, 0xc9, 0xe4, 0x45, - 0x6a, 0x5b, 0x4a, 0x30, 0xff, 0x51, 0x81, 0x83, 0x1b, 0x91, 0x87, 0xe3, 0xae, 0x28, 0x5f, 0x45, - 0x73, 0x61, 0x9b, 0x3c, 0xc4, 0x71, 0xa9, 0xcd, 0x42, 0x7d, 0xc1, 0xf7, 0xb4, 0xaf, 0x13, 0xd9, - 0xa9, 0x1d, 0xd5, 0x10, 0xf2, 0x10, 0x0e, 0xe8, 0x9c, 0x33, 0x4f, 0xcc, 0x52, 0x7b, 0x54, 0x3b, - 0xae, 0x0d, 0x1b, 0xd6, 0xbe, 0x52, 0xbc, 0x4b, 0x76, 0x64, 0x02, 0x47, 0xf3, 0xab, 0x0f, 0xd4, - 0x13, 0x8e, 0xc7, 0xd2, 0xf8, 0xba, 0xdc, 0xd3, 0x9e, 0x9e, 0xe7, 0xe5, 0xa5, 0x63, 0x33, 0x6f, - 0xc1, 0xf4, 0x4c, 0x87, 0xb1, 0x49, 0x32, 0x92, 0x79, 0x0c, 0xdd, 0xec, 0x65, 0x20, 0x5d, 0xa8, - 0x8a, 0xad, 0xf6, 0xa3, 0x2a, 0xb6, 0xa6, 0x19, 0x9f, 0x64, 0x1c, 0xf8, 0x37, 0x30, 0x0f, 0xa0, - 0x97, 0x8b, 0xf1, 0xd4, 0xa6, 0x56, 0xd2, 0x9b, 0x6a, 0xf6, 0x60, 0x2f, 0x13, 0xda, 0xe6, 0xb7, - 0x0d, 0x68, 0x5b, 0x8c, 0x07, 0xbe, 0xc7, 0x19, 0x79, 0x0a, 0x06, 0xdb, 0x2e, 0x98, 0xe2, 0xa3, - 0x4a, 0xee, 0xb6, 0x2b, 0xcc, 0xcb, 0x48, 0x8f, 0xd7, 0x2f, 0x06, 0x93, 0x07, 0x19, 0x2e, 0x3d, - 0xcc, 0x1b, 0xa5, 0xc9, 0xf4, 0x51, 0x96, 0x4c, 0x8f, 0x72, 0xd8, 0x1c, 0x9b, 0x3e, 0xc8, 0xb0, - 0x69, 0x7e, 0xe0, 0x0c, 0x9d, 0x3e, 0x2b, 0xa0, 0xd3, 0xfc, 0xf2, 0x4b, 0xf8, 0xf4, 0x59, 0x01, - 0x9f, 0xf6, 0x6f, 0xcc, 0x55, 0x48, 0xa8, 0x8f, 0xb2, 0x84, 0x9a, 0x77, 0x27, 0xc7, 0xa8, 0xbf, - 0x28, 0x62, 0xd4, 0xbb, 0x39, 0x9b, 0x52, 0x4a, 0xfd, 0xf4, 0x06, 0xa5, 0xde, 0xce, 0x99, 0x16, - 0x70, 0xea, 0xb3, 0x0c, 0xa7, 0x42, 0xa1, 0x6f, 0x25, 0xa4, 0xfa, 0xe4, 0x26, 0xa9, 0xde, 0xc9, - 0x1f, 0x6d, 0x11, 0xab, 0x8e, 0x72, 0xac, 0x7a, 0x2b, 0xbf, 0xca, 0x52, 0x5a, 0x7d, 0x80, 0xb7, - 0x3b, 0x17, 0x69, 0xc8, 0x04, 0x2c, 0x0c, 0xfd, 0x50, 0xf3, 0x9e, 0x12, 0xcc, 0x21, 0xf2, 0x4d, - 0x12, 0x5f, 0xdf, 0x43, 0xc1, 0x32, 0xe8, 0x53, 0xd1, 0x65, 0xfe, 0xb1, 0x92, 0xd8, 0x4a, 0x16, - 0x4e, 0x73, 0x95, 0xa1, 0xb9, 0x2a, 0xc5, 0xcc, 0xd5, 0x0c, 0x33, 0x93, 0x9f, 0xc0, 0xc1, 0x9a, - 0x72, 0xa1, 0xf6, 0x65, 0x96, 0x21, 0xaf, 0x1e, 0x2a, 0xd4, 0x86, 0x28, 0x16, 0xfb, 0x04, 0x0e, - 0x53, 0x58, 0x24, 0x52, 0x49, 0x54, 0x75, 0x79, 0x79, 0xf7, 0x63, 0xf4, 0x8b, 0x20, 0x98, 0x50, - 0xbe, 0x32, 0x7f, 0x93, 0xf8, 0x9f, 0xb0, 0x3e, 0x81, 0xfa, 0xc2, 0xb7, 0x95, 0x5b, 0x7b, 0x96, - 0x6c, 0x63, 0x26, 0x58, 0xfb, 0x4b, 0x39, 0xab, 0x61, 0x61, 0x13, 0x51, 0xf1, 0x4d, 0x31, 0xd4, - 0x95, 0x30, 0x0f, 0x93, 0xe1, 0xe2, 0xf0, 0x35, 0xff, 0x52, 0x49, 0xf6, 0x23, 0xa6, 0xea, 0xff, - 0x6e, 0x02, 0x3c, 0x1a, 0xc7, 0xb3, 0xd9, 0x56, 0x5e, 0xb7, 0x9a, 0xa5, 0x84, 0x28, 0x4d, 0x35, - 0xa5, 0x93, 0xd9, 0x34, 0xd5, 0x92, 0x7d, 0x4a, 0xd0, 0x14, 0xef, 0x5f, 0xc8, 0x7b, 0xb0, 0x6b, - 0x29, 0x21, 0xc5, 0x5d, 0x46, 0x86, 0xbb, 0x8e, 0x80, 0xdc, 0xbc, 0x21, 0xe6, 0xbf, 0x2a, 0xc8, - 0x7e, 0x99, 0xe8, 0x2f, 0xf4, 0x27, 0x3a, 0xe2, 0x6a, 0x2a, 0x1d, 0xfd, 0x30, 0x1f, 0x7f, 0x04, - 0xb0, 0xa4, 0x7c, 0xf6, 0x0d, 0xf5, 0x04, 0xb3, 0xb5, 0xa3, 0xc6, 0x92, 0xf2, 0xdf, 0xcb, 0x0e, - 0xf2, 0x1c, 0xea, 0x82, 0x2e, 0x79, 0xbf, 0x25, 0xd9, 0xbf, 0x7b, 0xa2, 0xaa, 0xce, 0x93, 0x2f, - 0xde, 0xbd, 0xa6, 0x4e, 0x38, 0xbe, 0x8d, 0xe4, 0xff, 0xef, 0xeb, 0x7b, 0x5d, 0xc4, 0x3c, 0xf2, - 0x5d, 0x47, 0x30, 0x37, 0x10, 0x57, 0x96, 0xb4, 0x21, 0x43, 0xa8, 0x5d, 0x30, 0xa6, 0x69, 0x60, - 0x3f, 0x36, 0x9d, 0x3e, 0xf9, 0xb9, 0x34, 0x56, 0x99, 0x03, 0x21, 0xe6, 0x3f, 0x2b, 0xc9, 0x51, - 0x26, 0x99, 0xe0, 0xff, 0xea, 0xe8, 0x5d, 0x68, 0xa3, 0x7a, 0xc3, 0x99, 0x2d, 0x8f, 0xb6, 0x66, - 0xb5, 0x96, 0x94, 0x7f, 0xc5, 0xff, 0xb7, 0x3d, 0x30, 0xff, 0x5c, 0xc1, 0x14, 0x97, 0x65, 0x13, - 0x72, 0x06, 0x07, 0x71, 0x62, 0x9d, 0x6d, 0x02, 0x9b, 0x62, 0xd9, 0xf1, 0xfd, 0x35, 0xcb, 0x7e, - 0x6c, 0xf0, 0x95, 0xc2, 0x93, 0xdf, 0xc2, 0x9d, 0x05, 0x8e, 0xea, 0xf1, 0x0d, 0x9f, 0x05, 0x34, - 0xa4, 0x6e, 0x3c, 0x54, 0x35, 0xc3, 0x9e, 0x67, 0x11, 0xea, 0x35, 0x82, 0xb8, 0x75, 0x6b, 0x91, - 0xe9, 0xd0, 0xe3, 0x99, 0x3f, 0xc6, 0x6c, 0x9d, 0x66, 0xb0, 0xa2, 0xbd, 0x36, 0xff, 0x54, 0x81, - 0x5e, 0x6e, 0x40, 0x32, 0x02, 0x50, 0x04, 0xc0, 0x9d, 0x0f, 0x4c, 0x67, 0xd6, 0xc8, 0x0f, 0xe9, - 0xf0, 0x1b, 0xe7, 0x03, 0xb3, 0x8c, 0x79, 0xd4, 0x24, 0xf7, 0xa1, 0x25, 0xb6, 0x0a, 0x9d, 0xad, - 0x5e, 0xde, 0x6e, 0x25, 0xb4, 0x29, 0xe4, 0x3f, 0x79, 0x0c, 0xbb, 0x6a, 0xe0, 0xa5, 0xcf, 0xb9, - 0x13, 0xe8, 0x9c, 0x4a, 0xd2, 0x43, 0xbf, 0x92, 0x1a, 0xab, 0x33, 0x4f, 0x04, 0xf3, 0x0f, 0x60, - 0xc4, 0xd3, 0x92, 0x8f, 0xc0, 0x70, 0xe9, 0x56, 0x97, 0x76, 0xb8, 0xb6, 0x86, 0xd5, 0x76, 0xe9, - 0x56, 0x56, 0x75, 0xe4, 0x0e, 0xb4, 0x50, 0x29, 0xb6, 0x6a, 0xcf, 0x1a, 0x56, 0xd3, 0xa5, 0xdb, - 0xb7, 0xdb, 0x58, 0xb1, 0xa4, 0x3c, 0xaa, 0xdb, 0x5c, 0xba, 0x7d, 0x45, 0xb9, 0xf9, 0x39, 0x34, - 0xd5, 0x22, 0x7f, 0xd0, 0xc0, 0x68, 0x5f, 0xcd, 0xd8, 0xff, 0x12, 0x3a, 0xa9, 0x75, 0x93, 0x9f, - 0xc1, 0x2d, 0xe5, 0x61, 0x40, 0x43, 0x21, 0x77, 0x24, 0x33, 0x20, 0x91, 0xca, 0xd7, 0x34, 0x14, - 0x38, 0xa5, 0xaa, 0x44, 0xff, 0x5e, 0x85, 0xa6, 0xaa, 0xf2, 0xc8, 0x7d, 0xcc, 0x98, 0xd4, 0xf1, - 0x66, 0x8e, 0xad, 0xc8, 0x7d, 0xdc, 0xf9, 0xee, 0xfa, 0x5e, 0x4b, 0x12, 0xe1, 0xf4, 0x1c, 0x93, - 0x24, 0x36, 0xec, 0x14, 0xe7, 0x54, 0x33, 0x45, 0x28, 0x81, 0xba, 0x70, 0x5c, 0xa6, 0x5d, 0x94, - 0x6d, 0x5c, 0xb9, 0xb7, 0x71, 0xe5, 0x96, 0xd4, 0xd5, 0x96, 0x78, 0x1b, 0x17, 0xb7, 0xe4, 0x15, - 0xec, 0xa5, 0xb8, 0xde, 0xb1, 0x75, 0x0d, 0xd2, 0x4d, 0x9f, 0xc6, 0xf4, 0x7c, 0x7c, 0x88, 0xe1, - 0xfa, 0xdd, 0xf5, 0xbd, 0xce, 0xaf, 0x23, 0xf6, 0x9f, 0x9e, 0x5b, 0x9d, 0x38, 0x15, 0x4c, 0x6d, - 0x32, 0x04, 0x99, 0x19, 0x66, 0x2a, 0x3b, 0xaa, 0x8c, 0xa1, 0xc8, 0xb4, 0x8b, 0xfd, 0x3a, 0x7d, - 0x62, 0x91, 0xfb, 0x11, 0x18, 0x18, 0x74, 0x0a, 0xa2, 0xb8, 0xb5, 0x8d, 0x1d, 0x52, 0xf9, 0x31, - 0xf4, 0x92, 0xea, 0x54, 0x41, 0x14, 0xd1, 0x76, 0x93, 0x6e, 0x09, 0xbc, 0x0b, 0xed, 0x38, 0x33, - 0x19, 0x12, 0xd1, 0xa2, 0x3a, 0x21, 0x7d, 0x09, 0x2d, 0xbd, 0xc4, 0xc2, 0x22, 0xfb, 0xa7, 0xd0, - 0xc0, 0x73, 0x89, 0x2e, 0x54, 0x54, 0xfd, 0xc8, 0xf3, 0x60, 0x22, 0x53, 0x6a, 0x2b, 0xa0, 0xf9, - 0x0c, 0xf6, 0x32, 0x5a, 0x4c, 0x02, 0xc2, 0x17, 0x74, 0xad, 0x0f, 0x54, 0x09, 0xf1, 0x64, 0xd5, - 0x64, 0x32, 0xf3, 0x39, 0x18, 0xf1, 0xa5, 0xc7, 0x53, 0x08, 0x36, 0xf3, 0x59, 0xf4, 0x39, 0xb4, - 0x6b, 0x35, 0x83, 0xcd, 0xfc, 0x0b, 0x95, 0x6a, 0x02, 0xff, 0x1b, 0x5d, 0xf6, 0xd7, 0x2c, 0x25, - 0x98, 0x9f, 0x41, 0x3b, 0x2a, 0xc8, 0xcb, 0x4d, 0x4b, 0xa2, 0xe0, 0xf4, 0xdb, 0x06, 0xf4, 0x5e, - 0x8c, 0xcf, 0xa6, 0x2f, 0x82, 0x60, 0xed, 0x2c, 0xa8, 0x4c, 0xca, 0x23, 0xa8, 0xcb, 0xb2, 0xa3, - 0xe0, 0xdd, 0x60, 0x50, 0x54, 0xff, 0x92, 0x53, 0x68, 0xc8, 0xea, 0x83, 0x14, 0x3d, 0x1f, 0x0c, - 0x0a, 0xcb, 0x60, 0x9c, 0x44, 0xd5, 0x27, 0x37, 0x5f, 0x11, 0x06, 0x45, 0xb5, 0x30, 0xf9, 0x1c, - 0x8c, 0xa4, 0x6e, 0x28, 0x7b, 0x4b, 0x18, 0x94, 0x56, 0xc5, 0x68, 0x9f, 0x64, 0x97, 0xb2, 0x2f, - 0xef, 0x41, 0x69, 0xf9, 0x48, 0x9e, 0x42, 0x2b, 0x4a, 0xc2, 0xc5, 0x5f, 0xfb, 0x83, 0x92, 0x8a, - 0x15, 0xb7, 0x47, 0x15, 0x23, 0x45, 0x4f, 0x12, 0x83, 0xc2, 0xb2, 0x9a, 0x3c, 0x86, 0xa6, 0x26, - 0xe2, 0xc2, 0xef, 0xf6, 0x41, 0x71, 0xdd, 0x89, 0x4e, 0x26, 0x9f, 0xc5, 0x65, 0xcf, 0x26, 0x83, - 0xd2, 0xfa, 0x9f, 0xbc, 0x00, 0x48, 0x7d, 0x7b, 0x96, 0xbe, 0x87, 0x0c, 0xca, 0xeb, 0x7a, 0x82, - 0xe1, 0x18, 0x7f, 0xab, 0x15, 0xbf, 0x53, 0x0c, 0xca, 0x4a, 0xed, 0x79, 0x53, 0xbe, 0x65, 0x7d, - 0xfa, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x11, 0xd7, 0x9f, 0xcd, 0x47, 0x13, 0x00, 0x00, + // 1756 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6e, 0x1b, 0xc9, + 0x11, 0x16, 0xff, 0x39, 0x45, 0x89, 0x94, 0x5a, 0xb2, 0x4d, 0x73, 0x11, 0x58, 0x18, 0x04, 0x5e, + 0x39, 0xf6, 0x8a, 0x89, 0x36, 0x36, 0x2c, 0x6f, 0xb0, 0x88, 0x28, 0x39, 0x26, 0xb1, 0x49, 0xd6, + 0x19, 0x7b, 0x1d, 0x20, 0x17, 0xa2, 0xc9, 0x69, 0x91, 0x03, 0x73, 0x7e, 0x76, 0xba, 0xa9, 0xa5, + 0xfc, 0x0c, 0x7b, 0xcf, 0x39, 0xa7, 0x3c, 0x41, 0x5e, 0x21, 0x48, 0x90, 0x77, 0xd0, 0x61, 0x8f, + 0x79, 0x83, 0x20, 0x97, 0xa0, 0xba, 0x7b, 0x7e, 0x35, 0xb3, 0x58, 0xe4, 0xba, 0x17, 0xb2, 0xab, + 0xeb, 0xab, 0xee, 0xae, 0xee, 0xea, 0xaf, 0x6a, 0x1a, 0xf6, 0xc4, 0x75, 0xc0, 0xf8, 0x50, 0xfe, + 0x1e, 0x07, 0xa1, 0x2f, 0x7c, 0xd2, 0x90, 0xc2, 0xe0, 0x93, 0x85, 0x23, 0x96, 0xeb, 0xd9, 0xf1, + 0xdc, 0x77, 0x87, 0x0b, 0x7f, 0xe1, 0x0f, 0xa5, 0x76, 0xb6, 0xbe, 0x94, 0x92, 0x14, 0x64, 0x4b, + 0x59, 0x0d, 0x86, 0x29, 0xb8, 0x60, 0x9e, 0xcd, 0x42, 0xd7, 0xf1, 0xc4, 0x50, 0xb8, 0x2b, 0x67, + 0xc6, 0x87, 0x73, 0xdf, 0x75, 0x7d, 0x2f, 0x3d, 0x8d, 0xf9, 0xf7, 0x3a, 0xb4, 0x2c, 0xf6, 0xf5, + 0x9a, 0x71, 0x41, 0x8e, 0xa0, 0xce, 0xe6, 0x4b, 0xbf, 0x5f, 0x3d, 0xac, 0x1c, 0x75, 0x4e, 0xc8, + 0xb1, 0xc2, 0x69, 0xed, 0xcb, 0xf9, 0xd2, 0x1f, 0x6f, 0x59, 0x12, 0x41, 0x1e, 0x43, 0xe3, 0x72, + 0xb5, 0xe6, 0xcb, 0x7e, 0x4d, 0x42, 0xf7, 0xb3, 0xd0, 0xdf, 0xa0, 0x6a, 0xbc, 0x65, 0x29, 0x0c, + 0x0e, 0xeb, 0x78, 0x97, 0x7e, 0xbf, 0x5e, 0x34, 0xec, 0xc4, 0xbb, 0x94, 0xc3, 0x22, 0x82, 0x3c, + 0x07, 0xe0, 0x4c, 0x4c, 0xfd, 0x40, 0x38, 0xbe, 0xd7, 0x6f, 0x48, 0xfc, 0xbd, 0x2c, 0xfe, 0x0d, + 0x13, 0x5f, 0x4a, 0xf5, 0x78, 0xcb, 0x32, 0x78, 0x24, 0xa0, 0xa5, 0xe3, 0x39, 0x62, 0x3a, 0x5f, + 0x52, 0xc7, 0xeb, 0x37, 0x8b, 0x2c, 0x27, 0x9e, 0x23, 0xce, 0x51, 0x8d, 0x96, 0x4e, 0x24, 0xa0, + 0x2b, 0x5f, 0xaf, 0x59, 0x78, 0xdd, 0x6f, 0x15, 0xb9, 0xf2, 0x07, 0x54, 0xa1, 0x2b, 0x12, 0x43, + 0x3e, 0x83, 0xce, 0x8c, 0x2d, 0x1c, 0x6f, 0x3a, 0x5b, 0xf9, 0xf3, 0xf7, 0xfd, 0xb6, 0x34, 0xe9, + 0x67, 0x4d, 0x46, 0x08, 0x18, 0xa1, 0x7e, 0xbc, 0x65, 0xc1, 0x2c, 0x96, 0xc8, 0x09, 0xb4, 0xe7, + 0x4b, 0x36, 0x7f, 0x3f, 0x15, 0x9b, 0xbe, 0x21, 0x2d, 0xef, 0x64, 0x2d, 0xcf, 0x51, 0xfb, 0x76, + 0x33, 0xde, 0xb2, 0x5a, 0x73, 0xd5, 0x44, 0xbf, 0x6c, 0xb6, 0x72, 0xae, 0x58, 0x88, 0x56, 0xfb, + 0x45, 0x7e, 0x5d, 0x28, 0xbd, 0xb4, 0x33, 0xec, 0x48, 0x20, 0x4f, 0xc1, 0x60, 0x9e, 0xad, 0x17, + 0xda, 0x91, 0x86, 0x77, 0x73, 0x27, 0xea, 0xd9, 0xd1, 0x32, 0xdb, 0x4c, 0xb7, 0xc9, 0x31, 0x34, + 0x31, 0x4a, 0x1c, 0xd1, 0xdf, 0x96, 0x36, 0x07, 0xb9, 0x25, 0x4a, 0xdd, 0x78, 0xcb, 0xd2, 0xa8, + 0x51, 0x0b, 0x1a, 0x57, 0x74, 0xb5, 0x66, 0xe6, 0xc7, 0xd0, 0x49, 0x45, 0x0a, 0xe9, 0x43, 0xcb, + 0x65, 0x9c, 0xd3, 0x05, 0xeb, 0x57, 0x0e, 0x2b, 0x47, 0x86, 0x15, 0x89, 0x66, 0x17, 0xb6, 0xd3, + 0x71, 0x92, 0x32, 0xc4, 0x58, 0x40, 0xc3, 0x2b, 0x16, 0x72, 0x0c, 0x00, 0x6d, 0xa8, 0x45, 0xf3, + 0x05, 0xec, 0xe6, 0x83, 0x80, 0xec, 0x42, 0xed, 0x3d, 0xbb, 0xd6, 0x48, 0x6c, 0x92, 0x03, 0xbd, + 0x20, 0x19, 0xc5, 0x86, 0xa5, 0x57, 0x17, 0xc6, 0xb6, 0x71, 0x18, 0x90, 0x67, 0x00, 0x57, 0x74, + 0xe5, 0xd8, 0x54, 0xf8, 0x21, 0xef, 0x57, 0x0e, 0x6b, 0x47, 0x9d, 0x93, 0x5d, 0xed, 0xee, 0xbb, + 0x48, 0x31, 0xaa, 0xff, 0xe3, 0xe6, 0xc1, 0x96, 0x95, 0x42, 0x92, 0x87, 0xd0, 0xa3, 0x41, 0x30, + 0xe5, 0x82, 0x0a, 0x36, 0x9d, 0x5d, 0x0b, 0xc6, 0xe5, 0x5c, 0xdb, 0xd6, 0x0e, 0x0d, 0x82, 0x37, + 0xd8, 0x3b, 0xc2, 0x4e, 0xd3, 0x8e, 0x1d, 0x95, 0x51, 0x44, 0x08, 0xd4, 0x6d, 0x2a, 0xa8, 0x5c, + 0xec, 0xb6, 0x25, 0xdb, 0xd8, 0x17, 0x50, 0xb1, 0xd4, 0x8b, 0x95, 0x6d, 0x72, 0x17, 0x9a, 0x4b, + 0xe6, 0x2c, 0x96, 0x42, 0xde, 0xae, 0x9a, 0xa5, 0x25, 0xf4, 0x2c, 0x08, 0xfd, 0x2b, 0x26, 0x2f, + 0x52, 0xdb, 0x52, 0x82, 0xf9, 0xaf, 0x0a, 0xec, 0xdd, 0x8a, 0x3c, 0x1c, 0x77, 0x49, 0xf9, 0x32, + 0x9a, 0x0b, 0xdb, 0xe4, 0x31, 0x8e, 0x4b, 0x6d, 0x16, 0xea, 0x0b, 0xbe, 0xa3, 0x7d, 0x1d, 0xcb, + 0x4e, 0xed, 0xa8, 0x86, 0x90, 0xc7, 0xb0, 0x47, 0x67, 0x9c, 0x79, 0x62, 0x9a, 0xda, 0xa3, 0xda, + 0x61, 0xed, 0xa8, 0x61, 0xed, 0x2a, 0xc5, 0xbb, 0x64, 0x47, 0xc6, 0x70, 0x30, 0xbb, 0xfe, 0x40, + 0x3d, 0xe1, 0x78, 0x2c, 0x8d, 0xaf, 0xcb, 0x3d, 0xed, 0xe9, 0x79, 0x5e, 0x5e, 0x39, 0x36, 0xf3, + 0xe6, 0x4c, 0xcf, 0xb4, 0x1f, 0x9b, 0x24, 0x23, 0x99, 0x87, 0xd0, 0xcd, 0x5e, 0x06, 0xd2, 0x85, + 0xaa, 0xd8, 0x68, 0x3f, 0xaa, 0x62, 0x63, 0x9a, 0xf1, 0x49, 0xc6, 0x81, 0x7f, 0x0b, 0xf3, 0x08, + 0x7a, 0xb9, 0x18, 0x4f, 0x6d, 0x6a, 0x25, 0xbd, 0xa9, 0x66, 0x0f, 0x76, 0x32, 0xa1, 0x6d, 0x7e, + 0xdb, 0x80, 0xb6, 0xc5, 0x78, 0xe0, 0x7b, 0x9c, 0x91, 0xe7, 0x60, 0xb0, 0xcd, 0x9c, 0x29, 0x3e, + 0xaa, 0xe4, 0x6e, 0xbb, 0xc2, 0xbc, 0x8c, 0xf4, 0x78, 0xfd, 0x62, 0x30, 0x79, 0x94, 0xe1, 0xd2, + 0xfd, 0xbc, 0x51, 0x9a, 0x4c, 0x9f, 0x64, 0xc9, 0xf4, 0x20, 0x87, 0xcd, 0xb1, 0xe9, 0xa3, 0x0c, + 0x9b, 0xe6, 0x07, 0xce, 0xd0, 0xe9, 0x69, 0x01, 0x9d, 0xe6, 0x97, 0x5f, 0xc2, 0xa7, 0xa7, 0x05, + 0x7c, 0xda, 0xbf, 0x35, 0x57, 0x21, 0xa1, 0x3e, 0xc9, 0x12, 0x6a, 0xde, 0x9d, 0x1c, 0xa3, 0xfe, + 0xaa, 0x88, 0x51, 0xef, 0xe7, 0x6c, 0x4a, 0x29, 0xf5, 0xd3, 0x5b, 0x94, 0x7a, 0x37, 0x67, 0x5a, + 0xc0, 0xa9, 0xa7, 0x19, 0x4e, 0x85, 0x42, 0xdf, 0x4a, 0x48, 0xf5, 0xd9, 0x6d, 0x52, 0xbd, 0x97, + 0x3f, 0xda, 0x22, 0x56, 0x1d, 0xe6, 0x58, 0xf5, 0x4e, 0x7e, 0x95, 0xa5, 0xb4, 0xfa, 0x08, 0x6f, + 0x77, 0x2e, 0xd2, 0x90, 0x09, 0x58, 0x18, 0xfa, 0xa1, 0xe6, 0x3d, 0x25, 0x98, 0x47, 0xc8, 0x37, + 0x49, 0x7c, 0x7d, 0x0f, 0x05, 0xcb, 0xa0, 0x4f, 0x45, 0x97, 0xf9, 0xe7, 0x4a, 0x62, 0x2b, 0x59, + 0x38, 0xcd, 0x55, 0x86, 0xe6, 0xaa, 0x14, 0x33, 0x57, 0x33, 0xcc, 0x4c, 0x7e, 0x06, 0x7b, 0x2b, + 0xca, 0x85, 0xda, 0x97, 0x69, 0x86, 0xbc, 0x7a, 0xa8, 0x50, 0x1b, 0xa2, 0x58, 0xec, 0x13, 0xd8, + 0x4f, 0x61, 0x91, 0x48, 0x25, 0x51, 0xd5, 0xe5, 0xe5, 0xdd, 0x8d, 0xd1, 0x67, 0x41, 0x30, 0xa6, + 0x7c, 0x69, 0xfe, 0x2e, 0xf1, 0x3f, 0x61, 0x7d, 0x02, 0xf5, 0xb9, 0x6f, 0x2b, 0xb7, 0x76, 0x2c, + 0xd9, 0xc6, 0x4c, 0xb0, 0xf2, 0x17, 0x72, 0x56, 0xc3, 0xc2, 0x26, 0xa2, 0xe2, 0x9b, 0x62, 0xa8, + 0x2b, 0x61, 0xee, 0x27, 0xc3, 0xc5, 0xe1, 0x6b, 0xfe, 0xad, 0x92, 0xec, 0x47, 0x4c, 0xd5, 0xff, + 0xdf, 0x04, 0x78, 0x34, 0x8e, 0x67, 0xb3, 0x8d, 0xbc, 0x6e, 0x35, 0x4b, 0x09, 0x51, 0x9a, 0x6a, + 0x4a, 0x27, 0xb3, 0x69, 0xaa, 0x25, 0xfb, 0x94, 0xa0, 0x29, 0xde, 0xbf, 0x94, 0xf7, 0x60, 0xdb, + 0x52, 0x42, 0x8a, 0xbb, 0x8c, 0x0c, 0x77, 0x1d, 0x00, 0xb9, 0x7d, 0x43, 0xcc, 0xff, 0x54, 0x90, + 0xfd, 0x32, 0xd1, 0x5f, 0xe8, 0x4f, 0x74, 0xc4, 0xd5, 0x54, 0x3a, 0xfa, 0x61, 0x3e, 0xfe, 0x04, + 0x60, 0x41, 0xf9, 0xf4, 0x1b, 0xea, 0x09, 0x66, 0x6b, 0x47, 0x8d, 0x05, 0xe5, 0x7f, 0x94, 0x1d, + 0xe4, 0x3e, 0xb4, 0x51, 0xbd, 0xe6, 0xcc, 0x96, 0x1e, 0xd7, 0xac, 0xd6, 0x82, 0xf2, 0xaf, 0x38, + 0xb3, 0xc9, 0x0b, 0xa8, 0x0b, 0xba, 0xe0, 0xfd, 0x96, 0x4c, 0x0c, 0xdd, 0x63, 0x55, 0x90, 0x1e, + 0x7f, 0xf1, 0xee, 0x35, 0x75, 0xc2, 0xd1, 0x5d, 0xcc, 0x0b, 0xff, 0xbe, 0x79, 0xd0, 0x45, 0xcc, + 0x13, 0xdf, 0x75, 0x04, 0x73, 0x03, 0x71, 0x6d, 0x49, 0x1b, 0x62, 0x42, 0xed, 0x92, 0x31, 0xcd, + 0x10, 0xbb, 0xb1, 0xe9, 0xe4, 0xd9, 0x2f, 0xd1, 0xd8, 0x42, 0xa5, 0xf9, 0xdf, 0x4a, 0x72, 0xbe, + 0x49, 0x7a, 0xf8, 0xb1, 0x78, 0xff, 0xd7, 0x0a, 0xe6, 0xc6, 0x2c, 0x0d, 0x91, 0x73, 0xd8, 0x8b, + 0x33, 0xf2, 0x74, 0x1d, 0xd8, 0x14, 0xeb, 0x95, 0xef, 0x2f, 0x76, 0x76, 0x63, 0x83, 0xaf, 0x14, + 0x9e, 0xfc, 0x1e, 0xee, 0xcd, 0x71, 0x54, 0x8f, 0xaf, 0xf9, 0x34, 0xa0, 0x21, 0x75, 0xe3, 0xa1, + 0xaa, 0x19, 0xda, 0x3d, 0x8f, 0x50, 0xaf, 0x11, 0xc4, 0xad, 0x3b, 0xf3, 0x4c, 0x87, 0x1e, 0xcf, + 0xfc, 0x29, 0xa6, 0xf9, 0x34, 0xf5, 0x15, 0x9d, 0x87, 0xf9, 0x97, 0x0a, 0xf4, 0x72, 0x03, 0x92, + 0x21, 0x80, 0x62, 0x0e, 0xee, 0x7c, 0x60, 0x3a, 0x25, 0x47, 0x7e, 0x48, 0x87, 0xdf, 0x38, 0x1f, + 0x98, 0x65, 0xcc, 0xa2, 0x26, 0x79, 0x08, 0x2d, 0xb1, 0x51, 0xe8, 0x6c, 0xd9, 0xf3, 0x76, 0x23, + 0xa1, 0x4d, 0x21, 0xff, 0xc9, 0x53, 0xd8, 0x56, 0x03, 0x2f, 0x7c, 0xce, 0x9d, 0x40, 0x27, 0x63, + 0x92, 0x1e, 0xfa, 0x95, 0xd4, 0x58, 0x9d, 0x59, 0x22, 0x98, 0x7f, 0x02, 0x23, 0x9e, 0x96, 0x7c, + 0x04, 0x86, 0x4b, 0x37, 0xba, 0x26, 0xc4, 0xb5, 0x35, 0xac, 0xb6, 0x4b, 0x37, 0xb2, 0x1c, 0x24, + 0xf7, 0xa0, 0x85, 0x4a, 0xb1, 0x51, 0x7b, 0xd6, 0xb0, 0x9a, 0x2e, 0xdd, 0xbc, 0xdd, 0xc4, 0x8a, + 0x05, 0xe5, 0x51, 0xc1, 0xe7, 0xd2, 0xcd, 0x2b, 0xca, 0xcd, 0xcf, 0xa1, 0xa9, 0x16, 0xf9, 0x83, + 0x06, 0x46, 0xfb, 0x6a, 0xc6, 0xfe, 0xd7, 0xd0, 0x49, 0xad, 0x9b, 0xfc, 0x02, 0xee, 0x28, 0x0f, + 0x03, 0x1a, 0x0a, 0xb9, 0x23, 0x99, 0x01, 0x89, 0x54, 0xbe, 0xa6, 0xa1, 0xc0, 0x29, 0x55, 0x09, + 0xfb, 0xcf, 0x2a, 0x34, 0x55, 0x79, 0x48, 0x1e, 0x62, 0xaa, 0xa5, 0x8e, 0x37, 0x75, 0x6c, 0x95, + 0x15, 0x46, 0x9d, 0xef, 0x6e, 0x1e, 0xb4, 0x24, 0x83, 0x4e, 0x2e, 0x30, 0xbb, 0x62, 0xc3, 0x4e, + 0x91, 0x55, 0x35, 0x53, 0xbd, 0x12, 0xa8, 0x0b, 0xc7, 0x65, 0xda, 0x45, 0xd9, 0xc6, 0x95, 0x7b, + 0x6b, 0x57, 0x6e, 0x49, 0x5d, 0x6d, 0x89, 0xb7, 0x76, 0x71, 0x4b, 0x5e, 0xc1, 0x4e, 0x2a, 0x49, + 0x38, 0xb6, 0x2e, 0x5e, 0xba, 0xe9, 0xd3, 0x98, 0x5c, 0x8c, 0xf6, 0x31, 0x5c, 0xbf, 0xbb, 0x79, + 0xd0, 0xf9, 0x6d, 0x94, 0x36, 0x26, 0x17, 0x56, 0x27, 0xce, 0x21, 0x13, 0x9b, 0x1c, 0x81, 0x4c, + 0x29, 0x53, 0x95, 0x56, 0x55, 0xaa, 0x51, 0x2c, 0xdc, 0xc5, 0x7e, 0x9d, 0x77, 0xb1, 0x3a, 0xfe, + 0x08, 0x0c, 0x0c, 0x3a, 0x05, 0x51, 0xa4, 0xdc, 0xc6, 0x0e, 0xa9, 0xfc, 0x18, 0x7a, 0x49, 0x59, + 0xab, 0x20, 0x8a, 0xa1, 0xbb, 0x49, 0xb7, 0x04, 0xde, 0x87, 0x76, 0x9c, 0xd2, 0x0c, 0x89, 0x68, + 0x51, 0x9d, 0xc9, 0xbe, 0x84, 0x96, 0x5e, 0x62, 0x61, 0x75, 0xfe, 0x73, 0x68, 0xe0, 0xb9, 0x44, + 0x17, 0x2a, 0x2a, 0x9b, 0xe4, 0x79, 0x30, 0x91, 0xa9, 0xd1, 0x15, 0xd0, 0x3c, 0x85, 0x9d, 0x8c, + 0x16, 0xb3, 0x87, 0xf0, 0x05, 0x5d, 0xe9, 0x03, 0x55, 0x42, 0x3c, 0x59, 0x35, 0x99, 0xcc, 0x7c, + 0x01, 0x46, 0x7c, 0xe9, 0xf1, 0x14, 0x82, 0xf5, 0x6c, 0x1a, 0x7d, 0x47, 0x6d, 0x5b, 0xcd, 0x60, + 0x3d, 0xfb, 0x42, 0xe5, 0xa8, 0xc0, 0xff, 0x46, 0x7f, 0x2f, 0xd4, 0x2c, 0x25, 0x98, 0x9f, 0x41, + 0x3b, 0xaa, 0xe4, 0xcb, 0x4d, 0x4b, 0xa2, 0xe0, 0xe4, 0xdb, 0x06, 0xf4, 0xce, 0x46, 0xe7, 0x93, + 0xb3, 0x20, 0x58, 0x39, 0x73, 0x2a, 0xb3, 0xf9, 0x10, 0xea, 0xb2, 0x5e, 0x29, 0x78, 0x70, 0x18, + 0x14, 0x15, 0xce, 0xe4, 0x04, 0x1a, 0xb2, 0x6c, 0x21, 0x45, 0xef, 0x0e, 0x83, 0xc2, 0xfa, 0x19, + 0x27, 0x51, 0x85, 0xcd, 0xed, 0xe7, 0x87, 0x41, 0x51, 0x11, 0x4d, 0x3e, 0x07, 0x23, 0x29, 0x38, + 0xca, 0x1e, 0x21, 0x06, 0xa5, 0xe5, 0x34, 0xda, 0x27, 0x19, 0xa8, 0xec, 0x93, 0x7d, 0x50, 0x5a, + 0x77, 0x92, 0xe7, 0xd0, 0x8a, 0xb2, 0x77, 0xf1, 0x33, 0xc1, 0xa0, 0xa4, 0xd4, 0xc5, 0xed, 0x51, + 0x55, 0x4c, 0xd1, 0x5b, 0xc6, 0xa0, 0xb0, 0x1e, 0x27, 0x4f, 0xa1, 0xa9, 0x89, 0xb8, 0xf0, 0x83, + 0x7f, 0x50, 0x5c, 0xb0, 0xa2, 0x93, 0xc9, 0xf7, 0x74, 0xd9, 0x7b, 0xcb, 0xa0, 0xf4, 0xc3, 0x81, + 0x9c, 0x01, 0xa4, 0x3e, 0x5a, 0x4b, 0x1f, 0x52, 0x06, 0xe5, 0x1f, 0x04, 0x04, 0xc3, 0x31, 0xfe, + 0xc8, 0x2b, 0x7e, 0xe0, 0x18, 0x94, 0xd5, 0xe8, 0xb3, 0xa6, 0x7c, 0x04, 0xfb, 0xf4, 0x7f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x78, 0xcf, 0xcd, 0xb3, 0x80, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index ba8a23cfe..9e9e4fbba 100644 --- a/types/types.proto +++ b/types/types.proto @@ -151,9 +151,9 @@ message ResponseCheckTx { string log = 3; // nondeterministic string info = 4; // nondeterministic int64 gas_wanted = 5; - // int64 gas_used = 6; + int64 gas_used = 6; repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"]; - common.KI64Pair fee = 8 [(gogoproto.nullable)=false]; + common.KI64Pair fee = 8 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"]; } message ResponseDeliverTx { @@ -164,7 +164,7 @@ message ResponseDeliverTx { int64 gas_wanted = 5; int64 gas_used = 6; repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"]; - // common.KI64Pair fee = 8; + common.KI64Pair fee = 8 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"]; } message ResponseEndBlock { diff --git a/version/version.go b/version/version.go index 4f7beb499..467cd9e43 100644 --- a/version/version.go +++ b/version/version.go @@ -4,6 +4,6 @@ package version const Maj = "0" const Min = "10" -const Fix = "0" +const Fix = "1" -const Version = "0.10.0" +const Version = "0.10.1"