diff --git a/.gitignore b/.gitignore index d2d414be4..920af7622 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.swo *.pyc +vendor diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..6f5cf42cb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,171 @@ +# Changelog + +## 0.4.0 (March 6, 2017) + +BREAKING CHANGES: + +- Query takes RequestQuery and returns ResponseQuery. The request is split into `data` and `path`, +can specify a height to query the state from, and whether or not the response should come with a proof. +The response returns the corresponding key-value pair, with proof if requested. + +``` +message RequestQuery{ + bytes data = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; +} + +message ResponseQuery{ + CodeType code = 1; + int64 index = 2; + bytes key = 3; + bytes value = 4; + bytes proof = 5; + uint64 height = 6; + string log = 7; +} +``` + +IMPROVEMENTS: + +- Updates to Makefile +- Various cleanup +- BaseApplication can be embedded by new apps to avoid implementing empty methods +- Drop BlockchainAware and make BeginBlock/EndBlock part of the `type Application interface` + +## 0.3.0 (January 12, 2017) + +BREAKING CHANGES: + +- TMSP is now ABCI (Application/Asynchronous/A BlockChain Interface or Atomic BroadCast Interface) +- AppendTx is now DeliverTx (conforms to the literature) +- BeginBlock takes a Header: + +``` +message RequestBeginBlock{ + bytes hash = 1; + Header header = 2; +} +``` + +- Info returns a ResponseInfo, containing last block height and app hash: + +``` +message ResponseInfo { + string data = 1; + string version = 2; + uint64 last_block_height = 3; + bytes last_block_app_hash = 4; +} +``` + +- EndBlock returns a ResponseEndBlock, containing the changed validators: + +``` +message ResponseEndBlock{ + repeated Validator diffs = 4; +} +``` + +- Hex strings are 0x-prefixed in the CLI +- Query on the Dummy app now uses hex-strings + +FEATURES: + +- New app, PersistentDummy, uses Info/BeginBlock to recover from failures and supports validator set changes +- New message types for blockchain data: + +``` +//---------------------------------------- +// 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; +} + +message BlockID { + bytes hash = 1; + PartSetHeader parts = 2; +} + +message PartSetHeader { + uint64 total = 1; + bytes hash = 2; +} + +message Validator { + bytes pubKey = 1; + uint64 power = 2; +} +``` + +- Add support for Query to Counter app + +IMPROVEMENT: + +- Don't exit the tmsp-cli console on bad args + +BUG FIXES: + +- Fix parsing in the Counter app to handle invalid transactions + + +## 0.2.1 (September 12, 2016) + +IMPROVEMENTS + +- Better error handling in console + + +## 0.2.0 (July 23, 2016) + +BREAKING CHANGES: + +- Use `oneof` types in protobuf + +FEATURES: + +- GRPC support + + +## PreHistory + +##### Mar 26h, 2016 +* Introduce BeginBlock + +##### Mar 6th, 2016 + +* Added InitChain, EndBlock + +##### Feb 14th, 2016 + +* s/GetHash/Commit/g +* Document Protobuf request/response fields + +##### Jan 23th, 2016 + +* Added CheckTx/Query ABCI message types +* Added Result/Log fields to DeliverTx/CheckTx/SetOption +* Removed Listener messages +* Removed Code from ResponseSetOption and ResponseGetHash +* Made examples BigEndian + +##### Jan 12th, 2016 + +* Added "RetCodeBadNonce = 0x06" return code + +##### Jan 8th, 2016 + +* Tendermint/ABCI now comes to consensus on the order first before DeliverTx. + + + diff --git a/Makefile b/Makefile index d80410ff1..31236551f 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,42 @@ -.PHONY: all test get_deps +.PHONY: all build test fmt lint get_deps all: protoc install test NOVENDOR = go list github.com/tendermint/abci/... | grep -v /vendor/ +install-protoc: + # Download: https://github.com/google/protobuf/releases + go get github.com/golang/protobuf/protoc-gen-go + protoc: - protoc --go_out=plugins=grpc:. types/*.proto + @ protoc --go_out=plugins=grpc:. types/*.proto install: - go install github.com/tendermint/abci/cmd/... + @ go install github.com/tendermint/abci/cmd/... + +build: + @ go build -i github.com/tendermint/abci/cmd/... + +# test.sh requires that we run the installed cmds, must not be out of date +test: install + find . -name test.sock -exec rm {} \; + @ go test -p 1 `${NOVENDOR}` + @ bash tests/test.sh + +fmt: + @ go fmt ./... -test: - go test `${NOVENDOR}` - bash tests/test.sh +lint: + @ go get -u github.com/golang/lint/golint + @ for file in $$(find "." -name '*.go' | grep -v '/vendor/' | grep -v '\.pb\.go'); do \ + golint -set_exit_status $${file}; \ + done; test_integrations: get_vendor_deps install test get_deps: - go get -d `${NOVENDOR}` + @ go get -d `${NOVENDOR}` get_vendor_deps: - go get github.com/Masterminds/glide - glide install + @ go get github.com/Masterminds/glide + @ glide install diff --git a/README.md b/README.md index 40efc50c5..2159f3cbf 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,14 @@ Other implementations: The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers. -As a [Go interface](https://github.com/tendermint/abci/blob/master/types/application.go), it might look like: + - The Protobuf file defining ABCI message types, and the optional GRPC interface. To build, run `make protoc` + - See `protoc --help` and [the GRPC docs](https://www.grpc.io/docs) for examples and details of other languages. +TendermintCore runs a client, and the ABCI application runs a server. There are three Golang implementation of ABCI client and server. + +1. ABCI-socket: Asynchronous, ordered message passing over Unix or TCP sockets. Messages are serialized using Protobuf and length prefixed. +2. GRPC: Synchronous (slow) implementation using GRPC. +3. Golang in-process: If the ABCI appliation is written in Golang, it is possible to compile both TendermintCore and the application as one binary. ```golang // Applications @@ -66,7 +72,7 @@ type ResponseEndBlock struct { Diffs []*Validator } -``` +_TODO: merge information from https://tendermint.com/blog/tendermint-0-8-release_ ## Message Types @@ -93,13 +99,13 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil Validate a mempool transaction, prior to broadcasting or proposing. This message should not mutate the main state, but application developers may want to keep a separate CheckTx state that gets reset upon Commit. - CheckTx can happen interspersed with DeliverTx, but they happen on different connections - CheckTx from the mempool connection, and DeliverTx from the consensus connection. During Commit, the mempool is locked, so you can reset the mempool state to the latest state after running all those delivertxs, and then the mempool will re run whatever txs it has against that latest mempool stte + CheckTx can happen interspersed with DeliverTx, but they happen on different connections - CheckTx from the mempool connection, and DeliverTx from the consensus connection. During Commit, the mempool is locked, so you can reset the mempool state to the latest state after running all those delivertxs, and then the mempool will re-run whatever txs it has against that latest mempool state. Transactions are first run through CheckTx before broadcast to peers in the mempool layer. You can make CheckTx semi-stateful and clear the state upon `Commit` or `BeginBlock`, to allow for dependent sequences of transactions in the same block. -#### Commit +#### Commit * __Returns__: * `Data ([]byte)`: The Merkle root hash * `Log (string)`: Debug or error message @@ -108,11 +114,20 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil #### Query * __Arguments__: - * `Data ([]byte)`: The query request bytes + * `Data ([]byte)`: Raw query bytes. Can be used with or in lieu of Path. + * `Path (string)`: Path of request, like an HTTP GET path. Can be used with or in liue of Data. + * Apps MUST interpret '/store' as a query by key on the underlying store. The key SHOULD be specified in the Data field. + * Apps SHOULD allow queries over specific types like '/accounts/...' or '/votes/...' + * `Height (uint64)`: The block height for which you want the query (default=0 returns data for the latest committed block). Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 + * `Prove (bool)`: Return Merkle proof with response if possible * __Returns__: * `Code (uint32)`: Response code - * `Data ([]byte)`: The query response bytes + * `Key ([]byte)`: The key of the matching data + * `Value ([]byte)`: The value of the matching data + * `Proof ([]byte)`: Proof for the data, if requested + * `Height (uint64)`: The block height from which data was derived. Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 * `Log (string)`: Debug or error message + *Please note* The current implementation of go-merkle doesn't support querying proofs from past blocks, so for the present moment, any height other than 0 will return an error (recall height=0 defaults to latest block). Hopefully this will be improved soon(ish) #### Info * __Returns__: @@ -142,7 +157,7 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil #### BeginBlock * __Arguments__: - * `Hash ([]byte)`: The block height that is starting + * `Hash ([]byte)`: The block's hash. This can be derived from the block header. * `Header (struct{})`: The block header * __Usage__:
Signals the beginning of a new block. Called prior to any DeliverTxs. The header is expected to at least contain the Height. diff --git a/client/client.go b/client/client.go index 8ea295937..38fff4863 100644 --- a/client/client.go +++ b/client/client.go @@ -4,12 +4,12 @@ import ( "fmt" "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) type Client interface { - Service + cmn.Service SetResponseCallback(Callback) Error() error @@ -20,7 +20,7 @@ type Client interface { SetOptionAsync(key string, value string) *ReqRes DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes - QueryAsync(tx []byte) *ReqRes + QueryAsync(reqQuery types.RequestQuery) *ReqRes CommitAsync() *ReqRes FlushSync() error @@ -29,7 +29,7 @@ type Client interface { SetOptionSync(key string, value string) (res types.Result) DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) - QuerySync(tx []byte) (res types.Result) + QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) CommitSync() (res types.Result) InitChainAsync(validators []*types.Validator) *ReqRes diff --git a/client/grpc_client.go b/client/grpc_client.go index 566ee183e..7cca5079a 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -1,6 +1,7 @@ package abcicli import ( + "fmt" "net" "sync" "time" @@ -8,14 +9,14 @@ import ( context "golang.org/x/net/context" grpc "google.golang.org/grpc" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) // A stripped copy of the remoteClient that makes // synchronous calls using grpc type grpcClient struct { - BaseService + cmn.BaseService mustConnect bool client types.ABCIApplicationClient @@ -31,13 +32,13 @@ func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { addr: addr, mustConnect: mustConnect, } - cli.BaseService = *NewBaseService(nil, "grpcClient", cli) + cli.BaseService = *cmn.NewBaseService(nil, "grpcClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err } func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { - return Connect(addr) + return cmn.Connect(addr) } func (cli *grpcClient) OnStart() error { @@ -49,11 +50,10 @@ RETRY_LOOP: if err != nil { if cli.mustConnect { return err - } else { - log.Warn(Fmt("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) - time.Sleep(time.Second * 3) - continue RETRY_LOOP } + log.Warn(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) + time.Sleep(time.Second * 3) + continue RETRY_LOOP } client := types.NewABCIApplicationClient(conn) @@ -93,7 +93,7 @@ func (cli *grpcClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(Fmt("Stopping abci.grpcClient for error: %v", err.Error())) + log.Warn(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error())) cli.Stop() } @@ -173,8 +173,8 @@ func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_CheckTx{res}}) } -func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { - req := types.ToRequestQuery(query) +func (cli *grpcClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { + req := types.ToRequestQuery(reqQuery) res, err := cli.client.Query(context.Background(), req.GetQuery(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -255,7 +255,7 @@ func (cli *grpcClient) EchoSync(msg string) (res types.Result) { return res } resp := reqres.Response.GetEcho() - return types.NewResultOK([]byte(resp.Message), LOG) + return types.NewResultOK([]byte(resp.Message), "") } func (cli *grpcClient) FlushSync() error { @@ -267,11 +267,10 @@ func (cli *grpcClient) InfoSync() (resInfo types.ResponseInfo, err error) { if err = cli.Error(); err != nil { return resInfo, err } - if resInfo_ := reqres.Response.GetInfo(); resInfo_ != nil { - return *resInfo_, nil - } else { - return resInfo, nil + if info := reqres.Response.GetInfo(); info != nil { + return *info, nil } + return resInfo, nil } func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { @@ -301,13 +300,15 @@ func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *grpcClient) QuerySync(query []byte) (res types.Result) { - reqres := cli.QueryAsync(query) - if res := cli.checkErrGetResult(); res.IsErr() { - return res +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 } - resp := reqres.Response.GetQuery() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { + return *resQuery_, nil + } + return resQuery, nil } func (cli *grpcClient) CommitSync() (res types.Result) { @@ -334,9 +335,8 @@ func (cli *grpcClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEn if err := cli.Error(); err != nil { return resEndBlock, err } - if resEndBlock_ := reqres.Response.GetEndBlock(); resEndBlock_ != nil { - return *resEndBlock_, nil - } else { - return resEndBlock, nil + if blk := reqres.Response.GetEndBlock(); blk != nil { + return *blk, nil } + return resEndBlock, nil } diff --git a/client/local_client.go b/client/local_client.go index b787eb365..1150db4a1 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -3,12 +3,12 @@ package abcicli import ( "sync" - . "github.com/tendermint/go-common" types "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) type localClient struct { - BaseService + cmn.BaseService mtx *sync.Mutex types.Application Callback @@ -22,7 +22,7 @@ func NewLocalClient(mtx *sync.Mutex, app types.Application) *localClient { mtx: mtx, Application: app, } - cli.BaseService = *NewBaseService(log, "localClient", cli) + cli.BaseService = *cmn.NewBaseService(log, "localClient", cli) return cli } @@ -89,13 +89,13 @@ func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { ) } -func (app *localClient) QueryAsync(tx []byte) *ReqRes { +func (app *localClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { app.mtx.Lock() - res := app.Application.Query(tx) + resQuery := app.Application.Query(reqQuery) app.mtx.Unlock() return app.callback( - types.ToRequestQuery(tx), - types.ToResponseQuery(res.Code, res.Data, res.Log), + types.ToRequestQuery(reqQuery), + types.ToResponseQuery(resQuery), ) } @@ -111,9 +111,7 @@ func (app *localClient) CommitAsync() *ReqRes { func (app *localClient) InitChainAsync(validators []*types.Validator) *ReqRes { app.mtx.Lock() - if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.InitChain(validators) - } + app.Application.InitChain(validators) reqRes := app.callback( types.ToRequestInitChain(validators), types.ToResponseInitChain(), @@ -124,9 +122,7 @@ func (app *localClient) InitChainAsync(validators []*types.Validator) *ReqRes { func (app *localClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { app.mtx.Lock() - if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.BeginBlock(hash, header) - } + app.Application.BeginBlock(hash, header) app.mtx.Unlock() return app.callback( types.ToRequestBeginBlock(hash, header), @@ -136,10 +132,7 @@ func (app *localClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqR func (app *localClient) EndBlockAsync(height uint64) *ReqRes { app.mtx.Lock() - var resEndBlock types.ResponseEndBlock - if bcApp, ok := app.Application.(types.BlockchainAware); ok { - resEndBlock = bcApp.EndBlock(height) - } + resEndBlock := app.Application.EndBlock(height) app.mtx.Unlock() return app.callback( types.ToRequestEndBlock(height), @@ -185,11 +178,11 @@ func (app *localClient) CheckTxSync(tx []byte) (res types.Result) { return res } -func (app *localClient) QuerySync(query []byte) (res types.Result) { +func (app *localClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { app.mtx.Lock() - res = app.Application.Query(query) + resQuery = app.Application.Query(reqQuery) app.mtx.Unlock() - return res + return resQuery, nil } func (app *localClient) CommitSync() (res types.Result) { @@ -201,27 +194,21 @@ func (app *localClient) CommitSync() (res types.Result) { func (app *localClient) InitChainSync(validators []*types.Validator) (err error) { app.mtx.Lock() - if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.InitChain(validators) - } + app.Application.InitChain(validators) app.mtx.Unlock() return nil } func (app *localClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { app.mtx.Lock() - if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.BeginBlock(hash, header) - } + app.Application.BeginBlock(hash, header) app.mtx.Unlock() return nil } func (app *localClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { app.mtx.Lock() - if bcApp, ok := app.Application.(types.BlockchainAware); ok { - resEndBlock = bcApp.EndBlock(height) - } + resEndBlock = app.Application.EndBlock(height) app.mtx.Unlock() return resEndBlock, nil } diff --git a/client/socket_client.go b/client/socket_client.go index 9b4f9aed4..5aeeac7ac 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -10,8 +10,8 @@ import ( "sync" "time" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) const ( @@ -27,10 +27,10 @@ const flushThrottleMS = 20 // Don't wait longer than... // the application in general is not meant to be interfaced // with concurrent callers. type socketClient struct { - BaseService + cmn.BaseService reqQueue chan *ReqRes - flushTimer *ThrottleTimer + flushTimer *cmn.ThrottleTimer mustConnect bool mtx sync.Mutex @@ -45,14 +45,14 @@ type socketClient struct { func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { cli := &socketClient{ reqQueue: make(chan *ReqRes, reqQueueSize), - flushTimer: NewThrottleTimer("socketClient", flushThrottleMS), + flushTimer: cmn.NewThrottleTimer("socketClient", flushThrottleMS), mustConnect: mustConnect, addr: addr, reqSent: list.New(), resCb: nil, } - cli.BaseService = *NewBaseService(nil, "socketClient", cli) + cli.BaseService = *cmn.NewBaseService(nil, "socketClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err @@ -65,15 +65,14 @@ func (cli *socketClient) OnStart() error { var conn net.Conn RETRY_LOOP: for { - conn, err = Connect(cli.addr) + conn, err = cmn.Connect(cli.addr) if err != nil { if cli.mustConnect { return err - } else { - log.Warn(Fmt("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) - time.Sleep(time.Second * 3) - continue RETRY_LOOP } + log.Warn(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) + time.Sleep(time.Second * 3) + continue RETRY_LOOP } cli.conn = conn @@ -82,7 +81,6 @@ RETRY_LOOP: return nil } - return nil // never happens } func (cli *socketClient) OnStop() { @@ -109,7 +107,7 @@ func (cli *socketClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(Fmt("Stopping abci.socketClient for error: %v", err.Error())) + log.Warn(fmt.Sprintf("Stopping abci.socketClient for error: %v", err.Error())) cli.Stop() } @@ -251,8 +249,8 @@ func (cli *socketClient) CheckTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.ToRequestCheckTx(tx)) } -func (cli *socketClient) QueryAsync(query []byte) *ReqRes { - return cli.queueRequest(types.ToRequestQuery(query)) +func (cli *socketClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { + return cli.queueRequest(types.ToRequestQuery(reqQuery)) } func (cli *socketClient) CommitAsync() *ReqRes { @@ -280,7 +278,7 @@ func (cli *socketClient) EchoSync(msg string) (res types.Result) { return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetEcho() - return types.Result{Code: OK, Data: []byte(resp.Message), Log: LOG} + return types.Result{Code: OK, Data: []byte(resp.Message)} } func (cli *socketClient) FlushSync() error { @@ -300,9 +298,8 @@ func (cli *socketClient) InfoSync() (resInfo types.ResponseInfo, err error) { } if resInfo_ := reqres.Response.GetInfo(); resInfo_ != nil { return *resInfo_, nil - } else { - return resInfo, nil } + return resInfo, nil } func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { @@ -335,14 +332,16 @@ func (cli *socketClient) CheckTxSync(tx []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *socketClient) QuerySync(query []byte) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestQuery(query)) +func (cli *socketClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { + reqres := cli.queueRequest(types.ToRequestQuery(reqQuery)) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return resQuery, err } - resp := reqres.Response.GetQuery() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { + return *resQuery_, nil + } + return resQuery, nil } func (cli *socketClient) CommitSync() (res types.Result) { @@ -379,11 +378,10 @@ func (cli *socketClient) EndBlockSync(height uint64) (resEndBlock types.Response if err := cli.Error(); err != nil { return resEndBlock, err } - if resEndBlock_ := reqres.Response.GetEndBlock(); resEndBlock_ != nil { - return *resEndBlock_, nil - } else { - return resEndBlock, nil + if blk := reqres.Response.GetEndBlock(); blk != nil { + return *blk, nil } + return resEndBlock, nil } //---------------------------------------- diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/abci-cli.go similarity index 76% rename from cmd/abci-cli/tmsp-cli.go rename to cmd/abci-cli/abci-cli.go index 39dace9f9..accae9d1e 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -6,37 +6,31 @@ import ( "errors" "fmt" "io" + "log" "os" "strings" "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + "github.com/tendermint/abci/version" "github.com/urfave/cli" ) -//structure for data passed to print response -// variables must be exposed for JSON to read +// Structure for data passed to print response. type response struct { - Res types.Result - Data string - PrintCode bool - Code string -} - -func newResponse(res types.Result, data string, printCode bool) *response { - rsp := &response{ - Res: res, - Data: data, - PrintCode: printCode, - Code: "", - } + // generic abci response + Data []byte + Code types.CodeType + Log string - if printCode { - rsp.Code = res.Code.String() - } + Query *queryResponse +} - return rsp +type queryResponse struct { + Key []byte + Value []byte + Height uint64 + Proof []byte } // client is a global variable so it can be reused by the console @@ -50,7 +44,7 @@ func main() { app := cli.NewApp() app.Name = "abci-cli" app.Usage = "abci-cli [command] [args...]" - app.Version = "0.3.0" // hex handling + app.Version = version.Version app.Flags = []cli.Flag{ cli.StringFlag{ Name: "address", @@ -135,7 +129,7 @@ func main() { app.Before = before err := app.Run(os.Args) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } } @@ -145,7 +139,7 @@ func before(c *cli.Context) error { var err error client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } } return nil @@ -220,9 +214,10 @@ func cmdEcho(c *cli.Context) error { if len(args) != 1 { return errors.New("Command echo takes 1 argument") } - res := client.EchoSync(args[0]) - rsp := newResponse(res, string(res.Data), false) - printResponse(c, rsp) + resEcho := client.EchoSync(args[0]) + printResponse(c, response{ + Data: resEcho.Data, + }) return nil } @@ -232,8 +227,9 @@ func cmdInfo(c *cli.Context) error { if err != nil { return err } - rsp := newResponse(types.Result{}, string(resInfo.Data), false) - printResponse(c, rsp) + printResponse(c, response{ + Data: []byte(resInfo.Data), + }) return nil } @@ -243,9 +239,10 @@ func cmdSetOption(c *cli.Context) error { if len(args) != 2 { return errors.New("Command set_option takes 2 arguments (key, value)") } - res := client.SetOptionSync(args[0], args[1]) - rsp := newResponse(res, Fmt("%s=%s", args[0], args[1]), false) - printResponse(c, rsp) + resSetOption := client.SetOptionSync(args[0], args[1]) + printResponse(c, response{ + Log: resSetOption.Log, + }) return nil } @@ -260,8 +257,11 @@ func cmdDeliverTx(c *cli.Context) error { return err } res := client.DeliverTxSync(txBytes) - rsp := newResponse(res, string(res.Data), true) - printResponse(c, rsp) + printResponse(c, response{ + Code: res.Code, + Data: res.Data, + Log: res.Log, + }) return nil } @@ -276,20 +276,27 @@ func cmdCheckTx(c *cli.Context) error { return err } res := client.CheckTxSync(txBytes) - rsp := newResponse(res, string(res.Data), true) - printResponse(c, rsp) + printResponse(c, response{ + Code: res.Code, + Data: res.Data, + Log: res.Log, + }) return nil } // Get application Merkle root hash func cmdCommit(c *cli.Context) error { res := client.CommitSync() - rsp := newResponse(res, Fmt("0x%X", res.Data), false) - printResponse(c, rsp) + printResponse(c, response{ + Code: res.Code, + Data: res.Data, + Log: res.Log, + }) return nil } // Query application state +// TODO: Make request and response support all fields. func cmdQuery(c *cli.Context) error { args := c.Args() if len(args) != 1 { @@ -299,15 +306,31 @@ func cmdQuery(c *cli.Context) error { if err != nil { return err } - res := client.QuerySync(queryBytes) - rsp := newResponse(res, string(res.Data), true) - printResponse(c, rsp) + resQuery, err := client.QuerySync(types.RequestQuery{ + Data: queryBytes, + Path: "/store", // TOOD expose + Height: 0, // TODO expose + //Prove: true, // TODO expose + }) + if err != nil { + return err + } + printResponse(c, response{ + Code: resQuery.Code, + Log: resQuery.Log, + Query: &queryResponse{ + Key: resQuery.Key, + Value: resQuery.Value, + Height: resQuery.Height, + Proof: resQuery.Proof, + }, + }) return nil } //-------------------------------------------------------------------------------- -func printResponse(c *cli.Context, rsp *response) { +func printResponse(c *cli.Context, rsp response) { verbose := c.GlobalBool("verbose") @@ -315,19 +338,30 @@ func printResponse(c *cli.Context, rsp *response) { fmt.Println(">", c.Command.Name, strings.Join(c.Args(), " ")) } - if rsp.PrintCode { - fmt.Printf("-> code: %s\n", rsp.Code) + if !rsp.Code.IsOK() { + fmt.Printf("-> code: %s\n", rsp.Code.String()) } - - //if pr.res.Error != "" { - // fmt.Printf("-> error: %s\n", pr.res.Error) - //} - - if rsp.Data != "" { + if len(rsp.Data) != 0 { fmt.Printf("-> data: %s\n", rsp.Data) + fmt.Printf("-> data.hex: %X\n", rsp.Data) + } + if rsp.Log != "" { + fmt.Printf("-> log: %s\n", rsp.Log) } - if rsp.Res.Log != "" { - fmt.Printf("-> log: %s\n", rsp.Res.Log) + + if rsp.Query != nil { + fmt.Printf("-> height: %d\n", rsp.Query.Height) + if rsp.Query.Key != nil { + fmt.Printf("-> key: %s\n", rsp.Query.Key) + fmt.Printf("-> key.hex: %X\n", rsp.Query.Key) + } + if rsp.Query.Value != nil { + fmt.Printf("-> value: %s\n", rsp.Query.Value) + fmt.Printf("-> value.hex: %X\n", rsp.Query.Value) + } + if rsp.Query.Proof != nil { + fmt.Printf("-> proof: %X\n", rsp.Query.Proof) + } } if verbose { diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 218224a0a..6858fc43e 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -2,10 +2,11 @@ package main import ( "flag" + "log" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" + cmn "github.com/tendermint/go-common" ) func main() { @@ -19,11 +20,11 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } // Wait forever - TrapSignal(func() { + cmn.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index aecb1138f..b48a15c7a 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -2,11 +2,12 @@ package main import ( "flag" + "log" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) func main() { @@ -27,11 +28,11 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } // Wait forever - TrapSignal(func() { + cmn.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go new file mode 100644 index 000000000..454c3560b --- /dev/null +++ b/example/block_aware/block_aware_app.go @@ -0,0 +1,57 @@ +package main + +import ( + "flag" + "log" + + "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" +) + +func main() { + + addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") + abciPtr := flag.String("abci", "socket", "socket | grpc") + flag.Parse() + + // Start the listener + srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) + if err != nil { + log.Fatal(err.Error()) + } + + // 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(hash []byte, header *types.Header) { + app.beginCount++ + return +} + +func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { + app.endCount++ + return +} diff --git a/example/chain_aware/chain_aware_test.go b/example/block_aware/block_aware_test.go similarity index 81% rename from example/chain_aware/chain_aware_test.go rename to example/block_aware/block_aware_test.go index f5283a386..2ce6aacf3 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -1,11 +1,12 @@ package main import ( + "fmt" + "log" "strconv" "strings" "testing" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" @@ -25,7 +26,7 @@ func TestChainAware(t *testing.T) { // Connect to the socket client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { - Exit(Fmt("Error starting socket client: %v", err.Error())) + log.Fatal(fmt.Sprintf("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() @@ -39,10 +40,10 @@ func TestChainAware(t *testing.T) { client.CommitSync() } - r := app.Query(nil) - spl := strings.Split(string(r.Data), ",") + 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.Data)) + t.Fatal("expected %d,%d ; got %s", n, n, string(r.Value)) } beginCount, _ := strconv.Atoi(spl[0]) endCount, _ := strconv.Atoi(spl[1]) diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go deleted file mode 100644 index e3543f13c..000000000 --- a/example/chain_aware/chain_aware_app.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "flag" - - . "github.com/tendermint/go-common" - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" -) - -func main() { - - addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - abciPtr := flag.String("abci", "socket", "socket | grpc") - flag.Parse() - - // Start the listener - srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) - if err != nil { - Exit(err.Error()) - } - - // Wait forever - TrapSignal(func() { - // Cleanup - srv.Stop() - }) - -} - -type ChainAwareApplication struct { - beginCount int - endCount int -} - -func NewChainAwareApplication() *ChainAwareApplication { - return &ChainAwareApplication{} -} - -func (app *ChainAwareApplication) Info() types.ResponseInfo { - return types.ResponseInfo{} -} - -func (app *ChainAwareApplication) SetOption(key string, value string) (log string) { - return "" -} - -func (app *ChainAwareApplication) DeliverTx(tx []byte) types.Result { - return types.NewResultOK(nil, "") -} - -func (app *ChainAwareApplication) CheckTx(tx []byte) types.Result { - return types.NewResultOK(nil, "") -} - -func (app *ChainAwareApplication) Commit() types.Result { - return types.NewResultOK([]byte("nil"), "") -} - -func (app *ChainAwareApplication) Query(query []byte) types.Result { - return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "") -} - -func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { - app.beginCount += 1 - return -} - -func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { - app.endCount += 1 - return -} - -func (app *ChainAwareApplication) InitChain(vals []*types.Validator) { - return -} diff --git a/example/counter/counter.go b/example/counter/counter.go index 90be6d92b..c40541ed9 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -3,11 +3,13 @@ package counter import ( "encoding/binary" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) type CounterApplication struct { + types.BaseApplication + hashCount int txCount int serial bool @@ -18,7 +20,7 @@ func NewCounterApplication(serial bool) *CounterApplication { } func (app *CounterApplication) Info() types.ResponseInfo { - return types.ResponseInfo{Data: Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} + return types.ResponseInfo{Data: cmn.Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } func (app *CounterApplication) SetOption(key string, value string) (log string) { @@ -31,55 +33,51 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) func (app *CounterApplication) DeliverTx(tx []byte) types.Result { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ErrEncodingError.SetLog(cmn.Fmt("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(Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) + return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) } } - app.txCount += 1 + app.txCount++ return types.OK } func (app *CounterApplication) CheckTx(tx []byte) types.Result { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ErrEncodingError.SetLog(cmn.Fmt("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(Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) + return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) } } return types.OK } func (app *CounterApplication) Commit() types.Result { - app.hashCount += 1 - + app.hashCount++ if app.txCount == 0 { return types.OK - } else { - hash := make([]byte, 8) - binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return types.NewResultOK(hash, "") } + hash := make([]byte, 8) + binary.BigEndian.PutUint64(hash, uint64(app.txCount)) + return types.NewResultOK(hash, "") } -func (app *CounterApplication) Query(query []byte) types.Result { - queryStr := string(query) - - switch queryStr { +func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { + switch reqQuery.Path { case "hash": - return types.NewResultOK(nil, Fmt("%v", app.hashCount)) + return types.ResponseQuery{Value: []byte(cmn.Fmt("%v", app.hashCount))} case "tx": - return types.NewResultOK(nil, Fmt("%v", app.txCount)) + return types.ResponseQuery{Value: []byte(cmn.Fmt("%v", app.txCount))} + default: + return types.ResponseQuery{Log: cmn.Fmt("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} } - - return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 6fdf87859..f88b1b20e 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,16 +1,16 @@ package dummy import ( - "encoding/hex" "strings" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" ) type DummyApplication struct { + types.BaseApplication + state merkle.Tree } @@ -20,11 +20,7 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info() (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: Fmt("{\"size\":%v}", app.state.Size())} -} - -func (app *DummyApplication) SetOption(key string, value string) (log string) { - return "" + return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} } // tx is either "key=value" or just arbitrary bytes @@ -47,15 +43,28 @@ func (app *DummyApplication) Commit() types.Result { return types.NewResultOK(hash, "") } -func (app *DummyApplication) Query(query []byte) types.Result { - index, value, exists := app.state.Get(query) - queryResult := QueryResult{index, string(value), hex.EncodeToString(value), exists} - return types.NewResultOK(wire.JSONBytes(queryResult), "") -} - -type QueryResult struct { - Index int `json:"index"` - Value string `json:"value"` - ValueHex string `json:"valueHex"` - Exists bool `json:"exists"` +func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { + if reqQuery.Prove { + value, proof, exists := app.state.Proof(reqQuery.Data) + resQuery.Index = -1 // TODO make Proof return index + resQuery.Key = reqQuery.Data + resQuery.Value = value + resQuery.Proof = proof + if exists { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } else { + index, value, exists := app.state.Get(reqQuery.Data) + resQuery.Index = int64(index) + resQuery.Value = value + if exists { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index d22943472..879cf3c4a 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -6,34 +6,41 @@ import ( "sort" "testing" - . "github.com/tendermint/go-common" - "github.com/tendermint/go-crypto" - "github.com/tendermint/go-wire" + "github.com/stretchr/testify/require" + abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" + "github.com/tendermint/go-crypto" + "github.com/tendermint/go-merkle" ) -func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) { - if r := dummy.DeliverTx(tx); r.IsErr() { - t.Fatal(r) - } - if r := dummy.DeliverTx(tx); r.IsErr() { - t.Fatal(r) - } - - r := dummy.Query([]byte(key)) - if r.IsErr() { - t.Fatal(r) - } - - q := new(QueryResult) - if err := wire.ReadJSONBytes(r.Data, q); err != nil { - t.Fatal(err) - } - - if q.Value != value { - t.Fatalf("Got %s, expected %s", q.Value, value) - } - +func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { + ar := app.DeliverTx(tx) + require.False(t, ar.IsErr(), ar) + // repeating tx doesn't raise error + ar = app.DeliverTx(tx) + require.False(t, ar.IsErr(), ar) + + // make sure query is fine + resQuery := app.Query(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + }) + require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) + + // make sure proof is fine + resQuery = app.Query(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + Prove: true, + }) + require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) + proof, err := merkle.ReadProof(resQuery.Proof) + require.Nil(t, err) + require.True(t, proof.Verify([]byte(key), resQuery.Value, proof.RootHash)) // NOTE: we have no way to verify the RootHash } func TestDummyKV(t *testing.T) { @@ -107,8 +114,8 @@ func TestValSetChanges(t *testing.T) { nInit := 5 vals := make([]*types.Validator, total) for i := 0; i < total; i++ { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(Fmt("test%d", i))).PubKey().Bytes() - power := RandInt() + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() + power := cmn.RandInt() vals[i] = &types.Validator{pubkey, uint64(power)} } // iniitalize with the first nInit @@ -172,14 +179,13 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ Height: height, } - dummyChain := dummy.(types.BlockchainAware) // hmm... - dummyChain.BeginBlock(hash, header) + dummy.BeginBlock(hash, header) for _, tx := range txs { if r := dummy.DeliverTx(tx); r.IsErr() { t.Fatal(r) } } - resEndBlock := dummyChain.EndBlock(height) + resEndBlock := dummy.EndBlock(height) dummy.Commit() valsEqual(t, diff, resEndBlock.Diffs) @@ -201,3 +207,102 @@ func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { } } } + +func makeSocketClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { + // Start the listener + socket := cmn.Fmt("unix://%s.sock", name) + server, err := server.NewSocketServer(socket, app) + if err != nil { + return nil, nil, err + } + + // Connect to the socket + client, err := abcicli.NewSocketClient(socket, false) + if err != nil { + server.Stop() + return nil, nil, err + } + client.Start() + + return client, server, err +} + +func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { + // Start the listener + socket := cmn.Fmt("unix://%s.sock", name) + + gapp := types.NewGRPCApplication(app) + server, err := server.NewGRPCServer(socket, gapp) + if err != nil { + return nil, nil, err + } + + client, err := abcicli.NewGRPCClient(socket, true) + if err != nil { + server.Stop() + return nil, nil, err + } + return client, server, err +} + +func TestClientServer(t *testing.T) { + // set up socket app + dummy := NewDummyApplication() + client, server, err := makeSocketClientServer(dummy, "dummy-socket") + require.Nil(t, err) + defer server.Stop() + defer client.Stop() + + runClientTests(t, client) + + // set up grpc app + dummy = NewDummyApplication() + gclient, gserver, err := makeGRPCClientServer(dummy, "dummy-grpc") + require.Nil(t, err) + defer gserver.Stop() + defer gclient.Stop() + + runClientTests(t, gclient) +} + +func runClientTests(t *testing.T, client abcicli.Client) { + // run some tests.... + key := "abc" + value := key + tx := []byte(key) + testClient(t, client, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testClient(t, client, tx, key, value) +} + +func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) { + ar := app.DeliverTxSync(tx) + require.False(t, ar.IsErr(), ar) + // repeating tx doesn't raise error + ar = app.DeliverTxSync(tx) + require.False(t, ar.IsErr(), ar) + + // make sure query is fine + resQuery, err := app.QuerySync(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + }) + require.Nil(t, err) + require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) + + // make sure proof is fine + resQuery, err = app.QuerySync(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + Prove: true, + }) + require.Nil(t, err) + require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) + proof, err := merkle.ReadProof(resQuery.Proof) + require.Nil(t, err) + require.True(t, proof.Verify([]byte(key), resQuery.Value, proof.RootHash)) // NOTE: we have no way to verify the RootHash +} diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index fa730bcb5..48eff420d 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -6,11 +6,11 @@ import ( "strconv" "strings" - . "github.com/tendermint/go-common" + "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" dbm "github.com/tendermint/go-db" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" - "github.com/tendermint/abci/types" ) const ( @@ -89,8 +89,8 @@ func (app *PersistentDummyApplication) Commit() types.Result { return types.NewResultOK(appHash, "") } -func (app *PersistentDummyApplication) Query(query []byte) types.Result { - return app.app.Query(query) +func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { + return app.app.Query(reqQuery) } // Save the validators in the merkle tree @@ -135,7 +135,7 @@ func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { wire.ReadBinaryPtr(&lastBlock, r, 0, n, err) if *err != nil { // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err)) + log.Crit(cmn.Fmt("Data has been corrupted or its spec has changed: %v\n", *err)) } // TODO: ensure that buf is completely read. } @@ -149,7 +149,7 @@ func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { wire.WriteBinary(lastBlock, buf, n, err) if *err != nil { // TODO - PanicCrisis(*err) + cmn.PanicCrisis(*err) } db.Set(lastBlockKey, buf.Bytes()) } @@ -173,7 +173,7 @@ func (app *PersistentDummyApplication) Validators() (validators []*types.Validat } func MakeValSetChangeTx(pubkey []byte, power uint64) []byte { - return []byte(Fmt("val:%X/%d", pubkey, power)) + return []byte(cmn.Fmt("val:%X/%d", pubkey, power)) } func isValidatorTx(tx []byte) bool { @@ -188,16 +188,16 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { tx = tx[len(ValidatorSetChangePrefix):] pubKeyAndPower := strings.Split(string(tx), "/") if len(pubKeyAndPower) != 2 { - return types.ErrEncodingError.SetLog(Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) + return types.ErrEncodingError.SetLog(cmn.Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) } pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] pubkey, err := hex.DecodeString(pubkeyS) if err != nil { - return types.ErrEncodingError.SetLog(Fmt("Pubkey (%s) is invalid hex", pubkeyS)) + return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%s) is invalid hex", pubkeyS)) } power, err := strconv.Atoi(powerS) if err != nil { - return types.ErrEncodingError.SetLog(Fmt("Power (%s) is not an int", powerS)) + return types.ErrEncodingError.SetLog(cmn.Fmt("Power (%s) is not an int", powerS)) } // update @@ -210,14 +210,14 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types if v.Power == 0 { // remove validator if !app.app.state.Has(key) { - return types.ErrUnauthorized.SetLog(Fmt("Cannot remove non-existent validator %X", key)) + return types.ErrUnauthorized.SetLog(cmn.Fmt("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(Fmt("Error encoding validator: %v", err)) + return types.ErrInternalError.SetLog(cmn.Fmt("Error encoding validator: %v", err)) } app.app.state.Set(key, value.Bytes()) } diff --git a/example/example_test.go b/example/example_test.go index 1ddefddb5..034331d62 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -2,20 +2,21 @@ package example import ( "fmt" + "log" "net" "reflect" "testing" "time" - "golang.org/x/net/context" "google.golang.org/grpc" - . "github.com/tendermint/go-common" + "golang.org/x/net/context" + "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/dummy" - nilapp "github.com/tendermint/abci/example/nil" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) func TestDummy(t *testing.T) { @@ -23,14 +24,14 @@ func TestDummy(t *testing.T) { testStream(t, dummy.NewDummyApplication()) } -func TestNilApp(t *testing.T) { - fmt.Println("### Testing NilApp") - testStream(t, nilapp.NewNilApplication()) +func TestBaseApp(t *testing.T) { + fmt.Println("### Testing BaseApp") + testStream(t, types.NewBaseApplication()) } func TestGRPC(t *testing.T) { fmt.Println("### Testing GRPC") - testGRPCSync(t, types.NewGRPCApplication(nilapp.NewNilApplication())) + testGRPCSync(t, types.NewGRPCApplication(types.NewBaseApplication())) } func testStream(t *testing.T, app types.Application) { @@ -40,14 +41,14 @@ func testStream(t *testing.T, app types.Application) { // Start the listener server, err := server.NewSocketServer("unix://test.sock", app) if err != nil { - Exit(Fmt("Error starting socket server: %v", err.Error())) + log.Fatal(cmn.Fmt("Error starting socket server: %v", err.Error())) } defer server.Stop() // Connect to the socket client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { - Exit(Fmt("Error starting socket client: %v", err.Error())) + log.Fatal(cmn.Fmt("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() @@ -58,7 +59,7 @@ func testStream(t *testing.T, app types.Application) { // Process response switch r := res.Value.(type) { case *types.Response_DeliverTx: - counter += 1 + counter++ if r.DeliverTx.Code != types.CodeType_OK { t.Error("DeliverTx failed with ret_code", r.DeliverTx.Code) } @@ -103,7 +104,7 @@ func testStream(t *testing.T, app types.Application) { // test grpc func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { - return Connect(addr) + return cmn.Connect(addr) } func testGRPCSync(t *testing.T, app *types.GRPCApplication) { @@ -113,14 +114,14 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { // Start the listener server, err := server.NewGRPCServer("unix://test.sock", app) if err != nil { - Exit(Fmt("Error starting GRPC server: %v", err.Error())) + log.Fatal(cmn.Fmt("Error starting GRPC server: %v", err.Error())) } defer server.Stop() // Connect to the socket conn, err := grpc.Dial("unix://test.sock", grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) if err != nil { - Exit(Fmt("Error dialing GRPC server: %v", err.Error())) + log.Fatal(cmn.Fmt("Error dialing GRPC server: %v", err.Error())) } defer conn.Close() @@ -133,7 +134,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { if err != nil { t.Fatalf("Error in GRPC DeliverTx: %v", err.Error()) } - counter += 1 + counter++ if response.Code != types.CodeType_OK { t.Error("DeliverTx failed with ret_code", response.Code) } diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go deleted file mode 100644 index cd57f0d98..000000000 --- a/example/nil/nil_app.go +++ /dev/null @@ -1,36 +0,0 @@ -package nilapp - -import ( - "github.com/tendermint/abci/types" -) - -type NilApplication struct { -} - -func NewNilApplication() *NilApplication { - return &NilApplication{} -} - -func (app *NilApplication) Info() (resInfo types.ResponseInfo) { - return -} - -func (app *NilApplication) SetOption(key string, value string) (log string) { - return "" -} - -func (app *NilApplication) DeliverTx(tx []byte) types.Result { - return types.NewResultOK(nil, "") -} - -func (app *NilApplication) CheckTx(tx []byte) types.Result { - return types.NewResultOK(nil, "") -} - -func (app *NilApplication) Commit() types.Result { - return types.NewResultOK([]byte("nil"), "") -} - -func (app *NilApplication) Query(query []byte) types.Result { - return types.NewResultOK(nil, "") -} diff --git a/glide.lock b/glide.lock index 42776a3a6..5e06cad2a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: febff7f2646081f635b5dc2a0a672d9b8e42eb59241269e6658eec916cd2a5a4 -updated: 2017-01-13T00:24:02.377918976-05:00 +hash: 54e49c7cb920a3390f631de12e38226494920bbc5e0c369514df18fe0ab5b693 +updated: 2017-02-14T16:51:55.592202262-05:00 imports: - name: github.com/btcsuite/btcd - version: 153dca5c1e4b5d1ea1523592495e5bedfa503391 + version: d06c0bb181529331be8f8d9350288c420d9e60e4 subpackages: - btcec - name: github.com/go-stack/stack @@ -12,13 +12,18 @@ imports: subpackages: - proto - name: github.com/golang/snappy - version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 + version: 7db9049039a047d955fe8c19b83c8ff5abd765c7 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable - version: d228849504861217f796da67fae4f6e347643f15 + version: 5411d3eea5978e6cdc258b30de592b60df6aba96 - name: github.com/mattn/go-isatty - version: 30a891c33c7cde7b02a981314b4228ec99380cca + version: 281032e84ae07510239465db46bf442aa44b953a +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require - name: github.com/syndtr/goleveldb version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 subpackages: @@ -40,7 +45,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-common - version: e289af53b6bf6af28da129d9ef64389a4cf7987f + version: 339e135776142939d82bc8e699db0bf391fd938d - name: github.com/tendermint/go-crypto version: 4b11d62bdb324027ea01554e5767b71174680ba0 - name: github.com/tendermint/go-db @@ -48,19 +53,19 @@ imports: - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 7a86b4486f2cd84ac885c5bbc609fdee2905f5d1 + version: 9f20e80cb188d07860caa70196dd7700659ec4a4 - name: github.com/tendermint/go-process version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire - version: 2f3b7aafe21c80b19b6ee3210ecb3e3d07c7a471 + version: 3216ec9d47bbdf8d4fc27d22169ea86a6688bc15 - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term - name: github.com/urfave/cli - version: 8ef3805c9de2519805c3f060524b695bba2cd715 + version: 347a9884a87374d000eec7e6445a34487c1f4a2b - name: golang.org/x/crypto - version: 7c6cc321c680f03b9ef0764448e780704f486b51 + version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8 subpackages: - nacl/secretbox - openpgp/armor @@ -69,7 +74,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 60c41d1de8da134c05b7b40154a9a82bf5b7edb9 + version: 61557ac0112b576429a0df080e1c2cef5dfbb642 subpackages: - context - http2 @@ -79,18 +84,11 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: d75a52659825e75fff6158388dddc6a5b04f9ba5 + version: e24f485414aeafb646f6fca458b0bf869c0880a1 subpackages: - unix -- name: golang.org/x/text - version: 44f4f658a783b0cee41fe0a23b8fc91d9c120558 - subpackages: - - secure/bidirule - - transform - - unicode/bidi - - unicode/norm - name: google.golang.org/grpc - version: 50955793b0183f9de69bd78e2ec251cf20aab121 + version: cbcceb2942a489498cf22b2f918536e819d33f0a subpackages: - codes - credentials @@ -102,4 +100,12 @@ imports: - stats - tap - transport -testImports: [] +testImports: +- name: github.com/davecgh/go-spew + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + subpackages: + - spew +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib diff --git a/glide.yaml b/glide.yaml index 295b3d3ec..2b19d8723 100644 --- a/glide.yaml +++ b/glide.yaml @@ -4,10 +4,13 @@ import: subpackages: - proto - package: github.com/tendermint/go-common + version: develop - package: github.com/tendermint/go-crypto + version: develop - package: github.com/tendermint/go-logger - package: github.com/tendermint/go-db - package: github.com/tendermint/go-merkle + version: develop - package: github.com/tendermint/go-process - package: github.com/tendermint/go-wire - package: github.com/urfave/cli @@ -15,3 +18,7 @@ import: subpackages: - context - package: google.golang.org/grpc +- package: github.com/stretchr/testify + version: ^1.1.4 + subpackages: + - require diff --git a/server/grpc_server.go b/server/grpc_server.go index 1acd45a36..944d4e42c 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -6,14 +6,14 @@ import ( "google.golang.org/grpc" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 type GRPCServer struct { - BaseService + cmn.BaseService proto string addr string @@ -23,7 +23,7 @@ type GRPCServer struct { app types.ABCIApplicationServer } -func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (Service, error) { +func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Service, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &GRPCServer{ @@ -32,7 +32,7 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (Service, listener: nil, app: app, } - s.BaseService = *NewBaseService(nil, "ABCIServer", s) + s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } diff --git a/server/server.go b/server/server.go index 496767470..eb71b1325 100644 --- a/server/server.go +++ b/server/server.go @@ -3,12 +3,12 @@ package server import ( "fmt" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) -func NewServer(protoAddr, transport string, app types.Application) (Service, error) { - var s Service +func NewServer(protoAddr, transport string, app types.Application) (cmn.Service, error) { + var s cmn.Service var err error switch transport { case "socket": diff --git a/server/socket_server.go b/server/socket_server.go index bd26a18a8..bc1980e2d 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -8,14 +8,14 @@ import ( "strings" "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 type SocketServer struct { - BaseService + cmn.BaseService proto string addr string @@ -29,7 +29,7 @@ type SocketServer struct { app types.Application } -func NewSocketServer(protoAddr string, app types.Application) (Service, error) { +func NewSocketServer(protoAddr string, app types.Application) (cmn.Service, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &SocketServer{ @@ -39,7 +39,7 @@ func NewSocketServer(protoAddr string, app types.Application) (Service, error) { app: app, conns: make(map[int]net.Conn), } - s.BaseService = *NewBaseService(nil, "ABCIServer", s) + s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } @@ -72,7 +72,7 @@ func (s *SocketServer) addConn(conn net.Conn) int { defer s.connsMtx.Unlock() connID := s.nextConnID - s.nextConnID += 1 + s.nextConnID++ s.conns[connID] = conn return connID @@ -100,7 +100,7 @@ func (s *SocketServer) acceptConnectionsRoutine() { if !s.IsRunning() { return // Ignore error from listener closing. } - Exit("Failed to accept connection: " + err.Error()) + log.Crit("Failed to accept connection: " + err.Error()) } else { log.Notice("Accepted a new connection") } @@ -184,25 +184,17 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types res := s.app.Commit() responses <- types.ToResponseCommit(res.Code, res.Data, res.Log) case *types.Request_Query: - res := s.app.Query(r.Query.Query) - responses <- types.ToResponseQuery(res.Code, res.Data, res.Log) + resQuery := s.app.Query(*r.Query) + responses <- types.ToResponseQuery(resQuery) case *types.Request_InitChain: - if app, ok := s.app.(types.BlockchainAware); ok { - app.InitChain(r.InitChain.Validators) - } + s.app.InitChain(r.InitChain.Validators) responses <- types.ToResponseInitChain() case *types.Request_BeginBlock: - if app, ok := s.app.(types.BlockchainAware); ok { - app.BeginBlock(r.BeginBlock.Hash, r.BeginBlock.Header) - } + s.app.BeginBlock(r.BeginBlock.Hash, r.BeginBlock.Header) responses <- types.ToResponseBeginBlock() case *types.Request_EndBlock: - if app, ok := s.app.(types.BlockchainAware); ok { - resEndBlock := app.EndBlock(r.EndBlock.Height) - responses <- types.ToResponseEndBlock(resEndBlock) - } else { - responses <- types.ToResponseEndBlock(types.ResponseEndBlock{}) - } + resEndBlock := s.app.EndBlock(r.EndBlock.Height) + responses <- types.ToResponseEndBlock(resEndBlock) default: responses <- types.ToResponseException("Unknown request") } diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 5960d529a..f01fba4c9 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -3,17 +3,17 @@ package main import ( "bufio" "fmt" - //"encoding/hex" + "log" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) func main() { - conn, err := Connect("unix://test.sock") + conn, err := cmn.Connect("unix://test.sock") if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } // Read a bunch of responses @@ -23,9 +23,9 @@ func main() { var res = &types.Response{} err := types.ReadMessage(conn, res) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } - counter += 1 + counter++ if counter%1000 == 0 { fmt.Println("Read", counter) } @@ -40,14 +40,14 @@ func main() { err := types.WriteMessage(req, bufWriter) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } err = bufWriter.Flush() if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } - counter += 1 + counter++ if counter%1000 == 0 { fmt.Println("Write", counter) } diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index fb536730c..498aac341 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -2,21 +2,20 @@ package main import ( "bufio" - "errors" "fmt" + "log" "net" "reflect" - //"encoding/hex" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" ) func main() { - conn, err := Connect("unix://test.sock") + conn, err := cmn.Connect("unix://test.sock") if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } // Make a bunch of requests @@ -25,9 +24,9 @@ func main() { req := types.ToRequestEcho("foobar") _, err := makeRequest(conn, req) if err != nil { - Exit(err.Error()) + log.Fatal(err.Error()) } - counter += 1 + counter++ if counter%1000 == 0 { fmt.Println(counter) } @@ -63,7 +62,7 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { return nil, err } if _, ok := resFlush.Value.(*types.Response_Flush); !ok { - return nil, errors.New(Fmt("Expected flush response but got something else: %v", reflect.TypeOf(resFlush))) + return nil, fmt.Errorf("Expected flush response but got something else: %v", reflect.TypeOf(resFlush)) } return res, nil diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 59d5b0e70..87b74ead0 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -2,18 +2,16 @@ package main import ( "bytes" + "fmt" "os" "time" - . "github.com/tendermint/go-common" - "github.com/tendermint/go-process" "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" + "github.com/tendermint/go-process" ) -//---------------------------------------- - -func StartApp(abciApp string) *process.Process { +func startApp(abciApp string) *process.Process { // Start the app //outBuf := NewBufferCloser(nil) proc, err := process.StartProcess("abci_app", @@ -33,7 +31,7 @@ func StartApp(abciApp string) *process.Process { return proc } -func StartClient(abciType string) abcicli.Client { +func startClient(abciType string) abcicli.Client { // Start client client, err := abcicli.NewClient("tcp://127.0.0.1:46658", abciType, true) if err != nil { @@ -42,51 +40,51 @@ func StartClient(abciType string) abcicli.Client { return client } -func SetOption(client abcicli.Client, key, value string) { +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("setting %v=%v: \nlog: %v", key, value, log)) + panic(fmt.Sprintf("setting %v=%v: \nlog: %v", key, value, log)) } } -func Commit(client abcicli.Client, hashExp []byte) { +func commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(Fmt("committing %v\nlog: %v", log)) + panic(fmt.Sprintf("committing %v\nlog: %v", log)) } if !bytes.Equal(res.Data, hashExp) { - panic(Fmt("Commit hash was unexpected. Got %X expected %X", + panic(fmt.Sprintf("Commit hash was unexpected. Got %X expected %X", data, hashExp)) } } -func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +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("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", + panic(fmt.Sprintf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", code, codeExp, log)) } if !bytes.Equal(data, dataExp) { - panic(Fmt("DeliverTx response data was unexpected. Got %X expected %X", + panic(fmt.Sprintf("DeliverTx response data was unexpected. Got %X expected %X", data, dataExp)) } } -func CheckTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +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 if res.IsErr() { - panic(Fmt("checking tx %X: %v\nlog: %v", txBytes, log)) + panic(fmt.Sprintf("checking tx %X: %v\nlog: %v", txBytes, log)) } if code != codeExp { - panic(Fmt("CheckTx response code was unexpected. Got %v expected %v. Log: %v", + panic(fmt.Sprintf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", code, codeExp, log)) } if !bytes.Equal(data, dataExp) { - panic(Fmt("CheckTx response data was unexpected. Got %X expected %X", + panic(fmt.Sprintf("CheckTx response data was unexpected. Got %X expected %X", data, dataExp)) } } diff --git a/tests/test_app/main.go b/tests/test_app/main.go index 05f66b07f..376c02fe5 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -27,22 +27,22 @@ func testCounter() { } fmt.Printf("Running %s test with abci=%s\n", abciApp, abciType) - appProc := StartApp(abciApp) + appProc := startApp(abciApp) defer appProc.StopProcess(true) - client := StartClient(abciType) + client := startClient(abciType) defer client.Stop() - SetOption(client, "serial", "on") - Commit(client, nil) - DeliverTx(client, []byte("abc"), types.CodeType_BadNonce, nil) - Commit(client, nil) - DeliverTx(client, []byte{0x00}, types.CodeType_OK, nil) - Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) - DeliverTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) - DeliverTx(client, []byte{0x01}, types.CodeType_OK, nil) - DeliverTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) - DeliverTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) - DeliverTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) - DeliverTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) - Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) + setOption(client, "serial", "on") + commit(client, nil) + deliverTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + commit(client, nil) + deliverTx(client, []byte{0x00}, types.CodeType_OK, nil) + commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) + deliverTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) + deliverTx(client, []byte{0x01}, types.CodeType_OK, nil) + deliverTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) + deliverTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) + deliverTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) + deliverTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) + commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) } diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index c8739758c..e434944a4 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -1,32 +1,38 @@ > echo hello -> data: hello +-> data.hex: 68656C6C6F > info -> data: {"size":0} +-> data.hex: 7B2273697A65223A307D > commit --> data: 0x > deliver_tx "abc" --> code: OK > info -> data: {"size":1} +-> data.hex: 7B2273697A65223A317D > commit --> data: 0x750502FC7E84BBD788ED589624F06CFA871845D1 +-> data: uü~„»×ˆíX–$ðlú‡EÑ +-> data.hex: 750502FC7E84BBD788ED589624F06CFA871845D1 > query "abc" --> code: OK --> data: {"index":0,"value":"abc","valueHex":"616263","exists":true} +-> log: exists +-> height: 0 +-> value: abc +-> value.hex: 616263 > deliver_tx "def=xyz" --> code: OK > commit --> data: 0x76393B8A182E450286B0694C629ECB51B286EFD5 +-> data: v9;Š.E†°iLbžËQ²†ïÕ +-> data.hex: 76393B8A182E450286B0694C629ECB51B286EFD5 > query "def" --> code: OK --> data: {"index":1,"value":"xyz","valueHex":"78797a","exists":true} +-> log: exists +-> height: 0 +-> value: xyz +-> value.hex: 78797A diff --git a/tests/test_cli/ex2.abci.out b/tests/test_cli/ex2.abci.out index 1fab1e841..202861cf4 100644 --- a/tests/test_cli/ex2.abci.out +++ b/tests/test_cli/ex2.abci.out @@ -1,21 +1,16 @@ > set_option serial on --> data: serial=on > check_tx 0x00 --> code: OK > check_tx 0xff --> code: OK > deliver_tx 0x00 --> code: OK > check_tx 0x00 -> code: BadNonce -> log: Invalid nonce. Expected >= 1, got 0 > deliver_tx 0x01 --> code: OK > deliver_tx 0x04 -> code: BadNonce @@ -23,4 +18,5 @@ > info -> data: {"hashes":0,"txs":2} +-> data.hex: 7B22686173686573223A302C22747873223A327D diff --git a/testutil/messages.go b/testutil/messages.go index 1036e48e4..0cdddb443 100644 --- a/testutil/messages.go +++ b/testutil/messages.go @@ -1,8 +1,8 @@ package testutil import ( - "github.com/tendermint/go-crypto" "github.com/tendermint/abci/types" + "github.com/tendermint/go-crypto" ) //---------------------------------------- diff --git a/types/application.go b/types/application.go index 4da5e6f76..b45305f8d 100644 --- a/types/application.go +++ b/types/application.go @@ -6,42 +6,25 @@ import ( // Applications type Application interface { - - // Return application info - Info() ResponseInfo - - // Set application option (e.g. mode=mempool, mode=consensus) - SetOption(key string, value string) (log string) - - // Deliver a tx - DeliverTx(tx []byte) Result - - // Validate a tx for the mempool - CheckTx(tx []byte) Result - - // Query for state - Query(query []byte) Result - - // Return the application Merkle root hash - Commit() Result -} - -// Some applications can choose to implement BlockchainAware -type BlockchainAware interface { - - // Initialize blockchain - // validators: genesis validators from TendermintCore - InitChain(validators []*Validator) - - // Signals the beginning of a block - BeginBlock(hash []byte, header *Header) - - // Signals the end of a block - // diffs: changed validators from app to TendermintCore - EndBlock(height uint64) ResponseEndBlock + // Info/Query Connection + Info() ResponseInfo // Return application info + SetOption(key string, value string) (log string) // Set application option + Query(reqQuery RequestQuery) ResponseQuery // Query for state + + // Mempool Connection + CheckTx(tx []byte) Result // Validate a tx for the mempool + + // Consensus Connection + InitChain(validators []*Validator) // Initialize blockchain with validators from TendermintCore + BeginBlock(hash []byte, header *Header) // 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 } //------------------------------------ + +// GRPC wrapper for application type GRPCApplication struct { app Application } @@ -78,8 +61,8 @@ func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (* } func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { - r := app.app.Query(req.Query) - return &ResponseQuery{r.Code, r.Data, r.Log}, nil + resQuery := app.app.Query(*req) + return &resQuery, nil } func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { @@ -88,23 +71,16 @@ func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*Re } func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - if chainAware, ok := app.app.(BlockchainAware); ok { - chainAware.InitChain(req.Validators) - } - return &ResponseInitChain{}, nil + app.app.InitChain(req.Validators) + return &ResponseInitChain{}, nil // NOTE: empty return } func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { - if chainAware, ok := app.app.(BlockchainAware); ok { - chainAware.BeginBlock(req.Hash, req.Header) - } - return &ResponseBeginBlock{}, nil + app.app.BeginBlock(req.Hash, req.Header) + return &ResponseBeginBlock{}, nil // NOTE: empty return } func (app *GRPCApplication) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { - if chainAware, ok := app.app.(BlockchainAware); ok { - resEndBlock := chainAware.EndBlock(req.Height) - return &resEndBlock, nil - } - return &ResponseEndBlock{}, nil + resEndBlock := app.app.EndBlock(req.Height) + return &resEndBlock, nil } diff --git a/types/base_app.go b/types/base_app.go new file mode 100644 index 000000000..1d4f84b8a --- /dev/null +++ b/types/base_app.go @@ -0,0 +1,42 @@ +package types + +type BaseApplication struct { +} + +func NewBaseApplication() *BaseApplication { + return &BaseApplication{} +} + +func (app *BaseApplication) Info() (resInfo ResponseInfo) { + return +} + +func (app *BaseApplication) SetOption(key string, value string) (log string) { + return "" +} + +func (app *BaseApplication) DeliverTx(tx []byte) Result { + return NewResultOK(nil, "") +} + +func (app *BaseApplication) CheckTx(tx []byte) Result { + return NewResultOK(nil, "") +} + +func (app *BaseApplication) Commit() Result { + return NewResultOK([]byte("nil"), "") +} + +func (app *BaseApplication) Query(reqQuery RequestQuery) (resQuery ResponseQuery) { + return +} + +func (app *BaseApplication) InitChain(validators []*Validator) { +} + +func (app *BaseApplication) BeginBlock(hash []byte, header *Header) { +} + +func (app *BaseApplication) EndBlock(height uint64) (resEndBlock ResponseEndBlock) { + return +} diff --git a/types/code.go b/types/code.go new file mode 100644 index 000000000..c99a0bbe1 --- /dev/null +++ b/types/code.go @@ -0,0 +1,3 @@ +package types + +func (c CodeType) IsOK() bool { return c == CodeType_OK } diff --git a/types/messages.go b/types/messages.go index 84e6ee0b3..fe2d310ac 100644 --- a/types/messages.go +++ b/types/messages.go @@ -49,9 +49,9 @@ func ToRequestCommit() *Request { } } -func ToRequestQuery(queryBytes []byte) *Request { +func ToRequestQuery(reqQuery RequestQuery) *Request { return &Request{ - Value: &Request_Query{&RequestQuery{queryBytes}}, + Value: &Request_Query{&reqQuery}, } } @@ -123,9 +123,9 @@ func ToResponseCommit(code CodeType, data []byte, log string) *Response { } } -func ToResponseQuery(code CodeType, data []byte, log string) *Response { +func ToResponseQuery(resQuery ResponseQuery) *Response { return &Response{ - Value: &Response_Query{&ResponseQuery{code, data, log}}, + Value: &Response_Query{&resQuery}, } } diff --git a/types/types.pb.go b/types/types.pb.go index 6cae54339..f59664530 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -716,7 +716,10 @@ func (m *RequestCheckTx) GetTx() []byte { } type RequestQuery struct { - Query []byte `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + Height uint64 `protobuf:"varint,3,opt,name=height" json:"height,omitempty"` + Prove bool `protobuf:"varint,4,opt,name=prove" json:"prove,omitempty"` } func (m *RequestQuery) Reset() { *m = RequestQuery{} } @@ -724,13 +727,34 @@ func (m *RequestQuery) String() string { return proto.CompactTextStri func (*RequestQuery) ProtoMessage() {} func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } -func (m *RequestQuery) GetQuery() []byte { +func (m *RequestQuery) GetData() []byte { if m != nil { - return m.Query + return m.Data } return nil } +func (m *RequestQuery) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *RequestQuery) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestQuery) GetProve() bool { + if m != nil { + return m.Prove + } + return false +} + type RequestCommit struct { } @@ -1387,9 +1411,13 @@ func (m *ResponseCheckTx) GetLog() string { } type ResponseQuery 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"` + Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` + Proof []byte `protobuf:"bytes,5,opt,name=proof,proto3" json:"proof,omitempty"` + Height uint64 `protobuf:"varint,6,opt,name=height" json:"height,omitempty"` + Log string `protobuf:"bytes,7,opt,name=log" json:"log,omitempty"` } func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } @@ -1404,13 +1432,41 @@ func (m *ResponseQuery) GetCode() CodeType { return CodeType_OK } -func (m *ResponseQuery) GetData() []byte { +func (m *ResponseQuery) GetIndex() int64 { if m != nil { - return m.Data + return m.Index + } + return 0 +} + +func (m *ResponseQuery) GetKey() []byte { + if m != nil { + return m.Key } return nil } +func (m *ResponseQuery) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *ResponseQuery) GetProof() []byte { + if m != nil { + return m.Proof + } + return nil +} + +func (m *ResponseQuery) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + func (m *ResponseQuery) GetLog() string { if m != nil { return m.Log @@ -2073,108 +2129,112 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1642 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0xc9, 0x6e, 0xdb, 0xdc, - 0x15, 0x36, 0x35, 0xeb, 0xc8, 0x96, 0xae, 0x8f, 0x65, 0x5b, 0x56, 0xbb, 0x08, 0xd8, 0xa6, 0xb1, - 0xdd, 0x34, 0x29, 0x1c, 0xa4, 0x88, 0x9b, 0xa2, 0x80, 0xa7, 0xd8, 0x42, 0x90, 0xc4, 0x65, 0x86, - 0x45, 0x5b, 0x54, 0xa0, 0xc5, 0x2b, 0x89, 0x35, 0x45, 0x32, 0x1c, 0x1c, 0xbb, 0xcf, 0x90, 0x7d, - 0x1f, 0xa1, 0x4f, 0xd0, 0xd5, 0xbf, 0xff, 0x81, 0x7f, 0x1e, 0x9e, 0xe8, 0xc7, 0x1d, 0x38, 0x9a, - 0xcc, 0x2a, 0x1b, 0x81, 0x67, 0xbc, 0xd3, 0x77, 0xbe, 0x7b, 0xae, 0x60, 0x35, 0xb8, 0x71, 0xa9, - 0xff, 0x90, 0xff, 0x3e, 0x70, 0x3d, 0x27, 0x70, 0xb0, 0xce, 0x05, 0xf5, 0xcb, 0x1a, 0x34, 0x35, - 0xfa, 0x3e, 0xa4, 0x7e, 0x80, 0xdb, 0x50, 0xa3, 0x93, 0xb9, 0x33, 0x50, 0xee, 0x28, 0xdb, 0x9d, - 0x3d, 0x7c, 0x20, 0xdc, 0xa5, 0xf5, 0x64, 0x32, 0x77, 0xce, 0x96, 0x34, 0xee, 0x81, 0xbf, 0x87, - 0xfa, 0xd4, 0x0a, 0xfd, 0xf9, 0xa0, 0xc2, 0x5d, 0xd7, 0xb2, 0xae, 0xcf, 0x98, 0xe9, 0x6c, 0x49, - 0x13, 0x3e, 0x2c, 0xad, 0x69, 0x4f, 0x9d, 0x41, 0xb5, 0x28, 0xed, 0xc8, 0x9e, 0xf2, 0xb4, 0xcc, - 0x03, 0x9f, 0x00, 0xf8, 0x34, 0x18, 0x3b, 0x6e, 0x60, 0x3a, 0xf6, 0xa0, 0xc6, 0xfd, 0x37, 0xb3, - 0xfe, 0xaf, 0x69, 0xf0, 0x8a, 0x9b, 0xcf, 0x96, 0xb4, 0xb6, 0x1f, 0x09, 0x2c, 0xd2, 0xa0, 0x96, - 0x79, 0x45, 0xbd, 0x71, 0x70, 0x3d, 0xa8, 0x17, 0x45, 0x1e, 0x0b, 0xfb, 0x9b, 0x6b, 0x16, 0x69, - 0x44, 0x02, 0xee, 0x41, 0x6b, 0x32, 0xa7, 0x93, 0x4b, 0x16, 0xd7, 0xe0, 0x71, 0xeb, 0xd9, 0xb8, - 0x23, 0x66, 0xe5, 0x51, 0xcd, 0x89, 0xf8, 0xc4, 0x07, 0xd0, 0x98, 0x38, 0x8b, 0x85, 0x19, 0x0c, - 0x9a, 0x3c, 0xa2, 0x9f, 0x8b, 0xe0, 0xb6, 0xb3, 0x25, 0x4d, 0x7a, 0xb1, 0xed, 0x7a, 0x1f, 0x52, - 0xef, 0x66, 0xd0, 0x2a, 0xda, 0xae, 0xbf, 0x31, 0x13, 0xdb, 0x2e, 0xee, 0xc3, 0x96, 0x62, 0xda, - 0x66, 0x30, 0x9e, 0xcc, 0x75, 0xd3, 0x1e, 0xb4, 0x8b, 0x96, 0x32, 0xb2, 0xcd, 0xe0, 0x88, 0x99, - 0xd9, 0x52, 0xcc, 0x48, 0xc0, 0xa7, 0xd0, 0xb9, 0xa0, 0x33, 0xd3, 0x1e, 0x5f, 0x58, 0xce, 0xe4, - 0x72, 0x00, 0x3c, 0x74, 0x90, 0x0d, 0x3d, 0x64, 0x0e, 0x87, 0xcc, 0x7e, 0xb6, 0xa4, 0xc1, 0x45, - 0x2c, 0xe1, 0x63, 0x68, 0x53, 0xdb, 0x90, 0xa1, 0x1d, 0x1e, 0xba, 0x91, 0x43, 0x80, 0x6d, 0x44, - 0x81, 0x2d, 0x2a, 0xbf, 0x0f, 0x9b, 0x50, 0xbf, 0xd2, 0xad, 0x90, 0xaa, 0xf7, 0xa0, 0x93, 0x42, - 0x0a, 0x0e, 0xa0, 0xb9, 0xa0, 0xbe, 0xaf, 0xcf, 0x28, 0x87, 0x53, 0x5b, 0x8b, 0x44, 0xb5, 0x0b, - 0xcb, 0x69, 0x9c, 0xa8, 0x2b, 0x71, 0x20, 0xc3, 0x82, 0xfa, 0x67, 0x20, 0xf9, 0xa3, 0x46, 0x02, - 0xd5, 0x4b, 0x7a, 0x23, 0x13, 0xb1, 0x4f, 0xec, 0xcb, 0x61, 0x39, 0x00, 0xdb, 0x9a, 0x9c, 0x83, - 0x1a, 0xc7, 0xc6, 0x87, 0x8d, 0x5d, 0xa8, 0x04, 0xd7, 0x3c, 0x74, 0x59, 0xab, 0x04, 0xd7, 0xea, - 0x1d, 0xe8, 0x66, 0x0f, 0xf6, 0x96, 0xc7, 0x6f, 0xe3, 0x09, 0xf2, 0x93, 0x61, 0x63, 0x89, 0xd3, - 0x13, 0x2e, 0x42, 0x50, 0x7b, 0xb0, 0x92, 0x39, 0x6e, 0xf5, 0x38, 0x1e, 0x3c, 0x3e, 0x1e, 0xfc, - 0x23, 0xc0, 0x95, 0x6e, 0x99, 0x86, 0x1e, 0x38, 0x9e, 0x3f, 0x50, 0xee, 0x54, 0xb7, 0x3b, 0x7b, - 0x44, 0xee, 0xea, 0xbb, 0xc8, 0xa0, 0xa5, 0x7c, 0xd4, 0x97, 0xb0, 0x7a, 0xeb, 0xa4, 0x10, 0xa1, - 0x36, 0xd7, 0xfd, 0xb9, 0x9c, 0x00, 0xff, 0xc6, 0xbb, 0xd0, 0x98, 0x53, 0xdd, 0xa0, 0x9e, 0xac, - 0xc1, 0x15, 0x99, 0xf6, 0x8c, 0x2b, 0x35, 0x69, 0x54, 0x77, 0xa0, 0x97, 0x3b, 0x3e, 0xdc, 0x60, - 0x91, 0xe6, 0x6c, 0x1e, 0xf0, 0x7c, 0x35, 0x4d, 0x4a, 0xea, 0xc7, 0x3a, 0xb4, 0x34, 0xea, 0xbb, - 0x8e, 0xed, 0x53, 0x7c, 0x02, 0x6d, 0x7a, 0x3d, 0xa1, 0xa2, 0x12, 0x95, 0x1c, 0x92, 0x84, 0xcf, - 0x49, 0x64, 0x67, 0x28, 0x8c, 0x9d, 0x71, 0x47, 0xb2, 0x48, 0x9e, 0x1a, 0x64, 0x50, 0x9a, 0x46, - 0xee, 0x47, 0x34, 0x52, 0xcd, 0x95, 0x91, 0xf0, 0xcd, 0xf1, 0xc8, 0x8e, 0xe4, 0x91, 0x5a, 0x61, - 0xe2, 0x0c, 0x91, 0xec, 0x67, 0x88, 0xa4, 0x5e, 0x38, 0xfd, 0x12, 0x26, 0xd9, 0xcf, 0x30, 0x49, - 0xa3, 0x30, 0xb4, 0x84, 0x4a, 0x1e, 0xa5, 0xa8, 0xa4, 0x99, 0xab, 0x20, 0x11, 0x58, 0xc0, 0x25, - 0x0f, 0x63, 0x2e, 0x69, 0xe5, 0xd8, 0x47, 0x86, 0xe4, 0xc9, 0xe4, 0x7e, 0x04, 0xc7, 0x76, 0xe1, - 0xa6, 0xe5, 0xd8, 0x64, 0x3f, 0xc3, 0x26, 0x50, 0xb8, 0x9c, 0x12, 0x3a, 0xf9, 0x4b, 0x96, 0x4e, - 0x04, 0x27, 0x6c, 0xe5, 0x62, 0x4b, 0xf9, 0xe4, 0x4f, 0x69, 0x3e, 0x59, 0xce, 0xb1, 0x98, 0xc4, - 0xc2, 0x27, 0x09, 0x65, 0x87, 0x55, 0x42, 0x0e, 0x69, 0xac, 0x16, 0xa9, 0xe7, 0x39, 0x9e, 0xe4, - 0x02, 0x21, 0xa8, 0xdb, 0xac, 0x62, 0x13, 0x7c, 0x7d, 0x82, 0x7c, 0x78, 0xd5, 0xa6, 0xd0, 0xa5, - 0xfe, 0x57, 0x49, 0x62, 0x19, 0x84, 0x58, 0xad, 0x19, 0x7a, 0xa0, 0xcb, 0x40, 0xfe, 0xcd, 0xf2, - 0x5d, 0x51, 0xcf, 0x67, 0x58, 0x12, 0x7c, 0x13, 0x89, 0xb8, 0x0b, 0xab, 0x96, 0xee, 0x07, 0x62, - 0x99, 0x63, 0x59, 0x56, 0x55, 0x5e, 0x56, 0x3d, 0x66, 0x10, 0xeb, 0xe3, 0x6a, 0xfc, 0x03, 0xac, - 0xa5, 0x7c, 0x75, 0xd7, 0x1d, 0xf3, 0xa2, 0xae, 0xf1, 0xa2, 0x26, 0xb1, 0xf7, 0x81, 0xeb, 0x9e, - 0xe9, 0xfe, 0x5c, 0xbd, 0x9b, 0xac, 0x3f, 0xc3, 0x84, 0x96, 0x33, 0x8b, 0x98, 0xd0, 0x72, 0x66, - 0xea, 0xbf, 0x12, 0xb7, 0x84, 0xf4, 0x7e, 0x03, 0xb5, 0x89, 0x63, 0x88, 0xd5, 0x77, 0xf7, 0x7a, - 0x72, 0xdf, 0x8f, 0x1c, 0x83, 0xbe, 0xb9, 0x71, 0xa9, 0xc6, 0x8d, 0xf1, 0x4a, 0x2b, 0x82, 0x55, - 0xf8, 0x4a, 0x65, 0xfe, 0x6a, 0x92, 0xff, 0x9f, 0x8c, 0x40, 0x32, 0xe8, 0xfd, 0x9c, 0xd9, 0xff, - 0x9e, 0x9c, 0x87, 0x20, 0xdb, 0xcf, 0x98, 0xfb, 0x1f, 0x8c, 0xe9, 0xd3, 0x45, 0xf4, 0x39, 0x93, - 0xaf, 0x25, 0xdb, 0x1e, 0x97, 0x8f, 0xda, 0x07, 0xbc, 0x5d, 0x17, 0xe2, 0x46, 0xcb, 0x22, 0x1e, - 0x7f, 0x07, 0x75, 0xc3, 0x9c, 0x4e, 0xfd, 0x41, 0xad, 0xe4, 0x4e, 0x10, 0x66, 0xf5, 0x7f, 0x15, - 0x68, 0x08, 0x46, 0xc7, 0x2d, 0xc6, 0x2e, 0xba, 0x69, 0x8f, 0x4d, 0x23, 0x42, 0x35, 0x97, 0x47, - 0x46, 0x8a, 0xd1, 0x2b, 0x69, 0x46, 0x67, 0x4b, 0x09, 0xcc, 0x05, 0x95, 0x80, 0xe4, 0xdf, 0xb8, - 0x09, 0x4d, 0x3b, 0x5c, 0x8c, 0x83, 0x6b, 0x9f, 0x23, 0xaf, 0xa6, 0x35, 0xec, 0x70, 0xf1, 0xe6, - 0xda, 0xc7, 0x3d, 0x58, 0x49, 0xc1, 0xd3, 0x34, 0x24, 0x6d, 0x76, 0xe5, 0xd4, 0xf8, 0xbc, 0x47, - 0xc7, 0x5a, 0x27, 0x06, 0xea, 0xc8, 0xc0, 0x6d, 0xe0, 0xb8, 0x1d, 0x0b, 0x6a, 0x12, 0x78, 0x6e, - 0xf0, 0x7d, 0xeb, 0x32, 0xbd, 0xe4, 0x2e, 0x76, 0x5d, 0xfd, 0x0a, 0xda, 0x6c, 0x27, 0x85, 0x4b, - 0x93, 0xbb, 0xb4, 0x98, 0x82, 0x1b, 0xef, 0x41, 0x2f, 0xb9, 0x02, 0x85, 0x4b, 0x4b, 0x64, 0x49, - 0xd4, 0xdc, 0x71, 0x0b, 0x5a, 0x71, 0xdd, 0xb4, 0xb9, 0x47, 0x53, 0x97, 0xe5, 0x32, 0x82, 0xa6, - 0x9c, 0x62, 0xe1, 0x75, 0xb9, 0x0b, 0x75, 0x57, 0xf7, 0x02, 0x5f, 0x5e, 0x4b, 0x11, 0x6b, 0x9e, - 0xeb, 0x1e, 0xeb, 0x33, 0xe4, 0xa5, 0x29, 0x5c, 0xd4, 0x7d, 0x58, 0xc9, 0xe8, 0x19, 0xeb, 0x04, - 0x4e, 0xa0, 0x5b, 0xf2, 0xc2, 0x14, 0x42, 0x3c, 0x4c, 0x25, 0x19, 0x46, 0xdd, 0x87, 0x76, 0x7c, - 0x86, 0xec, 0x58, 0xdc, 0xf0, 0xe2, 0x39, 0x8d, 0x3a, 0x07, 0x29, 0xb1, 0x74, 0xae, 0xf3, 0x41, - 0xde, 0xdc, 0x35, 0x4d, 0x08, 0xbb, 0x5f, 0x28, 0xd0, 0x79, 0x21, 0x68, 0x8a, 0xa1, 0x11, 0x7b, - 0xd0, 0x79, 0x19, 0x5a, 0x96, 0x54, 0x91, 0x25, 0x6c, 0x41, 0x8d, 0xb1, 0x1b, 0x51, 0xb0, 0x0d, - 0x75, 0xce, 0x5e, 0xa4, 0xc2, 0x94, 0x8c, 0xb6, 0x48, 0x15, 0x57, 0xa0, 0x1d, 0xf3, 0x04, 0xa9, - 0x31, 0x31, 0xa6, 0x4d, 0x52, 0x67, 0x62, 0x4c, 0x0f, 0x64, 0x15, 0x3b, 0xd0, 0x94, 0xd5, 0x4c, - 0x10, 0x01, 0x1a, 0xe2, 0xa4, 0xc8, 0x1a, 0x4b, 0xcd, 0x0b, 0x91, 0xf4, 0x59, 0x48, 0x0c, 0x6d, - 0xb2, 0x8e, 0x5d, 0x80, 0x04, 0xd4, 0x64, 0x03, 0x97, 0xa1, 0x15, 0xc1, 0x99, 0x6c, 0xee, 0xfe, - 0xbf, 0x0e, 0xad, 0xa8, 0x90, 0xb0, 0x01, 0x95, 0x57, 0xcf, 0xc9, 0x12, 0xae, 0xc2, 0xca, 0xc8, - 0x0e, 0xa8, 0x67, 0xeb, 0xd6, 0x09, 0x23, 0x6a, 0xa2, 0x30, 0xd5, 0x89, 0x3d, 0x71, 0x0c, 0xd3, - 0x9e, 0x09, 0x55, 0x85, 0x25, 0x3a, 0xd4, 0x8d, 0x97, 0x8e, 0x3d, 0xa1, 0xa4, 0x8a, 0x04, 0x96, - 0xdf, 0xda, 0x7a, 0x18, 0xcc, 0x1d, 0xcf, 0xfc, 0x0f, 0x35, 0x48, 0x0d, 0xd7, 0x61, 0x75, 0x64, - 0xfb, 0xe1, 0x74, 0x6a, 0x4e, 0x4c, 0x6a, 0x07, 0xcf, 0x42, 0xdb, 0xf0, 0x49, 0x1d, 0x11, 0xba, - 0x6f, 0xed, 0x4b, 0xdb, 0xf9, 0x60, 0xcb, 0x06, 0x87, 0x34, 0x70, 0x00, 0xfd, 0x43, 0xdd, 0xa7, - 0xc7, 0xa1, 0x6b, 0x99, 0x13, 0x3d, 0xa0, 0x07, 0x86, 0xe1, 0x51, 0xdf, 0x27, 0x94, 0x25, 0x61, - 0x96, 0xec, 0xd8, 0xd3, 0x28, 0x20, 0x93, 0x9f, 0x52, 0x9f, 0xcc, 0x70, 0x0b, 0xd6, 0x6f, 0x59, - 0xf8, 0xc8, 0x73, 0xfc, 0x35, 0x0c, 0xf2, 0xa6, 0x53, 0xdd, 0x3f, 0xf7, 0xcc, 0x09, 0x25, 0x26, - 0xf6, 0x81, 0x08, 0x2b, 0xc7, 0xee, 0xc8, 0x76, 0xc3, 0x80, 0xfc, 0x3b, 0x1a, 0x5f, 0x6a, 0x5f, - 0x85, 0x01, 0x53, 0x5f, 0xe6, 0xd4, 0xe7, 0x1c, 0x1f, 0xc4, 0xc2, 0x4d, 0x58, 0x4b, 0xa9, 0x5f, - 0xb3, 0xf5, 0xb1, 0xdd, 0x59, 0x24, 0xf3, 0x15, 0x06, 0x73, 0x66, 0xeb, 0x41, 0xe8, 0x51, 0x62, - 0xe3, 0x06, 0x20, 0xb3, 0xc8, 0x2d, 0x89, 0x16, 0xee, 0x44, 0x23, 0x48, 0xbd, 0x1c, 0xc1, 0xcd, - 0xab, 0xad, 0x70, 0x66, 0xda, 0xe4, 0x3d, 0xae, 0x03, 0x39, 0x75, 0xae, 0xa4, 0xf6, 0xc4, 0x0e, - 0xcc, 0xe0, 0x86, 0x7c, 0xa5, 0x60, 0x1f, 0x7a, 0x89, 0xfa, 0xd4, 0x73, 0x42, 0x97, 0x7c, 0xad, - 0xe0, 0x26, 0x60, 0xa2, 0x3d, 0xf7, 0x1c, 0xd7, 0xf1, 0x75, 0x8b, 0x7c, 0xa3, 0xe0, 0x06, 0xac, - 0x9e, 0x3a, 0x57, 0xf1, 0x29, 0x88, 0x80, 0x6f, 0xa3, 0x80, 0x58, 0xff, 0x82, 0x2e, 0x2e, 0xa8, - 0x47, 0xbe, 0x53, 0x70, 0x0b, 0xfa, 0x69, 0x43, 0x9c, 0xeb, 0x7b, 0x45, 0xce, 0x28, 0x36, 0xbd, - 0x73, 0x02, 0x4a, 0x7e, 0x88, 0xd4, 0x72, 0x1f, 0x64, 0xa2, 0x1f, 0x15, 0x5c, 0x83, 0x6e, 0xa2, - 0xe6, 0xbe, 0x3f, 0x29, 0x38, 0x84, 0xf5, 0x8c, 0xd2, 0xb4, 0x67, 0xe7, 0xac, 0xe4, 0xc8, 0xcf, - 0xca, 0xde, 0xc7, 0x3a, 0xf4, 0x0e, 0x0e, 0x8f, 0x46, 0x07, 0xae, 0x18, 0x80, 0x5d, 0xb2, 0x0f, - 0x45, 0xa1, 0x61, 0xc1, 0x0b, 0x78, 0x58, 0xd4, 0xcf, 0xe2, 0x9e, 0xac, 0x47, 0x2c, 0x7a, 0x08, - 0x0f, 0x0b, 0xdb, 0x5a, 0x36, 0x88, 0xe8, 0x37, 0x6e, 0xbf, 0x87, 0x87, 0x45, 0xbd, 0x2d, 0xfe, - 0x35, 0x55, 0xdf, 0x58, 0xf6, 0x2a, 0x1e, 0x96, 0x76, 0xb9, 0x2c, 0x3e, 0x69, 0x10, 0xca, 0xde, - 0xc6, 0xc3, 0xd2, 0x56, 0x17, 0x9f, 0xc4, 0x94, 0x81, 0xc5, 0x2f, 0xe4, 0x61, 0x49, 0xb7, 0xcb, - 0xb6, 0x47, 0x5c, 0xee, 0x45, 0x0f, 0xdf, 0x61, 0x61, 0x03, 0x8b, 0x8f, 0x23, 0x4e, 0xc2, 0xc2, - 0xc7, 0xf5, 0xb0, 0xb8, 0x4d, 0x66, 0x8b, 0x4c, 0x5e, 0x5f, 0x65, 0xaf, 0xe6, 0x61, 0x69, 0x03, - 0x8c, 0x07, 0x69, 0x92, 0xc3, 0xd2, 0xb7, 0xf3, 0xb0, 0xbc, 0x0d, 0xc6, 0xa7, 0x09, 0x2f, 0x62, - 0xc9, 0x0b, 0x7a, 0x58, 0xd6, 0x09, 0x5f, 0x34, 0xf8, 0x9f, 0x33, 0x8f, 0x7e, 0x09, 0x00, 0x00, - 0xff, 0xff, 0x84, 0x7d, 0xd1, 0x2f, 0xb1, 0x11, 0x00, 0x00, + // 1697 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x6f, 0x1b, 0x47, + 0x12, 0xf6, 0xf0, 0xcd, 0xa6, 0x44, 0xb6, 0x5a, 0x92, 0x4d, 0x73, 0xf7, 0x60, 0xcc, 0xc2, 0x6b, + 0x49, 0xeb, 0xb5, 0x17, 0x32, 0x76, 0xb1, 0x5a, 0x2f, 0x02, 0x48, 0xb2, 0x6c, 0x13, 0x86, 0x6d, + 0x65, 0xfc, 0xb8, 0x24, 0x08, 0x31, 0xe2, 0x34, 0xc5, 0x89, 0xa8, 0x99, 0xf1, 0x3c, 0x64, 0x29, + 0xbf, 0x21, 0xf7, 0xfc, 0x84, 0xdc, 0x03, 0xe4, 0x94, 0x7b, 0x80, 0xbc, 0x1f, 0xbf, 0x28, 0x55, + 0xdd, 0x3d, 0x4f, 0xcd, 0x18, 0x39, 0xf8, 0x42, 0x4c, 0x3d, 0xbb, 0xab, 0xab, 0xea, 0xeb, 0x6a, + 0x92, 0x95, 0xf0, 0xc2, 0xe3, 0xc1, 0x5d, 0xf1, 0x7b, 0xc7, 0xf3, 0xdd, 0xd0, 0x65, 0x4d, 0x41, + 0xe8, 0xdf, 0x36, 0x48, 0xdb, 0xe0, 0x6f, 0x22, 0x1e, 0x84, 0x6c, 0x83, 0x34, 0xf8, 0x74, 0xee, + 0x0e, 0xb5, 0x1b, 0xda, 0x46, 0x6f, 0x9b, 0xdd, 0x91, 0xea, 0x4a, 0x7a, 0x00, 0x92, 0xc7, 0x57, + 0x0c, 0xa1, 0xc1, 0xfe, 0x41, 0x9a, 0xb3, 0x45, 0x14, 0xcc, 0x87, 0x35, 0xa1, 0xba, 0x9a, 0x57, + 0x7d, 0x88, 0x22, 0xd0, 0x95, 0x3a, 0xe8, 0xd6, 0x76, 0x66, 0xee, 0xb0, 0x5e, 0xe6, 0x76, 0x0c, + 0x12, 0x74, 0x8b, 0x1a, 0xec, 0xbf, 0x84, 0x04, 0x3c, 0x9c, 0xb8, 0x5e, 0x68, 0xbb, 0xce, 0xb0, + 0x21, 0xf4, 0xaf, 0xe5, 0xf5, 0x5f, 0xf0, 0xf0, 0xb9, 0x10, 0x83, 0x51, 0x37, 0x88, 0x09, 0xb4, + 0xb4, 0xf8, 0xc2, 0x3e, 0xe3, 0xfe, 0x24, 0x3c, 0x1f, 0x36, 0xcb, 0x2c, 0x1f, 0x48, 0xf9, 0xcb, + 0x73, 0xb4, 0xb4, 0x62, 0x82, 0x6d, 0x93, 0xce, 0x74, 0xce, 0xa7, 0x27, 0x68, 0xd7, 0x12, 0x76, + 0xeb, 0x79, 0xbb, 0x7d, 0x94, 0x0a, 0xab, 0xf6, 0x54, 0x7e, 0xb2, 0x3b, 0xa4, 0x35, 0x75, 0x4f, + 0x4f, 0xed, 0x70, 0xd8, 0x16, 0x16, 0x6b, 0x05, 0x0b, 0x21, 0x03, 0x03, 0xa5, 0x85, 0xc7, 0x05, + 0x02, 0xff, 0x62, 0xd8, 0x29, 0x3b, 0xae, 0x0f, 0x51, 0x84, 0xc7, 0x25, 0x74, 0x30, 0x14, 0xdb, + 0xb1, 0xc3, 0xc9, 0x74, 0x6e, 0xda, 0xce, 0xb0, 0x5b, 0x16, 0xca, 0x18, 0xe4, 0xfb, 0x28, 0xc6, + 0x50, 0xec, 0x98, 0x60, 0xf7, 0x49, 0xef, 0x88, 0x1f, 0xdb, 0xce, 0xe4, 0x68, 0xe1, 0x4e, 0x4f, + 0x86, 0x44, 0x98, 0x0e, 0xf3, 0xa6, 0x7b, 0xa8, 0xb0, 0x87, 0x72, 0xb0, 0x25, 0x47, 0x09, 0xc5, + 0xfe, 0x4d, 0xba, 0xdc, 0xb1, 0x94, 0x69, 0x4f, 0x98, 0x5e, 0x2d, 0x54, 0x80, 0x63, 0xc5, 0x86, + 0x1d, 0xae, 0xbe, 0xf7, 0xda, 0xa4, 0x79, 0x66, 0x2e, 0x22, 0xae, 0xdf, 0x22, 0xbd, 0x4c, 0xa5, + 0xb0, 0x21, 0x69, 0x9f, 0xf2, 0x20, 0x30, 0x8f, 0xb9, 0x28, 0xa7, 0xae, 0x11, 0x93, 0x7a, 0x9f, + 0x2c, 0x65, 0xeb, 0x44, 0x5f, 0x4e, 0x0c, 0xb1, 0x16, 0xf4, 0xff, 0x11, 0x5a, 0x4c, 0x35, 0xa3, + 0xa4, 0x7e, 0xc2, 0x2f, 0x94, 0x23, 0xfc, 0x64, 0x6b, 0x6a, 0x59, 0x51, 0x80, 0x5d, 0x43, 0xed, + 0x41, 0x4f, 0x6c, 0x93, 0x64, 0xb3, 0x3e, 0xa9, 0x41, 0x66, 0xd1, 0x74, 0xc9, 0x80, 0x2f, 0xfd, + 0x06, 0xe9, 0xe7, 0x13, 0x7b, 0x49, 0xc3, 0x4a, 0x36, 0x28, 0x32, 0xc3, 0x18, 0x69, 0x58, 0x66, + 0x68, 0x2a, 0x0d, 0xf1, 0x8d, 0x3c, 0xcf, 0x0c, 0xe7, 0x6a, 0x79, 0xf1, 0xcd, 0xae, 0x92, 0xd6, + 0x9c, 0xdb, 0xc7, 0xf3, 0x50, 0x54, 0x7a, 0xc3, 0x50, 0x14, 0xee, 0x15, 0x5a, 0xee, 0x8c, 0x8b, + 0x82, 0xee, 0x18, 0x92, 0xd0, 0x07, 0x64, 0x39, 0x57, 0x2e, 0xfa, 0x83, 0x64, 0xf3, 0x49, 0x7a, + 0xd9, 0xbf, 0x08, 0x81, 0xc8, 0x6c, 0x58, 0xd2, 0xf5, 0x03, 0xd8, 0x40, 0x1d, 0xb2, 0x42, 0x55, + 0x56, 0x5e, 0xc7, 0x02, 0x23, 0xa3, 0xa3, 0x3f, 0x23, 0x2b, 0x97, 0x32, 0x8d, 0xbb, 0x9d, 0x9b, + 0xd0, 0xad, 0x2a, 0x02, 0xfc, 0x66, 0x37, 0x71, 0xb7, 0xa6, 0xc5, 0x7d, 0xd5, 0xc3, 0xcb, 0xca, + 0xed, 0x63, 0xc1, 0x34, 0x94, 0x50, 0xdf, 0x24, 0x83, 0x42, 0xfa, 0x33, 0x71, 0x6a, 0xd9, 0x38, + 0xf5, 0xcf, 0x9b, 0xa4, 0x63, 0xf0, 0xc0, 0x73, 0x9d, 0x80, 0x43, 0x15, 0x77, 0xf9, 0xf9, 0x94, + 0xcb, 0x4e, 0xd6, 0x0a, 0x95, 0x28, 0x75, 0x0e, 0x62, 0x39, 0x56, 0x71, 0xa2, 0xcc, 0x36, 0x15, + 0x0a, 0x15, 0xa1, 0x45, 0x19, 0x65, 0x61, 0xe8, 0x76, 0x0c, 0x43, 0xf5, 0x42, 0x1b, 0x4a, 0xdd, + 0x02, 0x0e, 0x6d, 0x2a, 0x1c, 0x6a, 0x94, 0x3a, 0xce, 0x01, 0xd1, 0x4e, 0x0e, 0x88, 0x9a, 0xa5, + 0xdb, 0xaf, 0x40, 0xa2, 0x9d, 0x1c, 0x12, 0xb5, 0x4a, 0x4d, 0x2b, 0xa0, 0xe8, 0x5e, 0x06, 0x8a, + 0xda, 0x85, 0x0e, 0x94, 0x86, 0x25, 0x58, 0x74, 0x37, 0xc1, 0xa2, 0x4e, 0x01, 0xbd, 0x94, 0x49, + 0x11, 0x8c, 0x6e, 0xc7, 0x60, 0xd4, 0x2d, 0x3d, 0xb4, 0x02, 0x1a, 0xed, 0xe4, 0xd0, 0x88, 0x94, + 0x86, 0x53, 0x01, 0x47, 0xff, 0xcf, 0xc3, 0x91, 0xc4, 0x94, 0xeb, 0x05, 0xdb, 0x4a, 0x3c, 0xfa, + 0x4f, 0x16, 0x8f, 0x96, 0x0a, 0x28, 0xa8, 0x6a, 0xe1, 0x9d, 0x80, 0xb4, 0x89, 0x9d, 0x50, 0xa8, + 0x34, 0xec, 0x45, 0xee, 0xfb, 0xae, 0xaf, 0xb0, 0x44, 0x12, 0xfa, 0x06, 0x76, 0x7c, 0x5a, 0x5f, + 0xef, 0x00, 0x2f, 0xd1, 0xb5, 0x99, 0xea, 0xd2, 0xbf, 0xd0, 0x52, 0x5b, 0x2c, 0xa1, 0x1c, 0x5a, + 0x74, 0x15, 0x5a, 0x80, 0x3f, 0xc8, 0x70, 0x80, 0xb5, 0x24, 0x01, 0x23, 0x26, 0xd9, 0x16, 0x59, + 0x59, 0x98, 0x41, 0x28, 0xc3, 0x9c, 0xe4, 0xe0, 0x63, 0x80, 0x02, 0x19, 0x9f, 0xc4, 0x91, 0x7f, + 0x92, 0xd5, 0x8c, 0xae, 0xe9, 0x79, 0x13, 0xd1, 0xd4, 0x0d, 0xd1, 0xd4, 0x34, 0xd1, 0xde, 0xf5, + 0xbc, 0xc7, 0xc0, 0xd7, 0x6f, 0xa6, 0xf1, 0xe7, 0x90, 0x74, 0xe1, 0x1e, 0xc7, 0x48, 0x0a, 0x9f, + 0xfa, 0x27, 0xa9, 0x5a, 0x0a, 0x9a, 0x7f, 0x23, 0x8d, 0xa9, 0x6b, 0xc9, 0xe8, 0xfb, 0xdb, 0x03, + 0x75, 0xee, 0xfb, 0xc0, 0x7a, 0x09, 0x5f, 0x86, 0x10, 0x26, 0x91, 0xd6, 0x32, 0xb8, 0xa8, 0xfc, + 0xd7, 0x53, 0xff, 0x1f, 0x23, 0x80, 0xe4, 0xaa, 0xf7, 0x7d, 0x7a, 0xff, 0x4a, 0x4b, 0x13, 0x22, + 0xd1, 0xfa, 0x4f, 0x39, 0x87, 0x32, 0xb0, 0x1d, 0x8b, 0x9f, 0x0b, 0xef, 0x75, 0x43, 0x12, 0xf1, + 0x35, 0x53, 0x17, 0x2b, 0xe6, 0xaf, 0x19, 0x79, 0xc8, 0x92, 0x50, 0x80, 0xee, 0xce, 0x04, 0x30, + 0x2c, 0x19, 0x92, 0xc8, 0xc0, 0x62, 0x2b, 0x07, 0xff, 0x6a, 0xd3, 0xed, 0x74, 0xd3, 0x1f, 0xe1, + 0x15, 0x94, 0xed, 0xce, 0xf7, 0x79, 0x22, 0xab, 0x69, 0x3e, 0x93, 0xbe, 0xd4, 0xd7, 0x08, 0xbb, + 0xdc, 0x70, 0xf2, 0xaa, 0xcd, 0xb7, 0x12, 0xfb, 0x3b, 0x69, 0x5a, 0xf6, 0x6c, 0x16, 0x40, 0xc4, + 0xe5, 0x97, 0x8d, 0x14, 0xeb, 0x5f, 0xd6, 0x48, 0x4b, 0x5e, 0x15, 0xec, 0x3a, 0xc2, 0x16, 0xac, + 0x32, 0xb1, 0xad, 0xb8, 0x5d, 0x04, 0x3d, 0xb6, 0x32, 0x67, 0x52, 0xcb, 0x9d, 0x09, 0x84, 0x12, + 0xda, 0xa7, 0x5c, 0x55, 0xba, 0xf8, 0x66, 0xd7, 0x48, 0xdb, 0x89, 0x4e, 0x01, 0xfb, 0x02, 0x71, + 0xda, 0xa0, 0x0c, 0xe4, 0xcb, 0xf3, 0x00, 0x26, 0xb4, 0xe5, 0x4c, 0xdd, 0xc3, 0x22, 0x12, 0x8f, + 0xfb, 0x6a, 0x6b, 0x62, 0xdf, 0xe3, 0x07, 0x46, 0x2f, 0xe9, 0x00, 0x58, 0x78, 0x83, 0x88, 0x86, + 0x98, 0x48, 0xcc, 0x93, 0x8d, 0xd2, 0x12, 0xe7, 0xd6, 0x47, 0xbe, 0x02, 0x45, 0xbc, 0x07, 0xff, + 0x42, 0xba, 0x78, 0x92, 0x52, 0xa5, 0x2d, 0x54, 0x3a, 0xc8, 0x10, 0xc2, 0x5b, 0x64, 0x90, 0xde, + 0xad, 0x52, 0xa5, 0x23, 0xbd, 0xa4, 0x6c, 0xa1, 0x08, 0x67, 0x90, 0x34, 0x64, 0x57, 0x68, 0xb4, + 0x4d, 0xd5, 0x87, 0x63, 0xd2, 0x56, 0x5b, 0x2c, 0xbd, 0x87, 0xb7, 0xa0, 0x98, 0x4c, 0x3f, 0x0c, + 0xd4, 0x7d, 0x17, 0xc3, 0xf1, 0x21, 0xf0, 0xa0, 0x6d, 0xd5, 0x6d, 0x2c, 0x55, 0xf4, 0x1d, 0xb2, + 0x9c, 0xe3, 0x63, 0x25, 0x86, 0x6e, 0x68, 0x2e, 0xd4, 0x4d, 0x2c, 0x89, 0x64, 0x99, 0x5a, 0xba, + 0x0c, 0x98, 0x76, 0x93, 0x1c, 0x62, 0x5a, 0xbc, 0xe8, 0xe8, 0x89, 0x1a, 0xa9, 0x96, 0x0c, 0x45, + 0x89, 0xc2, 0x76, 0xdf, 0xaa, 0x91, 0x00, 0xdc, 0x09, 0x62, 0xeb, 0x1b, 0x8d, 0xf4, 0x9e, 0x4a, + 0xfc, 0xc3, 0x6a, 0x64, 0x03, 0xd2, 0x7b, 0x16, 0x2d, 0x16, 0x8a, 0x45, 0xaf, 0xb0, 0x0e, 0x69, + 0x20, 0x6c, 0x52, 0x8d, 0x75, 0x49, 0x53, 0xc0, 0x22, 0xad, 0x21, 0x13, 0xf1, 0x90, 0xd6, 0xd9, + 0x32, 0xe9, 0x26, 0x00, 0x44, 0x1b, 0x48, 0x26, 0x78, 0x4c, 0x9b, 0x48, 0x26, 0xb8, 0x43, 0x57, + 0x58, 0x8f, 0xb4, 0x15, 0x4c, 0x50, 0x88, 0x83, 0xb4, 0x64, 0xa6, 0xe8, 0x2a, 0xba, 0x16, 0x0d, + 0x4e, 0xd7, 0xd0, 0x24, 0x29, 0x6d, 0xba, 0x0e, 0xf3, 0x1b, 0x49, 0x8b, 0x9a, 0x5e, 0x65, 0x4b, + 0xa4, 0x13, 0x97, 0x33, 0xbd, 0xb6, 0xf5, 0x35, 0x4c, 0x25, 0x71, 0x23, 0xb1, 0x16, 0xa9, 0x3d, + 0x7f, 0x02, 0x3b, 0x5e, 0x21, 0xcb, 0x63, 0x27, 0xe4, 0xbe, 0x63, 0x2e, 0x0e, 0xf0, 0x06, 0x80, + 0xad, 0x03, 0xeb, 0xc0, 0x81, 0x3e, 0xb3, 0x9d, 0x63, 0xc9, 0xaa, 0xa1, 0xa3, 0x3d, 0xd3, 0x7a, + 0xe6, 0x3a, 0x53, 0x0e, 0x61, 0x50, 0xb2, 0xf4, 0xca, 0x31, 0xa3, 0x70, 0xee, 0xfa, 0xf6, 0x67, + 0xdc, 0x82, 0x48, 0xd6, 0xc9, 0xca, 0xd8, 0x09, 0xa2, 0xd9, 0xcc, 0x9e, 0xda, 0xdc, 0x09, 0x1f, + 0x46, 0x8e, 0x15, 0x40, 0x44, 0x8c, 0xf4, 0x5f, 0x39, 0x27, 0x8e, 0xfb, 0xd6, 0x51, 0x93, 0x13, + 0x6d, 0xc1, 0x0d, 0xb0, 0xb6, 0x67, 0x02, 0xc2, 0x46, 0xde, 0xc2, 0x9e, 0x9a, 0x21, 0xdf, 0xb5, + 0x2c, 0x1f, 0xce, 0x8f, 0x72, 0x74, 0x82, 0x92, 0xfc, 0xda, 0xb3, 0xd8, 0x20, 0xe7, 0x9f, 0xf3, + 0x80, 0x1e, 0x43, 0xa9, 0xad, 0x5f, 0x92, 0x88, 0x95, 0xe7, 0xec, 0xaf, 0x64, 0x58, 0x14, 0x3d, + 0x32, 0x83, 0x43, 0xdf, 0x86, 0x00, 0x6c, 0xc8, 0x2e, 0x95, 0x52, 0x51, 0xbb, 0x63, 0xc7, 0x8b, + 0x42, 0xfa, 0x69, 0xbc, 0xbe, 0xe2, 0x3e, 0x8f, 0x42, 0x64, 0x9f, 0x14, 0xd8, 0x87, 0xa2, 0x3e, + 0xe8, 0x02, 0x9a, 0x74, 0x35, 0xc3, 0x7e, 0x81, 0xf1, 0xe1, 0xe9, 0x9c, 0xa6, 0xfb, 0x95, 0x02, + 0xfb, 0xd8, 0x31, 0xc3, 0xc8, 0xe7, 0xd4, 0x81, 0x62, 0x63, 0x28, 0x51, 0x47, 0x12, 0x07, 0xee, + 0xc6, 0x2b, 0x28, 0xbe, 0x5a, 0xc1, 0x2b, 0xb2, 0x17, 0x11, 0x64, 0x96, 0xbe, 0x01, 0x36, 0x7d, + 0xe4, 0x9e, 0x29, 0xee, 0x81, 0x13, 0xda, 0xe1, 0x05, 0xfd, 0x4e, 0x83, 0x98, 0x06, 0x29, 0xfb, + 0x91, 0xef, 0x46, 0x1e, 0xfd, 0x5e, 0x83, 0x5d, 0xb2, 0x94, 0x7b, 0xe8, 0xbb, 0x9e, 0x1b, 0x98, + 0x0b, 0xfa, 0x83, 0x06, 0x7b, 0x59, 0x01, 0x41, 0x92, 0x05, 0x69, 0xf0, 0x63, 0x6c, 0x90, 0xf0, + 0x9f, 0xf2, 0xd3, 0x23, 0xee, 0xd3, 0x9f, 0x34, 0x38, 0xec, 0xb5, 0xac, 0x20, 0xf1, 0xf5, 0xb3, + 0xa6, 0x76, 0x94, 0x88, 0x5e, 0xbb, 0x21, 0xa7, 0xbf, 0xc4, 0x6c, 0x75, 0x0e, 0xca, 0xd1, 0xaf, + 0x1a, 0x5b, 0x25, 0xfd, 0x94, 0x2d, 0x74, 0x7f, 0xd3, 0xd8, 0x88, 0xac, 0xe7, 0x98, 0x90, 0xff, + 0x43, 0x6c, 0x39, 0xfa, 0xbb, 0xb6, 0x0d, 0xd3, 0xf4, 0x60, 0x77, 0x6f, 0x7f, 0x0c, 0xd7, 0xb9, + 0x58, 0x00, 0x6f, 0xef, 0xbb, 0xb2, 0xd1, 0x58, 0xc9, 0xd3, 0x7c, 0x54, 0x36, 0x28, 0x03, 0x74, + 0xca, 0x7e, 0x64, 0x65, 0x2f, 0xf4, 0x51, 0xe9, 0xbc, 0x8c, 0x8b, 0xc8, 0x41, 0xe6, 0xf2, 0x43, + 0x7d, 0x54, 0x36, 0x34, 0xb3, 0x0f, 0x32, 0xfd, 0xcd, 0xaa, 0x9e, 0xeb, 0xa3, 0xca, 0xf1, 0x19, + 0xed, 0xd3, 0xc9, 0xa3, 0xea, 0xd1, 0x3e, 0xaa, 0x9c, 0xa1, 0xe1, 0xa9, 0x11, 0x43, 0x06, 0x2b, + 0x7f, 0xba, 0x8f, 0x2a, 0xc6, 0x68, 0x3c, 0x1e, 0x39, 0x34, 0x94, 0xbd, 0xc8, 0x47, 0xa5, 0x93, + 0x31, 0xbc, 0x93, 0x15, 0x26, 0xb1, 0xd2, 0x57, 0xff, 0xa8, 0x7c, 0xfe, 0xc6, 0x20, 0xd3, 0x67, + 0x5d, 0xd5, 0x73, 0x7e, 0x54, 0x39, 0x59, 0xb3, 0xdd, 0x2c, 0xc8, 0xb1, 0xca, 0x47, 0xfd, 0xa8, + 0x7a, 0xbe, 0x66, 0xf7, 0x53, 0x5c, 0x64, 0x15, 0x4f, 0xfb, 0x51, 0xd5, 0x88, 0x7d, 0xd4, 0x12, + 0xff, 0x1a, 0xdd, 0xfb, 0x23, 0x00, 0x00, 0xff, 0xff, 0x73, 0x34, 0x90, 0x2d, 0x4a, 0x12, 0x00, + 0x00, } diff --git a/types/types.proto b/types/types.proto index b3ff1655e..0c741d3d0 100644 --- a/types/types.proto +++ b/types/types.proto @@ -6,67 +6,67 @@ package types; //---------------------------------------- // Message types -// Not being used +// Not being used // Could be added to request/response // so we don't have to type switch // (would be twice as fast, but we're talking about 15ns) enum MessageType { - NullMessage = 0x00; - - Echo = 0x01; - Flush = 0x02; - Info = 0x03; - SetOption = 0x04; - Exception = 0x05; - DeliverTx = 0x11; - CheckTx = 0x12; - Commit = 0x13; - Query = 0x14; - InitChain = 0x15; - BeginBlock = 0x16; - EndBlock = 0x17; + NullMessage = 0x00; + + Echo = 0x01; + Flush = 0x02; + Info = 0x03; + SetOption = 0x04; + Exception = 0x05; + DeliverTx = 0x11; + CheckTx = 0x12; + Commit = 0x13; + Query = 0x14; + InitChain = 0x15; + BeginBlock = 0x16; + EndBlock = 0x17; } //---------------------------------------- // 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; } @@ -105,15 +105,18 @@ message RequestSetOption{ } message RequestDeliverTx{ - bytes tx = 1; + bytes tx = 1; } message RequestCheckTx{ - bytes tx = 1; + bytes tx = 1; } message RequestQuery{ - bytes query = 1; + bytes data = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; } message RequestCommit{ @@ -189,8 +192,12 @@ message ResponseCheckTx{ message ResponseQuery{ CodeType code = 1; - bytes data = 2; - string log = 3; + int64 index = 2; + bytes key = 3; + bytes value = 4; + bytes proof = 5; + uint64 height = 6; + string log = 7; } message ResponseCommit{ @@ -207,7 +214,7 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 4; + repeated Validator diffs = 1; } //---------------------------------------- @@ -222,7 +229,7 @@ message Header { bytes last_commit_hash = 6; bytes data_hash = 7; bytes validators_hash = 8; - bytes app_hash = 9; + bytes app_hash = 9; } message BlockID { @@ -236,8 +243,8 @@ message PartSetHeader { } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; } //---------------------------------------- diff --git a/version/version.go b/version/version.go new file mode 100644 index 000000000..04695d9b8 --- /dev/null +++ b/version/version.go @@ -0,0 +1,9 @@ +package version + +// NOTE: we should probably be versioning the ABCI and the abci-cli separately + +const Maj = "0" +const Min = "4" +const Fix = "0" + +const Version = "0.4.0" // new Query args and response (with proof!)