diff --git a/.editorconfig b/.editorconfig index d587999e1..82f774362 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,3 +13,7 @@ indent_style = tab [*.sh] indent_style = tab + +[*.proto] +indent_style = space +indent_size = 2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cd5046c0..44db318bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.8.0 (TBD) + +BREAKING CHANGES: + - [client] all XxxSync methods now return (ResponseXxx, error) + - [types] Application: all methods now take RequestXxx and return (ResponseXxx, error). + - Except `CheckTx`/`DeliverTx`, which takes a `tx []byte` argument. + - Except `Commit`, which takes no arguments. + - [types] removed Result + +FEATURES: + - [types] added Tags field to ResponseDeliverTx + - [types] added Gas and Fee fields to ResponseCheckTx + ## 0.7.1 (November 14, 2017) IMPROVEMENTS: diff --git a/Dockerfile.develop b/Dockerfile.develop new file mode 100644 index 000000000..d4643155a --- /dev/null +++ b/Dockerfile.develop @@ -0,0 +1,21 @@ +FROM golang:latest + +RUN mkdir -p /go/src/github.com/tendermint/abci +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 + +# 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/ + +RUN make get_vendor_deps + +COPY . /go/src/github.com/tendermint/abci diff --git a/Makefile b/Makefile index 6c99e3639..11a75664a 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,29 @@ GOTOOLS = \ github.com/mitchellh/gox \ github.com/Masterminds/glide \ - github.com/alecthomas/gometalinter + github.com/alecthomas/gometalinter \ + github.com/ckaznocha/protoc-gen-lint -all: protoc install test +all: install test PACKAGES=$(shell go list ./... | grep -v '/vendor/') -install-protoc: - # Download: https://github.com/google/protobuf/releases +install_protoc: + # https://github.com/google/protobuf/releases + curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ + cd protobuf-3.4.1 && \ + DIST_LANG=cpp ./configure && \ + make && \ + make install && \ + cd .. && \ + rm -rf protobuf-3.4.1 go get github.com/golang/protobuf/protoc-gen-go protoc: - @ protoc --go_out=plugins=grpc:. types/*.proto + ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" + ## ldconfig (may require sudo) + ## https://stackoverflow.com/a/25518702 + protoc --go_out=plugins=grpc:. types/*.proto install: @ go install ./cmd/... @@ -24,17 +35,22 @@ dist: @ bash scripts/dist.sh @ bash scripts/publish.sh -# test.sh requires that we run the installed cmds, must not be out of date -test: install - find . -path ./vendor -prune -o -name *.sock -exec rm {} \; +test: + @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @ echo "==> Running go test" @ go test $(PACKAGES) - @ bash tests/test.sh + +test_race: + @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @ echo "==> Running go test --race" + @go test -v -race $(PACKAGES) + +test_integrations: + @ bash test.sh fmt: @ go fmt ./... -test_integrations: get_vendor_deps install test - get_deps: @ go get -d $(PACKAGES) @@ -47,10 +63,12 @@ get_vendor_deps: metalinter: tools @gometalinter --install + protoc --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... metalinter_test: tools @gometalinter --install + # protoc --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ @@ -79,4 +97,10 @@ metalinter_test: tools #--enable=unparam \ #--enable=vet \ -.PHONY: all build test fmt get_deps tools +build-docker: + docker build -t "tendermint/abci-dev" -f Dockerfile.develop . + +run-docker: + docker run -it --rm -v "$PWD:/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash + +.PHONY: all build test fmt get_deps tools protoc install_protoc build-docker run-docker diff --git a/README.md b/README.md index aedebee60..f2546c004 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ Here, we describe the requests and responses as function arguments and return va * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message + * `Tags ([]*KVPair)`: Optional tags for indexing * __Usage__:
Append and run a transaction. If the transaction is valid, returns CodeType.OK @@ -101,6 +102,8 @@ Here, we describe the requests and responses as function arguments and return va * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message + * `Gas (uint64)`: Amount of gas consumed by transaction + * `Fee (uint64)`: Fee paid by 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. diff --git a/circle.yml b/circle.yml index daa4218e0..c6904fae6 100644 --- a/circle.yml +++ b/circle.yml @@ -12,11 +12,11 @@ checkout: - rm -rf $REPO - mkdir -p $HOME/.go_workspace/src/github.com/$CIRCLE_PROJECT_USERNAME - mv $HOME/$CIRCLE_PROJECT_REPONAME $REPO - # - git submodule sync - # - git submodule update --init # use submodules + - go version test: override: - - "go version" - - "cd $REPO && make get_vendor_deps && make metalinter_test" - - "cd $REPO && make test_integrations" + - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations + post: + - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt + - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" diff --git a/client/client.go b/client/client.go index 51d04124b..ddb589a40 100644 --- a/client/client.go +++ b/client/client.go @@ -8,6 +8,11 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +// Client defines an interface for an ABCI client. +// All `Async` methods return a `ReqRes` object. +// All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error. +// Note these are client errors, eg. ABCI socket connectivity issues. +// Application-related errors are reflected in response via ABCI error codes and logs. type Client interface { cmn.Service @@ -17,28 +22,26 @@ type Client interface { FlushAsync() *ReqRes EchoAsync(msg string) *ReqRes InfoAsync(types.RequestInfo) *ReqRes - SetOptionAsync(key string, value string) *ReqRes + SetOptionAsync(types.RequestSetOption) *ReqRes DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes QueryAsync(types.RequestQuery) *ReqRes CommitAsync() *ReqRes - - FlushSync() error - EchoSync(msg string) (res types.Result) - InfoSync(types.RequestInfo) (resInfo types.ResponseInfo, err error) - SetOptionSync(key string, value string) (res types.Result) - DeliverTxSync(tx []byte) (res types.Result) - CheckTxSync(tx []byte) (res types.Result) - QuerySync(types.RequestQuery) (resQuery types.ResponseQuery, err error) - CommitSync() (res types.Result) - InitChainAsync(types.RequestInitChain) *ReqRes BeginBlockAsync(types.RequestBeginBlock) *ReqRes - EndBlockAsync(height uint64) *ReqRes + EndBlockAsync(types.RequestEndBlock) *ReqRes - InitChainSync(types.RequestInitChain) (err error) - BeginBlockSync(types.RequestBeginBlock) (err error) - EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) + FlushSync() error + EchoSync(msg string) (*types.ResponseEcho, error) + InfoSync(types.RequestInfo) (*types.ResponseInfo, error) + SetOptionSync(types.RequestSetOption) (*types.ResponseSetOption, error) + DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) + CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) + QuerySync(types.RequestQuery) (*types.ResponseQuery, error) + CommitSync() (*types.ResponseCommit, error) + InitChainSync(types.RequestInitChain) (*types.ResponseInitChain, error) + BeginBlockSync(types.RequestBeginBlock) (*types.ResponseBeginBlock, error) + EndBlockSync(types.RequestEndBlock) (*types.ResponseEndBlock, error) } //---------------------------------------- diff --git a/client/grpc_client.go b/client/grpc_client.go index 30f5d088a..6079c90ce 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "github.com/pkg/errors" context "golang.org/x/net/context" grpc "google.golang.org/grpc" @@ -13,6 +14,8 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +var _ Client = (*grpcClient)(nil) + // A stripped copy of the remoteClient that makes // synchronous calls using grpc type grpcClient struct { @@ -101,7 +104,7 @@ func (cli *grpcClient) StopForError(err error) { func (cli *grpcClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return cli.err + return errors.Wrap(cli.err, types.HumanCode(types.CodeType_InternalError)) } // Set listener for all responses @@ -147,8 +150,8 @@ func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Info{res}}) } -func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { - req := types.ToRequestSetOption(key, value) +func (cli *grpcClient) SetOptionAsync(params types.RequestSetOption) *ReqRes { + req := types.ToRequestSetOption(params) res, err := cli.client.SetOption(context.Background(), req.GetSetOption(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -210,8 +213,8 @@ func (cli *grpcClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_BeginBlock{res}}) } -func (cli *grpcClient) EndBlockAsync(height uint64) *ReqRes { - req := types.ToRequestEndBlock(height) +func (cli *grpcClient) EndBlockAsync(params types.RequestEndBlock) *ReqRes { + req := types.ToRequestEndBlock(params) res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -240,104 +243,59 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) return reqres } -func (cli *grpcClient) checkErrGetResult() types.Result { - if err := cli.Error(); err != nil { - // StopForError should already have been called if error is set - return types.ErrInternalError.SetLog(err.Error()) - } - return types.Result{} -} - //---------------------------------------- -func (cli *grpcClient) EchoSync(msg string) (res types.Result) { - reqres := cli.EchoAsync(msg) - if res := cli.checkErrGetResult(); res.IsErr() { - return res - } - resp := reqres.Response.GetEcho() - return types.NewResultOK([]byte(resp.Message), "") -} - func (cli *grpcClient) FlushSync() error { return nil } -func (cli *grpcClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { +func (cli *grpcClient) EchoSync(msg string) (*types.ResponseEcho, error) { + reqres := cli.EchoAsync(msg) + // StopForError should already have been called if error is set + return reqres.Response.GetEcho(), cli.Error() +} + +func (cli *grpcClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { reqres := cli.InfoAsync(req) - if err = cli.Error(); err != nil { - return resInfo, err - } - if info := reqres.Response.GetInfo(); info != nil { - return *info, nil - } - return resInfo, nil + return reqres.Response.GetInfo(), cli.Error() } -func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { - reqres := cli.SetOptionAsync(key, value) - if res := cli.checkErrGetResult(); res.IsErr() { - return res - } - resp := reqres.Response.GetSetOption() - return types.Result{Code: OK, Data: nil, Log: resp.Log} +func (cli *grpcClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { + reqres := cli.SetOptionAsync(req) + return reqres.Response.GetSetOption(), cli.Error() } -func (cli *grpcClient) DeliverTxSync(tx []byte) (res types.Result) { +func (cli *grpcClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { reqres := cli.DeliverTxAsync(tx) - if res := cli.checkErrGetResult(); res.IsErr() { - return res - } - resp := reqres.Response.GetDeliverTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetDeliverTx(), cli.Error() } -func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { +func (cli *grpcClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { reqres := cli.CheckTxAsync(tx) - if res := cli.checkErrGetResult(); res.IsErr() { - return res - } - resp := reqres.Response.GetCheckTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCheckTx(), cli.Error() } -func (cli *grpcClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { - reqres := cli.QueryAsync(reqQuery) - if err = cli.Error(); err != nil { - return resQuery, err - } - if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { - return *resQuery_, nil - } - return resQuery, nil +func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { + reqres := cli.QueryAsync(req) + return reqres.Response.GetQuery(), cli.Error() } -func (cli *grpcClient) CommitSync() (res types.Result) { +func (cli *grpcClient) CommitSync() (*types.ResponseCommit, error) { reqres := cli.CommitAsync() - if res := cli.checkErrGetResult(); res.IsErr() { - return res - } - resp := reqres.Response.GetCommit() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCommit(), cli.Error() } -func (cli *grpcClient) InitChainSync(params types.RequestInitChain) (err error) { - cli.InitChainAsync(params) - return cli.Error() +func (cli *grpcClient) InitChainSync(params types.RequestInitChain) (*types.ResponseInitChain, error) { + reqres := cli.InitChainAsync(params) + return reqres.Response.GetInitChain(), cli.Error() } -func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { - cli.BeginBlockAsync(params) - return cli.Error() +func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { + reqres := cli.BeginBlockAsync(params) + return reqres.Response.GetBeginBlock(), cli.Error() } -func (cli *grpcClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { - reqres := cli.EndBlockAsync(height) - if err := cli.Error(); err != nil { - return resEndBlock, err - } - if blk := reqres.Response.GetEndBlock(); blk != nil { - return *blk, nil - } - return resEndBlock, nil +func (cli *grpcClient) EndBlockSync(params types.RequestEndBlock) (*types.ResponseEndBlock, error) { + reqres := cli.EndBlockAsync(params) + return reqres.Response.GetEndBlock(), cli.Error() } diff --git a/client/local_client.go b/client/local_client.go index 8494a468f..64bf5fe08 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -7,6 +7,8 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +var _ Client = (*localClient)(nil) + type localClient struct { cmn.BaseService mtx *sync.Mutex @@ -51,21 +53,21 @@ func (app *localClient) EchoAsync(msg string) *ReqRes { func (app *localClient) InfoAsync(req types.RequestInfo) *ReqRes { app.mtx.Lock() - resInfo := app.Application.Info(req) + res := app.Application.Info(req) app.mtx.Unlock() return app.callback( types.ToRequestInfo(req), - types.ToResponseInfo(resInfo), + types.ToResponseInfo(res), ) } -func (app *localClient) SetOptionAsync(key string, value string) *ReqRes { +func (app *localClient) SetOptionAsync(req types.RequestSetOption) *ReqRes { app.mtx.Lock() - log := app.Application.SetOption(key, value) + res := app.Application.SetOption(req) app.mtx.Unlock() return app.callback( - types.ToRequestSetOption(key, value), - types.ToResponseSetOption(log), + types.ToRequestSetOption(req), + types.ToResponseSetOption(res), ) } @@ -75,7 +77,7 @@ func (app *localClient) DeliverTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestDeliverTx(tx), - types.ToResponseDeliverTx(res.Code, res.Data, res.Log), + types.ToResponseDeliverTx(res), ) } @@ -85,17 +87,17 @@ func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestCheckTx(tx), - types.ToResponseCheckTx(res.Code, res.Data, res.Log), + types.ToResponseCheckTx(res), ) } -func (app *localClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { +func (app *localClient) QueryAsync(req types.RequestQuery) *ReqRes { app.mtx.Lock() - resQuery := app.Application.Query(reqQuery) + res := app.Application.Query(req) app.mtx.Unlock() return app.callback( - types.ToRequestQuery(reqQuery), - types.ToResponseQuery(resQuery), + types.ToRequestQuery(req), + types.ToResponseQuery(res), ) } @@ -105,38 +107,38 @@ func (app *localClient) CommitAsync() *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestCommit(), - types.ToResponseCommit(res.Code, res.Data, res.Log), + types.ToResponseCommit(res), ) } -func (app *localClient) InitChainAsync(params types.RequestInitChain) *ReqRes { +func (app *localClient) InitChainAsync(req types.RequestInitChain) *ReqRes { app.mtx.Lock() - app.Application.InitChain(params) + res := app.Application.InitChain(req) reqRes := app.callback( - types.ToRequestInitChain(params), - types.ToResponseInitChain(), + types.ToRequestInitChain(req), + types.ToResponseInitChain(res), ) app.mtx.Unlock() return reqRes } -func (app *localClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { +func (app *localClient) BeginBlockAsync(req types.RequestBeginBlock) *ReqRes { app.mtx.Lock() - app.Application.BeginBlock(params) + res := app.Application.BeginBlock(req) app.mtx.Unlock() return app.callback( - types.ToRequestBeginBlock(params), - types.ToResponseBeginBlock(), + types.ToRequestBeginBlock(req), + types.ToResponseBeginBlock(res), ) } -func (app *localClient) EndBlockAsync(height uint64) *ReqRes { +func (app *localClient) EndBlockAsync(req types.RequestEndBlock) *ReqRes { app.mtx.Lock() - resEndBlock := app.Application.EndBlock(height) + res := app.Application.EndBlock(req) app.mtx.Unlock() return app.callback( - types.ToRequestEndBlock(height), - types.ToResponseEndBlock(resEndBlock), + types.ToRequestEndBlock(req), + types.ToResponseEndBlock(res), ) } @@ -146,71 +148,71 @@ func (app *localClient) FlushSync() error { return nil } -func (app *localClient) EchoSync(msg string) (res types.Result) { - return types.OK.SetData([]byte(msg)) +func (app *localClient) EchoSync(msg string) (*types.ResponseEcho, error) { + return &types.ResponseEcho{msg}, nil } -func (app *localClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { +func (app *localClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { app.mtx.Lock() - defer app.mtx.Unlock() - resInfo = app.Application.Info(req) - return resInfo, nil + res := app.Application.Info(req) + app.mtx.Unlock() + return &res, nil } -func (app *localClient) SetOptionSync(key string, value string) (res types.Result) { +func (app *localClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { app.mtx.Lock() - log := app.Application.SetOption(key, value) + res := app.Application.SetOption(req) app.mtx.Unlock() - return types.OK.SetLog(log) + return &res, nil } -func (app *localClient) DeliverTxSync(tx []byte) (res types.Result) { +func (app *localClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { app.mtx.Lock() - res = app.Application.DeliverTx(tx) + res := app.Application.DeliverTx(tx) app.mtx.Unlock() - return res + return &res, nil } -func (app *localClient) CheckTxSync(tx []byte) (res types.Result) { +func (app *localClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { app.mtx.Lock() - res = app.Application.CheckTx(tx) + res := app.Application.CheckTx(tx) app.mtx.Unlock() - return res + return &res, nil } -func (app *localClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { +func (app *localClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { app.mtx.Lock() - resQuery = app.Application.Query(reqQuery) + res := app.Application.Query(req) app.mtx.Unlock() - return resQuery, nil + return &res, nil } -func (app *localClient) CommitSync() (res types.Result) { +func (app *localClient) CommitSync() (*types.ResponseCommit, error) { app.mtx.Lock() - res = app.Application.Commit() + res := app.Application.Commit() app.mtx.Unlock() - return res + return &res, nil } -func (app *localClient) InitChainSync(params types.RequestInitChain) (err error) { +func (app *localClient) InitChainSync(req types.RequestInitChain) (*types.ResponseInitChain, error) { app.mtx.Lock() - app.Application.InitChain(params) + res := app.Application.InitChain(req) app.mtx.Unlock() - return nil + return &res, nil } -func (app *localClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { +func (app *localClient) BeginBlockSync(req types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { app.mtx.Lock() - app.Application.BeginBlock(params) + res := app.Application.BeginBlock(req) app.mtx.Unlock() - return nil + return &res, nil } -func (app *localClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { +func (app *localClient) EndBlockSync(req types.RequestEndBlock) (*types.ResponseEndBlock, error) { app.mtx.Lock() - resEndBlock = app.Application.EndBlock(height) + res := app.Application.EndBlock(req) app.mtx.Unlock() - return resEndBlock, nil + return &res, nil } //------------------------------------------------------- diff --git a/client/socket_client.go b/client/socket_client.go index 1045dea78..7e5a1f30f 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -3,26 +3,23 @@ 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" ) -const ( - OK = types.CodeType_OK - LOG = "" -) - const reqQueueSize = 256 // TODO make configurable // const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... +var _ Client = (*socketClient)(nil) + // This is goroutine-safe, but users should beware that // the application in general is not meant to be interfaced // with concurrent callers. @@ -114,7 +111,7 @@ func (cli *socketClient) StopForError(err error) { func (cli *socketClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return cli.err + return errors.Wrap(cli.err, types.HumanCode(types.CodeType_InternalError)) } // Set listener for all responses @@ -237,8 +234,8 @@ func (cli *socketClient) InfoAsync(req types.RequestInfo) *ReqRes { return cli.queueRequest(types.ToRequestInfo(req)) } -func (cli *socketClient) SetOptionAsync(key string, value string) *ReqRes { - return cli.queueRequest(types.ToRequestSetOption(key, value)) +func (cli *socketClient) SetOptionAsync(req types.RequestSetOption) *ReqRes { + return cli.queueRequest(types.ToRequestSetOption(req)) } func (cli *socketClient) DeliverTxAsync(tx []byte) *ReqRes { @@ -249,133 +246,95 @@ func (cli *socketClient) CheckTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.ToRequestCheckTx(tx)) } -func (cli *socketClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { - return cli.queueRequest(types.ToRequestQuery(reqQuery)) +func (cli *socketClient) QueryAsync(req types.RequestQuery) *ReqRes { + return cli.queueRequest(types.ToRequestQuery(req)) } func (cli *socketClient) CommitAsync() *ReqRes { return cli.queueRequest(types.ToRequestCommit()) } -func (cli *socketClient) InitChainAsync(params types.RequestInitChain) *ReqRes { - return cli.queueRequest(types.ToRequestInitChain(params)) +func (cli *socketClient) InitChainAsync(req types.RequestInitChain) *ReqRes { + return cli.queueRequest(types.ToRequestInitChain(req)) } -func (cli *socketClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { - return cli.queueRequest(types.ToRequestBeginBlock(params)) +func (cli *socketClient) BeginBlockAsync(req types.RequestBeginBlock) *ReqRes { + return cli.queueRequest(types.ToRequestBeginBlock(req)) } -func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.ToRequestEndBlock(height)) +func (cli *socketClient) EndBlockAsync(req types.RequestEndBlock) *ReqRes { + return cli.queueRequest(types.ToRequestEndBlock(req)) } //---------------------------------------- -func (cli *socketClient) EchoSync(msg string) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestEcho(msg)) - cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetEcho() - return types.Result{Code: OK, Data: []byte(resp.Message)} -} - func (cli *socketClient) FlushSync() error { reqRes := cli.queueRequest(types.ToRequestFlush()) if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return err } reqRes.Wait() // NOTE: if we don't flush the queue, its possible to get stuck here return cli.Error() } -func (cli *socketClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { +func (cli *socketClient) EchoSync(msg string) (*types.ResponseEcho, error) { + reqres := cli.queueRequest(types.ToRequestEcho(msg)) + cli.FlushSync() + return reqres.Response.GetEcho(), cli.Error() +} + +func (cli *socketClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { reqres := cli.queueRequest(types.ToRequestInfo(req)) cli.FlushSync() - if err := cli.Error(); err != nil { - return resInfo, err - } - if resInfo_ := reqres.Response.GetInfo(); resInfo_ != nil { - return *resInfo_, nil - } - return resInfo, nil + return reqres.Response.GetInfo(), cli.Error() } -func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestSetOption(key, value)) +func (cli *socketClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { + reqres := cli.queueRequest(types.ToRequestSetOption(req)) cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetSetOption() - return types.Result{Code: OK, Data: nil, Log: resp.Log} + return reqres.Response.GetSetOption(), cli.Error() } -func (cli *socketClient) DeliverTxSync(tx []byte) (res types.Result) { +func (cli *socketClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { reqres := cli.queueRequest(types.ToRequestDeliverTx(tx)) cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetDeliverTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetDeliverTx(), cli.Error() } -func (cli *socketClient) CheckTxSync(tx []byte) (res types.Result) { +func (cli *socketClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetCheckTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCheckTx(), cli.Error() } -func (cli *socketClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { - reqres := cli.queueRequest(types.ToRequestQuery(reqQuery)) +func (cli *socketClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { + reqres := cli.queueRequest(types.ToRequestQuery(req)) cli.FlushSync() - if err := cli.Error(); err != nil { - return resQuery, err - } - if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { - return *resQuery_, nil - } - return resQuery, nil + return reqres.Response.GetQuery(), cli.Error() } -func (cli *socketClient) CommitSync() (res types.Result) { +func (cli *socketClient) CommitSync() (*types.ResponseCommit, error) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetCommit() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCommit(), cli.Error() } -func (cli *socketClient) InitChainSync(params types.RequestInitChain) (err error) { - cli.queueRequest(types.ToRequestInitChain(params)) +func (cli *socketClient) InitChainSync(req types.RequestInitChain) (*types.ResponseInitChain, error) { + reqres := cli.queueRequest(types.ToRequestInitChain(req)) cli.FlushSync() - return cli.Error() + return reqres.Response.GetInitChain(), cli.Error() } -func (cli *socketClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { - cli.queueRequest(types.ToRequestBeginBlock(params)) +func (cli *socketClient) BeginBlockSync(req types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { + reqres := cli.queueRequest(types.ToRequestBeginBlock(req)) cli.FlushSync() - return cli.Error() + return reqres.Response.GetBeginBlock(), cli.Error() } -func (cli *socketClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { - reqres := cli.queueRequest(types.ToRequestEndBlock(height)) +func (cli *socketClient) EndBlockSync(req types.RequestEndBlock) (*types.ResponseEndBlock, error) { + reqres := cli.queueRequest(types.ToRequestEndBlock(req)) cli.FlushSync() - if err := cli.Error(); err != nil { - return resEndBlock, err - } - if blk := reqres.Response.GetEndBlock(); blk != nil { - return *blk, nil - } - return resEndBlock, nil + return reqres.Response.GetEndBlock(), cli.Error() } //---------------------------------------- diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 9962380b4..789832508 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -96,10 +96,10 @@ var RootCmd = &cobra.Command{ }, } -func Execute() { +func Execute() error { addGlobalFlags() addCommands() - RootCmd.Execute() + return RootCmd.Execute() } func addGlobalFlags() { @@ -294,7 +294,7 @@ func cmdBatch(cmd *cobra.Command, args []string) error { } pArgs := persistentArgs(line) - out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() + out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() // nolint: gas if err != nil { return err } @@ -316,7 +316,7 @@ func cmdConsole(cmd *cobra.Command, args []string) error { } pArgs := persistentArgs(line) - out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() + out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() // nolint: gas if err != nil { return err } @@ -327,9 +327,12 @@ func cmdConsole(cmd *cobra.Command, args []string) error { // Have the application echo a message func cmdEcho(cmd *cobra.Command, args []string) error { - resEcho := client.EchoSync(args[0]) + res, err := client.EchoSync(args[0]) + if err != nil { + return err + } printResponse(cmd, args, response{ - Data: resEcho.Data, + Data: []byte(res.Message), }) return nil } @@ -340,21 +343,25 @@ func cmdInfo(cmd *cobra.Command, args []string) error { if len(args) == 1 { version = args[0] } - resInfo, err := client.InfoSync(types.RequestInfo{version}) + res, err := client.InfoSync(types.RequestInfo{version}) if err != nil { return err } printResponse(cmd, args, response{ - Data: []byte(resInfo.Data), + Data: []byte(res.Data), }) return nil } // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) error { - resSetOption := client.SetOptionSync(args[0], args[1]) + key, val := args[0], args[1] + res, err := client.SetOptionSync(types.RequestSetOption{key, val}) + if err != nil { + return err + } printResponse(cmd, args, response{ - Log: resSetOption.Log, + Log: res.Log, }) return nil } @@ -365,7 +372,10 @@ func cmdDeliverTx(cmd *cobra.Command, args []string) error { if err != nil { return err } - res := client.DeliverTxSync(txBytes) + res, err := client.DeliverTxSync(txBytes) + if err != nil { + return err + } printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, @@ -380,7 +390,10 @@ func cmdCheckTx(cmd *cobra.Command, args []string) error { if err != nil { return err } - res := client.CheckTxSync(txBytes) + res, err := client.CheckTxSync(txBytes) + if err != nil { + return err + } printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, @@ -391,7 +404,10 @@ func cmdCheckTx(cmd *cobra.Command, args []string) error { // Get application Merkle root hash func cmdCommit(cmd *cobra.Command, args []string) error { - res := client.CommitSync() + res, err := client.CommitSync() + if err != nil { + return err + } printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, diff --git a/cmd/abci-cli/main.go b/cmd/abci-cli/main.go index 736ef3102..a927e7ed8 100644 --- a/cmd/abci-cli/main.go +++ b/cmd/abci-cli/main.go @@ -1,5 +1,14 @@ package main +import ( + "fmt" + "os" +) + func main() { - Execute() + err := Execute() + if err != nil { + fmt.Print(err) + os.Exit(1) + } } diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go deleted file mode 100644 index 8a031da2f..000000000 --- a/example/block_aware/block_aware_app.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "flag" - "os" - - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" -) - -func main() { - - addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - abciPtr := flag.String("abci", "socket", "socket | grpc") - flag.Parse() - - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Start the listener - srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - srv.SetLogger(logger.With("module", "abci-server")) - if _, err := srv.Start(); err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - -} - -type ChainAwareApplication struct { - types.BaseApplication - - beginCount int - endCount int -} - -func NewChainAwareApplication() *ChainAwareApplication { - return &ChainAwareApplication{} -} - -func (app *ChainAwareApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { - return types.ResponseQuery{ - Value: []byte(cmn.Fmt("%d,%d", app.beginCount, app.endCount)), - } -} - -func (app *ChainAwareApplication) BeginBlock(reqBeginBlock types.RequestBeginBlock) { - app.beginCount++ -} - -func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { - app.endCount++ - return -} diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go deleted file mode 100644 index 2777ce1a2..000000000 --- a/example/block_aware/block_aware_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -import ( - "strconv" - "strings" - "testing" - - abcicli "github.com/tendermint/abci/client" - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" - "github.com/tendermint/tmlibs/log" -) - -func TestChainAware(t *testing.T) { - app := NewChainAwareApplication() - - // Start the listener - srv, err := server.NewServer("unix://test.sock", "socket", app) - if err != nil { - t.Fatal(err) - } - srv.SetLogger(log.TestingLogger().With("module", "abci-server")) - if _, err := srv.Start(); err != nil { - t.Fatal(err.Error()) - } - defer srv.Stop() - - // Connect to the socket - client := abcicli.NewSocketClient("unix://test.sock", false) - client.SetLogger(log.TestingLogger().With("module", "abci-client")) - if _, err := client.Start(); err != nil { - t.Fatalf("Error starting socket client: %v", err.Error()) - } - defer client.Stop() - - n := uint64(5) - hash := []byte("fake block hash") - header := &types.Header{} - for i := uint64(0); i < n; i++ { - client.BeginBlockSync(types.RequestBeginBlock{hash, header}) - client.EndBlockSync(i) - client.CommitSync() - } - - r := app.Query(types.RequestQuery{}) - spl := strings.Split(string(r.Value), ",") - if len(spl) != 2 { - t.Fatal("expected %d,%d ; got %s", n, n, string(r.Value)) - } - beginCount, _ := strconv.Atoi(spl[0]) - endCount, _ := strconv.Atoi(spl[1]) - if uint64(beginCount) != n { - t.Fatalf("expected beginCount of %d, got %d", n, beginCount) - } else if uint64(endCount) != n { - t.Fatalf("expected endCount of %d, got %d", n, endCount) - } -} diff --git a/example/counter/counter.go b/example/counter/counter.go index d2478ae28..a7b090275 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -2,6 +2,7 @@ package counter import ( "encoding/binary" + "fmt" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" @@ -23,52 +24,61 @@ func (app *CounterApplication) Info(req types.RequestInfo) types.ResponseInfo { return types.ResponseInfo{Data: cmn.Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } -func (app *CounterApplication) SetOption(key string, value string) (log string) { +func (app *CounterApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption { + key, value := req.Key, req.Value if key == "serial" && value == "on" { app.serial = true } - return "" + return types.ResponseSetOption{} } -func (app *CounterApplication) DeliverTx(tx []byte) types.Result { +func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) + return types.ResponseDeliverTx{ + Code: types.CodeType_BadNonce, + Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)} } } app.txCount++ - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } -func (app *CounterApplication) CheckTx(tx []byte) types.Result { +func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ResponseCheckTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) + return types.ResponseCheckTx{ + Code: types.CodeType_BadNonce, + Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} } } - return types.OK + return types.ResponseCheckTx{Code: types.CodeType_OK} } -func (app *CounterApplication) Commit() types.Result { +func (app *CounterApplication) Commit() (resp types.ResponseCommit) { app.hashCount++ if app.txCount == 0 { - return types.OK + return types.ResponseCommit{Code: types.CodeType_OK} } hash := make([]byte, 8) binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return types.NewResultOK(hash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} } func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 7e95c859b..65d524cfe 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,15 +1,17 @@ package dummy import ( + "fmt" "strings" "github.com/tendermint/abci/types" wire "github.com/tendermint/go-wire" "github.com/tendermint/iavl" - cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" ) +var _ types.Application = (*DummyApplication)(nil) + type DummyApplication struct { types.BaseApplication @@ -22,25 +24,25 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} } // tx is either "key=value" or just arbitrary bytes -func (app *DummyApplication) DeliverTx(tx []byte) types.Result { +func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { parts := strings.Split(string(tx), "=") if len(parts) == 2 { app.state.Set([]byte(parts[0]), []byte(parts[1])) } else { app.state.Set(tx, tx) } - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } -func (app *DummyApplication) CheckTx(tx []byte) types.Result { - return types.OK +func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { + return types.ResponseCheckTx{Code: types.CodeType_OK} } -func (app *DummyApplication) Commit() types.Result { +func (app *DummyApplication) Commit() types.ResponseCommit { // Save a new version var hash []byte var err error @@ -55,7 +57,7 @@ func (app *DummyApplication) Commit() types.Result { } } - return types.NewResultOK(hash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} } func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index efbc5af77..b7aef6a8b 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -93,7 +93,7 @@ func TestPersistentDummyInfo(t *testing.T) { Height: uint64(height), } dummy.BeginBlock(types.RequestBeginBlock{hash, header}) - dummy.EndBlock(height) + dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() resInfo = dummy.Info(types.RequestInfo{}) @@ -182,7 +182,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ t.Fatal(r) } } - resEndBlock := dummy.EndBlock(height) + resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() valsEqual(t, diff, resEndBlock.Diffs) @@ -281,10 +281,12 @@ func runClientTests(t *testing.T, client abcicli.Client) { } func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) { - ar := app.DeliverTxSync(tx) + ar, err := app.DeliverTxSync(tx) + require.NoError(t, err) require.False(t, ar.IsErr(), ar) // repeating tx doesn't raise error - ar = app.DeliverTxSync(tx) + ar, err = app.DeliverTxSync(tx) + require.NoError(t, err) require.False(t, ar.IsErr(), ar) // make sure query is fine diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 4c4801755..ed2845296 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,6 +3,7 @@ package dummy import ( "bytes" "encoding/hex" + "fmt" "strconv" "strings" @@ -20,6 +21,8 @@ const ( //----------------------------------------- +var _ types.Application = (*PersistentDummyApplication)(nil) + type PersistentDummyApplication struct { app *DummyApplication @@ -49,19 +52,19 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { app.logger = l } -func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - resInfo = app.app.Info(req) - resInfo.LastBlockHeight = app.app.state.LatestVersion() - resInfo.LastBlockAppHash = app.app.state.Hash() - return resInfo +func (app *PersistentDummyApplication) Info(req types.RequestInfo) types.ResponseInfo { + res := app.app.Info(req) + res.LastBlockHeight = app.app.state.LatestVersion() + res.LastBlockAppHash = app.app.state.Hash() + return res } -func (app *PersistentDummyApplication) SetOption(key string, value string) (log string) { - return app.app.SetOption(key, value) +func (app *PersistentDummyApplication) 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 *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { // if it starts with "val:", update the validator set // format is "val:pubkey/power" if isValidatorTx(tx) { @@ -74,12 +77,12 @@ func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { return app.app.DeliverTx(tx) } -func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { return app.app.CheckTx(tx) } // Commit will panic if InitChain was not called -func (app *PersistentDummyApplication) Commit() types.Result { +func (app *PersistentDummyApplication) Commit() types.ResponseCommit { // Save a new version for next height height := app.app.state.LatestVersion() + 1 @@ -93,7 +96,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { } app.logger.Info("Commit block", "height", height, "root", appHash) - return types.NewResultOK(appHash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: appHash} } func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { @@ -101,23 +104,25 @@ func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types. } // Save the validators in the merkle tree -func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) { - for _, v := range params.Validators { +func (app *PersistentDummyApplication) 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 *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { +func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { // reset valset changes app.changes = make([]*types.Validator, 0) + return types.ResponseBeginBlock{} } // Update the validator set -func (app *PersistentDummyApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { +func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { return types.ResponseEndBlock{Diffs: app.changes} } @@ -148,30 +153,38 @@ func isValidatorTx(tx []byte) bool { } // format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx -func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) 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.ErrEncodingError.SetLog(cmn.Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + 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.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%s) is invalid hex", pubkeyS)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)} } _, err = crypto.PubKeyFromBytes(pubkey) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%X) is invalid go-crypto encoded", pubkey)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Pubkey (%X) is invalid go-crypto encoded", pubkey)} } // decode the power power, err := strconv.Atoi(powerS) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Power (%s) is not an int", powerS)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Power (%s) is not an int", powerS)} } // update @@ -179,19 +192,23 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { } // add, update, or remove a validator -func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.Result { +func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.ResponseDeliverTx { key := []byte("val:" + string(v.PubKey)) if v.Power == 0 { // remove validator if !app.app.state.Has(key) { - return types.ErrUnauthorized.SetLog(cmn.Fmt("Cannot remove non-existent validator %X", key)) + return types.ResponseDeliverTx{ + Code: types.CodeType_Unauthorized, + Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)} } app.app.state.Remove(key) } else { // add or update validator value := bytes.NewBuffer(make([]byte, 0)) if err := types.WriteMessage(v, value); err != nil { - return types.ErrInternalError.SetLog(cmn.Fmt("Error encoding validator: %v", err)) + return types.ResponseDeliverTx{ + Code: types.CodeType_InternalError, + Log: fmt.Sprintf("Error encoding validator: %v", err)} } app.app.state.Set(key, value.Bytes()) } @@ -199,5 +216,5 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types // we only update the changes array if we successfully updated the tree app.changes = append(app.changes, v) - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } diff --git a/server/socket_server.go b/server/socket_server.go index 2396c556d..eb26dc353 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -56,13 +56,17 @@ func (s *SocketServer) OnStart() error { func (s *SocketServer) OnStop() { s.BaseService.OnStop() - s.listener.Close() + if err := s.listener.Close(); err != nil { + s.Logger.Error("Error closing listener", "err", err) + } s.connsMtx.Lock() defer s.connsMtx.Unlock() for id, conn := range s.conns { delete(s.conns, id) - conn.Close() + if err := conn.Close(); err != nil { + s.Logger.Error("Error closing connection", "id", id, "conn", conn, "err", err) + } } } @@ -168,33 +172,32 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Flush: responses <- types.ToResponseFlush() case *types.Request_Info: - resInfo := s.app.Info(*r.Info) - responses <- types.ToResponseInfo(resInfo) + res := s.app.Info(*r.Info) + responses <- types.ToResponseInfo(res) case *types.Request_SetOption: - so := r.SetOption - logStr := s.app.SetOption(so.Key, so.Value) - responses <- types.ToResponseSetOption(logStr) + res := s.app.SetOption(*r.SetOption) + responses <- types.ToResponseSetOption(res) case *types.Request_DeliverTx: res := s.app.DeliverTx(r.DeliverTx.Tx) - responses <- types.ToResponseDeliverTx(res.Code, res.Data, res.Log) + responses <- types.ToResponseDeliverTx(res) case *types.Request_CheckTx: res := s.app.CheckTx(r.CheckTx.Tx) - responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) + responses <- types.ToResponseCheckTx(res) case *types.Request_Commit: res := s.app.Commit() - responses <- types.ToResponseCommit(res.Code, res.Data, res.Log) + responses <- types.ToResponseCommit(res) case *types.Request_Query: - resQuery := s.app.Query(*r.Query) - responses <- types.ToResponseQuery(resQuery) + res := s.app.Query(*r.Query) + responses <- types.ToResponseQuery(res) case *types.Request_InitChain: - s.app.InitChain(*r.InitChain) - responses <- types.ToResponseInitChain() + res := s.app.InitChain(*r.InitChain) + responses <- types.ToResponseInitChain(res) case *types.Request_BeginBlock: - s.app.BeginBlock(*r.BeginBlock) - responses <- types.ToResponseBeginBlock() + res := s.app.BeginBlock(*r.BeginBlock) + responses <- types.ToResponseBeginBlock(res) case *types.Request_EndBlock: - resEndBlock := s.app.EndBlock(r.EndBlock.Height) - responses <- types.ToResponseEndBlock(resEndBlock) + res := s.app.EndBlock(*r.EndBlock) + responses <- types.ToResponseEndBlock(res) default: responses <- types.ToResponseException("Unknown request") } diff --git a/test.sh b/test.sh new file mode 100755 index 000000000..978b26e1f --- /dev/null +++ b/test.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e +echo "" > coverage.txt + +echo "==> Running unit tests" +for d in $(go list ./... | grep -v vendor); do + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done + +echo "==> Running integration tests (./tests)" +find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; +# tests/test.sh requires that we run the installed cmds, must not be out of date +make install +bash tests/test.sh diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 127ba78f7..59d7aec4b 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -23,7 +23,7 @@ func startApp(abciApp string) *process.Process { os.Stdout, ) if err != nil { - panic("running abci_app: " + err.Error()) + panicf("running abci_app: %v", err) } // TODO a better way to handle this? @@ -41,57 +41,63 @@ func startClient(abciType string) abcicli.Client { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) client.SetLogger(logger.With("module", "abcicli")) if _, err := client.Start(); err != nil { - panic("connecting to abci_app: " + err.Error()) + panicf("connecting to abci_app: %v", err.Error()) } return client } func setOption(client abcicli.Client, key, value string) { - res := client.SetOptionSync(key, value) - _, _, log := res.Code, res.Data, res.Log - if res.IsErr() { - panic(fmt.Sprintf("setting %v=%v: \nlog: %v", key, value, log)) + _, err := client.SetOptionSync(types.RequestSetOption{key, value}) + if err != nil { + panicf("setting %v=%v: \nerr: %v", key, value, err) } } func commit(client abcicli.Client, hashExp []byte) { - res := client.CommitSync() - _, data, _ := res.Code, res.Data, res.Log + res, err := client.CommitSync() + if err != nil { + panicf("client error: %v", err) + } if res.IsErr() { - panic(fmt.Sprintf("committing err %v\n", res)) + panicf("committing err %v\n", res) } if !bytes.Equal(res.Data, hashExp) { - panic(fmt.Sprintf("Commit hash was unexpected. Got %X expected %X", - data, hashExp)) + panicf("Commit hash was unexpected. Got %X expected %X", res.Data, hashExp) } } func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - res := client.DeliverTxSync(txBytes) - code, data, log := res.Code, res.Data, res.Log - if code != codeExp { - panic(fmt.Sprintf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", - code, codeExp, log)) + res, err := client.DeliverTxSync(txBytes) + if err != nil { + panicf("client error: %v", err) } - if !bytes.Equal(data, dataExp) { - panic(fmt.Sprintf("DeliverTx response data was unexpected. Got %X expected %X", - data, dataExp)) + if res.Code != codeExp { + panicf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", res.Code, codeExp, res.Log) + } + if !bytes.Equal(res.Data, dataExp) { + panicf("DeliverTx response data was unexpected. Got %X expected %X", res.Data, dataExp) } } /*func checkTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - res := client.CheckTxSync(txBytes) - code, data, log := res.Code, res.Data, res.Log + res, err := client.CheckTxSync(txBytes) + if err != nil { + panicf("client error: %v", err) + } if res.IsErr() { - panic(fmt.Sprintf("checking tx %X: %v\nlog: %v", txBytes, log)) + panicf("checking tx %X: %v\nlog: %v", txBytes, res.Log) } - if code != codeExp { - panic(fmt.Sprintf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", - code, codeExp, log)) + if res.Code != codeExp { + panicf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", + res.Code, codeExp, res.Log) } - if !bytes.Equal(data, dataExp) { - panic(fmt.Sprintf("CheckTx response data was unexpected. Got %X expected %X", - data, dataExp)) + if !bytes.Equal(res.Data, dataExp) { + panicf("CheckTx response data was unexpected. Got %X expected %X", + res.Data, dataExp) } }*/ + +func panicf(format string, a ...interface{}) { + panic(fmt.Sprintf(format, a...)) +} diff --git a/types/application.go b/types/application.go index 3d9716b74..bb9a0030d 100644 --- a/types/application.go +++ b/types/application.go @@ -5,22 +5,24 @@ import ( ) // Application is an interface that enables any finite, deterministic state machine -// to be driven by a blockchain-based replication engine via the ABCI +// to be driven by a blockchain-based replication engine via the ABCI. +// All methods take a RequestXxx argument and return a ResponseXxx argument, +// except CheckTx/DeliverTx, which take `tx []byte`, and `Commit`, which takes nothing. type Application interface { // Info/Query Connection - Info(RequestInfo) ResponseInfo // Return application info - SetOption(key string, value string) (log string) // Set application option - Query(RequestQuery) ResponseQuery // Query for state + Info(RequestInfo) ResponseInfo // Return application info + SetOption(RequestSetOption) ResponseSetOption // Set application option + Query(RequestQuery) ResponseQuery // Query for state // Mempool Connection - CheckTx(tx []byte) Result // Validate a tx for the mempool + CheckTx(tx []byte) ResponseCheckTx // Validate a tx for the mempool // Consensus Connection - InitChain(RequestInitChain) // Initialize blockchain with validators and other info from TendermintCore - BeginBlock(RequestBeginBlock) // Signals the beginning of a block - DeliverTx(tx []byte) Result // Deliver a tx for full processing - EndBlock(height uint64) ResponseEndBlock // Signals the end of a block, returns changes to the validator set - Commit() Result // Commit the state and return the application Merkle root hash + InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain with validators and other info from TendermintCore + BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block + DeliverTx(tx []byte) ResponseDeliverTx // Deliver a tx for full processing + EndBlock(RequestEndBlock) ResponseEndBlock // Signals the end of a block, returns changes to the validator set + Commit() ResponseCommit // Commit the state and return the application Merkle root hash } //------------------------------------ @@ -43,45 +45,46 @@ func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*Resp } func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { - resInfo := app.app.Info(*req) - return &resInfo, nil + res := app.app.Info(*req) + return &res, nil } func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { - return &ResponseSetOption{app.app.SetOption(req.Key, req.Value)}, nil + res := app.app.SetOption(*req) + return &res, nil } func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { - r := app.app.DeliverTx(req.Tx) - return &ResponseDeliverTx{r.Code, r.Data, r.Log}, nil + res := app.app.DeliverTx(req.Tx) + return &res, nil } func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { - r := app.app.CheckTx(req.Tx) - return &ResponseCheckTx{r.Code, r.Data, r.Log}, nil + res := app.app.CheckTx(req.Tx) + return &res, nil } func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { - resQuery := app.app.Query(*req) - return &resQuery, nil + res := app.app.Query(*req) + return &res, nil } func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { - r := app.app.Commit() - return &ResponseCommit{r.Code, r.Data, r.Log}, nil + res := app.app.Commit() + return &res, nil } func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - app.app.InitChain(*req) - return &ResponseInitChain{}, nil // NOTE: empty return + res := app.app.InitChain(*req) + return &res, nil } func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { - app.app.BeginBlock(*req) - return &ResponseBeginBlock{}, nil // NOTE: empty return + res := app.app.BeginBlock(*req) + return &res, nil } func (app *GRPCApplication) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { - resEndBlock := app.app.EndBlock(req.Height) - return &resEndBlock, nil + res := app.app.EndBlock(*req) + return &res, nil } diff --git a/types/base_app.go b/types/base_app.go index 94607e9ab..404678e95 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -7,36 +7,38 @@ func NewBaseApplication() *BaseApplication { return &BaseApplication{} } -func (app *BaseApplication) Info(req RequestInfo) (resInfo ResponseInfo) { - return +func (BaseApplication) Info(req RequestInfo) ResponseInfo { + return ResponseInfo{} } -func (app *BaseApplication) SetOption(key string, value string) (log string) { - return "" +func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { + return ResponseSetOption{} } -func (app *BaseApplication) DeliverTx(tx []byte) Result { - return NewResultOK(nil, "") +func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { + return ResponseDeliverTx{Code: CodeType_OK} } -func (app *BaseApplication) CheckTx(tx []byte) Result { - return NewResultOK(nil, "") +func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { + return ResponseCheckTx{Code: CodeType_OK} } -func (app *BaseApplication) Commit() Result { - return NewResultOK([]byte("nil"), "") +func (BaseApplication) Commit() ResponseCommit { + return ResponseCommit{Code: CodeType_OK, Data: []byte("nil")} } -func (app *BaseApplication) Query(req RequestQuery) (resQuery ResponseQuery) { - return +func (BaseApplication) Query(req RequestQuery) ResponseQuery { + return ResponseQuery{Code: CodeType_OK} } -func (app *BaseApplication) InitChain(req RequestInitChain) { +func (BaseApplication) InitChain(req RequestInitChain) ResponseInitChain { + return ResponseInitChain{} } -func (app *BaseApplication) BeginBlock(req RequestBeginBlock) { +func (BaseApplication) BeginBlock(req RequestBeginBlock) ResponseBeginBlock { + return ResponseBeginBlock{} } -func (app *BaseApplication) EndBlock(height uint64) (resEndBlock ResponseEndBlock) { - return +func (BaseApplication) EndBlock(req RequestEndBlock) ResponseEndBlock { + return ResponseEndBlock{} } diff --git a/types/code.go b/types/code.go index c99a0bbe1..613c4cda3 100644 --- a/types/code.go +++ b/types/code.go @@ -1,3 +1,37 @@ package types +var ( + code2string = map[CodeType]string{ + CodeType_InternalError: "Internal error", + CodeType_EncodingError: "Encoding error", + CodeType_BadNonce: "Error bad nonce", + CodeType_Unauthorized: "Unauthorized", + CodeType_InsufficientFunds: "Insufficient funds", + CodeType_UnknownRequest: "Unknown request", + + CodeType_BaseDuplicateAddress: "Error (base) duplicate address", + CodeType_BaseEncodingError: "Error (base) encoding error", + CodeType_BaseInsufficientFees: "Error (base) insufficient fees", + CodeType_BaseInsufficientFunds: "Error (base) insufficient funds", + CodeType_BaseInsufficientGasPrice: "Error (base) insufficient gas price", + CodeType_BaseInvalidInput: "Error (base) invalid input", + CodeType_BaseInvalidOutput: "Error (base) invalid output", + CodeType_BaseInvalidPubKey: "Error (base) invalid pubkey", + CodeType_BaseInvalidSequence: "Error (base) invalid sequence", + CodeType_BaseInvalidSignature: "Error (base) invalid signature", + CodeType_BaseUnknownAddress: "Error (base) unknown address", + CodeType_BaseUnknownPlugin: "Error (base) unknown plugin", + CodeType_BaseUnknownPubKey: "Error (base) unknown pubkey", + } +) + func (c CodeType) IsOK() bool { return c == CodeType_OK } + +// HumanCode transforms code into a more humane format, such as "Internal error" instead of 0. +func HumanCode(code CodeType) string { + s, ok := code2string[code] + if !ok { + return "Unknown code" + } + return s +} diff --git a/types/code_test.go b/types/code_test.go new file mode 100644 index 000000000..d9032d3c5 --- /dev/null +++ b/types/code_test.go @@ -0,0 +1,12 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestHumanCode(t *testing.T) { + assert.Equal(t, "Internal error", HumanCode(CodeType_InternalError)) + assert.Equal(t, "Unknown code", HumanCode(-1)) +} diff --git a/types/errors.go b/types/errors.go deleted file mode 100644 index 7fa1f0090..000000000 --- a/types/errors.go +++ /dev/null @@ -1,26 +0,0 @@ -package types - -var ( - OK = NewResultOK(nil, "") - - ErrInternalError = NewError(CodeType_InternalError, "Internal error") - ErrEncodingError = NewError(CodeType_EncodingError, "Encoding error") - ErrBadNonce = NewError(CodeType_BadNonce, "Error bad nonce") - ErrUnauthorized = NewError(CodeType_Unauthorized, "Unauthorized") - ErrInsufficientFunds = NewError(CodeType_InsufficientFunds, "Insufficient funds") - ErrUnknownRequest = NewError(CodeType_UnknownRequest, "Unknown request") - - ErrBaseDuplicateAddress = NewError(CodeType_BaseDuplicateAddress, "Error (base) duplicate address") - ErrBaseEncodingError = NewError(CodeType_BaseEncodingError, "Error (base) encoding error") - ErrBaseInsufficientFees = NewError(CodeType_BaseInsufficientFees, "Error (base) insufficient fees") - ErrBaseInsufficientFunds = NewError(CodeType_BaseInsufficientFunds, "Error (base) insufficient funds") - ErrBaseInsufficientGasPrice = NewError(CodeType_BaseInsufficientGasPrice, "Error (base) insufficient gas price") - ErrBaseInvalidInput = NewError(CodeType_BaseInvalidInput, "Error (base) invalid input") - ErrBaseInvalidOutput = NewError(CodeType_BaseInvalidOutput, "Error (base) invalid output") - ErrBaseInvalidPubKey = NewError(CodeType_BaseInvalidPubKey, "Error (base) invalid pubkey") - ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error (base) invalid sequence") - ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error (base) invalid signature") - ErrBaseUnknownAddress = NewError(CodeType_BaseUnknownAddress, "Error (base) unknown address") - ErrBaseUnknownPlugin = NewError(CodeType_BaseUnknownPlugin, "Error (base) unknown plugin") - ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error (base) unknown pubkey") -) diff --git a/types/messages.go b/types/messages.go index be272c387..77ad538ed 100644 --- a/types/messages.go +++ b/types/messages.go @@ -4,7 +4,7 @@ import ( "io" "github.com/golang/protobuf/proto" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" ) func ToRequestEcho(message string) *Request { @@ -25,21 +25,21 @@ func ToRequestInfo(req RequestInfo) *Request { } } -func ToRequestSetOption(key string, value string) *Request { +func ToRequestSetOption(req RequestSetOption) *Request { return &Request{ - Value: &Request_SetOption{&RequestSetOption{key, value}}, + Value: &Request_SetOption{&req}, } } -func ToRequestDeliverTx(txBytes []byte) *Request { +func ToRequestDeliverTx(tx []byte) *Request { return &Request{ - Value: &Request_DeliverTx{&RequestDeliverTx{txBytes}}, + Value: &Request_DeliverTx{&RequestDeliverTx{tx}}, } } -func ToRequestCheckTx(txBytes []byte) *Request { +func ToRequestCheckTx(tx []byte) *Request { return &Request{ - Value: &Request_CheckTx{&RequestCheckTx{txBytes}}, + Value: &Request_CheckTx{&RequestCheckTx{tx}}, } } @@ -67,9 +67,9 @@ func ToRequestBeginBlock(req RequestBeginBlock) *Request { } } -func ToRequestEndBlock(height uint64) *Request { +func ToRequestEndBlock(req RequestEndBlock) *Request { return &Request{ - Value: &Request_EndBlock{&RequestEndBlock{height}}, + Value: &Request_EndBlock{&req}, } } @@ -93,57 +93,57 @@ func ToResponseFlush() *Response { } } -func ToResponseInfo(resInfo ResponseInfo) *Response { +func ToResponseInfo(res ResponseInfo) *Response { return &Response{ - Value: &Response_Info{&resInfo}, + Value: &Response_Info{&res}, } } -func ToResponseSetOption(log string) *Response { +func ToResponseSetOption(res ResponseSetOption) *Response { return &Response{ - Value: &Response_SetOption{&ResponseSetOption{log}}, + Value: &Response_SetOption{&res}, } } -func ToResponseDeliverTx(code CodeType, data []byte, log string) *Response { +func ToResponseDeliverTx(res ResponseDeliverTx) *Response { return &Response{ - Value: &Response_DeliverTx{&ResponseDeliverTx{code, data, log}}, + Value: &Response_DeliverTx{&res}, } } -func ToResponseCheckTx(code CodeType, data []byte, log string) *Response { +func ToResponseCheckTx(res ResponseCheckTx) *Response { return &Response{ - Value: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, + Value: &Response_CheckTx{&res}, } } -func ToResponseCommit(code CodeType, data []byte, log string) *Response { +func ToResponseCommit(res ResponseCommit) *Response { return &Response{ - Value: &Response_Commit{&ResponseCommit{code, data, log}}, + Value: &Response_Commit{&res}, } } -func ToResponseQuery(resQuery ResponseQuery) *Response { +func ToResponseQuery(res ResponseQuery) *Response { return &Response{ - Value: &Response_Query{&resQuery}, + Value: &Response_Query{&res}, } } -func ToResponseInitChain() *Response { +func ToResponseInitChain(res ResponseInitChain) *Response { return &Response{ - Value: &Response_InitChain{&ResponseInitChain{}}, + Value: &Response_InitChain{&res}, } } -func ToResponseBeginBlock() *Response { +func ToResponseBeginBlock(res ResponseBeginBlock) *Response { return &Response{ - Value: &Response_BeginBlock{&ResponseBeginBlock{}}, + Value: &Response_BeginBlock{&res}, } } -func ToResponseEndBlock(resEndBlock ResponseEndBlock) *Response { +func ToResponseEndBlock(res ResponseEndBlock) *Response { return &Response{ - Value: &Response_EndBlock{&resEndBlock}, + Value: &Response_EndBlock{&res}, } } diff --git a/types/result.go b/types/result.go index abf1e964c..6ebad8ab2 100644 --- a/types/result.go +++ b/types/result.go @@ -6,114 +6,47 @@ import ( "github.com/tendermint/go-wire/data" ) -// Result is a common result object for ABCI calls. -// CONTRACT: a zero Result is OK. -type Result struct { - Code CodeType `json:"code"` - Data data.Bytes `json:"data"` - Log string `json:"log"` // Can be non-deterministic +// IsErr returns true if Code is something other than OK. +func (r ResponseCheckTx) IsErr() bool { + return r.Code != CodeType_OK } -func NewResult(code CodeType, data []byte, log string) Result { - return Result{ - Code: code, - Data: data, - Log: log, - } -} - -func (res Result) IsOK() bool { - return res.Code == CodeType_OK -} - -func (res Result) IsErr() bool { - return res.Code != CodeType_OK -} - -func (res Result) IsSameCode(compare Result) bool { - return res.Code == compare.Code -} - -func (res Result) Error() string { - return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) -} - -func (res Result) String() string { - return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) -} - -func (res Result) PrependLog(log string) Result { - return Result{ - Code: res.Code, - Data: res.Data, - Log: log + ";" + res.Log, - } -} - -func (res Result) AppendLog(log string) Result { - return Result{ - Code: res.Code, - Data: res.Data, - Log: res.Log + ";" + log, - } +// Error implements error interface by formatting response as string. +func (r ResponseCheckTx) Error() string { + return fmtError(r.Code, r.Log) } -func (res Result) SetLog(log string) Result { - return Result{ - Code: res.Code, - Data: res.Data, - Log: log, - } +// IsErr returns true if Code is something other than OK. +func (r ResponseDeliverTx) IsErr() bool { + return r.Code != CodeType_OK } -func (res Result) SetData(data []byte) Result { - return Result{ - Code: res.Code, - Data: data, - Log: res.Log, - } +// Error implements error interface by formatting response as string. +func (r ResponseDeliverTx) Error() string { + return fmtError(r.Code, r.Log) } -//---------------------------------------- - -// NOTE: if data == nil and log == "", same as zero Result. -func NewResultOK(data []byte, log string) Result { - return Result{ - Code: CodeType_OK, - Data: data, - Log: log, - } +// IsErr returns true if Code is something other than OK. +func (r ResponseCommit) IsErr() bool { + return r.Code != CodeType_OK } -func NewError(code CodeType, log string) Result { - return Result{ - Code: code, - Log: log, - } +// Error implements error interface by formatting response as string. +func (r ResponseCommit) Error() string { + return fmtError(r.Code, r.Log) } -//---------------------------------------- -// Convenience methods for turning the -// pb type into one using data.Bytes - -// Convert ResponseCheckTx to standard Result -func (r *ResponseCheckTx) Result() Result { - return Result{ - Code: r.Code, - Data: r.Data, - Log: r.Log, - } -} - -// Convert ResponseDeliverTx to standard Result -func (r *ResponseDeliverTx) Result() Result { - return Result{ - Code: r.Code, - Data: r.Data, - Log: r.Log, +func fmtError(code CodeType, log string) string { + codeAsStr, ok := code2string[code] + if ok { + return fmt.Sprintf("%s (%d): %s", codeAsStr, code, log) + } else { + return fmt.Sprintf("Unknown error (%d): %s", code, log) } } +// ResultQuery is a wrapper around ResponseQuery using data.Bytes instead of +// raw byte slices. type ResultQuery struct { Code CodeType `json:"code"` Index int64 `json:"index"` @@ -124,6 +57,7 @@ type ResultQuery struct { Log string `json:"log"` } +// Result converts response query to ResultQuery. func (r *ResponseQuery) Result() *ResultQuery { return &ResultQuery{ Code: r.Code, @@ -135,3 +69,13 @@ func (r *ResponseQuery) Result() *ResultQuery { Log: r.Log, } } + +// IsErr returns true if Code is something other than OK. +func (r *ResultQuery) IsErr() bool { + return r.Code != CodeType_OK +} + +// Error implements error interface by formatting result as string. +func (r *ResultQuery) Error() string { + return fmtError(r.Code, r.Log) +} diff --git a/types/result_test.go b/types/result_test.go new file mode 100644 index 000000000..14f334c49 --- /dev/null +++ b/types/result_test.go @@ -0,0 +1,76 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResultQuery(t *testing.T) { + orig := &ResponseQuery{ + Code: CodeType_OK, + Index: 0, + Key: []byte("hello"), + Value: []byte("world"), + Height: 1, + } + res := orig.Result() + assert.False(t, res.IsErr()) + + orig = &ResponseQuery{ + Code: CodeType_BadNonce, + Index: 0, + Key: []byte("hello"), + Value: []byte("world"), + Height: 1, + Log: "bad", + } + res = orig.Result() + assert.True(t, res.IsErr()) + assert.Equal(t, "Error bad nonce (3): bad", res.Error()) +} + +func TestResponseDeliverTx(t *testing.T) { + res := ResponseDeliverTx{ + Code: CodeType_OK, + Data: []byte("Victor Mancha"), + } + assert.False(t, res.IsErr()) + + res = ResponseDeliverTx{ + Code: CodeType_InternalError, + Log: "bad", + } + assert.True(t, res.IsErr()) + assert.Equal(t, "Internal error (1): bad", res.Error()) +} + +func TestResponseCheckTx(t *testing.T) { + res := ResponseCheckTx{ + Code: CodeType_OK, + Data: []byte("Talos"), + } + assert.False(t, res.IsErr()) + + res = ResponseCheckTx{ + Code: CodeType_InternalError, + Log: "bad", + } + assert.True(t, res.IsErr()) + assert.Equal(t, "Internal error (1): bad", res.Error()) +} + +func TestResponseCommit(t *testing.T) { + res := ResponseCommit{ + Code: CodeType_OK, + Data: []byte("Old Lace"), + } + assert.False(t, res.IsErr()) + + res = ResponseCommit{ + Code: CodeType_Unauthorized, + Log: "bad", + } + assert.True(t, res.IsErr()) + assert.Equal(t, "Unauthorized (4): bad", res.Error()) +} diff --git a/types/types.pb.go b/types/types.pb.go index 4ca304ac7..e433d1986 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -38,7 +38,9 @@ It has these top-level messages: BlockID PartSetHeader Validator + KVPair */ +//nolint: gas package types import proto "github.com/golang/protobuf/proto" @@ -169,6 +171,27 @@ func (x CodeType) String() string { } func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +type KVPair_Type int32 + +const ( + KVPair_STRING KVPair_Type = 0 + KVPair_INT KVPair_Type = 1 +) + +var KVPair_Type_name = map[int32]string{ + 0: "STRING", + 1: "INT", +} +var KVPair_Type_value = map[string]int32{ + "STRING": 0, + "INT": 1, +} + +func (x KVPair_Type) String() string { + return proto.EnumName(KVPair_Type_name, int32(x)) +} +func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{29, 0} } + type Request struct { // Types that are valid to be assigned to Value: // *Request_Echo @@ -1297,9 +1320,10 @@ func (m *ResponseSetOption) GetLog() string { } type ResponseDeliverTx struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` } func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } @@ -1328,10 +1352,19 @@ func (m *ResponseDeliverTx) GetLog() string { return "" } +func (m *ResponseDeliverTx) GetTags() []*KVPair { + if m != nil { + return m.Tags + } + return nil +} + type ResponseCheckTx struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Gas uint64 `protobuf:"varint,4,opt,name=gas" json:"gas,omitempty"` + Fee uint64 `protobuf:"varint,5,opt,name=fee" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1360,6 +1393,20 @@ func (m *ResponseCheckTx) GetLog() string { return "" } +func (m *ResponseCheckTx) GetGas() uint64 { + if m != nil { + return m.Gas + } + return 0 +} + +func (m *ResponseCheckTx) GetFee() uint64 { + if m != nil { + return m.Fee + } + return 0 +} + type ResponseQuery struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` @@ -1640,6 +1687,46 @@ func (m *Validator) GetPower() uint64 { return 0 } +type KVPair struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + ValueType KVPair_Type `protobuf:"varint,2,opt,name=value_type,json=valueType,enum=types.KVPair_Type" json:"value_type,omitempty"` + ValueString string `protobuf:"bytes,3,opt,name=value_string,json=valueString" json:"value_string,omitempty"` + ValueInt int64 `protobuf:"varint,4,opt,name=value_int,json=valueInt" json:"value_int,omitempty"` +} + +func (m *KVPair) Reset() { *m = KVPair{} } +func (m *KVPair) String() string { return proto.CompactTextString(m) } +func (*KVPair) ProtoMessage() {} +func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *KVPair) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *KVPair) GetValueType() KVPair_Type { + if m != nil { + return m.ValueType + } + return KVPair_STRING +} + +func (m *KVPair) GetValueString() string { + if m != nil { + return m.ValueString + } + return "" +} + +func (m *KVPair) GetValueInt() int64 { + if m != nil { + return m.ValueInt + } + return 0 +} + func init() { proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*RequestEcho)(nil), "types.RequestEcho") @@ -1670,7 +1757,9 @@ func init() { proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") + proto.RegisterType((*KVPair)(nil), "types.KVPair") proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) + proto.RegisterEnum("types.KVPair_Type", KVPair_Type_name, KVPair_Type_value) } // Reference imports to suppress errors if they are not otherwise used. @@ -2078,107 +2167,115 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1625 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x59, 0x6f, 0xdb, 0xc6, - 0x16, 0x36, 0xb5, 0xeb, 0xd8, 0x96, 0xe9, 0xb1, 0x6c, 0xcb, 0xba, 0xf7, 0x21, 0xe0, 0x45, 0x6e, - 0xec, 0xdc, 0xdc, 0xa4, 0x70, 0x90, 0x22, 0x6e, 0x8a, 0x02, 0xde, 0x62, 0x0b, 0x41, 0x13, 0x97, - 0x59, 0x5e, 0x5a, 0x54, 0xa0, 0xc9, 0x91, 0xc4, 0x5a, 0x9a, 0x61, 0xc8, 0xa1, 0x23, 0xf7, 0x37, - 0xe4, 0xbd, 0x3f, 0xa1, 0xef, 0x05, 0xfa, 0x17, 0x0a, 0x74, 0x5f, 0x7e, 0x51, 0x31, 0x0b, 0x57, - 0x93, 0x41, 0x1f, 0xf2, 0x22, 0xf0, 0x6c, 0x33, 0x73, 0xce, 0x9c, 0xf3, 0x9d, 0x33, 0x82, 0x55, - 0x76, 0xe5, 0xe1, 0xe0, 0x9e, 0xf8, 0xbd, 0xeb, 0xf9, 0x94, 0x51, 0x54, 0x17, 0x84, 0xf1, 0x43, - 0x0d, 0x9a, 0x26, 0x7e, 0x1d, 0xe2, 0x80, 0xa1, 0x6d, 0xa8, 0x61, 0x7b, 0x42, 0x7b, 0xda, 0x0d, - 0x6d, 0x7b, 0x71, 0x17, 0xdd, 0x95, 0xea, 0x4a, 0x7a, 0x6c, 0x4f, 0xe8, 0xe9, 0x82, 0x29, 0x34, - 0xd0, 0xff, 0xa0, 0x3e, 0x9a, 0x86, 0xc1, 0xa4, 0x57, 0x11, 0xaa, 0x6b, 0x59, 0xd5, 0xc7, 0x5c, - 0x74, 0xba, 0x60, 0x4a, 0x1d, 0xbe, 0xac, 0x4b, 0x46, 0xb4, 0x57, 0x2d, 0x5a, 0x76, 0x40, 0x46, - 0x62, 0x59, 0xae, 0x81, 0x1e, 0x02, 0x04, 0x98, 0x0d, 0xa9, 0xc7, 0x5c, 0x4a, 0x7a, 0x35, 0xa1, - 0xbf, 0x99, 0xd5, 0x7f, 0x8e, 0xd9, 0x33, 0x21, 0x3e, 0x5d, 0x30, 0xdb, 0x41, 0x44, 0x70, 0x4b, - 0x07, 0x4f, 0xdd, 0x4b, 0xec, 0x0f, 0xd9, 0xbc, 0x57, 0x2f, 0xb2, 0x3c, 0x92, 0xf2, 0x17, 0x73, - 0x6e, 0xe9, 0x44, 0x04, 0xda, 0x85, 0x96, 0x3d, 0xc1, 0xf6, 0x05, 0xb7, 0x6b, 0x08, 0xbb, 0xf5, - 0xac, 0xdd, 0x21, 0x97, 0x0a, 0xab, 0xa6, 0x2d, 0x3f, 0xd1, 0x5d, 0x68, 0xd8, 0x74, 0x36, 0x73, - 0x59, 0xaf, 0x29, 0x2c, 0xba, 0x39, 0x0b, 0x21, 0x3b, 0x5d, 0x30, 0x95, 0x16, 0x0f, 0xd7, 0xeb, - 0x10, 0xfb, 0x57, 0xbd, 0x56, 0x51, 0xb8, 0x3e, 0xe3, 0x22, 0x1e, 0x2e, 0xa1, 0xc3, 0x5d, 0x71, - 0x89, 0xcb, 0x86, 0xf6, 0xc4, 0x72, 0x49, 0xaf, 0x5d, 0xe4, 0xca, 0x80, 0xb8, 0xec, 0x90, 0x8b, - 0xb9, 0x2b, 0x6e, 0x44, 0xa0, 0x47, 0xb0, 0x78, 0x8e, 0xc7, 0x2e, 0x19, 0x9e, 0x4f, 0xa9, 0x7d, - 0xd1, 0x03, 0x61, 0xda, 0xcb, 0x9a, 0x1e, 0x70, 0x85, 0x03, 0x2e, 0x3f, 0x5d, 0x30, 0xe1, 0x3c, - 0xa6, 0xd0, 0x03, 0x68, 0x63, 0xe2, 0x28, 0xd3, 0x45, 0x61, 0xba, 0x91, 0xcb, 0x00, 0xe2, 0x44, - 0x86, 0x2d, 0xac, 0xbe, 0x0f, 0x9a, 0x50, 0xbf, 0xb4, 0xa6, 0x21, 0x36, 0x6e, 0xc1, 0x62, 0x2a, - 0x53, 0x50, 0x0f, 0x9a, 0x33, 0x1c, 0x04, 0xd6, 0x18, 0x8b, 0x74, 0x6a, 0x9b, 0x11, 0x69, 0x74, - 0x60, 0x29, 0x9d, 0x27, 0x29, 0x43, 0x9e, 0x0b, 0xdc, 0xf0, 0x12, 0xfb, 0x01, 0x4f, 0x00, 0x65, - 0xa8, 0x48, 0xe3, 0x23, 0xd0, 0xf3, 0x49, 0x80, 0x74, 0xa8, 0x5e, 0xe0, 0x2b, 0xa5, 0xc9, 0x3f, - 0x51, 0x57, 0x1d, 0x48, 0xa4, 0x66, 0xdb, 0x54, 0xa7, 0x33, 0x62, 0xdb, 0x38, 0x0d, 0x50, 0x07, - 0x2a, 0x6c, 0x2e, 0x4c, 0x97, 0xcc, 0x0a, 0x9b, 0x1b, 0x37, 0xa0, 0x93, 0xbd, 0xf2, 0x6b, 0x1a, - 0x4e, 0x7c, 0x74, 0x71, 0x67, 0x08, 0x41, 0xcd, 0xb1, 0x98, 0xa5, 0x34, 0xc4, 0x37, 0xe7, 0x79, - 0x16, 0x9b, 0xa8, 0xed, 0xc5, 0x37, 0xda, 0x80, 0xc6, 0x04, 0xbb, 0xe3, 0x09, 0x13, 0x35, 0x50, - 0x33, 0x15, 0xc5, 0xcf, 0xea, 0xf9, 0xf4, 0x12, 0x8b, 0x54, 0x6f, 0x99, 0x92, 0x30, 0x56, 0x60, - 0x39, 0x93, 0x48, 0xc6, 0x51, 0x7c, 0xf8, 0xf8, 0xe2, 0xd1, 0x07, 0x00, 0x97, 0xd6, 0xd4, 0x75, - 0x2c, 0x46, 0xfd, 0xa0, 0xa7, 0xdd, 0xa8, 0x6e, 0x2f, 0xee, 0xea, 0xea, 0xbe, 0x5e, 0x45, 0x02, - 0x33, 0xa5, 0x63, 0x3c, 0x85, 0xd5, 0x6b, 0x39, 0xc0, 0x4f, 0x3b, 0xb1, 0x82, 0x49, 0xe4, 0x01, - 0xff, 0x46, 0x37, 0xf9, 0x69, 0x2d, 0x07, 0xfb, 0xaa, 0xba, 0x97, 0xd5, 0xb2, 0xa7, 0x82, 0x69, - 0x2a, 0xa1, 0xb1, 0x03, 0x2b, 0xb9, 0xc4, 0x48, 0xf9, 0xa9, 0xa5, 0xfd, 0x34, 0xde, 0xd6, 0xa1, - 0x65, 0xe2, 0xc0, 0xa3, 0x24, 0xc0, 0xe8, 0x21, 0xb4, 0xf1, 0xdc, 0xc6, 0xb2, 0xc6, 0xb5, 0x5c, - 0x8e, 0x4a, 0x9d, 0xe3, 0x48, 0xce, 0xf3, 0x3b, 0x56, 0x46, 0x3b, 0x0a, 0x9f, 0xf2, 0xa0, 0xa3, - 0x8c, 0xd2, 0x00, 0x75, 0x27, 0x02, 0xa8, 0x6a, 0xae, 0x40, 0xa5, 0x6e, 0x0e, 0xa1, 0x76, 0x14, - 0x42, 0xd5, 0x0a, 0x17, 0xce, 0x40, 0xd4, 0x5e, 0x06, 0xa2, 0xea, 0x85, 0xc7, 0x2f, 0xc1, 0xa8, - 0xbd, 0x0c, 0x46, 0x35, 0x0a, 0x4d, 0x4b, 0x40, 0xea, 0x7e, 0x0a, 0xa4, 0x9a, 0xb9, 0xda, 0x94, - 0x86, 0x05, 0x28, 0x75, 0x2f, 0x46, 0xa9, 0x56, 0x0e, 0xd7, 0x94, 0x49, 0x1e, 0xa6, 0xee, 0x44, - 0x30, 0xd5, 0x2e, 0x0c, 0x5a, 0x0e, 0xa7, 0xf6, 0x32, 0x38, 0x05, 0x85, 0xee, 0x94, 0x00, 0xd5, - 0xc7, 0x59, 0xa0, 0x92, 0x68, 0xb3, 0x95, 0xb3, 0x2d, 0x45, 0xaa, 0x0f, 0xd3, 0x48, 0xb5, 0x94, - 0xc3, 0x47, 0x95, 0x0b, 0xef, 0x84, 0xaa, 0x1d, 0x5e, 0x09, 0xb9, 0x4c, 0xe3, 0xb5, 0x88, 0x7d, - 0x9f, 0xfa, 0x0a, 0x4b, 0x24, 0x61, 0x6c, 0xf3, 0x8a, 0x4f, 0xf2, 0xeb, 0x1d, 0xb0, 0x26, 0xaa, - 0x36, 0x95, 0x5d, 0xc6, 0x37, 0x5a, 0x62, 0x2b, 0x90, 0x2d, 0x8d, 0x16, 0x6d, 0x85, 0x16, 0x29, - 0xb4, 0xab, 0x64, 0xd0, 0x0e, 0xdd, 0x86, 0xd5, 0xa9, 0x15, 0x30, 0xe9, 0xe6, 0x30, 0x03, 0x1f, - 0x2b, 0x5c, 0x20, 0xfd, 0x93, 0x38, 0xf2, 0x7f, 0x58, 0x4b, 0xe9, 0x5a, 0x9e, 0x37, 0x14, 0x45, - 0x5d, 0x13, 0x45, 0xad, 0xc7, 0xda, 0xfb, 0x9e, 0x77, 0x6a, 0x05, 0x13, 0xe3, 0x66, 0xe2, 0x7f, - 0x06, 0x49, 0xa7, 0x74, 0x1c, 0x21, 0xe9, 0x94, 0x8e, 0x8d, 0x2f, 0x13, 0xb5, 0x04, 0x34, 0xff, - 0x03, 0x35, 0x9b, 0x3a, 0xd2, 0xfb, 0xce, 0xee, 0x8a, 0x8a, 0xfb, 0x21, 0x75, 0xf0, 0x8b, 0x2b, - 0x0f, 0x9b, 0x42, 0x18, 0x7b, 0x5a, 0x49, 0xe1, 0xa2, 0x5a, 0xbf, 0x9a, 0xac, 0xff, 0x05, 0x07, - 0x90, 0x4c, 0xf6, 0xbe, 0xcf, 0xd5, 0xbf, 0xd3, 0x92, 0x0b, 0x91, 0x68, 0xfd, 0x8f, 0x16, 0xef, - 0x42, 0xdd, 0x25, 0x0e, 0x9e, 0x8b, 0xd5, 0xab, 0xa6, 0x24, 0xa2, 0x36, 0x53, 0x15, 0x3b, 0x66, - 0xdb, 0x8c, 0x0c, 0xb2, 0x24, 0x14, 0xa0, 0xd3, 0x91, 0x00, 0x86, 0x25, 0x53, 0x12, 0x29, 0x58, - 0x6c, 0x64, 0xe0, 0x5f, 0x1d, 0xba, 0x99, 0x1c, 0xfa, 0x73, 0xde, 0x82, 0xd2, 0xd5, 0xf9, 0x3e, - 0x23, 0xb2, 0x96, 0xdc, 0x67, 0x5c, 0x97, 0x46, 0x17, 0xd0, 0xf5, 0x82, 0x93, 0xad, 0x36, 0x5b, - 0x4a, 0xe8, 0xbf, 0x50, 0x77, 0xdc, 0xd1, 0xa8, 0xbc, 0xd9, 0x48, 0xb1, 0xf1, 0x6d, 0x05, 0x1a, - 0xb2, 0x55, 0xa0, 0x2d, 0x0e, 0x5b, 0x96, 0x4b, 0x86, 0xae, 0x13, 0x95, 0x8b, 0xa0, 0x07, 0x4e, - 0x2a, 0x26, 0x95, 0x4c, 0x4c, 0x10, 0xd4, 0x98, 0x3b, 0xc3, 0x2a, 0xd3, 0xc5, 0x37, 0xda, 0x84, - 0x26, 0x09, 0x67, 0x43, 0x36, 0x0f, 0x44, 0xb4, 0x6b, 0x66, 0x83, 0x84, 0xb3, 0x17, 0xf3, 0x00, - 0xed, 0xc2, 0x72, 0x2a, 0xef, 0x5d, 0x47, 0xe1, 0x71, 0x47, 0x1d, 0x4d, 0x9c, 0x7b, 0x70, 0x64, - 0x2e, 0xc6, 0x15, 0x30, 0x70, 0xd0, 0x36, 0x88, 0x82, 0x18, 0x4a, 0xcc, 0x93, 0x85, 0xd2, 0x10, - 0x71, 0xeb, 0x70, 0xbe, 0x02, 0x45, 0xde, 0x07, 0xff, 0x05, 0x6d, 0x1e, 0x49, 0xa9, 0xd2, 0x14, - 0x2a, 0x2d, 0xce, 0x10, 0xc2, 0x5b, 0xb0, 0x92, 0xf4, 0x56, 0xa9, 0xd2, 0x92, 0xab, 0x24, 0x6c, - 0xa1, 0xb8, 0x05, 0xad, 0xb8, 0x20, 0xdb, 0x42, 0xa3, 0x69, 0xa9, 0x3a, 0x1c, 0x40, 0x53, 0x1d, - 0xb1, 0xb0, 0x0f, 0xdf, 0x86, 0xba, 0x67, 0xf9, 0x2c, 0x50, 0xfd, 0x2e, 0x82, 0xe3, 0x33, 0xcb, - 0xe7, 0x03, 0x90, 0xea, 0xc6, 0x52, 0xc5, 0xd8, 0x83, 0xe5, 0x0c, 0x9f, 0x67, 0x22, 0xa3, 0xcc, - 0x9a, 0xaa, 0x4e, 0x2c, 0x89, 0x78, 0x9b, 0x4a, 0xb2, 0x8d, 0xb1, 0x07, 0xed, 0xf8, 0x0e, 0xf9, - 0xb5, 0x78, 0xe1, 0xf9, 0x13, 0x35, 0x52, 0x2d, 0x99, 0x8a, 0x12, 0x89, 0x4d, 0xdf, 0xa8, 0x91, - 0xa0, 0x66, 0x4a, 0xe2, 0xf6, 0xf7, 0x75, 0x68, 0x45, 0xa9, 0x88, 0x1a, 0x50, 0x79, 0xf6, 0x44, - 0x5f, 0x40, 0xab, 0xb0, 0x3c, 0x20, 0x0c, 0xfb, 0xc4, 0x9a, 0x1e, 0x73, 0x0c, 0xd5, 0x35, 0xce, - 0x3a, 0x26, 0x36, 0x75, 0x5c, 0x32, 0x96, 0xac, 0x0a, 0x5a, 0x82, 0xd6, 0x81, 0xe5, 0x3c, 0xa5, - 0xc4, 0xc6, 0x7a, 0x15, 0xe9, 0xb0, 0xf4, 0x92, 0x58, 0x21, 0x9b, 0x50, 0xdf, 0xfd, 0x1a, 0x3b, - 0x7a, 0x0d, 0xad, 0xc3, 0xea, 0x80, 0x04, 0xe1, 0x68, 0xe4, 0xda, 0x2e, 0x26, 0xec, 0x71, 0x48, - 0x9c, 0x40, 0xaf, 0x23, 0x04, 0x9d, 0x97, 0xe4, 0x82, 0xd0, 0x37, 0x44, 0xcd, 0x1e, 0x7a, 0x03, - 0xf5, 0xa0, 0x7b, 0x60, 0x05, 0xf8, 0x28, 0xf4, 0xa6, 0xae, 0x6d, 0x31, 0xbc, 0xef, 0x38, 0x3e, - 0x0e, 0x02, 0x1d, 0xf3, 0x45, 0xb8, 0x24, 0xbb, 0xf7, 0x28, 0x32, 0xc8, 0xac, 0x8f, 0x71, 0xa0, - 0x8f, 0xd1, 0x16, 0xac, 0x5f, 0x93, 0x88, 0x9d, 0x27, 0xe8, 0xdf, 0xd0, 0xcb, 0x8b, 0x4e, 0xac, - 0xe0, 0xcc, 0x77, 0x6d, 0xac, 0xbb, 0xa8, 0x0b, 0xba, 0x94, 0x8a, 0xdb, 0x1f, 0x10, 0x2f, 0x64, - 0xfa, 0x57, 0xd1, 0xfe, 0x8a, 0xfb, 0x2c, 0x64, 0x9c, 0x7d, 0x91, 0x63, 0x9f, 0x89, 0x08, 0xeb, - 0x53, 0xb4, 0x09, 0x6b, 0x29, 0xf6, 0x73, 0xee, 0x1f, 0x8f, 0xce, 0x2c, 0x39, 0xaf, 0x14, 0xb8, - 0x63, 0x62, 0xb1, 0xd0, 0xc7, 0x3a, 0x41, 0x1b, 0x80, 0xb8, 0x44, 0x85, 0x24, 0x72, 0x9c, 0x46, - 0x3b, 0x28, 0xbe, 0xda, 0xc1, 0xcb, 0xb3, 0xa7, 0xe1, 0xd8, 0x25, 0xfa, 0x6b, 0xb4, 0x0e, 0xfa, - 0x09, 0xbd, 0x54, 0xdc, 0x63, 0xc2, 0x5c, 0x76, 0xa5, 0xff, 0xa8, 0xa1, 0x2e, 0xac, 0x24, 0xec, - 0x13, 0x9f, 0x86, 0x9e, 0xfe, 0x93, 0x86, 0x36, 0x01, 0x25, 0xdc, 0x33, 0x9f, 0x7a, 0x34, 0xb0, - 0xa6, 0xfa, 0xcf, 0x1a, 0xda, 0x80, 0xd5, 0x13, 0x7a, 0x19, 0xdf, 0x82, 0x34, 0xf8, 0x25, 0x32, - 0x88, 0xf9, 0x9f, 0xe2, 0xd9, 0x39, 0xf6, 0xf5, 0x5f, 0x35, 0xb4, 0x05, 0xdd, 0xb4, 0x20, 0x5e, - 0xeb, 0x37, 0x4d, 0x9d, 0x28, 0x16, 0xbd, 0xa2, 0x0c, 0xeb, 0xbf, 0x47, 0x6c, 0x15, 0x07, 0xb5, - 0xd0, 0x1f, 0x1a, 0x5a, 0x83, 0x4e, 0xc2, 0x16, 0xba, 0x7f, 0x6a, 0xa8, 0x0f, 0xeb, 0x19, 0xa6, - 0x4b, 0xc6, 0x67, 0x3c, 0x69, 0xf5, 0xbf, 0xb4, 0xdd, 0xb7, 0x75, 0x58, 0xd9, 0x3f, 0x38, 0x1c, - 0xec, 0x7b, 0x72, 0x03, 0xde, 0xff, 0xee, 0x41, 0x4d, 0x74, 0xf8, 0x82, 0x67, 0x6f, 0xbf, 0x68, - 0xd4, 0x44, 0xbb, 0x50, 0x17, 0x8d, 0x1e, 0x15, 0xbd, 0x7e, 0xfb, 0x85, 0x13, 0x27, 0xdf, 0x44, - 0x8e, 0x02, 0xd7, 0x1f, 0xc1, 0xfd, 0xa2, 0xb1, 0x13, 0x7d, 0x02, 0xed, 0xa4, 0x45, 0x97, 0x3d, - 0x85, 0xfb, 0xa5, 0x03, 0x28, 0xb7, 0x4f, 0x7a, 0x77, 0xd9, 0x83, 0xb8, 0x5f, 0x3a, 0x85, 0xa2, - 0x87, 0xd0, 0x8c, 0x7a, 0x73, 0xf1, 0xb3, 0xb8, 0x5f, 0x32, 0x88, 0xf2, 0xf0, 0xc8, 0xb6, 0x5b, - 0xf4, 0xda, 0xed, 0x17, 0xce, 0x96, 0xe8, 0x01, 0x34, 0x54, 0xdb, 0x2b, 0x7c, 0x51, 0xf7, 0x8b, - 0x27, 0x58, 0xee, 0x64, 0xf2, 0x30, 0x2a, 0x7b, 0x2a, 0xf7, 0x4b, 0x67, 0x53, 0xb4, 0x0f, 0x90, - 0x7a, 0x12, 0x95, 0x3e, 0x98, 0xfb, 0xe5, 0x13, 0x2a, 0x7a, 0x04, 0xad, 0xe4, 0x15, 0x54, 0xfc, - 0x6c, 0xee, 0x97, 0x0d, 0xa9, 0xe7, 0x0d, 0xf1, 0x8f, 0xcc, 0xfd, 0xbf, 0x03, 0x00, 0x00, 0xff, - 0xff, 0xbd, 0xb6, 0xa5, 0xad, 0xa6, 0x11, 0x00, 0x00, + // 1755 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x49, 0x6f, 0xdb, 0xce, + 0x15, 0x37, 0x25, 0x6a, 0x7b, 0x96, 0x65, 0x7a, 0x2c, 0xdb, 0xb2, 0xd2, 0x43, 0xc2, 0x22, 0x8d, + 0x9d, 0xa6, 0x4e, 0xeb, 0x20, 0x45, 0xdc, 0x14, 0x05, 0xbc, 0xc5, 0x16, 0x82, 0x3a, 0x2e, 0xed, + 0xe4, 0xd2, 0x83, 0x40, 0x8b, 0x23, 0x69, 0x6a, 0x69, 0xc8, 0x90, 0x43, 0x47, 0xee, 0xa9, 0xbd, + 0xe7, 0xde, 0x8f, 0x50, 0xa0, 0xc7, 0x02, 0xfd, 0x0a, 0x05, 0xfe, 0xfb, 0xf2, 0x89, 0xfe, 0x98, + 0x85, 0xab, 0xa9, 0xe0, 0x7f, 0xc8, 0x85, 0x98, 0xb7, 0xcd, 0xbc, 0x99, 0x79, 0xef, 0xf7, 0x1e, + 0x07, 0x56, 0xd8, 0xad, 0x87, 0x83, 0xa7, 0xe2, 0xbb, 0xe3, 0xf9, 0x2e, 0x73, 0x51, 0x45, 0x10, + 0xe6, 0xff, 0x75, 0xa8, 0x59, 0xf8, 0x7d, 0x88, 0x03, 0x86, 0xb6, 0x40, 0xc7, 0x83, 0xb1, 0xdb, + 0xd1, 0xee, 0x6b, 0x5b, 0x8b, 0xbb, 0x68, 0x47, 0xaa, 0x2b, 0xe9, 0xf1, 0x60, 0xec, 0x9e, 0x2e, + 0x58, 0x42, 0x03, 0xfd, 0x1a, 0x2a, 0xc3, 0x49, 0x18, 0x8c, 0x3b, 0x25, 0xa1, 0xba, 0x9a, 0x55, + 0x7d, 0xc5, 0x45, 0xa7, 0x0b, 0x96, 0xd4, 0xe1, 0xd3, 0x12, 0x3a, 0x74, 0x3b, 0xe5, 0xa2, 0x69, + 0x7b, 0x74, 0x28, 0xa6, 0xe5, 0x1a, 0xe8, 0x05, 0x40, 0x80, 0x59, 0xdf, 0xf5, 0x18, 0x71, 0x69, + 0x47, 0x17, 0xfa, 0x1b, 0x59, 0xfd, 0x0b, 0xcc, 0xde, 0x08, 0xf1, 0xe9, 0x82, 0xd5, 0x08, 0x22, + 0x82, 0x5b, 0x3a, 0x78, 0x42, 0x6e, 0xb0, 0xdf, 0x67, 0xb3, 0x4e, 0xa5, 0xc8, 0xf2, 0x48, 0xca, + 0x2f, 0x67, 0xdc, 0xd2, 0x89, 0x08, 0xb4, 0x0b, 0xf5, 0xc1, 0x18, 0x0f, 0xae, 0xb9, 0x5d, 0x55, + 0xd8, 0xad, 0x65, 0xed, 0x0e, 0xb9, 0x54, 0x58, 0xd5, 0x06, 0x72, 0x88, 0x76, 0xa0, 0x3a, 0x70, + 0xa7, 0x53, 0xc2, 0x3a, 0x35, 0x61, 0xd1, 0xce, 0x59, 0x08, 0xd9, 0xe9, 0x82, 0xa5, 0xb4, 0xf8, + 0x71, 0xbd, 0x0f, 0xb1, 0x7f, 0xdb, 0xa9, 0x17, 0x1d, 0xd7, 0x5f, 0xb8, 0x88, 0x1f, 0x97, 0xd0, + 0xe1, 0x5b, 0x21, 0x94, 0xb0, 0xfe, 0x60, 0x6c, 0x13, 0xda, 0x69, 0x14, 0x6d, 0xa5, 0x47, 0x09, + 0x3b, 0xe4, 0x62, 0xbe, 0x15, 0x12, 0x11, 0xe8, 0x25, 0x2c, 0x5e, 0xe1, 0x11, 0xa1, 0xfd, 0xab, + 0x89, 0x3b, 0xb8, 0xee, 0x80, 0x30, 0xed, 0x64, 0x4d, 0x0f, 0xb8, 0xc2, 0x01, 0x97, 0x9f, 0x2e, + 0x58, 0x70, 0x15, 0x53, 0xe8, 0x39, 0x34, 0x30, 0x75, 0x94, 0xe9, 0xa2, 0x30, 0x5d, 0xcf, 0x45, + 0x00, 0x75, 0x22, 0xc3, 0x3a, 0x56, 0xe3, 0x83, 0x1a, 0x54, 0x6e, 0xec, 0x49, 0x88, 0xcd, 0x47, + 0xb0, 0x98, 0x8a, 0x14, 0xd4, 0x81, 0xda, 0x14, 0x07, 0x81, 0x3d, 0xc2, 0x22, 0x9c, 0x1a, 0x56, + 0x44, 0x9a, 0x2d, 0x68, 0xa6, 0xe3, 0x24, 0x65, 0xc8, 0x63, 0x81, 0x1b, 0xde, 0x60, 0x3f, 0xe0, + 0x01, 0xa0, 0x0c, 0x15, 0x69, 0xfe, 0x01, 0x8c, 0x7c, 0x10, 0x20, 0x03, 0xca, 0xd7, 0xf8, 0x56, + 0x69, 0xf2, 0x21, 0x6a, 0x2b, 0x87, 0x44, 0x68, 0x36, 0x2c, 0xe5, 0x9d, 0x19, 0xdb, 0xc6, 0x61, + 0x80, 0x5a, 0x50, 0x62, 0x33, 0x61, 0xda, 0xb4, 0x4a, 0x6c, 0x66, 0xde, 0x87, 0x56, 0xf6, 0xca, + 0xef, 0x68, 0x38, 0xb1, 0xeb, 0xe2, 0xce, 0x10, 0x02, 0xdd, 0xb1, 0x99, 0xad, 0x34, 0xc4, 0x98, + 0xf3, 0x3c, 0x9b, 0x8d, 0xd5, 0xf2, 0x62, 0x8c, 0xd6, 0xa1, 0x3a, 0xc6, 0x64, 0x34, 0x66, 0x22, + 0x07, 0x74, 0x4b, 0x51, 0xdc, 0x57, 0xcf, 0x77, 0x6f, 0xb0, 0x08, 0xf5, 0xba, 0x25, 0x09, 0x73, + 0x19, 0x96, 0x32, 0x81, 0x64, 0x1e, 0xc5, 0xce, 0xc7, 0x17, 0x8f, 0x7e, 0x0b, 0x70, 0x63, 0x4f, + 0x88, 0x63, 0x33, 0xd7, 0x0f, 0x3a, 0xda, 0xfd, 0xf2, 0xd6, 0xe2, 0xae, 0xa1, 0xee, 0xeb, 0x5d, + 0x24, 0xb0, 0x52, 0x3a, 0xe6, 0x19, 0xac, 0xdc, 0x89, 0x01, 0xee, 0xed, 0xd8, 0x0e, 0xc6, 0xd1, + 0x0e, 0xf8, 0x18, 0x3d, 0xe4, 0xde, 0xda, 0x0e, 0xf6, 0x55, 0x76, 0x2f, 0xa9, 0x69, 0x4f, 0x05, + 0xd3, 0x52, 0x42, 0x73, 0x1b, 0x96, 0x73, 0x81, 0x91, 0xda, 0xa7, 0x96, 0xde, 0xa7, 0xf9, 0xb1, + 0x02, 0x75, 0x0b, 0x07, 0x9e, 0x4b, 0x03, 0x8c, 0x5e, 0x40, 0x03, 0xcf, 0x06, 0x58, 0xe6, 0xb8, + 0x96, 0x8b, 0x51, 0xa9, 0x73, 0x1c, 0xc9, 0x79, 0x7c, 0xc7, 0xca, 0x68, 0x5b, 0xe1, 0x53, 0x1e, + 0x74, 0x94, 0x51, 0x1a, 0xa0, 0x9e, 0x44, 0x00, 0x55, 0xce, 0x25, 0xa8, 0xd4, 0xcd, 0x21, 0xd4, + 0xb6, 0x42, 0x28, 0xbd, 0x70, 0xe2, 0x0c, 0x44, 0xed, 0x65, 0x20, 0xaa, 0x52, 0xe8, 0xfe, 0x1c, + 0x8c, 0xda, 0xcb, 0x60, 0x54, 0xb5, 0xd0, 0x74, 0x0e, 0x48, 0x3d, 0x4b, 0x81, 0x54, 0x2d, 0x97, + 0x9b, 0xd2, 0xb0, 0x00, 0xa5, 0x9e, 0xc6, 0x28, 0x55, 0xcf, 0xe1, 0x9a, 0x32, 0xc9, 0xc3, 0xd4, + 0x93, 0x08, 0xa6, 0x1a, 0x85, 0x87, 0x96, 0xc3, 0xa9, 0xbd, 0x0c, 0x4e, 0x41, 0xe1, 0x76, 0xe6, + 0x00, 0xd5, 0x1f, 0xb3, 0x40, 0x25, 0xd1, 0x66, 0x33, 0x67, 0x3b, 0x17, 0xa9, 0x7e, 0x9f, 0x46, + 0xaa, 0x66, 0x0e, 0x1f, 0x55, 0x2c, 0x7c, 0x12, 0xaa, 0xb6, 0x79, 0x26, 0xe4, 0x22, 0x8d, 0xe7, + 0x22, 0xf6, 0x7d, 0xd7, 0x57, 0x58, 0x22, 0x09, 0x73, 0x8b, 0x67, 0x7c, 0x12, 0x5f, 0x9f, 0x80, + 0x35, 0x91, 0xb5, 0xa9, 0xe8, 0x32, 0xff, 0xa5, 0x25, 0xb6, 0x02, 0xd9, 0xd2, 0x68, 0xd1, 0x50, + 0x68, 0x91, 0x42, 0xbb, 0x52, 0x06, 0xed, 0xd0, 0x63, 0x58, 0x99, 0xd8, 0x01, 0x93, 0xdb, 0xec, + 0x67, 0xe0, 0x63, 0x99, 0x0b, 0xe4, 0xfe, 0x24, 0x8e, 0xfc, 0x06, 0x56, 0x53, 0xba, 0xb6, 0xe7, + 0xf5, 0x45, 0x52, 0xeb, 0x22, 0xa9, 0x8d, 0x58, 0x7b, 0xdf, 0xf3, 0x4e, 0xed, 0x60, 0x6c, 0x3e, + 0x4c, 0xf6, 0x9f, 0x41, 0xd2, 0x89, 0x3b, 0x8a, 0x90, 0x74, 0xe2, 0x8e, 0xcc, 0x7f, 0x6a, 0x89, + 0x5e, 0x82, 0x9a, 0xbf, 0x04, 0x7d, 0xe0, 0x3a, 0x72, 0xfb, 0xad, 0xdd, 0x65, 0x75, 0xf0, 0x87, + 0xae, 0x83, 0x2f, 0x6f, 0x3d, 0x6c, 0x09, 0x61, 0xbc, 0xd5, 0x52, 0x0a, 0x18, 0xd5, 0x02, 0xe5, + 0x78, 0x01, 0xf4, 0x00, 0x74, 0x66, 0x8f, 0x82, 0x8e, 0x2e, 0xd0, 0x2b, 0x82, 0x99, 0xd7, 0xef, + 0xce, 0x6d, 0xe2, 0x5b, 0x42, 0x64, 0xfe, 0x43, 0xe3, 0x28, 0x93, 0x09, 0xf1, 0xcf, 0xe9, 0x81, + 0x01, 0xe5, 0x91, 0x1d, 0x88, 0x83, 0xd2, 0x2d, 0x3e, 0xe4, 0x9c, 0x21, 0xc6, 0x22, 0xb1, 0x75, + 0x8b, 0x0f, 0xcd, 0xff, 0x6a, 0xc9, 0xcd, 0x4a, 0xd8, 0xff, 0x59, 0x0e, 0xb4, 0xa1, 0x42, 0xa8, + 0x83, 0x67, 0xc2, 0x83, 0xb2, 0x25, 0x89, 0xa8, 0x5e, 0x95, 0x85, 0x57, 0xd9, 0x7a, 0x25, 0x6f, + 0x4b, 0x12, 0xaa, 0x32, 0xb8, 0x43, 0xe1, 0x48, 0xd3, 0x92, 0x44, 0x0a, 0x5f, 0xab, 0x99, 0x3a, + 0xa2, 0x36, 0x56, 0x4b, 0xee, 0xee, 0xaf, 0xbc, 0x96, 0xa5, 0xd3, 0xfc, 0x33, 0x9e, 0x9a, 0xb9, + 0x9a, 0xc4, 0x45, 0x9c, 0xe0, 0x66, 0x1b, 0xd0, 0xdd, 0xcc, 0x95, 0x35, 0x3b, 0x9b, 0x93, 0xe8, + 0x57, 0x50, 0x71, 0xc8, 0x70, 0x38, 0xbf, 0x6a, 0x49, 0xb1, 0xf9, 0xef, 0x12, 0x54, 0x65, 0xcd, + 0x41, 0x9b, 0x1c, 0xff, 0x6c, 0x42, 0xfb, 0xc4, 0x89, 0xf2, 0x4e, 0xd0, 0x3d, 0x27, 0x75, 0x26, + 0xa5, 0xcc, 0x99, 0x20, 0xd0, 0x19, 0x99, 0x62, 0x95, 0x32, 0x62, 0x8c, 0x36, 0xa0, 0x46, 0xc3, + 0x69, 0x9f, 0xcd, 0xa2, 0x2b, 0xaf, 0xd2, 0x70, 0x7a, 0x39, 0x0b, 0xd0, 0x2e, 0x2c, 0xa5, 0x12, + 0x88, 0x38, 0x0a, 0xd8, 0x5b, 0xca, 0x35, 0xe1, 0x77, 0xef, 0xc8, 0x5a, 0x8c, 0x53, 0xa9, 0xe7, + 0xa0, 0x2d, 0x10, 0x99, 0xd5, 0x97, 0xe0, 0x29, 0x33, 0xae, 0x2a, 0xce, 0xad, 0xc5, 0xf9, 0x0a, + 0x5d, 0x79, 0x41, 0xbd, 0x07, 0x0d, 0x7e, 0x92, 0x52, 0xa5, 0x26, 0x54, 0xea, 0x9c, 0x21, 0x84, + 0x8f, 0x60, 0x39, 0x29, 0xd2, 0x52, 0xa5, 0x2e, 0x67, 0x49, 0xd8, 0x42, 0x71, 0x13, 0xea, 0x71, + 0x66, 0x37, 0x84, 0x46, 0xcd, 0x56, 0x09, 0xdd, 0x83, 0x9a, 0x72, 0xb1, 0xb0, 0xa0, 0x3f, 0x86, + 0x8a, 0x67, 0xfb, 0x2c, 0x50, 0x85, 0x33, 0xc2, 0xf5, 0x73, 0xdb, 0xe7, 0x9d, 0x94, 0x2a, 0xeb, + 0x52, 0xc5, 0xdc, 0x83, 0xa5, 0x0c, 0x9f, 0x47, 0x22, 0x73, 0x99, 0x3d, 0x51, 0x25, 0x5d, 0x12, + 0xf1, 0x32, 0xa5, 0x64, 0x19, 0x73, 0x0f, 0x1a, 0xf1, 0x1d, 0xf2, 0x6b, 0xf1, 0xc2, 0xab, 0xd7, + 0xaa, 0x37, 0x6b, 0x5a, 0x8a, 0x12, 0x81, 0xed, 0x7e, 0x50, 0xbd, 0x85, 0x6e, 0x49, 0xc2, 0xfc, + 0x8f, 0x06, 0x55, 0x99, 0xf7, 0x05, 0x1d, 0xdd, 0xef, 0x44, 0xab, 0x13, 0xe2, 0x3e, 0x77, 0x5b, + 0xd8, 0xb5, 0xe2, 0xbf, 0x08, 0x69, 0xb4, 0x23, 0x42, 0xb8, 0x21, 0xb4, 0xf8, 0x10, 0x3d, 0x80, + 0xa6, 0x34, 0x09, 0x98, 0x4f, 0x68, 0x14, 0xbc, 0x8b, 0x82, 0x77, 0x21, 0x58, 0xfc, 0x52, 0xa4, + 0x0a, 0xa1, 0x4c, 0x44, 0x43, 0xd9, 0xaa, 0x0b, 0x46, 0x8f, 0x32, 0xf3, 0x1e, 0xe8, 0x62, 0x1e, + 0x80, 0xea, 0xc5, 0xa5, 0xd5, 0x3b, 0x3b, 0x31, 0x16, 0x50, 0x0d, 0xca, 0xbd, 0xb3, 0x4b, 0x43, + 0x7b, 0xfc, 0xbf, 0x0a, 0xd4, 0xa3, 0xbc, 0x41, 0x55, 0x28, 0xbd, 0x79, 0x6d, 0x2c, 0xa0, 0x15, + 0x58, 0xea, 0x51, 0x86, 0x7d, 0x6a, 0x4f, 0x8e, 0x79, 0xe5, 0x30, 0x34, 0xce, 0x3a, 0xa6, 0x03, + 0xd7, 0x21, 0x74, 0x24, 0x59, 0x25, 0xd4, 0x84, 0xfa, 0x81, 0xed, 0x9c, 0xb9, 0x74, 0x80, 0x8d, + 0x32, 0x32, 0xa0, 0xf9, 0x96, 0xda, 0x21, 0x1b, 0xbb, 0x3e, 0xf9, 0x3b, 0x76, 0x0c, 0x1d, 0xad, + 0xc1, 0x4a, 0x8f, 0x06, 0xe1, 0x70, 0x48, 0x06, 0x04, 0x53, 0xf6, 0x2a, 0xa4, 0x4e, 0x60, 0x54, + 0x10, 0x82, 0xd6, 0x5b, 0x7a, 0x4d, 0xdd, 0x0f, 0x54, 0x75, 0x5c, 0x46, 0x15, 0x75, 0xa0, 0x7d, + 0x60, 0x07, 0xf8, 0x28, 0xf4, 0x26, 0x64, 0x60, 0x33, 0xbc, 0xef, 0x38, 0x3e, 0x0e, 0x02, 0x03, + 0xf3, 0x49, 0xb8, 0x24, 0xbb, 0xf6, 0x30, 0x32, 0xc8, 0xcc, 0x8f, 0x71, 0x60, 0x8c, 0xd0, 0x26, + 0xac, 0xdd, 0x91, 0x88, 0x95, 0xc7, 0xe8, 0x17, 0xd0, 0xc9, 0x8b, 0x4e, 0xec, 0xe0, 0xdc, 0x27, + 0x03, 0x6c, 0x10, 0xd4, 0x06, 0x43, 0x4a, 0x45, 0xa8, 0xf6, 0xa8, 0x17, 0x32, 0xe3, 0x6f, 0xd1, + 0xfa, 0x8a, 0xfb, 0x26, 0x64, 0x9c, 0x7d, 0x9d, 0x63, 0x9f, 0x8b, 0x70, 0x30, 0x26, 0x68, 0x03, + 0x56, 0x53, 0xec, 0x0b, 0xbe, 0x3f, 0x7e, 0x3a, 0xd3, 0xc4, 0x5f, 0x29, 0x20, 0x23, 0x6a, 0xb3, + 0xd0, 0xc7, 0x06, 0x45, 0xeb, 0x80, 0xb8, 0x44, 0x1d, 0x49, 0xb4, 0x71, 0x37, 0x5a, 0x41, 0xf1, + 0xd5, 0x0a, 0x5e, 0x9e, 0x3d, 0x09, 0x47, 0x84, 0x1a, 0xef, 0xd1, 0x1a, 0x18, 0x27, 0xee, 0x8d, + 0xe2, 0x1e, 0x53, 0x46, 0xd8, 0xad, 0xf1, 0x85, 0x86, 0xda, 0xb0, 0x9c, 0xb0, 0x4f, 0x7c, 0x37, + 0xf4, 0x8c, 0x2f, 0x35, 0xb4, 0x01, 0x28, 0xe1, 0x9e, 0xfb, 0xae, 0xe7, 0x06, 0xf6, 0xc4, 0xf8, + 0x4a, 0x43, 0xeb, 0xb0, 0x72, 0xe2, 0xde, 0xc4, 0xb7, 0x20, 0x0d, 0xbe, 0x8e, 0x0c, 0x62, 0xfe, + 0x9f, 0xf1, 0xf4, 0x0a, 0xfb, 0xc6, 0x37, 0x1a, 0xda, 0x84, 0x76, 0x5a, 0x10, 0xcf, 0xf5, 0xad, + 0xa6, 0x3c, 0x8a, 0x45, 0xef, 0x5c, 0x86, 0x8d, 0xef, 0x22, 0xb6, 0x3a, 0x07, 0x35, 0xd1, 0xf7, + 0x1a, 0x5a, 0x85, 0x56, 0xc2, 0x16, 0xba, 0x3f, 0x68, 0xa8, 0x0b, 0x6b, 0x19, 0x26, 0xa1, 0xa3, + 0x73, 0x9e, 0x61, 0xc6, 0x8f, 0xda, 0xee, 0xc7, 0x0a, 0x2c, 0xef, 0x1f, 0x1c, 0xf6, 0xf6, 0x3d, + 0xb9, 0x00, 0xaf, 0xfa, 0x4f, 0x41, 0x17, 0x7d, 0x4d, 0xc1, 0xcf, 0x7e, 0xb7, 0xa8, 0xc1, 0x46, + 0xbb, 0x50, 0x11, 0xed, 0x0d, 0x2a, 0xfa, 0xe7, 0xef, 0x16, 0xf6, 0xd9, 0x7c, 0x11, 0xd9, 0x00, + 0xdd, 0xfd, 0xf5, 0xef, 0x16, 0x35, 0xdb, 0xe8, 0x4f, 0xd0, 0x48, 0x1a, 0x93, 0x79, 0x0f, 0x00, + 0xdd, 0xb9, 0x6d, 0x37, 0xb7, 0x4f, 0x1a, 0x96, 0x79, 0xcf, 0x00, 0xdd, 0xb9, 0xbd, 0x37, 0x7a, + 0x01, 0xb5, 0xa8, 0xd9, 0x28, 0x7e, 0x0c, 0xe8, 0xce, 0x69, 0xbf, 0xf9, 0xf1, 0xc8, 0x1e, 0xa1, + 0xe8, 0x1f, 0xbf, 0x5b, 0xd8, 0x51, 0xa3, 0xe7, 0x50, 0x55, 0x35, 0xba, 0xf0, 0x1d, 0xa1, 0x5b, + 0xdc, 0xb7, 0xf3, 0x4d, 0x26, 0xbf, 0x83, 0xf3, 0x1e, 0x08, 0xba, 0x73, 0x3b, 0x72, 0xb4, 0x0f, + 0x90, 0xfa, 0x11, 0x9c, 0xfb, 0x4c, 0xd0, 0x9d, 0xdf, 0x97, 0xa3, 0x97, 0x50, 0x4f, 0xfe, 0xfd, + 0x8a, 0x1f, 0x0b, 0xba, 0xf3, 0x5a, 0xf3, 0xab, 0xaa, 0x78, 0x87, 0x7a, 0xf6, 0x53, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x3c, 0xa1, 0xc6, 0x00, 0x9c, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 802d8fc5c..7b2c75e32 100644 --- a/types/types.proto +++ b/types/types.proto @@ -7,42 +7,42 @@ package types; // Code types enum CodeType { - OK = 0; - - // General response codes, 0 ~ 99 - InternalError = 1; - EncodingError = 2; - BadNonce = 3; - Unauthorized = 4; - InsufficientFunds = 5; - UnknownRequest = 6; - - // Reserved for basecoin, 100 ~ 199 - BaseDuplicateAddress = 101; - BaseEncodingError = 102; - BaseInsufficientFees = 103; - BaseInsufficientFunds = 104; - BaseInsufficientGasPrice = 105; - BaseInvalidInput = 106; - BaseInvalidOutput = 107; - BaseInvalidPubKey = 108; - BaseInvalidSequence = 109; - BaseInvalidSignature = 110; - BaseUnknownAddress = 111; - BaseUnknownPubKey = 112; - BaseUnknownPlugin = 113; - - // Reserved for governance, 200 ~ 299 - GovUnknownEntity = 201; - GovUnknownGroup = 202; - GovUnknownProposal = 203; - GovDuplicateGroup = 204; - GovDuplicateMember = 205; - GovDuplicateProposal = 206; - GovDuplicateVote = 207; - GovInvalidMember = 208; - GovInvalidVote = 209; - GovInvalidVotingPower = 210; + OK = 0; + + // General response codes, 0 ~ 99 + InternalError = 1; + EncodingError = 2; + BadNonce = 3; + Unauthorized = 4; + InsufficientFunds = 5; + UnknownRequest = 6; + + // Reserved for basecoin, 100 ~ 199 + BaseDuplicateAddress = 101; + BaseEncodingError = 102; + BaseInsufficientFees = 103; + BaseInsufficientFunds = 104; + BaseInsufficientGasPrice = 105; + BaseInvalidInput = 106; + BaseInvalidOutput = 107; + BaseInvalidPubKey = 108; + BaseInvalidSequence = 109; + BaseInvalidSignature = 110; + BaseUnknownAddress = 111; + BaseUnknownPubKey = 112; + BaseUnknownPlugin = 113; + + // Reserved for governance, 200 ~ 299 + GovUnknownEntity = 201; + GovUnknownGroup = 202; + GovUnknownProposal = 203; + GovDuplicateGroup = 204; + GovDuplicateMember = 205; + GovDuplicateProposal = 206; + GovDuplicateVote = 207; + GovInvalidMember = 208; + GovInvalidVote = 209; + GovInvalidVotingPower = 210; } @@ -50,66 +50,66 @@ enum CodeType { // Request types message Request { - oneof value{ - RequestEcho echo = 1; - RequestFlush flush = 2; - RequestInfo info = 3; - RequestSetOption set_option = 4; - RequestDeliverTx deliver_tx = 5; - RequestCheckTx check_tx = 6; - RequestCommit commit = 7; - RequestQuery query = 8; - RequestInitChain init_chain = 9; - RequestBeginBlock begin_block = 10; - RequestEndBlock end_block = 11; - } + oneof value{ + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestDeliverTx deliver_tx = 5; + RequestCheckTx check_tx = 6; + RequestCommit commit = 7; + RequestQuery query = 8; + RequestInitChain init_chain = 9; + RequestBeginBlock begin_block = 10; + RequestEndBlock end_block = 11; + } } message RequestEcho { - string message = 1; + string message = 1; } message RequestFlush { } message RequestInfo { - string version = 1; + string version = 1; } message RequestSetOption{ - string key = 1; - string value = 2; + string key = 1; + string value = 2; } message RequestDeliverTx{ - bytes tx = 1; + bytes tx = 1; } message RequestCheckTx{ - bytes tx = 1; + bytes tx = 1; } message RequestQuery{ - bytes data = 1; - string path = 2; - uint64 height = 3; - bool prove = 4; + bytes data = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; } message RequestCommit{ } message RequestInitChain{ - repeated Validator validators = 1; + repeated Validator validators = 1; } message RequestBeginBlock{ - bytes hash = 1; - Header header = 2; + bytes hash = 1; + Header header = 2; } message RequestEndBlock{ - uint64 height = 1; + uint64 height = 1; } //---------------------------------------- @@ -117,70 +117,73 @@ message RequestEndBlock{ message Response { - oneof value{ - ResponseException exception = 1; - ResponseEcho echo = 2; - ResponseFlush flush = 3; - ResponseInfo info = 4; - ResponseSetOption set_option = 5; - ResponseDeliverTx deliver_tx = 6; - ResponseCheckTx check_tx = 7; - ResponseCommit commit = 8; - ResponseQuery query = 9; - ResponseInitChain init_chain = 10; - ResponseBeginBlock begin_block = 11; - ResponseEndBlock end_block = 12; - } + oneof value{ + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseDeliverTx deliver_tx = 6; + ResponseCheckTx check_tx = 7; + ResponseCommit commit = 8; + ResponseQuery query = 9; + ResponseInitChain init_chain = 10; + ResponseBeginBlock begin_block = 11; + ResponseEndBlock end_block = 12; + } } message ResponseException{ - string error = 1; + string error = 1; } message ResponseEcho { - string message = 1; + string message = 1; } message ResponseFlush{ } message ResponseInfo { - string data = 1; - string version = 2; - uint64 last_block_height = 3; - bytes last_block_app_hash = 4; + string data = 1; + string version = 2; + uint64 last_block_height = 3; + bytes last_block_app_hash = 4; } message ResponseSetOption{ - string log = 1; + string log = 1; } message ResponseDeliverTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; + repeated KVPair tags = 4; } message ResponseCheckTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; + uint64 gas = 4; + uint64 fee = 5; } message ResponseQuery{ - CodeType code = 1; - int64 index = 2; - bytes key = 3; - bytes value = 4; - bytes proof = 5; - uint64 height = 6; - string log = 7; + CodeType code = 1; + int64 index = 2; + bytes key = 3; + bytes value = 4; + bytes proof = 5; + uint64 height = 6; + string log = 7; } message ResponseCommit{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } @@ -191,52 +194,66 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 1; + repeated Validator diffs = 1; } //---------------------------------------- // Blockchain Types message Header { - string chain_id = 1; - uint64 height = 2; - uint64 time = 3; - uint64 num_txs = 4; - BlockID last_block_id = 5; - bytes last_commit_hash = 6; - bytes data_hash = 7; - bytes validators_hash = 8; - bytes app_hash = 9; + string chain_id = 1; + uint64 height = 2; + uint64 time = 3; + uint64 num_txs = 4; + BlockID last_block_id = 5; + bytes last_commit_hash = 6; + bytes data_hash = 7; + bytes validators_hash = 8; + bytes app_hash = 9; } message BlockID { - bytes hash = 1; - PartSetHeader parts = 2; + bytes hash = 1; + PartSetHeader parts = 2; } message PartSetHeader { - uint64 total = 1; - bytes hash = 2; + uint64 total = 1; + bytes hash = 2; } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; +} + +//---------------------------------------- +// Abstract types + +message KVPair { + string key = 1; + enum Type { + STRING = 0; + INT = 1; + } + Type value_type = 2; + string value_string = 3; + int64 value_int = 4; } //---------------------------------------- // Service Definition service ABCIApplication { - rpc Echo(RequestEcho) returns (ResponseEcho) ; - rpc Flush(RequestFlush) returns (ResponseFlush); - rpc Info(RequestInfo) returns (ResponseInfo); - rpc SetOption(RequestSetOption) returns (ResponseSetOption); - rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); - rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); - rpc Query(RequestQuery) returns (ResponseQuery); - rpc Commit(RequestCommit) returns (ResponseCommit); - rpc InitChain(RequestInitChain) returns (ResponseInitChain); - rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); - rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); + rpc Echo(RequestEcho) returns (ResponseEcho) ; + rpc Flush(RequestFlush) returns (ResponseFlush); + rpc Info(RequestInfo) returns (ResponseInfo); + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + rpc Query(RequestQuery) returns (ResponseQuery); + rpc Commit(RequestCommit) returns (ResponseCommit); + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); }