From 0bd4061cf6496df6796d456f21fc6df28d20e48f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 2 Nov 2015 07:39:53 -0800 Subject: [PATCH 001/545] initial commit --- README.md | 63 ++++++++++++++++++ cmd/cli.go | 127 +++++++++++++++++++++++++++++++++++ example/main.go | 84 +++++++++++++++++++++++ example/main_test.go | 52 +++++++++++++++ server/server.go | 136 +++++++++++++++++++++++++++++++++++++ types/application.go | 31 +++++++++ types/events.go | 14 ++++ types/messages.go | 155 +++++++++++++++++++++++++++++++++++++++++++ types/retcode.go | 12 ++++ 9 files changed, 674 insertions(+) create mode 100644 README.md create mode 100644 cmd/cli.go create mode 100644 example/main.go create mode 100644 example/main_test.go create mode 100644 server/server.go create mode 100644 types/application.go create mode 100644 types/events.go create mode 100644 types/messages.go create mode 100644 types/retcode.go diff --git a/README.md b/README.md new file mode 100644 index 00000000..2e5b5652 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# Tendermint Streaming Protocol (TMSP) + +**TMSP** is a socket protocol, which means applications can be written in any programming language. +TMSP is an asynchronous streaming protocol: message responses are written back asynchronously to the platform. + +*Applications must be deterministic.* + +## Message types + +#### AppendTx + * __Arguments__: + * `TxBytes ([]byte)` + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Append and run a transaction. The transaction may or may not be final. + +#### GetHash + * __Returns__: + * `RetCode (int8)` + * `Hash ([]byte)` + * __Usage__:
+ Return a Merkle root hash of the application state + +#### Commit + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Finalize all appended transactions + +#### Rollback + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Roll back to the last commit + +#### SetEventsMode + * __Arguments__: + * `EventsMode (int8)`: + * `EventsModeOff (0)`: Events are not reported. Used for mempool. + * `EventsModeCached (1)`: Events are cached. + * `EventsModeOn (2)`: Flush cache and report events. + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Set event reporting mode for future transactions + +#### AddListener + * __Arguments__: + * `EventKey (string)` + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Add event listener callback for events with given key. + +#### RemoveListener + * __Arguments__: + * `EventKey (string)` + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Remove event listener callback for events with given key. + diff --git a/cmd/cli.go b/cmd/cli.go new file mode 100644 index 00000000..2885b991 --- /dev/null +++ b/cmd/cli.go @@ -0,0 +1,127 @@ +package main + +import ( + "fmt" + "net" + "os" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" + + "github.com/codegangsta/cli" +) + +func main() { + app := cli.NewApp() + app.Name = "cli" + app.Usage = "cli [command] [args...]" + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "address", + Value: "tcp://127.0.0.1:8080", + Usage: "address of application socket", + }, + } + app.Commands = []cli.Command{ + { + Name: "append_tx", + Usage: "Append a new tx to application", + Action: func(c *cli.Context) { + cmdAppendTx(c) + }, + }, + { + Name: "get_hash", + Usage: "Get application Merkle root hash", + Action: func(c *cli.Context) { + cmdGetHash(c) + }, + }, + { + Name: "commit", + Usage: "Commit the application state", + Action: func(c *cli.Context) { + cmdCommit(c) + }, + }, + { + Name: "rollback", + Usage: "Roll back the application state to the latest commit", + Action: func(c *cli.Context) { + cmdRollback(c) + }, + }, + } + app.Run(os.Args) + +} + +//-------------------------------------------------------------------------------- + +// Append a new tx to application +func cmdAppendTx(c *cli.Context) { + args := c.Args() // Args to AppendTx + conn, err := Connect(c.GlobalString("address")) + if err != nil { + Exit(err.Error()) + } + res, err := write(conn, types.RequestAppendTx{[]byte(args[0])}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("Sent tx:", args[0], "response:", res) +} + +// Get application Merkle root hash +func cmdGetHash(c *cli.Context) { + conn, err := Connect(c.GlobalString("address")) + if err != nil { + Exit(err.Error()) + } + res, err := write(conn, types.RequestGetHash{}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("Got hash:", Fmt("%X", res.(types.ResponseGetHash).Hash)) +} + +// Commit the application state +func cmdCommit(c *cli.Context) { + conn, err := Connect(c.GlobalString("address")) + if err != nil { + Exit(err.Error()) + } + _, err = write(conn, types.RequestCommit{}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("Committed.") +} + +// Roll back the application state to the latest commit +func cmdRollback(c *cli.Context) { + conn, err := Connect(c.GlobalString("address")) + if err != nil { + Exit(err.Error()) + } + _, err = write(conn, types.RequestRollback{}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("Rolled back.") +} + +//-------------------------------------------------------------------------------- + +func write(conn net.Conn, req types.Request) (types.Response, error) { + var n int64 + var err error + wire.WriteBinary(req, conn, &n, &err) + if err != nil { + return nil, err + } + var res types.Response + wire.ReadBinaryPtr(&res, conn, &n, &err) + return res, err +} diff --git a/example/main.go b/example/main.go new file mode 100644 index 00000000..bf6f06d9 --- /dev/null +++ b/example/main.go @@ -0,0 +1,84 @@ +package main + +import ( + . "github.com/tendermint/go-common" + "github.com/tendermint/go-merkle" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" +) + +func main() { + + // Start the listener + _, err := server.StartListener("tcp://127.0.0.1:8080", &DummyApplication{}) + if err != nil { + Exit(err.Error()) + } + + // Wait forever + TrapSignal(func() { + // Cleanup + }) + +} + +//-------------------------------------------------------------------------------- + +type DummyApplication struct { + state merkle.Tree + lastCommitState merkle.Tree +} + +func NewDummyApplication() *DummyApplication { + state := merkle.NewIAVLTree( + wire.BasicCodec, + wire.BasicCodec, + 0, + nil, + ) + return &DummyApplication{ + state: state, + lastCommitState: state, + } +} + +func (dapp *DummyApplication) Echo(message string) (types.RetCode, string) { + return 0, message +} + +func (dapp *DummyApplication) AppendTx(tx []byte) types.RetCode { + dapp.state.Set(tx, tx) + return 0 +} + +func (dapp *DummyApplication) GetHash() ([]byte, types.RetCode) { + hash := dapp.state.Hash() + return hash, 0 +} + +func (dapp *DummyApplication) Commit() types.RetCode { + dapp.lastCommitState = dapp.state.Copy() + return 0 +} + +func (dapp *DummyApplication) Rollback() types.RetCode { + dapp.state = dapp.lastCommitState.Copy() + return 0 +} + +func (dapp *DummyApplication) SetEventsMode(mode types.EventsMode) types.RetCode { + return 0 +} + +func (dapp *DummyApplication) AddListener(key string) types.RetCode { + return 0 +} + +func (dapp *DummyApplication) RemListener(key string) types.RetCode { + return 0 +} + +func (dapp *DummyApplication) GetEvents() []types.Event { + return nil +} diff --git a/example/main_test.go b/example/main_test.go new file mode 100644 index 00000000..0a5b53d6 --- /dev/null +++ b/example/main_test.go @@ -0,0 +1,52 @@ +package main + +import ( + // "fmt" + "testing" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" +) + +func TestStream(t *testing.T) { + + // Start the listener + _, err := server.StartListener("tcp://127.0.0.1:8080", NewDummyApplication()) + if err != nil { + Exit(err.Error()) + } + + // Connect to the socket + conn, err := Connect("tcp://127.0.0.1:8080") + if err != nil { + Exit(err.Error()) + } + + // Read response data + go func() { + for { + var n int64 + var err error + var res types.Response + wire.ReadBinaryPtr(&res, conn, &n, &err) + if err != nil { + Exit(err.Error()) + } + // fmt.Println("Read", n) + } + }() + + // Write requests + for { + var n int64 + var err error + var req types.Request = types.RequestAppendTx{TxBytes: []byte("test")} + wire.WriteBinary(req, conn, &n, &err) + if err != nil { + Exit(err.Error()) + } + // fmt.Println("Wrote", n) + } +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 00000000..2b22300e --- /dev/null +++ b/server/server.go @@ -0,0 +1,136 @@ +package server + +import ( + "fmt" + "net" + "reflect" + "strings" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func StartListener(protoAddr string, app types.Application) (net.Listener, error) { + parts := strings.SplitN(protoAddr, "://", 2) + proto, addr := parts[0], parts[1] + ln, err := net.Listen(proto, addr) + if err != nil { + return nil, err + } + + // A goroutine to accept a connection. + go func() { + + for { + // Accept a connection + conn, err := ln.Accept() + if err != nil { + Exit("Failed to accept connection") + } else { + fmt.Println("Accepted a new connection") + } + connClosed := make(chan struct{}, 2) // Push to signal connection closed + responses := make(chan types.Response, 1000) // A channel to buffer responses + + // Read requests from conn and deal with them + go handleRequests(app, connClosed, conn, responses) + // Pull responses from 'responses' and write them to conn. + go handleResponses(connClosed, responses, conn) + + // Wait until connection is closed + <-connClosed + fmt.Println("Connection was closed. Waiting for new connection...") + } + + }() + + return ln, nil +} + +// Read requests from conn and deal with them +func handleRequests(app types.Application, connClosed chan struct{}, conn net.Conn, responses chan<- types.Response) { + var count int + for { + var n int64 + var err error + var req types.Request + wire.ReadBinaryPtr(&req, conn, &n, &err) + + if err != nil { + fmt.Println(err.Error()) + connClosed <- struct{}{} + return + } + + count++ + if count%1000 == 0 { + fmt.Println("Received request", reflect.TypeOf(req), req, n, err, count) + } + + handleRequest(app, req, responses) + } +} + +func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) { + switch req := req.(type) { + case types.RequestEcho: + retCode, msg := app.Echo(req.Message) + responses <- types.ResponseEcho{retCode, msg} + case types.RequestAppendTx: + retCode := app.AppendTx(req.TxBytes) + responses <- types.ResponseAppendTx{retCode} + events := app.GetEvents() + for _, event := range events { + responses <- types.ResponseEvent{event} + } + case types.RequestGetHash: + hash, retCode := app.GetHash() + responses <- types.ResponseGetHash{retCode, hash} + case types.RequestCommit: + retCode := app.Commit() + responses <- types.ResponseCommit{retCode} + case types.RequestRollback: + retCode := app.Rollback() + responses <- types.ResponseRollback{retCode} + case types.RequestSetEventsMode: + retCode := app.SetEventsMode(req.EventsMode) + responses <- types.ResponseSetEventsMode{retCode} + if req.EventsMode == types.EventsModeOn { + events := app.GetEvents() + for _, event := range events { + responses <- types.ResponseEvent{event} + } + } + case types.RequestAddListener: + retCode := app.AddListener(req.EventKey) + responses <- types.ResponseAddListener{retCode} + case types.RequestRemListener: + retCode := app.RemListener(req.EventKey) + responses <- types.ResponseRemListener{retCode} + default: + responses <- types.ResponseException{"Unknown request"} + } +} + +// Pull responses from 'responses' and write them to conn. +func handleResponses(connClosed chan struct{}, responses <-chan types.Response, conn net.Conn) { + var count int + for { + var res = <-responses + var n int64 + var err error + wire.WriteBinary(res, conn, &n, &err) + + if err != nil { + fmt.Println(err.Error()) + connClosed <- struct{}{} + return + } + + count++ + if count%1000 == 0 { + fmt.Println("Sent response", reflect.TypeOf(res), res, n, err, count) + } + } +} diff --git a/types/application.go b/types/application.go new file mode 100644 index 00000000..2596f445 --- /dev/null +++ b/types/application.go @@ -0,0 +1,31 @@ +package types + +type Application interface { + + // Echo a message + Echo(message string) (RetCode, string) + + // Append a tx, which may or may not get committed + AppendTx(tx []byte) RetCode + + // Return the application Merkle root hash + GetHash() ([]byte, RetCode) + + // Set commit checkpoint + Commit() RetCode + + // Rollback to the latest commit + Rollback() RetCode + + // Set events reporting mode + SetEventsMode(mode EventsMode) RetCode + + // Add event listener + AddListener(key string) RetCode + + // Remove event listener + RemListener(key string) RetCode + + // Get all events + GetEvents() []Event +} diff --git a/types/events.go b/types/events.go new file mode 100644 index 00000000..8a7fa237 --- /dev/null +++ b/types/events.go @@ -0,0 +1,14 @@ +package types + +type EventsMode int8 + +const ( + EventsModeOff = EventsMode(0) + EventsModeCached = EventsMode(1) + EventsModeOn = EventsMode(2) +) + +type Event struct { + Key string + TxBytes []byte +} diff --git a/types/messages.go b/types/messages.go new file mode 100644 index 00000000..da4731ae --- /dev/null +++ b/types/messages.go @@ -0,0 +1,155 @@ +package types + +import "github.com/tendermint/go-wire" + +const ( + requestTypeEcho = byte(0x01) + requestTypeAppendTx = byte(0x02) + requestTypeGetHash = byte(0x03) + requestTypeCommit = byte(0x04) + requestTypeRollback = byte(0x05) + requestTypeSetEventsMode = byte(0x06) + requestTypeAddListener = byte(0x07) + requestTypeRemListener = byte(0x08) + + responseTypeEcho = byte(0x11) + responseTypeAppendTx = byte(0x12) + responseTypeGetHash = byte(0x13) + responseTypeCommit = byte(0x14) + responseTypeRollback = byte(0x15) + responseTypeSetEventsMode = byte(0x16) + responseTypeAddListener = byte(0x17) + responseTypeRemListener = byte(0x18) + + responseTypeException = byte(0x20) + responseTypeEvent = byte(0x21) +) + +//---------------------------------------- + +type RequestEcho struct { + Message string +} + +type RequestAppendTx struct { + TxBytes []byte +} + +type RequestGetHash struct { +} + +type RequestCommit struct { +} + +type RequestRollback struct { +} + +type RequestSetEventsMode struct { + EventsMode +} + +type RequestAddListener struct { + EventKey string +} + +type RequestRemListener struct { + EventKey string +} + +type Request interface { + AssertRequestType() +} + +func (_ RequestEcho) AssertRequestType() {} +func (_ RequestAppendTx) AssertRequestType() {} +func (_ RequestGetHash) AssertRequestType() {} +func (_ RequestCommit) AssertRequestType() {} +func (_ RequestRollback) AssertRequestType() {} +func (_ RequestSetEventsMode) AssertRequestType() {} +func (_ RequestAddListener) AssertRequestType() {} +func (_ RequestRemListener) AssertRequestType() {} + +var _ = wire.RegisterInterface( + struct{ Request }{}, + wire.ConcreteType{RequestEcho{}, requestTypeEcho}, + wire.ConcreteType{RequestAppendTx{}, requestTypeAppendTx}, + wire.ConcreteType{RequestGetHash{}, requestTypeGetHash}, + wire.ConcreteType{RequestCommit{}, requestTypeCommit}, + wire.ConcreteType{RequestRollback{}, requestTypeRollback}, + wire.ConcreteType{RequestSetEventsMode{}, requestTypeSetEventsMode}, + wire.ConcreteType{RequestAddListener{}, requestTypeAddListener}, + wire.ConcreteType{RequestRemListener{}, requestTypeRemListener}, +) + +//---------------------------------------- + +type ResponseEcho struct { + RetCode + Message string +} + +type ResponseAppendTx struct { + RetCode +} + +type ResponseGetHash struct { + RetCode + Hash []byte +} + +type ResponseCommit struct { + RetCode +} + +type ResponseRollback struct { + RetCode +} + +type ResponseSetEventsMode struct { + RetCode +} + +type ResponseAddListener struct { + RetCode +} + +type ResponseRemListener struct { + RetCode +} + +type ResponseException struct { + Error string +} + +type ResponseEvent struct { + Event +} + +type Response interface { + AssertResponseType() +} + +func (_ ResponseEcho) AssertResponseType() {} +func (_ ResponseAppendTx) AssertResponseType() {} +func (_ ResponseGetHash) AssertResponseType() {} +func (_ ResponseCommit) AssertResponseType() {} +func (_ ResponseRollback) AssertResponseType() {} +func (_ ResponseSetEventsMode) AssertResponseType() {} +func (_ ResponseAddListener) AssertResponseType() {} +func (_ ResponseRemListener) AssertResponseType() {} +func (_ ResponseException) AssertResponseType() {} +func (_ ResponseEvent) AssertResponseType() {} + +var _ = wire.RegisterInterface( + struct{ Response }{}, + wire.ConcreteType{ResponseEcho{}, responseTypeEcho}, + wire.ConcreteType{ResponseAppendTx{}, responseTypeAppendTx}, + wire.ConcreteType{ResponseGetHash{}, responseTypeGetHash}, + wire.ConcreteType{ResponseCommit{}, responseTypeCommit}, + wire.ConcreteType{ResponseRollback{}, responseTypeRollback}, + wire.ConcreteType{ResponseSetEventsMode{}, responseTypeSetEventsMode}, + wire.ConcreteType{ResponseAddListener{}, responseTypeAddListener}, + wire.ConcreteType{ResponseRemListener{}, responseTypeRemListener}, + wire.ConcreteType{ResponseException{}, responseTypeException}, + wire.ConcreteType{ResponseEvent{}, responseTypeEvent}, +) diff --git a/types/retcode.go b/types/retcode.go new file mode 100644 index 00000000..bccd9a4c --- /dev/null +++ b/types/retcode.go @@ -0,0 +1,12 @@ +package types + +type RetCode int + +// Reserved return codes +const ( + RetCodeOK = RetCode(0) + RetCodeInternalError = RetCode(1) + RetCodeUnauthorized = RetCode(2) + RetCodeInsufficientFees = RetCode(3) + RetCodeUnknownRequest = RetCode(4) +) From ef93c958532d7a827033a491ee55e711f00f4ecb Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 8 Nov 2015 15:18:58 -0800 Subject: [PATCH 002/545] Added new Flush request/response type --- server/server.go | 19 ++++++++++++++++--- types/messages.go | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/server/server.go b/server/server.go index 2b22300e..161e5e0b 100644 --- a/server/server.go +++ b/server/server.go @@ -1,6 +1,7 @@ package server import ( + "bufio" "fmt" "net" "reflect" @@ -51,11 +52,12 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error // Read requests from conn and deal with them func handleRequests(app types.Application, connClosed chan struct{}, conn net.Conn, responses chan<- types.Response) { var count int + var bufReader = bufio.NewReader(conn) for { var n int64 var err error var req types.Request - wire.ReadBinaryPtr(&req, conn, &n, &err) + wire.ReadBinaryPtr(&req, bufReader, &n, &err) if err != nil { fmt.Println(err.Error()) @@ -77,6 +79,8 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty case types.RequestEcho: retCode, msg := app.Echo(req.Message) responses <- types.ResponseEcho{retCode, msg} + case types.RequestFlush: + responses <- types.ResponseFlush{} case types.RequestAppendTx: retCode := app.AppendTx(req.TxBytes) responses <- types.ResponseAppendTx{retCode} @@ -116,18 +120,27 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty // Pull responses from 'responses' and write them to conn. func handleResponses(connClosed chan struct{}, responses <-chan types.Response, conn net.Conn) { var count int + var bufWriter = bufio.NewWriter(conn) for { var res = <-responses var n int64 var err error - wire.WriteBinary(res, conn, &n, &err) - + wire.WriteBinary(res, bufWriter, &n, &err) if err != nil { fmt.Println(err.Error()) connClosed <- struct{}{} return } + if _, ok := res.(types.ResponseFlush); ok { + err = bufWriter.Flush() + if err != nil { + fmt.Println(err.Error()) + connClosed <- struct{}{} + return + } + } + count++ if count%1000 == 0 { fmt.Println("Sent response", reflect.TypeOf(res), res, n, err, count) diff --git a/types/messages.go b/types/messages.go index da4731ae..70470a2d 100644 --- a/types/messages.go +++ b/types/messages.go @@ -4,22 +4,24 @@ import "github.com/tendermint/go-wire" const ( requestTypeEcho = byte(0x01) - requestTypeAppendTx = byte(0x02) - requestTypeGetHash = byte(0x03) - requestTypeCommit = byte(0x04) - requestTypeRollback = byte(0x05) - requestTypeSetEventsMode = byte(0x06) - requestTypeAddListener = byte(0x07) - requestTypeRemListener = byte(0x08) + requestTypeFlush = byte(0x02) + requestTypeAppendTx = byte(0x03) + requestTypeGetHash = byte(0x04) + requestTypeCommit = byte(0x05) + requestTypeRollback = byte(0x06) + requestTypeSetEventsMode = byte(0x07) + requestTypeAddListener = byte(0x08) + requestTypeRemListener = byte(0x09) responseTypeEcho = byte(0x11) - responseTypeAppendTx = byte(0x12) - responseTypeGetHash = byte(0x13) - responseTypeCommit = byte(0x14) - responseTypeRollback = byte(0x15) - responseTypeSetEventsMode = byte(0x16) - responseTypeAddListener = byte(0x17) - responseTypeRemListener = byte(0x18) + responseTypeFlush = byte(0x12) + responseTypeAppendTx = byte(0x13) + responseTypeGetHash = byte(0x14) + responseTypeCommit = byte(0x15) + responseTypeRollback = byte(0x16) + responseTypeSetEventsMode = byte(0x17) + responseTypeAddListener = byte(0x18) + responseTypeRemListener = byte(0x19) responseTypeException = byte(0x20) responseTypeEvent = byte(0x21) @@ -31,6 +33,9 @@ type RequestEcho struct { Message string } +type RequestFlush struct { +} + type RequestAppendTx struct { TxBytes []byte } @@ -61,6 +66,7 @@ type Request interface { } func (_ RequestEcho) AssertRequestType() {} +func (_ RequestFlush) AssertRequestType() {} func (_ RequestAppendTx) AssertRequestType() {} func (_ RequestGetHash) AssertRequestType() {} func (_ RequestCommit) AssertRequestType() {} @@ -72,6 +78,7 @@ func (_ RequestRemListener) AssertRequestType() {} var _ = wire.RegisterInterface( struct{ Request }{}, wire.ConcreteType{RequestEcho{}, requestTypeEcho}, + wire.ConcreteType{RequestFlush{}, requestTypeFlush}, wire.ConcreteType{RequestAppendTx{}, requestTypeAppendTx}, wire.ConcreteType{RequestGetHash{}, requestTypeGetHash}, wire.ConcreteType{RequestCommit{}, requestTypeCommit}, @@ -88,6 +95,9 @@ type ResponseEcho struct { Message string } +type ResponseFlush struct { +} + type ResponseAppendTx struct { RetCode } @@ -130,6 +140,7 @@ type Response interface { } func (_ ResponseEcho) AssertResponseType() {} +func (_ ResponseFlush) AssertResponseType() {} func (_ ResponseAppendTx) AssertResponseType() {} func (_ ResponseGetHash) AssertResponseType() {} func (_ ResponseCommit) AssertResponseType() {} @@ -143,6 +154,7 @@ func (_ ResponseEvent) AssertResponseType() {} var _ = wire.RegisterInterface( struct{ Response }{}, wire.ConcreteType{ResponseEcho{}, responseTypeEcho}, + wire.ConcreteType{ResponseFlush{}, responseTypeFlush}, wire.ConcreteType{ResponseAppendTx{}, responseTypeAppendTx}, wire.ConcreteType{ResponseGetHash{}, responseTypeGetHash}, wire.ConcreteType{ResponseCommit{}, responseTypeCommit}, From cce812b1fa560bea87ea652712ce65cfae3e4b88 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 9 Nov 2015 16:29:45 -0800 Subject: [PATCH 003/545] Remove retcode from echo; Add Info message --- example/main.go | 8 +++++-- server/server.go | 16 ++----------- types/application.go | 5 +++- types/messages.go | 56 +++++++++++++++++++++++++++----------------- 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/example/main.go b/example/main.go index bf6f06d9..efd4761e 100644 --- a/example/main.go +++ b/example/main.go @@ -43,8 +43,12 @@ func NewDummyApplication() *DummyApplication { } } -func (dapp *DummyApplication) Echo(message string) (types.RetCode, string) { - return 0, message +func (dapp *DummyApplication) Echo(message string) string { + return message +} + +func (dapp *DummyApplication) Info() []string { + return []string{Fmt("size:%v", dapp.state.Size())} } func (dapp *DummyApplication) AppendTx(tx []byte) types.RetCode { diff --git a/server/server.go b/server/server.go index 161e5e0b..cd1953b0 100644 --- a/server/server.go +++ b/server/server.go @@ -4,7 +4,6 @@ import ( "bufio" "fmt" "net" - "reflect" "strings" . "github.com/tendermint/go-common" @@ -58,18 +57,12 @@ func handleRequests(app types.Application, connClosed chan struct{}, conn net.Co var err error var req types.Request wire.ReadBinaryPtr(&req, bufReader, &n, &err) - if err != nil { fmt.Println(err.Error()) connClosed <- struct{}{} return } - count++ - if count%1000 == 0 { - fmt.Println("Received request", reflect.TypeOf(req), req, n, err, count) - } - handleRequest(app, req, responses) } } @@ -77,8 +70,8 @@ func handleRequests(app types.Application, connClosed chan struct{}, conn net.Co func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) { switch req := req.(type) { case types.RequestEcho: - retCode, msg := app.Echo(req.Message) - responses <- types.ResponseEcho{retCode, msg} + msg := app.Echo(req.Message) + responses <- types.ResponseEcho{msg} case types.RequestFlush: responses <- types.ResponseFlush{} case types.RequestAppendTx: @@ -131,7 +124,6 @@ func handleResponses(connClosed chan struct{}, responses <-chan types.Response, connClosed <- struct{}{} return } - if _, ok := res.(types.ResponseFlush); ok { err = bufWriter.Flush() if err != nil { @@ -140,10 +132,6 @@ func handleResponses(connClosed chan struct{}, responses <-chan types.Response, return } } - count++ - if count%1000 == 0 { - fmt.Println("Sent response", reflect.TypeOf(res), res, n, err, count) - } } } diff --git a/types/application.go b/types/application.go index 2596f445..ce9a6670 100644 --- a/types/application.go +++ b/types/application.go @@ -3,7 +3,10 @@ package types type Application interface { // Echo a message - Echo(message string) (RetCode, string) + Echo(message string) string + + // Return application info + Info() []string // Append a tx, which may or may not get committed AppendTx(tx []byte) RetCode diff --git a/types/messages.go b/types/messages.go index 70470a2d..5ef3944f 100644 --- a/types/messages.go +++ b/types/messages.go @@ -3,28 +3,32 @@ package types import "github.com/tendermint/go-wire" const ( - requestTypeEcho = byte(0x01) - requestTypeFlush = byte(0x02) - requestTypeAppendTx = byte(0x03) - requestTypeGetHash = byte(0x04) - requestTypeCommit = byte(0x05) - requestTypeRollback = byte(0x06) - requestTypeSetEventsMode = byte(0x07) - requestTypeAddListener = byte(0x08) - requestTypeRemListener = byte(0x09) + requestTypeEcho = byte(0x01) + requestTypeFlush = byte(0x02) + requestTypeInfo = byte(0x03) - responseTypeEcho = byte(0x11) - responseTypeFlush = byte(0x12) - responseTypeAppendTx = byte(0x13) - responseTypeGetHash = byte(0x14) - responseTypeCommit = byte(0x15) - responseTypeRollback = byte(0x16) - responseTypeSetEventsMode = byte(0x17) - responseTypeAddListener = byte(0x18) - responseTypeRemListener = byte(0x19) + responseTypeException = byte(0x10) + responseTypeEcho = byte(0x11) + responseTypeFlush = byte(0x12) + responseTypeInfo = byte(0x13) - responseTypeException = byte(0x20) - responseTypeEvent = byte(0x21) + requestTypeAppendTx = byte(0x21) + requestTypeGetHash = byte(0x22) + requestTypeCommit = byte(0x23) + requestTypeRollback = byte(0x24) + requestTypeSetEventsMode = byte(0x25) + requestTypeAddListener = byte(0x26) + requestTypeRemListener = byte(0x27) + // reserved for responseTypeEvent 0x28 + + responseTypeAppendTx = byte(0x31) + responseTypeGetHash = byte(0x32) + responseTypeCommit = byte(0x33) + responseTypeRollback = byte(0x34) + responseTypeSetEventsMode = byte(0x35) + responseTypeAddListener = byte(0x36) + responseTypeRemListener = byte(0x37) + responseTypeEvent = byte(0x38) ) //---------------------------------------- @@ -36,6 +40,9 @@ type RequestEcho struct { type RequestFlush struct { } +type RequestInfo struct { +} + type RequestAppendTx struct { TxBytes []byte } @@ -67,6 +74,7 @@ type Request interface { func (_ RequestEcho) AssertRequestType() {} func (_ RequestFlush) AssertRequestType() {} +func (_ RequestInfo) AssertRequestType() {} func (_ RequestAppendTx) AssertRequestType() {} func (_ RequestGetHash) AssertRequestType() {} func (_ RequestCommit) AssertRequestType() {} @@ -79,6 +87,7 @@ var _ = wire.RegisterInterface( struct{ Request }{}, wire.ConcreteType{RequestEcho{}, requestTypeEcho}, wire.ConcreteType{RequestFlush{}, requestTypeFlush}, + wire.ConcreteType{RequestInfo{}, requestTypeInfo}, wire.ConcreteType{RequestAppendTx{}, requestTypeAppendTx}, wire.ConcreteType{RequestGetHash{}, requestTypeGetHash}, wire.ConcreteType{RequestCommit{}, requestTypeCommit}, @@ -91,13 +100,16 @@ var _ = wire.RegisterInterface( //---------------------------------------- type ResponseEcho struct { - RetCode Message string } type ResponseFlush struct { } +type ResponseInfo struct { + Data []string +} + type ResponseAppendTx struct { RetCode } @@ -141,6 +153,7 @@ type Response interface { func (_ ResponseEcho) AssertResponseType() {} func (_ ResponseFlush) AssertResponseType() {} +func (_ ResponseInfo) AssertResponseType() {} func (_ ResponseAppendTx) AssertResponseType() {} func (_ ResponseGetHash) AssertResponseType() {} func (_ ResponseCommit) AssertResponseType() {} @@ -155,6 +168,7 @@ var _ = wire.RegisterInterface( struct{ Response }{}, wire.ConcreteType{ResponseEcho{}, responseTypeEcho}, wire.ConcreteType{ResponseFlush{}, responseTypeFlush}, + wire.ConcreteType{ResponseInfo{}, responseTypeInfo}, wire.ConcreteType{ResponseAppendTx{}, responseTypeAppendTx}, wire.ConcreteType{ResponseGetHash{}, responseTypeGetHash}, wire.ConcreteType{ResponseCommit{}, responseTypeCommit}, From 5aec38bdc6082a428da7a7a5e05d40946c65caa4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 9 Nov 2015 18:16:35 -0800 Subject: [PATCH 004/545] Fix DummyyApplication usage bug; Should call New --- example/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/main.go b/example/main.go index efd4761e..a86535d4 100644 --- a/example/main.go +++ b/example/main.go @@ -11,7 +11,7 @@ import ( func main() { // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:8080", &DummyApplication{}) + _, err := server.StartListener("tcp://127.0.0.1:8080", NewDummyApplication()) if err != nil { Exit(err.Error()) } From e8505a714b6b9753e751786e7ed7e4bc68457330 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 9 Nov 2015 18:17:00 -0800 Subject: [PATCH 005/545] Handle RequestInfo in handleRequest --- server/server.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/server.go b/server/server.go index cd1953b0..38f25c91 100644 --- a/server/server.go +++ b/server/server.go @@ -58,7 +58,7 @@ func handleRequests(app types.Application, connClosed chan struct{}, conn net.Co var req types.Request wire.ReadBinaryPtr(&req, bufReader, &n, &err) if err != nil { - fmt.Println(err.Error()) + fmt.Println("Error in handleRequests:", err.Error()) connClosed <- struct{}{} return } @@ -74,6 +74,9 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty responses <- types.ResponseEcho{msg} case types.RequestFlush: responses <- types.ResponseFlush{} + case types.RequestInfo: + data := app.Info() + responses <- types.ResponseInfo{data} case types.RequestAppendTx: retCode := app.AppendTx(req.TxBytes) responses <- types.ResponseAppendTx{retCode} From d319c5be0da1b9bc3de57ba2efedb6a2ce05b2b4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 10 Nov 2015 12:49:07 -0800 Subject: [PATCH 006/545] Conform to go-wire 1.0 --- cmd/cli.go | 4 ++-- example/main_test.go | 6 +++--- server/server.go | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/cli.go b/cmd/cli.go index 2885b991..6ff3109a 100644 --- a/cmd/cli.go +++ b/cmd/cli.go @@ -115,13 +115,13 @@ func cmdRollback(c *cli.Context) { //-------------------------------------------------------------------------------- func write(conn net.Conn, req types.Request) (types.Response, error) { - var n int64 + var n int var err error wire.WriteBinary(req, conn, &n, &err) if err != nil { return nil, err } var res types.Response - wire.ReadBinaryPtr(&res, conn, &n, &err) + wire.ReadBinaryPtr(&res, conn, 0, &n, &err) return res, err } diff --git a/example/main_test.go b/example/main_test.go index 0a5b53d6..a5475240 100644 --- a/example/main_test.go +++ b/example/main_test.go @@ -27,10 +27,10 @@ func TestStream(t *testing.T) { // Read response data go func() { for { - var n int64 + var n int var err error var res types.Response - wire.ReadBinaryPtr(&res, conn, &n, &err) + wire.ReadBinaryPtr(&res, conn, 0, &n, &err) if err != nil { Exit(err.Error()) } @@ -40,7 +40,7 @@ func TestStream(t *testing.T) { // Write requests for { - var n int64 + var n int var err error var req types.Request = types.RequestAppendTx{TxBytes: []byte("test")} wire.WriteBinary(req, conn, &n, &err) diff --git a/server/server.go b/server/server.go index 38f25c91..73c27d0e 100644 --- a/server/server.go +++ b/server/server.go @@ -53,10 +53,10 @@ func handleRequests(app types.Application, connClosed chan struct{}, conn net.Co var count int var bufReader = bufio.NewReader(conn) for { - var n int64 + var n int var err error var req types.Request - wire.ReadBinaryPtr(&req, bufReader, &n, &err) + wire.ReadBinaryPtr(&req, bufReader, 0, &n, &err) if err != nil { fmt.Println("Error in handleRequests:", err.Error()) connClosed <- struct{}{} @@ -119,7 +119,7 @@ func handleResponses(connClosed chan struct{}, responses <-chan types.Response, var bufWriter = bufio.NewWriter(conn) for { var res = <-responses - var n int64 + var n int var err error wire.WriteBinary(res, bufWriter, &n, &err) if err != nil { From 201bf2374bba6f381040ce3b7059f32a9f1a1d9f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 16 Nov 2015 15:50:26 -0800 Subject: [PATCH 007/545] Update README; Remove GetEvents() from Application --- README.md | 13 +++++++++++-- example/main.go | 8 ++------ server/server.go | 9 +-------- types/application.go | 5 +---- types/events.go | 9 ++++----- 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 2e5b5652..b1790e03 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,7 @@ TMSP is an asynchronous streaming protocol: message responses are written back a * __Arguments__: * `EventsMode (int8)`: * `EventsModeOff (0)`: Events are not reported. Used for mempool. - * `EventsModeCached (1)`: Events are cached. - * `EventsModeOn (2)`: Flush cache and report events. + * `EventsModeOn (1)`: Report events that are listened on. * __Returns__: * `RetCode (int8)` * __Usage__:
@@ -61,3 +60,13 @@ TMSP is an asynchronous streaming protocol: message responses are written back a * __Usage__:
Remove event listener callback for events with given key. +#### Flush + * __Usage__:
+ Flush the response queue. Applications that implement `types.Application` need not implement this message -- it's handled by the project. + +#### Info + * __Returns__: + * `Data ([]string)` + * __Usage__:
+ Return an array of strings about the application state. Application specific. + diff --git a/example/main.go b/example/main.go index a86535d4..dabb486e 100644 --- a/example/main.go +++ b/example/main.go @@ -51,9 +51,9 @@ func (dapp *DummyApplication) Info() []string { return []string{Fmt("size:%v", dapp.state.Size())} } -func (dapp *DummyApplication) AppendTx(tx []byte) types.RetCode { +func (dapp *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { dapp.state.Set(tx, tx) - return 0 + return nil, 0 } func (dapp *DummyApplication) GetHash() ([]byte, types.RetCode) { @@ -82,7 +82,3 @@ func (dapp *DummyApplication) AddListener(key string) types.RetCode { func (dapp *DummyApplication) RemListener(key string) types.RetCode { return 0 } - -func (dapp *DummyApplication) GetEvents() []types.Event { - return nil -} diff --git a/server/server.go b/server/server.go index 73c27d0e..27faa1d3 100644 --- a/server/server.go +++ b/server/server.go @@ -78,9 +78,8 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty data := app.Info() responses <- types.ResponseInfo{data} case types.RequestAppendTx: - retCode := app.AppendTx(req.TxBytes) + events, retCode := app.AppendTx(req.TxBytes) responses <- types.ResponseAppendTx{retCode} - events := app.GetEvents() for _, event := range events { responses <- types.ResponseEvent{event} } @@ -96,12 +95,6 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty case types.RequestSetEventsMode: retCode := app.SetEventsMode(req.EventsMode) responses <- types.ResponseSetEventsMode{retCode} - if req.EventsMode == types.EventsModeOn { - events := app.GetEvents() - for _, event := range events { - responses <- types.ResponseEvent{event} - } - } case types.RequestAddListener: retCode := app.AddListener(req.EventKey) responses <- types.ResponseAddListener{retCode} diff --git a/types/application.go b/types/application.go index ce9a6670..2b4e942f 100644 --- a/types/application.go +++ b/types/application.go @@ -9,7 +9,7 @@ type Application interface { Info() []string // Append a tx, which may or may not get committed - AppendTx(tx []byte) RetCode + AppendTx(tx []byte) ([]Event, RetCode) // Return the application Merkle root hash GetHash() ([]byte, RetCode) @@ -28,7 +28,4 @@ type Application interface { // Remove event listener RemListener(key string) RetCode - - // Get all events - GetEvents() []Event } diff --git a/types/events.go b/types/events.go index 8a7fa237..37f51a44 100644 --- a/types/events.go +++ b/types/events.go @@ -3,12 +3,11 @@ package types type EventsMode int8 const ( - EventsModeOff = EventsMode(0) - EventsModeCached = EventsMode(1) - EventsModeOn = EventsMode(2) + EventsModeOff = EventsMode(0) + EventsModeOn = EventsMode(1) ) type Event struct { - Key string - TxBytes []byte + Key string + Data []byte } From 4d0eb1d95aafbc4cfce95945d416910f0dd99240 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Nov 2015 11:07:16 -0500 Subject: [PATCH 008/545] retcode.Error() from go generate --- types/retcode.go | 29 ++++++++++++++++++++++++----- types/retcode_string.go | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 types/retcode_string.go diff --git a/types/retcode.go b/types/retcode.go index bccd9a4c..640f6236 100644 --- a/types/retcode.go +++ b/types/retcode.go @@ -1,12 +1,31 @@ package types +import ( + "errors" +) + type RetCode int // Reserved return codes const ( - RetCodeOK = RetCode(0) - RetCodeInternalError = RetCode(1) - RetCodeUnauthorized = RetCode(2) - RetCodeInsufficientFees = RetCode(3) - RetCodeUnknownRequest = RetCode(4) + RetCodeOK RetCode = 0 + RetCodeInternalError RetCode = 1 + RetCodeUnauthorized RetCode = 2 + RetCodeInsufficientFees RetCode = 3 + RetCodeUnknownRequest RetCode = 4 ) + +func (r RetCode) Error() error { + switch r { + case RetCodeOK: + return nil + default: + return errors.New(r.String()) + } +} + +//go:generate stringer -type=RetCode + +// NOTE: The previous comment generates r.String(). +// To run it, `go get golang.org/x/tools/cmd/stringer` +// and `go generate` in tmsp/types diff --git a/types/retcode_string.go b/types/retcode_string.go new file mode 100644 index 00000000..17ea7766 --- /dev/null +++ b/types/retcode_string.go @@ -0,0 +1,16 @@ +// generated by stringer -type=RetCode; DO NOT EDIT + +package types + +import "fmt" + +const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequest" + +var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92} + +func (i RetCode) String() string { + if i < 0 || i+1 >= RetCode(len(_RetCode_index)) { + return fmt.Sprintf("RetCode(%d)", i) + } + return _RetCode_name[_RetCode_index[i]:_RetCode_index[i+1]] +} From 32937f28159e3495f6c73d104a4caa8d1af3c131 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 27 Nov 2015 08:51:49 -0800 Subject: [PATCH 009/545] Add Apache2.0 license --- LICENSE.md | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 9a72da4fcd5a3cd120137b1b62d36eb00cad3a07 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 27 Nov 2015 09:57:08 -0800 Subject: [PATCH 010/545] Add .gitignore file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..38193138 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.swp +*.swo From e40c4834a8ac6caa438a14f413d412b72222e942 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 27 Nov 2015 10:14:46 -0800 Subject: [PATCH 011/545] Replace SetEventsMode with SetOption --- README.md | 20 ++++----- example/main.go | 8 ++-- server/server.go | 6 +-- types/application.go | 6 +-- types/events.go | 7 --- types/messages.go | 105 ++++++++++++++++++++++--------------------- 6 files changed, 74 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index b1790e03..5000b819 100644 --- a/README.md +++ b/README.md @@ -34,16 +34,6 @@ TMSP is an asynchronous streaming protocol: message responses are written back a * __Usage__:
Roll back to the last commit -#### SetEventsMode - * __Arguments__: - * `EventsMode (int8)`: - * `EventsModeOff (0)`: Events are not reported. Used for mempool. - * `EventsModeOn (1)`: Report events that are listened on. - * __Returns__: - * `RetCode (int8)` - * __Usage__:
- Set event reporting mode for future transactions - #### AddListener * __Arguments__: * `EventKey (string)` @@ -70,3 +60,13 @@ TMSP is an asynchronous streaming protocol: message responses are written back a * __Usage__:
Return an array of strings about the application state. Application specific. +#### SetOption + * __Arguments__: + * `Key (string)` + * `Value (string)` + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. + Other options are application specific. + diff --git a/example/main.go b/example/main.go index dabb486e..828ccb1a 100644 --- a/example/main.go +++ b/example/main.go @@ -51,6 +51,10 @@ func (dapp *DummyApplication) Info() []string { return []string{Fmt("size:%v", dapp.state.Size())} } +func (dapp *DummyApplication) SetOption(key string, value string) types.RetCode { + return 0 +} + func (dapp *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { dapp.state.Set(tx, tx) return nil, 0 @@ -71,10 +75,6 @@ func (dapp *DummyApplication) Rollback() types.RetCode { return 0 } -func (dapp *DummyApplication) SetEventsMode(mode types.EventsMode) types.RetCode { - return 0 -} - func (dapp *DummyApplication) AddListener(key string) types.RetCode { return 0 } diff --git a/server/server.go b/server/server.go index 27faa1d3..f7e18738 100644 --- a/server/server.go +++ b/server/server.go @@ -77,6 +77,9 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty case types.RequestInfo: data := app.Info() responses <- types.ResponseInfo{data} + case types.RequestSetOption: + retCode := app.SetOption(req.Key, req.Value) + responses <- types.ResponseSetOption{retCode} case types.RequestAppendTx: events, retCode := app.AppendTx(req.TxBytes) responses <- types.ResponseAppendTx{retCode} @@ -92,9 +95,6 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty case types.RequestRollback: retCode := app.Rollback() responses <- types.ResponseRollback{retCode} - case types.RequestSetEventsMode: - retCode := app.SetEventsMode(req.EventsMode) - responses <- types.ResponseSetEventsMode{retCode} case types.RequestAddListener: retCode := app.AddListener(req.EventKey) responses <- types.ResponseAddListener{retCode} diff --git a/types/application.go b/types/application.go index 2b4e942f..d3a46cb7 100644 --- a/types/application.go +++ b/types/application.go @@ -8,6 +8,9 @@ type Application interface { // Return application info Info() []string + // Set application option (e.g. mode=mempool, mode=consensus) + SetOption(key string, value string) RetCode + // Append a tx, which may or may not get committed AppendTx(tx []byte) ([]Event, RetCode) @@ -20,9 +23,6 @@ type Application interface { // Rollback to the latest commit Rollback() RetCode - // Set events reporting mode - SetEventsMode(mode EventsMode) RetCode - // Add event listener AddListener(key string) RetCode diff --git a/types/events.go b/types/events.go index 37f51a44..d1ba5f1f 100644 --- a/types/events.go +++ b/types/events.go @@ -1,12 +1,5 @@ package types -type EventsMode int8 - -const ( - EventsModeOff = EventsMode(0) - EventsModeOn = EventsMode(1) -) - type Event struct { Key string Data []byte diff --git a/types/messages.go b/types/messages.go index 5ef3944f..634c89b3 100644 --- a/types/messages.go +++ b/types/messages.go @@ -3,32 +3,34 @@ package types import "github.com/tendermint/go-wire" const ( - requestTypeEcho = byte(0x01) - requestTypeFlush = byte(0x02) - requestTypeInfo = byte(0x03) + requestTypeEcho = byte(0x01) + requestTypeFlush = byte(0x02) + requestTypeInfo = byte(0x03) + requestTypeSetOption = byte(0x04) + // reserved for GetOption = byte(0x05) responseTypeException = byte(0x10) responseTypeEcho = byte(0x11) responseTypeFlush = byte(0x12) responseTypeInfo = byte(0x13) + responseTypeSetOption = byte(0x14) + // reserved for GetOption = byte(0x15) - requestTypeAppendTx = byte(0x21) - requestTypeGetHash = byte(0x22) - requestTypeCommit = byte(0x23) - requestTypeRollback = byte(0x24) - requestTypeSetEventsMode = byte(0x25) - requestTypeAddListener = byte(0x26) - requestTypeRemListener = byte(0x27) - // reserved for responseTypeEvent 0x28 + requestTypeAppendTx = byte(0x21) + requestTypeGetHash = byte(0x22) + requestTypeCommit = byte(0x23) + requestTypeRollback = byte(0x24) + requestTypeAddListener = byte(0x25) + requestTypeRemListener = byte(0x26) + // reserved for responseTypeEvent 0x27 - responseTypeAppendTx = byte(0x31) - responseTypeGetHash = byte(0x32) - responseTypeCommit = byte(0x33) - responseTypeRollback = byte(0x34) - responseTypeSetEventsMode = byte(0x35) - responseTypeAddListener = byte(0x36) - responseTypeRemListener = byte(0x37) - responseTypeEvent = byte(0x38) + responseTypeAppendTx = byte(0x31) + responseTypeGetHash = byte(0x32) + responseTypeCommit = byte(0x33) + responseTypeRollback = byte(0x34) + responseTypeAddListener = byte(0x35) + responseTypeRemListener = byte(0x36) + responseTypeEvent = byte(0x37) ) //---------------------------------------- @@ -43,6 +45,11 @@ type RequestFlush struct { type RequestInfo struct { } +type RequestSetOption struct { + Key string + Value string +} + type RequestAppendTx struct { TxBytes []byte } @@ -56,10 +63,6 @@ type RequestCommit struct { type RequestRollback struct { } -type RequestSetEventsMode struct { - EventsMode -} - type RequestAddListener struct { EventKey string } @@ -72,27 +75,27 @@ type Request interface { AssertRequestType() } -func (_ RequestEcho) AssertRequestType() {} -func (_ RequestFlush) AssertRequestType() {} -func (_ RequestInfo) AssertRequestType() {} -func (_ RequestAppendTx) AssertRequestType() {} -func (_ RequestGetHash) AssertRequestType() {} -func (_ RequestCommit) AssertRequestType() {} -func (_ RequestRollback) AssertRequestType() {} -func (_ RequestSetEventsMode) AssertRequestType() {} -func (_ RequestAddListener) AssertRequestType() {} -func (_ RequestRemListener) AssertRequestType() {} +func (_ RequestEcho) AssertRequestType() {} +func (_ RequestFlush) AssertRequestType() {} +func (_ RequestInfo) AssertRequestType() {} +func (_ RequestSetOption) AssertRequestType() {} +func (_ RequestAppendTx) AssertRequestType() {} +func (_ RequestGetHash) AssertRequestType() {} +func (_ RequestCommit) AssertRequestType() {} +func (_ RequestRollback) AssertRequestType() {} +func (_ RequestAddListener) AssertRequestType() {} +func (_ RequestRemListener) AssertRequestType() {} var _ = wire.RegisterInterface( struct{ Request }{}, wire.ConcreteType{RequestEcho{}, requestTypeEcho}, wire.ConcreteType{RequestFlush{}, requestTypeFlush}, wire.ConcreteType{RequestInfo{}, requestTypeInfo}, + wire.ConcreteType{RequestSetOption{}, requestTypeSetOption}, wire.ConcreteType{RequestAppendTx{}, requestTypeAppendTx}, wire.ConcreteType{RequestGetHash{}, requestTypeGetHash}, wire.ConcreteType{RequestCommit{}, requestTypeCommit}, wire.ConcreteType{RequestRollback{}, requestTypeRollback}, - wire.ConcreteType{RequestSetEventsMode{}, requestTypeSetEventsMode}, wire.ConcreteType{RequestAddListener{}, requestTypeAddListener}, wire.ConcreteType{RequestRemListener{}, requestTypeRemListener}, ) @@ -110,6 +113,10 @@ type ResponseInfo struct { Data []string } +type ResponseSetOption struct { + RetCode +} + type ResponseAppendTx struct { RetCode } @@ -127,10 +134,6 @@ type ResponseRollback struct { RetCode } -type ResponseSetEventsMode struct { - RetCode -} - type ResponseAddListener struct { RetCode } @@ -151,29 +154,29 @@ type Response interface { AssertResponseType() } -func (_ ResponseEcho) AssertResponseType() {} -func (_ ResponseFlush) AssertResponseType() {} -func (_ ResponseInfo) AssertResponseType() {} -func (_ ResponseAppendTx) AssertResponseType() {} -func (_ ResponseGetHash) AssertResponseType() {} -func (_ ResponseCommit) AssertResponseType() {} -func (_ ResponseRollback) AssertResponseType() {} -func (_ ResponseSetEventsMode) AssertResponseType() {} -func (_ ResponseAddListener) AssertResponseType() {} -func (_ ResponseRemListener) AssertResponseType() {} -func (_ ResponseException) AssertResponseType() {} -func (_ ResponseEvent) AssertResponseType() {} +func (_ ResponseEcho) AssertResponseType() {} +func (_ ResponseFlush) AssertResponseType() {} +func (_ ResponseInfo) AssertResponseType() {} +func (_ ResponseSetOption) AssertResponseType() {} +func (_ ResponseAppendTx) AssertResponseType() {} +func (_ ResponseGetHash) AssertResponseType() {} +func (_ ResponseCommit) AssertResponseType() {} +func (_ ResponseRollback) AssertResponseType() {} +func (_ ResponseAddListener) AssertResponseType() {} +func (_ ResponseRemListener) AssertResponseType() {} +func (_ ResponseException) AssertResponseType() {} +func (_ ResponseEvent) AssertResponseType() {} var _ = wire.RegisterInterface( struct{ Response }{}, wire.ConcreteType{ResponseEcho{}, responseTypeEcho}, wire.ConcreteType{ResponseFlush{}, responseTypeFlush}, wire.ConcreteType{ResponseInfo{}, responseTypeInfo}, + wire.ConcreteType{ResponseSetOption{}, responseTypeSetOption}, wire.ConcreteType{ResponseAppendTx{}, responseTypeAppendTx}, wire.ConcreteType{ResponseGetHash{}, responseTypeGetHash}, wire.ConcreteType{ResponseCommit{}, responseTypeCommit}, wire.ConcreteType{ResponseRollback{}, responseTypeRollback}, - wire.ConcreteType{ResponseSetEventsMode{}, responseTypeSetEventsMode}, wire.ConcreteType{ResponseAddListener{}, responseTypeAddListener}, wire.ConcreteType{ResponseRemListener{}, responseTypeRemListener}, wire.ConcreteType{ResponseException{}, responseTypeException}, From 2de72d26cfcdced09e22fa7df925c671fb5c046a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Nov 2015 18:42:00 -0500 Subject: [PATCH 012/545] refactor dummy; flush tmsp reqs --- cmd/dummy/main.go | 22 ++++++++++++++++++++++ cmd/{ => tmsp}/cli.go | 7 +++++++ example/{main.go => dummy.go} | 20 +------------------- example/{main_test.go => dummy_test.go} | 2 +- 4 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 cmd/dummy/main.go rename cmd/{ => tmsp}/cli.go (96%) rename example/{main.go => dummy.go} (79%) rename example/{main_test.go => dummy_test.go} (98%) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go new file mode 100644 index 00000000..af2e1fa8 --- /dev/null +++ b/cmd/dummy/main.go @@ -0,0 +1,22 @@ +package main + +import ( + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/example" + "github.com/tendermint/tmsp/server" +) + +func main() { + + // Start the listener + _, err := server.StartListener("tcp://127.0.0.1:8080", example.NewDummyApplication()) + if err != nil { + Exit(err.Error()) + } + + // Wait forever + TrapSignal(func() { + // Cleanup + }) + +} diff --git a/cmd/cli.go b/cmd/tmsp/cli.go similarity index 96% rename from cmd/cli.go rename to cmd/tmsp/cli.go index 6ff3109a..1d1359c2 100644 --- a/cmd/cli.go +++ b/cmd/tmsp/cli.go @@ -121,6 +121,13 @@ func write(conn net.Conn, req types.Request) (types.Response, error) { if err != nil { return nil, err } + + // flush! + wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) + if err != nil { + return nil, err + } + var res types.Response wire.ReadBinaryPtr(&res, conn, 0, &n, &err) return res, err diff --git a/example/main.go b/example/dummy.go similarity index 79% rename from example/main.go rename to example/dummy.go index 828ccb1a..b3e9ae43 100644 --- a/example/main.go +++ b/example/dummy.go @@ -1,30 +1,12 @@ -package main +package example import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/server" "github.com/tendermint/tmsp/types" ) -func main() { - - // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:8080", NewDummyApplication()) - if err != nil { - Exit(err.Error()) - } - - // Wait forever - TrapSignal(func() { - // Cleanup - }) - -} - -//-------------------------------------------------------------------------------- - type DummyApplication struct { state merkle.Tree lastCommitState merkle.Tree diff --git a/example/main_test.go b/example/dummy_test.go similarity index 98% rename from example/main_test.go rename to example/dummy_test.go index a5475240..d0a40d87 100644 --- a/example/main_test.go +++ b/example/dummy_test.go @@ -1,4 +1,4 @@ -package main +package example import ( // "fmt" From c21c2ed69b243553dcff8da1d45b84d5f4a5621d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 29 Nov 2015 03:43:49 -0500 Subject: [PATCH 013/545] counter example --- example/counter.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 example/counter.go diff --git a/example/counter.go b/example/counter.go new file mode 100644 index 00000000..f5299732 --- /dev/null +++ b/example/counter.go @@ -0,0 +1,69 @@ +package example + +import ( + "encoding/binary" + "fmt" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/types" +) + +type CounterApplication struct { + hashCount int + lastHashCount int + + txCount int + lastTxCount int + + commitCount int +} + +func NewCounterApplication() *CounterApplication { + return &CounterApplication{} +} + +func (dapp *CounterApplication) Echo(message string) string { + return message +} + +func (dapp *CounterApplication) Info() []string { + return []string{Fmt("hash, tx, commit counts:%d, %d, %d", dapp.hashCount, dapp.txCount, dapp.commitCount)} +} + +func (dapp *CounterApplication) SetOption(key string, value string) types.RetCode { + return 0 +} + +func (dapp *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { + dapp.txCount += 1 + return nil, 0 +} + +func (dapp *CounterApplication) GetHash() ([]byte, types.RetCode) { + fmt.Println("getting hash!") + hash := make([]byte, 32) + binary.PutVarint(hash, int64(dapp.hashCount)) + dapp.hashCount += 1 + return hash, 0 +} + +func (dapp *CounterApplication) Commit() types.RetCode { + dapp.lastHashCount = dapp.hashCount + dapp.lastTxCount = dapp.txCount + dapp.commitCount += 1 + return 0 +} + +func (dapp *CounterApplication) Rollback() types.RetCode { + dapp.hashCount = dapp.lastHashCount + dapp.txCount = dapp.lastTxCount + return 0 +} + +func (dapp *CounterApplication) AddListener(key string) types.RetCode { + return 0 +} + +func (dapp *CounterApplication) RemListener(key string) types.RetCode { + return 0 +} From fe782cb8acfb62d45bacf81a83024ce578e7ead8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 29 Nov 2015 03:44:08 -0500 Subject: [PATCH 014/545] server: allow multiple connections --- example/counter.go | 2 -- server/server.go | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/example/counter.go b/example/counter.go index f5299732..1962cd91 100644 --- a/example/counter.go +++ b/example/counter.go @@ -2,7 +2,6 @@ package example import ( "encoding/binary" - "fmt" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" @@ -40,7 +39,6 @@ func (dapp *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCod } func (dapp *CounterApplication) GetHash() ([]byte, types.RetCode) { - fmt.Println("getting hash!") hash := make([]byte, 32) binary.PutVarint(hash, int64(dapp.hashCount)) dapp.hashCount += 1 diff --git a/server/server.go b/server/server.go index f7e18738..075e3e66 100644 --- a/server/server.go +++ b/server/server.go @@ -11,6 +11,8 @@ import ( "github.com/tendermint/tmsp/types" ) +var maxNumberConnections = 2 + func StartListener(protoAddr string, app types.Application) (net.Listener, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] @@ -22,7 +24,11 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error // A goroutine to accept a connection. go func() { + semaphore := make(chan struct{}, maxNumberConnections) + for { + semaphore <- struct{}{} + // Accept a connection conn, err := ln.Accept() if err != nil { @@ -38,9 +44,13 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error // Pull responses from 'responses' and write them to conn. go handleResponses(connClosed, responses, conn) - // Wait until connection is closed - <-connClosed - fmt.Println("Connection was closed. Waiting for new connection...") + go func() { + // Wait until connection is closed + <-connClosed + fmt.Println("Connection was closed. Waiting for new connection...") + + <-semaphore + }() } }() From 5d994944c6a1e4939bcf8ae34eb7aa0f45ee0629 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 29 Nov 2015 14:22:30 -0800 Subject: [PATCH 015/545] Refactor Application to Application & AppContext --- cmd/tmsp/cli.go | 28 ++++++++++++---- example/dummy.go | 69 ++++++++++++++++++++++++++++----------- example/dummy_test.go | 55 ++++++++++++++++++++++++++++--- server/server.go | 75 ++++++++++++++++++++++++++----------------- types/application.go | 9 ++++++ 5 files changed, 175 insertions(+), 61 deletions(-) diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index 1d1359c2..1eab662e 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -66,7 +66,7 @@ func cmdAppendTx(c *cli.Context) { if err != nil { Exit(err.Error()) } - res, err := write(conn, types.RequestAppendTx{[]byte(args[0])}) + res, err := makeRequest(conn, types.RequestAppendTx{[]byte(args[0])}) if err != nil { Exit(err.Error()) } @@ -79,7 +79,7 @@ func cmdGetHash(c *cli.Context) { if err != nil { Exit(err.Error()) } - res, err := write(conn, types.RequestGetHash{}) + res, err := makeRequest(conn, types.RequestGetHash{}) if err != nil { Exit(err.Error()) } @@ -92,7 +92,7 @@ func cmdCommit(c *cli.Context) { if err != nil { Exit(err.Error()) } - _, err = write(conn, types.RequestCommit{}) + _, err = makeRequest(conn, types.RequestCommit{}) if err != nil { Exit(err.Error()) } @@ -105,7 +105,7 @@ func cmdRollback(c *cli.Context) { if err != nil { Exit(err.Error()) } - _, err = write(conn, types.RequestRollback{}) + _, err = makeRequest(conn, types.RequestRollback{}) if err != nil { Exit(err.Error()) } @@ -114,21 +114,35 @@ func cmdRollback(c *cli.Context) { //-------------------------------------------------------------------------------- -func write(conn net.Conn, req types.Request) (types.Response, error) { +func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { var n int var err error + + // Write desired request wire.WriteBinary(req, conn, &n, &err) if err != nil { return nil, err } - // flush! + // Write flush request wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) if err != nil { return nil, err } + // Read desired response var res types.Response wire.ReadBinaryPtr(&res, conn, 0, &n, &err) - return res, err + if err != nil { + return nil, err + } + + // Read flush response + var resFlush types.ResponseFlush + wire.ReadBinaryPtr(&resFlush, conn, 0, &n, &err) + if err != nil { + return nil, err + } + + return res, nil } diff --git a/example/dummy.go b/example/dummy.go index b3e9ae43..7f8db3cd 100644 --- a/example/dummy.go +++ b/example/dummy.go @@ -1,6 +1,8 @@ package example import ( + "sync" + . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" @@ -8,8 +10,8 @@ import ( ) type DummyApplication struct { - state merkle.Tree - lastCommitState merkle.Tree + mtx sync.Mutex + state merkle.Tree } func NewDummyApplication() *DummyApplication { @@ -19,48 +21,77 @@ func NewDummyApplication() *DummyApplication { 0, nil, ) - return &DummyApplication{ - state: state, - lastCommitState: state, + return &DummyApplication{state: state} +} + +func (dapp *DummyApplication) Open() types.AppContext { + dapp.mtx.Lock() + defer dapp.mtx.Unlock() + return &DummyAppContext{ + app: dapp, + state: dapp.state.Copy(), } } -func (dapp *DummyApplication) Echo(message string) string { +func (dapp *DummyApplication) commitState(state merkle.Tree) { + dapp.mtx.Lock() + defer dapp.mtx.Unlock() + dapp.state = state.Copy() +} + +func (dapp *DummyApplication) getState() merkle.Tree { + dapp.mtx.Lock() + defer dapp.mtx.Unlock() + return dapp.state.Copy() +} + +//-------------------------------------------------------------------------------- + +type DummyAppContext struct { + app *DummyApplication + state merkle.Tree +} + +func (dac *DummyAppContext) Echo(message string) string { return message } -func (dapp *DummyApplication) Info() []string { - return []string{Fmt("size:%v", dapp.state.Size())} +func (dac *DummyAppContext) Info() []string { + return []string{Fmt("size:%v", dac.state.Size())} } -func (dapp *DummyApplication) SetOption(key string, value string) types.RetCode { +func (dac *DummyAppContext) SetOption(key string, value string) types.RetCode { return 0 } -func (dapp *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { - dapp.state.Set(tx, tx) +func (dac *DummyAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode) { + dac.state.Set(tx, tx) return nil, 0 } -func (dapp *DummyApplication) GetHash() ([]byte, types.RetCode) { - hash := dapp.state.Hash() +func (dac *DummyAppContext) GetHash() ([]byte, types.RetCode) { + hash := dac.state.Hash() return hash, 0 } -func (dapp *DummyApplication) Commit() types.RetCode { - dapp.lastCommitState = dapp.state.Copy() +func (dac *DummyAppContext) Commit() types.RetCode { + dac.app.commitState(dac.state) return 0 } -func (dapp *DummyApplication) Rollback() types.RetCode { - dapp.state = dapp.lastCommitState.Copy() +func (dac *DummyAppContext) Rollback() types.RetCode { + dac.state = dac.app.getState() return 0 } -func (dapp *DummyApplication) AddListener(key string) types.RetCode { +func (dac *DummyAppContext) AddListener(key string) types.RetCode { return 0 } -func (dapp *DummyApplication) RemListener(key string) types.RetCode { +func (dac *DummyAppContext) RemListener(key string) types.RetCode { return 0 } + +func (dac *DummyAppContext) Close() error { + return nil +} diff --git a/example/dummy_test.go b/example/dummy_test.go index d0a40d87..d6a4ad19 100644 --- a/example/dummy_test.go +++ b/example/dummy_test.go @@ -1,8 +1,9 @@ package example import ( - // "fmt" + "reflect" "testing" + "time" . "github.com/tendermint/go-common" "github.com/tendermint/go-wire" @@ -12,6 +13,8 @@ import ( func TestStream(t *testing.T) { + numAppendTxs := 200000 + // Start the listener _, err := server.StartListener("tcp://127.0.0.1:8080", NewDummyApplication()) if err != nil { @@ -25,7 +28,9 @@ func TestStream(t *testing.T) { } // Read response data + done := make(chan struct{}) go func() { + counter := 0 for { var n int var err error @@ -34,19 +39,59 @@ func TestStream(t *testing.T) { if err != nil { Exit(err.Error()) } - // fmt.Println("Read", n) + + // Process response + switch res := res.(type) { + case types.ResponseAppendTx: + counter += 1 + if res.RetCode != types.RetCodeOK { + t.Error("AppendTx failed with ret_code", res.RetCode) + } + if counter > numAppendTxs { + t.Fatal("Too many AppendTx responses") + } + t.Log("response", counter) + if counter == numAppendTxs { + go func() { + time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow + close(done) + }() + } + case types.ResponseFlush: + // ignore + default: + t.Error("Unexpected response type", reflect.TypeOf(res)) + } } }() // Write requests - for { + for counter := 0; counter < numAppendTxs; counter++ { + // Send request var n int var err error var req types.Request = types.RequestAppendTx{TxBytes: []byte("test")} wire.WriteBinary(req, conn, &n, &err) if err != nil { - Exit(err.Error()) + t.Fatal(err.Error()) + } + + // Sometimes send flush messages + if counter%123 == 0 { + t.Log("flush") + wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) + if err != nil { + t.Fatal(err.Error()) + } } - // fmt.Println("Wrote", n) } + + // Send final flush message + var n int + wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) + if err != nil { + t.Fatal(err.Error()) + } + + <-done } diff --git a/server/server.go b/server/server.go index 075e3e66..1ed2dec4 100644 --- a/server/server.go +++ b/server/server.go @@ -11,7 +11,7 @@ import ( "github.com/tendermint/tmsp/types" ) -var maxNumberConnections = 2 +// var maxNumberConnections = 2 func StartListener(protoAddr string, app types.Application) (net.Listener, error) { parts := strings.SplitN(protoAddr, "://", 2) @@ -23,33 +23,51 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error // A goroutine to accept a connection. go func() { - - semaphore := make(chan struct{}, maxNumberConnections) + // semaphore := make(chan struct{}, maxNumberConnections) for { - semaphore <- struct{}{} + // semaphore <- struct{}{} // Accept a connection + fmt.Println("Waiting for new connection...") conn, err := ln.Accept() if err != nil { Exit("Failed to accept connection") } else { fmt.Println("Accepted a new connection") } - connClosed := make(chan struct{}, 2) // Push to signal connection closed + + appContext := app.Open() + closeConn := make(chan error, 2) // Push to signal connection closed responses := make(chan types.Response, 1000) // A channel to buffer responses // Read requests from conn and deal with them - go handleRequests(app, connClosed, conn, responses) + go handleRequests(appContext, closeConn, conn, responses) // Pull responses from 'responses' and write them to conn. - go handleResponses(connClosed, responses, conn) + go handleResponses(closeConn, responses, conn) go func() { - // Wait until connection is closed - <-connClosed - fmt.Println("Connection was closed. Waiting for new connection...") + // Wait until signal to close connection + errClose := <-closeConn + if errClose != nil { + fmt.Printf("Connection error: %v\n", errClose) + } else { + fmt.Println("Connection was closed.") + } - <-semaphore + // Close the connection + err := conn.Close() + if err != nil { + fmt.Printf("Error in closing connection: %v\n", err) + } + + // Close the AppContext + err = appContext.Close() + if err != nil { + fmt.Printf("Error in closing app context: %v\n", err) + } + + // <-semaphore }() } @@ -59,7 +77,7 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error } // Read requests from conn and deal with them -func handleRequests(app types.Application, connClosed chan struct{}, conn net.Conn, responses chan<- types.Response) { +func handleRequests(appC types.AppContext, closeConn chan error, conn net.Conn, responses chan<- types.Response) { var count int var bufReader = bufio.NewReader(conn) for { @@ -68,48 +86,47 @@ func handleRequests(app types.Application, connClosed chan struct{}, conn net.Co var req types.Request wire.ReadBinaryPtr(&req, bufReader, 0, &n, &err) if err != nil { - fmt.Println("Error in handleRequests:", err.Error()) - connClosed <- struct{}{} + closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error()) return } count++ - handleRequest(app, req, responses) + handleRequest(appC, req, responses) } } -func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) { +func handleRequest(appC types.AppContext, req types.Request, responses chan<- types.Response) { switch req := req.(type) { case types.RequestEcho: - msg := app.Echo(req.Message) + msg := appC.Echo(req.Message) responses <- types.ResponseEcho{msg} case types.RequestFlush: responses <- types.ResponseFlush{} case types.RequestInfo: - data := app.Info() + data := appC.Info() responses <- types.ResponseInfo{data} case types.RequestSetOption: - retCode := app.SetOption(req.Key, req.Value) + retCode := appC.SetOption(req.Key, req.Value) responses <- types.ResponseSetOption{retCode} case types.RequestAppendTx: - events, retCode := app.AppendTx(req.TxBytes) + events, retCode := appC.AppendTx(req.TxBytes) responses <- types.ResponseAppendTx{retCode} for _, event := range events { responses <- types.ResponseEvent{event} } case types.RequestGetHash: - hash, retCode := app.GetHash() + hash, retCode := appC.GetHash() responses <- types.ResponseGetHash{retCode, hash} case types.RequestCommit: - retCode := app.Commit() + retCode := appC.Commit() responses <- types.ResponseCommit{retCode} case types.RequestRollback: - retCode := app.Rollback() + retCode := appC.Rollback() responses <- types.ResponseRollback{retCode} case types.RequestAddListener: - retCode := app.AddListener(req.EventKey) + retCode := appC.AddListener(req.EventKey) responses <- types.ResponseAddListener{retCode} case types.RequestRemListener: - retCode := app.RemListener(req.EventKey) + retCode := appC.RemListener(req.EventKey) responses <- types.ResponseRemListener{retCode} default: responses <- types.ResponseException{"Unknown request"} @@ -117,7 +134,7 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty } // Pull responses from 'responses' and write them to conn. -func handleResponses(connClosed chan struct{}, responses <-chan types.Response, conn net.Conn) { +func handleResponses(closeConn chan error, responses <-chan types.Response, conn net.Conn) { var count int var bufWriter = bufio.NewWriter(conn) for { @@ -126,15 +143,13 @@ func handleResponses(connClosed chan struct{}, responses <-chan types.Response, var err error wire.WriteBinary(res, bufWriter, &n, &err) if err != nil { - fmt.Println(err.Error()) - connClosed <- struct{}{} + closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return } if _, ok := res.(types.ResponseFlush); ok { err = bufWriter.Flush() if err != nil { - fmt.Println(err.Error()) - connClosed <- struct{}{} + closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return } } diff --git a/types/application.go b/types/application.go index d3a46cb7..555f97e7 100644 --- a/types/application.go +++ b/types/application.go @@ -2,6 +2,12 @@ package types type Application interface { + // For new socket connections + Open() AppContext +} + +type AppContext interface { + // Echo a message Echo(message string) string @@ -28,4 +34,7 @@ type Application interface { // Remove event listener RemListener(key string) RetCode + + // Close this AppContext + Close() error } From 6a5b80452379df9c9bcf671e071480a8592b8755 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 29 Nov 2015 14:34:15 -0800 Subject: [PATCH 016/545] Refactor CounterApplication to implement AppContext --- example/counter.go | 73 +++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/example/counter.go b/example/counter.go index 1962cd91..6e6b6527 100644 --- a/example/counter.go +++ b/example/counter.go @@ -2,18 +2,16 @@ package example import ( "encoding/binary" + "sync" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" ) type CounterApplication struct { - hashCount int - lastHashCount int - + mtx sync.Mutex + hashCount int txCount int - lastTxCount int - commitCount int } @@ -21,47 +19,76 @@ func NewCounterApplication() *CounterApplication { return &CounterApplication{} } -func (dapp *CounterApplication) Echo(message string) string { +func (app *CounterApplication) Open() types.AppContext { + return &CounterAppContext{ + app: app, + hashCount: app.hashCount, + txCount: app.txCount, + commitCount: app.commitCount, + } +} + +//-------------------------------------------------------------------------------- + +type CounterAppContext struct { + app *CounterApplication + hashCount int + txCount int + commitCount int +} + +func (appC *CounterAppContext) Echo(message string) string { return message } -func (dapp *CounterApplication) Info() []string { - return []string{Fmt("hash, tx, commit counts:%d, %d, %d", dapp.hashCount, dapp.txCount, dapp.commitCount)} +func (appC *CounterAppContext) Info() []string { + return []string{Fmt("hash, tx, commit counts:%d, %d, %d", appC.hashCount, appC.txCount, appC.commitCount)} } -func (dapp *CounterApplication) SetOption(key string, value string) types.RetCode { +func (appC *CounterAppContext) SetOption(key string, value string) types.RetCode { return 0 } -func (dapp *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { - dapp.txCount += 1 +func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode) { + appC.txCount += 1 return nil, 0 } -func (dapp *CounterApplication) GetHash() ([]byte, types.RetCode) { +func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) { hash := make([]byte, 32) - binary.PutVarint(hash, int64(dapp.hashCount)) - dapp.hashCount += 1 + binary.PutVarint(hash, int64(appC.hashCount)) + appC.hashCount += 1 return hash, 0 } -func (dapp *CounterApplication) Commit() types.RetCode { - dapp.lastHashCount = dapp.hashCount - dapp.lastTxCount = dapp.txCount - dapp.commitCount += 1 +func (appC *CounterAppContext) Commit() types.RetCode { + appC.commitCount += 1 + + appC.app.mtx.Lock() + appC.app.hashCount = appC.hashCount + appC.app.txCount = appC.txCount + appC.app.commitCount = appC.commitCount + appC.app.mtx.Unlock() return 0 } -func (dapp *CounterApplication) Rollback() types.RetCode { - dapp.hashCount = dapp.lastHashCount - dapp.txCount = dapp.lastTxCount +func (appC *CounterAppContext) Rollback() types.RetCode { + appC.app.mtx.Lock() + appC.hashCount = appC.app.hashCount + appC.txCount = appC.app.txCount + appC.commitCount = appC.app.commitCount + appC.app.mtx.Unlock() return 0 } -func (dapp *CounterApplication) AddListener(key string) types.RetCode { +func (appC *CounterAppContext) AddListener(key string) types.RetCode { return 0 } -func (dapp *CounterApplication) RemListener(key string) types.RetCode { +func (appC *CounterAppContext) RemListener(key string) types.RetCode { return 0 } + +func (appC *CounterAppContext) Close() error { + return nil +} From 7448cdc154e07b8e7c2ad4f6a8022c2088cd80a9 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 30 Nov 2015 15:22:42 -0800 Subject: [PATCH 017/545] Add serial=on option for CounterApplication --- example/counter.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/example/counter.go b/example/counter.go index 6e6b6527..870d5a80 100644 --- a/example/counter.go +++ b/example/counter.go @@ -35,6 +35,7 @@ type CounterAppContext struct { hashCount int txCount int commitCount int + serial bool } func (appC *CounterAppContext) Echo(message string) string { @@ -46,10 +47,22 @@ func (appC *CounterAppContext) Info() []string { } func (appC *CounterAppContext) SetOption(key string, value string) types.RetCode { + if key == "serial" && value == "on" { + appC.serial = true + } return 0 } func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode) { + if appC.serial { + txValue, bz := binary.Varint(tx) + if bz <= 0 { + return nil, types.RetCodeInternalError + } + if txValue != int64(appC.txCount) { + return nil, types.RetCodeInternalError + } + } appC.txCount += 1 return nil, 0 } From 93308a3e6f7b4879ed40993971e8c0042fd41468 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 30 Nov 2015 20:56:36 -0500 Subject: [PATCH 018/545] interactive tmsp console --- cmd/tmsp/cli.go | 61 ++++++++++++++++++++++++++++++++++-------------- server/server.go | 7 +++++- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index 1eab662e..e4550b8e 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -1,9 +1,11 @@ package main import ( + "bufio" "fmt" "net" "os" + "strings" . "github.com/tendermint/go-common" "github.com/tendermint/go-wire" @@ -12,6 +14,9 @@ import ( "github.com/codegangsta/cli" ) +// connection is a global variable so it can be reused by the console +var conn net.Conn + func main() { app := cli.NewApp() app.Name = "cli" @@ -24,6 +29,13 @@ func main() { }, } app.Commands = []cli.Command{ + { + Name: "console", + Usage: "Start an interactive tmsp console for multiple commands", + Action: func(c *cli.Context) { + cmdConsole(app, c) + }, + }, { Name: "append_tx", Usage: "Append a new tx to application", @@ -53,19 +65,44 @@ func main() { }, }, } + app.Before = before app.Run(os.Args) } +func before(c *cli.Context) error { + if conn == nil { + var err error + conn, err = Connect(c.GlobalString("address")) + if err != nil { + Exit(err.Error()) + } + } + return nil +} + //-------------------------------------------------------------------------------- +func cmdConsole(app *cli.App, c *cli.Context) { + for { + fmt.Printf("> ") + bufReader := bufio.NewReader(os.Stdin) + line, more, err := bufReader.ReadLine() + if more { + Exit("input is too long") + } else if err != nil { + Exit(err.Error()) + } + + args := []string{"tmsp"} + args = append(args, strings.Split(string(line), " ")...) + app.Run(args) + } +} + // Append a new tx to application func cmdAppendTx(c *cli.Context) { args := c.Args() // Args to AppendTx - conn, err := Connect(c.GlobalString("address")) - if err != nil { - Exit(err.Error()) - } res, err := makeRequest(conn, types.RequestAppendTx{[]byte(args[0])}) if err != nil { Exit(err.Error()) @@ -75,10 +112,6 @@ func cmdAppendTx(c *cli.Context) { // Get application Merkle root hash func cmdGetHash(c *cli.Context) { - conn, err := Connect(c.GlobalString("address")) - if err != nil { - Exit(err.Error()) - } res, err := makeRequest(conn, types.RequestGetHash{}) if err != nil { Exit(err.Error()) @@ -88,11 +121,7 @@ func cmdGetHash(c *cli.Context) { // Commit the application state func cmdCommit(c *cli.Context) { - conn, err := Connect(c.GlobalString("address")) - if err != nil { - Exit(err.Error()) - } - _, err = makeRequest(conn, types.RequestCommit{}) + _, err := makeRequest(conn, types.RequestCommit{}) if err != nil { Exit(err.Error()) } @@ -101,11 +130,7 @@ func cmdCommit(c *cli.Context) { // Roll back the application state to the latest commit func cmdRollback(c *cli.Context) { - conn, err := Connect(c.GlobalString("address")) - if err != nil { - Exit(err.Error()) - } - _, err = makeRequest(conn, types.RequestRollback{}) + _, err := makeRequest(conn, types.RequestRollback{}) if err != nil { Exit(err.Error()) } diff --git a/server/server.go b/server/server.go index 1ed2dec4..e5945c81 100644 --- a/server/server.go +++ b/server/server.go @@ -3,6 +3,7 @@ package server import ( "bufio" "fmt" + "io" "net" "strings" @@ -86,7 +87,11 @@ func handleRequests(appC types.AppContext, closeConn chan error, conn net.Conn, var req types.Request wire.ReadBinaryPtr(&req, bufReader, 0, &n, &err) if err != nil { - closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error()) + if err == io.EOF { + closeConn <- fmt.Errorf("Connection closed by client") + } else { + closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error()) + } return } count++ From 86c2484c29ef44555f49d176b7b19790c225ef65 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 30 Nov 2015 23:49:18 -0500 Subject: [PATCH 019/545] cmdInfo, cmdSetOption; append_tx can take hex --- cmd/tmsp/cli.go | 60 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index e4550b8e..aa5a5a8b 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "encoding/hex" "fmt" "net" "os" @@ -36,6 +37,20 @@ func main() { cmdConsole(app, c) }, }, + { + Name: "info", + Usage: "Get some info about the application", + Action: func(c *cli.Context) { + cmdInfo(c) + }, + }, + { + Name: "set_option", + Usage: "Set an option on the application", + Action: func(c *cli.Context) { + cmdSetOption(c) + }, + }, { Name: "append_tx", Usage: "Append a new tx to application", @@ -100,14 +115,49 @@ func cmdConsole(app *cli.App, c *cli.Context) { } } -// Append a new tx to application -func cmdAppendTx(c *cli.Context) { - args := c.Args() // Args to AppendTx - res, err := makeRequest(conn, types.RequestAppendTx{[]byte(args[0])}) +// Get some info from the application +func cmdInfo(c *cli.Context) { + res, err := makeRequest(conn, types.RequestInfo{}) if err != nil { Exit(err.Error()) } - fmt.Println("Sent tx:", args[0], "response:", res) + fmt.Println(res) +} + +// Set an option on the application +func cmdSetOption(c *cli.Context) { + args := c.Args() + if len(args) != 2 { + Exit("set_option takes 2 arguments (key, value)") + } + _, err := makeRequest(conn, types.RequestSetOption{args[0], args[1]}) + if err != nil { + Exit(err.Error()) + } + fmt.Printf("Set option %s = %s\n", args[0], args[1]) +} + +// Append a new tx to application +func cmdAppendTx(c *cli.Context) { + args := c.Args() + if len(args) != 1 { + Exit("append_tx takes 1 argument") + } + txString := args[0] + tx := []byte(txString) + if len(txString) > 2 && strings.HasPrefix(txString, "0x") { + var err error + tx, err = hex.DecodeString(txString[2:]) + if err != nil { + Exit(err.Error()) + } + } + + res, err := makeRequest(conn, types.RequestAppendTx{tx}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("Sent tx:", txString, "response:", res) } // Get application Merkle root hash From 3e721456f5c01556bdc35495e0c537f653d81ca1 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 1 Dec 2015 01:49:54 -0500 Subject: [PATCH 020/545] tmsp batch and some tests --- cmd/counter/main.go | 22 ++++++++++ cmd/tmsp/cli.go | 29 ++++++++++++- example/counter.go | 2 +- test.sh | 100 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 cmd/counter/main.go create mode 100644 test.sh diff --git a/cmd/counter/main.go b/cmd/counter/main.go new file mode 100644 index 00000000..36485996 --- /dev/null +++ b/cmd/counter/main.go @@ -0,0 +1,22 @@ +package main + +import ( + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/example" + "github.com/tendermint/tmsp/server" +) + +func main() { + + // Start the listener + _, err := server.StartListener("tcp://127.0.0.1:8080", example.NewCounterApplication()) + if err != nil { + Exit(err.Error()) + } + + // Wait forever + TrapSignal(func() { + // Cleanup + }) + +} diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index aa5a5a8b..242ffa60 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -4,6 +4,7 @@ import ( "bufio" "encoding/hex" "fmt" + "io" "net" "os" "strings" @@ -30,6 +31,13 @@ func main() { }, } app.Commands = []cli.Command{ + { + Name: "batch", + Usage: "Run a batch of tmsp commands against an application", + Action: func(c *cli.Context) { + cmdBatch(app, c) + }, + }, { Name: "console", Usage: "Start an interactive tmsp console for multiple commands", @@ -98,6 +106,23 @@ func before(c *cli.Context) error { //-------------------------------------------------------------------------------- +func cmdBatch(app *cli.App, c *cli.Context) { + bufReader := bufio.NewReader(os.Stdin) + for { + line, more, err := bufReader.ReadLine() + if more { + Exit("input line is too long") + } else if err == io.EOF { + break + } else if err != nil { + Exit(err.Error()) + } + args := []string{"tmsp"} + args = append(args, strings.Split(string(line), " ")...) + app.Run(args) + } +} + func cmdConsole(app *cli.App, c *cli.Context) { for { fmt.Printf("> ") @@ -134,7 +159,7 @@ func cmdSetOption(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Printf("Set option %s = %s\n", args[0], args[1]) + fmt.Printf("%s=%s\n", args[0], args[1]) } // Append a new tx to application @@ -166,7 +191,7 @@ func cmdGetHash(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Println("Got hash:", Fmt("%X", res.(types.ResponseGetHash).Hash)) + fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash) } // Commit the application state diff --git a/example/counter.go b/example/counter.go index 870d5a80..d4b0e477 100644 --- a/example/counter.go +++ b/example/counter.go @@ -69,7 +69,7 @@ func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) { hash := make([]byte, 32) - binary.PutVarint(hash, int64(appC.hashCount)) + binary.PutVarint(hash, int64(appC.txCount)) appC.hashCount += 1 return hash, 0 } diff --git a/test.sh b/test.sh new file mode 100644 index 00000000..00c1f203 --- /dev/null +++ b/test.sh @@ -0,0 +1,100 @@ +#! /bin/bash + +# Make sure the tmsp cli can connect to the dummy +echo "Dummy test ..." +dummy &> /dev/null & +PID=`echo $!` +sleep 1 +RESULT_HASH=`tmsp get_hash` +if [[ "$RESULT_HASH" != "" ]]; then + echo "Expected nothing but got: $RESULT_HASH" + exit 1 +fi +echo "... Pass!" +echo "" + +# Add a tx, get hash, commit, get hash +# hashes should be non-empty and identical +echo "Dummy batch test ..." +OUTPUT=`(tmsp batch) < /dev/null & +PID=`echo $!` +sleep 1 +OUTPUT=`(tmsp batch) < Date: Tue, 1 Dec 2015 15:27:50 -0800 Subject: [PATCH 021/545] Change port 8080 to 46658 --- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- cmd/tmsp/cli.go | 2 +- example/dummy_test.go | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 36485996..4870b8be 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -9,7 +9,7 @@ import ( func main() { // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:8080", example.NewCounterApplication()) + _, err := server.StartListener("tcp://127.0.0.1:46658", example.NewCounterApplication()) if err != nil { Exit(err.Error()) } diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index af2e1fa8..7f3176bf 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -9,7 +9,7 @@ import ( func main() { // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:8080", example.NewDummyApplication()) + _, err := server.StartListener("tcp://127.0.0.1:46658", example.NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index 242ffa60..5997cf5f 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -26,7 +26,7 @@ func main() { app.Flags = []cli.Flag{ cli.StringFlag{ Name: "address", - Value: "tcp://127.0.0.1:8080", + Value: "tcp://127.0.0.1:46658", Usage: "address of application socket", }, } diff --git a/example/dummy_test.go b/example/dummy_test.go index d6a4ad19..d8b5b0f6 100644 --- a/example/dummy_test.go +++ b/example/dummy_test.go @@ -16,13 +16,13 @@ func TestStream(t *testing.T) { numAppendTxs := 200000 // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:8080", NewDummyApplication()) + _, err := server.StartListener("tcp://127.0.0.1:46658", NewDummyApplication()) if err != nil { Exit(err.Error()) } // Connect to the socket - conn, err := Connect("tcp://127.0.0.1:8080") + conn, err := Connect("tcp://127.0.0.1:46658") if err != nil { Exit(err.Error()) } From bbaacce4721d00e6ab2ba4386ae96d4a82dad8e1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 2 Dec 2015 00:25:39 -0800 Subject: [PATCH 022/545] Change server listener addr to 0.0.0.0 --- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 4870b8be..7c31aff7 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -9,7 +9,7 @@ import ( func main() { // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:46658", example.NewCounterApplication()) + _, err := server.StartListener("tcp://0.0.0.0:46658", example.NewCounterApplication()) if err != nil { Exit(err.Error()) } diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 7f3176bf..fe5077bb 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -9,7 +9,7 @@ import ( func main() { // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:46658", example.NewDummyApplication()) + _, err := server.StartListener("tcp://0.0.0.0:46658", example.NewDummyApplication()) if err != nil { Exit(err.Error()) } From 7b1ebb924552ca95352a31bde2c4d97b53d7f083 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 3 Dec 2015 15:47:20 -0800 Subject: [PATCH 023/545] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5000b819..66d5f9fb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# Tendermint Streaming Protocol (TMSP) +# Tendermint Socket Protocol (TMSP) **TMSP** is a socket protocol, which means applications can be written in any programming language. -TMSP is an asynchronous streaming protocol: message responses are written back asynchronously to the platform. +TMSP is an asynchronous protocol: message responses are written back asynchronously to the platform. *Applications must be deterministic.* From 21abda0602e591991a2f1933018c113f0a85b9f6 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 4 Dec 2015 00:59:26 -0800 Subject: [PATCH 024/545] Make Counter app return nil hash initially --- example/counter.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/example/counter.go b/example/counter.go index d4b0e477..7b0ff1f8 100644 --- a/example/counter.go +++ b/example/counter.go @@ -68,10 +68,14 @@ func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode } func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) { - hash := make([]byte, 32) - binary.PutVarint(hash, int64(appC.txCount)) appC.hashCount += 1 - return hash, 0 + if appC.txCount == 0 { + return nil, 0 + } else { + hash := make([]byte, 32) + binary.PutVarint(hash, int64(appC.txCount)) + return hash, 0 + } } func (appC *CounterAppContext) Commit() types.RetCode { From 36e89b606e9527ba237795b6193d6101e1e5bce0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 5 Dec 2015 17:52:35 +0000 Subject: [PATCH 025/545] fix test --- test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.sh b/test.sh index 00c1f203..4bc0f8db 100644 --- a/test.sh +++ b/test.sh @@ -67,8 +67,8 @@ STDIN` # echo $? HASH1=`echo "$OUTPUT" | tail -n +2 | head -n 1` -if [[ "${HASH1:0:2}" != "00" ]]; then - echo "Expected opening hash to lead with 00. Got $HASH1" +if [[ "$HASH1" != "" ]]; then + echo "Expected opening hash to be empty. Got $HASH1" exit 1 fi From 5c20d1b3e561106143916edcfa1b46b646e1478c Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 8 Dec 2015 21:01:33 -0800 Subject: [PATCH 026/545] Add way to enforce serial order in counter app from command line --- cmd/counter/main.go | 8 +++++++- example/counter.go | 6 ++++-- test.sh | 0 3 files changed, 11 insertions(+), 3 deletions(-) mode change 100644 => 100755 test.sh diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 7c31aff7..f36394e7 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -1,6 +1,8 @@ package main import ( + "flag" + . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/example" "github.com/tendermint/tmsp/server" @@ -8,8 +10,12 @@ import ( func main() { + serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") + flag.Parse() + app := example.NewCounterApplication(*serialPtr) + // Start the listener - _, err := server.StartListener("tcp://0.0.0.0:46658", example.NewCounterApplication()) + _, err := server.StartListener("tcp://0.0.0.0:46658", app) if err != nil { Exit(err.Error()) } diff --git a/example/counter.go b/example/counter.go index 7b0ff1f8..9e4b8671 100644 --- a/example/counter.go +++ b/example/counter.go @@ -13,10 +13,11 @@ type CounterApplication struct { hashCount int txCount int commitCount int + serial bool } -func NewCounterApplication() *CounterApplication { - return &CounterApplication{} +func NewCounterApplication(serial bool) *CounterApplication { + return &CounterApplication{serial: serial} } func (app *CounterApplication) Open() types.AppContext { @@ -25,6 +26,7 @@ func (app *CounterApplication) Open() types.AppContext { hashCount: app.hashCount, txCount: app.txCount, commitCount: app.commitCount, + serial: app.serial, } } diff --git a/test.sh b/test.sh old mode 100644 new mode 100755 From 4a0469d3ecb9a699bcde7801724ce15a9075372b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 8 Dec 2015 21:52:40 -0800 Subject: [PATCH 027/545] Make counter app use LittleEndian uint64 encoding --- example/counter.go | 11 +++++------ test.sh | 10 +++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/example/counter.go b/example/counter.go index 9e4b8671..e96e78e5 100644 --- a/example/counter.go +++ b/example/counter.go @@ -57,11 +57,10 @@ func (appC *CounterAppContext) SetOption(key string, value string) types.RetCode func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode) { if appC.serial { - txValue, bz := binary.Varint(tx) - if bz <= 0 { - return nil, types.RetCodeInternalError - } - if txValue != int64(appC.txCount) { + tx8 := make([]byte, 8) + copy(tx8, tx) + txValue := binary.LittleEndian.Uint64(tx8) + if txValue != uint64(appC.txCount) { return nil, types.RetCodeInternalError } } @@ -75,7 +74,7 @@ func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) { return nil, 0 } else { hash := make([]byte, 32) - binary.PutVarint(hash, int64(appC.txCount)) + binary.LittleEndian.PutUint64(hash, uint64(appC.txCount)) return hash, 0 } } diff --git a/test.sh b/test.sh index 4bc0f8db..2f445861 100755 --- a/test.sh +++ b/test.sh @@ -76,20 +76,20 @@ OUTPUT=`(tmsp batch) < Date: Sun, 6 Dec 2015 18:18:13 -0500 Subject: [PATCH 028/545] add counter app in python --- cmd/tmsp/cli.go | 20 +++++ example/python/app.py | 83 +++++++++++++++++++++ example/python/tmsp/msg.py | 54 ++++++++++++++ example/python/tmsp/reader.py | 31 ++++++++ example/python/tmsp/server.py | 134 ++++++++++++++++++++++++++++++++++ example/python/tmsp/wire.py | 99 +++++++++++++++++++++++++ 6 files changed, 421 insertions(+) create mode 100644 example/python/app.py create mode 100644 example/python/tmsp/msg.py create mode 100644 example/python/tmsp/reader.py create mode 100644 example/python/tmsp/server.py create mode 100644 example/python/tmsp/wire.py diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index 5997cf5f..9f06c3f7 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -45,6 +45,13 @@ func main() { cmdConsole(app, c) }, }, + { + Name: "echo", + Usage: "Have the application echo a message", + Action: func(c *cli.Context) { + cmdEcho(c) + }, + }, { Name: "info", Usage: "Get some info about the application", @@ -140,6 +147,19 @@ func cmdConsole(app *cli.App, c *cli.Context) { } } +// Have the application echo a message +func cmdEcho(c *cli.Context) { + args := c.Args() + if len(args) != 1 { + Exit("echo takes 1 argument") + } + res, err := makeRequest(conn, types.RequestEcho{args[0]}) + if err != nil { + Exit(err.Error()) + } + fmt.Println(res) +} + // Get some info from the application func cmdInfo(c *cli.Context) { res, err := makeRequest(conn, types.RequestInfo{}) diff --git a/example/python/app.py b/example/python/app.py new file mode 100644 index 00000000..f7797698 --- /dev/null +++ b/example/python/app.py @@ -0,0 +1,83 @@ + +import sys +sys.path.insert(0, './tmsp') + +from wire import * +from server import * + + +# tmsp application interface + +class CounterApplication(): + def __init__(self): + self.hashCount = 0 + self.txCount = 0 + self.commitCount = 0 + + def open(self): + return CounterAppContext(self) + +class CounterAppContext(): + def __init__(self, app): + self.app = app + self.hashCount = app.hashCount + self.txCount = app.txCount + self.commitCount = app.commitCount + self.serial = False + + def echo(self, msg): + return msg, 0 + + def info(self): + return ["hash, tx, commit counts:%d, %d, %d"%(self.hashCount, self.txCount, self.commitCount)], 0 + + def set_option(self, key, value): + if key == "serial" and value == "on": + self.serial = True + return 0 + + def append_tx(self, txBytes): + if self.serial: + txValue = decode_big_endian(BytesReader(txBytes), len(txBytes)) + if txValue != self.txCount: + return [], 1 + self.txCount += 1 + return None, 0 + + def get_hash(self): + self.hashCount += 1 + if self.txCount == 0: + return "", 0 + return str(encode_big_endian(self.txCount, 8)), 0 + + def commit(self): + return 0 + + def rollback(self): + return 0 + + def add_listener(self): + return 0 + + def rm_listener(self): + return 0 + + def event(self): + return + + +if __name__ == '__main__': + l = len(sys.argv) + if l == 1: + port = 46658 + elif l == 2: + port = int(sys.argv[1]) + else: + print "too many arguments" + quit() + + print 'TMSP Demo APP (Python)' + + app = CounterApplication() + server = TMSPServer(app, port) + server.main_loop() diff --git a/example/python/tmsp/msg.py b/example/python/tmsp/msg.py new file mode 100644 index 00000000..a99386a3 --- /dev/null +++ b/example/python/tmsp/msg.py @@ -0,0 +1,54 @@ +from wire import * + +# map type_byte to message name +message_types = { +0x01 : "echo", +0x02 : "flush", +0x03 : "info", +0x04 : "set_option", +0x21 : "append_tx", +0x22 : "get_hash", +0x23 : "commit", +0x24 : "rollback", +0x25 : "add_listener", +0x26 : "rm_listener", +} + +# return the decoded arguments of tmsp messages +class RequestDecoder(): + def __init__(self, reader): + self.reader = reader + + def echo(self): + return decode_string(self.reader) + + def flush(self): + return + + def info(self): + return + + def set_option(self): + return decode_string(self.reader), decode_string(self.reader) + + def append_tx(self): + return decode_string(self.reader) + + def get_hash(self): + return + + def commit(self): + return + + def rollback(self): + return + + def add_listener(self): + # TODO + return + + def rm_listener(self): + # TODO + return + + diff --git a/example/python/tmsp/reader.py b/example/python/tmsp/reader.py new file mode 100644 index 00000000..edb88e67 --- /dev/null +++ b/example/python/tmsp/reader.py @@ -0,0 +1,31 @@ + +# Simple read() method around a bytearray +class BytesReader(): + def __init__(self, b): + self.buf = b + + def read(self, n): + if len(self.buf) < n: + # TODO: exception + return + r = self.buf[:n] + self.buf = self.buf[n:] + return r + +# Buffer bytes off a tcp connection and read them off in chunks +class ConnReader(): + def __init__(self, conn): + self.conn = conn + self.buf = bytearray() + + # blocking + def read(self, n): + while n > len(self.buf): + moreBuf = self.conn.recv(1024) + if not moreBuf: + raise IOError("dead connection") + self.buf = self.buf + bytearray(moreBuf) + + r = self.buf[:n] + self.buf = self.buf[n:] + return r diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py new file mode 100644 index 00000000..cc1970c4 --- /dev/null +++ b/example/python/tmsp/server.py @@ -0,0 +1,134 @@ +import socket +import select +import sys +import os + + +from wire import * +from reader import * +from msg import * + +# TMSP server responds to messges by calling methods on the app +class TMSPServer(): + def __init__(self, app, port=5410): + self.app = app + self.appMap = {} # map conn file descriptors to (appContext, msgDecoder) + + self.port = port + self.listen_backlog = 10 + + self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.listener.setblocking(0) + self.listener.bind(('', port)) + + self.listener.listen(self.listen_backlog) + + self.shutdown = False + + self.read_list = [self.listener] + self.write_list = [] + + def handle_new_connection(self, r): + new_fd, new_addr = r.accept() + self.read_list.append(new_fd) + self.write_list.append(new_fd) + print 'new connection to', new_addr + + appContext = self.app.open() + self.appMap[new_fd] = (appContext, RequestDecoder(ConnReader(new_fd))) + + def handle_conn_closed(self, r): + self.read_list.remove(r) + self.write_list.remove(r) + r.close() + print "connection closed" + + def handle_recv(self, r): + appCtx, conn = self.appMap[r] + response = bytearray() + while True: + try: + # first read the request type and get the msg decoder + typeByte = conn.reader.read(1) + typeByte = int(typeByte[0]) + resTypeByte = typeByte+0x10 + req_type = message_types[typeByte] + + if req_type == "flush": + response += bytearray([resTypeByte]) + sent = r.send(str(response)) + return + + decoder = getattr(conn, req_type) + + req_args = decoder() + req_f = getattr(appCtx, req_type) + if req_args == None: + res = req_f() + elif isinstance(req_args, tuple): + res = req_f(*req_args) + else: + res = req_f(req_args) + + if isinstance(res, tuple): + res, ret_code = res + else: + ret_code = res + res = None + + if ret_code != 0: + print "non-zero retcode:", ret_code + return + + if req_type in ("echo", "info"): # these dont return a ret code + response += bytearray([resTypeByte]) + encode(res) + else: + response += bytearray([resTypeByte]) + encode(ret_code) + encode(res) + except TypeError as e: + print "TypeError on reading from connection:", e + self.handle_conn_closed(r) + return + except ValueError as e: + print "ValueError on reading from connection:", e + self.handle_conn_closed(r) + return + except IOError as e: + print "IOError on reading from connection:", e + self.handle_conn_closed(r) + return + except: + print "error reading from connection", sys.exc_info()[0] # TODO better + self.handle_conn_closed(r) + return + + def main_loop(self): + while not self.shutdown: + r_list, w_list, _ = select.select(self.read_list, self.write_list, [], 2.5) + + for r in r_list: + if (r == self.listener): + try: + self.handle_new_connection(r) + + # undo adding to read list ... + except NameError as e: + print "Could not connect due to NameError:", e + except TypeError as e: + print "Could not connect due to TypeError:", e + except: + print "Could not connect due to unexpected error:", sys.exc_info()[0] + else: + self.handle_recv(r) + + + + def handle_shutdown(self): + for r in self.read_list: + r.close() + for w in self.write_list: + try: + w.close() + except: pass + self.shutdown = True + diff --git a/example/python/tmsp/wire.py b/example/python/tmsp/wire.py new file mode 100644 index 00000000..e1d37eff --- /dev/null +++ b/example/python/tmsp/wire.py @@ -0,0 +1,99 @@ + +# the decoder works off a reader +# the encoder returns bytearray + +def bytes2hex(b): + if type(b) in (str, unicode): + return "".join([hex(ord(c))[2:].zfill(2) for c in b]) + else: + return bytes2hex(b.decode()) + + +# expects uvarint64 (no crazy big nums!) +def uvarint_size(i): + if i == 0: + return 0 + for j in xrange(1, 8): + if i < 1< int(0xF0) else False + if negate: size = size -0xF0 + i = decode_big_endian(reader, size) + if negate: i = i*(-1) + return i + +def encode_string(s): + size = encode_varint(len(s)) + return size + bytearray(s) + +def decode_string(reader): + length = decode_varint(reader) + return str(reader.read(length)) + +def encode_list(s): + b = bytearray() + map(b.extend, map(encode, s)) + return encode_varint(len(s)) + b + +def encode(s): + if s == None: + return bytearray() + if isinstance(s, int): + return encode_varint(s) + elif isinstance(s, str): + return encode_string(s) + elif isinstance(s, list): + return encode_list(s) + else: + print "UNSUPPORTED TYPE!", type(s), s + + +import binascii + +if __name__ == '__main__': + ns = [100,100,1000,256] + ss = [2,5,5,2] + bs = map(encode_big_endian, ns,ss) + ds = map(decode_big_endian, bs,ss) + print ns + print [i[0] for i in ds] + + ss = ["abc", "hi there jim", "ok now what"] + e = map(encode_string, ss) + d = map(decode_string, e) + print ss + print [i[0] for i in d] From af2a1a6fc10e22513bb3e04c8dd855a9406971bc Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 14 Dec 2015 18:00:18 -0500 Subject: [PATCH 029/545] python fixes, tests --- cmd/tmsp/cli.go | 2 + example/python/app.py | 11 +++-- example/python/tmsp/reader.py | 1 + example/python/tmsp/server.py | 2 +- example/python/tmsp/wire.py | 3 ++ tests/test.sh | 13 ++++++ tests/test_counter.sh | 75 ++++++++++++++++++++++++++++++++++ test.sh => tests/test_dummy.sh | 47 --------------------- 8 files changed, 103 insertions(+), 51 deletions(-) create mode 100644 tests/test.sh create mode 100644 tests/test_counter.sh rename test.sh => tests/test_dummy.sh (56%) diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index 9f06c3f7..75cd921d 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -121,6 +121,8 @@ func cmdBatch(app *cli.App, c *cli.Context) { Exit("input line is too long") } else if err == io.EOF { break + } else if len(line) == 0 { + continue } else if err != nil { Exit(err.Error()) } diff --git a/example/python/app.py b/example/python/app.py index f7797698..a9e9d3b7 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -38,9 +38,12 @@ class CounterAppContext(): def append_tx(self, txBytes): if self.serial: - txValue = decode_big_endian(BytesReader(txBytes), len(txBytes)) + txByteArray = bytearray(txBytes) + if len(txBytes) >= 2 and txBytes[:2] == "0x": + txByteArray = hex2bytes(txBytes[2:]) + txValue = decode_big_endian(BytesReader(txByteArray), len(txBytes)) if txValue != self.txCount: - return [], 1 + return None, 1 self.txCount += 1 return None, 0 @@ -48,7 +51,9 @@ class CounterAppContext(): self.hashCount += 1 if self.txCount == 0: return "", 0 - return str(encode_big_endian(self.txCount, 8)), 0 + h = encode_big_endian(self.txCount, 8) + h.reverse() + return str(h), 0 def commit(self): return 0 diff --git a/example/python/tmsp/reader.py b/example/python/tmsp/reader.py index edb88e67..f1b3dfae 100644 --- a/example/python/tmsp/reader.py +++ b/example/python/tmsp/reader.py @@ -6,6 +6,7 @@ class BytesReader(): def read(self, n): if len(self.buf) < n: + print "reader err: buf less than n" # TODO: exception return r = self.buf[:n] diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py index cc1970c4..e25e4e1f 100644 --- a/example/python/tmsp/server.py +++ b/example/python/tmsp/server.py @@ -77,9 +77,9 @@ class TMSPServer(): ret_code = res res = None + print "called", req_type, "ret code:", ret_code if ret_code != 0: print "non-zero retcode:", ret_code - return if req_type in ("echo", "info"): # these dont return a ret code response += bytearray([resTypeByte]) + encode(res) diff --git a/example/python/tmsp/wire.py b/example/python/tmsp/wire.py index e1d37eff..fde4e160 100644 --- a/example/python/tmsp/wire.py +++ b/example/python/tmsp/wire.py @@ -2,6 +2,9 @@ # the decoder works off a reader # the encoder returns bytearray +def hex2bytes(h): + return bytearray(h.decode('hex')) + def bytes2hex(b): if type(b) in (str, unicode): return "".join([hex(ord(c))[2:].zfill(2) for c in b]) diff --git a/tests/test.sh b/tests/test.sh new file mode 100644 index 00000000..848d14cb --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,13 @@ + +ROOT=$GOPATH/src/github.com/tendermint/tmsp +cd $ROOT + +# test golang dummy +bash tests/test_dummy.sh + +# test golang counter +bash tests/test_counter.sh + +# test python counter +cd example/python +COUNTER_APP="python app.py" bash $ROOT/tests/test_counter.sh diff --git a/tests/test_counter.sh b/tests/test_counter.sh new file mode 100644 index 00000000..41909dde --- /dev/null +++ b/tests/test_counter.sh @@ -0,0 +1,75 @@ + +# so we can test other languages +if [[ "$COUNTER_APP" == "" ]]; then + COUNTER_APP="counter" +fi + +echo "Testing counter app for: $COUNTER_APP" + +# run the counter app +$COUNTER_APP &> /dev/null & +PID=`echo $!` + +if [[ "$?" != 0 ]]; then + echo "Error running tmsp command" + echo $OUTPUT + exit 1 +fi + +sleep 1 +OUTPUT=`(tmsp batch) < /dev/null +if [[ "$?" == "0" ]]; then + kill -9 $PID +fi + diff --git a/test.sh b/tests/test_dummy.sh similarity index 56% rename from test.sh rename to tests/test_dummy.sh index 2f445861..b88475df 100755 --- a/test.sh +++ b/tests/test_dummy.sh @@ -51,50 +51,3 @@ echo "" kill $PID sleep 1 - -# test the counter app -echo "Counter test ..." -counter &> /dev/null & -PID=`echo $!` -sleep 1 -OUTPUT=`(tmsp batch) < Date: Mon, 14 Dec 2015 18:06:56 -0500 Subject: [PATCH 030/545] example/golang --- README.md | 5 ++++- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- example/{ => golang}/counter.go | 0 example/{ => golang}/dummy.go | 0 example/{ => golang}/dummy_test.go | 0 6 files changed, 6 insertions(+), 3 deletions(-) rename example/{ => golang}/counter.go (100%) rename example/{ => golang}/dummy.go (100%) rename example/{ => golang}/dummy_test.go (100%) diff --git a/README.md b/README.md index 66d5f9fb..7e17768d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Tendermint Socket Protocol (TMSP) -**TMSP** is a socket protocol, which means applications can be written in any programming language. +**TMSP** is a socket protocol enabling a consensus engine, running in one process, +to manage an application state, running in another. +Thus the applications can be written in any programming language. + TMSP is an asynchronous protocol: message responses are written back asynchronously to the platform. *Applications must be deterministic.* diff --git a/cmd/counter/main.go b/cmd/counter/main.go index f36394e7..3e770a43 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -4,7 +4,7 @@ import ( "flag" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/example" + "github.com/tendermint/tmsp/example/golang" "github.com/tendermint/tmsp/server" ) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index fe5077bb..ce9bf8d0 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -2,7 +2,7 @@ package main import ( . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/example" + "github.com/tendermint/tmsp/example/golang" "github.com/tendermint/tmsp/server" ) diff --git a/example/counter.go b/example/golang/counter.go similarity index 100% rename from example/counter.go rename to example/golang/counter.go diff --git a/example/dummy.go b/example/golang/dummy.go similarity index 100% rename from example/dummy.go rename to example/golang/dummy.go diff --git a/example/dummy_test.go b/example/golang/dummy_test.go similarity index 100% rename from example/dummy_test.go rename to example/golang/dummy_test.go From 4b67e9e9d23e7b24db41cb8132fa1c842cce74e4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 17 Dec 2015 13:46:04 -0800 Subject: [PATCH 031/545] Add Makefile --- Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..13f25e8e --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: all test get_deps + +all: test get_deps install + +install: + go install github.com/tendermint/tmsp/cmd/... + +test: + go test github.com/tendermint/tmsp/... + +get_deps: + go get -d github.com/tendermint/tmsp/... From a357f3156a4a14734ae4d31ebd30f8d0bf62875e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 7 Dec 2015 18:16:03 -0500 Subject: [PATCH 032/545] RetCodeEncodingError --- cmd/tmsp/cli.go | 2 +- types/retcode.go | 1 + types/retcode_string.go | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/tmsp/cli.go b/cmd/tmsp/cli.go index 75cd921d..e8fb7a19 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp/cli.go @@ -204,7 +204,7 @@ func cmdAppendTx(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Println("Sent tx:", txString, "response:", res) + fmt.Println("Response:", res) } // Get application Merkle root hash diff --git a/types/retcode.go b/types/retcode.go index 640f6236..559164c6 100644 --- a/types/retcode.go +++ b/types/retcode.go @@ -13,6 +13,7 @@ const ( RetCodeUnauthorized RetCode = 2 RetCodeInsufficientFees RetCode = 3 RetCodeUnknownRequest RetCode = 4 + RetCodeEncodingError RetCode = 5 ) func (r RetCode) Error() error { diff --git a/types/retcode_string.go b/types/retcode_string.go index 17ea7766..f60dca15 100644 --- a/types/retcode_string.go +++ b/types/retcode_string.go @@ -4,9 +4,9 @@ package types import "fmt" -const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequest" +const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingError" -var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92} +var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112} func (i RetCode) String() string { if i < 0 || i+1 >= RetCode(len(_RetCode_index)) { From 3393fc34c28c4a357f59224ab6f8eeabe109b942 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 20 Dec 2015 09:16:05 -0800 Subject: [PATCH 033/545] Use wire.*LengthPrefixed --- cmd/{tmsp/cli.go => tmsp_cli/tmsp_cli.go} | 8 ++++---- example/golang/dummy_test.go | 7 ++++--- server/server.go | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) rename cmd/{tmsp/cli.go => tmsp_cli/tmsp_cli.go} (95%) diff --git a/cmd/tmsp/cli.go b/cmd/tmsp_cli/tmsp_cli.go similarity index 95% rename from cmd/tmsp/cli.go rename to cmd/tmsp_cli/tmsp_cli.go index e8fb7a19..d90dd10b 100644 --- a/cmd/tmsp/cli.go +++ b/cmd/tmsp_cli/tmsp_cli.go @@ -241,27 +241,27 @@ func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { var err error // Write desired request - wire.WriteBinary(req, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(req, conn, &n, &err) if err != nil { return nil, err } // Write flush request - wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) if err != nil { return nil, err } // Read desired response var res types.Response - wire.ReadBinaryPtr(&res, conn, 0, &n, &err) + wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) if err != nil { return nil, err } // Read flush response var resFlush types.ResponseFlush - wire.ReadBinaryPtr(&resFlush, conn, 0, &n, &err) + wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) if err != nil { return nil, err } diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index d8b5b0f6..8e93d7d3 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -35,6 +35,7 @@ func TestStream(t *testing.T) { var n int var err error var res types.Response + wire.ReadVarint(conn, &n, &err) // ignore wire.ReadBinaryPtr(&res, conn, 0, &n, &err) if err != nil { Exit(err.Error()) @@ -71,7 +72,7 @@ func TestStream(t *testing.T) { var n int var err error var req types.Request = types.RequestAppendTx{TxBytes: []byte("test")} - wire.WriteBinary(req, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(req, conn, &n, &err) if err != nil { t.Fatal(err.Error()) } @@ -79,7 +80,7 @@ func TestStream(t *testing.T) { // Sometimes send flush messages if counter%123 == 0 { t.Log("flush") - wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) if err != nil { t.Fatal(err.Error()) } @@ -88,7 +89,7 @@ func TestStream(t *testing.T) { // Send final flush message var n int - wire.WriteBinary(types.RequestFlush{}, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) if err != nil { t.Fatal(err.Error()) } diff --git a/server/server.go b/server/server.go index e5945c81..a9caae95 100644 --- a/server/server.go +++ b/server/server.go @@ -85,7 +85,7 @@ func handleRequests(appC types.AppContext, closeConn chan error, conn net.Conn, var n int var err error var req types.Request - wire.ReadBinaryPtr(&req, bufReader, 0, &n, &err) + wire.ReadBinaryPtrLengthPrefixed(&req, bufReader, 0, &n, &err) if err != nil { if err == io.EOF { closeConn <- fmt.Errorf("Connection closed by client") @@ -146,7 +146,7 @@ func handleResponses(closeConn chan error, responses <-chan types.Response, conn var res = <-responses var n int var err error - wire.WriteBinary(res, bufWriter, &n, &err) + wire.WriteBinaryLengthPrefixed(res, bufWriter, &n, &err) if err != nil { closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return From 2d9abb06cac6ebbc8ec9f30898d4a7763d454cd1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Dec 2015 09:58:27 -0800 Subject: [PATCH 034/545] Conform to new go-wire TypeByte behavior --- example/golang/dummy_test.go | 6 +++--- server/server.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index 8e93d7d3..38b9b3d3 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -72,7 +72,7 @@ func TestStream(t *testing.T) { var n int var err error var req types.Request = types.RequestAppendTx{TxBytes: []byte("test")} - wire.WriteBinaryLengthPrefixed(req, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, conn, &n, &err) if err != nil { t.Fatal(err.Error()) } @@ -80,7 +80,7 @@ func TestStream(t *testing.T) { // Sometimes send flush messages if counter%123 == 0 { t.Log("flush") - wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{types.RequestFlush{}}, conn, &n, &err) if err != nil { t.Fatal(err.Error()) } @@ -89,7 +89,7 @@ func TestStream(t *testing.T) { // Send final flush message var n int - wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{types.RequestFlush{}}, conn, &n, &err) if err != nil { t.Fatal(err.Error()) } diff --git a/server/server.go b/server/server.go index a9caae95..e109c9ac 100644 --- a/server/server.go +++ b/server/server.go @@ -146,7 +146,7 @@ func handleResponses(closeConn chan error, responses <-chan types.Response, conn var res = <-responses var n int var err error - wire.WriteBinaryLengthPrefixed(res, bufWriter, &n, &err) + wire.WriteBinaryLengthPrefixed(struct{ types.Response }{res}, bufWriter, &n, &err) if err != nil { closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return From b7b41094138e47cdbae606543f0d0751848bd6be Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 19 Dec 2015 21:31:53 -0500 Subject: [PATCH 035/545] msg prefix python --- example/python/app.py | 2 +- example/python/tmsp/reader.py | 20 +++++++- example/python/tmsp/server.py | 96 +++++++++++++++++++++++++++++------ 3 files changed, 101 insertions(+), 17 deletions(-) diff --git a/example/python/app.py b/example/python/app.py index a9e9d3b7..2875fcd6 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -41,7 +41,7 @@ class CounterAppContext(): txByteArray = bytearray(txBytes) if len(txBytes) >= 2 and txBytes[:2] == "0x": txByteArray = hex2bytes(txBytes[2:]) - txValue = decode_big_endian(BytesReader(txByteArray), len(txBytes)) + txValue = decode_big_endian(BytesBuffer(txByteArray), len(txBytes)) if txValue != self.txCount: return None, 1 self.txCount += 1 diff --git a/example/python/tmsp/reader.py b/example/python/tmsp/reader.py index f1b3dfae..3b1f87fc 100644 --- a/example/python/tmsp/reader.py +++ b/example/python/tmsp/reader.py @@ -1,14 +1,32 @@ # Simple read() method around a bytearray -class BytesReader(): +class BytesBuffer(): def __init__(self, b): self.buf = b + self.readCount = 0 + + def count(self): + return self.readCount + + def reset_count(self): + self.readCount = 0 + + def size(self): + return len(self.buf) + + def peek(self): + return self.buf[0] + + def write(self, b): + # b should be castable to byte array + self.buf += bytearray(b) def read(self, n): if len(self.buf) < n: print "reader err: buf less than n" # TODO: exception return + self.readCount += n r = self.buf[:n] self.buf = self.buf[n:] return r diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py index e25e4e1f..0beb59d1 100644 --- a/example/python/tmsp/server.py +++ b/example/python/tmsp/server.py @@ -8,11 +8,29 @@ from wire import * from reader import * from msg import * +# hold the asyncronous state of a connection +# ie. we may not get enough bytes on one read to decode the message +class Connection(): + def __init__(self, fd, appCtx): + self.fd = fd + self.appCtx = appCtx + self.recBuf = BytesBuffer(bytearray()) + self.resBuf = BytesBuffer(bytearray()) + self.msgLength = 0 + self.decoder = RequestDecoder(self.recBuf) + self.inProgress = False # are we in the middle of a message + + def recv(this): + data = this.fd.recv(1024) + if not data: # what about len(data) == 0 + raise IOError("dead connection") + this.recBuf.write(data) + # TMSP server responds to messges by calling methods on the app class TMSPServer(): def __init__(self, app, port=5410): self.app = app - self.appMap = {} # map conn file descriptors to (appContext, msgDecoder) + self.appMap = {} # map conn file descriptors to (appContext, reqBuf, resBuf, msgDecoder) self.port = port self.listen_backlog = 10 @@ -31,12 +49,13 @@ class TMSPServer(): def handle_new_connection(self, r): new_fd, new_addr = r.accept() + new_fd.setblocking(0) # non-blocking self.read_list.append(new_fd) self.write_list.append(new_fd) print 'new connection to', new_addr appContext = self.app.open() - self.appMap[new_fd] = (appContext, RequestDecoder(ConnReader(new_fd))) + self.appMap[new_fd] = Connection(new_fd, appContext) def handle_conn_closed(self, r): self.read_list.remove(r) @@ -45,25 +64,63 @@ class TMSPServer(): print "connection closed" def handle_recv(self, r): - appCtx, conn = self.appMap[r] - response = bytearray() +# appCtx, recBuf, resBuf, conn + conn = self.appMap[r] while True: try: - # first read the request type and get the msg decoder - typeByte = conn.reader.read(1) + print "recv loop" + # check if we need more data first + if conn.inProgress: + if conn.msgLength == 0 or conn.recBuf.size() < conn.msgLength: + conn.recv() + else: + if conn.recBuf.size() == 0: + conn.recv() + + conn.inProgress = True + + # see if we have enough to get the message length + if conn.msgLength == 0: + ll = conn.recBuf.peek() + if conn.recBuf.size() < 1 + ll: + # we don't have enough bytes to read the length yet + return + print "decoding msg length" + conn.msgLength = decode_varint(conn.recBuf) + + # see if we have enough to decode the message + if conn.recBuf.size() < conn.msgLength: + return + + # now we can decode the message + + # first read the request type and get the particular msg decoder + typeByte = conn.recBuf.read(1) typeByte = int(typeByte[0]) resTypeByte = typeByte+0x10 req_type = message_types[typeByte] if req_type == "flush": - response += bytearray([resTypeByte]) - sent = r.send(str(response)) + # messages are length prefixed + conn.resBuf.write(encode(1)) + conn.resBuf.write([resTypeByte]) + sent = conn.fd.send(str(conn.resBuf.buf)) + conn.msgLength = 0 + conn.inProgress = False + conn.resBuf = BytesBuffer(bytearray()) return - decoder = getattr(conn, req_type) + decoder = getattr(conn.decoder, req_type) + print "decoding args" req_args = decoder() - req_f = getattr(appCtx, req_type) + print "got args", req_args + + # done decoding message + conn.msgLength = 0 + conn.inProgress = False + + req_f = getattr(conn.appCtx, req_type) if req_args == None: res = req_f() elif isinstance(req_args, tuple): @@ -82,9 +139,18 @@ class TMSPServer(): print "non-zero retcode:", ret_code if req_type in ("echo", "info"): # these dont return a ret code - response += bytearray([resTypeByte]) + encode(res) + enc = encode(res) + # messages are length prefixed + conn.resBuf.write(encode(len(enc) + 1)) + conn.resBuf.write([resTypeByte]) + conn.resBuf.write(enc) else: - response += bytearray([resTypeByte]) + encode(ret_code) + encode(res) + enc, encRet = encode(res), encode(ret_code) + # messages are length prefixed + conn.resBuf.write(encode(len(enc)+len(encRet)+1)) + conn.resBuf.write([resTypeByte]) + conn.resBuf.write(encRet) + conn.resBuf.write(enc) except TypeError as e: print "TypeError on reading from connection:", e self.handle_conn_closed(r) @@ -97,8 +163,8 @@ class TMSPServer(): print "IOError on reading from connection:", e self.handle_conn_closed(r) return - except: - print "error reading from connection", sys.exc_info()[0] # TODO better + except Exception as e: + print "error reading from connection", str(e) # sys.exc_info()[0] # TODO better self.handle_conn_closed(r) return @@ -112,7 +178,7 @@ class TMSPServer(): self.handle_new_connection(r) # undo adding to read list ... - except NameError as e: + except rameError as e: print "Could not connect due to NameError:", e except TypeError as e: print "Could not connect due to TypeError:", e From d560c1d4552b49eff9a014f386783fb903683373 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 18 Dec 2015 20:44:48 -0500 Subject: [PATCH 036/545] example/js --- example/js/app.js | 87 ++++++++++++++++++++++++++++ example/js/msgs.js | 64 +++++++++++++++++++++ example/js/server.js | 130 ++++++++++++++++++++++++++++++++++++++++++ example/js/wire.js | 112 ++++++++++++++++++++++++++++++++++++ tests/test.sh | 4 ++ tests/test_counter.sh | 4 +- 6 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 example/js/app.js create mode 100644 example/js/msgs.js create mode 100644 example/js/server.js create mode 100644 example/js/wire.js diff --git a/example/js/app.js b/example/js/app.js new file mode 100644 index 00000000..0ddd16ad --- /dev/null +++ b/example/js/app.js @@ -0,0 +1,87 @@ +server = require("./server") +wire = require("./wire") +util = require("util") + +function CounterApp(){ + this.hashCount = 0; + this.txCount = 0; + this.commitCount = 0; +}; + +CounterApp.prototype.open = function(){ + return new CounterAppContext(this); +} + +function CounterAppContext(app) { + this.hashCount = app.hashCount; + this.txCount = app.txCount; + this.commitCount = app.commitCount; + this.serial = false; +} + +CounterAppContext.prototype.echo = function(msg){ + return {"response": msg, "ret_code":0} +} + +CounterAppContext.prototype.info = function(){ + return {"response": [util.format("hash, tx, commit counts: %d, %d, %d", this.hashCount, this.txCount, this.commitCount)]} +} + +CounterAppContext.prototype.set_option = function(key, value){ + if (key == "serial" && value == "on"){ + this.serial = true; + } + return {"ret_code":0} +} + +CounterAppContext.prototype.append_tx = function(txBytes){ + if (this.serial) { + txByteArray = txBytes + if (txByte.length >= 2 && txBytes.slice(0, 2) == "0x") { + txByteArray = wire.hex2bytes(txBytes.slice(2)); + } + r = new wire.BytesReader(txByteArray) + txValue = decode_big_endian(r, txBytes.length) + if (txValue != this.txcount){ + return {"ret_code":1} + } + } + this.txCount += 1; + return {"ret_code":0} // TODO: return events +} + +CounterAppContext.prototype.get_hash = function(){ + this.hashCount += 1; + if (this.txCount == 0){ + return {"response": "", "ret_code":0} + } + h = wire.encode_big_endian(this.txCount, 8); + h = wire.reverse(h); // TODO + return {"response": h.toString(), "ret_code":0} +} + +CounterAppContext.prototype.commit = function(){ + this.commitCount += 1; + return {"ret_code":0} +} + +CounterAppContext.prototype.rollback = function(){ + return {"ret_code":0} +} + +CounterAppContext.prototype.add_listener = function(){ + return {"ret_code":0} +} + +CounterAppContext.prototype.rm_listener = function(){ + return {"ret_code":0} +} + +CounterAppContext.prototype.event = function(){ +} + +console.log("Counter app in Javascript") + +var app = new CounterApp(); +var appServer = new server.AppServer(app); +appServer.server.listen(46658) diff --git a/example/js/msgs.js b/example/js/msgs.js new file mode 100644 index 00000000..a8b90ecd --- /dev/null +++ b/example/js/msgs.js @@ -0,0 +1,64 @@ +wire = require("./wire") + +module.exports = { + types : { + 0x01 : "echo", + 0x02 : "flush", + 0x03 : "info", + 0x04 : "set_option", + 0x21 : "append_tx", + 0x22 : "get_hash", + 0x23 : "commit", + 0x24 : "rollback", + 0x25 : "add_listener", + 0x26 : "rm_listener", + }, + + decoder : RequestDecoder, + + buffer: BytesBuffer + +} + +function RequestDecoder(buf){ + this.buf= buf +} + +var decode_string = wire.decode_string + +// return nothing, one thing, or a list of things +RequestDecoder.prototype.echo = function(){ return decode_string(this.buf) }; +RequestDecoder.prototype.flush = function(){}; +RequestDecoder.prototype.info = function(){}; +RequestDecoder.prototype.set_option = function(){ return [decode_string(this.buf), decode_string(this.buf)] }; +RequestDecoder.prototype.append_tx = function(){ return decode_string(this.buf)}; +RequestDecoder.prototype.get_hash = function(){ }; +RequestDecoder.prototype.commit = function(){ }; +RequestDecoder.prototype.rollback = function(){ }; +RequestDecoder.prototype.add_listener = function(){ }; // TODO +RequestDecoder.prototype.rm_listener = function(){ }; // TODO + +// buffered reader with read(n) method +function BytesBuffer(buf){ + this.buf = buf +} + +BytesBuffer.prototype.read = function(n){ + b = this.buf.slice(0, n) + this.buf = this.buf.slice(n) + return b +}; + +BytesBuffer.prototype.write = function(buf){ + this.buf = Buffer.concat([this.buf, buf]); +}; + + +BytesBuffer.prototype.size = function(){ + return this.buf.length +} + +BytesBuffer.prototype.peek = function(){ + return this.buf[0] +} + diff --git a/example/js/server.js b/example/js/server.js new file mode 100644 index 00000000..57af143e --- /dev/null +++ b/example/js/server.js @@ -0,0 +1,130 @@ + +// Load the TCP Library +net = require('net'); +msg = require('./msgs'); +wire = require("./wire") + +// Takes an application and handles tmsp connection +// which invoke methods on the app +function AppServer(app){ + // set the app for the socket handler + this.app = app; + + // create a server by providing callback for + // accepting new connection and callbacks for + // connection events ('data', 'end', etc.) + this.createServer() +} + +module.exports = { AppServer: AppServer }; + +AppServer.prototype.createServer = function(){ + app = this.app + conns = {} // map sockets to their state + + // define the socket handler + this.server = net.createServer(function(socket){ + socket.name = socket.remoteAddress + ":" + socket.remotePort + console.log("new connection from", socket.name) + + appCtx = app.open() + + var conn = { + recBuf: new msg.buffer(new Buffer(0)), + resBuf: new msg.buffer(new Buffer(0)), + msgLength: 0, + inProgress: false + } + conns[socket] = conn + + // Handle tmsp requests. + socket.on('data', function (data) { + + if (data.length == 0){ + // TODO err + console.log("empty data!") + return + } + conn = conns[socket] + + // we received data. append it + conn.recBuf.write(data) + + while ( conn.recBuf.size() > 0 ){ + + if (conn.msgLength == 0){ + ll = conn.recBuf.peek(); + if (conn.recBuf.size() < 1 + ll){ + // don't have enough bytes to read length yet + return + } + conn.msgLength = wire.decode_varint(conn.recBuf) + } + + if (conn.recBuf.size() < conn.msgLength) { + // don't have enough to decode the message + return + } + + // now we can decode + typeByte = conn.recBuf.read(1); + resTypeByte = typeByte[0] + 0x10 + reqType = msg.types[typeByte[0]]; + + if (reqType == "flush"){ + // msgs are length prefixed + conn.resBuf.write(wire.encode(1)); + conn.resBuf.write(new Buffer([resTypeByte])) + n = socket.write(conn.resBuf.buf); + conn.msgLength = 0; + conn.resBuf = new msg.buffer(new Buffer(0)); + return + } + + // decode args + decoder = new msg.decoder(conn.recBuf); + args = decoder[reqType](); + + // done decoding + conn.msgLength = 0 + + // NOTE: this throws of the "this"'s in app.js + //reqFunc = appCtx[reqType]; + var res = function(){ + if (args == null){ + return appCtx[reqType](); + } else if (Array.isArray(args)){ + return appCtx[reqType].apply(this, args); + } else { + return appCtx[reqType](args) + } + }() + + + var retCode = res["ret_code"] + var res = res["response"] + + if (retCode != null && retCode != 0){ + console.log("non-zero ret code", retCode) + } + + + if (reqType == "echo" || reqType == "info"){ + enc = Buffer.concat([new Buffer([resTypeByte]), wire.encode(res)]); + // length prefixed + conn.resBuf.write(wire.encode(enc.length)); + conn.resBuf.write(enc); + } else { + enc = Buffer.concat([new Buffer([resTypeByte]), wire.encode(retCode), wire.encode(res)]); + conn.resBuf.write(wire.encode(enc.length)); + conn.resBuf.write(enc); + } + } + }); + + socket.on('end', function () { + console.log("connection ended") + }); + }) +} + diff --git a/example/js/wire.js b/example/js/wire.js new file mode 100644 index 00000000..87cc9234 --- /dev/null +++ b/example/js/wire.js @@ -0,0 +1,112 @@ +math = require("math") + +module.exports = { + decode_string: decode_string, + decode_varint: decode_varint, + encode_big_endian: encode_big_endian, + encode: encode, + reverse: reverse, +} + +function reverse(buf){ + for (var i = 0; i < buf.length/2; i++){ + a = buf[i]; + b = buf[buf.length-1 - i]; + buf[i] = b; + buf[buf.length-1 - i] = a; + } + return buf +} + +function uvarint_size(i){ + if (i == 0){ + return 0 + } + + for(var j = 1; j < 9; j++) { + if ( i < 1< 0xF0){ negate = true } + if (negate) { size = size - 0xF0 } + i = decode_big_endian(reader, size); + if (negate) { i = i * -1} + return i +} + +function encode_list(l){ + var l2 = l.map(encode); + var buf = new Buffer(encode_varint(l2.length)); + return Buffer.concat([buf, Buffer.concat(l2)]); +} + +function encode(b){ + if (b == null){ + return Buffer(0) + } else if (typeof b == "number"){ + return encode_varint(b) + } else if (typeof b == "string"){ + return encode_string(b) + } else if (Array.isArray(b)){ + return encode_list(b) + } else{ + console.log("UNSUPPORTED TYPE!", typeof b, b) + } +} + + + + + diff --git a/tests/test.sh b/tests/test.sh index 848d14cb..9ee9be13 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -11,3 +11,7 @@ bash tests/test_counter.sh # test python counter cd example/python COUNTER_APP="python app.py" bash $ROOT/tests/test_counter.sh + +# test js counter +cd ../js +COUNTER_APP="node app.js" bash $ROOT/tests/test_counter.sh diff --git a/tests/test_counter.sh b/tests/test_counter.sh index 41909dde..8bbd8d37 100644 --- a/tests/test_counter.sh +++ b/tests/test_counter.sh @@ -11,7 +11,7 @@ $COUNTER_APP &> /dev/null & PID=`echo $!` if [[ "$?" != 0 ]]; then - echo "Error running tmsp command" + echo "Error running tmsp app" echo $OUTPUT exit 1 fi @@ -24,7 +24,7 @@ append_tx abc STDIN` if [[ "$?" != 0 ]]; then - echo "Error running tmsp command" + echo "Error running tmsp batch command" echo $OUTPUT exit 1 fi From dc75b71f55211349fc36d8fe0001a0183fb2ae7a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 21 Dec 2015 18:12:38 -0500 Subject: [PATCH 037/545] tmsp_cli -> tmsp-cli --- cmd/{tmsp_cli => tmsp-cli}/tmsp_cli.go | 0 example/python/app.py | 1 + 2 files changed, 1 insertion(+) rename cmd/{tmsp_cli => tmsp-cli}/tmsp_cli.go (100%) diff --git a/cmd/tmsp_cli/tmsp_cli.go b/cmd/tmsp-cli/tmsp_cli.go similarity index 100% rename from cmd/tmsp_cli/tmsp_cli.go rename to cmd/tmsp-cli/tmsp_cli.go diff --git a/example/python/app.py b/example/python/app.py index 2875fcd6..a439aa74 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -56,6 +56,7 @@ class CounterAppContext(): return str(h), 0 def commit(self): + self.commitCount += 1 return 0 def rollback(self): From 3fb3a81b929c77a16a318d6167c460d8f9a4ba28 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 21 Dec 2015 18:47:14 -0500 Subject: [PATCH 038/545] fix js --- example/js/app.js | 10 +++++----- example/js/server.js | 4 +--- example/js/wire.js | 1 + 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/example/js/app.js b/example/js/app.js index 0ddd16ad..f7def6a0 100644 --- a/example/js/app.js +++ b/example/js/app.js @@ -36,13 +36,13 @@ CounterAppContext.prototype.set_option = function(key, value){ CounterAppContext.prototype.append_tx = function(txBytes){ if (this.serial) { - txByteArray = txBytes - if (txByte.length >= 2 && txBytes.slice(0, 2) == "0x") { + txByteArray = new Buffer(txBytes) + if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { txByteArray = wire.hex2bytes(txBytes.slice(2)); } - r = new wire.BytesReader(txByteArray) - txValue = decode_big_endian(r, txBytes.length) - if (txValue != this.txcount){ + r = new msg.buffer(txByteArray) + txValue = wire.decode_big_endian(r, txBytes.length) + if (txValue != this.txCount){ return {"ret_code":1} } } diff --git a/example/js/server.js b/example/js/server.js index 57af143e..4ca870d9 100644 --- a/example/js/server.js +++ b/example/js/server.js @@ -88,13 +88,11 @@ AppServer.prototype.createServer = function(){ // done decoding conn.msgLength = 0 - // NOTE: this throws of the "this"'s in app.js - //reqFunc = appCtx[reqType]; var res = function(){ if (args == null){ return appCtx[reqType](); } else if (Array.isArray(args)){ - return appCtx[reqType].apply(this, args); + return appCtx[reqType].apply(appCtx, args); } else { return appCtx[reqType](args) } diff --git a/example/js/wire.js b/example/js/wire.js index 87cc9234..13ee5529 100644 --- a/example/js/wire.js +++ b/example/js/wire.js @@ -3,6 +3,7 @@ math = require("math") module.exports = { decode_string: decode_string, decode_varint: decode_varint, + decode_big_endian: decode_big_endian, encode_big_endian: encode_big_endian, encode: encode, reverse: reverse, From 844c4a519de53c02920f9aeac2aac5be32b77fa8 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Dec 2015 16:18:41 -0800 Subject: [PATCH 039/545] Fix tmsp-cli to conform to go-wire new TypeByte behavior; Rename tmsp_cli to tmsp-cli --- cmd/{tmsp_cli/tmsp_cli.go => tmsp-cli/tmsp-cli.go} | 11 ++++++++--- example/golang/dummy_test.go | 3 +-- 2 files changed, 9 insertions(+), 5 deletions(-) rename cmd/{tmsp_cli/tmsp_cli.go => tmsp-cli/tmsp-cli.go} (93%) diff --git a/cmd/tmsp_cli/tmsp_cli.go b/cmd/tmsp-cli/tmsp-cli.go similarity index 93% rename from cmd/tmsp_cli/tmsp_cli.go rename to cmd/tmsp-cli/tmsp-cli.go index d90dd10b..c9684063 100644 --- a/cmd/tmsp_cli/tmsp_cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -3,10 +3,12 @@ package main import ( "bufio" "encoding/hex" + "errors" "fmt" "io" "net" "os" + "reflect" "strings" . "github.com/tendermint/go-common" @@ -241,13 +243,13 @@ func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { var err error // Write desired request - wire.WriteBinaryLengthPrefixed(req, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, conn, &n, &err) if err != nil { return nil, err } // Write flush request - wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{types.RequestFlush{}}, conn, &n, &err) if err != nil { return nil, err } @@ -260,11 +262,14 @@ func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { } // Read flush response - var resFlush types.ResponseFlush + var resFlush types.Response wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) if err != nil { return nil, err } + if _, ok := resFlush.(types.ResponseFlush); !ok { + return nil, errors.New(Fmt("Expected types.ResponseFlush but got %v instead", reflect.TypeOf(resFlush))) + } return res, nil } diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index 38b9b3d3..d0d16ac9 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -35,8 +35,7 @@ func TestStream(t *testing.T) { var n int var err error var res types.Response - wire.ReadVarint(conn, &n, &err) // ignore - wire.ReadBinaryPtr(&res, conn, 0, &n, &err) + wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) if err != nil { Exit(err.Error()) } From cf3b287245b7b1a1365b6c19df47f8bd4375e43a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Dec 2015 16:36:50 -0800 Subject: [PATCH 040/545] Remove spurious tmsp_cli.go --- cmd/tmsp-cli/tmsp_cli.go | 270 --------------------------------------- 1 file changed, 270 deletions(-) delete mode 100644 cmd/tmsp-cli/tmsp_cli.go diff --git a/cmd/tmsp-cli/tmsp_cli.go b/cmd/tmsp-cli/tmsp_cli.go deleted file mode 100644 index d90dd10b..00000000 --- a/cmd/tmsp-cli/tmsp_cli.go +++ /dev/null @@ -1,270 +0,0 @@ -package main - -import ( - "bufio" - "encoding/hex" - "fmt" - "io" - "net" - "os" - "strings" - - . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/types" - - "github.com/codegangsta/cli" -) - -// connection is a global variable so it can be reused by the console -var conn net.Conn - -func main() { - app := cli.NewApp() - app.Name = "cli" - app.Usage = "cli [command] [args...]" - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "address", - Value: "tcp://127.0.0.1:46658", - Usage: "address of application socket", - }, - } - app.Commands = []cli.Command{ - { - Name: "batch", - Usage: "Run a batch of tmsp commands against an application", - Action: func(c *cli.Context) { - cmdBatch(app, c) - }, - }, - { - Name: "console", - Usage: "Start an interactive tmsp console for multiple commands", - Action: func(c *cli.Context) { - cmdConsole(app, c) - }, - }, - { - Name: "echo", - Usage: "Have the application echo a message", - Action: func(c *cli.Context) { - cmdEcho(c) - }, - }, - { - Name: "info", - Usage: "Get some info about the application", - Action: func(c *cli.Context) { - cmdInfo(c) - }, - }, - { - Name: "set_option", - Usage: "Set an option on the application", - Action: func(c *cli.Context) { - cmdSetOption(c) - }, - }, - { - Name: "append_tx", - Usage: "Append a new tx to application", - Action: func(c *cli.Context) { - cmdAppendTx(c) - }, - }, - { - Name: "get_hash", - Usage: "Get application Merkle root hash", - Action: func(c *cli.Context) { - cmdGetHash(c) - }, - }, - { - Name: "commit", - Usage: "Commit the application state", - Action: func(c *cli.Context) { - cmdCommit(c) - }, - }, - { - Name: "rollback", - Usage: "Roll back the application state to the latest commit", - Action: func(c *cli.Context) { - cmdRollback(c) - }, - }, - } - app.Before = before - app.Run(os.Args) - -} - -func before(c *cli.Context) error { - if conn == nil { - var err error - conn, err = Connect(c.GlobalString("address")) - if err != nil { - Exit(err.Error()) - } - } - return nil -} - -//-------------------------------------------------------------------------------- - -func cmdBatch(app *cli.App, c *cli.Context) { - bufReader := bufio.NewReader(os.Stdin) - for { - line, more, err := bufReader.ReadLine() - if more { - Exit("input line is too long") - } else if err == io.EOF { - break - } else if len(line) == 0 { - continue - } else if err != nil { - Exit(err.Error()) - } - args := []string{"tmsp"} - args = append(args, strings.Split(string(line), " ")...) - app.Run(args) - } -} - -func cmdConsole(app *cli.App, c *cli.Context) { - for { - fmt.Printf("> ") - bufReader := bufio.NewReader(os.Stdin) - line, more, err := bufReader.ReadLine() - if more { - Exit("input is too long") - } else if err != nil { - Exit(err.Error()) - } - - args := []string{"tmsp"} - args = append(args, strings.Split(string(line), " ")...) - app.Run(args) - } -} - -// Have the application echo a message -func cmdEcho(c *cli.Context) { - args := c.Args() - if len(args) != 1 { - Exit("echo takes 1 argument") - } - res, err := makeRequest(conn, types.RequestEcho{args[0]}) - if err != nil { - Exit(err.Error()) - } - fmt.Println(res) -} - -// Get some info from the application -func cmdInfo(c *cli.Context) { - res, err := makeRequest(conn, types.RequestInfo{}) - if err != nil { - Exit(err.Error()) - } - fmt.Println(res) -} - -// Set an option on the application -func cmdSetOption(c *cli.Context) { - args := c.Args() - if len(args) != 2 { - Exit("set_option takes 2 arguments (key, value)") - } - _, err := makeRequest(conn, types.RequestSetOption{args[0], args[1]}) - if err != nil { - Exit(err.Error()) - } - fmt.Printf("%s=%s\n", args[0], args[1]) -} - -// Append a new tx to application -func cmdAppendTx(c *cli.Context) { - args := c.Args() - if len(args) != 1 { - Exit("append_tx takes 1 argument") - } - txString := args[0] - tx := []byte(txString) - if len(txString) > 2 && strings.HasPrefix(txString, "0x") { - var err error - tx, err = hex.DecodeString(txString[2:]) - if err != nil { - Exit(err.Error()) - } - } - - res, err := makeRequest(conn, types.RequestAppendTx{tx}) - if err != nil { - Exit(err.Error()) - } - fmt.Println("Response:", res) -} - -// Get application Merkle root hash -func cmdGetHash(c *cli.Context) { - res, err := makeRequest(conn, types.RequestGetHash{}) - if err != nil { - Exit(err.Error()) - } - fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash) -} - -// Commit the application state -func cmdCommit(c *cli.Context) { - _, err := makeRequest(conn, types.RequestCommit{}) - if err != nil { - Exit(err.Error()) - } - fmt.Println("Committed.") -} - -// Roll back the application state to the latest commit -func cmdRollback(c *cli.Context) { - _, err := makeRequest(conn, types.RequestRollback{}) - if err != nil { - Exit(err.Error()) - } - fmt.Println("Rolled back.") -} - -//-------------------------------------------------------------------------------- - -func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { - var n int - var err error - - // Write desired request - wire.WriteBinaryLengthPrefixed(req, conn, &n, &err) - if err != nil { - return nil, err - } - - // Write flush request - wire.WriteBinaryLengthPrefixed(types.RequestFlush{}, conn, &n, &err) - if err != nil { - return nil, err - } - - // Read desired response - var res types.Response - wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) - if err != nil { - return nil, err - } - - // Read flush response - var resFlush types.ResponseFlush - wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) - if err != nil { - return nil, err - } - - return res, nil -} From 20913c5e0e8a4ba1cd020ece0f8766c6b7b146a9 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Dec 2015 17:23:05 -0800 Subject: [PATCH 041/545] Add .pyc to gitignore; Fix js example --- .gitignore | 1 + example/js/wire.js | 8 +++----- example/python/tmsp/wire.py | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 38193138..d2d414be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp *.swo +*.pyc diff --git a/example/js/wire.js b/example/js/wire.js index 13ee5529..42c30867 100644 --- a/example/js/wire.js +++ b/example/js/wire.js @@ -1,5 +1,3 @@ -math = require("math") - module.exports = { decode_string: decode_string, decode_varint: decode_varint, @@ -37,14 +35,14 @@ function encode_big_endian(i, size){ if (size == 0){ return new Buffer(0); } - b = encode_big_endian(math.floor(i/256), size-1); + b = encode_big_endian(Math.floor(i/256), size-1); return Buffer.concat([b, new Buffer([i%256])]); } function decode_big_endian(reader, size){ if (size == 0){ return 0 } firstByte = reader.read(1)[0]; - return firstByte*(math.pow(256, size-1)) + decode_big_endian(reader, size-1) + return firstByte*(Math.pow(256, size-1)) + decode_big_endian(reader, size-1) } function encode_string(s){ @@ -70,7 +68,7 @@ function encode_varint(i){ big_end = encode_big_endian(i, size); if (negate){ size += 0xF0 } - var buf = new Buffer([1]); + var buf = new Buffer([size]); return Buffer.concat([buf, big_end]) } diff --git a/example/python/tmsp/wire.py b/example/python/tmsp/wire.py index fde4e160..1f16855a 100644 --- a/example/python/tmsp/wire.py +++ b/example/python/tmsp/wire.py @@ -25,7 +25,7 @@ def uvarint_size(i): def encode_big_endian(i, size): if size == 0: return bytearray() - return encode_big_endian(i/256, size-1) + bytearray([i%256]) + return encode_big_endian(i/256, size-1) + bytearray([i%256]) def decode_big_endian(reader, size): if size == 0: @@ -36,14 +36,14 @@ def decode_big_endian(reader, size): # ints are max 16 bytes long def encode_varint(i): negate = False - if i < 0: + if i < 0: negate = True i = -i size = uvarint_size(i) if size == 0: return bytearray([0]) big_end = encode_big_endian(i, size) - if negate: + if negate: size += 0xF0 return bytearray([size]) + big_end @@ -57,7 +57,7 @@ def decode_varint(reader): if negate: size = size -0xF0 i = decode_big_endian(reader, size) if negate: i = i*(-1) - return i + return i def encode_string(s): size = encode_varint(len(s)) From da1ef93cefd3993596d91f857ecc9c46a8c4a43c Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Dec 2015 17:41:35 -0800 Subject: [PATCH 042/545] Added link to tendermint.com blog post --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7e17768d..7cb89baf 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ TMSP is an asynchronous protocol: message responses are written back asynchronou *Applications must be deterministic.* +For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/) that explains it all. + ## Message types #### AppendTx From 16e5e4e8c84dacd7320defbe43e16ed51b939525 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 23 Dec 2015 14:11:59 -0800 Subject: [PATCH 043/545] Change license format --- LICENSE.md => LICENSE | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) rename LICENSE.md => LICENSE (93%) diff --git a/LICENSE.md b/LICENSE similarity index 93% rename from LICENSE.md rename to LICENSE index d6456956..3934a10f 100644 --- a/LICENSE.md +++ b/LICENSE @@ -1,7 +1,11 @@ +Tendermint TMSP +Copyright (C) 2015 Tendermint + + Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -176,24 +180,11 @@ END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, From 0c4650f329ae7b124a7820f46d4943d28c81e404 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 1 Jan 2016 18:19:58 -0800 Subject: [PATCH 044/545] Update README.md Added introduction by Zaki --- README.md | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7cb89baf..28233328 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,42 @@ TMSP is an asynchronous protocol: message responses are written back asynchronou *Applications must be deterministic.* -For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/) that explains it all. +For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/). + +## Intro to TMSP + +The Tendermint Socket Protocol (TMSP) and Tendermint Core are a set of tools for building blockchain based databases. Blockchains are a system for creating shared multi-master application state. The Tendermint Core approach is to decouple the consensus engine and P2P layer from the details of the application state of the particular blockchain. + +To draw an analogy, lets talk about a well-known cryptocurrency, Bitcoin. Bitcoin creates a cryptocurrency from a blockchain by having each full node maintain a fully audited Unspent Transaction Output (UTXO) database. If one wanted to create a Bitcoin like system on top of TMSP, Tendermint Core would be responsible for + +- Sharing blocks and transactions between nodes +- Establishing a canonical/immutable order of transactions (the blockchain) + +The Applications developer will be responsible for + +- Maintaining the UTXO database +- Validating cryptographic signatures of transactions +- Preventing transactions from spending non-existent transactions +Allowing clients to query the UTXO database. + +Tendermint is able to decompose the blockchain design by offering a very simple API between the application layer and consensus layer. + +The API consists of 4 primary message types from the consensus engine that the application layer needs to respond to. + +The messages are specified here: +https://github.com/tendermint/tmsp#message-types + +The AppendTx message type is the work horse of the Application. Each transaction from the blockchain is delivered with this message. The developer needs to validate each transactions received with the AppendTx message against the current state, application protocol, and the cryptographic credentials of the transaction. A validated transaction then needs to update the application state — by binding a value into a key values store, or by updating the UTXO database. + +The purpose of the GetHash message is to allow a cryptographic commitment to the current application state to be placed into the next block header. This has some handy properties. Inconsistencies in updating that state will now appear as blockchain forks which catches a whole class of programming errors. This also simplifies the development of secure lightweight clients. + +Finally, in order to recover from faulty proposers (e.g. a malicious validator that proposes two conflicting blocks), the application must be able to roll back transactions. The Commit message tells the application to create a checkpoint, and the Rollback message to unwind the state back to that checkpoint. + +There can be multiple TMSP socket connections to an application. Each connection has an isolated “view†of the application state, but Commit/Rollback work across connections. Application developers can store the application state in an immutable data structure (such as Tendermint’s Go-Merkle library) to make this easy to develop. + +NOTE: Tendermint Core creates two TMSP connections to the application; one for the validation of transactions when broadcasting in the mempool layer, and another for the consensus engine to run block proposals. A commit on one connection followed by a rollback on the other syncs both views. + +It's probably evident that applications designers need to very carefully design their message handlers to create a blockchain that does anything useful but this architecture provides a place to start. ## Message types @@ -75,3 +110,6 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. +## Contributions + +* Thanks to Zaki Manian for the introductory text. From 1b7243a9909b86dc668f374fd68b17a405740bc4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 1 Jan 2016 19:09:03 -0800 Subject: [PATCH 045/545] Update README to point to blog post only --- README.md | 49 +++---------------------------------------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 28233328..786ab6fa 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,11 @@ # Tendermint Socket Protocol (TMSP) -**TMSP** is a socket protocol enabling a consensus engine, running in one process, -to manage an application state, running in another. -Thus the applications can be written in any programming language. - -TMSP is an asynchronous protocol: message responses are written back asynchronously to the platform. - -*Applications must be deterministic.* +Blockchains are a system for creating shared multi-master application state. +**TMSP** is a socket protocol enabling a blockchain consensus engine, running in one process, +to manage a blockchain application state, running in another. For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/). -## Intro to TMSP - -The Tendermint Socket Protocol (TMSP) and Tendermint Core are a set of tools for building blockchain based databases. Blockchains are a system for creating shared multi-master application state. The Tendermint Core approach is to decouple the consensus engine and P2P layer from the details of the application state of the particular blockchain. - -To draw an analogy, lets talk about a well-known cryptocurrency, Bitcoin. Bitcoin creates a cryptocurrency from a blockchain by having each full node maintain a fully audited Unspent Transaction Output (UTXO) database. If one wanted to create a Bitcoin like system on top of TMSP, Tendermint Core would be responsible for - -- Sharing blocks and transactions between nodes -- Establishing a canonical/immutable order of transactions (the blockchain) - -The Applications developer will be responsible for - -- Maintaining the UTXO database -- Validating cryptographic signatures of transactions -- Preventing transactions from spending non-existent transactions -Allowing clients to query the UTXO database. - -Tendermint is able to decompose the blockchain design by offering a very simple API between the application layer and consensus layer. - -The API consists of 4 primary message types from the consensus engine that the application layer needs to respond to. - -The messages are specified here: -https://github.com/tendermint/tmsp#message-types - -The AppendTx message type is the work horse of the Application. Each transaction from the blockchain is delivered with this message. The developer needs to validate each transactions received with the AppendTx message against the current state, application protocol, and the cryptographic credentials of the transaction. A validated transaction then needs to update the application state — by binding a value into a key values store, or by updating the UTXO database. - -The purpose of the GetHash message is to allow a cryptographic commitment to the current application state to be placed into the next block header. This has some handy properties. Inconsistencies in updating that state will now appear as blockchain forks which catches a whole class of programming errors. This also simplifies the development of secure lightweight clients. - -Finally, in order to recover from faulty proposers (e.g. a malicious validator that proposes two conflicting blocks), the application must be able to roll back transactions. The Commit message tells the application to create a checkpoint, and the Rollback message to unwind the state back to that checkpoint. - -There can be multiple TMSP socket connections to an application. Each connection has an isolated “view†of the application state, but Commit/Rollback work across connections. Application developers can store the application state in an immutable data structure (such as Tendermint’s Go-Merkle library) to make this easy to develop. - -NOTE: Tendermint Core creates two TMSP connections to the application; one for the validation of transactions when broadcasting in the mempool layer, and another for the consensus engine to run block proposals. A commit on one connection followed by a rollback on the other syncs both views. - -It's probably evident that applications designers need to very carefully design their message handlers to create a blockchain that does anything useful but this architecture provides a place to start. - ## Message types #### AppendTx @@ -109,7 +70,3 @@ It's probably evident that applications designers need to very carefully design * __Usage__:
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. - -## Contributions - -* Thanks to Zaki Manian for the introductory text. From 06b48fe99fe0aa5c3297f10b5e45be70d849afd5 Mon Sep 17 00:00:00 2001 From: tim watts Date: Sun, 3 Jan 2016 16:35:23 +0000 Subject: [PATCH 046/545] pep8 style fixes --- example/python/app.py | 115 +++++++------- example/python/tmsp/__init__.py | 0 example/python/tmsp/msg.py | 73 ++++----- example/python/tmsp/reader.py | 80 +++++----- example/python/tmsp/server.py | 266 ++++++++++++++++---------------- example/python/tmsp/wire.py | 151 +++++++++--------- 6 files changed, 357 insertions(+), 328 deletions(-) create mode 100644 example/python/tmsp/__init__.py diff --git a/example/python/app.py b/example/python/app.py index a439aa74..caed1783 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -1,82 +1,85 @@ - import sys -sys.path.insert(0, './tmsp') -from wire import * -from server import * +from wire import hex2bytes, decode_big_endian, encode_big_endian +from server import TMSPServer +from reader import BytesBuffer -# tmsp application interface - class CounterApplication(): + def __init__(self): self.hashCount = 0 - self.txCount = 0 - self.commitCount = 0 + self.txCount = 0 + self.commitCount = 0 def open(self): - return CounterAppContext(self) + return CounterAppContext(self) + class CounterAppContext(): - def __init__(self, app): - self.app = app - self.hashCount = app.hashCount - self.txCount = app.txCount - self.commitCount = app.commitCount - self.serial = False - - def echo(self, msg): - return msg, 0 - def info(self): - return ["hash, tx, commit counts:%d, %d, %d"%(self.hashCount, self.txCount, self.commitCount)], 0 + def __init__(self, app): + self.app = app + self.hashCount = app.hashCount + self.txCount = app.txCount + self.commitCount = app.commitCount + self.serial = False - def set_option(self, key, value): - if key == "serial" and value == "on": - self.serial = True - return 0 + def echo(self, msg): + return msg, 0 - def append_tx(self, txBytes): - if self.serial: - txByteArray = bytearray(txBytes) - if len(txBytes) >= 2 and txBytes[:2] == "0x": - txByteArray = hex2bytes(txBytes[2:]) - txValue = decode_big_endian(BytesBuffer(txByteArray), len(txBytes)) - if txValue != self.txCount: - return None, 1 - self.txCount += 1 - return None, 0 + def info(self): + return ["hash, tx, commit counts:%d, %d, %d" % (self.hashCount, + self.txCount, + self.commitCount)], 0 - def get_hash(self): - self.hashCount += 1 - if self.txCount == 0: - return "", 0 - h = encode_big_endian(self.txCount, 8) - h.reverse() - return str(h), 0 + def set_option(self, key, value): + if key == "serial" and value == "on": + self.serial = True + return 0 - def commit(self): - self.commitCount += 1 - return 0 + def append_tx(self, txBytes): + if self.serial: + txByteArray = bytearray(txBytes) + if len(txBytes) >= 2 and txBytes[:2] == "0x": + txByteArray = hex2bytes(txBytes[2:]) + txValue = decode_big_endian( + BytesBuffer(txByteArray), len(txBytes)) + if txValue != self.txCount: + return None, 1 + self.txCount += 1 + return None, 0 - def rollback(self): - return 0 + def get_hash(self): + self.hashCount += 1 + if self.txCount == 0: + return "", 0 + h = encode_big_endian(self.txCount, 8) + h.reverse() + return str(h), 0 - def add_listener(self): - return 0 + def commit(self): + self.commitCount += 1 + return 0 - def rm_listener(self): - return 0 + def rollback(self): + return 0 + + def add_listener(self): + return 0 + + def rm_listener(self): + return 0 + + def event(self): + return - def event(self): - return - if __name__ == '__main__': l = len(sys.argv) if l == 1: - port = 46658 - elif l == 2: + port = 46658 + elif l == 2: port = int(sys.argv[1]) else: print "too many arguments" @@ -84,6 +87,6 @@ if __name__ == '__main__': print 'TMSP Demo APP (Python)' - app = CounterApplication() + app = CounterApplication() server = TMSPServer(app, port) server.main_loop() diff --git a/example/python/tmsp/__init__.py b/example/python/tmsp/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example/python/tmsp/msg.py b/example/python/tmsp/msg.py index a99386a3..f9339fe9 100644 --- a/example/python/tmsp/msg.py +++ b/example/python/tmsp/msg.py @@ -1,54 +1,55 @@ -from wire import * +from wire import decode_string # map type_byte to message name message_types = { -0x01 : "echo", -0x02 : "flush", -0x03 : "info", -0x04 : "set_option", -0x21 : "append_tx", -0x22 : "get_hash", -0x23 : "commit", -0x24 : "rollback", -0x25 : "add_listener", -0x26 : "rm_listener", + 0x01: "echo", + 0x02: "flush", + 0x03: "info", + 0x04: "set_option", + 0x21: "append_tx", + 0x22: "get_hash", + 0x23: "commit", + 0x24: "rollback", + 0x25: "add_listener", + 0x26: "rm_listener", } # return the decoded arguments of tmsp messages + + class RequestDecoder(): - def __init__(self, reader): - self.reader = reader - def echo(self): - return decode_string(self.reader) + def __init__(self, reader): + self.reader = reader - def flush(self): - return + def echo(self): + return decode_string(self.reader) - def info(self): - return + def flush(self): + return - def set_option(self): - return decode_string(self.reader), decode_string(self.reader) + def info(self): + return - def append_tx(self): - return decode_string(self.reader) + def set_option(self): + return decode_string(self.reader), decode_string(self.reader) - def get_hash(self): - return + def append_tx(self): + return decode_string(self.reader) - def commit(self): - return + def get_hash(self): + return - def rollback(self): - return + def commit(self): + return - def add_listener(self): - # TODO - return - - def rm_listener(self): - # TODO - return + def rollback(self): + return + def add_listener(self): + # TODO + return + def rm_listener(self): + # TODO + return diff --git a/example/python/tmsp/reader.py b/example/python/tmsp/reader.py index 3b1f87fc..6c0dad94 100644 --- a/example/python/tmsp/reader.py +++ b/example/python/tmsp/reader.py @@ -1,50 +1,56 @@ # Simple read() method around a bytearray + + class BytesBuffer(): - def __init__(self, b): - self.buf = b - self.readCount = 0 - def count(self): - return self.readCount + def __init__(self, b): + self.buf = b + self.readCount = 0 - def reset_count(self): - self.readCount = 0 - - def size(self): - return len(self.buf) + def count(self): + return self.readCount - def peek(self): - return self.buf[0] + def reset_count(self): + self.readCount = 0 - def write(self, b): - # b should be castable to byte array - self.buf += bytearray(b) + def size(self): + return len(self.buf) - def read(self, n): - if len(self.buf) < n: - print "reader err: buf less than n" - # TODO: exception - return - self.readCount += n - r = self.buf[:n] - self.buf = self.buf[n:] - return r + def peek(self): + return self.buf[0] + + def write(self, b): + # b should be castable to byte array + self.buf += bytearray(b) + + def read(self, n): + if len(self.buf) < n: + print "reader err: buf less than n" + # TODO: exception + return + self.readCount += n + r = self.buf[:n] + self.buf = self.buf[n:] + return r # Buffer bytes off a tcp connection and read them off in chunks + + class ConnReader(): - def __init__(self, conn): - self.conn = conn - self.buf = bytearray() - # blocking - def read(self, n): - while n > len(self.buf): - moreBuf = self.conn.recv(1024) - if not moreBuf: - raise IOError("dead connection") - self.buf = self.buf + bytearray(moreBuf) + def __init__(self, conn): + self.conn = conn + self.buf = bytearray() - r = self.buf[:n] - self.buf = self.buf[n:] - return r + # blocking + def read(self, n): + while n > len(self.buf): + moreBuf = self.conn.recv(1024) + if not moreBuf: + raise IOError("dead connection") + self.buf = self.buf + bytearray(moreBuf) + + r = self.buf[:n] + self.buf = self.buf[n:] + return r diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py index 0beb59d1..eeb974b8 100644 --- a/example/python/tmsp/server.py +++ b/example/python/tmsp/server.py @@ -1,38 +1,44 @@ import socket import select import sys -import os -from wire import * -from reader import * -from msg import * +from wire import decode_varint, encode +from reader import BytesBuffer +from msg import RequestDecoder, message_types # hold the asyncronous state of a connection # ie. we may not get enough bytes on one read to decode the message + + class Connection(): - def __init__(self, fd, appCtx): - self.fd = fd - self.appCtx = appCtx - self.recBuf = BytesBuffer(bytearray()) - self.resBuf = BytesBuffer(bytearray()) - self.msgLength = 0 - self.decoder = RequestDecoder(self.recBuf) - self.inProgress = False # are we in the middle of a message - - def recv(this): - data = this.fd.recv(1024) - if not data: # what about len(data) == 0 - raise IOError("dead connection") - this.recBuf.write(data) + + def __init__(self, fd, appCtx): + self.fd = fd + self.appCtx = appCtx + self.recBuf = BytesBuffer(bytearray()) + self.resBuf = BytesBuffer(bytearray()) + self.msgLength = 0 + self.decoder = RequestDecoder(self.recBuf) + self.inProgress = False # are we in the middle of a message + + def recv(this): + data = this.fd.recv(1024) + if not data: # what about len(data) == 0 + raise IOError("dead connection") + this.recBuf.write(data) # TMSP server responds to messges by calling methods on the app -class TMSPServer(): - def __init__(self, app, port=5410): - self.app = app - self.appMap = {} # map conn file descriptors to (appContext, reqBuf, resBuf, msgDecoder) - self.port = port + +class TMSPServer(): + + def __init__(self, app, port=5410): + self.app = app + # map conn file descriptors to (appContext, reqBuf, resBuf, msgDecoder) + self.appMap = {} + + self.port = port self.listen_backlog = 10 self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -49,13 +55,13 @@ class TMSPServer(): def handle_new_connection(self, r): new_fd, new_addr = r.accept() - new_fd.setblocking(0) # non-blocking + new_fd.setblocking(0) # non-blocking self.read_list.append(new_fd) self.write_list.append(new_fd) print 'new connection to', new_addr - appContext = self.app.open() - self.appMap[new_fd] = Connection(new_fd, appContext) + appContext = self.app.open() + self.appMap[new_fd] = Connection(new_fd, appContext) def handle_conn_closed(self, r): self.read_list.remove(r) @@ -64,137 +70,137 @@ class TMSPServer(): print "connection closed" def handle_recv(self, r): -# appCtx, recBuf, resBuf, conn - conn = self.appMap[r] - while True: - try: - print "recv loop" - # check if we need more data first - if conn.inProgress: - if conn.msgLength == 0 or conn.recBuf.size() < conn.msgLength: - conn.recv() - else: - if conn.recBuf.size() == 0: - conn.recv() + # appCtx, recBuf, resBuf, conn + conn = self.appMap[r] + while True: + try: + print "recv loop" + # check if we need more data first + if conn.inProgress: + if (conn.msgLength == 0 or conn.recBuf.size() < conn.msgLength): + conn.recv() + else: + if conn.recBuf.size() == 0: + conn.recv() - conn.inProgress = True + conn.inProgress = True - # see if we have enough to get the message length - if conn.msgLength == 0: - ll = conn.recBuf.peek() - if conn.recBuf.size() < 1 + ll: - # we don't have enough bytes to read the length yet - return - print "decoding msg length" - conn.msgLength = decode_varint(conn.recBuf) + # see if we have enough to get the message length + if conn.msgLength == 0: + ll = conn.recBuf.peek() + if conn.recBuf.size() < 1 + ll: + # we don't have enough bytes to read the length yet + return + print "decoding msg length" + conn.msgLength = decode_varint(conn.recBuf) - # see if we have enough to decode the message - if conn.recBuf.size() < conn.msgLength: - return + # see if we have enough to decode the message + if conn.recBuf.size() < conn.msgLength: + return - # now we can decode the message + # now we can decode the message - # first read the request type and get the particular msg decoder - typeByte = conn.recBuf.read(1) - typeByte = int(typeByte[0]) - resTypeByte = typeByte+0x10 - req_type = message_types[typeByte] + # first read the request type and get the particular msg + # decoder + typeByte = conn.recBuf.read(1) + typeByte = int(typeByte[0]) + resTypeByte = typeByte + 0x10 + req_type = message_types[typeByte] - if req_type == "flush": - # messages are length prefixed - conn.resBuf.write(encode(1)) - conn.resBuf.write([resTypeByte]) - sent = conn.fd.send(str(conn.resBuf.buf)) - conn.msgLength = 0 - conn.inProgress = False - conn.resBuf = BytesBuffer(bytearray()) - return + if req_type == "flush": + # messages are length prefixed + conn.resBuf.write(encode(1)) + conn.resBuf.write([resTypeByte]) + conn.msgLength = 0 + conn.inProgress = False + conn.resBuf = BytesBuffer(bytearray()) + return - decoder = getattr(conn.decoder, req_type) + decoder = getattr(conn.decoder, req_type) - print "decoding args" - req_args = decoder() - print "got args", req_args + print "decoding args" + req_args = decoder() + print "got args", req_args - # done decoding message - conn.msgLength = 0 - conn.inProgress = False + # done decoding message + conn.msgLength = 0 + conn.inProgress = False - req_f = getattr(conn.appCtx, req_type) - if req_args == None: - res = req_f() - elif isinstance(req_args, tuple): - res = req_f(*req_args) - else: - res = req_f(req_args) + req_f = getattr(conn.appCtx, req_type) + if req_args is None: + res = req_f() + elif isinstance(req_args, tuple): + res = req_f(*req_args) + else: + res = req_f(req_args) - if isinstance(res, tuple): - res, ret_code = res - else: - ret_code = res - res = None + if isinstance(res, tuple): + res, ret_code = res + else: + ret_code = res + res = None - print "called", req_type, "ret code:", ret_code - if ret_code != 0: - print "non-zero retcode:", ret_code + print "called", req_type, "ret code:", ret_code + if ret_code != 0: + print "non-zero retcode:", ret_code - if req_type in ("echo", "info"): # these dont return a ret code - enc = encode(res) - # messages are length prefixed - conn.resBuf.write(encode(len(enc) + 1)) - conn.resBuf.write([resTypeByte]) - conn.resBuf.write(enc) - else: - enc, encRet = encode(res), encode(ret_code) - # messages are length prefixed - conn.resBuf.write(encode(len(enc)+len(encRet)+1)) - conn.resBuf.write([resTypeByte]) - conn.resBuf.write(encRet) - conn.resBuf.write(enc) - except TypeError as e: - print "TypeError on reading from connection:", e - self.handle_conn_closed(r) - return - except ValueError as e: - print "ValueError on reading from connection:", e - self.handle_conn_closed(r) - return - except IOError as e: - print "IOError on reading from connection:", e - self.handle_conn_closed(r) - return - except Exception as e: - print "error reading from connection", str(e) # sys.exc_info()[0] # TODO better - self.handle_conn_closed(r) - return + if req_type in ("echo", "info"): # these dont return a ret code + enc = encode(res) + # messages are length prefixed + conn.resBuf.write(encode(len(enc) + 1)) + conn.resBuf.write([resTypeByte]) + conn.resBuf.write(enc) + else: + enc, encRet = encode(res), encode(ret_code) + # messages are length prefixed + conn.resBuf.write(encode(len(enc) + len(encRet) + 1)) + conn.resBuf.write([resTypeByte]) + conn.resBuf.write(encRet) + conn.resBuf.write(enc) + except TypeError as e: + print "TypeError on reading from connection:", e + self.handle_conn_closed(r) + return + except ValueError as e: + print "ValueError on reading from connection:", e + self.handle_conn_closed(r) + return + except IOError as e: + print "IOError on reading from connection:", e + self.handle_conn_closed(r) + return + except Exception as e: + # sys.exc_info()[0] # TODO better + print "error reading from connection", str(e) + self.handle_conn_closed(r) + return def main_loop(self): while not self.shutdown: - r_list, w_list, _ = select.select(self.read_list, self.write_list, [], 2.5) + r_list, w_list, _ = select.select( + self.read_list, self.write_list, [], 2.5) for r in r_list: - if (r == self.listener): + if (r == self.listener): try: self.handle_new_connection(r) - # undo adding to read list ... - except rameError as e: - print "Could not connect due to NameError:", e - except TypeError as e: - print "Could not connect due to TypeError:", e - except: - print "Could not connect due to unexpected error:", sys.exc_info()[0] - else: + # undo adding to read list ... + except NameError as e: + print "Could not connect due to NameError:", e + except TypeError as e: + print "Could not connect due to TypeError:", e + except: + print "Could not connect due to unexpected error:", sys.exc_info()[0] + else: self.handle_recv(r) - - def handle_shutdown(self): for r in self.read_list: r.close() for w in self.write_list: try: w.close() - except: pass + except: + pass self.shutdown = True - diff --git a/example/python/tmsp/wire.py b/example/python/tmsp/wire.py index 1f16855a..1a07e89f 100644 --- a/example/python/tmsp/wire.py +++ b/example/python/tmsp/wire.py @@ -2,101 +2,114 @@ # the decoder works off a reader # the encoder returns bytearray + def hex2bytes(h): - return bytearray(h.decode('hex')) + return bytearray(h.decode('hex')) + def bytes2hex(b): - if type(b) in (str, unicode): - return "".join([hex(ord(c))[2:].zfill(2) for c in b]) - else: - return bytes2hex(b.decode()) + if type(b) in (str, unicode): + return "".join([hex(ord(c))[2:].zfill(2) for c in b]) + else: + return bytes2hex(b.decode()) # expects uvarint64 (no crazy big nums!) def uvarint_size(i): - if i == 0: - return 0 - for j in xrange(1, 8): - if i < 1< int(0xF0) else False - if negate: size = size -0xF0 - i = decode_big_endian(reader, size) - if negate: i = i*(-1) - return i - + +def decode_varint(reader): + size = reader.read(1)[0] + if size == 0: + return 0 + + negate = True if size > int(0xF0) else False + if negate: + size = size - 0xF0 + i = decode_big_endian(reader, size) + if negate: + i = i * (-1) + return i + + def encode_string(s): - size = encode_varint(len(s)) - return size + bytearray(s) + size = encode_varint(len(s)) + return size + bytearray(s) + def decode_string(reader): - length = decode_varint(reader) - return str(reader.read(length)) + length = decode_varint(reader) + return str(reader.read(length)) + def encode_list(s): - b = bytearray() - map(b.extend, map(encode, s)) - return encode_varint(len(s)) + b + b = bytearray() + map(b.extend, map(encode, s)) + return encode_varint(len(s)) + b + def encode(s): - if s == None: - return bytearray() - if isinstance(s, int): - return encode_varint(s) - elif isinstance(s, str): - return encode_string(s) - elif isinstance(s, list): - return encode_list(s) - else: - print "UNSUPPORTED TYPE!", type(s), s + if s is None: + return bytearray() + if isinstance(s, int): + return encode_varint(s) + elif isinstance(s, str): + return encode_string(s) + elif isinstance(s, list): + return encode_list(s) + else: + print "UNSUPPORTED TYPE!", type(s), s -import binascii - if __name__ == '__main__': - ns = [100,100,1000,256] - ss = [2,5,5,2] - bs = map(encode_big_endian, ns,ss) - ds = map(decode_big_endian, bs,ss) - print ns - print [i[0] for i in ds] + ns = [100, 100, 1000, 256] + ss = [2, 5, 5, 2] + bs = map(encode_big_endian, ns, ss) + ds = map(decode_big_endian, bs, ss) + print ns + print [i[0] for i in ds] - ss = ["abc", "hi there jim", "ok now what"] - e = map(encode_string, ss) - d = map(decode_string, e) - print ss - print [i[0] for i in d] + ss = ["abc", "hi there jim", "ok now what"] + e = map(encode_string, ss) + d = map(decode_string, e) + print ss + print [i[0] for i in d] From 8267f2ba4a860dd41598a87d2b819c461d87ac61 Mon Sep 17 00:00:00 2001 From: tim watts Date: Sun, 3 Jan 2016 16:42:58 +0000 Subject: [PATCH 047/545] Fix except/pass --- example/python/tmsp/server.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py index eeb974b8..91d87e5e 100644 --- a/example/python/tmsp/server.py +++ b/example/python/tmsp/server.py @@ -184,7 +184,6 @@ class TMSPServer(): if (r == self.listener): try: self.handle_new_connection(r) - # undo adding to read list ... except NameError as e: print "Could not connect due to NameError:", e @@ -201,6 +200,6 @@ class TMSPServer(): for w in self.write_list: try: w.close() - except: - pass + except Exception as e: + print(e) # TODO: add logging self.shutdown = True From 65a01564125ca1ba64b9566d81961be744f6774c Mon Sep 17 00:00:00 2001 From: tim watts Date: Tue, 5 Jan 2016 21:49:21 +0000 Subject: [PATCH 048/545] python3 example --- example/python3/app.py | 92 ++++++++++++++ example/python3/tmsp/__init__.py | 0 example/python3/tmsp/msg.py | 55 +++++++++ example/python3/tmsp/reader.py | 56 +++++++++ example/python3/tmsp/server.py | 201 +++++++++++++++++++++++++++++++ example/python3/tmsp/wire.py | 119 ++++++++++++++++++ 6 files changed, 523 insertions(+) create mode 100644 example/python3/app.py create mode 100644 example/python3/tmsp/__init__.py create mode 100644 example/python3/tmsp/msg.py create mode 100644 example/python3/tmsp/reader.py create mode 100644 example/python3/tmsp/server.py create mode 100644 example/python3/tmsp/wire.py diff --git a/example/python3/app.py b/example/python3/app.py new file mode 100644 index 00000000..547f73d8 --- /dev/null +++ b/example/python3/app.py @@ -0,0 +1,92 @@ +import sys + +from tmsp.wire import hex2bytes, decode_big_endian, encode_big_endian +from tmsp.server import TMSPServer +from tmsp.reader import BytesBuffer + + +class CounterApplication(): + + def __init__(self): + self.hashCount = 0 + self.txCount = 0 + self.commitCount = 0 + + def open(self): + return CounterAppContext(self) + + +class CounterAppContext(): + + def __init__(self, app): + self.app = app + self.hashCount = app.hashCount + self.txCount = app.txCount + self.commitCount = app.commitCount + self.serial = False + + def echo(self, msg): + return msg, 0 + + def info(self): + return ["hash, tx, commit counts:%d, %d, %d" % (self.hashCount, + self.txCount, + self.commitCount)], 0 + + def set_option(self, key, value): + if key == "serial" and value == "on": + self.serial = True + return 0 + + def append_tx(self, txBytes): + if self.serial: + txByteArray = bytearray(txBytes) + if len(txBytes) >= 2 and txBytes[:2] == "0x": + txByteArray = hex2bytes(txBytes[2:]) + txValue = decode_big_endian( + BytesBuffer(txByteArray), len(txBytes)) + if txValue != self.txCount: + return None, 1 + self.txCount += 1 + return None, 0 + + def get_hash(self): + self.hashCount += 1 + if self.txCount == 0: + return "", 0 + h = encode_big_endian(self.txCount, 8) + h.reverse() + return str(h), 0 + + def commit(self): + self.commitCount += 1 + return 0 + + def rollback(self): + return 0 + + def add_listener(self): + return 0 + + def rm_listener(self): + return 0 + + def event(self): + return + + +if __name__ == '__main__': + l = len(sys.argv) + if l == 1: + port = 46658 + elif l == 2: + port = int(sys.argv[1]) + else: + print("too many arguments") + quit() + + print('TMSP Demo APP (Python)') + + app = CounterApplication() + server = TMSPServer(app, port) + server.main_loop() diff --git a/example/python3/tmsp/__init__.py b/example/python3/tmsp/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example/python3/tmsp/msg.py b/example/python3/tmsp/msg.py new file mode 100644 index 00000000..daa0cc9d --- /dev/null +++ b/example/python3/tmsp/msg.py @@ -0,0 +1,55 @@ +from .wire import decode_string + +# map type_byte to message name +message_types = { + 0x01: "echo", + 0x02: "flush", + 0x03: "info", + 0x04: "set_option", + 0x21: "append_tx", + 0x22: "get_hash", + 0x23: "commit", + 0x24: "rollback", + 0x25: "add_listener", + 0x26: "rm_listener", +} + +# return the decoded arguments of tmsp messages + + +class RequestDecoder(): + + def __init__(self, reader): + self.reader = reader + + def echo(self): + return decode_string(self.reader) + + def flush(self): + return + + def info(self): + return + + def set_option(self): + return decode_string(self.reader), decode_string(self.reader) + + def append_tx(self): + return decode_string(self.reader) + + def get_hash(self): + return + + def commit(self): + return + + def rollback(self): + return + + def add_listener(self): + # TODO + return + + def rm_listener(self): + # TODO + return diff --git a/example/python3/tmsp/reader.py b/example/python3/tmsp/reader.py new file mode 100644 index 00000000..c016ac60 --- /dev/null +++ b/example/python3/tmsp/reader.py @@ -0,0 +1,56 @@ + +# Simple read() method around a bytearray + + +class BytesBuffer(): + + def __init__(self, b): + self.buf = b + self.readCount = 0 + + def count(self): + return self.readCount + + def reset_count(self): + self.readCount = 0 + + def size(self): + return len(self.buf) + + def peek(self): + return self.buf[0] + + def write(self, b): + # b should be castable to byte array + self.buf += bytearray(b) + + def read(self, n): + if len(self.buf) < n: + print("reader err: buf less than n") + # TODO: exception + return + self.readCount += n + r = self.buf[:n] + self.buf = self.buf[n:] + return r + +# Buffer bytes off a tcp connection and read them off in chunks + + +class ConnReader(): + + def __init__(self, conn): + self.conn = conn + self.buf = bytearray() + + # blocking + def read(self, n): + while n > len(self.buf): + moreBuf = self.conn.recv(1024) + if not moreBuf: + raise IOError("dead connection") + self.buf = self.buf + bytearray(moreBuf) + + r = self.buf[:n] + self.buf = self.buf[n:] + return r diff --git a/example/python3/tmsp/server.py b/example/python3/tmsp/server.py new file mode 100644 index 00000000..0034b600 --- /dev/null +++ b/example/python3/tmsp/server.py @@ -0,0 +1,201 @@ +import socket +import select +import sys +import logging + +from .wire import decode_varint, encode +from .reader import BytesBuffer +from .msg import RequestDecoder, message_types + +# hold the asyncronous state of a connection +# ie. we may not get enough bytes on one read to decode the message + +logger = logging.getLogger(__name__) + + +class Connection(): + + def __init__(self, fd, appCtx): + self.fd = fd + self.appCtx = appCtx + self.recBuf = BytesBuffer(bytearray()) + self.resBuf = BytesBuffer(bytearray()) + self.msgLength = 0 + self.decoder = RequestDecoder(self.recBuf) + self.inProgress = False # are we in the middle of a message + + def recv(this): + data = this.fd.recv(1024) + if not data: # what about len(data) == 0 + raise IOError("dead connection") + this.recBuf.write(data) + +# TMSP server responds to messges by calling methods on the app + + +class TMSPServer(): + + def __init__(self, app, port=5410): + self.app = app + # map conn file descriptors to (appContext, reqBuf, resBuf, msgDecoder) + self.appMap = {} + + self.port = port + self.listen_backlog = 10 + + self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.listener.setblocking(0) + self.listener.bind(('', port)) + + self.listener.listen(self.listen_backlog) + + self.shutdown = False + + self.read_list = [self.listener] + self.write_list = [] + + def handle_new_connection(self, r): + new_fd, new_addr = r.accept() + new_fd.setblocking(0) # non-blocking + self.read_list.append(new_fd) + self.write_list.append(new_fd) + print('new connection to', new_addr) + + appContext = self.app.open() + self.appMap[new_fd] = Connection(new_fd, appContext) + + def handle_conn_closed(self, r): + self.read_list.remove(r) + self.write_list.remove(r) + r.close() + print("connection closed") + + def handle_recv(self, r): + # appCtx, recBuf, resBuf, conn + conn = self.appMap[r] + while True: + try: + print("recv loop") + # check if we need more data first + if conn.inProgress: + if (conn.msgLength == 0 or conn.recBuf.size() < conn.msgLength): + conn.recv() + else: + if conn.recBuf.size() == 0: + conn.recv() + + conn.inProgress = True + + # see if we have enough to get the message length + if conn.msgLength == 0: + ll = conn.recBuf.peek() + if conn.recBuf.size() < 1 + ll: + # we don't have enough bytes to read the length yet + return + print("decoding msg length") + conn.msgLength = decode_varint(conn.recBuf) + + # see if we have enough to decode the message + if conn.recBuf.size() < conn.msgLength: + return + + # now we can decode the message + + # first read the request type and get the particular msg + # decoder + typeByte = conn.recBuf.read(1) + typeByte = int(typeByte[0]) + resTypeByte = typeByte + 0x10 + req_type = message_types[typeByte] + + if req_type == "flush": + # messages are length prefixed + conn.resBuf.write(encode(1)) + conn.resBuf.write([resTypeByte]) + conn.fd.send(conn.resBuf.buf) + conn.msgLength = 0 + conn.inProgress = False + conn.resBuf = BytesBuffer(bytearray()) + return + + decoder = getattr(conn.decoder, req_type) + + print("decoding args") + req_args = decoder() + print("got args", req_args) + + # done decoding message + conn.msgLength = 0 + conn.inProgress = False + + req_f = getattr(conn.appCtx, req_type) + if req_args is None: + res = req_f() + elif isinstance(req_args, tuple): + res = req_f(*req_args) + else: + res = req_f(req_args) + + if isinstance(res, tuple): + res, ret_code = res + else: + ret_code = res + res = None + + print("called", req_type, "ret code:", ret_code, 'res:', res) + if ret_code != 0: + print("non-zero retcode:", ret_code) + + if req_type in ("echo", "info"): # these dont return a ret code + enc = encode(res) + # messages are length prefixed + conn.resBuf.write(encode(len(enc) + 1)) + conn.resBuf.write([resTypeByte]) + conn.resBuf.write(enc) + else: + enc, encRet = encode(res), encode(ret_code) + # messages are length prefixed + conn.resBuf.write(encode(len(enc) + len(encRet) + 1)) + conn.resBuf.write([resTypeByte]) + conn.resBuf.write(encRet) + conn.resBuf.write(enc) + except IOError as e: + print("IOError on reading from connection:", e) + self.handle_conn_closed(r) + return + except Exception as e: + import sys + print(sys.exc_info()[0]) + print("error reading from connection", str(e)) + self.handle_conn_closed(r) + return + + def main_loop(self): + while not self.shutdown: + r_list, w_list, _ = select.select( + self.read_list, self.write_list, [], 2.5) + + for r in r_list: + if (r == self.listener): + try: + self.handle_new_connection(r) + # undo adding to read list ... + except NameError as e: + print("Could not connect due to NameError:", e) + except TypeError as e: + print("Could not connect due to TypeError:", e) + except: + print("Could not connect due to unexpected error:", sys.exc_info()[0]) + else: + self.handle_recv(r) + + def handle_shutdown(self): + for r in self.read_list: + r.close() + for w in self.write_list: + try: + w.close() + except Exception as e: + print(e) # TODO: add logging + self.shutdown = True diff --git a/example/python3/tmsp/wire.py b/example/python3/tmsp/wire.py new file mode 100644 index 00000000..ebf78a3a --- /dev/null +++ b/example/python3/tmsp/wire.py @@ -0,0 +1,119 @@ + +# the decoder works off a reader +# the encoder returns bytearray + + +def hex2bytes(h): + return bytearray(h.decode('hex')) + + +def bytes2hex(b): + if type(b) in (str, str): + return "".join([hex(ord(c))[2:].zfill(2) for c in b]) + else: + return bytes2hex(b.decode()) + + +# expects uvarint64 (no crazy big nums!) +def uvarint_size(i): + if i == 0: + return 0 + for j in range(1, 8): + if i < 1 << j * 8: + return j + return 8 + +# expects i < 2**size + + +def encode_big_endian(i, size): + if size == 0: + return bytearray() + return encode_big_endian(i / 256, size - 1) + bytearray([i % 256]) + + +def decode_big_endian(reader, size): + if size == 0: + return 0 + firstByte = reader.read(1)[0] + return firstByte * (256 ** (size - 1)) + decode_big_endian(reader, size - 1) + +# ints are max 16 bytes long + + +def encode_varint(i): + negate = False + if i < 0: + negate = True + i = -i + size = uvarint_size(i) + if size == 0: + return bytearray([0]) + big_end = encode_big_endian(i, size) + if negate: + size += 0xF0 + return bytearray([size]) + big_end + +# returns the int and whats left of the byte array + + +def decode_varint(reader): + size = reader.read(1)[0] + if size == 0: + return 0 + + negate = True if size > int(0xF0) else False + if negate: + size = size - 0xF0 + i = decode_big_endian(reader, size) + if negate: + i = i * (-1) + return i + + +def encode_string(s): + size = encode_varint(len(s)) + return size + bytearray(s, 'utf8') + + +def decode_string(reader): + length = decode_varint(reader) + raw_data = reader.read(length) + return raw_data.decode() + + +def encode_list(s): + b = bytearray() + list(map(b.extend, list(map(encode, s)))) + return encode_varint(len(s)) + b + + +def encode(s): + print('encoding', repr(s)) + if s is None: + return bytearray() + if isinstance(s, int): + return encode_varint(s) + elif isinstance(s, str): + return encode_string(s) + elif isinstance(s, list): + return encode_list(s) + elif isinstance(s, bytearray): + return encode_string(s) + else: + print("UNSUPPORTED TYPE!", type(s), s) + + +if __name__ == '__main__': + ns = [100, 100, 1000, 256] + ss = [2, 5, 5, 2] + bs = list(map(encode_big_endian, ns, ss)) + ds = list(map(decode_big_endian, bs, ss)) + print(ns) + print([i[0] for i in ds]) + + ss = ["abc", "hi there jim", "ok now what"] + e = list(map(encode_string, ss)) + d = list(map(decode_string, e)) + print(ss) + print([i[0] for i in d]) From 3092d2c0434d54fb46a3ab3c61b2c27abe1ffbc1 Mon Sep 17 00:00:00 2001 From: tim watts Date: Tue, 5 Jan 2016 22:00:19 +0000 Subject: [PATCH 049/545] missing modulename and fix refactoring --- example/python/app.py | 6 +++--- example/python/tmsp/server.py | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/example/python/app.py b/example/python/app.py index caed1783..b0c3d640 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -1,8 +1,8 @@ import sys -from wire import hex2bytes, decode_big_endian, encode_big_endian -from server import TMSPServer -from reader import BytesBuffer +from tmsp.wire import hex2bytes, decode_big_endian, encode_big_endian +from tmsp.server import TMSPServer +from tmsp.reader import BytesBuffer class CounterApplication(): diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py index 91d87e5e..731f30e9 100644 --- a/example/python/tmsp/server.py +++ b/example/python/tmsp/server.py @@ -111,6 +111,7 @@ class TMSPServer(): # messages are length prefixed conn.resBuf.write(encode(1)) conn.resBuf.write([resTypeByte]) + conn.fd.send(str(conn.resBuf.buf)) conn.msgLength = 0 conn.inProgress = False conn.resBuf = BytesBuffer(bytearray()) From eece2ae7a533d21b57f1f8371851be1e6f7910d5 Mon Sep 17 00:00:00 2001 From: tim watts Date: Tue, 5 Jan 2016 22:37:22 +0000 Subject: [PATCH 050/545] use floor division --- example/python3/app.py | 2 +- example/python3/tmsp/server.py | 4 +--- example/python3/tmsp/wire.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/example/python3/app.py b/example/python3/app.py index 547f73d8..6aae0836 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -56,7 +56,7 @@ class CounterAppContext(): return "", 0 h = encode_big_endian(self.txCount, 8) h.reverse() - return str(h), 0 + return h.decode(), 0 def commit(self): self.commitCount += 1 diff --git a/example/python3/tmsp/server.py b/example/python3/tmsp/server.py index 0034b600..38cb3ca8 100644 --- a/example/python3/tmsp/server.py +++ b/example/python3/tmsp/server.py @@ -165,9 +165,7 @@ class TMSPServer(): self.handle_conn_closed(r) return except Exception as e: - import sys - print(sys.exc_info()[0]) - print("error reading from connection", str(e)) + logger.exception("error reading from connection") self.handle_conn_closed(r) return diff --git a/example/python3/tmsp/wire.py b/example/python3/tmsp/wire.py index ebf78a3a..72f5fab8 100644 --- a/example/python3/tmsp/wire.py +++ b/example/python3/tmsp/wire.py @@ -29,7 +29,7 @@ def uvarint_size(i): def encode_big_endian(i, size): if size == 0: return bytearray() - return encode_big_endian(i / 256, size - 1) + bytearray([i % 256]) + return encode_big_endian(i // 256, size - 1) + bytearray([i % 256]) def decode_big_endian(reader, size): From aa3e87450a2916e3c7755ea60243f8856eb39cf1 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 8 Jan 2016 16:06:33 -0500 Subject: [PATCH 051/545] fix tests --- tests/test_counter.sh | 4 ++-- tests/test_dummy.sh | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/test_counter.sh b/tests/test_counter.sh index 8bbd8d37..99af772c 100644 --- a/tests/test_counter.sh +++ b/tests/test_counter.sh @@ -17,7 +17,7 @@ if [[ "$?" != 0 ]]; then fi sleep 1 -OUTPUT=`(tmsp batch) < /dev/null & PID=`echo $!` sleep 1 -RESULT_HASH=`tmsp get_hash` +RESULT_HASH=`tmsp-cli get_hash` if [[ "$RESULT_HASH" != "" ]]; then echo "Expected nothing but got: $RESULT_HASH" exit 1 @@ -16,7 +16,7 @@ echo "" # Add a tx, get hash, commit, get hash # hashes should be non-empty and identical echo "Dummy batch test ..." -OUTPUT=`(tmsp batch) < Date: Fri, 8 Jan 2016 16:52:02 -0800 Subject: [PATCH 052/545] Remove TMSP Commit/Rollback; Add CheckTx --- README.md | 34 +++++++----- cmd/tmsp-cli/tmsp-cli.go | 62 +++++++++++----------- example/golang/counter.go | 96 +++++++++++----------------------- example/golang/dummy.go | 69 +++++------------------- example/js/app.js | 55 +++++++++---------- example/js/msgs.js | 15 ++---- example/js/server.js | 8 ++- example/python/app.py | 35 +++++-------- example/python/tmsp/msg.py | 19 +++---- example/python/tmsp/server.py | 16 +++--- example/python3/app.py | 35 +++++-------- example/python3/tmsp/msg.py | 19 +++---- example/python3/tmsp/server.py | 15 +++--- server/server.go | 42 +++++++-------- tests/test_dummy.sh | 7 ++- types/application.go | 20 ++----- types/messages.go | 56 ++++++++------------ 17 files changed, 227 insertions(+), 376 deletions(-) diff --git a/README.md b/README.md index 786ab6fa..0df4c6c3 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,14 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * __Usage__:
Append and run a transaction. The transaction may or may not be final. +#### CheckTx + * __Arguments__: + * `TxBytes ([]byte)` + * __Returns__: + * `RetCode (int8)` + * __Usage__:
+ Validate a transaction. This message should not mutate the state. + #### GetHash * __Returns__: * `RetCode (int8)` @@ -23,18 +31,6 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * __Usage__:
Return a Merkle root hash of the application state -#### Commit - * __Returns__: - * `RetCode (int8)` - * __Usage__:
- Finalize all appended transactions - -#### Rollback - * __Returns__: - * `RetCode (int8)` - * __Usage__:
- Roll back to the last commit - #### AddListener * __Arguments__: * `EventKey (string)` @@ -70,3 +66,17 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * __Usage__:
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. + +## Changelog + +### Jan 8th, 2016 + +Tendermint/TMSP now comes to consensus on the order first before AppendTx. +This means that we no longer need the Commit/Rollback TMSP messages. +Instead, there’s a “CheckTx†message for mempool to check the validity of a message. +One consequence is that txs in blocks now may include invalid txs that are ignored. +In the future, we can include a bitarray or merkle structure in the block so anyone can see which txs were valid. +To prevent spam, applications can implement their “CheckTx†messages to deduct some balance, so at least spam txs will cost something. This isn’t any more work that what we already needed to do, so it’s not any worse. +You can see the new changes in the tendermint/tendermint “order_first†branch, and tendermint/tmsp “order_first†branch. If you your TMSP apps to me I can help with the transition. +Please take a look at how the examples in TMSP changed, e.g. how AppContext was removed, CheckTx was added, how the TMSP msg bytes changed, and how commit/rollback messages were removed. + diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index c9684063..96575fd0 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -75,6 +75,13 @@ func main() { cmdAppendTx(c) }, }, + { + Name: "check_tx", + Usage: "Validate a tx", + Action: func(c *cli.Context) { + cmdCheckTx(c) + }, + }, { Name: "get_hash", Usage: "Get application Merkle root hash", @@ -82,20 +89,6 @@ func main() { cmdGetHash(c) }, }, - { - Name: "commit", - Usage: "Commit the application state", - Action: func(c *cli.Context) { - cmdCommit(c) - }, - }, - { - Name: "rollback", - Usage: "Roll back the application state to the latest commit", - Action: func(c *cli.Context) { - cmdRollback(c) - }, - }, } app.Before = before app.Run(os.Args) @@ -209,6 +202,29 @@ func cmdAppendTx(c *cli.Context) { fmt.Println("Response:", res) } +// Validate a tx +func cmdCheckTx(c *cli.Context) { + args := c.Args() + if len(args) != 1 { + Exit("append_tx takes 1 argument") + } + txString := args[0] + tx := []byte(txString) + if len(txString) > 2 && strings.HasPrefix(txString, "0x") { + var err error + tx, err = hex.DecodeString(txString[2:]) + if err != nil { + Exit(err.Error()) + } + } + + res, err := makeRequest(conn, types.RequestCheckTx{tx}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("Response:", res) +} + // Get application Merkle root hash func cmdGetHash(c *cli.Context) { res, err := makeRequest(conn, types.RequestGetHash{}) @@ -218,24 +234,6 @@ func cmdGetHash(c *cli.Context) { fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash) } -// Commit the application state -func cmdCommit(c *cli.Context) { - _, err := makeRequest(conn, types.RequestCommit{}) - if err != nil { - Exit(err.Error()) - } - fmt.Println("Committed.") -} - -// Roll back the application state to the latest commit -func cmdRollback(c *cli.Context) { - _, err := makeRequest(conn, types.RequestRollback{}) - if err != nil { - Exit(err.Error()) - } - fmt.Println("Rolled back.") -} - //-------------------------------------------------------------------------------- func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { diff --git a/example/golang/counter.go b/example/golang/counter.go index e96e78e5..1c3b944a 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -2,111 +2,77 @@ package example import ( "encoding/binary" - "sync" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" ) type CounterApplication struct { - mtx sync.Mutex - hashCount int - txCount int - commitCount int - serial bool + hashCount int + txCount int + serial bool } func NewCounterApplication(serial bool) *CounterApplication { return &CounterApplication{serial: serial} } -func (app *CounterApplication) Open() types.AppContext { - return &CounterAppContext{ - app: app, - hashCount: app.hashCount, - txCount: app.txCount, - commitCount: app.commitCount, - serial: app.serial, - } -} - -//-------------------------------------------------------------------------------- - -type CounterAppContext struct { - app *CounterApplication - hashCount int - txCount int - commitCount int - serial bool -} - -func (appC *CounterAppContext) Echo(message string) string { +func (app *CounterApplication) Echo(message string) string { return message } -func (appC *CounterAppContext) Info() []string { - return []string{Fmt("hash, tx, commit counts:%d, %d, %d", appC.hashCount, appC.txCount, appC.commitCount)} +func (app *CounterApplication) Info() []string { + return []string{Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount)} } -func (appC *CounterAppContext) SetOption(key string, value string) types.RetCode { +func (app *CounterApplication) SetOption(key string, value string) types.RetCode { if key == "serial" && value == "on" { - appC.serial = true + app.serial = true } return 0 } -func (appC *CounterAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode) { - if appC.serial { +func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { + if app.serial { tx8 := make([]byte, 8) copy(tx8, tx) txValue := binary.LittleEndian.Uint64(tx8) - if txValue != uint64(appC.txCount) { + if txValue != uint64(app.txCount) { return nil, types.RetCodeInternalError } } - appC.txCount += 1 + app.txCount += 1 return nil, 0 } -func (appC *CounterAppContext) GetHash() ([]byte, types.RetCode) { - appC.hashCount += 1 - if appC.txCount == 0 { +func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { + if app.serial { + tx8 := make([]byte, 8) + copy(tx8, tx) + txValue := binary.LittleEndian.Uint64(tx8) + if txValue < uint64(app.txCount) { + return types.RetCodeInternalError + } + } + return 0 +} + +func (app *CounterApplication) GetHash() ([]byte, types.RetCode) { + app.hashCount += 1 + + if app.txCount == 0 { return nil, 0 } else { hash := make([]byte, 32) - binary.LittleEndian.PutUint64(hash, uint64(appC.txCount)) + binary.LittleEndian.PutUint64(hash, uint64(app.txCount)) return hash, 0 } } -func (appC *CounterAppContext) Commit() types.RetCode { - appC.commitCount += 1 - - appC.app.mtx.Lock() - appC.app.hashCount = appC.hashCount - appC.app.txCount = appC.txCount - appC.app.commitCount = appC.commitCount - appC.app.mtx.Unlock() +func (app *CounterApplication) AddListener(key string) types.RetCode { return 0 } -func (appC *CounterAppContext) Rollback() types.RetCode { - appC.app.mtx.Lock() - appC.hashCount = appC.app.hashCount - appC.txCount = appC.app.txCount - appC.commitCount = appC.app.commitCount - appC.app.mtx.Unlock() +func (app *CounterApplication) RemListener(key string) types.RetCode { return 0 } - -func (appC *CounterAppContext) AddListener(key string) types.RetCode { - return 0 -} - -func (appC *CounterAppContext) RemListener(key string) types.RetCode { - return 0 -} - -func (appC *CounterAppContext) Close() error { - return nil -} diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 7f8db3cd..e6f60ad7 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -1,8 +1,6 @@ package example import ( - "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" @@ -10,7 +8,6 @@ import ( ) type DummyApplication struct { - mtx sync.Mutex state merkle.Tree } @@ -24,74 +21,36 @@ func NewDummyApplication() *DummyApplication { return &DummyApplication{state: state} } -func (dapp *DummyApplication) Open() types.AppContext { - dapp.mtx.Lock() - defer dapp.mtx.Unlock() - return &DummyAppContext{ - app: dapp, - state: dapp.state.Copy(), - } -} - -func (dapp *DummyApplication) commitState(state merkle.Tree) { - dapp.mtx.Lock() - defer dapp.mtx.Unlock() - dapp.state = state.Copy() -} - -func (dapp *DummyApplication) getState() merkle.Tree { - dapp.mtx.Lock() - defer dapp.mtx.Unlock() - return dapp.state.Copy() -} - -//-------------------------------------------------------------------------------- - -type DummyAppContext struct { - app *DummyApplication - state merkle.Tree -} - -func (dac *DummyAppContext) Echo(message string) string { +func (app *DummyApplication) Echo(message string) string { return message } -func (dac *DummyAppContext) Info() []string { - return []string{Fmt("size:%v", dac.state.Size())} +func (app *DummyApplication) Info() []string { + return []string{Fmt("size:%v", app.state.Size())} } -func (dac *DummyAppContext) SetOption(key string, value string) types.RetCode { +func (app *DummyApplication) SetOption(key string, value string) types.RetCode { return 0 } -func (dac *DummyAppContext) AppendTx(tx []byte) ([]types.Event, types.RetCode) { - dac.state.Set(tx, tx) +func (app *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { + app.state.Set(tx, tx) return nil, 0 } -func (dac *DummyAppContext) GetHash() ([]byte, types.RetCode) { - hash := dac.state.Hash() +func (app *DummyApplication) CheckTx(tx []byte) types.RetCode { + return 0 // all txs are valid +} + +func (app *DummyApplication) GetHash() ([]byte, types.RetCode) { + hash := app.state.Hash() return hash, 0 } -func (dac *DummyAppContext) Commit() types.RetCode { - dac.app.commitState(dac.state) +func (app *DummyApplication) AddListener(key string) types.RetCode { return 0 } -func (dac *DummyAppContext) Rollback() types.RetCode { - dac.state = dac.app.getState() +func (app *DummyApplication) RemListener(key string) types.RetCode { return 0 } - -func (dac *DummyAppContext) AddListener(key string) types.RetCode { - return 0 -} - -func (dac *DummyAppContext) RemListener(key string) types.RetCode { - return 0 -} - -func (dac *DummyAppContext) Close() error { - return nil -} diff --git a/example/js/app.js b/example/js/app.js index f7def6a0..e6978e1d 100644 --- a/example/js/app.js +++ b/example/js/app.js @@ -5,36 +5,25 @@ util = require("util") function CounterApp(){ this.hashCount = 0; this.txCount = 0; - this.commitCount = 0; + this.serial = false; }; -CounterApp.prototype.open = function(){ - return new CounterAppContext(this); -} - -function CounterAppContext(app) { - this.hashCount = app.hashCount; - this.txCount = app.txCount; - this.commitCount = app.commitCount; - this.serial = false; -} - -CounterAppContext.prototype.echo = function(msg){ +CounterApp.prototype.echo = function(msg){ return {"response": msg, "ret_code":0} } -CounterAppContext.prototype.info = function(){ - return {"response": [util.format("hash, tx, commit counts: %d, %d, %d", this.hashCount, this.txCount, this.commitCount)]} +CounterApp.prototype.info = function(){ + return {"response": [util.format("hashes:%d, txs:%d", this.hashCount, this.txCount)]} } -CounterAppContext.prototype.set_option = function(key, value){ +CounterApp.prototype.set_option = function(key, value){ if (key == "serial" && value == "on"){ this.serial = true; } return {"ret_code":0} } -CounterAppContext.prototype.append_tx = function(txBytes){ +CounterApp.prototype.append_tx = function(txBytes){ if (this.serial) { txByteArray = new Buffer(txBytes) if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { @@ -50,7 +39,22 @@ CounterAppContext.prototype.append_tx = function(txBytes){ return {"ret_code":0} // TODO: return events } -CounterAppContext.prototype.get_hash = function(){ +CounterApp.prototype.check_tx = function(txBytes){ + if (this.serial) { + txByteArray = new Buffer(txBytes) + if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { + txByteArray = wire.hex2bytes(txBytes.slice(2)); + } + r = new msg.buffer(txByteArray) + txValue = wire.decode_big_endian(r, txBytes.length) + if (txValue < this.txCount){ + return {"ret_code":1} + } + } + return {"ret_code":0} +} + +CounterApp.prototype.get_hash = function(){ this.hashCount += 1; if (this.txCount == 0){ return {"response": "", "ret_code":0} @@ -60,24 +64,15 @@ CounterAppContext.prototype.get_hash = function(){ return {"response": h.toString(), "ret_code":0} } -CounterAppContext.prototype.commit = function(){ - this.commitCount += 1; +CounterApp.prototype.add_listener = function(){ return {"ret_code":0} } -CounterAppContext.prototype.rollback = function(){ +CounterApp.prototype.rm_listener = function(){ return {"ret_code":0} } -CounterAppContext.prototype.add_listener = function(){ - return {"ret_code":0} -} - -CounterAppContext.prototype.rm_listener = function(){ - return {"ret_code":0} -} - -CounterAppContext.prototype.event = function(){ +CounterApp.prototype.event = function(){ } console.log("Counter app in Javascript") diff --git a/example/js/msgs.js b/example/js/msgs.js index a8b90ecd..7993ca85 100644 --- a/example/js/msgs.js +++ b/example/js/msgs.js @@ -7,17 +7,13 @@ module.exports = { 0x03 : "info", 0x04 : "set_option", 0x21 : "append_tx", - 0x22 : "get_hash", - 0x23 : "commit", - 0x24 : "rollback", - 0x25 : "add_listener", - 0x26 : "rm_listener", + 0x22 : "check_tx", + 0x23 : "get_hash", + 0x24 : "add_listener", + 0x25 : "rm_listener", }, - decoder : RequestDecoder, - buffer: BytesBuffer - } function RequestDecoder(buf){ @@ -32,9 +28,8 @@ RequestDecoder.prototype.flush = function(){}; RequestDecoder.prototype.info = function(){}; RequestDecoder.prototype.set_option = function(){ return [decode_string(this.buf), decode_string(this.buf)] }; RequestDecoder.prototype.append_tx = function(){ return decode_string(this.buf)}; +RequestDecoder.prototype.check_tx = function(){ return decode_string(this.buf)}; RequestDecoder.prototype.get_hash = function(){ }; -RequestDecoder.prototype.commit = function(){ }; -RequestDecoder.prototype.rollback = function(){ }; RequestDecoder.prototype.add_listener = function(){ }; // TODO RequestDecoder.prototype.rm_listener = function(){ }; // TODO diff --git a/example/js/server.js b/example/js/server.js index 4ca870d9..ab6e59cf 100644 --- a/example/js/server.js +++ b/example/js/server.js @@ -27,8 +27,6 @@ AppServer.prototype.createServer = function(){ socket.name = socket.remoteAddress + ":" + socket.remotePort console.log("new connection from", socket.name) - appCtx = app.open() - var conn = { recBuf: new msg.buffer(new Buffer(0)), resBuf: new msg.buffer(new Buffer(0)), @@ -90,11 +88,11 @@ AppServer.prototype.createServer = function(){ var res = function(){ if (args == null){ - return appCtx[reqType](); + return app[reqType](); } else if (Array.isArray(args)){ - return appCtx[reqType].apply(appCtx, args); + return app[reqType].apply(app, args); } else { - return appCtx[reqType](args) + return app[reqType](args) } }() diff --git a/example/python/app.py b/example/python/app.py index b0c3d640..c8470d99 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -10,28 +10,13 @@ class CounterApplication(): def __init__(self): self.hashCount = 0 self.txCount = 0 - self.commitCount = 0 - - def open(self): - return CounterAppContext(self) - - -class CounterAppContext(): - - def __init__(self, app): - self.app = app - self.hashCount = app.hashCount - self.txCount = app.txCount - self.commitCount = app.commitCount self.serial = False def echo(self, msg): return msg, 0 def info(self): - return ["hash, tx, commit counts:%d, %d, %d" % (self.hashCount, - self.txCount, - self.commitCount)], 0 + return ["hashes:%d, txs:%d" % (self.hashCount, self.txCount)], 0 def set_option(self, key, value): if key == "serial" and value == "on": @@ -50,6 +35,17 @@ class CounterAppContext(): self.txCount += 1 return None, 0 + def check_tx(self, txBytes): + if self.serial: + txByteArray = bytearray(txBytes) + if len(txBytes) >= 2 and txBytes[:2] == "0x": + txByteArray = hex2bytes(txBytes[2:]) + txValue = decode_big_endian( + BytesBuffer(txByteArray), len(txBytes)) + if txValue < self.txCount: + return 1 + return 0 + def get_hash(self): self.hashCount += 1 if self.txCount == 0: @@ -58,13 +54,6 @@ class CounterAppContext(): h.reverse() return str(h), 0 - def commit(self): - self.commitCount += 1 - return 0 - - def rollback(self): - return 0 - def add_listener(self): return 0 diff --git a/example/python/tmsp/msg.py b/example/python/tmsp/msg.py index f9339fe9..17e71471 100644 --- a/example/python/tmsp/msg.py +++ b/example/python/tmsp/msg.py @@ -7,16 +7,14 @@ message_types = { 0x03: "info", 0x04: "set_option", 0x21: "append_tx", - 0x22: "get_hash", - 0x23: "commit", - 0x24: "rollback", - 0x25: "add_listener", - 0x26: "rm_listener", + 0x22: "check_tx", + 0x23: "get_hash", + 0x24: "add_listener", + 0x25: "rm_listener", } # return the decoded arguments of tmsp messages - class RequestDecoder(): def __init__(self, reader): @@ -37,15 +35,12 @@ class RequestDecoder(): def append_tx(self): return decode_string(self.reader) + def check_tx(self): + return decode_string(self.reader) + def get_hash(self): return - def commit(self): - return - - def rollback(self): - return - def add_listener(self): # TODO return diff --git a/example/python/tmsp/server.py b/example/python/tmsp/server.py index 731f30e9..60f76e3a 100644 --- a/example/python/tmsp/server.py +++ b/example/python/tmsp/server.py @@ -2,7 +2,6 @@ import socket import select import sys - from wire import decode_varint, encode from reader import BytesBuffer from msg import RequestDecoder, message_types @@ -10,12 +9,11 @@ from msg import RequestDecoder, message_types # hold the asyncronous state of a connection # ie. we may not get enough bytes on one read to decode the message - class Connection(): - def __init__(self, fd, appCtx): + def __init__(self, fd, app): self.fd = fd - self.appCtx = appCtx + self.app = app self.recBuf = BytesBuffer(bytearray()) self.resBuf = BytesBuffer(bytearray()) self.msgLength = 0 @@ -30,12 +28,11 @@ class Connection(): # TMSP server responds to messges by calling methods on the app - class TMSPServer(): def __init__(self, app, port=5410): self.app = app - # map conn file descriptors to (appContext, reqBuf, resBuf, msgDecoder) + # map conn file descriptors to (app, reqBuf, resBuf, msgDecoder) self.appMap = {} self.port = port @@ -60,8 +57,7 @@ class TMSPServer(): self.write_list.append(new_fd) print 'new connection to', new_addr - appContext = self.app.open() - self.appMap[new_fd] = Connection(new_fd, appContext) + self.appMap[new_fd] = Connection(new_fd, self.app) def handle_conn_closed(self, r): self.read_list.remove(r) @@ -70,7 +66,7 @@ class TMSPServer(): print "connection closed" def handle_recv(self, r): - # appCtx, recBuf, resBuf, conn + # app, recBuf, resBuf, conn conn = self.appMap[r] while True: try: @@ -127,7 +123,7 @@ class TMSPServer(): conn.msgLength = 0 conn.inProgress = False - req_f = getattr(conn.appCtx, req_type) + req_f = getattr(conn.app, req_type) if req_args is None: res = req_f() elif isinstance(req_args, tuple): diff --git a/example/python3/app.py b/example/python3/app.py index 6aae0836..6d950ff6 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -10,28 +10,13 @@ class CounterApplication(): def __init__(self): self.hashCount = 0 self.txCount = 0 - self.commitCount = 0 - - def open(self): - return CounterAppContext(self) - - -class CounterAppContext(): - - def __init__(self, app): - self.app = app - self.hashCount = app.hashCount - self.txCount = app.txCount - self.commitCount = app.commitCount self.serial = False def echo(self, msg): return msg, 0 def info(self): - return ["hash, tx, commit counts:%d, %d, %d" % (self.hashCount, - self.txCount, - self.commitCount)], 0 + return ["hashes:%d, txs:%d" % (self.hashCount, self.txCount)], 0 def set_option(self, key, value): if key == "serial" and value == "on": @@ -50,6 +35,17 @@ class CounterAppContext(): self.txCount += 1 return None, 0 + def check_tx(self, txBytes): + if self.serial: + txByteArray = bytearray(txBytes) + if len(txBytes) >= 2 and txBytes[:2] == "0x": + txByteArray = hex2bytes(txBytes[2:]) + txValue = decode_big_endian( + BytesBuffer(txByteArray), len(txBytes)) + if txValue < self.txCount: + return 1 + return 0 + def get_hash(self): self.hashCount += 1 if self.txCount == 0: @@ -58,13 +54,6 @@ class CounterAppContext(): h.reverse() return h.decode(), 0 - def commit(self): - self.commitCount += 1 - return 0 - - def rollback(self): - return 0 - def add_listener(self): return 0 diff --git a/example/python3/tmsp/msg.py b/example/python3/tmsp/msg.py index daa0cc9d..2f35d8be 100644 --- a/example/python3/tmsp/msg.py +++ b/example/python3/tmsp/msg.py @@ -7,16 +7,14 @@ message_types = { 0x03: "info", 0x04: "set_option", 0x21: "append_tx", - 0x22: "get_hash", - 0x23: "commit", - 0x24: "rollback", - 0x25: "add_listener", - 0x26: "rm_listener", + 0x22: "check_tx", + 0x23: "get_hash", + 0x24: "add_listener", + 0x25: "rm_listener", } # return the decoded arguments of tmsp messages - class RequestDecoder(): def __init__(self, reader): @@ -37,15 +35,12 @@ class RequestDecoder(): def append_tx(self): return decode_string(self.reader) + def check_tx(self): + return decode_string(self.reader) + def get_hash(self): return - def commit(self): - return - - def rollback(self): - return - def add_listener(self): # TODO return diff --git a/example/python3/tmsp/server.py b/example/python3/tmsp/server.py index 38cb3ca8..03735bb3 100644 --- a/example/python3/tmsp/server.py +++ b/example/python3/tmsp/server.py @@ -12,12 +12,11 @@ from .msg import RequestDecoder, message_types logger = logging.getLogger(__name__) - class Connection(): - def __init__(self, fd, appCtx): + def __init__(self, fd, app): self.fd = fd - self.appCtx = appCtx + self.app = app self.recBuf = BytesBuffer(bytearray()) self.resBuf = BytesBuffer(bytearray()) self.msgLength = 0 @@ -32,12 +31,11 @@ class Connection(): # TMSP server responds to messges by calling methods on the app - class TMSPServer(): def __init__(self, app, port=5410): self.app = app - # map conn file descriptors to (appContext, reqBuf, resBuf, msgDecoder) + # map conn file descriptors to (app, reqBuf, resBuf, msgDecoder) self.appMap = {} self.port = port @@ -62,8 +60,7 @@ class TMSPServer(): self.write_list.append(new_fd) print('new connection to', new_addr) - appContext = self.app.open() - self.appMap[new_fd] = Connection(new_fd, appContext) + self.appMap[new_fd] = Connection(new_fd, self.app) def handle_conn_closed(self, r): self.read_list.remove(r) @@ -72,7 +69,7 @@ class TMSPServer(): print("connection closed") def handle_recv(self, r): - # appCtx, recBuf, resBuf, conn + # app, recBuf, resBuf, conn conn = self.appMap[r] while True: try: @@ -129,7 +126,7 @@ class TMSPServer(): conn.msgLength = 0 conn.inProgress = False - req_f = getattr(conn.appCtx, req_type) + req_f = getattr(conn.app, req_type) if req_args is None: res = req_f() elif isinstance(req_args, tuple): diff --git a/server/server.go b/server/server.go index e109c9ac..a8d014c2 100644 --- a/server/server.go +++ b/server/server.go @@ -6,6 +6,7 @@ import ( "io" "net" "strings" + "sync" . "github.com/tendermint/go-common" "github.com/tendermint/go-wire" @@ -15,6 +16,7 @@ import ( // var maxNumberConnections = 2 func StartListener(protoAddr string, app types.Application) (net.Listener, error) { + var mtx sync.Mutex // global mutex parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] ln, err := net.Listen(proto, addr) @@ -38,12 +40,11 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error fmt.Println("Accepted a new connection") } - appContext := app.Open() closeConn := make(chan error, 2) // Push to signal connection closed responses := make(chan types.Response, 1000) // A channel to buffer responses // Read requests from conn and deal with them - go handleRequests(appContext, closeConn, conn, responses) + go handleRequests(&mtx, app, closeConn, conn, responses) // Pull responses from 'responses' and write them to conn. go handleResponses(closeConn, responses, conn) @@ -62,12 +63,6 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error fmt.Printf("Error in closing connection: %v\n", err) } - // Close the AppContext - err = appContext.Close() - if err != nil { - fmt.Printf("Error in closing app context: %v\n", err) - } - // <-semaphore }() } @@ -78,7 +73,7 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error } // Read requests from conn and deal with them -func handleRequests(appC types.AppContext, closeConn chan error, conn net.Conn, responses chan<- types.Response) { +func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error, conn net.Conn, responses chan<- types.Response) { var count int var bufReader = bufio.NewReader(conn) for { @@ -94,44 +89,43 @@ func handleRequests(appC types.AppContext, closeConn chan error, conn net.Conn, } return } + mtx.Lock() count++ - handleRequest(appC, req, responses) + handleRequest(app, req, responses) + mtx.Unlock() } } -func handleRequest(appC types.AppContext, req types.Request, responses chan<- types.Response) { +func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) { switch req := req.(type) { case types.RequestEcho: - msg := appC.Echo(req.Message) + msg := app.Echo(req.Message) responses <- types.ResponseEcho{msg} case types.RequestFlush: responses <- types.ResponseFlush{} case types.RequestInfo: - data := appC.Info() + data := app.Info() responses <- types.ResponseInfo{data} case types.RequestSetOption: - retCode := appC.SetOption(req.Key, req.Value) + retCode := app.SetOption(req.Key, req.Value) responses <- types.ResponseSetOption{retCode} case types.RequestAppendTx: - events, retCode := appC.AppendTx(req.TxBytes) + events, retCode := app.AppendTx(req.TxBytes) responses <- types.ResponseAppendTx{retCode} for _, event := range events { responses <- types.ResponseEvent{event} } + case types.RequestCheckTx: + retCode := app.CheckTx(req.TxBytes) + responses <- types.ResponseCheckTx{retCode} case types.RequestGetHash: - hash, retCode := appC.GetHash() + hash, retCode := app.GetHash() responses <- types.ResponseGetHash{retCode, hash} - case types.RequestCommit: - retCode := appC.Commit() - responses <- types.ResponseCommit{retCode} - case types.RequestRollback: - retCode := appC.Rollback() - responses <- types.ResponseRollback{retCode} case types.RequestAddListener: - retCode := appC.AddListener(req.EventKey) + retCode := app.AddListener(req.EventKey) responses <- types.ResponseAddListener{retCode} case types.RequestRemListener: - retCode := appC.RemListener(req.EventKey) + retCode := app.RemListener(req.EventKey) responses <- types.ResponseRemListener{retCode} default: responses <- types.ResponseException{"Unknown request"} diff --git a/tests/test_dummy.sh b/tests/test_dummy.sh index 097db09d..f0209a89 100755 --- a/tests/test_dummy.sh +++ b/tests/test_dummy.sh @@ -13,17 +13,16 @@ fi echo "... Pass!" echo "" -# Add a tx, get hash, commit, get hash +# Add a tx, get hash, get hash # hashes should be non-empty and identical echo "Dummy batch test ..." OUTPUT=`(tmsp-cli batch) < Date: Sat, 9 Jan 2016 19:05:41 -0800 Subject: [PATCH 053/545] Fix Makefile to get_deps then install --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 13f25e8e..bb750598 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ .PHONY: all test get_deps -all: test get_deps install +all: test install -install: +install: get_deps go install github.com/tendermint/tmsp/cmd/... test: From 44f22e351b207cafa05bfff3abdc35fd27ef3b4a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 12 Jan 2016 14:04:24 -0800 Subject: [PATCH 054/545] Add RetCodeBadNonce and fix response formats --- README.md | 5 ++++- cmd/tmsp-cli/tmsp-cli.go | 12 ++++++------ example/golang/counter.go | 4 ++-- example/js/app.js | 4 ++-- example/python/app.py | 4 ++-- example/python3/app.py | 4 ++-- types/retcode.go | 1 + types/retcode_string.go | 6 +++--- 8 files changed, 22 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 0df4c6c3..8924f57c 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,10 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog ## Changelog +### Jan 12th, 2016 + +* Added "RetCodeBadNonce = 0x06" return code + ### Jan 8th, 2016 Tendermint/TMSP now comes to consensus on the order first before AppendTx. @@ -79,4 +83,3 @@ In the future, we can include a bitarray or merkle structure in the block so any To prevent spam, applications can implement their “CheckTx†messages to deduct some balance, so at least spam txs will cost something. This isn’t any more work that what we already needed to do, so it’s not any worse. You can see the new changes in the tendermint/tendermint “order_first†branch, and tendermint/tmsp “order_first†branch. If you your TMSP apps to me I can help with the transition. Please take a look at how the examples in TMSP changed, e.g. how AppContext was removed, CheckTx was added, how the TMSP msg bytes changed, and how commit/rollback messages were removed. - diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 96575fd0..a623a95a 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -129,7 +129,7 @@ func cmdBatch(app *cli.App, c *cli.Context) { func cmdConsole(app *cli.App, c *cli.Context) { for { - fmt.Printf("> ") + fmt.Printf("\n> ") bufReader := bufio.NewReader(os.Stdin) line, more, err := bufReader.ReadLine() if more { @@ -154,7 +154,7 @@ func cmdEcho(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Println(res) + fmt.Println("->", res) } // Get some info from the application @@ -163,7 +163,7 @@ func cmdInfo(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Println(res) + fmt.Println("->", res) } // Set an option on the application @@ -176,7 +176,7 @@ func cmdSetOption(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Printf("%s=%s\n", args[0], args[1]) + fmt.Println("->", Fmt("%s=%s", args[0], args[1])) } // Append a new tx to application @@ -199,7 +199,7 @@ func cmdAppendTx(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Println("Response:", res) + fmt.Println("->", res) } // Validate a tx @@ -222,7 +222,7 @@ func cmdCheckTx(c *cli.Context) { if err != nil { Exit(err.Error()) } - fmt.Println("Response:", res) + fmt.Println("->", res) } // Get application Merkle root hash diff --git a/example/golang/counter.go b/example/golang/counter.go index 1c3b944a..56546700 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -38,7 +38,7 @@ func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode copy(tx8, tx) txValue := binary.LittleEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return nil, types.RetCodeInternalError + return nil, types.RetCodeBadNonce } } app.txCount += 1 @@ -51,7 +51,7 @@ func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { copy(tx8, tx) txValue := binary.LittleEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.RetCodeInternalError + return types.RetCodeBadNonce } } return 0 diff --git a/example/js/app.js b/example/js/app.js index e6978e1d..bbdf0490 100644 --- a/example/js/app.js +++ b/example/js/app.js @@ -32,7 +32,7 @@ CounterApp.prototype.append_tx = function(txBytes){ r = new msg.buffer(txByteArray) txValue = wire.decode_big_endian(r, txBytes.length) if (txValue != this.txCount){ - return {"ret_code":1} + return {"ret_code":6} } } this.txCount += 1; @@ -48,7 +48,7 @@ CounterApp.prototype.check_tx = function(txBytes){ r = new msg.buffer(txByteArray) txValue = wire.decode_big_endian(r, txBytes.length) if (txValue < this.txCount){ - return {"ret_code":1} + return {"ret_code":6} } } return {"ret_code":0} diff --git a/example/python/app.py b/example/python/app.py index c8470d99..49831ef5 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -31,7 +31,7 @@ class CounterApplication(): txValue = decode_big_endian( BytesBuffer(txByteArray), len(txBytes)) if txValue != self.txCount: - return None, 1 + return None, 6 self.txCount += 1 return None, 0 @@ -43,7 +43,7 @@ class CounterApplication(): txValue = decode_big_endian( BytesBuffer(txByteArray), len(txBytes)) if txValue < self.txCount: - return 1 + return 6 return 0 def get_hash(self): diff --git a/example/python3/app.py b/example/python3/app.py index 6d950ff6..b3616327 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -31,7 +31,7 @@ class CounterApplication(): txValue = decode_big_endian( BytesBuffer(txByteArray), len(txBytes)) if txValue != self.txCount: - return None, 1 + return None, 6 self.txCount += 1 return None, 0 @@ -43,7 +43,7 @@ class CounterApplication(): txValue = decode_big_endian( BytesBuffer(txByteArray), len(txBytes)) if txValue < self.txCount: - return 1 + return 6 return 0 def get_hash(self): diff --git a/types/retcode.go b/types/retcode.go index 559164c6..8f3ad5bf 100644 --- a/types/retcode.go +++ b/types/retcode.go @@ -14,6 +14,7 @@ const ( RetCodeInsufficientFees RetCode = 3 RetCodeUnknownRequest RetCode = 4 RetCodeEncodingError RetCode = 5 + RetCodeBadNonce RetCode = 6 ) func (r RetCode) Error() error { diff --git a/types/retcode_string.go b/types/retcode_string.go index f60dca15..65457041 100644 --- a/types/retcode_string.go +++ b/types/retcode_string.go @@ -4,12 +4,12 @@ package types import "fmt" -const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingError" +const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingErrorRetCodeInvalidNonce" -var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112} +var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112, 131} func (i RetCode) String() string { - if i < 0 || i+1 >= RetCode(len(_RetCode_index)) { + if i < 0 || i >= RetCode(len(_RetCode_index)-1) { return fmt.Sprintf("RetCode(%d)", i) } return _RetCode_name[_RetCode_index[i]:_RetCode_index[i+1]] From ca259ce82ab7e0706a759000c267e8b8178170ec Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 17 Jan 2016 21:29:18 -0800 Subject: [PATCH 055/545] Conform to go-merkle version 0.2.0 --- example/golang/dummy.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/example/golang/dummy.go b/example/golang/dummy.go index e6f60ad7..13c2c582 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -3,7 +3,6 @@ package example import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" "github.com/tendermint/tmsp/types" ) @@ -13,8 +12,6 @@ type DummyApplication struct { func NewDummyApplication() *DummyApplication { state := merkle.NewIAVLTree( - wire.BasicCodec, - wire.BasicCodec, 0, nil, ) From 3f812038a4527d0bb0b1c6aea65207691932b84d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 18 Jan 2016 14:37:42 -0800 Subject: [PATCH 056/545] Add Query; Add benchmark tests --- example/golang/counter.go | 18 +++-- example/golang/dummy.go | 16 +++-- server/server.go | 3 + tests/benchmarks/blank.go | 1 + tests/benchmarks/parallel/parallel.go | 58 ++++++++++++++++ tests/benchmarks/simple/simple.go | 70 +++++++++++++++++++ tests/benchmarks/wire_test.go | 44 ++++++++++++ types/application.go | 3 + types/messages.go | 97 ++++++++++++++++----------- 9 files changed, 256 insertions(+), 54 deletions(-) create mode 100644 tests/benchmarks/blank.go create mode 100644 tests/benchmarks/parallel/parallel.go create mode 100644 tests/benchmarks/simple/simple.go create mode 100644 tests/benchmarks/wire_test.go diff --git a/example/golang/counter.go b/example/golang/counter.go index 56546700..46edcb41 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -29,7 +29,7 @@ func (app *CounterApplication) SetOption(key string, value string) types.RetCode if key == "serial" && value == "on" { app.serial = true } - return 0 + return types.RetCodeOK } func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { @@ -42,7 +42,7 @@ func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode } } app.txCount += 1 - return nil, 0 + return nil, types.RetCodeOK } func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { @@ -54,25 +54,29 @@ func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { return types.RetCodeBadNonce } } - return 0 + return types.RetCodeOK } func (app *CounterApplication) GetHash() ([]byte, types.RetCode) { app.hashCount += 1 if app.txCount == 0 { - return nil, 0 + return nil, types.RetCodeOK } else { hash := make([]byte, 32) binary.LittleEndian.PutUint64(hash, uint64(app.txCount)) - return hash, 0 + return hash, types.RetCodeOK } } func (app *CounterApplication) AddListener(key string) types.RetCode { - return 0 + return types.RetCodeOK } func (app *CounterApplication) RemListener(key string) types.RetCode { - return 0 + return types.RetCodeOK +} + +func (app *CounterApplication) Query(query []byte) (types.RetCode, []byte) { + return types.RetCodeOK, nil } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 13c2c582..543e865b 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -27,27 +27,31 @@ func (app *DummyApplication) Info() []string { } func (app *DummyApplication) SetOption(key string, value string) types.RetCode { - return 0 + return types.RetCodeOK } func (app *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { app.state.Set(tx, tx) - return nil, 0 + return nil, types.RetCodeOK } func (app *DummyApplication) CheckTx(tx []byte) types.RetCode { - return 0 // all txs are valid + return types.RetCodeOK // all txs are valid } func (app *DummyApplication) GetHash() ([]byte, types.RetCode) { hash := app.state.Hash() - return hash, 0 + return hash, types.RetCodeOK } func (app *DummyApplication) AddListener(key string) types.RetCode { - return 0 + return types.RetCodeOK } func (app *DummyApplication) RemListener(key string) types.RetCode { - return 0 + return types.RetCodeOK +} + +func (app *DummyApplication) Query(query []byte) (types.RetCode, []byte) { + return types.RetCodeOK, nil } diff --git a/server/server.go b/server/server.go index a8d014c2..8a6a16d9 100644 --- a/server/server.go +++ b/server/server.go @@ -127,6 +127,9 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty case types.RequestRemListener: retCode := app.RemListener(req.EventKey) responses <- types.ResponseRemListener{retCode} + case types.RequestQuery: + retCode, result := app.Query(req.QueryBytes) + responses <- types.ResponseQuery{retCode, result} default: responses <- types.ResponseException{"Unknown request"} } diff --git a/tests/benchmarks/blank.go b/tests/benchmarks/blank.go new file mode 100644 index 00000000..20f08f14 --- /dev/null +++ b/tests/benchmarks/blank.go @@ -0,0 +1 @@ +package benchmarks diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go new file mode 100644 index 00000000..481c1432 --- /dev/null +++ b/tests/benchmarks/parallel/parallel.go @@ -0,0 +1,58 @@ +package main + +import ( + "bufio" + "fmt" + //"encoding/hex" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func main() { + + conn, err := Connect("unix://test.sock") + if err != nil { + Exit(err.Error()) + } + + // Read a bunch of responses + go func() { + counter := 0 + for { + var res types.Response + var n int + var err error + wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + if err != nil { + Exit(err.Error()) + } + counter += 1 + if counter%1000 == 0 { + fmt.Println("Read", counter) + } + } + }() + + // Write a bunch of requests + counter := 0 + for i := 0; ; i++ { + var bufWriter = bufio.NewWriter(conn) + var req types.Request = types.RequestEcho{"foobar"} + var n int + var err error + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, bufWriter, &n, &err) + if err != nil { + Exit(err.Error()) + } + err = bufWriter.Flush() + if err != nil { + Exit(err.Error()) + } + counter += 1 + if counter%1000 == 0 { + fmt.Println("Write", counter) + } + } +} diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go new file mode 100644 index 00000000..4009f848 --- /dev/null +++ b/tests/benchmarks/simple/simple.go @@ -0,0 +1,70 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "net" + "reflect" + //"encoding/hex" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func main() { + + conn, err := Connect("unix://test.sock") + if err != nil { + Exit(err.Error()) + } + + // Make a bunch of requests + counter := 0 + for i := 0; ; i++ { + req := types.RequestEcho{"foobar"} + _, err := makeRequest(conn, req) + if err != nil { + Exit(err.Error()) + } + counter += 1 + if counter%1000 == 0 { + fmt.Println(counter) + } + } +} + +func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { + var bufWriter = bufio.NewWriter(conn) + var n int + var err error + + // Write desired request + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, bufWriter, &n, &err) + if err != nil { + return nil, err + } + bufWriter.Write([]byte{0x01, 0x01, types.RequestTypeFlush}) // Write flush msg + err = bufWriter.Flush() + if err != nil { + return nil, err + } + + // Read desired response + var res types.Response + wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + if err != nil { + return nil, err + } + var resFlush types.Response // Read flush msg + wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) + if err != nil { + return nil, err + } + if _, ok := resFlush.(types.ResponseFlush); !ok { + return nil, errors.New(Fmt("Expected flush response but got something else", reflect.TypeOf(resFlush))) + } + + return res, nil +} diff --git a/tests/benchmarks/wire_test.go b/tests/benchmarks/wire_test.go new file mode 100644 index 00000000..c730089a --- /dev/null +++ b/tests/benchmarks/wire_test.go @@ -0,0 +1,44 @@ +package benchmarks + +import ( + "bytes" + "testing" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func BenchmarkRequestWire(b *testing.B) { + b.StopTimer() + var bz = make([]byte, 1024) + copy(bz, []byte{1, 9, 0x01, 1, 6, 34, 34, 34, 34, 34, 34}) + var buf = bytes.NewBuffer(bz) + var req types.Request + b.StartTimer() + + for i := 0; i < b.N; i++ { + { + buf = bytes.NewBuffer(bz) + var n int + var err error + wire.ReadBinaryPtrLengthPrefixed(&req, buf, 0, &n, &err) + if err != nil { + Exit(err.Error()) + return + } + } + { + buf = bytes.NewBuffer(bz) + var n int + var err error + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, buf, &n, &err) + if err != nil { + Exit(err.Error()) + return + } + + } + } + +} diff --git a/types/application.go b/types/application.go index d77b6c35..4a0818fd 100644 --- a/types/application.go +++ b/types/application.go @@ -25,4 +25,7 @@ type Application interface { // Remove event listener RemListener(key string) RetCode + + // Query for state + Query(query []byte) (RetCode, []byte) } diff --git a/types/messages.go b/types/messages.go index e98f1d3e..fa9b30d9 100644 --- a/types/messages.go +++ b/types/messages.go @@ -3,32 +3,34 @@ package types import "github.com/tendermint/go-wire" const ( - requestTypeEcho = byte(0x01) - requestTypeFlush = byte(0x02) - requestTypeInfo = byte(0x03) - requestTypeSetOption = byte(0x04) + RequestTypeEcho = byte(0x01) + RequestTypeFlush = byte(0x02) + RequestTypeInfo = byte(0x03) + RequestTypeSetOption = byte(0x04) // reserved for GetOption = byte(0x05) - responseTypeException = byte(0x10) - responseTypeEcho = byte(0x11) - responseTypeFlush = byte(0x12) - responseTypeInfo = byte(0x13) - responseTypeSetOption = byte(0x14) + ResponseTypeException = byte(0x10) + ResponseTypeEcho = byte(0x11) + ResponseTypeFlush = byte(0x12) + ResponseTypeInfo = byte(0x13) + ResponseTypeSetOption = byte(0x14) // reserved for GetOption = byte(0x15) - requestTypeAppendTx = byte(0x21) - requestTypeCheckTx = byte(0x22) - requestTypeGetHash = byte(0x23) - requestTypeAddListener = byte(0x24) - requestTypeRemListener = byte(0x25) - // reserved for responseTypeEvent 0x26 + RequestTypeAppendTx = byte(0x21) + RequestTypeCheckTx = byte(0x22) + RequestTypeGetHash = byte(0x23) + RequestTypeAddListener = byte(0x24) + RequestTypeRemListener = byte(0x25) + // reserved for ResponseTypeEvent 0x26 + RequestTypeQuery = byte(0x27) - responseTypeAppendTx = byte(0x31) - responseTypeCheckTx = byte(0x32) - responseTypeGetHash = byte(0x33) - responseTypeAddListener = byte(0x34) - responseTypeRemListener = byte(0x35) - responseTypeEvent = byte(0x36) + ResponseTypeAppendTx = byte(0x31) + ResponseTypeCheckTx = byte(0x32) + ResponseTypeGetHash = byte(0x33) + ResponseTypeAddListener = byte(0x34) + ResponseTypeRemListener = byte(0x35) + ResponseTypeEvent = byte(0x36) + ResponseTypeQuery = byte(0x37) ) //---------------------------------------- @@ -67,6 +69,10 @@ type RequestRemListener struct { EventKey string } +type RequestQuery struct { + QueryBytes []byte +} + type Request interface { AssertRequestType() } @@ -80,18 +86,20 @@ func (_ RequestCheckTx) AssertRequestType() {} func (_ RequestGetHash) AssertRequestType() {} func (_ RequestAddListener) AssertRequestType() {} func (_ RequestRemListener) AssertRequestType() {} +func (_ RequestQuery) AssertRequestType() {} var _ = wire.RegisterInterface( struct{ Request }{}, - wire.ConcreteType{RequestEcho{}, requestTypeEcho}, - wire.ConcreteType{RequestFlush{}, requestTypeFlush}, - wire.ConcreteType{RequestInfo{}, requestTypeInfo}, - wire.ConcreteType{RequestSetOption{}, requestTypeSetOption}, - wire.ConcreteType{RequestAppendTx{}, requestTypeAppendTx}, - wire.ConcreteType{RequestCheckTx{}, requestTypeCheckTx}, - wire.ConcreteType{RequestGetHash{}, requestTypeGetHash}, - wire.ConcreteType{RequestAddListener{}, requestTypeAddListener}, - wire.ConcreteType{RequestRemListener{}, requestTypeRemListener}, + wire.ConcreteType{RequestEcho{}, RequestTypeEcho}, + wire.ConcreteType{RequestFlush{}, RequestTypeFlush}, + wire.ConcreteType{RequestInfo{}, RequestTypeInfo}, + wire.ConcreteType{RequestSetOption{}, RequestTypeSetOption}, + wire.ConcreteType{RequestAppendTx{}, RequestTypeAppendTx}, + wire.ConcreteType{RequestCheckTx{}, RequestTypeCheckTx}, + wire.ConcreteType{RequestGetHash{}, RequestTypeGetHash}, + wire.ConcreteType{RequestAddListener{}, RequestTypeAddListener}, + wire.ConcreteType{RequestRemListener{}, RequestTypeRemListener}, + wire.ConcreteType{RequestQuery{}, RequestTypeQuery}, ) //---------------------------------------- @@ -140,6 +148,11 @@ type ResponseEvent struct { Event } +type ResponseQuery struct { + RetCode + Result []byte +} + type Response interface { AssertResponseType() } @@ -155,18 +168,20 @@ func (_ ResponseAddListener) AssertResponseType() {} func (_ ResponseRemListener) AssertResponseType() {} func (_ ResponseException) AssertResponseType() {} func (_ ResponseEvent) AssertResponseType() {} +func (_ ResponseQuery) AssertResponseType() {} var _ = wire.RegisterInterface( struct{ Response }{}, - wire.ConcreteType{ResponseEcho{}, responseTypeEcho}, - wire.ConcreteType{ResponseFlush{}, responseTypeFlush}, - wire.ConcreteType{ResponseInfo{}, responseTypeInfo}, - wire.ConcreteType{ResponseSetOption{}, responseTypeSetOption}, - wire.ConcreteType{ResponseAppendTx{}, responseTypeAppendTx}, - wire.ConcreteType{ResponseCheckTx{}, responseTypeCheckTx}, - wire.ConcreteType{ResponseGetHash{}, responseTypeGetHash}, - wire.ConcreteType{ResponseAddListener{}, responseTypeAddListener}, - wire.ConcreteType{ResponseRemListener{}, responseTypeRemListener}, - wire.ConcreteType{ResponseException{}, responseTypeException}, - wire.ConcreteType{ResponseEvent{}, responseTypeEvent}, + wire.ConcreteType{ResponseEcho{}, ResponseTypeEcho}, + wire.ConcreteType{ResponseFlush{}, ResponseTypeFlush}, + wire.ConcreteType{ResponseInfo{}, ResponseTypeInfo}, + wire.ConcreteType{ResponseSetOption{}, ResponseTypeSetOption}, + wire.ConcreteType{ResponseAppendTx{}, ResponseTypeAppendTx}, + wire.ConcreteType{ResponseCheckTx{}, ResponseTypeCheckTx}, + wire.ConcreteType{ResponseGetHash{}, ResponseTypeGetHash}, + wire.ConcreteType{ResponseAddListener{}, ResponseTypeAddListener}, + wire.ConcreteType{ResponseRemListener{}, ResponseTypeRemListener}, + wire.ConcreteType{ResponseException{}, ResponseTypeException}, + wire.ConcreteType{ResponseEvent{}, ResponseTypeEvent}, + wire.ConcreteType{ResponseQuery{}, ResponseTypeQuery}, ) From 8ae0a0a4816529e5f84744eb29ef6cf6358ec05d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 22 Jan 2016 15:50:11 -0800 Subject: [PATCH 057/545] Add Query; Add TMSPClient --- client/golang/client.go | 336 +++++++++++++++++++++++++++++++++++++++ cmd/tmsp-cli/tmsp-cli.go | 34 +++- 2 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 client/golang/client.go diff --git a/client/golang/client.go b/client/golang/client.go new file mode 100644 index 00000000..2dee848a --- /dev/null +++ b/client/golang/client.go @@ -0,0 +1,336 @@ +package tmspcli + +import ( + "bufio" + "container/list" + "errors" + "fmt" + "net" + "reflect" + "sync" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + tmsp "github.com/tendermint/tmsp/types" +) + +const maxResponseSize = 1048576 // 1MB TODO make configurable +const flushThrottleMS = 20 // Don't wait longer than... + +type Callback func(tmsp.Request, tmsp.Response) + +// This is goroutine-safe, but users should beware that +// the application in general is not meant to be interfaced +// with concurrent callers. +type TMSPClient struct { + QuitService + sync.Mutex // [EB]: is this even used? + + reqQueue chan *reqRes + flushTimer *ThrottleTimer + + mtx sync.Mutex + conn net.Conn + bufWriter *bufio.Writer + err error + reqSent *list.List + resCb func(tmsp.Request, tmsp.Response) +} + +func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { + cli := &TMSPClient{ + reqQueue: make(chan *reqRes, bufferSize), + flushTimer: NewThrottleTimer("TMSPClient", flushThrottleMS), + + conn: conn, + bufWriter: bufio.NewWriter(conn), + reqSent: list.New(), + resCb: nil, + } + cli.QuitService = *NewQuitService(nil, "TMSPClient", cli) + return cli +} + +func (cli *TMSPClient) OnStart() error { + cli.QuitService.OnStart() + go cli.sendRequestsRoutine() + go cli.recvResponseRoutine() + return nil +} + +func (cli *TMSPClient) OnStop() { + cli.QuitService.OnStop() + cli.conn.Close() +} + +// NOTE: callback may get internally generated flush responses. +func (cli *TMSPClient) SetResponseCallback(resCb Callback) { + cli.mtx.Lock() + defer cli.mtx.Unlock() + cli.resCb = resCb +} + +func (cli *TMSPClient) StopForError(err error) { + cli.mtx.Lock() + // log.Error("Stopping TMSPClient for error.", "error", err) + if cli.err == nil { + cli.err = err + } + cli.mtx.Unlock() + cli.Stop() +} + +func (cli *TMSPClient) Error() error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + return cli.err +} + +//---------------------------------------- + +func (cli *TMSPClient) sendRequestsRoutine() { + for { + var n int + var err error + select { + case <-cli.flushTimer.Ch: + select { + case cli.reqQueue <- newReqRes(tmsp.RequestFlush{}): + default: + // Probably will fill the buffer, or retry later. + } + case <-cli.QuitService.Quit: + return + case reqres := <-cli.reqQueue: + cli.willSendReq(reqres) + wire.WriteBinaryLengthPrefixed(struct{ tmsp.Request }{reqres.Request}, cli.bufWriter, &n, &err) // Length prefix + if err != nil { + cli.StopForError(err) + return + } + // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) + if _, ok := reqres.Request.(tmsp.RequestFlush); ok { + err = cli.bufWriter.Flush() + if err != nil { + cli.StopForError(err) + return + } + } + } + } +} + +func (cli *TMSPClient) recvResponseRoutine() { + r := bufio.NewReader(cli.conn) // Buffer reads + for { + var res tmsp.Response + var n int + var err error + wire.ReadBinaryPtrLengthPrefixed(&res, r, maxResponseSize, &n, &err) + if err != nil { + cli.StopForError(err) + return + } + switch res := res.(type) { + case tmsp.ResponseException: + cli.StopForError(errors.New(res.Error)) + default: + // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) + err := cli.didRecvResponse(res) + if err != nil { + cli.StopForError(err) + } + } + } +} + +func (cli *TMSPClient) willSendReq(reqres *reqRes) { + cli.mtx.Lock() + defer cli.mtx.Unlock() + cli.reqSent.PushBack(reqres) +} + +func (cli *TMSPClient) didRecvResponse(res tmsp.Response) error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + + // Special logic for events which have no corresponding requests. + if _, ok := res.(tmsp.ResponseEvent); ok && cli.resCb != nil { + cli.resCb(nil, res) + return nil + } + + // Get the first reqRes + next := cli.reqSent.Front() + if next == nil { + return fmt.Errorf("Unexpected result type %v when nothing expected", reflect.TypeOf(res)) + } + reqres := next.Value.(*reqRes) + if !resMatchesReq(reqres.Request, res) { + return fmt.Errorf("Unexpected result type %v when response to %v expected", + reflect.TypeOf(res), reflect.TypeOf(reqres.Request)) + } + + reqres.Response = res // Set response + reqres.Done() // Release waiters + cli.reqSent.Remove(next) // Pop first item from linked list + + // Callback if there is a listener + if cli.resCb != nil { + cli.resCb(reqres.Request, res) + } + + return nil +} + +//---------------------------------------- + +func (cli *TMSPClient) EchoAsync(msg string) { + cli.queueRequest(tmsp.RequestEcho{msg}) +} + +func (cli *TMSPClient) FlushAsync() { + cli.queueRequest(tmsp.RequestFlush{}) +} + +func (cli *TMSPClient) SetOptionAsync(key string, value string) { + cli.queueRequest(tmsp.RequestSetOption{key, value}) +} + +func (cli *TMSPClient) AppendTxAsync(tx []byte) { + cli.queueRequest(tmsp.RequestAppendTx{tx}) +} + +func (cli *TMSPClient) CheckTxAsync(tx []byte) { + cli.queueRequest(tmsp.RequestCheckTx{tx}) +} + +func (cli *TMSPClient) GetHashAsync() { + cli.queueRequest(tmsp.RequestGetHash{}) +} + +func (cli *TMSPClient) AddListenerAsync(key string) { + cli.queueRequest(tmsp.RequestAddListener{key}) +} + +func (cli *TMSPClient) RemListenerAsync(key string) { + cli.queueRequest(tmsp.RequestRemListener{key}) +} + +func (cli *TMSPClient) QueryAsync(query []byte) { + cli.queueRequest(tmsp.RequestQuery{query}) +} + +//---------------------------------------- + +func (cli *TMSPClient) InfoSync() (info []string, err error) { + reqres := cli.queueRequest(tmsp.RequestInfo{}) + cli.FlushSync() + if cli.err != nil { + return nil, cli.err + } + return reqres.Response.(tmsp.ResponseInfo).Data, nil +} + +func (cli *TMSPClient) FlushSync() error { + cli.queueRequest(tmsp.RequestFlush{}).Wait() + return cli.err +} + +func (cli *TMSPClient) AppendTxSync(tx []byte) error { + reqres := cli.queueRequest(tmsp.RequestAppendTx{tx}) + cli.FlushSync() + if cli.err != nil { + return cli.err + } + res := reqres.Response.(tmsp.ResponseAppendTx) + return res.RetCode.Error() +} + +func (cli *TMSPClient) GetHashSync() (hash []byte, err error) { + reqres := cli.queueRequest(tmsp.RequestGetHash{}) + cli.FlushSync() + if cli.err != nil { + return nil, cli.err + } + res := reqres.Response.(tmsp.ResponseGetHash) + return res.Hash, res.RetCode.Error() +} + +func (cli *TMSPClient) QuerySync(query []byte) (result []byte, err error) { + reqres := cli.queueRequest(tmsp.RequestQuery{query}) + cli.FlushSync() + if cli.err != nil { + return nil, cli.err + } + res := reqres.Response.(tmsp.ResponseQuery) + return res.Result, res.RetCode.Error() +} + +//---------------------------------------- + +func (cli *TMSPClient) queueRequest(req tmsp.Request) *reqRes { + reqres := newReqRes(req) + // TODO: set cli.err if reqQueue times out + cli.reqQueue <- reqres + + // Maybe auto-flush, or unset auto-flush + switch req.(type) { + case tmsp.RequestFlush: + cli.flushTimer.Unset() + default: + cli.flushTimer.Set() + } + + return reqres +} + +//---------------------------------------- + +func resMatchesReq(req tmsp.Request, res tmsp.Response) (ok bool) { + switch req.(type) { + case tmsp.RequestEcho: + _, ok = res.(tmsp.ResponseEcho) + case tmsp.RequestFlush: + _, ok = res.(tmsp.ResponseFlush) + case tmsp.RequestInfo: + _, ok = res.(tmsp.ResponseInfo) + case tmsp.RequestSetOption: + _, ok = res.(tmsp.ResponseSetOption) + case tmsp.RequestAppendTx: + _, ok = res.(tmsp.ResponseAppendTx) + case tmsp.RequestCheckTx: + _, ok = res.(tmsp.ResponseCheckTx) + case tmsp.RequestGetHash: + _, ok = res.(tmsp.ResponseGetHash) + case tmsp.RequestAddListener: + _, ok = res.(tmsp.ResponseAddListener) + case tmsp.RequestRemListener: + _, ok = res.(tmsp.ResponseRemListener) + case tmsp.RequestQuery: + _, ok = res.(tmsp.ResponseQuery) + default: + return false + } + return +} + +type reqRes struct { + tmsp.Request + *sync.WaitGroup + tmsp.Response // Not set atomically, so be sure to use WaitGroup. +} + +func newReqRes(req tmsp.Request) *reqRes { + return &reqRes{ + Request: req, + WaitGroup: waitGroup1(), + Response: nil, + } +} + +func waitGroup1() (wg *sync.WaitGroup) { + wg = &sync.WaitGroup{} + wg.Add(1) + return +} diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index a623a95a..f27af780 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -23,8 +23,8 @@ var conn net.Conn func main() { app := cli.NewApp() - app.Name = "cli" - app.Usage = "cli [command] [args...]" + app.Name = "tmsp-cli" + app.Usage = "tmsp-cli [command] [args...]" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "address", @@ -89,6 +89,13 @@ func main() { cmdGetHash(c) }, }, + { + Name: "query", + Usage: "Query application state", + Action: func(c *cli.Context) { + cmdQuery(c) + }, + }, } app.Before = before app.Run(os.Args) @@ -234,6 +241,29 @@ func cmdGetHash(c *cli.Context) { fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash) } +// Query application state +func cmdQuery(c *cli.Context) { + args := c.Args() + if len(args) != 1 { + Exit("append_tx takes 1 argument") + } + queryString := args[0] + query := []byte(queryString) + if len(queryString) > 2 && strings.HasPrefix(queryString, "0x") { + var err error + query, err = hex.DecodeString(queryString[2:]) + if err != nil { + Exit(err.Error()) + } + } + + res, err := makeRequest(conn, types.RequestQuery{query}) + if err != nil { + Exit(err.Error()) + } + fmt.Println("->", res) +} + //-------------------------------------------------------------------------------- func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { From 53a8a40785fe6c8d68f4d842fe49a41236721ec8 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 22 Jan 2016 16:18:35 -0800 Subject: [PATCH 058/545] Swap Query return params --- example/golang/counter.go | 4 ++-- example/golang/dummy.go | 4 ++-- server/server.go | 2 +- types/application.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/golang/counter.go b/example/golang/counter.go index 46edcb41..434aa57b 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -77,6 +77,6 @@ func (app *CounterApplication) RemListener(key string) types.RetCode { return types.RetCodeOK } -func (app *CounterApplication) Query(query []byte) (types.RetCode, []byte) { - return types.RetCodeOK, nil +func (app *CounterApplication) Query(query []byte) ([]byte, types.RetCode) { + return nil, types.RetCodeOK } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 543e865b..899bb495 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -52,6 +52,6 @@ func (app *DummyApplication) RemListener(key string) types.RetCode { return types.RetCodeOK } -func (app *DummyApplication) Query(query []byte) (types.RetCode, []byte) { - return types.RetCodeOK, nil +func (app *DummyApplication) Query(query []byte) ([]byte, types.RetCode) { + return nil, types.RetCodeOK } diff --git a/server/server.go b/server/server.go index 8a6a16d9..f6aa2297 100644 --- a/server/server.go +++ b/server/server.go @@ -128,7 +128,7 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty retCode := app.RemListener(req.EventKey) responses <- types.ResponseRemListener{retCode} case types.RequestQuery: - retCode, result := app.Query(req.QueryBytes) + result, retCode := app.Query(req.QueryBytes) responses <- types.ResponseQuery{retCode, result} default: responses <- types.ResponseException{"Unknown request"} diff --git a/types/application.go b/types/application.go index 4a0818fd..b9bd1985 100644 --- a/types/application.go +++ b/types/application.go @@ -27,5 +27,5 @@ type Application interface { RemListener(key string) RetCode // Query for state - Query(query []byte) (RetCode, []byte) + Query(query []byte) ([]byte, RetCode) } From e2426d2944739866d9701570176e871fa5187d1b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 22 Jan 2016 17:56:56 -0800 Subject: [PATCH 059/545] Start TMSPClient automatically --- client/golang/client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/golang/client.go b/client/golang/client.go index 2dee848a..270bb95e 100644 --- a/client/golang/client.go +++ b/client/golang/client.go @@ -48,6 +48,7 @@ func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { resCb: nil, } cli.QuitService = *NewQuitService(nil, "TMSPClient", cli) + cli.Start() // Just start it, it's confusing for callers to remember to start. return cli } From c4b87dcf14e2fe3c95838688ca7747ae334e8c87 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 23 Jan 2016 20:49:15 -0800 Subject: [PATCH 060/545] new_message --- README.md | 30 ++++++------- types/messages.go | 108 +++++++++++++++++----------------------------- 2 files changed, 52 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 8924f57c..2991b534 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * `TxBytes ([]byte)` * __Returns__: * `RetCode (int8)` + * `RetData ([]KVPair)` + * `Error (string)` * __Usage__:
Append and run a transaction. The transaction may or may not be final. @@ -21,32 +23,17 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * `TxBytes ([]byte)` * __Returns__: * `RetCode (int8)` + * `RetData ([]KVPair)` + * `Error (string)` * __Usage__:
Validate a transaction. This message should not mutate the state. #### GetHash * __Returns__: - * `RetCode (int8)` * `Hash ([]byte)` * __Usage__:
Return a Merkle root hash of the application state -#### AddListener - * __Arguments__: - * `EventKey (string)` - * __Returns__: - * `RetCode (int8)` - * __Usage__:
- Add event listener callback for events with given key. - -#### RemoveListener - * __Arguments__: - * `EventKey (string)` - * __Returns__: - * `RetCode (int8)` - * __Usage__:
- Remove event listener callback for events with given key. - #### Flush * __Usage__:
Flush the response queue. Applications that implement `types.Application` need not implement this message -- it's handled by the project. @@ -62,13 +49,20 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * `Key (string)` * `Value (string)` * __Returns__: - * `RetCode (int8)` + * `Error (string)` * __Usage__:
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. ## Changelog +### Jan 23th, 2016 + +* Added CheckTx/Query TMSP message types +* Added RetData/Error fields to AppendTx/CheckTx/SetOption +* Removed Listener messages +* Removed RetCode from ResponseSetOption and ResponseGetHash + ### Jan 12th, 2016 * Added "RetCodeBadNonce = 0x06" return code diff --git a/types/messages.go b/types/messages.go index fa9b30d9..063e2a57 100644 --- a/types/messages.go +++ b/types/messages.go @@ -16,21 +16,15 @@ const ( ResponseTypeSetOption = byte(0x14) // reserved for GetOption = byte(0x15) - RequestTypeAppendTx = byte(0x21) - RequestTypeCheckTx = byte(0x22) - RequestTypeGetHash = byte(0x23) - RequestTypeAddListener = byte(0x24) - RequestTypeRemListener = byte(0x25) - // reserved for ResponseTypeEvent 0x26 - RequestTypeQuery = byte(0x27) + RequestTypeAppendTx = byte(0x21) + RequestTypeCheckTx = byte(0x22) + RequestTypeGetHash = byte(0x23) + RequestTypeQuery = byte(0x24) - ResponseTypeAppendTx = byte(0x31) - ResponseTypeCheckTx = byte(0x32) - ResponseTypeGetHash = byte(0x33) - ResponseTypeAddListener = byte(0x34) - ResponseTypeRemListener = byte(0x35) - ResponseTypeEvent = byte(0x36) - ResponseTypeQuery = byte(0x37) + ResponseTypeAppendTx = byte(0x31) + ResponseTypeCheckTx = byte(0x32) + ResponseTypeGetHash = byte(0x33) + ResponseTypeQuery = byte(0x34) ) //---------------------------------------- @@ -61,14 +55,6 @@ type RequestCheckTx struct { type RequestGetHash struct { } -type RequestAddListener struct { - EventKey string -} - -type RequestRemListener struct { - EventKey string -} - type RequestQuery struct { QueryBytes []byte } @@ -77,16 +63,14 @@ type Request interface { AssertRequestType() } -func (_ RequestEcho) AssertRequestType() {} -func (_ RequestFlush) AssertRequestType() {} -func (_ RequestInfo) AssertRequestType() {} -func (_ RequestSetOption) AssertRequestType() {} -func (_ RequestAppendTx) AssertRequestType() {} -func (_ RequestCheckTx) AssertRequestType() {} -func (_ RequestGetHash) AssertRequestType() {} -func (_ RequestAddListener) AssertRequestType() {} -func (_ RequestRemListener) AssertRequestType() {} -func (_ RequestQuery) AssertRequestType() {} +func (_ RequestEcho) AssertRequestType() {} +func (_ RequestFlush) AssertRequestType() {} +func (_ RequestInfo) AssertRequestType() {} +func (_ RequestSetOption) AssertRequestType() {} +func (_ RequestAppendTx) AssertRequestType() {} +func (_ RequestCheckTx) AssertRequestType() {} +func (_ RequestGetHash) AssertRequestType() {} +func (_ RequestQuery) AssertRequestType() {} var _ = wire.RegisterInterface( struct{ Request }{}, @@ -97,13 +81,20 @@ var _ = wire.RegisterInterface( wire.ConcreteType{RequestAppendTx{}, RequestTypeAppendTx}, wire.ConcreteType{RequestCheckTx{}, RequestTypeCheckTx}, wire.ConcreteType{RequestGetHash{}, RequestTypeGetHash}, - wire.ConcreteType{RequestAddListener{}, RequestTypeAddListener}, - wire.ConcreteType{RequestRemListener{}, RequestTypeRemListener}, wire.ConcreteType{RequestQuery{}, RequestTypeQuery}, ) //---------------------------------------- +type KVPair struct { + Key []byte + Value []byte +} + +type ResponseException struct { + Error string +} + type ResponseEcho struct { Message string } @@ -116,59 +107,43 @@ type ResponseInfo struct { } type ResponseSetOption struct { - RetCode + Error string } type ResponseAppendTx struct { RetCode + RetData []KVPair + Error string } type ResponseCheckTx struct { RetCode + RetData []KVPair + Error string } type ResponseGetHash struct { - RetCode Hash []byte } -type ResponseAddListener struct { - RetCode -} - -type ResponseRemListener struct { - RetCode -} - -type ResponseException struct { - Error string -} - -type ResponseEvent struct { - Event -} - type ResponseQuery struct { - RetCode Result []byte + Error string } type Response interface { AssertResponseType() } -func (_ ResponseEcho) AssertResponseType() {} -func (_ ResponseFlush) AssertResponseType() {} -func (_ ResponseInfo) AssertResponseType() {} -func (_ ResponseSetOption) AssertResponseType() {} -func (_ ResponseAppendTx) AssertResponseType() {} -func (_ ResponseCheckTx) AssertResponseType() {} -func (_ ResponseGetHash) AssertResponseType() {} -func (_ ResponseAddListener) AssertResponseType() {} -func (_ ResponseRemListener) AssertResponseType() {} -func (_ ResponseException) AssertResponseType() {} -func (_ ResponseEvent) AssertResponseType() {} -func (_ ResponseQuery) AssertResponseType() {} +func (_ ResponseEcho) AssertResponseType() {} +func (_ ResponseFlush) AssertResponseType() {} +func (_ ResponseInfo) AssertResponseType() {} +func (_ ResponseSetOption) AssertResponseType() {} +func (_ ResponseAppendTx) AssertResponseType() {} +func (_ ResponseCheckTx) AssertResponseType() {} +func (_ ResponseGetHash) AssertResponseType() {} +func (_ ResponseException) AssertResponseType() {} +func (_ ResponseQuery) AssertResponseType() {} var _ = wire.RegisterInterface( struct{ Response }{}, @@ -179,9 +154,6 @@ var _ = wire.RegisterInterface( wire.ConcreteType{ResponseAppendTx{}, ResponseTypeAppendTx}, wire.ConcreteType{ResponseCheckTx{}, ResponseTypeCheckTx}, wire.ConcreteType{ResponseGetHash{}, ResponseTypeGetHash}, - wire.ConcreteType{ResponseAddListener{}, ResponseTypeAddListener}, - wire.ConcreteType{ResponseRemListener{}, ResponseTypeRemListener}, wire.ConcreteType{ResponseException{}, ResponseTypeException}, - wire.ConcreteType{ResponseEvent{}, ResponseTypeEvent}, wire.ConcreteType{ResponseQuery{}, ResponseTypeQuery}, ) From 9696a71f6e5109c22510f16ba63682285da359d3 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 25 Jan 2016 08:01:18 -0800 Subject: [PATCH 061/545] Log not error; Remove Listener TMSP messages...; Make counter BigEndian --- README.md | 20 +-- client/{golang => }/client.go | 53 ++++--- example/golang/counter.go | 55 +++----- example/golang/dummy.go | 38 ++--- example/golang/dummy_test.go | 4 +- example/js/.gitignore | 1 + example/js/app.js | 77 +++++------ example/js/msgs.js | 141 +++++++++++-------- example/js/package.json | 10 ++ example/js/server.js | 251 ++++++++++++++++++---------------- example/js/types.js | 27 ++++ example/js/wire.js | 111 --------------- example/python/app.py | 1 + example/python3/app.py | 1 + server/server.go | 32 ++--- tests/test.sh | 9 +- tests/test_counter.sh | 19 +-- tests/test_dummy.sh | 12 +- types/application.go | 21 +-- types/events.go | 6 - types/messages.go | 24 ++-- types/retcode.go | 13 -- types/retcode_string.go | 4 +- 23 files changed, 417 insertions(+), 513 deletions(-) rename client/{golang => }/client.go (87%) create mode 100644 example/js/.gitignore create mode 100644 example/js/package.json create mode 100644 example/js/types.js delete mode 100644 example/js/wire.js mode change 100644 => 100755 tests/test.sh mode change 100644 => 100755 tests/test_counter.sh delete mode 100644 types/events.go diff --git a/README.md b/README.md index 2991b534..284d2af9 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * __Arguments__: * `TxBytes ([]byte)` * __Returns__: - * `RetCode (int8)` - * `RetData ([]KVPair)` - * `Error (string)` + * `Code (int8)` + * `Result ([]byte)` + * `Log (string)` * __Usage__:
Append and run a transaction. The transaction may or may not be final. @@ -22,15 +22,16 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * __Arguments__: * `TxBytes ([]byte)` * __Returns__: - * `RetCode (int8)` - * `RetData ([]KVPair)` - * `Error (string)` + * `Code (int8)` + * `Result ([]byte)` + * `Log (string)` * __Usage__:
Validate a transaction. This message should not mutate the state. #### GetHash * __Returns__: * `Hash ([]byte)` + * `Log (string)` * __Usage__:
Return a Merkle root hash of the application state @@ -49,7 +50,7 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog * `Key (string)` * `Value (string)` * __Returns__: - * `Error (string)` + * `Log (string)` * __Usage__:
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. @@ -59,9 +60,10 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog ### Jan 23th, 2016 * Added CheckTx/Query TMSP message types -* Added RetData/Error fields to AppendTx/CheckTx/SetOption +* Added Result/Log fields to AppendTx/CheckTx/SetOption * Removed Listener messages -* Removed RetCode from ResponseSetOption and ResponseGetHash +* Removed Code from ResponseSetOption and ResponseGetHash +* Made examples BigEndian ### Jan 12th, 2016 diff --git a/client/golang/client.go b/client/client.go similarity index 87% rename from client/golang/client.go rename to client/client.go index 270bb95e..d25348d1 100644 --- a/client/golang/client.go +++ b/client/client.go @@ -134,6 +134,7 @@ func (cli *TMSPClient) recvResponseRoutine() { } switch res := res.(type) { case tmsp.ResponseException: + // XXX After setting cli.err, release waiters (e.g. reqres.Done()) cli.StopForError(errors.New(res.Error)) default: // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) @@ -155,12 +156,6 @@ func (cli *TMSPClient) didRecvResponse(res tmsp.Response) error { cli.mtx.Lock() defer cli.mtx.Unlock() - // Special logic for events which have no corresponding requests. - if _, ok := res.(tmsp.ResponseEvent); ok && cli.resCb != nil { - cli.resCb(nil, res) - return nil - } - // Get the first reqRes next := cli.reqSent.Front() if next == nil { @@ -210,27 +205,19 @@ func (cli *TMSPClient) GetHashAsync() { cli.queueRequest(tmsp.RequestGetHash{}) } -func (cli *TMSPClient) AddListenerAsync(key string) { - cli.queueRequest(tmsp.RequestAddListener{key}) -} - -func (cli *TMSPClient) RemListenerAsync(key string) { - cli.queueRequest(tmsp.RequestRemListener{key}) -} - func (cli *TMSPClient) QueryAsync(query []byte) { cli.queueRequest(tmsp.RequestQuery{query}) } //---------------------------------------- -func (cli *TMSPClient) InfoSync() (info []string, err error) { +func (cli *TMSPClient) InfoSync() (info string, err error) { reqres := cli.queueRequest(tmsp.RequestInfo{}) cli.FlushSync() if cli.err != nil { - return nil, cli.err + return "", cli.err } - return reqres.Response.(tmsp.ResponseInfo).Data, nil + return reqres.Response.(tmsp.ResponseInfo).Info, nil } func (cli *TMSPClient) FlushSync() error { @@ -238,34 +225,44 @@ func (cli *TMSPClient) FlushSync() error { return cli.err } -func (cli *TMSPClient) AppendTxSync(tx []byte) error { +func (cli *TMSPClient) AppendTxSync(tx []byte) (code tmsp.RetCode, result []byte, log string, err error) { reqres := cli.queueRequest(tmsp.RequestAppendTx{tx}) cli.FlushSync() if cli.err != nil { - return cli.err + return tmsp.RetCodeInternalError, nil, "", cli.err } res := reqres.Response.(tmsp.ResponseAppendTx) - return res.RetCode.Error() + return res.Code, res.Result, res.Log, nil } -func (cli *TMSPClient) GetHashSync() (hash []byte, err error) { +func (cli *TMSPClient) CheckTxSync(tx []byte) (code tmsp.RetCode, result []byte, log string, err error) { + reqres := cli.queueRequest(tmsp.RequestCheckTx{tx}) + cli.FlushSync() + if cli.err != nil { + return tmsp.RetCodeInternalError, nil, "", cli.err + } + res := reqres.Response.(tmsp.ResponseCheckTx) + return res.Code, res.Result, res.Log, nil +} + +func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) { reqres := cli.queueRequest(tmsp.RequestGetHash{}) cli.FlushSync() if cli.err != nil { - return nil, cli.err + return nil, "", cli.err } res := reqres.Response.(tmsp.ResponseGetHash) - return res.Hash, res.RetCode.Error() + return res.Hash, res.Log, nil } -func (cli *TMSPClient) QuerySync(query []byte) (result []byte, err error) { +func (cli *TMSPClient) QuerySync(query []byte) (result []byte, log string, err error) { reqres := cli.queueRequest(tmsp.RequestQuery{query}) cli.FlushSync() if cli.err != nil { - return nil, cli.err + return nil, "", cli.err } res := reqres.Response.(tmsp.ResponseQuery) - return res.Result, res.RetCode.Error() + return res.Result, res.Log, nil } //---------------------------------------- @@ -304,10 +301,6 @@ func resMatchesReq(req tmsp.Request, res tmsp.Response) (ok bool) { _, ok = res.(tmsp.ResponseCheckTx) case tmsp.RequestGetHash: _, ok = res.(tmsp.ResponseGetHash) - case tmsp.RequestAddListener: - _, ok = res.(tmsp.ResponseAddListener) - case tmsp.RequestRemListener: - _, ok = res.(tmsp.ResponseRemListener) case tmsp.RequestQuery: _, ok = res.(tmsp.ResponseQuery) default: diff --git a/example/golang/counter.go b/example/golang/counter.go index 434aa57b..962c0760 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -2,6 +2,7 @@ package example import ( "encoding/binary" + "fmt" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" @@ -17,66 +18,54 @@ func NewCounterApplication(serial bool) *CounterApplication { return &CounterApplication{serial: serial} } -func (app *CounterApplication) Echo(message string) string { - return message +func (app *CounterApplication) Info() string { + return Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount) } -func (app *CounterApplication) Info() []string { - return []string{Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount)} -} - -func (app *CounterApplication) SetOption(key string, value string) types.RetCode { +func (app *CounterApplication) SetOption(key string, value string) (log string) { if key == "serial" && value == "on" { app.serial = true } - return types.RetCodeOK + return "" } -func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { +func (app *CounterApplication) AppendTx(tx []byte) (code types.RetCode, result []byte, log string) { if app.serial { tx8 := make([]byte, 8) - copy(tx8, tx) - txValue := binary.LittleEndian.Uint64(tx8) + copy(tx8[len(tx8)-len(tx):], tx) + txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return nil, types.RetCodeBadNonce + return types.RetCodeBadNonce, nil, fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue) } } app.txCount += 1 - return nil, types.RetCodeOK + return types.RetCodeOK, nil, "" } -func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { +func (app *CounterApplication) CheckTx(tx []byte) (code types.RetCode, result []byte, log string) { if app.serial { tx8 := make([]byte, 8) - copy(tx8, tx) - txValue := binary.LittleEndian.Uint64(tx8) + copy(tx8[len(tx8)-len(tx):], tx) + txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.RetCodeBadNonce + return types.RetCodeBadNonce, nil, fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue) } } - return types.RetCodeOK + return types.RetCodeOK, nil, "" } -func (app *CounterApplication) GetHash() ([]byte, types.RetCode) { +func (app *CounterApplication) GetHash() (hash []byte, log string) { app.hashCount += 1 if app.txCount == 0 { - return nil, types.RetCodeOK + return nil, "" } else { - hash := make([]byte, 32) - binary.LittleEndian.PutUint64(hash, uint64(app.txCount)) - return hash, types.RetCodeOK + hash := make([]byte, 8) + binary.BigEndian.PutUint64(hash, uint64(app.txCount)) + return hash, "" } } -func (app *CounterApplication) AddListener(key string) types.RetCode { - return types.RetCodeOK -} - -func (app *CounterApplication) RemListener(key string) types.RetCode { - return types.RetCodeOK -} - -func (app *CounterApplication) Query(query []byte) ([]byte, types.RetCode) { - return nil, types.RetCodeOK +func (app *CounterApplication) Query(query []byte) (result []byte, log string) { + return nil, fmt.Sprintf("Query is not supported") } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 899bb495..9835eeb8 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -18,40 +18,28 @@ func NewDummyApplication() *DummyApplication { return &DummyApplication{state: state} } -func (app *DummyApplication) Echo(message string) string { - return message +func (app *DummyApplication) Info() string { + return Fmt("size:%v", app.state.Size()) } -func (app *DummyApplication) Info() []string { - return []string{Fmt("size:%v", app.state.Size())} +func (app *DummyApplication) SetOption(key string, value string) (log string) { + return "" } -func (app *DummyApplication) SetOption(key string, value string) types.RetCode { - return types.RetCodeOK -} - -func (app *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { +func (app *DummyApplication) AppendTx(tx []byte) (code types.RetCode, result []byte, log string) { app.state.Set(tx, tx) - return nil, types.RetCodeOK + return types.RetCodeOK, nil, "" } -func (app *DummyApplication) CheckTx(tx []byte) types.RetCode { - return types.RetCodeOK // all txs are valid +func (app *DummyApplication) CheckTx(tx []byte) (code types.RetCode, result []byte, log string) { + return types.RetCodeOK, nil, "" } -func (app *DummyApplication) GetHash() ([]byte, types.RetCode) { - hash := app.state.Hash() - return hash, types.RetCodeOK +func (app *DummyApplication) GetHash() (hash []byte, log string) { + hash = app.state.Hash() + return hash, "" } -func (app *DummyApplication) AddListener(key string) types.RetCode { - return types.RetCodeOK -} - -func (app *DummyApplication) RemListener(key string) types.RetCode { - return types.RetCodeOK -} - -func (app *DummyApplication) Query(query []byte) ([]byte, types.RetCode) { - return nil, types.RetCodeOK +func (app *DummyApplication) Query(query []byte) (result []byte, log string) { + return nil, "Query not supported" } diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index d0d16ac9..ccf34f3f 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -44,8 +44,8 @@ func TestStream(t *testing.T) { switch res := res.(type) { case types.ResponseAppendTx: counter += 1 - if res.RetCode != types.RetCodeOK { - t.Error("AppendTx failed with ret_code", res.RetCode) + if res.Code != types.RetCodeOK { + t.Error("AppendTx failed with ret_code", res.Code) } if counter > numAppendTxs { t.Fatal("Too many AppendTx responses") diff --git a/example/js/.gitignore b/example/js/.gitignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/example/js/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/example/js/app.js b/example/js/app.js index bbdf0490..78804e22 100644 --- a/example/js/app.js +++ b/example/js/app.js @@ -1,6 +1,9 @@ -server = require("./server") -wire = require("./wire") -util = require("util") +var server = require("./server"); +var wire = require("js-wire"); +var util = require("util"); +var msg = require("./msgs"); +var types = require("./types"); + function CounterApp(){ this.hashCount = 0; @@ -8,75 +11,65 @@ function CounterApp(){ this.serial = false; }; -CounterApp.prototype.echo = function(msg){ - return {"response": msg, "ret_code":0} +CounterApp.prototype.info = function(cb) { + return cb(util.format("hashes:%d, txs:%d", this.hashCount, this.txCount)); } -CounterApp.prototype.info = function(){ - return {"response": [util.format("hashes:%d, txs:%d", this.hashCount, this.txCount)]} -} - -CounterApp.prototype.set_option = function(key, value){ - if (key == "serial" && value == "on"){ +CounterApp.prototype.set_option = function(cb, key, value) { + if (key == "serial" && value == "on") { this.serial = true; } - return {"ret_code":0} + return cb(""); } -CounterApp.prototype.append_tx = function(txBytes){ +CounterApp.prototype.append_tx = function(cb, txBytes) { if (this.serial) { - txByteArray = new Buffer(txBytes) if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { - txByteArray = wire.hex2bytes(txBytes.slice(2)); + var hexString = txBytes.toString("ascii", 2); + var hexBytes = new Buffer(hexString, "hex"); + txBytes = hexBytes; } - r = new msg.buffer(txByteArray) - txValue = wire.decode_big_endian(r, txBytes.length) + var txValue = txBytes.readIntBE(0, txBytes.length); if (txValue != this.txCount){ - return {"ret_code":6} + return cb(types.RetCodeInvalidNonce, "", "Nonce is invalid"); } } this.txCount += 1; - return {"ret_code":0} // TODO: return events + return cb(types.RetCodeOK, "", ""); } -CounterApp.prototype.check_tx = function(txBytes){ +CounterApp.prototype.check_tx = function(cb, txBytes) { if (this.serial) { - txByteArray = new Buffer(txBytes) if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { - txByteArray = wire.hex2bytes(txBytes.slice(2)); + var hexString = txBytes.toString("ascii", 2); + var hexBytes = new Buffer(hexString, "hex"); + txBytes = hexBytes; } - r = new msg.buffer(txByteArray) - txValue = wire.decode_big_endian(r, txBytes.length) + var txValue = txBytes.readIntBE(0, txBytes.length); if (txValue < this.txCount){ - return {"ret_code":6} + return cb(types.RetCodeInvalidNonce, "", "Nonce is too low"); } } - return {"ret_code":0} + this.txCount += 1; + return cb(types.RetCodeOK, "", ""); } -CounterApp.prototype.get_hash = function(){ +CounterApp.prototype.get_hash = function(cb) { this.hashCount += 1; if (this.txCount == 0){ - return {"response": "", "ret_code":0} + return cb("", "Zero tx count; hash is empth"); } - h = wire.encode_big_endian(this.txCount, 8); - h = wire.reverse(h); // TODO - return {"response": h.toString(), "ret_code":0} + var buf = new Buffer(8); + buf.writeIntBE(this.txCount, 0, 8); + cb(buf, ""); } -CounterApp.prototype.add_listener = function(){ - return {"ret_code":0} +CounterApp.prototype.query = function(cb) { + return cb("", "Query not yet supporrted"); } -CounterApp.prototype.rm_listener = function(){ - return {"ret_code":0} -} - -CounterApp.prototype.event = function(){ -} - -console.log("Counter app in Javascript") +console.log("Counter app in Javascript"); var app = new CounterApp(); var appServer = new server.AppServer(app); -appServer.server.listen(46658) +appServer.server.listen(46658); diff --git a/example/js/msgs.js b/example/js/msgs.js index 7993ca85..da3070ed 100644 --- a/example/js/msgs.js +++ b/example/js/msgs.js @@ -1,59 +1,88 @@ -wire = require("./wire") +var wire = require("js-wire"); +var types = require("./types"); + +var readRequestInfo = function(r) { return []; }; +var readRequestSetOption = function(r) { return [r.readString(), r.readString()]; }; +var readRequestAppendTx = function(r) { return [r.readByteArray()]; }; +var readRequestCheckTx = function(r) { return [r.readByteArray()]; }; +var readRequestGetHash = function(r) { return []; }; +var readRequestQuery = function(r) { return [r.readByteArray()]; }; + +var runOnce = function(name, f) { + var ran = false; + return function() { + if (ran) { + console.log("Error: response was already written for "+name); + return + } else { + ran = true; + } + return f.apply(this, arguments); + }; +}; + +var makeWriteResponseInfo = function(w, cb) { return runOnce("info", function(info) { + w.writeUint8(types.ResponseTypeInfo); + w.writeString(info); + cb(w); +});}; +var makeWriteResponseSetOption = function(w, cb) { return runOnce("set_option", function(log) { + w.writeUint8(types.ResponseTypeSetOption); + w.writeString(log); + cb(w); +});}; +var makeWriteResponseAppendTx = function(w, cb) { return runOnce("append_tx", function(code, result, log) { + w.writeUint8(types.ResponseTypeAppendTx); + w.writeUint8(code); + w.writeByteArray(result); + w.writeString(log); + cb(w); +});}; +var makeWriteResponseCheckTx = function(w, cb) { return runOnce("check_tx", function(code, result, log) { + w.writeUint8(types.ResponseTypeCheckTx); + w.writeUint8(code); + w.writeByteArray(result); + w.writeString(log); + cb(w); +});}; +var makeWriteResponseGetHash = function(w, cb) { return runOnce("get_hash", function(hash, log) { + w.writeUint8(types.ResponseTypeGetHash); + w.writeByteArray(hash); + w.writeString(log); + cb(w); +});}; +var makeWriteResponseQuery = function(w, cb) { return runOnce("query", function(result, log) { + w.writeUint8(types.ResponseTypeQuery); + w.writeByteArray(result); + w.writeString(log); + cb(w); +});}; module.exports = { - types : { - 0x01 : "echo", - 0x02 : "flush", - 0x03 : "info", - 0x04 : "set_option", - 0x21 : "append_tx", - 0x22 : "check_tx", - 0x23 : "get_hash", - 0x24 : "add_listener", - 0x25 : "rm_listener", - }, - decoder : RequestDecoder, - buffer: BytesBuffer -} - -function RequestDecoder(buf){ - this.buf= buf -} - -var decode_string = wire.decode_string - -// return nothing, one thing, or a list of things -RequestDecoder.prototype.echo = function(){ return decode_string(this.buf) }; -RequestDecoder.prototype.flush = function(){}; -RequestDecoder.prototype.info = function(){}; -RequestDecoder.prototype.set_option = function(){ return [decode_string(this.buf), decode_string(this.buf)] }; -RequestDecoder.prototype.append_tx = function(){ return decode_string(this.buf)}; -RequestDecoder.prototype.check_tx = function(){ return decode_string(this.buf)}; -RequestDecoder.prototype.get_hash = function(){ }; -RequestDecoder.prototype.add_listener = function(){ }; // TODO -RequestDecoder.prototype.rm_listener = function(){ }; // TODO - -// buffered reader with read(n) method -function BytesBuffer(buf){ - this.buf = buf -} - -BytesBuffer.prototype.read = function(n){ - b = this.buf.slice(0, n) - this.buf = this.buf.slice(n) - return b + types : { + 0x01 : "echo", + 0x02 : "flush", + 0x03 : "info", + 0x04 : "set_option", + 0x21 : "append_tx", + 0x22 : "check_tx", + 0x23 : "get_hash", + 0x24 : "query", + }, + readers : { + "info": readRequestInfo, + "set_option": readRequestSetOption, + "append_tx": readRequestAppendTx, + "check_tx": readRequestCheckTx, + "get_hash": readRequestGetHash, + "query": readRequestQuery, + }, + writerGenerators: { + "info": makeWriteResponseInfo, + "set_option": makeWriteResponseSetOption, + "append_tx": makeWriteResponseAppendTx, + "check_tx": makeWriteResponseCheckTx, + "get_hash": makeWriteResponseGetHash, + "query": makeWriteResponseQuery, + }, }; - -BytesBuffer.prototype.write = function(buf){ - this.buf = Buffer.concat([this.buf, buf]); -}; - - -BytesBuffer.prototype.size = function(){ - return this.buf.length -} - -BytesBuffer.prototype.peek = function(){ - return this.buf[0] -} - diff --git a/example/js/package.json b/example/js/package.json new file mode 100644 index 00000000..ed9bff31 --- /dev/null +++ b/example/js/package.json @@ -0,0 +1,10 @@ +{ + "name": "example", + "version": "0.0.1", + "description": "Example javascript TMSP application", + "main": "index.js", + "dependencies": { + "js-wire": "0.0.2" + } +} + diff --git a/example/js/server.js b/example/js/server.js index ab6e59cf..5ba30ea3 100644 --- a/example/js/server.js +++ b/example/js/server.js @@ -1,126 +1,141 @@ +var net = require("net"); +var wire = require("js-wire"); +var msg = require("./msgs"); +var types = require("./types"); -// Load the TCP Library -net = require('net'); -msg = require('./msgs'); -wire = require("./wire") +var maxWriteBufferLength = 4096; // Any more and flush -// Takes an application and handles tmsp connection +// Takes an application and handles TMSP connection // which invoke methods on the app function AppServer(app){ - // set the app for the socket handler - this.app = app; + // set the app for the socket handler + this.app = app; - // create a server by providing callback for - // accepting new connection and callbacks for - // connection events ('data', 'end', etc.) - this.createServer() + // create a server by providing callback for + // accepting new connection and callbacks for + // connection events ('data', 'end', etc.) + this.createServer(); } +AppServer.prototype.createServer = function() { + var app = this.app; + + // Define the socket handler + this.server = net.createServer(function(socket) { + socket.name = socket.remoteAddress + ":" + socket.remotePort; + console.log("new connection from", socket.name); + + var conn = new Connection(socket, function(msgBytes, cb) { + var r = new wire.Reader(msgBytes); + + // Now we can decode + var typeByte = r.readByte(); + var reqType = msg.types[typeByte]; + + // Special messages. + // NOTE: msgs are length prefixed + if (reqType == "flush") { + var w = new wire.Writer(); + w.writeByte(types.ResponseTypeFlush); + conn.writeMessage(w.getBuffer()); + conn.flush(); + return cb(); + } else if (reqType == "echo") { + var message = r.readString(); + var w = new wire.Writer(); + w.writeByte(types.ResponseTypeEcho); + w.writeString(message); + conn.writeMessage(w.getBuffer()); + return cb(); + } + + // Make callback by wrapping cp + var resCb = msg.writerGenerators[reqType](new wire.Writer(), function(w) { + conn.writeMessage(w.getBuffer()); + return cb(); + }); + + // Decode arguments + var args = msg.readers[reqType](r); + args.unshift(resCb); + + // Call function + var res = app[reqType].apply(app, args); + if (res != undefined) { + console.log("Message handler shouldn't return anything!"); + } + + }); + }); +} + +//---------------------------------------- + +function Connection(socket, msgCb) { + this.socket = socket; + this.recvBuf = new Buffer(0); + this.sendBuf = new Buffer(0); + this.msgCb = msgCb; + this.waitingResult = false; + var conn = this; + + // Handle TMSP requests. + socket.on('data', function(data) { + conn.appendData(data); + }); + socket.on('end', function() { + console.log("connection ended"); + }); +} + +Connection.prototype.appendData = function(bytes) { + var conn = this; + if (bytes.length > 0) { + this.recvBuf = Buffer.concat([this.recvBuf, new Buffer(bytes)]); + } + if (this.waitingResult) { + return; + } + var r = new wire.Reader(this.recvBuf); + var msg; + try { + msg = r.readByteArray(); + } catch(e) { + return; + } + this.recvBuf = r.buf.slice(r.offset); + this.waitingResult = true; + this.socket.pause(); + //try { + this.msgCb(msg, function() { + // This gets called after msg handler is finished with response. + conn.waitingResult = false; + conn.socket.resume(); + if (conn.recvBuf.length > 0) { + conn.appendData(""); + } + }); + //} catch(e) { + // console.log("FATAL ERROR: ", e); + //} +}; + +Connection.prototype.writeMessage = function(msgBytes) { + var msgLength = wire.uvarintSize(msgBytes.length); + var buf = new Buffer(1+msgLength+msgBytes.length); + var w = new wire.Writer(buf); + w.writeByteArray(msgBytes); // TODO technically should be writeVarint + this.sendBuf = Buffer.concat([this.sendBuf, w.getBuffer()]); + if (this.sendBuf.length >= maxWriteBufferLength) { + this.flush(); + } +}; + +Connection.prototype.flush = function() { + var n = this.socket.write(this.sendBuf); + this.sendBuf = new Buffer(0); +} + +//---------------------------------------- + module.exports = { AppServer: AppServer }; - -AppServer.prototype.createServer = function(){ - app = this.app - conns = {} // map sockets to their state - - // define the socket handler - this.server = net.createServer(function(socket){ - socket.name = socket.remoteAddress + ":" + socket.remotePort - console.log("new connection from", socket.name) - - var conn = { - recBuf: new msg.buffer(new Buffer(0)), - resBuf: new msg.buffer(new Buffer(0)), - msgLength: 0, - inProgress: false - } - conns[socket] = conn - - // Handle tmsp requests. - socket.on('data', function (data) { - - if (data.length == 0){ - // TODO err - console.log("empty data!") - return - } - conn = conns[socket] - - // we received data. append it - conn.recBuf.write(data) - - while ( conn.recBuf.size() > 0 ){ - - if (conn.msgLength == 0){ - ll = conn.recBuf.peek(); - if (conn.recBuf.size() < 1 + ll){ - // don't have enough bytes to read length yet - return - } - conn.msgLength = wire.decode_varint(conn.recBuf) - } - - if (conn.recBuf.size() < conn.msgLength) { - // don't have enough to decode the message - return - } - - // now we can decode - typeByte = conn.recBuf.read(1); - resTypeByte = typeByte[0] + 0x10 - reqType = msg.types[typeByte[0]]; - - if (reqType == "flush"){ - // msgs are length prefixed - conn.resBuf.write(wire.encode(1)); - conn.resBuf.write(new Buffer([resTypeByte])) - n = socket.write(conn.resBuf.buf); - conn.msgLength = 0; - conn.resBuf = new msg.buffer(new Buffer(0)); - return - } - - // decode args - decoder = new msg.decoder(conn.recBuf); - args = decoder[reqType](); - - // done decoding - conn.msgLength = 0 - - var res = function(){ - if (args == null){ - return app[reqType](); - } else if (Array.isArray(args)){ - return app[reqType].apply(app, args); - } else { - return app[reqType](args) - } - }() - - - var retCode = res["ret_code"] - var res = res["response"] - - if (retCode != null && retCode != 0){ - console.log("non-zero ret code", retCode) - } - - - if (reqType == "echo" || reqType == "info"){ - enc = Buffer.concat([new Buffer([resTypeByte]), wire.encode(res)]); - // length prefixed - conn.resBuf.write(wire.encode(enc.length)); - conn.resBuf.write(enc); - } else { - enc = Buffer.concat([new Buffer([resTypeByte]), wire.encode(retCode), wire.encode(res)]); - conn.resBuf.write(wire.encode(enc.length)); - conn.resBuf.write(enc); - } - } - }); - - socket.on('end', function () { - console.log("connection ended") - }); - }) -} - diff --git a/example/js/types.js b/example/js/types.js new file mode 100644 index 00000000..d22d8f21 --- /dev/null +++ b/example/js/types.js @@ -0,0 +1,27 @@ +module.exports = { + RetCodeOK: 0, + RetCodeInternalError: 1, + RetCodeUnauthorized: 2, + RetCodeInsufficientFees: 3, + RetCodeUnknownRequest: 4, + RetCodeEncodingError: 5, + RetCodeNonce: 6, + + RequestTypeEcho: 0x01, + RequestTypeFlush: 0x02, + RequestTypeInfo: 0x03, + RequestTypeSetOption: 0x04, + RequestTypeAppendTx: 0x21, + RequestTypeCheckTx: 0x22, + RequestTypeGetHash: 0x23, + RequestTypeQuery: 0x24, + + ResponseTypeEcho: 0x11, + ResponseTypeFlush: 0x12, + ResponseTypeInfo: 0x13, + ResponseTypeSetOption: 0x14, + ResponseTypeAppendTx: 0x31, + ResponseTypeCheckTx: 0x32, + ResponseTypeGetHash: 0x33, + ResponseTypeQuery: 0x34, +}; diff --git a/example/js/wire.js b/example/js/wire.js deleted file mode 100644 index 42c30867..00000000 --- a/example/js/wire.js +++ /dev/null @@ -1,111 +0,0 @@ -module.exports = { - decode_string: decode_string, - decode_varint: decode_varint, - decode_big_endian: decode_big_endian, - encode_big_endian: encode_big_endian, - encode: encode, - reverse: reverse, -} - -function reverse(buf){ - for (var i = 0; i < buf.length/2; i++){ - a = buf[i]; - b = buf[buf.length-1 - i]; - buf[i] = b; - buf[buf.length-1 - i] = a; - } - return buf -} - -function uvarint_size(i){ - if (i == 0){ - return 0 - } - - for(var j = 1; j < 9; j++) { - if ( i < 1< 0xF0){ negate = true } - if (negate) { size = size - 0xF0 } - i = decode_big_endian(reader, size); - if (negate) { i = i * -1} - return i -} - -function encode_list(l){ - var l2 = l.map(encode); - var buf = new Buffer(encode_varint(l2.length)); - return Buffer.concat([buf, Buffer.concat(l2)]); -} - -function encode(b){ - if (b == null){ - return Buffer(0) - } else if (typeof b == "number"){ - return encode_varint(b) - } else if (typeof b == "string"){ - return encode_string(b) - } else if (Array.isArray(b)){ - return encode_list(b) - } else{ - console.log("UNSUPPORTED TYPE!", typeof b, b) - } -} - - - - - diff --git a/example/python/app.py b/example/python/app.py index 49831ef5..8eda9020 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -8,6 +8,7 @@ from tmsp.reader import BytesBuffer class CounterApplication(): def __init__(self): + sys.exit("The python example is out of date. Upgrading the Python examples is currently left as an exercise to you.") self.hashCount = 0 self.txCount = 0 self.serial = False diff --git a/example/python3/app.py b/example/python3/app.py index b3616327..01f3de0b 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -8,6 +8,7 @@ from tmsp.reader import BytesBuffer class CounterApplication(): def __init__(self): + sys.exit("The python example is out of date. Upgrading the Python examples is currently left as an exercise to you.") self.hashCount = 0 self.txCount = 0 self.serial = False diff --git a/server/server.go b/server/server.go index f6aa2297..b6d0e3f1 100644 --- a/server/server.go +++ b/server/server.go @@ -99,37 +99,27 @@ func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) { switch req := req.(type) { case types.RequestEcho: - msg := app.Echo(req.Message) - responses <- types.ResponseEcho{msg} + responses <- types.ResponseEcho{req.Message} case types.RequestFlush: responses <- types.ResponseFlush{} case types.RequestInfo: data := app.Info() responses <- types.ResponseInfo{data} case types.RequestSetOption: - retCode := app.SetOption(req.Key, req.Value) - responses <- types.ResponseSetOption{retCode} + logstr := app.SetOption(req.Key, req.Value) + responses <- types.ResponseSetOption{logstr} case types.RequestAppendTx: - events, retCode := app.AppendTx(req.TxBytes) - responses <- types.ResponseAppendTx{retCode} - for _, event := range events { - responses <- types.ResponseEvent{event} - } + code, result, logstr := app.AppendTx(req.TxBytes) + responses <- types.ResponseAppendTx{code, result, logstr} case types.RequestCheckTx: - retCode := app.CheckTx(req.TxBytes) - responses <- types.ResponseCheckTx{retCode} + code, result, logstr := app.CheckTx(req.TxBytes) + responses <- types.ResponseCheckTx{code, result, logstr} case types.RequestGetHash: - hash, retCode := app.GetHash() - responses <- types.ResponseGetHash{retCode, hash} - case types.RequestAddListener: - retCode := app.AddListener(req.EventKey) - responses <- types.ResponseAddListener{retCode} - case types.RequestRemListener: - retCode := app.RemListener(req.EventKey) - responses <- types.ResponseRemListener{retCode} + hash, logstr := app.GetHash() + responses <- types.ResponseGetHash{hash, logstr} case types.RequestQuery: - result, retCode := app.Query(req.QueryBytes) - responses <- types.ResponseQuery{retCode, result} + result, logstr := app.Query(req.QueryBytes) + responses <- types.ResponseQuery{result, logstr} default: responses <- types.ResponseException{"Unknown request"} } diff --git a/tests/test.sh b/tests/test.sh old mode 100644 new mode 100755 index 9ee9be13..c99f92dc --- a/tests/test.sh +++ b/tests/test.sh @@ -8,10 +8,11 @@ bash tests/test_dummy.sh # test golang counter bash tests/test_counter.sh +# test js counter +cd example/js +COUNTER_APP="node app.js" bash $ROOT/tests/test_counter.sh + # test python counter -cd example/python +cd ../python COUNTER_APP="python app.py" bash $ROOT/tests/test_counter.sh -# test js counter -cd ../js -COUNTER_APP="node app.js" bash $ROOT/tests/test_counter.sh diff --git a/tests/test_counter.sh b/tests/test_counter.sh old mode 100644 new mode 100755 index 99af772c..53edab3b --- a/tests/test_counter.sh +++ b/tests/test_counter.sh @@ -1,3 +1,12 @@ +#! /bin/bash +function finish { + echo "Cleaning up..." + ps -p $PID > /dev/null + if [[ "$?" == "0" ]]; then + kill -9 $PID + fi +} +trap finish EXIT # so we can test other languages if [[ "$COUNTER_APP" == "" ]]; then @@ -55,21 +64,15 @@ fi HASH1=`echo "$OUTPUT" | tail -n +3 | head -n 1` HASH2=`echo "$OUTPUT" | tail -n +5 | head -n 1` -if [[ "${HASH1:0:2}" != "01" ]]; then +if [[ "${HASH1: -2}" != "01" ]]; then echo "Expected hash to lead with 01. Got $HASH1" exit 1 fi -if [[ "${HASH2:0:2}" != "02" ]]; then +if [[ "${HASH2: -2}" != "02" ]]; then echo "Expected hash to lead with 02. Got $HASH2" exit 1 fi echo "... Pass!" echo "" - -ps -p $PID > /dev/null -if [[ "$?" == "0" ]]; then - kill -9 $PID -fi - diff --git a/tests/test_dummy.sh b/tests/test_dummy.sh index f0209a89..ac8c62ac 100755 --- a/tests/test_dummy.sh +++ b/tests/test_dummy.sh @@ -1,4 +1,12 @@ #! /bin/bash +function finish { + echo "Cleaning up..." + ps -p $PID > /dev/null + if [[ "$?" == "0" ]]; then + kill -9 $PID + fi +} +trap finish EXIT # Make sure the tmsp cli can connect to the dummy echo "Dummy test ..." @@ -51,7 +59,3 @@ if [[ "$HASH1" != "$RESULT_HASH" ]]; then fi echo "... Pass!" echo "" - - -kill $PID -sleep 1 diff --git a/types/application.go b/types/application.go index b9bd1985..cedf1240 100644 --- a/types/application.go +++ b/types/application.go @@ -2,30 +2,21 @@ package types type Application interface { - // Echo a message - Echo(message string) string - // Return application info - Info() []string + Info() (info string) // Set application option (e.g. mode=mempool, mode=consensus) - SetOption(key string, value string) RetCode + SetOption(key string, value string) (log string) // Append a tx - AppendTx(tx []byte) ([]Event, RetCode) + AppendTx(tx []byte) (code RetCode, result []byte, log string) // Validate a tx for the mempool - CheckTx(tx []byte) RetCode + CheckTx(tx []byte) (code RetCode, result []byte, log string) // Return the application Merkle root hash - GetHash() ([]byte, RetCode) - - // Add event listener - AddListener(key string) RetCode - - // Remove event listener - RemListener(key string) RetCode + GetHash() (hash []byte, log string) // Query for state - Query(query []byte) ([]byte, RetCode) + Query(query []byte) (result []byte, log string) } diff --git a/types/events.go b/types/events.go deleted file mode 100644 index d1ba5f1f..00000000 --- a/types/events.go +++ /dev/null @@ -1,6 +0,0 @@ -package types - -type Event struct { - Key string - Data []byte -} diff --git a/types/messages.go b/types/messages.go index 063e2a57..0e05706d 100644 --- a/types/messages.go +++ b/types/messages.go @@ -86,11 +86,6 @@ var _ = wire.RegisterInterface( //---------------------------------------- -type KVPair struct { - Key []byte - Value []byte -} - type ResponseException struct { Error string } @@ -103,32 +98,33 @@ type ResponseFlush struct { } type ResponseInfo struct { - Data []string + Info string } type ResponseSetOption struct { - Error string + Log string } type ResponseAppendTx struct { - RetCode - RetData []KVPair - Error string + Code RetCode + Result []byte + Log string } type ResponseCheckTx struct { - RetCode - RetData []KVPair - Error string + Code RetCode + Result []byte + Log string } type ResponseGetHash struct { Hash []byte + Log string } type ResponseQuery struct { Result []byte - Error string + Log string } type Response interface { diff --git a/types/retcode.go b/types/retcode.go index 8f3ad5bf..05e49a2e 100644 --- a/types/retcode.go +++ b/types/retcode.go @@ -1,9 +1,5 @@ package types -import ( - "errors" -) - type RetCode int // Reserved return codes @@ -17,15 +13,6 @@ const ( RetCodeBadNonce RetCode = 6 ) -func (r RetCode) Error() error { - switch r { - case RetCodeOK: - return nil - default: - return errors.New(r.String()) - } -} - //go:generate stringer -type=RetCode // NOTE: The previous comment generates r.String(). diff --git a/types/retcode_string.go b/types/retcode_string.go index 65457041..0f30688b 100644 --- a/types/retcode_string.go +++ b/types/retcode_string.go @@ -4,9 +4,9 @@ package types import "fmt" -const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingErrorRetCodeInvalidNonce" +const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingErrorRetCodeBadNonce" -var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112, 131} +var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112, 127} func (i RetCode) String() string { if i < 0 || i >= RetCode(len(_RetCode_index)-1) { From b21c6b5e5b8e35e2cd78e75324f5035bad546dc9 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 25 Jan 2016 14:15:17 -0800 Subject: [PATCH 062/545] s/logstr/logStr/g --- server/server.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/server/server.go b/server/server.go index b6d0e3f1..7c2a7c4c 100644 --- a/server/server.go +++ b/server/server.go @@ -106,20 +106,20 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty data := app.Info() responses <- types.ResponseInfo{data} case types.RequestSetOption: - logstr := app.SetOption(req.Key, req.Value) - responses <- types.ResponseSetOption{logstr} + logStr := app.SetOption(req.Key, req.Value) + responses <- types.ResponseSetOption{logStr} case types.RequestAppendTx: - code, result, logstr := app.AppendTx(req.TxBytes) - responses <- types.ResponseAppendTx{code, result, logstr} + code, result, logStr := app.AppendTx(req.TxBytes) + responses <- types.ResponseAppendTx{code, result, logStr} case types.RequestCheckTx: - code, result, logstr := app.CheckTx(req.TxBytes) - responses <- types.ResponseCheckTx{code, result, logstr} + code, result, logStr := app.CheckTx(req.TxBytes) + responses <- types.ResponseCheckTx{code, result, logStr} case types.RequestGetHash: - hash, logstr := app.GetHash() - responses <- types.ResponseGetHash{hash, logstr} + hash, logStr := app.GetHash() + responses <- types.ResponseGetHash{hash, logStr} case types.RequestQuery: - result, logstr := app.Query(req.QueryBytes) - responses <- types.ResponseQuery{result, logstr} + result, logStr := app.Query(req.QueryBytes) + responses <- types.ResponseQuery{result, logStr} default: responses <- types.ResponseException{"Unknown request"} } From 799ae4c006b5f6667d975e9932a07ee11566c1d2 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 29 Jan 2016 11:47:13 -0800 Subject: [PATCH 063/545] Move js example to js-tmsp/example --- example/js/README.md | 1 + example/js/app.js | 75 --------------------- example/js/msgs.js | 88 ------------------------- example/js/package.json | 10 --- example/js/server.js | 141 ---------------------------------------- example/js/types.js | 27 -------- 6 files changed, 1 insertion(+), 341 deletions(-) create mode 100644 example/js/README.md delete mode 100644 example/js/app.js delete mode 100644 example/js/msgs.js delete mode 100644 example/js/package.json delete mode 100644 example/js/server.js delete mode 100644 example/js/types.js diff --git a/example/js/README.md b/example/js/README.md new file mode 100644 index 00000000..f1875506 --- /dev/null +++ b/example/js/README.md @@ -0,0 +1 @@ +This example has been moved here: https://github.com/tendermint/js-tmsp/tree/master/example diff --git a/example/js/app.js b/example/js/app.js deleted file mode 100644 index 78804e22..00000000 --- a/example/js/app.js +++ /dev/null @@ -1,75 +0,0 @@ -var server = require("./server"); -var wire = require("js-wire"); -var util = require("util"); -var msg = require("./msgs"); -var types = require("./types"); - - -function CounterApp(){ - this.hashCount = 0; - this.txCount = 0; - this.serial = false; -}; - -CounterApp.prototype.info = function(cb) { - return cb(util.format("hashes:%d, txs:%d", this.hashCount, this.txCount)); -} - -CounterApp.prototype.set_option = function(cb, key, value) { - if (key == "serial" && value == "on") { - this.serial = true; - } - return cb(""); -} - -CounterApp.prototype.append_tx = function(cb, txBytes) { - if (this.serial) { - if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { - var hexString = txBytes.toString("ascii", 2); - var hexBytes = new Buffer(hexString, "hex"); - txBytes = hexBytes; - } - var txValue = txBytes.readIntBE(0, txBytes.length); - if (txValue != this.txCount){ - return cb(types.RetCodeInvalidNonce, "", "Nonce is invalid"); - } - } - this.txCount += 1; - return cb(types.RetCodeOK, "", ""); -} - -CounterApp.prototype.check_tx = function(cb, txBytes) { - if (this.serial) { - if (txBytes.length >= 2 && txBytes.slice(0, 2) == "0x") { - var hexString = txBytes.toString("ascii", 2); - var hexBytes = new Buffer(hexString, "hex"); - txBytes = hexBytes; - } - var txValue = txBytes.readIntBE(0, txBytes.length); - if (txValue < this.txCount){ - return cb(types.RetCodeInvalidNonce, "", "Nonce is too low"); - } - } - this.txCount += 1; - return cb(types.RetCodeOK, "", ""); -} - -CounterApp.prototype.get_hash = function(cb) { - this.hashCount += 1; - if (this.txCount == 0){ - return cb("", "Zero tx count; hash is empth"); - } - var buf = new Buffer(8); - buf.writeIntBE(this.txCount, 0, 8); - cb(buf, ""); -} - -CounterApp.prototype.query = function(cb) { - return cb("", "Query not yet supporrted"); -} - -console.log("Counter app in Javascript"); - -var app = new CounterApp(); -var appServer = new server.AppServer(app); -appServer.server.listen(46658); diff --git a/example/js/msgs.js b/example/js/msgs.js deleted file mode 100644 index da3070ed..00000000 --- a/example/js/msgs.js +++ /dev/null @@ -1,88 +0,0 @@ -var wire = require("js-wire"); -var types = require("./types"); - -var readRequestInfo = function(r) { return []; }; -var readRequestSetOption = function(r) { return [r.readString(), r.readString()]; }; -var readRequestAppendTx = function(r) { return [r.readByteArray()]; }; -var readRequestCheckTx = function(r) { return [r.readByteArray()]; }; -var readRequestGetHash = function(r) { return []; }; -var readRequestQuery = function(r) { return [r.readByteArray()]; }; - -var runOnce = function(name, f) { - var ran = false; - return function() { - if (ran) { - console.log("Error: response was already written for "+name); - return - } else { - ran = true; - } - return f.apply(this, arguments); - }; -}; - -var makeWriteResponseInfo = function(w, cb) { return runOnce("info", function(info) { - w.writeUint8(types.ResponseTypeInfo); - w.writeString(info); - cb(w); -});}; -var makeWriteResponseSetOption = function(w, cb) { return runOnce("set_option", function(log) { - w.writeUint8(types.ResponseTypeSetOption); - w.writeString(log); - cb(w); -});}; -var makeWriteResponseAppendTx = function(w, cb) { return runOnce("append_tx", function(code, result, log) { - w.writeUint8(types.ResponseTypeAppendTx); - w.writeUint8(code); - w.writeByteArray(result); - w.writeString(log); - cb(w); -});}; -var makeWriteResponseCheckTx = function(w, cb) { return runOnce("check_tx", function(code, result, log) { - w.writeUint8(types.ResponseTypeCheckTx); - w.writeUint8(code); - w.writeByteArray(result); - w.writeString(log); - cb(w); -});}; -var makeWriteResponseGetHash = function(w, cb) { return runOnce("get_hash", function(hash, log) { - w.writeUint8(types.ResponseTypeGetHash); - w.writeByteArray(hash); - w.writeString(log); - cb(w); -});}; -var makeWriteResponseQuery = function(w, cb) { return runOnce("query", function(result, log) { - w.writeUint8(types.ResponseTypeQuery); - w.writeByteArray(result); - w.writeString(log); - cb(w); -});}; - -module.exports = { - types : { - 0x01 : "echo", - 0x02 : "flush", - 0x03 : "info", - 0x04 : "set_option", - 0x21 : "append_tx", - 0x22 : "check_tx", - 0x23 : "get_hash", - 0x24 : "query", - }, - readers : { - "info": readRequestInfo, - "set_option": readRequestSetOption, - "append_tx": readRequestAppendTx, - "check_tx": readRequestCheckTx, - "get_hash": readRequestGetHash, - "query": readRequestQuery, - }, - writerGenerators: { - "info": makeWriteResponseInfo, - "set_option": makeWriteResponseSetOption, - "append_tx": makeWriteResponseAppendTx, - "check_tx": makeWriteResponseCheckTx, - "get_hash": makeWriteResponseGetHash, - "query": makeWriteResponseQuery, - }, -}; diff --git a/example/js/package.json b/example/js/package.json deleted file mode 100644 index ed9bff31..00000000 --- a/example/js/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "example", - "version": "0.0.1", - "description": "Example javascript TMSP application", - "main": "index.js", - "dependencies": { - "js-wire": "0.0.2" - } -} - diff --git a/example/js/server.js b/example/js/server.js deleted file mode 100644 index 5ba30ea3..00000000 --- a/example/js/server.js +++ /dev/null @@ -1,141 +0,0 @@ -var net = require("net"); -var wire = require("js-wire"); -var msg = require("./msgs"); -var types = require("./types"); - -var maxWriteBufferLength = 4096; // Any more and flush - -// Takes an application and handles TMSP connection -// which invoke methods on the app -function AppServer(app){ - // set the app for the socket handler - this.app = app; - - // create a server by providing callback for - // accepting new connection and callbacks for - // connection events ('data', 'end', etc.) - this.createServer(); -} - -AppServer.prototype.createServer = function() { - var app = this.app; - - // Define the socket handler - this.server = net.createServer(function(socket) { - socket.name = socket.remoteAddress + ":" + socket.remotePort; - console.log("new connection from", socket.name); - - var conn = new Connection(socket, function(msgBytes, cb) { - var r = new wire.Reader(msgBytes); - - // Now we can decode - var typeByte = r.readByte(); - var reqType = msg.types[typeByte]; - - // Special messages. - // NOTE: msgs are length prefixed - if (reqType == "flush") { - var w = new wire.Writer(); - w.writeByte(types.ResponseTypeFlush); - conn.writeMessage(w.getBuffer()); - conn.flush(); - return cb(); - } else if (reqType == "echo") { - var message = r.readString(); - var w = new wire.Writer(); - w.writeByte(types.ResponseTypeEcho); - w.writeString(message); - conn.writeMessage(w.getBuffer()); - return cb(); - } - - // Make callback by wrapping cp - var resCb = msg.writerGenerators[reqType](new wire.Writer(), function(w) { - conn.writeMessage(w.getBuffer()); - return cb(); - }); - - // Decode arguments - var args = msg.readers[reqType](r); - args.unshift(resCb); - - // Call function - var res = app[reqType].apply(app, args); - if (res != undefined) { - console.log("Message handler shouldn't return anything!"); - } - - }); - }); -} - -//---------------------------------------- - -function Connection(socket, msgCb) { - this.socket = socket; - this.recvBuf = new Buffer(0); - this.sendBuf = new Buffer(0); - this.msgCb = msgCb; - this.waitingResult = false; - var conn = this; - - // Handle TMSP requests. - socket.on('data', function(data) { - conn.appendData(data); - }); - socket.on('end', function() { - console.log("connection ended"); - }); -} - -Connection.prototype.appendData = function(bytes) { - var conn = this; - if (bytes.length > 0) { - this.recvBuf = Buffer.concat([this.recvBuf, new Buffer(bytes)]); - } - if (this.waitingResult) { - return; - } - var r = new wire.Reader(this.recvBuf); - var msg; - try { - msg = r.readByteArray(); - } catch(e) { - return; - } - this.recvBuf = r.buf.slice(r.offset); - this.waitingResult = true; - this.socket.pause(); - //try { - this.msgCb(msg, function() { - // This gets called after msg handler is finished with response. - conn.waitingResult = false; - conn.socket.resume(); - if (conn.recvBuf.length > 0) { - conn.appendData(""); - } - }); - //} catch(e) { - // console.log("FATAL ERROR: ", e); - //} -}; - -Connection.prototype.writeMessage = function(msgBytes) { - var msgLength = wire.uvarintSize(msgBytes.length); - var buf = new Buffer(1+msgLength+msgBytes.length); - var w = new wire.Writer(buf); - w.writeByteArray(msgBytes); // TODO technically should be writeVarint - this.sendBuf = Buffer.concat([this.sendBuf, w.getBuffer()]); - if (this.sendBuf.length >= maxWriteBufferLength) { - this.flush(); - } -}; - -Connection.prototype.flush = function() { - var n = this.socket.write(this.sendBuf); - this.sendBuf = new Buffer(0); -} - -//---------------------------------------- - -module.exports = { AppServer: AppServer }; diff --git a/example/js/types.js b/example/js/types.js deleted file mode 100644 index d22d8f21..00000000 --- a/example/js/types.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - RetCodeOK: 0, - RetCodeInternalError: 1, - RetCodeUnauthorized: 2, - RetCodeInsufficientFees: 3, - RetCodeUnknownRequest: 4, - RetCodeEncodingError: 5, - RetCodeNonce: 6, - - RequestTypeEcho: 0x01, - RequestTypeFlush: 0x02, - RequestTypeInfo: 0x03, - RequestTypeSetOption: 0x04, - RequestTypeAppendTx: 0x21, - RequestTypeCheckTx: 0x22, - RequestTypeGetHash: 0x23, - RequestTypeQuery: 0x24, - - ResponseTypeEcho: 0x11, - ResponseTypeFlush: 0x12, - ResponseTypeInfo: 0x13, - ResponseTypeSetOption: 0x14, - ResponseTypeAppendTx: 0x31, - ResponseTypeCheckTx: 0x32, - ResponseTypeGetHash: 0x33, - ResponseTypeQuery: 0x34, -}; From 6132ad7d6e8df6790b153babf838c1b1fdda45e2 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 29 Jan 2016 16:06:39 -0800 Subject: [PATCH 064/545] Do not exit upon error, for tmsp-cli console --- cmd/tmsp-cli/tmsp-cli.go | 57 ++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index f27af780..4aed1f1e 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -120,13 +120,15 @@ func cmdBatch(app *cli.App, c *cli.Context) { for { line, more, err := bufReader.ReadLine() if more { - Exit("input line is too long") + fmt.Println("input line is too long") + return } else if err == io.EOF { break } else if len(line) == 0 { continue } else if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } args := []string{"tmsp"} args = append(args, strings.Split(string(line), " ")...) @@ -140,9 +142,11 @@ func cmdConsole(app *cli.App, c *cli.Context) { bufReader := bufio.NewReader(os.Stdin) line, more, err := bufReader.ReadLine() if more { - Exit("input is too long") + fmt.Println("input is too long") + return } else if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } args := []string{"tmsp"} @@ -155,11 +159,13 @@ func cmdConsole(app *cli.App, c *cli.Context) { func cmdEcho(c *cli.Context) { args := c.Args() if len(args) != 1 { - Exit("echo takes 1 argument") + fmt.Println("echo takes 1 argument") + return } res, err := makeRequest(conn, types.RequestEcho{args[0]}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Println("->", res) } @@ -168,7 +174,8 @@ func cmdEcho(c *cli.Context) { func cmdInfo(c *cli.Context) { res, err := makeRequest(conn, types.RequestInfo{}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Println("->", res) } @@ -177,11 +184,13 @@ func cmdInfo(c *cli.Context) { func cmdSetOption(c *cli.Context) { args := c.Args() if len(args) != 2 { - Exit("set_option takes 2 arguments (key, value)") + fmt.Println("set_option takes 2 arguments (key, value)") + return } _, err := makeRequest(conn, types.RequestSetOption{args[0], args[1]}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Println("->", Fmt("%s=%s", args[0], args[1])) } @@ -190,7 +199,8 @@ func cmdSetOption(c *cli.Context) { func cmdAppendTx(c *cli.Context) { args := c.Args() if len(args) != 1 { - Exit("append_tx takes 1 argument") + fmt.Println("append_tx takes 1 argument") + return } txString := args[0] tx := []byte(txString) @@ -198,13 +208,15 @@ func cmdAppendTx(c *cli.Context) { var err error tx, err = hex.DecodeString(txString[2:]) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } } res, err := makeRequest(conn, types.RequestAppendTx{tx}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Println("->", res) } @@ -213,7 +225,8 @@ func cmdAppendTx(c *cli.Context) { func cmdCheckTx(c *cli.Context) { args := c.Args() if len(args) != 1 { - Exit("append_tx takes 1 argument") + fmt.Println("append_tx takes 1 argument") + return } txString := args[0] tx := []byte(txString) @@ -221,13 +234,15 @@ func cmdCheckTx(c *cli.Context) { var err error tx, err = hex.DecodeString(txString[2:]) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } } res, err := makeRequest(conn, types.RequestCheckTx{tx}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Println("->", res) } @@ -236,7 +251,8 @@ func cmdCheckTx(c *cli.Context) { func cmdGetHash(c *cli.Context) { res, err := makeRequest(conn, types.RequestGetHash{}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash) } @@ -245,7 +261,8 @@ func cmdGetHash(c *cli.Context) { func cmdQuery(c *cli.Context) { args := c.Args() if len(args) != 1 { - Exit("append_tx takes 1 argument") + fmt.Println("append_tx takes 1 argument") + return } queryString := args[0] query := []byte(queryString) @@ -253,13 +270,15 @@ func cmdQuery(c *cli.Context) { var err error query, err = hex.DecodeString(queryString[2:]) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } } res, err := makeRequest(conn, types.RequestQuery{query}) if err != nil { - Exit(err.Error()) + fmt.Println(err.Error()) + return } fmt.Println("->", res) } From 2936c68339f9b2926aa4fa6f50226ea10380658f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 30 Jan 2016 19:36:33 -0800 Subject: [PATCH 065/545] Convert TMSP to use Protobuf --- Makefile | 5 +- client/client.go | 120 +++++------- cmd/tmsp-cli/tmsp-cli.go | 43 ++--- example/golang/dummy_test.go | 30 ++- server/server.go | 66 +++---- tests/benchmarks/parallel/parallel.go | 15 +- tests/benchmarks/simple/simple.go | 25 +-- tests/benchmarks/wire_test.go | 44 ----- types/messages.go | 267 ++++++++++++++------------ types/retcode.go | 2 +- types/types.pb.go | 69 +++++++ types/types.proto | 47 +++++ 12 files changed, 392 insertions(+), 341 deletions(-) delete mode 100644 tests/benchmarks/wire_test.go create mode 100644 types/types.pb.go create mode 100644 types/types.proto diff --git a/Makefile b/Makefile index bb750598..20fb8a23 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ .PHONY: all test get_deps -all: test install +all: protoc test install + +protoc: + protoc --go_out=. types/*.proto install: get_deps go install github.com/tendermint/tmsp/cmd/... diff --git a/client/client.go b/client/client.go index d25348d1..e9563947 100644 --- a/client/client.go +++ b/client/client.go @@ -6,18 +6,16 @@ import ( "errors" "fmt" "net" - "reflect" "sync" . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" - tmsp "github.com/tendermint/tmsp/types" + "github.com/tendermint/tmsp/types" ) const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... -type Callback func(tmsp.Request, tmsp.Response) +type Callback func(*types.Request, *types.Response) // This is goroutine-safe, but users should beware that // the application in general is not meant to be interfaced @@ -34,7 +32,7 @@ type TMSPClient struct { bufWriter *bufio.Writer err error reqSent *list.List - resCb func(tmsp.Request, tmsp.Response) + resCb func(*types.Request, *types.Response) } func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { @@ -91,12 +89,10 @@ func (cli *TMSPClient) Error() error { func (cli *TMSPClient) sendRequestsRoutine() { for { - var n int - var err error select { case <-cli.flushTimer.Ch: select { - case cli.reqQueue <- newReqRes(tmsp.RequestFlush{}): + case cli.reqQueue <- newReqRes(types.RequestFlush()): default: // Probably will fill the buffer, or retry later. } @@ -104,13 +100,13 @@ func (cli *TMSPClient) sendRequestsRoutine() { return case reqres := <-cli.reqQueue: cli.willSendReq(reqres) - wire.WriteBinaryLengthPrefixed(struct{ tmsp.Request }{reqres.Request}, cli.bufWriter, &n, &err) // Length prefix + err := types.WriteMessage(reqres.Request, cli.bufWriter) if err != nil { cli.StopForError(err) return } // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) - if _, ok := reqres.Request.(tmsp.RequestFlush); ok { + if reqres.Request.Type == types.RequestTypeFlush { err = cli.bufWriter.Flush() if err != nil { cli.StopForError(err) @@ -124,16 +120,14 @@ func (cli *TMSPClient) sendRequestsRoutine() { func (cli *TMSPClient) recvResponseRoutine() { r := bufio.NewReader(cli.conn) // Buffer reads for { - var res tmsp.Response - var n int - var err error - wire.ReadBinaryPtrLengthPrefixed(&res, r, maxResponseSize, &n, &err) + var res = &types.Response{} + err := types.ReadMessage(r, res) if err != nil { cli.StopForError(err) return } - switch res := res.(type) { - case tmsp.ResponseException: + switch res.Type { + case types.ResponseTypeException: // XXX After setting cli.err, release waiters (e.g. reqres.Done()) cli.StopForError(errors.New(res.Error)) default: @@ -152,19 +146,19 @@ func (cli *TMSPClient) willSendReq(reqres *reqRes) { cli.reqSent.PushBack(reqres) } -func (cli *TMSPClient) didRecvResponse(res tmsp.Response) error { +func (cli *TMSPClient) didRecvResponse(res *types.Response) error { cli.mtx.Lock() defer cli.mtx.Unlock() // Get the first reqRes next := cli.reqSent.Front() if next == nil { - return fmt.Errorf("Unexpected result type %v when nothing expected", reflect.TypeOf(res)) + return fmt.Errorf("Unexpected result type %v when nothing expected", res.Type) } reqres := next.Value.(*reqRes) if !resMatchesReq(reqres.Request, res) { return fmt.Errorf("Unexpected result type %v when response to %v expected", - reflect.TypeOf(res), reflect.TypeOf(reqres.Request)) + res.Type, reqres.Request.Type) } reqres.Response = res // Set response @@ -182,99 +176,99 @@ func (cli *TMSPClient) didRecvResponse(res tmsp.Response) error { //---------------------------------------- func (cli *TMSPClient) EchoAsync(msg string) { - cli.queueRequest(tmsp.RequestEcho{msg}) + cli.queueRequest(types.RequestEcho(msg)) } func (cli *TMSPClient) FlushAsync() { - cli.queueRequest(tmsp.RequestFlush{}) + cli.queueRequest(types.RequestFlush()) } func (cli *TMSPClient) SetOptionAsync(key string, value string) { - cli.queueRequest(tmsp.RequestSetOption{key, value}) + cli.queueRequest(types.RequestSetOption(key, value)) } func (cli *TMSPClient) AppendTxAsync(tx []byte) { - cli.queueRequest(tmsp.RequestAppendTx{tx}) + cli.queueRequest(types.RequestAppendTx(tx)) } func (cli *TMSPClient) CheckTxAsync(tx []byte) { - cli.queueRequest(tmsp.RequestCheckTx{tx}) + cli.queueRequest(types.RequestCheckTx(tx)) } func (cli *TMSPClient) GetHashAsync() { - cli.queueRequest(tmsp.RequestGetHash{}) + cli.queueRequest(types.RequestGetHash()) } func (cli *TMSPClient) QueryAsync(query []byte) { - cli.queueRequest(tmsp.RequestQuery{query}) + cli.queueRequest(types.RequestQuery(query)) } //---------------------------------------- func (cli *TMSPClient) InfoSync() (info string, err error) { - reqres := cli.queueRequest(tmsp.RequestInfo{}) + reqres := cli.queueRequest(types.RequestInfo()) cli.FlushSync() if cli.err != nil { return "", cli.err } - return reqres.Response.(tmsp.ResponseInfo).Info, nil + return string(reqres.Response.Data), nil } func (cli *TMSPClient) FlushSync() error { - cli.queueRequest(tmsp.RequestFlush{}).Wait() + cli.queueRequest(types.RequestFlush()).Wait() return cli.err } -func (cli *TMSPClient) AppendTxSync(tx []byte) (code tmsp.RetCode, result []byte, log string, err error) { - reqres := cli.queueRequest(tmsp.RequestAppendTx{tx}) +func (cli *TMSPClient) AppendTxSync(tx []byte) (code types.RetCode, result []byte, log string, err error) { + reqres := cli.queueRequest(types.RequestAppendTx(tx)) cli.FlushSync() if cli.err != nil { - return tmsp.RetCodeInternalError, nil, "", cli.err + return types.RetCodeInternalError, nil, "", cli.err } - res := reqres.Response.(tmsp.ResponseAppendTx) - return res.Code, res.Result, res.Log, nil + res := reqres.Response + return types.RetCode(res.Code), res.Data, res.Log, nil } -func (cli *TMSPClient) CheckTxSync(tx []byte) (code tmsp.RetCode, result []byte, log string, err error) { - reqres := cli.queueRequest(tmsp.RequestCheckTx{tx}) +func (cli *TMSPClient) CheckTxSync(tx []byte) (code types.RetCode, result []byte, log string, err error) { + reqres := cli.queueRequest(types.RequestCheckTx(tx)) cli.FlushSync() if cli.err != nil { - return tmsp.RetCodeInternalError, nil, "", cli.err + return types.RetCodeInternalError, nil, "", cli.err } - res := reqres.Response.(tmsp.ResponseCheckTx) - return res.Code, res.Result, res.Log, nil + res := reqres.Response + return types.RetCode(res.Code), res.Data, res.Log, nil } func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) { - reqres := cli.queueRequest(tmsp.RequestGetHash{}) + reqres := cli.queueRequest(types.RequestGetHash()) cli.FlushSync() if cli.err != nil { return nil, "", cli.err } - res := reqres.Response.(tmsp.ResponseGetHash) - return res.Hash, res.Log, nil + res := reqres.Response + return res.Data, res.Log, nil } func (cli *TMSPClient) QuerySync(query []byte) (result []byte, log string, err error) { - reqres := cli.queueRequest(tmsp.RequestQuery{query}) + reqres := cli.queueRequest(types.RequestQuery(query)) cli.FlushSync() if cli.err != nil { return nil, "", cli.err } - res := reqres.Response.(tmsp.ResponseQuery) - return res.Result, res.Log, nil + res := reqres.Response + return res.Data, res.Log, nil } //---------------------------------------- -func (cli *TMSPClient) queueRequest(req tmsp.Request) *reqRes { +func (cli *TMSPClient) queueRequest(req *types.Request) *reqRes { reqres := newReqRes(req) // TODO: set cli.err if reqQueue times out cli.reqQueue <- reqres // Maybe auto-flush, or unset auto-flush - switch req.(type) { - case tmsp.RequestFlush: + switch req.Type { + case types.RequestTypeFlush: cli.flushTimer.Unset() default: cli.flushTimer.Set() @@ -285,37 +279,17 @@ func (cli *TMSPClient) queueRequest(req tmsp.Request) *reqRes { //---------------------------------------- -func resMatchesReq(req tmsp.Request, res tmsp.Response) (ok bool) { - switch req.(type) { - case tmsp.RequestEcho: - _, ok = res.(tmsp.ResponseEcho) - case tmsp.RequestFlush: - _, ok = res.(tmsp.ResponseFlush) - case tmsp.RequestInfo: - _, ok = res.(tmsp.ResponseInfo) - case tmsp.RequestSetOption: - _, ok = res.(tmsp.ResponseSetOption) - case tmsp.RequestAppendTx: - _, ok = res.(tmsp.ResponseAppendTx) - case tmsp.RequestCheckTx: - _, ok = res.(tmsp.ResponseCheckTx) - case tmsp.RequestGetHash: - _, ok = res.(tmsp.ResponseGetHash) - case tmsp.RequestQuery: - _, ok = res.(tmsp.ResponseQuery) - default: - return false - } - return +func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { + return req.Type+0x10 == res.Type } type reqRes struct { - tmsp.Request + *types.Request *sync.WaitGroup - tmsp.Response // Not set atomically, so be sure to use WaitGroup. + *types.Response // Not set atomically, so be sure to use WaitGroup. } -func newReqRes(req tmsp.Request) *reqRes { +func newReqRes(req *types.Request) *reqRes { return &reqRes{ Request: req, WaitGroup: waitGroup1(), diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 4aed1f1e..9526fab6 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -8,14 +8,11 @@ import ( "io" "net" "os" - "reflect" "strings" - . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/types" - "github.com/codegangsta/cli" + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/types" ) // connection is a global variable so it can be reused by the console @@ -162,7 +159,7 @@ func cmdEcho(c *cli.Context) { fmt.Println("echo takes 1 argument") return } - res, err := makeRequest(conn, types.RequestEcho{args[0]}) + res, err := makeRequest(conn, types.RequestEcho(args[0])) if err != nil { fmt.Println(err.Error()) return @@ -172,7 +169,7 @@ func cmdEcho(c *cli.Context) { // Get some info from the application func cmdInfo(c *cli.Context) { - res, err := makeRequest(conn, types.RequestInfo{}) + res, err := makeRequest(conn, types.RequestInfo()) if err != nil { fmt.Println(err.Error()) return @@ -187,7 +184,7 @@ func cmdSetOption(c *cli.Context) { fmt.Println("set_option takes 2 arguments (key, value)") return } - _, err := makeRequest(conn, types.RequestSetOption{args[0], args[1]}) + _, err := makeRequest(conn, types.RequestSetOption(args[0], args[1])) if err != nil { fmt.Println(err.Error()) return @@ -213,7 +210,7 @@ func cmdAppendTx(c *cli.Context) { } } - res, err := makeRequest(conn, types.RequestAppendTx{tx}) + res, err := makeRequest(conn, types.RequestAppendTx(tx)) if err != nil { fmt.Println(err.Error()) return @@ -239,7 +236,7 @@ func cmdCheckTx(c *cli.Context) { } } - res, err := makeRequest(conn, types.RequestCheckTx{tx}) + res, err := makeRequest(conn, types.RequestCheckTx(tx)) if err != nil { fmt.Println(err.Error()) return @@ -249,12 +246,12 @@ func cmdCheckTx(c *cli.Context) { // Get application Merkle root hash func cmdGetHash(c *cli.Context) { - res, err := makeRequest(conn, types.RequestGetHash{}) + res, err := makeRequest(conn, types.RequestGetHash()) if err != nil { fmt.Println(err.Error()) return } - fmt.Printf("%X\n", res.(types.ResponseGetHash).Hash) + fmt.Printf("%X\n", res.Data) } // Query application state @@ -275,7 +272,7 @@ func cmdQuery(c *cli.Context) { } } - res, err := makeRequest(conn, types.RequestQuery{query}) + res, err := makeRequest(conn, types.RequestQuery(query)) if err != nil { fmt.Println(err.Error()) return @@ -285,37 +282,35 @@ func cmdQuery(c *cli.Context) { //-------------------------------------------------------------------------------- -func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { - var n int - var err error +func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { // Write desired request - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, conn, &n, &err) + err := types.WriteMessage(req, conn) if err != nil { return nil, err } // Write flush request - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{types.RequestFlush{}}, conn, &n, &err) + err = types.WriteMessage(types.RequestFlush(), conn) if err != nil { return nil, err } // Read desired response - var res types.Response - wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + var res = &types.Response{} + err = types.ReadMessage(conn, res) if err != nil { return nil, err } // Read flush response - var resFlush types.Response - wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) + var resFlush = &types.Response{} + err = types.ReadMessage(conn, resFlush) if err != nil { return nil, err } - if _, ok := resFlush.(types.ResponseFlush); !ok { - return nil, errors.New(Fmt("Expected types.ResponseFlush but got %v instead", reflect.TypeOf(resFlush))) + if resFlush.Type != types.ResponseTypeFlush { + return nil, errors.New(Fmt("Expected types.ResponseTypesFlush but got %v instead", resFlush.Type)) } return res, nil diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index ccf34f3f..7926a803 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -1,12 +1,10 @@ package example import ( - "reflect" "testing" "time" . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" "github.com/tendermint/tmsp/server" "github.com/tendermint/tmsp/types" ) @@ -32,19 +30,18 @@ func TestStream(t *testing.T) { go func() { counter := 0 for { - var n int - var err error - var res types.Response - wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + + var res = &types.Response{} + err := types.ReadMessage(conn, res) if err != nil { Exit(err.Error()) } // Process response - switch res := res.(type) { - case types.ResponseAppendTx: + switch res.Type { + case types.ResponseTypeAppendTx: counter += 1 - if res.Code != types.RetCodeOK { + if types.RetCode(res.Code) != types.RetCodeOK { t.Error("AppendTx failed with ret_code", res.Code) } if counter > numAppendTxs { @@ -57,10 +54,10 @@ func TestStream(t *testing.T) { close(done) }() } - case types.ResponseFlush: + case types.ResponseTypeFlush: // ignore default: - t.Error("Unexpected response type", reflect.TypeOf(res)) + t.Error("Unexpected response type", res.Type) } } }() @@ -68,10 +65,8 @@ func TestStream(t *testing.T) { // Write requests for counter := 0; counter < numAppendTxs; counter++ { // Send request - var n int - var err error - var req types.Request = types.RequestAppendTx{TxBytes: []byte("test")} - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, conn, &n, &err) + var req = types.RequestAppendTx([]byte("test")) + err := types.WriteMessage(req, conn) if err != nil { t.Fatal(err.Error()) } @@ -79,7 +74,7 @@ func TestStream(t *testing.T) { // Sometimes send flush messages if counter%123 == 0 { t.Log("flush") - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{types.RequestFlush{}}, conn, &n, &err) + err := types.WriteMessage(types.RequestFlush(), conn) if err != nil { t.Fatal(err.Error()) } @@ -87,8 +82,7 @@ func TestStream(t *testing.T) { } // Send final flush message - var n int - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{types.RequestFlush{}}, conn, &n, &err) + err = types.WriteMessage(types.RequestFlush(), conn) if err != nil { t.Fatal(err.Error()) } diff --git a/server/server.go b/server/server.go index 7c2a7c4c..74b4ce74 100644 --- a/server/server.go +++ b/server/server.go @@ -9,7 +9,6 @@ import ( "sync" . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" "github.com/tendermint/tmsp/types" ) @@ -40,8 +39,8 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error fmt.Println("Accepted a new connection") } - closeConn := make(chan error, 2) // Push to signal connection closed - responses := make(chan types.Response, 1000) // A channel to buffer responses + closeConn := make(chan error, 2) // Push to signal connection closed + responses := make(chan *types.Response, 1000) // A channel to buffer responses // Read requests from conn and deal with them go handleRequests(&mtx, app, closeConn, conn, responses) @@ -73,14 +72,13 @@ func StartListener(protoAddr string, app types.Application) (net.Listener, error } // Read requests from conn and deal with them -func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error, conn net.Conn, responses chan<- types.Response) { +func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error, conn net.Conn, responses chan<- *types.Response) { var count int var bufReader = bufio.NewReader(conn) for { - var n int - var err error - var req types.Request - wire.ReadBinaryPtrLengthPrefixed(&req, bufReader, 0, &n, &err) + + var req = &types.Request{} + err := types.ReadMessage(bufReader, req) if err != nil { if err == io.EOF { closeConn <- fmt.Errorf("Connection closed by client") @@ -96,49 +94,47 @@ func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error } } -func handleRequest(app types.Application, req types.Request, responses chan<- types.Response) { - switch req := req.(type) { - case types.RequestEcho: - responses <- types.ResponseEcho{req.Message} - case types.RequestFlush: - responses <- types.ResponseFlush{} - case types.RequestInfo: +func handleRequest(app types.Application, req *types.Request, responses chan<- *types.Response) { + switch req.Type { + case types.RequestTypeEcho: + responses <- types.ResponseEcho(string(req.Data)) + case types.RequestTypeFlush: + responses <- types.ResponseFlush() + case types.RequestTypeInfo: data := app.Info() - responses <- types.ResponseInfo{data} - case types.RequestSetOption: + responses <- types.ResponseInfo(data) + case types.RequestTypeSetOption: logStr := app.SetOption(req.Key, req.Value) - responses <- types.ResponseSetOption{logStr} - case types.RequestAppendTx: - code, result, logStr := app.AppendTx(req.TxBytes) - responses <- types.ResponseAppendTx{code, result, logStr} - case types.RequestCheckTx: - code, result, logStr := app.CheckTx(req.TxBytes) - responses <- types.ResponseCheckTx{code, result, logStr} - case types.RequestGetHash: + responses <- types.ResponseSetOption(logStr) + case types.RequestTypeAppendTx: + code, result, logStr := app.AppendTx(req.Data) + responses <- types.ResponseAppendTx(code, result, logStr) + case types.RequestTypeCheckTx: + code, result, logStr := app.CheckTx(req.Data) + responses <- types.ResponseCheckTx(code, result, logStr) + case types.RequestTypeGetHash: hash, logStr := app.GetHash() - responses <- types.ResponseGetHash{hash, logStr} - case types.RequestQuery: - result, logStr := app.Query(req.QueryBytes) - responses <- types.ResponseQuery{result, logStr} + responses <- types.ResponseGetHash(hash, logStr) + case types.RequestTypeQuery: + result, logStr := app.Query(req.Data) + responses <- types.ResponseQuery(result, logStr) default: - responses <- types.ResponseException{"Unknown request"} + responses <- types.ResponseException("Unknown request") } } // Pull responses from 'responses' and write them to conn. -func handleResponses(closeConn chan error, responses <-chan types.Response, conn net.Conn) { +func handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) { var count int var bufWriter = bufio.NewWriter(conn) for { var res = <-responses - var n int - var err error - wire.WriteBinaryLengthPrefixed(struct{ types.Response }{res}, bufWriter, &n, &err) + err := types.WriteMessage(res, bufWriter) if err != nil { closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return } - if _, ok := res.(types.ResponseFlush); ok { + if res.Type == types.ResponseTypeFlush { err = bufWriter.Flush() if err != nil { closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 481c1432..7cab2eb2 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -6,7 +6,6 @@ import ( //"encoding/hex" . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" "github.com/tendermint/tmsp/types" ) @@ -21,10 +20,8 @@ func main() { go func() { counter := 0 for { - var res types.Response - var n int - var err error - wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + var res = &types.Response{} + err := types.ReadMessage(conn, res) if err != nil { Exit(err.Error()) } @@ -39,10 +36,9 @@ func main() { counter := 0 for i := 0; ; i++ { var bufWriter = bufio.NewWriter(conn) - var req types.Request = types.RequestEcho{"foobar"} - var n int - var err error - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, bufWriter, &n, &err) + var req = types.RequestEcho("foobar") + + err := types.WriteMessage(req, bufWriter) if err != nil { Exit(err.Error()) } @@ -50,6 +46,7 @@ func main() { if err != nil { Exit(err.Error()) } + counter += 1 if counter%1000 == 0 { fmt.Println("Write", counter) diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 4009f848..b40dbef5 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -5,11 +5,9 @@ import ( "errors" "fmt" "net" - "reflect" //"encoding/hex" . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" "github.com/tendermint/tmsp/types" ) @@ -23,7 +21,7 @@ func main() { // Make a bunch of requests counter := 0 for i := 0; ; i++ { - req := types.RequestEcho{"foobar"} + req := types.RequestEcho("foobar") _, err := makeRequest(conn, req) if err != nil { Exit(err.Error()) @@ -35,35 +33,32 @@ func main() { } } -func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { +func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { var bufWriter = bufio.NewWriter(conn) - var n int - var err error // Write desired request - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, bufWriter, &n, &err) + err := types.WriteMessage(req, bufWriter) if err != nil { return nil, err } - bufWriter.Write([]byte{0x01, 0x01, types.RequestTypeFlush}) // Write flush msg - err = bufWriter.Flush() + err = types.WriteMessage(types.RequestFlush(), bufWriter) if err != nil { return nil, err } // Read desired response - var res types.Response - wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + var res = &types.Response{} + err = types.ReadMessage(conn, res) if err != nil { return nil, err } - var resFlush types.Response // Read flush msg - wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) + var resFlush = &types.Response{} + err = types.ReadMessage(conn, resFlush) if err != nil { return nil, err } - if _, ok := resFlush.(types.ResponseFlush); !ok { - return nil, errors.New(Fmt("Expected flush response but got something else", reflect.TypeOf(resFlush))) + if resFlush.Type != types.ResponseTypeFlush { + return nil, errors.New(Fmt("Expected flush response but got something else: %v", resFlush.Type)) } return res, nil diff --git a/tests/benchmarks/wire_test.go b/tests/benchmarks/wire_test.go deleted file mode 100644 index c730089a..00000000 --- a/tests/benchmarks/wire_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package benchmarks - -import ( - "bytes" - "testing" - - . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/types" -) - -func BenchmarkRequestWire(b *testing.B) { - b.StopTimer() - var bz = make([]byte, 1024) - copy(bz, []byte{1, 9, 0x01, 1, 6, 34, 34, 34, 34, 34, 34}) - var buf = bytes.NewBuffer(bz) - var req types.Request - b.StartTimer() - - for i := 0; i < b.N; i++ { - { - buf = bytes.NewBuffer(bz) - var n int - var err error - wire.ReadBinaryPtrLengthPrefixed(&req, buf, 0, &n, &err) - if err != nil { - Exit(err.Error()) - return - } - } - { - buf = bytes.NewBuffer(bz) - var n int - var err error - wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, buf, &n, &err) - if err != nil { - Exit(err.Error()) - return - } - - } - } - -} diff --git a/types/messages.go b/types/messages.go index 0e05706d..8c21f327 100644 --- a/types/messages.go +++ b/types/messages.go @@ -1,155 +1,180 @@ package types -import "github.com/tendermint/go-wire" +import ( + "io" + + "github.com/golang/protobuf/proto" + "github.com/tendermint/go-wire" +) const ( - RequestTypeEcho = byte(0x01) - RequestTypeFlush = byte(0x02) - RequestTypeInfo = byte(0x03) - RequestTypeSetOption = byte(0x04) - // reserved for GetOption = byte(0x05) + RequestTypeEcho = uint32(0x01) + RequestTypeFlush = uint32(0x02) + RequestTypeInfo = uint32(0x03) + RequestTypeSetOption = uint32(0x04) + // reserved for GetOption = uint32(0x05) - ResponseTypeException = byte(0x10) - ResponseTypeEcho = byte(0x11) - ResponseTypeFlush = byte(0x12) - ResponseTypeInfo = byte(0x13) - ResponseTypeSetOption = byte(0x14) - // reserved for GetOption = byte(0x15) + ResponseTypeException = uint32(0x10) + ResponseTypeEcho = uint32(0x11) + ResponseTypeFlush = uint32(0x12) + ResponseTypeInfo = uint32(0x13) + ResponseTypeSetOption = uint32(0x14) + // reserved for GetOption = uint32(0x15) - RequestTypeAppendTx = byte(0x21) - RequestTypeCheckTx = byte(0x22) - RequestTypeGetHash = byte(0x23) - RequestTypeQuery = byte(0x24) + RequestTypeAppendTx = uint32(0x21) + RequestTypeCheckTx = uint32(0x22) + RequestTypeGetHash = uint32(0x23) + RequestTypeQuery = uint32(0x24) - ResponseTypeAppendTx = byte(0x31) - ResponseTypeCheckTx = byte(0x32) - ResponseTypeGetHash = byte(0x33) - ResponseTypeQuery = byte(0x34) + ResponseTypeAppendTx = uint32(0x31) + ResponseTypeCheckTx = uint32(0x32) + ResponseTypeGetHash = uint32(0x33) + ResponseTypeQuery = uint32(0x34) ) +func RequestEcho(message string) *Request { + return &Request{ + Type: RequestTypeEcho, + Data: []byte(message), + } +} + +func RequestFlush() *Request { + return &Request{ + Type: RequestTypeFlush, + } +} + +func RequestInfo() *Request { + return &Request{ + Type: RequestTypeInfo, + } +} + +func RequestSetOption(key string, value string) *Request { + return &Request{ + Type: RequestTypeSetOption, + Key: key, + Value: value, + } +} + +func RequestAppendTx(txBytes []byte) *Request { + return &Request{ + Type: RequestTypeAppendTx, + Data: txBytes, + } +} + +func RequestCheckTx(txBytes []byte) *Request { + return &Request{ + Type: RequestTypeCheckTx, + Data: txBytes, + } +} + +func RequestGetHash() *Request { + return &Request{ + Type: RequestTypeGetHash, + } +} + +func RequestQuery(queryBytes []byte) *Request { + return &Request{ + Type: RequestTypeQuery, + Data: queryBytes, + } +} + //---------------------------------------- -type RequestEcho struct { - Message string +func ResponseException(errStr string) *Response { + return &Response{ + Type: ResponseTypeException, + Error: errStr, + } } -type RequestFlush struct { +func ResponseEcho(message string) *Response { + return &Response{ + Type: ResponseTypeEcho, + Data: []byte(message), + } } -type RequestInfo struct { +func ResponseFlush() *Response { + return &Response{ + Type: ResponseTypeFlush, + } } -type RequestSetOption struct { - Key string - Value string +func ResponseInfo(info string) *Response { + return &Response{ + Type: ResponseTypeInfo, + Data: []byte(info), + } } -type RequestAppendTx struct { - TxBytes []byte +func ResponseSetOption(log string) *Response { + return &Response{ + Type: ResponseTypeSetOption, + Log: log, + } } -type RequestCheckTx struct { - TxBytes []byte +func ResponseAppendTx(code RetCode, result []byte, log string) *Response { + return &Response{ + Type: ResponseTypeAppendTx, + Data: result, + Log: log, + } } -type RequestGetHash struct { +func ResponseCheckTx(code RetCode, result []byte, log string) *Response { + return &Response{ + Type: ResponseTypeCheckTx, + Data: result, + Log: log, + } } -type RequestQuery struct { - QueryBytes []byte +func ResponseGetHash(hash []byte, log string) *Response { + return &Response{ + Type: ResponseTypeGetHash, + Data: hash, + Log: log, + } } -type Request interface { - AssertRequestType() +func ResponseQuery(result []byte, log string) *Response { + return &Response{ + Type: ResponseTypeQuery, + Data: result, + Log: log, + } } -func (_ RequestEcho) AssertRequestType() {} -func (_ RequestFlush) AssertRequestType() {} -func (_ RequestInfo) AssertRequestType() {} -func (_ RequestSetOption) AssertRequestType() {} -func (_ RequestAppendTx) AssertRequestType() {} -func (_ RequestCheckTx) AssertRequestType() {} -func (_ RequestGetHash) AssertRequestType() {} -func (_ RequestQuery) AssertRequestType() {} - -var _ = wire.RegisterInterface( - struct{ Request }{}, - wire.ConcreteType{RequestEcho{}, RequestTypeEcho}, - wire.ConcreteType{RequestFlush{}, RequestTypeFlush}, - wire.ConcreteType{RequestInfo{}, RequestTypeInfo}, - wire.ConcreteType{RequestSetOption{}, RequestTypeSetOption}, - wire.ConcreteType{RequestAppendTx{}, RequestTypeAppendTx}, - wire.ConcreteType{RequestCheckTx{}, RequestTypeCheckTx}, - wire.ConcreteType{RequestGetHash{}, RequestTypeGetHash}, - wire.ConcreteType{RequestQuery{}, RequestTypeQuery}, -) - //---------------------------------------- -type ResponseException struct { - Error string +// Write proto message, length delimited +func WriteMessage(msg proto.Message, w io.Writer) error { + bz, err := proto.Marshal(msg) + if err != nil { + return err + } + var n int + wire.WriteByteSlice(bz, w, &n, &err) + return err } -type ResponseEcho struct { - Message string +// Read proto message, length delimited +func ReadMessage(r io.Reader, msg proto.Message) error { + var n int + var err error + bz := wire.ReadByteSlice(r, 0, &n, &err) + if err != nil { + return err + } + err = proto.Unmarshal(bz, msg) + return err } - -type ResponseFlush struct { -} - -type ResponseInfo struct { - Info string -} - -type ResponseSetOption struct { - Log string -} - -type ResponseAppendTx struct { - Code RetCode - Result []byte - Log string -} - -type ResponseCheckTx struct { - Code RetCode - Result []byte - Log string -} - -type ResponseGetHash struct { - Hash []byte - Log string -} - -type ResponseQuery struct { - Result []byte - Log string -} - -type Response interface { - AssertResponseType() -} - -func (_ ResponseEcho) AssertResponseType() {} -func (_ ResponseFlush) AssertResponseType() {} -func (_ ResponseInfo) AssertResponseType() {} -func (_ ResponseSetOption) AssertResponseType() {} -func (_ ResponseAppendTx) AssertResponseType() {} -func (_ ResponseCheckTx) AssertResponseType() {} -func (_ ResponseGetHash) AssertResponseType() {} -func (_ ResponseException) AssertResponseType() {} -func (_ ResponseQuery) AssertResponseType() {} - -var _ = wire.RegisterInterface( - struct{ Response }{}, - wire.ConcreteType{ResponseEcho{}, ResponseTypeEcho}, - wire.ConcreteType{ResponseFlush{}, ResponseTypeFlush}, - wire.ConcreteType{ResponseInfo{}, ResponseTypeInfo}, - wire.ConcreteType{ResponseSetOption{}, ResponseTypeSetOption}, - wire.ConcreteType{ResponseAppendTx{}, ResponseTypeAppendTx}, - wire.ConcreteType{ResponseCheckTx{}, ResponseTypeCheckTx}, - wire.ConcreteType{ResponseGetHash{}, ResponseTypeGetHash}, - wire.ConcreteType{ResponseException{}, ResponseTypeException}, - wire.ConcreteType{ResponseQuery{}, ResponseTypeQuery}, -) diff --git a/types/retcode.go b/types/retcode.go index 05e49a2e..c6bf3e20 100644 --- a/types/retcode.go +++ b/types/retcode.go @@ -1,6 +1,6 @@ package types -type RetCode int +type RetCode uint // Reserved return codes const ( diff --git a/types/types.pb.go b/types/types.pb.go new file mode 100644 index 00000000..877c72ca --- /dev/null +++ b/types/types.pb.go @@ -0,0 +1,69 @@ +// Code generated by protoc-gen-go. +// source: types/types.proto +// DO NOT EDIT! + +/* +Package types is a generated protocol buffer package. + +It is generated from these files: + types/types.proto + +It has these top-level messages: + Request + Response +*/ +package types + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Request struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` + Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} +func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type Response struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Code uint32 `protobuf:"varint,3,opt,name=code" json:"code,omitempty"` + Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` + Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` +} + +func (m *Response) Reset() { *m = Response{} } +func (m *Response) String() string { return proto.CompactTextString(m) } +func (*Response) ProtoMessage() {} +func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func init() { + proto.RegisterType((*Request)(nil), "types.Request") + proto.RegisterType((*Response)(nil), "types.Response") +} + +var fileDescriptor0 = []byte{ + // 165 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x8f, 0xb1, 0xae, 0xc2, 0x30, + 0x0c, 0x45, 0xd5, 0xd7, 0xe6, 0x01, 0x16, 0x48, 0x10, 0x31, 0x64, 0x44, 0x9d, 0x98, 0x60, 0xe0, + 0x4f, 0xb2, 0x31, 0x06, 0x6a, 0x31, 0x50, 0xd5, 0x21, 0x49, 0x91, 0xfa, 0xf7, 0xd8, 0xae, 0xd8, + 0x59, 0xa2, 0x73, 0x8f, 0xa2, 0xab, 0x6b, 0xd8, 0x95, 0x29, 0x62, 0x3e, 0xeb, 0x7b, 0x8a, 0x89, + 0x0a, 0x59, 0xa3, 0xa1, 0xbd, 0xc2, 0xc2, 0xe3, 0x6b, 0xc4, 0x5c, 0xac, 0x85, 0x46, 0x9c, 0xab, + 0x0e, 0xd5, 0x71, 0xe3, 0x95, 0xc5, 0x75, 0xa1, 0x04, 0xf7, 0xc7, 0x6e, 0xed, 0x95, 0xed, 0x16, + 0xea, 0x27, 0x4e, 0xae, 0x66, 0xb5, 0xf2, 0x82, 0x76, 0x0f, 0xe6, 0x1d, 0xfa, 0x11, 0x5d, 0xa3, + 0x6e, 0x0e, 0xed, 0x00, 0x4b, 0x8f, 0x39, 0xd2, 0x90, 0xf1, 0xe7, 0x6e, 0x76, 0x77, 0xea, 0x50, + 0xcb, 0xf9, 0x9f, 0xb0, 0xb4, 0x63, 0x4a, 0x94, 0xbe, 0xed, 0x1a, 0x64, 0x45, 0x4f, 0x0f, 0x67, + 0xe6, 0x15, 0x8c, 0xb7, 0x7f, 0x3d, 0xec, 0xf2, 0x09, 0x00, 0x00, 0xff, 0xff, 0xce, 0x9d, 0x3d, + 0x4f, 0xed, 0x00, 0x00, 0x00, +} diff --git a/types/types.proto b/types/types.proto new file mode 100644 index 00000000..8a00c3ca --- /dev/null +++ b/types/types.proto @@ -0,0 +1,47 @@ +syntax = "proto3"; + +package types; + +//---------------------------------------- +// Message types + +/* + RequestTypeEcho = 0x01; + RequestTypeFlush = 0x02; + RequestTypeInfo = 0x03; + RequestTypeSetOption = 0x04; + RequestTypeAppendTx = 0x21; + RequestTypeCheckTx = 0x22; + RequestTypeGetHash = 0x23; + RequestTypeQuery = 0x24; + + ResponseTypeEcho = 0x11; + ResponseTypeFlush = 0x12; + ResponseTypeInfo = 0x13; + ResponseTypeSetOption = 0x14; + ResponseTypeAppendTx = 0x31; + ResponseTypeCheckTx = 0x32; + ResponseTypeGetHash = 0x33; + ResponseTypeQuery = 0x34; +*/ + +//---------------------------------------- +// Request types + +message Request { + uint32 type = 1; + bytes data = 2; + string key = 3; + string value = 4; +} + +//---------------------------------------- +// Response types + +message Response { + uint32 type = 1; + bytes data = 2; + uint32 code = 3; + string error = 4; + string log = 5; +} From e110a04ae28b3ef98327c781b75db5a23ff7cb5f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 30 Jan 2016 19:44:04 -0800 Subject: [PATCH 066/545] Fix benchmark -- needed to flush --- cmd/counter/main.go | 3 ++- cmd/dummy/main.go | 7 ++++++- tests/benchmarks/simple/simple.go | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 3e770a43..503908b4 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -10,12 +10,13 @@ import ( func main() { + addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") flag.Parse() app := example.NewCounterApplication(*serialPtr) // Start the listener - _, err := server.StartListener("tcp://0.0.0.0:46658", app) + _, err := server.StartListener(*addrPtr, app) if err != nil { Exit(err.Error()) } diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index ce9bf8d0..d1766e65 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -1,6 +1,8 @@ package main import ( + "flag" + . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/example/golang" "github.com/tendermint/tmsp/server" @@ -8,8 +10,11 @@ import ( func main() { + addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") + flag.Parse() + // Start the listener - _, err := server.StartListener("tcp://0.0.0.0:46658", example.NewDummyApplication()) + _, err := server.StartListener(*addrPtr, example.NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index b40dbef5..a8a8d7c4 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -45,6 +45,10 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { if err != nil { return nil, err } + err = bufWriter.Flush() + if err != nil { + return nil, err + } // Read desired response var res = &types.Response{} From 028cc4aa0684e28531c0ef6685f9783c98615ce1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 31 Jan 2016 18:11:24 -0800 Subject: [PATCH 067/545] Query returns Code --- client/client.go | 6 +++--- example/golang/counter.go | 4 ++-- example/golang/dummy.go | 4 ++-- server/server.go | 4 ++-- types/application.go | 2 +- types/messages.go | 5 ++++- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/client/client.go b/client/client.go index e9563947..c19a1ec4 100644 --- a/client/client.go +++ b/client/client.go @@ -249,14 +249,14 @@ func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) { return res.Data, res.Log, nil } -func (cli *TMSPClient) QuerySync(query []byte) (result []byte, log string, err error) { +func (cli *TMSPClient) QuerySync(query []byte) (code types.RetCode, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestQuery(query)) cli.FlushSync() if cli.err != nil { - return nil, "", cli.err + return types.RetCodeInternalError, nil, "", cli.err } res := reqres.Response - return res.Data, res.Log, nil + return types.RetCode(res.Code), res.Data, res.Log, nil } //---------------------------------------- diff --git a/example/golang/counter.go b/example/golang/counter.go index 962c0760..120eb318 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -66,6 +66,6 @@ func (app *CounterApplication) GetHash() (hash []byte, log string) { } } -func (app *CounterApplication) Query(query []byte) (result []byte, log string) { - return nil, fmt.Sprintf("Query is not supported") +func (app *CounterApplication) Query(query []byte) (code types.RetCode, result []byte, log string) { + return types.RetCodeOK, nil, fmt.Sprintf("Query is not supported") } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 9835eeb8..59d77dc3 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -40,6 +40,6 @@ func (app *DummyApplication) GetHash() (hash []byte, log string) { return hash, "" } -func (app *DummyApplication) Query(query []byte) (result []byte, log string) { - return nil, "Query not supported" +func (app *DummyApplication) Query(query []byte) (code types.RetCode, result []byte, log string) { + return types.RetCodeOK, nil, "Query not supported" } diff --git a/server/server.go b/server/server.go index 74b4ce74..b95f9e8b 100644 --- a/server/server.go +++ b/server/server.go @@ -116,8 +116,8 @@ func handleRequest(app types.Application, req *types.Request, responses chan<- * hash, logStr := app.GetHash() responses <- types.ResponseGetHash(hash, logStr) case types.RequestTypeQuery: - result, logStr := app.Query(req.Data) - responses <- types.ResponseQuery(result, logStr) + code, result, logStr := app.Query(req.Data) + responses <- types.ResponseQuery(code, result, logStr) default: responses <- types.ResponseException("Unknown request") } diff --git a/types/application.go b/types/application.go index cedf1240..0610d418 100644 --- a/types/application.go +++ b/types/application.go @@ -18,5 +18,5 @@ type Application interface { GetHash() (hash []byte, log string) // Query for state - Query(query []byte) (result []byte, log string) + Query(query []byte) (code RetCode, result []byte, log string) } diff --git a/types/messages.go b/types/messages.go index 8c21f327..061d34da 100644 --- a/types/messages.go +++ b/types/messages.go @@ -125,6 +125,7 @@ func ResponseSetOption(log string) *Response { func ResponseAppendTx(code RetCode, result []byte, log string) *Response { return &Response{ Type: ResponseTypeAppendTx, + Code: uint32(code), Data: result, Log: log, } @@ -133,6 +134,7 @@ func ResponseAppendTx(code RetCode, result []byte, log string) *Response { func ResponseCheckTx(code RetCode, result []byte, log string) *Response { return &Response{ Type: ResponseTypeCheckTx, + Code: uint32(code), Data: result, Log: log, } @@ -146,9 +148,10 @@ func ResponseGetHash(hash []byte, log string) *Response { } } -func ResponseQuery(result []byte, log string) *Response { +func ResponseQuery(code RetCode, result []byte, log string) *Response { return &Response{ Type: ResponseTypeQuery, + Code: uint32(code), Data: result, Log: log, } From 012abc437bc8edb4a7a8e2b83fcd99df46dab2d8 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 31 Jan 2016 19:56:02 -0800 Subject: [PATCH 068/545] Use protobuf enums --- client/client.go | 8 +-- cmd/tmsp-cli/tmsp-cli.go | 4 +- example/golang/dummy_test.go | 4 +- server/server.go | 18 +++--- tests/benchmarks/simple/simple.go | 2 +- types/messages.go | 59 ++++++------------- types/types.pb.go | 95 ++++++++++++++++++++++++------- types/types.proto | 38 ++++++------- 8 files changed, 126 insertions(+), 102 deletions(-) diff --git a/client/client.go b/client/client.go index c19a1ec4..93232b2d 100644 --- a/client/client.go +++ b/client/client.go @@ -106,7 +106,7 @@ func (cli *TMSPClient) sendRequestsRoutine() { return } // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) - if reqres.Request.Type == types.RequestTypeFlush { + if reqres.Request.Type == types.MessageType_Flush { err = cli.bufWriter.Flush() if err != nil { cli.StopForError(err) @@ -127,7 +127,7 @@ func (cli *TMSPClient) recvResponseRoutine() { return } switch res.Type { - case types.ResponseTypeException: + case types.MessageType_Exception: // XXX After setting cli.err, release waiters (e.g. reqres.Done()) cli.StopForError(errors.New(res.Error)) default: @@ -268,7 +268,7 @@ func (cli *TMSPClient) queueRequest(req *types.Request) *reqRes { // Maybe auto-flush, or unset auto-flush switch req.Type { - case types.RequestTypeFlush: + case types.MessageType_Flush: cli.flushTimer.Unset() default: cli.flushTimer.Set() @@ -280,7 +280,7 @@ func (cli *TMSPClient) queueRequest(req *types.Request) *reqRes { //---------------------------------------- func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { - return req.Type+0x10 == res.Type + return req.Type == res.Type } type reqRes struct { diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 9526fab6..5d516ed4 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -309,8 +309,8 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { if err != nil { return nil, err } - if resFlush.Type != types.ResponseTypeFlush { - return nil, errors.New(Fmt("Expected types.ResponseTypesFlush but got %v instead", resFlush.Type)) + if resFlush.Type != types.MessageType_Flush { + return nil, errors.New(Fmt("Expected types.MessageType_Flush but got %v instead", resFlush.Type)) } return res, nil diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index 7926a803..fa3d55c7 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -39,7 +39,7 @@ func TestStream(t *testing.T) { // Process response switch res.Type { - case types.ResponseTypeAppendTx: + case types.MessageType_AppendTx: counter += 1 if types.RetCode(res.Code) != types.RetCodeOK { t.Error("AppendTx failed with ret_code", res.Code) @@ -54,7 +54,7 @@ func TestStream(t *testing.T) { close(done) }() } - case types.ResponseTypeFlush: + case types.MessageType_Flush: // ignore default: t.Error("Unexpected response type", res.Type) diff --git a/server/server.go b/server/server.go index b95f9e8b..d5d1a124 100644 --- a/server/server.go +++ b/server/server.go @@ -96,26 +96,26 @@ func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error func handleRequest(app types.Application, req *types.Request, responses chan<- *types.Response) { switch req.Type { - case types.RequestTypeEcho: + case types.MessageType_Echo: responses <- types.ResponseEcho(string(req.Data)) - case types.RequestTypeFlush: + case types.MessageType_Flush: responses <- types.ResponseFlush() - case types.RequestTypeInfo: + case types.MessageType_Info: data := app.Info() responses <- types.ResponseInfo(data) - case types.RequestTypeSetOption: + case types.MessageType_SetOption: logStr := app.SetOption(req.Key, req.Value) responses <- types.ResponseSetOption(logStr) - case types.RequestTypeAppendTx: + case types.MessageType_AppendTx: code, result, logStr := app.AppendTx(req.Data) responses <- types.ResponseAppendTx(code, result, logStr) - case types.RequestTypeCheckTx: + case types.MessageType_CheckTx: code, result, logStr := app.CheckTx(req.Data) responses <- types.ResponseCheckTx(code, result, logStr) - case types.RequestTypeGetHash: + case types.MessageType_GetHash: hash, logStr := app.GetHash() responses <- types.ResponseGetHash(hash, logStr) - case types.RequestTypeQuery: + case types.MessageType_Query: code, result, logStr := app.Query(req.Data) responses <- types.ResponseQuery(code, result, logStr) default: @@ -134,7 +134,7 @@ func handleResponses(closeConn chan error, responses <-chan *types.Response, con closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return } - if res.Type == types.ResponseTypeFlush { + if res.Type == types.MessageType_Flush { err = bufWriter.Flush() if err != nil { closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index a8a8d7c4..8fb02585 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -61,7 +61,7 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { if err != nil { return nil, err } - if resFlush.Type != types.ResponseTypeFlush { + if resFlush.Type != types.MessageType_Flush { return nil, errors.New(Fmt("Expected flush response but got something else: %v", resFlush.Type)) } diff --git a/types/messages.go b/types/messages.go index 061d34da..76e98f6f 100644 --- a/types/messages.go +++ b/types/messages.go @@ -7,53 +7,28 @@ import ( "github.com/tendermint/go-wire" ) -const ( - RequestTypeEcho = uint32(0x01) - RequestTypeFlush = uint32(0x02) - RequestTypeInfo = uint32(0x03) - RequestTypeSetOption = uint32(0x04) - // reserved for GetOption = uint32(0x05) - - ResponseTypeException = uint32(0x10) - ResponseTypeEcho = uint32(0x11) - ResponseTypeFlush = uint32(0x12) - ResponseTypeInfo = uint32(0x13) - ResponseTypeSetOption = uint32(0x14) - // reserved for GetOption = uint32(0x15) - - RequestTypeAppendTx = uint32(0x21) - RequestTypeCheckTx = uint32(0x22) - RequestTypeGetHash = uint32(0x23) - RequestTypeQuery = uint32(0x24) - - ResponseTypeAppendTx = uint32(0x31) - ResponseTypeCheckTx = uint32(0x32) - ResponseTypeGetHash = uint32(0x33) - ResponseTypeQuery = uint32(0x34) -) - func RequestEcho(message string) *Request { return &Request{ - Type: RequestTypeEcho, + Type: MessageType_Echo, Data: []byte(message), } } func RequestFlush() *Request { return &Request{ - Type: RequestTypeFlush, + Type: MessageType_Flush, } } func RequestInfo() *Request { return &Request{ - Type: RequestTypeInfo, + Type: MessageType_Info, } } func RequestSetOption(key string, value string) *Request { return &Request{ - Type: RequestTypeSetOption, + Type: MessageType_SetOption, Key: key, Value: value, } @@ -61,27 +36,27 @@ func RequestSetOption(key string, value string) *Request { func RequestAppendTx(txBytes []byte) *Request { return &Request{ - Type: RequestTypeAppendTx, + Type: MessageType_AppendTx, Data: txBytes, } } func RequestCheckTx(txBytes []byte) *Request { return &Request{ - Type: RequestTypeCheckTx, + Type: MessageType_CheckTx, Data: txBytes, } } func RequestGetHash() *Request { return &Request{ - Type: RequestTypeGetHash, + Type: MessageType_GetHash, } } func RequestQuery(queryBytes []byte) *Request { return &Request{ - Type: RequestTypeQuery, + Type: MessageType_Query, Data: queryBytes, } } @@ -90,41 +65,41 @@ func RequestQuery(queryBytes []byte) *Request { func ResponseException(errStr string) *Response { return &Response{ - Type: ResponseTypeException, + Type: MessageType_Exception, Error: errStr, } } func ResponseEcho(message string) *Response { return &Response{ - Type: ResponseTypeEcho, + Type: MessageType_Echo, Data: []byte(message), } } func ResponseFlush() *Response { return &Response{ - Type: ResponseTypeFlush, + Type: MessageType_Flush, } } func ResponseInfo(info string) *Response { return &Response{ - Type: ResponseTypeInfo, + Type: MessageType_Info, Data: []byte(info), } } func ResponseSetOption(log string) *Response { return &Response{ - Type: ResponseTypeSetOption, + Type: MessageType_SetOption, Log: log, } } func ResponseAppendTx(code RetCode, result []byte, log string) *Response { return &Response{ - Type: ResponseTypeAppendTx, + Type: MessageType_AppendTx, Code: uint32(code), Data: result, Log: log, @@ -133,7 +108,7 @@ func ResponseAppendTx(code RetCode, result []byte, log string) *Response { func ResponseCheckTx(code RetCode, result []byte, log string) *Response { return &Response{ - Type: ResponseTypeCheckTx, + Type: MessageType_CheckTx, Code: uint32(code), Data: result, Log: log, @@ -142,7 +117,7 @@ func ResponseCheckTx(code RetCode, result []byte, log string) *Response { func ResponseGetHash(hash []byte, log string) *Response { return &Response{ - Type: ResponseTypeGetHash, + Type: MessageType_GetHash, Data: hash, Log: log, } @@ -150,7 +125,7 @@ func ResponseGetHash(hash []byte, log string) *Response { func ResponseQuery(code RetCode, result []byte, log string) *Response { return &Response{ - Type: ResponseTypeQuery, + Type: MessageType_Query, Code: uint32(code), Data: result, Log: log, diff --git a/types/types.pb.go b/types/types.pb.go index 877c72ca..77f35078 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -23,11 +23,56 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +type MessageType int32 + +const ( + MessageType_NullMessage MessageType = 0 + MessageType_Echo MessageType = 1 + MessageType_Flush MessageType = 2 + MessageType_Info MessageType = 3 + MessageType_SetOption MessageType = 4 + MessageType_Exception MessageType = 5 + MessageType_AppendTx MessageType = 17 + MessageType_CheckTx MessageType = 18 + MessageType_GetHash MessageType = 19 + MessageType_Query MessageType = 20 +) + +var MessageType_name = map[int32]string{ + 0: "NullMessage", + 1: "Echo", + 2: "Flush", + 3: "Info", + 4: "SetOption", + 5: "Exception", + 17: "AppendTx", + 18: "CheckTx", + 19: "GetHash", + 20: "Query", +} +var MessageType_value = map[string]int32{ + "NullMessage": 0, + "Echo": 1, + "Flush": 2, + "Info": 3, + "SetOption": 4, + "Exception": 5, + "AppendTx": 17, + "CheckTx": 18, + "GetHash": 19, + "Query": 20, +} + +func (x MessageType) String() string { + return proto.EnumName(MessageType_name, int32(x)) +} +func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + type Request struct { - Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` - Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` + Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` + Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` } func (m *Request) Reset() { *m = Request{} } @@ -36,11 +81,11 @@ func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } type Response struct { - Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Code uint32 `protobuf:"varint,3,opt,name=code" json:"code,omitempty"` - Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` - Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` + Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Code uint32 `protobuf:"varint,3,opt,name=code" json:"code,omitempty"` + Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` + Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` } func (m *Response) Reset() { *m = Response{} } @@ -51,19 +96,27 @@ func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} func init() { proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*Response)(nil), "types.Response") + proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) } var fileDescriptor0 = []byte{ - // 165 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x8f, 0xb1, 0xae, 0xc2, 0x30, - 0x0c, 0x45, 0xd5, 0xd7, 0xe6, 0x01, 0x16, 0x48, 0x10, 0x31, 0x64, 0x44, 0x9d, 0x98, 0x60, 0xe0, - 0x4f, 0xb2, 0x31, 0x06, 0x6a, 0x31, 0x50, 0xd5, 0x21, 0x49, 0x91, 0xfa, 0xf7, 0xd8, 0xae, 0xd8, - 0x59, 0xa2, 0x73, 0x8f, 0xa2, 0xab, 0x6b, 0xd8, 0x95, 0x29, 0x62, 0x3e, 0xeb, 0x7b, 0x8a, 0x89, - 0x0a, 0x59, 0xa3, 0xa1, 0xbd, 0xc2, 0xc2, 0xe3, 0x6b, 0xc4, 0x5c, 0xac, 0x85, 0x46, 0x9c, 0xab, - 0x0e, 0xd5, 0x71, 0xe3, 0x95, 0xc5, 0x75, 0xa1, 0x04, 0xf7, 0xc7, 0x6e, 0xed, 0x95, 0xed, 0x16, - 0xea, 0x27, 0x4e, 0xae, 0x66, 0xb5, 0xf2, 0x82, 0x76, 0x0f, 0xe6, 0x1d, 0xfa, 0x11, 0x5d, 0xa3, - 0x6e, 0x0e, 0xed, 0x00, 0x4b, 0x8f, 0x39, 0xd2, 0x90, 0xf1, 0xe7, 0x6e, 0x76, 0x77, 0xea, 0x50, - 0xcb, 0xf9, 0x9f, 0xb0, 0xb4, 0x63, 0x4a, 0x94, 0xbe, 0xed, 0x1a, 0x64, 0x45, 0x4f, 0x0f, 0x67, - 0xe6, 0x15, 0x8c, 0xb7, 0x7f, 0x3d, 0xec, 0xf2, 0x09, 0x00, 0x00, 0xff, 0xff, 0xce, 0x9d, 0x3d, - 0x4f, 0xed, 0x00, 0x00, 0x00, + // 284 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x91, 0x4d, 0x4e, 0xc3, 0x30, + 0x10, 0x85, 0x49, 0x9b, 0xd0, 0x64, 0xd2, 0x82, 0x3b, 0x74, 0x91, 0x25, 0xea, 0x02, 0x21, 0x16, + 0x45, 0x82, 0x13, 0x20, 0x54, 0x7e, 0x16, 0x80, 0x30, 0xbd, 0x40, 0x48, 0x86, 0x06, 0x35, 0xc4, + 0x26, 0xb6, 0x51, 0xb3, 0xe5, 0x00, 0x9c, 0x19, 0xdb, 0x01, 0x89, 0x3d, 0x9b, 0xe8, 0x7d, 0x5f, + 0x46, 0xf3, 0x46, 0x32, 0x4c, 0x75, 0x27, 0x49, 0x9d, 0xfa, 0xef, 0x42, 0xb6, 0x42, 0x0b, 0x8c, + 0x3c, 0xcc, 0xdf, 0x60, 0xc4, 0xe9, 0xdd, 0x90, 0xd2, 0x78, 0x04, 0xa1, 0x73, 0x59, 0x70, 0x18, + 0x1c, 0xef, 0x9d, 0xe1, 0xa2, 0x9f, 0xbe, 0x23, 0xa5, 0xf2, 0x35, 0xad, 0x2c, 0x70, 0xff, 0x1f, + 0x11, 0xc2, 0x32, 0xd7, 0x79, 0x36, 0xb0, 0x73, 0x63, 0xee, 0x33, 0x32, 0x18, 0x6e, 0xa8, 0xcb, + 0x86, 0x56, 0x25, 0xdc, 0x45, 0x9c, 0x41, 0xf4, 0x91, 0xd7, 0x86, 0xb2, 0xd0, 0xbb, 0x1e, 0xe6, + 0x9f, 0x01, 0xc4, 0x9c, 0x94, 0x14, 0x8d, 0xa2, 0x7f, 0x15, 0x5a, 0x57, 0x88, 0x92, 0x7c, 0xe3, + 0x84, 0xfb, 0xec, 0x2a, 0xa9, 0x6d, 0x45, 0xfb, 0x5b, 0xe9, 0xc1, 0x9d, 0x56, 0x8b, 0x75, 0x16, + 0xf5, 0xa7, 0xd9, 0x78, 0xf2, 0x15, 0x40, 0xfa, 0xa7, 0x05, 0xf7, 0x21, 0xbd, 0x37, 0x75, 0xfd, + 0xa3, 0xd8, 0x0e, 0xc6, 0x10, 0x2e, 0x8b, 0x4a, 0xb0, 0x00, 0x13, 0x88, 0xae, 0x6a, 0xa3, 0x2a, + 0x36, 0x70, 0xf2, 0xb6, 0x79, 0x11, 0x6c, 0x88, 0x13, 0x48, 0x9e, 0x48, 0x3f, 0x48, 0xfd, 0x2a, + 0x1a, 0x16, 0x3a, 0x5c, 0x6e, 0x0b, 0xea, 0x31, 0xc2, 0x31, 0xc4, 0x17, 0x52, 0x52, 0x53, 0xae, + 0xb6, 0x6c, 0x8a, 0x29, 0x8c, 0x2e, 0x2b, 0x2a, 0x36, 0x16, 0xd0, 0xc1, 0x35, 0xe9, 0x9b, 0xdc, + 0xee, 0x3b, 0x70, 0xab, 0x1f, 0x0d, 0xb5, 0x1d, 0x9b, 0x3d, 0xef, 0xfa, 0x27, 0x39, 0xff, 0x0e, + 0x00, 0x00, 0xff, 0xff, 0x14, 0xe1, 0x50, 0x1f, 0xa7, 0x01, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 8a00c3ca..25930329 100644 --- a/types/types.proto +++ b/types/types.proto @@ -1,35 +1,30 @@ syntax = "proto3"; - package types; +// This file is copied from http://github.com/tendermint/tmsp + //---------------------------------------- // Message types -/* - RequestTypeEcho = 0x01; - RequestTypeFlush = 0x02; - RequestTypeInfo = 0x03; - RequestTypeSetOption = 0x04; - RequestTypeAppendTx = 0x21; - RequestTypeCheckTx = 0x22; - RequestTypeGetHash = 0x23; - RequestTypeQuery = 0x24; +enum MessageType { + NullMessage = 0x00; - ResponseTypeEcho = 0x11; - ResponseTypeFlush = 0x12; - ResponseTypeInfo = 0x13; - ResponseTypeSetOption = 0x14; - ResponseTypeAppendTx = 0x31; - ResponseTypeCheckTx = 0x32; - ResponseTypeGetHash = 0x33; - ResponseTypeQuery = 0x34; -*/ + Echo = 0x01; + Flush = 0x02; + Info = 0x03; + SetOption = 0x04; + Exception = 0x05; + AppendTx = 0x11; + CheckTx = 0x12; + GetHash = 0x13; + Query = 0x14; +} //---------------------------------------- // Request types message Request { - uint32 type = 1; + MessageType type = 1; bytes data = 2; string key = 3; string value = 4; @@ -39,9 +34,10 @@ message Request { // Response types message Response { - uint32 type = 1; + MessageType type = 1; bytes data = 2; uint32 code = 3; string error = 4; string log = 5; } + From 69e587f57fe2f5dcec0d112e9f5395dcc6785c85 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 31 Jan 2016 20:39:43 -0800 Subject: [PATCH 069/545] Use protobuf enums for RetCode. s/RetCode/CodeType/g --- client/client.go | 18 ++++---- example/golang/counter.go | 16 +++---- example/golang/dummy.go | 12 +++--- example/golang/dummy_test.go | 2 +- types/application.go | 6 +-- types/messages.go | 12 +++--- types/retcode.go | 20 --------- types/retcode_string.go | 16 ------- types/types.pb.go | 83 +++++++++++++++++++++++++++--------- types/types.proto | 15 ++++++- 10 files changed, 110 insertions(+), 90 deletions(-) delete mode 100644 types/retcode.go delete mode 100644 types/retcode_string.go diff --git a/client/client.go b/client/client.go index 93232b2d..07da0e65 100644 --- a/client/client.go +++ b/client/client.go @@ -219,24 +219,24 @@ func (cli *TMSPClient) FlushSync() error { return cli.err } -func (cli *TMSPClient) AppendTxSync(tx []byte) (code types.RetCode, result []byte, log string, err error) { +func (cli *TMSPClient) AppendTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestAppendTx(tx)) cli.FlushSync() if cli.err != nil { - return types.RetCodeInternalError, nil, "", cli.err + return types.CodeType_InternalError, nil, "", cli.err } res := reqres.Response - return types.RetCode(res.Code), res.Data, res.Log, nil + return res.Code, res.Data, res.Log, nil } -func (cli *TMSPClient) CheckTxSync(tx []byte) (code types.RetCode, result []byte, log string, err error) { +func (cli *TMSPClient) CheckTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestCheckTx(tx)) cli.FlushSync() if cli.err != nil { - return types.RetCodeInternalError, nil, "", cli.err + return types.CodeType_InternalError, nil, "", cli.err } res := reqres.Response - return types.RetCode(res.Code), res.Data, res.Log, nil + return res.Code, res.Data, res.Log, nil } func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) { @@ -249,14 +249,14 @@ func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) { return res.Data, res.Log, nil } -func (cli *TMSPClient) QuerySync(query []byte) (code types.RetCode, result []byte, log string, err error) { +func (cli *TMSPClient) QuerySync(query []byte) (code types.CodeType, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestQuery(query)) cli.FlushSync() if cli.err != nil { - return types.RetCodeInternalError, nil, "", cli.err + return types.CodeType_InternalError, nil, "", cli.err } res := reqres.Response - return types.RetCode(res.Code), res.Data, res.Log, nil + return res.Code, res.Data, res.Log, nil } //---------------------------------------- diff --git a/example/golang/counter.go b/example/golang/counter.go index 120eb318..1d1081df 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -29,29 +29,29 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) return "" } -func (app *CounterApplication) AppendTx(tx []byte) (code types.RetCode, result []byte, log string) { +func (app *CounterApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { if app.serial { tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.RetCodeBadNonce, nil, fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue) + return types.CodeType_BadNonce, nil, fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue) } } app.txCount += 1 - return types.RetCodeOK, nil, "" + return types.CodeType_OK, nil, "" } -func (app *CounterApplication) CheckTx(tx []byte) (code types.RetCode, result []byte, log string) { +func (app *CounterApplication) CheckTx(tx []byte) (code types.CodeType, result []byte, log string) { if app.serial { tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.RetCodeBadNonce, nil, fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue) + return types.CodeType_BadNonce, nil, fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue) } } - return types.RetCodeOK, nil, "" + return types.CodeType_OK, nil, "" } func (app *CounterApplication) GetHash() (hash []byte, log string) { @@ -66,6 +66,6 @@ func (app *CounterApplication) GetHash() (hash []byte, log string) { } } -func (app *CounterApplication) Query(query []byte) (code types.RetCode, result []byte, log string) { - return types.RetCodeOK, nil, fmt.Sprintf("Query is not supported") +func (app *CounterApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { + return types.CodeType_OK, nil, fmt.Sprintf("Query is not supported") } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 59d77dc3..71d5d3e4 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -26,13 +26,13 @@ func (app *DummyApplication) SetOption(key string, value string) (log string) { return "" } -func (app *DummyApplication) AppendTx(tx []byte) (code types.RetCode, result []byte, log string) { +func (app *DummyApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { app.state.Set(tx, tx) - return types.RetCodeOK, nil, "" + return types.CodeType_OK, nil, "" } -func (app *DummyApplication) CheckTx(tx []byte) (code types.RetCode, result []byte, log string) { - return types.RetCodeOK, nil, "" +func (app *DummyApplication) CheckTx(tx []byte) (code types.CodeType, result []byte, log string) { + return types.CodeType_OK, nil, "" } func (app *DummyApplication) GetHash() (hash []byte, log string) { @@ -40,6 +40,6 @@ func (app *DummyApplication) GetHash() (hash []byte, log string) { return hash, "" } -func (app *DummyApplication) Query(query []byte) (code types.RetCode, result []byte, log string) { - return types.RetCodeOK, nil, "Query not supported" +func (app *DummyApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { + return types.CodeType_OK, nil, "Query not supported" } diff --git a/example/golang/dummy_test.go b/example/golang/dummy_test.go index fa3d55c7..3e27e5e8 100644 --- a/example/golang/dummy_test.go +++ b/example/golang/dummy_test.go @@ -41,7 +41,7 @@ func TestStream(t *testing.T) { switch res.Type { case types.MessageType_AppendTx: counter += 1 - if types.RetCode(res.Code) != types.RetCodeOK { + if res.Code != types.CodeType_OK { t.Error("AppendTx failed with ret_code", res.Code) } if counter > numAppendTxs { diff --git a/types/application.go b/types/application.go index 0610d418..8f27282f 100644 --- a/types/application.go +++ b/types/application.go @@ -9,14 +9,14 @@ type Application interface { SetOption(key string, value string) (log string) // Append a tx - AppendTx(tx []byte) (code RetCode, result []byte, log string) + AppendTx(tx []byte) (code CodeType, result []byte, log string) // Validate a tx for the mempool - CheckTx(tx []byte) (code RetCode, result []byte, log string) + CheckTx(tx []byte) (code CodeType, result []byte, log string) // Return the application Merkle root hash GetHash() (hash []byte, log string) // Query for state - Query(query []byte) (code RetCode, result []byte, log string) + Query(query []byte) (code CodeType, result []byte, log string) } diff --git a/types/messages.go b/types/messages.go index 76e98f6f..736745bf 100644 --- a/types/messages.go +++ b/types/messages.go @@ -97,19 +97,19 @@ func ResponseSetOption(log string) *Response { } } -func ResponseAppendTx(code RetCode, result []byte, log string) *Response { +func ResponseAppendTx(code CodeType, result []byte, log string) *Response { return &Response{ Type: MessageType_AppendTx, - Code: uint32(code), + Code: code, Data: result, Log: log, } } -func ResponseCheckTx(code RetCode, result []byte, log string) *Response { +func ResponseCheckTx(code CodeType, result []byte, log string) *Response { return &Response{ Type: MessageType_CheckTx, - Code: uint32(code), + Code: code, Data: result, Log: log, } @@ -123,10 +123,10 @@ func ResponseGetHash(hash []byte, log string) *Response { } } -func ResponseQuery(code RetCode, result []byte, log string) *Response { +func ResponseQuery(code CodeType, result []byte, log string) *Response { return &Response{ Type: MessageType_Query, - Code: uint32(code), + Code: code, Data: result, Log: log, } diff --git a/types/retcode.go b/types/retcode.go deleted file mode 100644 index c6bf3e20..00000000 --- a/types/retcode.go +++ /dev/null @@ -1,20 +0,0 @@ -package types - -type RetCode uint - -// Reserved return codes -const ( - RetCodeOK RetCode = 0 - RetCodeInternalError RetCode = 1 - RetCodeUnauthorized RetCode = 2 - RetCodeInsufficientFees RetCode = 3 - RetCodeUnknownRequest RetCode = 4 - RetCodeEncodingError RetCode = 5 - RetCodeBadNonce RetCode = 6 -) - -//go:generate stringer -type=RetCode - -// NOTE: The previous comment generates r.String(). -// To run it, `go get golang.org/x/tools/cmd/stringer` -// and `go generate` in tmsp/types diff --git a/types/retcode_string.go b/types/retcode_string.go deleted file mode 100644 index 0f30688b..00000000 --- a/types/retcode_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// generated by stringer -type=RetCode; DO NOT EDIT - -package types - -import "fmt" - -const _RetCode_name = "RetCodeOKRetCodeInternalErrorRetCodeUnauthorizedRetCodeInsufficientFeesRetCodeUnknownRequestRetCodeEncodingErrorRetCodeBadNonce" - -var _RetCode_index = [...]uint8{0, 9, 29, 48, 71, 92, 112, 127} - -func (i RetCode) String() string { - if i < 0 || i >= RetCode(len(_RetCode_index)-1) { - return fmt.Sprintf("RetCode(%d)", i) - } - return _RetCode_name[_RetCode_index[i]:_RetCode_index[i+1]] -} diff --git a/types/types.pb.go b/types/types.pb.go index 77f35078..e26f6d85 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -68,6 +68,42 @@ func (x MessageType) String() string { } func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +type CodeType int32 + +const ( + CodeType_OK CodeType = 0 + CodeType_InternalError CodeType = 1 + CodeType_Unauthorized CodeType = 2 + CodeType_InsufficientFees CodeType = 3 + CodeType_UnknownRequest CodeType = 4 + CodeType_EncodingError CodeType = 5 + CodeType_BadNonce CodeType = 6 +) + +var CodeType_name = map[int32]string{ + 0: "OK", + 1: "InternalError", + 2: "Unauthorized", + 3: "InsufficientFees", + 4: "UnknownRequest", + 5: "EncodingError", + 6: "BadNonce", +} +var CodeType_value = map[string]int32{ + "OK": 0, + "InternalError": 1, + "Unauthorized": 2, + "InsufficientFees": 3, + "UnknownRequest": 4, + "EncodingError": 5, + "BadNonce": 6, +} + +func (x CodeType) String() string { + return proto.EnumName(CodeType_name, int32(x)) +} +func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + type Request struct { Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` @@ -83,7 +119,7 @@ func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} type Response struct { Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Code uint32 `protobuf:"varint,3,opt,name=code" json:"code,omitempty"` + Code CodeType `protobuf:"varint,3,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` } @@ -97,26 +133,33 @@ func init() { proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*Response)(nil), "types.Response") proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) + proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) } var fileDescriptor0 = []byte{ - // 284 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x91, 0x4d, 0x4e, 0xc3, 0x30, - 0x10, 0x85, 0x49, 0x9b, 0xd0, 0x64, 0xd2, 0x82, 0x3b, 0x74, 0x91, 0x25, 0xea, 0x02, 0x21, 0x16, - 0x45, 0x82, 0x13, 0x20, 0x54, 0x7e, 0x16, 0x80, 0x30, 0xbd, 0x40, 0x48, 0x86, 0x06, 0x35, 0xc4, - 0x26, 0xb6, 0x51, 0xb3, 0xe5, 0x00, 0x9c, 0x19, 0xdb, 0x01, 0x89, 0x3d, 0x9b, 0xe8, 0x7d, 0x5f, - 0x46, 0xf3, 0x46, 0x32, 0x4c, 0x75, 0x27, 0x49, 0x9d, 0xfa, 0xef, 0x42, 0xb6, 0x42, 0x0b, 0x8c, - 0x3c, 0xcc, 0xdf, 0x60, 0xc4, 0xe9, 0xdd, 0x90, 0xd2, 0x78, 0x04, 0xa1, 0x73, 0x59, 0x70, 0x18, - 0x1c, 0xef, 0x9d, 0xe1, 0xa2, 0x9f, 0xbe, 0x23, 0xa5, 0xf2, 0x35, 0xad, 0x2c, 0x70, 0xff, 0x1f, - 0x11, 0xc2, 0x32, 0xd7, 0x79, 0x36, 0xb0, 0x73, 0x63, 0xee, 0x33, 0x32, 0x18, 0x6e, 0xa8, 0xcb, - 0x86, 0x56, 0x25, 0xdc, 0x45, 0x9c, 0x41, 0xf4, 0x91, 0xd7, 0x86, 0xb2, 0xd0, 0xbb, 0x1e, 0xe6, - 0x9f, 0x01, 0xc4, 0x9c, 0x94, 0x14, 0x8d, 0xa2, 0x7f, 0x15, 0x5a, 0x57, 0x88, 0x92, 0x7c, 0xe3, - 0x84, 0xfb, 0xec, 0x2a, 0xa9, 0x6d, 0x45, 0xfb, 0x5b, 0xe9, 0xc1, 0x9d, 0x56, 0x8b, 0x75, 0x16, - 0xf5, 0xa7, 0xd9, 0x78, 0xf2, 0x15, 0x40, 0xfa, 0xa7, 0x05, 0xf7, 0x21, 0xbd, 0x37, 0x75, 0xfd, - 0xa3, 0xd8, 0x0e, 0xc6, 0x10, 0x2e, 0x8b, 0x4a, 0xb0, 0x00, 0x13, 0x88, 0xae, 0x6a, 0xa3, 0x2a, - 0x36, 0x70, 0xf2, 0xb6, 0x79, 0x11, 0x6c, 0x88, 0x13, 0x48, 0x9e, 0x48, 0x3f, 0x48, 0xfd, 0x2a, - 0x1a, 0x16, 0x3a, 0x5c, 0x6e, 0x0b, 0xea, 0x31, 0xc2, 0x31, 0xc4, 0x17, 0x52, 0x52, 0x53, 0xae, - 0xb6, 0x6c, 0x8a, 0x29, 0x8c, 0x2e, 0x2b, 0x2a, 0x36, 0x16, 0xd0, 0xc1, 0x35, 0xe9, 0x9b, 0xdc, - 0xee, 0x3b, 0x70, 0xab, 0x1f, 0x0d, 0xb5, 0x1d, 0x9b, 0x3d, 0xef, 0xfa, 0x27, 0x39, 0xff, 0x0e, - 0x00, 0x00, 0xff, 0xff, 0x14, 0xe1, 0x50, 0x1f, 0xa7, 0x01, 0x00, 0x00, + // 382 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x92, 0xdf, 0x0e, 0xd2, 0x30, + 0x14, 0xc6, 0x1d, 0x6c, 0xfc, 0x39, 0xfc, 0x2b, 0x47, 0x2e, 0x76, 0x69, 0x30, 0x31, 0x86, 0x0b, + 0x4c, 0xf0, 0x09, 0x94, 0x0c, 0x25, 0x46, 0x88, 0x13, 0x1e, 0xa0, 0x6e, 0x07, 0xb6, 0x30, 0xdb, + 0xb9, 0x76, 0x0a, 0x5e, 0xfa, 0x00, 0xde, 0xf8, 0xc2, 0xb6, 0x1d, 0x24, 0xde, 0x7b, 0xb3, 0x9c, + 0xef, 0x6b, 0xfb, 0x9d, 0x5f, 0xcf, 0x0a, 0x53, 0x7d, 0x2b, 0x49, 0xbd, 0x72, 0xdf, 0x65, 0x59, + 0x49, 0x2d, 0x31, 0x70, 0x62, 0xfe, 0x15, 0xba, 0x31, 0x7d, 0xab, 0x49, 0x69, 0x7c, 0x01, 0xbe, + 0xf5, 0x42, 0xef, 0x99, 0xf7, 0x72, 0xbc, 0xc2, 0x65, 0xb3, 0xfb, 0x23, 0x29, 0xc5, 0xcf, 0x74, + 0x30, 0x22, 0x76, 0xeb, 0x88, 0xe0, 0xa7, 0x5c, 0xf3, 0xb0, 0x65, 0xf6, 0x0d, 0x63, 0x57, 0x23, + 0x83, 0xf6, 0x85, 0x6e, 0x61, 0xdb, 0x58, 0xfd, 0xd8, 0x96, 0x38, 0x83, 0xe0, 0x3b, 0x2f, 0x6a, + 0x0a, 0x7d, 0xe7, 0x35, 0x62, 0xfe, 0xc7, 0x83, 0x5e, 0x4c, 0xaa, 0x94, 0x42, 0xd1, 0x7f, 0x35, + 0x7c, 0x0e, 0x7e, 0x22, 0x53, 0x72, 0x1d, 0xc7, 0xab, 0xc9, 0xfd, 0xec, 0xda, 0x58, 0xcd, 0x41, + 0xbb, 0x68, 0x19, 0xa8, 0xaa, 0x64, 0xf5, 0x60, 0x70, 0xc2, 0xb2, 0x16, 0xf2, 0x1c, 0x06, 0x0d, + 0xab, 0x29, 0x17, 0xbf, 0x3d, 0x18, 0xfc, 0xd3, 0x16, 0x27, 0x30, 0xd8, 0xd5, 0x45, 0x71, 0xb7, + 0xd8, 0x13, 0xec, 0x81, 0x1f, 0x25, 0x99, 0x64, 0x1e, 0xf6, 0x21, 0xd8, 0x14, 0xb5, 0xca, 0x58, + 0xcb, 0x9a, 0x5b, 0x71, 0x92, 0xac, 0x8d, 0x23, 0xe8, 0x7f, 0x26, 0xbd, 0x2f, 0x75, 0x2e, 0x05, + 0xf3, 0xad, 0x8c, 0xae, 0x09, 0x35, 0x32, 0xc0, 0x21, 0xf4, 0xde, 0x94, 0x25, 0x89, 0xf4, 0x70, + 0x65, 0x53, 0x1c, 0x40, 0x77, 0x9d, 0x51, 0x72, 0x31, 0x02, 0xad, 0x78, 0x47, 0xfa, 0x3d, 0x37, + 0x79, 0x4f, 0x6d, 0xf4, 0xa7, 0x9a, 0xaa, 0x1b, 0x9b, 0x2d, 0x7e, 0x99, 0x31, 0x3d, 0xee, 0x82, + 0x1d, 0x68, 0xed, 0x3f, 0x18, 0x88, 0x29, 0x8c, 0xb6, 0x42, 0x53, 0x25, 0x78, 0x11, 0xd9, 0x8b, + 0x18, 0x1a, 0x06, 0xc3, 0xa3, 0xe0, 0xb5, 0xce, 0x64, 0x95, 0xff, 0xa4, 0xd4, 0x40, 0xcd, 0x80, + 0x6d, 0x85, 0xaa, 0x4f, 0xa7, 0x3c, 0xc9, 0x49, 0xe8, 0x0d, 0x91, 0x32, 0x80, 0x08, 0xe3, 0xa3, + 0xb8, 0x08, 0xf9, 0x43, 0xdc, 0x7f, 0xb6, 0xa1, 0x34, 0x71, 0x91, 0x30, 0x63, 0xca, 0xc5, 0xb9, + 0x89, 0x73, 0xa4, 0x6f, 0x79, 0xba, 0x93, 0x22, 0x21, 0xd6, 0xf9, 0xd2, 0x71, 0x0f, 0xe5, 0xf5, + 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x93, 0xf0, 0xfc, 0x3d, 0x02, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 25930329..457d3b91 100644 --- a/types/types.proto +++ b/types/types.proto @@ -20,6 +20,19 @@ enum MessageType { Query = 0x14; } +//---------------------------------------- +// Code types + +enum CodeType { + OK = 0; + InternalError = 1; + Unauthorized = 2; + InsufficientFees = 3; + UnknownRequest = 4; + EncodingError = 5; + BadNonce = 6; +} + //---------------------------------------- // Request types @@ -36,7 +49,7 @@ message Request { message Response { MessageType type = 1; bytes data = 2; - uint32 code = 3; + CodeType code = 3; string error = 4; string log = 5; } From 2281bba708c1ae8ec8ff55cb7f1e2d7e9bc63f8c Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 3 Feb 2016 01:58:23 -0800 Subject: [PATCH 070/545] Add two new CodeTypes --- types/types.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/types.proto b/types/types.proto index 457d3b91..f14276d1 100644 --- a/types/types.proto +++ b/types/types.proto @@ -31,6 +31,8 @@ enum CodeType { UnknownRequest = 4; EncodingError = 5; BadNonce = 6; + UnknownAccount = 7; + InsufficientFunds = 8; } //---------------------------------------- From cf0ad66d5130711558470cb4fcbfa761723eec0d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 5 Feb 2016 23:15:08 -0800 Subject: [PATCH 071/545] Compile new types.proto for new CodeType enums --- types/types.pb.go | 86 ++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index e26f6d85..8e86ed28 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -71,13 +71,15 @@ func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, [] type CodeType int32 const ( - CodeType_OK CodeType = 0 - CodeType_InternalError CodeType = 1 - CodeType_Unauthorized CodeType = 2 - CodeType_InsufficientFees CodeType = 3 - CodeType_UnknownRequest CodeType = 4 - CodeType_EncodingError CodeType = 5 - CodeType_BadNonce CodeType = 6 + CodeType_OK CodeType = 0 + CodeType_InternalError CodeType = 1 + CodeType_Unauthorized CodeType = 2 + CodeType_InsufficientFees CodeType = 3 + CodeType_UnknownRequest CodeType = 4 + CodeType_EncodingError CodeType = 5 + CodeType_BadNonce CodeType = 6 + CodeType_UnknownAccount CodeType = 7 + CodeType_InsufficientFunds CodeType = 8 ) var CodeType_name = map[int32]string{ @@ -88,15 +90,19 @@ var CodeType_name = map[int32]string{ 4: "UnknownRequest", 5: "EncodingError", 6: "BadNonce", + 7: "UnknownAccount", + 8: "InsufficientFunds", } var CodeType_value = map[string]int32{ - "OK": 0, - "InternalError": 1, - "Unauthorized": 2, - "InsufficientFees": 3, - "UnknownRequest": 4, - "EncodingError": 5, - "BadNonce": 6, + "OK": 0, + "InternalError": 1, + "Unauthorized": 2, + "InsufficientFees": 3, + "UnknownRequest": 4, + "EncodingError": 5, + "BadNonce": 6, + "UnknownAccount": 7, + "InsufficientFunds": 8, } func (x CodeType) String() string { @@ -137,29 +143,31 @@ func init() { } var fileDescriptor0 = []byte{ - // 382 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x92, 0xdf, 0x0e, 0xd2, 0x30, - 0x14, 0xc6, 0x1d, 0x6c, 0xfc, 0x39, 0xfc, 0x2b, 0x47, 0x2e, 0x76, 0x69, 0x30, 0x31, 0x86, 0x0b, - 0x4c, 0xf0, 0x09, 0x94, 0x0c, 0x25, 0x46, 0x88, 0x13, 0x1e, 0xa0, 0x6e, 0x07, 0xb6, 0x30, 0xdb, - 0xb9, 0x76, 0x0a, 0x5e, 0xfa, 0x00, 0xde, 0xf8, 0xc2, 0xb6, 0x1d, 0x24, 0xde, 0x7b, 0xb3, 0x9c, - 0xef, 0x6b, 0xfb, 0x9d, 0x5f, 0xcf, 0x0a, 0x53, 0x7d, 0x2b, 0x49, 0xbd, 0x72, 0xdf, 0x65, 0x59, - 0x49, 0x2d, 0x31, 0x70, 0x62, 0xfe, 0x15, 0xba, 0x31, 0x7d, 0xab, 0x49, 0x69, 0x7c, 0x01, 0xbe, - 0xf5, 0x42, 0xef, 0x99, 0xf7, 0x72, 0xbc, 0xc2, 0x65, 0xb3, 0xfb, 0x23, 0x29, 0xc5, 0xcf, 0x74, - 0x30, 0x22, 0x76, 0xeb, 0x88, 0xe0, 0xa7, 0x5c, 0xf3, 0xb0, 0x65, 0xf6, 0x0d, 0x63, 0x57, 0x23, - 0x83, 0xf6, 0x85, 0x6e, 0x61, 0xdb, 0x58, 0xfd, 0xd8, 0x96, 0x38, 0x83, 0xe0, 0x3b, 0x2f, 0x6a, - 0x0a, 0x7d, 0xe7, 0x35, 0x62, 0xfe, 0xc7, 0x83, 0x5e, 0x4c, 0xaa, 0x94, 0x42, 0xd1, 0x7f, 0x35, - 0x7c, 0x0e, 0x7e, 0x22, 0x53, 0x72, 0x1d, 0xc7, 0xab, 0xc9, 0xfd, 0xec, 0xda, 0x58, 0xcd, 0x41, - 0xbb, 0x68, 0x19, 0xa8, 0xaa, 0x64, 0xf5, 0x60, 0x70, 0xc2, 0xb2, 0x16, 0xf2, 0x1c, 0x06, 0x0d, - 0xab, 0x29, 0x17, 0xbf, 0x3d, 0x18, 0xfc, 0xd3, 0x16, 0x27, 0x30, 0xd8, 0xd5, 0x45, 0x71, 0xb7, - 0xd8, 0x13, 0xec, 0x81, 0x1f, 0x25, 0x99, 0x64, 0x1e, 0xf6, 0x21, 0xd8, 0x14, 0xb5, 0xca, 0x58, - 0xcb, 0x9a, 0x5b, 0x71, 0x92, 0xac, 0x8d, 0x23, 0xe8, 0x7f, 0x26, 0xbd, 0x2f, 0x75, 0x2e, 0x05, - 0xf3, 0xad, 0x8c, 0xae, 0x09, 0x35, 0x32, 0xc0, 0x21, 0xf4, 0xde, 0x94, 0x25, 0x89, 0xf4, 0x70, - 0x65, 0x53, 0x1c, 0x40, 0x77, 0x9d, 0x51, 0x72, 0x31, 0x02, 0xad, 0x78, 0x47, 0xfa, 0x3d, 0x37, - 0x79, 0x4f, 0x6d, 0xf4, 0xa7, 0x9a, 0xaa, 0x1b, 0x9b, 0x2d, 0x7e, 0x99, 0x31, 0x3d, 0xee, 0x82, - 0x1d, 0x68, 0xed, 0x3f, 0x18, 0x88, 0x29, 0x8c, 0xb6, 0x42, 0x53, 0x25, 0x78, 0x11, 0xd9, 0x8b, - 0x18, 0x1a, 0x06, 0xc3, 0xa3, 0xe0, 0xb5, 0xce, 0x64, 0x95, 0xff, 0xa4, 0xd4, 0x40, 0xcd, 0x80, - 0x6d, 0x85, 0xaa, 0x4f, 0xa7, 0x3c, 0xc9, 0x49, 0xe8, 0x0d, 0x91, 0x32, 0x80, 0x08, 0xe3, 0xa3, - 0xb8, 0x08, 0xf9, 0x43, 0xdc, 0x7f, 0xb6, 0xa1, 0x34, 0x71, 0x91, 0x30, 0x63, 0xca, 0xc5, 0xb9, - 0x89, 0x73, 0xa4, 0x6f, 0x79, 0xba, 0x93, 0x22, 0x21, 0xd6, 0xf9, 0xd2, 0x71, 0x0f, 0xe5, 0xf5, - 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x93, 0xf0, 0xfc, 0x3d, 0x02, 0x00, 0x00, + // 405 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x92, 0xdf, 0x6e, 0xd3, 0x30, + 0x14, 0xc6, 0x49, 0x9b, 0xf4, 0xcf, 0x69, 0xd7, 0xb9, 0x87, 0x22, 0xe5, 0x12, 0x0d, 0x09, 0xa1, + 0x5d, 0x0c, 0x69, 0x3c, 0xc1, 0x98, 0x3a, 0xa8, 0x10, 0x9b, 0x08, 0xdb, 0x03, 0x18, 0xe7, 0xb4, + 0x8d, 0x1a, 0x8e, 0x43, 0x6c, 0xc3, 0xca, 0x43, 0x70, 0xc3, 0x73, 0xf0, 0x8e, 0xd8, 0x4e, 0x27, + 0x8d, 0x6b, 0x6e, 0xa2, 0xf3, 0x7d, 0xf6, 0xf9, 0xce, 0xcf, 0x8e, 0x61, 0x6e, 0xf7, 0x0d, 0x99, + 0xd7, 0xf1, 0x7b, 0xd6, 0xb4, 0xda, 0x6a, 0xcc, 0xa2, 0x38, 0xf9, 0x0a, 0xc3, 0x82, 0xbe, 0x39, + 0x32, 0x16, 0x5f, 0x42, 0x1a, 0xbc, 0x3c, 0x79, 0x9e, 0xbc, 0x9a, 0x9d, 0xe3, 0x59, 0xb7, 0xfb, + 0x23, 0x19, 0x23, 0x37, 0x74, 0xeb, 0x45, 0x11, 0xd7, 0x11, 0x21, 0x2d, 0xa5, 0x95, 0x79, 0xcf, + 0xef, 0x9b, 0x16, 0xb1, 0x46, 0x01, 0xfd, 0x1d, 0xed, 0xf3, 0xbe, 0xb7, 0xc6, 0x45, 0x28, 0x71, + 0x01, 0xd9, 0x77, 0x59, 0x3b, 0xca, 0xd3, 0xe8, 0x75, 0xe2, 0xe4, 0x77, 0x02, 0xa3, 0x82, 0x4c, + 0xa3, 0xd9, 0xd0, 0x7f, 0x0d, 0x7c, 0x01, 0xa9, 0xd2, 0x25, 0xc5, 0x89, 0xb3, 0xf3, 0xe3, 0x43, + 0xef, 0xa5, 0xb7, 0xba, 0xc6, 0xb0, 0x18, 0x18, 0xa8, 0x6d, 0x75, 0xfb, 0xc0, 0x10, 0x45, 0x60, + 0xad, 0xf5, 0x26, 0xcf, 0x3a, 0x56, 0x5f, 0x9e, 0xfe, 0x4a, 0x60, 0xf2, 0x68, 0x2c, 0x1e, 0xc3, + 0xe4, 0xda, 0xd5, 0xf5, 0xc1, 0x12, 0x4f, 0x70, 0x04, 0xe9, 0x52, 0x6d, 0xb5, 0x48, 0x70, 0x0c, + 0xd9, 0x55, 0xed, 0xcc, 0x56, 0xf4, 0x82, 0xb9, 0xe2, 0xb5, 0x16, 0x7d, 0x3c, 0x82, 0xf1, 0x67, + 0xb2, 0x37, 0x8d, 0xad, 0x34, 0x8b, 0x34, 0xc8, 0xe5, 0xbd, 0xa2, 0x4e, 0x66, 0x38, 0x85, 0xd1, + 0x45, 0xd3, 0x10, 0x97, 0xb7, 0xf7, 0x62, 0x8e, 0x13, 0x18, 0x5e, 0x6e, 0x49, 0xed, 0xbc, 0xc0, + 0x20, 0xde, 0x91, 0x7d, 0x2f, 0x7d, 0xde, 0xd3, 0x10, 0xfd, 0xc9, 0x51, 0xbb, 0x17, 0x8b, 0xd3, + 0x3f, 0xfe, 0x9a, 0x1e, 0xce, 0x82, 0x03, 0xe8, 0xdd, 0x7c, 0xf0, 0x10, 0x73, 0x38, 0x5a, 0xb1, + 0xa5, 0x96, 0x65, 0xbd, 0x0c, 0x07, 0xf1, 0x34, 0x02, 0xa6, 0x77, 0x2c, 0x9d, 0xdd, 0xea, 0xb6, + 0xfa, 0x49, 0xa5, 0x87, 0x5a, 0x80, 0x58, 0xb1, 0x71, 0xeb, 0x75, 0xa5, 0x2a, 0x62, 0x7b, 0x45, + 0x64, 0x3c, 0x20, 0xc2, 0xec, 0x8e, 0x77, 0xac, 0x7f, 0xf0, 0xe1, 0x67, 0x7b, 0x4a, 0x1f, 0xb7, + 0x64, 0x7f, 0x4d, 0x15, 0x6f, 0xba, 0xb8, 0x48, 0xfa, 0x56, 0x96, 0xd7, 0x9a, 0x15, 0x89, 0xc1, + 0xa3, 0xa6, 0x0b, 0xa5, 0xb4, 0x63, 0x2b, 0x86, 0xf8, 0x0c, 0xe6, 0xff, 0xc4, 0x3b, 0x2e, 0x8d, + 0x18, 0x7d, 0x19, 0xc4, 0x37, 0xf5, 0xe6, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x90, 0x25, + 0x05, 0x68, 0x02, 0x00, 0x00, } From b35492d9e7b55f874d8f1d74324937982d9f98c7 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 7 Feb 2016 19:59:19 -0800 Subject: [PATCH 072/545] better response printing --- cmd/tmsp-cli/tmsp-cli.go | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 5d516ed4..e6ea2124 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -164,7 +164,7 @@ func cmdEcho(c *cli.Context) { fmt.Println(err.Error()) return } - fmt.Println("->", res) + printResponse(res, string(res.Data)) } // Get some info from the application @@ -174,7 +174,7 @@ func cmdInfo(c *cli.Context) { fmt.Println(err.Error()) return } - fmt.Println("->", res) + printResponse(res, string(res.Data)) } // Set an option on the application @@ -184,12 +184,12 @@ func cmdSetOption(c *cli.Context) { fmt.Println("set_option takes 2 arguments (key, value)") return } - _, err := makeRequest(conn, types.RequestSetOption(args[0], args[1])) + res, err := makeRequest(conn, types.RequestSetOption(args[0], args[1])) if err != nil { fmt.Println(err.Error()) return } - fmt.Println("->", Fmt("%s=%s", args[0], args[1])) + printResponse(res, Fmt("%s=%s", args[0], args[1])) } // Append a new tx to application @@ -215,7 +215,7 @@ func cmdAppendTx(c *cli.Context) { fmt.Println(err.Error()) return } - fmt.Println("->", res) + printResponse(res, string(res.Data)) } // Validate a tx @@ -241,7 +241,7 @@ func cmdCheckTx(c *cli.Context) { fmt.Println(err.Error()) return } - fmt.Println("->", res) + printResponse(res, string(res.Data)) } // Get application Merkle root hash @@ -251,7 +251,7 @@ func cmdGetHash(c *cli.Context) { fmt.Println(err.Error()) return } - fmt.Printf("%X\n", res.Data) + printResponse(res, Fmt("%X", res.Data)) } // Query application state @@ -277,11 +277,29 @@ func cmdQuery(c *cli.Context) { fmt.Println(err.Error()) return } - fmt.Println("->", res) + printResponse(res, string(res.Data)) } //-------------------------------------------------------------------------------- +func printResponse(res *types.Response, s string) { + fmt.Printf("-> ") + if res.Error != "" { + fmt.Printf("error: %s\t", res.Error) + } + if res.Code > 0 { + fmt.Printf("code: %s", res.Code.String()) + } + if s != "" { + fmt.Printf("data: {%s}", s) + } + fmt.Printf("\n") +} + +func responseString(res *types.Response) string { + return Fmt("type: %v\tdata: %v\tcode: %v", res.Type, res.Data, res.Code) +} + func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { // Write desired request From 2d5e1e8340d7a5af056a0bcf83fddbcef5c13067 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 8 Feb 2016 00:50:00 -0800 Subject: [PATCH 073/545] Callbacks for ReqRes --- client/client.go | 103 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/client/client.go b/client/client.go index 07da0e65..adb2c463 100644 --- a/client/client.go +++ b/client/client.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/tmsp/types" ) +const reqQueueSize = 256 // TODO make configurable const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... @@ -24,20 +25,25 @@ type TMSPClient struct { QuitService sync.Mutex // [EB]: is this even used? - reqQueue chan *reqRes + reqQueue chan *ReqRes flushTimer *ThrottleTimer mtx sync.Mutex + addr string conn net.Conn bufWriter *bufio.Writer err error reqSent *list.List - resCb func(*types.Request, *types.Response) + resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { +func NewTMSPClient(addr string) (*TMSPClient, error) { + conn, err := Connect(addr) + if err != nil { + return nil, err + } cli := &TMSPClient{ - reqQueue: make(chan *reqRes, bufferSize), + reqQueue: make(chan *ReqRes, reqQueueSize), flushTimer: NewThrottleTimer("TMSPClient", flushThrottleMS), conn: conn, @@ -47,7 +53,7 @@ func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { } cli.QuitService = *NewQuitService(nil, "TMSPClient", cli) cli.Start() // Just start it, it's confusing for callers to remember to start. - return cli + return cli, nil } func (cli *TMSPClient) OnStart() error { @@ -62,6 +68,7 @@ func (cli *TMSPClient) OnStop() { cli.conn.Close() } +// Set listener for all responses // NOTE: callback may get internally generated flush responses. func (cli *TMSPClient) SetResponseCallback(resCb Callback) { cli.mtx.Lock() @@ -140,7 +147,7 @@ func (cli *TMSPClient) recvResponseRoutine() { } } -func (cli *TMSPClient) willSendReq(reqres *reqRes) { +func (cli *TMSPClient) willSendReq(reqres *ReqRes) { cli.mtx.Lock() defer cli.mtx.Unlock() cli.reqSent.PushBack(reqres) @@ -150,12 +157,12 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { cli.mtx.Lock() defer cli.mtx.Unlock() - // Get the first reqRes + // Get the first ReqRes next := cli.reqSent.Front() if next == nil { return fmt.Errorf("Unexpected result type %v when nothing expected", res.Type) } - reqres := next.Value.(*reqRes) + reqres := next.Value.(*ReqRes) if !resMatchesReq(reqres.Request, res) { return fmt.Errorf("Unexpected result type %v when response to %v expected", res.Type, reqres.Request.Type) @@ -165,7 +172,12 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { reqres.Done() // Release waiters cli.reqSent.Remove(next) // Pop first item from linked list - // Callback if there is a listener + // Notify reqRes listener if set + if cb := reqres.GetCallback(); cb != nil { + cb(res) + } + + // Notify client listener if set if cli.resCb != nil { cli.resCb(reqres.Request, res) } @@ -175,32 +187,32 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { //---------------------------------------- -func (cli *TMSPClient) EchoAsync(msg string) { - cli.queueRequest(types.RequestEcho(msg)) +func (cli *TMSPClient) EchoAsync(msg string) *ReqRes { + return cli.queueRequest(types.RequestEcho(msg)) } -func (cli *TMSPClient) FlushAsync() { - cli.queueRequest(types.RequestFlush()) +func (cli *TMSPClient) FlushAsync() *ReqRes { + return cli.queueRequest(types.RequestFlush()) } -func (cli *TMSPClient) SetOptionAsync(key string, value string) { - cli.queueRequest(types.RequestSetOption(key, value)) +func (cli *TMSPClient) SetOptionAsync(key string, value string) *ReqRes { + return cli.queueRequest(types.RequestSetOption(key, value)) } -func (cli *TMSPClient) AppendTxAsync(tx []byte) { - cli.queueRequest(types.RequestAppendTx(tx)) +func (cli *TMSPClient) AppendTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.RequestAppendTx(tx)) } -func (cli *TMSPClient) CheckTxAsync(tx []byte) { - cli.queueRequest(types.RequestCheckTx(tx)) +func (cli *TMSPClient) CheckTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.RequestCheckTx(tx)) } -func (cli *TMSPClient) GetHashAsync() { - cli.queueRequest(types.RequestGetHash()) +func (cli *TMSPClient) GetHashAsync() *ReqRes { + return cli.queueRequest(types.RequestGetHash()) } -func (cli *TMSPClient) QueryAsync(query []byte) { - cli.queueRequest(types.RequestQuery(query)) +func (cli *TMSPClient) QueryAsync(query []byte) *ReqRes { + return cli.queueRequest(types.RequestQuery(query)) } //---------------------------------------- @@ -261,7 +273,7 @@ func (cli *TMSPClient) QuerySync(query []byte) (code types.CodeType, result []by //---------------------------------------- -func (cli *TMSPClient) queueRequest(req *types.Request) *reqRes { +func (cli *TMSPClient) queueRequest(req *types.Request) *ReqRes { reqres := newReqRes(req) // TODO: set cli.err if reqQueue times out cli.reqQueue <- reqres @@ -283,20 +295,57 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { return req.Type == res.Type } -type reqRes struct { +type ReqRes struct { *types.Request *sync.WaitGroup *types.Response // Not set atomically, so be sure to use WaitGroup. + + mtx sync.Mutex + done bool // Gets set to true once *after* WaitGroup.Done(). + cb func(*types.Response) // A single callback that may be set. } -func newReqRes(req *types.Request) *reqRes { - return &reqRes{ +func newReqRes(req *types.Request) *ReqRes { + return &ReqRes{ Request: req, WaitGroup: waitGroup1(), Response: nil, + + done: false, + cb: nil, } } +// Sets the callback for this ReqRes atomically. +// If reqRes is already done, calls cb immediately. +// NOTE: reqRes.cb should not change if reqRes.done. +// NOTE: only one callback is supported. +func (reqRes *ReqRes) SetCallback(cb func(res *types.Response)) { + reqRes.mtx.Lock() + + if reqRes.done { + reqRes.mtx.Unlock() + cb(reqRes.Response) + return + } + + defer reqRes.mtx.Unlock() + reqRes.cb = cb +} + +func (reqRes *ReqRes) GetCallback() func(*types.Response) { + reqRes.mtx.Lock() + defer reqRes.mtx.Unlock() + return reqRes.cb +} + +// NOTE: it should be safe to read reqRes.cb without locks after this. +func (reqRes *ReqRes) SetDone() { + reqRes.mtx.Lock() + reqRes.done = true + reqRes.mtx.Unlock() +} + func waitGroup1() (wg *sync.WaitGroup) { wg = &sync.WaitGroup{} wg.Add(1) From adf0392e561f06e434c54b89f0a3ef38cc1a3459 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 8 Feb 2016 00:50:00 -0800 Subject: [PATCH 074/545] Callbacks for ReqRes --- client/client.go | 103 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/client/client.go b/client/client.go index 07da0e65..adb2c463 100644 --- a/client/client.go +++ b/client/client.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/tmsp/types" ) +const reqQueueSize = 256 // TODO make configurable const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... @@ -24,20 +25,25 @@ type TMSPClient struct { QuitService sync.Mutex // [EB]: is this even used? - reqQueue chan *reqRes + reqQueue chan *ReqRes flushTimer *ThrottleTimer mtx sync.Mutex + addr string conn net.Conn bufWriter *bufio.Writer err error reqSent *list.List - resCb func(*types.Request, *types.Response) + resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { +func NewTMSPClient(addr string) (*TMSPClient, error) { + conn, err := Connect(addr) + if err != nil { + return nil, err + } cli := &TMSPClient{ - reqQueue: make(chan *reqRes, bufferSize), + reqQueue: make(chan *ReqRes, reqQueueSize), flushTimer: NewThrottleTimer("TMSPClient", flushThrottleMS), conn: conn, @@ -47,7 +53,7 @@ func NewTMSPClient(conn net.Conn, bufferSize int) *TMSPClient { } cli.QuitService = *NewQuitService(nil, "TMSPClient", cli) cli.Start() // Just start it, it's confusing for callers to remember to start. - return cli + return cli, nil } func (cli *TMSPClient) OnStart() error { @@ -62,6 +68,7 @@ func (cli *TMSPClient) OnStop() { cli.conn.Close() } +// Set listener for all responses // NOTE: callback may get internally generated flush responses. func (cli *TMSPClient) SetResponseCallback(resCb Callback) { cli.mtx.Lock() @@ -140,7 +147,7 @@ func (cli *TMSPClient) recvResponseRoutine() { } } -func (cli *TMSPClient) willSendReq(reqres *reqRes) { +func (cli *TMSPClient) willSendReq(reqres *ReqRes) { cli.mtx.Lock() defer cli.mtx.Unlock() cli.reqSent.PushBack(reqres) @@ -150,12 +157,12 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { cli.mtx.Lock() defer cli.mtx.Unlock() - // Get the first reqRes + // Get the first ReqRes next := cli.reqSent.Front() if next == nil { return fmt.Errorf("Unexpected result type %v when nothing expected", res.Type) } - reqres := next.Value.(*reqRes) + reqres := next.Value.(*ReqRes) if !resMatchesReq(reqres.Request, res) { return fmt.Errorf("Unexpected result type %v when response to %v expected", res.Type, reqres.Request.Type) @@ -165,7 +172,12 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { reqres.Done() // Release waiters cli.reqSent.Remove(next) // Pop first item from linked list - // Callback if there is a listener + // Notify reqRes listener if set + if cb := reqres.GetCallback(); cb != nil { + cb(res) + } + + // Notify client listener if set if cli.resCb != nil { cli.resCb(reqres.Request, res) } @@ -175,32 +187,32 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { //---------------------------------------- -func (cli *TMSPClient) EchoAsync(msg string) { - cli.queueRequest(types.RequestEcho(msg)) +func (cli *TMSPClient) EchoAsync(msg string) *ReqRes { + return cli.queueRequest(types.RequestEcho(msg)) } -func (cli *TMSPClient) FlushAsync() { - cli.queueRequest(types.RequestFlush()) +func (cli *TMSPClient) FlushAsync() *ReqRes { + return cli.queueRequest(types.RequestFlush()) } -func (cli *TMSPClient) SetOptionAsync(key string, value string) { - cli.queueRequest(types.RequestSetOption(key, value)) +func (cli *TMSPClient) SetOptionAsync(key string, value string) *ReqRes { + return cli.queueRequest(types.RequestSetOption(key, value)) } -func (cli *TMSPClient) AppendTxAsync(tx []byte) { - cli.queueRequest(types.RequestAppendTx(tx)) +func (cli *TMSPClient) AppendTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.RequestAppendTx(tx)) } -func (cli *TMSPClient) CheckTxAsync(tx []byte) { - cli.queueRequest(types.RequestCheckTx(tx)) +func (cli *TMSPClient) CheckTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.RequestCheckTx(tx)) } -func (cli *TMSPClient) GetHashAsync() { - cli.queueRequest(types.RequestGetHash()) +func (cli *TMSPClient) GetHashAsync() *ReqRes { + return cli.queueRequest(types.RequestGetHash()) } -func (cli *TMSPClient) QueryAsync(query []byte) { - cli.queueRequest(types.RequestQuery(query)) +func (cli *TMSPClient) QueryAsync(query []byte) *ReqRes { + return cli.queueRequest(types.RequestQuery(query)) } //---------------------------------------- @@ -261,7 +273,7 @@ func (cli *TMSPClient) QuerySync(query []byte) (code types.CodeType, result []by //---------------------------------------- -func (cli *TMSPClient) queueRequest(req *types.Request) *reqRes { +func (cli *TMSPClient) queueRequest(req *types.Request) *ReqRes { reqres := newReqRes(req) // TODO: set cli.err if reqQueue times out cli.reqQueue <- reqres @@ -283,20 +295,57 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { return req.Type == res.Type } -type reqRes struct { +type ReqRes struct { *types.Request *sync.WaitGroup *types.Response // Not set atomically, so be sure to use WaitGroup. + + mtx sync.Mutex + done bool // Gets set to true once *after* WaitGroup.Done(). + cb func(*types.Response) // A single callback that may be set. } -func newReqRes(req *types.Request) *reqRes { - return &reqRes{ +func newReqRes(req *types.Request) *ReqRes { + return &ReqRes{ Request: req, WaitGroup: waitGroup1(), Response: nil, + + done: false, + cb: nil, } } +// Sets the callback for this ReqRes atomically. +// If reqRes is already done, calls cb immediately. +// NOTE: reqRes.cb should not change if reqRes.done. +// NOTE: only one callback is supported. +func (reqRes *ReqRes) SetCallback(cb func(res *types.Response)) { + reqRes.mtx.Lock() + + if reqRes.done { + reqRes.mtx.Unlock() + cb(reqRes.Response) + return + } + + defer reqRes.mtx.Unlock() + reqRes.cb = cb +} + +func (reqRes *ReqRes) GetCallback() func(*types.Response) { + reqRes.mtx.Lock() + defer reqRes.mtx.Unlock() + return reqRes.cb +} + +// NOTE: it should be safe to read reqRes.cb without locks after this. +func (reqRes *ReqRes) SetDone() { + reqRes.mtx.Lock() + reqRes.done = true + reqRes.mtx.Unlock() +} + func waitGroup1() (wg *sync.WaitGroup) { wg = &sync.WaitGroup{} wg.Add(1) From b9499ad03e84c4b219b55abefe90e4a20c40f1e3 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 8 Feb 2016 13:47:47 -0800 Subject: [PATCH 075/545] Implemented dummy query --- cmd/tmsp-cli/tmsp-cli.go | 9 ++++++--- example/golang/dummy.go | 13 +++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index e6ea2124..fba8f130 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -222,7 +222,7 @@ func cmdAppendTx(c *cli.Context) { func cmdCheckTx(c *cli.Context) { args := c.Args() if len(args) != 1 { - fmt.Println("append_tx takes 1 argument") + fmt.Println("check_tx takes 1 argument") return } txString := args[0] @@ -258,7 +258,7 @@ func cmdGetHash(c *cli.Context) { func cmdQuery(c *cli.Context) { args := c.Args() if len(args) != 1 { - fmt.Println("append_tx takes 1 argument") + fmt.Println("query takes 1 argument") return } queryString := args[0] @@ -287,12 +287,15 @@ func printResponse(res *types.Response, s string) { if res.Error != "" { fmt.Printf("error: %s\t", res.Error) } - if res.Code > 0 { + if res.Code != types.CodeType_OK { fmt.Printf("code: %s", res.Code.String()) } if s != "" { fmt.Printf("data: {%s}", s) } + if res.Log != "" { + fmt.Printf("log: %s", res.Log) + } fmt.Printf("\n") } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 71d5d3e4..2f1e7b90 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -1,6 +1,8 @@ package example import ( + "strings" + . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/tmsp/types" @@ -27,7 +29,12 @@ func (app *DummyApplication) SetOption(key string, value string) (log string) { } func (app *DummyApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { - app.state.Set(tx, tx) + parts := strings.Split(string(tx), "=") + if len(parts) == 2 { + app.state.Set([]byte(parts[0]), []byte(parts[1])) + } else { + app.state.Set(tx, tx) + } return types.CodeType_OK, nil, "" } @@ -41,5 +48,7 @@ func (app *DummyApplication) GetHash() (hash []byte, log string) { } func (app *DummyApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { - return types.CodeType_OK, nil, "Query not supported" + index, value, exists := app.state.Get(query) + resStr := Fmt("Index=%v value=%v exists=%v", index, string(value), exists) + return types.CodeType_OK, []byte(resStr), "" } From 851b961daf47cd4acf8f09f21ecc04750514560a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 14 Feb 2016 12:51:49 -0800 Subject: [PATCH 076/545] Update README --- README.md | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 284d2af9..03e36f79 100644 --- a/README.md +++ b/README.md @@ -8,32 +8,44 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog ## Message types +TMSP requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/tmsp/blob/master/types/types.proto). + #### AppendTx * __Arguments__: - * `TxBytes ([]byte)` + * `Data ([]byte)`: The request transaction bytes * __Returns__: - * `Code (int8)` - * `Result ([]byte)` - * `Log (string)` + * `Code (uint)`: Response code + * `Data ([]byte)`: Result bytes, if any + * `Log (string)`: Debug or error message * __Usage__:
- Append and run a transaction. The transaction may or may not be final. + Append and run a transaction. If the transaction is valid, returns CodeType.OK #### CheckTx * __Arguments__: - * `TxBytes ([]byte)` + * `Data ([]byte)`: The request transaction bytes * __Returns__: - * `Code (int8)` - * `Result ([]byte)` - * `Log (string)` + * `Code (uint)`: Response code + * `Data ([]byte)`: Result bytes, if any + * `Log (string)`: Debug or error message * __Usage__:
Validate a transaction. This message should not mutate the state. + Transactions are first run through CheckTx before broadcast to peers in the mempool layer. + You can make CheckTx semi-stateful and clear the state upon `Commit`, to ensure that all txs in the blockchain are valid. -#### GetHash +#### Commit * __Returns__: - * `Hash ([]byte)` - * `Log (string)` + * `Data ([]byte)`: The Merkle root hash + * `Log (string)`: Debug or error message * __Usage__:
- Return a Merkle root hash of the application state + Return a Merkle root hash of the application state. + +#### Query + * __Arguments__: + * `Data ([]byte)`: The query request bytes + * __Returns__: + * `Code (uint)`: Response code + * `Data ([]byte)`: The query response bytes + * `Log (string)`: Debug or error message #### Flush * __Usage__:
@@ -41,22 +53,27 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog #### Info * __Returns__: - * `Data ([]string)` + * `Data ([]byte)`: The info bytes * __Usage__:
- Return an array of strings about the application state. Application specific. + Return information about the application state. Application specific. #### SetOption * __Arguments__: - * `Key (string)` - * `Value (string)` + * `Key (string)`: Key to set + * `Value (string)`: Value to set for key * __Returns__: - * `Log (string)` + * `Log (string)`: Debug or error message * __Usage__:
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. ## Changelog +### Feb 14th, 2016 + +* s/GetHash/Commit/g +* Document Protobuf request/response fields + ### Jan 23th, 2016 * Added CheckTx/Query TMSP message types From 88fcacac7aad3b2dc5fb6626a0bbd2e801ff1809 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 14 Feb 2016 13:11:06 -0800 Subject: [PATCH 077/545] s/GetHash/Commit/g --- client/client.go | 8 +++--- cmd/tmsp-cli/tmsp-cli.go | 6 ++-- example/golang/counter.go | 2 +- example/golang/dummy.go | 2 +- server/server.go | 6 ++-- types/application.go | 2 +- types/messages.go | 8 +++--- types/types.pb.go | 60 +++++++++++++++++++-------------------- types/types.proto | 2 +- 9 files changed, 48 insertions(+), 48 deletions(-) diff --git a/client/client.go b/client/client.go index adb2c463..5c123026 100644 --- a/client/client.go +++ b/client/client.go @@ -207,8 +207,8 @@ func (cli *TMSPClient) CheckTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.RequestCheckTx(tx)) } -func (cli *TMSPClient) GetHashAsync() *ReqRes { - return cli.queueRequest(types.RequestGetHash()) +func (cli *TMSPClient) CommitAsync() *ReqRes { + return cli.queueRequest(types.RequestCommit()) } func (cli *TMSPClient) QueryAsync(query []byte) *ReqRes { @@ -251,8 +251,8 @@ func (cli *TMSPClient) CheckTxSync(tx []byte) (code types.CodeType, result []byt return res.Code, res.Data, res.Log, nil } -func (cli *TMSPClient) GetHashSync() (hash []byte, log string, err error) { - reqres := cli.queueRequest(types.RequestGetHash()) +func (cli *TMSPClient) CommitSync() (hash []byte, log string, err error) { + reqres := cli.queueRequest(types.RequestCommit()) cli.FlushSync() if cli.err != nil { return nil, "", cli.err diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index fba8f130..f111b3e9 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -83,7 +83,7 @@ func main() { Name: "get_hash", Usage: "Get application Merkle root hash", Action: func(c *cli.Context) { - cmdGetHash(c) + cmdCommit(c) }, }, { @@ -245,8 +245,8 @@ func cmdCheckTx(c *cli.Context) { } // Get application Merkle root hash -func cmdGetHash(c *cli.Context) { - res, err := makeRequest(conn, types.RequestGetHash()) +func cmdCommit(c *cli.Context) { + res, err := makeRequest(conn, types.RequestCommit()) if err != nil { fmt.Println(err.Error()) return diff --git a/example/golang/counter.go b/example/golang/counter.go index 1d1081df..b4da31bf 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -54,7 +54,7 @@ func (app *CounterApplication) CheckTx(tx []byte) (code types.CodeType, result [ return types.CodeType_OK, nil, "" } -func (app *CounterApplication) GetHash() (hash []byte, log string) { +func (app *CounterApplication) Commit() (hash []byte, log string) { app.hashCount += 1 if app.txCount == 0 { diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 2f1e7b90..818cd363 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -42,7 +42,7 @@ func (app *DummyApplication) CheckTx(tx []byte) (code types.CodeType, result []b return types.CodeType_OK, nil, "" } -func (app *DummyApplication) GetHash() (hash []byte, log string) { +func (app *DummyApplication) Commit() (hash []byte, log string) { hash = app.state.Hash() return hash, "" } diff --git a/server/server.go b/server/server.go index d5d1a124..933aa4c6 100644 --- a/server/server.go +++ b/server/server.go @@ -112,9 +112,9 @@ func handleRequest(app types.Application, req *types.Request, responses chan<- * case types.MessageType_CheckTx: code, result, logStr := app.CheckTx(req.Data) responses <- types.ResponseCheckTx(code, result, logStr) - case types.MessageType_GetHash: - hash, logStr := app.GetHash() - responses <- types.ResponseGetHash(hash, logStr) + case types.MessageType_Commit: + hash, logStr := app.Commit() + responses <- types.ResponseCommit(hash, logStr) case types.MessageType_Query: code, result, logStr := app.Query(req.Data) responses <- types.ResponseQuery(code, result, logStr) diff --git a/types/application.go b/types/application.go index 8f27282f..d0379df0 100644 --- a/types/application.go +++ b/types/application.go @@ -15,7 +15,7 @@ type Application interface { CheckTx(tx []byte) (code CodeType, result []byte, log string) // Return the application Merkle root hash - GetHash() (hash []byte, log string) + Commit() (hash []byte, log string) // Query for state Query(query []byte) (code CodeType, result []byte, log string) diff --git a/types/messages.go b/types/messages.go index 736745bf..49c02bea 100644 --- a/types/messages.go +++ b/types/messages.go @@ -48,9 +48,9 @@ func RequestCheckTx(txBytes []byte) *Request { } } -func RequestGetHash() *Request { +func RequestCommit() *Request { return &Request{ - Type: MessageType_GetHash, + Type: MessageType_Commit, } } @@ -115,9 +115,9 @@ func ResponseCheckTx(code CodeType, result []byte, log string) *Response { } } -func ResponseGetHash(hash []byte, log string) *Response { +func ResponseCommit(hash []byte, log string) *Response { return &Response{ - Type: MessageType_GetHash, + Type: MessageType_Commit, Data: hash, Log: log, } diff --git a/types/types.pb.go b/types/types.pb.go index 8e86ed28..ec1bb40d 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -34,7 +34,7 @@ const ( MessageType_Exception MessageType = 5 MessageType_AppendTx MessageType = 17 MessageType_CheckTx MessageType = 18 - MessageType_GetHash MessageType = 19 + MessageType_Commit MessageType = 19 MessageType_Query MessageType = 20 ) @@ -47,7 +47,7 @@ var MessageType_name = map[int32]string{ 5: "Exception", 17: "AppendTx", 18: "CheckTx", - 19: "GetHash", + 19: "Commit", 20: "Query", } var MessageType_value = map[string]int32{ @@ -59,7 +59,7 @@ var MessageType_value = map[string]int32{ "Exception": 5, "AppendTx": 17, "CheckTx": 18, - "GetHash": 19, + "Commit": 19, "Query": 20, } @@ -143,31 +143,31 @@ func init() { } var fileDescriptor0 = []byte{ - // 405 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x92, 0xdf, 0x6e, 0xd3, 0x30, - 0x14, 0xc6, 0x49, 0x9b, 0xf4, 0xcf, 0x69, 0xd7, 0xb9, 0x87, 0x22, 0xe5, 0x12, 0x0d, 0x09, 0xa1, - 0x5d, 0x0c, 0x69, 0x3c, 0xc1, 0x98, 0x3a, 0xa8, 0x10, 0x9b, 0x08, 0xdb, 0x03, 0x18, 0xe7, 0xb4, - 0x8d, 0x1a, 0x8e, 0x43, 0x6c, 0xc3, 0xca, 0x43, 0x70, 0xc3, 0x73, 0xf0, 0x8e, 0xd8, 0x4e, 0x27, - 0x8d, 0x6b, 0x6e, 0xa2, 0xf3, 0x7d, 0xf6, 0xf9, 0xce, 0xcf, 0x8e, 0x61, 0x6e, 0xf7, 0x0d, 0x99, - 0xd7, 0xf1, 0x7b, 0xd6, 0xb4, 0xda, 0x6a, 0xcc, 0xa2, 0x38, 0xf9, 0x0a, 0xc3, 0x82, 0xbe, 0x39, - 0x32, 0x16, 0x5f, 0x42, 0x1a, 0xbc, 0x3c, 0x79, 0x9e, 0xbc, 0x9a, 0x9d, 0xe3, 0x59, 0xb7, 0xfb, - 0x23, 0x19, 0x23, 0x37, 0x74, 0xeb, 0x45, 0x11, 0xd7, 0x11, 0x21, 0x2d, 0xa5, 0x95, 0x79, 0xcf, - 0xef, 0x9b, 0x16, 0xb1, 0x46, 0x01, 0xfd, 0x1d, 0xed, 0xf3, 0xbe, 0xb7, 0xc6, 0x45, 0x28, 0x71, - 0x01, 0xd9, 0x77, 0x59, 0x3b, 0xca, 0xd3, 0xe8, 0x75, 0xe2, 0xe4, 0x77, 0x02, 0xa3, 0x82, 0x4c, - 0xa3, 0xd9, 0xd0, 0x7f, 0x0d, 0x7c, 0x01, 0xa9, 0xd2, 0x25, 0xc5, 0x89, 0xb3, 0xf3, 0xe3, 0x43, - 0xef, 0xa5, 0xb7, 0xba, 0xc6, 0xb0, 0x18, 0x18, 0xa8, 0x6d, 0x75, 0xfb, 0xc0, 0x10, 0x45, 0x60, - 0xad, 0xf5, 0x26, 0xcf, 0x3a, 0x56, 0x5f, 0x9e, 0xfe, 0x4a, 0x60, 0xf2, 0x68, 0x2c, 0x1e, 0xc3, - 0xe4, 0xda, 0xd5, 0xf5, 0xc1, 0x12, 0x4f, 0x70, 0x04, 0xe9, 0x52, 0x6d, 0xb5, 0x48, 0x70, 0x0c, - 0xd9, 0x55, 0xed, 0xcc, 0x56, 0xf4, 0x82, 0xb9, 0xe2, 0xb5, 0x16, 0x7d, 0x3c, 0x82, 0xf1, 0x67, - 0xb2, 0x37, 0x8d, 0xad, 0x34, 0x8b, 0x34, 0xc8, 0xe5, 0xbd, 0xa2, 0x4e, 0x66, 0x38, 0x85, 0xd1, - 0x45, 0xd3, 0x10, 0x97, 0xb7, 0xf7, 0x62, 0x8e, 0x13, 0x18, 0x5e, 0x6e, 0x49, 0xed, 0xbc, 0xc0, - 0x20, 0xde, 0x91, 0x7d, 0x2f, 0x7d, 0xde, 0xd3, 0x10, 0xfd, 0xc9, 0x51, 0xbb, 0x17, 0x8b, 0xd3, - 0x3f, 0xfe, 0x9a, 0x1e, 0xce, 0x82, 0x03, 0xe8, 0xdd, 0x7c, 0xf0, 0x10, 0x73, 0x38, 0x5a, 0xb1, - 0xa5, 0x96, 0x65, 0xbd, 0x0c, 0x07, 0xf1, 0x34, 0x02, 0xa6, 0x77, 0x2c, 0x9d, 0xdd, 0xea, 0xb6, - 0xfa, 0x49, 0xa5, 0x87, 0x5a, 0x80, 0x58, 0xb1, 0x71, 0xeb, 0x75, 0xa5, 0x2a, 0x62, 0x7b, 0x45, - 0x64, 0x3c, 0x20, 0xc2, 0xec, 0x8e, 0x77, 0xac, 0x7f, 0xf0, 0xe1, 0x67, 0x7b, 0x4a, 0x1f, 0xb7, - 0x64, 0x7f, 0x4d, 0x15, 0x6f, 0xba, 0xb8, 0x48, 0xfa, 0x56, 0x96, 0xd7, 0x9a, 0x15, 0x89, 0xc1, - 0xa3, 0xa6, 0x0b, 0xa5, 0xb4, 0x63, 0x2b, 0x86, 0xf8, 0x0c, 0xe6, 0xff, 0xc4, 0x3b, 0x2e, 0x8d, - 0x18, 0x7d, 0x19, 0xc4, 0x37, 0xf5, 0xe6, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x90, 0x25, - 0x05, 0x68, 0x02, 0x00, 0x00, + // 406 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x92, 0x5f, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0x71, 0x62, 0xe7, 0xcf, 0x24, 0x4d, 0x37, 0x43, 0x90, 0xfc, 0x88, 0x8a, 0x84, 0x50, + 0x1f, 0x8a, 0x54, 0x4e, 0x50, 0xa2, 0x54, 0x8a, 0x10, 0xad, 0x30, 0xed, 0x01, 0xcc, 0x7a, 0x12, + 0x5b, 0x71, 0x66, 0x8d, 0x77, 0x17, 0x1a, 0xee, 0xc0, 0x13, 0xe7, 0xe0, 0x8e, 0xec, 0xae, 0x53, + 0xa9, 0x3c, 0xf7, 0xc5, 0x9a, 0xef, 0xdb, 0x9d, 0x99, 0xdf, 0x8c, 0x17, 0xe6, 0xe6, 0xd0, 0x90, + 0x7e, 0x1f, 0xbe, 0x17, 0x4d, 0xab, 0x8c, 0xc2, 0x24, 0x88, 0xb3, 0x3d, 0x0c, 0x33, 0xfa, 0x6e, + 0x49, 0x1b, 0x7c, 0x0b, 0xb1, 0xf7, 0xd2, 0xe8, 0x75, 0xf4, 0x6e, 0x76, 0x89, 0x17, 0xdd, 0xed, + 0xcf, 0xa4, 0x75, 0xbe, 0xa5, 0x3b, 0x27, 0xb2, 0x70, 0x8e, 0x08, 0x71, 0x91, 0x9b, 0x3c, 0xed, + 0xb9, 0x7b, 0xd3, 0x2c, 0xc4, 0x28, 0xa0, 0xbf, 0xa3, 0x43, 0xda, 0x77, 0xd6, 0x38, 0xf3, 0x21, + 0x2e, 0x20, 0xf9, 0x91, 0xd7, 0x96, 0xd2, 0x38, 0x78, 0x9d, 0x38, 0xfb, 0x13, 0xc1, 0x28, 0x23, + 0xdd, 0x28, 0xd6, 0xf4, 0xac, 0x86, 0x6f, 0x20, 0x96, 0xaa, 0xa0, 0xd0, 0x71, 0x76, 0x79, 0x7a, + 0xcc, 0x5d, 0x3a, 0xab, 0x4b, 0xf4, 0x87, 0x9e, 0x81, 0xda, 0x56, 0xb5, 0x8f, 0x0c, 0x41, 0x78, + 0xd6, 0x5a, 0x6d, 0xd3, 0xa4, 0x63, 0x75, 0xe1, 0xf9, 0xef, 0x08, 0x26, 0x4f, 0xda, 0xe2, 0x29, + 0x4c, 0x6e, 0x6c, 0x5d, 0x1f, 0x2d, 0xf1, 0x02, 0x47, 0x10, 0xaf, 0x64, 0xa9, 0x44, 0x84, 0x63, + 0x48, 0xae, 0x6b, 0xab, 0x4b, 0xd1, 0xf3, 0xe6, 0x9a, 0x37, 0x4a, 0xf4, 0xf1, 0x04, 0xc6, 0x5f, + 0xc9, 0xdc, 0x36, 0xa6, 0x52, 0x2c, 0x62, 0x2f, 0x57, 0x0f, 0x92, 0x3a, 0x99, 0xe0, 0x14, 0x46, + 0x57, 0x4d, 0x43, 0x5c, 0xdc, 0x3d, 0x88, 0x39, 0x4e, 0x60, 0xb8, 0x2c, 0x49, 0xee, 0x9c, 0x70, + 0x83, 0xc1, 0x60, 0xa9, 0xf6, 0xfb, 0xca, 0x88, 0x97, 0xbe, 0xf2, 0x17, 0x4b, 0xed, 0x41, 0x2c, + 0xce, 0xff, 0xba, 0x2d, 0x3d, 0x8e, 0x82, 0x03, 0xe8, 0xdd, 0x7e, 0x72, 0x0c, 0x73, 0x38, 0x59, + 0xb3, 0xa1, 0x96, 0xf3, 0x7a, 0xe5, 0xe7, 0x70, 0x30, 0x02, 0xa6, 0xf7, 0x9c, 0x5b, 0x53, 0xaa, + 0xb6, 0xfa, 0x45, 0x85, 0x63, 0x5a, 0x80, 0x58, 0xb3, 0xb6, 0x9b, 0x4d, 0x25, 0x2b, 0x62, 0x73, + 0x4d, 0xa4, 0x1d, 0x1f, 0xc2, 0xec, 0x9e, 0x77, 0xac, 0x7e, 0xf2, 0xf1, 0x5f, 0x3b, 0x48, 0x57, + 0x6e, 0xc5, 0x6e, 0x4b, 0x15, 0x6f, 0xbb, 0x72, 0x01, 0xf4, 0x63, 0x5e, 0xdc, 0x28, 0x96, 0x24, + 0x06, 0x4f, 0x92, 0xae, 0xa4, 0x54, 0x96, 0x8d, 0x18, 0xe2, 0x2b, 0x98, 0xff, 0x57, 0xde, 0x72, + 0xa1, 0xc5, 0xe8, 0xdb, 0x20, 0x3c, 0xa9, 0x0f, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x41, 0x3b, + 0x4f, 0x97, 0x67, 0x02, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index f14276d1..f9da8e7d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -16,7 +16,7 @@ enum MessageType { Exception = 0x05; AppendTx = 0x11; CheckTx = 0x12; - GetHash = 0x13; + Commit = 0x13; Query = 0x14; } From 90e38f08f4d0edd307b23d463ace8299d01c8fad Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 14 Feb 2016 14:59:53 -0800 Subject: [PATCH 078/545] Added counter test written in Golang --- client/client.go | 15 ++- cmd/counter/main.go | 4 +- cmd/dummy/main.go | 4 +- example/{golang => counter}/counter.go | 2 +- example/{golang => dummy}/dummy.go | 2 +- example/{golang => dummy}/dummy_test.go | 2 +- example/python/app.py | 2 +- example/python/tmsp/msg.py | 4 +- example/python3/app.py | 2 +- example/python3/tmsp/msg.py | 4 +- tests/test.sh | 15 +-- tests/test_counter.go | 126 ++++++++++++++++++++++++ tests/test_counter.sh | 78 --------------- tests/test_dummy.sh | 61 ------------ 14 files changed, 154 insertions(+), 167 deletions(-) rename example/{golang => counter}/counter.go (99%) rename example/{golang => dummy}/dummy.go (98%) rename example/{golang => dummy}/dummy_test.go (99%) create mode 100644 tests/test_counter.go delete mode 100755 tests/test_counter.sh delete mode 100755 tests/test_dummy.sh diff --git a/client/client.go b/client/client.go index 5c123026..80fbc396 100644 --- a/client/client.go +++ b/client/client.go @@ -217,6 +217,11 @@ func (cli *TMSPClient) QueryAsync(query []byte) *ReqRes { //---------------------------------------- +func (cli *TMSPClient) FlushSync() error { + cli.queueRequest(types.RequestFlush()).Wait() + return cli.err +} + func (cli *TMSPClient) InfoSync() (info string, err error) { reqres := cli.queueRequest(types.RequestInfo()) cli.FlushSync() @@ -226,9 +231,13 @@ func (cli *TMSPClient) InfoSync() (info string, err error) { return string(reqres.Response.Data), nil } -func (cli *TMSPClient) FlushSync() error { - cli.queueRequest(types.RequestFlush()).Wait() - return cli.err +func (cli *TMSPClient) SetOptionSync(key string, value string) (log string, err error) { + reqres := cli.queueRequest(types.RequestSetOption(key, value)) + cli.FlushSync() + if cli.err != nil { + return "", cli.err + } + return reqres.Response.Log, nil } func (cli *TMSPClient) AppendTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 503908b4..37e73568 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -4,7 +4,7 @@ import ( "flag" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/example/golang" + "github.com/tendermint/tmsp/example/counter" "github.com/tendermint/tmsp/server" ) @@ -13,7 +13,7 @@ func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") flag.Parse() - app := example.NewCounterApplication(*serialPtr) + app := counter.NewCounterApplication(*serialPtr) // Start the listener _, err := server.StartListener(*addrPtr, app) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index d1766e65..b4e542c6 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -4,7 +4,7 @@ import ( "flag" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/example/golang" + "github.com/tendermint/tmsp/example/dummy" "github.com/tendermint/tmsp/server" ) @@ -14,7 +14,7 @@ func main() { flag.Parse() // Start the listener - _, err := server.StartListener(*addrPtr, example.NewDummyApplication()) + _, err := server.StartListener(*addrPtr, dummy.NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/example/golang/counter.go b/example/counter/counter.go similarity index 99% rename from example/golang/counter.go rename to example/counter/counter.go index b4da31bf..f97786f8 100644 --- a/example/golang/counter.go +++ b/example/counter/counter.go @@ -1,4 +1,4 @@ -package example +package counter import ( "encoding/binary" diff --git a/example/golang/dummy.go b/example/dummy/dummy.go similarity index 98% rename from example/golang/dummy.go rename to example/dummy/dummy.go index 818cd363..dc4441d9 100644 --- a/example/golang/dummy.go +++ b/example/dummy/dummy.go @@ -1,4 +1,4 @@ -package example +package dummy import ( "strings" diff --git a/example/golang/dummy_test.go b/example/dummy/dummy_test.go similarity index 99% rename from example/golang/dummy_test.go rename to example/dummy/dummy_test.go index 3e27e5e8..266cf635 100644 --- a/example/golang/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -1,4 +1,4 @@ -package example +package dummy import ( "testing" diff --git a/example/python/app.py b/example/python/app.py index 8eda9020..b8cfcca8 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -47,7 +47,7 @@ class CounterApplication(): return 6 return 0 - def get_hash(self): + def commit(self): self.hashCount += 1 if self.txCount == 0: return "", 0 diff --git a/example/python/tmsp/msg.py b/example/python/tmsp/msg.py index 17e71471..a03c0a07 100644 --- a/example/python/tmsp/msg.py +++ b/example/python/tmsp/msg.py @@ -8,7 +8,7 @@ message_types = { 0x04: "set_option", 0x21: "append_tx", 0x22: "check_tx", - 0x23: "get_hash", + 0x23: "commit", 0x24: "add_listener", 0x25: "rm_listener", } @@ -38,7 +38,7 @@ class RequestDecoder(): def check_tx(self): return decode_string(self.reader) - def get_hash(self): + def commit(self): return def add_listener(self): diff --git a/example/python3/app.py b/example/python3/app.py index 01f3de0b..c3d11490 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -47,7 +47,7 @@ class CounterApplication(): return 6 return 0 - def get_hash(self): + def commit(self): self.hashCount += 1 if self.txCount == 0: return "", 0 diff --git a/example/python3/tmsp/msg.py b/example/python3/tmsp/msg.py index 2f35d8be..ae30f88d 100644 --- a/example/python3/tmsp/msg.py +++ b/example/python3/tmsp/msg.py @@ -8,7 +8,7 @@ message_types = { 0x04: "set_option", 0x21: "append_tx", 0x22: "check_tx", - 0x23: "get_hash", + 0x23: "commit", 0x24: "add_listener", 0x25: "rm_listener", } @@ -38,7 +38,7 @@ class RequestDecoder(): def check_tx(self): return decode_string(self.reader) - def get_hash(self): + def commit(self): return def add_listener(self): diff --git a/tests/test.sh b/tests/test.sh index c99f92dc..d375eafa 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -2,17 +2,8 @@ ROOT=$GOPATH/src/github.com/tendermint/tmsp cd $ROOT -# test golang dummy -bash tests/test_dummy.sh - # test golang counter -bash tests/test_counter.sh - -# test js counter -cd example/js -COUNTER_APP="node app.js" bash $ROOT/tests/test_counter.sh - -# test python counter -cd ../python -COUNTER_APP="python app.py" bash $ROOT/tests/test_counter.sh +COUNTER_APP="counter" go run $ROOT/tests/test_counter.go +# test nodejs counter +COUNTER_APP="node ../js-tmsp/example/app.js" go run $ROOT/tests/test_counter.go diff --git a/tests/test_counter.go b/tests/test_counter.go new file mode 100644 index 00000000..ff04ec32 --- /dev/null +++ b/tests/test_counter.go @@ -0,0 +1,126 @@ +package main + +import ( + "bytes" + "fmt" + "os" + "time" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-process" + "github.com/tendermint/tmsp/client" + "github.com/tendermint/tmsp/types" +) + +func main() { + + // Run tests + testBasic() + + fmt.Println("Success!") +} + +func testBasic() { + fmt.Println("Running basic tests") + appProc := startApp() + defer appProc.StopProcess(true) + client := startClient() + defer client.Stop() + + setOption(client, "serial", "on") + commit(client, nil) + appendTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + commit(client, nil) + appendTx(client, []byte{0x00}, types.CodeType_OK, nil) + commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) + appendTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) + appendTx(client, []byte{0x01}, types.CodeType_OK, nil) + appendTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) + appendTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) + appendTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) + appendTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) + commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) +} + +//---------------------------------------- + +func startApp() *process.Process { + counterApp := os.Getenv("COUNTER_APP") + if counterApp == "" { + panic("No COUNTER_APP specified") + } + + // Start the app + //outBuf := NewBufferCloser(nil) + proc, err := process.StartProcess("counter_app", + "bash", + []string{"-c", counterApp}, + nil, + os.Stdout, + ) + if err != nil { + panic("running counter_app: " + err.Error()) + } + + // TODO a better way to handle this? + time.Sleep(time.Second) + + return proc +} + +func startClient() *tmspcli.TMSPClient { + // Start client + client, err := tmspcli.NewTMSPClient("tcp://127.0.0.1:46658") + if err != nil { + panic("connecting to counter_app: " + err.Error()) + } + return client +} + +func setOption(client *tmspcli.TMSPClient, key, value string) { + log, err := client.SetOptionSync(key, value) + if err != nil { + panic(Fmt("setting %v=%v: %v\nlog: %v", key, value, err, log)) + } +} + +func commit(client *tmspcli.TMSPClient, hashExp []byte) { + hash, log, err := client.CommitSync() + if err != nil { + panic(Fmt("committing %v\nlog: %v", err, log)) + } + if !bytes.Equal(hash, hashExp) { + panic(Fmt("Commit hash was unexpected. Got %X expected %X", + hash, hashExp)) + } +} + +func appendTx(client *tmspcli.TMSPClient, txBytes []byte, codeExp types.CodeType, dataExp []byte) { + code, data, log, err := client.AppendTxSync(txBytes) + if err != nil { + panic(Fmt("appending tx %X: %v\nlog: %v", txBytes, err, log)) + } + if code != codeExp { + panic(Fmt("AppendTx response code was unexpected. Got %v expected %v. Log: %v", + code, codeExp, log)) + } + if !bytes.Equal(data, dataExp) { + panic(Fmt("AppendTx response data was unexpected. Got %X expected %X", + data, dataExp)) + } +} + +func checkTx(client *tmspcli.TMSPClient, txBytes []byte, codeExp types.CodeType, dataExp []byte) { + code, data, log, err := client.CheckTxSync(txBytes) + if err != nil { + panic(Fmt("checking tx %X: %v\nlog: %v", txBytes, err, log)) + } + if code != codeExp { + panic(Fmt("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", + data, dataExp)) + } +} diff --git a/tests/test_counter.sh b/tests/test_counter.sh deleted file mode 100755 index 53edab3b..00000000 --- a/tests/test_counter.sh +++ /dev/null @@ -1,78 +0,0 @@ -#! /bin/bash -function finish { - echo "Cleaning up..." - ps -p $PID > /dev/null - if [[ "$?" == "0" ]]; then - kill -9 $PID - fi -} -trap finish EXIT - -# so we can test other languages -if [[ "$COUNTER_APP" == "" ]]; then - COUNTER_APP="counter" -fi - -echo "Testing counter app for: $COUNTER_APP" - -# run the counter app -$COUNTER_APP &> /dev/null & -PID=`echo $!` - -if [[ "$?" != 0 ]]; then - echo "Error running tmsp app" - echo $OUTPUT - exit 1 -fi - -sleep 1 -OUTPUT=`(tmsp-cli batch) < /dev/null - if [[ "$?" == "0" ]]; then - kill -9 $PID - fi -} -trap finish EXIT - -# Make sure the tmsp cli can connect to the dummy -echo "Dummy test ..." -dummy &> /dev/null & -PID=`echo $!` -sleep 1 -RESULT_HASH=`tmsp-cli get_hash` -if [[ "$RESULT_HASH" != "" ]]; then - echo "Expected nothing but got: $RESULT_HASH" - exit 1 -fi -echo "... Pass!" -echo "" - -# Add a tx, get hash, get hash -# hashes should be non-empty and identical -echo "Dummy batch test ..." -OUTPUT=`(tmsp-cli batch) < Date: Sun, 21 Feb 2016 23:44:33 -0800 Subject: [PATCH 079/545] s/StartListener/NewServer/g --- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- example/dummy/dummy_test.go | 2 +- server/server.go | 144 ++++++++++++++++++++++-------------- 4 files changed, 90 insertions(+), 60 deletions(-) diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 37e73568..fc003fb8 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -16,7 +16,7 @@ func main() { app := counter.NewCounterApplication(*serialPtr) // Start the listener - _, err := server.StartListener(*addrPtr, app) + _, err := server.NewServer(*addrPtr, app) if err != nil { Exit(err.Error()) } diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index b4e542c6..25486e44 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -14,7 +14,7 @@ func main() { flag.Parse() // Start the listener - _, err := server.StartListener(*addrPtr, dummy.NewDummyApplication()) + _, err := server.NewServer(*addrPtr, dummy.NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 266cf635..073815be 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -14,7 +14,7 @@ func TestStream(t *testing.T) { numAppendTxs := 200000 // Start the listener - _, err := server.StartListener("tcp://127.0.0.1:46658", NewDummyApplication()) + _, err := server.NewServer("tcp://127.0.0.1:46658", NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/server/server.go b/server/server.go index 933aa4c6..e3ac8a37 100644 --- a/server/server.go +++ b/server/server.go @@ -14,65 +14,95 @@ import ( // var maxNumberConnections = 2 -func StartListener(protoAddr string, app types.Application) (net.Listener, error) { - var mtx sync.Mutex // global mutex +type Server struct { + QuitService + + proto string + addr string + listener net.Listener + + appMtx sync.Mutex + app types.Application +} + +func NewServer(protoAddr string, app types.Application) (*Server, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] - ln, err := net.Listen(proto, addr) - if err != nil { - return nil, err + s := &Server{ + proto: proto, + addr: addr, + listener: nil, + app: app, } + s.QuitService = *NewQuitService(nil, "TMSPServer", s) + s.Start() // Just start it + return s, nil +} - // A goroutine to accept a connection. - go func() { - // semaphore := make(chan struct{}, maxNumberConnections) +func (s *Server) OnStart() error { + s.QuitService.OnStart() + ln, err := net.Listen(s.proto, s.addr) + if err != nil { + return err + } + s.listener = ln + go s.acceptConnectionsRoutine() + return nil +} - for { - // semaphore <- struct{}{} +func (s *Server) OnStop() { + s.QuitService.OnStop() + s.listener.Close() +} - // Accept a connection - fmt.Println("Waiting for new connection...") - conn, err := ln.Accept() - if err != nil { - Exit("Failed to accept connection") - } else { - fmt.Println("Accepted a new connection") +func (s *Server) acceptConnectionsRoutine() { + // semaphore := make(chan struct{}, maxNumberConnections) + + for { + // semaphore <- struct{}{} + + // Accept a connection + fmt.Println("Waiting for new connection...") + conn, err := s.listener.Accept() + if err != nil { + if !s.IsRunning() { + return // Ignore error from listener closing. } - - closeConn := make(chan error, 2) // Push to signal connection closed - responses := make(chan *types.Response, 1000) // A channel to buffer responses - - // Read requests from conn and deal with them - go handleRequests(&mtx, app, closeConn, conn, responses) - // Pull responses from 'responses' and write them to conn. - go handleResponses(closeConn, responses, conn) - - go func() { - // Wait until signal to close connection - errClose := <-closeConn - if errClose != nil { - fmt.Printf("Connection error: %v\n", errClose) - } else { - fmt.Println("Connection was closed.") - } - - // Close the connection - err := conn.Close() - if err != nil { - fmt.Printf("Error in closing connection: %v\n", err) - } - - // <-semaphore - }() + Exit("Failed to accept connection: " + err.Error()) + } else { + fmt.Println("Accepted a new connection") } - }() + closeConn := make(chan error, 2) // Push to signal connection closed + responses := make(chan *types.Response, 1000) // A channel to buffer responses - return ln, nil + // Read requests from conn and deal with them + go s.handleRequests(closeConn, conn, responses) + // Pull responses from 'responses' and write them to conn. + go s.handleResponses(closeConn, responses, conn) + + go func() { + // Wait until signal to close connection + errClose := <-closeConn + if errClose != nil { + fmt.Printf("Connection error: %v\n", errClose) + } else { + fmt.Println("Connection was closed.") + } + + // Close the connection + err := conn.Close() + if err != nil { + fmt.Printf("Error in closing connection: %v\n", err) + } + + // <-semaphore + }() + } } // Read requests from conn and deal with them -func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error, conn net.Conn, responses chan<- *types.Response) { +func (s *Server) handleRequests(closeConn chan error, conn net.Conn, responses chan<- *types.Response) { var count int var bufReader = bufio.NewReader(conn) for { @@ -87,36 +117,36 @@ func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error } return } - mtx.Lock() + s.appMtx.Lock() count++ - handleRequest(app, req, responses) - mtx.Unlock() + s.handleRequest(req, responses) + s.appMtx.Unlock() } } -func handleRequest(app types.Application, req *types.Request, responses chan<- *types.Response) { +func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Response) { switch req.Type { case types.MessageType_Echo: responses <- types.ResponseEcho(string(req.Data)) case types.MessageType_Flush: responses <- types.ResponseFlush() case types.MessageType_Info: - data := app.Info() + data := s.app.Info() responses <- types.ResponseInfo(data) case types.MessageType_SetOption: - logStr := app.SetOption(req.Key, req.Value) + logStr := s.app.SetOption(req.Key, req.Value) responses <- types.ResponseSetOption(logStr) case types.MessageType_AppendTx: - code, result, logStr := app.AppendTx(req.Data) + code, result, logStr := s.app.AppendTx(req.Data) responses <- types.ResponseAppendTx(code, result, logStr) case types.MessageType_CheckTx: - code, result, logStr := app.CheckTx(req.Data) + code, result, logStr := s.app.CheckTx(req.Data) responses <- types.ResponseCheckTx(code, result, logStr) case types.MessageType_Commit: - hash, logStr := app.Commit() + hash, logStr := s.app.Commit() responses <- types.ResponseCommit(hash, logStr) case types.MessageType_Query: - code, result, logStr := app.Query(req.Data) + code, result, logStr := s.app.Query(req.Data) responses <- types.ResponseQuery(code, result, logStr) default: responses <- types.ResponseException("Unknown request") @@ -124,7 +154,7 @@ func handleRequest(app types.Application, req *types.Request, responses chan<- * } // Pull responses from 'responses' and write them to conn. -func handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) { +func (s *Server) handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) { var count int var bufWriter = bufio.NewWriter(conn) for { From b2bd661a6175cefaf664ba285fc3708d07ec12c3 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 21 Feb 2016 23:55:45 -0800 Subject: [PATCH 080/545] s/TMSPClient/Client/g --- client/client.go | 60 +++++++++++++++++++++---------------------- tests/test_counter.go | 12 ++++----- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/client/client.go b/client/client.go index 80fbc396..f4af5256 100644 --- a/client/client.go +++ b/client/client.go @@ -21,7 +21,7 @@ type Callback func(*types.Request, *types.Response) // This is goroutine-safe, but users should beware that // the application in general is not meant to be interfaced // with concurrent callers. -type TMSPClient struct { +type Client struct { QuitService sync.Mutex // [EB]: is this even used? @@ -37,48 +37,48 @@ type TMSPClient struct { resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewTMSPClient(addr string) (*TMSPClient, error) { +func NewClient(addr string) (*Client, error) { conn, err := Connect(addr) if err != nil { return nil, err } - cli := &TMSPClient{ + cli := &Client{ reqQueue: make(chan *ReqRes, reqQueueSize), - flushTimer: NewThrottleTimer("TMSPClient", flushThrottleMS), + flushTimer: NewThrottleTimer("Client", flushThrottleMS), conn: conn, bufWriter: bufio.NewWriter(conn), reqSent: list.New(), resCb: nil, } - cli.QuitService = *NewQuitService(nil, "TMSPClient", cli) + cli.QuitService = *NewQuitService(nil, "Client", cli) cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, nil } -func (cli *TMSPClient) OnStart() error { +func (cli *Client) OnStart() error { cli.QuitService.OnStart() go cli.sendRequestsRoutine() go cli.recvResponseRoutine() return nil } -func (cli *TMSPClient) OnStop() { +func (cli *Client) OnStop() { cli.QuitService.OnStop() cli.conn.Close() } // Set listener for all responses // NOTE: callback may get internally generated flush responses. -func (cli *TMSPClient) SetResponseCallback(resCb Callback) { +func (cli *Client) SetResponseCallback(resCb Callback) { cli.mtx.Lock() defer cli.mtx.Unlock() cli.resCb = resCb } -func (cli *TMSPClient) StopForError(err error) { +func (cli *Client) StopForError(err error) { cli.mtx.Lock() - // log.Error("Stopping TMSPClient for error.", "error", err) + // log.Error("Stopping Client for error.", "error", err) if cli.err == nil { cli.err = err } @@ -86,7 +86,7 @@ func (cli *TMSPClient) StopForError(err error) { cli.Stop() } -func (cli *TMSPClient) Error() error { +func (cli *Client) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() return cli.err @@ -94,7 +94,7 @@ func (cli *TMSPClient) Error() error { //---------------------------------------- -func (cli *TMSPClient) sendRequestsRoutine() { +func (cli *Client) sendRequestsRoutine() { for { select { case <-cli.flushTimer.Ch: @@ -124,7 +124,7 @@ func (cli *TMSPClient) sendRequestsRoutine() { } } -func (cli *TMSPClient) recvResponseRoutine() { +func (cli *Client) recvResponseRoutine() { r := bufio.NewReader(cli.conn) // Buffer reads for { var res = &types.Response{} @@ -147,13 +147,13 @@ func (cli *TMSPClient) recvResponseRoutine() { } } -func (cli *TMSPClient) willSendReq(reqres *ReqRes) { +func (cli *Client) willSendReq(reqres *ReqRes) { cli.mtx.Lock() defer cli.mtx.Unlock() cli.reqSent.PushBack(reqres) } -func (cli *TMSPClient) didRecvResponse(res *types.Response) error { +func (cli *Client) didRecvResponse(res *types.Response) error { cli.mtx.Lock() defer cli.mtx.Unlock() @@ -187,42 +187,42 @@ func (cli *TMSPClient) didRecvResponse(res *types.Response) error { //---------------------------------------- -func (cli *TMSPClient) EchoAsync(msg string) *ReqRes { +func (cli *Client) EchoAsync(msg string) *ReqRes { return cli.queueRequest(types.RequestEcho(msg)) } -func (cli *TMSPClient) FlushAsync() *ReqRes { +func (cli *Client) FlushAsync() *ReqRes { return cli.queueRequest(types.RequestFlush()) } -func (cli *TMSPClient) SetOptionAsync(key string, value string) *ReqRes { +func (cli *Client) SetOptionAsync(key string, value string) *ReqRes { return cli.queueRequest(types.RequestSetOption(key, value)) } -func (cli *TMSPClient) AppendTxAsync(tx []byte) *ReqRes { +func (cli *Client) AppendTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.RequestAppendTx(tx)) } -func (cli *TMSPClient) CheckTxAsync(tx []byte) *ReqRes { +func (cli *Client) CheckTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.RequestCheckTx(tx)) } -func (cli *TMSPClient) CommitAsync() *ReqRes { +func (cli *Client) CommitAsync() *ReqRes { return cli.queueRequest(types.RequestCommit()) } -func (cli *TMSPClient) QueryAsync(query []byte) *ReqRes { +func (cli *Client) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.RequestQuery(query)) } //---------------------------------------- -func (cli *TMSPClient) FlushSync() error { +func (cli *Client) FlushSync() error { cli.queueRequest(types.RequestFlush()).Wait() return cli.err } -func (cli *TMSPClient) InfoSync() (info string, err error) { +func (cli *Client) InfoSync() (info string, err error) { reqres := cli.queueRequest(types.RequestInfo()) cli.FlushSync() if cli.err != nil { @@ -231,7 +231,7 @@ func (cli *TMSPClient) InfoSync() (info string, err error) { return string(reqres.Response.Data), nil } -func (cli *TMSPClient) SetOptionSync(key string, value string) (log string, err error) { +func (cli *Client) SetOptionSync(key string, value string) (log string, err error) { reqres := cli.queueRequest(types.RequestSetOption(key, value)) cli.FlushSync() if cli.err != nil { @@ -240,7 +240,7 @@ func (cli *TMSPClient) SetOptionSync(key string, value string) (log string, err return reqres.Response.Log, nil } -func (cli *TMSPClient) AppendTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { +func (cli *Client) AppendTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestAppendTx(tx)) cli.FlushSync() if cli.err != nil { @@ -250,7 +250,7 @@ func (cli *TMSPClient) AppendTxSync(tx []byte) (code types.CodeType, result []by return res.Code, res.Data, res.Log, nil } -func (cli *TMSPClient) CheckTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { +func (cli *Client) CheckTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestCheckTx(tx)) cli.FlushSync() if cli.err != nil { @@ -260,7 +260,7 @@ func (cli *TMSPClient) CheckTxSync(tx []byte) (code types.CodeType, result []byt return res.Code, res.Data, res.Log, nil } -func (cli *TMSPClient) CommitSync() (hash []byte, log string, err error) { +func (cli *Client) CommitSync() (hash []byte, log string, err error) { reqres := cli.queueRequest(types.RequestCommit()) cli.FlushSync() if cli.err != nil { @@ -270,7 +270,7 @@ func (cli *TMSPClient) CommitSync() (hash []byte, log string, err error) { return res.Data, res.Log, nil } -func (cli *TMSPClient) QuerySync(query []byte) (code types.CodeType, result []byte, log string, err error) { +func (cli *Client) QuerySync(query []byte) (code types.CodeType, result []byte, log string, err error) { reqres := cli.queueRequest(types.RequestQuery(query)) cli.FlushSync() if cli.err != nil { @@ -282,7 +282,7 @@ func (cli *TMSPClient) QuerySync(query []byte) (code types.CodeType, result []by //---------------------------------------- -func (cli *TMSPClient) queueRequest(req *types.Request) *ReqRes { +func (cli *Client) queueRequest(req *types.Request) *ReqRes { reqres := newReqRes(req) // TODO: set cli.err if reqQueue times out cli.reqQueue <- reqres diff --git a/tests/test_counter.go b/tests/test_counter.go index ff04ec32..4c01d865 100644 --- a/tests/test_counter.go +++ b/tests/test_counter.go @@ -68,23 +68,23 @@ func startApp() *process.Process { return proc } -func startClient() *tmspcli.TMSPClient { +func startClient() *tmspcli.Client { // Start client - client, err := tmspcli.NewTMSPClient("tcp://127.0.0.1:46658") + client, err := tmspcli.NewClient("tcp://127.0.0.1:46658") if err != nil { panic("connecting to counter_app: " + err.Error()) } return client } -func setOption(client *tmspcli.TMSPClient, key, value string) { +func setOption(client *tmspcli.Client, key, value string) { log, err := client.SetOptionSync(key, value) if err != nil { panic(Fmt("setting %v=%v: %v\nlog: %v", key, value, err, log)) } } -func commit(client *tmspcli.TMSPClient, hashExp []byte) { +func commit(client *tmspcli.Client, hashExp []byte) { hash, log, err := client.CommitSync() if err != nil { panic(Fmt("committing %v\nlog: %v", err, log)) @@ -95,7 +95,7 @@ func commit(client *tmspcli.TMSPClient, hashExp []byte) { } } -func appendTx(client *tmspcli.TMSPClient, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func appendTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { code, data, log, err := client.AppendTxSync(txBytes) if err != nil { panic(Fmt("appending tx %X: %v\nlog: %v", txBytes, err, log)) @@ -110,7 +110,7 @@ func appendTx(client *tmspcli.TMSPClient, txBytes []byte, codeExp types.CodeType } } -func checkTx(client *tmspcli.TMSPClient, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func checkTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { code, data, log, err := client.CheckTxSync(txBytes) if err != nil { panic(Fmt("checking tx %X: %v\nlog: %v", txBytes, err, log)) From 727fcd4ada90cddde23629f0fc5e775a603b7d8d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 23 Feb 2016 13:36:18 -0500 Subject: [PATCH 081/545] get_hash -> commit; printResponse improvement --- cmd/tmsp-cli/tmsp-cli.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index f111b3e9..0b1a4ad8 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -80,8 +80,8 @@ func main() { }, }, { - Name: "get_hash", - Usage: "Get application Merkle root hash", + Name: "commit", + Usage: "Commit the application state and return the Merkle root hash", Action: func(c *cli.Context) { cmdCommit(c) }, @@ -283,20 +283,20 @@ func cmdQuery(c *cli.Context) { //-------------------------------------------------------------------------------- func printResponse(res *types.Response, s string) { - fmt.Printf("-> ") - if res.Error != "" { - fmt.Printf("error: %s\t", res.Error) + switch res.Type { + case types.MessageType_AppendTx, types.MessageType_CheckTx, types.MessageType_Query: + fmt.Printf("-> code: %s\n", res.Code.String()) } - if res.Code != types.CodeType_OK { - fmt.Printf("code: %s", res.Code.String()) + if res.Error != "" { + fmt.Printf("-> error: %s\n", res.Error) } if s != "" { - fmt.Printf("data: {%s}", s) + fmt.Printf("-> data: {%s}\n", s) } if res.Log != "" { - fmt.Printf("log: %s", res.Log) + fmt.Printf("-> log: %s\n", res.Log) } - fmt.Printf("\n") + } func responseString(res *types.Response) string { From 500c1736044f14e00551d6f31270dd342fe4efed Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 26 Feb 2016 20:04:28 -0500 Subject: [PATCH 082/545] nil app --- example/nil/nil_app.go | 36 ++++++++++++++++ example/nil/nil_test.go | 91 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 example/nil/nil_app.go create mode 100644 example/nil/nil_test.go diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go new file mode 100644 index 00000000..f417862b --- /dev/null +++ b/example/nil/nil_app.go @@ -0,0 +1,36 @@ +package nilapp + +import ( + "github.com/tendermint/tmsp/types" +) + +type NilApplication struct { +} + +func NewNilApplication() *NilApplication { + return &NilApplication{} +} + +func (app *NilApplication) Info() string { + return "nil" +} + +func (app *NilApplication) SetOption(key string, value string) (log string) { + return "" +} + +func (app *NilApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { + return types.CodeType_OK, nil, "" +} + +func (app *NilApplication) CheckTx(tx []byte) (code types.CodeType, result []byte, log string) { + return types.CodeType_OK, nil, "" +} + +func (app *NilApplication) Commit() (hash []byte, log string) { + return []byte("nil"), "" +} + +func (app *NilApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { + return types.CodeType_OK, nil, "" +} diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go new file mode 100644 index 00000000..8ffa388e --- /dev/null +++ b/example/nil/nil_test.go @@ -0,0 +1,91 @@ +package nilapp + +import ( + "testing" + "time" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" +) + +func TestStream(t *testing.T) { + + numAppendTxs := 200000 + + // Start the listener + _, err := server.NewServer("tcp://127.0.0.1:46658", NewNilApplication()) + if err != nil { + Exit(err.Error()) + } + + // Connect to the socket + conn, err := Connect("tcp://127.0.0.1:46658") + if err != nil { + Exit(err.Error()) + } + + // Read response data + done := make(chan struct{}) + go func() { + counter := 0 + for { + + var res = &types.Response{} + err := types.ReadMessage(conn, res) + if err != nil { + Exit(err.Error()) + } + + // Process response + switch res.Type { + case types.MessageType_AppendTx: + counter += 1 + if res.Code != types.CodeType_OK { + t.Error("AppendTx failed with ret_code", res.Code) + } + if counter > numAppendTxs { + t.Fatal("Too many AppendTx responses") + } + t.Log("response", counter) + if counter == numAppendTxs { + go func() { + time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow + close(done) + }() + } + case types.MessageType_Flush: + // ignore + default: + t.Error("Unexpected response type", res.Type) + } + } + }() + + // Write requests + for counter := 0; counter < numAppendTxs; counter++ { + // Send request + var req = types.RequestAppendTx([]byte("test")) + err := types.WriteMessage(req, conn) + if err != nil { + t.Fatal(err.Error()) + } + + // Sometimes send flush messages + if counter%123 == 0 { + t.Log("flush") + err := types.WriteMessage(types.RequestFlush(), conn) + if err != nil { + t.Fatal(err.Error()) + } + } + } + + // Send final flush message + err = types.WriteMessage(types.RequestFlush(), conn) + if err != nil { + t.Fatal(err.Error()) + } + + <-done +} From f23822bf5585040ab89f5c01dcef641d553d52fa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 27 Feb 2016 07:02:34 +0000 Subject: [PATCH 083/545] export NewReqRes --- client/client.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/client.go b/client/client.go index f4af5256..37243cfe 100644 --- a/client/client.go +++ b/client/client.go @@ -99,7 +99,7 @@ func (cli *Client) sendRequestsRoutine() { select { case <-cli.flushTimer.Ch: select { - case cli.reqQueue <- newReqRes(types.RequestFlush()): + case cli.reqQueue <- NewReqRes(types.RequestFlush()): default: // Probably will fill the buffer, or retry later. } @@ -283,7 +283,7 @@ func (cli *Client) QuerySync(query []byte) (code types.CodeType, result []byte, //---------------------------------------- func (cli *Client) queueRequest(req *types.Request) *ReqRes { - reqres := newReqRes(req) + reqres := NewReqRes(req) // TODO: set cli.err if reqQueue times out cli.reqQueue <- reqres @@ -314,7 +314,7 @@ type ReqRes struct { cb func(*types.Response) // A single callback that may be set. } -func newReqRes(req *types.Request) *ReqRes { +func NewReqRes(req *types.Request) *ReqRes { return &ReqRes{ Request: req, WaitGroup: waitGroup1(), From 1ffe780976e9bedca73536c9b5042134da69fef3 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 28 Feb 2016 18:53:24 -0800 Subject: [PATCH 084/545] Initial update for Init/SyncValidators --- README.md | 16 +++++ types/types.pb.go | 151 +++++++++++++++++++++++++++++----------------- types/types.proto | 29 ++++++--- 3 files changed, 131 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 03e36f79..2bad63f0 100644 --- a/README.md +++ b/README.md @@ -67,8 +67,24 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. +#### InitValidators + * __Arguments__: + * `Validators ([]Validator)`: Initial genesis validators + * __Usage__:
+ Called once upon genesis, to inform the app about the initial validators. + +#### SyncValidators + * __Returns__: + * `Validators ([]Validator)`: Changed validators with new voting powers (0 to remove) + * __Usage__:
+ Called prior to each Commit to get validator updates from the application. + ## Changelog +### Feb 28th, 2016 + +* Added InitValidators, SyncValidators + ### Feb 14th, 2016 * s/GetHash/Commit/g diff --git a/types/types.pb.go b/types/types.pb.go index ec1bb40d..a51b5123 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -11,6 +11,7 @@ It is generated from these files: It has these top-level messages: Request Response + Validator */ package types @@ -26,16 +27,18 @@ var _ = math.Inf type MessageType int32 const ( - MessageType_NullMessage MessageType = 0 - MessageType_Echo MessageType = 1 - MessageType_Flush MessageType = 2 - MessageType_Info MessageType = 3 - MessageType_SetOption MessageType = 4 - MessageType_Exception MessageType = 5 - MessageType_AppendTx MessageType = 17 - MessageType_CheckTx MessageType = 18 - MessageType_Commit MessageType = 19 - MessageType_Query MessageType = 20 + MessageType_NullMessage MessageType = 0 + MessageType_Echo MessageType = 1 + MessageType_Flush MessageType = 2 + MessageType_Info MessageType = 3 + MessageType_SetOption MessageType = 4 + MessageType_Exception MessageType = 5 + MessageType_AppendTx MessageType = 17 + MessageType_CheckTx MessageType = 18 + MessageType_Commit MessageType = 19 + MessageType_Query MessageType = 20 + MessageType_InitValdiators MessageType = 21 + MessageType_SyncValdiators MessageType = 22 ) var MessageType_name = map[int32]string{ @@ -49,18 +52,22 @@ var MessageType_name = map[int32]string{ 18: "CheckTx", 19: "Commit", 20: "Query", + 21: "InitValdiators", + 22: "SyncValdiators", } var MessageType_value = map[string]int32{ - "NullMessage": 0, - "Echo": 1, - "Flush": 2, - "Info": 3, - "SetOption": 4, - "Exception": 5, - "AppendTx": 17, - "CheckTx": 18, - "Commit": 19, - "Query": 20, + "NullMessage": 0, + "Echo": 1, + "Flush": 2, + "Info": 3, + "SetOption": 4, + "Exception": 5, + "AppendTx": 17, + "CheckTx": 18, + "Commit": 19, + "Query": 20, + "InitValdiators": 21, + "SyncValdiators": 22, } func (x MessageType) String() string { @@ -111,10 +118,11 @@ func (x CodeType) String() string { func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } type Request struct { - Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` - Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` + Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` + Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` + Validators []*Validator `protobuf:"bytes,5,rep,name=validators" json:"validators,omitempty"` } func (m *Request) Reset() { *m = Request{} } @@ -122,12 +130,20 @@ func (m *Request) String() string { return proto.CompactTextString(m) func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *Request) GetValidators() []*Validator { + if m != nil { + return m.Validators + } + return nil +} + type Response struct { - Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Code CodeType `protobuf:"varint,3,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` - Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` + Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Code CodeType `protobuf:"varint,3,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` + Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` + Validators []*Validator `protobuf:"bytes,6,rep,name=validators" json:"validators,omitempty"` } func (m *Response) Reset() { *m = Response{} } @@ -135,39 +151,62 @@ func (m *Response) String() string { return proto.CompactTextString(m func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *Response) GetValidators() []*Validator { + if m != nil { + return m.Validators + } + return nil +} + +type Validator struct { + PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` + Power uint64 `protobuf:"varint,2,opt,name=power" json:"power,omitempty"` +} + +func (m *Validator) Reset() { *m = Validator{} } +func (m *Validator) String() string { return proto.CompactTextString(m) } +func (*Validator) ProtoMessage() {} +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + func init() { proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*Response)(nil), "types.Response") + proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) } var fileDescriptor0 = []byte{ - // 406 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x92, 0x5f, 0x6e, 0xd3, 0x40, - 0x10, 0xc6, 0x71, 0x62, 0xe7, 0xcf, 0x24, 0x4d, 0x37, 0x43, 0x90, 0xfc, 0x88, 0x8a, 0x84, 0x50, - 0x1f, 0x8a, 0x54, 0x4e, 0x50, 0xa2, 0x54, 0x8a, 0x10, 0xad, 0x30, 0xed, 0x01, 0xcc, 0x7a, 0x12, - 0x5b, 0x71, 0x66, 0x8d, 0x77, 0x17, 0x1a, 0xee, 0xc0, 0x13, 0xe7, 0xe0, 0x8e, 0xec, 0xae, 0x53, - 0xa9, 0x3c, 0xf7, 0xc5, 0x9a, 0xef, 0xdb, 0x9d, 0x99, 0xdf, 0x8c, 0x17, 0xe6, 0xe6, 0xd0, 0x90, - 0x7e, 0x1f, 0xbe, 0x17, 0x4d, 0xab, 0x8c, 0xc2, 0x24, 0x88, 0xb3, 0x3d, 0x0c, 0x33, 0xfa, 0x6e, - 0x49, 0x1b, 0x7c, 0x0b, 0xb1, 0xf7, 0xd2, 0xe8, 0x75, 0xf4, 0x6e, 0x76, 0x89, 0x17, 0xdd, 0xed, - 0xcf, 0xa4, 0x75, 0xbe, 0xa5, 0x3b, 0x27, 0xb2, 0x70, 0x8e, 0x08, 0x71, 0x91, 0x9b, 0x3c, 0xed, - 0xb9, 0x7b, 0xd3, 0x2c, 0xc4, 0x28, 0xa0, 0xbf, 0xa3, 0x43, 0xda, 0x77, 0xd6, 0x38, 0xf3, 0x21, - 0x2e, 0x20, 0xf9, 0x91, 0xd7, 0x96, 0xd2, 0x38, 0x78, 0x9d, 0x38, 0xfb, 0x13, 0xc1, 0x28, 0x23, - 0xdd, 0x28, 0xd6, 0xf4, 0xac, 0x86, 0x6f, 0x20, 0x96, 0xaa, 0xa0, 0xd0, 0x71, 0x76, 0x79, 0x7a, - 0xcc, 0x5d, 0x3a, 0xab, 0x4b, 0xf4, 0x87, 0x9e, 0x81, 0xda, 0x56, 0xb5, 0x8f, 0x0c, 0x41, 0x78, - 0xd6, 0x5a, 0x6d, 0xd3, 0xa4, 0x63, 0x75, 0xe1, 0xf9, 0xef, 0x08, 0x26, 0x4f, 0xda, 0xe2, 0x29, - 0x4c, 0x6e, 0x6c, 0x5d, 0x1f, 0x2d, 0xf1, 0x02, 0x47, 0x10, 0xaf, 0x64, 0xa9, 0x44, 0x84, 0x63, - 0x48, 0xae, 0x6b, 0xab, 0x4b, 0xd1, 0xf3, 0xe6, 0x9a, 0x37, 0x4a, 0xf4, 0xf1, 0x04, 0xc6, 0x5f, - 0xc9, 0xdc, 0x36, 0xa6, 0x52, 0x2c, 0x62, 0x2f, 0x57, 0x0f, 0x92, 0x3a, 0x99, 0xe0, 0x14, 0x46, - 0x57, 0x4d, 0x43, 0x5c, 0xdc, 0x3d, 0x88, 0x39, 0x4e, 0x60, 0xb8, 0x2c, 0x49, 0xee, 0x9c, 0x70, - 0x83, 0xc1, 0x60, 0xa9, 0xf6, 0xfb, 0xca, 0x88, 0x97, 0xbe, 0xf2, 0x17, 0x4b, 0xed, 0x41, 0x2c, - 0xce, 0xff, 0xba, 0x2d, 0x3d, 0x8e, 0x82, 0x03, 0xe8, 0xdd, 0x7e, 0x72, 0x0c, 0x73, 0x38, 0x59, - 0xb3, 0xa1, 0x96, 0xf3, 0x7a, 0xe5, 0xe7, 0x70, 0x30, 0x02, 0xa6, 0xf7, 0x9c, 0x5b, 0x53, 0xaa, - 0xb6, 0xfa, 0x45, 0x85, 0x63, 0x5a, 0x80, 0x58, 0xb3, 0xb6, 0x9b, 0x4d, 0x25, 0x2b, 0x62, 0x73, - 0x4d, 0xa4, 0x1d, 0x1f, 0xc2, 0xec, 0x9e, 0x77, 0xac, 0x7e, 0xf2, 0xf1, 0x5f, 0x3b, 0x48, 0x57, - 0x6e, 0xc5, 0x6e, 0x4b, 0x15, 0x6f, 0xbb, 0x72, 0x01, 0xf4, 0x63, 0x5e, 0xdc, 0x28, 0x96, 0x24, - 0x06, 0x4f, 0x92, 0xae, 0xa4, 0x54, 0x96, 0x8d, 0x18, 0xe2, 0x2b, 0x98, 0xff, 0x57, 0xde, 0x72, - 0xa1, 0xc5, 0xe8, 0xdb, 0x20, 0x3c, 0xa9, 0x0f, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x41, 0x3b, - 0x4f, 0x97, 0x67, 0x02, 0x00, 0x00, + // 486 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x53, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0x89, 0xed, 0x24, 0x93, 0x34, 0xdd, 0x2c, 0x69, 0xe5, 0x63, 0x55, 0x24, 0x54, 0xf5, + 0x50, 0x50, 0x38, 0x71, 0x2c, 0x51, 0x2a, 0x45, 0x15, 0xad, 0x70, 0x5b, 0xee, 0xae, 0x3d, 0x49, + 0xac, 0xb8, 0xbb, 0xc6, 0xbb, 0x4b, 0x1b, 0x5e, 0x86, 0x27, 0xe0, 0xc8, 0x23, 0xf0, 0x5e, 0xcc, + 0xae, 0x1d, 0x14, 0x38, 0x21, 0xf5, 0x12, 0xcd, 0xf7, 0xcd, 0xdf, 0xf7, 0xcd, 0xc6, 0x30, 0xd2, + 0x9b, 0x12, 0xd5, 0x1b, 0xf7, 0x7b, 0x56, 0x56, 0x52, 0x4b, 0x1e, 0x38, 0x70, 0xfc, 0xdd, 0x83, + 0x4e, 0x8c, 0x5f, 0x0c, 0x2a, 0xcd, 0x5f, 0x83, 0x6f, 0xc9, 0xc8, 0x3b, 0xf2, 0x4e, 0x86, 0x13, + 0x7e, 0x56, 0x97, 0x7f, 0x44, 0xa5, 0x92, 0x25, 0xde, 0x12, 0x88, 0x5d, 0x9e, 0x73, 0xf0, 0xb3, + 0x44, 0x27, 0x51, 0x8b, 0xea, 0x06, 0xb1, 0x8b, 0x39, 0x83, 0xf6, 0x1a, 0x37, 0x51, 0x9b, 0xa8, + 0x5e, 0x6c, 0x43, 0x3e, 0x86, 0xe0, 0x6b, 0x52, 0x18, 0x8c, 0x7c, 0xc7, 0xd5, 0x80, 0xbf, 0x05, + 0xa0, 0x20, 0xa7, 0x1e, 0x59, 0xa9, 0x28, 0x38, 0x6a, 0x9f, 0xf4, 0x27, 0xac, 0xd9, 0xf4, 0x79, + 0x9b, 0x88, 0x77, 0x6a, 0x8e, 0x7f, 0x79, 0xd0, 0x8d, 0x51, 0x95, 0x52, 0x28, 0x7c, 0x96, 0xc4, + 0x57, 0xe0, 0xa7, 0x32, 0x43, 0xa7, 0x71, 0x38, 0xd9, 0x6f, 0x7a, 0xa7, 0x44, 0xd5, 0x8d, 0x36, + 0x69, 0x55, 0x63, 0x55, 0xc9, 0x6a, 0xab, 0xda, 0x01, 0xeb, 0xae, 0x90, 0x4b, 0x92, 0xeb, 0xdc, + 0x51, 0xf8, 0x8f, 0x8f, 0xf0, 0x3f, 0x7c, 0xbc, 0x87, 0xde, 0x9f, 0x04, 0x3f, 0x84, 0xb0, 0x34, + 0xf7, 0x97, 0x74, 0x31, 0xcf, 0x29, 0x6c, 0x90, 0x5d, 0x5f, 0xca, 0x47, 0xac, 0x9c, 0x70, 0x3f, + 0xae, 0xc1, 0xe9, 0x4f, 0x0f, 0xfa, 0x3b, 0x1e, 0xf9, 0x3e, 0xf4, 0xaf, 0x4c, 0x51, 0x34, 0x14, + 0x7b, 0xc1, 0xbb, 0xe0, 0xcf, 0xd2, 0x95, 0x64, 0x1e, 0xef, 0x41, 0x70, 0x51, 0x18, 0xb5, 0x62, + 0x2d, 0x4b, 0xce, 0xc5, 0x42, 0xb2, 0x36, 0xdf, 0x83, 0xde, 0x0d, 0xea, 0xeb, 0x52, 0xe7, 0x52, + 0x30, 0xdf, 0xc2, 0xd9, 0x53, 0x8a, 0x35, 0x0c, 0xf8, 0x00, 0xba, 0xe7, 0x65, 0x89, 0x22, 0xbb, + 0x7d, 0x62, 0x23, 0xde, 0x87, 0xce, 0x74, 0x85, 0xe9, 0x9a, 0x00, 0x5d, 0x11, 0xc2, 0xa9, 0x7c, + 0x78, 0xc8, 0x35, 0x7b, 0x69, 0x27, 0x7f, 0x32, 0x58, 0x6d, 0xd8, 0x98, 0xf8, 0xe1, 0x5c, 0xe4, + 0x9a, 0xec, 0x64, 0xb9, 0x33, 0xc7, 0x0e, 0x2c, 0x77, 0xb3, 0x11, 0xe9, 0x0e, 0x77, 0x78, 0xfa, + 0x83, 0x9e, 0x6e, 0x7b, 0x5f, 0x1e, 0x42, 0xeb, 0xfa, 0x92, 0xb4, 0x8e, 0x60, 0x6f, 0x2e, 0x34, + 0x56, 0x22, 0x29, 0x66, 0xf6, 0xb8, 0x24, 0x9a, 0xc1, 0xe0, 0x4e, 0x24, 0x46, 0xaf, 0x64, 0x95, + 0x7f, 0xc3, 0x8c, 0xb4, 0x8f, 0x81, 0xcd, 0x85, 0x32, 0x8b, 0x45, 0x9e, 0xe6, 0x28, 0xf4, 0x05, + 0xa2, 0x22, 0x1f, 0xb4, 0xe3, 0x4e, 0xac, 0x85, 0x7c, 0x14, 0xcd, 0x5f, 0x96, 0xcc, 0xd0, 0xb8, + 0x99, 0xa0, 0xa7, 0xcb, 0xc5, 0xb2, 0x1e, 0xe7, 0x0c, 0x7d, 0x48, 0xb2, 0x2b, 0x29, 0x52, 0x64, + 0xe1, 0x4e, 0xd3, 0x79, 0x9a, 0x4a, 0x23, 0x34, 0xeb, 0xf0, 0x03, 0x18, 0xfd, 0x35, 0xde, 0x88, + 0x4c, 0xb1, 0xee, 0x7d, 0xe8, 0x3e, 0x8d, 0x77, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa5, 0x71, + 0x5f, 0x3f, 0x2f, 0x03, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index f9da8e7d..000062a0 100644 --- a/types/types.proto +++ b/types/types.proto @@ -9,15 +9,17 @@ package types; enum MessageType { NullMessage = 0x00; - Echo = 0x01; - Flush = 0x02; - Info = 0x03; - SetOption = 0x04; - Exception = 0x05; - AppendTx = 0x11; - CheckTx = 0x12; - Commit = 0x13; - Query = 0x14; + Echo = 0x01; + Flush = 0x02; + Info = 0x03; + SetOption = 0x04; + Exception = 0x05; + AppendTx = 0x11; + CheckTx = 0x12; + Commit = 0x13; + Query = 0x14; + InitValdiators = 0x15; + SyncValdiators = 0x16; } //---------------------------------------- @@ -43,6 +45,7 @@ message Request { bytes data = 2; string key = 3; string value = 4; + repeated Validator validators = 5; } //---------------------------------------- @@ -54,5 +57,13 @@ message Response { CodeType code = 3; string error = 4; string log = 5; + repeated Validator validators = 6; } +//---------------------------------------- +// Misc types + +message Validator { + bytes pubKey = 1; + uint64 power = 2; +} From dcabdad9b954cac47efdfe2dbc00949daf5140ab Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 28 Feb 2016 19:19:29 -0800 Subject: [PATCH 085/545] Implement Init/Sync Validators --- client/client.go | 26 ++++++++++++++++++++++++++ server/server.go | 14 ++++++++++++++ types/application.go | 11 +++++++++++ types/messages.go | 26 ++++++++++++++++++++++++++ types/types.pb.go | 42 +++++++++++++++++++++--------------------- types/types.proto | 4 ++-- 6 files changed, 100 insertions(+), 23 deletions(-) diff --git a/client/client.go b/client/client.go index f4af5256..25de047f 100644 --- a/client/client.go +++ b/client/client.go @@ -215,6 +215,14 @@ func (cli *Client) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.RequestQuery(query)) } +func (cli *Client) InitValidatorsAsync(validators []*types.Validator) *ReqRes { + return cli.queueRequest(types.RequestInitValidators(validators)) +} + +func (cli *Client) SyncValidatorsAsync() *ReqRes { + return cli.queueRequest(types.RequestSyncValidators()) +} + //---------------------------------------- func (cli *Client) FlushSync() error { @@ -280,6 +288,24 @@ func (cli *Client) QuerySync(query []byte) (code types.CodeType, result []byte, return res.Code, res.Data, res.Log, nil } +func (cli *Client) InitValidatorsSync(validators []*types.Validator) (err error) { + cli.queueRequest(types.RequestInitValidators(validators)) + cli.FlushSync() + if cli.err != nil { + return cli.err + } + return nil +} + +func (cli *Client) SyncValidatorsSync() (validators []*types.Validator, err error) { + reqres := cli.queueRequest(types.RequestSyncValidators()) + cli.FlushSync() + if cli.err != nil { + return nil, cli.err + } + return reqres.Response.Validators, nil +} + //---------------------------------------- func (cli *Client) queueRequest(req *types.Request) *ReqRes { diff --git a/server/server.go b/server/server.go index e3ac8a37..47a64dcd 100644 --- a/server/server.go +++ b/server/server.go @@ -148,6 +148,20 @@ func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Respo case types.MessageType_Query: code, result, logStr := s.app.Query(req.Data) responses <- types.ResponseQuery(code, result, logStr) + case types.MessageType_InitValidators: + if app, ok := s.app.(types.ValidatorAware); ok { + app.InitValidators(req.Validators) + responses <- types.ResponseInitValidators() + } else { + responses <- types.ResponseInitValidators() + } + case types.MessageType_SyncValidators: + if app, ok := s.app.(types.ValidatorAware); ok { + validators := app.SyncValidators() + responses <- types.ResponseSyncValidators(validators) + } else { + responses <- types.ResponseSyncValidators(nil) + } default: responses <- types.ResponseException("Unknown request") } diff --git a/types/application.go b/types/application.go index d0379df0..74a2a5cc 100644 --- a/types/application.go +++ b/types/application.go @@ -1,5 +1,6 @@ package types +// Applications type Application interface { // Return application info @@ -20,3 +21,13 @@ type Application interface { // Query for state Query(query []byte) (code CodeType, result []byte, log string) } + +// Some applications can choose to implement ValidatorAware +type ValidatorAware interface { + + // Give app initial list of validators upon genesis + InitValidators([]*Validator) + + // Receive updates to validators from app, prior to commit + SyncValidators() []*Validator +} diff --git a/types/messages.go b/types/messages.go index 49c02bea..71a86c7d 100644 --- a/types/messages.go +++ b/types/messages.go @@ -61,6 +61,19 @@ func RequestQuery(queryBytes []byte) *Request { } } +func RequestInitValidators(validators []*Validator) *Request { + return &Request{ + Type: MessageType_InitValidators, + Validators: validators, + } +} + +func RequestSyncValidators() *Request { + return &Request{ + Type: MessageType_SyncValidators, + } +} + //---------------------------------------- func ResponseException(errStr string) *Response { @@ -132,6 +145,19 @@ func ResponseQuery(code CodeType, result []byte, log string) *Response { } } +func ResponseInitValidators() *Response { + return &Response{ + Type: MessageType_InitValidators, + } +} + +func ResponseSyncValidators(validators []*Validator) *Response { + return &Response{ + Type: MessageType_SyncValidators, + Validators: validators, + } +} + //---------------------------------------- // Write proto message, length delimited diff --git a/types/types.pb.go b/types/types.pb.go index a51b5123..81267107 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -37,8 +37,8 @@ const ( MessageType_CheckTx MessageType = 18 MessageType_Commit MessageType = 19 MessageType_Query MessageType = 20 - MessageType_InitValdiators MessageType = 21 - MessageType_SyncValdiators MessageType = 22 + MessageType_InitValidators MessageType = 21 + MessageType_SyncValidators MessageType = 22 ) var MessageType_name = map[int32]string{ @@ -52,8 +52,8 @@ var MessageType_name = map[int32]string{ 18: "CheckTx", 19: "Commit", 20: "Query", - 21: "InitValdiators", - 22: "SyncValdiators", + 21: "InitValidators", + 22: "SyncValidators", } var MessageType_value = map[string]int32{ "NullMessage": 0, @@ -66,8 +66,8 @@ var MessageType_value = map[string]int32{ "CheckTx": 18, "Commit": 19, "Query": 20, - "InitValdiators": 21, - "SyncValdiators": 22, + "InitValidators": 21, + "SyncValidators": 22, } func (x MessageType) String() string { @@ -177,22 +177,22 @@ func init() { } var fileDescriptor0 = []byte{ - // 486 bytes of a gzipped FileDescriptorProto + // 484 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x53, 0xcd, 0x6e, 0xd3, 0x40, 0x10, 0xc6, 0x89, 0xed, 0x24, 0x93, 0x34, 0xdd, 0x2c, 0x69, 0xe5, 0x63, 0x55, 0x24, 0x54, 0xf5, 0x50, 0x50, 0x38, 0x71, 0x2c, 0x51, 0x2a, 0x45, 0x15, 0xad, 0x70, 0x5b, 0xee, 0xae, 0x3d, 0x49, 0xac, 0xb8, 0xbb, 0xc6, 0xbb, 0x4b, 0x1b, 0x5e, 0x86, 0x27, 0xe0, 0xc8, 0x23, 0xf0, 0x5e, 0xcc, - 0xae, 0x1d, 0x14, 0x38, 0x21, 0xf5, 0x12, 0xcd, 0xf7, 0xcd, 0xdf, 0xf7, 0xcd, 0xc6, 0x30, 0xd2, + 0xae, 0x9d, 0x2a, 0x70, 0x42, 0xe2, 0x12, 0xcd, 0xf7, 0xcd, 0xdf, 0xf7, 0xcd, 0xc6, 0x30, 0xd2, 0x9b, 0x12, 0xd5, 0x1b, 0xf7, 0x7b, 0x56, 0x56, 0x52, 0x4b, 0x1e, 0x38, 0x70, 0xfc, 0xdd, 0x83, 0x4e, 0x8c, 0x5f, 0x0c, 0x2a, 0xcd, 0x5f, 0x83, 0x6f, 0xc9, 0xc8, 0x3b, 0xf2, 0x4e, 0x86, 0x13, 0x7e, 0x56, 0x97, 0x7f, 0x44, 0xa5, 0x92, 0x25, 0xde, 0x12, 0x88, 0x5d, 0x9e, 0x73, 0xf0, 0xb3, 0x44, 0x27, 0x51, 0x8b, 0xea, 0x06, 0xb1, 0x8b, 0x39, 0x83, 0xf6, 0x1a, 0x37, 0x51, 0x9b, 0xa8, 0x5e, 0x6c, 0x43, 0x3e, 0x86, 0xe0, 0x6b, 0x52, 0x18, 0x8c, 0x7c, 0xc7, 0xd5, 0x80, 0xbf, 0x05, 0xa0, 0x20, 0xa7, 0x1e, 0x59, 0xa9, 0x28, 0x38, 0x6a, 0x9f, 0xf4, 0x27, 0xac, 0xd9, 0xf4, 0x79, - 0x9b, 0x88, 0x77, 0x6a, 0x8e, 0x7f, 0x79, 0xd0, 0x8d, 0x51, 0x95, 0x52, 0x28, 0x7c, 0x96, 0xc4, - 0x57, 0xe0, 0xa7, 0x32, 0x43, 0xa7, 0x71, 0x38, 0xd9, 0x6f, 0x7a, 0xa7, 0x44, 0xd5, 0x8d, 0x36, - 0x69, 0x55, 0x63, 0x55, 0xc9, 0x6a, 0xab, 0xda, 0x01, 0xeb, 0xae, 0x90, 0x4b, 0x92, 0xeb, 0xdc, - 0x51, 0xf8, 0x8f, 0x8f, 0xf0, 0x3f, 0x7c, 0xbc, 0x87, 0xde, 0x9f, 0x04, 0x3f, 0x84, 0xb0, 0x34, + 0x9b, 0x88, 0x77, 0x6a, 0x8e, 0x7f, 0x79, 0xd0, 0x8d, 0x51, 0x95, 0x52, 0x28, 0xfc, 0x2f, 0x89, + 0xaf, 0xc0, 0x4f, 0x65, 0x86, 0x4e, 0xe3, 0x70, 0xb2, 0xdf, 0xf4, 0x4e, 0x89, 0xaa, 0x1b, 0x6d, + 0xd2, 0xaa, 0xc6, 0xaa, 0x92, 0xd5, 0x56, 0xb5, 0x03, 0xd6, 0x5d, 0x21, 0x97, 0x24, 0xd7, 0xb9, + 0xa3, 0xf0, 0x2f, 0x1f, 0xe1, 0x3f, 0xf8, 0x78, 0x0f, 0xbd, 0xe7, 0x04, 0x3f, 0x84, 0xb0, 0x34, 0xf7, 0x97, 0x74, 0x31, 0xcf, 0x29, 0x6c, 0x90, 0x5d, 0x5f, 0xca, 0x47, 0xac, 0x9c, 0x70, 0x3f, 0xae, 0xc1, 0xe9, 0x4f, 0x0f, 0xfa, 0x3b, 0x1e, 0xf9, 0x3e, 0xf4, 0xaf, 0x4c, 0x51, 0x34, 0x14, 0x7b, 0xc1, 0xbb, 0xe0, 0xcf, 0xd2, 0x95, 0x64, 0x1e, 0xef, 0x41, 0x70, 0x51, 0x18, 0xb5, 0x62, @@ -200,13 +200,13 @@ var fileDescriptor0 = []byte{ 0x30, 0xdf, 0xc2, 0xd9, 0x53, 0x8a, 0x35, 0x0c, 0xf8, 0x00, 0xba, 0xe7, 0x65, 0x89, 0x22, 0xbb, 0x7d, 0x62, 0x23, 0xde, 0x87, 0xce, 0x74, 0x85, 0xe9, 0x9a, 0x00, 0x5d, 0x11, 0xc2, 0xa9, 0x7c, 0x78, 0xc8, 0x35, 0x7b, 0x69, 0x27, 0x7f, 0x32, 0x58, 0x6d, 0xd8, 0x98, 0xf8, 0xe1, 0x5c, 0xe4, - 0x9a, 0xec, 0x64, 0xb9, 0x33, 0xc7, 0x0e, 0x2c, 0x77, 0xb3, 0x11, 0xe9, 0x0e, 0x77, 0x78, 0xfa, - 0x83, 0x9e, 0x6e, 0x7b, 0x5f, 0x1e, 0x42, 0xeb, 0xfa, 0x92, 0xb4, 0x8e, 0x60, 0x6f, 0x2e, 0x34, - 0x56, 0x22, 0x29, 0x66, 0xf6, 0xb8, 0x24, 0x9a, 0xc1, 0xe0, 0x4e, 0x24, 0x46, 0xaf, 0x64, 0x95, - 0x7f, 0xc3, 0x8c, 0xb4, 0x8f, 0x81, 0xcd, 0x85, 0x32, 0x8b, 0x45, 0x9e, 0xe6, 0x28, 0xf4, 0x05, - 0xa2, 0x22, 0x1f, 0xb4, 0xe3, 0x4e, 0xac, 0x85, 0x7c, 0x14, 0xcd, 0x5f, 0x96, 0xcc, 0xd0, 0xb8, - 0x99, 0xa0, 0xa7, 0xcb, 0xc5, 0xb2, 0x1e, 0xe7, 0x0c, 0x7d, 0x48, 0xb2, 0x2b, 0x29, 0x52, 0x64, - 0xe1, 0x4e, 0xd3, 0x79, 0x9a, 0x4a, 0x23, 0x34, 0xeb, 0xf0, 0x03, 0x18, 0xfd, 0x35, 0xde, 0x88, - 0x4c, 0xb1, 0xee, 0x7d, 0xe8, 0x3e, 0x8d, 0x77, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa5, 0x71, - 0x5f, 0x3f, 0x2f, 0x03, 0x00, 0x00, + 0xfa, 0xd9, 0x8e, 0x62, 0x07, 0x96, 0xbb, 0xd9, 0x88, 0x74, 0x87, 0x3b, 0x3c, 0xfd, 0x41, 0x4f, + 0xb7, 0xbd, 0x2f, 0x0f, 0xa1, 0x75, 0x7d, 0x49, 0x5a, 0x47, 0xb0, 0x37, 0x17, 0x1a, 0x2b, 0x91, + 0x14, 0x33, 0x7b, 0x5c, 0x12, 0xcd, 0x60, 0x70, 0x27, 0x12, 0xa3, 0x57, 0xb2, 0xca, 0xbf, 0x61, + 0x46, 0xda, 0xc7, 0xc0, 0xe6, 0x42, 0x99, 0xc5, 0x22, 0x4f, 0x73, 0x14, 0xfa, 0x02, 0x51, 0x91, + 0x0f, 0xda, 0x71, 0x27, 0xd6, 0x42, 0x3e, 0x8a, 0xe6, 0x2f, 0x4b, 0x66, 0x68, 0xdc, 0x4c, 0xd0, + 0xd3, 0xe5, 0x62, 0x59, 0x8f, 0x73, 0x86, 0x3e, 0x24, 0xd9, 0x95, 0x14, 0x29, 0xb2, 0x70, 0xa7, + 0xe9, 0x3c, 0x4d, 0xa5, 0x11, 0x9a, 0x75, 0xf8, 0x01, 0x8c, 0xfe, 0x18, 0x6f, 0x44, 0xa6, 0x58, + 0xf7, 0x3e, 0x74, 0x9f, 0xc6, 0xbb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x33, 0x74, 0xc9, 0x67, + 0x2f, 0x03, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 000062a0..349fb701 100644 --- a/types/types.proto +++ b/types/types.proto @@ -18,8 +18,8 @@ enum MessageType { CheckTx = 0x12; Commit = 0x13; Query = 0x14; - InitValdiators = 0x15; - SyncValdiators = 0x16; + InitValidators = 0x15; + SyncValidators = 0x16; } //---------------------------------------- From 72540f9cac4840989cb05b147cc89be8cd91f043 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 29 Feb 2016 21:53:04 -0800 Subject: [PATCH 086/545] Fix tests to clean up after themselves --- example/dummy/dummy_test.go | 5 +++-- example/nil/nil_test.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 073815be..22338b00 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -14,13 +14,14 @@ func TestStream(t *testing.T) { numAppendTxs := 200000 // Start the listener - _, err := server.NewServer("tcp://127.0.0.1:46658", NewDummyApplication()) + server, err := server.NewServer("unix://test.sock", NewDummyApplication()) if err != nil { Exit(err.Error()) } + defer server.Stop() // Connect to the socket - conn, err := Connect("tcp://127.0.0.1:46658") + conn, err := Connect("unix://test.sock") if err != nil { Exit(err.Error()) } diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go index 8ffa388e..0f3f6adb 100644 --- a/example/nil/nil_test.go +++ b/example/nil/nil_test.go @@ -14,13 +14,14 @@ func TestStream(t *testing.T) { numAppendTxs := 200000 // Start the listener - _, err := server.NewServer("tcp://127.0.0.1:46658", NewNilApplication()) + server, err := server.NewServer("unix://test.sock", NewNilApplication()) if err != nil { Exit(err.Error()) } + defer server.Stop() // Connect to the socket - conn, err := Connect("tcp://127.0.0.1:46658") + conn, err := Connect("unix://test.sock") if err != nil { Exit(err.Error()) } From 36c25f242fc92f842181a52a7c8db2af77dbf54f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 5 Mar 2016 19:18:34 -0800 Subject: [PATCH 087/545] s/InitValidators/InitChain/g, s/SyncValidators/EndBlock/g, added BeginBlock --- README.md | 22 +++-- client/client.go | 29 ++++-- server/server.go | 20 ++-- types/application.go | 17 ++-- types/messages.go | 29 ++++-- types/types.pb.go | 224 +++++++++++++++++++++++++++---------------- types/types.proto | 45 ++++++--- 7 files changed, 252 insertions(+), 134 deletions(-) diff --git a/README.md b/README.md index 2bad63f0..4da88227 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Arguments__: * `Data ([]byte)`: The request transaction bytes * __Returns__: - * `Code (uint)`: Response code + * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message * __Usage__:
@@ -24,7 +24,7 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Arguments__: * `Data ([]byte)`: The request transaction bytes * __Returns__: - * `Code (uint)`: Response code + * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message * __Usage__:
@@ -43,7 +43,7 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Arguments__: * `Data ([]byte)`: The query request bytes * __Returns__: - * `Code (uint)`: Response code + * `Code (uint32)`: Response code * `Data ([]byte)`: The query response bytes * `Log (string)`: Debug or error message @@ -67,23 +67,29 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. Other options are application specific. -#### InitValidators +#### InitChain * __Arguments__: * `Validators ([]Validator)`: Initial genesis validators * __Usage__:
- Called once upon genesis, to inform the app about the initial validators. + Called once upon genesis -#### SyncValidators +#### BeginBlock + * __Arguments__: + * `Height (uint64)`: Block number + * __Usage__:
+ Signals the beginning of a block + +#### EndBlock * __Returns__: * `Validators ([]Validator)`: Changed validators with new voting powers (0 to remove) * __Usage__:
- Called prior to each Commit to get validator updates from the application. + Signals the end of a block. Called prior to each Commit after all transactions ## Changelog ### Feb 28th, 2016 -* Added InitValidators, SyncValidators +* Added InitChain, BeginBlock, EndBlock ### Feb 14th, 2016 diff --git a/client/client.go b/client/client.go index f5503e14..dff12854 100644 --- a/client/client.go +++ b/client/client.go @@ -215,12 +215,16 @@ func (cli *Client) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.RequestQuery(query)) } -func (cli *Client) InitValidatorsAsync(validators []*types.Validator) *ReqRes { - return cli.queueRequest(types.RequestInitValidators(validators)) +func (cli *Client) InitChainAsync(validators []*types.Validator) *ReqRes { + return cli.queueRequest(types.RequestInitChain(validators)) } -func (cli *Client) SyncValidatorsAsync() *ReqRes { - return cli.queueRequest(types.RequestSyncValidators()) +func (cli *Client) BeginBlockAsync(height uint64) *ReqRes { + return cli.queueRequest(types.RequestBeginBlock(height)) +} + +func (cli *Client) EndBlockAsync() *ReqRes { + return cli.queueRequest(types.RequestEndBlock()) } //---------------------------------------- @@ -288,8 +292,8 @@ func (cli *Client) QuerySync(query []byte) (code types.CodeType, result []byte, return res.Code, res.Data, res.Log, nil } -func (cli *Client) InitValidatorsSync(validators []*types.Validator) (err error) { - cli.queueRequest(types.RequestInitValidators(validators)) +func (cli *Client) InitChainSync(validators []*types.Validator) (err error) { + cli.queueRequest(types.RequestInitChain(validators)) cli.FlushSync() if cli.err != nil { return cli.err @@ -297,8 +301,17 @@ func (cli *Client) InitValidatorsSync(validators []*types.Validator) (err error) return nil } -func (cli *Client) SyncValidatorsSync() (validators []*types.Validator, err error) { - reqres := cli.queueRequest(types.RequestSyncValidators()) +func (cli *Client) BeginBlockSync(height uint64) (err error) { + cli.queueRequest(types.RequestBeginBlock(height)) + cli.FlushSync() + if cli.err != nil { + return cli.err + } + return nil +} + +func (cli *Client) EndBlockSync() (validators []*types.Validator, err error) { + reqres := cli.queueRequest(types.RequestEndBlock()) cli.FlushSync() if cli.err != nil { return nil, cli.err diff --git a/server/server.go b/server/server.go index 47a64dcd..586a1a60 100644 --- a/server/server.go +++ b/server/server.go @@ -148,19 +148,19 @@ func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Respo case types.MessageType_Query: code, result, logStr := s.app.Query(req.Data) responses <- types.ResponseQuery(code, result, logStr) - case types.MessageType_InitValidators: - if app, ok := s.app.(types.ValidatorAware); ok { - app.InitValidators(req.Validators) - responses <- types.ResponseInitValidators() + case types.MessageType_InitChain: + if app, ok := s.app.(types.BlockchainAware); ok { + app.InitChain(req.Validators) + responses <- types.ResponseInitChain() } else { - responses <- types.ResponseInitValidators() + responses <- types.ResponseInitChain() } - case types.MessageType_SyncValidators: - if app, ok := s.app.(types.ValidatorAware); ok { - validators := app.SyncValidators() - responses <- types.ResponseSyncValidators(validators) + case types.MessageType_EndBlock: + if app, ok := s.app.(types.BlockchainAware); ok { + validators := app.EndBlock() + responses <- types.ResponseEndBlock(validators) } else { - responses <- types.ResponseSyncValidators(nil) + responses <- types.ResponseEndBlock(nil) } default: responses <- types.ResponseException("Unknown request") diff --git a/types/application.go b/types/application.go index 74a2a5cc..6c916a29 100644 --- a/types/application.go +++ b/types/application.go @@ -22,12 +22,17 @@ type Application interface { Query(query []byte) (code CodeType, result []byte, log string) } -// Some applications can choose to implement ValidatorAware -type ValidatorAware interface { +// Some applications can choose to implement BlockchainAware +type BlockchainAware interface { - // Give app initial list of validators upon genesis - InitValidators([]*Validator) + // Initialize blockchain + // validators: genesis validators from TendermintCore + InitChain(validators []*Validator) - // Receive updates to validators from app, prior to commit - SyncValidators() []*Validator + // Signals the beginning of a block + BeginBlock(height uint64) + + // Signals the end of a block + // validators: changed validators from app to TendermintCore + EndBlock() (validators []*Validator) } diff --git a/types/messages.go b/types/messages.go index 71a86c7d..368e2f1f 100644 --- a/types/messages.go +++ b/types/messages.go @@ -61,16 +61,23 @@ func RequestQuery(queryBytes []byte) *Request { } } -func RequestInitValidators(validators []*Validator) *Request { +func RequestInitChain(validators []*Validator) *Request { return &Request{ - Type: MessageType_InitValidators, + Type: MessageType_InitChain, Validators: validators, } } -func RequestSyncValidators() *Request { +func RequestBeginBlock(height uint64) *Request { return &Request{ - Type: MessageType_SyncValidators, + Type: MessageType_BeginBlock, + Height: height, + } +} + +func RequestEndBlock() *Request { + return &Request{ + Type: MessageType_EndBlock, } } @@ -145,15 +152,21 @@ func ResponseQuery(code CodeType, result []byte, log string) *Response { } } -func ResponseInitValidators() *Response { +func ResponseInitChain() *Response { return &Response{ - Type: MessageType_InitValidators, + Type: MessageType_InitChain, } } -func ResponseSyncValidators(validators []*Validator) *Response { +func ResponseBeginBlock() *Response { return &Response{ - Type: MessageType_SyncValidators, + Type: MessageType_BeginBlock, + } +} + +func ResponseEndBlock(validators []*Validator) *Response { + return &Response{ + Type: MessageType_EndBlock, Validators: validators, } } diff --git a/types/types.pb.go b/types/types.pb.go index 81267107..d8b71f96 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -27,18 +27,19 @@ var _ = math.Inf type MessageType int32 const ( - MessageType_NullMessage MessageType = 0 - MessageType_Echo MessageType = 1 - MessageType_Flush MessageType = 2 - MessageType_Info MessageType = 3 - MessageType_SetOption MessageType = 4 - MessageType_Exception MessageType = 5 - MessageType_AppendTx MessageType = 17 - MessageType_CheckTx MessageType = 18 - MessageType_Commit MessageType = 19 - MessageType_Query MessageType = 20 - MessageType_InitValidators MessageType = 21 - MessageType_SyncValidators MessageType = 22 + MessageType_NullMessage MessageType = 0 + MessageType_Echo MessageType = 1 + MessageType_Flush MessageType = 2 + MessageType_Info MessageType = 3 + MessageType_SetOption MessageType = 4 + MessageType_Exception MessageType = 5 + MessageType_AppendTx MessageType = 17 + MessageType_CheckTx MessageType = 18 + MessageType_Commit MessageType = 19 + MessageType_Query MessageType = 20 + MessageType_InitChain MessageType = 21 + MessageType_BeginBlock MessageType = 22 + MessageType_EndBlock MessageType = 23 ) var MessageType_name = map[int32]string{ @@ -52,22 +53,24 @@ var MessageType_name = map[int32]string{ 18: "CheckTx", 19: "Commit", 20: "Query", - 21: "InitValidators", - 22: "SyncValidators", + 21: "InitChain", + 22: "BeginBlock", + 23: "EndBlock", } var MessageType_value = map[string]int32{ - "NullMessage": 0, - "Echo": 1, - "Flush": 2, - "Info": 3, - "SetOption": 4, - "Exception": 5, - "AppendTx": 17, - "CheckTx": 18, - "Commit": 19, - "Query": 20, - "InitValidators": 21, - "SyncValidators": 22, + "NullMessage": 0, + "Echo": 1, + "Flush": 2, + "Info": 3, + "SetOption": 4, + "Exception": 5, + "AppendTx": 17, + "CheckTx": 18, + "Commit": 19, + "Query": 20, + "InitChain": 21, + "BeginBlock": 22, + "EndBlock": 23, } func (x MessageType) String() string { @@ -80,36 +83,80 @@ type CodeType int32 const ( CodeType_OK CodeType = 0 CodeType_InternalError CodeType = 1 - CodeType_Unauthorized CodeType = 2 - CodeType_InsufficientFees CodeType = 3 - CodeType_UnknownRequest CodeType = 4 - CodeType_EncodingError CodeType = 5 - CodeType_BadNonce CodeType = 6 - CodeType_UnknownAccount CodeType = 7 - CodeType_InsufficientFunds CodeType = 8 + CodeType_EncodingError CodeType = 2 + CodeType_BadNonce CodeType = 3 + CodeType_Unauthorized CodeType = 4 + CodeType_InsufficientFunds CodeType = 5 + CodeType_UnknownRequest CodeType = 6 + // Reserved for basecoin, 100 ~ 199 + CodeType_BaseEncodingError CodeType = 101 + CodeType_BaseBadNonce CodeType = 102 + CodeType_BaseUnknownAccount CodeType = 103 + CodeType_BaseUnauthorized CodeType = 104 + CodeType_BaseInsufficientFunds CodeType = 105 + CodeType_BaseInsufficientFees CodeType = 106 + // Reserved for governance, 200 ~ 299 + CodeType_GovUnknownEntity CodeType = 201 + CodeType_GovUnknownGroup CodeType = 202 + CodeType_GovUnknownMember CodeType = 203 + CodeType_GovUnknownProposal CodeType = 204 + CodeType_GovDuplicateEntity CodeType = 205 + CodeType_GovDuplicateGroup CodeType = 206 + CodeType_GovDuplicateMember CodeType = 207 + CodeType_GovDuplicateProposal CodeType = 208 + CodeType_GovDuplicateVote CodeType = 209 + CodeType_GovInvalidVotingPower CodeType = 210 ) var CodeType_name = map[int32]string{ - 0: "OK", - 1: "InternalError", - 2: "Unauthorized", - 3: "InsufficientFees", - 4: "UnknownRequest", - 5: "EncodingError", - 6: "BadNonce", - 7: "UnknownAccount", - 8: "InsufficientFunds", + 0: "OK", + 1: "InternalError", + 2: "EncodingError", + 3: "BadNonce", + 4: "Unauthorized", + 5: "InsufficientFunds", + 6: "UnknownRequest", + 101: "BaseEncodingError", + 102: "BaseBadNonce", + 103: "BaseUnknownAccount", + 104: "BaseUnauthorized", + 105: "BaseInsufficientFunds", + 106: "BaseInsufficientFees", + 201: "GovUnknownEntity", + 202: "GovUnknownGroup", + 203: "GovUnknownMember", + 204: "GovUnknownProposal", + 205: "GovDuplicateEntity", + 206: "GovDuplicateGroup", + 207: "GovDuplicateMember", + 208: "GovDuplicateProposal", + 209: "GovDuplicateVote", + 210: "GovInvalidVotingPower", } var CodeType_value = map[string]int32{ - "OK": 0, - "InternalError": 1, - "Unauthorized": 2, - "InsufficientFees": 3, - "UnknownRequest": 4, - "EncodingError": 5, - "BadNonce": 6, - "UnknownAccount": 7, - "InsufficientFunds": 8, + "OK": 0, + "InternalError": 1, + "EncodingError": 2, + "BadNonce": 3, + "Unauthorized": 4, + "InsufficientFunds": 5, + "UnknownRequest": 6, + "BaseEncodingError": 101, + "BaseBadNonce": 102, + "BaseUnknownAccount": 103, + "BaseUnauthorized": 104, + "BaseInsufficientFunds": 105, + "BaseInsufficientFees": 106, + "GovUnknownEntity": 201, + "GovUnknownGroup": 202, + "GovUnknownMember": 203, + "GovUnknownProposal": 204, + "GovDuplicateEntity": 205, + "GovDuplicateGroup": 206, + "GovDuplicateMember": 207, + "GovDuplicateProposal": 208, + "GovDuplicateVote": 209, + "GovInvalidVotingPower": 210, } func (x CodeType) String() string { @@ -123,6 +170,7 @@ type Request struct { Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` Validators []*Validator `protobuf:"bytes,5,rep,name=validators" json:"validators,omitempty"` + Height uint64 `protobuf:"varint,6,opt,name=height" json:"height,omitempty"` } func (m *Request) Reset() { *m = Request{} } @@ -177,36 +225,46 @@ func init() { } var fileDescriptor0 = []byte{ - // 484 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x53, 0xcd, 0x6e, 0xd3, 0x40, - 0x10, 0xc6, 0x89, 0xed, 0x24, 0x93, 0x34, 0xdd, 0x2c, 0x69, 0xe5, 0x63, 0x55, 0x24, 0x54, 0xf5, - 0x50, 0x50, 0x38, 0x71, 0x2c, 0x51, 0x2a, 0x45, 0x15, 0xad, 0x70, 0x5b, 0xee, 0xae, 0x3d, 0x49, - 0xac, 0xb8, 0xbb, 0xc6, 0xbb, 0x4b, 0x1b, 0x5e, 0x86, 0x27, 0xe0, 0xc8, 0x23, 0xf0, 0x5e, 0xcc, - 0xae, 0x9d, 0x2a, 0x70, 0x42, 0xe2, 0x12, 0xcd, 0xf7, 0xcd, 0xdf, 0xf7, 0xcd, 0xc6, 0x30, 0xd2, - 0x9b, 0x12, 0xd5, 0x1b, 0xf7, 0x7b, 0x56, 0x56, 0x52, 0x4b, 0x1e, 0x38, 0x70, 0xfc, 0xdd, 0x83, - 0x4e, 0x8c, 0x5f, 0x0c, 0x2a, 0xcd, 0x5f, 0x83, 0x6f, 0xc9, 0xc8, 0x3b, 0xf2, 0x4e, 0x86, 0x13, - 0x7e, 0x56, 0x97, 0x7f, 0x44, 0xa5, 0x92, 0x25, 0xde, 0x12, 0x88, 0x5d, 0x9e, 0x73, 0xf0, 0xb3, - 0x44, 0x27, 0x51, 0x8b, 0xea, 0x06, 0xb1, 0x8b, 0x39, 0x83, 0xf6, 0x1a, 0x37, 0x51, 0x9b, 0xa8, - 0x5e, 0x6c, 0x43, 0x3e, 0x86, 0xe0, 0x6b, 0x52, 0x18, 0x8c, 0x7c, 0xc7, 0xd5, 0x80, 0xbf, 0x05, - 0xa0, 0x20, 0xa7, 0x1e, 0x59, 0xa9, 0x28, 0x38, 0x6a, 0x9f, 0xf4, 0x27, 0xac, 0xd9, 0xf4, 0x79, - 0x9b, 0x88, 0x77, 0x6a, 0x8e, 0x7f, 0x79, 0xd0, 0x8d, 0x51, 0x95, 0x52, 0x28, 0xfc, 0x2f, 0x89, - 0xaf, 0xc0, 0x4f, 0x65, 0x86, 0x4e, 0xe3, 0x70, 0xb2, 0xdf, 0xf4, 0x4e, 0x89, 0xaa, 0x1b, 0x6d, - 0xd2, 0xaa, 0xc6, 0xaa, 0x92, 0xd5, 0x56, 0xb5, 0x03, 0xd6, 0x5d, 0x21, 0x97, 0x24, 0xd7, 0xb9, - 0xa3, 0xf0, 0x2f, 0x1f, 0xe1, 0x3f, 0xf8, 0x78, 0x0f, 0xbd, 0xe7, 0x04, 0x3f, 0x84, 0xb0, 0x34, - 0xf7, 0x97, 0x74, 0x31, 0xcf, 0x29, 0x6c, 0x90, 0x5d, 0x5f, 0xca, 0x47, 0xac, 0x9c, 0x70, 0x3f, - 0xae, 0xc1, 0xe9, 0x4f, 0x0f, 0xfa, 0x3b, 0x1e, 0xf9, 0x3e, 0xf4, 0xaf, 0x4c, 0x51, 0x34, 0x14, - 0x7b, 0xc1, 0xbb, 0xe0, 0xcf, 0xd2, 0x95, 0x64, 0x1e, 0xef, 0x41, 0x70, 0x51, 0x18, 0xb5, 0x62, - 0x2d, 0x4b, 0xce, 0xc5, 0x42, 0xb2, 0x36, 0xdf, 0x83, 0xde, 0x0d, 0xea, 0xeb, 0x52, 0xe7, 0x52, - 0x30, 0xdf, 0xc2, 0xd9, 0x53, 0x8a, 0x35, 0x0c, 0xf8, 0x00, 0xba, 0xe7, 0x65, 0x89, 0x22, 0xbb, - 0x7d, 0x62, 0x23, 0xde, 0x87, 0xce, 0x74, 0x85, 0xe9, 0x9a, 0x00, 0x5d, 0x11, 0xc2, 0xa9, 0x7c, - 0x78, 0xc8, 0x35, 0x7b, 0x69, 0x27, 0x7f, 0x32, 0x58, 0x6d, 0xd8, 0x98, 0xf8, 0xe1, 0x5c, 0xe4, - 0xfa, 0xd9, 0x8e, 0x62, 0x07, 0x96, 0xbb, 0xd9, 0x88, 0x74, 0x87, 0x3b, 0x3c, 0xfd, 0x41, 0x4f, - 0xb7, 0xbd, 0x2f, 0x0f, 0xa1, 0x75, 0x7d, 0x49, 0x5a, 0x47, 0xb0, 0x37, 0x17, 0x1a, 0x2b, 0x91, - 0x14, 0x33, 0x7b, 0x5c, 0x12, 0xcd, 0x60, 0x70, 0x27, 0x12, 0xa3, 0x57, 0xb2, 0xca, 0xbf, 0x61, - 0x46, 0xda, 0xc7, 0xc0, 0xe6, 0x42, 0x99, 0xc5, 0x22, 0x4f, 0x73, 0x14, 0xfa, 0x02, 0x51, 0x91, - 0x0f, 0xda, 0x71, 0x27, 0xd6, 0x42, 0x3e, 0x8a, 0xe6, 0x2f, 0x4b, 0x66, 0x68, 0xdc, 0x4c, 0xd0, - 0xd3, 0xe5, 0x62, 0x59, 0x8f, 0x73, 0x86, 0x3e, 0x24, 0xd9, 0x95, 0x14, 0x29, 0xb2, 0x70, 0xa7, - 0xe9, 0x3c, 0x4d, 0xa5, 0x11, 0x9a, 0x75, 0xf8, 0x01, 0x8c, 0xfe, 0x18, 0x6f, 0x44, 0xa6, 0x58, - 0xf7, 0x3e, 0x74, 0x9f, 0xc6, 0xbb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x33, 0x74, 0xc9, 0x67, - 0x2f, 0x03, 0x00, 0x00, + // 654 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x4f, 0xdb, 0x40, + 0x10, 0xad, 0x13, 0x27, 0x24, 0x13, 0x08, 0x9b, 0x6d, 0x02, 0x69, 0x4f, 0x88, 0x4a, 0x15, 0xe2, + 0x40, 0x2b, 0x7a, 0xea, 0x91, 0xa4, 0x01, 0x45, 0x88, 0x8f, 0xba, 0xc0, 0xdd, 0x38, 0x93, 0x78, + 0x1b, 0xb3, 0xeb, 0xda, 0x6b, 0x20, 0x3d, 0xf7, 0x3f, 0x55, 0xea, 0xbd, 0x87, 0x7e, 0x7f, 0xfc, + 0xa2, 0xce, 0xda, 0x4e, 0x08, 0xe5, 0xd0, 0x43, 0x2f, 0xd1, 0xbe, 0x37, 0xb3, 0xf3, 0xde, 0x1b, + 0xaf, 0x02, 0x0d, 0x3d, 0x09, 0x31, 0x7e, 0x92, 0xfe, 0x6e, 0x85, 0x91, 0xd2, 0x8a, 0x97, 0x52, + 0xb0, 0xfe, 0xde, 0x82, 0x05, 0x07, 0xdf, 0x24, 0x18, 0x6b, 0xfe, 0x18, 0x6c, 0x43, 0xb6, 0xad, + 0x35, 0x6b, 0xa3, 0xbe, 0xcd, 0xb7, 0xb2, 0xf6, 0x03, 0x8c, 0x63, 0x77, 0x84, 0x27, 0x04, 0x9c, + 0xb4, 0xce, 0x39, 0xd8, 0x03, 0x57, 0xbb, 0xed, 0x02, 0xf5, 0x2d, 0x3a, 0xe9, 0x99, 0x33, 0x28, + 0x8e, 0x71, 0xd2, 0x2e, 0x12, 0x55, 0x75, 0xcc, 0x91, 0x37, 0xa1, 0x74, 0xe9, 0x06, 0x09, 0xb6, + 0xed, 0x94, 0xcb, 0x00, 0x7f, 0x0a, 0x40, 0x07, 0x41, 0x77, 0x54, 0x14, 0xb7, 0x4b, 0x6b, 0xc5, + 0x8d, 0xda, 0x36, 0xcb, 0x95, 0xce, 0xa6, 0x05, 0x67, 0xae, 0x87, 0xaf, 0x40, 0xd9, 0x47, 0x31, + 0xf2, 0x75, 0xbb, 0x4c, 0x83, 0x6c, 0x27, 0x47, 0xeb, 0x1f, 0x2d, 0xa8, 0x38, 0x18, 0x87, 0x4a, + 0xc6, 0xf8, 0x5f, 0xd6, 0x1f, 0x81, 0xed, 0xa9, 0x01, 0xa6, 0xde, 0xeb, 0xdb, 0xcb, 0xf9, 0xdd, + 0x2e, 0x51, 0xd9, 0x45, 0x53, 0x34, 0x69, 0x30, 0x8a, 0x54, 0x34, 0x4d, 0x93, 0x02, 0x93, 0x3a, + 0x50, 0x23, 0x8a, 0x91, 0xa6, 0xa6, 0xe3, 0x5f, 0xf9, 0xca, 0xff, 0xce, 0xb7, 0xfe, 0x1c, 0xaa, + 0xb3, 0x82, 0x09, 0x1b, 0x26, 0xe7, 0xfb, 0xb4, 0x49, 0x2b, 0x75, 0x98, 0x23, 0x23, 0x1f, 0xaa, + 0x2b, 0x8c, 0x52, 0xe3, 0xb6, 0x93, 0x81, 0xcd, 0x0f, 0x16, 0xd4, 0xe6, 0x32, 0xf2, 0x65, 0xa8, + 0x1d, 0x26, 0x41, 0x90, 0x53, 0xec, 0x1e, 0xaf, 0x80, 0xdd, 0xf3, 0x7c, 0xc5, 0x2c, 0x5e, 0x85, + 0xd2, 0x6e, 0x90, 0xc4, 0x3e, 0x2b, 0x18, 0xb2, 0x2f, 0x87, 0x8a, 0x15, 0xf9, 0x12, 0x54, 0x5f, + 0xa1, 0x3e, 0x0a, 0xb5, 0x50, 0x92, 0xd9, 0x06, 0xf6, 0xae, 0x3d, 0xcc, 0x60, 0x89, 0x2f, 0x42, + 0x65, 0x27, 0x0c, 0x51, 0x0e, 0x4e, 0xae, 0x59, 0x83, 0xd7, 0x60, 0xa1, 0xeb, 0xa3, 0x37, 0x26, + 0x40, 0x5b, 0x84, 0x72, 0x57, 0x5d, 0x5c, 0x08, 0xcd, 0xee, 0x9b, 0xc9, 0x2f, 0x13, 0x8c, 0x26, + 0xac, 0x69, 0x06, 0xf4, 0xa5, 0xd0, 0x5d, 0xdf, 0x15, 0x92, 0xb5, 0x78, 0x1d, 0xa0, 0x83, 0x23, + 0x21, 0x3b, 0x81, 0xf2, 0xc6, 0x6c, 0xc5, 0x0c, 0xec, 0xc9, 0x41, 0x86, 0x56, 0x37, 0xdf, 0xd9, + 0x50, 0x99, 0x2e, 0x99, 0x97, 0xa1, 0x70, 0xb4, 0x4f, 0x86, 0x1b, 0xb0, 0xd4, 0x97, 0x1a, 0x23, + 0xe9, 0x06, 0x3d, 0xb3, 0x61, 0x72, 0x4e, 0x54, 0x4f, 0xd2, 0x37, 0x10, 0x72, 0x94, 0x51, 0x05, + 0x33, 0xa8, 0xe3, 0x0e, 0x0e, 0x95, 0xf4, 0x90, 0x52, 0x30, 0x58, 0x3c, 0x95, 0x6e, 0xa2, 0x7d, + 0x15, 0x89, 0xb7, 0x38, 0xa0, 0x20, 0x2d, 0x68, 0xf4, 0x65, 0x9c, 0x0c, 0x87, 0xc2, 0x13, 0x28, + 0xf5, 0x6e, 0x22, 0x07, 0x31, 0x05, 0xe2, 0x50, 0x3f, 0x95, 0x63, 0xa9, 0xae, 0x64, 0xfe, 0xe2, + 0x59, 0xd9, 0xb4, 0x76, 0xdc, 0x18, 0x6f, 0x2b, 0xa0, 0x99, 0x69, 0xe8, 0x99, 0xca, 0x90, 0xbe, + 0x0c, 0x37, 0x4c, 0x3e, 0x60, 0xc7, 0xf3, 0x54, 0x22, 0x35, 0x1b, 0xd1, 0x97, 0x61, 0x19, 0x3f, + 0xe7, 0xc0, 0xe7, 0x0f, 0xa0, 0x65, 0xd8, 0xbb, 0x2e, 0x04, 0x6f, 0x43, 0xf3, 0x4e, 0x09, 0x31, + 0x66, 0xaf, 0xc9, 0x0b, 0xdb, 0x53, 0x97, 0xb9, 0x42, 0x4f, 0x6a, 0xa1, 0x27, 0xec, 0x93, 0x45, + 0x0a, 0xcb, 0x37, 0xf4, 0x5e, 0xa4, 0x92, 0x90, 0x7d, 0xb6, 0x6e, 0x37, 0x1f, 0xe0, 0xc5, 0x39, + 0x46, 0xec, 0x8b, 0xc5, 0x57, 0x81, 0xdf, 0xd0, 0xc7, 0x91, 0x0a, 0x55, 0xec, 0x06, 0xec, 0xeb, + 0xb4, 0xf0, 0x22, 0x09, 0x03, 0xe1, 0xb9, 0x1a, 0xf3, 0xf1, 0xdf, 0x2c, 0x0a, 0xd6, 0x98, 0x2f, + 0x64, 0x02, 0xdf, 0xef, 0x5c, 0xc8, 0x25, 0x7e, 0x58, 0x94, 0xad, 0x39, 0x5f, 0x98, 0x89, 0xfc, + 0x9c, 0x9a, 0x9a, 0x95, 0xce, 0x94, 0x46, 0xf6, 0xcb, 0xe2, 0x0f, 0xa1, 0x45, 0x74, 0x5f, 0xa6, + 0xaf, 0x9e, 0x48, 0x5a, 0xf4, 0xb1, 0x79, 0xc0, 0xec, 0xb7, 0x75, 0x5e, 0x4e, 0xff, 0x8e, 0x9e, + 0xfd, 0x09, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x69, 0x85, 0x09, 0xa3, 0x04, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 349fb701..ccb4869e 100644 --- a/types/types.proto +++ b/types/types.proto @@ -18,23 +18,45 @@ enum MessageType { CheckTx = 0x12; Commit = 0x13; Query = 0x14; - InitValidators = 0x15; - SyncValidators = 0x16; + InitChain = 0x15; + BeginBlock = 0x16; + EndBlock = 0x17; } //---------------------------------------- // Code types enum CodeType { - OK = 0; - InternalError = 1; - Unauthorized = 2; - InsufficientFees = 3; - UnknownRequest = 4; - EncodingError = 5; - BadNonce = 6; - UnknownAccount = 7; - InsufficientFunds = 8; + OK = 0; + + // General response codes, 0 ~ 99 + InternalError = 1; + EncodingError = 2; + BadNonce = 3; + Unauthorized = 4; + InsufficientFunds = 5; + UnknownRequest = 6; + + // Reserved for basecoin, 100 ~ 199 + BaseEncodingError = 101; + BaseBadNonce = 102; + BaseUnknownAccount = 103; + BaseUnauthorized = 104; + BaseInsufficientFunds = 105; + BaseInsufficientFees = 106; + + // Reserved for governance, 200 ~ 299 + GovUnknownEntity = 201; + GovUnknownGroup = 202; + GovUnknownMember = 203; + GovUnknownProposal = 204; + GovDuplicateEntity = 205; + GovDuplicateGroup = 206; + GovDuplicateMember = 207; + GovDuplicateProposal = 208; + GovDuplicateVote = 209; + GovInvalidVotingPower = 210; + } //---------------------------------------- @@ -46,6 +68,7 @@ message Request { string key = 3; string value = 4; repeated Validator validators = 5; + uint64 height = 6; } //---------------------------------------- From 61c34ade0d480b8f23d6cdcd8fe7fea0dfec3279 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 6 Mar 2016 17:57:47 -0800 Subject: [PATCH 088/545] Remove BeginBlock --- README.md | 12 ++---- client/client.go | 21 ++-------- server/server.go | 2 +- types/application.go | 5 +-- types/messages.go | 16 +------- types/types.pb.go | 93 ++++++++++++++++++++++---------------------- types/types.proto | 2 +- 7 files changed, 59 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 4da88227..9d1db358 100644 --- a/README.md +++ b/README.md @@ -73,13 +73,9 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Usage__:
Called once upon genesis -#### BeginBlock - * __Arguments__: - * `Height (uint64)`: Block number - * __Usage__:
- Signals the beginning of a block - #### EndBlock + * __Arguments__: + * `Height (uint64)`: The block height that ended * __Returns__: * `Validators ([]Validator)`: Changed validators with new voting powers (0 to remove) * __Usage__:
@@ -87,9 +83,9 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil ## Changelog -### Feb 28th, 2016 +### Mar 6th, 2016 -* Added InitChain, BeginBlock, EndBlock +* Added InitChain, EndBlock ### Feb 14th, 2016 diff --git a/client/client.go b/client/client.go index dff12854..02a55710 100644 --- a/client/client.go +++ b/client/client.go @@ -219,12 +219,8 @@ func (cli *Client) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.queueRequest(types.RequestInitChain(validators)) } -func (cli *Client) BeginBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.RequestBeginBlock(height)) -} - -func (cli *Client) EndBlockAsync() *ReqRes { - return cli.queueRequest(types.RequestEndBlock()) +func (cli *Client) EndBlockAsync(height uint64) *ReqRes { + return cli.queueRequest(types.RequestEndBlock(height)) } //---------------------------------------- @@ -301,17 +297,8 @@ func (cli *Client) InitChainSync(validators []*types.Validator) (err error) { return nil } -func (cli *Client) BeginBlockSync(height uint64) (err error) { - cli.queueRequest(types.RequestBeginBlock(height)) - cli.FlushSync() - if cli.err != nil { - return cli.err - } - return nil -} - -func (cli *Client) EndBlockSync() (validators []*types.Validator, err error) { - reqres := cli.queueRequest(types.RequestEndBlock()) +func (cli *Client) EndBlockSync(height uint64) (validators []*types.Validator, err error) { + reqres := cli.queueRequest(types.RequestEndBlock(height)) cli.FlushSync() if cli.err != nil { return nil, cli.err diff --git a/server/server.go b/server/server.go index 586a1a60..afef937f 100644 --- a/server/server.go +++ b/server/server.go @@ -157,7 +157,7 @@ func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Respo } case types.MessageType_EndBlock: if app, ok := s.app.(types.BlockchainAware); ok { - validators := app.EndBlock() + validators := app.EndBlock(req.Height) responses <- types.ResponseEndBlock(validators) } else { responses <- types.ResponseEndBlock(nil) diff --git a/types/application.go b/types/application.go index 6c916a29..79c1f9fd 100644 --- a/types/application.go +++ b/types/application.go @@ -29,10 +29,7 @@ type BlockchainAware interface { // validators: genesis validators from TendermintCore InitChain(validators []*Validator) - // Signals the beginning of a block - BeginBlock(height uint64) - // Signals the end of a block // validators: changed validators from app to TendermintCore - EndBlock() (validators []*Validator) + EndBlock(height uint64) (validators []*Validator) } diff --git a/types/messages.go b/types/messages.go index 368e2f1f..4a35c343 100644 --- a/types/messages.go +++ b/types/messages.go @@ -68,19 +68,13 @@ func RequestInitChain(validators []*Validator) *Request { } } -func RequestBeginBlock(height uint64) *Request { +func RequestEndBlock(height uint64) *Request { return &Request{ - Type: MessageType_BeginBlock, + Type: MessageType_EndBlock, Height: height, } } -func RequestEndBlock() *Request { - return &Request{ - Type: MessageType_EndBlock, - } -} - //---------------------------------------- func ResponseException(errStr string) *Response { @@ -158,12 +152,6 @@ func ResponseInitChain() *Response { } } -func ResponseBeginBlock() *Response { - return &Response{ - Type: MessageType_BeginBlock, - } -} - func ResponseEndBlock(validators []*Validator) *Response { return &Response{ Type: MessageType_EndBlock, diff --git a/types/types.pb.go b/types/types.pb.go index d8b71f96..2571d7f8 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -38,8 +38,8 @@ const ( MessageType_Commit MessageType = 19 MessageType_Query MessageType = 20 MessageType_InitChain MessageType = 21 - MessageType_BeginBlock MessageType = 22 - MessageType_EndBlock MessageType = 23 + // BeginBlock = 0x16; NOT USED + MessageType_EndBlock MessageType = 23 ) var MessageType_name = map[int32]string{ @@ -54,7 +54,6 @@ var MessageType_name = map[int32]string{ 19: "Commit", 20: "Query", 21: "InitChain", - 22: "BeginBlock", 23: "EndBlock", } var MessageType_value = map[string]int32{ @@ -69,7 +68,6 @@ var MessageType_value = map[string]int32{ "Commit": 19, "Query": 20, "InitChain": 21, - "BeginBlock": 22, "EndBlock": 23, } @@ -81,7 +79,8 @@ func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, [] type CodeType int32 const ( - CodeType_OK CodeType = 0 + CodeType_OK CodeType = 0 + // General response codes, 0 ~ 99 CodeType_InternalError CodeType = 1 CodeType_EncodingError CodeType = 2 CodeType_BadNonce CodeType = 3 @@ -225,46 +224,46 @@ func init() { } var fileDescriptor0 = []byte{ - // 654 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x4f, 0xdb, 0x40, - 0x10, 0xad, 0x13, 0x27, 0x24, 0x13, 0x08, 0x9b, 0x6d, 0x02, 0x69, 0x4f, 0x88, 0x4a, 0x15, 0xe2, - 0x40, 0x2b, 0x7a, 0xea, 0x91, 0xa4, 0x01, 0x45, 0x88, 0x8f, 0xba, 0xc0, 0xdd, 0x38, 0x93, 0x78, - 0x1b, 0xb3, 0xeb, 0xda, 0x6b, 0x20, 0x3d, 0xf7, 0x3f, 0x55, 0xea, 0xbd, 0x87, 0x7e, 0x7f, 0xfc, - 0xa2, 0xce, 0xda, 0x4e, 0x08, 0xe5, 0xd0, 0x43, 0x2f, 0xd1, 0xbe, 0x37, 0xb3, 0xf3, 0xde, 0x1b, - 0xaf, 0x02, 0x0d, 0x3d, 0x09, 0x31, 0x7e, 0x92, 0xfe, 0x6e, 0x85, 0x91, 0xd2, 0x8a, 0x97, 0x52, - 0xb0, 0xfe, 0xde, 0x82, 0x05, 0x07, 0xdf, 0x24, 0x18, 0x6b, 0xfe, 0x18, 0x6c, 0x43, 0xb6, 0xad, - 0x35, 0x6b, 0xa3, 0xbe, 0xcd, 0xb7, 0xb2, 0xf6, 0x03, 0x8c, 0x63, 0x77, 0x84, 0x27, 0x04, 0x9c, - 0xb4, 0xce, 0x39, 0xd8, 0x03, 0x57, 0xbb, 0xed, 0x02, 0xf5, 0x2d, 0x3a, 0xe9, 0x99, 0x33, 0x28, - 0x8e, 0x71, 0xd2, 0x2e, 0x12, 0x55, 0x75, 0xcc, 0x91, 0x37, 0xa1, 0x74, 0xe9, 0x06, 0x09, 0xb6, - 0xed, 0x94, 0xcb, 0x00, 0x7f, 0x0a, 0x40, 0x07, 0x41, 0x77, 0x54, 0x14, 0xb7, 0x4b, 0x6b, 0xc5, - 0x8d, 0xda, 0x36, 0xcb, 0x95, 0xce, 0xa6, 0x05, 0x67, 0xae, 0x87, 0xaf, 0x40, 0xd9, 0x47, 0x31, - 0xf2, 0x75, 0xbb, 0x4c, 0x83, 0x6c, 0x27, 0x47, 0xeb, 0x1f, 0x2d, 0xa8, 0x38, 0x18, 0x87, 0x4a, - 0xc6, 0xf8, 0x5f, 0xd6, 0x1f, 0x81, 0xed, 0xa9, 0x01, 0xa6, 0xde, 0xeb, 0xdb, 0xcb, 0xf9, 0xdd, - 0x2e, 0x51, 0xd9, 0x45, 0x53, 0x34, 0x69, 0x30, 0x8a, 0x54, 0x34, 0x4d, 0x93, 0x02, 0x93, 0x3a, - 0x50, 0x23, 0x8a, 0x91, 0xa6, 0xa6, 0xe3, 0x5f, 0xf9, 0xca, 0xff, 0xce, 0xb7, 0xfe, 0x1c, 0xaa, - 0xb3, 0x82, 0x09, 0x1b, 0x26, 0xe7, 0xfb, 0xb4, 0x49, 0x2b, 0x75, 0x98, 0x23, 0x23, 0x1f, 0xaa, - 0x2b, 0x8c, 0x52, 0xe3, 0xb6, 0x93, 0x81, 0xcd, 0x0f, 0x16, 0xd4, 0xe6, 0x32, 0xf2, 0x65, 0xa8, - 0x1d, 0x26, 0x41, 0x90, 0x53, 0xec, 0x1e, 0xaf, 0x80, 0xdd, 0xf3, 0x7c, 0xc5, 0x2c, 0x5e, 0x85, - 0xd2, 0x6e, 0x90, 0xc4, 0x3e, 0x2b, 0x18, 0xb2, 0x2f, 0x87, 0x8a, 0x15, 0xf9, 0x12, 0x54, 0x5f, - 0xa1, 0x3e, 0x0a, 0xb5, 0x50, 0x92, 0xd9, 0x06, 0xf6, 0xae, 0x3d, 0xcc, 0x60, 0x89, 0x2f, 0x42, - 0x65, 0x27, 0x0c, 0x51, 0x0e, 0x4e, 0xae, 0x59, 0x83, 0xd7, 0x60, 0xa1, 0xeb, 0xa3, 0x37, 0x26, - 0x40, 0x5b, 0x84, 0x72, 0x57, 0x5d, 0x5c, 0x08, 0xcd, 0xee, 0x9b, 0xc9, 0x2f, 0x13, 0x8c, 0x26, - 0xac, 0x69, 0x06, 0xf4, 0xa5, 0xd0, 0x5d, 0xdf, 0x15, 0x92, 0xb5, 0x78, 0x1d, 0xa0, 0x83, 0x23, - 0x21, 0x3b, 0x81, 0xf2, 0xc6, 0x6c, 0xc5, 0x0c, 0xec, 0xc9, 0x41, 0x86, 0x56, 0x37, 0xdf, 0xd9, - 0x50, 0x99, 0x2e, 0x99, 0x97, 0xa1, 0x70, 0xb4, 0x4f, 0x86, 0x1b, 0xb0, 0xd4, 0x97, 0x1a, 0x23, - 0xe9, 0x06, 0x3d, 0xb3, 0x61, 0x72, 0x4e, 0x54, 0x4f, 0xd2, 0x37, 0x10, 0x72, 0x94, 0x51, 0x05, - 0x33, 0xa8, 0xe3, 0x0e, 0x0e, 0x95, 0xf4, 0x90, 0x52, 0x30, 0x58, 0x3c, 0x95, 0x6e, 0xa2, 0x7d, - 0x15, 0x89, 0xb7, 0x38, 0xa0, 0x20, 0x2d, 0x68, 0xf4, 0x65, 0x9c, 0x0c, 0x87, 0xc2, 0x13, 0x28, - 0xf5, 0x6e, 0x22, 0x07, 0x31, 0x05, 0xe2, 0x50, 0x3f, 0x95, 0x63, 0xa9, 0xae, 0x64, 0xfe, 0xe2, - 0x59, 0xd9, 0xb4, 0x76, 0xdc, 0x18, 0x6f, 0x2b, 0xa0, 0x99, 0x69, 0xe8, 0x99, 0xca, 0x90, 0xbe, - 0x0c, 0x37, 0x4c, 0x3e, 0x60, 0xc7, 0xf3, 0x54, 0x22, 0x35, 0x1b, 0xd1, 0x97, 0x61, 0x19, 0x3f, - 0xe7, 0xc0, 0xe7, 0x0f, 0xa0, 0x65, 0xd8, 0xbb, 0x2e, 0x04, 0x6f, 0x43, 0xf3, 0x4e, 0x09, 0x31, - 0x66, 0xaf, 0xc9, 0x0b, 0xdb, 0x53, 0x97, 0xb9, 0x42, 0x4f, 0x6a, 0xa1, 0x27, 0xec, 0x93, 0x45, - 0x0a, 0xcb, 0x37, 0xf4, 0x5e, 0xa4, 0x92, 0x90, 0x7d, 0xb6, 0x6e, 0x37, 0x1f, 0xe0, 0xc5, 0x39, - 0x46, 0xec, 0x8b, 0xc5, 0x57, 0x81, 0xdf, 0xd0, 0xc7, 0x91, 0x0a, 0x55, 0xec, 0x06, 0xec, 0xeb, - 0xb4, 0xf0, 0x22, 0x09, 0x03, 0xe1, 0xb9, 0x1a, 0xf3, 0xf1, 0xdf, 0x2c, 0x0a, 0xd6, 0x98, 0x2f, - 0x64, 0x02, 0xdf, 0xef, 0x5c, 0xc8, 0x25, 0x7e, 0x58, 0x94, 0xad, 0x39, 0x5f, 0x98, 0x89, 0xfc, - 0x9c, 0x9a, 0x9a, 0x95, 0xce, 0x94, 0x46, 0xf6, 0xcb, 0xe2, 0x0f, 0xa1, 0x45, 0x74, 0x5f, 0xa6, - 0xaf, 0x9e, 0x48, 0x5a, 0xf4, 0xb1, 0x79, 0xc0, 0xec, 0xb7, 0x75, 0x5e, 0x4e, 0xff, 0x8e, 0x9e, - 0xfd, 0x09, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x69, 0x85, 0x09, 0xa3, 0x04, 0x00, 0x00, + // 649 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x52, 0xdb, 0x4a, + 0x10, 0xbd, 0x63, 0xcb, 0xc6, 0x6e, 0xf3, 0x18, 0xcf, 0xb5, 0x2f, 0xba, 0x77, 0x45, 0x71, 0xab, + 0x52, 0x14, 0x0b, 0x92, 0x22, 0xab, 0x2c, 0xc1, 0x31, 0x94, 0x8b, 0xe2, 0x11, 0x05, 0xd8, 0x0b, + 0xa9, 0x6d, 0x29, 0x16, 0x33, 0x8a, 0x34, 0x02, 0x9c, 0x75, 0xbe, 0x26, 0x3f, 0x90, 0x2f, 0xc8, + 0x22, 0xef, 0xc7, 0x17, 0xa5, 0x47, 0x92, 0x8d, 0x09, 0x8b, 0x2c, 0xb2, 0x71, 0xcd, 0x39, 0xdd, + 0xd3, 0xe7, 0x9c, 0xd6, 0x94, 0xa1, 0xad, 0x27, 0x31, 0xa6, 0x0f, 0xf3, 0xdf, 0xad, 0x38, 0x51, + 0x5a, 0x89, 0x5a, 0x0e, 0xd6, 0xdf, 0x32, 0x58, 0x70, 0xf0, 0x65, 0x86, 0xa9, 0x16, 0x0f, 0xc0, + 0x32, 0xa4, 0xcd, 0xd6, 0xd8, 0xc6, 0xf2, 0xb6, 0xd8, 0x2a, 0xda, 0x0f, 0x31, 0x4d, 0xdd, 0x11, + 0x9e, 0x12, 0x70, 0xf2, 0xba, 0x10, 0x60, 0xf9, 0xae, 0x76, 0xed, 0x0a, 0xf5, 0x2d, 0x3a, 0xf9, + 0x59, 0x70, 0xa8, 0x8e, 0x71, 0x62, 0x57, 0x89, 0x6a, 0x3a, 0xe6, 0x28, 0x3a, 0x50, 0xbb, 0x72, + 0xa3, 0x0c, 0x6d, 0x2b, 0xe7, 0x0a, 0x20, 0x1e, 0x01, 0xd0, 0x21, 0xa4, 0x3b, 0x2a, 0x49, 0xed, + 0xda, 0x5a, 0x75, 0xa3, 0xb5, 0xcd, 0x4b, 0xa5, 0xf3, 0x69, 0xc1, 0x99, 0xeb, 0x11, 0xff, 0x40, + 0x3d, 0xc0, 0x70, 0x14, 0x68, 0xbb, 0x4e, 0x83, 0x2c, 0xa7, 0x44, 0xeb, 0xef, 0x18, 0x34, 0x1c, + 0x4c, 0x63, 0x25, 0x53, 0xfc, 0x23, 0xeb, 0xff, 0x83, 0xe5, 0x29, 0x1f, 0x73, 0xef, 0xcb, 0xdb, + 0x2b, 0xe5, 0xdd, 0x1e, 0x51, 0xc5, 0x45, 0x53, 0x34, 0x69, 0x30, 0x49, 0x54, 0x32, 0x4d, 0x93, + 0x03, 0x93, 0x3a, 0x52, 0x23, 0x8a, 0x91, 0xa7, 0xa6, 0xe3, 0x2f, 0xf9, 0xea, 0xbf, 0xcf, 0xb7, + 0xfe, 0x04, 0x9a, 0xb3, 0x82, 0x09, 0x1b, 0x67, 0x17, 0x07, 0xb4, 0x49, 0x96, 0x3b, 0x2c, 0x91, + 0x91, 0x8f, 0xd5, 0x35, 0x26, 0xb9, 0x71, 0xcb, 0x29, 0xc0, 0xe6, 0x1b, 0x06, 0xad, 0xb9, 0x8c, + 0x62, 0x05, 0x5a, 0x47, 0x59, 0x14, 0x95, 0x14, 0xff, 0x4b, 0x34, 0xc0, 0xea, 0x7b, 0x81, 0xe2, + 0x4c, 0x34, 0xa1, 0xb6, 0x17, 0x65, 0x69, 0xc0, 0x2b, 0x86, 0x1c, 0xc8, 0xa1, 0xe2, 0x55, 0xb1, + 0x04, 0xcd, 0xe7, 0xa8, 0x8f, 0x63, 0x1d, 0x2a, 0xc9, 0x2d, 0x03, 0xfb, 0x37, 0x1e, 0x16, 0xb0, + 0x26, 0x16, 0xa1, 0xb1, 0x13, 0xc7, 0x28, 0xfd, 0xd3, 0x1b, 0xde, 0x16, 0x2d, 0x58, 0xe8, 0x05, + 0xe8, 0x8d, 0x09, 0xd0, 0x16, 0xa1, 0xde, 0x53, 0x97, 0x97, 0xa1, 0xe6, 0x7f, 0x9b, 0xc9, 0xcf, + 0x32, 0x4c, 0x26, 0xbc, 0x63, 0x06, 0x0c, 0x64, 0xa8, 0x7b, 0x81, 0x1b, 0x4a, 0xde, 0x35, 0x03, + 0xfa, 0xd2, 0xdf, 0x8d, 0x94, 0x37, 0xe6, 0xab, 0x9b, 0xaf, 0x2d, 0x68, 0x4c, 0x97, 0x2a, 0xea, + 0x50, 0x39, 0x3e, 0x20, 0x83, 0x6d, 0x58, 0x1a, 0x48, 0x8d, 0x89, 0x74, 0xa3, 0xbe, 0xd9, 0x28, + 0x39, 0x25, 0xaa, 0x2f, 0x69, 0xe7, 0xa1, 0x1c, 0x15, 0x54, 0xc5, 0x0c, 0xda, 0x75, 0xfd, 0x23, + 0x25, 0x3d, 0x24, 0xd7, 0x1c, 0x16, 0xcf, 0xa4, 0x9b, 0xe9, 0x40, 0x25, 0xe1, 0x2b, 0xf4, 0xc9, + 0x78, 0x17, 0xda, 0x03, 0x99, 0x66, 0xc3, 0x61, 0xe8, 0x85, 0x28, 0xf5, 0x5e, 0x26, 0xfd, 0x94, + 0x02, 0x08, 0x58, 0x3e, 0x93, 0x63, 0xa9, 0xae, 0x65, 0xf9, 0xc2, 0x79, 0xdd, 0xb4, 0xee, 0xba, + 0x29, 0xde, 0x55, 0x40, 0x33, 0xd3, 0xd0, 0x33, 0x95, 0x21, 0x7d, 0x09, 0x61, 0x98, 0x72, 0xc0, + 0x8e, 0xe7, 0xa9, 0x4c, 0x6a, 0x3e, 0xa2, 0x2f, 0xc1, 0x0b, 0x7e, 0xce, 0x41, 0x20, 0xfe, 0x85, + 0xae, 0x61, 0xef, 0xbb, 0x08, 0x85, 0x0d, 0x9d, 0x7b, 0x25, 0xc4, 0x94, 0xbf, 0x20, 0x2f, 0x7c, + 0x5f, 0x5d, 0x95, 0x0a, 0x7d, 0xa9, 0x43, 0x3d, 0xe1, 0xef, 0x19, 0x29, 0xac, 0xdc, 0xd2, 0xfb, + 0x89, 0xca, 0x62, 0xfe, 0x81, 0xdd, 0x6d, 0x3e, 0xc4, 0xcb, 0x0b, 0x4c, 0xf8, 0x47, 0x26, 0x56, + 0x41, 0xdc, 0xd2, 0x27, 0x89, 0x8a, 0x55, 0xea, 0x46, 0xfc, 0xd3, 0xb4, 0xf0, 0x34, 0x8b, 0xa3, + 0xd0, 0x73, 0x35, 0x96, 0xe3, 0x3f, 0x33, 0x0a, 0xd6, 0x9e, 0x2f, 0x14, 0x02, 0x5f, 0xee, 0x5d, + 0x28, 0x25, 0xbe, 0x32, 0xca, 0xd6, 0x99, 0x2f, 0xcc, 0x44, 0xbe, 0x4d, 0x4d, 0xcd, 0x4a, 0xe7, + 0x4a, 0x23, 0xff, 0xce, 0xc4, 0x7f, 0xd0, 0x25, 0x7a, 0x20, 0xf3, 0x57, 0x4e, 0x24, 0x2d, 0xfa, + 0xc4, 0x3c, 0x58, 0xfe, 0x83, 0x5d, 0xd4, 0xf3, 0xbf, 0x9f, 0xc7, 0x3f, 0x03, 0x00, 0x00, 0xff, + 0xff, 0x7f, 0x32, 0xc0, 0xd9, 0x93, 0x04, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index ccb4869e..3d520d05 100644 --- a/types/types.proto +++ b/types/types.proto @@ -19,7 +19,7 @@ enum MessageType { Commit = 0x13; Query = 0x14; InitChain = 0x15; - BeginBlock = 0x16; + // BeginBlock = 0x16; NOT USED EndBlock = 0x17; } From 29a6d511b48e5c2dc3feff0c57237062baa83f33 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 15 Mar 2016 11:36:05 -0700 Subject: [PATCH 089/545] Add testutil; Clean gov return codes --- testutil/messages.go | 17 ++++++ types/types.pb.go | 124 +++++++++++++++++++++---------------------- types/types.proto | 14 ++--- 3 files changed, 86 insertions(+), 69 deletions(-) create mode 100644 testutil/messages.go diff --git a/testutil/messages.go b/testutil/messages.go new file mode 100644 index 00000000..2890fbd5 --- /dev/null +++ b/testutil/messages.go @@ -0,0 +1,17 @@ +package testutil + +import ( + "github.com/tendermint/go-crypto" + "github.com/tendermint/tmsp/types" +) + +//---------------------------------------- + +// UTILITY +func Validator(secret string, power uint64) *types.Validator { + privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret)) + return &types.Validator{ + PubKey: privKey.PubKey().Bytes(), + Power: power, + } +} diff --git a/types/types.pb.go b/types/types.pb.go index 2571d7f8..8c8a370e 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -97,13 +97,13 @@ const ( // Reserved for governance, 200 ~ 299 CodeType_GovUnknownEntity CodeType = 201 CodeType_GovUnknownGroup CodeType = 202 - CodeType_GovUnknownMember CodeType = 203 - CodeType_GovUnknownProposal CodeType = 204 - CodeType_GovDuplicateEntity CodeType = 205 - CodeType_GovDuplicateGroup CodeType = 206 - CodeType_GovDuplicateMember CodeType = 207 - CodeType_GovDuplicateProposal CodeType = 208 - CodeType_GovDuplicateVote CodeType = 209 + CodeType_GovUnknownProposal CodeType = 203 + CodeType_GovDuplicateGroup CodeType = 204 + CodeType_GovDuplicateMember CodeType = 205 + CodeType_GovDuplicateProposal CodeType = 206 + CodeType_GovDuplicateVote CodeType = 207 + CodeType_GovInvalidMember CodeType = 208 + CodeType_GovInvalidVote CodeType = 209 CodeType_GovInvalidVotingPower CodeType = 210 ) @@ -123,13 +123,13 @@ var CodeType_name = map[int32]string{ 106: "BaseInsufficientFees", 201: "GovUnknownEntity", 202: "GovUnknownGroup", - 203: "GovUnknownMember", - 204: "GovUnknownProposal", - 205: "GovDuplicateEntity", - 206: "GovDuplicateGroup", - 207: "GovDuplicateMember", - 208: "GovDuplicateProposal", - 209: "GovDuplicateVote", + 203: "GovUnknownProposal", + 204: "GovDuplicateGroup", + 205: "GovDuplicateMember", + 206: "GovDuplicateProposal", + 207: "GovDuplicateVote", + 208: "GovInvalidMember", + 209: "GovInvalidVote", 210: "GovInvalidVotingPower", } var CodeType_value = map[string]int32{ @@ -148,13 +148,13 @@ var CodeType_value = map[string]int32{ "BaseInsufficientFees": 106, "GovUnknownEntity": 201, "GovUnknownGroup": 202, - "GovUnknownMember": 203, - "GovUnknownProposal": 204, - "GovDuplicateEntity": 205, - "GovDuplicateGroup": 206, - "GovDuplicateMember": 207, - "GovDuplicateProposal": 208, - "GovDuplicateVote": 209, + "GovUnknownProposal": 203, + "GovDuplicateGroup": 204, + "GovDuplicateMember": 205, + "GovDuplicateProposal": 206, + "GovDuplicateVote": 207, + "GovInvalidMember": 208, + "GovInvalidVote": 209, "GovInvalidVotingPower": 210, } @@ -224,46 +224,46 @@ func init() { } var fileDescriptor0 = []byte{ - // 649 bytes of a gzipped FileDescriptorProto + // 652 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x52, 0xdb, 0x4a, - 0x10, 0xbd, 0x63, 0xcb, 0xc6, 0x6e, 0xf3, 0x18, 0xcf, 0xb5, 0x2f, 0xba, 0x77, 0x45, 0x71, 0xab, - 0x52, 0x14, 0x0b, 0x92, 0x22, 0xab, 0x2c, 0xc1, 0x31, 0x94, 0x8b, 0xe2, 0x11, 0x05, 0xd8, 0x0b, - 0xa9, 0x6d, 0x29, 0x16, 0x33, 0x8a, 0x34, 0x02, 0x9c, 0x75, 0xbe, 0x26, 0x3f, 0x90, 0x2f, 0xc8, - 0x22, 0xef, 0xc7, 0x17, 0xa5, 0x47, 0x92, 0x8d, 0x09, 0x8b, 0x2c, 0xb2, 0x71, 0xcd, 0x39, 0xdd, - 0xd3, 0xe7, 0x9c, 0xd6, 0x94, 0xa1, 0xad, 0x27, 0x31, 0xa6, 0x0f, 0xf3, 0xdf, 0xad, 0x38, 0x51, - 0x5a, 0x89, 0x5a, 0x0e, 0xd6, 0xdf, 0x32, 0x58, 0x70, 0xf0, 0x65, 0x86, 0xa9, 0x16, 0x0f, 0xc0, - 0x32, 0xa4, 0xcd, 0xd6, 0xd8, 0xc6, 0xf2, 0xb6, 0xd8, 0x2a, 0xda, 0x0f, 0x31, 0x4d, 0xdd, 0x11, - 0x9e, 0x12, 0x70, 0xf2, 0xba, 0x10, 0x60, 0xf9, 0xae, 0x76, 0xed, 0x0a, 0xf5, 0x2d, 0x3a, 0xf9, - 0x59, 0x70, 0xa8, 0x8e, 0x71, 0x62, 0x57, 0x89, 0x6a, 0x3a, 0xe6, 0x28, 0x3a, 0x50, 0xbb, 0x72, - 0xa3, 0x0c, 0x6d, 0x2b, 0xe7, 0x0a, 0x20, 0x1e, 0x01, 0xd0, 0x21, 0xa4, 0x3b, 0x2a, 0x49, 0xed, - 0xda, 0x5a, 0x75, 0xa3, 0xb5, 0xcd, 0x4b, 0xa5, 0xf3, 0x69, 0xc1, 0x99, 0xeb, 0x11, 0xff, 0x40, - 0x3d, 0xc0, 0x70, 0x14, 0x68, 0xbb, 0x4e, 0x83, 0x2c, 0xa7, 0x44, 0xeb, 0xef, 0x18, 0x34, 0x1c, - 0x4c, 0x63, 0x25, 0x53, 0xfc, 0x23, 0xeb, 0xff, 0x83, 0xe5, 0x29, 0x1f, 0x73, 0xef, 0xcb, 0xdb, - 0x2b, 0xe5, 0xdd, 0x1e, 0x51, 0xc5, 0x45, 0x53, 0x34, 0x69, 0x30, 0x49, 0x54, 0x32, 0x4d, 0x93, - 0x03, 0x93, 0x3a, 0x52, 0x23, 0x8a, 0x91, 0xa7, 0xa6, 0xe3, 0x2f, 0xf9, 0xea, 0xbf, 0xcf, 0xb7, - 0xfe, 0x04, 0x9a, 0xb3, 0x82, 0x09, 0x1b, 0x67, 0x17, 0x07, 0xb4, 0x49, 0x96, 0x3b, 0x2c, 0x91, - 0x91, 0x8f, 0xd5, 0x35, 0x26, 0xb9, 0x71, 0xcb, 0x29, 0xc0, 0xe6, 0x1b, 0x06, 0xad, 0xb9, 0x8c, - 0x62, 0x05, 0x5a, 0x47, 0x59, 0x14, 0x95, 0x14, 0xff, 0x4b, 0x34, 0xc0, 0xea, 0x7b, 0x81, 0xe2, - 0x4c, 0x34, 0xa1, 0xb6, 0x17, 0x65, 0x69, 0xc0, 0x2b, 0x86, 0x1c, 0xc8, 0xa1, 0xe2, 0x55, 0xb1, - 0x04, 0xcd, 0xe7, 0xa8, 0x8f, 0x63, 0x1d, 0x2a, 0xc9, 0x2d, 0x03, 0xfb, 0x37, 0x1e, 0x16, 0xb0, - 0x26, 0x16, 0xa1, 0xb1, 0x13, 0xc7, 0x28, 0xfd, 0xd3, 0x1b, 0xde, 0x16, 0x2d, 0x58, 0xe8, 0x05, - 0xe8, 0x8d, 0x09, 0xd0, 0x16, 0xa1, 0xde, 0x53, 0x97, 0x97, 0xa1, 0xe6, 0x7f, 0x9b, 0xc9, 0xcf, - 0x32, 0x4c, 0x26, 0xbc, 0x63, 0x06, 0x0c, 0x64, 0xa8, 0x7b, 0x81, 0x1b, 0x4a, 0xde, 0x35, 0x03, - 0xfa, 0xd2, 0xdf, 0x8d, 0x94, 0x37, 0xe6, 0xab, 0x9b, 0xaf, 0x2d, 0x68, 0x4c, 0x97, 0x2a, 0xea, - 0x50, 0x39, 0x3e, 0x20, 0x83, 0x6d, 0x58, 0x1a, 0x48, 0x8d, 0x89, 0x74, 0xa3, 0xbe, 0xd9, 0x28, - 0x39, 0x25, 0xaa, 0x2f, 0x69, 0xe7, 0xa1, 0x1c, 0x15, 0x54, 0xc5, 0x0c, 0xda, 0x75, 0xfd, 0x23, - 0x25, 0x3d, 0x24, 0xd7, 0x1c, 0x16, 0xcf, 0xa4, 0x9b, 0xe9, 0x40, 0x25, 0xe1, 0x2b, 0xf4, 0xc9, - 0x78, 0x17, 0xda, 0x03, 0x99, 0x66, 0xc3, 0x61, 0xe8, 0x85, 0x28, 0xf5, 0x5e, 0x26, 0xfd, 0x94, - 0x02, 0x08, 0x58, 0x3e, 0x93, 0x63, 0xa9, 0xae, 0x65, 0xf9, 0xc2, 0x79, 0xdd, 0xb4, 0xee, 0xba, - 0x29, 0xde, 0x55, 0x40, 0x33, 0xd3, 0xd0, 0x33, 0x95, 0x21, 0x7d, 0x09, 0x61, 0x98, 0x72, 0xc0, - 0x8e, 0xe7, 0xa9, 0x4c, 0x6a, 0x3e, 0xa2, 0x2f, 0xc1, 0x0b, 0x7e, 0xce, 0x41, 0x20, 0xfe, 0x85, - 0xae, 0x61, 0xef, 0xbb, 0x08, 0x85, 0x0d, 0x9d, 0x7b, 0x25, 0xc4, 0x94, 0xbf, 0x20, 0x2f, 0x7c, - 0x5f, 0x5d, 0x95, 0x0a, 0x7d, 0xa9, 0x43, 0x3d, 0xe1, 0xef, 0x19, 0x29, 0xac, 0xdc, 0xd2, 0xfb, - 0x89, 0xca, 0x62, 0xfe, 0x81, 0xdd, 0x6d, 0x3e, 0xc4, 0xcb, 0x0b, 0x4c, 0xf8, 0x47, 0x26, 0x56, - 0x41, 0xdc, 0xd2, 0x27, 0x89, 0x8a, 0x55, 0xea, 0x46, 0xfc, 0xd3, 0xb4, 0xf0, 0x34, 0x8b, 0xa3, - 0xd0, 0x73, 0x35, 0x96, 0xe3, 0x3f, 0x33, 0x0a, 0xd6, 0x9e, 0x2f, 0x14, 0x02, 0x5f, 0xee, 0x5d, - 0x28, 0x25, 0xbe, 0x32, 0xca, 0xd6, 0x99, 0x2f, 0xcc, 0x44, 0xbe, 0x4d, 0x4d, 0xcd, 0x4a, 0xe7, - 0x4a, 0x23, 0xff, 0xce, 0xc4, 0x7f, 0xd0, 0x25, 0x7a, 0x20, 0xf3, 0x57, 0x4e, 0x24, 0x2d, 0xfa, - 0xc4, 0x3c, 0x58, 0xfe, 0x83, 0x5d, 0xd4, 0xf3, 0xbf, 0x9f, 0xc7, 0x3f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0x7f, 0x32, 0xc0, 0xd9, 0x93, 0x04, 0x00, 0x00, + 0x10, 0xbd, 0x63, 0xcb, 0xc6, 0x6e, 0x83, 0x19, 0x0f, 0xf6, 0xc5, 0xf7, 0xae, 0x28, 0x52, 0x95, + 0xa2, 0x58, 0x90, 0x14, 0x59, 0x65, 0x09, 0x8e, 0xa1, 0x5c, 0x14, 0x8f, 0x28, 0xc0, 0x5e, 0x48, + 0x6d, 0x4b, 0xb1, 0x98, 0x51, 0xa4, 0x11, 0xe0, 0xac, 0xf2, 0x3d, 0xf9, 0x81, 0x7c, 0x41, 0x16, + 0x79, 0x3f, 0xbe, 0x28, 0x3d, 0x92, 0x6c, 0x4c, 0x58, 0x64, 0x91, 0x8d, 0x6b, 0xce, 0xe9, 0xe9, + 0xd3, 0xe7, 0xb4, 0xa6, 0x0c, 0x2d, 0x3d, 0x89, 0x30, 0x79, 0x94, 0xfd, 0x6e, 0x45, 0xb1, 0xd2, + 0x4a, 0x54, 0x32, 0xb0, 0xfe, 0x8e, 0xc1, 0x82, 0x8d, 0xaf, 0x52, 0x4c, 0xb4, 0x78, 0x08, 0x96, + 0x21, 0xbb, 0x6c, 0x8d, 0x6d, 0x34, 0xb7, 0xc5, 0x56, 0x7e, 0xfd, 0x10, 0x93, 0xc4, 0x19, 0xe1, + 0x29, 0x01, 0x3b, 0xab, 0x0b, 0x01, 0x96, 0xe7, 0x68, 0xa7, 0x5b, 0xa2, 0x7b, 0x8b, 0x76, 0x76, + 0x16, 0x1c, 0xca, 0x63, 0x9c, 0x74, 0xcb, 0x44, 0xd5, 0x6d, 0x73, 0x14, 0x6d, 0xa8, 0x5c, 0x39, + 0x61, 0x8a, 0x5d, 0x2b, 0xe3, 0x72, 0x20, 0x1e, 0x03, 0xd0, 0x21, 0xa0, 0x1e, 0x15, 0x27, 0xdd, + 0xca, 0x5a, 0x79, 0xa3, 0xb1, 0xcd, 0x8b, 0x49, 0xe7, 0xd3, 0x82, 0x3d, 0x77, 0x47, 0xfc, 0x0b, + 0x55, 0x1f, 0x83, 0x91, 0xaf, 0xbb, 0x55, 0x12, 0xb2, 0xec, 0x02, 0xad, 0xbf, 0x67, 0x50, 0xb3, + 0x31, 0x89, 0x94, 0x4c, 0xf0, 0xaf, 0xac, 0x3f, 0x00, 0xcb, 0x55, 0x1e, 0x66, 0xde, 0x9b, 0xdb, + 0xcb, 0x45, 0x6f, 0x8f, 0xa8, 0xbc, 0xd1, 0x14, 0x4d, 0x1a, 0x8c, 0x63, 0x15, 0x4f, 0xd3, 0x64, + 0xc0, 0xa4, 0x0e, 0xd5, 0x88, 0x62, 0x64, 0xa9, 0xe9, 0xf8, 0x5b, 0xbe, 0xea, 0x9f, 0xf3, 0xad, + 0x3f, 0x85, 0xfa, 0xac, 0x60, 0xc2, 0x46, 0xe9, 0xc5, 0x01, 0x6d, 0x92, 0x65, 0x0e, 0x0b, 0x64, + 0xc6, 0x47, 0xea, 0x1a, 0xe3, 0xcc, 0xb8, 0x65, 0xe7, 0x60, 0xf3, 0x2d, 0x83, 0xc6, 0x5c, 0x46, + 0xb1, 0x0c, 0x8d, 0xa3, 0x34, 0x0c, 0x0b, 0x8a, 0xff, 0x23, 0x6a, 0x60, 0xf5, 0x5d, 0x5f, 0x71, + 0x26, 0xea, 0x50, 0xd9, 0x0b, 0xd3, 0xc4, 0xe7, 0x25, 0x43, 0x0e, 0xe4, 0x50, 0xf1, 0xb2, 0x58, + 0x82, 0xfa, 0x0b, 0xd4, 0xc7, 0x91, 0x0e, 0x94, 0xe4, 0x96, 0x81, 0xfd, 0x1b, 0x17, 0x73, 0x58, + 0x11, 0x8b, 0x50, 0xdb, 0x89, 0x22, 0x94, 0xde, 0xe9, 0x0d, 0x6f, 0x89, 0x06, 0x2c, 0xf4, 0x7c, + 0x74, 0xc7, 0x04, 0x68, 0x8b, 0x50, 0xed, 0xa9, 0xcb, 0xcb, 0x40, 0xf3, 0x15, 0xa3, 0xfc, 0x3c, + 0xc5, 0x78, 0xc2, 0xdb, 0x46, 0x60, 0x20, 0x03, 0xdd, 0xf3, 0x9d, 0x40, 0xf2, 0x8e, 0x11, 0xe8, + 0x4b, 0x6f, 0x37, 0x54, 0xee, 0x98, 0xaf, 0x6e, 0xbe, 0xb1, 0xa0, 0x36, 0x5d, 0xaa, 0xa8, 0x42, + 0xe9, 0xf8, 0x80, 0x0c, 0xb6, 0x60, 0x69, 0x20, 0x35, 0xc6, 0xd2, 0x09, 0xfb, 0x66, 0xa3, 0xe4, + 0x94, 0xa8, 0xbe, 0xa4, 0x9d, 0x07, 0x72, 0x94, 0x53, 0x25, 0x23, 0xb4, 0xeb, 0x78, 0x47, 0x4a, + 0xba, 0x48, 0xae, 0x39, 0x2c, 0x9e, 0x49, 0x27, 0xd5, 0xbe, 0x8a, 0x83, 0xd7, 0xe8, 0x91, 0xf1, + 0x0e, 0xb4, 0x06, 0x32, 0x49, 0x87, 0xc3, 0xc0, 0x0d, 0x50, 0xea, 0xbd, 0x54, 0x7a, 0x09, 0x05, + 0x10, 0xd0, 0x3c, 0x93, 0x63, 0xa9, 0xae, 0x65, 0xf1, 0xc2, 0x79, 0xd5, 0x5c, 0xdd, 0x75, 0x12, + 0xbc, 0x3b, 0x01, 0x8d, 0xa6, 0xa1, 0x67, 0x53, 0x86, 0xf4, 0x25, 0x84, 0x61, 0x0a, 0x81, 0x1d, + 0xd7, 0x55, 0xa9, 0xd4, 0x7c, 0x44, 0x5f, 0x82, 0xe7, 0xfc, 0x9c, 0x03, 0x5f, 0xfc, 0x07, 0x1d, + 0xc3, 0xde, 0x77, 0x11, 0x88, 0x2e, 0xb4, 0xef, 0x95, 0x10, 0x13, 0xfe, 0x92, 0xbc, 0xf0, 0x7d, + 0x75, 0x55, 0x4c, 0xe8, 0x4b, 0x1d, 0xe8, 0x09, 0xff, 0xc0, 0x68, 0xc2, 0xf2, 0x2d, 0xbd, 0x1f, + 0xab, 0x34, 0xe2, 0x1f, 0x99, 0x58, 0x05, 0x71, 0xcb, 0x9e, 0xc4, 0x2a, 0x52, 0x89, 0x13, 0xf2, + 0x4f, 0x8c, 0x8c, 0xb6, 0xa8, 0xf0, 0x2c, 0x8d, 0xc2, 0xc0, 0x75, 0x34, 0xe6, 0x0d, 0x9f, 0xa7, + 0x0d, 0x33, 0xfe, 0x10, 0x2f, 0x2f, 0x30, 0xe6, 0x5f, 0x18, 0x79, 0x6d, 0xcf, 0x17, 0x66, 0x5a, + 0x5f, 0x59, 0xe1, 0x68, 0x56, 0x3a, 0x57, 0x1a, 0xf9, 0xb7, 0x29, 0x3d, 0x90, 0xd9, 0xab, 0x2d, + 0x84, 0xbe, 0x33, 0xb1, 0x02, 0xcd, 0x5b, 0x3a, 0xbb, 0xfb, 0x83, 0x89, 0xff, 0xa1, 0x73, 0x87, + 0xa4, 0x25, 0x9f, 0x98, 0xc7, 0xca, 0x7f, 0xb2, 0x8b, 0x6a, 0xf6, 0xd7, 0xf3, 0xe4, 0x57, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x9d, 0x98, 0x5a, 0xc8, 0x8f, 0x04, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 3d520d05..8716e6cb 100644 --- a/types/types.proto +++ b/types/types.proto @@ -48,13 +48,13 @@ enum CodeType { // Reserved for governance, 200 ~ 299 GovUnknownEntity = 201; GovUnknownGroup = 202; - GovUnknownMember = 203; - GovUnknownProposal = 204; - GovDuplicateEntity = 205; - GovDuplicateGroup = 206; - GovDuplicateMember = 207; - GovDuplicateProposal = 208; - GovDuplicateVote = 209; + GovUnknownProposal = 203; + GovDuplicateGroup = 204; + GovDuplicateMember = 205; + GovDuplicateProposal = 206; + GovDuplicateVote = 207; + GovInvalidMember = 208; + GovInvalidVote = 209; GovInvalidVotingPower = 210; } From 55e2ce9de26688c7674d6aed8dbe0405de9dfb98 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 20 Mar 2016 17:10:13 -0700 Subject: [PATCH 090/545] Group (code,data,log) return values into types.Result --- example/counter/counter.go | 24 ++++++++++++++++-------- example/dummy/dummy.go | 12 ++++++------ example/nil/nil_app.go | 12 ++++++------ server/server.go | 12 ++++++------ types/application.go | 6 +++--- types/result.go | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 29 deletions(-) create mode 100644 types/result.go diff --git a/example/counter/counter.go b/example/counter/counter.go index f97786f8..d6b9da2e 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -29,29 +29,37 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) return "" } -func (app *CounterApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { +func (app *CounterApplication) AppendTx(tx []byte) types.Result { if app.serial { tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.CodeType_BadNonce, nil, fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue) + return types.Result{ + Code: types.CodeType_BadNonce, + Data: nil, + Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue), + } } } app.txCount += 1 - return types.CodeType_OK, nil, "" + return types.NewResultOK(nil, "") } -func (app *CounterApplication) CheckTx(tx []byte) (code types.CodeType, result []byte, log string) { +func (app *CounterApplication) CheckTx(tx []byte) types.Result { if app.serial { tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.CodeType_BadNonce, nil, fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue) + return types.Result{ + Code: types.CodeType_BadNonce, + Data: nil, + Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue), + } } } - return types.CodeType_OK, nil, "" + return types.NewResultOK(nil, "") } func (app *CounterApplication) Commit() (hash []byte, log string) { @@ -66,6 +74,6 @@ func (app *CounterApplication) Commit() (hash []byte, log string) { } } -func (app *CounterApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { - return types.CodeType_OK, nil, fmt.Sprintf("Query is not supported") +func (app *CounterApplication) Query(query []byte) types.Result { + return types.NewResultOK(nil, fmt.Sprintf("Query is not supported")) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index dc4441d9..e2d4a09e 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -28,18 +28,18 @@ func (app *DummyApplication) SetOption(key string, value string) (log string) { return "" } -func (app *DummyApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { +func (app *DummyApplication) AppendTx(tx []byte) types.Result { parts := strings.Split(string(tx), "=") if len(parts) == 2 { app.state.Set([]byte(parts[0]), []byte(parts[1])) } else { app.state.Set(tx, tx) } - return types.CodeType_OK, nil, "" + return types.NewResultOK(nil, "") } -func (app *DummyApplication) CheckTx(tx []byte) (code types.CodeType, result []byte, log string) { - return types.CodeType_OK, nil, "" +func (app *DummyApplication) CheckTx(tx []byte) types.Result { + return types.NewResultOK(nil, "") } func (app *DummyApplication) Commit() (hash []byte, log string) { @@ -47,8 +47,8 @@ func (app *DummyApplication) Commit() (hash []byte, log string) { return hash, "" } -func (app *DummyApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { +func (app *DummyApplication) Query(query []byte) types.Result { index, value, exists := app.state.Get(query) resStr := Fmt("Index=%v value=%v exists=%v", index, string(value), exists) - return types.CodeType_OK, []byte(resStr), "" + return types.NewResultOK([]byte(resStr), "") } diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index f417862b..6233ea5e 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -19,18 +19,18 @@ func (app *NilApplication) SetOption(key string, value string) (log string) { return "" } -func (app *NilApplication) AppendTx(tx []byte) (code types.CodeType, result []byte, log string) { - return types.CodeType_OK, nil, "" +func (app *NilApplication) AppendTx(tx []byte) types.Result { + return types.NewResultOK(nil, "") } -func (app *NilApplication) CheckTx(tx []byte) (code types.CodeType, result []byte, log string) { - return types.CodeType_OK, nil, "" +func (app *NilApplication) CheckTx(tx []byte) types.Result { + return types.NewResultOK(nil, "") } func (app *NilApplication) Commit() (hash []byte, log string) { return []byte("nil"), "" } -func (app *NilApplication) Query(query []byte) (code types.CodeType, result []byte, log string) { - return types.CodeType_OK, nil, "" +func (app *NilApplication) Query(query []byte) types.Result { + return types.NewResultOK(nil, "") } diff --git a/server/server.go b/server/server.go index afef937f..edc65989 100644 --- a/server/server.go +++ b/server/server.go @@ -137,17 +137,17 @@ func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Respo logStr := s.app.SetOption(req.Key, req.Value) responses <- types.ResponseSetOption(logStr) case types.MessageType_AppendTx: - code, result, logStr := s.app.AppendTx(req.Data) - responses <- types.ResponseAppendTx(code, result, logStr) + res := s.app.AppendTx(req.Data) + responses <- types.ResponseAppendTx(res.Code, res.Data, res.Log) case types.MessageType_CheckTx: - code, result, logStr := s.app.CheckTx(req.Data) - responses <- types.ResponseCheckTx(code, result, logStr) + res := s.app.CheckTx(req.Data) + responses <- types.ResponseCheckTx(res.Code, res.Data, res.Log) case types.MessageType_Commit: hash, logStr := s.app.Commit() responses <- types.ResponseCommit(hash, logStr) case types.MessageType_Query: - code, result, logStr := s.app.Query(req.Data) - responses <- types.ResponseQuery(code, result, logStr) + res := s.app.Query(req.Data) + responses <- types.ResponseQuery(res.Code, res.Data, res.Log) case types.MessageType_InitChain: if app, ok := s.app.(types.BlockchainAware); ok { app.InitChain(req.Validators) diff --git a/types/application.go b/types/application.go index 79c1f9fd..1d65ba8b 100644 --- a/types/application.go +++ b/types/application.go @@ -10,16 +10,16 @@ type Application interface { SetOption(key string, value string) (log string) // Append a tx - AppendTx(tx []byte) (code CodeType, result []byte, log string) + AppendTx(tx []byte) Result // Validate a tx for the mempool - CheckTx(tx []byte) (code CodeType, result []byte, log string) + CheckTx(tx []byte) Result // Return the application Merkle root hash Commit() (hash []byte, log string) // Query for state - Query(query []byte) (code CodeType, result []byte, log string) + Query(query []byte) Result } // Some applications can choose to implement BlockchainAware diff --git a/types/result.go b/types/result.go new file mode 100644 index 00000000..48af9f39 --- /dev/null +++ b/types/result.go @@ -0,0 +1,37 @@ +package types + +import ( + "fmt" +) + +type Result struct { + Code CodeType + Data []byte + Log string // Can be non-deterministic +} + +func NewResult(code CodeType, data []byte, log string) Result { + return Result{ + Code: code, + Data: data, + Log: log, + } +} + +func (res Result) IsOK() bool { + return res.Code == CodeType_OK +} + +func (res Result) Error() string { + return fmt.Sprintf("TMSP error code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) +} + +//---------------------------------------- + +func NewResultOK(data []byte, log string) Result { + return Result{ + Code: CodeType_OK, + Data: data, + Log: log, + } +} From 06a0ac8188c10700e9c8448bed9f4a41efb7ff63 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 20 Mar 2016 17:20:41 -0700 Subject: [PATCH 091/545] Add NewError -> Result with no data --- types/result.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/types/result.go b/types/result.go index 48af9f39..17c272f8 100644 --- a/types/result.go +++ b/types/result.go @@ -35,3 +35,10 @@ func NewResultOK(data []byte, log string) Result { Log: log, } } + +func NewError(code CodeType, log string) Result { + return Result{ + Code: code, + Log: log, + } +} From 8cac8600e59d46f58a03ca2e25ad6de143b819ed Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 20 Mar 2016 17:38:03 -0700 Subject: [PATCH 092/545] Return NewServer listener start error --- server/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index edc65989..cf8cf338 100644 --- a/server/server.go +++ b/server/server.go @@ -35,8 +35,8 @@ func NewServer(protoAddr string, app types.Application) (*Server, error) { app: app, } s.QuitService = *NewQuitService(nil, "TMSPServer", s) - s.Start() // Just start it - return s, nil + _, err := s.Start() // Just start it + return s, err } func (s *Server) OnStart() error { From 3d2d8c7d6a2ca0020112c392f2e95df36d036cf1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 21 Mar 2016 15:33:16 -0700 Subject: [PATCH 093/545] Result convenience methods; Shuffled Base* code types --- types/result.go | 32 +++++++++ types/types.pb.go | 170 +++++++++++++++++++++++++--------------------- types/types.proto | 17 +++-- 3 files changed, 137 insertions(+), 82 deletions(-) diff --git a/types/result.go b/types/result.go index 17c272f8..305fe928 100644 --- a/types/result.go +++ b/types/result.go @@ -26,6 +26,38 @@ func (res Result) Error() string { return fmt.Sprintf("TMSP error code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) } +func (res Result) PrependLog(log string) Result { + return Result{ + Code: res.Code, + Data: res.Data, + Log: log + ";" + res.Log, + } +} + +func (res Result) AppendLog(log string) Result { + return Result{ + Code: res.Code, + Data: res.Data, + Log: res.Log + ";" + log, + } +} + +func (res Result) SetLog(log string) Result { + return Result{ + Code: res.Code, + Data: res.Data, + Log: log, + } +} + +func (res Result) SetData(data []byte) Result { + return Result{ + Code: res.Code, + Data: data, + Log: res.Log, + } +} + //---------------------------------------- func NewResultOK(data []byte, log string) Result { diff --git a/types/types.pb.go b/types/types.pb.go index 8c8a370e..41323e72 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -88,12 +88,17 @@ const ( CodeType_InsufficientFunds CodeType = 5 CodeType_UnknownRequest CodeType = 6 // Reserved for basecoin, 100 ~ 199 - CodeType_BaseEncodingError CodeType = 101 - CodeType_BaseBadNonce CodeType = 102 - CodeType_BaseUnknownAccount CodeType = 103 - CodeType_BaseUnauthorized CodeType = 104 - CodeType_BaseInsufficientFunds CodeType = 105 - CodeType_BaseInsufficientFees CodeType = 106 + CodeType_BaseDuplicateAddress CodeType = 101 + CodeType_BaseEncodingError CodeType = 102 + CodeType_BaseInsufficientFees CodeType = 103 + CodeType_BaseInsufficientFunds CodeType = 104 + CodeType_BaseInsufficientGasPrice CodeType = 105 + CodeType_BaseInvalidAddress CodeType = 106 + CodeType_BaseInvalidAmount CodeType = 107 + CodeType_BaseInvalidPubKey CodeType = 108 + CodeType_BaseInvalidSequence CodeType = 109 + CodeType_BaseInvalidSignature CodeType = 110 + CodeType_BaseUnknownPubKey CodeType = 111 // Reserved for governance, 200 ~ 299 CodeType_GovUnknownEntity CodeType = 201 CodeType_GovUnknownGroup CodeType = 202 @@ -115,12 +120,17 @@ var CodeType_name = map[int32]string{ 4: "Unauthorized", 5: "InsufficientFunds", 6: "UnknownRequest", - 101: "BaseEncodingError", - 102: "BaseBadNonce", - 103: "BaseUnknownAccount", - 104: "BaseUnauthorized", - 105: "BaseInsufficientFunds", - 106: "BaseInsufficientFees", + 101: "BaseDuplicateAddress", + 102: "BaseEncodingError", + 103: "BaseInsufficientFees", + 104: "BaseInsufficientFunds", + 105: "BaseInsufficientGasPrice", + 106: "BaseInvalidAddress", + 107: "BaseInvalidAmount", + 108: "BaseInvalidPubKey", + 109: "BaseInvalidSequence", + 110: "BaseInvalidSignature", + 111: "BaseUnknownPubKey", 201: "GovUnknownEntity", 202: "GovUnknownGroup", 203: "GovUnknownProposal", @@ -133,29 +143,34 @@ var CodeType_name = map[int32]string{ 210: "GovInvalidVotingPower", } var CodeType_value = map[string]int32{ - "OK": 0, - "InternalError": 1, - "EncodingError": 2, - "BadNonce": 3, - "Unauthorized": 4, - "InsufficientFunds": 5, - "UnknownRequest": 6, - "BaseEncodingError": 101, - "BaseBadNonce": 102, - "BaseUnknownAccount": 103, - "BaseUnauthorized": 104, - "BaseInsufficientFunds": 105, - "BaseInsufficientFees": 106, - "GovUnknownEntity": 201, - "GovUnknownGroup": 202, - "GovUnknownProposal": 203, - "GovDuplicateGroup": 204, - "GovDuplicateMember": 205, - "GovDuplicateProposal": 206, - "GovDuplicateVote": 207, - "GovInvalidMember": 208, - "GovInvalidVote": 209, - "GovInvalidVotingPower": 210, + "OK": 0, + "InternalError": 1, + "EncodingError": 2, + "BadNonce": 3, + "Unauthorized": 4, + "InsufficientFunds": 5, + "UnknownRequest": 6, + "BaseDuplicateAddress": 101, + "BaseEncodingError": 102, + "BaseInsufficientFees": 103, + "BaseInsufficientFunds": 104, + "BaseInsufficientGasPrice": 105, + "BaseInvalidAddress": 106, + "BaseInvalidAmount": 107, + "BaseInvalidPubKey": 108, + "BaseInvalidSequence": 109, + "BaseInvalidSignature": 110, + "BaseUnknownPubKey": 111, + "GovUnknownEntity": 201, + "GovUnknownGroup": 202, + "GovUnknownProposal": 203, + "GovDuplicateGroup": 204, + "GovDuplicateMember": 205, + "GovDuplicateProposal": 206, + "GovDuplicateVote": 207, + "GovInvalidMember": 208, + "GovInvalidVote": 209, + "GovInvalidVotingPower": 210, } func (x CodeType) String() string { @@ -224,46 +239,49 @@ func init() { } var fileDescriptor0 = []byte{ - // 652 bytes of a gzipped FileDescriptorProto + // 703 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x52, 0xdb, 0x4a, - 0x10, 0xbd, 0x63, 0xcb, 0xc6, 0x6e, 0x83, 0x19, 0x0f, 0xf6, 0xc5, 0xf7, 0xae, 0x28, 0x52, 0x95, - 0xa2, 0x58, 0x90, 0x14, 0x59, 0x65, 0x09, 0x8e, 0xa1, 0x5c, 0x14, 0x8f, 0x28, 0xc0, 0x5e, 0x48, - 0x6d, 0x4b, 0xb1, 0x98, 0x51, 0xa4, 0x11, 0xe0, 0xac, 0xf2, 0x3d, 0xf9, 0x81, 0x7c, 0x41, 0x16, - 0x79, 0x3f, 0xbe, 0x28, 0x3d, 0x92, 0x6c, 0x4c, 0x58, 0x64, 0x91, 0x8d, 0x6b, 0xce, 0xe9, 0xe9, - 0xd3, 0xe7, 0xb4, 0xa6, 0x0c, 0x2d, 0x3d, 0x89, 0x30, 0x79, 0x94, 0xfd, 0x6e, 0x45, 0xb1, 0xd2, - 0x4a, 0x54, 0x32, 0xb0, 0xfe, 0x8e, 0xc1, 0x82, 0x8d, 0xaf, 0x52, 0x4c, 0xb4, 0x78, 0x08, 0x96, - 0x21, 0xbb, 0x6c, 0x8d, 0x6d, 0x34, 0xb7, 0xc5, 0x56, 0x7e, 0xfd, 0x10, 0x93, 0xc4, 0x19, 0xe1, - 0x29, 0x01, 0x3b, 0xab, 0x0b, 0x01, 0x96, 0xe7, 0x68, 0xa7, 0x5b, 0xa2, 0x7b, 0x8b, 0x76, 0x76, - 0x16, 0x1c, 0xca, 0x63, 0x9c, 0x74, 0xcb, 0x44, 0xd5, 0x6d, 0x73, 0x14, 0x6d, 0xa8, 0x5c, 0x39, - 0x61, 0x8a, 0x5d, 0x2b, 0xe3, 0x72, 0x20, 0x1e, 0x03, 0xd0, 0x21, 0xa0, 0x1e, 0x15, 0x27, 0xdd, - 0xca, 0x5a, 0x79, 0xa3, 0xb1, 0xcd, 0x8b, 0x49, 0xe7, 0xd3, 0x82, 0x3d, 0x77, 0x47, 0xfc, 0x0b, - 0x55, 0x1f, 0x83, 0x91, 0xaf, 0xbb, 0x55, 0x12, 0xb2, 0xec, 0x02, 0xad, 0xbf, 0x67, 0x50, 0xb3, - 0x31, 0x89, 0x94, 0x4c, 0xf0, 0xaf, 0xac, 0x3f, 0x00, 0xcb, 0x55, 0x1e, 0x66, 0xde, 0x9b, 0xdb, - 0xcb, 0x45, 0x6f, 0x8f, 0xa8, 0xbc, 0xd1, 0x14, 0x4d, 0x1a, 0x8c, 0x63, 0x15, 0x4f, 0xd3, 0x64, - 0xc0, 0xa4, 0x0e, 0xd5, 0x88, 0x62, 0x64, 0xa9, 0xe9, 0xf8, 0x5b, 0xbe, 0xea, 0x9f, 0xf3, 0xad, - 0x3f, 0x85, 0xfa, 0xac, 0x60, 0xc2, 0x46, 0xe9, 0xc5, 0x01, 0x6d, 0x92, 0x65, 0x0e, 0x0b, 0x64, - 0xc6, 0x47, 0xea, 0x1a, 0xe3, 0xcc, 0xb8, 0x65, 0xe7, 0x60, 0xf3, 0x2d, 0x83, 0xc6, 0x5c, 0x46, - 0xb1, 0x0c, 0x8d, 0xa3, 0x34, 0x0c, 0x0b, 0x8a, 0xff, 0x23, 0x6a, 0x60, 0xf5, 0x5d, 0x5f, 0x71, - 0x26, 0xea, 0x50, 0xd9, 0x0b, 0xd3, 0xc4, 0xe7, 0x25, 0x43, 0x0e, 0xe4, 0x50, 0xf1, 0xb2, 0x58, - 0x82, 0xfa, 0x0b, 0xd4, 0xc7, 0x91, 0x0e, 0x94, 0xe4, 0x96, 0x81, 0xfd, 0x1b, 0x17, 0x73, 0x58, - 0x11, 0x8b, 0x50, 0xdb, 0x89, 0x22, 0x94, 0xde, 0xe9, 0x0d, 0x6f, 0x89, 0x06, 0x2c, 0xf4, 0x7c, - 0x74, 0xc7, 0x04, 0x68, 0x8b, 0x50, 0xed, 0xa9, 0xcb, 0xcb, 0x40, 0xf3, 0x15, 0xa3, 0xfc, 0x3c, - 0xc5, 0x78, 0xc2, 0xdb, 0x46, 0x60, 0x20, 0x03, 0xdd, 0xf3, 0x9d, 0x40, 0xf2, 0x8e, 0x11, 0xe8, - 0x4b, 0x6f, 0x37, 0x54, 0xee, 0x98, 0xaf, 0x6e, 0xbe, 0xb1, 0xa0, 0x36, 0x5d, 0xaa, 0xa8, 0x42, - 0xe9, 0xf8, 0x80, 0x0c, 0xb6, 0x60, 0x69, 0x20, 0x35, 0xc6, 0xd2, 0x09, 0xfb, 0x66, 0xa3, 0xe4, - 0x94, 0xa8, 0xbe, 0xa4, 0x9d, 0x07, 0x72, 0x94, 0x53, 0x25, 0x23, 0xb4, 0xeb, 0x78, 0x47, 0x4a, - 0xba, 0x48, 0xae, 0x39, 0x2c, 0x9e, 0x49, 0x27, 0xd5, 0xbe, 0x8a, 0x83, 0xd7, 0xe8, 0x91, 0xf1, - 0x0e, 0xb4, 0x06, 0x32, 0x49, 0x87, 0xc3, 0xc0, 0x0d, 0x50, 0xea, 0xbd, 0x54, 0x7a, 0x09, 0x05, - 0x10, 0xd0, 0x3c, 0x93, 0x63, 0xa9, 0xae, 0x65, 0xf1, 0xc2, 0x79, 0xd5, 0x5c, 0xdd, 0x75, 0x12, - 0xbc, 0x3b, 0x01, 0x8d, 0xa6, 0xa1, 0x67, 0x53, 0x86, 0xf4, 0x25, 0x84, 0x61, 0x0a, 0x81, 0x1d, - 0xd7, 0x55, 0xa9, 0xd4, 0x7c, 0x44, 0x5f, 0x82, 0xe7, 0xfc, 0x9c, 0x03, 0x5f, 0xfc, 0x07, 0x1d, - 0xc3, 0xde, 0x77, 0x11, 0x88, 0x2e, 0xb4, 0xef, 0x95, 0x10, 0x13, 0xfe, 0x92, 0xbc, 0xf0, 0x7d, - 0x75, 0x55, 0x4c, 0xe8, 0x4b, 0x1d, 0xe8, 0x09, 0xff, 0xc0, 0x68, 0xc2, 0xf2, 0x2d, 0xbd, 0x1f, - 0xab, 0x34, 0xe2, 0x1f, 0x99, 0x58, 0x05, 0x71, 0xcb, 0x9e, 0xc4, 0x2a, 0x52, 0x89, 0x13, 0xf2, - 0x4f, 0x8c, 0x8c, 0xb6, 0xa8, 0xf0, 0x2c, 0x8d, 0xc2, 0xc0, 0x75, 0x34, 0xe6, 0x0d, 0x9f, 0xa7, - 0x0d, 0x33, 0xfe, 0x10, 0x2f, 0x2f, 0x30, 0xe6, 0x5f, 0x18, 0x79, 0x6d, 0xcf, 0x17, 0x66, 0x5a, - 0x5f, 0x59, 0xe1, 0x68, 0x56, 0x3a, 0x57, 0x1a, 0xf9, 0xb7, 0x29, 0x3d, 0x90, 0xd9, 0xab, 0x2d, - 0x84, 0xbe, 0x33, 0xb1, 0x02, 0xcd, 0x5b, 0x3a, 0xbb, 0xfb, 0x83, 0x89, 0xff, 0xa1, 0x73, 0x87, - 0xa4, 0x25, 0x9f, 0x98, 0xc7, 0xca, 0x7f, 0xb2, 0x8b, 0x6a, 0xf6, 0xd7, 0xf3, 0xe4, 0x57, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x9d, 0x98, 0x5a, 0xc8, 0x8f, 0x04, 0x00, 0x00, + 0x10, 0xbd, 0xb2, 0x65, 0x63, 0xb7, 0xc1, 0x8c, 0x07, 0xfb, 0xa2, 0x7b, 0x2b, 0x0b, 0x8a, 0x54, + 0xa5, 0x28, 0x16, 0x24, 0x45, 0x56, 0x59, 0x82, 0x63, 0x28, 0x17, 0x05, 0x38, 0xe2, 0xb1, 0x17, + 0x52, 0xdb, 0x52, 0x2c, 0xcf, 0x28, 0xd2, 0x08, 0x70, 0xbe, 0x20, 0xdf, 0x92, 0x1f, 0xc8, 0x17, + 0x64, 0x91, 0xf7, 0xe3, 0x8b, 0x32, 0x33, 0x92, 0x6c, 0x43, 0x16, 0x59, 0x64, 0x43, 0x4d, 0x9f, + 0x33, 0x7d, 0xfa, 0x9c, 0xd6, 0x60, 0x68, 0x89, 0x69, 0x84, 0xc9, 0x63, 0xfd, 0x77, 0x27, 0x8a, + 0xb9, 0xe0, 0xb4, 0xa2, 0x8b, 0xcd, 0x77, 0x06, 0x2c, 0xd9, 0xf8, 0x2a, 0xc5, 0x44, 0xd0, 0x47, + 0x60, 0x2a, 0xd0, 0x32, 0x36, 0x8c, 0xad, 0xe6, 0x2e, 0xdd, 0xc9, 0xae, 0x1f, 0x63, 0x92, 0x38, + 0x23, 0x3c, 0x97, 0x85, 0xad, 0x79, 0x4a, 0xc1, 0xf4, 0x1c, 0xe1, 0x58, 0x25, 0x79, 0x6f, 0xd9, + 0xd6, 0x67, 0x4a, 0xa0, 0x3c, 0xc6, 0xa9, 0x55, 0x96, 0x50, 0xdd, 0x56, 0x47, 0xda, 0x86, 0xca, + 0xb5, 0x13, 0xa6, 0x68, 0x99, 0x1a, 0xcb, 0x0a, 0xfa, 0x04, 0x40, 0x1e, 0x02, 0xd9, 0xc3, 0xe3, + 0xc4, 0xaa, 0x6c, 0x94, 0xb7, 0x1a, 0xbb, 0x24, 0x9f, 0x74, 0x59, 0x10, 0xf6, 0xc2, 0x1d, 0xfa, + 0x2f, 0x54, 0x7d, 0x0c, 0x46, 0xbe, 0xb0, 0xaa, 0x52, 0xc8, 0xb4, 0xf3, 0x6a, 0xf3, 0xbd, 0x01, + 0x35, 0x1b, 0x93, 0x88, 0xb3, 0x04, 0xff, 0xca, 0xfa, 0x43, 0x30, 0x5d, 0xee, 0xa1, 0xf6, 0xde, + 0xdc, 0x5d, 0xcd, 0x7b, 0xbb, 0x12, 0xca, 0x1a, 0x15, 0xa9, 0xd2, 0x60, 0x1c, 0xf3, 0xb8, 0x48, + 0xa3, 0x0b, 0x95, 0x3a, 0xe4, 0x23, 0x19, 0x43, 0xa7, 0x96, 0xc7, 0x7b, 0xf9, 0xaa, 0x7f, 0xce, + 0xb7, 0xf9, 0x0c, 0xea, 0x33, 0x42, 0x85, 0x8d, 0xd2, 0xab, 0x23, 0xb9, 0x49, 0x43, 0x3b, 0xcc, + 0x2b, 0x35, 0x3e, 0xe2, 0x37, 0x18, 0x6b, 0xe3, 0xa6, 0x9d, 0x15, 0xdb, 0x6f, 0x0d, 0x68, 0x2c, + 0x64, 0xa4, 0xab, 0xd0, 0x38, 0x49, 0xc3, 0x30, 0x87, 0xc8, 0x3f, 0xb4, 0x06, 0x66, 0xcf, 0xf5, + 0x39, 0x31, 0x68, 0x1d, 0x2a, 0x07, 0x61, 0x9a, 0xf8, 0xa4, 0xa4, 0xc0, 0x3e, 0x1b, 0x72, 0x52, + 0xa6, 0x2b, 0x50, 0x3f, 0x43, 0x71, 0x1a, 0x89, 0x80, 0x33, 0x62, 0xaa, 0xb2, 0x77, 0xeb, 0x62, + 0x56, 0x56, 0xe8, 0x32, 0xd4, 0xf6, 0xa2, 0x08, 0x99, 0x77, 0x7e, 0x4b, 0x5a, 0xb4, 0x01, 0x4b, + 0x5d, 0x1f, 0xdd, 0xb1, 0x2c, 0xe4, 0x16, 0xa1, 0xda, 0xe5, 0x93, 0x49, 0x20, 0xc8, 0x9a, 0x52, + 0x7e, 0x91, 0x62, 0x3c, 0x25, 0x6d, 0x25, 0xd0, 0x67, 0x81, 0xe8, 0xfa, 0x4e, 0xc0, 0x48, 0x47, + 0x09, 0xf4, 0x98, 0xb7, 0x1f, 0x72, 0x77, 0x4c, 0xd6, 0xb7, 0xdf, 0x54, 0xa0, 0x56, 0x2c, 0x95, + 0x56, 0xa1, 0x74, 0x7a, 0x24, 0x0d, 0xb6, 0x60, 0xa5, 0xcf, 0x04, 0xc6, 0xcc, 0x09, 0x7b, 0x6a, + 0xa3, 0xd2, 0xa9, 0x84, 0x7a, 0x4c, 0xee, 0x3c, 0x60, 0xa3, 0x0c, 0x2a, 0x29, 0xa1, 0x7d, 0xc7, + 0x3b, 0xe1, 0xcc, 0x45, 0xe9, 0x9a, 0xc0, 0xf2, 0x05, 0x73, 0x52, 0xe1, 0xf3, 0x38, 0x78, 0x8d, + 0x9e, 0x34, 0xde, 0x81, 0x56, 0x9f, 0x25, 0xe9, 0x70, 0x18, 0xb8, 0x01, 0x32, 0x71, 0x90, 0x32, + 0x2f, 0x91, 0x01, 0x28, 0x34, 0x2f, 0xd8, 0x98, 0xf1, 0x1b, 0x96, 0xbf, 0x70, 0x52, 0xa5, 0x16, + 0xb4, 0xf7, 0x9d, 0x04, 0x9f, 0xa7, 0x51, 0x18, 0xb8, 0x8e, 0xc0, 0x3d, 0xcf, 0x8b, 0xe5, 0xba, + 0x08, 0x2a, 0x11, 0xc5, 0xdc, 0x9d, 0x3d, 0x2c, 0x1a, 0xee, 0xe8, 0x23, 0x26, 0x64, 0x44, 0xff, + 0x83, 0xce, 0x6f, 0x8c, 0x9e, 0xec, 0xd3, 0x07, 0x60, 0xdd, 0xa7, 0x0e, 0x9d, 0x64, 0x10, 0x07, + 0x32, 0x40, 0x20, 0x3f, 0x32, 0xcd, 0x58, 0xfd, 0x0a, 0x0a, 0x07, 0x2f, 0x0b, 0x07, 0x05, 0x3e, + 0xe1, 0x29, 0x13, 0x64, 0x7c, 0x0f, 0x1e, 0xe8, 0x07, 0x41, 0x42, 0xba, 0x0e, 0x6b, 0x0b, 0xf0, + 0x99, 0x4a, 0xa8, 0xf6, 0x33, 0x99, 0x3b, 0xce, 0x88, 0x60, 0xc4, 0x1c, 0x91, 0xc6, 0x48, 0x58, + 0xa1, 0x94, 0x2f, 0x25, 0x57, 0xe2, 0x12, 0x26, 0x87, 0xfc, 0x3a, 0x47, 0x7b, 0x4c, 0x04, 0x62, + 0x4a, 0x3e, 0x18, 0xf2, 0xcd, 0xad, 0xce, 0xe1, 0xc3, 0x98, 0xa7, 0x11, 0xf9, 0x68, 0xc8, 0xb1, + 0x74, 0x8e, 0x0e, 0x62, 0x1e, 0xf1, 0xc4, 0x09, 0xc9, 0x27, 0x43, 0xa6, 0x6a, 0x49, 0x62, 0xb6, + 0xd8, 0xac, 0xe1, 0x73, 0xd1, 0x30, 0xc3, 0x8f, 0x71, 0x72, 0x85, 0x31, 0xf9, 0x62, 0xc8, 0xfd, + 0xb5, 0x17, 0x89, 0x99, 0xd6, 0x57, 0x23, 0x77, 0x34, 0xa3, 0x2e, 0xb9, 0x40, 0xf2, 0xad, 0x80, + 0xf3, 0x60, 0xb9, 0xd0, 0x77, 0x83, 0xae, 0x41, 0x73, 0x0e, 0xeb, 0xbb, 0x3f, 0x0c, 0xfa, 0x3f, + 0x74, 0xee, 0x80, 0xf2, 0x93, 0x0e, 0xd4, 0x3f, 0x0d, 0xf9, 0x69, 0x5c, 0x55, 0xf5, 0x4f, 0xe0, + 0xd3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x92, 0xa5, 0x2c, 0x76, 0x17, 0x05, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 8716e6cb..5a7a226f 100644 --- a/types/types.proto +++ b/types/types.proto @@ -38,12 +38,17 @@ enum CodeType { UnknownRequest = 6; // Reserved for basecoin, 100 ~ 199 - BaseEncodingError = 101; - BaseBadNonce = 102; - BaseUnknownAccount = 103; - BaseUnauthorized = 104; - BaseInsufficientFunds = 105; - BaseInsufficientFees = 106; + BaseDuplicateAddress = 101; + BaseEncodingError = 102; + BaseInsufficientFees = 103; + BaseInsufficientFunds = 104; + BaseInsufficientGasPrice = 105; + BaseInvalidAddress = 106; + BaseInvalidAmount = 107; + BaseInvalidPubKey = 108; + BaseInvalidSequence = 109; + BaseInvalidSignature = 110; + BaseUnknownPubKey = 111; // Reserved for governance, 200 ~ 299 GovUnknownEntity = 201; From 5a3975d54a695387362c07d0b2906ac2e60ef797 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 22 Mar 2016 15:18:03 -0700 Subject: [PATCH 094/545] Add wire expression support --- cmd/tmsp-cli/tmsp-cli.go | 50 +++++++++++++++------------------------- types/result.go | 2 ++ 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 0b1a4ad8..986a4dd8 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "encoding/hex" "errors" "fmt" "io" @@ -12,6 +11,7 @@ import ( "github.com/codegangsta/cli" . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire/expr" "github.com/tendermint/tmsp/types" ) @@ -199,18 +199,14 @@ func cmdAppendTx(c *cli.Context) { fmt.Println("append_tx takes 1 argument") return } - txString := args[0] - tx := []byte(txString) - if len(txString) > 2 && strings.HasPrefix(txString, "0x") { - var err error - tx, err = hex.DecodeString(txString[2:]) - if err != nil { - fmt.Println(err.Error()) - return - } + txExprString := c.Args()[0] + txBytes, err := expr.Compile(txExprString) + if err != nil { + fmt.Println(err.Error()) + return } - res, err := makeRequest(conn, types.RequestAppendTx(tx)) + res, err := makeRequest(conn, types.RequestAppendTx(txBytes)) if err != nil { fmt.Println(err.Error()) return @@ -225,18 +221,14 @@ func cmdCheckTx(c *cli.Context) { fmt.Println("check_tx takes 1 argument") return } - txString := args[0] - tx := []byte(txString) - if len(txString) > 2 && strings.HasPrefix(txString, "0x") { - var err error - tx, err = hex.DecodeString(txString[2:]) - if err != nil { - fmt.Println(err.Error()) - return - } + txExprString := c.Args()[0] + txBytes, err := expr.Compile(txExprString) + if err != nil { + fmt.Println(err.Error()) + return } - res, err := makeRequest(conn, types.RequestCheckTx(tx)) + res, err := makeRequest(conn, types.RequestCheckTx(txBytes)) if err != nil { fmt.Println(err.Error()) return @@ -261,18 +253,14 @@ func cmdQuery(c *cli.Context) { fmt.Println("query takes 1 argument") return } - queryString := args[0] - query := []byte(queryString) - if len(queryString) > 2 && strings.HasPrefix(queryString, "0x") { - var err error - query, err = hex.DecodeString(queryString[2:]) - if err != nil { - fmt.Println(err.Error()) - return - } + queryExprString := args[0] + queryBytes, err := expr.Compile(queryExprString) + if err != nil { + fmt.Println(err.Error()) + return } - res, err := makeRequest(conn, types.RequestQuery(query)) + res, err := makeRequest(conn, types.RequestQuery(queryBytes)) if err != nil { fmt.Println(err.Error()) return diff --git a/types/result.go b/types/result.go index 305fe928..3b403d8d 100644 --- a/types/result.go +++ b/types/result.go @@ -4,6 +4,7 @@ import ( "fmt" ) +// CONTRACT: a zero Result is OK. type Result struct { Code CodeType Data []byte @@ -60,6 +61,7 @@ func (res Result) SetData(data []byte) Result { //---------------------------------------- +// NOTE: if data == nil and log == "", same as zero Result. func NewResultOK(data []byte, log string) Result { return Result{ Code: CodeType_OK, From 6785b9a3b60ac8f3c22b96f54d08a19e854fbe8a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 23 Mar 2016 02:50:29 -0700 Subject: [PATCH 095/545] CommitSync returns tmsp.Result --- client/client.go | 32 ++++++++++++++++---------------- example/counter/counter.go | 10 +++++----- example/dummy/dummy.go | 10 +++++----- example/nil/nil_app.go | 4 ++-- server/server.go | 4 ++-- tests/test_counter.go | 25 ++++++++++++++----------- types/application.go | 2 +- types/errors.go | 24 ++++++++++++++++++++++++ types/messages.go | 17 +++++++++-------- types/result.go | 4 ++++ 10 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 types/errors.go diff --git a/client/client.go b/client/client.go index 02a55710..ceec1143 100644 --- a/client/client.go +++ b/client/client.go @@ -248,44 +248,44 @@ func (cli *Client) SetOptionSync(key string, value string) (log string, err erro return reqres.Response.Log, nil } -func (cli *Client) AppendTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { +func (cli *Client) AppendTxSync(tx []byte) (res types.Result) { reqres := cli.queueRequest(types.RequestAppendTx(tx)) cli.FlushSync() if cli.err != nil { - return types.CodeType_InternalError, nil, "", cli.err + return types.ErrInternalError.SetLog(cli.err.Error()) } - res := reqres.Response - return res.Code, res.Data, res.Log, nil + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *Client) CheckTxSync(tx []byte) (code types.CodeType, result []byte, log string, err error) { +func (cli *Client) CheckTxSync(tx []byte) (res types.Result) { reqres := cli.queueRequest(types.RequestCheckTx(tx)) cli.FlushSync() if cli.err != nil { - return types.CodeType_InternalError, nil, "", cli.err + return types.ErrInternalError.SetLog(cli.err.Error()) } - res := reqres.Response - return res.Code, res.Data, res.Log, nil + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *Client) CommitSync() (hash []byte, log string, err error) { +func (cli *Client) CommitSync() (res types.Result) { reqres := cli.queueRequest(types.RequestCommit()) cli.FlushSync() if cli.err != nil { - return nil, "", cli.err + return types.ErrInternalError.SetLog(cli.err.Error()) } - res := reqres.Response - return res.Data, res.Log, nil + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *Client) QuerySync(query []byte) (code types.CodeType, result []byte, log string, err error) { +func (cli *Client) QuerySync(query []byte) (res types.Result) { reqres := cli.queueRequest(types.RequestQuery(query)) cli.FlushSync() if cli.err != nil { - return types.CodeType_InternalError, nil, "", cli.err + return types.ErrInternalError.SetLog(cli.err.Error()) } - res := reqres.Response - return res.Code, res.Data, res.Log, nil + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } func (cli *Client) InitChainSync(validators []*types.Validator) (err error) { diff --git a/example/counter/counter.go b/example/counter/counter.go index d6b9da2e..711ddc3f 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -43,7 +43,7 @@ func (app *CounterApplication) AppendTx(tx []byte) types.Result { } } app.txCount += 1 - return types.NewResultOK(nil, "") + return types.OK } func (app *CounterApplication) CheckTx(tx []byte) types.Result { @@ -59,18 +59,18 @@ func (app *CounterApplication) CheckTx(tx []byte) types.Result { } } } - return types.NewResultOK(nil, "") + return types.OK } -func (app *CounterApplication) Commit() (hash []byte, log string) { +func (app *CounterApplication) Commit() types.Result { app.hashCount += 1 if app.txCount == 0 { - return nil, "" + return types.OK } else { hash := make([]byte, 8) binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return hash, "" + return types.NewResultOK(hash, "") } } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index e2d4a09e..3fa237f0 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -35,16 +35,16 @@ func (app *DummyApplication) AppendTx(tx []byte) types.Result { } else { app.state.Set(tx, tx) } - return types.NewResultOK(nil, "") + return types.OK } func (app *DummyApplication) CheckTx(tx []byte) types.Result { - return types.NewResultOK(nil, "") + return types.OK } -func (app *DummyApplication) Commit() (hash []byte, log string) { - hash = app.state.Hash() - return hash, "" +func (app *DummyApplication) Commit() types.Result { + hash := app.state.Hash() + return types.NewResultOK(hash, "") } func (app *DummyApplication) Query(query []byte) types.Result { diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 6233ea5e..40474a9f 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -27,8 +27,8 @@ func (app *NilApplication) CheckTx(tx []byte) types.Result { return types.NewResultOK(nil, "") } -func (app *NilApplication) Commit() (hash []byte, log string) { - return []byte("nil"), "" +func (app *NilApplication) Commit() types.Result { + return types.NewResultOK([]byte("nil"), "") } func (app *NilApplication) Query(query []byte) types.Result { diff --git a/server/server.go b/server/server.go index cf8cf338..e64ab30b 100644 --- a/server/server.go +++ b/server/server.go @@ -143,8 +143,8 @@ func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Respo res := s.app.CheckTx(req.Data) responses <- types.ResponseCheckTx(res.Code, res.Data, res.Log) case types.MessageType_Commit: - hash, logStr := s.app.Commit() - responses <- types.ResponseCommit(hash, logStr) + res := s.app.Commit() + responses <- types.ResponseCommit(res.Code, res.Data, res.Log) case types.MessageType_Query: res := s.app.Query(req.Data) responses <- types.ResponseQuery(res.Code, res.Data, res.Log) diff --git a/tests/test_counter.go b/tests/test_counter.go index 4c01d865..91b23f39 100644 --- a/tests/test_counter.go +++ b/tests/test_counter.go @@ -85,20 +85,22 @@ func setOption(client *tmspcli.Client, key, value string) { } func commit(client *tmspcli.Client, hashExp []byte) { - hash, log, err := client.CommitSync() - if err != nil { - panic(Fmt("committing %v\nlog: %v", err, log)) + res := client.CommitSync() + _, data, log := res.Code, res.Data, res.Log + if res.IsErr() { + panic(Fmt("committing %v\nlog: %v", log)) } - if !bytes.Equal(hash, hashExp) { + if !bytes.Equal(res.Data, hashExp) { panic(Fmt("Commit hash was unexpected. Got %X expected %X", - hash, hashExp)) + data, hashExp)) } } func appendTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - code, data, log, err := client.AppendTxSync(txBytes) - if err != nil { - panic(Fmt("appending tx %X: %v\nlog: %v", txBytes, err, log)) + res := client.AppendTxSync(txBytes) + code, data, log := res.Code, res.Data, res.Log + if res.IsErr() { + panic(Fmt("appending tx %X: %v\nlog: %v", txBytes, log)) } if code != codeExp { panic(Fmt("AppendTx response code was unexpected. Got %v expected %v. Log: %v", @@ -111,9 +113,10 @@ func appendTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, da } func checkTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - code, data, log, err := client.CheckTxSync(txBytes) - if err != nil { - panic(Fmt("checking tx %X: %v\nlog: %v", txBytes, err, log)) + 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)) } if code != codeExp { panic(Fmt("CheckTx response code was unexpected. Got %v expected %v. Log: %v", diff --git a/types/application.go b/types/application.go index 1d65ba8b..d8ea4891 100644 --- a/types/application.go +++ b/types/application.go @@ -16,7 +16,7 @@ type Application interface { CheckTx(tx []byte) Result // Return the application Merkle root hash - Commit() (hash []byte, log string) + Commit() Result // Query for state Query(query []byte) Result diff --git a/types/errors.go b/types/errors.go new file mode 100644 index 00000000..814b186e --- /dev/null +++ b/types/errors.go @@ -0,0 +1,24 @@ +package types + +var ( + OK = NewResultOK(nil, "") + + ErrInternalError = NewError(CodeType_InternalError, "Internal error") + ErrEncodingError = NewError(CodeType_EncodingError, "Encoding error") + ErrBadNonce = NewError(CodeType_BadNonce, "Error bad nonce") + ErrUnauthorized = NewError(CodeType_Unauthorized, "Unauthorized") + ErrInsufficientFunds = NewError(CodeType_InsufficientFunds, "Insufficient funds") + ErrUnknownRequest = NewError(CodeType_UnknownRequest, "Unknown request") + + ErrBaseDuplicateAddress = NewError(CodeType_BaseDuplicateAddress, "Error duplicate address") + ErrBaseEncodingError = NewError(CodeType_BaseEncodingError, "Error encoding error") + ErrBaseInsufficientFees = NewError(CodeType_BaseInsufficientFees, "Error insufficient fees") + ErrBaseInsufficientFunds = NewError(CodeType_BaseInsufficientFunds, "Error insufficient funds") + ErrBaseInsufficientGasPrice = NewError(CodeType_BaseInsufficientGasPrice, "Error insufficient gas price") + ErrBaseInvalidAddress = NewError(CodeType_BaseInvalidAddress, "Error invalid address") + ErrBaseInvalidAmount = NewError(CodeType_BaseInvalidAmount, "Error invalid amount") + ErrBaseInvalidPubKey = NewError(CodeType_BaseInvalidPubKey, "Error invalid pubkey") + ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error invalid sequence") + ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error invalid signature") + ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error unknown pubkey") +) diff --git a/types/messages.go b/types/messages.go index 4a35c343..af0a7109 100644 --- a/types/messages.go +++ b/types/messages.go @@ -111,37 +111,38 @@ func ResponseSetOption(log string) *Response { } } -func ResponseAppendTx(code CodeType, result []byte, log string) *Response { +func ResponseAppendTx(code CodeType, data []byte, log string) *Response { return &Response{ Type: MessageType_AppendTx, Code: code, - Data: result, + Data: data, Log: log, } } -func ResponseCheckTx(code CodeType, result []byte, log string) *Response { +func ResponseCheckTx(code CodeType, data []byte, log string) *Response { return &Response{ Type: MessageType_CheckTx, Code: code, - Data: result, + Data: data, Log: log, } } -func ResponseCommit(hash []byte, log string) *Response { +func ResponseCommit(code CodeType, data []byte, log string) *Response { return &Response{ Type: MessageType_Commit, - Data: hash, + Code: code, + Data: data, Log: log, } } -func ResponseQuery(code CodeType, result []byte, log string) *Response { +func ResponseQuery(code CodeType, data []byte, log string) *Response { return &Response{ Type: MessageType_Query, Code: code, - Data: result, + Data: data, Log: log, } } diff --git a/types/result.go b/types/result.go index 3b403d8d..e5cb6bbd 100644 --- a/types/result.go +++ b/types/result.go @@ -23,6 +23,10 @@ func (res Result) IsOK() bool { return res.Code == CodeType_OK } +func (res Result) IsErr() bool { + return res.Code != CodeType_OK +} + func (res Result) Error() string { return fmt.Sprintf("TMSP error code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) } From 83fc4fc3b6c7a4603319aca5d9a1ea85d7ca576f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 23 Mar 2016 21:07:03 -0700 Subject: [PATCH 096/545] Allow late connecting --- client/client.go | 91 +++++++++++++++++++++++++++---------------- tests/test_counter.go | 2 +- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/client/client.go b/client/client.go index ceec1143..19de9e00 100644 --- a/client/client.go +++ b/client/client.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "sync" + "time" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" @@ -25,47 +26,70 @@ type Client struct { QuitService sync.Mutex // [EB]: is this even used? - reqQueue chan *ReqRes - flushTimer *ThrottleTimer + reqQueue chan *ReqRes + flushTimer *ThrottleTimer + mustConnect bool - mtx sync.Mutex - addr string - conn net.Conn - bufWriter *bufio.Writer - err error - reqSent *list.List - resCb func(*types.Request, *types.Response) // listens to all callbacks + mtx sync.Mutex + addr string + conn net.Conn + err error + reqSent *list.List + resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewClient(addr string) (*Client, error) { - conn, err := Connect(addr) - if err != nil { - return nil, err - } +func NewClient(addr string, mustConnect bool) (*Client, error) { cli := &Client{ - reqQueue: make(chan *ReqRes, reqQueueSize), - flushTimer: NewThrottleTimer("Client", flushThrottleMS), + reqQueue: make(chan *ReqRes, reqQueueSize), + flushTimer: NewThrottleTimer("Client", flushThrottleMS), + mustConnect: mustConnect, - conn: conn, - bufWriter: bufio.NewWriter(conn), - reqSent: list.New(), - resCb: nil, + addr: addr, + reqSent: list.New(), + resCb: nil, } cli.QuitService = *NewQuitService(nil, "Client", cli) - cli.Start() // Just start it, it's confusing for callers to remember to start. - return cli, nil + _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. + if mustConnect { + return nil, err + } else { + return cli, nil + } } -func (cli *Client) OnStart() error { +func (cli *Client) OnStart() (err error) { cli.QuitService.OnStart() - go cli.sendRequestsRoutine() - go cli.recvResponseRoutine() - return nil + doneCh := make(chan struct{}) + go func() { + RETRY_LOOP: + for { + conn, err_ := Connect(cli.addr) + if err_ != nil { + if cli.mustConnect { + err = err_ // OnStart() will return this. + close(doneCh) + return + } else { + fmt.Printf("tmsp.Client failed to connect to %v. Retrying...\n", cli.addr) + time.Sleep(time.Second * 3) + continue RETRY_LOOP + } + } + go cli.sendRequestsRoutine(conn) + go cli.recvResponseRoutine(conn) + close(doneCh) // OnStart() will return no error. + return + } + }() + <-doneCh + return // err } func (cli *Client) OnStop() { cli.QuitService.OnStop() - cli.conn.Close() + if cli.conn != nil { + cli.conn.Close() + } } // Set listener for all responses @@ -78,7 +102,7 @@ func (cli *Client) SetResponseCallback(resCb Callback) { func (cli *Client) StopForError(err error) { cli.mtx.Lock() - // log.Error("Stopping Client for error.", "error", err) + fmt.Printf("Stopping tmsp.Client for error: %v\n", err.Error()) if cli.err == nil { cli.err = err } @@ -94,7 +118,8 @@ func (cli *Client) Error() error { //---------------------------------------- -func (cli *Client) sendRequestsRoutine() { +func (cli *Client) sendRequestsRoutine(conn net.Conn) { + w := bufio.NewWriter(conn) for { select { case <-cli.flushTimer.Ch: @@ -107,14 +132,14 @@ func (cli *Client) sendRequestsRoutine() { return case reqres := <-cli.reqQueue: cli.willSendReq(reqres) - err := types.WriteMessage(reqres.Request, cli.bufWriter) + err := types.WriteMessage(reqres.Request, w) if err != nil { cli.StopForError(err) return } // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) if reqres.Request.Type == types.MessageType_Flush { - err = cli.bufWriter.Flush() + err = w.Flush() if err != nil { cli.StopForError(err) return @@ -124,8 +149,8 @@ func (cli *Client) sendRequestsRoutine() { } } -func (cli *Client) recvResponseRoutine() { - r := bufio.NewReader(cli.conn) // Buffer reads +func (cli *Client) recvResponseRoutine(conn net.Conn) { + r := bufio.NewReader(conn) // Buffer reads for { var res = &types.Response{} err := types.ReadMessage(r, res) diff --git a/tests/test_counter.go b/tests/test_counter.go index 91b23f39..6ed8f4f4 100644 --- a/tests/test_counter.go +++ b/tests/test_counter.go @@ -70,7 +70,7 @@ func startApp() *process.Process { func startClient() *tmspcli.Client { // Start client - client, err := tmspcli.NewClient("tcp://127.0.0.1:46658") + client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", true) if err != nil { panic("connecting to counter_app: " + err.Error()) } From 062c33c1096761f142db1eda66479591b65e1e15 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 24 Mar 2016 10:19:48 -0700 Subject: [PATCH 097/545] TMSP Client is an interface --- client/client.go | 375 ++++------------------------------------ client/local_client.go | 193 +++++++++++++++++++++ client/remote_client.go | 370 +++++++++++++++++++++++++++++++++++++++ tests/test_counter.go | 17 +- 4 files changed, 601 insertions(+), 354 deletions(-) create mode 100644 client/local_client.go create mode 100644 client/remote_client.go diff --git a/client/client.go b/client/client.go index 19de9e00..acd99f60 100644 --- a/client/client.go +++ b/client/client.go @@ -1,360 +1,43 @@ package tmspcli import ( - "bufio" - "container/list" - "errors" - "fmt" - "net" - "sync" - "time" - - . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" + "sync" ) -const reqQueueSize = 256 // TODO make configurable -const maxResponseSize = 1048576 // 1MB TODO make configurable -const flushThrottleMS = 20 // Don't wait longer than... +type Client interface { + SetResponseCallback(Callback) + Error() error + Stop() bool + + FlushAsync() *ReqRes + EchoAsync(msg string) *ReqRes + InfoAsync() *ReqRes + SetOptionAsync(key string, value string) *ReqRes + AppendTxAsync(tx []byte) *ReqRes + CheckTxAsync(tx []byte) *ReqRes + QueryAsync(tx []byte) *ReqRes + CommitAsync() *ReqRes + + FlushSync() error + EchoSync(msg string) (res types.Result) + InfoSync() (res types.Result) + SetOptionSync(key string, value string) (res types.Result) + AppendTxSync(tx []byte) (res types.Result) + CheckTxSync(tx []byte) (res types.Result) + QuerySync(tx []byte) (res types.Result) + CommitSync() (res types.Result) + + InitChainSync(validators []*types.Validator) (err error) + EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) +} + +//---------------------------------------- type Callback func(*types.Request, *types.Response) -// This is goroutine-safe, but users should beware that -// the application in general is not meant to be interfaced -// with concurrent callers. -type Client struct { - QuitService - sync.Mutex // [EB]: is this even used? - - reqQueue chan *ReqRes - flushTimer *ThrottleTimer - mustConnect bool - - mtx sync.Mutex - addr string - conn net.Conn - err error - reqSent *list.List - resCb func(*types.Request, *types.Response) // listens to all callbacks -} - -func NewClient(addr string, mustConnect bool) (*Client, error) { - cli := &Client{ - reqQueue: make(chan *ReqRes, reqQueueSize), - flushTimer: NewThrottleTimer("Client", flushThrottleMS), - mustConnect: mustConnect, - - addr: addr, - reqSent: list.New(), - resCb: nil, - } - cli.QuitService = *NewQuitService(nil, "Client", cli) - _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. - if mustConnect { - return nil, err - } else { - return cli, nil - } -} - -func (cli *Client) OnStart() (err error) { - cli.QuitService.OnStart() - doneCh := make(chan struct{}) - go func() { - RETRY_LOOP: - for { - conn, err_ := Connect(cli.addr) - if err_ != nil { - if cli.mustConnect { - err = err_ // OnStart() will return this. - close(doneCh) - return - } else { - fmt.Printf("tmsp.Client failed to connect to %v. Retrying...\n", cli.addr) - time.Sleep(time.Second * 3) - continue RETRY_LOOP - } - } - go cli.sendRequestsRoutine(conn) - go cli.recvResponseRoutine(conn) - close(doneCh) // OnStart() will return no error. - return - } - }() - <-doneCh - return // err -} - -func (cli *Client) OnStop() { - cli.QuitService.OnStop() - if cli.conn != nil { - cli.conn.Close() - } -} - -// Set listener for all responses -// NOTE: callback may get internally generated flush responses. -func (cli *Client) SetResponseCallback(resCb Callback) { - cli.mtx.Lock() - defer cli.mtx.Unlock() - cli.resCb = resCb -} - -func (cli *Client) StopForError(err error) { - cli.mtx.Lock() - fmt.Printf("Stopping tmsp.Client for error: %v\n", err.Error()) - if cli.err == nil { - cli.err = err - } - cli.mtx.Unlock() - cli.Stop() -} - -func (cli *Client) Error() error { - cli.mtx.Lock() - defer cli.mtx.Unlock() - return cli.err -} - //---------------------------------------- -func (cli *Client) sendRequestsRoutine(conn net.Conn) { - w := bufio.NewWriter(conn) - for { - select { - case <-cli.flushTimer.Ch: - select { - case cli.reqQueue <- NewReqRes(types.RequestFlush()): - default: - // Probably will fill the buffer, or retry later. - } - case <-cli.QuitService.Quit: - return - case reqres := <-cli.reqQueue: - cli.willSendReq(reqres) - err := types.WriteMessage(reqres.Request, w) - if err != nil { - cli.StopForError(err) - return - } - // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) - if reqres.Request.Type == types.MessageType_Flush { - err = w.Flush() - if err != nil { - cli.StopForError(err) - return - } - } - } - } -} - -func (cli *Client) recvResponseRoutine(conn net.Conn) { - r := bufio.NewReader(conn) // Buffer reads - for { - var res = &types.Response{} - err := types.ReadMessage(r, res) - if err != nil { - cli.StopForError(err) - return - } - switch res.Type { - case types.MessageType_Exception: - // XXX After setting cli.err, release waiters (e.g. reqres.Done()) - cli.StopForError(errors.New(res.Error)) - default: - // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) - err := cli.didRecvResponse(res) - if err != nil { - cli.StopForError(err) - } - } - } -} - -func (cli *Client) willSendReq(reqres *ReqRes) { - cli.mtx.Lock() - defer cli.mtx.Unlock() - cli.reqSent.PushBack(reqres) -} - -func (cli *Client) didRecvResponse(res *types.Response) error { - cli.mtx.Lock() - defer cli.mtx.Unlock() - - // Get the first ReqRes - next := cli.reqSent.Front() - if next == nil { - return fmt.Errorf("Unexpected result type %v when nothing expected", res.Type) - } - reqres := next.Value.(*ReqRes) - if !resMatchesReq(reqres.Request, res) { - return fmt.Errorf("Unexpected result type %v when response to %v expected", - res.Type, reqres.Request.Type) - } - - reqres.Response = res // Set response - reqres.Done() // Release waiters - cli.reqSent.Remove(next) // Pop first item from linked list - - // Notify reqRes listener if set - if cb := reqres.GetCallback(); cb != nil { - cb(res) - } - - // Notify client listener if set - if cli.resCb != nil { - cli.resCb(reqres.Request, res) - } - - return nil -} - -//---------------------------------------- - -func (cli *Client) EchoAsync(msg string) *ReqRes { - return cli.queueRequest(types.RequestEcho(msg)) -} - -func (cli *Client) FlushAsync() *ReqRes { - return cli.queueRequest(types.RequestFlush()) -} - -func (cli *Client) SetOptionAsync(key string, value string) *ReqRes { - return cli.queueRequest(types.RequestSetOption(key, value)) -} - -func (cli *Client) AppendTxAsync(tx []byte) *ReqRes { - return cli.queueRequest(types.RequestAppendTx(tx)) -} - -func (cli *Client) CheckTxAsync(tx []byte) *ReqRes { - return cli.queueRequest(types.RequestCheckTx(tx)) -} - -func (cli *Client) CommitAsync() *ReqRes { - return cli.queueRequest(types.RequestCommit()) -} - -func (cli *Client) QueryAsync(query []byte) *ReqRes { - return cli.queueRequest(types.RequestQuery(query)) -} - -func (cli *Client) InitChainAsync(validators []*types.Validator) *ReqRes { - return cli.queueRequest(types.RequestInitChain(validators)) -} - -func (cli *Client) EndBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.RequestEndBlock(height)) -} - -//---------------------------------------- - -func (cli *Client) FlushSync() error { - cli.queueRequest(types.RequestFlush()).Wait() - return cli.err -} - -func (cli *Client) InfoSync() (info string, err error) { - reqres := cli.queueRequest(types.RequestInfo()) - cli.FlushSync() - if cli.err != nil { - return "", cli.err - } - return string(reqres.Response.Data), nil -} - -func (cli *Client) SetOptionSync(key string, value string) (log string, err error) { - reqres := cli.queueRequest(types.RequestSetOption(key, value)) - cli.FlushSync() - if cli.err != nil { - return "", cli.err - } - return reqres.Response.Log, nil -} - -func (cli *Client) AppendTxSync(tx []byte) (res types.Result) { - reqres := cli.queueRequest(types.RequestAppendTx(tx)) - cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) - } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} -} - -func (cli *Client) CheckTxSync(tx []byte) (res types.Result) { - reqres := cli.queueRequest(types.RequestCheckTx(tx)) - cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) - } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} -} - -func (cli *Client) CommitSync() (res types.Result) { - reqres := cli.queueRequest(types.RequestCommit()) - cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) - } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} -} - -func (cli *Client) QuerySync(query []byte) (res types.Result) { - reqres := cli.queueRequest(types.RequestQuery(query)) - cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) - } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} -} - -func (cli *Client) InitChainSync(validators []*types.Validator) (err error) { - cli.queueRequest(types.RequestInitChain(validators)) - cli.FlushSync() - if cli.err != nil { - return cli.err - } - return nil -} - -func (cli *Client) EndBlockSync(height uint64) (validators []*types.Validator, err error) { - reqres := cli.queueRequest(types.RequestEndBlock(height)) - cli.FlushSync() - if cli.err != nil { - return nil, cli.err - } - return reqres.Response.Validators, nil -} - -//---------------------------------------- - -func (cli *Client) queueRequest(req *types.Request) *ReqRes { - reqres := NewReqRes(req) - // TODO: set cli.err if reqQueue times out - cli.reqQueue <- reqres - - // Maybe auto-flush, or unset auto-flush - switch req.Type { - case types.MessageType_Flush: - cli.flushTimer.Unset() - default: - cli.flushTimer.Set() - } - - return reqres -} - -//---------------------------------------- - -func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { - return req.Type == res.Type -} - type ReqRes struct { *types.Request *sync.WaitGroup diff --git a/client/local_client.go b/client/local_client.go new file mode 100644 index 00000000..b14164f8 --- /dev/null +++ b/client/local_client.go @@ -0,0 +1,193 @@ +package tmspcli + +import ( + types "github.com/tendermint/tmsp/types" + "sync" +) + +type localClient struct { + mtx *sync.Mutex + types.Application + Callback +} + +func NewLocalClient(mtx *sync.Mutex, app types.Application) *localClient { + if mtx == nil { + mtx = new(sync.Mutex) + } + return &localClient{ + mtx: mtx, + Application: app, + } +} + +func (app *localClient) SetResponseCallback(cb Callback) { + app.mtx.Lock() + defer app.mtx.Unlock() + app.Callback = cb +} + +// TODO: change types.Application to include Error()? +func (app *localClient) Error() error { + return nil +} + +func (app *localClient) Stop() bool { + return true +} + +func (app *localClient) FlushAsync() *ReqRes { + // Do nothing + return newLocalReqRes(types.RequestFlush(), nil) +} + +func (app *localClient) EchoAsync(msg string) *ReqRes { + return app.callback( + types.RequestEcho(msg), + types.ResponseEcho(msg), + ) +} + +func (app *localClient) InfoAsync() *ReqRes { + app.mtx.Lock() + info := app.Application.Info() + app.mtx.Unlock() + return app.callback( + types.RequestInfo(), + types.ResponseInfo(info), + ) +} + +func (app *localClient) SetOptionAsync(key string, value string) *ReqRes { + app.mtx.Lock() + log := app.Application.SetOption(key, value) + app.mtx.Unlock() + return app.callback( + types.RequestSetOption(key, value), + types.ResponseSetOption(log), + ) +} + +func (app *localClient) AppendTxAsync(tx []byte) *ReqRes { + app.mtx.Lock() + res := app.Application.AppendTx(tx) + app.mtx.Unlock() + return app.callback( + types.RequestAppendTx(tx), + types.ResponseAppendTx(res.Code, res.Data, res.Log), + ) +} + +func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { + app.mtx.Lock() + res := app.Application.CheckTx(tx) + app.mtx.Unlock() + return app.callback( + types.RequestCheckTx(tx), + types.ResponseCheckTx(res.Code, res.Data, res.Log), + ) +} + +func (app *localClient) QueryAsync(tx []byte) *ReqRes { + app.mtx.Lock() + res := app.Application.Query(tx) + app.mtx.Unlock() + return app.callback( + types.RequestQuery(tx), + types.ResponseQuery(res.Code, res.Data, res.Log), + ) +} + +func (app *localClient) CommitAsync() *ReqRes { + app.mtx.Lock() + res := app.Application.Commit() + app.mtx.Unlock() + return app.callback( + types.RequestCommit(), + types.ResponseCommit(res.Code, res.Data, res.Log), + ) +} + +//------------------------------------------------------- + +func (app *localClient) FlushSync() error { + return nil +} + +func (app *localClient) EchoSync(msg string) (res types.Result) { + return types.OK.SetData([]byte(msg)) +} + +func (app *localClient) InfoSync() (res types.Result) { + app.mtx.Lock() + info := app.Application.Info() + app.mtx.Unlock() + return types.OK.SetData([]byte(info)) +} + +func (app *localClient) SetOptionSync(key string, value string) (res types.Result) { + app.mtx.Lock() + log := app.Application.SetOption(key, value) + app.mtx.Unlock() + return types.OK.SetLog(log) +} + +func (app *localClient) AppendTxSync(tx []byte) (res types.Result) { + app.mtx.Lock() + res = app.Application.AppendTx(tx) + app.mtx.Unlock() + return res +} + +func (app *localClient) CheckTxSync(tx []byte) (res types.Result) { + app.mtx.Lock() + res = app.Application.CheckTx(tx) + app.mtx.Unlock() + return res +} + +func (app *localClient) QuerySync(query []byte) (res types.Result) { + app.mtx.Lock() + res = app.Application.Query(query) + app.mtx.Unlock() + return res +} + +func (app *localClient) CommitSync() (res types.Result) { + app.mtx.Lock() + res = app.Application.Commit() + app.mtx.Unlock() + return res +} + +func (app *localClient) InitChainSync(validators []*types.Validator) (err error) { + app.mtx.Lock() + if bcApp, ok := app.Application.(types.BlockchainAware); ok { + bcApp.InitChain(validators) + } + app.mtx.Unlock() + return nil +} + +func (app *localClient) EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) { + app.mtx.Lock() + if bcApp, ok := app.Application.(types.BlockchainAware); ok { + changedValidators = bcApp.EndBlock(height) + } + app.mtx.Unlock() + return changedValidators, nil +} + +//------------------------------------------------------- + +func (app *localClient) callback(req *types.Request, res *types.Response) *ReqRes { + app.Callback(req, res) + return newLocalReqRes(req, res) +} + +func newLocalReqRes(req *types.Request, res *types.Response) *ReqRes { + reqRes := NewReqRes(req) + reqRes.Response = res + reqRes.SetDone() + return reqRes +} diff --git a/client/remote_client.go b/client/remote_client.go new file mode 100644 index 00000000..fb8a5c8e --- /dev/null +++ b/client/remote_client.go @@ -0,0 +1,370 @@ +package tmspcli + +import ( + "bufio" + "container/list" + "errors" + "fmt" + "net" + "sync" + "time" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/types" +) + +const reqQueueSize = 256 // TODO make configurable +const maxResponseSize = 1048576 // 1MB TODO make configurable +const flushThrottleMS = 20 // Don't wait longer than... + +// This is goroutine-safe, but users should beware that +// the application in general is not meant to be interfaced +// with concurrent callers. +type remoteClient struct { + QuitService + sync.Mutex // [EB]: is this even used? + + reqQueue chan *ReqRes + flushTimer *ThrottleTimer + mustConnect bool + + mtx sync.Mutex + addr string + conn net.Conn + err error + reqSent *list.List + resCb func(*types.Request, *types.Response) // listens to all callbacks +} + +func NewClient(addr string, mustConnect bool) (*remoteClient, error) { + cli := &remoteClient{ + reqQueue: make(chan *ReqRes, reqQueueSize), + flushTimer: NewThrottleTimer("remoteClient", flushThrottleMS), + mustConnect: mustConnect, + + addr: addr, + reqSent: list.New(), + resCb: nil, + } + cli.QuitService = *NewQuitService(nil, "remoteClient", cli) + _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. + if mustConnect { + return nil, err + } else { + return cli, nil + } +} + +func (cli *remoteClient) OnStart() (err error) { + cli.QuitService.OnStart() + doneCh := make(chan struct{}) + go func() { + RETRY_LOOP: + for { + conn, err_ := Connect(cli.addr) + if err_ != nil { + if cli.mustConnect { + err = err_ // OnStart() will return this. + close(doneCh) + return + } else { + fmt.Printf("tmsp.remoteClient failed to connect to %v. Retrying...\n", cli.addr) + time.Sleep(time.Second * 3) + continue RETRY_LOOP + } + } + go cli.sendRequestsRoutine(conn) + go cli.recvResponseRoutine(conn) + close(doneCh) // OnStart() will return no error. + return + } + }() + <-doneCh + return // err +} + +func (cli *remoteClient) OnStop() { + cli.QuitService.OnStop() + if cli.conn != nil { + cli.conn.Close() + } +} + +// Set listener for all responses +// NOTE: callback may get internally generated flush responses. +func (cli *remoteClient) SetResponseCallback(resCb Callback) { + cli.mtx.Lock() + defer cli.mtx.Unlock() + cli.resCb = resCb +} + +func (cli *remoteClient) StopForError(err error) { + cli.mtx.Lock() + fmt.Printf("Stopping tmsp.remoteClient for error: %v\n", err.Error()) + if cli.err == nil { + cli.err = err + } + cli.mtx.Unlock() + cli.Stop() +} + +func (cli *remoteClient) Error() error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + return cli.err +} + +//---------------------------------------- + +func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { + w := bufio.NewWriter(conn) + for { + select { + case <-cli.flushTimer.Ch: + select { + case cli.reqQueue <- NewReqRes(types.RequestFlush()): + default: + // Probably will fill the buffer, or retry later. + } + case <-cli.QuitService.Quit: + return + case reqres := <-cli.reqQueue: + cli.willSendReq(reqres) + err := types.WriteMessage(reqres.Request, w) + if err != nil { + cli.StopForError(err) + return + } + // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) + if reqres.Request.Type == types.MessageType_Flush { + err = w.Flush() + if err != nil { + cli.StopForError(err) + return + } + } + } + } +} + +func (cli *remoteClient) recvResponseRoutine(conn net.Conn) { + r := bufio.NewReader(conn) // Buffer reads + for { + var res = &types.Response{} + err := types.ReadMessage(r, res) + if err != nil { + cli.StopForError(err) + return + } + switch res.Type { + case types.MessageType_Exception: + // XXX After setting cli.err, release waiters (e.g. reqres.Done()) + cli.StopForError(errors.New(res.Error)) + default: + // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) + err := cli.didRecvResponse(res) + if err != nil { + cli.StopForError(err) + } + } + } +} + +func (cli *remoteClient) willSendReq(reqres *ReqRes) { + cli.mtx.Lock() + defer cli.mtx.Unlock() + cli.reqSent.PushBack(reqres) +} + +func (cli *remoteClient) didRecvResponse(res *types.Response) error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + + // Get the first ReqRes + next := cli.reqSent.Front() + if next == nil { + return fmt.Errorf("Unexpected result type %v when nothing expected", res.Type) + } + reqres := next.Value.(*ReqRes) + if !resMatchesReq(reqres.Request, res) { + return fmt.Errorf("Unexpected result type %v when response to %v expected", + res.Type, reqres.Request.Type) + } + + reqres.Response = res // Set response + reqres.Done() // Release waiters + cli.reqSent.Remove(next) // Pop first item from linked list + + // Notify reqRes listener if set + if cb := reqres.GetCallback(); cb != nil { + cb(res) + } + + // Notify client listener if set + if cli.resCb != nil { + cli.resCb(reqres.Request, res) + } + + return nil +} + +//---------------------------------------- + +func (cli *remoteClient) EchoAsync(msg string) *ReqRes { + return cli.queueRequest(types.RequestEcho(msg)) +} + +func (cli *remoteClient) FlushAsync() *ReqRes { + return cli.queueRequest(types.RequestFlush()) +} + +func (cli *remoteClient) InfoAsync() *ReqRes { + return cli.queueRequest(types.RequestInfo()) +} + +func (cli *remoteClient) SetOptionAsync(key string, value string) *ReqRes { + return cli.queueRequest(types.RequestSetOption(key, value)) +} + +func (cli *remoteClient) AppendTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.RequestAppendTx(tx)) +} + +func (cli *remoteClient) CheckTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.RequestCheckTx(tx)) +} + +func (cli *remoteClient) QueryAsync(query []byte) *ReqRes { + return cli.queueRequest(types.RequestQuery(query)) +} + +func (cli *remoteClient) CommitAsync() *ReqRes { + return cli.queueRequest(types.RequestCommit()) +} + +func (cli *remoteClient) InitChainAsync(validators []*types.Validator) *ReqRes { + return cli.queueRequest(types.RequestInitChain(validators)) +} + +func (cli *remoteClient) EndBlockAsync(height uint64) *ReqRes { + return cli.queueRequest(types.RequestEndBlock(height)) +} + +//---------------------------------------- + +func (cli *remoteClient) EchoSync(msg string) (res types.Result) { + reqres := cli.queueRequest(types.RequestEcho(msg)) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) FlushSync() error { + cli.queueRequest(types.RequestFlush()).Wait() + return cli.err +} + +func (cli *remoteClient) InfoSync() (res types.Result) { + reqres := cli.queueRequest(types.RequestInfo()) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) SetOptionSync(key string, value string) (res types.Result) { + reqres := cli.queueRequest(types.RequestSetOption(key, value)) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) AppendTxSync(tx []byte) (res types.Result) { + reqres := cli.queueRequest(types.RequestAppendTx(tx)) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) CheckTxSync(tx []byte) (res types.Result) { + reqres := cli.queueRequest(types.RequestCheckTx(tx)) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) QuerySync(query []byte) (res types.Result) { + reqres := cli.queueRequest(types.RequestQuery(query)) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) CommitSync() (res types.Result) { + reqres := cli.queueRequest(types.RequestCommit()) + cli.FlushSync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *remoteClient) InitChainSync(validators []*types.Validator) (err error) { + cli.queueRequest(types.RequestInitChain(validators)) + cli.FlushSync() + if cli.err != nil { + return cli.err + } + return nil +} + +func (cli *remoteClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { + reqres := cli.queueRequest(types.RequestEndBlock(height)) + cli.FlushSync() + if cli.err != nil { + return nil, cli.err + } + return reqres.Response.Validators, nil +} + +//---------------------------------------- + +func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { + reqres := NewReqRes(req) + // TODO: set cli.err if reqQueue times out + cli.reqQueue <- reqres + + // Maybe auto-flush, or unset auto-flush + switch req.Type { + case types.MessageType_Flush: + cli.flushTimer.Unset() + default: + cli.flushTimer.Set() + } + + return reqres +} + +//---------------------------------------- + +func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { + return req.Type == res.Type +} diff --git a/tests/test_counter.go b/tests/test_counter.go index 6ed8f4f4..44adc320 100644 --- a/tests/test_counter.go +++ b/tests/test_counter.go @@ -68,7 +68,7 @@ func startApp() *process.Process { return proc } -func startClient() *tmspcli.Client { +func startClient() tmspcli.Client { // Start client client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", true) if err != nil { @@ -77,14 +77,15 @@ func startClient() *tmspcli.Client { return client } -func setOption(client *tmspcli.Client, key, value string) { - log, err := client.SetOptionSync(key, value) - if err != nil { - panic(Fmt("setting %v=%v: %v\nlog: %v", key, value, err, log)) +func setOption(client tmspcli.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)) } } -func commit(client *tmspcli.Client, hashExp []byte) { +func commit(client tmspcli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { @@ -96,7 +97,7 @@ func commit(client *tmspcli.Client, hashExp []byte) { } } -func appendTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func appendTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.AppendTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if res.IsErr() { @@ -112,7 +113,7 @@ func appendTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, da } } -func checkTx(client *tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func checkTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.CheckTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if res.IsErr() { From ccc55bd3040ff9b1d340c1c146e358a0cd1bc7f7 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 24 Mar 2016 11:12:16 -0700 Subject: [PATCH 098/545] Add ErrUnknownAddress --- types/errors.go | 23 ++++++------ types/types.pb.go | 94 ++++++++++++++++++++++++----------------------- types/types.proto | 3 +- 3 files changed, 63 insertions(+), 57 deletions(-) diff --git a/types/errors.go b/types/errors.go index 814b186e..15d16c53 100644 --- a/types/errors.go +++ b/types/errors.go @@ -10,15 +10,16 @@ var ( ErrInsufficientFunds = NewError(CodeType_InsufficientFunds, "Insufficient funds") ErrUnknownRequest = NewError(CodeType_UnknownRequest, "Unknown request") - ErrBaseDuplicateAddress = NewError(CodeType_BaseDuplicateAddress, "Error duplicate address") - ErrBaseEncodingError = NewError(CodeType_BaseEncodingError, "Error encoding error") - ErrBaseInsufficientFees = NewError(CodeType_BaseInsufficientFees, "Error insufficient fees") - ErrBaseInsufficientFunds = NewError(CodeType_BaseInsufficientFunds, "Error insufficient funds") - ErrBaseInsufficientGasPrice = NewError(CodeType_BaseInsufficientGasPrice, "Error insufficient gas price") - ErrBaseInvalidAddress = NewError(CodeType_BaseInvalidAddress, "Error invalid address") - ErrBaseInvalidAmount = NewError(CodeType_BaseInvalidAmount, "Error invalid amount") - ErrBaseInvalidPubKey = NewError(CodeType_BaseInvalidPubKey, "Error invalid pubkey") - ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error invalid sequence") - ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error invalid signature") - ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error unknown pubkey") + ErrBaseDuplicateAddress = NewError(CodeType_BaseDuplicateAddress, "Error (base) duplicate address") + ErrBaseEncodingError = NewError(CodeType_BaseEncodingError, "Error (base) encoding error") + ErrBaseInsufficientFees = NewError(CodeType_BaseInsufficientFees, "Error (base) insufficient fees") + ErrBaseInsufficientFunds = NewError(CodeType_BaseInsufficientFunds, "Error (base) insufficient funds") + ErrBaseInsufficientGasPrice = NewError(CodeType_BaseInsufficientGasPrice, "Error (base) insufficient gas price") + ErrBaseInvalidAddress = NewError(CodeType_BaseInvalidAddress, "Error (base) invalid address") + ErrBaseInvalidAmount = NewError(CodeType_BaseInvalidAmount, "Error (base) invalid amount") + ErrBaseInvalidPubKey = NewError(CodeType_BaseInvalidPubKey, "Error (base) invalid pubkey") + ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error (base) invalid sequence") + ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error (base) invalid signature") + ErrBaseUnknownAddress = NewError(CodeType_BaseUnknownAddress, "Error (base) unknown address") + ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error (base) unknown pubkey") ) diff --git a/types/types.pb.go b/types/types.pb.go index 41323e72..3f79161d 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -98,7 +98,8 @@ const ( CodeType_BaseInvalidPubKey CodeType = 108 CodeType_BaseInvalidSequence CodeType = 109 CodeType_BaseInvalidSignature CodeType = 110 - CodeType_BaseUnknownPubKey CodeType = 111 + CodeType_BaseUnknownAddress CodeType = 111 + CodeType_BaseUnknownPubKey CodeType = 112 // Reserved for governance, 200 ~ 299 CodeType_GovUnknownEntity CodeType = 201 CodeType_GovUnknownGroup CodeType = 202 @@ -130,7 +131,8 @@ var CodeType_name = map[int32]string{ 108: "BaseInvalidPubKey", 109: "BaseInvalidSequence", 110: "BaseInvalidSignature", - 111: "BaseUnknownPubKey", + 111: "BaseUnknownAddress", + 112: "BaseUnknownPubKey", 201: "GovUnknownEntity", 202: "GovUnknownGroup", 203: "GovUnknownProposal", @@ -160,7 +162,8 @@ var CodeType_value = map[string]int32{ "BaseInvalidPubKey": 108, "BaseInvalidSequence": 109, "BaseInvalidSignature": 110, - "BaseUnknownPubKey": 111, + "BaseUnknownAddress": 111, + "BaseUnknownPubKey": 112, "GovUnknownEntity": 201, "GovUnknownGroup": 202, "GovUnknownProposal": 203, @@ -239,49 +242,50 @@ func init() { } var fileDescriptor0 = []byte{ - // 703 bytes of a gzipped FileDescriptorProto + // 708 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x52, 0xdb, 0x4a, 0x10, 0xbd, 0xb2, 0x65, 0x63, 0xb7, 0xc1, 0x8c, 0x07, 0xfb, 0xa2, 0x7b, 0x2b, 0x0b, 0x8a, 0x54, 0xa5, 0x28, 0x16, 0x24, 0x45, 0x56, 0x59, 0x82, 0x63, 0x28, 0x17, 0x05, 0x38, 0xe2, 0xb1, 0x17, - 0x52, 0xdb, 0x52, 0x2c, 0xcf, 0x28, 0xd2, 0x08, 0x70, 0xbe, 0x20, 0xdf, 0x92, 0x1f, 0xc8, 0x17, - 0x64, 0x91, 0xf7, 0xe3, 0x8b, 0x32, 0x33, 0x92, 0x6c, 0x43, 0x16, 0x59, 0x64, 0x43, 0x4d, 0x9f, - 0x33, 0x7d, 0xfa, 0x9c, 0xd6, 0x60, 0x68, 0x89, 0x69, 0x84, 0xc9, 0x63, 0xfd, 0x77, 0x27, 0x8a, - 0xb9, 0xe0, 0xb4, 0xa2, 0x8b, 0xcd, 0x77, 0x06, 0x2c, 0xd9, 0xf8, 0x2a, 0xc5, 0x44, 0xd0, 0x47, - 0x60, 0x2a, 0xd0, 0x32, 0x36, 0x8c, 0xad, 0xe6, 0x2e, 0xdd, 0xc9, 0xae, 0x1f, 0x63, 0x92, 0x38, - 0x23, 0x3c, 0x97, 0x85, 0xad, 0x79, 0x4a, 0xc1, 0xf4, 0x1c, 0xe1, 0x58, 0x25, 0x79, 0x6f, 0xd9, - 0xd6, 0x67, 0x4a, 0xa0, 0x3c, 0xc6, 0xa9, 0x55, 0x96, 0x50, 0xdd, 0x56, 0x47, 0xda, 0x86, 0xca, - 0xb5, 0x13, 0xa6, 0x68, 0x99, 0x1a, 0xcb, 0x0a, 0xfa, 0x04, 0x40, 0x1e, 0x02, 0xd9, 0xc3, 0xe3, - 0xc4, 0xaa, 0x6c, 0x94, 0xb7, 0x1a, 0xbb, 0x24, 0x9f, 0x74, 0x59, 0x10, 0xf6, 0xc2, 0x1d, 0xfa, - 0x2f, 0x54, 0x7d, 0x0c, 0x46, 0xbe, 0xb0, 0xaa, 0x52, 0xc8, 0xb4, 0xf3, 0x6a, 0xf3, 0xbd, 0x01, - 0x35, 0x1b, 0x93, 0x88, 0xb3, 0x04, 0xff, 0xca, 0xfa, 0x43, 0x30, 0x5d, 0xee, 0xa1, 0xf6, 0xde, - 0xdc, 0x5d, 0xcd, 0x7b, 0xbb, 0x12, 0xca, 0x1a, 0x15, 0xa9, 0xd2, 0x60, 0x1c, 0xf3, 0xb8, 0x48, - 0xa3, 0x0b, 0x95, 0x3a, 0xe4, 0x23, 0x19, 0x43, 0xa7, 0x96, 0xc7, 0x7b, 0xf9, 0xaa, 0x7f, 0xce, - 0xb7, 0xf9, 0x0c, 0xea, 0x33, 0x42, 0x85, 0x8d, 0xd2, 0xab, 0x23, 0xb9, 0x49, 0x43, 0x3b, 0xcc, - 0x2b, 0x35, 0x3e, 0xe2, 0x37, 0x18, 0x6b, 0xe3, 0xa6, 0x9d, 0x15, 0xdb, 0x6f, 0x0d, 0x68, 0x2c, - 0x64, 0xa4, 0xab, 0xd0, 0x38, 0x49, 0xc3, 0x30, 0x87, 0xc8, 0x3f, 0xb4, 0x06, 0x66, 0xcf, 0xf5, - 0x39, 0x31, 0x68, 0x1d, 0x2a, 0x07, 0x61, 0x9a, 0xf8, 0xa4, 0xa4, 0xc0, 0x3e, 0x1b, 0x72, 0x52, - 0xa6, 0x2b, 0x50, 0x3f, 0x43, 0x71, 0x1a, 0x89, 0x80, 0x33, 0x62, 0xaa, 0xb2, 0x77, 0xeb, 0x62, - 0x56, 0x56, 0xe8, 0x32, 0xd4, 0xf6, 0xa2, 0x08, 0x99, 0x77, 0x7e, 0x4b, 0x5a, 0xb4, 0x01, 0x4b, - 0x5d, 0x1f, 0xdd, 0xb1, 0x2c, 0xe4, 0x16, 0xa1, 0xda, 0xe5, 0x93, 0x49, 0x20, 0xc8, 0x9a, 0x52, - 0x7e, 0x91, 0x62, 0x3c, 0x25, 0x6d, 0x25, 0xd0, 0x67, 0x81, 0xe8, 0xfa, 0x4e, 0xc0, 0x48, 0x47, - 0x09, 0xf4, 0x98, 0xb7, 0x1f, 0x72, 0x77, 0x4c, 0xd6, 0xb7, 0xdf, 0x54, 0xa0, 0x56, 0x2c, 0x95, - 0x56, 0xa1, 0x74, 0x7a, 0x24, 0x0d, 0xb6, 0x60, 0xa5, 0xcf, 0x04, 0xc6, 0xcc, 0x09, 0x7b, 0x6a, - 0xa3, 0xd2, 0xa9, 0x84, 0x7a, 0x4c, 0xee, 0x3c, 0x60, 0xa3, 0x0c, 0x2a, 0x29, 0xa1, 0x7d, 0xc7, - 0x3b, 0xe1, 0xcc, 0x45, 0xe9, 0x9a, 0xc0, 0xf2, 0x05, 0x73, 0x52, 0xe1, 0xf3, 0x38, 0x78, 0x8d, - 0x9e, 0x34, 0xde, 0x81, 0x56, 0x9f, 0x25, 0xe9, 0x70, 0x18, 0xb8, 0x01, 0x32, 0x71, 0x90, 0x32, - 0x2f, 0x91, 0x01, 0x28, 0x34, 0x2f, 0xd8, 0x98, 0xf1, 0x1b, 0x96, 0xbf, 0x70, 0x52, 0xa5, 0x16, - 0xb4, 0xf7, 0x9d, 0x04, 0x9f, 0xa7, 0x51, 0x18, 0xb8, 0x8e, 0xc0, 0x3d, 0xcf, 0x8b, 0xe5, 0xba, - 0x08, 0x2a, 0x11, 0xc5, 0xdc, 0x9d, 0x3d, 0x2c, 0x1a, 0xee, 0xe8, 0x23, 0x26, 0x64, 0x44, 0xff, - 0x83, 0xce, 0x6f, 0x8c, 0x9e, 0xec, 0xd3, 0x07, 0x60, 0xdd, 0xa7, 0x0e, 0x9d, 0x64, 0x10, 0x07, - 0x32, 0x40, 0x20, 0x3f, 0x32, 0xcd, 0x58, 0xfd, 0x0a, 0x0a, 0x07, 0x2f, 0x0b, 0x07, 0x05, 0x3e, - 0xe1, 0x29, 0x13, 0x64, 0x7c, 0x0f, 0x1e, 0xe8, 0x07, 0x41, 0x42, 0xba, 0x0e, 0x6b, 0x0b, 0xf0, - 0x99, 0x4a, 0xa8, 0xf6, 0x33, 0x99, 0x3b, 0xce, 0x88, 0x60, 0xc4, 0x1c, 0x91, 0xc6, 0x48, 0x58, - 0xa1, 0x94, 0x2f, 0x25, 0x57, 0xe2, 0x12, 0x26, 0x87, 0xfc, 0x3a, 0x47, 0x7b, 0x4c, 0x04, 0x62, - 0x4a, 0x3e, 0x18, 0xf2, 0xcd, 0xad, 0xce, 0xe1, 0xc3, 0x98, 0xa7, 0x11, 0xf9, 0x68, 0xc8, 0xb1, - 0x74, 0x8e, 0x0e, 0x62, 0x1e, 0xf1, 0xc4, 0x09, 0xc9, 0x27, 0x43, 0xa6, 0x6a, 0x49, 0x62, 0xb6, - 0xd8, 0xac, 0xe1, 0x73, 0xd1, 0x30, 0xc3, 0x8f, 0x71, 0x72, 0x85, 0x31, 0xf9, 0x62, 0xc8, 0xfd, - 0xb5, 0x17, 0x89, 0x99, 0xd6, 0x57, 0x23, 0x77, 0x34, 0xa3, 0x2e, 0xb9, 0x40, 0xf2, 0xad, 0x80, - 0xf3, 0x60, 0xb9, 0xd0, 0x77, 0x83, 0xae, 0x41, 0x73, 0x0e, 0xeb, 0xbb, 0x3f, 0x0c, 0xfa, 0x3f, - 0x74, 0xee, 0x80, 0xf2, 0x93, 0x0e, 0xd4, 0x3f, 0x0d, 0xf9, 0x69, 0x5c, 0x55, 0xf5, 0x4f, 0xe0, - 0xd3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x92, 0xa5, 0x2c, 0x76, 0x17, 0x05, 0x00, 0x00, + 0x52, 0xdb, 0x52, 0x2c, 0xcf, 0x28, 0xd2, 0x08, 0x70, 0xbe, 0x26, 0xeb, 0xfc, 0x40, 0xbe, 0x20, + 0x8b, 0xbc, 0x1f, 0x5f, 0x94, 0x99, 0x91, 0x64, 0x1b, 0xb2, 0xc8, 0x22, 0x1b, 0x6a, 0xfa, 0x9c, + 0xe9, 0xee, 0x73, 0x8e, 0x06, 0x43, 0x4b, 0x4c, 0x23, 0x4c, 0x1e, 0xeb, 0xbf, 0x3b, 0x51, 0xcc, + 0x05, 0xa7, 0x15, 0x5d, 0x6c, 0xbe, 0x33, 0x60, 0xc9, 0xc6, 0x57, 0x29, 0x26, 0x82, 0x3e, 0x02, + 0x53, 0x81, 0x96, 0xb1, 0x61, 0x6c, 0x35, 0x77, 0xe9, 0x4e, 0x76, 0xfd, 0x18, 0x93, 0xc4, 0x19, + 0xe1, 0xb9, 0x2c, 0x6c, 0xcd, 0x53, 0x0a, 0xa6, 0xe7, 0x08, 0xc7, 0x2a, 0xc9, 0x7b, 0xcb, 0xb6, + 0x3e, 0x53, 0x02, 0xe5, 0x31, 0x4e, 0xad, 0xb2, 0x84, 0xea, 0xb6, 0x3a, 0xd2, 0x36, 0x54, 0xae, + 0x9d, 0x30, 0x45, 0xcb, 0xd4, 0x58, 0x56, 0xd0, 0x27, 0x00, 0xf2, 0x10, 0xc8, 0x1e, 0x1e, 0x27, + 0x56, 0x65, 0xa3, 0xbc, 0xd5, 0xd8, 0x25, 0xf9, 0xa6, 0xcb, 0x82, 0xb0, 0x17, 0xee, 0xd0, 0x7f, + 0xa1, 0xea, 0x63, 0x30, 0xf2, 0x85, 0x55, 0x95, 0x83, 0x4c, 0x3b, 0xaf, 0x36, 0xdf, 0x1b, 0x50, + 0xb3, 0x31, 0x89, 0x38, 0x4b, 0xf0, 0xaf, 0xa4, 0x3f, 0x04, 0xd3, 0xe5, 0x1e, 0x6a, 0xed, 0xcd, + 0xdd, 0xd5, 0xbc, 0xb7, 0x2b, 0xa1, 0xac, 0x51, 0x91, 0xca, 0x0d, 0xc6, 0x31, 0x8f, 0x0b, 0x37, + 0xba, 0x50, 0xae, 0x43, 0x3e, 0x92, 0x36, 0xb4, 0x6b, 0x79, 0xbc, 0xe7, 0xaf, 0xfa, 0x67, 0x7f, + 0x9b, 0xcf, 0xa0, 0x3e, 0x23, 0x94, 0xd9, 0x28, 0xbd, 0x3a, 0x92, 0x49, 0x1a, 0x5a, 0x61, 0x5e, + 0xa9, 0xf5, 0x11, 0xbf, 0xc1, 0x58, 0x0b, 0x37, 0xed, 0xac, 0xd8, 0x7e, 0x6b, 0x40, 0x63, 0xc1, + 0x23, 0x5d, 0x85, 0xc6, 0x49, 0x1a, 0x86, 0x39, 0x44, 0xfe, 0xa1, 0x35, 0x30, 0x7b, 0xae, 0xcf, + 0x89, 0x41, 0xeb, 0x50, 0x39, 0x08, 0xd3, 0xc4, 0x27, 0x25, 0x05, 0xf6, 0xd9, 0x90, 0x93, 0x32, + 0x5d, 0x81, 0xfa, 0x19, 0x8a, 0xd3, 0x48, 0x04, 0x9c, 0x11, 0x53, 0x95, 0xbd, 0x5b, 0x17, 0xb3, + 0xb2, 0x42, 0x97, 0xa1, 0xb6, 0x17, 0x45, 0xc8, 0xbc, 0xf3, 0x5b, 0xd2, 0xa2, 0x0d, 0x58, 0xea, + 0xfa, 0xe8, 0x8e, 0x65, 0x21, 0x53, 0x84, 0x6a, 0x97, 0x4f, 0x26, 0x81, 0x20, 0x6b, 0x6a, 0xf2, + 0x8b, 0x14, 0xe3, 0x29, 0x69, 0xab, 0x01, 0x7d, 0x16, 0x88, 0xae, 0xef, 0x04, 0x8c, 0x74, 0xd4, + 0x80, 0x1e, 0xf3, 0xf6, 0x43, 0xee, 0x8e, 0xc9, 0xfa, 0xf6, 0x9b, 0x0a, 0xd4, 0x8a, 0x50, 0x69, + 0x15, 0x4a, 0xa7, 0x47, 0x52, 0x60, 0x0b, 0x56, 0xfa, 0x4c, 0x60, 0xcc, 0x9c, 0xb0, 0xa7, 0x12, + 0x95, 0x4a, 0x25, 0xd4, 0x63, 0x32, 0xf3, 0x80, 0x8d, 0x32, 0xa8, 0xa4, 0x06, 0xed, 0x3b, 0xde, + 0x09, 0x67, 0x2e, 0x4a, 0xd5, 0x04, 0x96, 0x2f, 0x98, 0x93, 0x0a, 0x9f, 0xc7, 0xc1, 0x6b, 0xf4, + 0xa4, 0xf0, 0x0e, 0xb4, 0xfa, 0x2c, 0x49, 0x87, 0xc3, 0xc0, 0x0d, 0x90, 0x89, 0x83, 0x94, 0x79, + 0x89, 0x34, 0x40, 0xa1, 0x79, 0xc1, 0xc6, 0x8c, 0xdf, 0xb0, 0xfc, 0x85, 0x93, 0x2a, 0xb5, 0xa0, + 0xbd, 0xef, 0x24, 0xf8, 0x3c, 0x8d, 0xc2, 0xc0, 0x75, 0x04, 0xee, 0x79, 0x5e, 0x2c, 0xe3, 0x22, + 0xa8, 0x86, 0x28, 0xe6, 0xee, 0xee, 0x61, 0xd1, 0x70, 0x67, 0x3e, 0x62, 0x42, 0x46, 0xf4, 0x3f, + 0xe8, 0xfc, 0xc6, 0xe8, 0xcd, 0x3e, 0x7d, 0x00, 0xd6, 0x7d, 0xea, 0xd0, 0x49, 0x06, 0x71, 0x20, + 0x0d, 0x04, 0xf2, 0x23, 0xd3, 0x8c, 0xd5, 0xaf, 0xa0, 0x50, 0xf0, 0xb2, 0x50, 0x50, 0xe0, 0x13, + 0x9e, 0x32, 0x41, 0xc6, 0xf7, 0xe0, 0x81, 0x7e, 0x10, 0x24, 0xa4, 0xeb, 0xb0, 0xb6, 0x00, 0x9f, + 0x29, 0x87, 0x2a, 0x9f, 0xc9, 0x5c, 0x71, 0x46, 0x04, 0x23, 0xe6, 0x88, 0x34, 0x46, 0xc2, 0x8a, + 0xc5, 0x79, 0x28, 0xc5, 0x62, 0x5e, 0x6c, 0xc8, 0xf1, 0x7c, 0x43, 0x24, 0x61, 0x72, 0xc8, 0xaf, + 0x73, 0xb4, 0xc7, 0x44, 0x20, 0xa6, 0xe4, 0x83, 0x21, 0xdf, 0xe2, 0xea, 0x1c, 0x3e, 0x8c, 0x79, + 0x1a, 0x91, 0x8f, 0x86, 0x94, 0x43, 0xe7, 0xe8, 0x20, 0xe6, 0x11, 0x4f, 0x9c, 0x90, 0x7c, 0x32, + 0xe4, 0xd2, 0x96, 0x24, 0x66, 0x81, 0x67, 0x0d, 0x9f, 0x8b, 0x86, 0x19, 0x7e, 0x8c, 0x93, 0x2b, + 0x8c, 0xc9, 0x17, 0x43, 0xe6, 0xda, 0x5e, 0x24, 0x66, 0xb3, 0xbe, 0x1a, 0xb9, 0xa2, 0x19, 0x75, + 0xc9, 0x05, 0x92, 0x6f, 0x05, 0x9c, 0x1b, 0xce, 0x07, 0x7d, 0x37, 0xe8, 0x1a, 0x34, 0xe7, 0xb0, + 0xbe, 0xfb, 0xc3, 0xa0, 0xff, 0x43, 0xe7, 0x0e, 0x28, 0x3f, 0xf5, 0x40, 0xfd, 0x33, 0x91, 0x9f, + 0xc6, 0x55, 0x55, 0xff, 0x34, 0x3e, 0xfd, 0x15, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x8b, 0x89, 0x86, + 0x2f, 0x05, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 5a7a226f..1735fa29 100644 --- a/types/types.proto +++ b/types/types.proto @@ -48,7 +48,8 @@ enum CodeType { BaseInvalidPubKey = 108; BaseInvalidSequence = 109; BaseInvalidSignature = 110; - BaseUnknownPubKey = 111; + BaseUnknownAddress = 111; + BaseUnknownPubKey = 112; // Reserved for governance, 200 ~ 299 GovUnknownEntity = 201; From 1dfc6950dddf47ff397e670a67d405d25da138ea Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 24 Mar 2016 11:27:04 -0700 Subject: [PATCH 099/545] TMSPResult tweak --- types/result.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/result.go b/types/result.go index e5cb6bbd..717ae2fa 100644 --- a/types/result.go +++ b/types/result.go @@ -28,7 +28,7 @@ func (res Result) IsErr() bool { } func (res Result) Error() string { - return fmt.Sprintf("TMSP error code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) + return fmt.Sprintf("TMSP code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) } func (res Result) PrependLog(log string) Result { From 121db71f48b7f3f5ef547920acd670d653e180b1 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 24 Mar 2016 14:17:48 -0700 Subject: [PATCH 100/545] Add ErrBaseUnknownPlugin --- types/errors.go | 1 + types/types.pb.go | 95 ++++++++++++++++++++++++----------------------- types/types.proto | 1 + 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/types/errors.go b/types/errors.go index 15d16c53..475e92fe 100644 --- a/types/errors.go +++ b/types/errors.go @@ -21,5 +21,6 @@ var ( ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error (base) invalid sequence") ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error (base) invalid signature") ErrBaseUnknownAddress = NewError(CodeType_BaseUnknownAddress, "Error (base) unknown address") + ErrBaseUnknownPlugin = NewError(CodeType_BaseUnknownPlugin, "Error (base) unknown plugin") ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error (base) unknown pubkey") ) diff --git a/types/types.pb.go b/types/types.pb.go index 3f79161d..96067a15 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -100,6 +100,7 @@ const ( CodeType_BaseInvalidSignature CodeType = 110 CodeType_BaseUnknownAddress CodeType = 111 CodeType_BaseUnknownPubKey CodeType = 112 + CodeType_BaseUnknownPlugin CodeType = 113 // Reserved for governance, 200 ~ 299 CodeType_GovUnknownEntity CodeType = 201 CodeType_GovUnknownGroup CodeType = 202 @@ -133,6 +134,7 @@ var CodeType_name = map[int32]string{ 110: "BaseInvalidSignature", 111: "BaseUnknownAddress", 112: "BaseUnknownPubKey", + 113: "BaseUnknownPlugin", 201: "GovUnknownEntity", 202: "GovUnknownGroup", 203: "GovUnknownProposal", @@ -164,6 +166,7 @@ var CodeType_value = map[string]int32{ "BaseInvalidSignature": 110, "BaseUnknownAddress": 111, "BaseUnknownPubKey": 112, + "BaseUnknownPlugin": 113, "GovUnknownEntity": 201, "GovUnknownGroup": 202, "GovUnknownProposal": 203, @@ -242,50 +245,50 @@ func init() { } var fileDescriptor0 = []byte{ - // 708 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcb, 0x52, 0xdb, 0x4a, - 0x10, 0xbd, 0xb2, 0x65, 0x63, 0xb7, 0xc1, 0x8c, 0x07, 0xfb, 0xa2, 0x7b, 0x2b, 0x0b, 0x8a, 0x54, - 0xa5, 0x28, 0x16, 0x24, 0x45, 0x56, 0x59, 0x82, 0x63, 0x28, 0x17, 0x05, 0x38, 0xe2, 0xb1, 0x17, - 0x52, 0xdb, 0x52, 0x2c, 0xcf, 0x28, 0xd2, 0x08, 0x70, 0xbe, 0x26, 0xeb, 0xfc, 0x40, 0xbe, 0x20, - 0x8b, 0xbc, 0x1f, 0x5f, 0x94, 0x99, 0x91, 0x64, 0x1b, 0xb2, 0xc8, 0x22, 0x1b, 0x6a, 0xfa, 0x9c, - 0xe9, 0xee, 0x73, 0x8e, 0x06, 0x43, 0x4b, 0x4c, 0x23, 0x4c, 0x1e, 0xeb, 0xbf, 0x3b, 0x51, 0xcc, - 0x05, 0xa7, 0x15, 0x5d, 0x6c, 0xbe, 0x33, 0x60, 0xc9, 0xc6, 0x57, 0x29, 0x26, 0x82, 0x3e, 0x02, - 0x53, 0x81, 0x96, 0xb1, 0x61, 0x6c, 0x35, 0x77, 0xe9, 0x4e, 0x76, 0xfd, 0x18, 0x93, 0xc4, 0x19, - 0xe1, 0xb9, 0x2c, 0x6c, 0xcd, 0x53, 0x0a, 0xa6, 0xe7, 0x08, 0xc7, 0x2a, 0xc9, 0x7b, 0xcb, 0xb6, - 0x3e, 0x53, 0x02, 0xe5, 0x31, 0x4e, 0xad, 0xb2, 0x84, 0xea, 0xb6, 0x3a, 0xd2, 0x36, 0x54, 0xae, - 0x9d, 0x30, 0x45, 0xcb, 0xd4, 0x58, 0x56, 0xd0, 0x27, 0x00, 0xf2, 0x10, 0xc8, 0x1e, 0x1e, 0x27, - 0x56, 0x65, 0xa3, 0xbc, 0xd5, 0xd8, 0x25, 0xf9, 0xa6, 0xcb, 0x82, 0xb0, 0x17, 0xee, 0xd0, 0x7f, - 0xa1, 0xea, 0x63, 0x30, 0xf2, 0x85, 0x55, 0x95, 0x83, 0x4c, 0x3b, 0xaf, 0x36, 0xdf, 0x1b, 0x50, - 0xb3, 0x31, 0x89, 0x38, 0x4b, 0xf0, 0xaf, 0xa4, 0x3f, 0x04, 0xd3, 0xe5, 0x1e, 0x6a, 0xed, 0xcd, - 0xdd, 0xd5, 0xbc, 0xb7, 0x2b, 0xa1, 0xac, 0x51, 0x91, 0xca, 0x0d, 0xc6, 0x31, 0x8f, 0x0b, 0x37, - 0xba, 0x50, 0xae, 0x43, 0x3e, 0x92, 0x36, 0xb4, 0x6b, 0x79, 0xbc, 0xe7, 0xaf, 0xfa, 0x67, 0x7f, - 0x9b, 0xcf, 0xa0, 0x3e, 0x23, 0x94, 0xd9, 0x28, 0xbd, 0x3a, 0x92, 0x49, 0x1a, 0x5a, 0x61, 0x5e, - 0xa9, 0xf5, 0x11, 0xbf, 0xc1, 0x58, 0x0b, 0x37, 0xed, 0xac, 0xd8, 0x7e, 0x6b, 0x40, 0x63, 0xc1, - 0x23, 0x5d, 0x85, 0xc6, 0x49, 0x1a, 0x86, 0x39, 0x44, 0xfe, 0xa1, 0x35, 0x30, 0x7b, 0xae, 0xcf, - 0x89, 0x41, 0xeb, 0x50, 0x39, 0x08, 0xd3, 0xc4, 0x27, 0x25, 0x05, 0xf6, 0xd9, 0x90, 0x93, 0x32, - 0x5d, 0x81, 0xfa, 0x19, 0x8a, 0xd3, 0x48, 0x04, 0x9c, 0x11, 0x53, 0x95, 0xbd, 0x5b, 0x17, 0xb3, - 0xb2, 0x42, 0x97, 0xa1, 0xb6, 0x17, 0x45, 0xc8, 0xbc, 0xf3, 0x5b, 0xd2, 0xa2, 0x0d, 0x58, 0xea, - 0xfa, 0xe8, 0x8e, 0x65, 0x21, 0x53, 0x84, 0x6a, 0x97, 0x4f, 0x26, 0x81, 0x20, 0x6b, 0x6a, 0xf2, - 0x8b, 0x14, 0xe3, 0x29, 0x69, 0xab, 0x01, 0x7d, 0x16, 0x88, 0xae, 0xef, 0x04, 0x8c, 0x74, 0xd4, - 0x80, 0x1e, 0xf3, 0xf6, 0x43, 0xee, 0x8e, 0xc9, 0xfa, 0xf6, 0x9b, 0x0a, 0xd4, 0x8a, 0x50, 0x69, - 0x15, 0x4a, 0xa7, 0x47, 0x52, 0x60, 0x0b, 0x56, 0xfa, 0x4c, 0x60, 0xcc, 0x9c, 0xb0, 0xa7, 0x12, - 0x95, 0x4a, 0x25, 0xd4, 0x63, 0x32, 0xf3, 0x80, 0x8d, 0x32, 0xa8, 0xa4, 0x06, 0xed, 0x3b, 0xde, - 0x09, 0x67, 0x2e, 0x4a, 0xd5, 0x04, 0x96, 0x2f, 0x98, 0x93, 0x0a, 0x9f, 0xc7, 0xc1, 0x6b, 0xf4, - 0xa4, 0xf0, 0x0e, 0xb4, 0xfa, 0x2c, 0x49, 0x87, 0xc3, 0xc0, 0x0d, 0x90, 0x89, 0x83, 0x94, 0x79, - 0x89, 0x34, 0x40, 0xa1, 0x79, 0xc1, 0xc6, 0x8c, 0xdf, 0xb0, 0xfc, 0x85, 0x93, 0x2a, 0xb5, 0xa0, - 0xbd, 0xef, 0x24, 0xf8, 0x3c, 0x8d, 0xc2, 0xc0, 0x75, 0x04, 0xee, 0x79, 0x5e, 0x2c, 0xe3, 0x22, - 0xa8, 0x86, 0x28, 0xe6, 0xee, 0xee, 0x61, 0xd1, 0x70, 0x67, 0x3e, 0x62, 0x42, 0x46, 0xf4, 0x3f, - 0xe8, 0xfc, 0xc6, 0xe8, 0xcd, 0x3e, 0x7d, 0x00, 0xd6, 0x7d, 0xea, 0xd0, 0x49, 0x06, 0x71, 0x20, - 0x0d, 0x04, 0xf2, 0x23, 0xd3, 0x8c, 0xd5, 0xaf, 0xa0, 0x50, 0xf0, 0xb2, 0x50, 0x50, 0xe0, 0x13, - 0x9e, 0x32, 0x41, 0xc6, 0xf7, 0xe0, 0x81, 0x7e, 0x10, 0x24, 0xa4, 0xeb, 0xb0, 0xb6, 0x00, 0x9f, - 0x29, 0x87, 0x2a, 0x9f, 0xc9, 0x5c, 0x71, 0x46, 0x04, 0x23, 0xe6, 0x88, 0x34, 0x46, 0xc2, 0x8a, - 0xc5, 0x79, 0x28, 0xc5, 0x62, 0x5e, 0x6c, 0xc8, 0xf1, 0x7c, 0x43, 0x24, 0x61, 0x72, 0xc8, 0xaf, - 0x73, 0xb4, 0xc7, 0x44, 0x20, 0xa6, 0xe4, 0x83, 0x21, 0xdf, 0xe2, 0xea, 0x1c, 0x3e, 0x8c, 0x79, - 0x1a, 0x91, 0x8f, 0x86, 0x94, 0x43, 0xe7, 0xe8, 0x20, 0xe6, 0x11, 0x4f, 0x9c, 0x90, 0x7c, 0x32, - 0xe4, 0xd2, 0x96, 0x24, 0x66, 0x81, 0x67, 0x0d, 0x9f, 0x8b, 0x86, 0x19, 0x7e, 0x8c, 0x93, 0x2b, - 0x8c, 0xc9, 0x17, 0x43, 0xe6, 0xda, 0x5e, 0x24, 0x66, 0xb3, 0xbe, 0x1a, 0xb9, 0xa2, 0x19, 0x75, - 0xc9, 0x05, 0x92, 0x6f, 0x05, 0x9c, 0x1b, 0xce, 0x07, 0x7d, 0x37, 0xe8, 0x1a, 0x34, 0xe7, 0xb0, - 0xbe, 0xfb, 0xc3, 0xa0, 0xff, 0x43, 0xe7, 0x0e, 0x28, 0x3f, 0xf5, 0x40, 0xfd, 0x33, 0x91, 0x9f, - 0xc6, 0x55, 0x55, 0xff, 0x34, 0x3e, 0xfd, 0x15, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x8b, 0x89, 0x86, - 0x2f, 0x05, 0x00, 0x00, + // 716 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x52, 0xdb, 0x48, + 0x10, 0x5e, 0xd9, 0xb2, 0xb1, 0xdb, 0x60, 0xc6, 0x83, 0xbd, 0x68, 0xb7, 0xf6, 0x40, 0xb1, 0x55, + 0x5b, 0x14, 0x07, 0x76, 0x8b, 0x3d, 0xe5, 0x08, 0x8e, 0xa1, 0x5c, 0x14, 0xe0, 0x88, 0x9f, 0xbb, + 0x90, 0xda, 0x96, 0x62, 0x79, 0x46, 0x48, 0x23, 0xc0, 0x79, 0xa4, 0xbc, 0x00, 0x4f, 0x90, 0x43, + 0xfe, 0x7f, 0x9e, 0x28, 0x33, 0x23, 0xc9, 0x36, 0xce, 0x21, 0x87, 0x5c, 0x5c, 0xd3, 0xdf, 0x37, + 0xdd, 0xfd, 0x7d, 0x3d, 0x6d, 0x41, 0x4b, 0x4c, 0x23, 0x4c, 0xfe, 0xd5, 0xbf, 0x7b, 0x51, 0xcc, + 0x05, 0xa7, 0x15, 0x1d, 0x6c, 0x3f, 0x1a, 0xb0, 0x62, 0xe3, 0x6d, 0x8a, 0x89, 0xa0, 0xff, 0x80, + 0xa9, 0x40, 0xcb, 0xd8, 0x32, 0x76, 0x9a, 0xfb, 0x74, 0x2f, 0xbb, 0x7e, 0x8a, 0x49, 0xe2, 0x8c, + 0xf0, 0x52, 0x06, 0xb6, 0xe6, 0x29, 0x05, 0xd3, 0x73, 0x84, 0x63, 0x95, 0xe4, 0xbd, 0x55, 0x5b, + 0x9f, 0x29, 0x81, 0xf2, 0x18, 0xa7, 0x56, 0x59, 0x42, 0x75, 0x5b, 0x1d, 0x69, 0x1b, 0x2a, 0x77, + 0x4e, 0x98, 0xa2, 0x65, 0x6a, 0x2c, 0x0b, 0xe8, 0x7f, 0x00, 0xf2, 0x10, 0xc8, 0x1c, 0x1e, 0x27, + 0x56, 0x65, 0xab, 0xbc, 0xd3, 0xd8, 0x27, 0x79, 0xa7, 0xeb, 0x82, 0xb0, 0x17, 0xee, 0xd0, 0xdf, + 0xa1, 0xea, 0x63, 0x30, 0xf2, 0x85, 0x55, 0x95, 0x85, 0x4c, 0x3b, 0x8f, 0xb6, 0xdf, 0x18, 0x50, + 0xb3, 0x31, 0x89, 0x38, 0x4b, 0xf0, 0x97, 0xa4, 0xff, 0x0d, 0xa6, 0xcb, 0x3d, 0xd4, 0xda, 0x9b, + 0xfb, 0xeb, 0x79, 0x6e, 0x57, 0x42, 0x59, 0xa2, 0x22, 0x95, 0x1b, 0x8c, 0x63, 0x1e, 0x17, 0x6e, + 0x74, 0xa0, 0x5c, 0x87, 0x7c, 0x24, 0x6d, 0x68, 0xd7, 0xf2, 0xb8, 0xe4, 0xaf, 0xfa, 0x73, 0x7f, + 0xdb, 0xcf, 0xa0, 0x3e, 0x23, 0x94, 0xd9, 0x28, 0xbd, 0x39, 0x91, 0x93, 0x34, 0xb4, 0xc2, 0x3c, + 0x52, 0xed, 0x23, 0x7e, 0x8f, 0xb1, 0x16, 0x6e, 0xda, 0x59, 0xb0, 0xfb, 0xda, 0x80, 0xc6, 0x82, + 0x47, 0xba, 0x0e, 0x8d, 0xb3, 0x34, 0x0c, 0x73, 0x88, 0xfc, 0x46, 0x6b, 0x60, 0xf6, 0x5c, 0x9f, + 0x13, 0x83, 0xd6, 0xa1, 0x72, 0x14, 0xa6, 0x89, 0x4f, 0x4a, 0x0a, 0xec, 0xb3, 0x21, 0x27, 0x65, + 0xba, 0x06, 0xf5, 0x0b, 0x14, 0xe7, 0x91, 0x08, 0x38, 0x23, 0xa6, 0x0a, 0x7b, 0x0f, 0x2e, 0x66, + 0x61, 0x85, 0xae, 0x42, 0xed, 0x20, 0x8a, 0x90, 0x79, 0x97, 0x0f, 0xa4, 0x45, 0x1b, 0xb0, 0xd2, + 0xf5, 0xd1, 0x1d, 0xcb, 0x40, 0x4e, 0x11, 0xaa, 0x5d, 0x3e, 0x99, 0x04, 0x82, 0x6c, 0xa8, 0xca, + 0x2f, 0x52, 0x8c, 0xa7, 0xa4, 0xad, 0x0a, 0xf4, 0x59, 0x20, 0xba, 0xbe, 0x13, 0x30, 0xd2, 0x51, + 0x05, 0x7a, 0xcc, 0x3b, 0x0c, 0xb9, 0x3b, 0x26, 0x9b, 0xbb, 0x8f, 0x15, 0xa8, 0x15, 0x43, 0xa5, + 0x55, 0x28, 0x9d, 0x9f, 0x48, 0x81, 0x2d, 0x58, 0xeb, 0x33, 0x81, 0x31, 0x73, 0xc2, 0x9e, 0x9a, + 0xa8, 0x54, 0x2a, 0xa1, 0x1e, 0x93, 0x33, 0x0f, 0xd8, 0x28, 0x83, 0x4a, 0xaa, 0xd0, 0xa1, 0xe3, + 0x9d, 0x71, 0xe6, 0xa2, 0x54, 0x4d, 0x60, 0xf5, 0x8a, 0x39, 0xa9, 0xf0, 0x79, 0x1c, 0xbc, 0x42, + 0x4f, 0x0a, 0xef, 0x40, 0xab, 0xcf, 0x92, 0x74, 0x38, 0x0c, 0xdc, 0x00, 0x99, 0x38, 0x4a, 0x99, + 0x97, 0x48, 0x03, 0x14, 0x9a, 0x57, 0x6c, 0xcc, 0xf8, 0x3d, 0xcb, 0x37, 0x9c, 0x54, 0xa9, 0x05, + 0xed, 0x43, 0x27, 0xc1, 0xe7, 0x69, 0x14, 0x06, 0xae, 0x23, 0xf0, 0xc0, 0xf3, 0x62, 0x39, 0x2e, + 0x82, 0xaa, 0x88, 0x62, 0x9e, 0xf6, 0x1e, 0x16, 0x09, 0x4f, 0xea, 0x23, 0x26, 0x64, 0x44, 0xff, + 0x80, 0xce, 0x0f, 0x8c, 0xee, 0xec, 0xd3, 0xbf, 0xc0, 0x5a, 0xa6, 0x8e, 0x9d, 0x64, 0x10, 0x07, + 0xd2, 0x40, 0x20, 0x1f, 0x99, 0x66, 0xac, 0xde, 0x82, 0x42, 0xc1, 0xcb, 0x42, 0x41, 0x81, 0x4f, + 0x78, 0xca, 0x04, 0x19, 0x2f, 0xc1, 0x03, 0xbd, 0x10, 0x24, 0xa4, 0x9b, 0xb0, 0xb1, 0x00, 0x5f, + 0x28, 0x87, 0x6a, 0x3e, 0x93, 0xb9, 0xe2, 0x8c, 0x08, 0x46, 0xcc, 0x11, 0x69, 0x8c, 0x84, 0x15, + 0x8d, 0xf3, 0xa1, 0x14, 0x8d, 0x79, 0xd1, 0x21, 0xc7, 0xf3, 0x0e, 0xd1, 0x32, 0x1c, 0xa6, 0x23, + 0xf9, 0xac, 0xb7, 0x12, 0x26, 0xc7, 0xfc, 0x2e, 0x47, 0x7b, 0x4c, 0x04, 0x62, 0x4a, 0xde, 0x1a, + 0x72, 0x45, 0xd7, 0xe7, 0xf0, 0x71, 0xcc, 0xd3, 0x88, 0xbc, 0x33, 0xa4, 0x4a, 0x3a, 0x47, 0x07, + 0x31, 0x8f, 0x78, 0xe2, 0x84, 0xe4, 0xbd, 0x21, 0xb5, 0xb4, 0x24, 0x31, 0x7b, 0x87, 0x2c, 0xe1, + 0x43, 0x91, 0x30, 0xc3, 0x4f, 0x71, 0x72, 0x83, 0x31, 0xf9, 0x68, 0xc8, 0x71, 0xb7, 0x17, 0x89, + 0x59, 0xad, 0x4f, 0x46, 0xae, 0x68, 0x46, 0x5d, 0x73, 0x81, 0xe4, 0x73, 0x01, 0xe7, 0x73, 0xc8, + 0x0b, 0x7d, 0x31, 0xe8, 0x06, 0x34, 0xe7, 0xb0, 0xbe, 0xfb, 0xd5, 0xa0, 0x7f, 0x42, 0xe7, 0x09, + 0x28, 0x37, 0x60, 0xa0, 0xfe, 0x63, 0xe4, 0x9b, 0x71, 0x53, 0xd5, 0x5f, 0xcc, 0xff, 0xbf, 0x07, + 0x00, 0x00, 0xff, 0xff, 0x91, 0x57, 0x50, 0xd8, 0x46, 0x05, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 1735fa29..12ae6d29 100644 --- a/types/types.proto +++ b/types/types.proto @@ -50,6 +50,7 @@ enum CodeType { BaseInvalidSignature = 110; BaseUnknownAddress = 111; BaseUnknownPubKey = 112; + BaseUnknownPlugin = 113; // Reserved for governance, 200 ~ 299 GovUnknownEntity = 201; From 82a411fca58b3b1e2ac8fc3a6784a17579012d68 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 26 Mar 2016 22:35:23 -0700 Subject: [PATCH 101/545] New TMSP message BeginBlock --- README.md | 33 +++++++------- client/client.go | 5 +++ client/local_client.go | 47 +++++++++++++++++++ client/remote_client.go | 13 ++++++ types/application.go | 3 ++ types/messages.go | 13 ++++++ types/types.pb.go | 99 +++++++++++++++++++++-------------------- types/types.proto | 2 +- 8 files changed, 151 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 9d1db358..6c35736e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Usage__:
Validate a transaction. This message should not mutate the state. Transactions are first run through CheckTx before broadcast to peers in the mempool layer. - You can make CheckTx semi-stateful and clear the state upon `Commit`, to ensure that all txs in the blockchain are valid. + 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 * __Returns__: @@ -73,6 +74,12 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Usage__:
Called once upon genesis +#### BeginBlock + * __Arguments__: + * `Height (uint64)`: The block height that is starting + * __Usage__:
+ Signals the beginning of a new block. Called prior to any AppendTxs. + #### EndBlock * __Arguments__: * `Height (uint64)`: The block height that ended @@ -81,18 +88,21 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions -## Changelog +### Changelog -### Mar 6th, 2016 +#### Mar 26h, 2016 +* Introduce BeginBlock + +#### Mar 6th, 2016 * Added InitChain, EndBlock -### Feb 14th, 2016 +#### Feb 14th, 2016 * s/GetHash/Commit/g * Document Protobuf request/response fields -### Jan 23th, 2016 +#### Jan 23th, 2016 * Added CheckTx/Query TMSP message types * Added Result/Log fields to AppendTx/CheckTx/SetOption @@ -100,17 +110,10 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * Removed Code from ResponseSetOption and ResponseGetHash * Made examples BigEndian -### Jan 12th, 2016 +#### Jan 12th, 2016 * Added "RetCodeBadNonce = 0x06" return code -### Jan 8th, 2016 +#### Jan 8th, 2016 -Tendermint/TMSP now comes to consensus on the order first before AppendTx. -This means that we no longer need the Commit/Rollback TMSP messages. -Instead, there’s a “CheckTx†message for mempool to check the validity of a message. -One consequence is that txs in blocks now may include invalid txs that are ignored. -In the future, we can include a bitarray or merkle structure in the block so anyone can see which txs were valid. -To prevent spam, applications can implement their “CheckTx†messages to deduct some balance, so at least spam txs will cost something. This isn’t any more work that what we already needed to do, so it’s not any worse. -You can see the new changes in the tendermint/tendermint “order_first†branch, and tendermint/tmsp “order_first†branch. If you your TMSP apps to me I can help with the transition. -Please take a look at how the examples in TMSP changed, e.g. how AppContext was removed, CheckTx was added, how the TMSP msg bytes changed, and how commit/rollback messages were removed. +* Tendermint/TMSP now comes to consensus on the order first before AppendTx. diff --git a/client/client.go b/client/client.go index acd99f60..b4adfbcd 100644 --- a/client/client.go +++ b/client/client.go @@ -28,7 +28,12 @@ type Client interface { QuerySync(tx []byte) (res types.Result) CommitSync() (res types.Result) + InitChainAsync(validators []*types.Validator) *ReqRes + BeginBlockAsync(height uint64) *ReqRes + EndBlockAsync(height uint64) *ReqRes + InitChainSync(validators []*types.Validator) (err error) + BeginBlockSync(height uint64) (err error) EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) } diff --git a/client/local_client.go b/client/local_client.go index b14164f8..28ef6f32 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -108,6 +108,44 @@ 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) + } + reqRes := app.callback( + types.RequestInitChain(validators), + types.ResponseInitChain(), + ) + app.mtx.Unlock() + return reqRes +} + +func (app *localClient) BeginBlockAsync(height uint64) *ReqRes { + app.mtx.Lock() + if bcApp, ok := app.Application.(types.BlockchainAware); ok { + bcApp.BeginBlock(height) + } + app.mtx.Unlock() + return app.callback( + types.RequestBeginBlock(height), + types.ResponseBeginBlock(), + ) +} + +func (app *localClient) EndBlockAsync(height uint64) *ReqRes { + app.mtx.Lock() + var validators []*types.Validator + if bcApp, ok := app.Application.(types.BlockchainAware); ok { + validators = bcApp.EndBlock(height) + } + app.mtx.Unlock() + return app.callback( + types.RequestEndBlock(height), + types.ResponseEndBlock(validators), + ) +} + //------------------------------------------------------- func (app *localClient) FlushSync() error { @@ -169,6 +207,15 @@ func (app *localClient) InitChainSync(validators []*types.Validator) (err error) return nil } +func (app *localClient) BeginBlockSync(height uint64) (err error) { + app.mtx.Lock() + if bcApp, ok := app.Application.(types.BlockchainAware); ok { + bcApp.BeginBlock(height) + } + app.mtx.Unlock() + return nil +} + func (app *localClient) EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) { app.mtx.Lock() if bcApp, ok := app.Application.(types.BlockchainAware); ok { diff --git a/client/remote_client.go b/client/remote_client.go index fb8a5c8e..d0aff152 100644 --- a/client/remote_client.go +++ b/client/remote_client.go @@ -246,6 +246,10 @@ func (cli *remoteClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.queueRequest(types.RequestInitChain(validators)) } +func (cli *remoteClient) BeginBlockAsync(height uint64) *ReqRes { + return cli.queueRequest(types.RequestBeginBlock(height)) +} + func (cli *remoteClient) EndBlockAsync(height uint64) *ReqRes { return cli.queueRequest(types.RequestEndBlock(height)) } @@ -336,6 +340,15 @@ func (cli *remoteClient) InitChainSync(validators []*types.Validator) (err error return nil } +func (cli *remoteClient) BeginBlockSync(height uint64) (err error) { + cli.queueRequest(types.RequestBeginBlock(height)) + cli.FlushSync() + if cli.err != nil { + return cli.err + } + return nil +} + func (cli *remoteClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { reqres := cli.queueRequest(types.RequestEndBlock(height)) cli.FlushSync() diff --git a/types/application.go b/types/application.go index d8ea4891..0d793d77 100644 --- a/types/application.go +++ b/types/application.go @@ -29,6 +29,9 @@ type BlockchainAware interface { // validators: genesis validators from TendermintCore InitChain(validators []*Validator) + // Signals the beginning of a block + BeginBlock(height uint64) + // Signals the end of a block // validators: changed validators from app to TendermintCore EndBlock(height uint64) (validators []*Validator) diff --git a/types/messages.go b/types/messages.go index af0a7109..facc3bfc 100644 --- a/types/messages.go +++ b/types/messages.go @@ -68,6 +68,13 @@ func RequestInitChain(validators []*Validator) *Request { } } +func RequestBeginBlock(height uint64) *Request { + return &Request{ + Type: MessageType_BeginBlock, + Height: height, + } +} + func RequestEndBlock(height uint64) *Request { return &Request{ Type: MessageType_EndBlock, @@ -153,6 +160,12 @@ func ResponseInitChain() *Response { } } +func ResponseBeginBlock() *Response { + return &Response{ + Type: MessageType_BeginBlock, + } +} + func ResponseEndBlock(validators []*Validator) *Response { return &Response{ Type: MessageType_EndBlock, diff --git a/types/types.pb.go b/types/types.pb.go index 96067a15..75bf1b79 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -38,8 +38,8 @@ const ( MessageType_Commit MessageType = 19 MessageType_Query MessageType = 20 MessageType_InitChain MessageType = 21 - // BeginBlock = 0x16; NOT USED - MessageType_EndBlock MessageType = 23 + MessageType_BeginBlock MessageType = 22 + MessageType_EndBlock MessageType = 23 ) var MessageType_name = map[int32]string{ @@ -54,6 +54,7 @@ var MessageType_name = map[int32]string{ 19: "Commit", 20: "Query", 21: "InitChain", + 22: "BeginBlock", 23: "EndBlock", } var MessageType_value = map[string]int32{ @@ -68,6 +69,7 @@ var MessageType_value = map[string]int32{ "Commit": 19, "Query": 20, "InitChain": 21, + "BeginBlock": 22, "EndBlock": 23, } @@ -245,50 +247,51 @@ func init() { } var fileDescriptor0 = []byte{ - // 716 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x52, 0xdb, 0x48, - 0x10, 0x5e, 0xd9, 0xb2, 0xb1, 0xdb, 0x60, 0xc6, 0x83, 0xbd, 0x68, 0xb7, 0xf6, 0x40, 0xb1, 0x55, - 0x5b, 0x14, 0x07, 0x76, 0x8b, 0x3d, 0xe5, 0x08, 0x8e, 0xa1, 0x5c, 0x14, 0xe0, 0x88, 0x9f, 0xbb, - 0x90, 0xda, 0x96, 0x62, 0x79, 0x46, 0x48, 0x23, 0xc0, 0x79, 0xa4, 0xbc, 0x00, 0x4f, 0x90, 0x43, - 0xfe, 0x7f, 0x9e, 0x28, 0x33, 0x23, 0xc9, 0x36, 0xce, 0x21, 0x87, 0x5c, 0x5c, 0xd3, 0xdf, 0x37, - 0xdd, 0xfd, 0x7d, 0x3d, 0x6d, 0x41, 0x4b, 0x4c, 0x23, 0x4c, 0xfe, 0xd5, 0xbf, 0x7b, 0x51, 0xcc, - 0x05, 0xa7, 0x15, 0x1d, 0x6c, 0x3f, 0x1a, 0xb0, 0x62, 0xe3, 0x6d, 0x8a, 0x89, 0xa0, 0xff, 0x80, - 0xa9, 0x40, 0xcb, 0xd8, 0x32, 0x76, 0x9a, 0xfb, 0x74, 0x2f, 0xbb, 0x7e, 0x8a, 0x49, 0xe2, 0x8c, - 0xf0, 0x52, 0x06, 0xb6, 0xe6, 0x29, 0x05, 0xd3, 0x73, 0x84, 0x63, 0x95, 0xe4, 0xbd, 0x55, 0x5b, - 0x9f, 0x29, 0x81, 0xf2, 0x18, 0xa7, 0x56, 0x59, 0x42, 0x75, 0x5b, 0x1d, 0x69, 0x1b, 0x2a, 0x77, - 0x4e, 0x98, 0xa2, 0x65, 0x6a, 0x2c, 0x0b, 0xe8, 0x7f, 0x00, 0xf2, 0x10, 0xc8, 0x1c, 0x1e, 0x27, - 0x56, 0x65, 0xab, 0xbc, 0xd3, 0xd8, 0x27, 0x79, 0xa7, 0xeb, 0x82, 0xb0, 0x17, 0xee, 0xd0, 0xdf, - 0xa1, 0xea, 0x63, 0x30, 0xf2, 0x85, 0x55, 0x95, 0x85, 0x4c, 0x3b, 0x8f, 0xb6, 0xdf, 0x18, 0x50, - 0xb3, 0x31, 0x89, 0x38, 0x4b, 0xf0, 0x97, 0xa4, 0xff, 0x0d, 0xa6, 0xcb, 0x3d, 0xd4, 0xda, 0x9b, - 0xfb, 0xeb, 0x79, 0x6e, 0x57, 0x42, 0x59, 0xa2, 0x22, 0x95, 0x1b, 0x8c, 0x63, 0x1e, 0x17, 0x6e, - 0x74, 0xa0, 0x5c, 0x87, 0x7c, 0x24, 0x6d, 0x68, 0xd7, 0xf2, 0xb8, 0xe4, 0xaf, 0xfa, 0x73, 0x7f, - 0xdb, 0xcf, 0xa0, 0x3e, 0x23, 0x94, 0xd9, 0x28, 0xbd, 0x39, 0x91, 0x93, 0x34, 0xb4, 0xc2, 0x3c, - 0x52, 0xed, 0x23, 0x7e, 0x8f, 0xb1, 0x16, 0x6e, 0xda, 0x59, 0xb0, 0xfb, 0xda, 0x80, 0xc6, 0x82, - 0x47, 0xba, 0x0e, 0x8d, 0xb3, 0x34, 0x0c, 0x73, 0x88, 0xfc, 0x46, 0x6b, 0x60, 0xf6, 0x5c, 0x9f, - 0x13, 0x83, 0xd6, 0xa1, 0x72, 0x14, 0xa6, 0x89, 0x4f, 0x4a, 0x0a, 0xec, 0xb3, 0x21, 0x27, 0x65, - 0xba, 0x06, 0xf5, 0x0b, 0x14, 0xe7, 0x91, 0x08, 0x38, 0x23, 0xa6, 0x0a, 0x7b, 0x0f, 0x2e, 0x66, - 0x61, 0x85, 0xae, 0x42, 0xed, 0x20, 0x8a, 0x90, 0x79, 0x97, 0x0f, 0xa4, 0x45, 0x1b, 0xb0, 0xd2, - 0xf5, 0xd1, 0x1d, 0xcb, 0x40, 0x4e, 0x11, 0xaa, 0x5d, 0x3e, 0x99, 0x04, 0x82, 0x6c, 0xa8, 0xca, - 0x2f, 0x52, 0x8c, 0xa7, 0xa4, 0xad, 0x0a, 0xf4, 0x59, 0x20, 0xba, 0xbe, 0x13, 0x30, 0xd2, 0x51, - 0x05, 0x7a, 0xcc, 0x3b, 0x0c, 0xb9, 0x3b, 0x26, 0x9b, 0xbb, 0x8f, 0x15, 0xa8, 0x15, 0x43, 0xa5, - 0x55, 0x28, 0x9d, 0x9f, 0x48, 0x81, 0x2d, 0x58, 0xeb, 0x33, 0x81, 0x31, 0x73, 0xc2, 0x9e, 0x9a, - 0xa8, 0x54, 0x2a, 0xa1, 0x1e, 0x93, 0x33, 0x0f, 0xd8, 0x28, 0x83, 0x4a, 0xaa, 0xd0, 0xa1, 0xe3, - 0x9d, 0x71, 0xe6, 0xa2, 0x54, 0x4d, 0x60, 0xf5, 0x8a, 0x39, 0xa9, 0xf0, 0x79, 0x1c, 0xbc, 0x42, - 0x4f, 0x0a, 0xef, 0x40, 0xab, 0xcf, 0x92, 0x74, 0x38, 0x0c, 0xdc, 0x00, 0x99, 0x38, 0x4a, 0x99, - 0x97, 0x48, 0x03, 0x14, 0x9a, 0x57, 0x6c, 0xcc, 0xf8, 0x3d, 0xcb, 0x37, 0x9c, 0x54, 0xa9, 0x05, - 0xed, 0x43, 0x27, 0xc1, 0xe7, 0x69, 0x14, 0x06, 0xae, 0x23, 0xf0, 0xc0, 0xf3, 0x62, 0x39, 0x2e, - 0x82, 0xaa, 0x88, 0x62, 0x9e, 0xf6, 0x1e, 0x16, 0x09, 0x4f, 0xea, 0x23, 0x26, 0x64, 0x44, 0xff, - 0x80, 0xce, 0x0f, 0x8c, 0xee, 0xec, 0xd3, 0xbf, 0xc0, 0x5a, 0xa6, 0x8e, 0x9d, 0x64, 0x10, 0x07, - 0xd2, 0x40, 0x20, 0x1f, 0x99, 0x66, 0xac, 0xde, 0x82, 0x42, 0xc1, 0xcb, 0x42, 0x41, 0x81, 0x4f, - 0x78, 0xca, 0x04, 0x19, 0x2f, 0xc1, 0x03, 0xbd, 0x10, 0x24, 0xa4, 0x9b, 0xb0, 0xb1, 0x00, 0x5f, - 0x28, 0x87, 0x6a, 0x3e, 0x93, 0xb9, 0xe2, 0x8c, 0x08, 0x46, 0xcc, 0x11, 0x69, 0x8c, 0x84, 0x15, - 0x8d, 0xf3, 0xa1, 0x14, 0x8d, 0x79, 0xd1, 0x21, 0xc7, 0xf3, 0x0e, 0xd1, 0x32, 0x1c, 0xa6, 0x23, - 0xf9, 0xac, 0xb7, 0x12, 0x26, 0xc7, 0xfc, 0x2e, 0x47, 0x7b, 0x4c, 0x04, 0x62, 0x4a, 0xde, 0x1a, - 0x72, 0x45, 0xd7, 0xe7, 0xf0, 0x71, 0xcc, 0xd3, 0x88, 0xbc, 0x33, 0xa4, 0x4a, 0x3a, 0x47, 0x07, - 0x31, 0x8f, 0x78, 0xe2, 0x84, 0xe4, 0xbd, 0x21, 0xb5, 0xb4, 0x24, 0x31, 0x7b, 0x87, 0x2c, 0xe1, - 0x43, 0x91, 0x30, 0xc3, 0x4f, 0x71, 0x72, 0x83, 0x31, 0xf9, 0x68, 0xc8, 0x71, 0xb7, 0x17, 0x89, - 0x59, 0xad, 0x4f, 0x46, 0xae, 0x68, 0x46, 0x5d, 0x73, 0x81, 0xe4, 0x73, 0x01, 0xe7, 0x73, 0xc8, - 0x0b, 0x7d, 0x31, 0xe8, 0x06, 0x34, 0xe7, 0xb0, 0xbe, 0xfb, 0xd5, 0xa0, 0x7f, 0x42, 0xe7, 0x09, - 0x28, 0x37, 0x60, 0xa0, 0xfe, 0x63, 0xe4, 0x9b, 0x71, 0x53, 0xd5, 0x5f, 0xcc, 0xff, 0xbf, 0x07, - 0x00, 0x00, 0xff, 0xff, 0x91, 0x57, 0x50, 0xd8, 0x46, 0x05, 0x00, 0x00, + // 722 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x53, 0xeb, 0x36, + 0x14, 0xad, 0x13, 0x27, 0x24, 0x37, 0x10, 0x14, 0x91, 0x80, 0xdb, 0xe9, 0x82, 0xa1, 0x33, 0x1d, + 0x86, 0x05, 0xed, 0xd0, 0x55, 0x97, 0x24, 0x0d, 0x4c, 0x86, 0x01, 0x52, 0xf3, 0xb1, 0x37, 0xf6, + 0x4d, 0xac, 0xc6, 0x91, 0x8c, 0x2d, 0x03, 0xe9, 0x1f, 0x63, 0xa6, 0xfb, 0x2e, 0xde, 0xf7, 0xc7, + 0x2f, 0x7a, 0x92, 0x3f, 0x92, 0x90, 0xb7, 0x78, 0x8b, 0xb7, 0xc9, 0xe8, 0x9c, 0x23, 0xdd, 0x7b, + 0xce, 0x95, 0x62, 0x68, 0xc9, 0x59, 0x88, 0xf1, 0x6f, 0xe9, 0xef, 0x61, 0x18, 0x09, 0x29, 0x68, + 0x25, 0x05, 0x7b, 0xcf, 0x06, 0xac, 0xd9, 0x78, 0x9f, 0x60, 0x2c, 0xe9, 0xaf, 0x60, 0x6a, 0xd2, + 0x32, 0x76, 0x8d, 0xfd, 0xe6, 0x11, 0x3d, 0xcc, 0xb6, 0x9f, 0x63, 0x1c, 0x3b, 0x63, 0xbc, 0x56, + 0xc0, 0x4e, 0x75, 0x4a, 0xc1, 0xf4, 0x1c, 0xe9, 0x58, 0x25, 0xb5, 0x6f, 0xdd, 0x4e, 0xd7, 0x94, + 0x40, 0x79, 0x82, 0x33, 0xab, 0xac, 0xa8, 0xba, 0xad, 0x97, 0xb4, 0x0d, 0x95, 0x07, 0x27, 0x48, + 0xd0, 0x32, 0x53, 0x2e, 0x03, 0xf4, 0x77, 0x00, 0xb5, 0x60, 0xea, 0x8c, 0x88, 0x62, 0xab, 0xb2, + 0x5b, 0xde, 0x6f, 0x1c, 0x91, 0xbc, 0xd3, 0x6d, 0x21, 0xd8, 0x4b, 0x7b, 0xe8, 0x36, 0x54, 0x7d, + 0x64, 0x63, 0x5f, 0x5a, 0x55, 0x55, 0xc8, 0xb4, 0x73, 0xb4, 0xf7, 0xbf, 0x01, 0x35, 0x1b, 0xe3, + 0x50, 0xf0, 0x18, 0xbf, 0xcb, 0xfa, 0x2f, 0x60, 0xba, 0xc2, 0xc3, 0xd4, 0x7b, 0xf3, 0x68, 0x33, + 0x3f, 0xdb, 0x53, 0x54, 0x76, 0x50, 0x8b, 0x3a, 0x0d, 0x46, 0x91, 0x88, 0x8a, 0x34, 0x29, 0xd0, + 0xa9, 0x03, 0x31, 0x56, 0x31, 0xd2, 0xd4, 0x6a, 0xb9, 0x92, 0xaf, 0xfa, 0xed, 0x7c, 0x7b, 0x7f, + 0x42, 0x7d, 0x2e, 0xe8, 0xb0, 0x61, 0x72, 0x77, 0xa6, 0x26, 0x69, 0xa4, 0x0e, 0x73, 0xa4, 0xdb, + 0x87, 0xe2, 0x11, 0xa3, 0xd4, 0xb8, 0x69, 0x67, 0xe0, 0xe0, 0x3f, 0x03, 0x1a, 0x4b, 0x19, 0xe9, + 0x26, 0x34, 0x2e, 0x92, 0x20, 0xc8, 0x29, 0xf2, 0x03, 0xad, 0x81, 0xd9, 0x77, 0x7d, 0x41, 0x0c, + 0x5a, 0x87, 0xca, 0x49, 0x90, 0xc4, 0x3e, 0x29, 0x69, 0x72, 0xc0, 0x47, 0x82, 0x94, 0xe9, 0x06, + 0xd4, 0xaf, 0x50, 0x5e, 0x86, 0x92, 0x09, 0x4e, 0x4c, 0x0d, 0xfb, 0x4f, 0x2e, 0x66, 0xb0, 0x42, + 0xd7, 0xa1, 0x76, 0x1c, 0x86, 0xc8, 0xbd, 0xeb, 0x27, 0xd2, 0xa2, 0x0d, 0x58, 0xeb, 0xf9, 0xe8, + 0x4e, 0x14, 0x50, 0x53, 0x84, 0x6a, 0x4f, 0x4c, 0xa7, 0x4c, 0x92, 0x2d, 0x5d, 0xf9, 0xef, 0x04, + 0xa3, 0x19, 0x69, 0xeb, 0x02, 0x03, 0xce, 0x64, 0xcf, 0x77, 0x18, 0x27, 0x1d, 0xda, 0x04, 0xe8, + 0xe2, 0x98, 0xf1, 0x6e, 0x20, 0xdc, 0x09, 0xd9, 0xd6, 0x05, 0xfb, 0xdc, 0xcb, 0xd0, 0xce, 0xc1, + 0x73, 0x05, 0x6a, 0xc5, 0x90, 0x69, 0x15, 0x4a, 0x97, 0x67, 0xca, 0x70, 0x0b, 0x36, 0x06, 0x5c, + 0x62, 0xc4, 0x9d, 0xa0, 0xaf, 0x27, 0xac, 0x9c, 0x2b, 0xaa, 0xcf, 0xd5, 0x1d, 0x30, 0x3e, 0xce, + 0xa8, 0x92, 0x2e, 0xd4, 0x75, 0xbc, 0x0b, 0xc1, 0x5d, 0x54, 0x29, 0x08, 0xac, 0xdf, 0x70, 0x27, + 0x91, 0xbe, 0x88, 0xd8, 0xbf, 0xe8, 0xa9, 0x20, 0x1d, 0x68, 0x0d, 0x78, 0x9c, 0x8c, 0x46, 0xcc, + 0x65, 0xc8, 0xe5, 0x49, 0xc2, 0xbd, 0x58, 0x05, 0xa2, 0xd0, 0xbc, 0xe1, 0x13, 0x2e, 0x1e, 0x79, + 0xfe, 0xe2, 0x49, 0x95, 0x5a, 0xd0, 0xee, 0x3a, 0x31, 0xfe, 0x95, 0x84, 0x01, 0x73, 0x1d, 0x89, + 0xc7, 0x9e, 0x17, 0xa9, 0xf1, 0x11, 0xd4, 0x45, 0xb4, 0xf2, 0xb2, 0xf7, 0xa8, 0x38, 0xf0, 0xa2, + 0x3e, 0x62, 0x4c, 0xc6, 0xf4, 0x47, 0xe8, 0x7c, 0xa5, 0xa4, 0x9d, 0x7d, 0xfa, 0x33, 0x58, 0xab, + 0xd2, 0xa9, 0x13, 0x0f, 0x23, 0xa6, 0x02, 0x30, 0x75, 0xe9, 0x34, 0x53, 0xd3, 0x57, 0x51, 0x38, + 0xf8, 0xa7, 0x70, 0x50, 0xf0, 0x53, 0x91, 0x70, 0x49, 0x26, 0x2b, 0xf4, 0x30, 0x7d, 0x20, 0x24, + 0xa0, 0x3b, 0xb0, 0xb5, 0x44, 0x5f, 0xe9, 0x84, 0x7a, 0x3e, 0xd3, 0x85, 0xe3, 0x4c, 0x60, 0x63, + 0xee, 0xc8, 0x24, 0x42, 0xc2, 0x8b, 0xc6, 0xf9, 0x50, 0x8a, 0xc6, 0xa2, 0xe8, 0x90, 0xf3, 0x79, + 0x87, 0x70, 0x95, 0x0e, 0x12, 0x75, 0xb7, 0xe4, 0x5e, 0xd1, 0xe4, 0x54, 0x3c, 0xe4, 0x6c, 0x9f, + 0x4b, 0x26, 0x67, 0xe4, 0x95, 0xa1, 0x9e, 0xec, 0xe6, 0x82, 0x3e, 0x8d, 0x44, 0x12, 0x92, 0xd7, + 0x86, 0x72, 0x49, 0x17, 0xec, 0x30, 0x12, 0xa1, 0x88, 0x9d, 0x80, 0xbc, 0x31, 0x94, 0x97, 0x96, + 0x12, 0xe6, 0xf7, 0x90, 0x1d, 0x78, 0x5b, 0x1c, 0x98, 0xf3, 0xe7, 0x38, 0xbd, 0xc3, 0x88, 0xbc, + 0x33, 0xd4, 0xb8, 0xdb, 0xcb, 0xc2, 0xbc, 0xd6, 0x7b, 0x23, 0x77, 0x34, 0x97, 0x6e, 0x85, 0x44, + 0xf2, 0xa1, 0xa0, 0xf3, 0x39, 0xe4, 0x85, 0x3e, 0x1a, 0x74, 0x0b, 0x9a, 0x0b, 0x3a, 0xdd, 0xfb, + 0xc9, 0xa0, 0x3f, 0x41, 0xe7, 0x05, 0xa9, 0x5e, 0xc0, 0x50, 0xff, 0xe7, 0xc8, 0x67, 0xe3, 0xae, + 0x9a, 0x7e, 0x41, 0xff, 0xf8, 0x12, 0x00, 0x00, 0xff, 0xff, 0x65, 0x9a, 0x2e, 0x13, 0x56, 0x05, + 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 12ae6d29..8bead59a 100644 --- a/types/types.proto +++ b/types/types.proto @@ -19,7 +19,7 @@ enum MessageType { Commit = 0x13; Query = 0x14; InitChain = 0x15; - // BeginBlock = 0x16; NOT USED + BeginBlock = 0x16; EndBlock = 0x17; } From ca95184373680029dc310ec7f0e1841de9e4a951 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 13 Apr 2016 14:42:00 -0700 Subject: [PATCH 102/545] s/Invalid[Address,Amount]/Invalid[Input,Output]/g --- types/errors.go | 4 +- types/types.pb.go | 106 +++++++++++++++++++++++----------------------- types/types.proto | 4 +- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/types/errors.go b/types/errors.go index 475e92fe..7fa1f009 100644 --- a/types/errors.go +++ b/types/errors.go @@ -15,8 +15,8 @@ var ( ErrBaseInsufficientFees = NewError(CodeType_BaseInsufficientFees, "Error (base) insufficient fees") ErrBaseInsufficientFunds = NewError(CodeType_BaseInsufficientFunds, "Error (base) insufficient funds") ErrBaseInsufficientGasPrice = NewError(CodeType_BaseInsufficientGasPrice, "Error (base) insufficient gas price") - ErrBaseInvalidAddress = NewError(CodeType_BaseInvalidAddress, "Error (base) invalid address") - ErrBaseInvalidAmount = NewError(CodeType_BaseInvalidAmount, "Error (base) invalid amount") + ErrBaseInvalidInput = NewError(CodeType_BaseInvalidInput, "Error (base) invalid input") + ErrBaseInvalidOutput = NewError(CodeType_BaseInvalidOutput, "Error (base) invalid output") ErrBaseInvalidPubKey = NewError(CodeType_BaseInvalidPubKey, "Error (base) invalid pubkey") ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error (base) invalid sequence") ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error (base) invalid signature") diff --git a/types/types.pb.go b/types/types.pb.go index 75bf1b79..933e62ca 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -95,8 +95,8 @@ const ( CodeType_BaseInsufficientFees CodeType = 103 CodeType_BaseInsufficientFunds CodeType = 104 CodeType_BaseInsufficientGasPrice CodeType = 105 - CodeType_BaseInvalidAddress CodeType = 106 - CodeType_BaseInvalidAmount CodeType = 107 + CodeType_BaseInvalidInput CodeType = 106 + CodeType_BaseInvalidOutput CodeType = 107 CodeType_BaseInvalidPubKey CodeType = 108 CodeType_BaseInvalidSequence CodeType = 109 CodeType_BaseInvalidSignature CodeType = 110 @@ -129,8 +129,8 @@ var CodeType_name = map[int32]string{ 103: "BaseInsufficientFees", 104: "BaseInsufficientFunds", 105: "BaseInsufficientGasPrice", - 106: "BaseInvalidAddress", - 107: "BaseInvalidAmount", + 106: "BaseInvalidInput", + 107: "BaseInvalidOutput", 108: "BaseInvalidPubKey", 109: "BaseInvalidSequence", 110: "BaseInvalidSignature", @@ -161,8 +161,8 @@ var CodeType_value = map[string]int32{ "BaseInsufficientFees": 103, "BaseInsufficientFunds": 104, "BaseInsufficientGasPrice": 105, - "BaseInvalidAddress": 106, - "BaseInvalidAmount": 107, + "BaseInvalidInput": 106, + "BaseInvalidOutput": 107, "BaseInvalidPubKey": 108, "BaseInvalidSequence": 109, "BaseInvalidSignature": 110, @@ -247,51 +247,51 @@ func init() { } var fileDescriptor0 = []byte{ - // 722 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x53, 0xeb, 0x36, - 0x14, 0xad, 0x13, 0x27, 0x24, 0x37, 0x10, 0x14, 0x91, 0x80, 0xdb, 0xe9, 0x82, 0xa1, 0x33, 0x1d, - 0x86, 0x05, 0xed, 0xd0, 0x55, 0x97, 0x24, 0x0d, 0x4c, 0x86, 0x01, 0x52, 0xf3, 0xb1, 0x37, 0xf6, - 0x4d, 0xac, 0xc6, 0x91, 0x8c, 0x2d, 0x03, 0xe9, 0x1f, 0x63, 0xa6, 0xfb, 0x2e, 0xde, 0xf7, 0xc7, - 0x2f, 0x7a, 0x92, 0x3f, 0x92, 0x90, 0xb7, 0x78, 0x8b, 0xb7, 0xc9, 0xe8, 0x9c, 0x23, 0xdd, 0x7b, - 0xce, 0x95, 0x62, 0x68, 0xc9, 0x59, 0x88, 0xf1, 0x6f, 0xe9, 0xef, 0x61, 0x18, 0x09, 0x29, 0x68, - 0x25, 0x05, 0x7b, 0xcf, 0x06, 0xac, 0xd9, 0x78, 0x9f, 0x60, 0x2c, 0xe9, 0xaf, 0x60, 0x6a, 0xd2, - 0x32, 0x76, 0x8d, 0xfd, 0xe6, 0x11, 0x3d, 0xcc, 0xb6, 0x9f, 0x63, 0x1c, 0x3b, 0x63, 0xbc, 0x56, - 0xc0, 0x4e, 0x75, 0x4a, 0xc1, 0xf4, 0x1c, 0xe9, 0x58, 0x25, 0xb5, 0x6f, 0xdd, 0x4e, 0xd7, 0x94, - 0x40, 0x79, 0x82, 0x33, 0xab, 0xac, 0xa8, 0xba, 0xad, 0x97, 0xb4, 0x0d, 0x95, 0x07, 0x27, 0x48, - 0xd0, 0x32, 0x53, 0x2e, 0x03, 0xf4, 0x77, 0x00, 0xb5, 0x60, 0xea, 0x8c, 0x88, 0x62, 0xab, 0xb2, - 0x5b, 0xde, 0x6f, 0x1c, 0x91, 0xbc, 0xd3, 0x6d, 0x21, 0xd8, 0x4b, 0x7b, 0xe8, 0x36, 0x54, 0x7d, - 0x64, 0x63, 0x5f, 0x5a, 0x55, 0x55, 0xc8, 0xb4, 0x73, 0xb4, 0xf7, 0xbf, 0x01, 0x35, 0x1b, 0xe3, - 0x50, 0xf0, 0x18, 0xbf, 0xcb, 0xfa, 0x2f, 0x60, 0xba, 0xc2, 0xc3, 0xd4, 0x7b, 0xf3, 0x68, 0x33, - 0x3f, 0xdb, 0x53, 0x54, 0x76, 0x50, 0x8b, 0x3a, 0x0d, 0x46, 0x91, 0x88, 0x8a, 0x34, 0x29, 0xd0, - 0xa9, 0x03, 0x31, 0x56, 0x31, 0xd2, 0xd4, 0x6a, 0xb9, 0x92, 0xaf, 0xfa, 0xed, 0x7c, 0x7b, 0x7f, - 0x42, 0x7d, 0x2e, 0xe8, 0xb0, 0x61, 0x72, 0x77, 0xa6, 0x26, 0x69, 0xa4, 0x0e, 0x73, 0xa4, 0xdb, - 0x87, 0xe2, 0x11, 0xa3, 0xd4, 0xb8, 0x69, 0x67, 0xe0, 0xe0, 0x3f, 0x03, 0x1a, 0x4b, 0x19, 0xe9, - 0x26, 0x34, 0x2e, 0x92, 0x20, 0xc8, 0x29, 0xf2, 0x03, 0xad, 0x81, 0xd9, 0x77, 0x7d, 0x41, 0x0c, - 0x5a, 0x87, 0xca, 0x49, 0x90, 0xc4, 0x3e, 0x29, 0x69, 0x72, 0xc0, 0x47, 0x82, 0x94, 0xe9, 0x06, - 0xd4, 0xaf, 0x50, 0x5e, 0x86, 0x92, 0x09, 0x4e, 0x4c, 0x0d, 0xfb, 0x4f, 0x2e, 0x66, 0xb0, 0x42, - 0xd7, 0xa1, 0x76, 0x1c, 0x86, 0xc8, 0xbd, 0xeb, 0x27, 0xd2, 0xa2, 0x0d, 0x58, 0xeb, 0xf9, 0xe8, - 0x4e, 0x14, 0x50, 0x53, 0x84, 0x6a, 0x4f, 0x4c, 0xa7, 0x4c, 0x92, 0x2d, 0x5d, 0xf9, 0xef, 0x04, - 0xa3, 0x19, 0x69, 0xeb, 0x02, 0x03, 0xce, 0x64, 0xcf, 0x77, 0x18, 0x27, 0x1d, 0xda, 0x04, 0xe8, - 0xe2, 0x98, 0xf1, 0x6e, 0x20, 0xdc, 0x09, 0xd9, 0xd6, 0x05, 0xfb, 0xdc, 0xcb, 0xd0, 0xce, 0xc1, - 0x73, 0x05, 0x6a, 0xc5, 0x90, 0x69, 0x15, 0x4a, 0x97, 0x67, 0xca, 0x70, 0x0b, 0x36, 0x06, 0x5c, - 0x62, 0xc4, 0x9d, 0xa0, 0xaf, 0x27, 0xac, 0x9c, 0x2b, 0xaa, 0xcf, 0xd5, 0x1d, 0x30, 0x3e, 0xce, - 0xa8, 0x92, 0x2e, 0xd4, 0x75, 0xbc, 0x0b, 0xc1, 0x5d, 0x54, 0x29, 0x08, 0xac, 0xdf, 0x70, 0x27, - 0x91, 0xbe, 0x88, 0xd8, 0xbf, 0xe8, 0xa9, 0x20, 0x1d, 0x68, 0x0d, 0x78, 0x9c, 0x8c, 0x46, 0xcc, - 0x65, 0xc8, 0xe5, 0x49, 0xc2, 0xbd, 0x58, 0x05, 0xa2, 0xd0, 0xbc, 0xe1, 0x13, 0x2e, 0x1e, 0x79, - 0xfe, 0xe2, 0x49, 0x95, 0x5a, 0xd0, 0xee, 0x3a, 0x31, 0xfe, 0x95, 0x84, 0x01, 0x73, 0x1d, 0x89, - 0xc7, 0x9e, 0x17, 0xa9, 0xf1, 0x11, 0xd4, 0x45, 0xb4, 0xf2, 0xb2, 0xf7, 0xa8, 0x38, 0xf0, 0xa2, - 0x3e, 0x62, 0x4c, 0xc6, 0xf4, 0x47, 0xe8, 0x7c, 0xa5, 0xa4, 0x9d, 0x7d, 0xfa, 0x33, 0x58, 0xab, - 0xd2, 0xa9, 0x13, 0x0f, 0x23, 0xa6, 0x02, 0x30, 0x75, 0xe9, 0x34, 0x53, 0xd3, 0x57, 0x51, 0x38, - 0xf8, 0xa7, 0x70, 0x50, 0xf0, 0x53, 0x91, 0x70, 0x49, 0x26, 0x2b, 0xf4, 0x30, 0x7d, 0x20, 0x24, - 0xa0, 0x3b, 0xb0, 0xb5, 0x44, 0x5f, 0xe9, 0x84, 0x7a, 0x3e, 0xd3, 0x85, 0xe3, 0x4c, 0x60, 0x63, - 0xee, 0xc8, 0x24, 0x42, 0xc2, 0x8b, 0xc6, 0xf9, 0x50, 0x8a, 0xc6, 0xa2, 0xe8, 0x90, 0xf3, 0x79, - 0x87, 0x70, 0x95, 0x0e, 0x12, 0x75, 0xb7, 0xe4, 0x5e, 0xd1, 0xe4, 0x54, 0x3c, 0xe4, 0x6c, 0x9f, - 0x4b, 0x26, 0x67, 0xe4, 0x95, 0xa1, 0x9e, 0xec, 0xe6, 0x82, 0x3e, 0x8d, 0x44, 0x12, 0x92, 0xd7, - 0x86, 0x72, 0x49, 0x17, 0xec, 0x30, 0x12, 0xa1, 0x88, 0x9d, 0x80, 0xbc, 0x31, 0x94, 0x97, 0x96, - 0x12, 0xe6, 0xf7, 0x90, 0x1d, 0x78, 0x5b, 0x1c, 0x98, 0xf3, 0xe7, 0x38, 0xbd, 0xc3, 0x88, 0xbc, - 0x33, 0xd4, 0xb8, 0xdb, 0xcb, 0xc2, 0xbc, 0xd6, 0x7b, 0x23, 0x77, 0x34, 0x97, 0x6e, 0x85, 0x44, - 0xf2, 0xa1, 0xa0, 0xf3, 0x39, 0xe4, 0x85, 0x3e, 0x1a, 0x74, 0x0b, 0x9a, 0x0b, 0x3a, 0xdd, 0xfb, - 0xc9, 0xa0, 0x3f, 0x41, 0xe7, 0x05, 0xa9, 0x5e, 0xc0, 0x50, 0xff, 0xe7, 0xc8, 0x67, 0xe3, 0xae, - 0x9a, 0x7e, 0x41, 0xff, 0xf8, 0x12, 0x00, 0x00, 0xff, 0xff, 0x65, 0x9a, 0x2e, 0x13, 0x56, 0x05, - 0x00, 0x00, + // 729 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x94, 0x4b, 0x4f, 0xeb, 0x46, + 0x14, 0xc7, 0xeb, 0xc4, 0x09, 0xc9, 0x09, 0x84, 0xc9, 0x90, 0x80, 0x5b, 0x75, 0x81, 0xa8, 0x54, + 0x21, 0x16, 0xb4, 0xa2, 0xab, 0x2e, 0x49, 0x1a, 0x50, 0x84, 0x80, 0xd4, 0x3c, 0xf6, 0xc6, 0x3e, + 0x89, 0xa7, 0x71, 0x66, 0x8c, 0x3d, 0x06, 0xd2, 0xef, 0x55, 0x55, 0xba, 0xfb, 0xbb, 0xb8, 0xef, + 0xc7, 0x27, 0xba, 0x33, 0x7e, 0x24, 0x21, 0x77, 0x71, 0x17, 0x77, 0x13, 0xcd, 0xf9, 0xfd, 0x67, + 0xce, 0x39, 0xff, 0x33, 0x13, 0x43, 0x4b, 0xce, 0x42, 0x8c, 0x7f, 0x4b, 0x7f, 0x0f, 0xc3, 0x48, + 0x48, 0x41, 0x2b, 0x69, 0xb0, 0xf7, 0xbf, 0x01, 0x6b, 0x36, 0xde, 0x27, 0x18, 0x4b, 0xfa, 0x2b, + 0x98, 0x1a, 0x5a, 0xc6, 0xae, 0xb1, 0xdf, 0x3c, 0xa2, 0x87, 0xd9, 0xf6, 0x73, 0x8c, 0x63, 0x67, + 0x8c, 0xd7, 0x2a, 0xb0, 0x53, 0x9d, 0x52, 0x30, 0x3d, 0x47, 0x3a, 0x56, 0x49, 0xed, 0x5b, 0xb7, + 0xd3, 0x35, 0x25, 0x50, 0x9e, 0xe0, 0xcc, 0x2a, 0x2b, 0x54, 0xb7, 0xf5, 0x92, 0xb6, 0xa1, 0xf2, + 0xe0, 0x04, 0x09, 0x5a, 0x66, 0xca, 0xb2, 0x80, 0xfe, 0x0e, 0xa0, 0x16, 0x4c, 0x9d, 0x11, 0x51, + 0x6c, 0x55, 0x76, 0xcb, 0xfb, 0x8d, 0x23, 0x92, 0x57, 0xba, 0x2d, 0x04, 0x7b, 0x69, 0x0f, 0xdd, + 0x86, 0xaa, 0x8f, 0x6c, 0xec, 0x4b, 0xab, 0xaa, 0x12, 0x99, 0x76, 0x1e, 0xed, 0xbd, 0x34, 0xa0, + 0x66, 0x63, 0x1c, 0x0a, 0x1e, 0xe3, 0x77, 0xb5, 0xfe, 0x0b, 0x98, 0xae, 0xf0, 0x30, 0xed, 0xbd, + 0x79, 0xb4, 0x99, 0x9f, 0xed, 0x29, 0x94, 0x1d, 0xd4, 0xa2, 0x76, 0x83, 0x51, 0x24, 0xa2, 0xc2, + 0x4d, 0x1a, 0x68, 0xd7, 0x81, 0x18, 0x2b, 0x1b, 0xa9, 0x6b, 0xb5, 0x5c, 0xf1, 0x57, 0xfd, 0xb6, + 0xbf, 0xbd, 0x3f, 0xa1, 0x3e, 0x17, 0xb4, 0xd9, 0x30, 0xb9, 0x3b, 0x53, 0x93, 0x34, 0xd2, 0x0e, + 0xf3, 0x48, 0x97, 0x0f, 0xc5, 0x23, 0x46, 0x69, 0xe3, 0xa6, 0x9d, 0x05, 0x07, 0x2f, 0x0c, 0x68, + 0x2c, 0x79, 0xa4, 0x9b, 0xd0, 0xb8, 0x48, 0x82, 0x20, 0x47, 0xe4, 0x07, 0x5a, 0x03, 0xb3, 0xef, + 0xfa, 0x82, 0x18, 0xb4, 0x0e, 0x95, 0x93, 0x20, 0x89, 0x7d, 0x52, 0xd2, 0x70, 0xc0, 0x47, 0x82, + 0x94, 0xe9, 0x06, 0xd4, 0xaf, 0x50, 0x5e, 0x86, 0x92, 0x09, 0x4e, 0x4c, 0x1d, 0xf6, 0x9f, 0x5c, + 0xcc, 0xc2, 0x0a, 0x5d, 0x87, 0xda, 0x71, 0x18, 0x22, 0xf7, 0xae, 0x9f, 0x48, 0x8b, 0x36, 0x60, + 0xad, 0xe7, 0xa3, 0x3b, 0x51, 0x81, 0x9a, 0x22, 0x54, 0x7b, 0x62, 0x3a, 0x65, 0x92, 0x6c, 0xe9, + 0xcc, 0x7f, 0x27, 0x18, 0xcd, 0x48, 0x5b, 0x27, 0x18, 0x70, 0x26, 0x7b, 0xbe, 0xc3, 0x38, 0xe9, + 0xd0, 0x26, 0x40, 0x17, 0xc7, 0x8c, 0x77, 0x03, 0xe1, 0x4e, 0xc8, 0xb6, 0x4e, 0xd8, 0xe7, 0x5e, + 0x16, 0xed, 0x1c, 0xfc, 0x57, 0x81, 0x5a, 0x31, 0x64, 0x5a, 0x85, 0xd2, 0xe5, 0x99, 0x6a, 0xb8, + 0x05, 0x1b, 0x03, 0x2e, 0x31, 0xe2, 0x4e, 0xd0, 0xd7, 0x13, 0x56, 0x9d, 0x2b, 0xd4, 0xe7, 0xea, + 0x0e, 0x18, 0x1f, 0x67, 0xa8, 0xa4, 0x13, 0x75, 0x1d, 0xef, 0x42, 0x70, 0x17, 0x95, 0x0b, 0x02, + 0xeb, 0x37, 0xdc, 0x49, 0xa4, 0x2f, 0x22, 0xf6, 0x2f, 0x7a, 0xca, 0x48, 0x07, 0x5a, 0x03, 0x1e, + 0x27, 0xa3, 0x11, 0x73, 0x19, 0x72, 0x79, 0x92, 0x70, 0x2f, 0x56, 0x86, 0x28, 0x34, 0x6f, 0xf8, + 0x84, 0x8b, 0x47, 0x9e, 0xbf, 0x78, 0x52, 0xa5, 0x16, 0xb4, 0xbb, 0x4e, 0x8c, 0x7f, 0x25, 0x61, + 0xc0, 0x5c, 0x47, 0xe2, 0xb1, 0xe7, 0x45, 0x6a, 0x7c, 0x04, 0x75, 0x12, 0xad, 0x3c, 0xaf, 0x3d, + 0x2a, 0x0e, 0x3c, 0xcb, 0x8f, 0x18, 0x93, 0x31, 0xfd, 0x11, 0x3a, 0x5f, 0x29, 0x69, 0x65, 0x9f, + 0xfe, 0x0c, 0xd6, 0xaa, 0x74, 0xea, 0xc4, 0xc3, 0x88, 0x29, 0x03, 0x4c, 0x5d, 0x2e, 0xc9, 0xd4, + 0xf4, 0x55, 0x0c, 0x78, 0x98, 0x48, 0xf2, 0x4f, 0x51, 0x3f, 0xa7, 0x97, 0x89, 0xd4, 0x78, 0xb2, + 0x82, 0x87, 0xe9, 0xf3, 0x20, 0x01, 0xdd, 0x81, 0xad, 0x25, 0x7c, 0xa5, 0xfd, 0xe9, 0xe9, 0x4c, + 0x17, 0xfd, 0x66, 0x02, 0x1b, 0x73, 0x47, 0x26, 0x11, 0x12, 0xae, 0xde, 0x1a, 0xd5, 0x4a, 0x3e, + 0x92, 0xc2, 0xb8, 0x28, 0x2a, 0xe4, 0x3c, 0xaf, 0x10, 0xae, 0xe2, 0x20, 0x51, 0x37, 0x4b, 0xee, + 0x15, 0x26, 0xa7, 0xe2, 0x21, 0xa7, 0x7d, 0x2e, 0x99, 0x9c, 0x91, 0x57, 0x86, 0xf2, 0xb4, 0xb9, + 0xc0, 0xa7, 0x91, 0x48, 0x42, 0xf2, 0xda, 0x50, 0x5d, 0xd2, 0x05, 0x1d, 0x46, 0x22, 0x14, 0xb1, + 0x13, 0x90, 0x37, 0x86, 0xea, 0xa5, 0xa5, 0x84, 0xf9, 0x2d, 0x64, 0x07, 0xde, 0x16, 0x07, 0xe6, + 0xfc, 0x1c, 0xa7, 0x77, 0x18, 0x91, 0x77, 0x86, 0x1a, 0x76, 0x7b, 0x59, 0x98, 0xe7, 0x7a, 0x6f, + 0xe4, 0x1d, 0xcd, 0xa5, 0x5b, 0x21, 0x91, 0x7c, 0x28, 0x70, 0x3e, 0x87, 0x3c, 0xd1, 0x47, 0x83, + 0x6e, 0x41, 0x73, 0x81, 0xd3, 0xbd, 0x9f, 0x0c, 0xfa, 0x13, 0x74, 0x9e, 0x41, 0x75, 0xff, 0x43, + 0xfd, 0x8f, 0x23, 0x9f, 0x8d, 0xbb, 0x6a, 0xfa, 0xfd, 0xfc, 0xe3, 0x4b, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xc9, 0xcf, 0x96, 0x2d, 0x54, 0x05, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 8bead59a..37a4fa6a 100644 --- a/types/types.proto +++ b/types/types.proto @@ -43,8 +43,8 @@ enum CodeType { BaseInsufficientFees = 103; BaseInsufficientFunds = 104; BaseInsufficientGasPrice = 105; - BaseInvalidAddress = 106; - BaseInvalidAmount = 107; + BaseInvalidInput = 106; + BaseInvalidOutput = 107; BaseInvalidPubKey = 108; BaseInvalidSequence = 109; BaseInvalidSignature = 110; From d471b06bd8ddb12f7275d49422b9b376dbdd84ad Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 15 Apr 2016 15:01:05 -0700 Subject: [PATCH 103/545] Added C++ and Javascript impls --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6c35736e..26035705 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ to manage a blockchain application state, running in another. For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/). +Other implementations: +* [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen +* [js-tmsp](https://github.com/tendermint/js-tmsp) + ## Message types TMSP requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/tmsp/blob/master/types/types.proto). From 9a8d40b87cceeb44117c6ae08fa0ff636747d3c8 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 4 May 2016 13:37:22 -0700 Subject: [PATCH 104/545] Update README.md --- README.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 26035705..6c842083 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen * [js-tmsp](https://github.com/tendermint/js-tmsp) +## Message format + +Since this is a streaming protocol, all messages are encoded with a length-prefix followed by the message encoded in Protobuf3. Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. + +For example, if the Protobuf3 encoded TMSP message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded TMSP message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. + ## Message types TMSP requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/tmsp/blob/master/types/types.proto). @@ -92,21 +98,21 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions -### Changelog +## Changelog -#### Mar 26h, 2016 +##### Mar 26h, 2016 * Introduce BeginBlock -#### Mar 6th, 2016 +##### Mar 6th, 2016 * Added InitChain, EndBlock -#### Feb 14th, 2016 +##### Feb 14th, 2016 * s/GetHash/Commit/g * Document Protobuf request/response fields -#### Jan 23th, 2016 +##### Jan 23th, 2016 * Added CheckTx/Query TMSP message types * Added Result/Log fields to AppendTx/CheckTx/SetOption @@ -114,10 +120,10 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * Removed Code from ResponseSetOption and ResponseGetHash * Made examples BigEndian -#### Jan 12th, 2016 +##### Jan 12th, 2016 * Added "RetCodeBadNonce = 0x06" return code -#### Jan 8th, 2016 +##### Jan 8th, 2016 * Tendermint/TMSP now comes to consensus on the order first before AppendTx. From 3910f871dd5c3acb3c9b305abafd570f7106ebd4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 5 May 2016 13:58:10 -0700 Subject: [PATCH 105/545] Trivial --- types/application.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/types/application.go b/types/application.go index 0d793d77..65ca9ab0 100644 --- a/types/application.go +++ b/types/application.go @@ -15,11 +15,11 @@ type Application interface { // Validate a tx for the mempool CheckTx(tx []byte) Result - // Return the application Merkle root hash - Commit() Result - // Query for state Query(query []byte) Result + + // Return the application Merkle root hash + Commit() Result } // Some applications can choose to implement BlockchainAware @@ -33,6 +33,6 @@ type BlockchainAware interface { BeginBlock(height uint64) // Signals the end of a block - // validators: changed validators from app to TendermintCore - EndBlock(height uint64) (validators []*Validator) + // diffs: changed validators from app to TendermintCore + EndBlock(height uint64) (diffs []*Validator) } From 7ffd2899092f47110a5ffebe20247a9b7f80f4ad Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 5 May 2016 14:11:18 -0700 Subject: [PATCH 106/545] Conform to new codegangsta.cli ActionFunc interface --- cmd/tmsp-cli/tmsp-cli.go | 125 ++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 986a4dd8..275bb23a 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -33,69 +33,72 @@ func main() { { Name: "batch", Usage: "Run a batch of tmsp commands against an application", - Action: func(c *cli.Context) { - cmdBatch(app, c) + Action: func(c *cli.Context) error { + return cmdBatch(app, c) }, }, { Name: "console", Usage: "Start an interactive tmsp console for multiple commands", - Action: func(c *cli.Context) { - cmdConsole(app, c) + Action: func(c *cli.Context) error { + return cmdConsole(app, c) }, }, { Name: "echo", Usage: "Have the application echo a message", - Action: func(c *cli.Context) { - cmdEcho(c) + Action: func(c *cli.Context) error { + return cmdEcho(c) }, }, { Name: "info", Usage: "Get some info about the application", - Action: func(c *cli.Context) { - cmdInfo(c) + Action: func(c *cli.Context) error { + return cmdInfo(c) }, }, { Name: "set_option", Usage: "Set an option on the application", - Action: func(c *cli.Context) { - cmdSetOption(c) + Action: func(c *cli.Context) error { + return cmdSetOption(c) }, }, { Name: "append_tx", Usage: "Append a new tx to application", - Action: func(c *cli.Context) { - cmdAppendTx(c) + Action: func(c *cli.Context) error { + return cmdAppendTx(c) }, }, { Name: "check_tx", Usage: "Validate a tx", - Action: func(c *cli.Context) { - cmdCheckTx(c) + Action: func(c *cli.Context) error { + return cmdCheckTx(c) }, }, { Name: "commit", Usage: "Commit the application state and return the Merkle root hash", - Action: func(c *cli.Context) { - cmdCommit(c) + Action: func(c *cli.Context) error { + return cmdCommit(c) }, }, { Name: "query", Usage: "Query application state", - Action: func(c *cli.Context) { - cmdQuery(c) + Action: func(c *cli.Context) error { + return cmdQuery(c) }, }, } app.Before = before - app.Run(os.Args) + err := app.Run(os.Args) + if err != nil { + Exit(err.Error()) + } } @@ -112,160 +115,150 @@ func before(c *cli.Context) error { //-------------------------------------------------------------------------------- -func cmdBatch(app *cli.App, c *cli.Context) { +func cmdBatch(app *cli.App, c *cli.Context) error { bufReader := bufio.NewReader(os.Stdin) for { line, more, err := bufReader.ReadLine() if more { - fmt.Println("input line is too long") - return + return errors.New("Input line is too long") } else if err == io.EOF { break } else if len(line) == 0 { continue } else if err != nil { - fmt.Println(err.Error()) - return + return err } args := []string{"tmsp"} args = append(args, strings.Split(string(line), " ")...) app.Run(args) } + return nil } -func cmdConsole(app *cli.App, c *cli.Context) { +func cmdConsole(app *cli.App, c *cli.Context) error { for { fmt.Printf("\n> ") bufReader := bufio.NewReader(os.Stdin) line, more, err := bufReader.ReadLine() if more { - fmt.Println("input is too long") - return + return errors.New("Input is too long") } else if err != nil { - fmt.Println(err.Error()) - return + return err } args := []string{"tmsp"} args = append(args, strings.Split(string(line), " ")...) app.Run(args) } + return nil } // Have the application echo a message -func cmdEcho(c *cli.Context) { +func cmdEcho(c *cli.Context) error { args := c.Args() if len(args) != 1 { - fmt.Println("echo takes 1 argument") - return + return errors.New("Command echo takes 1 argument") } res, err := makeRequest(conn, types.RequestEcho(args[0])) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, string(res.Data)) + return nil } // Get some info from the application -func cmdInfo(c *cli.Context) { +func cmdInfo(c *cli.Context) error { res, err := makeRequest(conn, types.RequestInfo()) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, string(res.Data)) + return nil } // Set an option on the application -func cmdSetOption(c *cli.Context) { +func cmdSetOption(c *cli.Context) error { args := c.Args() if len(args) != 2 { - fmt.Println("set_option takes 2 arguments (key, value)") - return + return errors.New("Command set_option takes 2 arguments (key, value)") } res, err := makeRequest(conn, types.RequestSetOption(args[0], args[1])) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, Fmt("%s=%s", args[0], args[1])) + return nil } // Append a new tx to application -func cmdAppendTx(c *cli.Context) { +func cmdAppendTx(c *cli.Context) error { args := c.Args() if len(args) != 1 { - fmt.Println("append_tx takes 1 argument") - return + return errors.New("Command append_tx takes 1 argument") } txExprString := c.Args()[0] txBytes, err := expr.Compile(txExprString) if err != nil { - fmt.Println(err.Error()) - return + return err } res, err := makeRequest(conn, types.RequestAppendTx(txBytes)) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, string(res.Data)) + return nil } // Validate a tx -func cmdCheckTx(c *cli.Context) { +func cmdCheckTx(c *cli.Context) error { args := c.Args() if len(args) != 1 { - fmt.Println("check_tx takes 1 argument") - return + return errors.New("Command check_tx takes 1 argument") } txExprString := c.Args()[0] txBytes, err := expr.Compile(txExprString) if err != nil { - fmt.Println(err.Error()) - return + return err } res, err := makeRequest(conn, types.RequestCheckTx(txBytes)) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, string(res.Data)) + return nil } // Get application Merkle root hash -func cmdCommit(c *cli.Context) { +func cmdCommit(c *cli.Context) error { res, err := makeRequest(conn, types.RequestCommit()) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, Fmt("%X", res.Data)) + return nil } // Query application state -func cmdQuery(c *cli.Context) { +func cmdQuery(c *cli.Context) error { args := c.Args() if len(args) != 1 { - fmt.Println("query takes 1 argument") - return + return errors.New("Command query takes 1 argument") } queryExprString := args[0] queryBytes, err := expr.Compile(queryExprString) if err != nil { - fmt.Println(err.Error()) - return + return err } res, err := makeRequest(conn, types.RequestQuery(queryBytes)) if err != nil { - fmt.Println(err.Error()) - return + return err } printResponse(res, string(res.Data)) + return nil } //-------------------------------------------------------------------------------- From 35f4f0e271cfa6b7c35b61dfdddc77e01ab8106a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 14 May 2016 02:22:32 -0400 Subject: [PATCH 107/545] use real protobuf message types --- client/local_client.go | 42 +- client/remote_client.go | 114 ++-- server/server.go | 63 +- types/messages.go | 118 ++-- types/types.pb.go | 1227 ++++++++++++++++++++++++++++++++++++--- types/types.proto | 136 ++++- 6 files changed, 1455 insertions(+), 245 deletions(-) diff --git a/client/local_client.go b/client/local_client.go index 28ef6f32..06db859b 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -38,13 +38,13 @@ func (app *localClient) Stop() bool { func (app *localClient) FlushAsync() *ReqRes { // Do nothing - return newLocalReqRes(types.RequestFlush(), nil) + return newLocalReqRes(types.ToRequestFlush(), nil) } func (app *localClient) EchoAsync(msg string) *ReqRes { return app.callback( - types.RequestEcho(msg), - types.ResponseEcho(msg), + types.ToRequestEcho(msg), + types.ToResponseEcho(msg), ) } @@ -53,8 +53,8 @@ func (app *localClient) InfoAsync() *ReqRes { info := app.Application.Info() app.mtx.Unlock() return app.callback( - types.RequestInfo(), - types.ResponseInfo(info), + types.ToRequestInfo(), + types.ToResponseInfo(info), ) } @@ -63,8 +63,8 @@ func (app *localClient) SetOptionAsync(key string, value string) *ReqRes { log := app.Application.SetOption(key, value) app.mtx.Unlock() return app.callback( - types.RequestSetOption(key, value), - types.ResponseSetOption(log), + types.ToRequestSetOption(key, value), + types.ToResponseSetOption(log), ) } @@ -73,8 +73,8 @@ func (app *localClient) AppendTxAsync(tx []byte) *ReqRes { res := app.Application.AppendTx(tx) app.mtx.Unlock() return app.callback( - types.RequestAppendTx(tx), - types.ResponseAppendTx(res.Code, res.Data, res.Log), + types.ToRequestAppendTx(tx), + types.ToResponseAppendTx(res.Code, res.Data, res.Log), ) } @@ -83,8 +83,8 @@ func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { res := app.Application.CheckTx(tx) app.mtx.Unlock() return app.callback( - types.RequestCheckTx(tx), - types.ResponseCheckTx(res.Code, res.Data, res.Log), + types.ToRequestCheckTx(tx), + types.ToResponseCheckTx(res.Code, res.Data, res.Log), ) } @@ -93,8 +93,8 @@ func (app *localClient) QueryAsync(tx []byte) *ReqRes { res := app.Application.Query(tx) app.mtx.Unlock() return app.callback( - types.RequestQuery(tx), - types.ResponseQuery(res.Code, res.Data, res.Log), + types.ToRequestQuery(tx), + types.ToResponseQuery(res.Code, res.Data, res.Log), ) } @@ -103,8 +103,8 @@ func (app *localClient) CommitAsync() *ReqRes { res := app.Application.Commit() app.mtx.Unlock() return app.callback( - types.RequestCommit(), - types.ResponseCommit(res.Code, res.Data, res.Log), + types.ToRequestCommit(), + types.ToResponseCommit(res.Code, res.Data, res.Log), ) } @@ -114,8 +114,8 @@ func (app *localClient) InitChainAsync(validators []*types.Validator) *ReqRes { bcApp.InitChain(validators) } reqRes := app.callback( - types.RequestInitChain(validators), - types.ResponseInitChain(), + types.ToRequestInitChain(validators), + types.ToResponseInitChain(), ) app.mtx.Unlock() return reqRes @@ -128,8 +128,8 @@ func (app *localClient) BeginBlockAsync(height uint64) *ReqRes { } app.mtx.Unlock() return app.callback( - types.RequestBeginBlock(height), - types.ResponseBeginBlock(), + types.ToRequestBeginBlock(height), + types.ToResponseBeginBlock(), ) } @@ -141,8 +141,8 @@ func (app *localClient) EndBlockAsync(height uint64) *ReqRes { } app.mtx.Unlock() return app.callback( - types.RequestEndBlock(height), - types.ResponseEndBlock(validators), + types.ToRequestEndBlock(height), + types.ToResponseEndBlock(validators), ) } diff --git a/client/remote_client.go b/client/remote_client.go index d0aff152..5d6dd6dc 100644 --- a/client/remote_client.go +++ b/client/remote_client.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net" + "reflect" "sync" "time" @@ -13,6 +14,11 @@ import ( "github.com/tendermint/tmsp/types" ) +const ( + OK = types.CodeType_OK + LOG = "" +) + const reqQueueSize = 256 // TODO make configurable const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... @@ -122,7 +128,7 @@ func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { select { case <-cli.flushTimer.Ch: select { - case cli.reqQueue <- NewReqRes(types.RequestFlush()): + case cli.reqQueue <- NewReqRes(types.ToRequestFlush()): default: // Probably will fill the buffer, or retry later. } @@ -136,7 +142,7 @@ func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { return } // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) - if reqres.Request.Type == types.MessageType_Flush { + if _, ok := reqres.Request.Requests.(*types.Request_Flush); ok { err = w.Flush() if err != nil { cli.StopForError(err) @@ -156,10 +162,10 @@ func (cli *remoteClient) recvResponseRoutine(conn net.Conn) { cli.StopForError(err) return } - switch res.Type { - case types.MessageType_Exception: + switch r := res.Responses.(type) { + case *types.Response_Exception: // XXX After setting cli.err, release waiters (e.g. reqres.Done()) - cli.StopForError(errors.New(res.Error)) + cli.StopForError(errors.New(r.Exception.Error)) default: // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) err := cli.didRecvResponse(res) @@ -183,12 +189,12 @@ func (cli *remoteClient) didRecvResponse(res *types.Response) error { // Get the first ReqRes next := cli.reqSent.Front() if next == nil { - return fmt.Errorf("Unexpected result type %v when nothing expected", res.Type) + return fmt.Errorf("Unexpected result type %v when nothing expected", reflect.TypeOf(res.Responses)) } reqres := next.Value.(*ReqRes) if !resMatchesReq(reqres.Request, res) { return fmt.Errorf("Unexpected result type %v when response to %v expected", - res.Type, reqres.Request.Type) + reflect.TypeOf(res.Responses), reflect.TypeOf(reqres.Request.Requests)) } reqres.Response = res // Set response @@ -211,128 +217,128 @@ func (cli *remoteClient) didRecvResponse(res *types.Response) error { //---------------------------------------- func (cli *remoteClient) EchoAsync(msg string) *ReqRes { - return cli.queueRequest(types.RequestEcho(msg)) + return cli.queueRequest(types.ToRequestEcho(msg)) } func (cli *remoteClient) FlushAsync() *ReqRes { - return cli.queueRequest(types.RequestFlush()) + return cli.queueRequest(types.ToRequestFlush()) } func (cli *remoteClient) InfoAsync() *ReqRes { - return cli.queueRequest(types.RequestInfo()) + return cli.queueRequest(types.ToRequestInfo()) } func (cli *remoteClient) SetOptionAsync(key string, value string) *ReqRes { - return cli.queueRequest(types.RequestSetOption(key, value)) + return cli.queueRequest(types.ToRequestSetOption(key, value)) } func (cli *remoteClient) AppendTxAsync(tx []byte) *ReqRes { - return cli.queueRequest(types.RequestAppendTx(tx)) + return cli.queueRequest(types.ToRequestAppendTx(tx)) } func (cli *remoteClient) CheckTxAsync(tx []byte) *ReqRes { - return cli.queueRequest(types.RequestCheckTx(tx)) + return cli.queueRequest(types.ToRequestCheckTx(tx)) } func (cli *remoteClient) QueryAsync(query []byte) *ReqRes { - return cli.queueRequest(types.RequestQuery(query)) + return cli.queueRequest(types.ToRequestQuery(query)) } func (cli *remoteClient) CommitAsync() *ReqRes { - return cli.queueRequest(types.RequestCommit()) + return cli.queueRequest(types.ToRequestCommit()) } func (cli *remoteClient) InitChainAsync(validators []*types.Validator) *ReqRes { - return cli.queueRequest(types.RequestInitChain(validators)) + return cli.queueRequest(types.ToRequestInitChain(validators)) } func (cli *remoteClient) BeginBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.RequestBeginBlock(height)) + return cli.queueRequest(types.ToRequestBeginBlock(height)) } func (cli *remoteClient) EndBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.RequestEndBlock(height)) + return cli.queueRequest(types.ToRequestEndBlock(height)) } //---------------------------------------- func (cli *remoteClient) EchoSync(msg string) (res types.Result) { - reqres := cli.queueRequest(types.RequestEcho(msg)) + reqres := cli.queueRequest(types.ToRequestEcho(msg)) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + resp := reqres.Response.GetEcho() + return types.Result{Code: OK, Data: []byte(resp.Message), Log: LOG} } func (cli *remoteClient) FlushSync() error { - cli.queueRequest(types.RequestFlush()).Wait() + cli.queueRequest(types.ToRequestFlush()).Wait() return cli.err } func (cli *remoteClient) InfoSync() (res types.Result) { - reqres := cli.queueRequest(types.RequestInfo()) + reqres := cli.queueRequest(types.ToRequestInfo()) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + resp := reqres.Response.GetInfo() + return types.Result{Code: OK, Data: []byte(resp.Info), Log: LOG} } func (cli *remoteClient) SetOptionSync(key string, value string) (res types.Result) { - reqres := cli.queueRequest(types.RequestSetOption(key, value)) + reqres := cli.queueRequest(types.ToRequestSetOption(key, value)) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + resp := reqres.Response.GetSetOption() + return types.Result{Code: OK, Data: nil, Log: resp.Log} } func (cli *remoteClient) AppendTxSync(tx []byte) (res types.Result) { - reqres := cli.queueRequest(types.RequestAppendTx(tx)) + reqres := cli.queueRequest(types.ToRequestAppendTx(tx)) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response + resp := reqres.Response.GetAppendTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } func (cli *remoteClient) CheckTxSync(tx []byte) (res types.Result) { - reqres := cli.queueRequest(types.RequestCheckTx(tx)) + reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response + resp := reqres.Response.GetCheckTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } func (cli *remoteClient) QuerySync(query []byte) (res types.Result) { - reqres := cli.queueRequest(types.RequestQuery(query)) + reqres := cli.queueRequest(types.ToRequestQuery(query)) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response + resp := reqres.Response.GetQuery() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } func (cli *remoteClient) CommitSync() (res types.Result) { - reqres := cli.queueRequest(types.RequestCommit()) + reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() if cli.err != nil { return types.ErrInternalError.SetLog(cli.err.Error()) } - resp := reqres.Response + resp := reqres.Response.GetCommit() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } func (cli *remoteClient) InitChainSync(validators []*types.Validator) (err error) { - cli.queueRequest(types.RequestInitChain(validators)) + cli.queueRequest(types.ToRequestInitChain(validators)) cli.FlushSync() if cli.err != nil { return cli.err @@ -341,7 +347,7 @@ func (cli *remoteClient) InitChainSync(validators []*types.Validator) (err error } func (cli *remoteClient) BeginBlockSync(height uint64) (err error) { - cli.queueRequest(types.RequestBeginBlock(height)) + cli.queueRequest(types.ToRequestBeginBlock(height)) cli.FlushSync() if cli.err != nil { return cli.err @@ -350,12 +356,12 @@ func (cli *remoteClient) BeginBlockSync(height uint64) (err error) { } func (cli *remoteClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { - reqres := cli.queueRequest(types.RequestEndBlock(height)) + reqres := cli.queueRequest(types.ToRequestEndBlock(height)) cli.FlushSync() if cli.err != nil { return nil, cli.err } - return reqres.Response.Validators, nil + return reqres.Response.GetEndBlock().Diffs, nil } //---------------------------------------- @@ -366,8 +372,8 @@ func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { cli.reqQueue <- reqres // Maybe auto-flush, or unset auto-flush - switch req.Type { - case types.MessageType_Flush: + switch req.Requests.(type) { + case *types.Request_Flush: cli.flushTimer.Unset() default: cli.flushTimer.Set() @@ -379,5 +385,27 @@ func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { //---------------------------------------- func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { - return req.Type == res.Type + switch req.Requests.(type) { + case *types.Request_Echo: + _, ok = res.Responses.(*types.Response_Echo) + case *types.Request_Flush: + _, ok = res.Responses.(*types.Response_Flush) + case *types.Request_Info: + _, ok = res.Responses.(*types.Response_Info) + case *types.Request_SetOption: + _, ok = res.Responses.(*types.Response_SetOption) + case *types.Request_AppendTx: + _, ok = res.Responses.(*types.Response_AppendTx) + case *types.Request_CheckTx: + _, ok = res.Responses.(*types.Response_CheckTx) + case *types.Request_Commit: + _, ok = res.Responses.(*types.Response_Commit) + case *types.Request_Query: + _, ok = res.Responses.(*types.Response_Query) + case *types.Request_InitChain: + _, ok = res.Responses.(*types.Response_InitChain) + case *types.Request_EndBlock: + _, ok = res.Responses.(*types.Response_EndBlock) + } + return ok } diff --git a/server/server.go b/server/server.go index e64ab30b..dd2430a1 100644 --- a/server/server.go +++ b/server/server.go @@ -125,45 +125,46 @@ func (s *Server) handleRequests(closeConn chan error, conn net.Conn, responses c } func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Response) { - switch req.Type { - case types.MessageType_Echo: - responses <- types.ResponseEcho(string(req.Data)) - case types.MessageType_Flush: - responses <- types.ResponseFlush() - case types.MessageType_Info: + switch r := req.Requests.(type) { + case *types.Request_Echo: + responses <- types.ToResponseEcho(r.Echo.Message) + case *types.Request_Flush: + responses <- types.ToResponseFlush() + case *types.Request_Info: data := s.app.Info() - responses <- types.ResponseInfo(data) - case types.MessageType_SetOption: - logStr := s.app.SetOption(req.Key, req.Value) - responses <- types.ResponseSetOption(logStr) - case types.MessageType_AppendTx: - res := s.app.AppendTx(req.Data) - responses <- types.ResponseAppendTx(res.Code, res.Data, res.Log) - case types.MessageType_CheckTx: - res := s.app.CheckTx(req.Data) - responses <- types.ResponseCheckTx(res.Code, res.Data, res.Log) - case types.MessageType_Commit: + responses <- types.ToResponseInfo(data) + case *types.Request_SetOption: + so := r.SetOption + logStr := s.app.SetOption(so.Key, so.Value) + responses <- types.ToResponseSetOption(logStr) + case *types.Request_AppendTx: + res := s.app.AppendTx(r.AppendTx.Tx) + responses <- types.ToResponseAppendTx(res.Code, res.Data, res.Log) + case *types.Request_CheckTx: + res := s.app.CheckTx(r.CheckTx.Tx) + responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) + case *types.Request_Commit: res := s.app.Commit() - responses <- types.ResponseCommit(res.Code, res.Data, res.Log) - case types.MessageType_Query: - res := s.app.Query(req.Data) - responses <- types.ResponseQuery(res.Code, res.Data, res.Log) - case types.MessageType_InitChain: + 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) + case *types.Request_InitChain: if app, ok := s.app.(types.BlockchainAware); ok { - app.InitChain(req.Validators) - responses <- types.ResponseInitChain() + app.InitChain(r.InitChain.Validators) + responses <- types.ToResponseInitChain() } else { - responses <- types.ResponseInitChain() + responses <- types.ToResponseInitChain() } - case types.MessageType_EndBlock: + case *types.Request_EndBlock: if app, ok := s.app.(types.BlockchainAware); ok { - validators := app.EndBlock(req.Height) - responses <- types.ResponseEndBlock(validators) + validators := app.EndBlock(r.EndBlock.Height) + responses <- types.ToResponseEndBlock(validators) } else { - responses <- types.ResponseEndBlock(nil) + responses <- types.ToResponseEndBlock(nil) } default: - responses <- types.ResponseException("Unknown request") + responses <- types.ToResponseException("Unknown request") } } @@ -178,7 +179,7 @@ func (s *Server) handleResponses(closeConn chan error, responses <-chan *types.R closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) return } - if res.Type == types.MessageType_Flush { + if _, ok := res.Responses.(*types.Response_Flush); ok { err = bufWriter.Flush() if err != nil { closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) diff --git a/types/messages.go b/types/messages.go index facc3bfc..730e3d6f 100644 --- a/types/messages.go +++ b/types/messages.go @@ -7,169 +7,143 @@ import ( "github.com/tendermint/go-wire" ) -func RequestEcho(message string) *Request { +func ToRequestEcho(message string) *Request { return &Request{ - Type: MessageType_Echo, - Data: []byte(message), + Requests: &Request_Echo{&RequestEcho{}}, } } -func RequestFlush() *Request { +func ToRequestFlush() *Request { return &Request{ - Type: MessageType_Flush, + Requests: &Request_Flush{&RequestFlush{}}, } } -func RequestInfo() *Request { +func ToRequestInfo() *Request { return &Request{ - Type: MessageType_Info, + Requests: &Request_Info{&RequestInfo{}}, } } -func RequestSetOption(key string, value string) *Request { +func ToRequestSetOption(key string, value string) *Request { return &Request{ - Type: MessageType_SetOption, - Key: key, - Value: value, + Requests: &Request_SetOption{&RequestSetOption{key, value}}, } } -func RequestAppendTx(txBytes []byte) *Request { +func ToRequestAppendTx(txBytes []byte) *Request { return &Request{ - Type: MessageType_AppendTx, - Data: txBytes, + Requests: &Request_AppendTx{&RequestAppendTx{txBytes}}, } } -func RequestCheckTx(txBytes []byte) *Request { +func ToRequestCheckTx(txBytes []byte) *Request { return &Request{ - Type: MessageType_CheckTx, - Data: txBytes, + Requests: &Request_CheckTx{&RequestCheckTx{txBytes}}, } } -func RequestCommit() *Request { +func ToRequestCommit() *Request { return &Request{ - Type: MessageType_Commit, + Requests: &Request_Commit{&RequestCommit{}}, } } -func RequestQuery(queryBytes []byte) *Request { +func ToRequestQuery(queryBytes []byte) *Request { return &Request{ - Type: MessageType_Query, - Data: queryBytes, + Requests: &Request_Query{&RequestQuery{queryBytes}}, } } -func RequestInitChain(validators []*Validator) *Request { +func ToRequestInitChain(validators []*Validator) *Request { return &Request{ - Type: MessageType_InitChain, - Validators: validators, + Requests: &Request_InitChain{&RequestInitChain{validators}}, } } -func RequestBeginBlock(height uint64) *Request { +func ToRequestBeginBlock(height uint64) *Request { return &Request{ - Type: MessageType_BeginBlock, - Height: height, + Requests: &Request_BeginBlock{&RequestBeginBlock{height}}, } } -func RequestEndBlock(height uint64) *Request { +func ToRequestEndBlock(height uint64) *Request { return &Request{ - Type: MessageType_EndBlock, - Height: height, + Requests: &Request_EndBlock{&RequestEndBlock{height}}, } } //---------------------------------------- -func ResponseException(errStr string) *Response { +func ToResponseException(errStr string) *Response { return &Response{ - Type: MessageType_Exception, - Error: errStr, + Responses: &Response_Exception{&ResponseException{errStr}}, } } -func ResponseEcho(message string) *Response { +func ToResponseEcho(message string) *Response { return &Response{ - Type: MessageType_Echo, - Data: []byte(message), + Responses: &Response_Echo{&ResponseEcho{message}}, } } -func ResponseFlush() *Response { +func ToResponseFlush() *Response { return &Response{ - Type: MessageType_Flush, + Responses: &Response_Flush{&ResponseFlush{}}, } } -func ResponseInfo(info string) *Response { +func ToResponseInfo(info string) *Response { return &Response{ - Type: MessageType_Info, - Data: []byte(info), + Responses: &Response_Info{&ResponseInfo{info}}, } } -func ResponseSetOption(log string) *Response { +func ToResponseSetOption(log string) *Response { return &Response{ - Type: MessageType_SetOption, - Log: log, + Responses: &Response_SetOption{&ResponseSetOption{log}}, } } -func ResponseAppendTx(code CodeType, data []byte, log string) *Response { +func ToResponseAppendTx(code CodeType, data []byte, log string) *Response { return &Response{ - Type: MessageType_AppendTx, - Code: code, - Data: data, - Log: log, + Responses: &Response_AppendTx{&ResponseAppendTx{code, data, log}}, } } -func ResponseCheckTx(code CodeType, data []byte, log string) *Response { +func ToResponseCheckTx(code CodeType, data []byte, log string) *Response { return &Response{ - Type: MessageType_CheckTx, - Code: code, - Data: data, - Log: log, + Responses: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, } } -func ResponseCommit(code CodeType, data []byte, log string) *Response { +func ToResponseCommit(code CodeType, data []byte, log string) *Response { return &Response{ - Type: MessageType_Commit, - Code: code, - Data: data, - Log: log, + Responses: &Response_Commit{&ResponseCommit{code, data, log}}, } } -func ResponseQuery(code CodeType, data []byte, log string) *Response { +func ToResponseQuery(code CodeType, data []byte, log string) *Response { return &Response{ - Type: MessageType_Query, - Code: code, - Data: data, - Log: log, + Responses: &Response_Query{&ResponseQuery{code, data, log}}, } } -func ResponseInitChain() *Response { +func ToResponseInitChain() *Response { return &Response{ - Type: MessageType_InitChain, + Responses: &Response_InitChain{&ResponseInitChain{}}, } } -func ResponseBeginBlock() *Response { +func ToResponseBeginBlock() *Response { return &Response{ - Type: MessageType_BeginBlock, + Responses: &Response_BeginBlock{&ResponseBeginBlock{}}, } } -func ResponseEndBlock(validators []*Validator) *Response { +func ToResponseEndBlock(validators []*Validator) *Response { return &Response{ - Type: MessageType_EndBlock, - Validators: validators, + Responses: &Response_EndBlock{&ResponseEndBlock{validators}}, } } diff --git a/types/types.pb.go b/types/types.pb.go index 933e62ca..5e94e290 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1,16 +1,39 @@ // Code generated by protoc-gen-go. -// source: types/types.proto +// source: types.proto // DO NOT EDIT! /* Package types is a generated protocol buffer package. It is generated from these files: - types/types.proto + types.proto It has these top-level messages: Request + RequestEcho + RequestFlush + RequestInfo + RequestSetOption + RequestAppendTx + RequestCheckTx + RequestQuery + RequestCommit + RequestInitChain + RequestBeginBlock + RequestEndBlock Response + ResponseException + ResponseEcho + ResponseFlush + ResponseInfo + ResponseSetOption + ResponseAppendTx + ResponseCheckTx + ResponseQuery + ResponseCommit + ResponseInitChain + ResponseBeginBlock + ResponseEndBlock Validator */ package types @@ -24,6 +47,10 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +const _ = proto.ProtoPackageIsVersion1 + type MessageType int32 const ( @@ -187,12 +214,19 @@ func (x CodeType) String() string { func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } type Request struct { - Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Key string `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` - Value string `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` - Validators []*Validator `protobuf:"bytes,5,rep,name=validators" json:"validators,omitempty"` - Height uint64 `protobuf:"varint,6,opt,name=height" json:"height,omitempty"` + // Types that are valid to be assigned to Requests: + // *Request_Echo + // *Request_Flush + // *Request_Info + // *Request_SetOption + // *Request_AppendTx + // *Request_CheckTx + // *Request_Commit + // *Request_Query + // *Request_InitChain + // *Request_BeginBlock + // *Request_EndBlock + Requests isRequest_Requests `protobuf_oneof:"requests"` } func (m *Request) Reset() { *m = Request{} } @@ -200,30 +234,1036 @@ func (m *Request) String() string { return proto.CompactTextString(m) func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (m *Request) GetValidators() []*Validator { +type isRequest_Requests interface { + isRequest_Requests() +} + +type Request_Echo struct { + Echo *RequestEcho `protobuf:"bytes,1,opt,name=echo,oneof"` +} +type Request_Flush struct { + Flush *RequestFlush `protobuf:"bytes,2,opt,name=flush,oneof"` +} +type Request_Info struct { + Info *RequestInfo `protobuf:"bytes,3,opt,name=info,oneof"` +} +type Request_SetOption struct { + SetOption *RequestSetOption `protobuf:"bytes,4,opt,name=set_option,json=setOption,oneof"` +} +type Request_AppendTx struct { + AppendTx *RequestAppendTx `protobuf:"bytes,5,opt,name=append_tx,json=appendTx,oneof"` +} +type Request_CheckTx struct { + CheckTx *RequestCheckTx `protobuf:"bytes,6,opt,name=check_tx,json=checkTx,oneof"` +} +type Request_Commit struct { + Commit *RequestCommit `protobuf:"bytes,7,opt,name=commit,oneof"` +} +type Request_Query struct { + Query *RequestQuery `protobuf:"bytes,8,opt,name=query,oneof"` +} +type Request_InitChain struct { + InitChain *RequestInitChain `protobuf:"bytes,9,opt,name=init_chain,json=initChain,oneof"` +} +type Request_BeginBlock struct { + BeginBlock *RequestBeginBlock `protobuf:"bytes,10,opt,name=begin_block,json=beginBlock,oneof"` +} +type Request_EndBlock struct { + EndBlock *RequestEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,oneof"` +} + +func (*Request_Echo) isRequest_Requests() {} +func (*Request_Flush) isRequest_Requests() {} +func (*Request_Info) isRequest_Requests() {} +func (*Request_SetOption) isRequest_Requests() {} +func (*Request_AppendTx) isRequest_Requests() {} +func (*Request_CheckTx) isRequest_Requests() {} +func (*Request_Commit) isRequest_Requests() {} +func (*Request_Query) isRequest_Requests() {} +func (*Request_InitChain) isRequest_Requests() {} +func (*Request_BeginBlock) isRequest_Requests() {} +func (*Request_EndBlock) isRequest_Requests() {} + +func (m *Request) GetRequests() isRequest_Requests { + if m != nil { + return m.Requests + } + return nil +} + +func (m *Request) GetEcho() *RequestEcho { + if x, ok := m.GetRequests().(*Request_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Request) GetFlush() *RequestFlush { + if x, ok := m.GetRequests().(*Request_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Request) GetInfo() *RequestInfo { + if x, ok := m.GetRequests().(*Request_Info); ok { + return x.Info + } + return nil +} + +func (m *Request) GetSetOption() *RequestSetOption { + if x, ok := m.GetRequests().(*Request_SetOption); ok { + return x.SetOption + } + return nil +} + +func (m *Request) GetAppendTx() *RequestAppendTx { + if x, ok := m.GetRequests().(*Request_AppendTx); ok { + return x.AppendTx + } + return nil +} + +func (m *Request) GetCheckTx() *RequestCheckTx { + if x, ok := m.GetRequests().(*Request_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Request) GetCommit() *RequestCommit { + if x, ok := m.GetRequests().(*Request_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Request) GetQuery() *RequestQuery { + if x, ok := m.GetRequests().(*Request_Query); ok { + return x.Query + } + return nil +} + +func (m *Request) GetInitChain() *RequestInitChain { + if x, ok := m.GetRequests().(*Request_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Request) GetBeginBlock() *RequestBeginBlock { + if x, ok := m.GetRequests().(*Request_BeginBlock); ok { + return x.BeginBlock + } + return nil +} + +func (m *Request) GetEndBlock() *RequestEndBlock { + if x, ok := m.GetRequests().(*Request_EndBlock); ok { + return x.EndBlock + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Request_OneofMarshaler, _Request_OneofUnmarshaler, _Request_OneofSizer, []interface{}{ + (*Request_Echo)(nil), + (*Request_Flush)(nil), + (*Request_Info)(nil), + (*Request_SetOption)(nil), + (*Request_AppendTx)(nil), + (*Request_CheckTx)(nil), + (*Request_Commit)(nil), + (*Request_Query)(nil), + (*Request_InitChain)(nil), + (*Request_BeginBlock)(nil), + (*Request_EndBlock)(nil), + } +} + +func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Request) + // requests + switch x := m.Requests.(type) { + case *Request_Echo: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Echo); err != nil { + return err + } + case *Request_Flush: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Flush); err != nil { + return err + } + case *Request_Info: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Info); err != nil { + return err + } + case *Request_SetOption: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.SetOption); err != nil { + return err + } + case *Request_AppendTx: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.AppendTx); err != nil { + return err + } + case *Request_CheckTx: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CheckTx); err != nil { + return err + } + case *Request_Commit: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Commit); err != nil { + return err + } + case *Request_Query: + b.EncodeVarint(8<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Query); err != nil { + return err + } + case *Request_InitChain: + b.EncodeVarint(9<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InitChain); err != nil { + return err + } + case *Request_BeginBlock: + b.EncodeVarint(10<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.BeginBlock); err != nil { + return err + } + case *Request_EndBlock: + b.EncodeVarint(11<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.EndBlock); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Request.Requests has unexpected type %T", x) + } + return nil +} + +func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Request) + switch tag { + case 1: // requests.echo + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestEcho) + err := b.DecodeMessage(msg) + m.Requests = &Request_Echo{msg} + return true, err + case 2: // requests.flush + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestFlush) + err := b.DecodeMessage(msg) + m.Requests = &Request_Flush{msg} + return true, err + case 3: // requests.info + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestInfo) + err := b.DecodeMessage(msg) + m.Requests = &Request_Info{msg} + return true, err + case 4: // requests.set_option + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestSetOption) + err := b.DecodeMessage(msg) + m.Requests = &Request_SetOption{msg} + return true, err + case 5: // requests.append_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestAppendTx) + err := b.DecodeMessage(msg) + m.Requests = &Request_AppendTx{msg} + return true, err + case 6: // requests.check_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestCheckTx) + err := b.DecodeMessage(msg) + m.Requests = &Request_CheckTx{msg} + return true, err + case 7: // requests.commit + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestCommit) + err := b.DecodeMessage(msg) + m.Requests = &Request_Commit{msg} + return true, err + case 8: // requests.query + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestQuery) + err := b.DecodeMessage(msg) + m.Requests = &Request_Query{msg} + return true, err + case 9: // requests.init_chain + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestInitChain) + err := b.DecodeMessage(msg) + m.Requests = &Request_InitChain{msg} + return true, err + case 10: // requests.begin_block + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestBeginBlock) + err := b.DecodeMessage(msg) + m.Requests = &Request_BeginBlock{msg} + return true, err + case 11: // requests.end_block + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestEndBlock) + err := b.DecodeMessage(msg) + m.Requests = &Request_EndBlock{msg} + return true, err + default: + return false, nil + } +} + +func _Request_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Request) + // requests + switch x := m.Requests.(type) { + case *Request_Echo: + s := proto.Size(x.Echo) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_Flush: + s := proto.Size(x.Flush) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_Info: + s := proto.Size(x.Info) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_SetOption: + s := proto.Size(x.SetOption) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_AppendTx: + s := proto.Size(x.AppendTx) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_CheckTx: + s := proto.Size(x.CheckTx) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_Commit: + s := proto.Size(x.Commit) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_Query: + s := proto.Size(x.Query) + n += proto.SizeVarint(8<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_InitChain: + s := proto.Size(x.InitChain) + n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_BeginBlock: + s := proto.Size(x.BeginBlock) + n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_EndBlock: + s := proto.Size(x.EndBlock) + n += proto.SizeVarint(11<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type RequestEcho struct { + Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` +} + +func (m *RequestEcho) Reset() { *m = RequestEcho{} } +func (m *RequestEcho) String() string { return proto.CompactTextString(m) } +func (*RequestEcho) ProtoMessage() {} +func (*RequestEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type RequestFlush struct { +} + +func (m *RequestFlush) Reset() { *m = RequestFlush{} } +func (m *RequestFlush) String() string { return proto.CompactTextString(m) } +func (*RequestFlush) ProtoMessage() {} +func (*RequestFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type RequestInfo struct { +} + +func (m *RequestInfo) Reset() { *m = RequestInfo{} } +func (m *RequestInfo) String() string { return proto.CompactTextString(m) } +func (*RequestInfo) ProtoMessage() {} +func (*RequestInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +type RequestSetOption struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` +} + +func (m *RequestSetOption) Reset() { *m = RequestSetOption{} } +func (m *RequestSetOption) String() string { return proto.CompactTextString(m) } +func (*RequestSetOption) ProtoMessage() {} +func (*RequestSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +type RequestAppendTx struct { + Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` +} + +func (m *RequestAppendTx) Reset() { *m = RequestAppendTx{} } +func (m *RequestAppendTx) String() string { return proto.CompactTextString(m) } +func (*RequestAppendTx) ProtoMessage() {} +func (*RequestAppendTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +type RequestCheckTx struct { + Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` +} + +func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } +func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } +func (*RequestCheckTx) ProtoMessage() {} +func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +type RequestQuery struct { + Query []byte `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` +} + +func (m *RequestQuery) Reset() { *m = RequestQuery{} } +func (m *RequestQuery) String() string { return proto.CompactTextString(m) } +func (*RequestQuery) ProtoMessage() {} +func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +type RequestCommit struct { +} + +func (m *RequestCommit) Reset() { *m = RequestCommit{} } +func (m *RequestCommit) String() string { return proto.CompactTextString(m) } +func (*RequestCommit) ProtoMessage() {} +func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +type RequestInitChain struct { + Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` +} + +func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } +func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } +func (*RequestInitChain) ProtoMessage() {} +func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *RequestInitChain) GetValidators() []*Validator { if m != nil { return m.Validators } return nil } +type RequestBeginBlock struct { + Height uint64 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` +} + +func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } +func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } +func (*RequestBeginBlock) ProtoMessage() {} +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +type RequestEndBlock struct { + Height uint64 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` +} + +func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } +func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } +func (*RequestEndBlock) ProtoMessage() {} +func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + type Response struct { - Type MessageType `protobuf:"varint,1,opt,name=type,enum=types.MessageType" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Code CodeType `protobuf:"varint,3,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Error string `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"` - Log string `protobuf:"bytes,5,opt,name=log" json:"log,omitempty"` - Validators []*Validator `protobuf:"bytes,6,rep,name=validators" json:"validators,omitempty"` + // Types that are valid to be assigned to Responses: + // *Response_Exception + // *Response_Echo + // *Response_Flush + // *Response_Info + // *Response_SetOption + // *Response_AppendTx + // *Response_CheckTx + // *Response_Commit + // *Response_Query + // *Response_InitChain + // *Response_BeginBlock + // *Response_EndBlock + Responses isResponse_Responses `protobuf_oneof:"responses"` } func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} -func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } -func (m *Response) GetValidators() []*Validator { +type isResponse_Responses interface { + isResponse_Responses() +} + +type Response_Exception struct { + Exception *ResponseException `protobuf:"bytes,1,opt,name=exception,oneof"` +} +type Response_Echo struct { + Echo *ResponseEcho `protobuf:"bytes,2,opt,name=echo,oneof"` +} +type Response_Flush struct { + Flush *ResponseFlush `protobuf:"bytes,3,opt,name=flush,oneof"` +} +type Response_Info struct { + Info *ResponseInfo `protobuf:"bytes,4,opt,name=info,oneof"` +} +type Response_SetOption struct { + SetOption *ResponseSetOption `protobuf:"bytes,5,opt,name=set_option,json=setOption,oneof"` +} +type Response_AppendTx struct { + AppendTx *ResponseAppendTx `protobuf:"bytes,6,opt,name=append_tx,json=appendTx,oneof"` +} +type Response_CheckTx struct { + CheckTx *ResponseCheckTx `protobuf:"bytes,7,opt,name=check_tx,json=checkTx,oneof"` +} +type Response_Commit struct { + Commit *ResponseCommit `protobuf:"bytes,8,opt,name=commit,oneof"` +} +type Response_Query struct { + Query *ResponseQuery `protobuf:"bytes,9,opt,name=query,oneof"` +} +type Response_InitChain struct { + InitChain *ResponseInitChain `protobuf:"bytes,10,opt,name=init_chain,json=initChain,oneof"` +} +type Response_BeginBlock struct { + BeginBlock *ResponseBeginBlock `protobuf:"bytes,11,opt,name=begin_block,json=beginBlock,oneof"` +} +type Response_EndBlock struct { + EndBlock *ResponseEndBlock `protobuf:"bytes,12,opt,name=end_block,json=endBlock,oneof"` +} + +func (*Response_Exception) isResponse_Responses() {} +func (*Response_Echo) isResponse_Responses() {} +func (*Response_Flush) isResponse_Responses() {} +func (*Response_Info) isResponse_Responses() {} +func (*Response_SetOption) isResponse_Responses() {} +func (*Response_AppendTx) isResponse_Responses() {} +func (*Response_CheckTx) isResponse_Responses() {} +func (*Response_Commit) isResponse_Responses() {} +func (*Response_Query) isResponse_Responses() {} +func (*Response_InitChain) isResponse_Responses() {} +func (*Response_BeginBlock) isResponse_Responses() {} +func (*Response_EndBlock) isResponse_Responses() {} + +func (m *Response) GetResponses() isResponse_Responses { if m != nil { - return m.Validators + return m.Responses + } + return nil +} + +func (m *Response) GetException() *ResponseException { + if x, ok := m.GetResponses().(*Response_Exception); ok { + return x.Exception + } + return nil +} + +func (m *Response) GetEcho() *ResponseEcho { + if x, ok := m.GetResponses().(*Response_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Response) GetFlush() *ResponseFlush { + if x, ok := m.GetResponses().(*Response_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Response) GetInfo() *ResponseInfo { + if x, ok := m.GetResponses().(*Response_Info); ok { + return x.Info + } + return nil +} + +func (m *Response) GetSetOption() *ResponseSetOption { + if x, ok := m.GetResponses().(*Response_SetOption); ok { + return x.SetOption + } + return nil +} + +func (m *Response) GetAppendTx() *ResponseAppendTx { + if x, ok := m.GetResponses().(*Response_AppendTx); ok { + return x.AppendTx + } + return nil +} + +func (m *Response) GetCheckTx() *ResponseCheckTx { + if x, ok := m.GetResponses().(*Response_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Response) GetCommit() *ResponseCommit { + if x, ok := m.GetResponses().(*Response_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Response) GetQuery() *ResponseQuery { + if x, ok := m.GetResponses().(*Response_Query); ok { + return x.Query + } + return nil +} + +func (m *Response) GetInitChain() *ResponseInitChain { + if x, ok := m.GetResponses().(*Response_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Response) GetBeginBlock() *ResponseBeginBlock { + if x, ok := m.GetResponses().(*Response_BeginBlock); ok { + return x.BeginBlock + } + return nil +} + +func (m *Response) GetEndBlock() *ResponseEndBlock { + if x, ok := m.GetResponses().(*Response_EndBlock); ok { + return x.EndBlock + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Response_OneofMarshaler, _Response_OneofUnmarshaler, _Response_OneofSizer, []interface{}{ + (*Response_Exception)(nil), + (*Response_Echo)(nil), + (*Response_Flush)(nil), + (*Response_Info)(nil), + (*Response_SetOption)(nil), + (*Response_AppendTx)(nil), + (*Response_CheckTx)(nil), + (*Response_Commit)(nil), + (*Response_Query)(nil), + (*Response_InitChain)(nil), + (*Response_BeginBlock)(nil), + (*Response_EndBlock)(nil), + } +} + +func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Response) + // responses + switch x := m.Responses.(type) { + case *Response_Exception: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Exception); err != nil { + return err + } + case *Response_Echo: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Echo); err != nil { + return err + } + case *Response_Flush: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Flush); err != nil { + return err + } + case *Response_Info: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Info); err != nil { + return err + } + case *Response_SetOption: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.SetOption); err != nil { + return err + } + case *Response_AppendTx: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.AppendTx); err != nil { + return err + } + case *Response_CheckTx: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CheckTx); err != nil { + return err + } + case *Response_Commit: + b.EncodeVarint(8<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Commit); err != nil { + return err + } + case *Response_Query: + b.EncodeVarint(9<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Query); err != nil { + return err + } + case *Response_InitChain: + b.EncodeVarint(10<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InitChain); err != nil { + return err + } + case *Response_BeginBlock: + b.EncodeVarint(11<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.BeginBlock); err != nil { + return err + } + case *Response_EndBlock: + b.EncodeVarint(12<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.EndBlock); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Response.Responses has unexpected type %T", x) + } + return nil +} + +func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Response) + switch tag { + case 1: // responses.exception + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseException) + err := b.DecodeMessage(msg) + m.Responses = &Response_Exception{msg} + return true, err + case 2: // responses.echo + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseEcho) + err := b.DecodeMessage(msg) + m.Responses = &Response_Echo{msg} + return true, err + case 3: // responses.flush + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseFlush) + err := b.DecodeMessage(msg) + m.Responses = &Response_Flush{msg} + return true, err + case 4: // responses.info + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseInfo) + err := b.DecodeMessage(msg) + m.Responses = &Response_Info{msg} + return true, err + case 5: // responses.set_option + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseSetOption) + err := b.DecodeMessage(msg) + m.Responses = &Response_SetOption{msg} + return true, err + case 6: // responses.append_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseAppendTx) + err := b.DecodeMessage(msg) + m.Responses = &Response_AppendTx{msg} + return true, err + case 7: // responses.check_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseCheckTx) + err := b.DecodeMessage(msg) + m.Responses = &Response_CheckTx{msg} + return true, err + case 8: // responses.commit + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseCommit) + err := b.DecodeMessage(msg) + m.Responses = &Response_Commit{msg} + return true, err + case 9: // responses.query + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseQuery) + err := b.DecodeMessage(msg) + m.Responses = &Response_Query{msg} + return true, err + case 10: // responses.init_chain + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseInitChain) + err := b.DecodeMessage(msg) + m.Responses = &Response_InitChain{msg} + return true, err + case 11: // responses.begin_block + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseBeginBlock) + err := b.DecodeMessage(msg) + m.Responses = &Response_BeginBlock{msg} + return true, err + case 12: // responses.end_block + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseEndBlock) + err := b.DecodeMessage(msg) + m.Responses = &Response_EndBlock{msg} + return true, err + default: + return false, nil + } +} + +func _Response_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Response) + // responses + switch x := m.Responses.(type) { + case *Response_Exception: + s := proto.Size(x.Exception) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_Echo: + s := proto.Size(x.Echo) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_Flush: + s := proto.Size(x.Flush) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_Info: + s := proto.Size(x.Info) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_SetOption: + s := proto.Size(x.SetOption) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_AppendTx: + s := proto.Size(x.AppendTx) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_CheckTx: + s := proto.Size(x.CheckTx) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_Commit: + s := proto.Size(x.Commit) + n += proto.SizeVarint(8<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_Query: + s := proto.Size(x.Query) + n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_InitChain: + s := proto.Size(x.InitChain) + n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_BeginBlock: + s := proto.Size(x.BeginBlock) + n += proto.SizeVarint(11<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_EndBlock: + s := proto.Size(x.EndBlock) + n += proto.SizeVarint(12<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type ResponseException struct { + Error string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` +} + +func (m *ResponseException) Reset() { *m = ResponseException{} } +func (m *ResponseException) String() string { return proto.CompactTextString(m) } +func (*ResponseException) ProtoMessage() {} +func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +type ResponseEcho struct { + Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` +} + +func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } +func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } +func (*ResponseEcho) ProtoMessage() {} +func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +type ResponseFlush struct { +} + +func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } +func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } +func (*ResponseFlush) ProtoMessage() {} +func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +type ResponseInfo struct { + Info string `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` +} + +func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } +func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } +func (*ResponseInfo) ProtoMessage() {} +func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +type ResponseSetOption struct { + Log string `protobuf:"bytes,1,opt,name=log" json:"log,omitempty"` +} + +func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } +func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } +func (*ResponseSetOption) ProtoMessage() {} +func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +type ResponseAppendTx 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"` +} + +func (m *ResponseAppendTx) Reset() { *m = ResponseAppendTx{} } +func (m *ResponseAppendTx) String() string { return proto.CompactTextString(m) } +func (*ResponseAppendTx) ProtoMessage() {} +func (*ResponseAppendTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +type ResponseCheckTx struct { + Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` +} + +func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } +func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } +func (*ResponseCheckTx) ProtoMessage() {} +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +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"` +} + +func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } +func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } +func (*ResponseQuery) ProtoMessage() {} +func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } + +type ResponseCommit 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"` +} + +func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } +func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } +func (*ResponseCommit) ProtoMessage() {} +func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } + +type ResponseInitChain struct { +} + +func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } +func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } +func (*ResponseInitChain) ProtoMessage() {} +func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } + +type ResponseBeginBlock struct { +} + +func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } +func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseBeginBlock) ProtoMessage() {} +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } + +type ResponseEndBlock struct { + Diffs []*Validator `protobuf:"bytes,4,rep,name=diffs" json:"diffs,omitempty"` +} + +func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } +func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseEndBlock) ProtoMessage() {} +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } + +func (m *ResponseEndBlock) GetDiffs() []*Validator { + if m != nil { + return m.Diffs } return nil } @@ -236,62 +1276,117 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func init() { proto.RegisterType((*Request)(nil), "types.Request") + proto.RegisterType((*RequestEcho)(nil), "types.RequestEcho") + proto.RegisterType((*RequestFlush)(nil), "types.RequestFlush") + proto.RegisterType((*RequestInfo)(nil), "types.RequestInfo") + proto.RegisterType((*RequestSetOption)(nil), "types.RequestSetOption") + proto.RegisterType((*RequestAppendTx)(nil), "types.RequestAppendTx") + proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") + proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") + proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") + proto.RegisterType((*RequestInitChain)(nil), "types.RequestInitChain") + proto.RegisterType((*RequestBeginBlock)(nil), "types.RequestBeginBlock") + proto.RegisterType((*RequestEndBlock)(nil), "types.RequestEndBlock") proto.RegisterType((*Response)(nil), "types.Response") + proto.RegisterType((*ResponseException)(nil), "types.ResponseException") + proto.RegisterType((*ResponseEcho)(nil), "types.ResponseEcho") + proto.RegisterType((*ResponseFlush)(nil), "types.ResponseFlush") + proto.RegisterType((*ResponseInfo)(nil), "types.ResponseInfo") + proto.RegisterType((*ResponseSetOption)(nil), "types.ResponseSetOption") + proto.RegisterType((*ResponseAppendTx)(nil), "types.ResponseAppendTx") + proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") + proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") + proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") + proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") + proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") + proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) } var fileDescriptor0 = []byte{ - // 729 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x94, 0x4b, 0x4f, 0xeb, 0x46, - 0x14, 0xc7, 0xeb, 0xc4, 0x09, 0xc9, 0x09, 0x84, 0xc9, 0x90, 0x80, 0x5b, 0x75, 0x81, 0xa8, 0x54, - 0x21, 0x16, 0xb4, 0xa2, 0xab, 0x2e, 0x49, 0x1a, 0x50, 0x84, 0x80, 0xd4, 0x3c, 0xf6, 0xc6, 0x3e, - 0x89, 0xa7, 0x71, 0x66, 0x8c, 0x3d, 0x06, 0xd2, 0xef, 0x55, 0x55, 0xba, 0xfb, 0xbb, 0xb8, 0xef, - 0xc7, 0x27, 0xba, 0x33, 0x7e, 0x24, 0x21, 0x77, 0x71, 0x17, 0x77, 0x13, 0xcd, 0xf9, 0xfd, 0x67, - 0xce, 0x39, 0xff, 0x33, 0x13, 0x43, 0x4b, 0xce, 0x42, 0x8c, 0x7f, 0x4b, 0x7f, 0x0f, 0xc3, 0x48, - 0x48, 0x41, 0x2b, 0x69, 0xb0, 0xf7, 0xbf, 0x01, 0x6b, 0x36, 0xde, 0x27, 0x18, 0x4b, 0xfa, 0x2b, - 0x98, 0x1a, 0x5a, 0xc6, 0xae, 0xb1, 0xdf, 0x3c, 0xa2, 0x87, 0xd9, 0xf6, 0x73, 0x8c, 0x63, 0x67, - 0x8c, 0xd7, 0x2a, 0xb0, 0x53, 0x9d, 0x52, 0x30, 0x3d, 0x47, 0x3a, 0x56, 0x49, 0xed, 0x5b, 0xb7, - 0xd3, 0x35, 0x25, 0x50, 0x9e, 0xe0, 0xcc, 0x2a, 0x2b, 0x54, 0xb7, 0xf5, 0x92, 0xb6, 0xa1, 0xf2, - 0xe0, 0x04, 0x09, 0x5a, 0x66, 0xca, 0xb2, 0x80, 0xfe, 0x0e, 0xa0, 0x16, 0x4c, 0x9d, 0x11, 0x51, - 0x6c, 0x55, 0x76, 0xcb, 0xfb, 0x8d, 0x23, 0x92, 0x57, 0xba, 0x2d, 0x04, 0x7b, 0x69, 0x0f, 0xdd, - 0x86, 0xaa, 0x8f, 0x6c, 0xec, 0x4b, 0xab, 0xaa, 0x12, 0x99, 0x76, 0x1e, 0xed, 0xbd, 0x34, 0xa0, - 0x66, 0x63, 0x1c, 0x0a, 0x1e, 0xe3, 0x77, 0xb5, 0xfe, 0x0b, 0x98, 0xae, 0xf0, 0x30, 0xed, 0xbd, - 0x79, 0xb4, 0x99, 0x9f, 0xed, 0x29, 0x94, 0x1d, 0xd4, 0xa2, 0x76, 0x83, 0x51, 0x24, 0xa2, 0xc2, - 0x4d, 0x1a, 0x68, 0xd7, 0x81, 0x18, 0x2b, 0x1b, 0xa9, 0x6b, 0xb5, 0x5c, 0xf1, 0x57, 0xfd, 0xb6, - 0xbf, 0xbd, 0x3f, 0xa1, 0x3e, 0x17, 0xb4, 0xd9, 0x30, 0xb9, 0x3b, 0x53, 0x93, 0x34, 0xd2, 0x0e, - 0xf3, 0x48, 0x97, 0x0f, 0xc5, 0x23, 0x46, 0x69, 0xe3, 0xa6, 0x9d, 0x05, 0x07, 0x2f, 0x0c, 0x68, - 0x2c, 0x79, 0xa4, 0x9b, 0xd0, 0xb8, 0x48, 0x82, 0x20, 0x47, 0xe4, 0x07, 0x5a, 0x03, 0xb3, 0xef, - 0xfa, 0x82, 0x18, 0xb4, 0x0e, 0x95, 0x93, 0x20, 0x89, 0x7d, 0x52, 0xd2, 0x70, 0xc0, 0x47, 0x82, - 0x94, 0xe9, 0x06, 0xd4, 0xaf, 0x50, 0x5e, 0x86, 0x92, 0x09, 0x4e, 0x4c, 0x1d, 0xf6, 0x9f, 0x5c, - 0xcc, 0xc2, 0x0a, 0x5d, 0x87, 0xda, 0x71, 0x18, 0x22, 0xf7, 0xae, 0x9f, 0x48, 0x8b, 0x36, 0x60, - 0xad, 0xe7, 0xa3, 0x3b, 0x51, 0x81, 0x9a, 0x22, 0x54, 0x7b, 0x62, 0x3a, 0x65, 0x92, 0x6c, 0xe9, - 0xcc, 0x7f, 0x27, 0x18, 0xcd, 0x48, 0x5b, 0x27, 0x18, 0x70, 0x26, 0x7b, 0xbe, 0xc3, 0x38, 0xe9, - 0xd0, 0x26, 0x40, 0x17, 0xc7, 0x8c, 0x77, 0x03, 0xe1, 0x4e, 0xc8, 0xb6, 0x4e, 0xd8, 0xe7, 0x5e, - 0x16, 0xed, 0x1c, 0xfc, 0x57, 0x81, 0x5a, 0x31, 0x64, 0x5a, 0x85, 0xd2, 0xe5, 0x99, 0x6a, 0xb8, - 0x05, 0x1b, 0x03, 0x2e, 0x31, 0xe2, 0x4e, 0xd0, 0xd7, 0x13, 0x56, 0x9d, 0x2b, 0xd4, 0xe7, 0xea, - 0x0e, 0x18, 0x1f, 0x67, 0xa8, 0xa4, 0x13, 0x75, 0x1d, 0xef, 0x42, 0x70, 0x17, 0x95, 0x0b, 0x02, - 0xeb, 0x37, 0xdc, 0x49, 0xa4, 0x2f, 0x22, 0xf6, 0x2f, 0x7a, 0xca, 0x48, 0x07, 0x5a, 0x03, 0x1e, - 0x27, 0xa3, 0x11, 0x73, 0x19, 0x72, 0x79, 0x92, 0x70, 0x2f, 0x56, 0x86, 0x28, 0x34, 0x6f, 0xf8, - 0x84, 0x8b, 0x47, 0x9e, 0xbf, 0x78, 0x52, 0xa5, 0x16, 0xb4, 0xbb, 0x4e, 0x8c, 0x7f, 0x25, 0x61, - 0xc0, 0x5c, 0x47, 0xe2, 0xb1, 0xe7, 0x45, 0x6a, 0x7c, 0x04, 0x75, 0x12, 0xad, 0x3c, 0xaf, 0x3d, - 0x2a, 0x0e, 0x3c, 0xcb, 0x8f, 0x18, 0x93, 0x31, 0xfd, 0x11, 0x3a, 0x5f, 0x29, 0x69, 0x65, 0x9f, - 0xfe, 0x0c, 0xd6, 0xaa, 0x74, 0xea, 0xc4, 0xc3, 0x88, 0x29, 0x03, 0x4c, 0x5d, 0x2e, 0xc9, 0xd4, - 0xf4, 0x55, 0x0c, 0x78, 0x98, 0x48, 0xf2, 0x4f, 0x51, 0x3f, 0xa7, 0x97, 0x89, 0xd4, 0x78, 0xb2, - 0x82, 0x87, 0xe9, 0xf3, 0x20, 0x01, 0xdd, 0x81, 0xad, 0x25, 0x7c, 0xa5, 0xfd, 0xe9, 0xe9, 0x4c, - 0x17, 0xfd, 0x66, 0x02, 0x1b, 0x73, 0x47, 0x26, 0x11, 0x12, 0xae, 0xde, 0x1a, 0xd5, 0x4a, 0x3e, - 0x92, 0xc2, 0xb8, 0x28, 0x2a, 0xe4, 0x3c, 0xaf, 0x10, 0xae, 0xe2, 0x20, 0x51, 0x37, 0x4b, 0xee, - 0x15, 0x26, 0xa7, 0xe2, 0x21, 0xa7, 0x7d, 0x2e, 0x99, 0x9c, 0x91, 0x57, 0x86, 0xf2, 0xb4, 0xb9, - 0xc0, 0xa7, 0x91, 0x48, 0x42, 0xf2, 0xda, 0x50, 0x5d, 0xd2, 0x05, 0x1d, 0x46, 0x22, 0x14, 0xb1, - 0x13, 0x90, 0x37, 0x86, 0xea, 0xa5, 0xa5, 0x84, 0xf9, 0x2d, 0x64, 0x07, 0xde, 0x16, 0x07, 0xe6, - 0xfc, 0x1c, 0xa7, 0x77, 0x18, 0x91, 0x77, 0x86, 0x1a, 0x76, 0x7b, 0x59, 0x98, 0xe7, 0x7a, 0x6f, - 0xe4, 0x1d, 0xcd, 0xa5, 0x5b, 0x21, 0x91, 0x7c, 0x28, 0x70, 0x3e, 0x87, 0x3c, 0xd1, 0x47, 0x83, - 0x6e, 0x41, 0x73, 0x81, 0xd3, 0xbd, 0x9f, 0x0c, 0xfa, 0x13, 0x74, 0x9e, 0x41, 0x75, 0xff, 0x43, - 0xfd, 0x8f, 0x23, 0x9f, 0x8d, 0xbb, 0x6a, 0xfa, 0xfd, 0xfc, 0xe3, 0x4b, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xc9, 0xcf, 0x96, 0x2d, 0x54, 0x05, 0x00, 0x00, + // 1244 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xc9, 0x72, 0xdb, 0x46, + 0x13, 0x36, 0xc4, 0xbd, 0x49, 0x51, 0xc3, 0x11, 0x65, 0xc3, 0x7f, 0xfd, 0x07, 0x07, 0xd9, 0xbc, + 0x95, 0x92, 0x92, 0x2b, 0xae, 0x28, 0xc9, 0xc5, 0x92, 0x69, 0x45, 0xe5, 0xb2, 0xa5, 0xd0, 0xcb, + 0x21, 0x4b, 0xa9, 0x40, 0x70, 0x48, 0x22, 0xa2, 0x66, 0x60, 0x2c, 0xb6, 0x94, 0x77, 0xc8, 0xe3, + 0xe4, 0x92, 0x07, 0x48, 0x55, 0xf6, 0xe5, 0x89, 0x32, 0x3d, 0x33, 0x00, 0x09, 0x08, 0xca, 0x49, + 0xb7, 0x99, 0xee, 0xfe, 0x1a, 0x3d, 0xdd, 0x5f, 0x7f, 0x2c, 0x42, 0x3b, 0x3e, 0x0b, 0x58, 0xb4, + 0x19, 0x84, 0x22, 0x16, 0xb4, 0xa6, 0x2e, 0xce, 0x4f, 0x55, 0x68, 0x0c, 0xd9, 0xab, 0x84, 0x45, + 0x31, 0xbd, 0x09, 0x55, 0xe6, 0xcd, 0x84, 0x6d, 0xdd, 0xb0, 0x6e, 0xb6, 0xb7, 0xe8, 0xa6, 0x0e, + 0x37, 0xde, 0x81, 0xf4, 0x7c, 0x7e, 0x65, 0xa8, 0x22, 0xe8, 0x1d, 0xa8, 0x4d, 0xe6, 0x49, 0x34, + 0xb3, 0x57, 0x54, 0xe8, 0x7a, 0x3e, 0xf4, 0x11, 0xba, 0x64, 0xac, 0x8e, 0xc1, 0xb4, 0x3e, 0x9f, + 0x08, 0xbb, 0x52, 0x96, 0x76, 0x5f, 0x7a, 0x30, 0x2d, 0x46, 0xd0, 0x8f, 0x01, 0x22, 0x16, 0x1f, + 0x89, 0x20, 0xf6, 0x05, 0xb7, 0xab, 0x2a, 0xfe, 0x5a, 0x3e, 0xfe, 0x19, 0x8b, 0x0f, 0x94, 0x5b, + 0x82, 0x5a, 0x51, 0x7a, 0xa1, 0x1f, 0x41, 0xcb, 0x0d, 0x02, 0xc6, 0xc7, 0x47, 0xf1, 0xa9, 0x5d, + 0x53, 0xc0, 0xab, 0x79, 0xe0, 0x03, 0xe5, 0x7e, 0x7e, 0x2a, 0x71, 0x4d, 0xd7, 0x9c, 0xe9, 0x16, + 0x34, 0xbd, 0x19, 0xf3, 0x8e, 0x11, 0x55, 0x57, 0xa8, 0x8d, 0x3c, 0x6a, 0x17, 0xbd, 0x0a, 0xd4, + 0xf0, 0xf4, 0x91, 0x6e, 0x42, 0xdd, 0x13, 0x27, 0x27, 0x7e, 0x6c, 0x37, 0x14, 0xa2, 0x5f, 0x40, + 0x28, 0x9f, 0x04, 0x98, 0x28, 0xec, 0x95, 0x74, 0x84, 0x67, 0x76, 0xb3, 0xac, 0x57, 0x5f, 0xa0, + 0x0b, 0x7b, 0xa5, 0x62, 0xb0, 0x03, 0x3e, 0xf7, 0xe3, 0x23, 0x6f, 0xe6, 0xfa, 0xdc, 0x6e, 0x95, + 0x75, 0x60, 0x5f, 0xfa, 0x77, 0xd1, 0x8d, 0x1d, 0xf0, 0xd3, 0x0b, 0xfd, 0x14, 0xda, 0x23, 0x36, + 0xf5, 0xf9, 0xd1, 0x68, 0x2e, 0xbc, 0x63, 0x1b, 0x14, 0xd4, 0xce, 0x43, 0x77, 0x30, 0x60, 0x07, + 0xfd, 0x12, 0x0b, 0xa3, 0xec, 0x86, 0xed, 0xc3, 0xde, 0x69, 0x68, 0xbb, 0xac, 0x7d, 0x03, 0x3e, + 0x4e, 0x81, 0x4d, 0x66, 0xce, 0x3b, 0x00, 0xcd, 0x50, 0xbb, 0x23, 0xe7, 0x7d, 0x68, 0x2f, 0x31, + 0x85, 0xda, 0xd0, 0x38, 0x61, 0x51, 0xe4, 0x4e, 0x99, 0xa2, 0x53, 0x6b, 0x98, 0x5e, 0x9d, 0x2e, + 0x74, 0x96, 0x79, 0xe2, 0xac, 0x66, 0x40, 0xe4, 0x82, 0xf3, 0x09, 0x90, 0xe2, 0xa8, 0x29, 0x81, + 0xca, 0x31, 0x3b, 0x33, 0x89, 0xf0, 0x48, 0xfb, 0x50, 0x7b, 0xed, 0xce, 0x13, 0xa6, 0x08, 0xd8, + 0x1a, 0xea, 0x8b, 0xf3, 0x16, 0xac, 0x15, 0xa6, 0x4d, 0xbb, 0xb0, 0x22, 0x67, 0x8b, 0xc8, 0xce, + 0x50, 0x9e, 0x9c, 0x1b, 0xd0, 0xcd, 0x8f, 0xf6, 0x5c, 0xc4, 0x3b, 0x59, 0x7d, 0x6a, 0x36, 0xf8, + 0x29, 0x3d, 0x3f, 0x1d, 0xa2, 0x2f, 0xce, 0x1a, 0xac, 0xe6, 0x06, 0xee, 0x3c, 0xcc, 0xea, 0xce, + 0x06, 0x44, 0x3f, 0x04, 0x90, 0x85, 0xf9, 0x63, 0x37, 0x16, 0x61, 0x24, 0xf1, 0x15, 0xd9, 0x57, + 0x62, 0xfa, 0xfa, 0x32, 0x75, 0x0c, 0x97, 0x62, 0x9c, 0x3b, 0xd0, 0x3b, 0x37, 0x2b, 0x7a, 0x15, + 0xea, 0x33, 0xe6, 0x4f, 0x67, 0xb1, 0x2a, 0xa1, 0x3a, 0x34, 0x37, 0xe7, 0x56, 0xf6, 0xdc, 0x74, + 0x3a, 0x17, 0x86, 0x7e, 0x5f, 0x83, 0xe6, 0x90, 0x45, 0x81, 0xe0, 0x11, 0x93, 0x24, 0x6b, 0xb1, + 0x53, 0x8f, 0xe9, 0x2d, 0xb3, 0x0a, 0x44, 0xd1, 0x31, 0x83, 0xd4, 0x8f, 0x24, 0xcb, 0x82, 0xe9, + 0x2d, 0xa3, 0x10, 0xc5, 0xb5, 0x37, 0xa0, 0x65, 0x89, 0xb8, 0x9b, 0x4a, 0x44, 0xa5, 0xb0, 0x25, + 0x3a, 0xb6, 0xa0, 0x11, 0xb7, 0x8c, 0x46, 0x54, 0x4b, 0x13, 0xe7, 0x44, 0x62, 0x3b, 0x27, 0x12, + 0xb5, 0xd2, 0xf2, 0x2f, 0x50, 0x89, 0xfb, 0xcb, 0x2a, 0x51, 0x2f, 0x2c, 0x97, 0x46, 0x96, 0xca, + 0xc4, 0xbd, 0x25, 0x99, 0x68, 0x14, 0xb6, 0x43, 0xc3, 0x4a, 0x74, 0xe2, 0x83, 0x4c, 0x27, 0x9a, + 0x05, 0x65, 0x31, 0x90, 0xa2, 0x50, 0xdc, 0x4d, 0x89, 0xd6, 0x2a, 0xed, 0x58, 0x41, 0x29, 0xb6, + 0x73, 0x4a, 0x01, 0xa5, 0x6d, 0xb8, 0x40, 0x2a, 0x3e, 0xcb, 0x4b, 0x85, 0xde, 0xf7, 0xeb, 0x05, + 0xec, 0x85, 0x5a, 0x71, 0x7f, 0x59, 0x2b, 0x3a, 0xa5, 0x4d, 0x2c, 0x15, 0x8b, 0x36, 0xb4, 0x42, + 0xe3, 0x8f, 0x24, 0x75, 0x7b, 0xe7, 0xa8, 0x86, 0x9b, 0xc6, 0xc2, 0x50, 0x84, 0x66, 0xd1, 0xf5, + 0xc5, 0xb9, 0x89, 0xfb, 0xb8, 0x20, 0xd8, 0x7f, 0x28, 0x8b, 0xda, 0xc9, 0x25, 0x7a, 0x39, 0xce, + 0x02, 0x8a, 0x14, 0xa2, 0xd4, 0xb0, 0x4c, 0xe3, 0xd4, 0xd9, 0x79, 0x77, 0x51, 0x49, 0x4e, 0x70, + 0xe6, 0x62, 0x9a, 0x0a, 0x8e, 0x3c, 0x3a, 0xdf, 0xe0, 0x7a, 0xe7, 0x29, 0x42, 0xdf, 0x86, 0xaa, + 0x27, 0xc6, 0xba, 0x8c, 0xee, 0xd6, 0x9a, 0x69, 0xc2, 0xae, 0x34, 0x3d, 0x97, 0xa7, 0xa1, 0x72, + 0xe2, 0x37, 0xe5, 0x6e, 0xbb, 0x6a, 0x65, 0x3a, 0x43, 0x75, 0x4e, 0xd3, 0x57, 0x16, 0xe9, 0xbf, + 0xc6, 0x55, 0xce, 0x51, 0xe9, 0x32, 0xb3, 0x7f, 0xb9, 0x68, 0x8c, 0xd6, 0xb4, 0x4b, 0xcc, 0xfd, + 0x15, 0x0a, 0xea, 0x32, 0xa3, 0x2f, 0x33, 0xf9, 0xfa, 0x62, 0x38, 0x19, 0x97, 0x9d, 0x3e, 0xd0, + 0xf3, 0x24, 0xd5, 0xbf, 0x1b, 0x79, 0xfa, 0xd1, 0xf7, 0xa0, 0x36, 0xf6, 0x27, 0x93, 0x48, 0xca, + 0x4a, 0xb9, 0xf4, 0x6a, 0xb7, 0xb3, 0x0d, 0xad, 0xcc, 0x86, 0x12, 0x1a, 0x24, 0xa3, 0xc7, 0x2c, + 0x15, 0x7c, 0x73, 0x43, 0x76, 0x06, 0xe2, 0x0d, 0x0b, 0x55, 0xc9, 0xd5, 0xa1, 0xbe, 0xdc, 0xfe, + 0xd1, 0x82, 0xf6, 0x13, 0xcd, 0x3f, 0x7c, 0x1d, 0x5d, 0x83, 0xf6, 0xd3, 0x64, 0x3e, 0x37, 0x26, + 0x72, 0x85, 0x36, 0xa1, 0x8a, 0xb4, 0x25, 0x16, 0x6d, 0x41, 0x4d, 0xd1, 0x92, 0xac, 0xa0, 0x11, + 0x09, 0x49, 0x2a, 0x74, 0x15, 0x5a, 0x19, 0xed, 0x48, 0x15, 0xaf, 0xd9, 0x3e, 0x90, 0x1a, 0xed, + 0x40, 0x33, 0x65, 0x1b, 0xe9, 0xd1, 0x36, 0x34, 0x0c, 0x39, 0x88, 0xec, 0x1f, 0xd4, 0x75, 0xbf, + 0xc9, 0x3a, 0x66, 0x56, 0x73, 0x25, 0x7d, 0x4c, 0x90, 0x75, 0x8a, 0x6c, 0xc8, 0x1f, 0x37, 0x58, + 0xf4, 0x88, 0x5c, 0xc5, 0x84, 0x69, 0x77, 0xc8, 0xb5, 0xdb, 0x3f, 0xc8, 0x5f, 0x85, 0x74, 0x2e, + 0xb4, 0x0e, 0x2b, 0x07, 0x8f, 0x65, 0xc1, 0x3d, 0x58, 0xdd, 0xe7, 0x31, 0x0b, 0xb9, 0x3b, 0x1f, + 0xe0, 0x02, 0xca, 0xca, 0xa5, 0x69, 0xc0, 0xe5, 0xd8, 0x7c, 0x3e, 0xd5, 0xa6, 0x15, 0x4c, 0xb4, + 0xe3, 0x8e, 0x9f, 0x0a, 0xee, 0x31, 0xf9, 0x0a, 0x02, 0x9d, 0x17, 0xdc, 0x4d, 0xe2, 0x99, 0x08, + 0xfd, 0xef, 0xd8, 0x58, 0x3e, 0x64, 0x03, 0x7a, 0xfb, 0x3c, 0x4a, 0x26, 0x13, 0xdf, 0xf3, 0x19, + 0x8f, 0x1f, 0x25, 0x7c, 0x1c, 0xc9, 0x07, 0x51, 0xe8, 0xbe, 0xe0, 0xc7, 0x5c, 0xbc, 0xe1, 0xe6, + 0x97, 0x8b, 0xd4, 0xe5, 0x42, 0xf7, 0x77, 0xdc, 0x88, 0x3d, 0x4c, 0x82, 0xb9, 0xef, 0xb9, 0x31, + 0x7b, 0x30, 0x1e, 0x4b, 0xa1, 0x88, 0x08, 0xc3, 0x24, 0xe8, 0xc9, 0x7f, 0x7b, 0x92, 0x02, 0x72, + 0xf9, 0x19, 0x8b, 0xc8, 0x94, 0x5e, 0x87, 0x8d, 0x73, 0x1e, 0xf5, 0xe5, 0x19, 0xfd, 0x3f, 0xd8, + 0x45, 0xd7, 0x9e, 0x1b, 0x1d, 0x86, 0xbe, 0x7c, 0x80, 0x2f, 0x87, 0x4b, 0xb4, 0x57, 0xfd, 0x16, + 0xef, 0xf3, 0x20, 0x89, 0xc9, 0xb7, 0xe9, 0xf7, 0x8d, 0xf5, 0x20, 0x89, 0xd1, 0x7c, 0x5c, 0x30, + 0x1f, 0x2a, 0x7a, 0x90, 0x39, 0xbd, 0x06, 0xeb, 0x4b, 0xe6, 0x67, 0xf8, 0x3e, 0xec, 0xce, 0xc9, + 0xa2, 0x5e, 0xed, 0xf0, 0xa7, 0xdc, 0x8d, 0x93, 0x90, 0x11, 0x2e, 0xb9, 0x46, 0xd1, 0x63, 0x5a, + 0x92, 0x3e, 0x5c, 0xa4, 0x5f, 0x30, 0x76, 0xf3, 0x85, 0xa0, 0x68, 0x9e, 0x27, 0x72, 0xb2, 0xe4, + 0x95, 0x34, 0x93, 0x3d, 0xf1, 0xda, 0x58, 0x07, 0x3c, 0xf6, 0xe3, 0x33, 0xf2, 0xb3, 0x25, 0xdf, + 0xb4, 0xb6, 0x30, 0xef, 0x85, 0x22, 0x09, 0xc8, 0x2f, 0x96, 0xac, 0x92, 0x2e, 0xac, 0x87, 0xa1, + 0x08, 0x44, 0xe4, 0xce, 0xc9, 0xaf, 0x96, 0xac, 0xa5, 0x27, 0x1d, 0xd9, 0x14, 0x34, 0xe0, 0xb7, + 0x14, 0x90, 0xd9, 0x9f, 0xb0, 0x93, 0x11, 0x0b, 0xc9, 0xef, 0x96, 0x6c, 0x76, 0x7f, 0xd9, 0x91, + 0xe5, 0xfa, 0xc3, 0x32, 0x15, 0x65, 0xae, 0x97, 0x22, 0x66, 0xe4, 0xcf, 0xd4, 0x6c, 0xfa, 0x60, + 0x12, 0xfd, 0x65, 0xd1, 0x75, 0xe8, 0x2e, 0xcc, 0x2a, 0xf6, 0x6f, 0x8b, 0xfe, 0x0f, 0x36, 0x72, + 0x46, 0x39, 0xff, 0x43, 0xdc, 0x38, 0xf2, 0x8f, 0x35, 0xaa, 0xab, 0xbf, 0x30, 0xf7, 0xfe, 0x0d, + 0x00, 0x00, 0xff, 0xff, 0x54, 0x89, 0x64, 0x9a, 0xd1, 0x0c, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 37a4fa6a..4df19b82 100644 --- a/types/types.proto +++ b/types/types.proto @@ -70,24 +70,136 @@ enum CodeType { // Request types message Request { - MessageType type = 1; - bytes data = 2; - string key = 3; - string value = 4; - repeated Validator validators = 5; - uint64 height = 6; + oneof requests{ + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestAppendTx append_tx = 5; + RequestCheckTx check_tx = 6; + RequestCommit commit = 7; + RequestQuery query = 8; + RequestInitChain init_chain = 9; + RequestBeginBlock begin_block = 10; + RequestEndBlock end_block = 11; + } +} + +message RequestEcho { + string message = 1; +} + +message RequestFlush { +} + +message RequestInfo { +} + +message RequestSetOption{ + string key = 1; + string value = 2; +} + +message RequestAppendTx{ + bytes tx = 1; +} + +message RequestCheckTx{ + bytes tx = 1; +} + +message RequestQuery{ + bytes query = 1; +} + +message RequestCommit{ +} + +message RequestInitChain{ + repeated Validator validators = 1; +} + +message RequestBeginBlock{ + uint64 height = 1; +} + +message RequestEndBlock{ + uint64 height = 1; } //---------------------------------------- // Response types + message Response { - MessageType type = 1; - bytes data = 2; - CodeType code = 3; - string error = 4; - string log = 5; - repeated Validator validators = 6; + oneof responses{ + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseAppendTx append_tx = 6; + ResponseCheckTx check_tx = 7; + ResponseCommit commit = 8; + ResponseQuery query = 9; + ResponseInitChain init_chain = 10; + ResponseBeginBlock begin_block = 11; + ResponseEndBlock end_block = 12; + } +} + +message ResponseException{ + string error = 1; +} + +message ResponseEcho { + string message = 1; +} + +message ResponseFlush{ +} + +message ResponseInfo { + string info = 1; +} + +message ResponseSetOption{ + string log = 1; +} + +message ResponseAppendTx{ + CodeType code = 1; + bytes data = 2; + string log = 3; +} + +message ResponseCheckTx{ + CodeType code = 1; + bytes data = 2; + string log = 3; +} + +message ResponseQuery{ + CodeType code = 1; + bytes data = 2; + string log = 3; +} + +message ResponseCommit{ + CodeType code = 1; + bytes data = 2; + string log = 3; +} + + +message ResponseInitChain{ +} + +message ResponseBeginBlock{ +} + +message ResponseEndBlock{ + repeated Validator diffs = 4; } //---------------------------------------- From 32f83f9494b2fc908808f5246dd854a846c72deb Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 14 May 2016 03:09:47 -0400 Subject: [PATCH 108/545] fix up tmsp-cli, tests --- cmd/tmsp-cli/tmsp-cli.go | 110 ++++++-------------------- example/dummy/dummy_test.go | 19 ++--- example/nil/nil_test.go | 19 ++--- tests/benchmarks/parallel/parallel.go | 2 +- tests/benchmarks/simple/simple.go | 9 ++- types/messages.go | 2 +- 6 files changed, 53 insertions(+), 108 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 275bb23a..9e746b57 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -5,18 +5,18 @@ import ( "errors" "fmt" "io" - "net" "os" "strings" "github.com/codegangsta/cli" . "github.com/tendermint/go-common" "github.com/tendermint/go-wire/expr" + "github.com/tendermint/tmsp/client" "github.com/tendermint/tmsp/types" ) -// connection is a global variable so it can be reused by the console -var conn net.Conn +// clientection is a global variable so it can be reused by the console +var client tmspcli.Client func main() { app := cli.NewApp() @@ -103,9 +103,9 @@ func main() { } func before(c *cli.Context) error { - if conn == nil { + if client == nil { var err error - conn, err = Connect(c.GlobalString("address")) + client, err = tmspcli.NewClient(c.GlobalString("address"), false) if err != nil { Exit(err.Error()) } @@ -148,7 +148,9 @@ func cmdConsole(app *cli.App, c *cli.Context) error { args := []string{"tmsp"} args = append(args, strings.Split(string(line), " ")...) - app.Run(args) + if err := app.Run(args); err != nil { + return err + } } return nil } @@ -159,21 +161,15 @@ func cmdEcho(c *cli.Context) error { if len(args) != 1 { return errors.New("Command echo takes 1 argument") } - res, err := makeRequest(conn, types.RequestEcho(args[0])) - if err != nil { - return err - } - printResponse(res, string(res.Data)) + res := client.EchoSync(args[0]) + printResponse(res, string(res.Data), false) return nil } // Get some info from the application func cmdInfo(c *cli.Context) error { - res, err := makeRequest(conn, types.RequestInfo()) - if err != nil { - return err - } - printResponse(res, string(res.Data)) + res := client.InfoSync() + printResponse(res, string(res.Data), false) return nil } @@ -183,11 +179,8 @@ func cmdSetOption(c *cli.Context) error { if len(args) != 2 { return errors.New("Command set_option takes 2 arguments (key, value)") } - res, err := makeRequest(conn, types.RequestSetOption(args[0], args[1])) - if err != nil { - return err - } - printResponse(res, Fmt("%s=%s", args[0], args[1])) + res := client.SetOptionSync(args[0], args[1]) + printResponse(res, Fmt("%s=%s", args[0], args[1]), false) return nil } @@ -203,11 +196,8 @@ func cmdAppendTx(c *cli.Context) error { return err } - res, err := makeRequest(conn, types.RequestAppendTx(txBytes)) - if err != nil { - return err - } - printResponse(res, string(res.Data)) + res := client.AppendTxSync(txBytes) + printResponse(res, string(res.Data), true) return nil } @@ -223,21 +213,15 @@ func cmdCheckTx(c *cli.Context) error { return err } - res, err := makeRequest(conn, types.RequestCheckTx(txBytes)) - if err != nil { - return err - } - printResponse(res, string(res.Data)) + res := client.CheckTxSync(txBytes) + printResponse(res, string(res.Data), true) return nil } // Get application Merkle root hash func cmdCommit(c *cli.Context) error { - res, err := makeRequest(conn, types.RequestCommit()) - if err != nil { - return err - } - printResponse(res, Fmt("%X", res.Data)) + res := client.CommitSync() + printResponse(res, Fmt("%X", res.Data), false) return nil } @@ -253,24 +237,20 @@ func cmdQuery(c *cli.Context) error { return err } - res, err := makeRequest(conn, types.RequestQuery(queryBytes)) - if err != nil { - return err - } - printResponse(res, string(res.Data)) + res := client.QuerySync(queryBytes) + printResponse(res, string(res.Data), true) return nil } //-------------------------------------------------------------------------------- -func printResponse(res *types.Response, s string) { - switch res.Type { - case types.MessageType_AppendTx, types.MessageType_CheckTx, types.MessageType_Query: +func printResponse(res types.Result, s string, printCode bool) { + if printCode { fmt.Printf("-> code: %s\n", res.Code.String()) } - if res.Error != "" { + /*if res.Error != "" { fmt.Printf("-> error: %s\n", res.Error) - } + }*/ if s != "" { fmt.Printf("-> data: {%s}\n", s) } @@ -279,41 +259,3 @@ func printResponse(res *types.Response, s string) { } } - -func responseString(res *types.Response) string { - return Fmt("type: %v\tdata: %v\tcode: %v", res.Type, res.Data, res.Code) -} - -func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { - - // Write desired request - err := types.WriteMessage(req, conn) - if err != nil { - return nil, err - } - - // Write flush request - err = types.WriteMessage(types.RequestFlush(), conn) - if err != nil { - return nil, err - } - - // Read desired response - var res = &types.Response{} - err = types.ReadMessage(conn, res) - if err != nil { - return nil, err - } - - // Read flush response - var resFlush = &types.Response{} - err = types.ReadMessage(conn, resFlush) - if err != nil { - return nil, err - } - if resFlush.Type != types.MessageType_Flush { - return nil, errors.New(Fmt("Expected types.MessageType_Flush but got %v instead", resFlush.Type)) - } - - return res, nil -} diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 22338b00..bfde4001 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -1,6 +1,7 @@ package dummy import ( + "reflect" "testing" "time" @@ -39,11 +40,11 @@ func TestStream(t *testing.T) { } // Process response - switch res.Type { - case types.MessageType_AppendTx: + switch r := res.Responses.(type) { + case *types.Response_AppendTx: counter += 1 - if res.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", res.Code) + if r.AppendTx.Code != types.CodeType_OK { + t.Error("AppendTx failed with ret_code", r.AppendTx.Code) } if counter > numAppendTxs { t.Fatal("Too many AppendTx responses") @@ -55,10 +56,10 @@ func TestStream(t *testing.T) { close(done) }() } - case types.MessageType_Flush: + case *types.Response_Flush: // ignore default: - t.Error("Unexpected response type", res.Type) + t.Error("Unexpected response type", reflect.TypeOf(res.Responses)) } } }() @@ -66,7 +67,7 @@ func TestStream(t *testing.T) { // Write requests for counter := 0; counter < numAppendTxs; counter++ { // Send request - var req = types.RequestAppendTx([]byte("test")) + var req = types.ToRequestAppendTx([]byte("test")) err := types.WriteMessage(req, conn) if err != nil { t.Fatal(err.Error()) @@ -75,7 +76,7 @@ func TestStream(t *testing.T) { // Sometimes send flush messages if counter%123 == 0 { t.Log("flush") - err := types.WriteMessage(types.RequestFlush(), conn) + err := types.WriteMessage(types.ToRequestFlush(), conn) if err != nil { t.Fatal(err.Error()) } @@ -83,7 +84,7 @@ func TestStream(t *testing.T) { } // Send final flush message - err = types.WriteMessage(types.RequestFlush(), conn) + err = types.WriteMessage(types.ToRequestFlush(), conn) if err != nil { t.Fatal(err.Error()) } diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go index 0f3f6adb..953e86d9 100644 --- a/example/nil/nil_test.go +++ b/example/nil/nil_test.go @@ -1,6 +1,7 @@ package nilapp import ( + "reflect" "testing" "time" @@ -39,11 +40,11 @@ func TestStream(t *testing.T) { } // Process response - switch res.Type { - case types.MessageType_AppendTx: + switch r := res.Responses.(type) { + case *types.Response_AppendTx: counter += 1 - if res.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", res.Code) + if r.AppendTx.Code != types.CodeType_OK { + t.Error("AppendTx failed with ret_code", r.AppendTx.Code) } if counter > numAppendTxs { t.Fatal("Too many AppendTx responses") @@ -55,10 +56,10 @@ func TestStream(t *testing.T) { close(done) }() } - case types.MessageType_Flush: + case *types.Response_Flush: // ignore default: - t.Error("Unexpected response type", res.Type) + t.Error("Unexpected response type", reflect.TypeOf(res.Responses)) } } }() @@ -66,7 +67,7 @@ func TestStream(t *testing.T) { // Write requests for counter := 0; counter < numAppendTxs; counter++ { // Send request - var req = types.RequestAppendTx([]byte("test")) + var req = types.ToRequestAppendTx([]byte("test")) err := types.WriteMessage(req, conn) if err != nil { t.Fatal(err.Error()) @@ -75,7 +76,7 @@ func TestStream(t *testing.T) { // Sometimes send flush messages if counter%123 == 0 { t.Log("flush") - err := types.WriteMessage(types.RequestFlush(), conn) + err := types.WriteMessage(types.ToRequestFlush(), conn) if err != nil { t.Fatal(err.Error()) } @@ -83,7 +84,7 @@ func TestStream(t *testing.T) { } // Send final flush message - err = types.WriteMessage(types.RequestFlush(), conn) + err = types.WriteMessage(types.ToRequestFlush(), conn) if err != nil { t.Fatal(err.Error()) } diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 7cab2eb2..db57e19b 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -36,7 +36,7 @@ func main() { counter := 0 for i := 0; ; i++ { var bufWriter = bufio.NewWriter(conn) - var req = types.RequestEcho("foobar") + var req = types.ToRequestEcho("foobar") err := types.WriteMessage(req, bufWriter) if err != nil { diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 8fb02585..61016ab8 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net" + "reflect" //"encoding/hex" . "github.com/tendermint/go-common" @@ -21,7 +22,7 @@ func main() { // Make a bunch of requests counter := 0 for i := 0; ; i++ { - req := types.RequestEcho("foobar") + req := types.ToRequestEcho("foobar") _, err := makeRequest(conn, req) if err != nil { Exit(err.Error()) @@ -41,7 +42,7 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { if err != nil { return nil, err } - err = types.WriteMessage(types.RequestFlush(), bufWriter) + err = types.WriteMessage(types.ToRequestFlush(), bufWriter) if err != nil { return nil, err } @@ -61,8 +62,8 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { if err != nil { return nil, err } - if resFlush.Type != types.MessageType_Flush { - return nil, errors.New(Fmt("Expected flush response but got something else: %v", resFlush.Type)) + if _, ok := resFlush.Responses.(*types.Response_Flush); !ok { + return nil, errors.New(Fmt("Expected flush response but got something else: %v", reflect.TypeOf(resFlush))) } return res, nil diff --git a/types/messages.go b/types/messages.go index 730e3d6f..4249c1c0 100644 --- a/types/messages.go +++ b/types/messages.go @@ -9,7 +9,7 @@ import ( func ToRequestEcho(message string) *Request { return &Request{ - Requests: &Request_Echo{&RequestEcho{}}, + Requests: &Request_Echo{&RequestEcho{message}}, } } From 5dc7bee57b1b3b50a5cbf5230f541cb85ed84125 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 17 May 2016 20:06:24 -0400 Subject: [PATCH 109/545] Responses/Requests -> Value --- client/remote_client.go | 36 +-- example/dummy/dummy_test.go | 4 +- example/nil/nil_test.go | 4 +- server/server.go | 10 +- tests/benchmarks/simple/simple.go | 2 +- types/messages.go | 46 ++-- types/types.pb.go | 388 +++++++++++++++--------------- types/types.proto | 8 +- 8 files changed, 253 insertions(+), 245 deletions(-) diff --git a/client/remote_client.go b/client/remote_client.go index 5d6dd6dc..d8370eee 100644 --- a/client/remote_client.go +++ b/client/remote_client.go @@ -79,7 +79,7 @@ func (cli *remoteClient) OnStart() (err error) { continue RETRY_LOOP } } - go cli.sendRequestsRoutine(conn) + go cli.sendValueRoutine(conn) go cli.recvResponseRoutine(conn) close(doneCh) // OnStart() will return no error. return @@ -122,7 +122,7 @@ func (cli *remoteClient) Error() error { //---------------------------------------- -func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { +func (cli *remoteClient) sendValueRoutine(conn net.Conn) { w := bufio.NewWriter(conn) for { select { @@ -142,7 +142,7 @@ func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { return } // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) - if _, ok := reqres.Request.Requests.(*types.Request_Flush); ok { + if _, ok := reqres.Request.Value.(*types.Request_Flush); ok { err = w.Flush() if err != nil { cli.StopForError(err) @@ -162,7 +162,7 @@ func (cli *remoteClient) recvResponseRoutine(conn net.Conn) { cli.StopForError(err) return } - switch r := res.Responses.(type) { + switch r := res.Value.(type) { case *types.Response_Exception: // XXX After setting cli.err, release waiters (e.g. reqres.Done()) cli.StopForError(errors.New(r.Exception.Error)) @@ -189,12 +189,12 @@ func (cli *remoteClient) didRecvResponse(res *types.Response) error { // Get the first ReqRes next := cli.reqSent.Front() if next == nil { - return fmt.Errorf("Unexpected result type %v when nothing expected", reflect.TypeOf(res.Responses)) + return fmt.Errorf("Unexpected result type %v when nothing expected", reflect.TypeOf(res.Value)) } reqres := next.Value.(*ReqRes) if !resMatchesReq(reqres.Request, res) { return fmt.Errorf("Unexpected result type %v when response to %v expected", - reflect.TypeOf(res.Responses), reflect.TypeOf(reqres.Request.Requests)) + reflect.TypeOf(res.Value), reflect.TypeOf(reqres.Request.Value)) } reqres.Response = res // Set response @@ -372,7 +372,7 @@ func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { cli.reqQueue <- reqres // Maybe auto-flush, or unset auto-flush - switch req.Requests.(type) { + switch req.Value.(type) { case *types.Request_Flush: cli.flushTimer.Unset() default: @@ -385,27 +385,27 @@ func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { //---------------------------------------- func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { - switch req.Requests.(type) { + switch req.Value.(type) { case *types.Request_Echo: - _, ok = res.Responses.(*types.Response_Echo) + _, ok = res.Value.(*types.Response_Echo) case *types.Request_Flush: - _, ok = res.Responses.(*types.Response_Flush) + _, ok = res.Value.(*types.Response_Flush) case *types.Request_Info: - _, ok = res.Responses.(*types.Response_Info) + _, ok = res.Value.(*types.Response_Info) case *types.Request_SetOption: - _, ok = res.Responses.(*types.Response_SetOption) + _, ok = res.Value.(*types.Response_SetOption) case *types.Request_AppendTx: - _, ok = res.Responses.(*types.Response_AppendTx) + _, ok = res.Value.(*types.Response_AppendTx) case *types.Request_CheckTx: - _, ok = res.Responses.(*types.Response_CheckTx) + _, ok = res.Value.(*types.Response_CheckTx) case *types.Request_Commit: - _, ok = res.Responses.(*types.Response_Commit) + _, ok = res.Value.(*types.Response_Commit) case *types.Request_Query: - _, ok = res.Responses.(*types.Response_Query) + _, ok = res.Value.(*types.Response_Query) case *types.Request_InitChain: - _, ok = res.Responses.(*types.Response_InitChain) + _, ok = res.Value.(*types.Response_InitChain) case *types.Request_EndBlock: - _, ok = res.Responses.(*types.Response_EndBlock) + _, ok = res.Value.(*types.Response_EndBlock) } return ok } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index bfde4001..7fcffd84 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -40,7 +40,7 @@ func TestStream(t *testing.T) { } // Process response - switch r := res.Responses.(type) { + switch r := res.Value.(type) { case *types.Response_AppendTx: counter += 1 if r.AppendTx.Code != types.CodeType_OK { @@ -59,7 +59,7 @@ func TestStream(t *testing.T) { case *types.Response_Flush: // ignore default: - t.Error("Unexpected response type", reflect.TypeOf(res.Responses)) + t.Error("Unexpected response type", reflect.TypeOf(res.Value)) } } }() diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go index 953e86d9..0ef143c7 100644 --- a/example/nil/nil_test.go +++ b/example/nil/nil_test.go @@ -40,7 +40,7 @@ func TestStream(t *testing.T) { } // Process response - switch r := res.Responses.(type) { + switch r := res.Value.(type) { case *types.Response_AppendTx: counter += 1 if r.AppendTx.Code != types.CodeType_OK { @@ -59,7 +59,7 @@ func TestStream(t *testing.T) { case *types.Response_Flush: // ignore default: - t.Error("Unexpected response type", reflect.TypeOf(res.Responses)) + t.Error("Unexpected response type", reflect.TypeOf(res.Value)) } } }() diff --git a/server/server.go b/server/server.go index dd2430a1..f5d6e556 100644 --- a/server/server.go +++ b/server/server.go @@ -113,7 +113,7 @@ func (s *Server) handleRequests(closeConn chan error, conn net.Conn, responses c if err == io.EOF { closeConn <- fmt.Errorf("Connection closed by client") } else { - closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error()) + closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) } return } @@ -125,7 +125,7 @@ func (s *Server) handleRequests(closeConn chan error, conn net.Conn, responses c } func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Response) { - switch r := req.Requests.(type) { + switch r := req.Value.(type) { case *types.Request_Echo: responses <- types.ToResponseEcho(r.Echo.Message) case *types.Request_Flush: @@ -176,13 +176,13 @@ func (s *Server) handleResponses(closeConn chan error, responses <-chan *types.R var res = <-responses err := types.WriteMessage(res, bufWriter) if err != nil { - closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) + closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) return } - if _, ok := res.Responses.(*types.Response_Flush); ok { + if _, ok := res.Value.(*types.Response_Flush); ok { err = bufWriter.Flush() if err != nil { - closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error()) + closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) return } } diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 61016ab8..585ebd2b 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -62,7 +62,7 @@ func makeRequest(conn net.Conn, req *types.Request) (*types.Response, error) { if err != nil { return nil, err } - if _, ok := resFlush.Responses.(*types.Response_Flush); !ok { + if _, ok := resFlush.Value.(*types.Response_Flush); !ok { return nil, errors.New(Fmt("Expected flush response but got something else: %v", reflect.TypeOf(resFlush))) } diff --git a/types/messages.go b/types/messages.go index 4249c1c0..6b047d47 100644 --- a/types/messages.go +++ b/types/messages.go @@ -9,67 +9,67 @@ import ( func ToRequestEcho(message string) *Request { return &Request{ - Requests: &Request_Echo{&RequestEcho{message}}, + Value: &Request_Echo{&RequestEcho{message}}, } } func ToRequestFlush() *Request { return &Request{ - Requests: &Request_Flush{&RequestFlush{}}, + Value: &Request_Flush{&RequestFlush{}}, } } func ToRequestInfo() *Request { return &Request{ - Requests: &Request_Info{&RequestInfo{}}, + Value: &Request_Info{&RequestInfo{}}, } } func ToRequestSetOption(key string, value string) *Request { return &Request{ - Requests: &Request_SetOption{&RequestSetOption{key, value}}, + Value: &Request_SetOption{&RequestSetOption{key, value}}, } } func ToRequestAppendTx(txBytes []byte) *Request { return &Request{ - Requests: &Request_AppendTx{&RequestAppendTx{txBytes}}, + Value: &Request_AppendTx{&RequestAppendTx{txBytes}}, } } func ToRequestCheckTx(txBytes []byte) *Request { return &Request{ - Requests: &Request_CheckTx{&RequestCheckTx{txBytes}}, + Value: &Request_CheckTx{&RequestCheckTx{txBytes}}, } } func ToRequestCommit() *Request { return &Request{ - Requests: &Request_Commit{&RequestCommit{}}, + Value: &Request_Commit{&RequestCommit{}}, } } func ToRequestQuery(queryBytes []byte) *Request { return &Request{ - Requests: &Request_Query{&RequestQuery{queryBytes}}, + Value: &Request_Query{&RequestQuery{queryBytes}}, } } func ToRequestInitChain(validators []*Validator) *Request { return &Request{ - Requests: &Request_InitChain{&RequestInitChain{validators}}, + Value: &Request_InitChain{&RequestInitChain{validators}}, } } func ToRequestBeginBlock(height uint64) *Request { return &Request{ - Requests: &Request_BeginBlock{&RequestBeginBlock{height}}, + Value: &Request_BeginBlock{&RequestBeginBlock{height}}, } } func ToRequestEndBlock(height uint64) *Request { return &Request{ - Requests: &Request_EndBlock{&RequestEndBlock{height}}, + Value: &Request_EndBlock{&RequestEndBlock{height}}, } } @@ -77,73 +77,73 @@ func ToRequestEndBlock(height uint64) *Request { func ToResponseException(errStr string) *Response { return &Response{ - Responses: &Response_Exception{&ResponseException{errStr}}, + Value: &Response_Exception{&ResponseException{errStr}}, } } func ToResponseEcho(message string) *Response { return &Response{ - Responses: &Response_Echo{&ResponseEcho{message}}, + Value: &Response_Echo{&ResponseEcho{message}}, } } func ToResponseFlush() *Response { return &Response{ - Responses: &Response_Flush{&ResponseFlush{}}, + Value: &Response_Flush{&ResponseFlush{}}, } } func ToResponseInfo(info string) *Response { return &Response{ - Responses: &Response_Info{&ResponseInfo{info}}, + Value: &Response_Info{&ResponseInfo{info}}, } } func ToResponseSetOption(log string) *Response { return &Response{ - Responses: &Response_SetOption{&ResponseSetOption{log}}, + Value: &Response_SetOption{&ResponseSetOption{log}}, } } func ToResponseAppendTx(code CodeType, data []byte, log string) *Response { return &Response{ - Responses: &Response_AppendTx{&ResponseAppendTx{code, data, log}}, + Value: &Response_AppendTx{&ResponseAppendTx{code, data, log}}, } } func ToResponseCheckTx(code CodeType, data []byte, log string) *Response { return &Response{ - Responses: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, + Value: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, } } func ToResponseCommit(code CodeType, data []byte, log string) *Response { return &Response{ - Responses: &Response_Commit{&ResponseCommit{code, data, log}}, + Value: &Response_Commit{&ResponseCommit{code, data, log}}, } } func ToResponseQuery(code CodeType, data []byte, log string) *Response { return &Response{ - Responses: &Response_Query{&ResponseQuery{code, data, log}}, + Value: &Response_Query{&ResponseQuery{code, data, log}}, } } func ToResponseInitChain() *Response { return &Response{ - Responses: &Response_InitChain{&ResponseInitChain{}}, + Value: &Response_InitChain{&ResponseInitChain{}}, } } func ToResponseBeginBlock() *Response { return &Response{ - Responses: &Response_BeginBlock{&ResponseBeginBlock{}}, + Value: &Response_BeginBlock{&ResponseBeginBlock{}}, } } func ToResponseEndBlock(validators []*Validator) *Response { return &Response{ - Responses: &Response_EndBlock{&ResponseEndBlock{validators}}, + Value: &Response_EndBlock{&ResponseEndBlock{validators}}, } } diff --git a/types/types.pb.go b/types/types.pb.go index 5e94e290..3d803236 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -51,6 +51,10 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. const _ = proto.ProtoPackageIsVersion1 +// 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) type MessageType int32 const ( @@ -214,7 +218,7 @@ func (x CodeType) String() string { func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } type Request struct { - // Types that are valid to be assigned to Requests: + // Types that are valid to be assigned to Value: // *Request_Echo // *Request_Flush // *Request_Info @@ -226,7 +230,7 @@ type Request struct { // *Request_InitChain // *Request_BeginBlock // *Request_EndBlock - Requests isRequest_Requests `protobuf_oneof:"requests"` + Value isRequest_Value `protobuf_oneof:"value"` } func (m *Request) Reset() { *m = Request{} } @@ -234,8 +238,8 @@ func (m *Request) String() string { return proto.CompactTextString(m) func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -type isRequest_Requests interface { - isRequest_Requests() +type isRequest_Value interface { + isRequest_Value() } type Request_Echo struct { @@ -272,97 +276,97 @@ type Request_EndBlock struct { EndBlock *RequestEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,oneof"` } -func (*Request_Echo) isRequest_Requests() {} -func (*Request_Flush) isRequest_Requests() {} -func (*Request_Info) isRequest_Requests() {} -func (*Request_SetOption) isRequest_Requests() {} -func (*Request_AppendTx) isRequest_Requests() {} -func (*Request_CheckTx) isRequest_Requests() {} -func (*Request_Commit) isRequest_Requests() {} -func (*Request_Query) isRequest_Requests() {} -func (*Request_InitChain) isRequest_Requests() {} -func (*Request_BeginBlock) isRequest_Requests() {} -func (*Request_EndBlock) isRequest_Requests() {} +func (*Request_Echo) isRequest_Value() {} +func (*Request_Flush) isRequest_Value() {} +func (*Request_Info) isRequest_Value() {} +func (*Request_SetOption) isRequest_Value() {} +func (*Request_AppendTx) isRequest_Value() {} +func (*Request_CheckTx) isRequest_Value() {} +func (*Request_Commit) isRequest_Value() {} +func (*Request_Query) isRequest_Value() {} +func (*Request_InitChain) isRequest_Value() {} +func (*Request_BeginBlock) isRequest_Value() {} +func (*Request_EndBlock) isRequest_Value() {} -func (m *Request) GetRequests() isRequest_Requests { +func (m *Request) GetValue() isRequest_Value { if m != nil { - return m.Requests + return m.Value } return nil } func (m *Request) GetEcho() *RequestEcho { - if x, ok := m.GetRequests().(*Request_Echo); ok { + if x, ok := m.GetValue().(*Request_Echo); ok { return x.Echo } return nil } func (m *Request) GetFlush() *RequestFlush { - if x, ok := m.GetRequests().(*Request_Flush); ok { + if x, ok := m.GetValue().(*Request_Flush); ok { return x.Flush } return nil } func (m *Request) GetInfo() *RequestInfo { - if x, ok := m.GetRequests().(*Request_Info); ok { + if x, ok := m.GetValue().(*Request_Info); ok { return x.Info } return nil } func (m *Request) GetSetOption() *RequestSetOption { - if x, ok := m.GetRequests().(*Request_SetOption); ok { + if x, ok := m.GetValue().(*Request_SetOption); ok { return x.SetOption } return nil } func (m *Request) GetAppendTx() *RequestAppendTx { - if x, ok := m.GetRequests().(*Request_AppendTx); ok { + if x, ok := m.GetValue().(*Request_AppendTx); ok { return x.AppendTx } return nil } func (m *Request) GetCheckTx() *RequestCheckTx { - if x, ok := m.GetRequests().(*Request_CheckTx); ok { + if x, ok := m.GetValue().(*Request_CheckTx); ok { return x.CheckTx } return nil } func (m *Request) GetCommit() *RequestCommit { - if x, ok := m.GetRequests().(*Request_Commit); ok { + if x, ok := m.GetValue().(*Request_Commit); ok { return x.Commit } return nil } func (m *Request) GetQuery() *RequestQuery { - if x, ok := m.GetRequests().(*Request_Query); ok { + if x, ok := m.GetValue().(*Request_Query); ok { return x.Query } return nil } func (m *Request) GetInitChain() *RequestInitChain { - if x, ok := m.GetRequests().(*Request_InitChain); ok { + if x, ok := m.GetValue().(*Request_InitChain); ok { return x.InitChain } return nil } func (m *Request) GetBeginBlock() *RequestBeginBlock { - if x, ok := m.GetRequests().(*Request_BeginBlock); ok { + if x, ok := m.GetValue().(*Request_BeginBlock); ok { return x.BeginBlock } return nil } func (m *Request) GetEndBlock() *RequestEndBlock { - if x, ok := m.GetRequests().(*Request_EndBlock); ok { + if x, ok := m.GetValue().(*Request_EndBlock); ok { return x.EndBlock } return nil @@ -387,8 +391,8 @@ func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Request) - // requests - switch x := m.Requests.(type) { + // value + switch x := m.Value.(type) { case *Request_Echo: b.EncodeVarint(1<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Echo); err != nil { @@ -446,7 +450,7 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { } case nil: default: - return fmt.Errorf("Request.Requests has unexpected type %T", x) + return fmt.Errorf("Request.Value has unexpected type %T", x) } return nil } @@ -454,93 +458,93 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Request) switch tag { - case 1: // requests.echo + case 1: // value.echo if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestEcho) err := b.DecodeMessage(msg) - m.Requests = &Request_Echo{msg} + m.Value = &Request_Echo{msg} return true, err - case 2: // requests.flush + case 2: // value.flush if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestFlush) err := b.DecodeMessage(msg) - m.Requests = &Request_Flush{msg} + m.Value = &Request_Flush{msg} return true, err - case 3: // requests.info + case 3: // value.info if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestInfo) err := b.DecodeMessage(msg) - m.Requests = &Request_Info{msg} + m.Value = &Request_Info{msg} return true, err - case 4: // requests.set_option + case 4: // value.set_option if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestSetOption) err := b.DecodeMessage(msg) - m.Requests = &Request_SetOption{msg} + m.Value = &Request_SetOption{msg} return true, err - case 5: // requests.append_tx + case 5: // value.append_tx if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestAppendTx) err := b.DecodeMessage(msg) - m.Requests = &Request_AppendTx{msg} + m.Value = &Request_AppendTx{msg} return true, err - case 6: // requests.check_tx + case 6: // value.check_tx if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestCheckTx) err := b.DecodeMessage(msg) - m.Requests = &Request_CheckTx{msg} + m.Value = &Request_CheckTx{msg} return true, err - case 7: // requests.commit + case 7: // value.commit if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestCommit) err := b.DecodeMessage(msg) - m.Requests = &Request_Commit{msg} + m.Value = &Request_Commit{msg} return true, err - case 8: // requests.query + case 8: // value.query if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestQuery) err := b.DecodeMessage(msg) - m.Requests = &Request_Query{msg} + m.Value = &Request_Query{msg} return true, err - case 9: // requests.init_chain + case 9: // value.init_chain if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestInitChain) err := b.DecodeMessage(msg) - m.Requests = &Request_InitChain{msg} + m.Value = &Request_InitChain{msg} return true, err - case 10: // requests.begin_block + case 10: // value.begin_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestBeginBlock) err := b.DecodeMessage(msg) - m.Requests = &Request_BeginBlock{msg} + m.Value = &Request_BeginBlock{msg} return true, err - case 11: // requests.end_block + case 11: // value.end_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(RequestEndBlock) err := b.DecodeMessage(msg) - m.Requests = &Request_EndBlock{msg} + m.Value = &Request_EndBlock{msg} return true, err default: return false, nil @@ -549,8 +553,8 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer func _Request_OneofSizer(msg proto.Message) (n int) { m := msg.(*Request) - // requests - switch x := m.Requests.(type) { + // value + switch x := m.Value.(type) { case *Request_Echo: s := proto.Size(x.Echo) n += proto.SizeVarint(1<<3 | proto.WireBytes) @@ -718,7 +722,7 @@ func (*RequestEndBlock) ProtoMessage() {} func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } type Response struct { - // Types that are valid to be assigned to Responses: + // Types that are valid to be assigned to Value: // *Response_Exception // *Response_Echo // *Response_Flush @@ -731,7 +735,7 @@ type Response struct { // *Response_InitChain // *Response_BeginBlock // *Response_EndBlock - Responses isResponse_Responses `protobuf_oneof:"responses"` + Value isResponse_Value `protobuf_oneof:"value"` } func (m *Response) Reset() { *m = Response{} } @@ -739,8 +743,8 @@ func (m *Response) String() string { return proto.CompactTextString(m func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } -type isResponse_Responses interface { - isResponse_Responses() +type isResponse_Value interface { + isResponse_Value() } type Response_Exception struct { @@ -780,105 +784,105 @@ type Response_EndBlock struct { EndBlock *ResponseEndBlock `protobuf:"bytes,12,opt,name=end_block,json=endBlock,oneof"` } -func (*Response_Exception) isResponse_Responses() {} -func (*Response_Echo) isResponse_Responses() {} -func (*Response_Flush) isResponse_Responses() {} -func (*Response_Info) isResponse_Responses() {} -func (*Response_SetOption) isResponse_Responses() {} -func (*Response_AppendTx) isResponse_Responses() {} -func (*Response_CheckTx) isResponse_Responses() {} -func (*Response_Commit) isResponse_Responses() {} -func (*Response_Query) isResponse_Responses() {} -func (*Response_InitChain) isResponse_Responses() {} -func (*Response_BeginBlock) isResponse_Responses() {} -func (*Response_EndBlock) isResponse_Responses() {} +func (*Response_Exception) isResponse_Value() {} +func (*Response_Echo) isResponse_Value() {} +func (*Response_Flush) isResponse_Value() {} +func (*Response_Info) isResponse_Value() {} +func (*Response_SetOption) isResponse_Value() {} +func (*Response_AppendTx) isResponse_Value() {} +func (*Response_CheckTx) isResponse_Value() {} +func (*Response_Commit) isResponse_Value() {} +func (*Response_Query) isResponse_Value() {} +func (*Response_InitChain) isResponse_Value() {} +func (*Response_BeginBlock) isResponse_Value() {} +func (*Response_EndBlock) isResponse_Value() {} -func (m *Response) GetResponses() isResponse_Responses { +func (m *Response) GetValue() isResponse_Value { if m != nil { - return m.Responses + return m.Value } return nil } func (m *Response) GetException() *ResponseException { - if x, ok := m.GetResponses().(*Response_Exception); ok { + if x, ok := m.GetValue().(*Response_Exception); ok { return x.Exception } return nil } func (m *Response) GetEcho() *ResponseEcho { - if x, ok := m.GetResponses().(*Response_Echo); ok { + if x, ok := m.GetValue().(*Response_Echo); ok { return x.Echo } return nil } func (m *Response) GetFlush() *ResponseFlush { - if x, ok := m.GetResponses().(*Response_Flush); ok { + if x, ok := m.GetValue().(*Response_Flush); ok { return x.Flush } return nil } func (m *Response) GetInfo() *ResponseInfo { - if x, ok := m.GetResponses().(*Response_Info); ok { + if x, ok := m.GetValue().(*Response_Info); ok { return x.Info } return nil } func (m *Response) GetSetOption() *ResponseSetOption { - if x, ok := m.GetResponses().(*Response_SetOption); ok { + if x, ok := m.GetValue().(*Response_SetOption); ok { return x.SetOption } return nil } func (m *Response) GetAppendTx() *ResponseAppendTx { - if x, ok := m.GetResponses().(*Response_AppendTx); ok { + if x, ok := m.GetValue().(*Response_AppendTx); ok { return x.AppendTx } return nil } func (m *Response) GetCheckTx() *ResponseCheckTx { - if x, ok := m.GetResponses().(*Response_CheckTx); ok { + if x, ok := m.GetValue().(*Response_CheckTx); ok { return x.CheckTx } return nil } func (m *Response) GetCommit() *ResponseCommit { - if x, ok := m.GetResponses().(*Response_Commit); ok { + if x, ok := m.GetValue().(*Response_Commit); ok { return x.Commit } return nil } func (m *Response) GetQuery() *ResponseQuery { - if x, ok := m.GetResponses().(*Response_Query); ok { + if x, ok := m.GetValue().(*Response_Query); ok { return x.Query } return nil } func (m *Response) GetInitChain() *ResponseInitChain { - if x, ok := m.GetResponses().(*Response_InitChain); ok { + if x, ok := m.GetValue().(*Response_InitChain); ok { return x.InitChain } return nil } func (m *Response) GetBeginBlock() *ResponseBeginBlock { - if x, ok := m.GetResponses().(*Response_BeginBlock); ok { + if x, ok := m.GetValue().(*Response_BeginBlock); ok { return x.BeginBlock } return nil } func (m *Response) GetEndBlock() *ResponseEndBlock { - if x, ok := m.GetResponses().(*Response_EndBlock); ok { + if x, ok := m.GetValue().(*Response_EndBlock); ok { return x.EndBlock } return nil @@ -904,8 +908,8 @@ func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) erro func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { m := msg.(*Response) - // responses - switch x := m.Responses.(type) { + // value + switch x := m.Value.(type) { case *Response_Exception: b.EncodeVarint(1<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Exception); err != nil { @@ -968,7 +972,7 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { } case nil: default: - return fmt.Errorf("Response.Responses has unexpected type %T", x) + return fmt.Errorf("Response.Value has unexpected type %T", x) } return nil } @@ -976,101 +980,101 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Response) switch tag { - case 1: // responses.exception + case 1: // value.exception if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseException) err := b.DecodeMessage(msg) - m.Responses = &Response_Exception{msg} + m.Value = &Response_Exception{msg} return true, err - case 2: // responses.echo + case 2: // value.echo if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseEcho) err := b.DecodeMessage(msg) - m.Responses = &Response_Echo{msg} + m.Value = &Response_Echo{msg} return true, err - case 3: // responses.flush + case 3: // value.flush if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseFlush) err := b.DecodeMessage(msg) - m.Responses = &Response_Flush{msg} + m.Value = &Response_Flush{msg} return true, err - case 4: // responses.info + case 4: // value.info if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseInfo) err := b.DecodeMessage(msg) - m.Responses = &Response_Info{msg} + m.Value = &Response_Info{msg} return true, err - case 5: // responses.set_option + case 5: // value.set_option if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseSetOption) err := b.DecodeMessage(msg) - m.Responses = &Response_SetOption{msg} + m.Value = &Response_SetOption{msg} return true, err - case 6: // responses.append_tx + case 6: // value.append_tx if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseAppendTx) err := b.DecodeMessage(msg) - m.Responses = &Response_AppendTx{msg} + m.Value = &Response_AppendTx{msg} return true, err - case 7: // responses.check_tx + case 7: // value.check_tx if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseCheckTx) err := b.DecodeMessage(msg) - m.Responses = &Response_CheckTx{msg} + m.Value = &Response_CheckTx{msg} return true, err - case 8: // responses.commit + case 8: // value.commit if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseCommit) err := b.DecodeMessage(msg) - m.Responses = &Response_Commit{msg} + m.Value = &Response_Commit{msg} return true, err - case 9: // responses.query + case 9: // value.query if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseQuery) err := b.DecodeMessage(msg) - m.Responses = &Response_Query{msg} + m.Value = &Response_Query{msg} return true, err - case 10: // responses.init_chain + case 10: // value.init_chain if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseInitChain) err := b.DecodeMessage(msg) - m.Responses = &Response_InitChain{msg} + m.Value = &Response_InitChain{msg} return true, err - case 11: // responses.begin_block + case 11: // value.begin_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseBeginBlock) err := b.DecodeMessage(msg) - m.Responses = &Response_BeginBlock{msg} + m.Value = &Response_BeginBlock{msg} return true, err - case 12: // responses.end_block + case 12: // value.end_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } msg := new(ResponseEndBlock) err := b.DecodeMessage(msg) - m.Responses = &Response_EndBlock{msg} + m.Value = &Response_EndBlock{msg} return true, err default: return false, nil @@ -1079,8 +1083,8 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe func _Response_OneofSizer(msg proto.Message) (n int) { m := msg.(*Response) - // responses - switch x := m.Responses.(type) { + // value + switch x := m.Value.(type) { case *Response_Exception: s := proto.Size(x.Exception) n += proto.SizeVarint(1<<3 | proto.WireBytes) @@ -1310,83 +1314,83 @@ func init() { } var fileDescriptor0 = []byte{ - // 1244 bytes of a gzipped FileDescriptorProto + // 1235 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xc9, 0x72, 0xdb, 0x46, - 0x13, 0x36, 0xc4, 0xbd, 0x49, 0x51, 0xc3, 0x11, 0x65, 0xc3, 0x7f, 0xfd, 0x07, 0x07, 0xd9, 0xbc, - 0x95, 0x92, 0x92, 0x2b, 0xae, 0x28, 0xc9, 0xc5, 0x92, 0x69, 0x45, 0xe5, 0xb2, 0xa5, 0xd0, 0xcb, - 0x21, 0x4b, 0xa9, 0x40, 0x70, 0x48, 0x22, 0xa2, 0x66, 0x60, 0x2c, 0xb6, 0x94, 0x77, 0xc8, 0xe3, - 0xe4, 0x92, 0x07, 0x48, 0x55, 0xf6, 0xe5, 0x89, 0x32, 0x3d, 0x33, 0x00, 0x09, 0x08, 0xca, 0x49, - 0xb7, 0x99, 0xee, 0xfe, 0x1a, 0x3d, 0xdd, 0x5f, 0x7f, 0x2c, 0x42, 0x3b, 0x3e, 0x0b, 0x58, 0xb4, - 0x19, 0x84, 0x22, 0x16, 0xb4, 0xa6, 0x2e, 0xce, 0x4f, 0x55, 0x68, 0x0c, 0xd9, 0xab, 0x84, 0x45, - 0x31, 0xbd, 0x09, 0x55, 0xe6, 0xcd, 0x84, 0x6d, 0xdd, 0xb0, 0x6e, 0xb6, 0xb7, 0xe8, 0xa6, 0x0e, - 0x37, 0xde, 0x81, 0xf4, 0x7c, 0x7e, 0x65, 0xa8, 0x22, 0xe8, 0x1d, 0xa8, 0x4d, 0xe6, 0x49, 0x34, - 0xb3, 0x57, 0x54, 0xe8, 0x7a, 0x3e, 0xf4, 0x11, 0xba, 0x64, 0xac, 0x8e, 0xc1, 0xb4, 0x3e, 0x9f, - 0x08, 0xbb, 0x52, 0x96, 0x76, 0x5f, 0x7a, 0x30, 0x2d, 0x46, 0xd0, 0x8f, 0x01, 0x22, 0x16, 0x1f, - 0x89, 0x20, 0xf6, 0x05, 0xb7, 0xab, 0x2a, 0xfe, 0x5a, 0x3e, 0xfe, 0x19, 0x8b, 0x0f, 0x94, 0x5b, - 0x82, 0x5a, 0x51, 0x7a, 0xa1, 0x1f, 0x41, 0xcb, 0x0d, 0x02, 0xc6, 0xc7, 0x47, 0xf1, 0xa9, 0x5d, - 0x53, 0xc0, 0xab, 0x79, 0xe0, 0x03, 0xe5, 0x7e, 0x7e, 0x2a, 0x71, 0x4d, 0xd7, 0x9c, 0xe9, 0x16, - 0x34, 0xbd, 0x19, 0xf3, 0x8e, 0x11, 0x55, 0x57, 0xa8, 0x8d, 0x3c, 0x6a, 0x17, 0xbd, 0x0a, 0xd4, - 0xf0, 0xf4, 0x91, 0x6e, 0x42, 0xdd, 0x13, 0x27, 0x27, 0x7e, 0x6c, 0x37, 0x14, 0xa2, 0x5f, 0x40, - 0x28, 0x9f, 0x04, 0x98, 0x28, 0xec, 0x95, 0x74, 0x84, 0x67, 0x76, 0xb3, 0xac, 0x57, 0x5f, 0xa0, - 0x0b, 0x7b, 0xa5, 0x62, 0xb0, 0x03, 0x3e, 0xf7, 0xe3, 0x23, 0x6f, 0xe6, 0xfa, 0xdc, 0x6e, 0x95, - 0x75, 0x60, 0x5f, 0xfa, 0x77, 0xd1, 0x8d, 0x1d, 0xf0, 0xd3, 0x0b, 0xfd, 0x14, 0xda, 0x23, 0x36, - 0xf5, 0xf9, 0xd1, 0x68, 0x2e, 0xbc, 0x63, 0x1b, 0x14, 0xd4, 0xce, 0x43, 0x77, 0x30, 0x60, 0x07, - 0xfd, 0x12, 0x0b, 0xa3, 0xec, 0x86, 0xed, 0xc3, 0xde, 0x69, 0x68, 0xbb, 0xac, 0x7d, 0x03, 0x3e, - 0x4e, 0x81, 0x4d, 0x66, 0xce, 0x3b, 0x00, 0xcd, 0x50, 0xbb, 0x23, 0xe7, 0x7d, 0x68, 0x2f, 0x31, - 0x85, 0xda, 0xd0, 0x38, 0x61, 0x51, 0xe4, 0x4e, 0x99, 0xa2, 0x53, 0x6b, 0x98, 0x5e, 0x9d, 0x2e, - 0x74, 0x96, 0x79, 0xe2, 0xac, 0x66, 0x40, 0xe4, 0x82, 0xf3, 0x09, 0x90, 0xe2, 0xa8, 0x29, 0x81, - 0xca, 0x31, 0x3b, 0x33, 0x89, 0xf0, 0x48, 0xfb, 0x50, 0x7b, 0xed, 0xce, 0x13, 0xa6, 0x08, 0xd8, - 0x1a, 0xea, 0x8b, 0xf3, 0x16, 0xac, 0x15, 0xa6, 0x4d, 0xbb, 0xb0, 0x22, 0x67, 0x8b, 0xc8, 0xce, - 0x50, 0x9e, 0x9c, 0x1b, 0xd0, 0xcd, 0x8f, 0xf6, 0x5c, 0xc4, 0x3b, 0x59, 0x7d, 0x6a, 0x36, 0xf8, - 0x29, 0x3d, 0x3f, 0x1d, 0xa2, 0x2f, 0xce, 0x1a, 0xac, 0xe6, 0x06, 0xee, 0x3c, 0xcc, 0xea, 0xce, - 0x06, 0x44, 0x3f, 0x04, 0x90, 0x85, 0xf9, 0x63, 0x37, 0x16, 0x61, 0x24, 0xf1, 0x15, 0xd9, 0x57, - 0x62, 0xfa, 0xfa, 0x32, 0x75, 0x0c, 0x97, 0x62, 0x9c, 0x3b, 0xd0, 0x3b, 0x37, 0x2b, 0x7a, 0x15, - 0xea, 0x33, 0xe6, 0x4f, 0x67, 0xb1, 0x2a, 0xa1, 0x3a, 0x34, 0x37, 0xe7, 0x56, 0xf6, 0xdc, 0x74, - 0x3a, 0x17, 0x86, 0x7e, 0x5f, 0x83, 0xe6, 0x90, 0x45, 0x81, 0xe0, 0x11, 0x93, 0x24, 0x6b, 0xb1, - 0x53, 0x8f, 0xe9, 0x2d, 0xb3, 0x0a, 0x44, 0xd1, 0x31, 0x83, 0xd4, 0x8f, 0x24, 0xcb, 0x82, 0xe9, - 0x2d, 0xa3, 0x10, 0xc5, 0xb5, 0x37, 0xa0, 0x65, 0x89, 0xb8, 0x9b, 0x4a, 0x44, 0xa5, 0xb0, 0x25, - 0x3a, 0xb6, 0xa0, 0x11, 0xb7, 0x8c, 0x46, 0x54, 0x4b, 0x13, 0xe7, 0x44, 0x62, 0x3b, 0x27, 0x12, - 0xb5, 0xd2, 0xf2, 0x2f, 0x50, 0x89, 0xfb, 0xcb, 0x2a, 0x51, 0x2f, 0x2c, 0x97, 0x46, 0x96, 0xca, - 0xc4, 0xbd, 0x25, 0x99, 0x68, 0x14, 0xb6, 0x43, 0xc3, 0x4a, 0x74, 0xe2, 0x83, 0x4c, 0x27, 0x9a, - 0x05, 0x65, 0x31, 0x90, 0xa2, 0x50, 0xdc, 0x4d, 0x89, 0xd6, 0x2a, 0xed, 0x58, 0x41, 0x29, 0xb6, - 0x73, 0x4a, 0x01, 0xa5, 0x6d, 0xb8, 0x40, 0x2a, 0x3e, 0xcb, 0x4b, 0x85, 0xde, 0xf7, 0xeb, 0x05, - 0xec, 0x85, 0x5a, 0x71, 0x7f, 0x59, 0x2b, 0x3a, 0xa5, 0x4d, 0x2c, 0x15, 0x8b, 0x36, 0xb4, 0x42, - 0xe3, 0x8f, 0x24, 0x75, 0x7b, 0xe7, 0xa8, 0x86, 0x9b, 0xc6, 0xc2, 0x50, 0x84, 0x66, 0xd1, 0xf5, - 0xc5, 0xb9, 0x89, 0xfb, 0xb8, 0x20, 0xd8, 0x7f, 0x28, 0x8b, 0xda, 0xc9, 0x25, 0x7a, 0x39, 0xce, - 0x02, 0x8a, 0x14, 0xa2, 0xd4, 0xb0, 0x4c, 0xe3, 0xd4, 0xd9, 0x79, 0x77, 0x51, 0x49, 0x4e, 0x70, - 0xe6, 0x62, 0x9a, 0x0a, 0x8e, 0x3c, 0x3a, 0xdf, 0xe0, 0x7a, 0xe7, 0x29, 0x42, 0xdf, 0x86, 0xaa, - 0x27, 0xc6, 0xba, 0x8c, 0xee, 0xd6, 0x9a, 0x69, 0xc2, 0xae, 0x34, 0x3d, 0x97, 0xa7, 0xa1, 0x72, - 0xe2, 0x37, 0xe5, 0x6e, 0xbb, 0x6a, 0x65, 0x3a, 0x43, 0x75, 0x4e, 0xd3, 0x57, 0x16, 0xe9, 0xbf, - 0xc6, 0x55, 0xce, 0x51, 0xe9, 0x32, 0xb3, 0x7f, 0xb9, 0x68, 0x8c, 0xd6, 0xb4, 0x4b, 0xcc, 0xfd, - 0x15, 0x0a, 0xea, 0x32, 0xa3, 0x2f, 0x33, 0xf9, 0xfa, 0x62, 0x38, 0x19, 0x97, 0x9d, 0x3e, 0xd0, - 0xf3, 0x24, 0xd5, 0xbf, 0x1b, 0x79, 0xfa, 0xd1, 0xf7, 0xa0, 0x36, 0xf6, 0x27, 0x93, 0x48, 0xca, - 0x4a, 0xb9, 0xf4, 0x6a, 0xb7, 0xb3, 0x0d, 0xad, 0xcc, 0x86, 0x12, 0x1a, 0x24, 0xa3, 0xc7, 0x2c, - 0x15, 0x7c, 0x73, 0x43, 0x76, 0x06, 0xe2, 0x0d, 0x0b, 0x55, 0xc9, 0xd5, 0xa1, 0xbe, 0xdc, 0xfe, - 0xd1, 0x82, 0xf6, 0x13, 0xcd, 0x3f, 0x7c, 0x1d, 0x5d, 0x83, 0xf6, 0xd3, 0x64, 0x3e, 0x37, 0x26, - 0x72, 0x85, 0x36, 0xa1, 0x8a, 0xb4, 0x25, 0x16, 0x6d, 0x41, 0x4d, 0xd1, 0x92, 0xac, 0xa0, 0x11, - 0x09, 0x49, 0x2a, 0x74, 0x15, 0x5a, 0x19, 0xed, 0x48, 0x15, 0xaf, 0xd9, 0x3e, 0x90, 0x1a, 0xed, - 0x40, 0x33, 0x65, 0x1b, 0xe9, 0xd1, 0x36, 0x34, 0x0c, 0x39, 0x88, 0xec, 0x1f, 0xd4, 0x75, 0xbf, - 0xc9, 0x3a, 0x66, 0x56, 0x73, 0x25, 0x7d, 0x4c, 0x90, 0x75, 0x8a, 0x6c, 0xc8, 0x1f, 0x37, 0x58, - 0xf4, 0x88, 0x5c, 0xc5, 0x84, 0x69, 0x77, 0xc8, 0xb5, 0xdb, 0x3f, 0xc8, 0x5f, 0x85, 0x74, 0x2e, - 0xb4, 0x0e, 0x2b, 0x07, 0x8f, 0x65, 0xc1, 0x3d, 0x58, 0xdd, 0xe7, 0x31, 0x0b, 0xb9, 0x3b, 0x1f, - 0xe0, 0x02, 0xca, 0xca, 0xa5, 0x69, 0xc0, 0xe5, 0xd8, 0x7c, 0x3e, 0xd5, 0xa6, 0x15, 0x4c, 0xb4, - 0xe3, 0x8e, 0x9f, 0x0a, 0xee, 0x31, 0xf9, 0x0a, 0x02, 0x9d, 0x17, 0xdc, 0x4d, 0xe2, 0x99, 0x08, - 0xfd, 0xef, 0xd8, 0x58, 0x3e, 0x64, 0x03, 0x7a, 0xfb, 0x3c, 0x4a, 0x26, 0x13, 0xdf, 0xf3, 0x19, - 0x8f, 0x1f, 0x25, 0x7c, 0x1c, 0xc9, 0x07, 0x51, 0xe8, 0xbe, 0xe0, 0xc7, 0x5c, 0xbc, 0xe1, 0xe6, - 0x97, 0x8b, 0xd4, 0xe5, 0x42, 0xf7, 0x77, 0xdc, 0x88, 0x3d, 0x4c, 0x82, 0xb9, 0xef, 0xb9, 0x31, - 0x7b, 0x30, 0x1e, 0x4b, 0xa1, 0x88, 0x08, 0xc3, 0x24, 0xe8, 0xc9, 0x7f, 0x7b, 0x92, 0x02, 0x72, - 0xf9, 0x19, 0x8b, 0xc8, 0x94, 0x5e, 0x87, 0x8d, 0x73, 0x1e, 0xf5, 0xe5, 0x19, 0xfd, 0x3f, 0xd8, - 0x45, 0xd7, 0x9e, 0x1b, 0x1d, 0x86, 0xbe, 0x7c, 0x80, 0x2f, 0x87, 0x4b, 0xb4, 0x57, 0xfd, 0x16, - 0xef, 0xf3, 0x20, 0x89, 0xc9, 0xb7, 0xe9, 0xf7, 0x8d, 0xf5, 0x20, 0x89, 0xd1, 0x7c, 0x5c, 0x30, - 0x1f, 0x2a, 0x7a, 0x90, 0x39, 0xbd, 0x06, 0xeb, 0x4b, 0xe6, 0x67, 0xf8, 0x3e, 0xec, 0xce, 0xc9, - 0xa2, 0x5e, 0xed, 0xf0, 0xa7, 0xdc, 0x8d, 0x93, 0x90, 0x11, 0x2e, 0xb9, 0x46, 0xd1, 0x63, 0x5a, - 0x92, 0x3e, 0x5c, 0xa4, 0x5f, 0x30, 0x76, 0xf3, 0x85, 0xa0, 0x68, 0x9e, 0x27, 0x72, 0xb2, 0xe4, - 0x95, 0x34, 0x93, 0x3d, 0xf1, 0xda, 0x58, 0x07, 0x3c, 0xf6, 0xe3, 0x33, 0xf2, 0xb3, 0x25, 0xdf, - 0xb4, 0xb6, 0x30, 0xef, 0x85, 0x22, 0x09, 0xc8, 0x2f, 0x96, 0xac, 0x92, 0x2e, 0xac, 0x87, 0xa1, - 0x08, 0x44, 0xe4, 0xce, 0xc9, 0xaf, 0x96, 0xac, 0xa5, 0x27, 0x1d, 0xd9, 0x14, 0x34, 0xe0, 0xb7, - 0x14, 0x90, 0xd9, 0x9f, 0xb0, 0x93, 0x11, 0x0b, 0xc9, 0xef, 0x96, 0x6c, 0x76, 0x7f, 0xd9, 0x91, - 0xe5, 0xfa, 0xc3, 0x32, 0x15, 0x65, 0xae, 0x97, 0x22, 0x66, 0xe4, 0xcf, 0xd4, 0x6c, 0xfa, 0x60, - 0x12, 0xfd, 0x65, 0xd1, 0x75, 0xe8, 0x2e, 0xcc, 0x2a, 0xf6, 0x6f, 0x8b, 0xfe, 0x0f, 0x36, 0x72, - 0x46, 0x39, 0xff, 0x43, 0xdc, 0x38, 0xf2, 0x8f, 0x35, 0xaa, 0xab, 0xbf, 0x30, 0xf7, 0xfe, 0x0d, - 0x00, 0x00, 0xff, 0xff, 0x54, 0x89, 0x64, 0x9a, 0xd1, 0x0c, 0x00, 0x00, + 0x10, 0x35, 0xc4, 0xbd, 0x49, 0x51, 0xa3, 0x11, 0x65, 0xc3, 0xa9, 0x1c, 0x1c, 0x64, 0xb3, 0x6c, + 0x97, 0x92, 0x92, 0x2b, 0xae, 0x28, 0xc9, 0xc5, 0x92, 0x69, 0x45, 0xe5, 0xb2, 0xa5, 0xd0, 0xcb, + 0x21, 0x4b, 0xa9, 0x40, 0x70, 0x48, 0x22, 0xa2, 0x66, 0x60, 0x2c, 0xb6, 0x94, 0x3f, 0xc8, 0x07, + 0xe5, 0x92, 0x6b, 0x4e, 0xd9, 0x97, 0x2f, 0xca, 0xf4, 0xcc, 0x00, 0x24, 0x20, 0xc8, 0x27, 0xdd, + 0x66, 0xba, 0xfb, 0x35, 0x7a, 0xba, 0x5f, 0x3f, 0x16, 0xa1, 0x1d, 0x9f, 0x05, 0x2c, 0xda, 0x0c, + 0x42, 0x11, 0x0b, 0x5a, 0x53, 0x17, 0xe7, 0x97, 0x2a, 0x34, 0x06, 0xec, 0x65, 0xc2, 0xa2, 0x98, + 0xde, 0x84, 0x2a, 0xf3, 0xa6, 0xc2, 0xb6, 0x6e, 0x58, 0x37, 0xdb, 0x5b, 0x74, 0x53, 0x87, 0x1b, + 0x6f, 0x5f, 0x7a, 0xbe, 0xbc, 0x32, 0x50, 0x11, 0xf4, 0x36, 0xd4, 0xc6, 0xb3, 0x24, 0x9a, 0xda, + 0x4b, 0x2a, 0x74, 0x2d, 0x1f, 0xfa, 0x10, 0x5d, 0x32, 0x56, 0xc7, 0x60, 0x5a, 0x9f, 0x8f, 0x85, + 0x5d, 0x29, 0x4b, 0xbb, 0x2f, 0x3d, 0x98, 0x16, 0x23, 0xe8, 0xa7, 0x00, 0x11, 0x8b, 0x8f, 0x44, + 0x10, 0xfb, 0x82, 0xdb, 0x55, 0x15, 0x7f, 0x2d, 0x1f, 0xff, 0x94, 0xc5, 0x07, 0xca, 0x2d, 0x41, + 0xad, 0x28, 0xbd, 0xd0, 0x4f, 0xa0, 0xe5, 0x06, 0x01, 0xe3, 0xa3, 0xa3, 0xf8, 0xd4, 0xae, 0x29, + 0xe0, 0xd5, 0x3c, 0xf0, 0xbe, 0x72, 0x3f, 0x3b, 0x95, 0xb8, 0xa6, 0x6b, 0xce, 0x74, 0x0b, 0x9a, + 0xde, 0x94, 0x79, 0xc7, 0x88, 0xaa, 0x2b, 0xd4, 0x7a, 0x1e, 0xb5, 0x8b, 0x5e, 0x05, 0x6a, 0x78, + 0xfa, 0x48, 0x37, 0xa1, 0xee, 0x89, 0x93, 0x13, 0x3f, 0xb6, 0x1b, 0x0a, 0xd1, 0x2b, 0x20, 0x94, + 0x4f, 0x02, 0x4c, 0x14, 0xf6, 0x4a, 0x3a, 0xc2, 0x33, 0xbb, 0x59, 0xd6, 0xab, 0xaf, 0xd0, 0x85, + 0xbd, 0x52, 0x31, 0xd8, 0x01, 0x9f, 0xfb, 0xf1, 0x91, 0x37, 0x75, 0x7d, 0x6e, 0xb7, 0xca, 0x3a, + 0xb0, 0x2f, 0xfd, 0xbb, 0xe8, 0xc6, 0x0e, 0xf8, 0xe9, 0x85, 0x7e, 0x0e, 0xed, 0x21, 0x9b, 0xf8, + 0xfc, 0x68, 0x38, 0x13, 0xde, 0xb1, 0x0d, 0x0a, 0x6a, 0xe7, 0xa1, 0x3b, 0x18, 0xb0, 0x83, 0x7e, + 0x89, 0x85, 0x61, 0x76, 0xc3, 0xf6, 0x61, 0xef, 0x34, 0xb4, 0x5d, 0xd6, 0xbe, 0x3e, 0x1f, 0xa5, + 0xc0, 0x26, 0x33, 0xe7, 0x9d, 0x06, 0xd4, 0x5e, 0xb9, 0xb3, 0x84, 0x39, 0x1f, 0x42, 0x7b, 0x81, + 0x26, 0xd4, 0x86, 0xc6, 0x09, 0x8b, 0x22, 0x77, 0xc2, 0x14, 0x97, 0x5a, 0x83, 0xf4, 0xea, 0x74, + 0xa1, 0xb3, 0x48, 0x12, 0x67, 0x39, 0x03, 0x22, 0x11, 0x9c, 0xcf, 0x80, 0x14, 0xe7, 0x4c, 0x09, + 0x54, 0x8e, 0xd9, 0x99, 0x49, 0x84, 0x47, 0xda, 0x33, 0x9f, 0x55, 0xec, 0x6b, 0x0d, 0x4c, 0x0d, + 0xef, 0xc0, 0x4a, 0x61, 0xd4, 0xb4, 0x0b, 0x4b, 0x72, 0xb0, 0x88, 0xec, 0x0c, 0xe4, 0xc9, 0xb9, + 0x01, 0xdd, 0xfc, 0x5c, 0xcf, 0x45, 0xbc, 0x97, 0xd5, 0xa7, 0x06, 0x83, 0x9f, 0xd2, 0xc3, 0xd3, + 0x21, 0xfa, 0xe2, 0xac, 0xc0, 0x72, 0x6e, 0xda, 0xce, 0x83, 0xac, 0xee, 0x6c, 0x3a, 0xf4, 0x63, + 0x00, 0x59, 0x98, 0x3f, 0x72, 0x63, 0x11, 0x46, 0x12, 0x5f, 0x91, 0x4d, 0x25, 0xa6, 0xa9, 0x2f, + 0x52, 0xc7, 0x60, 0x21, 0xc6, 0xb9, 0x0d, 0xab, 0xe7, 0x06, 0x45, 0xaf, 0x42, 0x7d, 0xca, 0xfc, + 0xc9, 0x34, 0x56, 0x25, 0x54, 0x07, 0xe6, 0xe6, 0x6c, 0x64, 0xcf, 0x4d, 0x47, 0x73, 0x61, 0xe8, + 0x8f, 0x35, 0x68, 0x0e, 0x58, 0x14, 0x08, 0x1e, 0x31, 0xc9, 0xb0, 0x16, 0x3b, 0xf5, 0x98, 0x5e, + 0x31, 0xab, 0xc0, 0x12, 0x1d, 0xd3, 0x4f, 0xfd, 0xc8, 0xb0, 0x2c, 0x98, 0x6e, 0x18, 0x79, 0x28, + 0xee, 0xbc, 0x01, 0x2d, 0xea, 0xc3, 0x9d, 0x54, 0x1f, 0x2a, 0x85, 0x15, 0xd1, 0xb1, 0x05, 0x81, + 0xd8, 0x30, 0x02, 0x51, 0x2d, 0x4d, 0x9c, 0x53, 0x88, 0xed, 0x9c, 0x42, 0xd4, 0x4a, 0xcb, 0xbf, + 0x40, 0x22, 0xee, 0x2d, 0x4a, 0x44, 0xbd, 0xb0, 0x59, 0x1a, 0x59, 0xaa, 0x11, 0x77, 0x17, 0x34, + 0xa2, 0x51, 0x58, 0x0d, 0x0d, 0x2b, 0x11, 0x89, 0x8f, 0x32, 0x91, 0x68, 0x16, 0x64, 0xc5, 0x40, + 0x8a, 0x2a, 0x71, 0x27, 0x25, 0x5a, 0xab, 0xb4, 0x63, 0x05, 0x99, 0xd8, 0xce, 0xc9, 0x04, 0x94, + 0xb6, 0xe1, 0x02, 0x9d, 0xf8, 0x22, 0xaf, 0x13, 0x7a, 0xd9, 0xaf, 0x17, 0xb0, 0x17, 0x0a, 0xc5, + 0xbd, 0x45, 0xa1, 0xe8, 0x94, 0x36, 0xf1, 0xcd, 0x4a, 0xb1, 0x81, 0x1c, 0x2f, 0xd0, 0x0c, 0xb7, + 0x8c, 0x85, 0xa1, 0x08, 0xcd, 0x92, 0xeb, 0x8b, 0x73, 0x13, 0x77, 0x71, 0x4e, 0xae, 0x37, 0xa8, + 0x8a, 0xda, 0xc7, 0x05, 0x6a, 0x39, 0xce, 0x1c, 0x8a, 0xf4, 0xa1, 0xd4, 0x30, 0x4c, 0xe3, 0xd4, + 0xd9, 0x79, 0x7f, 0x5e, 0x49, 0x4e, 0x6c, 0x66, 0x62, 0x92, 0x8a, 0x8d, 0x3c, 0x3a, 0xdf, 0xe1, + 0x6a, 0xe7, 0xe9, 0x41, 0xdf, 0x85, 0xaa, 0x27, 0x46, 0xba, 0x8c, 0xee, 0xd6, 0x8a, 0x69, 0xc0, + 0xae, 0x34, 0x3d, 0x93, 0xa7, 0x81, 0x72, 0xe2, 0x37, 0xe5, 0x5e, 0xbb, 0x6a, 0x5d, 0x3a, 0x03, + 0x75, 0x4e, 0xd3, 0x57, 0xe6, 0xe9, 0xbf, 0xc5, 0x35, 0xce, 0xd1, 0xe8, 0x32, 0xb3, 0x7f, 0x3d, + 0x6f, 0x8c, 0xd6, 0xb3, 0x4b, 0xcc, 0xfd, 0x0d, 0x8a, 0xe9, 0x22, 0x9b, 0x2f, 0x33, 0xf9, 0xda, + 0x7c, 0x38, 0x19, 0x8f, 0x9d, 0x1e, 0xd0, 0xf3, 0x04, 0xd5, 0xbf, 0x19, 0x79, 0xea, 0xd1, 0x0f, + 0xa0, 0x36, 0xf2, 0xc7, 0xe3, 0x48, 0x4a, 0x4a, 0xb9, 0xec, 0x6a, 0xb7, 0xb3, 0x0d, 0xad, 0xcc, + 0x86, 0xf2, 0x19, 0x24, 0xc3, 0x47, 0x2c, 0x15, 0x7b, 0x73, 0x43, 0x76, 0x06, 0xe2, 0x35, 0x0b, + 0x55, 0xc9, 0xd5, 0x81, 0xbe, 0xdc, 0xfa, 0xd9, 0x82, 0xf6, 0x63, 0xcd, 0x3f, 0x7c, 0x1d, 0x5d, + 0x81, 0xf6, 0x93, 0x64, 0x36, 0x33, 0x26, 0x72, 0x85, 0x36, 0xa1, 0x8a, 0xb4, 0x25, 0x16, 0x6d, + 0x41, 0x4d, 0xd1, 0x92, 0x2c, 0xa1, 0x11, 0x09, 0x49, 0x2a, 0x74, 0x19, 0x5a, 0x19, 0xed, 0x48, + 0x15, 0xaf, 0xd9, 0x3e, 0x90, 0x1a, 0xed, 0x40, 0x33, 0x65, 0x1b, 0x59, 0xa5, 0x6d, 0x68, 0x18, + 0x72, 0x10, 0xd9, 0x3f, 0xa8, 0xeb, 0x7e, 0x93, 0x35, 0xcc, 0xac, 0xe6, 0x4a, 0x7a, 0x98, 0x20, + 0xeb, 0x14, 0x59, 0x97, 0x3f, 0x6c, 0x30, 0xef, 0x11, 0xb9, 0x8a, 0x09, 0xd3, 0xee, 0x90, 0x6b, + 0xb7, 0x7e, 0x92, 0xbf, 0x08, 0xe9, 0x5c, 0x68, 0x1d, 0x96, 0x0e, 0x1e, 0xc9, 0x82, 0x57, 0x61, + 0x79, 0x9f, 0xc7, 0x2c, 0xe4, 0xee, 0xac, 0x8f, 0x0b, 0x28, 0x2b, 0x97, 0xa6, 0x3e, 0x97, 0x63, + 0xf3, 0xf9, 0x44, 0x9b, 0x96, 0x30, 0xd1, 0x8e, 0x3b, 0x7a, 0x22, 0xb8, 0xc7, 0xe4, 0x2b, 0x08, + 0x74, 0x9e, 0x73, 0x37, 0x89, 0xa7, 0x22, 0xf4, 0x7f, 0x60, 0x23, 0xf9, 0x90, 0x75, 0x58, 0xdd, + 0xe7, 0x51, 0x32, 0x1e, 0xfb, 0x9e, 0xcf, 0x78, 0xfc, 0x30, 0xe1, 0xa3, 0x48, 0x3e, 0x88, 0x42, + 0xf7, 0x39, 0x3f, 0xe6, 0xe2, 0x35, 0x37, 0xbf, 0x5a, 0xa4, 0x2e, 0x17, 0xba, 0xb7, 0xe3, 0x46, + 0xec, 0x41, 0x12, 0xcc, 0x7c, 0xcf, 0x8d, 0xd9, 0xfd, 0xd1, 0x28, 0x94, 0xed, 0x23, 0x0c, 0x93, + 0xa0, 0x27, 0xff, 0xed, 0x71, 0x0a, 0xc8, 0xe5, 0x67, 0x2c, 0x22, 0x13, 0x7a, 0x1d, 0xd6, 0xcf, + 0x79, 0xd4, 0x97, 0xa7, 0xf4, 0x6d, 0xb0, 0x8b, 0xae, 0x3d, 0x37, 0x3a, 0x0c, 0x7d, 0xf9, 0x00, + 0x5f, 0x0e, 0x97, 0x68, 0xaf, 0xfa, 0x1d, 0xde, 0xe7, 0x41, 0x12, 0x93, 0xef, 0xd3, 0xef, 0x1b, + 0xeb, 0x41, 0x12, 0xa3, 0xf9, 0xb8, 0x60, 0x3e, 0x54, 0xf4, 0x20, 0x33, 0x7a, 0x0d, 0xd6, 0x16, + 0xcc, 0x4f, 0xf1, 0x7d, 0xd8, 0x9d, 0x93, 0x79, 0xbd, 0xda, 0xe1, 0x4f, 0xb8, 0x1b, 0x27, 0x21, + 0x23, 0x5c, 0x72, 0x8d, 0xa2, 0xc7, 0xb4, 0x24, 0x7d, 0xb8, 0x48, 0xbf, 0x60, 0xec, 0xe6, 0x0b, + 0x41, 0xd1, 0x3c, 0x4b, 0xe4, 0x64, 0xc9, 0x4b, 0x69, 0x26, 0x7b, 0xe2, 0x95, 0xb1, 0xf6, 0x79, + 0xec, 0xc7, 0x67, 0xe4, 0x57, 0x4b, 0xbe, 0x69, 0x65, 0x6e, 0xde, 0x0b, 0x45, 0x12, 0x90, 0xdf, + 0x2c, 0x59, 0x25, 0x9d, 0x5b, 0x0f, 0x43, 0x11, 0x88, 0xc8, 0x9d, 0x91, 0xdf, 0x2d, 0x59, 0xcb, + 0xaa, 0x74, 0x64, 0x53, 0xd0, 0x80, 0x3f, 0x52, 0x40, 0x66, 0x7f, 0xcc, 0x4e, 0x86, 0x2c, 0x24, + 0x7f, 0x5a, 0xb2, 0xd9, 0xbd, 0x45, 0x47, 0x96, 0xeb, 0x2f, 0xcb, 0x54, 0x94, 0xb9, 0x5e, 0x88, + 0x98, 0x91, 0xbf, 0x53, 0xb3, 0xe9, 0x83, 0x49, 0xf4, 0x8f, 0x45, 0xd7, 0xa0, 0x3b, 0x37, 0xab, + 0xd8, 0x7f, 0x2d, 0xfa, 0x16, 0xac, 0xe7, 0x8c, 0x72, 0xfe, 0x87, 0xb8, 0x71, 0xe4, 0x3f, 0x6b, + 0x58, 0x57, 0xff, 0x5d, 0xee, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x7d, 0xee, 0xf0, 0xca, + 0x0c, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 4df19b82..e132ef65 100644 --- a/types/types.proto +++ b/types/types.proto @@ -6,6 +6,10 @@ package types; //---------------------------------------- // Message types +// 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; @@ -70,7 +74,7 @@ enum CodeType { // Request types message Request { - oneof requests{ + oneof value{ RequestEcho echo = 1; RequestFlush flush = 2; RequestInfo info = 3; @@ -132,7 +136,7 @@ message RequestEndBlock{ message Response { - oneof responses{ + oneof value{ ResponseException exception = 1; ResponseEcho echo = 2; ResponseFlush flush = 3; From c3cc5375be4638adb39c013dd60ccb194bb4e00f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 17 May 2016 22:45:45 -0400 Subject: [PATCH 110/545] ignore mustConnect for now. fix test_counter --- client/remote_client.go | 1 + tests/test_counter.go | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/remote_client.go b/client/remote_client.go index d8370eee..aa8a4aea 100644 --- a/client/remote_client.go +++ b/client/remote_client.go @@ -54,6 +54,7 @@ func NewClient(addr string, mustConnect bool) (*remoteClient, error) { } cli.QuitService = *NewQuitService(nil, "remoteClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. + return cli, err if mustConnect { return nil, err } else { diff --git a/tests/test_counter.go b/tests/test_counter.go index 44adc320..2d60543e 100644 --- a/tests/test_counter.go +++ b/tests/test_counter.go @@ -100,9 +100,6 @@ func commit(client tmspcli.Client, hashExp []byte) { func appendTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.AppendTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log - if res.IsErr() { - panic(Fmt("appending tx %X: %v\nlog: %v", txBytes, log)) - } if code != codeExp { panic(Fmt("AppendTx response code was unexpected. Got %v expected %v. Log: %v", code, codeExp, log)) From f84f11ffe75bafc1bb411d87166a557d23cf8e27 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 18 May 2016 00:54:32 -0400 Subject: [PATCH 111/545] base grpc support --- cmd/counter/main.go | 18 +- example/nil/nil_test.go | 55 ++++ server/grpc_server.go | 55 ++++ server/server.go | 2 +- types/application.go | 71 +++++ types/types.pb.go | 575 ++++++++++++++++++++++++++++++++++------ types/types.proto | 19 ++ 7 files changed, 711 insertions(+), 84 deletions(-) create mode 100644 server/grpc_server.go diff --git a/cmd/counter/main.go b/cmd/counter/main.go index fc003fb8..07bf4403 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -6,19 +6,31 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/example/counter" "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" ) func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") + grpcPtr := flag.String("tmsp", "socket", "TMSP server: socket | grpc") serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") flag.Parse() app := counter.NewCounterApplication(*serialPtr) // Start the listener - _, err := server.NewServer(*addrPtr, app) - if err != nil { - Exit(err.Error()) + switch *grpcPtr { + case "socket": + _, err := server.NewServer(*addrPtr, app) + if err != nil { + Exit(err.Error()) + } + case "grpc": + _, err := server.NewGRPCServer(*addrPtr, types.NewGRPCApplication(app)) + if err != nil { + Exit(err.Error()) + } + default: + Exit(Fmt("Unknown server type %s", *grpcPtr)) } // Wait forever diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go index 0ef143c7..ba038b87 100644 --- a/example/nil/nil_test.go +++ b/example/nil/nil_test.go @@ -1,10 +1,14 @@ package nilapp import ( + "net" "reflect" "testing" "time" + "golang.org/x/net/context" + "google.golang.org/grpc" + . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/server" "github.com/tendermint/tmsp/types" @@ -91,3 +95,54 @@ func TestStream(t *testing.T) { <-done } + +//------------------------- +// test grpc + +func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { + return Connect(addr) +} + +func TestGRPCSync(t *testing.T) { + + numAppendTxs := 2000 + + // Start the listener + server, err := server.NewGRPCServer("unix://test.sock", types.NewGRPCApplication(NewNilApplication())) + if err != nil { + Exit(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(err.Error()) + } + defer conn.Close() + + client := types.NewTMSPApplicationClient(conn) + + // Write requests + for counter := 0; counter < numAppendTxs; counter++ { + // Send request + response, err := client.AppendTx(context.Background(), &types.RequestAppendTx{[]byte("test")}) + if err != nil { + t.Fatal(err.Error()) + } + counter += 1 + if response.Code != types.CodeType_OK { + t.Error("AppendTx failed with ret_code", response.Code) + } + if counter > numAppendTxs { + t.Fatal("Too many AppendTx responses") + } + t.Log("response", counter) + if counter == numAppendTxs { + go func() { + time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow + }() + } + + } +} diff --git a/server/grpc_server.go b/server/grpc_server.go new file mode 100644 index 00000000..3a21e3fb --- /dev/null +++ b/server/grpc_server.go @@ -0,0 +1,55 @@ +package server + +import ( + "net" + "strings" + + "google.golang.org/grpc" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/types" +) + +// var maxNumberConnections = 2 + +type GRPCServer struct { + QuitService + + proto string + addr string + listener net.Listener + + app types.TMSPApplicationServer +} + +func NewGRPCServer(protoAddr string, app types.TMSPApplicationServer) (Service, error) { + parts := strings.SplitN(protoAddr, "://", 2) + proto, addr := parts[0], parts[1] + s := &GRPCServer{ + proto: proto, + addr: addr, + listener: nil, + app: app, + } + s.QuitService = *NewQuitService(nil, "TMSPServer", s) + _, err := s.Start() // Just start it + return s, err +} + +func (s *GRPCServer) OnStart() error { + s.QuitService.OnStart() + ln, err := net.Listen(s.proto, s.addr) + if err != nil { + return err + } + s.listener = ln + grpcServer := grpc.NewServer() + types.RegisterTMSPApplicationServer(grpcServer, s.app) + go grpcServer.Serve(ln) + return nil +} + +func (s *GRPCServer) OnStop() { + s.QuitService.OnStop() + s.listener.Close() +} diff --git a/server/server.go b/server/server.go index f5d6e556..ed832595 100644 --- a/server/server.go +++ b/server/server.go @@ -25,7 +25,7 @@ type Server struct { app types.Application } -func NewServer(protoAddr string, app types.Application) (*Server, error) { +func NewServer(protoAddr string, app types.Application) (Service, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &Server{ diff --git a/types/application.go b/types/application.go index 65ca9ab0..c6e6f24b 100644 --- a/types/application.go +++ b/types/application.go @@ -1,5 +1,9 @@ package types +import ( + context "golang.org/x/net/context" +) + // Applications type Application interface { @@ -36,3 +40,70 @@ type BlockchainAware interface { // diffs: changed validators from app to TendermintCore EndBlock(height uint64) (diffs []*Validator) } + +//------------------------------------ +type GRPCApplication struct { + app Application +} + +func NewGRPCApplication(app Application) *GRPCApplication { + return &GRPCApplication{app} +} + +func (app *GRPCApplication) Echo(ctx context.Context, req *RequestEcho) (*ResponseEcho, error) { + return &ResponseEcho{req.Message}, nil +} + +func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*ResponseFlush, error) { + return &ResponseFlush{}, nil +} + +func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { + return &ResponseInfo{app.app.Info()}, nil +} + +func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { + return &ResponseSetOption{app.app.SetOption(req.Key, req.Value)}, nil +} + +func (app *GRPCApplication) AppendTx(ctx context.Context, req *RequestAppendTx) (*ResponseAppendTx, error) { + r := app.app.AppendTx(req.Tx) + return &ResponseAppendTx{r.Code, r.Data, r.Log}, nil +} + +func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { + r := app.app.CheckTx(req.Tx) + return &ResponseCheckTx{r.Code, r.Data, r.Log}, nil +} + +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 +} + +func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { + r := app.app.Commit() + return &ResponseCommit{r.Code, r.Data, r.Log}, nil +} + +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 +} + +func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { + if chainAware, ok := app.app.(BlockchainAware); ok { + chainAware.BeginBlock(req.Height) + } + return &ResponseBeginBlock{}, nil +} + +func (app *GRPCApplication) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { + if chainAware, ok := app.app.(BlockchainAware); ok { + diffs := chainAware.EndBlock(req.Height) + return &ResponseEndBlock{diffs}, nil + } + return &ResponseEndBlock{}, nil +} diff --git a/types/types.pb.go b/types/types.pb.go index 3d803236..181a0608 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -42,6 +42,11 @@ import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf @@ -1313,84 +1318,494 @@ func init() { proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) } -var fileDescriptor0 = []byte{ - // 1235 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xc9, 0x72, 0xdb, 0x46, - 0x10, 0x35, 0xc4, 0xbd, 0x49, 0x51, 0xa3, 0x11, 0x65, 0xc3, 0xa9, 0x1c, 0x1c, 0x64, 0xb3, 0x6c, - 0x97, 0x92, 0x92, 0x2b, 0xae, 0x28, 0xc9, 0xc5, 0x92, 0x69, 0x45, 0xe5, 0xb2, 0xa5, 0xd0, 0xcb, - 0x21, 0x4b, 0xa9, 0x40, 0x70, 0x48, 0x22, 0xa2, 0x66, 0x60, 0x2c, 0xb6, 0x94, 0x3f, 0xc8, 0x07, - 0xe5, 0x92, 0x6b, 0x4e, 0xd9, 0x97, 0x2f, 0xca, 0xf4, 0xcc, 0x00, 0x24, 0x20, 0xc8, 0x27, 0xdd, - 0x66, 0xba, 0xfb, 0x35, 0x7a, 0xba, 0x5f, 0x3f, 0x16, 0xa1, 0x1d, 0x9f, 0x05, 0x2c, 0xda, 0x0c, - 0x42, 0x11, 0x0b, 0x5a, 0x53, 0x17, 0xe7, 0x97, 0x2a, 0x34, 0x06, 0xec, 0x65, 0xc2, 0xa2, 0x98, - 0xde, 0x84, 0x2a, 0xf3, 0xa6, 0xc2, 0xb6, 0x6e, 0x58, 0x37, 0xdb, 0x5b, 0x74, 0x53, 0x87, 0x1b, - 0x6f, 0x5f, 0x7a, 0xbe, 0xbc, 0x32, 0x50, 0x11, 0xf4, 0x36, 0xd4, 0xc6, 0xb3, 0x24, 0x9a, 0xda, - 0x4b, 0x2a, 0x74, 0x2d, 0x1f, 0xfa, 0x10, 0x5d, 0x32, 0x56, 0xc7, 0x60, 0x5a, 0x9f, 0x8f, 0x85, - 0x5d, 0x29, 0x4b, 0xbb, 0x2f, 0x3d, 0x98, 0x16, 0x23, 0xe8, 0xa7, 0x00, 0x11, 0x8b, 0x8f, 0x44, - 0x10, 0xfb, 0x82, 0xdb, 0x55, 0x15, 0x7f, 0x2d, 0x1f, 0xff, 0x94, 0xc5, 0x07, 0xca, 0x2d, 0x41, - 0xad, 0x28, 0xbd, 0xd0, 0x4f, 0xa0, 0xe5, 0x06, 0x01, 0xe3, 0xa3, 0xa3, 0xf8, 0xd4, 0xae, 0x29, - 0xe0, 0xd5, 0x3c, 0xf0, 0xbe, 0x72, 0x3f, 0x3b, 0x95, 0xb8, 0xa6, 0x6b, 0xce, 0x74, 0x0b, 0x9a, - 0xde, 0x94, 0x79, 0xc7, 0x88, 0xaa, 0x2b, 0xd4, 0x7a, 0x1e, 0xb5, 0x8b, 0x5e, 0x05, 0x6a, 0x78, - 0xfa, 0x48, 0x37, 0xa1, 0xee, 0x89, 0x93, 0x13, 0x3f, 0xb6, 0x1b, 0x0a, 0xd1, 0x2b, 0x20, 0x94, - 0x4f, 0x02, 0x4c, 0x14, 0xf6, 0x4a, 0x3a, 0xc2, 0x33, 0xbb, 0x59, 0xd6, 0xab, 0xaf, 0xd0, 0x85, - 0xbd, 0x52, 0x31, 0xd8, 0x01, 0x9f, 0xfb, 0xf1, 0x91, 0x37, 0x75, 0x7d, 0x6e, 0xb7, 0xca, 0x3a, - 0xb0, 0x2f, 0xfd, 0xbb, 0xe8, 0xc6, 0x0e, 0xf8, 0xe9, 0x85, 0x7e, 0x0e, 0xed, 0x21, 0x9b, 0xf8, - 0xfc, 0x68, 0x38, 0x13, 0xde, 0xb1, 0x0d, 0x0a, 0x6a, 0xe7, 0xa1, 0x3b, 0x18, 0xb0, 0x83, 0x7e, - 0x89, 0x85, 0x61, 0x76, 0xc3, 0xf6, 0x61, 0xef, 0x34, 0xb4, 0x5d, 0xd6, 0xbe, 0x3e, 0x1f, 0xa5, - 0xc0, 0x26, 0x33, 0xe7, 0x9d, 0x06, 0xd4, 0x5e, 0xb9, 0xb3, 0x84, 0x39, 0x1f, 0x42, 0x7b, 0x81, - 0x26, 0xd4, 0x86, 0xc6, 0x09, 0x8b, 0x22, 0x77, 0xc2, 0x14, 0x97, 0x5a, 0x83, 0xf4, 0xea, 0x74, - 0xa1, 0xb3, 0x48, 0x12, 0x67, 0x39, 0x03, 0x22, 0x11, 0x9c, 0xcf, 0x80, 0x14, 0xe7, 0x4c, 0x09, - 0x54, 0x8e, 0xd9, 0x99, 0x49, 0x84, 0x47, 0xda, 0x33, 0x9f, 0x55, 0xec, 0x6b, 0x0d, 0x4c, 0x0d, - 0xef, 0xc0, 0x4a, 0x61, 0xd4, 0xb4, 0x0b, 0x4b, 0x72, 0xb0, 0x88, 0xec, 0x0c, 0xe4, 0xc9, 0xb9, - 0x01, 0xdd, 0xfc, 0x5c, 0xcf, 0x45, 0xbc, 0x97, 0xd5, 0xa7, 0x06, 0x83, 0x9f, 0xd2, 0xc3, 0xd3, - 0x21, 0xfa, 0xe2, 0xac, 0xc0, 0x72, 0x6e, 0xda, 0xce, 0x83, 0xac, 0xee, 0x6c, 0x3a, 0xf4, 0x63, - 0x00, 0x59, 0x98, 0x3f, 0x72, 0x63, 0x11, 0x46, 0x12, 0x5f, 0x91, 0x4d, 0x25, 0xa6, 0xa9, 0x2f, - 0x52, 0xc7, 0x60, 0x21, 0xc6, 0xb9, 0x0d, 0xab, 0xe7, 0x06, 0x45, 0xaf, 0x42, 0x7d, 0xca, 0xfc, - 0xc9, 0x34, 0x56, 0x25, 0x54, 0x07, 0xe6, 0xe6, 0x6c, 0x64, 0xcf, 0x4d, 0x47, 0x73, 0x61, 0xe8, - 0x8f, 0x35, 0x68, 0x0e, 0x58, 0x14, 0x08, 0x1e, 0x31, 0xc9, 0xb0, 0x16, 0x3b, 0xf5, 0x98, 0x5e, - 0x31, 0xab, 0xc0, 0x12, 0x1d, 0xd3, 0x4f, 0xfd, 0xc8, 0xb0, 0x2c, 0x98, 0x6e, 0x18, 0x79, 0x28, - 0xee, 0xbc, 0x01, 0x2d, 0xea, 0xc3, 0x9d, 0x54, 0x1f, 0x2a, 0x85, 0x15, 0xd1, 0xb1, 0x05, 0x81, - 0xd8, 0x30, 0x02, 0x51, 0x2d, 0x4d, 0x9c, 0x53, 0x88, 0xed, 0x9c, 0x42, 0xd4, 0x4a, 0xcb, 0xbf, - 0x40, 0x22, 0xee, 0x2d, 0x4a, 0x44, 0xbd, 0xb0, 0x59, 0x1a, 0x59, 0xaa, 0x11, 0x77, 0x17, 0x34, - 0xa2, 0x51, 0x58, 0x0d, 0x0d, 0x2b, 0x11, 0x89, 0x8f, 0x32, 0x91, 0x68, 0x16, 0x64, 0xc5, 0x40, - 0x8a, 0x2a, 0x71, 0x27, 0x25, 0x5a, 0xab, 0xb4, 0x63, 0x05, 0x99, 0xd8, 0xce, 0xc9, 0x04, 0x94, - 0xb6, 0xe1, 0x02, 0x9d, 0xf8, 0x22, 0xaf, 0x13, 0x7a, 0xd9, 0xaf, 0x17, 0xb0, 0x17, 0x0a, 0xc5, - 0xbd, 0x45, 0xa1, 0xe8, 0x94, 0x36, 0xf1, 0xcd, 0x4a, 0xb1, 0x81, 0x1c, 0x2f, 0xd0, 0x0c, 0xb7, - 0x8c, 0x85, 0xa1, 0x08, 0xcd, 0x92, 0xeb, 0x8b, 0x73, 0x13, 0x77, 0x71, 0x4e, 0xae, 0x37, 0xa8, - 0x8a, 0xda, 0xc7, 0x05, 0x6a, 0x39, 0xce, 0x1c, 0x8a, 0xf4, 0xa1, 0xd4, 0x30, 0x4c, 0xe3, 0xd4, - 0xd9, 0x79, 0x7f, 0x5e, 0x49, 0x4e, 0x6c, 0x66, 0x62, 0x92, 0x8a, 0x8d, 0x3c, 0x3a, 0xdf, 0xe1, - 0x6a, 0xe7, 0xe9, 0x41, 0xdf, 0x85, 0xaa, 0x27, 0x46, 0xba, 0x8c, 0xee, 0xd6, 0x8a, 0x69, 0xc0, - 0xae, 0x34, 0x3d, 0x93, 0xa7, 0x81, 0x72, 0xe2, 0x37, 0xe5, 0x5e, 0xbb, 0x6a, 0x5d, 0x3a, 0x03, - 0x75, 0x4e, 0xd3, 0x57, 0xe6, 0xe9, 0xbf, 0xc5, 0x35, 0xce, 0xd1, 0xe8, 0x32, 0xb3, 0x7f, 0x3d, - 0x6f, 0x8c, 0xd6, 0xb3, 0x4b, 0xcc, 0xfd, 0x0d, 0x8a, 0xe9, 0x22, 0x9b, 0x2f, 0x33, 0xf9, 0xda, - 0x7c, 0x38, 0x19, 0x8f, 0x9d, 0x1e, 0xd0, 0xf3, 0x04, 0xd5, 0xbf, 0x19, 0x79, 0xea, 0xd1, 0x0f, - 0xa0, 0x36, 0xf2, 0xc7, 0xe3, 0x48, 0x4a, 0x4a, 0xb9, 0xec, 0x6a, 0xb7, 0xb3, 0x0d, 0xad, 0xcc, - 0x86, 0xf2, 0x19, 0x24, 0xc3, 0x47, 0x2c, 0x15, 0x7b, 0x73, 0x43, 0x76, 0x06, 0xe2, 0x35, 0x0b, - 0x55, 0xc9, 0xd5, 0x81, 0xbe, 0xdc, 0xfa, 0xd9, 0x82, 0xf6, 0x63, 0xcd, 0x3f, 0x7c, 0x1d, 0x5d, - 0x81, 0xf6, 0x93, 0x64, 0x36, 0x33, 0x26, 0x72, 0x85, 0x36, 0xa1, 0x8a, 0xb4, 0x25, 0x16, 0x6d, - 0x41, 0x4d, 0xd1, 0x92, 0x2c, 0xa1, 0x11, 0x09, 0x49, 0x2a, 0x74, 0x19, 0x5a, 0x19, 0xed, 0x48, - 0x15, 0xaf, 0xd9, 0x3e, 0x90, 0x1a, 0xed, 0x40, 0x33, 0x65, 0x1b, 0x59, 0xa5, 0x6d, 0x68, 0x18, - 0x72, 0x10, 0xd9, 0x3f, 0xa8, 0xeb, 0x7e, 0x93, 0x35, 0xcc, 0xac, 0xe6, 0x4a, 0x7a, 0x98, 0x20, - 0xeb, 0x14, 0x59, 0x97, 0x3f, 0x6c, 0x30, 0xef, 0x11, 0xb9, 0x8a, 0x09, 0xd3, 0xee, 0x90, 0x6b, - 0xb7, 0x7e, 0x92, 0xbf, 0x08, 0xe9, 0x5c, 0x68, 0x1d, 0x96, 0x0e, 0x1e, 0xc9, 0x82, 0x57, 0x61, - 0x79, 0x9f, 0xc7, 0x2c, 0xe4, 0xee, 0xac, 0x8f, 0x0b, 0x28, 0x2b, 0x97, 0xa6, 0x3e, 0x97, 0x63, - 0xf3, 0xf9, 0x44, 0x9b, 0x96, 0x30, 0xd1, 0x8e, 0x3b, 0x7a, 0x22, 0xb8, 0xc7, 0xe4, 0x2b, 0x08, - 0x74, 0x9e, 0x73, 0x37, 0x89, 0xa7, 0x22, 0xf4, 0x7f, 0x60, 0x23, 0xf9, 0x90, 0x75, 0x58, 0xdd, - 0xe7, 0x51, 0x32, 0x1e, 0xfb, 0x9e, 0xcf, 0x78, 0xfc, 0x30, 0xe1, 0xa3, 0x48, 0x3e, 0x88, 0x42, - 0xf7, 0x39, 0x3f, 0xe6, 0xe2, 0x35, 0x37, 0xbf, 0x5a, 0xa4, 0x2e, 0x17, 0xba, 0xb7, 0xe3, 0x46, - 0xec, 0x41, 0x12, 0xcc, 0x7c, 0xcf, 0x8d, 0xd9, 0xfd, 0xd1, 0x28, 0x94, 0xed, 0x23, 0x0c, 0x93, - 0xa0, 0x27, 0xff, 0xed, 0x71, 0x0a, 0xc8, 0xe5, 0x67, 0x2c, 0x22, 0x13, 0x7a, 0x1d, 0xd6, 0xcf, - 0x79, 0xd4, 0x97, 0xa7, 0xf4, 0x6d, 0xb0, 0x8b, 0xae, 0x3d, 0x37, 0x3a, 0x0c, 0x7d, 0xf9, 0x00, - 0x5f, 0x0e, 0x97, 0x68, 0xaf, 0xfa, 0x1d, 0xde, 0xe7, 0x41, 0x12, 0x93, 0xef, 0xd3, 0xef, 0x1b, - 0xeb, 0x41, 0x12, 0xa3, 0xf9, 0xb8, 0x60, 0x3e, 0x54, 0xf4, 0x20, 0x33, 0x7a, 0x0d, 0xd6, 0x16, - 0xcc, 0x4f, 0xf1, 0x7d, 0xd8, 0x9d, 0x93, 0x79, 0xbd, 0xda, 0xe1, 0x4f, 0xb8, 0x1b, 0x27, 0x21, - 0x23, 0x5c, 0x72, 0x8d, 0xa2, 0xc7, 0xb4, 0x24, 0x7d, 0xb8, 0x48, 0xbf, 0x60, 0xec, 0xe6, 0x0b, - 0x41, 0xd1, 0x3c, 0x4b, 0xe4, 0x64, 0xc9, 0x4b, 0x69, 0x26, 0x7b, 0xe2, 0x95, 0xb1, 0xf6, 0x79, - 0xec, 0xc7, 0x67, 0xe4, 0x57, 0x4b, 0xbe, 0x69, 0x65, 0x6e, 0xde, 0x0b, 0x45, 0x12, 0x90, 0xdf, - 0x2c, 0x59, 0x25, 0x9d, 0x5b, 0x0f, 0x43, 0x11, 0x88, 0xc8, 0x9d, 0x91, 0xdf, 0x2d, 0x59, 0xcb, - 0xaa, 0x74, 0x64, 0x53, 0xd0, 0x80, 0x3f, 0x52, 0x40, 0x66, 0x7f, 0xcc, 0x4e, 0x86, 0x2c, 0x24, - 0x7f, 0x5a, 0xb2, 0xd9, 0xbd, 0x45, 0x47, 0x96, 0xeb, 0x2f, 0xcb, 0x54, 0x94, 0xb9, 0x5e, 0x88, - 0x98, 0x91, 0xbf, 0x53, 0xb3, 0xe9, 0x83, 0x49, 0xf4, 0x8f, 0x45, 0xd7, 0xa0, 0x3b, 0x37, 0xab, - 0xd8, 0x7f, 0x2d, 0xfa, 0x16, 0xac, 0xe7, 0x8c, 0x72, 0xfe, 0x87, 0xb8, 0x71, 0xe4, 0x3f, 0x6b, - 0x58, 0x57, 0xff, 0x5d, 0xee, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xc3, 0x7d, 0xee, 0xf0, 0xca, - 0x0c, 0x00, 0x00, +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion2 + +// Client API for TMSPApplication service + +type TMSPApplicationClient interface { + Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) + Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) + Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) + SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) + AppendTx(ctx context.Context, in *RequestAppendTx, opts ...grpc.CallOption) (*ResponseAppendTx, error) + CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) + Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) + Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) + InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) + BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) + EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) +} + +type tMSPApplicationClient struct { + cc *grpc.ClientConn +} + +func NewTMSPApplicationClient(cc *grpc.ClientConn) TMSPApplicationClient { + return &tMSPApplicationClient{cc} +} + +func (c *tMSPApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { + out := new(ResponseEcho) + err := grpc.Invoke(ctx, "/types.TMSPApplication/Echo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { + out := new(ResponseFlush) + err := grpc.Invoke(ctx, "/types.TMSPApplication/Flush", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { + out := new(ResponseInfo) + err := grpc.Invoke(ctx, "/types.TMSPApplication/Info", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { + out := new(ResponseSetOption) + err := grpc.Invoke(ctx, "/types.TMSPApplication/SetOption", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) AppendTx(ctx context.Context, in *RequestAppendTx, opts ...grpc.CallOption) (*ResponseAppendTx, error) { + out := new(ResponseAppendTx) + err := grpc.Invoke(ctx, "/types.TMSPApplication/AppendTx", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { + out := new(ResponseCheckTx) + err := grpc.Invoke(ctx, "/types.TMSPApplication/CheckTx", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { + out := new(ResponseQuery) + err := grpc.Invoke(ctx, "/types.TMSPApplication/Query", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { + out := new(ResponseCommit) + err := grpc.Invoke(ctx, "/types.TMSPApplication/Commit", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { + out := new(ResponseInitChain) + err := grpc.Invoke(ctx, "/types.TMSPApplication/InitChain", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { + out := new(ResponseBeginBlock) + err := grpc.Invoke(ctx, "/types.TMSPApplication/BeginBlock", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tMSPApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { + out := new(ResponseEndBlock) + err := grpc.Invoke(ctx, "/types.TMSPApplication/EndBlock", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for TMSPApplication service + +type TMSPApplicationServer interface { + Echo(context.Context, *RequestEcho) (*ResponseEcho, error) + Flush(context.Context, *RequestFlush) (*ResponseFlush, error) + Info(context.Context, *RequestInfo) (*ResponseInfo, error) + SetOption(context.Context, *RequestSetOption) (*ResponseSetOption, error) + AppendTx(context.Context, *RequestAppendTx) (*ResponseAppendTx, error) + CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) + Query(context.Context, *RequestQuery) (*ResponseQuery, error) + Commit(context.Context, *RequestCommit) (*ResponseCommit, error) + InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) + BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) + EndBlock(context.Context, *RequestEndBlock) (*ResponseEndBlock, error) +} + +func RegisterTMSPApplicationServer(s *grpc.Server, srv TMSPApplicationServer) { + s.RegisterService(&_TMSPApplication_serviceDesc, srv) +} + +func _TMSPApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestEcho) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).Echo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/Echo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).Echo(ctx, req.(*RequestEcho)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestFlush) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).Flush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/Flush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).Flush(ctx, req.(*RequestFlush)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/Info", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).Info(ctx, req.(*RequestInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_SetOption_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestSetOption) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).SetOption(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/SetOption", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).SetOption(ctx, req.(*RequestSetOption)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_AppendTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestAppendTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).AppendTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/AppendTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).AppendTx(ctx, req.(*RequestAppendTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestCheckTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).CheckTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/CheckTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).CheckTx(ctx, req.(*RequestCheckTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestQuery) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).Query(ctx, req.(*RequestQuery)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestCommit) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).Commit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/Commit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).Commit(ctx, req.(*RequestCommit)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInitChain) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).InitChain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/InitChain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).InitChain(ctx, req.(*RequestInitChain)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestBeginBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).BeginBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/BeginBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) + } + return interceptor(ctx, in, info, handler) +} + +func _TMSPApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestEndBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TMSPApplicationServer).EndBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.TMSPApplication/EndBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TMSPApplicationServer).EndBlock(ctx, req.(*RequestEndBlock)) + } + return interceptor(ctx, in, info, handler) +} + +var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ + ServiceName: "types.TMSPApplication", + HandlerType: (*TMSPApplicationServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Echo", + Handler: _TMSPApplication_Echo_Handler, + }, + { + MethodName: "Flush", + Handler: _TMSPApplication_Flush_Handler, + }, + { + MethodName: "Info", + Handler: _TMSPApplication_Info_Handler, + }, + { + MethodName: "SetOption", + Handler: _TMSPApplication_SetOption_Handler, + }, + { + MethodName: "AppendTx", + Handler: _TMSPApplication_AppendTx_Handler, + }, + { + MethodName: "CheckTx", + Handler: _TMSPApplication_CheckTx_Handler, + }, + { + MethodName: "Query", + Handler: _TMSPApplication_Query_Handler, + }, + { + MethodName: "Commit", + Handler: _TMSPApplication_Commit_Handler, + }, + { + MethodName: "InitChain", + Handler: _TMSPApplication_InitChain_Handler, + }, + { + MethodName: "BeginBlock", + Handler: _TMSPApplication_BeginBlock_Handler, + }, + { + MethodName: "EndBlock", + Handler: _TMSPApplication_EndBlock_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, +} + +var fileDescriptor0 = []byte{ + // 1379 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xc9, 0x72, 0x14, 0x47, + 0x13, 0xa6, 0xa5, 0x59, 0x73, 0xb4, 0x94, 0x4a, 0x12, 0x0c, 0x13, 0xff, 0x81, 0xbf, 0xbd, 0x21, + 0x20, 0xc0, 0x21, 0xc2, 0x84, 0xb1, 0x1d, 0x8e, 0x40, 0x20, 0xb0, 0x82, 0x00, 0xe4, 0x61, 0x39, + 0x78, 0x09, 0x45, 0x6b, 0xa6, 0x66, 0xa6, 0xad, 0x51, 0x75, 0xd3, 0x0b, 0x20, 0xbf, 0x81, 0x1f, + 0xc8, 0x17, 0x5f, 0x7d, 0xf2, 0xbe, 0x3c, 0x91, 0x33, 0xab, 0xaa, 0x57, 0x75, 0x73, 0xd2, 0xad, + 0x2b, 0xb7, 0xaa, 0xca, 0xfc, 0xf2, 0xeb, 0x2c, 0xe8, 0x45, 0x27, 0xbe, 0x08, 0xaf, 0xfb, 0x81, + 0x17, 0x79, 0xbc, 0xa9, 0x16, 0xf6, 0xcf, 0x0d, 0x68, 0x0f, 0xc5, 0xcb, 0x58, 0x84, 0x11, 0xbf, + 0x0c, 0x0d, 0x31, 0x9a, 0x79, 0x7d, 0xeb, 0x92, 0x75, 0xb9, 0xb7, 0xcd, 0xaf, 0x6b, 0x73, 0xa3, + 0xdd, 0x45, 0xcd, 0x17, 0xe7, 0x86, 0xca, 0x82, 0x5f, 0x85, 0xe6, 0x64, 0x1e, 0x87, 0xb3, 0xfe, + 0x82, 0x32, 0x5d, 0x2f, 0x9a, 0xde, 0x27, 0x15, 0xda, 0x6a, 0x1b, 0x0a, 0xeb, 0xca, 0x89, 0xd7, + 0x5f, 0xac, 0x0a, 0xbb, 0x87, 0x1a, 0x0a, 0x4b, 0x16, 0xfc, 0x63, 0x80, 0x50, 0x44, 0x07, 0x9e, + 0x1f, 0xb9, 0x9e, 0xec, 0x37, 0x94, 0xfd, 0x85, 0xa2, 0xfd, 0x53, 0x11, 0x3d, 0x51, 0x6a, 0x74, + 0xea, 0x86, 0xc9, 0x82, 0x7f, 0x04, 0x5d, 0xc7, 0xf7, 0x85, 0x1c, 0x1f, 0x44, 0x6f, 0xfa, 0x4d, + 0xe5, 0x78, 0xbe, 0xe8, 0x78, 0x47, 0xa9, 0x9f, 0xbd, 0x41, 0xbf, 0x8e, 0x63, 0xbe, 0xf9, 0x36, + 0x74, 0x46, 0x33, 0x31, 0x3a, 0x22, 0xaf, 0x96, 0xf2, 0xda, 0x2c, 0x7a, 0xdd, 0x25, 0xad, 0x72, + 0x6a, 0x8f, 0xf4, 0x27, 0xbf, 0x0e, 0xad, 0x91, 0x77, 0x7c, 0xec, 0x46, 0xfd, 0xb6, 0xf2, 0xd8, + 0x28, 0x79, 0x28, 0x1d, 0x3a, 0x18, 0x2b, 0xca, 0x15, 0x2a, 0x82, 0x93, 0x7e, 0xa7, 0x2a, 0x57, + 0x5f, 0x92, 0x8a, 0x72, 0xa5, 0x6c, 0x28, 0x03, 0xae, 0x74, 0xa3, 0x83, 0xd1, 0xcc, 0x71, 0x65, + 0xbf, 0x5b, 0x95, 0x81, 0x3d, 0xd4, 0xdf, 0x25, 0x35, 0x65, 0xc0, 0x4d, 0x16, 0xfc, 0x53, 0xe8, + 0x1d, 0x8a, 0xa9, 0x2b, 0x0f, 0x0e, 0xe7, 0xde, 0xe8, 0xa8, 0x0f, 0xca, 0xb5, 0x5f, 0x74, 0xdd, + 0x21, 0x83, 0x1d, 0xd2, 0xa3, 0x2f, 0x1c, 0xa6, 0x2b, 0x4a, 0x1f, 0xe5, 0x4e, 0xbb, 0xf6, 0xaa, + 0xd2, 0xb7, 0x2b, 0xc7, 0x89, 0x63, 0x47, 0x98, 0xef, 0x9d, 0x36, 0x34, 0x5f, 0x39, 0xf3, 0x58, + 0xd8, 0x1f, 0x40, 0x2f, 0x07, 0x13, 0xde, 0x87, 0xf6, 0xb1, 0x08, 0x43, 0x67, 0x2a, 0x14, 0x96, + 0xba, 0xc3, 0x64, 0x69, 0xaf, 0xc0, 0x52, 0x1e, 0x24, 0xf6, 0x72, 0xea, 0x48, 0x40, 0xb0, 0x3f, + 0x01, 0x56, 0xae, 0x33, 0x67, 0xb0, 0x78, 0x24, 0x4e, 0x4c, 0x20, 0xfa, 0xe4, 0x1b, 0x66, 0x5b, + 0x85, 0xbe, 0xee, 0xd0, 0x9c, 0xe1, 0xff, 0xb0, 0x5a, 0x2a, 0x35, 0x5f, 0x81, 0x05, 0x2c, 0x2c, + 0x79, 0x2e, 0x0d, 0xf1, 0xcb, 0xbe, 0x04, 0x2b, 0xc5, 0xba, 0x9e, 0xb2, 0x78, 0x37, 0x3d, 0x9f, + 0x2a, 0x0c, 0x6d, 0xa5, 0x8b, 0xa7, 0x4d, 0xf4, 0xc2, 0x5e, 0x85, 0xe5, 0x42, 0xb5, 0xed, 0x7b, + 0xe9, 0xb9, 0xd3, 0xea, 0xf0, 0x0f, 0x01, 0xf0, 0x60, 0xee, 0xd8, 0x89, 0xbc, 0x20, 0x44, 0xff, + 0x45, 0x4c, 0x2a, 0x33, 0x49, 0x7d, 0x91, 0x28, 0x86, 0x39, 0x1b, 0xfb, 0x2a, 0xac, 0x9d, 0x2a, + 0x14, 0x3f, 0x0f, 0xad, 0x99, 0x70, 0xa7, 0xb3, 0x48, 0x1d, 0xa1, 0x31, 0x34, 0x2b, 0x7b, 0x2b, + 0xbd, 0x6e, 0x52, 0x9a, 0x5a, 0xd3, 0x1f, 0x9a, 0xd0, 0x19, 0x8a, 0xd0, 0xf7, 0x64, 0x28, 0x10, + 0x61, 0x5d, 0xf1, 0x66, 0x24, 0x74, 0x8b, 0x59, 0x25, 0x94, 0x68, 0x9b, 0xdd, 0x44, 0x4f, 0x08, + 0x4b, 0x8d, 0xf9, 0x96, 0xa1, 0x87, 0x72, 0xcf, 0x1b, 0xa7, 0x3c, 0x3f, 0x5c, 0x4b, 0xf8, 0x61, + 0xb1, 0xd4, 0x22, 0xda, 0xb6, 0x44, 0x10, 0x5b, 0x86, 0x20, 0x1a, 0x95, 0x81, 0x0b, 0x0c, 0x71, + 0xbb, 0xc0, 0x10, 0xcd, 0xca, 0xe3, 0xd7, 0x50, 0xc4, 0xad, 0x3c, 0x45, 0xb4, 0x4a, 0x9d, 0xa5, + 0x3d, 0x2b, 0x39, 0xe2, 0x66, 0x8e, 0x23, 0xda, 0xa5, 0xd6, 0xd0, 0x6e, 0x15, 0x24, 0x71, 0x23, + 0x25, 0x89, 0x4e, 0x89, 0x56, 0x8c, 0x4b, 0x99, 0x25, 0xae, 0x25, 0x40, 0xeb, 0x56, 0x66, 0xac, + 0x44, 0x13, 0xb7, 0x0b, 0x34, 0x01, 0x95, 0x69, 0xa8, 0xe1, 0x89, 0xcf, 0x8a, 0x3c, 0xa1, 0x9b, + 0xfd, 0x62, 0xc9, 0xb7, 0x96, 0x28, 0x6e, 0xe5, 0x89, 0x62, 0xa9, 0x32, 0x89, 0x6f, 0x67, 0x8a, + 0x2d, 0xc2, 0x78, 0x09, 0x66, 0xd4, 0x65, 0x22, 0x08, 0xbc, 0xc0, 0x34, 0xb9, 0x5e, 0xd8, 0x97, + 0xa9, 0x17, 0x33, 0x70, 0xbd, 0x85, 0x55, 0x54, 0x3f, 0xe6, 0xa0, 0x65, 0xdb, 0x99, 0x2b, 0xc1, + 0x87, 0x73, 0x83, 0x30, 0xed, 0xa7, 0xbe, 0xed, 0xf7, 0xb2, 0x93, 0x14, 0xc8, 0x66, 0xee, 0x4d, + 0x13, 0xb2, 0xc1, 0x4f, 0xfb, 0x5b, 0x6a, 0xed, 0x22, 0x3c, 0xf8, 0x3b, 0xd0, 0x18, 0x79, 0x63, + 0x7d, 0x8c, 0x95, 0xed, 0x55, 0x93, 0x80, 0xbb, 0x28, 0x7a, 0x86, 0x5f, 0x43, 0xa5, 0xa4, 0x3d, + 0xb1, 0xaf, 0x1d, 0xd5, 0x2e, 0x4b, 0x43, 0xf5, 0x9d, 0x84, 0x5f, 0xcc, 0xc2, 0x7f, 0x43, 0x6d, + 0x5c, 0x80, 0xd1, 0x59, 0x46, 0xff, 0x2a, 0x4b, 0x8c, 0xe6, 0xb3, 0x33, 0x8c, 0xfd, 0x35, 0x91, + 0x69, 0x1e, 0xcd, 0x67, 0x19, 0x7c, 0x3d, 0x2b, 0x4e, 0x8a, 0x63, 0x7b, 0x03, 0xf8, 0x69, 0x80, + 0xea, 0x7f, 0x46, 0x11, 0x7a, 0xfc, 0x7d, 0x68, 0x8e, 0xdd, 0xc9, 0x24, 0x44, 0x4a, 0xa9, 0xa6, + 0x5d, 0xad, 0xb6, 0x6f, 0x43, 0x37, 0x95, 0x11, 0x7d, 0xfa, 0xf1, 0xe1, 0x43, 0x91, 0x90, 0xbd, + 0x59, 0x11, 0x3a, 0x7d, 0xef, 0xb5, 0x08, 0xd4, 0x91, 0x1b, 0x43, 0xbd, 0xb8, 0xf2, 0x93, 0x05, + 0xbd, 0x47, 0x1a, 0x7f, 0x74, 0x3b, 0xbe, 0x0a, 0xbd, 0xc7, 0xf1, 0x7c, 0x6e, 0x44, 0xec, 0x1c, + 0xef, 0x40, 0x83, 0x60, 0xcb, 0x2c, 0xde, 0x85, 0xa6, 0x82, 0x25, 0x5b, 0x20, 0x21, 0x01, 0x92, + 0x2d, 0xf2, 0x65, 0xe8, 0xa6, 0xb0, 0x63, 0x0d, 0x5a, 0xa6, 0xfd, 0xc0, 0x9a, 0x7c, 0x09, 0x3a, + 0x09, 0xda, 0xd8, 0x1a, 0xef, 0x41, 0xdb, 0x80, 0x83, 0x61, 0xfe, 0xa0, 0xa5, 0xf3, 0xcd, 0xd6, + 0x29, 0xb2, 0xaa, 0x2b, 0xdb, 0xa0, 0x00, 0x69, 0xa6, 0xd8, 0x26, 0xfe, 0xd8, 0x20, 0xcb, 0x11, + 0x3b, 0x4f, 0x01, 0x93, 0xec, 0xb0, 0x0b, 0x57, 0x7e, 0xc4, 0x3f, 0x42, 0x52, 0x17, 0xde, 0x82, + 0x85, 0x27, 0x0f, 0xf1, 0xc0, 0x6b, 0xb0, 0xbc, 0x27, 0x23, 0x11, 0x48, 0x67, 0xbe, 0x4b, 0x0d, + 0x88, 0x27, 0x47, 0xd1, 0xae, 0xc4, 0xb2, 0xb9, 0x72, 0xaa, 0x45, 0x0b, 0x14, 0x68, 0xc7, 0x19, + 0x3f, 0xf6, 0xe4, 0x48, 0xe0, 0x2d, 0x18, 0x2c, 0x3d, 0x97, 0x4e, 0x1c, 0xcd, 0xbc, 0xc0, 0xfd, + 0x5e, 0x8c, 0xf1, 0x22, 0x9b, 0xb0, 0xb6, 0x27, 0xc3, 0x78, 0x32, 0x71, 0x47, 0xae, 0x90, 0xd1, + 0xfd, 0x58, 0x8e, 0x43, 0xbc, 0x10, 0x87, 0x95, 0xe7, 0xf2, 0x48, 0x7a, 0xaf, 0xa5, 0xf9, 0x6b, + 0xb1, 0x16, 0x36, 0xf4, 0xc6, 0x8e, 0x13, 0x8a, 0x7b, 0xb1, 0x3f, 0x77, 0x47, 0x4e, 0x24, 0xee, + 0x8c, 0xc7, 0x01, 0xa6, 0x8f, 0x09, 0x0a, 0x42, 0x9a, 0xe2, 0xde, 0x93, 0xc4, 0xa1, 0x10, 0x5f, + 0x88, 0x90, 0x4d, 0xf9, 0x45, 0xd8, 0x3c, 0xa5, 0x51, 0x3b, 0xcf, 0xf8, 0xff, 0xa0, 0x5f, 0x56, + 0x3d, 0x70, 0xc2, 0xfd, 0xc0, 0xc5, 0x0b, 0xb8, 0x58, 0x5c, 0xa6, 0xb5, 0xea, 0x3f, 0xbc, 0x27, + 0xfd, 0x38, 0x62, 0xdf, 0x25, 0xfb, 0x1b, 0xe9, 0x93, 0x38, 0x22, 0xf1, 0x51, 0x49, 0xbc, 0xaf, + 0xe0, 0xc1, 0xe6, 0xfc, 0x02, 0xac, 0xe7, 0xc4, 0x4f, 0xe9, 0x7e, 0x94, 0x9d, 0xe3, 0xec, 0xbc, + 0x5a, 0xe1, 0x4e, 0xa5, 0x13, 0xc5, 0x81, 0x60, 0x12, 0xb1, 0xc6, 0x49, 0x63, 0x52, 0x92, 0x5c, + 0xdc, 0x4b, 0x76, 0x30, 0x72, 0xb3, 0x83, 0x5f, 0x16, 0xcf, 0x63, 0xac, 0x2c, 0x7b, 0x89, 0x62, + 0xf6, 0xc0, 0x7b, 0x65, 0xa4, 0xbb, 0x32, 0x72, 0xa3, 0x13, 0xf6, 0x8b, 0x85, 0x77, 0x5a, 0xcd, + 0xc4, 0x0f, 0x02, 0x2f, 0xf6, 0xd9, 0xaf, 0x16, 0x9e, 0x92, 0x67, 0xd2, 0xfd, 0xc0, 0xf3, 0xbd, + 0xd0, 0x99, 0xb3, 0xdf, 0x2c, 0x3c, 0xcb, 0x1a, 0x2a, 0xd2, 0x2a, 0x68, 0x87, 0xdf, 0x13, 0x87, + 0x54, 0xfe, 0x48, 0x1c, 0x1f, 0x8a, 0x80, 0xfd, 0x61, 0x61, 0xb2, 0x37, 0xf2, 0x8a, 0x34, 0xd6, + 0x9f, 0x96, 0x39, 0x51, 0xaa, 0x7a, 0xe1, 0x45, 0x82, 0xfd, 0x95, 0x88, 0x4d, 0x1e, 0x4c, 0xa0, + 0xbf, 0x2d, 0xbe, 0x0e, 0x2b, 0x99, 0x58, 0xd9, 0xfe, 0x63, 0xf1, 0x01, 0x6c, 0x16, 0x84, 0x58, + 0xff, 0x7d, 0xea, 0x38, 0xf6, 0xaf, 0xb5, 0x8d, 0x93, 0xcc, 0xea, 0xb3, 0x47, 0x4f, 0xf7, 0xb1, + 0x37, 0xd4, 0x06, 0x44, 0xd9, 0x37, 0x74, 0x9f, 0xf1, 0x8a, 0xf7, 0xca, 0xa0, 0x6a, 0x48, 0xc1, + 0xa1, 0x5f, 0xb7, 0x23, 0xaf, 0x7a, 0xb6, 0x0c, 0x2a, 0x67, 0x15, 0xda, 0x44, 0xff, 0x48, 0x4e, + 0xbf, 0x5e, 0x06, 0x55, 0x03, 0x0b, 0xff, 0x3c, 0xd7, 0xde, 0xbc, 0xee, 0x0d, 0x33, 0xa8, 0x1d, + 0x5d, 0x70, 0x9c, 0x4f, 0x09, 0x80, 0xd7, 0xbc, 0x64, 0x06, 0x75, 0xe3, 0x0b, 0xce, 0x78, 0x09, + 0x5f, 0xf0, 0xea, 0xf7, 0xcc, 0xa0, 0x66, 0x84, 0xa1, 0xdc, 0xe8, 0x1f, 0x45, 0xd5, 0x33, 0x65, + 0x50, 0x39, 0x95, 0xe0, 0xe3, 0xc1, 0x10, 0x12, 0xaf, 0x7c, 0x0a, 0x0d, 0xaa, 0x67, 0x1f, 0xca, + 0x50, 0x36, 0x2c, 0xd7, 0xbd, 0x71, 0x06, 0xb5, 0x53, 0x0d, 0xbf, 0x93, 0x67, 0x38, 0x5e, 0xfb, + 0xd2, 0x19, 0xd4, 0xcf, 0x36, 0x94, 0xe4, 0x6c, 0x78, 0xae, 0x7e, 0xef, 0x0c, 0xea, 0xc6, 0x9b, + 0xc3, 0x96, 0x7a, 0x47, 0xdf, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xe3, 0x58, 0x48, 0x56, + 0x0f, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index e132ef65..22a2da4f 100644 --- a/types/types.proto +++ b/types/types.proto @@ -213,3 +213,22 @@ message Validator { bytes pubKey = 1; uint64 power = 2; } + +//---------------------------------------- +// Service Definition + +// NOTE: we may want to make CheckTx and AppendTx two way streams. +// we should be able to drop Flush for sync calls +service TMSPApplication { + rpc Echo(RequestEcho) returns (ResponseEcho) ; + rpc Flush(RequestFlush) returns (ResponseFlush); + rpc Info(RequestInfo) returns (ResponseInfo); + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + rpc AppendTx(RequestAppendTx) returns (ResponseAppendTx); + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + rpc Query(RequestQuery) returns (ResponseQuery); + rpc Commit(RequestCommit) returns (ResponseCommit); + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); +} From 1ab3c747182aaa38418258679c667090c2bb1e0d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 18 May 2016 18:30:38 -0400 Subject: [PATCH 112/545] silly grpc client --- client/client.go | 19 ++- client/grpc_client.go | 298 ++++++++++++++++++++++++++++++++++++ client/remote_client.go | 5 +- cmd/counter/main.go | 19 +-- cmd/dummy/main.go | 3 +- cmd/tmsp-cli/tmsp-cli.go | 9 +- example/dummy/dummy_test.go | 2 +- example/nil/nil_test.go | 2 +- server/server.go | 189 ++--------------------- server/socket_server.go | 191 +++++++++++++++++++++++ tests/test.sh | 3 + tests/test_counter.go | 6 +- 12 files changed, 544 insertions(+), 202 deletions(-) create mode 100644 client/grpc_client.go create mode 100644 server/socket_server.go diff --git a/client/client.go b/client/client.go index b4adfbcd..3afb838f 100644 --- a/client/client.go +++ b/client/client.go @@ -1,8 +1,10 @@ package tmspcli import ( - "github.com/tendermint/tmsp/types" + "fmt" "sync" + + "github.com/tendermint/tmsp/types" ) type Client interface { @@ -39,6 +41,21 @@ type Client interface { //---------------------------------------- +func NewClient(addr, transport string, mustConnect bool) (client Client, err error) { + switch transport { + case "socket": + client, err = NewSocketClient(addr, mustConnect) + case "grpc": + client, err = NewGRPCClient(addr, mustConnect) + default: + err = fmt.Errorf("Unknown tmsp transport %s", transport) + + } + return +} + +//---------------------------------------- + type Callback func(*types.Request, *types.Response) //---------------------------------------- diff --git a/client/grpc_client.go b/client/grpc_client.go new file mode 100644 index 00000000..0d28eed5 --- /dev/null +++ b/client/grpc_client.go @@ -0,0 +1,298 @@ +package tmspcli + +import ( + "fmt" + "net" + "sync" + "time" + + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/types" +) + +// This is goroutine-safe, but users should beware that +// the application in general is not meant to be interfaced +// with concurrent callers. +type grpcClient struct { + QuitService + mustConnect bool + + client types.TMSPApplicationClient + + mtx sync.Mutex + addr string + err error + resCb func(*types.Request, *types.Response) // listens to all callbacks +} + +func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { + cli := &grpcClient{ + addr: addr, + mustConnect: mustConnect, + } + cli.QuitService = *NewQuitService(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) +} + +func (cli *grpcClient) OnStart() (err error) { + cli.QuitService.OnStart() +RETRY_LOOP: + for { + conn, err_ := grpc.Dial(cli.addr, grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) + if err_ != nil { + if cli.mustConnect { + err = err_ // OnStart() will return this. + return + } else { + fmt.Printf("tmsp.grpcClient failed to connect to %v. Retrying...\n", cli.addr) + time.Sleep(time.Second * 3) + continue RETRY_LOOP + } + } + cli.client = types.NewTMSPApplicationClient(conn) + return + } +} + +func (cli *grpcClient) OnStop() { + cli.QuitService.OnStop() + // TODO: close client (?) +} + +// Set listener for all responses +// NOTE: callback may get internally generated flush responses. +func (cli *grpcClient) SetResponseCallback(resCb Callback) { + cli.mtx.Lock() + defer cli.mtx.Unlock() + cli.resCb = resCb +} + +func (cli *grpcClient) StopForError(err error) { + cli.mtx.Lock() + fmt.Printf("Stopping tmsp.grpcClient for error: %v\n", err.Error()) + if cli.err == nil { + cli.err = err + } + cli.mtx.Unlock() + cli.Stop() +} + +func (cli *grpcClient) Error() error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + return cli.err +} + +//---------------------------------------- +// async calls are really sync. +// maybe one day, if people really want it, we use grpc streams, +// but hopefully not :D + +func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes { + reqres := NewReqRes(req) + reqres.Response = res // Set response + reqres.Done() // Release waiters + + // Notify reqRes listener if set + if cb := reqres.GetCallback(); cb != nil { + cb(res) + } + + // Notify client listener if set + if cli.resCb != nil { + cli.resCb(reqres.Request, res) + } + return reqres +} + +func (cli *grpcClient) EchoAsync(msg string) *ReqRes { + req := types.ToRequestEcho(msg) + res, err := cli.client.Echo(context.Background(), req.GetEcho()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_Echo{res}}) +} + +func (cli *grpcClient) FlushAsync() *ReqRes { + req := types.ToRequestFlush() + res, err := cli.client.Flush(context.Background(), req.GetFlush()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_Flush{res}}) +} + +func (cli *grpcClient) InfoAsync() *ReqRes { + req := types.ToRequestInfo() + res, err := cli.client.Info(context.Background(), req.GetInfo()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_Info{res}}) +} + +func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { + req := types.ToRequestSetOption(key, value) + res, err := cli.client.SetOption(context.Background(), req.GetSetOption()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_SetOption{res}}) +} + +func (cli *grpcClient) AppendTxAsync(tx []byte) *ReqRes { + req := types.ToRequestAppendTx(tx) + res, err := cli.client.AppendTx(context.Background(), req.GetAppendTx()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_AppendTx{res}}) +} + +func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { + req := types.ToRequestCheckTx(tx) + res, err := cli.client.CheckTx(context.Background(), req.GetCheckTx()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_CheckTx{res}}) +} + +func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { + req := types.ToRequestQuery(query) + res, err := cli.client.Query(context.Background(), req.GetQuery()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}}) +} + +func (cli *grpcClient) CommitAsync() *ReqRes { + req := types.ToRequestCommit() + res, err := cli.client.Commit(context.Background(), req.GetCommit()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_Commit{res}}) +} + +func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { + req := types.ToRequestInitChain(validators) + res, err := cli.client.InitChain(context.Background(), req.GetInitChain()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_InitChain{res}}) +} + +func (cli *grpcClient) BeginBlockAsync(height uint64) *ReqRes { + req := types.ToRequestBeginBlock(height) + res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_BeginBlock{res}}) +} + +func (cli *grpcClient) EndBlockAsync(height uint64) *ReqRes { + req := types.ToRequestEndBlock(height) + res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock()) + if err != nil { + cli.err = err + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_EndBlock{res}}) +} + +//---------------------------------------- + +func (cli *grpcClient) EchoSync(msg string) (res types.Result) { + r := cli.EchoAsync(msg).Response.GetEcho() + return types.NewResultOK([]byte(r.Message), LOG) +} + +func (cli *grpcClient) FlushSync() error { + return nil +} + +func (cli *grpcClient) InfoSync() (res types.Result) { + r := cli.InfoAsync().Response.GetInfo() + return types.NewResultOK([]byte(r.Info), LOG) +} + +func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { + reqres := cli.SetOptionAsync(key, value) + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response.GetSetOption() + return types.Result{Code: OK, Data: nil, Log: resp.Log} +} + +func (cli *grpcClient) AppendTxSync(tx []byte) (res types.Result) { + reqres := cli.AppendTxAsync(tx) + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response.GetAppendTx() + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { + reqres := cli.CheckTxAsync(tx) + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response.GetCheckTx() + 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 cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response.GetQuery() + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *grpcClient) CommitSync() (res types.Result) { + reqres := cli.CommitAsync() + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) + } + resp := reqres.Response.GetCommit() + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} + +func (cli *grpcClient) InitChainSync(validators []*types.Validator) (err error) { + cli.InitChainAsync(validators) + if cli.err != nil { + return cli.err + } + return nil +} + +func (cli *grpcClient) BeginBlockSync(height uint64) (err error) { + cli.BeginBlockAsync(height) + if cli.err != nil { + return cli.err + } + return nil +} + +func (cli *grpcClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { + reqres := cli.EndBlockAsync(height) + if cli.err != nil { + return nil, cli.err + } + return reqres.Response.GetEndBlock().Diffs, nil +} diff --git a/client/remote_client.go b/client/remote_client.go index aa8a4aea..ae832716 100644 --- a/client/remote_client.go +++ b/client/remote_client.go @@ -42,7 +42,7 @@ type remoteClient struct { resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewClient(addr string, mustConnect bool) (*remoteClient, error) { +func NewSocketClient(addr string, mustConnect bool) (*remoteClient, error) { cli := &remoteClient{ reqQueue: make(chan *ReqRes, reqQueueSize), flushTimer: NewThrottleTimer("remoteClient", flushThrottleMS), @@ -129,7 +129,7 @@ func (cli *remoteClient) sendValueRoutine(conn net.Conn) { select { case <-cli.flushTimer.Ch: select { - case cli.reqQueue <- NewReqRes(types.ToRequestFlush()): + case cli.reqQueue <- NewReqRes(types.ToRequestFlush()): // cant this block ? default: // Probably will fill the buffer, or retry later. } @@ -369,6 +369,7 @@ func (cli *remoteClient) EndBlockSync(height uint64) (validators []*types.Valida func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { reqres := NewReqRes(req) + // TODO: set cli.err if reqQueue times out cli.reqQueue <- reqres diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 07bf4403..c04a40e0 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -6,31 +6,20 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/example/counter" "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" ) func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - grpcPtr := flag.String("tmsp", "socket", "TMSP server: socket | grpc") + tmspPtr := flag.String("tmsp", "socket", "TMSP server: socket | grpc") serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") flag.Parse() app := counter.NewCounterApplication(*serialPtr) // Start the listener - switch *grpcPtr { - case "socket": - _, err := server.NewServer(*addrPtr, app) - if err != nil { - Exit(err.Error()) - } - case "grpc": - _, err := server.NewGRPCServer(*addrPtr, types.NewGRPCApplication(app)) - if err != nil { - Exit(err.Error()) - } - default: - Exit(Fmt("Unknown server type %s", *grpcPtr)) + _, err := server.NewServer(*addrPtr, *tmspPtr, app) + if err != nil { + Exit(err.Error()) } // Wait forever diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 25486e44..8efa69e6 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -11,10 +11,11 @@ import ( func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") + tmspPtr := flag.String("tmsp", "socket", "socket | grpc") flag.Parse() // Start the listener - _, err := server.NewServer(*addrPtr, dummy.NewDummyApplication()) + _, err := server.NewServer(*addrPtr, *tmspPtr, dummy.NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 9e746b57..6e02166a 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -29,6 +29,13 @@ func main() { Usage: "address of application socket", }, } + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "tmsp", + Value: "socket", + Usage: "socket or grpc", + }, + } app.Commands = []cli.Command{ { Name: "batch", @@ -105,7 +112,7 @@ func main() { func before(c *cli.Context) error { if client == nil { var err error - client, err = tmspcli.NewClient(c.GlobalString("address"), false) + client, err = tmspcli.NewClient(c.GlobalString("address"), c.GlobalString("tmsp"), false) if err != nil { Exit(err.Error()) } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 7fcffd84..c5ac2d27 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -15,7 +15,7 @@ func TestStream(t *testing.T) { numAppendTxs := 200000 // Start the listener - server, err := server.NewServer("unix://test.sock", NewDummyApplication()) + server, err := server.NewSocketServer("unix://test.sock", NewDummyApplication()) if err != nil { Exit(err.Error()) } diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go index ba038b87..ed7a36dd 100644 --- a/example/nil/nil_test.go +++ b/example/nil/nil_test.go @@ -19,7 +19,7 @@ func TestStream(t *testing.T) { numAppendTxs := 200000 // Start the listener - server, err := server.NewServer("unix://test.sock", NewNilApplication()) + server, err := server.NewSocketServer("unix://test.sock", NewNilApplication()) if err != nil { Exit(err.Error()) } diff --git a/server/server.go b/server/server.go index ed832595..f2b9d0af 100644 --- a/server/server.go +++ b/server/server.go @@ -1,191 +1,22 @@ package server import ( - "bufio" "fmt" - "io" - "net" - "strings" - "sync" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" ) -// var maxNumberConnections = 2 - -type Server struct { - QuitService - - proto string - addr string - listener net.Listener - - appMtx sync.Mutex - app types.Application -} - -func NewServer(protoAddr string, app types.Application) (Service, error) { - parts := strings.SplitN(protoAddr, "://", 2) - proto, addr := parts[0], parts[1] - s := &Server{ - proto: proto, - addr: addr, - listener: nil, - app: app, +func NewServer(protoAddr, transport string, app types.Application) (Service, error) { + var s Service + var err error + switch transport { + case "socket": + s, err = NewSocketServer(protoAddr, app) + case "grpc": + s, err = NewGRPCServer(protoAddr, types.NewGRPCApplication(app)) + default: + err = fmt.Errorf("Unknown server type %s", transport) } - s.QuitService = *NewQuitService(nil, "TMSPServer", s) - _, err := s.Start() // Just start it return s, err } - -func (s *Server) OnStart() error { - s.QuitService.OnStart() - ln, err := net.Listen(s.proto, s.addr) - if err != nil { - return err - } - s.listener = ln - go s.acceptConnectionsRoutine() - return nil -} - -func (s *Server) OnStop() { - s.QuitService.OnStop() - s.listener.Close() -} - -func (s *Server) acceptConnectionsRoutine() { - // semaphore := make(chan struct{}, maxNumberConnections) - - for { - // semaphore <- struct{}{} - - // Accept a connection - fmt.Println("Waiting for new connection...") - conn, err := s.listener.Accept() - if err != nil { - if !s.IsRunning() { - return // Ignore error from listener closing. - } - Exit("Failed to accept connection: " + err.Error()) - } else { - fmt.Println("Accepted a new connection") - } - - closeConn := make(chan error, 2) // Push to signal connection closed - responses := make(chan *types.Response, 1000) // A channel to buffer responses - - // Read requests from conn and deal with them - go s.handleRequests(closeConn, conn, responses) - // Pull responses from 'responses' and write them to conn. - go s.handleResponses(closeConn, responses, conn) - - go func() { - // Wait until signal to close connection - errClose := <-closeConn - if errClose != nil { - fmt.Printf("Connection error: %v\n", errClose) - } else { - fmt.Println("Connection was closed.") - } - - // Close the connection - err := conn.Close() - if err != nil { - fmt.Printf("Error in closing connection: %v\n", err) - } - - // <-semaphore - }() - } -} - -// Read requests from conn and deal with them -func (s *Server) handleRequests(closeConn chan error, conn net.Conn, responses chan<- *types.Response) { - var count int - var bufReader = bufio.NewReader(conn) - for { - - var req = &types.Request{} - err := types.ReadMessage(bufReader, req) - if err != nil { - if err == io.EOF { - closeConn <- fmt.Errorf("Connection closed by client") - } else { - closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) - } - return - } - s.appMtx.Lock() - count++ - s.handleRequest(req, responses) - s.appMtx.Unlock() - } -} - -func (s *Server) handleRequest(req *types.Request, responses chan<- *types.Response) { - switch r := req.Value.(type) { - case *types.Request_Echo: - responses <- types.ToResponseEcho(r.Echo.Message) - case *types.Request_Flush: - responses <- types.ToResponseFlush() - case *types.Request_Info: - data := s.app.Info() - responses <- types.ToResponseInfo(data) - case *types.Request_SetOption: - so := r.SetOption - logStr := s.app.SetOption(so.Key, so.Value) - responses <- types.ToResponseSetOption(logStr) - case *types.Request_AppendTx: - res := s.app.AppendTx(r.AppendTx.Tx) - responses <- types.ToResponseAppendTx(res.Code, res.Data, res.Log) - case *types.Request_CheckTx: - res := s.app.CheckTx(r.CheckTx.Tx) - responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) - case *types.Request_Commit: - 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) - case *types.Request_InitChain: - if app, ok := s.app.(types.BlockchainAware); ok { - app.InitChain(r.InitChain.Validators) - responses <- types.ToResponseInitChain() - } else { - responses <- types.ToResponseInitChain() - } - case *types.Request_EndBlock: - if app, ok := s.app.(types.BlockchainAware); ok { - validators := app.EndBlock(r.EndBlock.Height) - responses <- types.ToResponseEndBlock(validators) - } else { - responses <- types.ToResponseEndBlock(nil) - } - default: - responses <- types.ToResponseException("Unknown request") - } -} - -// Pull responses from 'responses' and write them to conn. -func (s *Server) handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) { - var count int - var bufWriter = bufio.NewWriter(conn) - for { - var res = <-responses - err := types.WriteMessage(res, bufWriter) - if err != nil { - closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) - return - } - if _, ok := res.Value.(*types.Response_Flush); ok { - err = bufWriter.Flush() - if err != nil { - closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) - return - } - } - count++ - } -} diff --git a/server/socket_server.go b/server/socket_server.go new file mode 100644 index 00000000..7969974e --- /dev/null +++ b/server/socket_server.go @@ -0,0 +1,191 @@ +package server + +import ( + "bufio" + "fmt" + "io" + "net" + "strings" + "sync" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/types" +) + +// var maxNumberConnections = 2 + +type SocketServer struct { + QuitService + + proto string + addr string + listener net.Listener + + appMtx sync.Mutex + app types.Application +} + +func NewSocketServer(protoAddr string, app types.Application) (Service, error) { + parts := strings.SplitN(protoAddr, "://", 2) + proto, addr := parts[0], parts[1] + s := &SocketServer{ + proto: proto, + addr: addr, + listener: nil, + app: app, + } + s.QuitService = *NewQuitService(nil, "TMSPServer", s) + _, err := s.Start() // Just start it + return s, err +} + +func (s *SocketServer) OnStart() error { + s.QuitService.OnStart() + ln, err := net.Listen(s.proto, s.addr) + if err != nil { + return err + } + s.listener = ln + go s.acceptConnectionsRoutine() + return nil +} + +func (s *SocketServer) OnStop() { + s.QuitService.OnStop() + s.listener.Close() +} + +func (s *SocketServer) acceptConnectionsRoutine() { + // semaphore := make(chan struct{}, maxNumberConnections) + + for { + // semaphore <- struct{}{} + + // Accept a connection + fmt.Println("Waiting for new connection...") + conn, err := s.listener.Accept() + if err != nil { + if !s.IsRunning() { + return // Ignore error from listener closing. + } + Exit("Failed to accept connection: " + err.Error()) + } else { + fmt.Println("Accepted a new connection") + } + + closeConn := make(chan error, 2) // Push to signal connection closed + responses := make(chan *types.Response, 1000) // A channel to buffer responses + + // Read requests from conn and deal with them + go s.handleRequests(closeConn, conn, responses) + // Pull responses from 'responses' and write them to conn. + go s.handleResponses(closeConn, responses, conn) + + go func() { + // Wait until signal to close connection + errClose := <-closeConn + if errClose != nil { + fmt.Printf("Connection error: %v\n", errClose) + } else { + fmt.Println("Connection was closed.") + } + + // Close the connection + err := conn.Close() + if err != nil { + fmt.Printf("Error in closing connection: %v\n", err) + } + + // <-semaphore + }() + } +} + +// Read requests from conn and deal with them +func (s *SocketServer) handleRequests(closeConn chan error, conn net.Conn, responses chan<- *types.Response) { + var count int + var bufReader = bufio.NewReader(conn) + for { + + var req = &types.Request{} + err := types.ReadMessage(bufReader, req) + if err != nil { + if err == io.EOF { + closeConn <- fmt.Errorf("Connection closed by client") + } else { + closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) + } + return + } + s.appMtx.Lock() + count++ + s.handleRequest(req, responses) + s.appMtx.Unlock() + } +} + +func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types.Response) { + switch r := req.Value.(type) { + case *types.Request_Echo: + responses <- types.ToResponseEcho(r.Echo.Message) + case *types.Request_Flush: + responses <- types.ToResponseFlush() + case *types.Request_Info: + data := s.app.Info() + responses <- types.ToResponseInfo(data) + case *types.Request_SetOption: + so := r.SetOption + logStr := s.app.SetOption(so.Key, so.Value) + responses <- types.ToResponseSetOption(logStr) + case *types.Request_AppendTx: + res := s.app.AppendTx(r.AppendTx.Tx) + responses <- types.ToResponseAppendTx(res.Code, res.Data, res.Log) + case *types.Request_CheckTx: + res := s.app.CheckTx(r.CheckTx.Tx) + responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) + case *types.Request_Commit: + 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) + case *types.Request_InitChain: + if app, ok := s.app.(types.BlockchainAware); ok { + app.InitChain(r.InitChain.Validators) + responses <- types.ToResponseInitChain() + } else { + responses <- types.ToResponseInitChain() + } + case *types.Request_EndBlock: + if app, ok := s.app.(types.BlockchainAware); ok { + validators := app.EndBlock(r.EndBlock.Height) + responses <- types.ToResponseEndBlock(validators) + } else { + responses <- types.ToResponseEndBlock(nil) + } + default: + responses <- types.ToResponseException("Unknown request") + } +} + +// Pull responses from 'responses' and write them to conn. +func (s *SocketServer) handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) { + var count int + var bufWriter = bufio.NewWriter(conn) + for { + var res = <-responses + err := types.WriteMessage(res, bufWriter) + if err != nil { + closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) + return + } + if _, ok := res.Value.(*types.Response_Flush); ok { + err = bufWriter.Flush() + if err != nil { + closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) + return + } + } + count++ + } +} diff --git a/tests/test.sh b/tests/test.sh index d375eafa..ebdab0c8 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -5,5 +5,8 @@ cd $ROOT # test golang counter COUNTER_APP="counter" go run $ROOT/tests/test_counter.go +# test golang counter via grpc +COUNTER_APP="counter -tmsp=grpc" go run $ROOT/tests/test_counter.go -tmsp=grpc + # test nodejs counter COUNTER_APP="node ../js-tmsp/example/app.js" go run $ROOT/tests/test_counter.go diff --git a/tests/test_counter.go b/tests/test_counter.go index 2d60543e..2f78b696 100644 --- a/tests/test_counter.go +++ b/tests/test_counter.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "flag" "fmt" "os" "time" @@ -12,7 +13,10 @@ import ( "github.com/tendermint/tmsp/types" ) +var tmspPtr = flag.String("tmsp", "socket", "socket or grpc") + func main() { + flag.Parse() // Run tests testBasic() @@ -70,7 +74,7 @@ func startApp() *process.Process { func startClient() tmspcli.Client { // Start client - client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", true) + client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", *tmspPtr, true) if err != nil { panic("connecting to counter_app: " + err.Error()) } From 516a929e5f58c5cb6ce2ce639f689aae11fc6761 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 24 May 2016 21:51:28 -0400 Subject: [PATCH 113/545] some cleanup --- client/grpc_client.go | 52 +++++++++++++++++++--------------------- client/remote_client.go | 46 +++++++++++++---------------------- cmd/tmsp-cli/tmsp-cli.go | 4 +--- types/types.proto | 2 -- 4 files changed, 43 insertions(+), 61 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 0d28eed5..3fbd000b 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -13,9 +13,8 @@ import ( "github.com/tendermint/tmsp/types" ) -// This is goroutine-safe, but users should beware that -// the application in general is not meant to be interfaced -// with concurrent callers. +// A stripped copy of the remoteClient that makes +// synchronous calls using grpc type grpcClient struct { QuitService mustConnect bool @@ -42,15 +41,14 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { return Connect(addr) } -func (cli *grpcClient) OnStart() (err error) { +func (cli *grpcClient) OnStart() error { cli.QuitService.OnStart() RETRY_LOOP: for { - conn, err_ := grpc.Dial(cli.addr, grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) - if err_ != nil { + conn, err := grpc.Dial(cli.addr, grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) + if err != nil { if cli.mustConnect { - err = err_ // OnStart() will return this. - return + return err } else { fmt.Printf("tmsp.grpcClient failed to connect to %v. Retrying...\n", cli.addr) time.Sleep(time.Second * 3) @@ -58,13 +56,13 @@ RETRY_LOOP: } } cli.client = types.NewTMSPApplicationClient(conn) - return + return nil } } func (cli *grpcClient) OnStop() { cli.QuitService.OnStop() - // TODO: close client (?) + // TODO: how to close when TMSPApplicationClient interface doesn't expose Close ? } // Set listener for all responses @@ -96,23 +94,6 @@ func (cli *grpcClient) Error() error { // maybe one day, if people really want it, we use grpc streams, // but hopefully not :D -func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes { - reqres := NewReqRes(req) - reqres.Response = res // Set response - reqres.Done() // Release waiters - - // Notify reqRes listener if set - if cb := reqres.GetCallback(); cb != nil { - cb(res) - } - - // Notify client listener if set - if cli.resCb != nil { - cli.resCb(reqres.Request, res) - } - return reqres -} - func (cli *grpcClient) EchoAsync(msg string) *ReqRes { req := types.ToRequestEcho(msg) res, err := cli.client.Echo(context.Background(), req.GetEcho()) @@ -212,6 +193,23 @@ func (cli *grpcClient) EndBlockAsync(height uint64) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_EndBlock{res}}) } +func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes { + reqres := NewReqRes(req) + reqres.Response = res // Set response + reqres.Done() // Release waiters + + // Notify reqRes listener if set + if cb := reqres.GetCallback(); cb != nil { + cb(res) + } + + // Notify client listener if set + if cli.resCb != nil { + cli.resCb(reqres.Request, res) + } + return reqres +} + //---------------------------------------- func (cli *grpcClient) EchoSync(msg string) (res types.Result) { diff --git a/client/remote_client.go b/client/remote_client.go index ae832716..3c6803b7 100644 --- a/client/remote_client.go +++ b/client/remote_client.go @@ -55,39 +55,27 @@ func NewSocketClient(addr string, mustConnect bool) (*remoteClient, error) { cli.QuitService = *NewQuitService(nil, "remoteClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err - if mustConnect { - return nil, err - } else { - return cli, nil - } } -func (cli *remoteClient) OnStart() (err error) { +func (cli *remoteClient) OnStart() error { cli.QuitService.OnStart() - doneCh := make(chan struct{}) - go func() { - RETRY_LOOP: - for { - conn, err_ := Connect(cli.addr) - if err_ != nil { - if cli.mustConnect { - err = err_ // OnStart() will return this. - close(doneCh) - return - } else { - fmt.Printf("tmsp.remoteClient failed to connect to %v. Retrying...\n", cli.addr) - time.Sleep(time.Second * 3) - continue RETRY_LOOP - } +RETRY_LOOP: + for { + conn, err := Connect(cli.addr) + if err != nil { + if cli.mustConnect { + return err + } else { + fmt.Printf("tmsp.remoteClient failed to connect to %v. Retrying...\n", cli.addr) + time.Sleep(time.Second * 3) + continue RETRY_LOOP } - go cli.sendValueRoutine(conn) - go cli.recvResponseRoutine(conn) - close(doneCh) // OnStart() will return no error. - return } - }() - <-doneCh - return // err + go cli.sendRequestsRoutine(conn) + go cli.recvResponseRoutine(conn) + return err + } + return nil // never happens } func (cli *remoteClient) OnStop() { @@ -123,7 +111,7 @@ func (cli *remoteClient) Error() error { //---------------------------------------- -func (cli *remoteClient) sendValueRoutine(conn net.Conn) { +func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { w := bufio.NewWriter(conn) for { select { diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 6e02166a..373266ef 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -15,7 +15,7 @@ import ( "github.com/tendermint/tmsp/types" ) -// clientection is a global variable so it can be reused by the console +// client is a global variable so it can be reused by the console var client tmspcli.Client func main() { @@ -28,8 +28,6 @@ func main() { Value: "tcp://127.0.0.1:46658", Usage: "address of application socket", }, - } - app.Flags = []cli.Flag{ cli.StringFlag{ Name: "tmsp", Value: "socket", diff --git a/types/types.proto b/types/types.proto index 22a2da4f..cb3d82c1 100644 --- a/types/types.proto +++ b/types/types.proto @@ -217,8 +217,6 @@ message Validator { //---------------------------------------- // Service Definition -// NOTE: we may want to make CheckTx and AppendTx two way streams. -// we should be able to drop Flush for sync calls service TMSPApplication { rpc Echo(RequestEcho) returns (ResponseEcho) ; rpc Flush(RequestFlush) returns (ResponseFlush); From 8c947760e6d17309353c315b3144b6ff2b19717e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 16 Jun 2016 19:04:59 -0400 Subject: [PATCH 114/545] grpc.SupportPackageIsVersion3 --- types/types.pb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/types.pb.go b/types/types.pb.go index 181a0608..c9cc6e3f 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1324,7 +1324,7 @@ var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion2 +const _ = grpc.SupportPackageIsVersion3 // Client API for TMSPApplication service From 73e5c3cb7bbee2f9c49792e5a0fcbcab442bf7dc Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 16 Jun 2016 19:12:44 -0400 Subject: [PATCH 115/545] update grpc version --- types/types.pb.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index c9cc6e3f..a624e3f0 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -54,7 +54,9 @@ var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. -const _ = proto.ProtoPackageIsVersion1 +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // Not being used // Could be added to request/response @@ -1716,9 +1718,12 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ Handler: _TMSPApplication_EndBlock_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptor0, } +func init() { proto.RegisterFile("types.proto", fileDescriptor0) } + var fileDescriptor0 = []byte{ // 1379 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xc9, 0x72, 0x14, 0x47, From 2c21c7be894c187b3cdb884f5d22fe4f9da85377 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 22 Jun 2016 14:25:18 -0400 Subject: [PATCH 116/545] call reqRes.SetDone in grpc client --- client/grpc_client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/grpc_client.go b/client/grpc_client.go index 3fbd000b..a1c51410 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -197,6 +197,7 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) reqres := NewReqRes(req) reqres.Response = res // Set response reqres.Done() // Release waiters + reqres.SetDone() // so reqRes.SetCallback will run the callback // Notify reqRes listener if set if cb := reqres.GetCallback(); cb != nil { From 88f8141ab872a688702706c4ca73008a1d6b0985 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Jul 2016 20:22:58 -0400 Subject: [PATCH 117/545] cleanup cli, drop expr --- cmd/tmsp-cli/tmsp-cli.go | 35 +++++++++++------------- example/dummy/dummy.go | 1 + tests/test.sh | 12 -------- tests/test_counter/test.sh | 13 +++++++++ tests/{ => test_counter}/test_counter.go | 0 5 files changed, 30 insertions(+), 31 deletions(-) delete mode 100755 tests/test.sh create mode 100755 tests/test_counter/test.sh rename tests/{ => test_counter}/test_counter.go (100%) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 373266ef..f3097911 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "encoding/hex" "errors" "fmt" "io" @@ -10,7 +11,6 @@ import ( "github.com/codegangsta/cli" . "github.com/tendermint/go-common" - "github.com/tendermint/go-wire/expr" "github.com/tendermint/tmsp/client" "github.com/tendermint/tmsp/types" ) @@ -195,12 +195,7 @@ func cmdAppendTx(c *cli.Context) error { if len(args) != 1 { return errors.New("Command append_tx takes 1 argument") } - txExprString := c.Args()[0] - txBytes, err := expr.Compile(txExprString) - if err != nil { - return err - } - + txBytes := stringOrHexToBytes(c.Args()[0]) res := client.AppendTxSync(txBytes) printResponse(res, string(res.Data), true) return nil @@ -212,12 +207,7 @@ func cmdCheckTx(c *cli.Context) error { if len(args) != 1 { return errors.New("Command check_tx takes 1 argument") } - txExprString := c.Args()[0] - txBytes, err := expr.Compile(txExprString) - if err != nil { - return err - } - + txBytes := stringOrHexToBytes(c.Args()[0]) res := client.CheckTxSync(txBytes) printResponse(res, string(res.Data), true) return nil @@ -236,12 +226,7 @@ func cmdQuery(c *cli.Context) error { if len(args) != 1 { return errors.New("Command query takes 1 argument") } - queryExprString := args[0] - queryBytes, err := expr.Compile(queryExprString) - if err != nil { - return err - } - + queryBytes := stringOrHexToBytes(c.Args()[0]) res := client.QuerySync(queryBytes) printResponse(res, string(res.Data), true) return nil @@ -264,3 +249,15 @@ func printResponse(res types.Result, s string, printCode bool) { } } + +// NOTE: s is interpreted as a string unless prefixed with 0x +func stringOrHexToBytes(s string) []byte { + if len(s) > 2 && s[:2] == "0x" { + b, err := hex.DecodeString(s[2:]) + if err != nil { + fmt.Println("Error decoding hex argument:", err.Error()) + } + return b + } + return []byte(s) +} diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 3fa237f0..ca3a8c03 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -28,6 +28,7 @@ func (app *DummyApplication) SetOption(key string, value string) (log string) { return "" } +// tx is either "key=value" or just arbitrary bytes func (app *DummyApplication) AppendTx(tx []byte) types.Result { parts := strings.Split(string(tx), "=") if len(parts) == 2 { diff --git a/tests/test.sh b/tests/test.sh deleted file mode 100755 index ebdab0c8..00000000 --- a/tests/test.sh +++ /dev/null @@ -1,12 +0,0 @@ - -ROOT=$GOPATH/src/github.com/tendermint/tmsp -cd $ROOT - -# test golang counter -COUNTER_APP="counter" go run $ROOT/tests/test_counter.go - -# test golang counter via grpc -COUNTER_APP="counter -tmsp=grpc" go run $ROOT/tests/test_counter.go -tmsp=grpc - -# test nodejs counter -COUNTER_APP="node ../js-tmsp/example/app.js" go run $ROOT/tests/test_counter.go diff --git a/tests/test_counter/test.sh b/tests/test_counter/test.sh new file mode 100755 index 00000000..c1a0f58b --- /dev/null +++ b/tests/test_counter/test.sh @@ -0,0 +1,13 @@ +# These tests spawn the counter app and server by execing the COUNTER_APP command and run some simple client tests against it + +ROOT=$GOPATH/src/github.com/tendermint/tmsp/tests/test_counter +cd $ROOT + +# test golang counter +COUNTER_APP="counter" go run test_counter.go + +# test golang counter via grpc +COUNTER_APP="counter -tmsp=grpc" go run test_counter.go -tmsp=grpc + +# test nodejs counter +COUNTER_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go run test_counter.go diff --git a/tests/test_counter.go b/tests/test_counter/test_counter.go similarity index 100% rename from tests/test_counter.go rename to tests/test_counter/test_counter.go From 732634112b2643ad1d704d0c8deeb537811ede0f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Jul 2016 16:57:02 -0400 Subject: [PATCH 118/545] run grpc finishAsyncCall in go routine --- client/grpc_client.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index a1c51410..5937b5c5 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -90,7 +90,10 @@ func (cli *grpcClient) Error() error { } //---------------------------------------- -// async calls are really sync. +// GRPC calls are synchronous, but some callbacks expect to be called asynchronously +// (eg. the mempool expects to be able to lock to remove bad txs from cache). +// To accomodate, we finish each call in its own go-routine, +// which is expensive, but easy - if you want something better, use the socket protocol! // maybe one day, if people really want it, we use grpc streams, // but hopefully not :D @@ -199,15 +202,20 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) reqres.Done() // Release waiters reqres.SetDone() // so reqRes.SetCallback will run the callback - // Notify reqRes listener if set - if cb := reqres.GetCallback(); cb != nil { - cb(res) - } + // go routine for callbacks + go func() { + // Notify reqRes listener if set + if cb := reqres.GetCallback(); cb != nil { + fmt.Println("CALLING reqres CB") + cb(res) + } - // Notify client listener if set - if cli.resCb != nil { - cli.resCb(reqres.Request, res) - } + // Notify client listener if set + if cli.resCb != nil { + fmt.Println("CALLING client CB") + cli.resCb(reqres.Request, res) + } + }() return reqres } From 49a67aee8a7984a68eabe2c45ff6eb0ff51e31f9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Jul 2016 17:01:20 -0400 Subject: [PATCH 119/545] add circle.yml. disable js test --- README.md | 2 ++ circle.yml | 24 ++++++++++++++++++++++++ client/grpc_client.go | 2 -- tests/test_counter/test.sh | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 circle.yml diff --git a/README.md b/README.md index 6c842083..617e581b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Tendermint Socket Protocol (TMSP) +[![CircleCI](https://circleci.com/gh/tendermint/tmsp.svg?style=svg)](https://circleci.com/gh/tendermint/tmsp) + Blockchains are a system for creating shared multi-master application state. **TMSP** is a socket protocol enabling a blockchain consensus engine, running in one process, to manage a blockchain application state, running in another. diff --git a/circle.yml b/circle.yml new file mode 100644 index 00000000..548dcc3e --- /dev/null +++ b/circle.yml @@ -0,0 +1,24 @@ +machine: + environment: + GOPATH: /home/ubuntu/.go_workspace + REPO: $GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME + hosts: + circlehost: 127.0.0.1 + localhost: 127.0.0.1 + +checkout: + post: + - rm -rf $REPO + - mkdir -p $HOME/.go_workspace/src/github.com/$CIRCLE_PROJECT_USERNAME + - mv $HOME/$CIRCLE_PROJECT_REPONAME $REPO + # - git submodule sync + # - git submodule update --init # use submodules + +dependencies: + override: + - "cd $REPO && go get -t ./..." + +test: + override: + - "cd $REPO && go test ./..." + - "cd $REPO && bash tests/test_counter/test.sh" diff --git a/client/grpc_client.go b/client/grpc_client.go index 5937b5c5..813be658 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -206,13 +206,11 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) go func() { // Notify reqRes listener if set if cb := reqres.GetCallback(); cb != nil { - fmt.Println("CALLING reqres CB") cb(res) } // Notify client listener if set if cli.resCb != nil { - fmt.Println("CALLING client CB") cli.resCb(reqres.Request, res) } }() diff --git a/tests/test_counter/test.sh b/tests/test_counter/test.sh index c1a0f58b..7acd5d14 100755 --- a/tests/test_counter/test.sh +++ b/tests/test_counter/test.sh @@ -10,4 +10,4 @@ COUNTER_APP="counter" go run test_counter.go COUNTER_APP="counter -tmsp=grpc" go run test_counter.go -tmsp=grpc # test nodejs counter -COUNTER_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go run test_counter.go +#COUNTER_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go run test_counter.go From ba11348508939e9d273cdc1cc476c5c611e14e66 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Jul 2016 01:23:13 -0400 Subject: [PATCH 120/545] update make test --- Makefile | 1 + circle.yml | 3 +-- tests/test_counter/test.sh | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 20fb8a23..0f8adc5b 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ install: get_deps test: go test github.com/tendermint/tmsp/... + bash tests/test_counter/test.sh get_deps: go get -d github.com/tendermint/tmsp/... diff --git a/circle.yml b/circle.yml index 548dcc3e..33e50dc7 100644 --- a/circle.yml +++ b/circle.yml @@ -20,5 +20,4 @@ dependencies: test: override: - - "cd $REPO && go test ./..." - - "cd $REPO && bash tests/test_counter/test.sh" + - "cd $REPO && make test" diff --git a/tests/test_counter/test.sh b/tests/test_counter/test.sh index 7acd5d14..4883a5e0 100755 --- a/tests/test_counter/test.sh +++ b/tests/test_counter/test.sh @@ -10,4 +10,5 @@ COUNTER_APP="counter" go run test_counter.go COUNTER_APP="counter -tmsp=grpc" go run test_counter.go -tmsp=grpc # test nodejs counter +# TODO: fix node app #COUNTER_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go run test_counter.go From a263323d5c816030ff75eb9808028d8e6d747ffa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 23 Jul 2016 17:37:09 -0400 Subject: [PATCH 121/545] update readme. --verbose makes batch look like console --- README.md | 23 +++++++++++++++++++++++ cmd/tmsp-cli/tmsp-cli.go | 36 ++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 617e581b..11559c9a 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,29 @@ Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen * [js-tmsp](https://github.com/tendermint/js-tmsp) +## Contents + +This repository holds a number of important pieces: + +- `types/types.proto` + - the protobuf file definig TMSP message types, and the optional grpc interface. + - use `protoc --go_out=plugins=grpc:./types types/types.proto` to generate the `types/types.pb.go` file + - see `protoc --help` and [the grpc docs](www.grpc.io/docs) for examples and details of other languages + +- golang implementation of TMSP client and server + - two implementations: + - asynchronous, ordered message passing over unix or tcp + - grpc + - TendermintCore runs a client, and the application runs a server + +- `cmd/tmsp-cli` + - command line tool wrapping the client for probing/testing a TMSP application + +- examples: + - the `cmd/counter` application, which illustrates nonce checking in txs + - the `cmd/dummy` application, which illustrates a simple key-value merkle tree + + ## Message format Since this is a streaming protocol, all messages are encoded with a length-prefix followed by the message encoded in Protobuf3. Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index f3097911..964dbe69 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -22,6 +22,7 @@ func main() { app := cli.NewApp() app.Name = "tmsp-cli" app.Usage = "tmsp-cli [command] [args...]" + app.Version = "0.2" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "address", @@ -33,6 +34,10 @@ func main() { Value: "socket", Usage: "socket or grpc", }, + cli.BoolFlag{ + Name: "verbose", + Usage: "print the command and results as if it were a console session", + }, } app.Commands = []cli.Command{ { @@ -133,7 +138,10 @@ func cmdBatch(app *cli.App, c *cli.Context) error { } else if err != nil { return err } - args := []string{"tmsp"} + args := []string{"tmsp-cli"} + if c.GlobalBool("verbose") { + args = append(args, "--verbose") + } args = append(args, strings.Split(string(line), " ")...) app.Run(args) } @@ -151,7 +159,7 @@ func cmdConsole(app *cli.App, c *cli.Context) error { return err } - args := []string{"tmsp"} + args := []string{"tmsp-cli"} args = append(args, strings.Split(string(line), " ")...) if err := app.Run(args); err != nil { return err @@ -167,14 +175,14 @@ func cmdEcho(c *cli.Context) error { return errors.New("Command echo takes 1 argument") } res := client.EchoSync(args[0]) - printResponse(res, string(res.Data), false) + printResponse(c, res, string(res.Data), false) return nil } // Get some info from the application func cmdInfo(c *cli.Context) error { res := client.InfoSync() - printResponse(res, string(res.Data), false) + printResponse(c, res, string(res.Data), false) return nil } @@ -185,7 +193,7 @@ func cmdSetOption(c *cli.Context) error { return errors.New("Command set_option takes 2 arguments (key, value)") } res := client.SetOptionSync(args[0], args[1]) - printResponse(res, Fmt("%s=%s", args[0], args[1]), false) + printResponse(c, res, Fmt("%s=%s", args[0], args[1]), false) return nil } @@ -197,7 +205,7 @@ func cmdAppendTx(c *cli.Context) error { } txBytes := stringOrHexToBytes(c.Args()[0]) res := client.AppendTxSync(txBytes) - printResponse(res, string(res.Data), true) + printResponse(c, res, string(res.Data), true) return nil } @@ -209,14 +217,14 @@ func cmdCheckTx(c *cli.Context) error { } txBytes := stringOrHexToBytes(c.Args()[0]) res := client.CheckTxSync(txBytes) - printResponse(res, string(res.Data), true) + printResponse(c, res, string(res.Data), true) return nil } // Get application Merkle root hash func cmdCommit(c *cli.Context) error { res := client.CommitSync() - printResponse(res, Fmt("%X", res.Data), false) + printResponse(c, res, Fmt("%X", res.Data), false) return nil } @@ -228,13 +236,17 @@ func cmdQuery(c *cli.Context) error { } queryBytes := stringOrHexToBytes(c.Args()[0]) res := client.QuerySync(queryBytes) - printResponse(res, string(res.Data), true) + printResponse(c, res, string(res.Data), true) return nil } //-------------------------------------------------------------------------------- -func printResponse(res types.Result, s string, printCode bool) { +func printResponse(c *cli.Context, res types.Result, s string, printCode bool) { + if c.GlobalBool("verbose") { + fmt.Println(">", c.Command.Name, strings.Join(c.Args(), " ")) + } + if printCode { fmt.Printf("-> code: %s\n", res.Code.String()) } @@ -248,6 +260,10 @@ func printResponse(res types.Result, s string, printCode bool) { fmt.Printf("-> log: %s\n", res.Log) } + if c.GlobalBool("verbose") { + fmt.Println("") + } + } // NOTE: s is interpreted as a string unless prefixed with 0x From 3b329039d8b0dfaf5bfaf24724e2bd9d68d3c581 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 23 Jul 2016 18:54:58 -0400 Subject: [PATCH 122/545] better testing. cli test for tutorial --- Makefile | 2 +- README.md | 3 +- tests/test.sh | 8 +++ .../test_counter.go => test_app/app.go} | 62 ++++--------------- tests/test_app/main.go | 48 ++++++++++++++ tests/test_app/test.sh | 17 +++++ tests/test_cli/ex1.tmsp | 10 +++ tests/test_cli/ex1.tmsp.out | 31 ++++++++++ tests/test_cli/ex2.tmsp | 8 +++ tests/test_cli/ex2.tmsp.out | 26 ++++++++ tests/test_cli/test.sh | 29 +++++++++ tests/test_counter/test.sh | 14 ----- 12 files changed, 191 insertions(+), 67 deletions(-) create mode 100644 tests/test.sh rename tests/{test_counter/test_counter.go => test_app/app.go} (51%) create mode 100644 tests/test_app/main.go create mode 100755 tests/test_app/test.sh create mode 100644 tests/test_cli/ex1.tmsp create mode 100644 tests/test_cli/ex1.tmsp.out create mode 100644 tests/test_cli/ex2.tmsp create mode 100644 tests/test_cli/ex2.tmsp.out create mode 100644 tests/test_cli/test.sh delete mode 100755 tests/test_counter/test.sh diff --git a/Makefile b/Makefile index 0f8adc5b..b47dc0e2 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ install: get_deps test: go test github.com/tendermint/tmsp/... - bash tests/test_counter/test.sh + bash tests/test.sh get_deps: go get -d github.com/tendermint/tmsp/... diff --git a/README.md b/README.md index 11559c9a..ba751383 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This repository holds a number of important pieces: - `types/types.proto` - the protobuf file definig TMSP message types, and the optional grpc interface. - - use `protoc --go_out=plugins=grpc:./types types/types.proto` to generate the `types/types.pb.go` file + - use `protoc --go_out=plugins=grpc:. types.proto` to from the `types` dir to generate the `types/types.pb.go` file - see `protoc --help` and [the grpc docs](www.grpc.io/docs) for examples and details of other languages - golang implementation of TMSP client and server @@ -29,6 +29,7 @@ This repository holds a number of important pieces: - `cmd/tmsp-cli` - command line tool wrapping the client for probing/testing a TMSP application + - use `tmsp-cli --version` to get the TMSP version - examples: - the `cmd/counter` application, which illustrates nonce checking in txs diff --git a/tests/test.sh b/tests/test.sh new file mode 100644 index 00000000..4087cdce --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,8 @@ +#! /bin/bash + +# test the counter using a go test script +bash tests/test_app/test.sh + +# test the cli against the examples in the tutorial at tendermint.com +bash tests/test_cli/test.sh + diff --git a/tests/test_counter/test_counter.go b/tests/test_app/app.go similarity index 51% rename from tests/test_counter/test_counter.go rename to tests/test_app/app.go index 2f78b696..2a1bf15a 100644 --- a/tests/test_counter/test_counter.go +++ b/tests/test_app/app.go @@ -2,8 +2,6 @@ package main import ( "bytes" - "flag" - "fmt" "os" "time" @@ -13,57 +11,19 @@ import ( "github.com/tendermint/tmsp/types" ) -var tmspPtr = flag.String("tmsp", "socket", "socket or grpc") - -func main() { - flag.Parse() - - // Run tests - testBasic() - - fmt.Println("Success!") -} - -func testBasic() { - fmt.Println("Running basic tests") - appProc := startApp() - defer appProc.StopProcess(true) - client := startClient() - defer client.Stop() - - setOption(client, "serial", "on") - commit(client, nil) - appendTx(client, []byte("abc"), types.CodeType_BadNonce, nil) - commit(client, nil) - appendTx(client, []byte{0x00}, types.CodeType_OK, nil) - commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) - appendTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) - appendTx(client, []byte{0x01}, types.CodeType_OK, nil) - appendTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) - appendTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) - appendTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) - appendTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) - commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) -} - //---------------------------------------- -func startApp() *process.Process { - counterApp := os.Getenv("COUNTER_APP") - if counterApp == "" { - panic("No COUNTER_APP specified") - } - +func StartApp(tmspApp string) *process.Process { // Start the app //outBuf := NewBufferCloser(nil) - proc, err := process.StartProcess("counter_app", + proc, err := process.StartProcess("tmsp_app", "bash", - []string{"-c", counterApp}, + []string{"-c", tmspApp}, nil, os.Stdout, ) if err != nil { - panic("running counter_app: " + err.Error()) + panic("running tmsp_app: " + err.Error()) } // TODO a better way to handle this? @@ -72,16 +32,16 @@ func startApp() *process.Process { return proc } -func startClient() tmspcli.Client { +func StartClient(tmspType string) tmspcli.Client { // Start client - client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", *tmspPtr, true) + client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", tmspType, true) if err != nil { - panic("connecting to counter_app: " + err.Error()) + panic("connecting to tmsp_app: " + err.Error()) } return client } -func setOption(client tmspcli.Client, key, value string) { +func SetOption(client tmspcli.Client, key, value string) { res := client.SetOptionSync(key, value) _, _, log := res.Code, res.Data, res.Log if res.IsErr() { @@ -89,7 +49,7 @@ func setOption(client tmspcli.Client, key, value string) { } } -func commit(client tmspcli.Client, hashExp []byte) { +func Commit(client tmspcli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { @@ -101,7 +61,7 @@ func commit(client tmspcli.Client, hashExp []byte) { } } -func appendTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func AppendTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.AppendTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if code != codeExp { @@ -114,7 +74,7 @@ func appendTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dat } } -func checkTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func CheckTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.CheckTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if res.IsErr() { diff --git a/tests/test_app/main.go b/tests/test_app/main.go new file mode 100644 index 00000000..ada63718 --- /dev/null +++ b/tests/test_app/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "fmt" + "os" + + "github.com/tendermint/tmsp/types" +) + +var tmspType string + +func init() { + tmspType = os.Getenv("TMSP") + if tmspType == "" { + tmspType = "socket" + } +} + +func main() { + testCounter() +} + +func testCounter() { + tmspApp := os.Getenv("TMSP_APP") + if tmspApp == "" { + panic("No TMSP_APP specified") + } + + fmt.Printf("Running %s test with tmsp=%s\n", tmspApp, tmspType) + appProc := StartApp(tmspApp) + defer appProc.StopProcess(true) + client := StartClient(tmspType) + defer client.Stop() + + SetOption(client, "serial", "on") + Commit(client, nil) + AppendTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + Commit(client, nil) + AppendTx(client, []byte{0x00}, types.CodeType_OK, nil) + Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) + AppendTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) + AppendTx(client, []byte{0x01}, types.CodeType_OK, nil) + AppendTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) + AppendTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) + AppendTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) + AppendTx(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_app/test.sh b/tests/test_app/test.sh new file mode 100755 index 00000000..4c28a831 --- /dev/null +++ b/tests/test_app/test.sh @@ -0,0 +1,17 @@ +#! /bin/bash +set -e + +# These tests spawn the counter app and server by execing the TMSP_APP command and run some simple client tests against it + +ROOT=$GOPATH/src/github.com/tendermint/tmsp/tests/test_app +cd $ROOT + +# test golang counter +TMSP_APP="counter" go run *.go + +# test golang counter via grpc +TMSP_APP="counter -tmsp=grpc" TMSP="grpc" go run *.go + +# test nodejs counter +# TODO: fix node app +#TMSP_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go test -test.run TestCounter diff --git a/tests/test_cli/ex1.tmsp b/tests/test_cli/ex1.tmsp new file mode 100644 index 00000000..de61c8b2 --- /dev/null +++ b/tests/test_cli/ex1.tmsp @@ -0,0 +1,10 @@ +echo hello +info +commit +append_tx abc +info +commit +query abc +append_tx def=xyz +commit +query def diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.tmsp.out new file mode 100644 index 00000000..89bd61c2 --- /dev/null +++ b/tests/test_cli/ex1.tmsp.out @@ -0,0 +1,31 @@ +> echo hello +-> data: {hello} + +> info +-> data: {size:0} + +> commit + +> append_tx abc +-> code: OK + +> info +-> data: {size:1} + +> commit +-> data: {750502FC7E84BBD788ED589624F06CFA871845D1} + +> query abc +-> code: OK +-> data: {Index=0 value=abc exists=true} + +> append_tx def=xyz +-> code: OK + +> commit +-> data: {76393B8A182E450286B0694C629ECB51B286EFD5} + +> query def +-> code: OK +-> data: {Index=1 value=xyz exists=true} + diff --git a/tests/test_cli/ex2.tmsp b/tests/test_cli/ex2.tmsp new file mode 100644 index 00000000..e9550db8 --- /dev/null +++ b/tests/test_cli/ex2.tmsp @@ -0,0 +1,8 @@ +set_option serial on +check_tx 0x00 +check_tx 0xff +append_tx 0x00 +check_tx 0x00 +append_tx 0x01 +append_tx 0x04 +info diff --git a/tests/test_cli/ex2.tmsp.out b/tests/test_cli/ex2.tmsp.out new file mode 100644 index 00000000..3aa7744b --- /dev/null +++ b/tests/test_cli/ex2.tmsp.out @@ -0,0 +1,26 @@ +> set_option serial on +-> data: {serial=on} + +> check_tx 0x00 +-> code: OK + +> check_tx 0xff +-> code: OK + +> append_tx 0x00 +-> code: OK + +> check_tx 0x00 +-> code: BadNonce +-> log: Invalid nonce. Expected >= 1, got 0 + +> append_tx 0x01 +-> code: OK + +> append_tx 0x04 +-> code: BadNonce +-> log: Invalid nonce. Expected 2, got 4 + +> info +-> data: {hashes:0, txs:2} + diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh new file mode 100644 index 00000000..f8920958 --- /dev/null +++ b/tests/test_cli/test.sh @@ -0,0 +1,29 @@ +#! /bin/bash + +function testExample() { + N=$1 + INPUT=$2 + APP=$3 + + echo "Example $N" + $APP &> /dev/null & + sleep 2 + tmsp-cli --verbose batch < $INPUT > "${INPUT}.out.new" + killall "$APP" > /dev/null + + pre=`shasum < "${INPUT}.out"` + post=`shasum < "${INPUT}.out.new"` + + if [[ "$pre" != "$post" ]]; then + echo "You broke the tutorial" + exit 1 + fi + + rm "${INPUT}".out.new +} + +testExample 1 tests/test_cli/ex1.tmsp dummy +testExample 2 tests/test_cli/ex2.tmsp counter + +echo "" +echo "PASS" diff --git a/tests/test_counter/test.sh b/tests/test_counter/test.sh deleted file mode 100755 index 4883a5e0..00000000 --- a/tests/test_counter/test.sh +++ /dev/null @@ -1,14 +0,0 @@ -# These tests spawn the counter app and server by execing the COUNTER_APP command and run some simple client tests against it - -ROOT=$GOPATH/src/github.com/tendermint/tmsp/tests/test_counter -cd $ROOT - -# test golang counter -COUNTER_APP="counter" go run test_counter.go - -# test golang counter via grpc -COUNTER_APP="counter -tmsp=grpc" go run test_counter.go -tmsp=grpc - -# test nodejs counter -# TODO: fix node app -#COUNTER_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go run test_counter.go From fbbf82ec64c338bf9f66ad43b5d0c32d807ddcda Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 23 Jul 2016 19:05:46 -0400 Subject: [PATCH 123/545] update README.md --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ba751383..fc5c7bb2 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,14 @@ Other implementations: This repository holds a number of important pieces: - `types/types.proto` - - the protobuf file definig TMSP message types, and the optional grpc interface. - - use `protoc --go_out=plugins=grpc:. types.proto` to from the `types` dir to generate the `types/types.pb.go` file - - see `protoc --help` and [the grpc docs](www.grpc.io/docs) for examples and details of other languages + - the protobuf file defining TMSP message types, and the optional grpc interface. + - run `protoc --go_out=plugins=grpc:. types.proto` in the `types` dir to generate the `types/types.pb.go` file + - see `protoc --help` and [the grpc docs](https://www.grpc.io/docs) for examples and details of other languages - golang implementation of TMSP client and server - two implementations: - - asynchronous, ordered message passing over unix or tcp + - asynchronous, ordered message passing over unix or tcp; + - messages are serialized using protobuf and length prefixed - grpc - TendermintCore runs a client, and the application runs a server @@ -42,6 +43,8 @@ Since this is a streaming protocol, all messages are encoded with a length-prefi For example, if the Protobuf3 encoded TMSP message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded TMSP message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. +Note this prefixing does not apply for grpc. + ## Message types TMSP requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/tmsp/blob/master/types/types.proto). From d3bdb49aae984a3866a72e5980c932f13de63b75 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 10 Aug 2016 17:49:15 -0400 Subject: [PATCH 124/545] remote_client -> socket_client; use logger --- client/grpc_client.go | 5 +- client/log.go | 7 ++ client/{remote_client.go => socket_client.go} | 82 ++++++++++--------- 3 files changed, 51 insertions(+), 43 deletions(-) create mode 100644 client/log.go rename client/{remote_client.go => socket_client.go} (77%) diff --git a/client/grpc_client.go b/client/grpc_client.go index 813be658..745de2f8 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -1,7 +1,6 @@ package tmspcli import ( - "fmt" "net" "sync" "time" @@ -50,7 +49,7 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - fmt.Printf("tmsp.grpcClient failed to connect to %v. Retrying...\n", cli.addr) + log.Warn(Fmt("tmsp.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -75,7 +74,7 @@ func (cli *grpcClient) SetResponseCallback(resCb Callback) { func (cli *grpcClient) StopForError(err error) { cli.mtx.Lock() - fmt.Printf("Stopping tmsp.grpcClient for error: %v\n", err.Error()) + log.Warn(Fmt("Stopping tmsp.grpcClient for error: %v\n", err.Error())) if cli.err == nil { cli.err = err } diff --git a/client/log.go b/client/log.go new file mode 100644 index 00000000..deadf6c3 --- /dev/null +++ b/client/log.go @@ -0,0 +1,7 @@ +package tmspcli + +import ( + "github.com/tendermint/go-logger" +) + +var log = logger.New("module", "tmspcli") diff --git a/client/remote_client.go b/client/socket_client.go similarity index 77% rename from client/remote_client.go rename to client/socket_client.go index 3c6803b7..2b89b294 100644 --- a/client/remote_client.go +++ b/client/socket_client.go @@ -26,7 +26,7 @@ const flushThrottleMS = 20 // Don't wait longer than... // This is goroutine-safe, but users should beware that // the application in general is not meant to be interfaced // with concurrent callers. -type remoteClient struct { +type socketClient struct { QuitService sync.Mutex // [EB]: is this even used? @@ -42,22 +42,22 @@ type remoteClient struct { resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewSocketClient(addr string, mustConnect bool) (*remoteClient, error) { - cli := &remoteClient{ +func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { + cli := &socketClient{ reqQueue: make(chan *ReqRes, reqQueueSize), - flushTimer: NewThrottleTimer("remoteClient", flushThrottleMS), + flushTimer: NewThrottleTimer("socketClient", flushThrottleMS), mustConnect: mustConnect, addr: addr, reqSent: list.New(), resCb: nil, } - cli.QuitService = *NewQuitService(nil, "remoteClient", cli) + cli.QuitService = *NewQuitService(nil, "socketClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err } -func (cli *remoteClient) OnStart() error { +func (cli *socketClient) OnStart() error { cli.QuitService.OnStart() RETRY_LOOP: for { @@ -66,7 +66,7 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - fmt.Printf("tmsp.remoteClient failed to connect to %v. Retrying...\n", cli.addr) + log.Warn(Fmt("tmsp.socketClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -78,7 +78,7 @@ RETRY_LOOP: return nil // never happens } -func (cli *remoteClient) OnStop() { +func (cli *socketClient) OnStop() { cli.QuitService.OnStop() if cli.conn != nil { cli.conn.Close() @@ -87,15 +87,15 @@ func (cli *remoteClient) OnStop() { // Set listener for all responses // NOTE: callback may get internally generated flush responses. -func (cli *remoteClient) SetResponseCallback(resCb Callback) { +func (cli *socketClient) SetResponseCallback(resCb Callback) { cli.mtx.Lock() defer cli.mtx.Unlock() cli.resCb = resCb } -func (cli *remoteClient) StopForError(err error) { +func (cli *socketClient) StopForError(err error) { cli.mtx.Lock() - fmt.Printf("Stopping tmsp.remoteClient for error: %v\n", err.Error()) + log.Warn(Fmt("Stopping tmsp.socketClient for error: %v\n", err.Error())) if cli.err == nil { cli.err = err } @@ -103,7 +103,7 @@ func (cli *remoteClient) StopForError(err error) { cli.Stop() } -func (cli *remoteClient) Error() error { +func (cli *socketClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() return cli.err @@ -111,13 +111,13 @@ func (cli *remoteClient) Error() error { //---------------------------------------- -func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { +func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { w := bufio.NewWriter(conn) for { select { case <-cli.flushTimer.Ch: select { - case cli.reqQueue <- NewReqRes(types.ToRequestFlush()): // cant this block ? + case cli.reqQueue <- NewReqRes(types.ToRequestFlush()): default: // Probably will fill the buffer, or retry later. } @@ -142,7 +142,7 @@ func (cli *remoteClient) sendRequestsRoutine(conn net.Conn) { } } -func (cli *remoteClient) recvResponseRoutine(conn net.Conn) { +func (cli *socketClient) recvResponseRoutine(conn net.Conn) { r := bufio.NewReader(conn) // Buffer reads for { var res = &types.Response{} @@ -165,13 +165,13 @@ func (cli *remoteClient) recvResponseRoutine(conn net.Conn) { } } -func (cli *remoteClient) willSendReq(reqres *ReqRes) { +func (cli *socketClient) willSendReq(reqres *ReqRes) { cli.mtx.Lock() defer cli.mtx.Unlock() cli.reqSent.PushBack(reqres) } -func (cli *remoteClient) didRecvResponse(res *types.Response) error { +func (cli *socketClient) didRecvResponse(res *types.Response) error { cli.mtx.Lock() defer cli.mtx.Unlock() @@ -205,53 +205,53 @@ func (cli *remoteClient) didRecvResponse(res *types.Response) error { //---------------------------------------- -func (cli *remoteClient) EchoAsync(msg string) *ReqRes { +func (cli *socketClient) EchoAsync(msg string) *ReqRes { return cli.queueRequest(types.ToRequestEcho(msg)) } -func (cli *remoteClient) FlushAsync() *ReqRes { +func (cli *socketClient) FlushAsync() *ReqRes { return cli.queueRequest(types.ToRequestFlush()) } -func (cli *remoteClient) InfoAsync() *ReqRes { +func (cli *socketClient) InfoAsync() *ReqRes { return cli.queueRequest(types.ToRequestInfo()) } -func (cli *remoteClient) SetOptionAsync(key string, value string) *ReqRes { +func (cli *socketClient) SetOptionAsync(key string, value string) *ReqRes { return cli.queueRequest(types.ToRequestSetOption(key, value)) } -func (cli *remoteClient) AppendTxAsync(tx []byte) *ReqRes { +func (cli *socketClient) AppendTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.ToRequestAppendTx(tx)) } -func (cli *remoteClient) CheckTxAsync(tx []byte) *ReqRes { +func (cli *socketClient) CheckTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.ToRequestCheckTx(tx)) } -func (cli *remoteClient) QueryAsync(query []byte) *ReqRes { +func (cli *socketClient) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.ToRequestQuery(query)) } -func (cli *remoteClient) CommitAsync() *ReqRes { +func (cli *socketClient) CommitAsync() *ReqRes { return cli.queueRequest(types.ToRequestCommit()) } -func (cli *remoteClient) InitChainAsync(validators []*types.Validator) *ReqRes { +func (cli *socketClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.queueRequest(types.ToRequestInitChain(validators)) } -func (cli *remoteClient) BeginBlockAsync(height uint64) *ReqRes { +func (cli *socketClient) BeginBlockAsync(height uint64) *ReqRes { return cli.queueRequest(types.ToRequestBeginBlock(height)) } -func (cli *remoteClient) EndBlockAsync(height uint64) *ReqRes { +func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { return cli.queueRequest(types.ToRequestEndBlock(height)) } //---------------------------------------- -func (cli *remoteClient) EchoSync(msg string) (res types.Result) { +func (cli *socketClient) EchoSync(msg string) (res types.Result) { reqres := cli.queueRequest(types.ToRequestEcho(msg)) cli.FlushSync() if cli.err != nil { @@ -261,12 +261,14 @@ func (cli *remoteClient) EchoSync(msg string) (res types.Result) { return types.Result{Code: OK, Data: []byte(resp.Message), Log: LOG} } -func (cli *remoteClient) FlushSync() error { +func (cli *socketClient) FlushSync() error { + log.Warn("FlushSync") cli.queueRequest(types.ToRequestFlush()).Wait() + log.Warn("Done FlushSync") return cli.err } -func (cli *remoteClient) InfoSync() (res types.Result) { +func (cli *socketClient) InfoSync() (res types.Result) { reqres := cli.queueRequest(types.ToRequestInfo()) cli.FlushSync() if cli.err != nil { @@ -276,7 +278,7 @@ func (cli *remoteClient) InfoSync() (res types.Result) { return types.Result{Code: OK, Data: []byte(resp.Info), Log: LOG} } -func (cli *remoteClient) SetOptionSync(key string, value string) (res types.Result) { +func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { reqres := cli.queueRequest(types.ToRequestSetOption(key, value)) cli.FlushSync() if cli.err != nil { @@ -286,7 +288,7 @@ func (cli *remoteClient) SetOptionSync(key string, value string) (res types.Resu return types.Result{Code: OK, Data: nil, Log: resp.Log} } -func (cli *remoteClient) AppendTxSync(tx []byte) (res types.Result) { +func (cli *socketClient) AppendTxSync(tx []byte) (res types.Result) { reqres := cli.queueRequest(types.ToRequestAppendTx(tx)) cli.FlushSync() if cli.err != nil { @@ -296,7 +298,7 @@ func (cli *remoteClient) AppendTxSync(tx []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *remoteClient) CheckTxSync(tx []byte) (res types.Result) { +func (cli *socketClient) CheckTxSync(tx []byte) (res types.Result) { reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() if cli.err != nil { @@ -306,7 +308,7 @@ func (cli *remoteClient) CheckTxSync(tx []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *remoteClient) QuerySync(query []byte) (res types.Result) { +func (cli *socketClient) QuerySync(query []byte) (res types.Result) { reqres := cli.queueRequest(types.ToRequestQuery(query)) cli.FlushSync() if cli.err != nil { @@ -316,7 +318,7 @@ func (cli *remoteClient) QuerySync(query []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *remoteClient) CommitSync() (res types.Result) { +func (cli *socketClient) CommitSync() (res types.Result) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() if cli.err != nil { @@ -326,7 +328,7 @@ func (cli *remoteClient) CommitSync() (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *remoteClient) InitChainSync(validators []*types.Validator) (err error) { +func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error) { cli.queueRequest(types.ToRequestInitChain(validators)) cli.FlushSync() if cli.err != nil { @@ -335,7 +337,7 @@ func (cli *remoteClient) InitChainSync(validators []*types.Validator) (err error return nil } -func (cli *remoteClient) BeginBlockSync(height uint64) (err error) { +func (cli *socketClient) BeginBlockSync(height uint64) (err error) { cli.queueRequest(types.ToRequestBeginBlock(height)) cli.FlushSync() if cli.err != nil { @@ -344,7 +346,7 @@ func (cli *remoteClient) BeginBlockSync(height uint64) (err error) { return nil } -func (cli *remoteClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { +func (cli *socketClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { reqres := cli.queueRequest(types.ToRequestEndBlock(height)) cli.FlushSync() if cli.err != nil { @@ -355,7 +357,7 @@ func (cli *remoteClient) EndBlockSync(height uint64) (validators []*types.Valida //---------------------------------------- -func (cli *remoteClient) queueRequest(req *types.Request) *ReqRes { +func (cli *socketClient) queueRequest(req *types.Request) *ReqRes { reqres := NewReqRes(req) // TODO: set cli.err if reqQueue times out From a8066f9c8200203e64913ccd5c7bc67f3e9c683d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 10 Aug 2016 17:58:11 -0400 Subject: [PATCH 125/545] return error if not running --- client/socket_client.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/client/socket_client.go b/client/socket_client.go index 2b89b294..ea1e7d6e 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -83,6 +83,19 @@ func (cli *socketClient) OnStop() { if cli.conn != nil { cli.conn.Close() } + cli.flushQueue() +} + +func (cli *socketClient) flushQueue() { +LOOP: + for { + select { + case reqres := <-cli.reqQueue: + reqres.Done() + default: + break LOOP + } + } } // Set listener for all responses @@ -94,6 +107,10 @@ func (cli *socketClient) SetResponseCallback(resCb Callback) { } func (cli *socketClient) StopForError(err error) { + if !cli.IsRunning() { + return + } + cli.mtx.Lock() log.Warn(Fmt("Stopping tmsp.socketClient for error: %v\n", err.Error())) if cli.err == nil { @@ -262,9 +279,12 @@ func (cli *socketClient) EchoSync(msg string) (res types.Result) { } func (cli *socketClient) FlushSync() error { - log.Warn("FlushSync") - cli.queueRequest(types.ToRequestFlush()).Wait() - log.Warn("Done FlushSync") + reqRes := cli.queueRequest(types.ToRequestFlush()) + if reqRes == nil { + return fmt.Errorf("Remote app is not running") + + } + reqRes.Wait() // NOTE: if we don't flush the queue, its possible to get stuck here return cli.err } @@ -358,6 +378,10 @@ func (cli *socketClient) EndBlockSync(height uint64) (validators []*types.Valida //---------------------------------------- func (cli *socketClient) queueRequest(req *types.Request) *ReqRes { + if !cli.IsRunning() { + return nil + } + reqres := NewReqRes(req) // TODO: set cli.err if reqQueue times out From 1b13f14e08e0058989b5b602e0c7e52777ad4455 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 10 Aug 2016 18:29:46 -0400 Subject: [PATCH 126/545] consolidate example tests; grpc fail fast --- client/client.go | 4 +- client/grpc_client.go | 150 +++++++++++++++++++++++------------ client/local_client.go | 13 ++-- client/socket_client.go | 96 +++++++++++++---------- example/dummy/dummy_test.go | 93 ---------------------- example/example_test.go | 151 ++++++++++++++++++++++++++++++++++++ example/nil/nil_test.go | 148 ----------------------------------- server/grpc_server.go | 9 ++- server/log.go | 7 ++ server/socket_server.go | 60 +++++++++++--- tests/test_cli/test.sh | 2 +- 11 files changed, 378 insertions(+), 355 deletions(-) delete mode 100644 example/dummy/dummy_test.go create mode 100644 example/example_test.go delete mode 100644 example/nil/nil_test.go create mode 100644 server/log.go diff --git a/client/client.go b/client/client.go index 3afb838f..291c4863 100644 --- a/client/client.go +++ b/client/client.go @@ -4,13 +4,15 @@ import ( "fmt" "sync" + . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" ) type Client interface { + Service + SetResponseCallback(Callback) Error() error - Stop() bool FlushAsync() *ReqRes EchoAsync(msg string) *ReqRes diff --git a/client/grpc_client.go b/client/grpc_client.go index 745de2f8..3e44dcc1 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -1,6 +1,7 @@ package tmspcli import ( + "errors" "net" "sync" "time" @@ -43,6 +44,7 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { func (cli *grpcClient) OnStart() error { cli.QuitService.OnStart() RETRY_LOOP: + for { conn, err := grpc.Dial(cli.addr, grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) if err != nil { @@ -54,14 +56,52 @@ RETRY_LOOP: continue RETRY_LOOP } } - cli.client = types.NewTMSPApplicationClient(conn) + + client := types.NewTMSPApplicationClient(conn) + + ENSURE_CONNECTED: + for { + _, err := client.Echo(context.Background(), &types.RequestEcho{"hello"}, grpc.FailFast(true)) + if err == nil { + break ENSURE_CONNECTED + } + time.Sleep(time.Second) + } + + cli.client = client return nil } } func (cli *grpcClient) OnStop() { cli.QuitService.OnStop() - // TODO: how to close when TMSPApplicationClient interface doesn't expose Close ? + cli.mtx.Lock() + defer cli.mtx.Unlock() + // TODO: how to close conn? its not a net.Conn and grpc doesn't expose a Close() + /*if cli.conn != nil { + cli.conn.Close() + }*/ +} + +func (cli *grpcClient) StopForError(err error) { + cli.mtx.Lock() + if !cli.IsRunning() { + return + } + + if cli.err == nil { + cli.err = err + } + cli.mtx.Unlock() + + log.Warn(Fmt("Stopping tmsp.grpcClient for error: %v", err.Error())) + cli.Stop() +} + +func (cli *grpcClient) Error() error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + return cli.err } // Set listener for all responses @@ -72,22 +112,6 @@ func (cli *grpcClient) SetResponseCallback(resCb Callback) { cli.resCb = resCb } -func (cli *grpcClient) StopForError(err error) { - cli.mtx.Lock() - log.Warn(Fmt("Stopping tmsp.grpcClient for error: %v\n", err.Error())) - if cli.err == nil { - cli.err = err - } - cli.mtx.Unlock() - cli.Stop() -} - -func (cli *grpcClient) Error() error { - cli.mtx.Lock() - defer cli.mtx.Unlock() - return cli.err -} - //---------------------------------------- // GRPC calls are synchronous, but some callbacks expect to be called asynchronously // (eg. the mempool expects to be able to lock to remove bad txs from cache). @@ -98,7 +122,7 @@ func (cli *grpcClient) Error() error { func (cli *grpcClient) EchoAsync(msg string) *ReqRes { req := types.ToRequestEcho(msg) - res, err := cli.client.Echo(context.Background(), req.GetEcho()) + res, err := cli.client.Echo(context.Background(), req.GetEcho(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -107,7 +131,7 @@ func (cli *grpcClient) EchoAsync(msg string) *ReqRes { func (cli *grpcClient) FlushAsync() *ReqRes { req := types.ToRequestFlush() - res, err := cli.client.Flush(context.Background(), req.GetFlush()) + res, err := cli.client.Flush(context.Background(), req.GetFlush(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -116,7 +140,7 @@ func (cli *grpcClient) FlushAsync() *ReqRes { func (cli *grpcClient) InfoAsync() *ReqRes { req := types.ToRequestInfo() - res, err := cli.client.Info(context.Background(), req.GetInfo()) + res, err := cli.client.Info(context.Background(), req.GetInfo(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -125,7 +149,7 @@ func (cli *grpcClient) InfoAsync() *ReqRes { func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { req := types.ToRequestSetOption(key, value) - res, err := cli.client.SetOption(context.Background(), req.GetSetOption()) + res, err := cli.client.SetOption(context.Background(), req.GetSetOption(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -134,7 +158,7 @@ func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { func (cli *grpcClient) AppendTxAsync(tx []byte) *ReqRes { req := types.ToRequestAppendTx(tx) - res, err := cli.client.AppendTx(context.Background(), req.GetAppendTx()) + res, err := cli.client.AppendTx(context.Background(), req.GetAppendTx(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -143,7 +167,7 @@ func (cli *grpcClient) AppendTxAsync(tx []byte) *ReqRes { func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { req := types.ToRequestCheckTx(tx) - res, err := cli.client.CheckTx(context.Background(), req.GetCheckTx()) + res, err := cli.client.CheckTx(context.Background(), req.GetCheckTx(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -152,7 +176,7 @@ func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { req := types.ToRequestQuery(query) - res, err := cli.client.Query(context.Background(), req.GetQuery()) + res, err := cli.client.Query(context.Background(), req.GetQuery(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -161,7 +185,7 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { func (cli *grpcClient) CommitAsync() *ReqRes { req := types.ToRequestCommit() - res, err := cli.client.Commit(context.Background(), req.GetCommit()) + res, err := cli.client.Commit(context.Background(), req.GetCommit(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -170,7 +194,7 @@ func (cli *grpcClient) CommitAsync() *ReqRes { func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { req := types.ToRequestInitChain(validators) - res, err := cli.client.InitChain(context.Background(), req.GetInitChain()) + res, err := cli.client.InitChain(context.Background(), req.GetInitChain(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -179,7 +203,7 @@ func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { func (cli *grpcClient) BeginBlockAsync(height uint64) *ReqRes { req := types.ToRequestBeginBlock(height) - res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock()) + res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -188,7 +212,7 @@ func (cli *grpcClient) BeginBlockAsync(height uint64) *ReqRes { func (cli *grpcClient) EndBlockAsync(height uint64) *ReqRes { req := types.ToRequestEndBlock(height) - res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock()) + res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock(), grpc.FailFast(true)) if err != nil { cli.err = err } @@ -216,11 +240,35 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) return reqres } +func (cli *grpcClient) checkErrGetResult() *types.Result { + if cli.err != nil { + errorLog := cli.err.Error() + cli.StopForError(cli.err) + result := types.ErrInternalError + result.SetLog(errorLog) + return &result + } + return nil +} + +func (cli *grpcClient) checkGetErr() error { + if cli.err != nil { + err := errors.New(cli.err.Error()) + cli.StopForError(cli.err) + return err + } + return nil +} + //---------------------------------------- func (cli *grpcClient) EchoSync(msg string) (res types.Result) { - r := cli.EchoAsync(msg).Response.GetEcho() - return types.NewResultOK([]byte(r.Message), LOG) + reqres := cli.EchoAsync(msg) + if res := cli.checkErrGetResult(); res != nil { + return *res + } + resp := reqres.Response.GetEcho() + return types.NewResultOK([]byte(resp.Message), LOG) } func (cli *grpcClient) FlushSync() error { @@ -228,14 +276,18 @@ func (cli *grpcClient) FlushSync() error { } func (cli *grpcClient) InfoSync() (res types.Result) { - r := cli.InfoAsync().Response.GetInfo() - return types.NewResultOK([]byte(r.Info), LOG) + reqres := cli.InfoAsync() + if res := cli.checkErrGetResult(); res != nil { + return *res + } + resp := reqres.Response.GetInfo() + return types.NewResultOK([]byte(resp.Info), LOG) } func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { reqres := cli.SetOptionAsync(key, value) - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if res := cli.checkErrGetResult(); res != nil { + return *res } resp := reqres.Response.GetSetOption() return types.Result{Code: OK, Data: nil, Log: resp.Log} @@ -243,8 +295,8 @@ func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result func (cli *grpcClient) AppendTxSync(tx []byte) (res types.Result) { reqres := cli.AppendTxAsync(tx) - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if res := cli.checkErrGetResult(); res != nil { + return *res } resp := reqres.Response.GetAppendTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -252,8 +304,8 @@ func (cli *grpcClient) AppendTxSync(tx []byte) (res types.Result) { func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { reqres := cli.CheckTxAsync(tx) - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if res := cli.checkErrGetResult(); res != nil { + return *res } resp := reqres.Response.GetCheckTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -261,8 +313,8 @@ func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { func (cli *grpcClient) QuerySync(query []byte) (res types.Result) { reqres := cli.QueryAsync(query) - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if res := cli.checkErrGetResult(); res != nil { + return *res } resp := reqres.Response.GetQuery() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -270,8 +322,8 @@ func (cli *grpcClient) QuerySync(query []byte) (res types.Result) { func (cli *grpcClient) CommitSync() (res types.Result) { reqres := cli.CommitAsync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if res := cli.checkErrGetResult(); res != nil { + return *res } resp := reqres.Response.GetCommit() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -279,24 +331,24 @@ func (cli *grpcClient) CommitSync() (res types.Result) { func (cli *grpcClient) InitChainSync(validators []*types.Validator) (err error) { cli.InitChainAsync(validators) - if cli.err != nil { - return cli.err + if err := cli.checkGetErr(); err != nil { + return err } return nil } func (cli *grpcClient) BeginBlockSync(height uint64) (err error) { cli.BeginBlockAsync(height) - if cli.err != nil { - return cli.err + if err := cli.checkGetErr(); err != nil { + return err } return nil } func (cli *grpcClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { reqres := cli.EndBlockAsync(height) - if cli.err != nil { - return nil, cli.err + if err := cli.checkGetErr(); err != nil { + return nil, err } return reqres.Response.GetEndBlock().Diffs, nil } diff --git a/client/local_client.go b/client/local_client.go index 06db859b..eac5661b 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -1,11 +1,14 @@ package tmspcli import ( - types "github.com/tendermint/tmsp/types" "sync" + + . "github.com/tendermint/go-common" + types "github.com/tendermint/tmsp/types" ) type localClient struct { + *BaseService mtx *sync.Mutex types.Application Callback @@ -15,10 +18,12 @@ func NewLocalClient(mtx *sync.Mutex, app types.Application) *localClient { if mtx == nil { mtx = new(sync.Mutex) } - return &localClient{ + cli := &localClient{ mtx: mtx, Application: app, } + cli.BaseService = NewBaseService(log, "localClient", cli) + return cli } func (app *localClient) SetResponseCallback(cb Callback) { @@ -32,10 +37,6 @@ func (app *localClient) Error() error { return nil } -func (app *localClient) Stop() bool { - return true -} - func (app *localClient) FlushAsync() *ReqRes { // Do nothing return newLocalReqRes(types.ToRequestFlush(), nil) diff --git a/client/socket_client.go b/client/socket_client.go index ea1e7d6e..10f780bc 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -28,7 +28,6 @@ const flushThrottleMS = 20 // Don't wait longer than... // with concurrent callers. type socketClient struct { QuitService - sync.Mutex // [EB]: is this even used? reqQueue chan *ReqRes flushTimer *ThrottleTimer @@ -40,6 +39,7 @@ type socketClient struct { err error reqSent *list.List resCb func(*types.Request, *types.Response) // listens to all callbacks + } func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { @@ -53,49 +53,70 @@ func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { resCb: nil, } cli.QuitService = *NewQuitService(nil, "socketClient", cli) + _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err } func (cli *socketClient) OnStart() error { cli.QuitService.OnStart() + + var err error + var conn net.Conn RETRY_LOOP: for { - conn, err := Connect(cli.addr) + conn, err = Connect(cli.addr) if err != nil { if cli.mustConnect { return err } else { - log.Warn(Fmt("tmsp.socketClient failed to connect to %v. Retrying...\n", cli.addr)) + log.Warn(Fmt("tmsp.socketClient failed to connect to %v. Retrying...", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } } + cli.conn = conn + go cli.sendRequestsRoutine(conn) go cli.recvResponseRoutine(conn) - return err + + return nil } return nil // never happens } func (cli *socketClient) OnStop() { cli.QuitService.OnStop() + + cli.mtx.Lock() + defer cli.mtx.Unlock() if cli.conn != nil { cli.conn.Close() } + cli.flushQueue() } -func (cli *socketClient) flushQueue() { -LOOP: - for { - select { - case reqres := <-cli.reqQueue: - reqres.Done() - default: - break LOOP - } +// Stop the client and set the error +func (cli *socketClient) StopForError(err error) { + cli.mtx.Lock() + if !cli.IsRunning() { + return } + + if cli.err == nil { + cli.err = err + } + cli.mtx.Unlock() + + log.Warn(Fmt("Stopping tmsp.socketClient for error: %v", err.Error())) + cli.Stop() +} + +func (cli *socketClient) Error() error { + cli.mtx.Lock() + defer cli.mtx.Unlock() + return cli.err } // Set listener for all responses @@ -106,29 +127,10 @@ func (cli *socketClient) SetResponseCallback(resCb Callback) { cli.resCb = resCb } -func (cli *socketClient) StopForError(err error) { - if !cli.IsRunning() { - return - } - - cli.mtx.Lock() - log.Warn(Fmt("Stopping tmsp.socketClient for error: %v\n", err.Error())) - if cli.err == nil { - cli.err = err - } - cli.mtx.Unlock() - cli.Stop() -} - -func (cli *socketClient) Error() error { - cli.mtx.Lock() - defer cli.mtx.Unlock() - return cli.err -} - //---------------------------------------- func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { + w := bufio.NewWriter(conn) for { select { @@ -144,14 +146,14 @@ func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { cli.willSendReq(reqres) err := types.WriteMessage(reqres.Request, w) if err != nil { - cli.StopForError(err) + cli.StopForError(fmt.Errorf("Error writing msg: %v", err)) return } // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) if _, ok := reqres.Request.Value.(*types.Request_Flush); ok { err = w.Flush() if err != nil { - cli.StopForError(err) + cli.StopForError(fmt.Errorf("Error flushing writer: %v", err)) return } } @@ -160,6 +162,7 @@ func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { } func (cli *socketClient) recvResponseRoutine(conn net.Conn) { + r := bufio.NewReader(conn) // Buffer reads for { var res = &types.Response{} @@ -172,11 +175,13 @@ func (cli *socketClient) recvResponseRoutine(conn net.Conn) { case *types.Response_Exception: // XXX After setting cli.err, release waiters (e.g. reqres.Done()) cli.StopForError(errors.New(r.Exception.Error)) + return default: // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) err := cli.didRecvResponse(res) if err != nil { cli.StopForError(err) + return } } } @@ -280,9 +285,8 @@ func (cli *socketClient) EchoSync(msg string) (res types.Result) { func (cli *socketClient) FlushSync() error { reqRes := cli.queueRequest(types.ToRequestFlush()) - if reqRes == nil { - return fmt.Errorf("Remote app is not running") - + if cli.err != nil { + return types.ErrInternalError.SetLog(cli.err.Error()) } reqRes.Wait() // NOTE: if we don't flush the queue, its possible to get stuck here return cli.err @@ -378,10 +382,6 @@ func (cli *socketClient) EndBlockSync(height uint64) (validators []*types.Valida //---------------------------------------- func (cli *socketClient) queueRequest(req *types.Request) *ReqRes { - if !cli.IsRunning() { - return nil - } - reqres := NewReqRes(req) // TODO: set cli.err if reqQueue times out @@ -398,6 +398,18 @@ func (cli *socketClient) queueRequest(req *types.Request) *ReqRes { return reqres } +func (cli *socketClient) flushQueue() { +LOOP: + for { + select { + case reqres := <-cli.reqQueue: + reqres.Done() + default: + break LOOP + } + } +} + //---------------------------------------- func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go deleted file mode 100644 index c5ac2d27..00000000 --- a/example/dummy/dummy_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package dummy - -import ( - "reflect" - "testing" - "time" - - . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" -) - -func TestStream(t *testing.T) { - - numAppendTxs := 200000 - - // Start the listener - server, err := server.NewSocketServer("unix://test.sock", NewDummyApplication()) - if err != nil { - Exit(err.Error()) - } - defer server.Stop() - - // Connect to the socket - conn, err := Connect("unix://test.sock") - if err != nil { - Exit(err.Error()) - } - - // Read response data - done := make(chan struct{}) - go func() { - counter := 0 - for { - - var res = &types.Response{} - err := types.ReadMessage(conn, res) - if err != nil { - Exit(err.Error()) - } - - // Process response - switch r := res.Value.(type) { - case *types.Response_AppendTx: - counter += 1 - if r.AppendTx.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", r.AppendTx.Code) - } - if counter > numAppendTxs { - t.Fatal("Too many AppendTx responses") - } - t.Log("response", counter) - if counter == numAppendTxs { - go func() { - time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow - close(done) - }() - } - case *types.Response_Flush: - // ignore - default: - t.Error("Unexpected response type", reflect.TypeOf(res.Value)) - } - } - }() - - // Write requests - for counter := 0; counter < numAppendTxs; counter++ { - // Send request - var req = types.ToRequestAppendTx([]byte("test")) - err := types.WriteMessage(req, conn) - if err != nil { - t.Fatal(err.Error()) - } - - // Sometimes send flush messages - if counter%123 == 0 { - t.Log("flush") - err := types.WriteMessage(types.ToRequestFlush(), conn) - if err != nil { - t.Fatal(err.Error()) - } - } - } - - // Send final flush message - err = types.WriteMessage(types.ToRequestFlush(), conn) - if err != nil { - t.Fatal(err.Error()) - } - - <-done -} diff --git a/example/example_test.go b/example/example_test.go new file mode 100644 index 00000000..fc9066d8 --- /dev/null +++ b/example/example_test.go @@ -0,0 +1,151 @@ +package nilapp + +import ( + "fmt" + "net" + "reflect" + "testing" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/client" + "github.com/tendermint/tmsp/example/dummy" + nilapp "github.com/tendermint/tmsp/example/nil" + "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" +) + +func TestDummy(t *testing.T) { + fmt.Println("### Testing Dummy") + testStream(t, dummy.NewDummyApplication()) +} + +func TestNilApp(t *testing.T) { + fmt.Println("### Testing NilApp") + testStream(t, nilapp.NewNilApplication()) +} + +func TestGRPC(t *testing.T) { + fmt.Println("### Testing GRPC") + testGRPCSync(t, types.NewGRPCApplication(nilapp.NewNilApplication())) +} + +func testStream(t *testing.T, app types.Application) { + + numAppendTxs := 200000 + + // Start the listener + server, err := server.NewSocketServer("unix://test.sock", app) + if err != nil { + Exit(Fmt("Error starting socket server: %v", err.Error())) + } + defer server.Stop() + + // Connect to the socket + client, err := tmspcli.NewSocketClient("unix://test.sock", false) + if err != nil { + Exit(Fmt("Error starting socket client: %v", err.Error())) + } + client.Start() + defer client.Stop() + + done := make(chan struct{}) + counter := 0 + client.SetResponseCallback(func(req *types.Request, res *types.Response) { + // Process response + switch r := res.Value.(type) { + case *types.Response_AppendTx: + counter += 1 + if r.AppendTx.Code != types.CodeType_OK { + t.Error("AppendTx failed with ret_code", r.AppendTx.Code) + } + if counter > numAppendTxs { + t.Fatalf("Too many AppendTx responses. Got %d, expected %d", counter, numAppendTxs) + } + if counter == numAppendTxs { + go func() { + time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow + close(done) + }() + return + } + case *types.Response_Flush: + // ignore + default: + t.Error("Unexpected response type", reflect.TypeOf(res.Value)) + } + }) + + // Write requests + for counter := 0; counter < numAppendTxs; counter++ { + // Send request + reqRes := client.AppendTxAsync([]byte("test")) + _ = reqRes + // check err ? + + // Sometimes send flush messages + if counter%123 == 0 { + client.FlushAsync() + // check err ? + } + } + + // Send final flush message + client.FlushAsync() + + <-done +} + +//------------------------- +// test grpc + +func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { + return Connect(addr) +} + +func testGRPCSync(t *testing.T, app *types.GRPCApplication) { + + numAppendTxs := 2000 + + // Start the listener + server, err := server.NewGRPCServer("unix://test.sock", app) + if err != nil { + Exit(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())) + } + defer conn.Close() + + client := types.NewTMSPApplicationClient(conn) + + // Write requests + for counter := 0; counter < numAppendTxs; counter++ { + // Send request + response, err := client.AppendTx(context.Background(), &types.RequestAppendTx{[]byte("test")}) + if err != nil { + t.Fatalf("Error in GRPC AppendTx: %v", err.Error()) + } + counter += 1 + if response.Code != types.CodeType_OK { + t.Error("AppendTx failed with ret_code", response.Code) + } + if counter > numAppendTxs { + t.Fatal("Too many AppendTx responses") + } + t.Log("response", counter) + if counter == numAppendTxs { + go func() { + time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow + }() + } + + } +} diff --git a/example/nil/nil_test.go b/example/nil/nil_test.go deleted file mode 100644 index ed7a36dd..00000000 --- a/example/nil/nil_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package nilapp - -import ( - "net" - "reflect" - "testing" - "time" - - "golang.org/x/net/context" - "google.golang.org/grpc" - - . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" -) - -func TestStream(t *testing.T) { - - numAppendTxs := 200000 - - // Start the listener - server, err := server.NewSocketServer("unix://test.sock", NewNilApplication()) - if err != nil { - Exit(err.Error()) - } - defer server.Stop() - - // Connect to the socket - conn, err := Connect("unix://test.sock") - if err != nil { - Exit(err.Error()) - } - - // Read response data - done := make(chan struct{}) - go func() { - counter := 0 - for { - - var res = &types.Response{} - err := types.ReadMessage(conn, res) - if err != nil { - Exit(err.Error()) - } - - // Process response - switch r := res.Value.(type) { - case *types.Response_AppendTx: - counter += 1 - if r.AppendTx.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", r.AppendTx.Code) - } - if counter > numAppendTxs { - t.Fatal("Too many AppendTx responses") - } - t.Log("response", counter) - if counter == numAppendTxs { - go func() { - time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow - close(done) - }() - } - case *types.Response_Flush: - // ignore - default: - t.Error("Unexpected response type", reflect.TypeOf(res.Value)) - } - } - }() - - // Write requests - for counter := 0; counter < numAppendTxs; counter++ { - // Send request - var req = types.ToRequestAppendTx([]byte("test")) - err := types.WriteMessage(req, conn) - if err != nil { - t.Fatal(err.Error()) - } - - // Sometimes send flush messages - if counter%123 == 0 { - t.Log("flush") - err := types.WriteMessage(types.ToRequestFlush(), conn) - if err != nil { - t.Fatal(err.Error()) - } - } - } - - // Send final flush message - err = types.WriteMessage(types.ToRequestFlush(), conn) - if err != nil { - t.Fatal(err.Error()) - } - - <-done -} - -//------------------------- -// test grpc - -func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { - return Connect(addr) -} - -func TestGRPCSync(t *testing.T) { - - numAppendTxs := 2000 - - // Start the listener - server, err := server.NewGRPCServer("unix://test.sock", types.NewGRPCApplication(NewNilApplication())) - if err != nil { - Exit(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(err.Error()) - } - defer conn.Close() - - client := types.NewTMSPApplicationClient(conn) - - // Write requests - for counter := 0; counter < numAppendTxs; counter++ { - // Send request - response, err := client.AppendTx(context.Background(), &types.RequestAppendTx{[]byte("test")}) - if err != nil { - t.Fatal(err.Error()) - } - counter += 1 - if response.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", response.Code) - } - if counter > numAppendTxs { - t.Fatal("Too many AppendTx responses") - } - t.Log("response", counter) - if counter == numAppendTxs { - go func() { - time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow - }() - } - - } -} diff --git a/server/grpc_server.go b/server/grpc_server.go index 3a21e3fb..02f6fa3f 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -18,6 +18,7 @@ type GRPCServer struct { proto string addr string listener net.Listener + server *grpc.Server app types.TMSPApplicationServer } @@ -43,13 +44,13 @@ func (s *GRPCServer) OnStart() error { return err } s.listener = ln - grpcServer := grpc.NewServer() - types.RegisterTMSPApplicationServer(grpcServer, s.app) - go grpcServer.Serve(ln) + s.server = grpc.NewServer() + types.RegisterTMSPApplicationServer(s.server, s.app) + go s.server.Serve(s.listener) return nil } func (s *GRPCServer) OnStop() { s.QuitService.OnStop() - s.listener.Close() + s.server.Stop() } diff --git a/server/log.go b/server/log.go new file mode 100644 index 00000000..8ac4092e --- /dev/null +++ b/server/log.go @@ -0,0 +1,7 @@ +package server + +import ( + "github.com/tendermint/go-logger" +) + +var log = logger.New("module", "tmsp-server") diff --git a/server/socket_server.go b/server/socket_server.go index 7969974e..8e837d8f 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -21,6 +21,10 @@ type SocketServer struct { addr string listener net.Listener + connsMtx sync.Mutex + conns map[int]net.Conn + nextConnID int + appMtx sync.Mutex app types.Application } @@ -33,6 +37,7 @@ func NewSocketServer(protoAddr string, app types.Application) (Service, error) { addr: addr, listener: nil, app: app, + conns: make(map[int]net.Conn), } s.QuitService = *NewQuitService(nil, "TMSPServer", s) _, err := s.Start() // Just start it @@ -53,6 +58,33 @@ func (s *SocketServer) OnStart() error { func (s *SocketServer) OnStop() { s.QuitService.OnStop() s.listener.Close() + + s.connsMtx.Lock() + for id, conn := range s.conns { + delete(s.conns, id) + conn.Close() + } + s.connsMtx.Unlock() +} + +func (s *SocketServer) addConn(conn net.Conn) int { + s.connsMtx.Lock() + defer s.connsMtx.Unlock() + + connID := s.nextConnID + s.nextConnID += 1 + s.conns[connID] = conn + + return connID +} + +// deletes conn even if close errs +func (s *SocketServer) rmConn(connID int, conn net.Conn) error { + s.connsMtx.Lock() + defer s.connsMtx.Unlock() + + delete(s.conns, connID) + return conn.Close() } func (s *SocketServer) acceptConnectionsRoutine() { @@ -62,7 +94,7 @@ func (s *SocketServer) acceptConnectionsRoutine() { // semaphore <- struct{}{} // Accept a connection - fmt.Println("Waiting for new connection...") + log.Notice("Waiting for new connection...") conn, err := s.listener.Accept() if err != nil { if !s.IsRunning() { @@ -70,9 +102,11 @@ func (s *SocketServer) acceptConnectionsRoutine() { } Exit("Failed to accept connection: " + err.Error()) } else { - fmt.Println("Accepted a new connection") + log.Notice("Accepted a new connection") } + connID := s.addConn(conn) + closeConn := make(chan error, 2) // Push to signal connection closed responses := make(chan *types.Response, 1000) // A channel to buffer responses @@ -84,16 +118,20 @@ func (s *SocketServer) acceptConnectionsRoutine() { go func() { // Wait until signal to close connection errClose := <-closeConn - if errClose != nil { - fmt.Printf("Connection error: %v\n", errClose) + if err == io.EOF { + log.Warn("Connection was closed by client") + return // is this correct? the conn is closed? + } else if errClose != nil { + log.Warn("Connection error", "error", errClose) } else { - fmt.Println("Connection was closed.") + // never happens + log.Warn("Connection was closed.") } // Close the connection - err := conn.Close() + err := s.rmConn(connID, conn) if err != nil { - fmt.Printf("Error in closing connection: %v\n", err) + log.Warn("Error in closing connection", "error", err) } // <-semaphore @@ -111,9 +149,9 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn net.Conn, respo err := types.ReadMessage(bufReader, req) if err != nil { if err == io.EOF { - closeConn <- fmt.Errorf("Connection closed by client") + closeConn <- err } else { - closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) + closeConn <- fmt.Errorf("Error reading message: %v", err.Error()) } return } @@ -176,13 +214,13 @@ func (s *SocketServer) handleResponses(closeConn chan error, responses <-chan *t var res = <-responses err := types.WriteMessage(res, bufWriter) if err != nil { - closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) + closeConn <- fmt.Errorf("Error writing message: %v", err.Error()) return } if _, ok := res.Value.(*types.Response_Flush); ok { err = bufWriter.Flush() if err != nil { - closeConn <- fmt.Errorf("Error in handleValue: %v", err.Error()) + closeConn <- fmt.Errorf("Error flushing write buffer: %v", err.Error()) return } } diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index f8920958..adb3e4bd 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -9,7 +9,7 @@ function testExample() { $APP &> /dev/null & sleep 2 tmsp-cli --verbose batch < $INPUT > "${INPUT}.out.new" - killall "$APP" > /dev/null + killall "$APP" &> /dev/null pre=`shasum < "${INPUT}.out"` post=`shasum < "${INPUT}.out.new"` From 83920a1c373d4e9c91b4f2d0f8ba3a40b8cdf5b0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 17 Aug 2016 23:27:49 -0400 Subject: [PATCH 127/545] fixes from review --- client/grpc_client.go | 38 +++++++++++++++++--------------------- client/local_client.go | 4 ++-- server/socket_server.go | 1 - 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 3e44dcc1..916189b5 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -240,22 +240,18 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) return reqres } -func (cli *grpcClient) checkErrGetResult() *types.Result { +func (cli *grpcClient) checkErrGetResult() types.Result { if cli.err != nil { - errorLog := cli.err.Error() cli.StopForError(cli.err) - result := types.ErrInternalError - result.SetLog(errorLog) - return &result + return types.ErrInternalError.SetLog(cli.err.Error()) } return nil } func (cli *grpcClient) checkGetErr() error { if cli.err != nil { - err := errors.New(cli.err.Error()) cli.StopForError(cli.err) - return err + return cli.err } return nil } @@ -264,8 +260,8 @@ func (cli *grpcClient) checkGetErr() error { func (cli *grpcClient) EchoSync(msg string) (res types.Result) { reqres := cli.EchoAsync(msg) - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetEcho() return types.NewResultOK([]byte(resp.Message), LOG) @@ -277,8 +273,8 @@ func (cli *grpcClient) FlushSync() error { func (cli *grpcClient) InfoSync() (res types.Result) { reqres := cli.InfoAsync() - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetInfo() return types.NewResultOK([]byte(resp.Info), LOG) @@ -286,8 +282,8 @@ func (cli *grpcClient) InfoSync() (res types.Result) { func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { reqres := cli.SetOptionAsync(key, value) - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetSetOption() return types.Result{Code: OK, Data: nil, Log: resp.Log} @@ -295,8 +291,8 @@ func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result func (cli *grpcClient) AppendTxSync(tx []byte) (res types.Result) { reqres := cli.AppendTxAsync(tx) - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetAppendTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -304,8 +300,8 @@ func (cli *grpcClient) AppendTxSync(tx []byte) (res types.Result) { func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { reqres := cli.CheckTxAsync(tx) - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetCheckTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -313,8 +309,8 @@ func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { func (cli *grpcClient) QuerySync(query []byte) (res types.Result) { reqres := cli.QueryAsync(query) - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetQuery() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -322,8 +318,8 @@ func (cli *grpcClient) QuerySync(query []byte) (res types.Result) { func (cli *grpcClient) CommitSync() (res types.Result) { reqres := cli.CommitAsync() - if res := cli.checkErrGetResult(); res != nil { - return *res + if res := cli.checkErrGetResult(); res.IsErr() { + return res } resp := reqres.Response.GetCommit() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} diff --git a/client/local_client.go b/client/local_client.go index eac5661b..ce17f6c0 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -8,7 +8,7 @@ import ( ) type localClient struct { - *BaseService + 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 = *NewBaseService(log, "localClient", cli) return cli } diff --git a/server/socket_server.go b/server/socket_server.go index 8e837d8f..ff01a908 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -120,7 +120,6 @@ func (s *SocketServer) acceptConnectionsRoutine() { errClose := <-closeConn if err == io.EOF { log.Warn("Connection was closed by client") - return // is this correct? the conn is closed? } else if errClose != nil { log.Warn("Connection error", "error", errClose) } else { From 3329868a1d19c8f7c67088a275fa6c877d3743ba Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 24 Aug 2016 02:11:31 -0400 Subject: [PATCH 128/545] grpc fix --- client/grpc_client.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 916189b5..7d43ae6e 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -1,7 +1,6 @@ package tmspcli import ( - "errors" "net" "sync" "time" @@ -245,7 +244,7 @@ func (cli *grpcClient) checkErrGetResult() types.Result { cli.StopForError(cli.err) return types.ErrInternalError.SetLog(cli.err.Error()) } - return nil + return types.Result{} } func (cli *grpcClient) checkGetErr() error { From 22894d2f605e1a8634c74196d505ca273b2cf6e8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 24 Aug 2016 20:13:17 -0400 Subject: [PATCH 129/545] fix tests --- example/example.go | 3 +++ example/example_test.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 example/example.go diff --git a/example/example.go b/example/example.go new file mode 100644 index 00000000..ee491c1b --- /dev/null +++ b/example/example.go @@ -0,0 +1,3 @@ +package example + +// so the go tool doesn't return errors about no buildable go files ... diff --git a/example/example_test.go b/example/example_test.go index fc9066d8..3293be55 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -1,4 +1,4 @@ -package nilapp +package example import ( "fmt" From 42e4f4693c3c25f2022395027bb9136ed0a0bc4d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 8 Sep 2016 21:41:35 -0400 Subject: [PATCH 130/545] client: safe error handling --- client/grpc_client.go | 48 +++++++++++++++-------------------------- client/socket_client.go | 46 +++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 7d43ae6e..771302c1 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -123,7 +123,7 @@ func (cli *grpcClient) EchoAsync(msg string) *ReqRes { req := types.ToRequestEcho(msg) res, err := cli.client.Echo(context.Background(), req.GetEcho(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_Echo{res}}) } @@ -132,7 +132,7 @@ func (cli *grpcClient) FlushAsync() *ReqRes { req := types.ToRequestFlush() res, err := cli.client.Flush(context.Background(), req.GetFlush(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_Flush{res}}) } @@ -141,7 +141,7 @@ func (cli *grpcClient) InfoAsync() *ReqRes { req := types.ToRequestInfo() res, err := cli.client.Info(context.Background(), req.GetInfo(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_Info{res}}) } @@ -150,7 +150,7 @@ func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { req := types.ToRequestSetOption(key, value) res, err := cli.client.SetOption(context.Background(), req.GetSetOption(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_SetOption{res}}) } @@ -159,7 +159,7 @@ func (cli *grpcClient) AppendTxAsync(tx []byte) *ReqRes { req := types.ToRequestAppendTx(tx) res, err := cli.client.AppendTx(context.Background(), req.GetAppendTx(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_AppendTx{res}}) } @@ -168,7 +168,7 @@ func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { req := types.ToRequestCheckTx(tx) res, err := cli.client.CheckTx(context.Background(), req.GetCheckTx(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_CheckTx{res}}) } @@ -177,7 +177,7 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { req := types.ToRequestQuery(query) res, err := cli.client.Query(context.Background(), req.GetQuery(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}}) } @@ -186,7 +186,7 @@ func (cli *grpcClient) CommitAsync() *ReqRes { req := types.ToRequestCommit() res, err := cli.client.Commit(context.Background(), req.GetCommit(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_Commit{res}}) } @@ -195,7 +195,7 @@ func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { req := types.ToRequestInitChain(validators) res, err := cli.client.InitChain(context.Background(), req.GetInitChain(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_InitChain{res}}) } @@ -204,7 +204,7 @@ func (cli *grpcClient) BeginBlockAsync(height uint64) *ReqRes { req := types.ToRequestBeginBlock(height) res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_BeginBlock{res}}) } @@ -213,7 +213,7 @@ func (cli *grpcClient) EndBlockAsync(height uint64) *ReqRes { req := types.ToRequestEndBlock(height) res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock(), grpc.FailFast(true)) if err != nil { - cli.err = err + cli.StopForError(err) } return cli.finishAsyncCall(req, &types.Response{&types.Response_EndBlock{res}}) } @@ -240,21 +240,13 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) } func (cli *grpcClient) checkErrGetResult() types.Result { - if cli.err != nil { - cli.StopForError(cli.err) - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + // StopForError should already have been called if error is set + return types.ErrInternalError.SetLog(err.Error()) } return types.Result{} } -func (cli *grpcClient) checkGetErr() error { - if cli.err != nil { - cli.StopForError(cli.err) - return cli.err - } - return nil -} - //---------------------------------------- func (cli *grpcClient) EchoSync(msg string) (res types.Result) { @@ -326,23 +318,17 @@ func (cli *grpcClient) CommitSync() (res types.Result) { func (cli *grpcClient) InitChainSync(validators []*types.Validator) (err error) { cli.InitChainAsync(validators) - if err := cli.checkGetErr(); err != nil { - return err - } - return nil + return cli.Error() } func (cli *grpcClient) BeginBlockSync(height uint64) (err error) { cli.BeginBlockAsync(height) - if err := cli.checkGetErr(); err != nil { - return err - } - return nil + return cli.Error() } func (cli *grpcClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { reqres := cli.EndBlockAsync(height) - if err := cli.checkGetErr(); err != nil { + if err := cli.Error(); err != nil { return nil, err } return reqres.Response.GetEndBlock().Diffs, nil diff --git a/client/socket_client.go b/client/socket_client.go index 10f780bc..27e74787 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -276,8 +276,8 @@ func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { func (cli *socketClient) EchoSync(msg string) (res types.Result) { reqres := cli.queueRequest(types.ToRequestEcho(msg)) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetEcho() return types.Result{Code: OK, Data: []byte(resp.Message), Log: LOG} @@ -285,18 +285,18 @@ func (cli *socketClient) EchoSync(msg string) (res types.Result) { func (cli *socketClient) FlushSync() error { reqRes := cli.queueRequest(types.ToRequestFlush()) - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } reqRes.Wait() // NOTE: if we don't flush the queue, its possible to get stuck here - return cli.err + return cli.Error() } func (cli *socketClient) InfoSync() (res types.Result) { reqres := cli.queueRequest(types.ToRequestInfo()) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetInfo() return types.Result{Code: OK, Data: []byte(resp.Info), Log: LOG} @@ -305,8 +305,8 @@ func (cli *socketClient) InfoSync() (res types.Result) { func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { reqres := cli.queueRequest(types.ToRequestSetOption(key, value)) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetSetOption() return types.Result{Code: OK, Data: nil, Log: resp.Log} @@ -315,8 +315,8 @@ func (cli *socketClient) SetOptionSync(key string, value string) (res types.Resu func (cli *socketClient) AppendTxSync(tx []byte) (res types.Result) { reqres := cli.queueRequest(types.ToRequestAppendTx(tx)) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetAppendTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -325,8 +325,8 @@ func (cli *socketClient) AppendTxSync(tx []byte) (res types.Result) { func (cli *socketClient) CheckTxSync(tx []byte) (res types.Result) { reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetCheckTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -335,8 +335,8 @@ func (cli *socketClient) CheckTxSync(tx []byte) (res types.Result) { func (cli *socketClient) QuerySync(query []byte) (res types.Result) { reqres := cli.queueRequest(types.ToRequestQuery(query)) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetQuery() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -345,8 +345,8 @@ func (cli *socketClient) QuerySync(query []byte) (res types.Result) { func (cli *socketClient) CommitSync() (res types.Result) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() - if cli.err != nil { - return types.ErrInternalError.SetLog(cli.err.Error()) + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) } resp := reqres.Response.GetCommit() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} @@ -355,8 +355,8 @@ func (cli *socketClient) CommitSync() (res types.Result) { func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error) { cli.queueRequest(types.ToRequestInitChain(validators)) cli.FlushSync() - if cli.err != nil { - return cli.err + if err := cli.Error(); err != nil { + return err } return nil } @@ -364,8 +364,8 @@ func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error func (cli *socketClient) BeginBlockSync(height uint64) (err error) { cli.queueRequest(types.ToRequestBeginBlock(height)) cli.FlushSync() - if cli.err != nil { - return cli.err + if err := cli.Error(); err != nil { + return err } return nil } @@ -373,8 +373,8 @@ func (cli *socketClient) BeginBlockSync(height uint64) (err error) { func (cli *socketClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { reqres := cli.queueRequest(types.ToRequestEndBlock(height)) cli.FlushSync() - if cli.err != nil { - return nil, cli.err + if err := cli.Error(); err != nil { + return nil, err } return reqres.Response.GetEndBlock().Diffs, nil } From ead192adbbbf85ac581cf775b18ae70d59f86457 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 10 Sep 2016 20:10:59 -0400 Subject: [PATCH 131/545] test: more verbosity --- tests/test_cli/test.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index adb3e4bd..00446c45 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -9,13 +9,17 @@ function testExample() { $APP &> /dev/null & sleep 2 tmsp-cli --verbose batch < $INPUT > "${INPUT}.out.new" - killall "$APP" &> /dev/null + killall "$APP" pre=`shasum < "${INPUT}.out"` post=`shasum < "${INPUT}.out.new"` if [[ "$pre" != "$post" ]]; then echo "You broke the tutorial" + echo "Got:" + cat "${INPUT}.out.new" + echo "Expected:" + cat "${INPUT}.out" exit 1 fi From dcd4ab5cd2415519a129da23230f0126ff162092 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 12 Sep 2016 10:21:20 +0200 Subject: [PATCH 132/545] Make console more robust to typos --- cmd/tmsp-cli/tmsp-cli.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 964dbe69..0c2e1c4f 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -123,6 +123,14 @@ func before(c *cli.Context) error { return nil } +// badCmd is called when we invoke with an invalid first argument (just for console for now) +func badCmd(c *cli.Context, cmd string) { + fmt.Println("Unknown command:", cmd) + fmt.Println("Please try one of the following:") + fmt.Println("") + cli.DefaultAppComplete(c) +} + //-------------------------------------------------------------------------------- func cmdBatch(app *cli.App, c *cli.Context) error { @@ -149,6 +157,8 @@ func cmdBatch(app *cli.App, c *cli.Context) error { } func cmdConsole(app *cli.App, c *cli.Context) error { + // don't hard exit on mistyped commands (eg. check vs check_tx) + app.CommandNotFound = badCmd for { fmt.Printf("\n> ") bufReader := bufio.NewReader(os.Stdin) @@ -162,10 +172,10 @@ func cmdConsole(app *cli.App, c *cli.Context) error { args := []string{"tmsp-cli"} args = append(args, strings.Split(string(line), " ")...) if err := app.Run(args); err != nil { - return err + // if the command doesn't succeed, inform the user without exiting + fmt.Println("Error:", err.Error()) } } - return nil } // Have the application echo a message From 538862321aed1120d6e5e7fbd8e0a23b00bbc4c3 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 12 Sep 2016 12:23:36 -0400 Subject: [PATCH 133/545] bump version --- cmd/tmsp-cli/tmsp-cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 0c2e1c4f..c80866e3 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -22,7 +22,7 @@ func main() { app := cli.NewApp() app.Name = "tmsp-cli" app.Usage = "tmsp-cli [command] [args...]" - app.Version = "0.2" + app.Version = "0.2.1" // better error handling in console app.Flags = []cli.Flag{ cli.StringFlag{ Name: "address", From 5d3eb0328a615ba55b580ce871033e605aa8b97d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 28 Sep 2016 09:57:04 +0900 Subject: [PATCH 134/545] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fc5c7bb2..7f38a8a1 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ For more information on TMSP, motivations, and tutorials, please visit [our blog Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen * [js-tmsp](https://github.com/tendermint/js-tmsp) +* [jTMSP](https://github.com/jTMSP/) for Java ## Contents From ab98bffbb1a9d8e1df9fb673406f892ac7f8a414 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 20 Oct 2016 21:57:33 -0400 Subject: [PATCH 135/545] codegangsta => urfave --- cmd/tmsp-cli/tmsp-cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index c80866e3..08424129 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -9,10 +9,10 @@ import ( "os" "strings" - "github.com/codegangsta/cli" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/client" "github.com/tendermint/tmsp/types" + "github.com/urfave/cli" ) // client is a global variable so it can be reused by the console From 1f9142873ba7c2099326ef7521bddf4e96ab6b4f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 10 Nov 2016 01:12:29 +0000 Subject: [PATCH 136/545] add glide --- Makefile | 14 ++++++-- circle.yml | 8 ++--- glide.lock | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ glide.yaml | 16 +++++++++ 4 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 glide.lock create mode 100644 glide.yaml diff --git a/Makefile b/Makefile index b47dc0e2..e5a7f043 100644 --- a/Makefile +++ b/Makefile @@ -2,15 +2,23 @@ all: protoc test install +NOVENDOR = go list github.com/tendermint/tmsp/... | grep -v /vendor/ + protoc: protoc --go_out=. types/*.proto -install: get_deps +install: go install github.com/tendermint/tmsp/cmd/... test: - go test github.com/tendermint/tmsp/... + go test `${NOVENDOR}` bash tests/test.sh +test_integrations: get_vendor_deps install test + get_deps: - go get -d github.com/tendermint/tmsp/... + go get -d `${NOVENDOR}` + +get_vendor_deps: + go get github.com/Masterminds/glide + glide install diff --git a/circle.yml b/circle.yml index 33e50dc7..6355bc04 100644 --- a/circle.yml +++ b/circle.yml @@ -2,6 +2,7 @@ machine: environment: GOPATH: /home/ubuntu/.go_workspace REPO: $GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME + GO15VENDOREXPERIMENT: 1 hosts: circlehost: 127.0.0.1 localhost: 127.0.0.1 @@ -14,10 +15,7 @@ checkout: # - git submodule sync # - git submodule update --init # use submodules -dependencies: - override: - - "cd $REPO && go get -t ./..." - test: override: - - "cd $REPO && make test" + - "go version" + - "cd $REPO && make test_integrations" diff --git a/glide.lock b/glide.lock new file mode 100644 index 00000000..2b3ec516 --- /dev/null +++ b/glide.lock @@ -0,0 +1,98 @@ +hash: 65769cd1c6d94a9733e9109e1bd7004f31b8df60c6d2cd47d9d8aecb9a94ffc2 +updated: 2016-11-10T00:51:46.9785435Z +imports: +- name: github.com/btcsuite/btcd + version: df33d4340e921eb9195225c67eed8b65071d40a5 + subpackages: + - btcec +- name: github.com/btcsuite/fastsha256 + version: 637e656429416087660c84436a2a035d69d54e2e +- name: github.com/go-stack/stack + version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 +- name: github.com/golang/protobuf + version: 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a + subpackages: + - proto +- name: github.com/golang/snappy + version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 +- name: github.com/mattn/go-colorable + version: d228849504861217f796da67fae4f6e347643f15 +- name: github.com/mattn/go-isatty + version: 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8 +- name: github.com/syndtr/goleveldb + version: 6b4daa5362b502898ddf367c5c11deb9e7a5c727 + subpackages: + - leveldb + - leveldb/errors + - leveldb/opt + - leveldb/cache + - leveldb/comparer + - leveldb/filter + - leveldb/iterator + - leveldb/journal + - leveldb/memdb + - leveldb/storage + - leveldb/table + - leveldb/util +- name: github.com/tendermint/ed25519 + version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + subpackages: + - extra25519 + - edwards25519 +- name: github.com/tendermint/go-common + version: 1c62bb6dadc6269aeecad5f9e7b153d950a54362 +- name: github.com/tendermint/go-crypto + version: 4b11d62bdb324027ea01554e5767b71174680ba0 +- name: github.com/tendermint/go-db + version: 31fdd21c7eaeed53e0ea7ca597fb1e960e2988a5 +- name: github.com/tendermint/go-logger + version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 +- name: github.com/tendermint/go-merkle + version: 05042c6ab9cad51d12e4cecf717ae68e3b1409a8 +- name: github.com/tendermint/go-process + version: ba01cfbb58d446673beff17e72883cb49c835fb9 +- name: github.com/tendermint/go-wire + version: 287d8caeae91d21686340f5f87170560531681e6 +- name: github.com/tendermint/log15 + version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 + subpackages: + - term +- name: github.com/urfave/cli + version: d86a009f5e13f83df65d0d6cee9a2e3f1445f0da +- name: golang.org/x/crypto + version: 9477e0b78b9ac3d0b03822fd95422e2fe07627cd + subpackages: + - ripemd160 + - nacl/secretbox + - openpgp/armor + - poly1305 + - salsa20/salsa + - openpgp/errors +- name: golang.org/x/net + version: 9ef22118a4b25863aa94546daffbc0a18feaafb3 + subpackages: + - context + - http2 + - trace + - http2/hpack + - idna + - lex/httplex + - internal/timeseries +- name: golang.org/x/sys + version: 9a2e24c3733eddc63871eda99f253e2db29bd3b9 + subpackages: + - unix +- name: google.golang.org/grpc + version: 28707e14b1d2b2f5da81474dea2790d71e526987 + subpackages: + - codes + - credentials + - grpclog + - internal + - metadata + - naming + - stats + - tap + - transport + - peer +devImports: [] diff --git a/glide.yaml b/glide.yaml new file mode 100644 index 00000000..f39ae801 --- /dev/null +++ b/glide.yaml @@ -0,0 +1,16 @@ +package: github.com/tendermint/tmsp +import: +- package: github.com/golang/protobuf + subpackages: + - proto +- package: github.com/tendermint/go-common +- package: github.com/tendermint/go-crypto +- package: github.com/tendermint/go-logger +- package: github.com/tendermint/go-merkle +- package: github.com/tendermint/go-process +- package: github.com/tendermint/go-wire +- package: github.com/urfave/cli +- package: golang.org/x/net + subpackages: + - context +- package: google.golang.org/grpc From 8374785c1db85ed6013fb8485088e85341ac6d67 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 15 Nov 2016 14:11:01 -0500 Subject: [PATCH 137/545] update glide, grpc to v4 --- Makefile | 2 +- README.md | 2 +- glide.lock | 34 ++--- types/types.pb.go | 369 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 295 insertions(+), 112 deletions(-) diff --git a/Makefile b/Makefile index e5a7f043..b00c5a67 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ all: protoc test install NOVENDOR = go list github.com/tendermint/tmsp/... | grep -v /vendor/ protoc: - protoc --go_out=. types/*.proto + protoc --go_out=plugins=grpc:. types/*.proto install: go install github.com/tendermint/tmsp/cmd/... diff --git a/README.md b/README.md index 7f38a8a1..d034a6b1 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ This repository holds a number of important pieces: - `types/types.proto` - the protobuf file defining TMSP message types, and the optional grpc interface. - - run `protoc --go_out=plugins=grpc:. types.proto` in the `types` dir to generate the `types/types.pb.go` file + - to build, run `make protoc` - see `protoc --help` and [the grpc docs](https://www.grpc.io/docs) for examples and details of other languages - golang implementation of TMSP client and server diff --git a/glide.lock b/glide.lock index 2b3ec516..a87f5dc1 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ hash: 65769cd1c6d94a9733e9109e1bd7004f31b8df60c6d2cd47d9d8aecb9a94ffc2 -updated: 2016-11-10T00:51:46.9785435Z +updated: 2016-11-15T14:05:15.057591061-05:00 imports: - name: github.com/btcsuite/btcd - version: df33d4340e921eb9195225c67eed8b65071d40a5 + version: d9a674e1b7bc09d0830d6986c71cf5f535d753c3 subpackages: - btcec - name: github.com/btcsuite/fastsha256 @@ -10,7 +10,7 @@ imports: - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a + version: da116c3771bf4a398a43f44e069195ef1c9688ef subpackages: - proto - name: github.com/golang/snappy @@ -23,22 +23,22 @@ imports: version: 6b4daa5362b502898ddf367c5c11deb9e7a5c727 subpackages: - leveldb - - leveldb/errors - - leveldb/opt - leveldb/cache - leveldb/comparer + - leveldb/errors - leveldb/filter - leveldb/iterator - leveldb/journal - leveldb/memdb + - leveldb/opt - leveldb/storage - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - - extra25519 - edwards25519 + - extra25519 - name: github.com/tendermint/go-common version: 1c62bb6dadc6269aeecad5f9e7b153d950a54362 - name: github.com/tendermint/go-crypto @@ -58,32 +58,32 @@ imports: subpackages: - term - name: github.com/urfave/cli - version: d86a009f5e13f83df65d0d6cee9a2e3f1445f0da + version: b4f4786f378c0c1d3336b5bb798094b166edf5a9 - name: golang.org/x/crypto version: 9477e0b78b9ac3d0b03822fd95422e2fe07627cd subpackages: - - ripemd160 - nacl/secretbox - openpgp/armor - - poly1305 - - salsa20/salsa - openpgp/errors + - poly1305 + - ripemd160 + - salsa20/salsa - name: golang.org/x/net - version: 9ef22118a4b25863aa94546daffbc0a18feaafb3 + version: cac22060de4e495155959e69adcb4b45763ccb10 subpackages: - context - http2 - - trace - http2/hpack - idna - - lex/httplex - internal/timeseries + - lex/httplex + - trace - name: golang.org/x/sys - version: 9a2e24c3733eddc63871eda99f253e2db29bd3b9 + version: b699b7032584f0953262cb2788a0ca19bb494703 subpackages: - unix - name: google.golang.org/grpc - version: 28707e14b1d2b2f5da81474dea2790d71e526987 + version: 0d9891286aca15aeb2b0a73be9f5946c3cfefa85 subpackages: - codes - credentials @@ -91,8 +91,8 @@ imports: - internal - metadata - naming + - peer - stats - tap - transport - - peer -devImports: [] +testImports: [] diff --git a/types/types.pb.go b/types/types.pb.go index a624e3f0..40630bf2 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-go. -// source: types.proto +// source: types/types.proto // DO NOT EDIT! /* Package types is a generated protocol buffer package. It is generated from these files: - types.proto + types/types.proto It has these top-level messages: Request @@ -633,6 +633,13 @@ func (m *RequestEcho) String() string { return proto.CompactTextStrin func (*RequestEcho) ProtoMessage() {} func (*RequestEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (m *RequestEcho) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type RequestFlush struct { } @@ -659,6 +666,20 @@ func (m *RequestSetOption) String() string { return proto.CompactText func (*RequestSetOption) ProtoMessage() {} func (*RequestSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (m *RequestSetOption) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *RequestSetOption) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + type RequestAppendTx struct { Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` } @@ -668,6 +689,13 @@ func (m *RequestAppendTx) String() string { return proto.CompactTextS func (*RequestAppendTx) ProtoMessage() {} func (*RequestAppendTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (m *RequestAppendTx) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + type RequestCheckTx struct { Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` } @@ -677,6 +705,13 @@ func (m *RequestCheckTx) String() string { return proto.CompactTextSt func (*RequestCheckTx) ProtoMessage() {} func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (m *RequestCheckTx) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + type RequestQuery struct { Query []byte `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` } @@ -686,6 +721,13 @@ 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 { + if m != nil { + return m.Query + } + return nil +} + type RequestCommit struct { } @@ -719,6 +761,13 @@ func (m *RequestBeginBlock) String() string { return proto.CompactTex func (*RequestBeginBlock) ProtoMessage() {} func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (m *RequestBeginBlock) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + type RequestEndBlock struct { Height uint64 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` } @@ -728,6 +777,13 @@ func (m *RequestEndBlock) String() string { return proto.CompactTextS func (*RequestEndBlock) ProtoMessage() {} func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (m *RequestEndBlock) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + type Response struct { // Types that are valid to be assigned to Value: // *Response_Exception @@ -1168,6 +1224,13 @@ func (m *ResponseException) String() string { return proto.CompactTex func (*ResponseException) ProtoMessage() {} func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (m *ResponseException) GetError() string { + if m != nil { + return m.Error + } + return "" +} + type ResponseEcho struct { Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` } @@ -1177,6 +1240,13 @@ func (m *ResponseEcho) String() string { return proto.CompactTextStri func (*ResponseEcho) ProtoMessage() {} func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (m *ResponseEcho) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type ResponseFlush struct { } @@ -1194,6 +1264,13 @@ func (m *ResponseInfo) String() string { return proto.CompactTextStri func (*ResponseInfo) ProtoMessage() {} func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (m *ResponseInfo) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + type ResponseSetOption struct { Log string `protobuf:"bytes,1,opt,name=log" json:"log,omitempty"` } @@ -1203,6 +1280,13 @@ func (m *ResponseSetOption) String() string { return proto.CompactTex func (*ResponseSetOption) ProtoMessage() {} func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (m *ResponseSetOption) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + type ResponseAppendTx 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"` @@ -1214,6 +1298,27 @@ func (m *ResponseAppendTx) String() string { return proto.CompactText func (*ResponseAppendTx) ProtoMessage() {} func (*ResponseAppendTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (m *ResponseAppendTx) GetCode() CodeType { + if m != nil { + return m.Code + } + return CodeType_OK +} + +func (m *ResponseAppendTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseAppendTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + type ResponseCheckTx struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` @@ -1225,6 +1330,27 @@ func (m *ResponseCheckTx) String() string { return proto.CompactTextS func (*ResponseCheckTx) ProtoMessage() {} func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (m *ResponseCheckTx) GetCode() CodeType { + if m != nil { + return m.Code + } + return CodeType_OK +} + +func (m *ResponseCheckTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseCheckTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + 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"` @@ -1236,6 +1362,27 @@ func (m *ResponseQuery) String() string { return proto.CompactTextStr func (*ResponseQuery) ProtoMessage() {} func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (m *ResponseQuery) GetCode() CodeType { + if m != nil { + return m.Code + } + return CodeType_OK +} + +func (m *ResponseQuery) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseQuery) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + type ResponseCommit 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"` @@ -1247,6 +1394,27 @@ func (m *ResponseCommit) String() string { return proto.CompactTextSt func (*ResponseCommit) ProtoMessage() {} func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (m *ResponseCommit) GetCode() CodeType { + if m != nil { + return m.Code + } + return CodeType_OK +} + +func (m *ResponseCommit) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseCommit) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + type ResponseInitChain struct { } @@ -1289,6 +1457,20 @@ func (m *Validator) String() string { return proto.CompactTextString( func (*Validator) ProtoMessage() {} func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (m *Validator) GetPubKey() []byte { + if m != nil { + return m.PubKey + } + return nil +} + +func (m *Validator) GetPower() uint64 { + if m != nil { + return m.Power + } + return 0 +} + func init() { proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*RequestEcho)(nil), "types.RequestEcho") @@ -1326,7 +1508,7 @@ var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion3 +const _ = grpc.SupportPackageIsVersion4 // Client API for TMSPApplication service @@ -1719,98 +1901,99 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: fileDescriptor0, + Metadata: "types/types.proto", } -func init() { proto.RegisterFile("types.proto", fileDescriptor0) } +func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1379 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xc9, 0x72, 0x14, 0x47, - 0x13, 0xa6, 0xa5, 0x59, 0x73, 0xb4, 0x94, 0x4a, 0x12, 0x0c, 0x13, 0xff, 0x81, 0xbf, 0xbd, 0x21, - 0x20, 0xc0, 0x21, 0xc2, 0x84, 0xb1, 0x1d, 0x8e, 0x40, 0x20, 0xb0, 0x82, 0x00, 0xe4, 0x61, 0x39, - 0x78, 0x09, 0x45, 0x6b, 0xa6, 0x66, 0xa6, 0xad, 0x51, 0x75, 0xd3, 0x0b, 0x20, 0xbf, 0x81, 0x1f, - 0xc8, 0x17, 0x5f, 0x7d, 0xf2, 0xbe, 0x3c, 0x91, 0x33, 0xab, 0xaa, 0x57, 0x75, 0x73, 0xd2, 0xad, - 0x2b, 0xb7, 0xaa, 0xca, 0xfc, 0xf2, 0xeb, 0x2c, 0xe8, 0x45, 0x27, 0xbe, 0x08, 0xaf, 0xfb, 0x81, - 0x17, 0x79, 0xbc, 0xa9, 0x16, 0xf6, 0xcf, 0x0d, 0x68, 0x0f, 0xc5, 0xcb, 0x58, 0x84, 0x11, 0xbf, - 0x0c, 0x0d, 0x31, 0x9a, 0x79, 0x7d, 0xeb, 0x92, 0x75, 0xb9, 0xb7, 0xcd, 0xaf, 0x6b, 0x73, 0xa3, - 0xdd, 0x45, 0xcd, 0x17, 0xe7, 0x86, 0xca, 0x82, 0x5f, 0x85, 0xe6, 0x64, 0x1e, 0x87, 0xb3, 0xfe, - 0x82, 0x32, 0x5d, 0x2f, 0x9a, 0xde, 0x27, 0x15, 0xda, 0x6a, 0x1b, 0x0a, 0xeb, 0xca, 0x89, 0xd7, - 0x5f, 0xac, 0x0a, 0xbb, 0x87, 0x1a, 0x0a, 0x4b, 0x16, 0xfc, 0x63, 0x80, 0x50, 0x44, 0x07, 0x9e, - 0x1f, 0xb9, 0x9e, 0xec, 0x37, 0x94, 0xfd, 0x85, 0xa2, 0xfd, 0x53, 0x11, 0x3d, 0x51, 0x6a, 0x74, - 0xea, 0x86, 0xc9, 0x82, 0x7f, 0x04, 0x5d, 0xc7, 0xf7, 0x85, 0x1c, 0x1f, 0x44, 0x6f, 0xfa, 0x4d, - 0xe5, 0x78, 0xbe, 0xe8, 0x78, 0x47, 0xa9, 0x9f, 0xbd, 0x41, 0xbf, 0x8e, 0x63, 0xbe, 0xf9, 0x36, - 0x74, 0x46, 0x33, 0x31, 0x3a, 0x22, 0xaf, 0x96, 0xf2, 0xda, 0x2c, 0x7a, 0xdd, 0x25, 0xad, 0x72, - 0x6a, 0x8f, 0xf4, 0x27, 0xbf, 0x0e, 0xad, 0x91, 0x77, 0x7c, 0xec, 0x46, 0xfd, 0xb6, 0xf2, 0xd8, - 0x28, 0x79, 0x28, 0x1d, 0x3a, 0x18, 0x2b, 0xca, 0x15, 0x2a, 0x82, 0x93, 0x7e, 0xa7, 0x2a, 0x57, - 0x5f, 0x92, 0x8a, 0x72, 0xa5, 0x6c, 0x28, 0x03, 0xae, 0x74, 0xa3, 0x83, 0xd1, 0xcc, 0x71, 0x65, - 0xbf, 0x5b, 0x95, 0x81, 0x3d, 0xd4, 0xdf, 0x25, 0x35, 0x65, 0xc0, 0x4d, 0x16, 0xfc, 0x53, 0xe8, - 0x1d, 0x8a, 0xa9, 0x2b, 0x0f, 0x0e, 0xe7, 0xde, 0xe8, 0xa8, 0x0f, 0xca, 0xb5, 0x5f, 0x74, 0xdd, - 0x21, 0x83, 0x1d, 0xd2, 0xa3, 0x2f, 0x1c, 0xa6, 0x2b, 0x4a, 0x1f, 0xe5, 0x4e, 0xbb, 0xf6, 0xaa, - 0xd2, 0xb7, 0x2b, 0xc7, 0x89, 0x63, 0x47, 0x98, 0xef, 0x9d, 0x36, 0x34, 0x5f, 0x39, 0xf3, 0x58, - 0xd8, 0x1f, 0x40, 0x2f, 0x07, 0x13, 0xde, 0x87, 0xf6, 0xb1, 0x08, 0x43, 0x67, 0x2a, 0x14, 0x96, - 0xba, 0xc3, 0x64, 0x69, 0xaf, 0xc0, 0x52, 0x1e, 0x24, 0xf6, 0x72, 0xea, 0x48, 0x40, 0xb0, 0x3f, - 0x01, 0x56, 0xae, 0x33, 0x67, 0xb0, 0x78, 0x24, 0x4e, 0x4c, 0x20, 0xfa, 0xe4, 0x1b, 0x66, 0x5b, - 0x85, 0xbe, 0xee, 0xd0, 0x9c, 0xe1, 0xff, 0xb0, 0x5a, 0x2a, 0x35, 0x5f, 0x81, 0x05, 0x2c, 0x2c, - 0x79, 0x2e, 0x0d, 0xf1, 0xcb, 0xbe, 0x04, 0x2b, 0xc5, 0xba, 0x9e, 0xb2, 0x78, 0x37, 0x3d, 0x9f, - 0x2a, 0x0c, 0x6d, 0xa5, 0x8b, 0xa7, 0x4d, 0xf4, 0xc2, 0x5e, 0x85, 0xe5, 0x42, 0xb5, 0xed, 0x7b, - 0xe9, 0xb9, 0xd3, 0xea, 0xf0, 0x0f, 0x01, 0xf0, 0x60, 0xee, 0xd8, 0x89, 0xbc, 0x20, 0x44, 0xff, - 0x45, 0x4c, 0x2a, 0x33, 0x49, 0x7d, 0x91, 0x28, 0x86, 0x39, 0x1b, 0xfb, 0x2a, 0xac, 0x9d, 0x2a, - 0x14, 0x3f, 0x0f, 0xad, 0x99, 0x70, 0xa7, 0xb3, 0x48, 0x1d, 0xa1, 0x31, 0x34, 0x2b, 0x7b, 0x2b, - 0xbd, 0x6e, 0x52, 0x9a, 0x5a, 0xd3, 0x1f, 0x9a, 0xd0, 0x19, 0x8a, 0xd0, 0xf7, 0x64, 0x28, 0x10, - 0x61, 0x5d, 0xf1, 0x66, 0x24, 0x74, 0x8b, 0x59, 0x25, 0x94, 0x68, 0x9b, 0xdd, 0x44, 0x4f, 0x08, - 0x4b, 0x8d, 0xf9, 0x96, 0xa1, 0x87, 0x72, 0xcf, 0x1b, 0xa7, 0x3c, 0x3f, 0x5c, 0x4b, 0xf8, 0x61, - 0xb1, 0xd4, 0x22, 0xda, 0xb6, 0x44, 0x10, 0x5b, 0x86, 0x20, 0x1a, 0x95, 0x81, 0x0b, 0x0c, 0x71, - 0xbb, 0xc0, 0x10, 0xcd, 0xca, 0xe3, 0xd7, 0x50, 0xc4, 0xad, 0x3c, 0x45, 0xb4, 0x4a, 0x9d, 0xa5, - 0x3d, 0x2b, 0x39, 0xe2, 0x66, 0x8e, 0x23, 0xda, 0xa5, 0xd6, 0xd0, 0x6e, 0x15, 0x24, 0x71, 0x23, - 0x25, 0x89, 0x4e, 0x89, 0x56, 0x8c, 0x4b, 0x99, 0x25, 0xae, 0x25, 0x40, 0xeb, 0x56, 0x66, 0xac, - 0x44, 0x13, 0xb7, 0x0b, 0x34, 0x01, 0x95, 0x69, 0xa8, 0xe1, 0x89, 0xcf, 0x8a, 0x3c, 0xa1, 0x9b, - 0xfd, 0x62, 0xc9, 0xb7, 0x96, 0x28, 0x6e, 0xe5, 0x89, 0x62, 0xa9, 0x32, 0x89, 0x6f, 0x67, 0x8a, - 0x2d, 0xc2, 0x78, 0x09, 0x66, 0xd4, 0x65, 0x22, 0x08, 0xbc, 0xc0, 0x34, 0xb9, 0x5e, 0xd8, 0x97, - 0xa9, 0x17, 0x33, 0x70, 0xbd, 0x85, 0x55, 0x54, 0x3f, 0xe6, 0xa0, 0x65, 0xdb, 0x99, 0x2b, 0xc1, - 0x87, 0x73, 0x83, 0x30, 0xed, 0xa7, 0xbe, 0xed, 0xf7, 0xb2, 0x93, 0x14, 0xc8, 0x66, 0xee, 0x4d, - 0x13, 0xb2, 0xc1, 0x4f, 0xfb, 0x5b, 0x6a, 0xed, 0x22, 0x3c, 0xf8, 0x3b, 0xd0, 0x18, 0x79, 0x63, - 0x7d, 0x8c, 0x95, 0xed, 0x55, 0x93, 0x80, 0xbb, 0x28, 0x7a, 0x86, 0x5f, 0x43, 0xa5, 0xa4, 0x3d, - 0xb1, 0xaf, 0x1d, 0xd5, 0x2e, 0x4b, 0x43, 0xf5, 0x9d, 0x84, 0x5f, 0xcc, 0xc2, 0x7f, 0x43, 0x6d, - 0x5c, 0x80, 0xd1, 0x59, 0x46, 0xff, 0x2a, 0x4b, 0x8c, 0xe6, 0xb3, 0x33, 0x8c, 0xfd, 0x35, 0x91, - 0x69, 0x1e, 0xcd, 0x67, 0x19, 0x7c, 0x3d, 0x2b, 0x4e, 0x8a, 0x63, 0x7b, 0x03, 0xf8, 0x69, 0x80, - 0xea, 0x7f, 0x46, 0x11, 0x7a, 0xfc, 0x7d, 0x68, 0x8e, 0xdd, 0xc9, 0x24, 0x44, 0x4a, 0xa9, 0xa6, - 0x5d, 0xad, 0xb6, 0x6f, 0x43, 0x37, 0x95, 0x11, 0x7d, 0xfa, 0xf1, 0xe1, 0x43, 0x91, 0x90, 0xbd, - 0x59, 0x11, 0x3a, 0x7d, 0xef, 0xb5, 0x08, 0xd4, 0x91, 0x1b, 0x43, 0xbd, 0xb8, 0xf2, 0x93, 0x05, - 0xbd, 0x47, 0x1a, 0x7f, 0x74, 0x3b, 0xbe, 0x0a, 0xbd, 0xc7, 0xf1, 0x7c, 0x6e, 0x44, 0xec, 0x1c, - 0xef, 0x40, 0x83, 0x60, 0xcb, 0x2c, 0xde, 0x85, 0xa6, 0x82, 0x25, 0x5b, 0x20, 0x21, 0x01, 0x92, - 0x2d, 0xf2, 0x65, 0xe8, 0xa6, 0xb0, 0x63, 0x0d, 0x5a, 0xa6, 0xfd, 0xc0, 0x9a, 0x7c, 0x09, 0x3a, - 0x09, 0xda, 0xd8, 0x1a, 0xef, 0x41, 0xdb, 0x80, 0x83, 0x61, 0xfe, 0xa0, 0xa5, 0xf3, 0xcd, 0xd6, - 0x29, 0xb2, 0xaa, 0x2b, 0xdb, 0xa0, 0x00, 0x69, 0xa6, 0xd8, 0x26, 0xfe, 0xd8, 0x20, 0xcb, 0x11, - 0x3b, 0x4f, 0x01, 0x93, 0xec, 0xb0, 0x0b, 0x57, 0x7e, 0xc4, 0x3f, 0x42, 0x52, 0x17, 0xde, 0x82, - 0x85, 0x27, 0x0f, 0xf1, 0xc0, 0x6b, 0xb0, 0xbc, 0x27, 0x23, 0x11, 0x48, 0x67, 0xbe, 0x4b, 0x0d, - 0x88, 0x27, 0x47, 0xd1, 0xae, 0xc4, 0xb2, 0xb9, 0x72, 0xaa, 0x45, 0x0b, 0x14, 0x68, 0xc7, 0x19, - 0x3f, 0xf6, 0xe4, 0x48, 0xe0, 0x2d, 0x18, 0x2c, 0x3d, 0x97, 0x4e, 0x1c, 0xcd, 0xbc, 0xc0, 0xfd, - 0x5e, 0x8c, 0xf1, 0x22, 0x9b, 0xb0, 0xb6, 0x27, 0xc3, 0x78, 0x32, 0x71, 0x47, 0xae, 0x90, 0xd1, - 0xfd, 0x58, 0x8e, 0x43, 0xbc, 0x10, 0x87, 0x95, 0xe7, 0xf2, 0x48, 0x7a, 0xaf, 0xa5, 0xf9, 0x6b, - 0xb1, 0x16, 0x36, 0xf4, 0xc6, 0x8e, 0x13, 0x8a, 0x7b, 0xb1, 0x3f, 0x77, 0x47, 0x4e, 0x24, 0xee, - 0x8c, 0xc7, 0x01, 0xa6, 0x8f, 0x09, 0x0a, 0x42, 0x9a, 0xe2, 0xde, 0x93, 0xc4, 0xa1, 0x10, 0x5f, - 0x88, 0x90, 0x4d, 0xf9, 0x45, 0xd8, 0x3c, 0xa5, 0x51, 0x3b, 0xcf, 0xf8, 0xff, 0xa0, 0x5f, 0x56, - 0x3d, 0x70, 0xc2, 0xfd, 0xc0, 0xc5, 0x0b, 0xb8, 0x58, 0x5c, 0xa6, 0xb5, 0xea, 0x3f, 0xbc, 0x27, - 0xfd, 0x38, 0x62, 0xdf, 0x25, 0xfb, 0x1b, 0xe9, 0x93, 0x38, 0x22, 0xf1, 0x51, 0x49, 0xbc, 0xaf, - 0xe0, 0xc1, 0xe6, 0xfc, 0x02, 0xac, 0xe7, 0xc4, 0x4f, 0xe9, 0x7e, 0x94, 0x9d, 0xe3, 0xec, 0xbc, - 0x5a, 0xe1, 0x4e, 0xa5, 0x13, 0xc5, 0x81, 0x60, 0x12, 0xb1, 0xc6, 0x49, 0x63, 0x52, 0x92, 0x5c, - 0xdc, 0x4b, 0x76, 0x30, 0x72, 0xb3, 0x83, 0x5f, 0x16, 0xcf, 0x63, 0xac, 0x2c, 0x7b, 0x89, 0x62, - 0xf6, 0xc0, 0x7b, 0x65, 0xa4, 0xbb, 0x32, 0x72, 0xa3, 0x13, 0xf6, 0x8b, 0x85, 0x77, 0x5a, 0xcd, - 0xc4, 0x0f, 0x02, 0x2f, 0xf6, 0xd9, 0xaf, 0x16, 0x9e, 0x92, 0x67, 0xd2, 0xfd, 0xc0, 0xf3, 0xbd, - 0xd0, 0x99, 0xb3, 0xdf, 0x2c, 0x3c, 0xcb, 0x1a, 0x2a, 0xd2, 0x2a, 0x68, 0x87, 0xdf, 0x13, 0x87, - 0x54, 0xfe, 0x48, 0x1c, 0x1f, 0x8a, 0x80, 0xfd, 0x61, 0x61, 0xb2, 0x37, 0xf2, 0x8a, 0x34, 0xd6, - 0x9f, 0x96, 0x39, 0x51, 0xaa, 0x7a, 0xe1, 0x45, 0x82, 0xfd, 0x95, 0x88, 0x4d, 0x1e, 0x4c, 0xa0, - 0xbf, 0x2d, 0xbe, 0x0e, 0x2b, 0x99, 0x58, 0xd9, 0xfe, 0x63, 0xf1, 0x01, 0x6c, 0x16, 0x84, 0x58, - 0xff, 0x7d, 0xea, 0x38, 0xf6, 0xaf, 0xb5, 0x8d, 0x93, 0xcc, 0xea, 0xb3, 0x47, 0x4f, 0xf7, 0xb1, - 0x37, 0xd4, 0x06, 0x44, 0xd9, 0x37, 0x74, 0x9f, 0xf1, 0x8a, 0xf7, 0xca, 0xa0, 0x6a, 0x48, 0xc1, - 0xa1, 0x5f, 0xb7, 0x23, 0xaf, 0x7a, 0xb6, 0x0c, 0x2a, 0x67, 0x15, 0xda, 0x44, 0xff, 0x48, 0x4e, - 0xbf, 0x5e, 0x06, 0x55, 0x03, 0x0b, 0xff, 0x3c, 0xd7, 0xde, 0xbc, 0xee, 0x0d, 0x33, 0xa8, 0x1d, - 0x5d, 0x70, 0x9c, 0x4f, 0x09, 0x80, 0xd7, 0xbc, 0x64, 0x06, 0x75, 0xe3, 0x0b, 0xce, 0x78, 0x09, - 0x5f, 0xf0, 0xea, 0xf7, 0xcc, 0xa0, 0x66, 0x84, 0xa1, 0xdc, 0xe8, 0x1f, 0x45, 0xd5, 0x33, 0x65, - 0x50, 0x39, 0x95, 0xe0, 0xe3, 0xc1, 0x10, 0x12, 0xaf, 0x7c, 0x0a, 0x0d, 0xaa, 0x67, 0x1f, 0xca, - 0x50, 0x36, 0x2c, 0xd7, 0xbd, 0x71, 0x06, 0xb5, 0x53, 0x0d, 0xbf, 0x93, 0x67, 0x38, 0x5e, 0xfb, - 0xd2, 0x19, 0xd4, 0xcf, 0x36, 0x94, 0xe4, 0x6c, 0x78, 0xae, 0x7e, 0xef, 0x0c, 0xea, 0xc6, 0x9b, - 0xc3, 0x96, 0x7a, 0x47, 0xdf, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xe3, 0x58, 0x48, 0x56, - 0x0f, 0x00, 0x00, + // 1393 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x59, 0x53, 0xdc, 0xc6, + 0x16, 0x1e, 0xc1, 0xac, 0x67, 0x60, 0x68, 0x0e, 0x03, 0xc8, 0x53, 0xf7, 0xc1, 0x57, 0xf7, 0x26, + 0x01, 0xdb, 0x65, 0xa7, 0x70, 0xd9, 0x65, 0xc7, 0xa9, 0x54, 0x81, 0x8d, 0x81, 0x72, 0xd9, 0x26, + 0xf2, 0xf2, 0x90, 0xa5, 0x28, 0xa1, 0xe9, 0x99, 0x51, 0x18, 0xba, 0x65, 0x2d, 0x18, 0xf2, 0x0f, + 0xfc, 0x83, 0xf2, 0x92, 0xd7, 0x3c, 0x65, 0x5f, 0x7e, 0x51, 0xaa, 0x17, 0x49, 0x23, 0x21, 0xf9, + 0xc9, 0x2f, 0x53, 0xdd, 0x67, 0xeb, 0x9e, 0x73, 0xbe, 0xf3, 0xe9, 0x34, 0x2c, 0x47, 0x17, 0x3e, + 0x0d, 0x6f, 0xc9, 0xdf, 0x9b, 0x7e, 0xc0, 0x23, 0x8e, 0x0d, 0xb9, 0xb1, 0x7e, 0xaa, 0x43, 0xcb, + 0xa6, 0x6f, 0x62, 0x1a, 0x46, 0xb8, 0x01, 0x75, 0xea, 0x4e, 0xb8, 0x69, 0x5c, 0x35, 0x36, 0xba, + 0x5b, 0x78, 0x53, 0x99, 0x6b, 0xed, 0xae, 0x3b, 0xe1, 0xfb, 0x35, 0x5b, 0x5a, 0xe0, 0x75, 0x68, + 0x8c, 0xa6, 0x71, 0x38, 0x31, 0xe7, 0xa4, 0xe9, 0x4a, 0xde, 0xf4, 0xb1, 0x50, 0xed, 0xd7, 0x6c, + 0x65, 0x23, 0xc2, 0x7a, 0x6c, 0xc4, 0xcd, 0xf9, 0xb2, 0xb0, 0x07, 0x6c, 0x24, 0xc3, 0x0a, 0x0b, + 0xbc, 0x07, 0x10, 0xd2, 0xe8, 0x88, 0xfb, 0x91, 0xc7, 0x99, 0x59, 0x97, 0xf6, 0xeb, 0x79, 0xfb, + 0x17, 0x34, 0x7a, 0x2e, 0xd5, 0xfb, 0x35, 0xbb, 0x13, 0x26, 0x1b, 0xbc, 0x03, 0x1d, 0xc7, 0xf7, + 0x29, 0x1b, 0x1e, 0x45, 0xe7, 0x66, 0x43, 0x3a, 0xae, 0xe5, 0x1d, 0xb7, 0xa5, 0xfa, 0xe5, 0xf9, + 0x7e, 0xcd, 0x6e, 0x3b, 0x7a, 0x8d, 0x5b, 0xd0, 0x76, 0x27, 0xd4, 0x3d, 0x11, 0x5e, 0x4d, 0xe9, + 0xb5, 0x9a, 0xf7, 0x7a, 0x28, 0xb4, 0xd2, 0xa9, 0xe5, 0xaa, 0x25, 0xde, 0x84, 0xa6, 0xcb, 0x4f, + 0x4f, 0xbd, 0xc8, 0x6c, 0x49, 0x8f, 0x7e, 0xc1, 0x43, 0xea, 0xf6, 0x6b, 0xb6, 0xb6, 0x12, 0xb9, + 0x7a, 0x13, 0xd3, 0xe0, 0xc2, 0x6c, 0x97, 0xe5, 0xea, 0x4b, 0xa1, 0x12, 0xb9, 0x92, 0x36, 0x22, + 0x03, 0x1e, 0xf3, 0xa2, 0x23, 0x77, 0xe2, 0x78, 0xcc, 0xec, 0x94, 0x65, 0xe0, 0x80, 0x79, 0xd1, + 0x43, 0xa1, 0x16, 0x19, 0xf0, 0x92, 0x0d, 0x3e, 0x80, 0xee, 0x31, 0x1d, 0x7b, 0xec, 0xe8, 0x78, + 0xca, 0xdd, 0x13, 0x13, 0xa4, 0xab, 0x99, 0x77, 0xdd, 0x11, 0x06, 0x3b, 0x42, 0xbf, 0x5f, 0xb3, + 0xe1, 0x38, 0xdd, 0x89, 0xf4, 0x89, 0xdc, 0x29, 0xd7, 0x6e, 0x59, 0xfa, 0x76, 0xd9, 0x30, 0x71, + 0x6c, 0x53, 0xbd, 0xde, 0x69, 0x41, 0xe3, 0xcc, 0x99, 0xc6, 0xd4, 0xfa, 0x04, 0xba, 0x33, 0x30, + 0x41, 0x13, 0x5a, 0xa7, 0x34, 0x0c, 0x9d, 0x31, 0x95, 0x58, 0xea, 0xd8, 0xc9, 0xd6, 0xea, 0xc1, + 0xc2, 0x2c, 0x48, 0xac, 0xc5, 0xd4, 0x51, 0x00, 0xc1, 0xfa, 0x0c, 0x48, 0xb1, 0xce, 0x48, 0x60, + 0xfe, 0x84, 0x5e, 0xe8, 0x40, 0x62, 0x89, 0x7d, 0x7d, 0xac, 0x44, 0x5f, 0xc7, 0xd6, 0x77, 0xf8, + 0x2f, 0x2c, 0x15, 0x4a, 0x8d, 0x3d, 0x98, 0x8b, 0xce, 0xa5, 0xe7, 0x82, 0x3d, 0x17, 0x9d, 0x5b, + 0x57, 0xa1, 0x97, 0xaf, 0xeb, 0x25, 0x8b, 0xff, 0xa7, 0xf7, 0x93, 0x85, 0x11, 0x47, 0xa9, 0xe2, + 0x29, 0x13, 0xb5, 0xb1, 0x96, 0x60, 0x31, 0x57, 0x6d, 0xeb, 0x51, 0x7a, 0xef, 0xb4, 0x3a, 0xf8, + 0x29, 0xc0, 0x99, 0x33, 0xf5, 0x86, 0x4e, 0xc4, 0x83, 0xd0, 0x34, 0xae, 0xce, 0x6f, 0x74, 0xb7, + 0x88, 0x4e, 0xea, 0xeb, 0x44, 0x61, 0xcf, 0xd8, 0x58, 0xd7, 0x61, 0xf9, 0x52, 0xa1, 0x70, 0x0d, + 0x9a, 0x13, 0xea, 0x8d, 0x27, 0x91, 0xbc, 0x42, 0xdd, 0xd6, 0x3b, 0x6b, 0x33, 0xfd, 0xbb, 0x49, + 0x69, 0x2a, 0x4d, 0xdf, 0x35, 0xa0, 0x6d, 0xd3, 0xd0, 0xe7, 0x2c, 0xa4, 0x78, 0x0f, 0x3a, 0xf4, + 0xdc, 0xa5, 0xaa, 0xc5, 0x8c, 0x02, 0x4a, 0x94, 0xcd, 0x6e, 0xa2, 0x17, 0x08, 0x4b, 0x8d, 0x71, + 0x53, 0xd3, 0x43, 0xb1, 0xe7, 0xb5, 0xd3, 0x2c, 0x3f, 0xdc, 0x48, 0xf8, 0x61, 0xbe, 0xd0, 0x22, + 0xca, 0xb6, 0x40, 0x10, 0x9b, 0x9a, 0x20, 0xea, 0xa5, 0x81, 0x73, 0x0c, 0x71, 0x3f, 0xc7, 0x10, + 0x8d, 0xd2, 0xeb, 0x57, 0x50, 0xc4, 0xdd, 0x59, 0x8a, 0x68, 0x16, 0x3a, 0x4b, 0x79, 0x96, 0x72, + 0xc4, 0xed, 0x19, 0x8e, 0x68, 0x15, 0x5a, 0x43, 0xb9, 0x95, 0x90, 0xc4, 0xad, 0x94, 0x24, 0xda, + 0x05, 0x5a, 0xd1, 0x2e, 0x45, 0x96, 0xb8, 0x91, 0x00, 0xad, 0x53, 0x9a, 0xb1, 0x02, 0x4d, 0xdc, + 0xcf, 0xd1, 0x04, 0x94, 0xa6, 0xa1, 0x82, 0x27, 0x3e, 0xcf, 0xf3, 0x84, 0x6a, 0xf6, 0x2b, 0x05, + 0xdf, 0x4a, 0xa2, 0xb8, 0x3b, 0x4b, 0x14, 0x0b, 0xa5, 0x49, 0x7c, 0x3f, 0x53, 0x6c, 0x0a, 0x8c, + 0x17, 0x60, 0x26, 0xba, 0x8c, 0x06, 0x01, 0x0f, 0x74, 0x93, 0xab, 0x8d, 0xb5, 0x21, 0x7a, 0x31, + 0x03, 0xd7, 0x7b, 0x58, 0x45, 0xf6, 0xe3, 0x0c, 0xb4, 0x2c, 0x2b, 0x73, 0x15, 0xf0, 0x41, 0xd4, + 0x08, 0x53, 0x7e, 0x72, 0x6d, 0x7d, 0x94, 0xdd, 0x24, 0x47, 0x36, 0x53, 0x3e, 0x4e, 0xc8, 0x66, + 0xca, 0xc7, 0xd6, 0xb7, 0xa2, 0xb5, 0xf3, 0xf0, 0xc0, 0xff, 0x41, 0xdd, 0xe5, 0x43, 0x75, 0x8d, + 0xde, 0xd6, 0x92, 0x4e, 0xc0, 0x43, 0x3e, 0xa4, 0x2f, 0x2f, 0x7c, 0x6a, 0x4b, 0xa5, 0x38, 0x73, + 0xe8, 0x44, 0x8e, 0x6c, 0x97, 0x05, 0x5b, 0xae, 0x93, 0xf0, 0xf3, 0x59, 0xf8, 0x6f, 0x44, 0x1b, + 0xe7, 0x60, 0xf4, 0x21, 0xa3, 0x7f, 0x95, 0x25, 0x46, 0xf1, 0xd9, 0x07, 0x8c, 0xfd, 0xb5, 0x20, + 0xd3, 0x59, 0x34, 0x7f, 0xc8, 0xe0, 0x2b, 0x59, 0x71, 0x52, 0x1c, 0x5b, 0x7d, 0xc0, 0xcb, 0x00, + 0x55, 0xdf, 0x8c, 0x3c, 0xf4, 0xf0, 0x63, 0x68, 0x0c, 0xbd, 0xd1, 0x28, 0x34, 0xeb, 0x15, 0xb4, + 0xab, 0xd4, 0xd6, 0x7d, 0xe8, 0xa4, 0x32, 0x41, 0x9f, 0x7e, 0x7c, 0xfc, 0x84, 0x26, 0x64, 0xaf, + 0x77, 0x02, 0x9d, 0x3e, 0x7f, 0x4b, 0x03, 0x79, 0xe5, 0xba, 0xad, 0x36, 0xd7, 0x7e, 0x34, 0xa0, + 0xfb, 0x54, 0xe1, 0x4f, 0xfc, 0x3b, 0x5c, 0x82, 0xee, 0xb3, 0x78, 0x3a, 0xd5, 0x22, 0x52, 0xc3, + 0x36, 0xd4, 0x05, 0x6c, 0x89, 0x81, 0x1d, 0x68, 0x48, 0x58, 0x92, 0x39, 0x21, 0x14, 0x80, 0x24, + 0xf3, 0xb8, 0x08, 0x9d, 0x14, 0x76, 0xa4, 0x2e, 0xb6, 0x69, 0x3f, 0x90, 0x06, 0x2e, 0x40, 0x3b, + 0x41, 0x1b, 0x59, 0xc6, 0x2e, 0xb4, 0x34, 0x38, 0x08, 0x22, 0x40, 0x53, 0xe5, 0x9b, 0xac, 0x88, + 0xc8, 0xb2, 0xae, 0xa4, 0x2f, 0x02, 0xa4, 0x99, 0x22, 0xab, 0xd8, 0x03, 0xc8, 0x72, 0x44, 0xd6, + 0x44, 0xc0, 0x24, 0x3b, 0x64, 0xfd, 0xda, 0x0f, 0x0d, 0x68, 0x27, 0x75, 0xc1, 0x26, 0xcc, 0x3d, + 0x7f, 0x42, 0x6a, 0xb8, 0x0c, 0x8b, 0x07, 0x2c, 0xa2, 0x01, 0x73, 0xa6, 0xbb, 0xa2, 0x01, 0x89, + 0x21, 0x44, 0xbb, 0xcc, 0xe5, 0x43, 0x8f, 0x8d, 0x95, 0x68, 0x4e, 0x04, 0xda, 0x71, 0x86, 0xcf, + 0x38, 0x73, 0x29, 0x99, 0x47, 0x02, 0x0b, 0xaf, 0x98, 0x13, 0x47, 0x13, 0x1e, 0x78, 0xdf, 0xd3, + 0x21, 0xa9, 0xe3, 0x2a, 0x2c, 0x1f, 0xb0, 0x30, 0x1e, 0x8d, 0x3c, 0xd7, 0xa3, 0x2c, 0x7a, 0x1c, + 0xb3, 0x61, 0x48, 0x1a, 0x88, 0xd0, 0x7b, 0xc5, 0x4e, 0x18, 0x7f, 0xcb, 0xf4, 0x57, 0x8b, 0x34, + 0xd1, 0x84, 0xfe, 0x8e, 0x13, 0xd2, 0x47, 0xb1, 0x3f, 0xf5, 0x5c, 0x27, 0xa2, 0xdb, 0xc3, 0x61, + 0x40, 0xc3, 0x90, 0x50, 0x11, 0x44, 0x68, 0xf2, 0x67, 0x8f, 0x12, 0x87, 0x5c, 0x7c, 0x4a, 0x43, + 0x32, 0xc6, 0x2b, 0xb0, 0x7a, 0x49, 0x23, 0x4f, 0x9e, 0xe0, 0x7f, 0xc0, 0x2c, 0xaa, 0xf6, 0x9c, + 0xf0, 0x30, 0xf0, 0x5c, 0x4a, 0x3c, 0xec, 0x03, 0x51, 0x5a, 0xf9, 0x1d, 0x3e, 0x60, 0x7e, 0x1c, + 0x91, 0xef, 0x92, 0xf3, 0xb5, 0xf4, 0x79, 0x1c, 0x09, 0xf1, 0x49, 0x41, 0x7c, 0x28, 0xe1, 0x41, + 0xa6, 0xb8, 0x0e, 0x2b, 0x33, 0xe2, 0x17, 0xe2, 0xff, 0x89, 0xec, 0x9c, 0x66, 0xf7, 0x55, 0x0a, + 0x6f, 0xcc, 0x9c, 0x28, 0x0e, 0x28, 0x61, 0xb8, 0x06, 0x28, 0x34, 0x3a, 0x25, 0xc9, 0x1f, 0xe7, + 0xc9, 0x09, 0x5a, 0xae, 0x4f, 0xf0, 0x8b, 0xe2, 0x69, 0x3c, 0xf6, 0x18, 0x79, 0x83, 0xab, 0x40, + 0xf6, 0xf8, 0x99, 0x96, 0xee, 0xb2, 0xc8, 0x8b, 0x2e, 0xc8, 0xcf, 0x06, 0xf6, 0x61, 0x29, 0x13, + 0xef, 0x05, 0x3c, 0xf6, 0xc9, 0x2f, 0x06, 0xae, 0x03, 0x66, 0xd2, 0xc3, 0x80, 0xfb, 0x3c, 0x74, + 0xa6, 0xe4, 0x57, 0x03, 0xd7, 0x60, 0x79, 0x8f, 0x9f, 0xa5, 0x55, 0x50, 0x0e, 0xbf, 0x25, 0x0e, + 0xa9, 0xfc, 0x29, 0x3d, 0x3d, 0xa6, 0x01, 0xf9, 0xdd, 0xc0, 0x2b, 0xd0, 0x9f, 0x55, 0xa4, 0xb1, + 0xfe, 0x30, 0xf4, 0x8d, 0x52, 0xd5, 0x6b, 0x1e, 0x51, 0xf2, 0x67, 0x22, 0xd6, 0x79, 0xd0, 0x81, + 0xfe, 0x32, 0x70, 0x05, 0x7a, 0x99, 0x58, 0xda, 0xfe, 0x6d, 0xe0, 0x00, 0x56, 0x73, 0x42, 0x8f, + 0x8d, 0x0f, 0x45, 0xc7, 0x91, 0x7f, 0x8c, 0xad, 0x77, 0x0d, 0x58, 0x7a, 0xf9, 0xf4, 0xc5, 0xe1, + 0xb6, 0xaf, 0x0e, 0x10, 0x94, 0x7d, 0x4b, 0xf5, 0x19, 0x96, 0xbc, 0x57, 0x06, 0x65, 0x43, 0x0a, + 0x6e, 0xe9, 0x76, 0xc4, 0xb2, 0x67, 0xcb, 0xa0, 0x74, 0x56, 0x11, 0x87, 0xa8, 0x0f, 0xc9, 0xe5, + 0xd7, 0xcb, 0xa0, 0x6c, 0x60, 0xc1, 0x2f, 0x66, 0xda, 0x1b, 0xab, 0xde, 0x30, 0x83, 0xca, 0xd1, + 0x05, 0x1f, 0x64, 0x04, 0x80, 0x15, 0x2f, 0x99, 0x41, 0xd5, 0xf8, 0x82, 0xf7, 0x52, 0xbe, 0xc0, + 0xf2, 0xf7, 0xcc, 0xa0, 0x62, 0x84, 0x11, 0xb9, 0x51, 0x1f, 0x8a, 0xb2, 0x67, 0xca, 0xa0, 0x74, + 0x2a, 0xc1, 0x3b, 0x09, 0x21, 0x61, 0xe9, 0x53, 0x68, 0x50, 0x3e, 0xfb, 0x88, 0x0c, 0x65, 0xc3, + 0x72, 0xd5, 0x1b, 0x67, 0x50, 0x39, 0xd5, 0xe0, 0xf6, 0x2c, 0xc3, 0x61, 0xe5, 0x4b, 0x67, 0x50, + 0x3d, 0xdb, 0x88, 0x24, 0x67, 0xc3, 0x73, 0xf9, 0x7b, 0x67, 0x50, 0x35, 0xde, 0x1c, 0x37, 0xe5, + 0x3b, 0xfa, 0xf6, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xac, 0x2d, 0x4b, 0x5c, 0x0f, 0x00, + 0x00, } From 7998ba668ab8d11448f46925b7d8c6c8165a2126 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 28 Oct 2016 12:06:40 -0700 Subject: [PATCH 138/545] QuitService->BaseService --- README.md | 6 +++++- client/grpc_client.go | 8 ++++---- client/socket_client.go | 10 +++++----- server/grpc_server.go | 8 ++++---- server/socket_server.go | 8 ++++---- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d034a6b1..d6f1e53a 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,11 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message * __Usage__:
- Validate a transaction. This message should not mutate the state. + 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 AppendTx, but they happen on different connections - CheckTx from the mempool connection, and AppendTx 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 appendtxs, and then the mempool will re run whatever txs it has against that latest mempool stte + 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. diff --git a/client/grpc_client.go b/client/grpc_client.go index 771302c1..0c1ecf1c 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -15,7 +15,7 @@ import ( // A stripped copy of the remoteClient that makes // synchronous calls using grpc type grpcClient struct { - QuitService + BaseService mustConnect bool client types.TMSPApplicationClient @@ -31,7 +31,7 @@ func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { addr: addr, mustConnect: mustConnect, } - cli.QuitService = *NewQuitService(nil, "grpcClient", cli) + cli.BaseService = *NewBaseService(nil, "grpcClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err } @@ -41,7 +41,7 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { } func (cli *grpcClient) OnStart() error { - cli.QuitService.OnStart() + cli.BaseService.OnStart() RETRY_LOOP: for { @@ -73,7 +73,7 @@ RETRY_LOOP: } func (cli *grpcClient) OnStop() { - cli.QuitService.OnStop() + cli.BaseService.OnStop() cli.mtx.Lock() defer cli.mtx.Unlock() // TODO: how to close conn? its not a net.Conn and grpc doesn't expose a Close() diff --git a/client/socket_client.go b/client/socket_client.go index 27e74787..0b7be91d 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -27,7 +27,7 @@ const flushThrottleMS = 20 // Don't wait longer than... // the application in general is not meant to be interfaced // with concurrent callers. type socketClient struct { - QuitService + BaseService reqQueue chan *ReqRes flushTimer *ThrottleTimer @@ -52,14 +52,14 @@ func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { reqSent: list.New(), resCb: nil, } - cli.QuitService = *NewQuitService(nil, "socketClient", cli) + cli.BaseService = *NewBaseService(nil, "socketClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err } func (cli *socketClient) OnStart() error { - cli.QuitService.OnStart() + cli.BaseService.OnStart() var err error var conn net.Conn @@ -86,7 +86,7 @@ RETRY_LOOP: } func (cli *socketClient) OnStop() { - cli.QuitService.OnStop() + cli.BaseService.OnStop() cli.mtx.Lock() defer cli.mtx.Unlock() @@ -140,7 +140,7 @@ func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { default: // Probably will fill the buffer, or retry later. } - case <-cli.QuitService.Quit: + case <-cli.BaseService.Quit: return case reqres := <-cli.reqQueue: cli.willSendReq(reqres) diff --git a/server/grpc_server.go b/server/grpc_server.go index 02f6fa3f..472da25d 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -13,7 +13,7 @@ import ( // var maxNumberConnections = 2 type GRPCServer struct { - QuitService + BaseService proto string addr string @@ -32,13 +32,13 @@ func NewGRPCServer(protoAddr string, app types.TMSPApplicationServer) (Service, listener: nil, app: app, } - s.QuitService = *NewQuitService(nil, "TMSPServer", s) + s.BaseService = *NewBaseService(nil, "TMSPServer", s) _, err := s.Start() // Just start it return s, err } func (s *GRPCServer) OnStart() error { - s.QuitService.OnStart() + s.BaseService.OnStart() ln, err := net.Listen(s.proto, s.addr) if err != nil { return err @@ -51,6 +51,6 @@ func (s *GRPCServer) OnStart() error { } func (s *GRPCServer) OnStop() { - s.QuitService.OnStop() + s.BaseService.OnStop() s.server.Stop() } diff --git a/server/socket_server.go b/server/socket_server.go index ff01a908..3eec302f 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -15,7 +15,7 @@ import ( // var maxNumberConnections = 2 type SocketServer struct { - QuitService + BaseService proto string addr string @@ -39,13 +39,13 @@ func NewSocketServer(protoAddr string, app types.Application) (Service, error) { app: app, conns: make(map[int]net.Conn), } - s.QuitService = *NewQuitService(nil, "TMSPServer", s) + s.BaseService = *NewBaseService(nil, "TMSPServer", s) _, err := s.Start() // Just start it return s, err } func (s *SocketServer) OnStart() error { - s.QuitService.OnStart() + s.BaseService.OnStart() ln, err := net.Listen(s.proto, s.addr) if err != nil { return err @@ -56,7 +56,7 @@ func (s *SocketServer) OnStart() error { } func (s *SocketServer) OnStop() { - s.QuitService.OnStop() + s.BaseService.OnStop() s.listener.Close() s.connsMtx.Lock() From 6aa85b642e4691dc9c57b2ba2d23a46972378175 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 3 Nov 2016 19:50:57 -0400 Subject: [PATCH 139/545] BeginBlock --- client/socket_client.go | 2 + example/chain_aware/chain_aware_app.go | 75 +++++++++++++++++++++++++ example/chain_aware/chain_aware_test.go | 50 +++++++++++++++++ example/dummy/dummy.go | 1 + server/socket_server.go | 7 +++ 5 files changed, 135 insertions(+) create mode 100644 example/chain_aware/chain_aware_app.go create mode 100644 example/chain_aware/chain_aware_test.go diff --git a/client/socket_client.go b/client/socket_client.go index 0b7be91d..f650bd5c 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -432,6 +432,8 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { _, ok = res.Value.(*types.Response_Query) case *types.Request_InitChain: _, ok = res.Value.(*types.Response_InitChain) + case *types.Request_BeginBlock: + _, ok = res.Value.(*types.Response_BeginBlock) case *types.Request_EndBlock: _, ok = res.Value.(*types.Response_EndBlock) } diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go new file mode 100644 index 00000000..df18891b --- /dev/null +++ b/example/chain_aware/chain_aware_app.go @@ -0,0 +1,75 @@ +package main + +import ( + "flag" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" +) + +func main() { + + addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") + tmspPtr := flag.String("tmsp", "socket", "socket | grpc") + flag.Parse() + + // Start the listener + _, err := server.NewServer(*addrPtr, *tmspPtr, NewChainAwareApplication()) + if err != nil { + Exit(err.Error()) + } + + // Wait forever + TrapSignal(func() { + // Cleanup + }) + +} + +type ChainAwareApplication struct { + beginCount int + endCount int +} + +func NewChainAwareApplication() *ChainAwareApplication { + return &ChainAwareApplication{} +} + +func (app *ChainAwareApplication) Info() string { + return "nil" +} + +func (app *ChainAwareApplication) SetOption(key string, value string) (log string) { + return "" +} + +func (app *ChainAwareApplication) AppendTx(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(height uint64) { + app.beginCount += 1 + return +} + +func (app *ChainAwareApplication) EndBlock(height uint64) []*types.Validator { + app.endCount += 1 + return nil +} + +func (app *ChainAwareApplication) InitChain(vals []*types.Validator) { + return +} diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go new file mode 100644 index 00000000..21eb1b3f --- /dev/null +++ b/example/chain_aware/chain_aware_test.go @@ -0,0 +1,50 @@ +package main + +import ( + "strconv" + "strings" + "testing" + + . "github.com/tendermint/go-common" + "github.com/tendermint/tmsp/client" + "github.com/tendermint/tmsp/server" +) + +func TestChainAware(t *testing.T) { + + app := NewChainAwareApplication() + + // Start the listener + _, err := server.NewServer("unix://test.sock", "socket", app) + if err != nil { + t.Fatal(err) + } + + // Connect to the socket + client, err := tmspcli.NewSocketClient("unix://test.sock", false) + if err != nil { + Exit(Fmt("Error starting socket client: %v", err.Error())) + } + client.Start() + defer client.Stop() + + n := uint64(5) + for i := uint64(0); i < n; i++ { + client.BeginBlockSync(i) + client.EndBlockSync(i) + client.CommitSync() + } + + r := app.Query(nil) + spl := strings.Split(string(r.Data), ",") + if len(spl) != 2 { + t.Fatal("expected %d,%d ; got %s", n, n, string(r.Data)) + } + beginCount, _ := strconv.Atoi(spl[0]) + endCount, _ := strconv.Atoi(spl[1]) + if uint64(beginCount) != n { + t.Fatalf("expected beginCount of %d, got %d", n, beginCount) + } else if uint64(endCount) != n { + t.Fatalf("expected endCount of %d, got %d", n, endCount) + } +} diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index ca3a8c03..21f7c771 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,6 +1,7 @@ package dummy import ( + "fmt" "strings" . "github.com/tendermint/go-common" diff --git a/server/socket_server.go b/server/socket_server.go index 3eec302f..12d39fef 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -193,6 +193,13 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types } else { responses <- types.ToResponseInitChain() } + case *types.Request_BeginBlock: + if app, ok := s.app.(types.BlockchainAware); ok { + app.BeginBlock(r.BeginBlock.Height) + responses <- types.ToResponseBeginBlock() + } else { + responses <- types.ToResponseBeginBlock() + } case *types.Request_EndBlock: if app, ok := s.app.(types.BlockchainAware); ok { validators := app.EndBlock(r.EndBlock.Height) From 1dafd3a89b632487f3bac2c44fd54cc141ec27e4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 4 Nov 2016 06:41:51 -0700 Subject: [PATCH 140/545] Remove spurious fmt call --- example/dummy/dummy.go | 1 - 1 file changed, 1 deletion(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 21f7c771..ca3a8c03 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,7 +1,6 @@ package dummy import ( - "fmt" "strings" . "github.com/tendermint/go-common" From eece35eeebacee1ab94b8338e77e0d1c2d880ecc Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 15 Nov 2016 14:47:39 -0500 Subject: [PATCH 141/545] glide: update go-common --- glide.lock | 6 +++--- glide.yaml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/glide.lock b/glide.lock index a87f5dc1..9171ff8d 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 65769cd1c6d94a9733e9109e1bd7004f31b8df60c6d2cd47d9d8aecb9a94ffc2 -updated: 2016-11-15T14:05:15.057591061-05:00 +hash: 603c43870dfc63a3113a3d13ae799038206bd77889e2e9596a860d3644b8fb67 +updated: 2016-11-15T14:46:00.011667442-05:00 imports: - name: github.com/btcsuite/btcd version: d9a674e1b7bc09d0830d6986c71cf5f535d753c3 @@ -40,7 +40,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-common - version: 1c62bb6dadc6269aeecad5f9e7b153d950a54362 + version: fa3daa7abc253264c916c12fecce3effa01a1287 - name: github.com/tendermint/go-crypto version: 4b11d62bdb324027ea01554e5767b71174680ba0 - name: github.com/tendermint/go-db diff --git a/glide.yaml b/glide.yaml index f39ae801..bc1ad142 100644 --- a/glide.yaml +++ b/glide.yaml @@ -4,6 +4,7 @@ import: subpackages: - proto - package: github.com/tendermint/go-common + version: develop - package: github.com/tendermint/go-crypto - package: github.com/tendermint/go-logger - package: github.com/tendermint/go-merkle From debbf122db0a4cfc90f73ed2421e333822283451 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 22 Aug 2016 14:01:26 -0400 Subject: [PATCH 142/545] add version/block/config to Info. add header to BeginBlock --- client/client.go | 6 +- client/grpc_client.go | 12 +- client/local_client.go | 22 +- client/socket_client.go | 14 +- cmd/tmsp-cli/tmsp-cli.go | 2 +- example/counter/counter.go | 4 +- example/dummy/dummy.go | 4 +- example/nil/nil_app.go | 4 +- server/socket_server.go | 13 +- types/application.go | 9 +- types/messages.go | 8 +- types/types.pb.go | 420 ++++++++++++++++++++++++++++--------- types/types.proto | 45 +++- 13 files changed, 414 insertions(+), 149 deletions(-) diff --git a/client/client.go b/client/client.go index 291c4863..be1383e4 100644 --- a/client/client.go +++ b/client/client.go @@ -25,7 +25,7 @@ type Client interface { FlushSync() error EchoSync(msg string) (res types.Result) - InfoSync() (res types.Result) + InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) SetOptionSync(key string, value string) (res types.Result) AppendTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) @@ -33,11 +33,11 @@ type Client interface { CommitSync() (res types.Result) InitChainAsync(validators []*types.Validator) *ReqRes - BeginBlockAsync(height uint64) *ReqRes + BeginBlockAsync(header *types.Header) *ReqRes EndBlockAsync(height uint64) *ReqRes InitChainSync(validators []*types.Validator) (err error) - BeginBlockSync(height uint64) (err error) + BeginBlockSync(header *types.Header) (err error) EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) } diff --git a/client/grpc_client.go b/client/grpc_client.go index 0c1ecf1c..f7a80268 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -200,8 +200,8 @@ func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_InitChain{res}}) } -func (cli *grpcClient) BeginBlockAsync(height uint64) *ReqRes { - req := types.ToRequestBeginBlock(height) +func (cli *grpcClient) BeginBlockAsync(header *types.Header) *ReqRes { + req := types.ToRequestBeginBlock(header) res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -262,13 +262,13 @@ func (cli *grpcClient) FlushSync() error { return nil } -func (cli *grpcClient) InfoSync() (res types.Result) { +func (cli *grpcClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { reqres := cli.InfoAsync() if res := cli.checkErrGetResult(); res.IsErr() { return res } resp := reqres.Response.GetInfo() - return types.NewResultOK([]byte(resp.Info), LOG) + return types.NewResultOK([]byte(resp.Info), LOG), r.TmspInfo, r.LastBlock, r.Config } func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { @@ -321,8 +321,8 @@ func (cli *grpcClient) InitChainSync(validators []*types.Validator) (err error) return cli.Error() } -func (cli *grpcClient) BeginBlockSync(height uint64) (err error) { - cli.BeginBlockAsync(height) +func (cli *grpcClient) BeginBlockSync(header *types.Header) (err error) { + cli.BeginBlockAsync(header) return cli.Error() } diff --git a/client/local_client.go b/client/local_client.go index ce17f6c0..0ce735c8 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -51,11 +51,11 @@ func (app *localClient) EchoAsync(msg string) *ReqRes { func (app *localClient) InfoAsync() *ReqRes { app.mtx.Lock() - info := app.Application.Info() + info, tmspInfo, blockInfo, configInfo := app.Application.Info() app.mtx.Unlock() return app.callback( types.ToRequestInfo(), - types.ToResponseInfo(info), + types.ToResponseInfo(info, tmspInfo, blockInfo, configInfo), ) } @@ -122,14 +122,14 @@ func (app *localClient) InitChainAsync(validators []*types.Validator) *ReqRes { return reqRes } -func (app *localClient) BeginBlockAsync(height uint64) *ReqRes { +func (app *localClient) BeginBlockAsync(header *types.Header) *ReqRes { app.mtx.Lock() if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.BeginBlock(height) + bcApp.BeginBlock(header) } app.mtx.Unlock() return app.callback( - types.ToRequestBeginBlock(height), + types.ToRequestBeginBlock(header), types.ToResponseBeginBlock(), ) } @@ -157,11 +157,11 @@ func (app *localClient) EchoSync(msg string) (res types.Result) { return types.OK.SetData([]byte(msg)) } -func (app *localClient) InfoSync() (res types.Result) { +func (app *localClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { app.mtx.Lock() - info := app.Application.Info() - app.mtx.Unlock() - return types.OK.SetData([]byte(info)) + defer app.mtx.Unlock() + info, tmspInfo, blockInfo, configInfo := app.Application.Info() + return types.OK.SetData([]byte(info)), tmspInfo, blockInfo, configInfo } func (app *localClient) SetOptionSync(key string, value string) (res types.Result) { @@ -208,10 +208,10 @@ func (app *localClient) InitChainSync(validators []*types.Validator) (err error) return nil } -func (app *localClient) BeginBlockSync(height uint64) (err error) { +func (app *localClient) BeginBlockSync(header *types.Header) (err error) { app.mtx.Lock() if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.BeginBlock(height) + bcApp.BeginBlock(header) } app.mtx.Unlock() return nil diff --git a/client/socket_client.go b/client/socket_client.go index f650bd5c..18dc0b0e 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -263,8 +263,8 @@ func (cli *socketClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.queueRequest(types.ToRequestInitChain(validators)) } -func (cli *socketClient) BeginBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.ToRequestBeginBlock(height)) +func (cli *socketClient) BeginBlockAsync(header *types.Header) *ReqRes { + return cli.queueRequest(types.ToRequestBeginBlock(header)) } func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { @@ -292,14 +292,14 @@ func (cli *socketClient) FlushSync() error { return cli.Error() } -func (cli *socketClient) InfoSync() (res types.Result) { +func (cli *socketClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { reqres := cli.queueRequest(types.ToRequestInfo()) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return types.ErrInternalError.SetLog(err.Error()), nil, nil, nil } resp := reqres.Response.GetInfo() - return types.Result{Code: OK, Data: []byte(resp.Info), Log: LOG} + return types.Result{Code: OK, Data: []byte(resp.Info), Log: LOG}, resp.TmspInfo, resp.LastBlock, resp.Config } func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { @@ -361,8 +361,8 @@ func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error return nil } -func (cli *socketClient) BeginBlockSync(height uint64) (err error) { - cli.queueRequest(types.ToRequestBeginBlock(height)) +func (cli *socketClient) BeginBlockSync(header *types.Header) (err error) { + cli.queueRequest(types.ToRequestBeginBlock(header)) cli.FlushSync() if err := cli.Error(); err != nil { return err diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 08424129..fe6dbd45 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -191,7 +191,7 @@ func cmdEcho(c *cli.Context) error { // Get some info from the application func cmdInfo(c *cli.Context) error { - res := client.InfoSync() + res, _, _, _ := client.InfoSync() printResponse(c, res, string(res.Data), false) return nil } diff --git a/example/counter/counter.go b/example/counter/counter.go index 711ddc3f..2596eb10 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -18,8 +18,8 @@ func NewCounterApplication(serial bool) *CounterApplication { return &CounterApplication{serial: serial} } -func (app *CounterApplication) Info() string { - return Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount) +func (app *CounterApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { + return Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount), nil, nil, nil } func (app *CounterApplication) SetOption(key string, value string) (log string) { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index ca3a8c03..5bf52a78 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -20,8 +20,8 @@ func NewDummyApplication() *DummyApplication { return &DummyApplication{state: state} } -func (app *DummyApplication) Info() string { - return Fmt("size:%v", app.state.Size()) +func (app *DummyApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { + return Fmt("size:%v", app.state.Size()), nil, nil, nil } func (app *DummyApplication) SetOption(key string, value string) (log string) { diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 40474a9f..05b5c788 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -11,8 +11,8 @@ func NewNilApplication() *NilApplication { return &NilApplication{} } -func (app *NilApplication) Info() string { - return "nil" +func (app *NilApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { + return "nil", nil, nil, nil } func (app *NilApplication) SetOption(key string, value string) (log string) { diff --git a/server/socket_server.go b/server/socket_server.go index 12d39fef..fb141aa9 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -168,8 +168,7 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Flush: responses <- types.ToResponseFlush() case *types.Request_Info: - data := s.app.Info() - responses <- types.ToResponseInfo(data) + responses <- types.ToResponseInfo(s.app.Info()) case *types.Request_SetOption: so := r.SetOption logStr := s.app.SetOption(so.Key, so.Value) @@ -189,17 +188,13 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_InitChain: if app, ok := s.app.(types.BlockchainAware); ok { app.InitChain(r.InitChain.Validators) - responses <- types.ToResponseInitChain() - } else { - responses <- types.ToResponseInitChain() } + responses <- types.ToResponseInitChain() case *types.Request_BeginBlock: if app, ok := s.app.(types.BlockchainAware); ok { - app.BeginBlock(r.BeginBlock.Height) - responses <- types.ToResponseBeginBlock() - } else { - responses <- types.ToResponseBeginBlock() + app.BeginBlock(r.BeginBlock.Header) } + responses <- types.ToResponseBeginBlock() case *types.Request_EndBlock: if app, ok := s.app.(types.BlockchainAware); ok { validators := app.EndBlock(r.EndBlock.Height) diff --git a/types/application.go b/types/application.go index c6e6f24b..ba6565f5 100644 --- a/types/application.go +++ b/types/application.go @@ -8,7 +8,7 @@ import ( type Application interface { // Return application info - Info() (info string) + Info() (string, *TMSPInfo, *LastBlockInfo, *ConfigInfo) // Set application option (e.g. mode=mempool, mode=consensus) SetOption(key string, value string) (log string) @@ -34,7 +34,7 @@ type BlockchainAware interface { InitChain(validators []*Validator) // Signals the beginning of a block - BeginBlock(height uint64) + BeginBlock(header *Header) // Signals the end of a block // diffs: changed validators from app to TendermintCore @@ -59,7 +59,8 @@ func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*Resp } func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { - return &ResponseInfo{app.app.Info()}, nil + info, tmspInfo, blockInfo, configInfo := app.app.Info() + return &ResponseInfo{info, tmspInfo, blockInfo, configInfo}, nil } func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { @@ -95,7 +96,7 @@ func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { if chainAware, ok := app.app.(BlockchainAware); ok { - chainAware.BeginBlock(req.Height) + chainAware.BeginBlock(req.Header) } return &ResponseBeginBlock{}, nil } diff --git a/types/messages.go b/types/messages.go index 6b047d47..304289e4 100644 --- a/types/messages.go +++ b/types/messages.go @@ -61,9 +61,9 @@ func ToRequestInitChain(validators []*Validator) *Request { } } -func ToRequestBeginBlock(height uint64) *Request { +func ToRequestBeginBlock(header *Header) *Request { return &Request{ - Value: &Request_BeginBlock{&RequestBeginBlock{height}}, + Value: &Request_BeginBlock{&RequestBeginBlock{header}}, } } @@ -93,9 +93,9 @@ func ToResponseFlush() *Response { } } -func ToResponseInfo(info string) *Response { +func ToResponseInfo(info string, tmspInfo *TMSPInfo, blockInfo *LastBlockInfo, configInfo *ConfigInfo) *Response { return &Response{ - Value: &Response_Info{&ResponseInfo{info}}, + Value: &Response_Info{&ResponseInfo{info, tmspInfo, blockInfo, configInfo}}, } } diff --git a/types/types.pb.go b/types/types.pb.go index 40630bf2..d8251961 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -34,6 +34,11 @@ It has these top-level messages: ResponseInitChain ResponseBeginBlock ResponseEndBlock + TMSPInfo + LastBlockInfo + ConfigInfo + Header + PartSetHeader Validator */ package types @@ -753,7 +758,7 @@ func (m *RequestInitChain) GetValidators() []*Validator { } type RequestBeginBlock struct { - Height uint64 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` + Header *Header `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` } func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } @@ -761,11 +766,11 @@ func (m *RequestBeginBlock) String() string { return proto.CompactTex func (*RequestBeginBlock) ProtoMessage() {} func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } -func (m *RequestBeginBlock) GetHeight() uint64 { +func (m *RequestBeginBlock) GetHeader() *Header { if m != nil { - return m.Height + return m.Header } - return 0 + return nil } type RequestEndBlock struct { @@ -1256,7 +1261,10 @@ func (*ResponseFlush) ProtoMessage() {} func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } type ResponseInfo struct { - Info string `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` + Info string `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` + TmspInfo *TMSPInfo `protobuf:"bytes,2,opt,name=tmsp_info,json=tmspInfo" json:"tmsp_info,omitempty"` + LastBlock *LastBlockInfo `protobuf:"bytes,3,opt,name=last_block,json=lastBlock" json:"last_block,omitempty"` + Config *ConfigInfo `protobuf:"bytes,4,opt,name=config" json:"config,omitempty"` } func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } @@ -1271,6 +1279,27 @@ func (m *ResponseInfo) GetInfo() string { return "" } +func (m *ResponseInfo) GetTmspInfo() *TMSPInfo { + if m != nil { + return m.TmspInfo + } + return nil +} + +func (m *ResponseInfo) GetLastBlock() *LastBlockInfo { + if m != nil { + return m.LastBlock + } + return nil +} + +func (m *ResponseInfo) GetConfig() *ConfigInfo { + if m != nil { + return m.Config + } + return nil +} + type ResponseSetOption struct { Log string `protobuf:"bytes,1,opt,name=log" json:"log,omitempty"` } @@ -1447,6 +1476,182 @@ func (m *ResponseEndBlock) GetDiffs() []*Validator { return nil } +type TMSPInfo struct { + Version string `protobuf:"bytes,1,opt,name=Version" json:"Version,omitempty"` +} + +func (m *TMSPInfo) Reset() { *m = TMSPInfo{} } +func (m *TMSPInfo) String() string { return proto.CompactTextString(m) } +func (*TMSPInfo) ProtoMessage() {} +func (*TMSPInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } + +func (m *TMSPInfo) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +type LastBlockInfo struct { + BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` + BlockHash []byte `protobuf:"bytes,2,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *LastBlockInfo) Reset() { *m = LastBlockInfo{} } +func (m *LastBlockInfo) String() string { return proto.CompactTextString(m) } +func (*LastBlockInfo) ProtoMessage() {} +func (*LastBlockInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } + +func (m *LastBlockInfo) GetBlockHeight() uint64 { + if m != nil { + return m.BlockHeight + } + return 0 +} + +func (m *LastBlockInfo) GetBlockHash() []byte { + if m != nil { + return m.BlockHash + } + return nil +} + +func (m *LastBlockInfo) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +type ConfigInfo struct { + MaxBlockSize uint64 `protobuf:"varint,1,opt,name=max_block_size,json=maxBlockSize" json:"max_block_size,omitempty"` +} + +func (m *ConfigInfo) Reset() { *m = ConfigInfo{} } +func (m *ConfigInfo) String() string { return proto.CompactTextString(m) } +func (*ConfigInfo) ProtoMessage() {} +func (*ConfigInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } + +func (m *ConfigInfo) GetMaxBlockSize() uint64 { + if m != nil { + return m.MaxBlockSize + } + return 0 +} + +type Header struct { + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` + Time uint64 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"` + NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs" json:"num_txs,omitempty"` + LastBlockHash []byte `protobuf:"bytes,5,opt,name=last_block_hash,json=lastBlockHash,proto3" json:"last_block_hash,omitempty"` + LastBlockParts *PartSetHeader `protobuf:"bytes,6,opt,name=last_block_parts,json=lastBlockParts" json:"last_block_parts,omitempty"` + LastCommitHash []byte `protobuf:"bytes,7,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` + DataHash []byte `protobuf:"bytes,8,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` + ValidatorsHash []byte `protobuf:"bytes,9,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` + AppHash []byte `protobuf:"bytes,10,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *Header) Reset() { *m = Header{} } +func (m *Header) String() string { return proto.CompactTextString(m) } +func (*Header) ProtoMessage() {} +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } + +func (m *Header) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *Header) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Header) GetTime() uint64 { + if m != nil { + return m.Time + } + return 0 +} + +func (m *Header) GetNumTxs() uint64 { + if m != nil { + return m.NumTxs + } + return 0 +} + +func (m *Header) GetLastBlockHash() []byte { + if m != nil { + return m.LastBlockHash + } + return nil +} + +func (m *Header) GetLastBlockParts() *PartSetHeader { + if m != nil { + return m.LastBlockParts + } + return nil +} + +func (m *Header) GetLastCommitHash() []byte { + if m != nil { + return m.LastCommitHash + } + return nil +} + +func (m *Header) GetDataHash() []byte { + if m != nil { + return m.DataHash + } + return nil +} + +func (m *Header) GetValidatorsHash() []byte { + if m != nil { + return m.ValidatorsHash + } + return nil +} + +func (m *Header) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +type PartSetHeader struct { + Total uint64 `protobuf:"varint,1,opt,name=total" json:"total,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } +func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } +func (*PartSetHeader) ProtoMessage() {} +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *PartSetHeader) GetTotal() uint64 { + if m != nil { + return m.Total + } + return 0 +} + +func (m *PartSetHeader) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + type Validator struct { PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` Power uint64 `protobuf:"varint,2,opt,name=power" json:"power,omitempty"` @@ -1455,7 +1660,7 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1497,6 +1702,11 @@ func init() { proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") + proto.RegisterType((*TMSPInfo)(nil), "types.TMSPInfo") + proto.RegisterType((*LastBlockInfo)(nil), "types.LastBlockInfo") + proto.RegisterType((*ConfigInfo)(nil), "types.ConfigInfo") + proto.RegisterType((*Header)(nil), "types.Header") + proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) @@ -1907,93 +2117,113 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1393 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x59, 0x53, 0xdc, 0xc6, - 0x16, 0x1e, 0xc1, 0xac, 0x67, 0x60, 0x68, 0x0e, 0x03, 0xc8, 0x53, 0xf7, 0xc1, 0x57, 0xf7, 0x26, - 0x01, 0xdb, 0x65, 0xa7, 0x70, 0xd9, 0x65, 0xc7, 0xa9, 0x54, 0x81, 0x8d, 0x81, 0x72, 0xd9, 0x26, - 0xf2, 0xf2, 0x90, 0xa5, 0x28, 0xa1, 0xe9, 0x99, 0x51, 0x18, 0xba, 0x65, 0x2d, 0x18, 0xf2, 0x0f, - 0xfc, 0x83, 0xf2, 0x92, 0xd7, 0x3c, 0x65, 0x5f, 0x7e, 0x51, 0xaa, 0x17, 0x49, 0x23, 0x21, 0xf9, - 0xc9, 0x2f, 0x53, 0xdd, 0x67, 0xeb, 0x9e, 0x73, 0xbe, 0xf3, 0xe9, 0x34, 0x2c, 0x47, 0x17, 0x3e, - 0x0d, 0x6f, 0xc9, 0xdf, 0x9b, 0x7e, 0xc0, 0x23, 0x8e, 0x0d, 0xb9, 0xb1, 0x7e, 0xaa, 0x43, 0xcb, - 0xa6, 0x6f, 0x62, 0x1a, 0x46, 0xb8, 0x01, 0x75, 0xea, 0x4e, 0xb8, 0x69, 0x5c, 0x35, 0x36, 0xba, - 0x5b, 0x78, 0x53, 0x99, 0x6b, 0xed, 0xae, 0x3b, 0xe1, 0xfb, 0x35, 0x5b, 0x5a, 0xe0, 0x75, 0x68, - 0x8c, 0xa6, 0x71, 0x38, 0x31, 0xe7, 0xa4, 0xe9, 0x4a, 0xde, 0xf4, 0xb1, 0x50, 0xed, 0xd7, 0x6c, - 0x65, 0x23, 0xc2, 0x7a, 0x6c, 0xc4, 0xcd, 0xf9, 0xb2, 0xb0, 0x07, 0x6c, 0x24, 0xc3, 0x0a, 0x0b, - 0xbc, 0x07, 0x10, 0xd2, 0xe8, 0x88, 0xfb, 0x91, 0xc7, 0x99, 0x59, 0x97, 0xf6, 0xeb, 0x79, 0xfb, - 0x17, 0x34, 0x7a, 0x2e, 0xd5, 0xfb, 0x35, 0xbb, 0x13, 0x26, 0x1b, 0xbc, 0x03, 0x1d, 0xc7, 0xf7, - 0x29, 0x1b, 0x1e, 0x45, 0xe7, 0x66, 0x43, 0x3a, 0xae, 0xe5, 0x1d, 0xb7, 0xa5, 0xfa, 0xe5, 0xf9, - 0x7e, 0xcd, 0x6e, 0x3b, 0x7a, 0x8d, 0x5b, 0xd0, 0x76, 0x27, 0xd4, 0x3d, 0x11, 0x5e, 0x4d, 0xe9, - 0xb5, 0x9a, 0xf7, 0x7a, 0x28, 0xb4, 0xd2, 0xa9, 0xe5, 0xaa, 0x25, 0xde, 0x84, 0xa6, 0xcb, 0x4f, - 0x4f, 0xbd, 0xc8, 0x6c, 0x49, 0x8f, 0x7e, 0xc1, 0x43, 0xea, 0xf6, 0x6b, 0xb6, 0xb6, 0x12, 0xb9, - 0x7a, 0x13, 0xd3, 0xe0, 0xc2, 0x6c, 0x97, 0xe5, 0xea, 0x4b, 0xa1, 0x12, 0xb9, 0x92, 0x36, 0x22, - 0x03, 0x1e, 0xf3, 0xa2, 0x23, 0x77, 0xe2, 0x78, 0xcc, 0xec, 0x94, 0x65, 0xe0, 0x80, 0x79, 0xd1, - 0x43, 0xa1, 0x16, 0x19, 0xf0, 0x92, 0x0d, 0x3e, 0x80, 0xee, 0x31, 0x1d, 0x7b, 0xec, 0xe8, 0x78, - 0xca, 0xdd, 0x13, 0x13, 0xa4, 0xab, 0x99, 0x77, 0xdd, 0x11, 0x06, 0x3b, 0x42, 0xbf, 0x5f, 0xb3, - 0xe1, 0x38, 0xdd, 0x89, 0xf4, 0x89, 0xdc, 0x29, 0xd7, 0x6e, 0x59, 0xfa, 0x76, 0xd9, 0x30, 0x71, - 0x6c, 0x53, 0xbd, 0xde, 0x69, 0x41, 0xe3, 0xcc, 0x99, 0xc6, 0xd4, 0xfa, 0x04, 0xba, 0x33, 0x30, - 0x41, 0x13, 0x5a, 0xa7, 0x34, 0x0c, 0x9d, 0x31, 0x95, 0x58, 0xea, 0xd8, 0xc9, 0xd6, 0xea, 0xc1, - 0xc2, 0x2c, 0x48, 0xac, 0xc5, 0xd4, 0x51, 0x00, 0xc1, 0xfa, 0x0c, 0x48, 0xb1, 0xce, 0x48, 0x60, - 0xfe, 0x84, 0x5e, 0xe8, 0x40, 0x62, 0x89, 0x7d, 0x7d, 0xac, 0x44, 0x5f, 0xc7, 0xd6, 0x77, 0xf8, - 0x2f, 0x2c, 0x15, 0x4a, 0x8d, 0x3d, 0x98, 0x8b, 0xce, 0xa5, 0xe7, 0x82, 0x3d, 0x17, 0x9d, 0x5b, - 0x57, 0xa1, 0x97, 0xaf, 0xeb, 0x25, 0x8b, 0xff, 0xa7, 0xf7, 0x93, 0x85, 0x11, 0x47, 0xa9, 0xe2, - 0x29, 0x13, 0xb5, 0xb1, 0x96, 0x60, 0x31, 0x57, 0x6d, 0xeb, 0x51, 0x7a, 0xef, 0xb4, 0x3a, 0xf8, - 0x29, 0xc0, 0x99, 0x33, 0xf5, 0x86, 0x4e, 0xc4, 0x83, 0xd0, 0x34, 0xae, 0xce, 0x6f, 0x74, 0xb7, - 0x88, 0x4e, 0xea, 0xeb, 0x44, 0x61, 0xcf, 0xd8, 0x58, 0xd7, 0x61, 0xf9, 0x52, 0xa1, 0x70, 0x0d, - 0x9a, 0x13, 0xea, 0x8d, 0x27, 0x91, 0xbc, 0x42, 0xdd, 0xd6, 0x3b, 0x6b, 0x33, 0xfd, 0xbb, 0x49, - 0x69, 0x2a, 0x4d, 0xdf, 0x35, 0xa0, 0x6d, 0xd3, 0xd0, 0xe7, 0x2c, 0xa4, 0x78, 0x0f, 0x3a, 0xf4, - 0xdc, 0xa5, 0xaa, 0xc5, 0x8c, 0x02, 0x4a, 0x94, 0xcd, 0x6e, 0xa2, 0x17, 0x08, 0x4b, 0x8d, 0x71, - 0x53, 0xd3, 0x43, 0xb1, 0xe7, 0xb5, 0xd3, 0x2c, 0x3f, 0xdc, 0x48, 0xf8, 0x61, 0xbe, 0xd0, 0x22, - 0xca, 0xb6, 0x40, 0x10, 0x9b, 0x9a, 0x20, 0xea, 0xa5, 0x81, 0x73, 0x0c, 0x71, 0x3f, 0xc7, 0x10, - 0x8d, 0xd2, 0xeb, 0x57, 0x50, 0xc4, 0xdd, 0x59, 0x8a, 0x68, 0x16, 0x3a, 0x4b, 0x79, 0x96, 0x72, - 0xc4, 0xed, 0x19, 0x8e, 0x68, 0x15, 0x5a, 0x43, 0xb9, 0x95, 0x90, 0xc4, 0xad, 0x94, 0x24, 0xda, - 0x05, 0x5a, 0xd1, 0x2e, 0x45, 0x96, 0xb8, 0x91, 0x00, 0xad, 0x53, 0x9a, 0xb1, 0x02, 0x4d, 0xdc, - 0xcf, 0xd1, 0x04, 0x94, 0xa6, 0xa1, 0x82, 0x27, 0x3e, 0xcf, 0xf3, 0x84, 0x6a, 0xf6, 0x2b, 0x05, - 0xdf, 0x4a, 0xa2, 0xb8, 0x3b, 0x4b, 0x14, 0x0b, 0xa5, 0x49, 0x7c, 0x3f, 0x53, 0x6c, 0x0a, 0x8c, - 0x17, 0x60, 0x26, 0xba, 0x8c, 0x06, 0x01, 0x0f, 0x74, 0x93, 0xab, 0x8d, 0xb5, 0x21, 0x7a, 0x31, - 0x03, 0xd7, 0x7b, 0x58, 0x45, 0xf6, 0xe3, 0x0c, 0xb4, 0x2c, 0x2b, 0x73, 0x15, 0xf0, 0x41, 0xd4, - 0x08, 0x53, 0x7e, 0x72, 0x6d, 0x7d, 0x94, 0xdd, 0x24, 0x47, 0x36, 0x53, 0x3e, 0x4e, 0xc8, 0x66, - 0xca, 0xc7, 0xd6, 0xb7, 0xa2, 0xb5, 0xf3, 0xf0, 0xc0, 0xff, 0x41, 0xdd, 0xe5, 0x43, 0x75, 0x8d, - 0xde, 0xd6, 0x92, 0x4e, 0xc0, 0x43, 0x3e, 0xa4, 0x2f, 0x2f, 0x7c, 0x6a, 0x4b, 0xa5, 0x38, 0x73, - 0xe8, 0x44, 0x8e, 0x6c, 0x97, 0x05, 0x5b, 0xae, 0x93, 0xf0, 0xf3, 0x59, 0xf8, 0x6f, 0x44, 0x1b, - 0xe7, 0x60, 0xf4, 0x21, 0xa3, 0x7f, 0x95, 0x25, 0x46, 0xf1, 0xd9, 0x07, 0x8c, 0xfd, 0xb5, 0x20, - 0xd3, 0x59, 0x34, 0x7f, 0xc8, 0xe0, 0x2b, 0x59, 0x71, 0x52, 0x1c, 0x5b, 0x7d, 0xc0, 0xcb, 0x00, - 0x55, 0xdf, 0x8c, 0x3c, 0xf4, 0xf0, 0x63, 0x68, 0x0c, 0xbd, 0xd1, 0x28, 0x34, 0xeb, 0x15, 0xb4, - 0xab, 0xd4, 0xd6, 0x7d, 0xe8, 0xa4, 0x32, 0x41, 0x9f, 0x7e, 0x7c, 0xfc, 0x84, 0x26, 0x64, 0xaf, - 0x77, 0x02, 0x9d, 0x3e, 0x7f, 0x4b, 0x03, 0x79, 0xe5, 0xba, 0xad, 0x36, 0xd7, 0x7e, 0x34, 0xa0, - 0xfb, 0x54, 0xe1, 0x4f, 0xfc, 0x3b, 0x5c, 0x82, 0xee, 0xb3, 0x78, 0x3a, 0xd5, 0x22, 0x52, 0xc3, - 0x36, 0xd4, 0x05, 0x6c, 0x89, 0x81, 0x1d, 0x68, 0x48, 0x58, 0x92, 0x39, 0x21, 0x14, 0x80, 0x24, - 0xf3, 0xb8, 0x08, 0x9d, 0x14, 0x76, 0xa4, 0x2e, 0xb6, 0x69, 0x3f, 0x90, 0x06, 0x2e, 0x40, 0x3b, - 0x41, 0x1b, 0x59, 0xc6, 0x2e, 0xb4, 0x34, 0x38, 0x08, 0x22, 0x40, 0x53, 0xe5, 0x9b, 0xac, 0x88, - 0xc8, 0xb2, 0xae, 0xa4, 0x2f, 0x02, 0xa4, 0x99, 0x22, 0xab, 0xd8, 0x03, 0xc8, 0x72, 0x44, 0xd6, - 0x44, 0xc0, 0x24, 0x3b, 0x64, 0xfd, 0xda, 0x0f, 0x0d, 0x68, 0x27, 0x75, 0xc1, 0x26, 0xcc, 0x3d, - 0x7f, 0x42, 0x6a, 0xb8, 0x0c, 0x8b, 0x07, 0x2c, 0xa2, 0x01, 0x73, 0xa6, 0xbb, 0xa2, 0x01, 0x89, - 0x21, 0x44, 0xbb, 0xcc, 0xe5, 0x43, 0x8f, 0x8d, 0x95, 0x68, 0x4e, 0x04, 0xda, 0x71, 0x86, 0xcf, - 0x38, 0x73, 0x29, 0x99, 0x47, 0x02, 0x0b, 0xaf, 0x98, 0x13, 0x47, 0x13, 0x1e, 0x78, 0xdf, 0xd3, - 0x21, 0xa9, 0xe3, 0x2a, 0x2c, 0x1f, 0xb0, 0x30, 0x1e, 0x8d, 0x3c, 0xd7, 0xa3, 0x2c, 0x7a, 0x1c, - 0xb3, 0x61, 0x48, 0x1a, 0x88, 0xd0, 0x7b, 0xc5, 0x4e, 0x18, 0x7f, 0xcb, 0xf4, 0x57, 0x8b, 0x34, - 0xd1, 0x84, 0xfe, 0x8e, 0x13, 0xd2, 0x47, 0xb1, 0x3f, 0xf5, 0x5c, 0x27, 0xa2, 0xdb, 0xc3, 0x61, - 0x40, 0xc3, 0x90, 0x50, 0x11, 0x44, 0x68, 0xf2, 0x67, 0x8f, 0x12, 0x87, 0x5c, 0x7c, 0x4a, 0x43, - 0x32, 0xc6, 0x2b, 0xb0, 0x7a, 0x49, 0x23, 0x4f, 0x9e, 0xe0, 0x7f, 0xc0, 0x2c, 0xaa, 0xf6, 0x9c, - 0xf0, 0x30, 0xf0, 0x5c, 0x4a, 0x3c, 0xec, 0x03, 0x51, 0x5a, 0xf9, 0x1d, 0x3e, 0x60, 0x7e, 0x1c, - 0x91, 0xef, 0x92, 0xf3, 0xb5, 0xf4, 0x79, 0x1c, 0x09, 0xf1, 0x49, 0x41, 0x7c, 0x28, 0xe1, 0x41, - 0xa6, 0xb8, 0x0e, 0x2b, 0x33, 0xe2, 0x17, 0xe2, 0xff, 0x89, 0xec, 0x9c, 0x66, 0xf7, 0x55, 0x0a, - 0x6f, 0xcc, 0x9c, 0x28, 0x0e, 0x28, 0x61, 0xb8, 0x06, 0x28, 0x34, 0x3a, 0x25, 0xc9, 0x1f, 0xe7, - 0xc9, 0x09, 0x5a, 0xae, 0x4f, 0xf0, 0x8b, 0xe2, 0x69, 0x3c, 0xf6, 0x18, 0x79, 0x83, 0xab, 0x40, - 0xf6, 0xf8, 0x99, 0x96, 0xee, 0xb2, 0xc8, 0x8b, 0x2e, 0xc8, 0xcf, 0x06, 0xf6, 0x61, 0x29, 0x13, - 0xef, 0x05, 0x3c, 0xf6, 0xc9, 0x2f, 0x06, 0xae, 0x03, 0x66, 0xd2, 0xc3, 0x80, 0xfb, 0x3c, 0x74, - 0xa6, 0xe4, 0x57, 0x03, 0xd7, 0x60, 0x79, 0x8f, 0x9f, 0xa5, 0x55, 0x50, 0x0e, 0xbf, 0x25, 0x0e, - 0xa9, 0xfc, 0x29, 0x3d, 0x3d, 0xa6, 0x01, 0xf9, 0xdd, 0xc0, 0x2b, 0xd0, 0x9f, 0x55, 0xa4, 0xb1, - 0xfe, 0x30, 0xf4, 0x8d, 0x52, 0xd5, 0x6b, 0x1e, 0x51, 0xf2, 0x67, 0x22, 0xd6, 0x79, 0xd0, 0x81, - 0xfe, 0x32, 0x70, 0x05, 0x7a, 0x99, 0x58, 0xda, 0xfe, 0x6d, 0xe0, 0x00, 0x56, 0x73, 0x42, 0x8f, - 0x8d, 0x0f, 0x45, 0xc7, 0x91, 0x7f, 0x8c, 0xad, 0x77, 0x0d, 0x58, 0x7a, 0xf9, 0xf4, 0xc5, 0xe1, - 0xb6, 0xaf, 0x0e, 0x10, 0x94, 0x7d, 0x4b, 0xf5, 0x19, 0x96, 0xbc, 0x57, 0x06, 0x65, 0x43, 0x0a, - 0x6e, 0xe9, 0x76, 0xc4, 0xb2, 0x67, 0xcb, 0xa0, 0x74, 0x56, 0x11, 0x87, 0xa8, 0x0f, 0xc9, 0xe5, - 0xd7, 0xcb, 0xa0, 0x6c, 0x60, 0xc1, 0x2f, 0x66, 0xda, 0x1b, 0xab, 0xde, 0x30, 0x83, 0xca, 0xd1, - 0x05, 0x1f, 0x64, 0x04, 0x80, 0x15, 0x2f, 0x99, 0x41, 0xd5, 0xf8, 0x82, 0xf7, 0x52, 0xbe, 0xc0, - 0xf2, 0xf7, 0xcc, 0xa0, 0x62, 0x84, 0x11, 0xb9, 0x51, 0x1f, 0x8a, 0xb2, 0x67, 0xca, 0xa0, 0x74, - 0x2a, 0xc1, 0x3b, 0x09, 0x21, 0x61, 0xe9, 0x53, 0x68, 0x50, 0x3e, 0xfb, 0x88, 0x0c, 0x65, 0xc3, - 0x72, 0xd5, 0x1b, 0x67, 0x50, 0x39, 0xd5, 0xe0, 0xf6, 0x2c, 0xc3, 0x61, 0xe5, 0x4b, 0x67, 0x50, - 0x3d, 0xdb, 0x88, 0x24, 0x67, 0xc3, 0x73, 0xf9, 0x7b, 0x67, 0x50, 0x35, 0xde, 0x1c, 0x37, 0xe5, - 0x3b, 0xfa, 0xf6, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xac, 0x2d, 0x4b, 0x5c, 0x0f, 0x00, - 0x00, + // 1721 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x73, 0xdb, 0xc6, + 0x15, 0x16, 0x25, 0xde, 0x70, 0x48, 0x51, 0xab, 0xa3, 0x1b, 0xcd, 0xb6, 0x33, 0x0e, 0xea, 0x24, + 0x52, 0xea, 0xb1, 0x3b, 0xf2, 0x24, 0x63, 0x27, 0x9d, 0xcc, 0x58, 0x8e, 0x62, 0x69, 0x52, 0xc7, + 0x2a, 0xec, 0xf8, 0xa1, 0x97, 0xe1, 0x40, 0xc4, 0x92, 0x44, 0x05, 0x02, 0x30, 0xb0, 0x70, 0x28, + 0xff, 0x83, 0xfc, 0x9b, 0xbe, 0xf4, 0xa5, 0xaf, 0x7d, 0xea, 0xfd, 0xf2, 0xda, 0x3f, 0xd3, 0x39, + 0xbb, 0x8b, 0xab, 0x40, 0x3f, 0xf9, 0x85, 0x83, 0x73, 0xdd, 0xdd, 0x73, 0xf9, 0xf6, 0x2c, 0x61, + 0x5b, 0x5c, 0x87, 0x3c, 0xbe, 0x2f, 0x7f, 0xef, 0x85, 0x51, 0x20, 0x02, 0x6c, 0x49, 0xc2, 0xfc, + 0x73, 0x13, 0x3a, 0x16, 0x7f, 0x9d, 0xf0, 0x58, 0xe0, 0x21, 0x34, 0xf9, 0x64, 0x1e, 0x0c, 0x1b, + 0xb7, 0x1b, 0x87, 0xbd, 0x63, 0xbc, 0xa7, 0xd4, 0xb5, 0xf4, 0x74, 0x32, 0x0f, 0xce, 0xd6, 0x2c, + 0xa9, 0x81, 0x3f, 0x83, 0xd6, 0xd4, 0x4b, 0xe2, 0xf9, 0x70, 0x5d, 0xaa, 0xee, 0x94, 0x55, 0xbf, + 0x26, 0xd1, 0xd9, 0x9a, 0xa5, 0x74, 0xc8, 0xad, 0xeb, 0x4f, 0x83, 0xe1, 0x46, 0x9d, 0xdb, 0x73, + 0x7f, 0x2a, 0xdd, 0x92, 0x06, 0x3e, 0x04, 0x88, 0xb9, 0x18, 0x07, 0xa1, 0x70, 0x03, 0x7f, 0xd8, + 0x94, 0xfa, 0x07, 0x65, 0xfd, 0x17, 0x5c, 0x3c, 0x97, 0xe2, 0xb3, 0x35, 0xcb, 0x88, 0x53, 0x02, + 0x3f, 0x05, 0xc3, 0x0e, 0x43, 0xee, 0x3b, 0x63, 0xb1, 0x1c, 0xb6, 0xa4, 0xe1, 0x7e, 0xd9, 0xf0, + 0xb1, 0x14, 0xbf, 0x5c, 0x9e, 0xad, 0x59, 0x5d, 0x5b, 0x7f, 0xe3, 0x31, 0x74, 0x27, 0x73, 0x3e, + 0xb9, 0x22, 0xab, 0xb6, 0xb4, 0xda, 0x2b, 0x5b, 0x3d, 0x21, 0xa9, 0x34, 0xea, 0x4c, 0xd4, 0x27, + 0xde, 0x83, 0xf6, 0x24, 0x58, 0x2c, 0x5c, 0x31, 0xec, 0x48, 0x8b, 0xdd, 0x8a, 0x85, 0x94, 0x9d, + 0xad, 0x59, 0x5a, 0x8b, 0x62, 0xf5, 0x3a, 0xe1, 0xd1, 0xf5, 0xb0, 0x5b, 0x17, 0xab, 0x5f, 0x91, + 0x88, 0x62, 0x25, 0x75, 0x28, 0x02, 0xae, 0xef, 0x8a, 0xf1, 0x64, 0x6e, 0xbb, 0xfe, 0xd0, 0xa8, + 0x8b, 0xc0, 0xb9, 0xef, 0x8a, 0x27, 0x24, 0xa6, 0x08, 0xb8, 0x29, 0x81, 0x5f, 0x40, 0xef, 0x92, + 0xcf, 0x5c, 0x7f, 0x7c, 0xe9, 0x05, 0x93, 0xab, 0x21, 0x48, 0xd3, 0x61, 0xd9, 0xf4, 0x84, 0x14, + 0x4e, 0x48, 0x7e, 0xb6, 0x66, 0xc1, 0x65, 0x46, 0x51, 0xf8, 0x28, 0x76, 0xca, 0xb4, 0x57, 0x17, + 0xbe, 0x53, 0xdf, 0x49, 0x0d, 0xbb, 0x5c, 0x7f, 0x9f, 0x74, 0xa0, 0xf5, 0xc6, 0xf6, 0x12, 0x6e, + 0x7e, 0x0c, 0xbd, 0x42, 0x99, 0xe0, 0x10, 0x3a, 0x0b, 0x1e, 0xc7, 0xf6, 0x8c, 0xcb, 0x5a, 0x32, + 0xac, 0x94, 0x34, 0x07, 0xd0, 0x2f, 0x16, 0x89, 0xb9, 0x99, 0x19, 0x52, 0x21, 0x98, 0x9f, 0x03, + 0xab, 0xe6, 0x19, 0x19, 0x6c, 0x5c, 0xf1, 0x6b, 0xed, 0x88, 0x3e, 0x71, 0x57, 0x2f, 0x2b, 0xab, + 0xcf, 0xb0, 0xf4, 0x1e, 0x3e, 0x80, 0xad, 0x4a, 0xaa, 0x71, 0x00, 0xeb, 0x62, 0x29, 0x2d, 0xfb, + 0xd6, 0xba, 0x58, 0x9a, 0xb7, 0x61, 0x50, 0xce, 0xeb, 0x0d, 0x8d, 0x3b, 0xd9, 0xfe, 0x64, 0x62, + 0x68, 0x29, 0x95, 0x3c, 0xa5, 0xa2, 0x08, 0x73, 0x0b, 0x36, 0x4b, 0xd9, 0x36, 0xbf, 0xca, 0xf6, + 0x9d, 0x65, 0x07, 0x7f, 0x0e, 0xf0, 0xc6, 0xf6, 0x5c, 0xc7, 0x16, 0x41, 0x14, 0x0f, 0x1b, 0xb7, + 0x37, 0x0e, 0x7b, 0xc7, 0x4c, 0x07, 0xf5, 0x55, 0x2a, 0xb0, 0x0a, 0x3a, 0xe6, 0xe7, 0xb0, 0x7d, + 0x23, 0x51, 0xf8, 0x21, 0xb4, 0xe7, 0xdc, 0x76, 0x78, 0xa4, 0xdb, 0x72, 0x53, 0xbb, 0x38, 0x93, + 0x4c, 0x4b, 0x0b, 0xcd, 0xa3, 0xec, 0xf4, 0x69, 0xa6, 0x70, 0x9f, 0x2c, 0xdd, 0xd9, 0x5c, 0x48, + 0xcb, 0xa6, 0xa5, 0x29, 0xf3, 0x87, 0x16, 0x74, 0x2d, 0x1e, 0x87, 0x81, 0x1f, 0x73, 0x7c, 0x08, + 0x06, 0x5f, 0x4e, 0xb8, 0xea, 0xb8, 0x46, 0xa5, 0x68, 0x94, 0xce, 0x69, 0x2a, 0xa7, 0x82, 0xcb, + 0x94, 0xf1, 0x48, 0xa3, 0x45, 0x15, 0x02, 0xb4, 0x51, 0x11, 0x2e, 0xee, 0xa6, 0x70, 0xb1, 0x51, + 0xe9, 0x18, 0xa5, 0x5b, 0xc1, 0x8b, 0x23, 0x8d, 0x17, 0xcd, 0x5a, 0xc7, 0x25, 0xc0, 0x78, 0x54, + 0x02, 0x8c, 0x56, 0xed, 0xf6, 0x57, 0x20, 0xc6, 0x67, 0x45, 0xc4, 0x68, 0x57, 0x1a, 0x4d, 0x59, + 0xd6, 0x42, 0xc6, 0x83, 0x02, 0x64, 0x74, 0x2a, 0x9d, 0xa2, 0xcc, 0x6a, 0x30, 0xe3, 0x7e, 0x86, + 0x19, 0xdd, 0x0a, 0xca, 0x68, 0x93, 0x2a, 0x68, 0xdc, 0x4d, 0xeb, 0xce, 0xa8, 0x8d, 0x58, 0x05, + 0x35, 0x1e, 0x95, 0x50, 0x03, 0x6a, 0xc3, 0xb0, 0x02, 0x36, 0x7e, 0x51, 0x86, 0x0d, 0xd5, 0xfb, + 0xb7, 0x2a, 0xb6, 0x2b, 0x71, 0xe3, 0xb3, 0x22, 0x6e, 0xf4, 0x6b, 0x83, 0xf8, 0x6e, 0xe0, 0x38, + 0xa2, 0x92, 0xaf, 0x94, 0x19, 0x35, 0x1d, 0x8f, 0xa2, 0x20, 0xd2, 0x3d, 0xaf, 0x08, 0xf3, 0x90, + 0x5a, 0x33, 0x2f, 0xae, 0x77, 0x80, 0x8c, 0x6c, 0xcf, 0x42, 0x69, 0x99, 0x7f, 0x68, 0xe4, 0xb6, + 0x54, 0x3f, 0x88, 0xba, 0xc4, 0x94, 0xa1, 0xaa, 0xa5, 0xbb, 0x60, 0x88, 0x45, 0x1c, 0x8e, 0xa5, + 0x40, 0x15, 0xf5, 0x96, 0x3e, 0xcb, 0xcb, 0x67, 0x2f, 0x2e, 0xc8, 0xce, 0xea, 0x92, 0x86, 0xf4, + 0xf0, 0x00, 0xc0, 0xb3, 0x63, 0xa1, 0x8f, 0x5e, 0xae, 0xeb, 0x5f, 0xda, 0xb1, 0x90, 0xe7, 0x94, + 0x36, 0x86, 0x97, 0x92, 0x78, 0x44, 0x65, 0xe0, 0x4f, 0xdd, 0x99, 0xae, 0xed, 0x6d, 0x6d, 0xf0, + 0x44, 0x32, 0xa5, 0xb6, 0x56, 0x30, 0x3f, 0xcc, 0x03, 0x53, 0x82, 0x42, 0x2f, 0x98, 0xa5, 0x50, + 0xe8, 0x05, 0x33, 0xf3, 0x77, 0x04, 0x3c, 0xe5, 0x6a, 0xc5, 0x9f, 0x42, 0x73, 0x12, 0x38, 0x2a, + 0x2a, 0x83, 0xec, 0x0c, 0x4f, 0x02, 0x87, 0xbf, 0xbc, 0x0e, 0xb9, 0x25, 0x85, 0x14, 0x01, 0xc7, + 0x16, 0xb6, 0x3c, 0x68, 0xdf, 0x92, 0xdf, 0xa9, 0xfb, 0x8d, 0xdc, 0xfd, 0x6f, 0x09, 0x55, 0x4a, + 0x55, 0xfd, 0x3e, 0xbd, 0xff, 0x3a, 0xcf, 0x93, 0x42, 0xdb, 0xf7, 0xe8, 0xfb, 0x37, 0x04, 0xf5, + 0xc5, 0xe6, 0x7a, 0x9f, 0xce, 0x77, 0xf2, 0xe4, 0x64, 0x6d, 0x65, 0xee, 0x02, 0xde, 0xec, 0x17, + 0x75, 0xa3, 0x95, 0x3b, 0x01, 0x3f, 0x82, 0x96, 0xe3, 0x4e, 0xa7, 0xf1, 0xb0, 0xb9, 0xe2, 0x52, + 0x50, 0x62, 0xf3, 0x0e, 0x74, 0xd3, 0xca, 0xa3, 0x6a, 0x7f, 0xc5, 0xa3, 0x38, 0x45, 0x69, 0xc3, + 0x4a, 0x49, 0xd3, 0x83, 0xcd, 0x52, 0xc1, 0xe1, 0x07, 0xd0, 0x97, 0x55, 0x39, 0x2e, 0xa1, 0x7f, + 0x4f, 0xf2, 0xce, 0x24, 0x0b, 0x7f, 0x02, 0xa0, 0x55, 0x6c, 0x3d, 0xc4, 0xf5, 0x2d, 0x43, 0x29, + 0xd8, 0xf1, 0x1c, 0x6f, 0x01, 0xe1, 0x9d, 0x12, 0x6e, 0x48, 0x61, 0xc7, 0x0e, 0x43, 0x12, 0x99, + 0xc7, 0x00, 0x79, 0xb5, 0xe2, 0x1d, 0x18, 0x2c, 0xec, 0xa5, 0x6a, 0x82, 0x71, 0xec, 0xbe, 0xe5, + 0x7a, 0xb1, 0xfe, 0xc2, 0x5e, 0xca, 0x0d, 0xbd, 0x70, 0xdf, 0x72, 0xf3, 0x7f, 0xeb, 0xd0, 0x56, + 0xd7, 0x15, 0x79, 0x96, 0x20, 0x35, 0x76, 0x9d, 0xf4, 0x1c, 0x92, 0x3e, 0x77, 0x0a, 0xd7, 0xd5, + 0x7a, 0xf1, 0xba, 0xa2, 0x94, 0x08, 0x77, 0xc1, 0xe5, 0x46, 0x9a, 0x96, 0xfc, 0xc6, 0x03, 0xe8, + 0xf8, 0xc9, 0x62, 0x2c, 0x96, 0xb1, 0xec, 0xa4, 0xa6, 0xd5, 0xf6, 0x93, 0xc5, 0xcb, 0x65, 0x8c, + 0x1f, 0xc1, 0x56, 0xde, 0x96, 0xea, 0x00, 0x2d, 0x79, 0x80, 0xcd, 0xac, 0x0b, 0xe5, 0x09, 0xbf, + 0x04, 0x56, 0xd0, 0x0b, 0xed, 0x48, 0xc4, 0xfa, 0x12, 0x48, 0x9b, 0xf8, 0xc2, 0x8e, 0x68, 0x08, + 0xd1, 0xd7, 0xec, 0x20, 0x33, 0x27, 0x7e, 0x8c, 0x87, 0xda, 0x5e, 0xc1, 0xb5, 0x5a, 0xa8, 0x23, + 0x17, 0x92, 0x9a, 0x1a, 0xcf, 0x69, 0xa5, 0x1f, 0x81, 0x41, 0x55, 0xa4, 0x54, 0xba, 0x52, 0xa5, + 0x4b, 0x0c, 0x29, 0xfc, 0x18, 0xb6, 0xf2, 0xfb, 0x5f, 0xa9, 0x18, 0xca, 0x4b, 0xce, 0xbe, 0x91, + 0x11, 0x28, 0x67, 0xe4, 0x11, 0x6c, 0x96, 0xf6, 0x4a, 0xf0, 0x29, 0x02, 0x61, 0x7b, 0x3a, 0x17, + 0x8a, 0xa0, 0x30, 0x16, 0x92, 0x2d, 0xbf, 0xcd, 0x47, 0x60, 0x64, 0x45, 0x47, 0xf1, 0x0f, 0x93, + 0xcb, 0x6f, 0x78, 0x3a, 0xeb, 0x68, 0x8a, 0xdc, 0x85, 0xc1, 0xf7, 0x3c, 0xd2, 0x69, 0x51, 0xc4, + 0x27, 0x7f, 0x6a, 0x40, 0xef, 0x99, 0xc2, 0x5b, 0x6a, 0x1f, 0xdc, 0x82, 0xde, 0xb7, 0x89, 0xe7, + 0x69, 0x16, 0x5b, 0xc3, 0x2e, 0x34, 0x09, 0xa6, 0x59, 0x03, 0x0d, 0x68, 0x49, 0x18, 0x66, 0xeb, + 0xc4, 0xa4, 0xba, 0x61, 0x1b, 0xb8, 0x09, 0x46, 0x86, 0x6b, 0xac, 0x49, 0x64, 0x86, 0xff, 0xac, + 0x85, 0x7d, 0xe8, 0xa6, 0x70, 0xc6, 0xb6, 0xb1, 0x07, 0x1d, 0x8d, 0x3e, 0x0c, 0x11, 0xa0, 0xad, + 0xa2, 0xcb, 0x76, 0xc8, 0xb3, 0x04, 0x0e, 0xb6, 0x4b, 0x0e, 0xb2, 0x56, 0x64, 0x7b, 0x38, 0x00, + 0xc8, 0x9b, 0x90, 0xed, 0x93, 0xc3, 0xb4, 0xfd, 0xd8, 0xc1, 0x27, 0x7f, 0x6c, 0x41, 0x37, 0x6d, + 0x7c, 0x6c, 0xc3, 0xfa, 0xf3, 0x6f, 0xd8, 0x1a, 0x6e, 0xc3, 0xe6, 0xb9, 0x2f, 0x78, 0xe4, 0xdb, + 0xde, 0x29, 0x5d, 0x38, 0xac, 0x41, 0xac, 0x53, 0x7f, 0x12, 0x38, 0xae, 0x3f, 0x53, 0xac, 0x75, + 0x72, 0x74, 0x62, 0x3b, 0xdf, 0x06, 0xfe, 0x84, 0xb3, 0x0d, 0x64, 0xd0, 0xff, 0xce, 0xb7, 0x13, + 0x31, 0x0f, 0x22, 0xf7, 0x2d, 0x77, 0x58, 0x13, 0xf7, 0x60, 0xfb, 0xdc, 0x8f, 0x93, 0xe9, 0xd4, + 0x9d, 0xb8, 0xdc, 0x17, 0x5f, 0x27, 0xbe, 0x13, 0xb3, 0x16, 0x22, 0x0c, 0xbe, 0xf3, 0xaf, 0xfc, + 0xe0, 0x7b, 0x5f, 0x4f, 0x69, 0xac, 0x8d, 0x43, 0xd8, 0x3d, 0xb1, 0x63, 0xfe, 0x55, 0x12, 0x7a, + 0xee, 0xc4, 0x16, 0xfc, 0xb1, 0xe3, 0x44, 0x3c, 0x8e, 0x19, 0x27, 0x27, 0x24, 0x29, 0xaf, 0x3d, + 0x4d, 0x0d, 0x4a, 0xfe, 0x39, 0x8f, 0xd9, 0x0c, 0x6f, 0xc1, 0xde, 0x0d, 0x89, 0x5c, 0x79, 0x8e, + 0x3f, 0x86, 0x61, 0x55, 0xf4, 0xd4, 0x8e, 0x2f, 0x22, 0x77, 0xc2, 0x99, 0x8b, 0xbb, 0xc0, 0x94, + 0x54, 0xd6, 0xdb, 0xb9, 0x1f, 0x26, 0x82, 0xfd, 0x3e, 0x5d, 0x5f, 0x73, 0x9f, 0x27, 0x82, 0xd8, + 0x57, 0x15, 0xf6, 0x85, 0x2c, 0x0f, 0xe6, 0xe1, 0x01, 0xec, 0x14, 0xd8, 0x2f, 0xe8, 0x7c, 0x14, + 0x9d, 0x45, 0xbe, 0x5f, 0x25, 0x70, 0x67, 0xbe, 0x2d, 0x92, 0x88, 0x33, 0x1f, 0xf7, 0x01, 0x49, + 0xa2, 0x43, 0x92, 0x1e, 0x3c, 0x48, 0x57, 0xd0, 0x7c, 0xbd, 0x42, 0x58, 0x65, 0x7b, 0xc9, 0xcc, + 0xf5, 0xd9, 0x6b, 0xdc, 0x03, 0xf6, 0x34, 0x78, 0xa3, 0xb9, 0xa7, 0xbe, 0x70, 0xc5, 0x35, 0xfb, + 0x4b, 0x03, 0x77, 0x61, 0x2b, 0x67, 0x3f, 0x8d, 0x82, 0x24, 0x64, 0x7f, 0x6d, 0xe0, 0x01, 0x60, + 0xce, 0xbd, 0x88, 0x82, 0x30, 0x88, 0x6d, 0x8f, 0xfd, 0xad, 0x81, 0xfb, 0xb0, 0xfd, 0x34, 0x78, + 0x93, 0x65, 0x41, 0x19, 0xfc, 0x3d, 0x35, 0xc8, 0xf8, 0xcf, 0xf8, 0xe2, 0x92, 0x47, 0xec, 0x1f, + 0x0d, 0xbc, 0x05, 0xbb, 0x45, 0x41, 0xe6, 0xeb, 0x9f, 0x0d, 0xbd, 0xa3, 0x4c, 0xf4, 0x2a, 0x10, + 0x9c, 0xfd, 0x2b, 0x65, 0xeb, 0x38, 0x68, 0x47, 0xff, 0x6e, 0xe0, 0x0e, 0x0c, 0x72, 0xb6, 0xd4, + 0xfd, 0x4f, 0x03, 0x47, 0xb0, 0x57, 0x62, 0xba, 0xfe, 0xec, 0x82, 0x3a, 0x8e, 0xfd, 0xb7, 0x71, + 0xfc, 0x43, 0x0b, 0xb6, 0xe8, 0x46, 0x78, 0x1c, 0xaa, 0x05, 0x68, 0x26, 0xb8, 0xaf, 0xfa, 0x0c, + 0x6b, 0x9e, 0xeb, 0xa3, 0xba, 0xa1, 0x1c, 0x8f, 0x75, 0x3b, 0x62, 0xdd, 0xab, 0x7d, 0x54, 0x3b, + 0x9b, 0xd3, 0x22, 0x6a, 0x6e, 0xba, 0xf9, 0x78, 0x1f, 0xd5, 0x0d, 0xe8, 0xf8, 0x65, 0xa1, 0xbd, + 0x71, 0xd5, 0x13, 0x7e, 0xb4, 0x72, 0x54, 0xc7, 0x2f, 0x72, 0x00, 0xc0, 0x15, 0x0f, 0xf9, 0xd1, + 0xaa, 0x71, 0x1d, 0x1f, 0x66, 0x78, 0x81, 0xf5, 0xcf, 0xf9, 0xd1, 0x8a, 0x91, 0x9d, 0x62, 0xa3, + 0x26, 0x91, 0xba, 0x57, 0xfa, 0xa8, 0x76, 0x0a, 0xc7, 0x4f, 0x53, 0x40, 0xc2, 0xda, 0x7f, 0x02, + 0x46, 0xf5, 0xb3, 0x3e, 0x45, 0x28, 0x7f, 0x2b, 0xae, 0x7a, 0xe2, 0x8f, 0x56, 0x4e, 0xf1, 0xf8, + 0xb8, 0x88, 0x70, 0xb8, 0xf2, 0xa1, 0x3f, 0x5a, 0x3d, 0xcb, 0x53, 0x90, 0xf3, 0xc7, 0x62, 0xfd, + 0x73, 0x7f, 0xb4, 0x6a, 0x9c, 0xbf, 0x6c, 0xcb, 0xbf, 0x91, 0x1e, 0xfc, 0x3f, 0x00, 0x00, 0xff, + 0xff, 0x89, 0x5e, 0xff, 0xe3, 0x5b, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index cb3d82c1..e2c7d9b4 100644 --- a/types/types.proto +++ b/types/types.proto @@ -124,7 +124,7 @@ message RequestInitChain{ } message RequestBeginBlock{ - uint64 height = 1; + Header header = 1; } message RequestEndBlock{ @@ -164,7 +164,11 @@ message ResponseFlush{ } message ResponseInfo { - string info = 1; + string info = 1; // backwards compatible + + TMSPInfo tmsp_info = 2; + LastBlockInfo last_block = 3; + ConfigInfo config = 4; } message ResponseSetOption{ @@ -207,7 +211,42 @@ message ResponseEndBlock{ } //---------------------------------------- -// Misc types +// Info types + +message TMSPInfo { + string Version = 1; +} + +message LastBlockInfo { + uint64 block_height = 1; + bytes block_hash = 2; + bytes app_hash = 3; +} + +message ConfigInfo { + uint64 max_block_size = 1; +} + +//---------------------------------------- +// Blockchain Types + +message Header { + string chain_id = 1; + uint64 height = 2; + uint64 time = 3; + uint64 num_txs = 4; + bytes last_block_hash = 5; + PartSetHeader last_block_parts = 6; + bytes last_commit_hash = 7; + bytes data_hash = 8; + bytes validators_hash = 9; + bytes app_hash = 10; +} + +message PartSetHeader { + uint64 total = 1; + bytes hash = 2; +} message Validator { bytes pubKey = 1; From 7901825ad93a69556cb33e63b295555cd01d1306 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 24 Aug 2016 01:42:57 -0400 Subject: [PATCH 143/545] persistent dummy --- client/grpc_client.go | 4 +- cmd/dummy/main.go | 12 ++- example/dummy/dummy.go | 1 + example/dummy/log.go | 7 ++ example/dummy/persistent_dummy.go | 117 ++++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 example/dummy/log.go create mode 100644 example/dummy/persistent_dummy.go diff --git a/client/grpc_client.go b/client/grpc_client.go index f7a80268..36589322 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -265,10 +265,10 @@ func (cli *grpcClient) FlushSync() error { func (cli *grpcClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { reqres := cli.InfoAsync() if res := cli.checkErrGetResult(); res.IsErr() { - return res + return res, nil, nil, nil } resp := reqres.Response.GetInfo() - return types.NewResultOK([]byte(resp.Info), LOG), r.TmspInfo, r.LastBlock, r.Config + return types.NewResultOK([]byte(resp.Info), LOG), resp.TmspInfo, resp.LastBlock, resp.Config } func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 8efa69e6..8a1465c4 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -6,16 +6,26 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/example/dummy" "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" ) func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") tmspPtr := flag.String("tmsp", "socket", "socket | grpc") + persistencePtr := flag.String("persist", "", "directory to use for a database") flag.Parse() + // Create the application - in memory or persisted to disk + var app types.Application + if *persistencePtr == "" { + app = dummy.NewDummyApplication() + } else { + app = dummy.NewPersistentDummyApplication(*persistencePtr) + } + // Start the listener - _, err := server.NewServer(*addrPtr, *tmspPtr, dummy.NewDummyApplication()) + _, err := server.NewServer(*addrPtr, *tmspPtr, app) if err != nil { Exit(err.Error()) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 5bf52a78..0c6a9089 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -50,6 +50,7 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(query []byte) types.Result { index, value, exists := app.state.Get(query) + resStr := Fmt("Index=%v value=%v exists=%v", index, string(value), exists) return types.NewResultOK([]byte(resStr), "") } diff --git a/example/dummy/log.go b/example/dummy/log.go new file mode 100644 index 00000000..8571fa01 --- /dev/null +++ b/example/dummy/log.go @@ -0,0 +1,7 @@ +package dummy + +import ( + "github.com/tendermint/go-logger" +) + +var log = logger.New("module", "dummy") diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go new file mode 100644 index 00000000..60e677e9 --- /dev/null +++ b/example/dummy/persistent_dummy.go @@ -0,0 +1,117 @@ +package dummy + +import ( + "bytes" + + . "github.com/tendermint/go-common" + dbm "github.com/tendermint/go-db" + "github.com/tendermint/go-merkle" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +//----------------------------------------- +// persist the last block info + +var lastBlockKey = []byte("lastblock") + +// Get the last block from the db +func LoadLastBlock(db dbm.DB) (lastBlock types.LastBlockInfo) { + buf := db.Get(lastBlockKey) + if len(buf) != 0 { + r, n, err := bytes.NewReader(buf), new(int), new(error) + 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)) + } + // TODO: ensure that buf is completely read. + } + + return lastBlock +} + +func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { + log.Notice("Saving block", "height", lastBlock.BlockHeight, "hash", lastBlock.BlockHash, "root", lastBlock.AppHash) + buf, n, err := new(bytes.Buffer), new(int), new(error) + wire.WriteBinary(lastBlock, buf, n, err) + if *err != nil { + // TODO + PanicCrisis(*err) + } + db.Set(lastBlockKey, buf.Bytes()) +} + +//----------------------------------------- + +type PersistentDummyApplication struct { + app *DummyApplication + db dbm.DB +} + +func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { + db := dbm.NewDB("dummy", "leveldb", dbDir) + lastBlock := LoadLastBlock(db) + + stateTree := merkle.NewIAVLTree( + 0, + db, + ) + stateTree.Load(lastBlock.AppHash) + + log.Notice("Loaded state", "block", lastBlock.BlockHeight, "root", stateTree.Hash()) + + return &PersistentDummyApplication{ + app: &DummyApplication{state: stateTree}, + db: db, + } +} + +func (app *PersistentDummyApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { + s, _, _, _ := app.app.Info() + lastBlock := LoadLastBlock(app.db) + return s, nil, &lastBlock, nil +} + +func (app *PersistentDummyApplication) SetOption(key string, value string) (log string) { + return app.app.SetOption(key, value) +} + +// tx is either "key=value" or just arbitrary bytes +func (app *PersistentDummyApplication) AppendTx(tx []byte) types.Result { + return app.app.AppendTx(tx) +} + +func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { + return app.app.CheckTx(tx) +} + +func (app *PersistentDummyApplication) Commit() types.Result { + // Save + hash := app.app.state.Save() + log.Info("Saved state", "root", hash) + return types.NewResultOK(hash, "") +} + +func (app *PersistentDummyApplication) Query(query []byte) types.Result { + return app.app.Query(query) +} + +func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) { + return +} + +func (app *PersistentDummyApplication) BeginBlock(header *types.Header) { + // we commit the previous block state on BeginBlock because thats + // when we get the prev block hash and the app hash + lastBlock := types.LastBlockInfo{ + BlockHeight: header.Height - 1, + BlockHash: header.LastBlockHash, + AppHash: header.AppHash, + } + SaveLastBlock(app.db, lastBlock) +} + +func (app *PersistentDummyApplication) EndBlock(height uint64) (diffs []*types.Validator) { + return nil +} From ddb2b0163184704756299198758789eb654c77ca Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 9 Sep 2016 23:01:53 -0400 Subject: [PATCH 144/545] BeginBlock(hash, header) --- client/client.go | 4 +- client/grpc_client.go | 8 +- client/local_client.go | 10 +- client/socket_client.go | 8 +- example/dummy/persistent_dummy.go | 29 ++-- server/socket_server.go | 2 +- types/application.go | 4 +- types/messages.go | 4 +- types/types.pb.go | 229 ++++++++++++++++-------------- types/types.proto | 3 +- 10 files changed, 158 insertions(+), 143 deletions(-) diff --git a/client/client.go b/client/client.go index be1383e4..d1954e3f 100644 --- a/client/client.go +++ b/client/client.go @@ -33,11 +33,11 @@ type Client interface { CommitSync() (res types.Result) InitChainAsync(validators []*types.Validator) *ReqRes - BeginBlockAsync(header *types.Header) *ReqRes + BeginBlockAsync(hash []byte, header *types.Header) *ReqRes EndBlockAsync(height uint64) *ReqRes InitChainSync(validators []*types.Validator) (err error) - BeginBlockSync(header *types.Header) (err error) + BeginBlockSync(hash []byte, header *types.Header) (err error) EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) } diff --git a/client/grpc_client.go b/client/grpc_client.go index 36589322..1e016973 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -200,8 +200,8 @@ func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_InitChain{res}}) } -func (cli *grpcClient) BeginBlockAsync(header *types.Header) *ReqRes { - req := types.ToRequestBeginBlock(header) +func (cli *grpcClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { + req := types.ToRequestBeginBlock(hash, header) res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -321,8 +321,8 @@ func (cli *grpcClient) InitChainSync(validators []*types.Validator) (err error) return cli.Error() } -func (cli *grpcClient) BeginBlockSync(header *types.Header) (err error) { - cli.BeginBlockAsync(header) +func (cli *grpcClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { + cli.BeginBlockAsync(hash, header) return cli.Error() } diff --git a/client/local_client.go b/client/local_client.go index 0ce735c8..e50763a8 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -122,14 +122,14 @@ func (app *localClient) InitChainAsync(validators []*types.Validator) *ReqRes { return reqRes } -func (app *localClient) BeginBlockAsync(header *types.Header) *ReqRes { +func (app *localClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { app.mtx.Lock() if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.BeginBlock(header) + bcApp.BeginBlock(hash, header) } app.mtx.Unlock() return app.callback( - types.ToRequestBeginBlock(header), + types.ToRequestBeginBlock(hash, header), types.ToResponseBeginBlock(), ) } @@ -208,10 +208,10 @@ func (app *localClient) InitChainSync(validators []*types.Validator) (err error) return nil } -func (app *localClient) BeginBlockSync(header *types.Header) (err error) { +func (app *localClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { app.mtx.Lock() if bcApp, ok := app.Application.(types.BlockchainAware); ok { - bcApp.BeginBlock(header) + bcApp.BeginBlock(hash, header) } app.mtx.Unlock() return nil diff --git a/client/socket_client.go b/client/socket_client.go index 18dc0b0e..01a33036 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -263,8 +263,8 @@ func (cli *socketClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.queueRequest(types.ToRequestInitChain(validators)) } -func (cli *socketClient) BeginBlockAsync(header *types.Header) *ReqRes { - return cli.queueRequest(types.ToRequestBeginBlock(header)) +func (cli *socketClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { + return cli.queueRequest(types.ToRequestBeginBlock(hash, header)) } func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { @@ -361,8 +361,8 @@ func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error return nil } -func (cli *socketClient) BeginBlockSync(header *types.Header) (err error) { - cli.queueRequest(types.ToRequestBeginBlock(header)) +func (cli *socketClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { + cli.queueRequest(types.ToRequestBeginBlock(hash, header)) cli.FlushSync() if err := cli.Error(); err != nil { return err diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 60e677e9..df46b8d1 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -47,6 +47,10 @@ func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { type PersistentDummyApplication struct { app *DummyApplication db dbm.DB + + // latest received + blockHash []byte + blockHeader *types.Header } func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { @@ -88,9 +92,16 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { func (app *PersistentDummyApplication) Commit() types.Result { // Save - hash := app.app.state.Save() - log.Info("Saved state", "root", hash) - return types.NewResultOK(hash, "") + appHash := app.app.state.Save() + log.Info("Saved state", "root", appHash) + + lastBlock := types.LastBlockInfo{ + BlockHeight: app.blockHeader.Height, + BlockHash: app.blockHash, + AppHash: appHash, // this hash will be in the next block header + } + SaveLastBlock(app.db, lastBlock) + return types.NewResultOK(appHash, "") } func (app *PersistentDummyApplication) Query(query []byte) types.Result { @@ -101,15 +112,9 @@ func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) return } -func (app *PersistentDummyApplication) BeginBlock(header *types.Header) { - // we commit the previous block state on BeginBlock because thats - // when we get the prev block hash and the app hash - lastBlock := types.LastBlockInfo{ - BlockHeight: header.Height - 1, - BlockHash: header.LastBlockHash, - AppHash: header.AppHash, - } - SaveLastBlock(app.db, lastBlock) +func (app *PersistentDummyApplication) BeginBlock(hash []byte, header *types.Header) { + app.blockHash = hash + app.blockHeader = header } func (app *PersistentDummyApplication) EndBlock(height uint64) (diffs []*types.Validator) { diff --git a/server/socket_server.go b/server/socket_server.go index fb141aa9..43b4ed63 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -192,7 +192,7 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types responses <- types.ToResponseInitChain() case *types.Request_BeginBlock: if app, ok := s.app.(types.BlockchainAware); ok { - app.BeginBlock(r.BeginBlock.Header) + app.BeginBlock(r.BeginBlock.Hash, r.BeginBlock.Header) } responses <- types.ToResponseBeginBlock() case *types.Request_EndBlock: diff --git a/types/application.go b/types/application.go index ba6565f5..0137f1e1 100644 --- a/types/application.go +++ b/types/application.go @@ -34,7 +34,7 @@ type BlockchainAware interface { InitChain(validators []*Validator) // Signals the beginning of a block - BeginBlock(header *Header) + BeginBlock(hash []byte, header *Header) // Signals the end of a block // diffs: changed validators from app to TendermintCore @@ -96,7 +96,7 @@ func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { if chainAware, ok := app.app.(BlockchainAware); ok { - chainAware.BeginBlock(req.Header) + chainAware.BeginBlock(req.Hash, req.Header) } return &ResponseBeginBlock{}, nil } diff --git a/types/messages.go b/types/messages.go index 304289e4..16e4fbd2 100644 --- a/types/messages.go +++ b/types/messages.go @@ -61,9 +61,9 @@ func ToRequestInitChain(validators []*Validator) *Request { } } -func ToRequestBeginBlock(header *Header) *Request { +func ToRequestBeginBlock(hash []byte, header *Header) *Request { return &Request{ - Value: &Request_BeginBlock{&RequestBeginBlock{header}}, + Value: &Request_BeginBlock{&RequestBeginBlock{hash, header}}, } } diff --git a/types/types.pb.go b/types/types.pb.go index d8251961..3eafb483 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -758,7 +758,8 @@ func (m *RequestInitChain) GetValidators() []*Validator { } type RequestBeginBlock struct { - Header *Header `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` } func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } @@ -766,6 +767,13 @@ func (m *RequestBeginBlock) String() string { return proto.CompactTex func (*RequestBeginBlock) ProtoMessage() {} func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (m *RequestBeginBlock) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + func (m *RequestBeginBlock) GetHeader() *Header { if m != nil { return m.Header @@ -2117,113 +2125,114 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1721 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x73, 0xdb, 0xc6, - 0x15, 0x16, 0x25, 0xde, 0x70, 0x48, 0x51, 0xab, 0xa3, 0x1b, 0xcd, 0xb6, 0x33, 0x0e, 0xea, 0x24, - 0x52, 0xea, 0xb1, 0x3b, 0xf2, 0x24, 0x63, 0x27, 0x9d, 0xcc, 0x58, 0x8e, 0x62, 0x69, 0x52, 0xc7, - 0x2a, 0xec, 0xf8, 0xa1, 0x97, 0xe1, 0x40, 0xc4, 0x92, 0x44, 0x05, 0x02, 0x30, 0xb0, 0x70, 0x28, - 0xff, 0x83, 0xfc, 0x9b, 0xbe, 0xf4, 0xa5, 0xaf, 0x7d, 0xea, 0xfd, 0xf2, 0xda, 0x3f, 0xd3, 0x39, - 0xbb, 0x8b, 0xab, 0x40, 0x3f, 0xf9, 0x85, 0x83, 0x73, 0xdd, 0xdd, 0x73, 0xf9, 0xf6, 0x2c, 0x61, - 0x5b, 0x5c, 0x87, 0x3c, 0xbe, 0x2f, 0x7f, 0xef, 0x85, 0x51, 0x20, 0x02, 0x6c, 0x49, 0xc2, 0xfc, - 0x73, 0x13, 0x3a, 0x16, 0x7f, 0x9d, 0xf0, 0x58, 0xe0, 0x21, 0x34, 0xf9, 0x64, 0x1e, 0x0c, 0x1b, - 0xb7, 0x1b, 0x87, 0xbd, 0x63, 0xbc, 0xa7, 0xd4, 0xb5, 0xf4, 0x74, 0x32, 0x0f, 0xce, 0xd6, 0x2c, - 0xa9, 0x81, 0x3f, 0x83, 0xd6, 0xd4, 0x4b, 0xe2, 0xf9, 0x70, 0x5d, 0xaa, 0xee, 0x94, 0x55, 0xbf, - 0x26, 0xd1, 0xd9, 0x9a, 0xa5, 0x74, 0xc8, 0xad, 0xeb, 0x4f, 0x83, 0xe1, 0x46, 0x9d, 0xdb, 0x73, - 0x7f, 0x2a, 0xdd, 0x92, 0x06, 0x3e, 0x04, 0x88, 0xb9, 0x18, 0x07, 0xa1, 0x70, 0x03, 0x7f, 0xd8, - 0x94, 0xfa, 0x07, 0x65, 0xfd, 0x17, 0x5c, 0x3c, 0x97, 0xe2, 0xb3, 0x35, 0xcb, 0x88, 0x53, 0x02, - 0x3f, 0x05, 0xc3, 0x0e, 0x43, 0xee, 0x3b, 0x63, 0xb1, 0x1c, 0xb6, 0xa4, 0xe1, 0x7e, 0xd9, 0xf0, - 0xb1, 0x14, 0xbf, 0x5c, 0x9e, 0xad, 0x59, 0x5d, 0x5b, 0x7f, 0xe3, 0x31, 0x74, 0x27, 0x73, 0x3e, - 0xb9, 0x22, 0xab, 0xb6, 0xb4, 0xda, 0x2b, 0x5b, 0x3d, 0x21, 0xa9, 0x34, 0xea, 0x4c, 0xd4, 0x27, - 0xde, 0x83, 0xf6, 0x24, 0x58, 0x2c, 0x5c, 0x31, 0xec, 0x48, 0x8b, 0xdd, 0x8a, 0x85, 0x94, 0x9d, - 0xad, 0x59, 0x5a, 0x8b, 0x62, 0xf5, 0x3a, 0xe1, 0xd1, 0xf5, 0xb0, 0x5b, 0x17, 0xab, 0x5f, 0x91, - 0x88, 0x62, 0x25, 0x75, 0x28, 0x02, 0xae, 0xef, 0x8a, 0xf1, 0x64, 0x6e, 0xbb, 0xfe, 0xd0, 0xa8, - 0x8b, 0xc0, 0xb9, 0xef, 0x8a, 0x27, 0x24, 0xa6, 0x08, 0xb8, 0x29, 0x81, 0x5f, 0x40, 0xef, 0x92, - 0xcf, 0x5c, 0x7f, 0x7c, 0xe9, 0x05, 0x93, 0xab, 0x21, 0x48, 0xd3, 0x61, 0xd9, 0xf4, 0x84, 0x14, - 0x4e, 0x48, 0x7e, 0xb6, 0x66, 0xc1, 0x65, 0x46, 0x51, 0xf8, 0x28, 0x76, 0xca, 0xb4, 0x57, 0x17, - 0xbe, 0x53, 0xdf, 0x49, 0x0d, 0xbb, 0x5c, 0x7f, 0x9f, 0x74, 0xa0, 0xf5, 0xc6, 0xf6, 0x12, 0x6e, - 0x7e, 0x0c, 0xbd, 0x42, 0x99, 0xe0, 0x10, 0x3a, 0x0b, 0x1e, 0xc7, 0xf6, 0x8c, 0xcb, 0x5a, 0x32, - 0xac, 0x94, 0x34, 0x07, 0xd0, 0x2f, 0x16, 0x89, 0xb9, 0x99, 0x19, 0x52, 0x21, 0x98, 0x9f, 0x03, - 0xab, 0xe6, 0x19, 0x19, 0x6c, 0x5c, 0xf1, 0x6b, 0xed, 0x88, 0x3e, 0x71, 0x57, 0x2f, 0x2b, 0xab, - 0xcf, 0xb0, 0xf4, 0x1e, 0x3e, 0x80, 0xad, 0x4a, 0xaa, 0x71, 0x00, 0xeb, 0x62, 0x29, 0x2d, 0xfb, - 0xd6, 0xba, 0x58, 0x9a, 0xb7, 0x61, 0x50, 0xce, 0xeb, 0x0d, 0x8d, 0x3b, 0xd9, 0xfe, 0x64, 0x62, - 0x68, 0x29, 0x95, 0x3c, 0xa5, 0xa2, 0x08, 0x73, 0x0b, 0x36, 0x4b, 0xd9, 0x36, 0xbf, 0xca, 0xf6, - 0x9d, 0x65, 0x07, 0x7f, 0x0e, 0xf0, 0xc6, 0xf6, 0x5c, 0xc7, 0x16, 0x41, 0x14, 0x0f, 0x1b, 0xb7, - 0x37, 0x0e, 0x7b, 0xc7, 0x4c, 0x07, 0xf5, 0x55, 0x2a, 0xb0, 0x0a, 0x3a, 0xe6, 0xe7, 0xb0, 0x7d, - 0x23, 0x51, 0xf8, 0x21, 0xb4, 0xe7, 0xdc, 0x76, 0x78, 0xa4, 0xdb, 0x72, 0x53, 0xbb, 0x38, 0x93, - 0x4c, 0x4b, 0x0b, 0xcd, 0xa3, 0xec, 0xf4, 0x69, 0xa6, 0x70, 0x9f, 0x2c, 0xdd, 0xd9, 0x5c, 0x48, - 0xcb, 0xa6, 0xa5, 0x29, 0xf3, 0x87, 0x16, 0x74, 0x2d, 0x1e, 0x87, 0x81, 0x1f, 0x73, 0x7c, 0x08, - 0x06, 0x5f, 0x4e, 0xb8, 0xea, 0xb8, 0x46, 0xa5, 0x68, 0x94, 0xce, 0x69, 0x2a, 0xa7, 0x82, 0xcb, - 0x94, 0xf1, 0x48, 0xa3, 0x45, 0x15, 0x02, 0xb4, 0x51, 0x11, 0x2e, 0xee, 0xa6, 0x70, 0xb1, 0x51, - 0xe9, 0x18, 0xa5, 0x5b, 0xc1, 0x8b, 0x23, 0x8d, 0x17, 0xcd, 0x5a, 0xc7, 0x25, 0xc0, 0x78, 0x54, - 0x02, 0x8c, 0x56, 0xed, 0xf6, 0x57, 0x20, 0xc6, 0x67, 0x45, 0xc4, 0x68, 0x57, 0x1a, 0x4d, 0x59, - 0xd6, 0x42, 0xc6, 0x83, 0x02, 0x64, 0x74, 0x2a, 0x9d, 0xa2, 0xcc, 0x6a, 0x30, 0xe3, 0x7e, 0x86, - 0x19, 0xdd, 0x0a, 0xca, 0x68, 0x93, 0x2a, 0x68, 0xdc, 0x4d, 0xeb, 0xce, 0xa8, 0x8d, 0x58, 0x05, - 0x35, 0x1e, 0x95, 0x50, 0x03, 0x6a, 0xc3, 0xb0, 0x02, 0x36, 0x7e, 0x51, 0x86, 0x0d, 0xd5, 0xfb, - 0xb7, 0x2a, 0xb6, 0x2b, 0x71, 0xe3, 0xb3, 0x22, 0x6e, 0xf4, 0x6b, 0x83, 0xf8, 0x6e, 0xe0, 0x38, - 0xa2, 0x92, 0xaf, 0x94, 0x19, 0x35, 0x1d, 0x8f, 0xa2, 0x20, 0xd2, 0x3d, 0xaf, 0x08, 0xf3, 0x90, - 0x5a, 0x33, 0x2f, 0xae, 0x77, 0x80, 0x8c, 0x6c, 0xcf, 0x42, 0x69, 0x99, 0x7f, 0x68, 0xe4, 0xb6, - 0x54, 0x3f, 0x88, 0xba, 0xc4, 0x94, 0xa1, 0xaa, 0xa5, 0xbb, 0x60, 0x88, 0x45, 0x1c, 0x8e, 0xa5, - 0x40, 0x15, 0xf5, 0x96, 0x3e, 0xcb, 0xcb, 0x67, 0x2f, 0x2e, 0xc8, 0xce, 0xea, 0x92, 0x86, 0xf4, - 0xf0, 0x00, 0xc0, 0xb3, 0x63, 0xa1, 0x8f, 0x5e, 0xae, 0xeb, 0x5f, 0xda, 0xb1, 0x90, 0xe7, 0x94, - 0x36, 0x86, 0x97, 0x92, 0x78, 0x44, 0x65, 0xe0, 0x4f, 0xdd, 0x99, 0xae, 0xed, 0x6d, 0x6d, 0xf0, - 0x44, 0x32, 0xa5, 0xb6, 0x56, 0x30, 0x3f, 0xcc, 0x03, 0x53, 0x82, 0x42, 0x2f, 0x98, 0xa5, 0x50, - 0xe8, 0x05, 0x33, 0xf3, 0x77, 0x04, 0x3c, 0xe5, 0x6a, 0xc5, 0x9f, 0x42, 0x73, 0x12, 0x38, 0x2a, - 0x2a, 0x83, 0xec, 0x0c, 0x4f, 0x02, 0x87, 0xbf, 0xbc, 0x0e, 0xb9, 0x25, 0x85, 0x14, 0x01, 0xc7, - 0x16, 0xb6, 0x3c, 0x68, 0xdf, 0x92, 0xdf, 0xa9, 0xfb, 0x8d, 0xdc, 0xfd, 0x6f, 0x09, 0x55, 0x4a, - 0x55, 0xfd, 0x3e, 0xbd, 0xff, 0x3a, 0xcf, 0x93, 0x42, 0xdb, 0xf7, 0xe8, 0xfb, 0x37, 0x04, 0xf5, - 0xc5, 0xe6, 0x7a, 0x9f, 0xce, 0x77, 0xf2, 0xe4, 0x64, 0x6d, 0x65, 0xee, 0x02, 0xde, 0xec, 0x17, - 0x75, 0xa3, 0x95, 0x3b, 0x01, 0x3f, 0x82, 0x96, 0xe3, 0x4e, 0xa7, 0xf1, 0xb0, 0xb9, 0xe2, 0x52, - 0x50, 0x62, 0xf3, 0x0e, 0x74, 0xd3, 0xca, 0xa3, 0x6a, 0x7f, 0xc5, 0xa3, 0x38, 0x45, 0x69, 0xc3, - 0x4a, 0x49, 0xd3, 0x83, 0xcd, 0x52, 0xc1, 0xe1, 0x07, 0xd0, 0x97, 0x55, 0x39, 0x2e, 0xa1, 0x7f, - 0x4f, 0xf2, 0xce, 0x24, 0x0b, 0x7f, 0x02, 0xa0, 0x55, 0x6c, 0x3d, 0xc4, 0xf5, 0x2d, 0x43, 0x29, - 0xd8, 0xf1, 0x1c, 0x6f, 0x01, 0xe1, 0x9d, 0x12, 0x6e, 0x48, 0x61, 0xc7, 0x0e, 0x43, 0x12, 0x99, - 0xc7, 0x00, 0x79, 0xb5, 0xe2, 0x1d, 0x18, 0x2c, 0xec, 0xa5, 0x6a, 0x82, 0x71, 0xec, 0xbe, 0xe5, - 0x7a, 0xb1, 0xfe, 0xc2, 0x5e, 0xca, 0x0d, 0xbd, 0x70, 0xdf, 0x72, 0xf3, 0x7f, 0xeb, 0xd0, 0x56, - 0xd7, 0x15, 0x79, 0x96, 0x20, 0x35, 0x76, 0x9d, 0xf4, 0x1c, 0x92, 0x3e, 0x77, 0x0a, 0xd7, 0xd5, - 0x7a, 0xf1, 0xba, 0xa2, 0x94, 0x08, 0x77, 0xc1, 0xe5, 0x46, 0x9a, 0x96, 0xfc, 0xc6, 0x03, 0xe8, - 0xf8, 0xc9, 0x62, 0x2c, 0x96, 0xb1, 0xec, 0xa4, 0xa6, 0xd5, 0xf6, 0x93, 0xc5, 0xcb, 0x65, 0x8c, - 0x1f, 0xc1, 0x56, 0xde, 0x96, 0xea, 0x00, 0x2d, 0x79, 0x80, 0xcd, 0xac, 0x0b, 0xe5, 0x09, 0xbf, - 0x04, 0x56, 0xd0, 0x0b, 0xed, 0x48, 0xc4, 0xfa, 0x12, 0x48, 0x9b, 0xf8, 0xc2, 0x8e, 0x68, 0x08, - 0xd1, 0xd7, 0xec, 0x20, 0x33, 0x27, 0x7e, 0x8c, 0x87, 0xda, 0x5e, 0xc1, 0xb5, 0x5a, 0xa8, 0x23, - 0x17, 0x92, 0x9a, 0x1a, 0xcf, 0x69, 0xa5, 0x1f, 0x81, 0x41, 0x55, 0xa4, 0x54, 0xba, 0x52, 0xa5, - 0x4b, 0x0c, 0x29, 0xfc, 0x18, 0xb6, 0xf2, 0xfb, 0x5f, 0xa9, 0x18, 0xca, 0x4b, 0xce, 0xbe, 0x91, - 0x11, 0x28, 0x67, 0xe4, 0x11, 0x6c, 0x96, 0xf6, 0x4a, 0xf0, 0x29, 0x02, 0x61, 0x7b, 0x3a, 0x17, - 0x8a, 0xa0, 0x30, 0x16, 0x92, 0x2d, 0xbf, 0xcd, 0x47, 0x60, 0x64, 0x45, 0x47, 0xf1, 0x0f, 0x93, - 0xcb, 0x6f, 0x78, 0x3a, 0xeb, 0x68, 0x8a, 0xdc, 0x85, 0xc1, 0xf7, 0x3c, 0xd2, 0x69, 0x51, 0xc4, - 0x27, 0x7f, 0x6a, 0x40, 0xef, 0x99, 0xc2, 0x5b, 0x6a, 0x1f, 0xdc, 0x82, 0xde, 0xb7, 0x89, 0xe7, - 0x69, 0x16, 0x5b, 0xc3, 0x2e, 0x34, 0x09, 0xa6, 0x59, 0x03, 0x0d, 0x68, 0x49, 0x18, 0x66, 0xeb, - 0xc4, 0xa4, 0xba, 0x61, 0x1b, 0xb8, 0x09, 0x46, 0x86, 0x6b, 0xac, 0x49, 0x64, 0x86, 0xff, 0xac, - 0x85, 0x7d, 0xe8, 0xa6, 0x70, 0xc6, 0xb6, 0xb1, 0x07, 0x1d, 0x8d, 0x3e, 0x0c, 0x11, 0xa0, 0xad, - 0xa2, 0xcb, 0x76, 0xc8, 0xb3, 0x04, 0x0e, 0xb6, 0x4b, 0x0e, 0xb2, 0x56, 0x64, 0x7b, 0x38, 0x00, - 0xc8, 0x9b, 0x90, 0xed, 0x93, 0xc3, 0xb4, 0xfd, 0xd8, 0xc1, 0x27, 0x7f, 0x6c, 0x41, 0x37, 0x6d, - 0x7c, 0x6c, 0xc3, 0xfa, 0xf3, 0x6f, 0xd8, 0x1a, 0x6e, 0xc3, 0xe6, 0xb9, 0x2f, 0x78, 0xe4, 0xdb, - 0xde, 0x29, 0x5d, 0x38, 0xac, 0x41, 0xac, 0x53, 0x7f, 0x12, 0x38, 0xae, 0x3f, 0x53, 0xac, 0x75, - 0x72, 0x74, 0x62, 0x3b, 0xdf, 0x06, 0xfe, 0x84, 0xb3, 0x0d, 0x64, 0xd0, 0xff, 0xce, 0xb7, 0x13, - 0x31, 0x0f, 0x22, 0xf7, 0x2d, 0x77, 0x58, 0x13, 0xf7, 0x60, 0xfb, 0xdc, 0x8f, 0x93, 0xe9, 0xd4, - 0x9d, 0xb8, 0xdc, 0x17, 0x5f, 0x27, 0xbe, 0x13, 0xb3, 0x16, 0x22, 0x0c, 0xbe, 0xf3, 0xaf, 0xfc, - 0xe0, 0x7b, 0x5f, 0x4f, 0x69, 0xac, 0x8d, 0x43, 0xd8, 0x3d, 0xb1, 0x63, 0xfe, 0x55, 0x12, 0x7a, - 0xee, 0xc4, 0x16, 0xfc, 0xb1, 0xe3, 0x44, 0x3c, 0x8e, 0x19, 0x27, 0x27, 0x24, 0x29, 0xaf, 0x3d, - 0x4d, 0x0d, 0x4a, 0xfe, 0x39, 0x8f, 0xd9, 0x0c, 0x6f, 0xc1, 0xde, 0x0d, 0x89, 0x5c, 0x79, 0x8e, - 0x3f, 0x86, 0x61, 0x55, 0xf4, 0xd4, 0x8e, 0x2f, 0x22, 0x77, 0xc2, 0x99, 0x8b, 0xbb, 0xc0, 0x94, - 0x54, 0xd6, 0xdb, 0xb9, 0x1f, 0x26, 0x82, 0xfd, 0x3e, 0x5d, 0x5f, 0x73, 0x9f, 0x27, 0x82, 0xd8, - 0x57, 0x15, 0xf6, 0x85, 0x2c, 0x0f, 0xe6, 0xe1, 0x01, 0xec, 0x14, 0xd8, 0x2f, 0xe8, 0x7c, 0x14, - 0x9d, 0x45, 0xbe, 0x5f, 0x25, 0x70, 0x67, 0xbe, 0x2d, 0x92, 0x88, 0x33, 0x1f, 0xf7, 0x01, 0x49, - 0xa2, 0x43, 0x92, 0x1e, 0x3c, 0x48, 0x57, 0xd0, 0x7c, 0xbd, 0x42, 0x58, 0x65, 0x7b, 0xc9, 0xcc, - 0xf5, 0xd9, 0x6b, 0xdc, 0x03, 0xf6, 0x34, 0x78, 0xa3, 0xb9, 0xa7, 0xbe, 0x70, 0xc5, 0x35, 0xfb, - 0x4b, 0x03, 0x77, 0x61, 0x2b, 0x67, 0x3f, 0x8d, 0x82, 0x24, 0x64, 0x7f, 0x6d, 0xe0, 0x01, 0x60, - 0xce, 0xbd, 0x88, 0x82, 0x30, 0x88, 0x6d, 0x8f, 0xfd, 0xad, 0x81, 0xfb, 0xb0, 0xfd, 0x34, 0x78, - 0x93, 0x65, 0x41, 0x19, 0xfc, 0x3d, 0x35, 0xc8, 0xf8, 0xcf, 0xf8, 0xe2, 0x92, 0x47, 0xec, 0x1f, - 0x0d, 0xbc, 0x05, 0xbb, 0x45, 0x41, 0xe6, 0xeb, 0x9f, 0x0d, 0xbd, 0xa3, 0x4c, 0xf4, 0x2a, 0x10, - 0x9c, 0xfd, 0x2b, 0x65, 0xeb, 0x38, 0x68, 0x47, 0xff, 0x6e, 0xe0, 0x0e, 0x0c, 0x72, 0xb6, 0xd4, - 0xfd, 0x4f, 0x03, 0x47, 0xb0, 0x57, 0x62, 0xba, 0xfe, 0xec, 0x82, 0x3a, 0x8e, 0xfd, 0xb7, 0x71, - 0xfc, 0x43, 0x0b, 0xb6, 0xe8, 0x46, 0x78, 0x1c, 0xaa, 0x05, 0x68, 0x26, 0xb8, 0xaf, 0xfa, 0x0c, - 0x6b, 0x9e, 0xeb, 0xa3, 0xba, 0xa1, 0x1c, 0x8f, 0x75, 0x3b, 0x62, 0xdd, 0xab, 0x7d, 0x54, 0x3b, - 0x9b, 0xd3, 0x22, 0x6a, 0x6e, 0xba, 0xf9, 0x78, 0x1f, 0xd5, 0x0d, 0xe8, 0xf8, 0x65, 0xa1, 0xbd, - 0x71, 0xd5, 0x13, 0x7e, 0xb4, 0x72, 0x54, 0xc7, 0x2f, 0x72, 0x00, 0xc0, 0x15, 0x0f, 0xf9, 0xd1, - 0xaa, 0x71, 0x1d, 0x1f, 0x66, 0x78, 0x81, 0xf5, 0xcf, 0xf9, 0xd1, 0x8a, 0x91, 0x9d, 0x62, 0xa3, - 0x26, 0x91, 0xba, 0x57, 0xfa, 0xa8, 0x76, 0x0a, 0xc7, 0x4f, 0x53, 0x40, 0xc2, 0xda, 0x7f, 0x02, - 0x46, 0xf5, 0xb3, 0x3e, 0x45, 0x28, 0x7f, 0x2b, 0xae, 0x7a, 0xe2, 0x8f, 0x56, 0x4e, 0xf1, 0xf8, - 0xb8, 0x88, 0x70, 0xb8, 0xf2, 0xa1, 0x3f, 0x5a, 0x3d, 0xcb, 0x53, 0x90, 0xf3, 0xc7, 0x62, 0xfd, - 0x73, 0x7f, 0xb4, 0x6a, 0x9c, 0xbf, 0x6c, 0xcb, 0xbf, 0x91, 0x1e, 0xfc, 0x3f, 0x00, 0x00, 0xff, - 0xff, 0x89, 0x5e, 0xff, 0xe3, 0x5b, 0x12, 0x00, 0x00, + // 1732 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0x1b, 0xc7, + 0x15, 0x26, 0x40, 0xac, 0x0f, 0x20, 0xd8, 0x7c, 0xdc, 0x20, 0x24, 0xa9, 0x92, 0x27, 0xb2, 0x4d, + 0x3a, 0x2a, 0x29, 0x45, 0x95, 0x5d, 0x52, 0x9c, 0x72, 0x95, 0x28, 0xd3, 0x02, 0xcb, 0x91, 0xc4, + 0x8c, 0x64, 0x1d, 0xb2, 0x14, 0x6a, 0x88, 0x69, 0x00, 0x13, 0x0e, 0x66, 0x46, 0x33, 0x3d, 0x32, + 0xa8, 0x7f, 0xe0, 0x7f, 0x93, 0x4b, 0x2e, 0xb9, 0xe6, 0x94, 0x7d, 0xb9, 0xe6, 0xcf, 0xb8, 0x5e, + 0x77, 0xcf, 0xca, 0x81, 0x4f, 0xba, 0xa0, 0xe6, 0xad, 0xdd, 0xfd, 0x96, 0xaf, 0x5f, 0x03, 0x76, + 0xc4, 0x75, 0xc0, 0xa3, 0xfb, 0xf2, 0xf7, 0x5e, 0x10, 0xfa, 0xc2, 0xc7, 0xa6, 0x24, 0x8c, 0xbf, + 0x34, 0xa0, 0x6d, 0xf2, 0x37, 0x31, 0x8f, 0x04, 0x1e, 0x41, 0x83, 0x4f, 0x17, 0xfe, 0xb0, 0x76, + 0xbb, 0x76, 0xd4, 0x3b, 0xc1, 0x7b, 0x4a, 0x5d, 0x4b, 0xcf, 0xa6, 0x0b, 0x7f, 0xbc, 0x61, 0x4a, + 0x0d, 0xfc, 0x19, 0x34, 0x67, 0x6e, 0x1c, 0x2d, 0x86, 0x75, 0xa9, 0xba, 0x5b, 0x54, 0xfd, 0x8a, + 0x44, 0xe3, 0x0d, 0x53, 0xe9, 0x90, 0x5b, 0xc7, 0x9b, 0xf9, 0xc3, 0xcd, 0x2a, 0xb7, 0xe7, 0xde, + 0x4c, 0xba, 0x25, 0x0d, 0x7c, 0x08, 0x10, 0x71, 0x31, 0xf1, 0x03, 0xe1, 0xf8, 0xde, 0xb0, 0x21, + 0xf5, 0x0f, 0x8b, 0xfa, 0x2f, 0xb9, 0x78, 0x21, 0xc5, 0xe3, 0x0d, 0xb3, 0x1b, 0x25, 0x04, 0x7e, + 0x0a, 0x5d, 0x2b, 0x08, 0xb8, 0x67, 0x4f, 0xc4, 0x6a, 0xd8, 0x94, 0x86, 0x07, 0x45, 0xc3, 0xc7, + 0x52, 0xfc, 0x6a, 0x35, 0xde, 0x30, 0x3b, 0x96, 0xfe, 0xc6, 0x13, 0xe8, 0x4c, 0x17, 0x7c, 0x7a, + 0x45, 0x56, 0x2d, 0x69, 0xb5, 0x5f, 0xb4, 0x7a, 0x42, 0x52, 0x69, 0xd4, 0x9e, 0xaa, 0x4f, 0xbc, + 0x07, 0xad, 0xa9, 0xbf, 0x5c, 0x3a, 0x62, 0xd8, 0x96, 0x16, 0x7b, 0x25, 0x0b, 0x29, 0x1b, 0x6f, + 0x98, 0x5a, 0x8b, 0x62, 0xf5, 0x26, 0xe6, 0xe1, 0xf5, 0xb0, 0x53, 0x15, 0xab, 0x5f, 0x93, 0x88, + 0x62, 0x25, 0x75, 0x28, 0x02, 0x8e, 0xe7, 0x88, 0xc9, 0x74, 0x61, 0x39, 0xde, 0xb0, 0x5b, 0x15, + 0x81, 0x73, 0xcf, 0x11, 0x4f, 0x48, 0x4c, 0x11, 0x70, 0x12, 0x02, 0x3f, 0x87, 0xde, 0x25, 0x9f, + 0x3b, 0xde, 0xe4, 0xd2, 0xf5, 0xa7, 0x57, 0x43, 0x90, 0xa6, 0xc3, 0xa2, 0xe9, 0x29, 0x29, 0x9c, + 0x92, 0x7c, 0xbc, 0x61, 0xc2, 0x65, 0x4a, 0x51, 0xf8, 0x28, 0x76, 0xca, 0xb4, 0x57, 0x15, 0xbe, + 0x33, 0xcf, 0x4e, 0x0c, 0x3b, 0x5c, 0x7f, 0x9f, 0xb6, 0xa1, 0xf9, 0xd6, 0x72, 0x63, 0x6e, 0x7c, + 0x0c, 0xbd, 0x5c, 0x99, 0xe0, 0x10, 0xda, 0x4b, 0x1e, 0x45, 0xd6, 0x9c, 0xcb, 0x5a, 0xea, 0x9a, + 0x09, 0x69, 0x0c, 0xa0, 0x9f, 0x2f, 0x12, 0x63, 0x2b, 0x35, 0xa4, 0x42, 0x30, 0x7e, 0x01, 0xac, + 0x9c, 0x67, 0x64, 0xb0, 0x79, 0xc5, 0xaf, 0xb5, 0x23, 0xfa, 0xc4, 0x3d, 0xbd, 0xac, 0xac, 0xbe, + 0xae, 0xa9, 0xf7, 0xf0, 0x01, 0x6c, 0x97, 0x52, 0x8d, 0x03, 0xa8, 0x8b, 0x95, 0xb4, 0xec, 0x9b, + 0x75, 0xb1, 0x32, 0x6e, 0xc3, 0xa0, 0x98, 0xd7, 0x1b, 0x1a, 0x77, 0xd2, 0xfd, 0xc9, 0xc4, 0xd0, + 0x52, 0x2a, 0x79, 0x4a, 0x45, 0x11, 0xc6, 0x36, 0x6c, 0x15, 0xb2, 0x6d, 0x7c, 0x99, 0xee, 0x3b, + 0xcd, 0x0e, 0xfe, 0x1c, 0xe0, 0xad, 0xe5, 0x3a, 0xb6, 0x25, 0xfc, 0x30, 0x1a, 0xd6, 0x6e, 0x6f, + 0x1e, 0xf5, 0x4e, 0x98, 0x0e, 0xea, 0xeb, 0x44, 0x60, 0xe6, 0x74, 0x8c, 0xe7, 0xb0, 0x73, 0x23, + 0x51, 0x88, 0xd0, 0x58, 0x58, 0xd1, 0x42, 0x6f, 0x40, 0x7e, 0xe3, 0x87, 0xd0, 0x5a, 0x70, 0xcb, + 0xe6, 0xa1, 0xee, 0xbf, 0x2d, 0xed, 0x76, 0x2c, 0x99, 0xa6, 0x16, 0x1a, 0xc7, 0x69, 0x44, 0x92, + 0xec, 0xe1, 0x01, 0x59, 0x3a, 0xf3, 0x85, 0x90, 0xfe, 0x1a, 0xa6, 0xa6, 0x8c, 0xef, 0x9a, 0xd0, + 0x31, 0x79, 0x14, 0xf8, 0x5e, 0xc4, 0xf1, 0x21, 0x74, 0xf9, 0x6a, 0xca, 0x55, 0x17, 0xd6, 0x4a, + 0x85, 0xa4, 0x74, 0xce, 0x12, 0x39, 0x15, 0x61, 0xaa, 0x8c, 0xc7, 0x1a, 0x41, 0xca, 0xb0, 0xa0, + 0x8d, 0xf2, 0x10, 0x72, 0x37, 0x81, 0x90, 0xcd, 0x52, 0x17, 0x29, 0xdd, 0x12, 0x86, 0x1c, 0x6b, + 0x0c, 0x69, 0x54, 0x3a, 0x2e, 0x80, 0xc8, 0xa3, 0x02, 0x88, 0x34, 0x2b, 0xb7, 0xbf, 0x06, 0x45, + 0x3e, 0xcb, 0xa3, 0x48, 0xab, 0xd4, 0x7c, 0xca, 0xb2, 0x12, 0x46, 0x1e, 0xe4, 0x60, 0xa4, 0x5d, + 0xea, 0x1e, 0x65, 0x56, 0x81, 0x23, 0xf7, 0x53, 0x1c, 0xe9, 0x94, 0x90, 0x47, 0x9b, 0x94, 0x81, + 0xe4, 0x6e, 0x52, 0x8b, 0xdd, 0xca, 0x88, 0x95, 0x90, 0xe4, 0x51, 0x01, 0x49, 0xa0, 0x32, 0x0c, + 0x6b, 0xa0, 0xe4, 0x97, 0x45, 0x28, 0x51, 0x78, 0x70, 0xab, 0x64, 0xbb, 0x16, 0x4b, 0x3e, 0xcb, + 0x63, 0x49, 0xbf, 0x32, 0x88, 0x3f, 0x0c, 0x26, 0xc7, 0xd4, 0x06, 0xa5, 0x32, 0xa3, 0x46, 0xe4, + 0x61, 0xe8, 0x87, 0x1a, 0x07, 0x14, 0x61, 0x1c, 0x51, 0xbb, 0x66, 0xc5, 0xf5, 0x03, 0xc0, 0x23, + 0x5b, 0x36, 0x57, 0x5a, 0xc6, 0x1f, 0x6b, 0x99, 0x2d, 0xd5, 0x0f, 0x35, 0x9a, 0x2c, 0x31, 0x65, + 0xa8, 0x6a, 0xe9, 0x2e, 0x74, 0xc5, 0x32, 0x0a, 0x26, 0x52, 0xa0, 0x8a, 0x7a, 0x5b, 0x9f, 0xe5, + 0xd5, 0xb3, 0x97, 0x17, 0x64, 0x67, 0x76, 0x48, 0x43, 0x7a, 0x78, 0x00, 0xe0, 0x5a, 0x91, 0xd0, + 0x47, 0x2f, 0xd6, 0xf5, 0xaf, 0xac, 0x48, 0xc8, 0x73, 0x4a, 0x9b, 0xae, 0x9b, 0x90, 0x78, 0x4c, + 0x65, 0xe0, 0xcd, 0x9c, 0xb9, 0xae, 0xed, 0x1d, 0x6d, 0xf0, 0x44, 0x32, 0xa5, 0xb6, 0x56, 0x30, + 0x3e, 0xcc, 0x02, 0x53, 0x80, 0x47, 0xd7, 0x9f, 0x27, 0xf0, 0xe8, 0xfa, 0x73, 0xe3, 0xf7, 0x04, + 0x46, 0xc5, 0x6a, 0xc5, 0x9f, 0x42, 0x63, 0xea, 0xdb, 0x2a, 0x2a, 0x83, 0xf4, 0x0c, 0x4f, 0x7c, + 0x9b, 0xbf, 0xba, 0x0e, 0xb8, 0x29, 0x85, 0x14, 0x01, 0xdb, 0x12, 0x96, 0x3c, 0x68, 0xdf, 0x94, + 0xdf, 0x89, 0xfb, 0xcd, 0xcc, 0xfd, 0xef, 0x08, 0x55, 0x0a, 0x55, 0xfd, 0x3e, 0xbd, 0xff, 0x26, + 0xcb, 0x93, 0x42, 0xe0, 0xf7, 0xe8, 0xfb, 0xb7, 0x04, 0xff, 0xf9, 0xe6, 0x7a, 0x9f, 0xce, 0x77, + 0xb3, 0xe4, 0xa4, 0x6d, 0x65, 0xec, 0x01, 0xde, 0xec, 0x17, 0x75, 0xcb, 0x15, 0x3b, 0x01, 0x3f, + 0x82, 0xa6, 0xed, 0xcc, 0x66, 0xd1, 0xb0, 0xb1, 0xe6, 0xa2, 0x50, 0x62, 0xe3, 0x0e, 0x74, 0x92, + 0xca, 0xa3, 0x6a, 0x7f, 0xcd, 0xc3, 0x28, 0x41, 0xe9, 0xae, 0x99, 0x90, 0x86, 0x0b, 0x5b, 0x85, + 0x82, 0xc3, 0x0f, 0xa0, 0x2f, 0xab, 0x72, 0x52, 0x40, 0xff, 0x9e, 0xe4, 0x8d, 0x25, 0x0b, 0x7f, + 0x02, 0xa0, 0x55, 0x2c, 0x3d, 0xd8, 0xf5, 0xcd, 0xae, 0x52, 0xa0, 0x3b, 0xe7, 0x16, 0x10, 0xde, + 0x29, 0xe1, 0xa6, 0x14, 0xb6, 0xad, 0x20, 0x20, 0x91, 0x71, 0x02, 0x90, 0x55, 0x2b, 0xde, 0x81, + 0xc1, 0xd2, 0x5a, 0xa9, 0x26, 0x98, 0x44, 0xce, 0x3b, 0xae, 0x17, 0xeb, 0x2f, 0xad, 0x95, 0xdc, + 0xd0, 0x4b, 0xe7, 0x1d, 0x37, 0xfe, 0x5f, 0x87, 0x96, 0xba, 0xae, 0xc8, 0xb3, 0x04, 0xa9, 0x89, + 0x63, 0x27, 0xe7, 0x90, 0xf4, 0xb9, 0x9d, 0xbb, 0xae, 0xea, 0xf9, 0xeb, 0x8a, 0x52, 0x22, 0x9c, + 0x25, 0x97, 0x1b, 0x69, 0x98, 0xf2, 0x1b, 0x0f, 0xa1, 0xed, 0xc5, 0xcb, 0x89, 0x58, 0x45, 0xb2, + 0x93, 0x1a, 0x66, 0xcb, 0x8b, 0x97, 0xaf, 0x56, 0x11, 0x7e, 0x04, 0xdb, 0x59, 0x5b, 0xaa, 0x03, + 0x34, 0xe5, 0x01, 0xb6, 0xd2, 0x2e, 0x94, 0x27, 0xfc, 0x02, 0x58, 0x4e, 0x2f, 0xb0, 0x42, 0x11, + 0xe9, 0x4b, 0x20, 0x69, 0xe2, 0x0b, 0x2b, 0xa4, 0xc1, 0x44, 0x5f, 0xb3, 0x83, 0xd4, 0x9c, 0xf8, + 0x11, 0x1e, 0x69, 0x7b, 0x05, 0xd7, 0x6a, 0xa1, 0xb6, 0x5c, 0x48, 0x6a, 0x6a, 0x3c, 0xa7, 0x95, + 0x7e, 0x04, 0x5d, 0xaa, 0x22, 0xa5, 0xd2, 0x91, 0x2a, 0x1d, 0x62, 0x48, 0xe1, 0xc7, 0xb0, 0x9d, + 0xcd, 0x04, 0x4a, 0xa5, 0xab, 0xbc, 0x64, 0xec, 0x1b, 0x19, 0x81, 0x62, 0x46, 0x1e, 0xc1, 0x56, + 0x61, 0xaf, 0x04, 0x9f, 0xc2, 0x17, 0x96, 0xab, 0x73, 0xa1, 0x88, 0x74, 0xb6, 0xa8, 0x67, 0xb3, + 0x85, 0xf1, 0x08, 0xba, 0x69, 0xd1, 0x51, 0xfc, 0x83, 0xf8, 0xf2, 0x6b, 0x9e, 0xcc, 0x3f, 0x9a, + 0x22, 0x77, 0x81, 0xff, 0xad, 0x9e, 0x3f, 0x1a, 0xa6, 0x22, 0x3e, 0xf9, 0x73, 0x0d, 0x7a, 0xcf, + 0x14, 0xde, 0x52, 0xfb, 0xe0, 0x36, 0xf4, 0x9e, 0xc7, 0xae, 0xab, 0x59, 0x6c, 0x03, 0x3b, 0xd0, + 0x20, 0x98, 0x66, 0x35, 0xec, 0x42, 0x53, 0xc2, 0x30, 0xab, 0x13, 0x93, 0xea, 0x86, 0x6d, 0xe2, + 0x16, 0x74, 0x53, 0x5c, 0x63, 0x0d, 0x22, 0x53, 0xfc, 0x67, 0x4d, 0xec, 0x43, 0x27, 0x81, 0x33, + 0xb6, 0x83, 0x3d, 0x68, 0x6b, 0xf4, 0x61, 0x88, 0x00, 0x2d, 0x15, 0x5d, 0xb6, 0x4b, 0x9e, 0x25, + 0x70, 0xb0, 0x3d, 0x72, 0x90, 0xb6, 0x22, 0xdb, 0xc7, 0x01, 0x40, 0xd6, 0x84, 0xec, 0x80, 0x1c, + 0x26, 0xed, 0xc7, 0x0e, 0x3f, 0xf9, 0x53, 0x13, 0x3a, 0x49, 0xe3, 0x63, 0x0b, 0xea, 0x2f, 0xbe, + 0x66, 0x1b, 0xb8, 0x03, 0x5b, 0xe7, 0x9e, 0xe0, 0xa1, 0x67, 0xb9, 0x67, 0x74, 0xe1, 0xb0, 0x1a, + 0xb1, 0xce, 0xbc, 0xa9, 0x6f, 0x3b, 0xde, 0x5c, 0xb1, 0xea, 0xe4, 0xe8, 0xd4, 0xb2, 0x9f, 0xfb, + 0xde, 0x94, 0xb3, 0x4d, 0x64, 0xd0, 0xff, 0xc6, 0xb3, 0x62, 0xb1, 0xf0, 0x43, 0xe7, 0x1d, 0xb7, + 0x59, 0x03, 0xf7, 0x61, 0xe7, 0xdc, 0x8b, 0xe2, 0xd9, 0xcc, 0x99, 0x3a, 0xdc, 0x13, 0x5f, 0xc5, + 0x9e, 0x1d, 0xb1, 0x26, 0x22, 0x0c, 0xbe, 0xf1, 0xae, 0x3c, 0xff, 0x5b, 0x4f, 0x4f, 0x69, 0xac, + 0x85, 0x43, 0xd8, 0x3b, 0xb5, 0x22, 0xfe, 0x65, 0x1c, 0xb8, 0xce, 0xd4, 0x12, 0xfc, 0xb1, 0x6d, + 0x87, 0x3c, 0x8a, 0x18, 0x27, 0x27, 0x24, 0x29, 0xae, 0x3d, 0x4b, 0x0c, 0x0a, 0xfe, 0x39, 0x8f, + 0xd8, 0x1c, 0x6f, 0xc1, 0xfe, 0x0d, 0x89, 0x5c, 0x79, 0x81, 0x3f, 0x86, 0x61, 0x59, 0xf4, 0xd4, + 0x8a, 0x2e, 0x42, 0x67, 0xca, 0x99, 0x83, 0x7b, 0xc0, 0x94, 0x54, 0xd6, 0xdb, 0xb9, 0x17, 0xc4, + 0x82, 0xfd, 0x21, 0x59, 0x5f, 0x73, 0x5f, 0xc4, 0x82, 0xd8, 0x57, 0x25, 0xf6, 0x85, 0x2c, 0x0f, + 0xe6, 0xe2, 0x21, 0xec, 0xe6, 0xd8, 0x2f, 0xe9, 0x7c, 0x14, 0x9d, 0x65, 0xb6, 0x5f, 0x25, 0x70, + 0xe6, 0x9e, 0x25, 0xe2, 0x90, 0x33, 0x0f, 0x0f, 0x00, 0x49, 0xa2, 0x43, 0x92, 0x1c, 0xdc, 0x4f, + 0x56, 0xd0, 0x7c, 0xbd, 0x42, 0x50, 0x66, 0xbb, 0xf1, 0xdc, 0xf1, 0xd8, 0x1b, 0xdc, 0x07, 0xf6, + 0xd4, 0x7f, 0xab, 0xb9, 0x67, 0x9e, 0x70, 0xc4, 0x35, 0xfb, 0x6b, 0x0d, 0xf7, 0x60, 0x3b, 0x63, + 0x3f, 0x0d, 0xfd, 0x38, 0x60, 0x7f, 0xab, 0xe1, 0x21, 0x60, 0xc6, 0xbd, 0x08, 0xfd, 0xc0, 0x8f, + 0x2c, 0x97, 0xfd, 0xbd, 0x86, 0x07, 0xb0, 0xf3, 0xd4, 0x7f, 0x9b, 0x66, 0x41, 0x19, 0xfc, 0x23, + 0x31, 0x48, 0xf9, 0xcf, 0xf8, 0xf2, 0x92, 0x87, 0xec, 0x9f, 0x35, 0xbc, 0x05, 0x7b, 0x79, 0x41, + 0xea, 0xeb, 0x5f, 0x35, 0xbd, 0xa3, 0x54, 0xf4, 0xda, 0x17, 0x9c, 0xfd, 0x3b, 0x61, 0xeb, 0x38, + 0x68, 0x47, 0xff, 0xa9, 0xe1, 0x2e, 0x0c, 0x32, 0xb6, 0xd4, 0xfd, 0x6f, 0x0d, 0x47, 0xb0, 0x5f, + 0x60, 0x3a, 0xde, 0xfc, 0x82, 0x3a, 0x8e, 0xfd, 0xaf, 0x76, 0xf2, 0x5d, 0x13, 0xb6, 0xe9, 0x46, + 0x78, 0x1c, 0xa8, 0x05, 0x68, 0x26, 0xb8, 0xaf, 0xfa, 0x0c, 0x2b, 0x9e, 0xf0, 0xa3, 0xaa, 0xa1, + 0x1c, 0x4f, 0x74, 0x3b, 0x62, 0xd5, 0x4b, 0x7e, 0x54, 0x39, 0x9b, 0xd3, 0x22, 0x6a, 0x6e, 0xba, + 0xf9, 0xa0, 0x1f, 0x55, 0x0d, 0xe8, 0xf8, 0x45, 0xae, 0xbd, 0x71, 0xdd, 0xb3, 0x7e, 0xb4, 0x76, + 0x54, 0xc7, 0xcf, 0x33, 0x00, 0xc0, 0x35, 0x8f, 0xfb, 0xd1, 0xba, 0x71, 0x1d, 0x1f, 0xa6, 0x78, + 0x81, 0xd5, 0x4f, 0xfc, 0xd1, 0x9a, 0x91, 0x9d, 0x62, 0xa3, 0x26, 0x91, 0xaa, 0x97, 0xfb, 0xa8, + 0x72, 0x0a, 0xc7, 0x4f, 0x13, 0x40, 0xc2, 0xca, 0x7f, 0x07, 0x46, 0xd5, 0xb3, 0x3e, 0x45, 0x28, + 0x7b, 0x3f, 0xae, 0x7b, 0xf6, 0x8f, 0xd6, 0x4e, 0xf1, 0xf8, 0x38, 0x8f, 0x70, 0xb8, 0xf6, 0xf1, + 0x3f, 0x5a, 0x3f, 0xcb, 0x53, 0x90, 0xb3, 0xc7, 0x62, 0xf5, 0x5f, 0x00, 0xa3, 0x75, 0xe3, 0xfc, + 0x65, 0x4b, 0xfe, 0xb5, 0xf4, 0xe0, 0xfb, 0x00, 0x00, 0x00, 0xff, 0xff, 0x70, 0x47, 0x17, 0xd1, + 0x6f, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index e2c7d9b4..7b6a7915 100644 --- a/types/types.proto +++ b/types/types.proto @@ -124,7 +124,8 @@ message RequestInitChain{ } message RequestBeginBlock{ - Header header = 1; + bytes hash = 1; + Header header = 2; } message RequestEndBlock{ From df299d03c4a3c151a4afa949e45d7e5f3e43d08e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 6 Nov 2016 02:02:08 +0000 Subject: [PATCH 145/545] block_height is int32 --- example/dummy/persistent_dummy.go | 64 +++++++++++++++---------------- types/types.proto | 2 +- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index df46b8d1..cb2171f5 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -10,38 +10,6 @@ import ( "github.com/tendermint/tmsp/types" ) -//----------------------------------------- -// persist the last block info - -var lastBlockKey = []byte("lastblock") - -// Get the last block from the db -func LoadLastBlock(db dbm.DB) (lastBlock types.LastBlockInfo) { - buf := db.Get(lastBlockKey) - if len(buf) != 0 { - r, n, err := bytes.NewReader(buf), new(int), new(error) - 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)) - } - // TODO: ensure that buf is completely read. - } - - return lastBlock -} - -func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { - log.Notice("Saving block", "height", lastBlock.BlockHeight, "hash", lastBlock.BlockHash, "root", lastBlock.AppHash) - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(lastBlock, buf, n, err) - if *err != nil { - // TODO - PanicCrisis(*err) - } - db.Set(lastBlockKey, buf.Bytes()) -} - //----------------------------------------- type PersistentDummyApplication struct { @@ -120,3 +88,35 @@ func (app *PersistentDummyApplication) BeginBlock(hash []byte, header *types.Hea func (app *PersistentDummyApplication) EndBlock(height uint64) (diffs []*types.Validator) { return nil } + +//----------------------------------------- +// persist the last block info + +var lastBlockKey = []byte("lastblock") + +// Get the last block from the db +func LoadLastBlock(db dbm.DB) (lastBlock types.LastBlockInfo) { + buf := db.Get(lastBlockKey) + if len(buf) != 0 { + r, n, err := bytes.NewReader(buf), new(int), new(error) + 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)) + } + // TODO: ensure that buf is completely read. + } + + return lastBlock +} + +func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { + log.Notice("Saving block", "height", lastBlock.BlockHeight, "hash", lastBlock.BlockHash, "root", lastBlock.AppHash) + buf, n, err := new(bytes.Buffer), new(int), new(error) + wire.WriteBinary(lastBlock, buf, n, err) + if *err != nil { + // TODO + PanicCrisis(*err) + } + db.Set(lastBlockKey, buf.Bytes()) +} diff --git a/types/types.proto b/types/types.proto index 7b6a7915..6633d4e3 100644 --- a/types/types.proto +++ b/types/types.proto @@ -219,7 +219,7 @@ message TMSPInfo { } message LastBlockInfo { - uint64 block_height = 1; + int32 block_height = 1; bytes block_hash = 2; bytes app_hash = 3; } From 60e0842ef9a87c840d0bf95eea7b54a1e3d312b3 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 16 Nov 2016 16:11:36 -0500 Subject: [PATCH 146/545] Header.LastBlockID --- types/types.pb.go | 287 ++++++++++++++++++++++++---------------------- types/types.proto | 18 +-- 2 files changed, 164 insertions(+), 141 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index 3eafb483..0b3248a3 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -38,6 +38,7 @@ It has these top-level messages: LastBlockInfo ConfigInfo Header + BlockID PartSetHeader Validator */ @@ -1501,7 +1502,7 @@ func (m *TMSPInfo) GetVersion() string { } type LastBlockInfo struct { - BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` + BlockHeight int32 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` BlockHash []byte `protobuf:"bytes,2,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } @@ -1511,7 +1512,7 @@ func (m *LastBlockInfo) String() string { return proto.CompactTextStr func (*LastBlockInfo) ProtoMessage() {} func (*LastBlockInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } -func (m *LastBlockInfo) GetBlockHeight() uint64 { +func (m *LastBlockInfo) GetBlockHeight() int32 { if m != nil { return m.BlockHeight } @@ -1549,16 +1550,15 @@ func (m *ConfigInfo) GetMaxBlockSize() uint64 { } type Header struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` - Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` - Time uint64 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"` - NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs" json:"num_txs,omitempty"` - LastBlockHash []byte `protobuf:"bytes,5,opt,name=last_block_hash,json=lastBlockHash,proto3" json:"last_block_hash,omitempty"` - LastBlockParts *PartSetHeader `protobuf:"bytes,6,opt,name=last_block_parts,json=lastBlockParts" json:"last_block_parts,omitempty"` - LastCommitHash []byte `protobuf:"bytes,7,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` - DataHash []byte `protobuf:"bytes,8,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` - ValidatorsHash []byte `protobuf:"bytes,9,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` - AppHash []byte `protobuf:"bytes,10,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` + Height int32 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` + Time uint64 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"` + NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs" json:"num_txs,omitempty"` + LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` + LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` + DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` + ValidatorsHash []byte `protobuf:"bytes,8,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` + AppHash []byte `protobuf:"bytes,9,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } func (m *Header) Reset() { *m = Header{} } @@ -1573,7 +1573,7 @@ func (m *Header) GetChainId() string { return "" } -func (m *Header) GetHeight() uint64 { +func (m *Header) GetHeight() int32 { if m != nil { return m.Height } @@ -1594,16 +1594,9 @@ func (m *Header) GetNumTxs() uint64 { return 0 } -func (m *Header) GetLastBlockHash() []byte { +func (m *Header) GetLastBlockId() *BlockID { if m != nil { - return m.LastBlockHash - } - return nil -} - -func (m *Header) GetLastBlockParts() *PartSetHeader { - if m != nil { - return m.LastBlockParts + return m.LastBlockId } return nil } @@ -1636,6 +1629,30 @@ func (m *Header) GetAppHash() []byte { return nil } +type BlockID struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Parts *PartSetHeader `protobuf:"bytes,2,opt,name=parts" json:"parts,omitempty"` +} + +func (m *BlockID) Reset() { *m = BlockID{} } +func (m *BlockID) String() string { return proto.CompactTextString(m) } +func (*BlockID) ProtoMessage() {} +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *BlockID) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *BlockID) GetParts() *PartSetHeader { + if m != nil { + return m.Parts + } + return nil +} + type PartSetHeader struct { Total uint64 `protobuf:"varint,1,opt,name=total" json:"total,omitempty"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` @@ -1644,7 +1661,7 @@ type PartSetHeader struct { func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } func (m *PartSetHeader) GetTotal() uint64 { if m != nil { @@ -1668,7 +1685,7 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1714,6 +1731,7 @@ func init() { proto.RegisterType((*LastBlockInfo)(nil), "types.LastBlockInfo") proto.RegisterType((*ConfigInfo)(nil), "types.ConfigInfo") proto.RegisterType((*Header)(nil), "types.Header") + proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) @@ -2125,114 +2143,115 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1732 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0x1b, 0xc7, - 0x15, 0x26, 0x40, 0xac, 0x0f, 0x20, 0xd8, 0x7c, 0xdc, 0x20, 0x24, 0xa9, 0x92, 0x27, 0xb2, 0x4d, - 0x3a, 0x2a, 0x29, 0x45, 0x95, 0x5d, 0x52, 0x9c, 0x72, 0x95, 0x28, 0xd3, 0x02, 0xcb, 0x91, 0xc4, - 0x8c, 0x64, 0x1d, 0xb2, 0x14, 0x6a, 0x88, 0x69, 0x00, 0x13, 0x0e, 0x66, 0x46, 0x33, 0x3d, 0x32, - 0xa8, 0x7f, 0xe0, 0x7f, 0x93, 0x4b, 0x2e, 0xb9, 0xe6, 0x94, 0x7d, 0xb9, 0xe6, 0xcf, 0xb8, 0x5e, - 0x77, 0xcf, 0xca, 0x81, 0x4f, 0xba, 0xa0, 0xe6, 0xad, 0xdd, 0xfd, 0x96, 0xaf, 0x5f, 0x03, 0x76, - 0xc4, 0x75, 0xc0, 0xa3, 0xfb, 0xf2, 0xf7, 0x5e, 0x10, 0xfa, 0xc2, 0xc7, 0xa6, 0x24, 0x8c, 0xbf, - 0x34, 0xa0, 0x6d, 0xf2, 0x37, 0x31, 0x8f, 0x04, 0x1e, 0x41, 0x83, 0x4f, 0x17, 0xfe, 0xb0, 0x76, - 0xbb, 0x76, 0xd4, 0x3b, 0xc1, 0x7b, 0x4a, 0x5d, 0x4b, 0xcf, 0xa6, 0x0b, 0x7f, 0xbc, 0x61, 0x4a, - 0x0d, 0xfc, 0x19, 0x34, 0x67, 0x6e, 0x1c, 0x2d, 0x86, 0x75, 0xa9, 0xba, 0x5b, 0x54, 0xfd, 0x8a, - 0x44, 0xe3, 0x0d, 0x53, 0xe9, 0x90, 0x5b, 0xc7, 0x9b, 0xf9, 0xc3, 0xcd, 0x2a, 0xb7, 0xe7, 0xde, - 0x4c, 0xba, 0x25, 0x0d, 0x7c, 0x08, 0x10, 0x71, 0x31, 0xf1, 0x03, 0xe1, 0xf8, 0xde, 0xb0, 0x21, - 0xf5, 0x0f, 0x8b, 0xfa, 0x2f, 0xb9, 0x78, 0x21, 0xc5, 0xe3, 0x0d, 0xb3, 0x1b, 0x25, 0x04, 0x7e, - 0x0a, 0x5d, 0x2b, 0x08, 0xb8, 0x67, 0x4f, 0xc4, 0x6a, 0xd8, 0x94, 0x86, 0x07, 0x45, 0xc3, 0xc7, - 0x52, 0xfc, 0x6a, 0x35, 0xde, 0x30, 0x3b, 0x96, 0xfe, 0xc6, 0x13, 0xe8, 0x4c, 0x17, 0x7c, 0x7a, - 0x45, 0x56, 0x2d, 0x69, 0xb5, 0x5f, 0xb4, 0x7a, 0x42, 0x52, 0x69, 0xd4, 0x9e, 0xaa, 0x4f, 0xbc, - 0x07, 0xad, 0xa9, 0xbf, 0x5c, 0x3a, 0x62, 0xd8, 0x96, 0x16, 0x7b, 0x25, 0x0b, 0x29, 0x1b, 0x6f, - 0x98, 0x5a, 0x8b, 0x62, 0xf5, 0x26, 0xe6, 0xe1, 0xf5, 0xb0, 0x53, 0x15, 0xab, 0x5f, 0x93, 0x88, - 0x62, 0x25, 0x75, 0x28, 0x02, 0x8e, 0xe7, 0x88, 0xc9, 0x74, 0x61, 0x39, 0xde, 0xb0, 0x5b, 0x15, - 0x81, 0x73, 0xcf, 0x11, 0x4f, 0x48, 0x4c, 0x11, 0x70, 0x12, 0x02, 0x3f, 0x87, 0xde, 0x25, 0x9f, - 0x3b, 0xde, 0xe4, 0xd2, 0xf5, 0xa7, 0x57, 0x43, 0x90, 0xa6, 0xc3, 0xa2, 0xe9, 0x29, 0x29, 0x9c, - 0x92, 0x7c, 0xbc, 0x61, 0xc2, 0x65, 0x4a, 0x51, 0xf8, 0x28, 0x76, 0xca, 0xb4, 0x57, 0x15, 0xbe, - 0x33, 0xcf, 0x4e, 0x0c, 0x3b, 0x5c, 0x7f, 0x9f, 0xb6, 0xa1, 0xf9, 0xd6, 0x72, 0x63, 0x6e, 0x7c, - 0x0c, 0xbd, 0x5c, 0x99, 0xe0, 0x10, 0xda, 0x4b, 0x1e, 0x45, 0xd6, 0x9c, 0xcb, 0x5a, 0xea, 0x9a, - 0x09, 0x69, 0x0c, 0xa0, 0x9f, 0x2f, 0x12, 0x63, 0x2b, 0x35, 0xa4, 0x42, 0x30, 0x7e, 0x01, 0xac, - 0x9c, 0x67, 0x64, 0xb0, 0x79, 0xc5, 0xaf, 0xb5, 0x23, 0xfa, 0xc4, 0x3d, 0xbd, 0xac, 0xac, 0xbe, - 0xae, 0xa9, 0xf7, 0xf0, 0x01, 0x6c, 0x97, 0x52, 0x8d, 0x03, 0xa8, 0x8b, 0x95, 0xb4, 0xec, 0x9b, - 0x75, 0xb1, 0x32, 0x6e, 0xc3, 0xa0, 0x98, 0xd7, 0x1b, 0x1a, 0x77, 0xd2, 0xfd, 0xc9, 0xc4, 0xd0, - 0x52, 0x2a, 0x79, 0x4a, 0x45, 0x11, 0xc6, 0x36, 0x6c, 0x15, 0xb2, 0x6d, 0x7c, 0x99, 0xee, 0x3b, - 0xcd, 0x0e, 0xfe, 0x1c, 0xe0, 0xad, 0xe5, 0x3a, 0xb6, 0x25, 0xfc, 0x30, 0x1a, 0xd6, 0x6e, 0x6f, - 0x1e, 0xf5, 0x4e, 0x98, 0x0e, 0xea, 0xeb, 0x44, 0x60, 0xe6, 0x74, 0x8c, 0xe7, 0xb0, 0x73, 0x23, - 0x51, 0x88, 0xd0, 0x58, 0x58, 0xd1, 0x42, 0x6f, 0x40, 0x7e, 0xe3, 0x87, 0xd0, 0x5a, 0x70, 0xcb, - 0xe6, 0xa1, 0xee, 0xbf, 0x2d, 0xed, 0x76, 0x2c, 0x99, 0xa6, 0x16, 0x1a, 0xc7, 0x69, 0x44, 0x92, - 0xec, 0xe1, 0x01, 0x59, 0x3a, 0xf3, 0x85, 0x90, 0xfe, 0x1a, 0xa6, 0xa6, 0x8c, 0xef, 0x9a, 0xd0, - 0x31, 0x79, 0x14, 0xf8, 0x5e, 0xc4, 0xf1, 0x21, 0x74, 0xf9, 0x6a, 0xca, 0x55, 0x17, 0xd6, 0x4a, - 0x85, 0xa4, 0x74, 0xce, 0x12, 0x39, 0x15, 0x61, 0xaa, 0x8c, 0xc7, 0x1a, 0x41, 0xca, 0xb0, 0xa0, - 0x8d, 0xf2, 0x10, 0x72, 0x37, 0x81, 0x90, 0xcd, 0x52, 0x17, 0x29, 0xdd, 0x12, 0x86, 0x1c, 0x6b, - 0x0c, 0x69, 0x54, 0x3a, 0x2e, 0x80, 0xc8, 0xa3, 0x02, 0x88, 0x34, 0x2b, 0xb7, 0xbf, 0x06, 0x45, - 0x3e, 0xcb, 0xa3, 0x48, 0xab, 0xd4, 0x7c, 0xca, 0xb2, 0x12, 0x46, 0x1e, 0xe4, 0x60, 0xa4, 0x5d, - 0xea, 0x1e, 0x65, 0x56, 0x81, 0x23, 0xf7, 0x53, 0x1c, 0xe9, 0x94, 0x90, 0x47, 0x9b, 0x94, 0x81, - 0xe4, 0x6e, 0x52, 0x8b, 0xdd, 0xca, 0x88, 0x95, 0x90, 0xe4, 0x51, 0x01, 0x49, 0xa0, 0x32, 0x0c, - 0x6b, 0xa0, 0xe4, 0x97, 0x45, 0x28, 0x51, 0x78, 0x70, 0xab, 0x64, 0xbb, 0x16, 0x4b, 0x3e, 0xcb, - 0x63, 0x49, 0xbf, 0x32, 0x88, 0x3f, 0x0c, 0x26, 0xc7, 0xd4, 0x06, 0xa5, 0x32, 0xa3, 0x46, 0xe4, - 0x61, 0xe8, 0x87, 0x1a, 0x07, 0x14, 0x61, 0x1c, 0x51, 0xbb, 0x66, 0xc5, 0xf5, 0x03, 0xc0, 0x23, - 0x5b, 0x36, 0x57, 0x5a, 0xc6, 0x1f, 0x6b, 0x99, 0x2d, 0xd5, 0x0f, 0x35, 0x9a, 0x2c, 0x31, 0x65, - 0xa8, 0x6a, 0xe9, 0x2e, 0x74, 0xc5, 0x32, 0x0a, 0x26, 0x52, 0xa0, 0x8a, 0x7a, 0x5b, 0x9f, 0xe5, - 0xd5, 0xb3, 0x97, 0x17, 0x64, 0x67, 0x76, 0x48, 0x43, 0x7a, 0x78, 0x00, 0xe0, 0x5a, 0x91, 0xd0, - 0x47, 0x2f, 0xd6, 0xf5, 0xaf, 0xac, 0x48, 0xc8, 0x73, 0x4a, 0x9b, 0xae, 0x9b, 0x90, 0x78, 0x4c, - 0x65, 0xe0, 0xcd, 0x9c, 0xb9, 0xae, 0xed, 0x1d, 0x6d, 0xf0, 0x44, 0x32, 0xa5, 0xb6, 0x56, 0x30, - 0x3e, 0xcc, 0x02, 0x53, 0x80, 0x47, 0xd7, 0x9f, 0x27, 0xf0, 0xe8, 0xfa, 0x73, 0xe3, 0xf7, 0x04, - 0x46, 0xc5, 0x6a, 0xc5, 0x9f, 0x42, 0x63, 0xea, 0xdb, 0x2a, 0x2a, 0x83, 0xf4, 0x0c, 0x4f, 0x7c, - 0x9b, 0xbf, 0xba, 0x0e, 0xb8, 0x29, 0x85, 0x14, 0x01, 0xdb, 0x12, 0x96, 0x3c, 0x68, 0xdf, 0x94, - 0xdf, 0x89, 0xfb, 0xcd, 0xcc, 0xfd, 0xef, 0x08, 0x55, 0x0a, 0x55, 0xfd, 0x3e, 0xbd, 0xff, 0x26, - 0xcb, 0x93, 0x42, 0xe0, 0xf7, 0xe8, 0xfb, 0xb7, 0x04, 0xff, 0xf9, 0xe6, 0x7a, 0x9f, 0xce, 0x77, - 0xb3, 0xe4, 0xa4, 0x6d, 0x65, 0xec, 0x01, 0xde, 0xec, 0x17, 0x75, 0xcb, 0x15, 0x3b, 0x01, 0x3f, - 0x82, 0xa6, 0xed, 0xcc, 0x66, 0xd1, 0xb0, 0xb1, 0xe6, 0xa2, 0x50, 0x62, 0xe3, 0x0e, 0x74, 0x92, - 0xca, 0xa3, 0x6a, 0x7f, 0xcd, 0xc3, 0x28, 0x41, 0xe9, 0xae, 0x99, 0x90, 0x86, 0x0b, 0x5b, 0x85, - 0x82, 0xc3, 0x0f, 0xa0, 0x2f, 0xab, 0x72, 0x52, 0x40, 0xff, 0x9e, 0xe4, 0x8d, 0x25, 0x0b, 0x7f, - 0x02, 0xa0, 0x55, 0x2c, 0x3d, 0xd8, 0xf5, 0xcd, 0xae, 0x52, 0xa0, 0x3b, 0xe7, 0x16, 0x10, 0xde, - 0x29, 0xe1, 0xa6, 0x14, 0xb6, 0xad, 0x20, 0x20, 0x91, 0x71, 0x02, 0x90, 0x55, 0x2b, 0xde, 0x81, - 0xc1, 0xd2, 0x5a, 0xa9, 0x26, 0x98, 0x44, 0xce, 0x3b, 0xae, 0x17, 0xeb, 0x2f, 0xad, 0x95, 0xdc, - 0xd0, 0x4b, 0xe7, 0x1d, 0x37, 0xfe, 0x5f, 0x87, 0x96, 0xba, 0xae, 0xc8, 0xb3, 0x04, 0xa9, 0x89, - 0x63, 0x27, 0xe7, 0x90, 0xf4, 0xb9, 0x9d, 0xbb, 0xae, 0xea, 0xf9, 0xeb, 0x8a, 0x52, 0x22, 0x9c, - 0x25, 0x97, 0x1b, 0x69, 0x98, 0xf2, 0x1b, 0x0f, 0xa1, 0xed, 0xc5, 0xcb, 0x89, 0x58, 0x45, 0xb2, - 0x93, 0x1a, 0x66, 0xcb, 0x8b, 0x97, 0xaf, 0x56, 0x11, 0x7e, 0x04, 0xdb, 0x59, 0x5b, 0xaa, 0x03, - 0x34, 0xe5, 0x01, 0xb6, 0xd2, 0x2e, 0x94, 0x27, 0xfc, 0x02, 0x58, 0x4e, 0x2f, 0xb0, 0x42, 0x11, - 0xe9, 0x4b, 0x20, 0x69, 0xe2, 0x0b, 0x2b, 0xa4, 0xc1, 0x44, 0x5f, 0xb3, 0x83, 0xd4, 0x9c, 0xf8, - 0x11, 0x1e, 0x69, 0x7b, 0x05, 0xd7, 0x6a, 0xa1, 0xb6, 0x5c, 0x48, 0x6a, 0x6a, 0x3c, 0xa7, 0x95, - 0x7e, 0x04, 0x5d, 0xaa, 0x22, 0xa5, 0xd2, 0x91, 0x2a, 0x1d, 0x62, 0x48, 0xe1, 0xc7, 0xb0, 0x9d, - 0xcd, 0x04, 0x4a, 0xa5, 0xab, 0xbc, 0x64, 0xec, 0x1b, 0x19, 0x81, 0x62, 0x46, 0x1e, 0xc1, 0x56, - 0x61, 0xaf, 0x04, 0x9f, 0xc2, 0x17, 0x96, 0xab, 0x73, 0xa1, 0x88, 0x74, 0xb6, 0xa8, 0x67, 0xb3, - 0x85, 0xf1, 0x08, 0xba, 0x69, 0xd1, 0x51, 0xfc, 0x83, 0xf8, 0xf2, 0x6b, 0x9e, 0xcc, 0x3f, 0x9a, - 0x22, 0x77, 0x81, 0xff, 0xad, 0x9e, 0x3f, 0x1a, 0xa6, 0x22, 0x3e, 0xf9, 0x73, 0x0d, 0x7a, 0xcf, - 0x14, 0xde, 0x52, 0xfb, 0xe0, 0x36, 0xf4, 0x9e, 0xc7, 0xae, 0xab, 0x59, 0x6c, 0x03, 0x3b, 0xd0, - 0x20, 0x98, 0x66, 0x35, 0xec, 0x42, 0x53, 0xc2, 0x30, 0xab, 0x13, 0x93, 0xea, 0x86, 0x6d, 0xe2, - 0x16, 0x74, 0x53, 0x5c, 0x63, 0x0d, 0x22, 0x53, 0xfc, 0x67, 0x4d, 0xec, 0x43, 0x27, 0x81, 0x33, - 0xb6, 0x83, 0x3d, 0x68, 0x6b, 0xf4, 0x61, 0x88, 0x00, 0x2d, 0x15, 0x5d, 0xb6, 0x4b, 0x9e, 0x25, - 0x70, 0xb0, 0x3d, 0x72, 0x90, 0xb6, 0x22, 0xdb, 0xc7, 0x01, 0x40, 0xd6, 0x84, 0xec, 0x80, 0x1c, - 0x26, 0xed, 0xc7, 0x0e, 0x3f, 0xf9, 0x53, 0x13, 0x3a, 0x49, 0xe3, 0x63, 0x0b, 0xea, 0x2f, 0xbe, - 0x66, 0x1b, 0xb8, 0x03, 0x5b, 0xe7, 0x9e, 0xe0, 0xa1, 0x67, 0xb9, 0x67, 0x74, 0xe1, 0xb0, 0x1a, - 0xb1, 0xce, 0xbc, 0xa9, 0x6f, 0x3b, 0xde, 0x5c, 0xb1, 0xea, 0xe4, 0xe8, 0xd4, 0xb2, 0x9f, 0xfb, - 0xde, 0x94, 0xb3, 0x4d, 0x64, 0xd0, 0xff, 0xc6, 0xb3, 0x62, 0xb1, 0xf0, 0x43, 0xe7, 0x1d, 0xb7, - 0x59, 0x03, 0xf7, 0x61, 0xe7, 0xdc, 0x8b, 0xe2, 0xd9, 0xcc, 0x99, 0x3a, 0xdc, 0x13, 0x5f, 0xc5, - 0x9e, 0x1d, 0xb1, 0x26, 0x22, 0x0c, 0xbe, 0xf1, 0xae, 0x3c, 0xff, 0x5b, 0x4f, 0x4f, 0x69, 0xac, - 0x85, 0x43, 0xd8, 0x3b, 0xb5, 0x22, 0xfe, 0x65, 0x1c, 0xb8, 0xce, 0xd4, 0x12, 0xfc, 0xb1, 0x6d, - 0x87, 0x3c, 0x8a, 0x18, 0x27, 0x27, 0x24, 0x29, 0xae, 0x3d, 0x4b, 0x0c, 0x0a, 0xfe, 0x39, 0x8f, - 0xd8, 0x1c, 0x6f, 0xc1, 0xfe, 0x0d, 0x89, 0x5c, 0x79, 0x81, 0x3f, 0x86, 0x61, 0x59, 0xf4, 0xd4, - 0x8a, 0x2e, 0x42, 0x67, 0xca, 0x99, 0x83, 0x7b, 0xc0, 0x94, 0x54, 0xd6, 0xdb, 0xb9, 0x17, 0xc4, - 0x82, 0xfd, 0x21, 0x59, 0x5f, 0x73, 0x5f, 0xc4, 0x82, 0xd8, 0x57, 0x25, 0xf6, 0x85, 0x2c, 0x0f, - 0xe6, 0xe2, 0x21, 0xec, 0xe6, 0xd8, 0x2f, 0xe9, 0x7c, 0x14, 0x9d, 0x65, 0xb6, 0x5f, 0x25, 0x70, - 0xe6, 0x9e, 0x25, 0xe2, 0x90, 0x33, 0x0f, 0x0f, 0x00, 0x49, 0xa2, 0x43, 0x92, 0x1c, 0xdc, 0x4f, - 0x56, 0xd0, 0x7c, 0xbd, 0x42, 0x50, 0x66, 0xbb, 0xf1, 0xdc, 0xf1, 0xd8, 0x1b, 0xdc, 0x07, 0xf6, - 0xd4, 0x7f, 0xab, 0xb9, 0x67, 0x9e, 0x70, 0xc4, 0x35, 0xfb, 0x6b, 0x0d, 0xf7, 0x60, 0x3b, 0x63, - 0x3f, 0x0d, 0xfd, 0x38, 0x60, 0x7f, 0xab, 0xe1, 0x21, 0x60, 0xc6, 0xbd, 0x08, 0xfd, 0xc0, 0x8f, - 0x2c, 0x97, 0xfd, 0xbd, 0x86, 0x07, 0xb0, 0xf3, 0xd4, 0x7f, 0x9b, 0x66, 0x41, 0x19, 0xfc, 0x23, - 0x31, 0x48, 0xf9, 0xcf, 0xf8, 0xf2, 0x92, 0x87, 0xec, 0x9f, 0x35, 0xbc, 0x05, 0x7b, 0x79, 0x41, - 0xea, 0xeb, 0x5f, 0x35, 0xbd, 0xa3, 0x54, 0xf4, 0xda, 0x17, 0x9c, 0xfd, 0x3b, 0x61, 0xeb, 0x38, - 0x68, 0x47, 0xff, 0xa9, 0xe1, 0x2e, 0x0c, 0x32, 0xb6, 0xd4, 0xfd, 0x6f, 0x0d, 0x47, 0xb0, 0x5f, - 0x60, 0x3a, 0xde, 0xfc, 0x82, 0x3a, 0x8e, 0xfd, 0xaf, 0x76, 0xf2, 0x5d, 0x13, 0xb6, 0xe9, 0x46, - 0x78, 0x1c, 0xa8, 0x05, 0x68, 0x26, 0xb8, 0xaf, 0xfa, 0x0c, 0x2b, 0x9e, 0xf0, 0xa3, 0xaa, 0xa1, - 0x1c, 0x4f, 0x74, 0x3b, 0x62, 0xd5, 0x4b, 0x7e, 0x54, 0x39, 0x9b, 0xd3, 0x22, 0x6a, 0x6e, 0xba, - 0xf9, 0xa0, 0x1f, 0x55, 0x0d, 0xe8, 0xf8, 0x45, 0xae, 0xbd, 0x71, 0xdd, 0xb3, 0x7e, 0xb4, 0x76, - 0x54, 0xc7, 0xcf, 0x33, 0x00, 0xc0, 0x35, 0x8f, 0xfb, 0xd1, 0xba, 0x71, 0x1d, 0x1f, 0xa6, 0x78, - 0x81, 0xd5, 0x4f, 0xfc, 0xd1, 0x9a, 0x91, 0x9d, 0x62, 0xa3, 0x26, 0x91, 0xaa, 0x97, 0xfb, 0xa8, - 0x72, 0x0a, 0xc7, 0x4f, 0x13, 0x40, 0xc2, 0xca, 0x7f, 0x07, 0x46, 0xd5, 0xb3, 0x3e, 0x45, 0x28, - 0x7b, 0x3f, 0xae, 0x7b, 0xf6, 0x8f, 0xd6, 0x4e, 0xf1, 0xf8, 0x38, 0x8f, 0x70, 0xb8, 0xf6, 0xf1, - 0x3f, 0x5a, 0x3f, 0xcb, 0x53, 0x90, 0xb3, 0xc7, 0x62, 0xf5, 0x5f, 0x00, 0xa3, 0x75, 0xe3, 0xfc, - 0x65, 0x4b, 0xfe, 0xb5, 0xf4, 0xe0, 0xfb, 0x00, 0x00, 0x00, 0xff, 0xff, 0x70, 0x47, 0x17, 0xd1, - 0x6f, 0x12, 0x00, 0x00, + // 1746 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0xdb, 0xc8, + 0x15, 0x16, 0x29, 0x6e, 0x78, 0xa4, 0xa8, 0xd6, 0xd3, 0x46, 0x33, 0x49, 0x95, 0x07, 0xf1, 0x64, + 0x24, 0xc7, 0x65, 0xa7, 0xe4, 0x9a, 0x29, 0x3b, 0x93, 0x4a, 0x95, 0x65, 0x6b, 0x2c, 0xd5, 0xc4, + 0xb6, 0x02, 0x7b, 0x7c, 0xc8, 0x52, 0x2c, 0x88, 0x68, 0x92, 0x88, 0x40, 0x00, 0x06, 0x1a, 0x1a, + 0xca, 0xff, 0x60, 0x7e, 0x49, 0xae, 0xb9, 0xe4, 0x92, 0x6b, 0x4e, 0xd9, 0x97, 0x5f, 0x34, 0xf5, + 0xba, 0x1b, 0x00, 0x01, 0x81, 0x3e, 0xf9, 0xc2, 0xc2, 0x5b, 0xbb, 0xfb, 0x2d, 0x5f, 0xbf, 0x26, + 0x6c, 0x89, 0xeb, 0x90, 0xc7, 0x0f, 0xe4, 0xef, 0xfd, 0x30, 0x0a, 0x44, 0x80, 0x4d, 0x49, 0x98, + 0x7f, 0x6d, 0x40, 0xdb, 0xe2, 0xef, 0x12, 0x1e, 0x0b, 0x3c, 0x80, 0x06, 0x1f, 0xcf, 0x82, 0x41, + 0xed, 0x76, 0xed, 0xa0, 0x7b, 0x84, 0xf7, 0x95, 0xba, 0x96, 0x9e, 0x8c, 0x67, 0xc1, 0xe9, 0x9a, + 0x25, 0x35, 0xf0, 0xa7, 0xd0, 0x9c, 0x78, 0x49, 0x3c, 0x1b, 0xd4, 0xa5, 0xea, 0x76, 0x51, 0xf5, + 0x2b, 0x12, 0x9d, 0xae, 0x59, 0x4a, 0x87, 0xdc, 0xba, 0xfe, 0x24, 0x18, 0xac, 0x57, 0xb9, 0x3d, + 0xf3, 0x27, 0xd2, 0x2d, 0x69, 0xe0, 0x23, 0x80, 0x98, 0x8b, 0x51, 0x10, 0x0a, 0x37, 0xf0, 0x07, + 0x0d, 0xa9, 0xbf, 0x5f, 0xd4, 0x7f, 0xcd, 0xc5, 0x2b, 0x29, 0x3e, 0x5d, 0xb3, 0x8c, 0x38, 0x25, + 0xf0, 0x73, 0x30, 0xec, 0x30, 0xe4, 0xbe, 0x33, 0x12, 0x8b, 0x41, 0x53, 0x1a, 0xee, 0x15, 0x0d, + 0x9f, 0x48, 0xf1, 0x9b, 0xc5, 0xe9, 0x9a, 0xd5, 0xb1, 0xf5, 0x37, 0x1e, 0x41, 0x67, 0x3c, 0xe3, + 0xe3, 0x4b, 0xb2, 0x6a, 0x49, 0xab, 0xdd, 0xa2, 0xd5, 0x53, 0x92, 0x4a, 0xa3, 0xf6, 0x58, 0x7d, + 0xe2, 0x7d, 0x68, 0x8d, 0x83, 0xf9, 0xdc, 0x15, 0x83, 0xb6, 0xb4, 0xd8, 0x29, 0x59, 0x48, 0xd9, + 0xe9, 0x9a, 0xa5, 0xb5, 0x28, 0x56, 0xef, 0x12, 0x1e, 0x5d, 0x0f, 0x3a, 0x55, 0xb1, 0xfa, 0x35, + 0x89, 0x28, 0x56, 0x52, 0x87, 0x22, 0xe0, 0xfa, 0xae, 0x18, 0x8d, 0x67, 0xb6, 0xeb, 0x0f, 0x8c, + 0xaa, 0x08, 0x9c, 0xf9, 0xae, 0x78, 0x4a, 0x62, 0x8a, 0x80, 0x9b, 0x12, 0xf8, 0x25, 0x74, 0x2f, + 0xf8, 0xd4, 0xf5, 0x47, 0x17, 0x5e, 0x30, 0xbe, 0x1c, 0x80, 0x34, 0x1d, 0x14, 0x4d, 0x8f, 0x49, + 0xe1, 0x98, 0xe4, 0xa7, 0x6b, 0x16, 0x5c, 0x64, 0x14, 0x85, 0x8f, 0x62, 0xa7, 0x4c, 0xbb, 0x55, + 0xe1, 0x3b, 0xf1, 0x9d, 0xd4, 0xb0, 0xc3, 0xf5, 0xf7, 0x71, 0x1b, 0x9a, 0x57, 0xb6, 0x97, 0x70, + 0xf3, 0x33, 0xe8, 0x2e, 0x95, 0x09, 0x0e, 0xa0, 0x3d, 0xe7, 0x71, 0x6c, 0x4f, 0xb9, 0xac, 0x25, + 0xc3, 0x4a, 0x49, 0xb3, 0x0f, 0xbd, 0xe5, 0x22, 0x31, 0x37, 0x32, 0x43, 0x2a, 0x04, 0xf3, 0xe7, + 0xc0, 0xca, 0x79, 0x46, 0x06, 0xeb, 0x97, 0xfc, 0x5a, 0x3b, 0xa2, 0x4f, 0xdc, 0xd1, 0xcb, 0xca, + 0xea, 0x33, 0x2c, 0xbd, 0x87, 0x4f, 0x60, 0xb3, 0x94, 0x6a, 0xec, 0x43, 0x5d, 0x2c, 0xa4, 0x65, + 0xcf, 0xaa, 0x8b, 0x85, 0x79, 0x1b, 0xfa, 0xc5, 0xbc, 0xde, 0xd0, 0xb8, 0x93, 0xed, 0x4f, 0x26, + 0x86, 0x96, 0x52, 0xc9, 0x53, 0x2a, 0x8a, 0x30, 0x37, 0x61, 0xa3, 0x90, 0x6d, 0xf3, 0x59, 0xb6, + 0xef, 0x2c, 0x3b, 0xf8, 0x33, 0x80, 0x2b, 0xdb, 0x73, 0x1d, 0x5b, 0x04, 0x51, 0x3c, 0xa8, 0xdd, + 0x5e, 0x3f, 0xe8, 0x1e, 0x31, 0x1d, 0xd4, 0xb7, 0xa9, 0xc0, 0x5a, 0xd2, 0x31, 0x5f, 0xc2, 0xd6, + 0x8d, 0x44, 0x21, 0x42, 0x63, 0x66, 0xc7, 0x33, 0xbd, 0x01, 0xf9, 0x8d, 0x9f, 0x42, 0x6b, 0xc6, + 0x6d, 0x87, 0x47, 0xba, 0xff, 0x36, 0xb4, 0xdb, 0x53, 0xc9, 0xb4, 0xb4, 0xd0, 0x3c, 0xcc, 0x22, + 0x92, 0x66, 0x0f, 0xf7, 0xc8, 0xd2, 0x9d, 0xce, 0x84, 0xf4, 0xd7, 0xb0, 0x34, 0x65, 0x7e, 0xd7, + 0x84, 0x8e, 0xc5, 0xe3, 0x30, 0xf0, 0x63, 0x8e, 0x8f, 0xc0, 0xe0, 0x8b, 0x31, 0x57, 0x5d, 0x58, + 0x2b, 0x15, 0x92, 0xd2, 0x39, 0x49, 0xe5, 0x54, 0x84, 0x99, 0x32, 0x1e, 0x6a, 0x04, 0x29, 0xc3, + 0x82, 0x36, 0x5a, 0x86, 0x90, 0x7b, 0x29, 0x84, 0xac, 0x97, 0xba, 0x48, 0xe9, 0x96, 0x30, 0xe4, + 0x50, 0x63, 0x48, 0xa3, 0xd2, 0x71, 0x01, 0x44, 0x1e, 0x17, 0x40, 0xa4, 0x59, 0xb9, 0xfd, 0x15, + 0x28, 0xf2, 0xc5, 0x32, 0x8a, 0xb4, 0x4a, 0xcd, 0xa7, 0x2c, 0x2b, 0x61, 0xe4, 0xe1, 0x12, 0x8c, + 0xb4, 0x4b, 0xdd, 0xa3, 0xcc, 0x2a, 0x70, 0xe4, 0x41, 0x86, 0x23, 0x9d, 0x12, 0xf2, 0x68, 0x93, + 0x32, 0x90, 0xdc, 0x4b, 0x6b, 0xd1, 0xa8, 0x8c, 0x58, 0x09, 0x49, 0x1e, 0x17, 0x90, 0x04, 0x2a, + 0xc3, 0xb0, 0x02, 0x4a, 0x7e, 0x51, 0x84, 0x12, 0x85, 0x07, 0xb7, 0x4a, 0xb6, 0x2b, 0xb1, 0xe4, + 0x8b, 0x65, 0x2c, 0xe9, 0x55, 0x06, 0xf1, 0xc3, 0x60, 0x72, 0x48, 0x6d, 0x50, 0x2a, 0x33, 0x6a, + 0x44, 0x1e, 0x45, 0x41, 0xa4, 0x71, 0x40, 0x11, 0xe6, 0x01, 0xb5, 0x6b, 0x5e, 0x5c, 0x1f, 0x00, + 0x1e, 0xd9, 0xb2, 0x4b, 0xa5, 0x65, 0xfe, 0xa9, 0x96, 0xdb, 0x52, 0xfd, 0x50, 0xa3, 0xc9, 0x12, + 0x53, 0x86, 0xaa, 0x96, 0xee, 0x81, 0x21, 0xe6, 0x71, 0x38, 0x92, 0x02, 0x55, 0xd4, 0x9b, 0xfa, + 0x2c, 0x6f, 0x5e, 0xbc, 0x3e, 0x27, 0x3b, 0xab, 0x43, 0x1a, 0xd2, 0xc3, 0x43, 0x00, 0xcf, 0x8e, + 0x85, 0x3e, 0x7a, 0xb1, 0xae, 0x7f, 0x65, 0xc7, 0x42, 0x9e, 0x53, 0xda, 0x18, 0x5e, 0x4a, 0xe2, + 0x21, 0x95, 0x81, 0x3f, 0x71, 0xa7, 0xba, 0xb6, 0xb7, 0xb4, 0xc1, 0x53, 0xc9, 0x94, 0xda, 0x5a, + 0xc1, 0xfc, 0x34, 0x0f, 0x4c, 0x01, 0x1e, 0xbd, 0x60, 0x9a, 0xc2, 0xa3, 0x17, 0x4c, 0xcd, 0xdf, + 0x13, 0x18, 0x15, 0xab, 0x15, 0x7f, 0x0c, 0x8d, 0x71, 0xe0, 0xa8, 0xa8, 0xf4, 0xb3, 0x33, 0x3c, + 0x0d, 0x1c, 0xfe, 0xe6, 0x3a, 0xe4, 0x96, 0x14, 0x52, 0x04, 0x1c, 0x5b, 0xd8, 0xf2, 0xa0, 0x3d, + 0x4b, 0x7e, 0xa7, 0xee, 0xd7, 0x73, 0xf7, 0xbf, 0x23, 0x54, 0x29, 0x54, 0xf5, 0xc7, 0xf4, 0xfe, + 0x9b, 0x3c, 0x4f, 0x0a, 0x81, 0x3f, 0xa2, 0xef, 0xdf, 0x12, 0xfc, 0x2f, 0x37, 0xd7, 0xc7, 0x74, + 0xbe, 0x9d, 0x27, 0x27, 0x6b, 0x2b, 0x73, 0x07, 0xf0, 0x66, 0xbf, 0xa8, 0x5b, 0xae, 0xd8, 0x09, + 0xf8, 0x13, 0x68, 0x3a, 0xee, 0x64, 0x12, 0x0f, 0x1a, 0x2b, 0x2e, 0x0a, 0x25, 0x36, 0xef, 0x40, + 0x27, 0xad, 0x3c, 0xaa, 0xf6, 0xb7, 0x3c, 0x8a, 0x53, 0x94, 0x36, 0xac, 0x94, 0x34, 0x3d, 0xd8, + 0x28, 0x14, 0x1c, 0x7e, 0x02, 0x3d, 0x59, 0x95, 0xa3, 0x25, 0xf4, 0x6f, 0x5a, 0x5d, 0xc9, 0x3b, + 0x95, 0x2c, 0xfc, 0x11, 0x80, 0x56, 0xb1, 0xf5, 0x60, 0xd7, 0xb3, 0x0c, 0xa5, 0x40, 0x77, 0xce, + 0x2d, 0x20, 0xbc, 0x53, 0xc2, 0x75, 0x29, 0x6c, 0xdb, 0x61, 0x48, 0x22, 0xf3, 0x08, 0x20, 0xaf, + 0x56, 0xbc, 0x03, 0xfd, 0xb9, 0xbd, 0x50, 0x4d, 0x30, 0x8a, 0xdd, 0xf7, 0x5c, 0x5f, 0x35, 0xbd, + 0xb9, 0xbd, 0x90, 0x1b, 0x7a, 0xed, 0xbe, 0xe7, 0xe6, 0x1f, 0xeb, 0xd0, 0x52, 0xd7, 0x15, 0x79, + 0x96, 0x20, 0x35, 0x72, 0x9d, 0xf4, 0x1c, 0x92, 0x3e, 0x73, 0x96, 0xae, 0xab, 0xba, 0xdc, 0xb0, + 0xa6, 0x28, 0x25, 0xc2, 0x9d, 0x73, 0xb9, 0x91, 0x86, 0x25, 0xbf, 0x71, 0x1f, 0xda, 0x7e, 0x32, + 0x1f, 0x89, 0x45, 0x2c, 0x3b, 0xa9, 0x61, 0xb5, 0xfc, 0x64, 0xfe, 0x66, 0x11, 0xe3, 0x11, 0x6c, + 0xe4, 0x6d, 0x49, 0x8b, 0xa8, 0x3b, 0xa1, 0xaf, 0x43, 0xac, 0x82, 0xf4, 0xcc, 0xea, 0x66, 0x3d, + 0x79, 0xe6, 0xe0, 0x01, 0x30, 0x69, 0xa3, 0xa0, 0x57, 0x9d, 0xba, 0x25, 0x4f, 0xdd, 0x27, 0xbe, + 0xc6, 0x66, 0x8a, 0xcb, 0x0f, 0xc0, 0xa0, 0x8a, 0x50, 0x2a, 0x6d, 0xa9, 0xd2, 0x21, 0x86, 0x14, + 0x7e, 0x06, 0x9b, 0xf9, 0xfd, 0xae, 0x54, 0x3a, 0xca, 0x4b, 0xce, 0xbe, 0x11, 0x5d, 0xa3, 0x18, + 0xdd, 0x33, 0x68, 0xeb, 0x2d, 0x56, 0xce, 0x02, 0x77, 0xa1, 0x19, 0xda, 0x91, 0x88, 0x35, 0x3c, + 0xa5, 0x78, 0x73, 0x6e, 0x47, 0x34, 0x43, 0xe9, 0x89, 0x40, 0xa9, 0x98, 0x8f, 0x61, 0xa3, 0xc0, + 0x27, 0x54, 0x15, 0x81, 0xb0, 0x3d, 0x9d, 0x22, 0x45, 0x64, 0xcb, 0xd4, 0xf3, 0x65, 0xcc, 0xc7, + 0x60, 0x64, 0xb5, 0x48, 0x69, 0x09, 0x93, 0x8b, 0xaf, 0x79, 0x3a, 0x16, 0x69, 0x8a, 0xdc, 0x85, + 0xc1, 0xb7, 0x7a, 0x2c, 0x69, 0x58, 0x8a, 0xb8, 0xfb, 0x97, 0x1a, 0x74, 0x5f, 0x28, 0x18, 0xa6, + 0xae, 0xc2, 0x4d, 0xe8, 0xbe, 0x4c, 0x3c, 0x4f, 0xb3, 0xd8, 0x1a, 0x76, 0xa0, 0x41, 0xe8, 0xcd, + 0x6a, 0x68, 0x40, 0x53, 0xa2, 0x33, 0xab, 0x13, 0x93, 0xca, 0x89, 0xad, 0xe3, 0x06, 0x18, 0x19, + 0xdc, 0xb1, 0x06, 0x91, 0xd9, 0xb5, 0xc0, 0x9a, 0xd8, 0x83, 0x4e, 0x8a, 0x72, 0x6c, 0x0b, 0xbb, + 0xd0, 0xd6, 0xa0, 0xc4, 0x10, 0x01, 0x5a, 0x2a, 0x51, 0x6c, 0x9b, 0x3c, 0x4b, 0x3c, 0x61, 0x3b, + 0xe4, 0x20, 0xeb, 0x50, 0xb6, 0x8b, 0x7d, 0x80, 0xbc, 0x37, 0xd9, 0x1e, 0x39, 0x4c, 0xbb, 0x92, + 0xed, 0xdf, 0xfd, 0x73, 0x13, 0x3a, 0x29, 0x1e, 0x60, 0x0b, 0xea, 0xaf, 0xbe, 0x66, 0x6b, 0xb8, + 0x05, 0x1b, 0x67, 0xbe, 0xe0, 0x91, 0x6f, 0x7b, 0x27, 0x74, 0x0f, 0xb1, 0x1a, 0xb1, 0x4e, 0xfc, + 0x71, 0xe0, 0xb8, 0xfe, 0x54, 0xb1, 0xea, 0xe4, 0xe8, 0xd8, 0x76, 0x5e, 0x06, 0xfe, 0x98, 0xb3, + 0x75, 0x64, 0xd0, 0xfb, 0xc6, 0xb7, 0x13, 0x31, 0x0b, 0x22, 0xf7, 0x3d, 0x77, 0x58, 0x03, 0x77, + 0x61, 0xeb, 0xcc, 0x8f, 0x93, 0xc9, 0xc4, 0x1d, 0xbb, 0xdc, 0x17, 0x5f, 0x25, 0xbe, 0x13, 0xb3, + 0x26, 0x22, 0xf4, 0xbf, 0xf1, 0x2f, 0xfd, 0xe0, 0x5b, 0x5f, 0x0f, 0x6f, 0xac, 0x85, 0x03, 0xd8, + 0x39, 0xb6, 0x63, 0xfe, 0x2c, 0x09, 0x3d, 0x77, 0x6c, 0x0b, 0xfe, 0xc4, 0x71, 0x22, 0x1e, 0xc7, + 0x8c, 0x93, 0x13, 0x92, 0x14, 0xd7, 0x9e, 0xa4, 0x06, 0x05, 0xff, 0x9c, 0xc7, 0x6c, 0x8a, 0xb7, + 0x60, 0xf7, 0x86, 0x44, 0xae, 0x3c, 0xc3, 0x1f, 0xc2, 0xa0, 0x2c, 0x7a, 0x6e, 0xc7, 0xe7, 0x91, + 0x3b, 0xe6, 0xcc, 0xc5, 0x1d, 0x60, 0x4a, 0x2a, 0x4b, 0xf7, 0xcc, 0x0f, 0x13, 0xc1, 0xfe, 0x90, + 0xae, 0xaf, 0xb9, 0xaf, 0x12, 0x41, 0xec, 0xcb, 0x12, 0xfb, 0x5c, 0x96, 0x07, 0xf3, 0x70, 0x1f, + 0xb6, 0x97, 0xd8, 0xaf, 0xe9, 0x7c, 0x14, 0x9d, 0x79, 0xbe, 0x5f, 0x25, 0x70, 0xa7, 0xbe, 0x2d, + 0x92, 0x88, 0x33, 0x1f, 0xf7, 0x00, 0x49, 0xa2, 0x43, 0x92, 0x1e, 0x3c, 0x48, 0x57, 0xd0, 0x7c, + 0xbd, 0x42, 0x58, 0x66, 0x7b, 0xc9, 0xd4, 0xf5, 0xd9, 0x3b, 0xdc, 0x05, 0xf6, 0x3c, 0xb8, 0xd2, + 0xdc, 0x13, 0x5f, 0xb8, 0xe2, 0x9a, 0xfd, 0xad, 0x86, 0x3b, 0xb0, 0x99, 0xb3, 0x9f, 0x47, 0x41, + 0x12, 0xb2, 0xbf, 0xd7, 0x70, 0x1f, 0x30, 0xe7, 0x9e, 0x47, 0x41, 0x18, 0xc4, 0xb6, 0xc7, 0xfe, + 0x51, 0xc3, 0x3d, 0xd8, 0x7a, 0x1e, 0x5c, 0x65, 0x59, 0x50, 0x06, 0xff, 0x4c, 0x0d, 0x32, 0xfe, + 0x0b, 0x3e, 0xbf, 0xe0, 0x11, 0xfb, 0x57, 0x0d, 0x6f, 0xc1, 0xce, 0xb2, 0x20, 0xf3, 0xf5, 0xef, + 0x9a, 0xde, 0x51, 0x26, 0x7a, 0x1b, 0x08, 0xce, 0xfe, 0x93, 0xb2, 0x75, 0x1c, 0xb4, 0xa3, 0xff, + 0xd6, 0x70, 0x1b, 0xfa, 0x39, 0x5b, 0xea, 0xfe, 0xaf, 0x86, 0x43, 0xd8, 0x2d, 0x30, 0x5d, 0x7f, + 0x7a, 0x4e, 0x1d, 0xc7, 0xfe, 0x5f, 0x3b, 0xfa, 0xae, 0x09, 0x9b, 0x74, 0x51, 0x3c, 0x09, 0xd5, + 0x02, 0x34, 0x2a, 0x3c, 0x50, 0x7d, 0x86, 0x15, 0x2f, 0xfb, 0x61, 0xd5, 0xac, 0x8e, 0x47, 0xba, + 0x1d, 0xb1, 0xea, 0x81, 0x3f, 0xac, 0x1c, 0xd9, 0x69, 0x11, 0x35, 0x4e, 0xdd, 0x7c, 0xe7, 0x0f, + 0xab, 0xe6, 0x76, 0xfc, 0xe5, 0x52, 0x7b, 0xe3, 0xaa, 0xd7, 0xfe, 0x70, 0xe5, 0x04, 0x8f, 0x5f, + 0xe6, 0x00, 0x80, 0x2b, 0xde, 0xfc, 0xc3, 0x55, 0x53, 0x3c, 0x3e, 0xca, 0xf0, 0x02, 0xab, 0x5f, + 0xfe, 0xc3, 0x15, 0x93, 0x3c, 0xc5, 0x46, 0x0d, 0x28, 0x55, 0x0f, 0xfa, 0x61, 0xe5, 0x70, 0x8e, + 0x9f, 0xa7, 0x80, 0x84, 0x95, 0x7f, 0x1a, 0x0c, 0xab, 0x9f, 0x00, 0x14, 0xa1, 0xfc, 0x59, 0xb9, + 0xea, 0xdf, 0x80, 0xe1, 0xca, 0xe1, 0x1e, 0x9f, 0x2c, 0x23, 0x1c, 0xae, 0xfc, 0x4f, 0x60, 0xb8, + 0x7a, 0xc4, 0xa7, 0x20, 0xe7, 0x6f, 0xc8, 0xea, 0x7f, 0x06, 0x86, 0xab, 0xa6, 0xfc, 0x8b, 0x96, + 0xfc, 0xc7, 0xe9, 0xe1, 0xf7, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x0f, 0x72, 0x7a, 0x86, 0x12, + 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 6633d4e3..db25fbba 100644 --- a/types/types.proto +++ b/types/types.proto @@ -233,15 +233,19 @@ message ConfigInfo { message Header { string chain_id = 1; - uint64 height = 2; + int32 height = 2; uint64 time = 3; uint64 num_txs = 4; - bytes last_block_hash = 5; - PartSetHeader last_block_parts = 6; - bytes last_commit_hash = 7; - bytes data_hash = 8; - bytes validators_hash = 9; - bytes app_hash = 10; + 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 { From 0bdb3b887e70b1ef16d32eece0248ec071fd8490 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 16 Nov 2016 16:22:52 -0500 Subject: [PATCH 147/545] fix chain_aware app --- example/chain_aware/chain_aware_app.go | 6 +++--- example/chain_aware/chain_aware_test.go | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index df18891b..aec7fe1b 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -36,8 +36,8 @@ func NewChainAwareApplication() *ChainAwareApplication { return &ChainAwareApplication{} } -func (app *ChainAwareApplication) Info() string { - return "nil" +func (app *ChainAwareApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { + return "nil", nil, nil, nil } func (app *ChainAwareApplication) SetOption(key string, value string) (log string) { @@ -60,7 +60,7 @@ func (app *ChainAwareApplication) Query(query []byte) types.Result { return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "") } -func (app *ChainAwareApplication) BeginBlock(height uint64) { +func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { app.beginCount += 1 return } diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index 21eb1b3f..bad7c812 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -8,6 +8,7 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/client" "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" ) func TestChainAware(t *testing.T) { @@ -29,8 +30,10 @@ func TestChainAware(t *testing.T) { defer client.Stop() n := uint64(5) + hash := []byte("fake block hash") + header := &types.Header{} for i := uint64(0); i < n; i++ { - client.BeginBlockSync(i) + client.BeginBlockSync(hash, header) client.EndBlockSync(i) client.CommitSync() } From 9a2d3e51ede632cd1aeafb9835e6050a5a946ebe Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 Nov 2016 13:59:27 -0500 Subject: [PATCH 148/545] heights are uint64 --- types/types.pb.go | 115 +++++++++++++++++++++++----------------------- types/types.proto | 4 +- 2 files changed, 59 insertions(+), 60 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index 0b3248a3..7204767e 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1502,7 +1502,7 @@ func (m *TMSPInfo) GetVersion() string { } type LastBlockInfo struct { - BlockHeight int32 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` + BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` BlockHash []byte `protobuf:"bytes,2,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } @@ -1512,7 +1512,7 @@ func (m *LastBlockInfo) String() string { return proto.CompactTextStr func (*LastBlockInfo) ProtoMessage() {} func (*LastBlockInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } -func (m *LastBlockInfo) GetBlockHeight() int32 { +func (m *LastBlockInfo) GetBlockHeight() uint64 { if m != nil { return m.BlockHeight } @@ -1551,7 +1551,7 @@ func (m *ConfigInfo) GetMaxBlockSize() uint64 { type Header struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` - Height int32 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` Time uint64 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"` NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs" json:"num_txs,omitempty"` LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` @@ -1573,7 +1573,7 @@ func (m *Header) GetChainId() string { return "" } -func (m *Header) GetHeight() int32 { +func (m *Header) GetHeight() uint64 { if m != nil { return m.Height } @@ -2143,7 +2143,7 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1746 bytes of a gzipped FileDescriptorProto + // 1743 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0xdb, 0xc8, 0x15, 0x16, 0x29, 0x6e, 0x78, 0xa4, 0xa8, 0xd6, 0xd3, 0x46, 0x33, 0x49, 0x95, 0x07, 0xf1, 0x64, 0x24, 0xc7, 0x65, 0xa7, 0xe4, 0x9a, 0x29, 0x3b, 0x93, 0x4a, 0x95, 0x65, 0x6b, 0x2c, 0xd5, 0xc4, @@ -2201,57 +2201,56 @@ var fileDescriptor0 = []byte{ 0xbe, 0x9d, 0x27, 0x27, 0x6b, 0x2b, 0x73, 0x07, 0xf0, 0x66, 0xbf, 0xa8, 0x5b, 0xae, 0xd8, 0x09, 0xf8, 0x13, 0x68, 0x3a, 0xee, 0x64, 0x12, 0x0f, 0x1a, 0x2b, 0x2e, 0x0a, 0x25, 0x36, 0xef, 0x40, 0x27, 0xad, 0x3c, 0xaa, 0xf6, 0xb7, 0x3c, 0x8a, 0x53, 0x94, 0x36, 0xac, 0x94, 0x34, 0x3d, 0xd8, - 0x28, 0x14, 0x1c, 0x7e, 0x02, 0x3d, 0x59, 0x95, 0xa3, 0x25, 0xf4, 0x6f, 0x5a, 0x5d, 0xc9, 0x3b, - 0x95, 0x2c, 0xfc, 0x11, 0x80, 0x56, 0xb1, 0xf5, 0x60, 0xd7, 0xb3, 0x0c, 0xa5, 0x40, 0x77, 0xce, - 0x2d, 0x20, 0xbc, 0x53, 0xc2, 0x75, 0x29, 0x6c, 0xdb, 0x61, 0x48, 0x22, 0xf3, 0x08, 0x20, 0xaf, - 0x56, 0xbc, 0x03, 0xfd, 0xb9, 0xbd, 0x50, 0x4d, 0x30, 0x8a, 0xdd, 0xf7, 0x5c, 0x5f, 0x35, 0xbd, - 0xb9, 0xbd, 0x90, 0x1b, 0x7a, 0xed, 0xbe, 0xe7, 0xe6, 0x1f, 0xeb, 0xd0, 0x52, 0xd7, 0x15, 0x79, - 0x96, 0x20, 0x35, 0x72, 0x9d, 0xf4, 0x1c, 0x92, 0x3e, 0x73, 0x96, 0xae, 0xab, 0xba, 0xdc, 0xb0, - 0xa6, 0x28, 0x25, 0xc2, 0x9d, 0x73, 0xb9, 0x91, 0x86, 0x25, 0xbf, 0x71, 0x1f, 0xda, 0x7e, 0x32, - 0x1f, 0x89, 0x45, 0x2c, 0x3b, 0xa9, 0x61, 0xb5, 0xfc, 0x64, 0xfe, 0x66, 0x11, 0xe3, 0x11, 0x6c, - 0xe4, 0x6d, 0x49, 0x8b, 0xa8, 0x3b, 0xa1, 0xaf, 0x43, 0xac, 0x82, 0xf4, 0xcc, 0xea, 0x66, 0x3d, - 0x79, 0xe6, 0xe0, 0x01, 0x30, 0x69, 0xa3, 0xa0, 0x57, 0x9d, 0xba, 0x25, 0x4f, 0xdd, 0x27, 0xbe, - 0xc6, 0x66, 0x8a, 0xcb, 0x0f, 0xc0, 0xa0, 0x8a, 0x50, 0x2a, 0x6d, 0xa9, 0xd2, 0x21, 0x86, 0x14, - 0x7e, 0x06, 0x9b, 0xf9, 0xfd, 0xae, 0x54, 0x3a, 0xca, 0x4b, 0xce, 0xbe, 0x11, 0x5d, 0xa3, 0x18, - 0xdd, 0x33, 0x68, 0xeb, 0x2d, 0x56, 0xce, 0x02, 0x77, 0xa1, 0x19, 0xda, 0x91, 0x88, 0x35, 0x3c, - 0xa5, 0x78, 0x73, 0x6e, 0x47, 0x34, 0x43, 0xe9, 0x89, 0x40, 0xa9, 0x98, 0x8f, 0x61, 0xa3, 0xc0, - 0x27, 0x54, 0x15, 0x81, 0xb0, 0x3d, 0x9d, 0x22, 0x45, 0x64, 0xcb, 0xd4, 0xf3, 0x65, 0xcc, 0xc7, - 0x60, 0x64, 0xb5, 0x48, 0x69, 0x09, 0x93, 0x8b, 0xaf, 0x79, 0x3a, 0x16, 0x69, 0x8a, 0xdc, 0x85, - 0xc1, 0xb7, 0x7a, 0x2c, 0x69, 0x58, 0x8a, 0xb8, 0xfb, 0x97, 0x1a, 0x74, 0x5f, 0x28, 0x18, 0xa6, - 0xae, 0xc2, 0x4d, 0xe8, 0xbe, 0x4c, 0x3c, 0x4f, 0xb3, 0xd8, 0x1a, 0x76, 0xa0, 0x41, 0xe8, 0xcd, - 0x6a, 0x68, 0x40, 0x53, 0xa2, 0x33, 0xab, 0x13, 0x93, 0xca, 0x89, 0xad, 0xe3, 0x06, 0x18, 0x19, - 0xdc, 0xb1, 0x06, 0x91, 0xd9, 0xb5, 0xc0, 0x9a, 0xd8, 0x83, 0x4e, 0x8a, 0x72, 0x6c, 0x0b, 0xbb, - 0xd0, 0xd6, 0xa0, 0xc4, 0x10, 0x01, 0x5a, 0x2a, 0x51, 0x6c, 0x9b, 0x3c, 0x4b, 0x3c, 0x61, 0x3b, - 0xe4, 0x20, 0xeb, 0x50, 0xb6, 0x8b, 0x7d, 0x80, 0xbc, 0x37, 0xd9, 0x1e, 0x39, 0x4c, 0xbb, 0x92, - 0xed, 0xdf, 0xfd, 0x73, 0x13, 0x3a, 0x29, 0x1e, 0x60, 0x0b, 0xea, 0xaf, 0xbe, 0x66, 0x6b, 0xb8, - 0x05, 0x1b, 0x67, 0xbe, 0xe0, 0x91, 0x6f, 0x7b, 0x27, 0x74, 0x0f, 0xb1, 0x1a, 0xb1, 0x4e, 0xfc, - 0x71, 0xe0, 0xb8, 0xfe, 0x54, 0xb1, 0xea, 0xe4, 0xe8, 0xd8, 0x76, 0x5e, 0x06, 0xfe, 0x98, 0xb3, - 0x75, 0x64, 0xd0, 0xfb, 0xc6, 0xb7, 0x13, 0x31, 0x0b, 0x22, 0xf7, 0x3d, 0x77, 0x58, 0x03, 0x77, - 0x61, 0xeb, 0xcc, 0x8f, 0x93, 0xc9, 0xc4, 0x1d, 0xbb, 0xdc, 0x17, 0x5f, 0x25, 0xbe, 0x13, 0xb3, - 0x26, 0x22, 0xf4, 0xbf, 0xf1, 0x2f, 0xfd, 0xe0, 0x5b, 0x5f, 0x0f, 0x6f, 0xac, 0x85, 0x03, 0xd8, - 0x39, 0xb6, 0x63, 0xfe, 0x2c, 0x09, 0x3d, 0x77, 0x6c, 0x0b, 0xfe, 0xc4, 0x71, 0x22, 0x1e, 0xc7, - 0x8c, 0x93, 0x13, 0x92, 0x14, 0xd7, 0x9e, 0xa4, 0x06, 0x05, 0xff, 0x9c, 0xc7, 0x6c, 0x8a, 0xb7, - 0x60, 0xf7, 0x86, 0x44, 0xae, 0x3c, 0xc3, 0x1f, 0xc2, 0xa0, 0x2c, 0x7a, 0x6e, 0xc7, 0xe7, 0x91, - 0x3b, 0xe6, 0xcc, 0xc5, 0x1d, 0x60, 0x4a, 0x2a, 0x4b, 0xf7, 0xcc, 0x0f, 0x13, 0xc1, 0xfe, 0x90, - 0xae, 0xaf, 0xb9, 0xaf, 0x12, 0x41, 0xec, 0xcb, 0x12, 0xfb, 0x5c, 0x96, 0x07, 0xf3, 0x70, 0x1f, - 0xb6, 0x97, 0xd8, 0xaf, 0xe9, 0x7c, 0x14, 0x9d, 0x79, 0xbe, 0x5f, 0x25, 0x70, 0xa7, 0xbe, 0x2d, - 0x92, 0x88, 0x33, 0x1f, 0xf7, 0x00, 0x49, 0xa2, 0x43, 0x92, 0x1e, 0x3c, 0x48, 0x57, 0xd0, 0x7c, - 0xbd, 0x42, 0x58, 0x66, 0x7b, 0xc9, 0xd4, 0xf5, 0xd9, 0x3b, 0xdc, 0x05, 0xf6, 0x3c, 0xb8, 0xd2, - 0xdc, 0x13, 0x5f, 0xb8, 0xe2, 0x9a, 0xfd, 0xad, 0x86, 0x3b, 0xb0, 0x99, 0xb3, 0x9f, 0x47, 0x41, - 0x12, 0xb2, 0xbf, 0xd7, 0x70, 0x1f, 0x30, 0xe7, 0x9e, 0x47, 0x41, 0x18, 0xc4, 0xb6, 0xc7, 0xfe, - 0x51, 0xc3, 0x3d, 0xd8, 0x7a, 0x1e, 0x5c, 0x65, 0x59, 0x50, 0x06, 0xff, 0x4c, 0x0d, 0x32, 0xfe, - 0x0b, 0x3e, 0xbf, 0xe0, 0x11, 0xfb, 0x57, 0x0d, 0x6f, 0xc1, 0xce, 0xb2, 0x20, 0xf3, 0xf5, 0xef, - 0x9a, 0xde, 0x51, 0x26, 0x7a, 0x1b, 0x08, 0xce, 0xfe, 0x93, 0xb2, 0x75, 0x1c, 0xb4, 0xa3, 0xff, - 0xd6, 0x70, 0x1b, 0xfa, 0x39, 0x5b, 0xea, 0xfe, 0xaf, 0x86, 0x43, 0xd8, 0x2d, 0x30, 0x5d, 0x7f, - 0x7a, 0x4e, 0x1d, 0xc7, 0xfe, 0x5f, 0x3b, 0xfa, 0xae, 0x09, 0x9b, 0x74, 0x51, 0x3c, 0x09, 0xd5, - 0x02, 0x34, 0x2a, 0x3c, 0x50, 0x7d, 0x86, 0x15, 0x2f, 0xfb, 0x61, 0xd5, 0xac, 0x8e, 0x47, 0xba, - 0x1d, 0xb1, 0xea, 0x81, 0x3f, 0xac, 0x1c, 0xd9, 0x69, 0x11, 0x35, 0x4e, 0xdd, 0x7c, 0xe7, 0x0f, - 0xab, 0xe6, 0x76, 0xfc, 0xe5, 0x52, 0x7b, 0xe3, 0xaa, 0xd7, 0xfe, 0x70, 0xe5, 0x04, 0x8f, 0x5f, - 0xe6, 0x00, 0x80, 0x2b, 0xde, 0xfc, 0xc3, 0x55, 0x53, 0x3c, 0x3e, 0xca, 0xf0, 0x02, 0xab, 0x5f, - 0xfe, 0xc3, 0x15, 0x93, 0x3c, 0xc5, 0x46, 0x0d, 0x28, 0x55, 0x0f, 0xfa, 0x61, 0xe5, 0x70, 0x8e, - 0x9f, 0xa7, 0x80, 0x84, 0x95, 0x7f, 0x1a, 0x0c, 0xab, 0x9f, 0x00, 0x14, 0xa1, 0xfc, 0x59, 0xb9, - 0xea, 0xdf, 0x80, 0xe1, 0xca, 0xe1, 0x1e, 0x9f, 0x2c, 0x23, 0x1c, 0xae, 0xfc, 0x4f, 0x60, 0xb8, - 0x7a, 0xc4, 0xa7, 0x20, 0xe7, 0x6f, 0xc8, 0xea, 0x7f, 0x06, 0x86, 0xab, 0xa6, 0xfc, 0x8b, 0x96, - 0xfc, 0xc7, 0xe9, 0xe1, 0xf7, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x0f, 0x72, 0x7a, 0x86, 0x12, - 0x00, 0x00, + 0x28, 0x14, 0x1c, 0x7e, 0x02, 0x3d, 0x59, 0x95, 0xa3, 0x02, 0xfa, 0x77, 0x25, 0xef, 0x54, 0xb2, + 0xf0, 0x47, 0x00, 0x5a, 0xc5, 0xd6, 0x83, 0x5d, 0xcf, 0x32, 0x94, 0x02, 0xdd, 0x39, 0xb7, 0x80, + 0xf0, 0x4e, 0x09, 0xd7, 0xa5, 0xb0, 0x6d, 0x87, 0x21, 0x89, 0xcc, 0x23, 0x80, 0xbc, 0x5a, 0xf1, + 0x0e, 0xf4, 0xe7, 0xf6, 0x42, 0x35, 0xc1, 0x28, 0x76, 0xdf, 0x73, 0xbd, 0x58, 0x6f, 0x6e, 0x2f, + 0xe4, 0x86, 0x5e, 0xbb, 0xef, 0xb9, 0xf9, 0xc7, 0x3a, 0xb4, 0xd4, 0x75, 0x45, 0x9e, 0x25, 0x48, + 0x8d, 0x5c, 0x27, 0x3d, 0x87, 0xa4, 0xcf, 0x9c, 0xa5, 0xeb, 0xaa, 0xbe, 0x7c, 0x5d, 0x51, 0x4a, + 0x84, 0x3b, 0xe7, 0x72, 0x23, 0x0d, 0x4b, 0x7e, 0xe3, 0x3e, 0xb4, 0xfd, 0x64, 0x3e, 0x12, 0x8b, + 0x58, 0x76, 0x52, 0xc3, 0x6a, 0xf9, 0xc9, 0xfc, 0xcd, 0x22, 0xc6, 0x23, 0xd8, 0xc8, 0xdb, 0x92, + 0x16, 0x51, 0x77, 0x42, 0x5f, 0x87, 0x58, 0x05, 0xe9, 0x99, 0xd5, 0xcd, 0x7a, 0xf2, 0xcc, 0xc1, + 0x03, 0x60, 0xd2, 0x46, 0x41, 0xaf, 0x3a, 0x75, 0x4b, 0x9e, 0xba, 0x4f, 0x7c, 0x8d, 0xcd, 0x14, + 0x97, 0x1f, 0x80, 0x41, 0x15, 0xa1, 0x54, 0xda, 0x52, 0xa5, 0x43, 0x0c, 0x29, 0xfc, 0x0c, 0x36, + 0xf3, 0xfb, 0x5d, 0xa9, 0x74, 0x94, 0x97, 0x9c, 0x7d, 0x23, 0xba, 0x46, 0x31, 0xba, 0x67, 0xd0, + 0xd6, 0x5b, 0xac, 0x9c, 0x05, 0xee, 0x42, 0x33, 0xb4, 0x23, 0x11, 0x6b, 0x78, 0x4a, 0xf1, 0xe6, + 0xdc, 0x8e, 0x68, 0x86, 0xd2, 0x13, 0x81, 0x52, 0x31, 0x1f, 0xc3, 0x46, 0x81, 0x4f, 0xa8, 0x2a, + 0x02, 0x61, 0x7b, 0x3a, 0x45, 0x8a, 0xc8, 0x96, 0xa9, 0xe7, 0xcb, 0x98, 0x8f, 0xc1, 0xc8, 0x6a, + 0x91, 0xd2, 0x12, 0x26, 0x17, 0x5f, 0xf3, 0x74, 0x2c, 0xd2, 0x14, 0xb9, 0x0b, 0x83, 0x6f, 0xf5, + 0x58, 0xd2, 0xb0, 0x14, 0x71, 0xf7, 0x2f, 0x35, 0xe8, 0xbe, 0x50, 0x30, 0x4c, 0x5d, 0x85, 0x9b, + 0xd0, 0x7d, 0x99, 0x78, 0x9e, 0x66, 0xb1, 0x35, 0xec, 0x40, 0x83, 0xd0, 0x9b, 0xd5, 0xd0, 0x80, + 0xa6, 0x44, 0x67, 0x56, 0x27, 0x26, 0x95, 0x13, 0x5b, 0xc7, 0x0d, 0x30, 0x32, 0xb8, 0x63, 0x0d, + 0x22, 0xb3, 0x6b, 0x81, 0x35, 0xb1, 0x07, 0x9d, 0x14, 0xe5, 0xd8, 0x16, 0x76, 0xa1, 0xad, 0x41, + 0x89, 0x21, 0x02, 0xb4, 0x54, 0xa2, 0xd8, 0x36, 0x79, 0x96, 0x78, 0xc2, 0x76, 0xc8, 0x41, 0xd6, + 0xa1, 0x6c, 0x17, 0xfb, 0x00, 0x79, 0x6f, 0xb2, 0x3d, 0x72, 0x98, 0x76, 0x25, 0xdb, 0xbf, 0xfb, + 0xe7, 0x26, 0x74, 0x52, 0x3c, 0xc0, 0x16, 0xd4, 0x5f, 0x7d, 0xcd, 0xd6, 0x70, 0x0b, 0x36, 0xce, + 0x7c, 0xc1, 0x23, 0xdf, 0xf6, 0x4e, 0xe8, 0x1e, 0x62, 0x35, 0x62, 0x9d, 0xf8, 0xe3, 0xc0, 0x71, + 0xfd, 0xa9, 0x62, 0xd5, 0xc9, 0xd1, 0xb1, 0xed, 0xbc, 0x0c, 0xfc, 0x31, 0x67, 0xeb, 0xc8, 0xa0, + 0xf7, 0x8d, 0x6f, 0x27, 0x62, 0x16, 0x44, 0xee, 0x7b, 0xee, 0xb0, 0x06, 0xee, 0xc2, 0xd6, 0x99, + 0x1f, 0x27, 0x93, 0x89, 0x3b, 0x76, 0xb9, 0x2f, 0xbe, 0x4a, 0x7c, 0x27, 0x66, 0x4d, 0x44, 0xe8, + 0x7f, 0xe3, 0x5f, 0xfa, 0xc1, 0xb7, 0xbe, 0x1e, 0xde, 0x58, 0x0b, 0x07, 0xb0, 0x73, 0x6c, 0xc7, + 0xfc, 0x59, 0x12, 0x7a, 0xee, 0xd8, 0x16, 0xfc, 0x89, 0xe3, 0x44, 0x3c, 0x8e, 0x19, 0x27, 0x27, + 0x24, 0x29, 0xae, 0x3d, 0x49, 0x0d, 0x0a, 0xfe, 0x39, 0x8f, 0xd9, 0x14, 0x6f, 0xc1, 0xee, 0x0d, + 0x89, 0x5c, 0x79, 0x86, 0x3f, 0x84, 0x41, 0x59, 0xf4, 0xdc, 0x8e, 0xcf, 0x23, 0x77, 0xcc, 0x99, + 0x8b, 0x3b, 0xc0, 0x94, 0x54, 0x96, 0xee, 0x99, 0x1f, 0x26, 0x82, 0xfd, 0x21, 0x5d, 0x5f, 0x73, + 0x5f, 0x25, 0x82, 0xd8, 0x97, 0x25, 0xf6, 0xb9, 0x2c, 0x0f, 0xe6, 0xe1, 0x3e, 0x6c, 0x2f, 0xb1, + 0x5f, 0xd3, 0xf9, 0x28, 0x3a, 0xf3, 0x7c, 0xbf, 0x4a, 0xe0, 0x4e, 0x7d, 0x5b, 0x24, 0x11, 0x67, + 0x3e, 0xee, 0x01, 0x92, 0x44, 0x87, 0x24, 0x3d, 0x78, 0x90, 0xae, 0xa0, 0xf9, 0x7a, 0x85, 0xb0, + 0xcc, 0xf6, 0x92, 0xa9, 0xeb, 0xb3, 0x77, 0xb8, 0x0b, 0xec, 0x79, 0x70, 0xa5, 0xb9, 0x27, 0xbe, + 0x70, 0xc5, 0x35, 0xfb, 0x5b, 0x0d, 0x77, 0x60, 0x33, 0x67, 0x3f, 0x8f, 0x82, 0x24, 0x64, 0x7f, + 0xaf, 0xe1, 0x3e, 0x60, 0xce, 0x3d, 0x8f, 0x82, 0x30, 0x88, 0x6d, 0x8f, 0xfd, 0xa3, 0x86, 0x7b, + 0xb0, 0xf5, 0x3c, 0xb8, 0xca, 0xb2, 0xa0, 0x0c, 0xfe, 0x99, 0x1a, 0x64, 0xfc, 0x17, 0x7c, 0x7e, + 0xc1, 0x23, 0xf6, 0xaf, 0x1a, 0xde, 0x82, 0x9d, 0x65, 0x41, 0xe6, 0xeb, 0xdf, 0x35, 0xbd, 0xa3, + 0x4c, 0xf4, 0x36, 0x10, 0x9c, 0xfd, 0x27, 0x65, 0xeb, 0x38, 0x68, 0x47, 0xff, 0xad, 0xe1, 0x36, + 0xf4, 0x73, 0xb6, 0xd4, 0xfd, 0x5f, 0x0d, 0x87, 0xb0, 0x5b, 0x60, 0xba, 0xfe, 0xf4, 0x9c, 0x3a, + 0x8e, 0xfd, 0xbf, 0x76, 0xf4, 0x5d, 0x13, 0x36, 0xe9, 0xa2, 0x78, 0x12, 0xaa, 0x05, 0x68, 0x54, + 0x78, 0xa0, 0xfa, 0x0c, 0x2b, 0x5e, 0xf6, 0xc3, 0xaa, 0x59, 0x1d, 0x8f, 0x74, 0x3b, 0x62, 0xd5, + 0x03, 0x7f, 0x58, 0x39, 0xb2, 0xd3, 0x22, 0x6a, 0x9c, 0xba, 0xf9, 0xce, 0x1f, 0x56, 0xcd, 0xed, + 0xf8, 0xcb, 0xa5, 0xf6, 0xc6, 0x55, 0xaf, 0xfd, 0xe1, 0xca, 0x09, 0x1e, 0xbf, 0xcc, 0x01, 0x00, + 0x57, 0xbc, 0xf9, 0x87, 0xab, 0xa6, 0x78, 0x7c, 0x94, 0xe1, 0x05, 0x56, 0xbf, 0xfc, 0x87, 0x2b, + 0x26, 0x79, 0x8a, 0x8d, 0x1a, 0x50, 0xaa, 0x1e, 0xf4, 0xc3, 0xca, 0xe1, 0x1c, 0x3f, 0x4f, 0x01, + 0x09, 0x2b, 0xff, 0x34, 0x18, 0x56, 0x3f, 0x01, 0x28, 0x42, 0xf9, 0xb3, 0x72, 0xd5, 0xbf, 0x01, + 0xc3, 0x95, 0xc3, 0x3d, 0x3e, 0x59, 0x46, 0x38, 0x5c, 0xf9, 0x9f, 0xc0, 0x70, 0xf5, 0x88, 0x4f, + 0x41, 0xce, 0xdf, 0x90, 0xd5, 0xff, 0x0c, 0x0c, 0x57, 0x4d, 0xf9, 0x17, 0x2d, 0xf9, 0x8f, 0xd3, + 0xc3, 0xef, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x81, 0xd5, 0x01, 0x86, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index db25fbba..3e9ebfe5 100644 --- a/types/types.proto +++ b/types/types.proto @@ -219,7 +219,7 @@ message TMSPInfo { } message LastBlockInfo { - int32 block_height = 1; + uint64 block_height = 1; bytes block_hash = 2; bytes app_hash = 3; } @@ -233,7 +233,7 @@ message ConfigInfo { message Header { string chain_id = 1; - int32 height = 2; + uint64 height = 2; uint64 time = 3; uint64 num_txs = 4; BlockID last_block_id = 5; From b200b82418ead1effd488e80bba19532bebce2ac Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 21 Nov 2016 23:42:42 -0500 Subject: [PATCH 149/545] dummy: valset changes and tests --- example/counter/counter.go | 15 +-- example/dummy/README.md | 31 +++++ example/dummy/dummy.go | 11 +- example/dummy/dummy_test.go | 203 ++++++++++++++++++++++++++++++ example/dummy/persistent_dummy.go | 110 +++++++++++++++- types/validators.go | 24 ++++ 6 files changed, 378 insertions(+), 16 deletions(-) create mode 100644 example/dummy/README.md create mode 100644 example/dummy/dummy_test.go create mode 100644 types/validators.go diff --git a/example/counter/counter.go b/example/counter/counter.go index 2596eb10..230556e1 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -2,7 +2,6 @@ package counter import ( "encoding/binary" - "fmt" . "github.com/tendermint/go-common" "github.com/tendermint/tmsp/types" @@ -35,11 +34,7 @@ func (app *CounterApplication) AppendTx(tx []byte) types.Result { copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.Result{ - Code: types.CodeType_BadNonce, - Data: nil, - Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue), - } + return types.ErrBadNonce.SetLog(Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) } } app.txCount += 1 @@ -52,11 +47,7 @@ func (app *CounterApplication) CheckTx(tx []byte) types.Result { copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.Result{ - Code: types.CodeType_BadNonce, - Data: nil, - Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue), - } + return types.ErrBadNonce.SetLog(Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) } } return types.OK @@ -75,5 +66,5 @@ func (app *CounterApplication) Commit() types.Result { } func (app *CounterApplication) Query(query []byte) types.Result { - return types.NewResultOK(nil, fmt.Sprintf("Query is not supported")) + return types.NewResultOK(nil, Fmt("Query is not supported")) } diff --git a/example/dummy/README.md b/example/dummy/README.md new file mode 100644 index 00000000..19f82fda --- /dev/null +++ b/example/dummy/README.md @@ -0,0 +1,31 @@ +# Dummy + +There are two app's here: the DummyApplication and the PersistentDummyApplication. + +## DummyApplication + +The DummyApplication is a simple merkle key-value store. +Transactions of the form `key=value` are stored as key-value pairs in the tree. +Transactions without an `=` sign set the value to the key. +The app has no replay protection (other than what the mempool provides). + +## PersistentDummyApplication + +The PersistentDummyApplication wraps the DummyApplication +and provides two additional features: + +1) persistence of state across app restarts (using Tendermint's TMSP-Handshake mechanism) +2) validator set changes + +The state is persisted in leveldb along with the last block committed, +and the Handshake allows any necessary blocks to be replayed. +Validator set changes are effected using the following transaction format: + +``` +val:pubkey1/power1,addr2/power2,addr3/power3" +``` + +where `power1` is the new voting power for the validator with `pubkey1` (possibly a new one). +There is no sybil protection against new validators joining. +Validators can be removed by setting their power to `0`. + diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 0c6a9089..9bed4089 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -5,6 +5,7 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" + "github.com/tendermint/go-wire" "github.com/tendermint/tmsp/types" ) @@ -51,6 +52,12 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(query []byte) types.Result { index, value, exists := app.state.Get(query) - resStr := Fmt("Index=%v value=%v exists=%v", index, string(value), exists) - return types.NewResultOK([]byte(resStr), "") + queryResult := QueryResult{index, string(value), exists} + return types.NewResultOK(wire.JSONBytes(queryResult), "") +} + +type QueryResult struct { + Index int `json:"index"` + Value string `json:"value"` + Exists bool `json:"exists"` } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go new file mode 100644 index 00000000..e284f125 --- /dev/null +++ b/example/dummy/dummy_test.go @@ -0,0 +1,203 @@ +package dummy + +import ( + "bytes" + "io/ioutil" + "sort" + "testing" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-crypto" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) { + if r := dummy.AppendTx(tx); r.IsErr() { + t.Fatal(r) + } + if r := dummy.AppendTx(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 TestDummyKV(t *testing.T) { + dummy := NewDummyApplication() + key := "abc" + value := key + tx := []byte(key) + testDummy(t, dummy, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testDummy(t, dummy, tx, key, value) +} + +func TestPersistentDummyKV(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "tmsp-dummy-test") // TODO + if err != nil { + t.Fatal(err) + } + dummy := NewPersistentDummyApplication(dir) + key := "abc" + value := key + tx := []byte(key) + testDummy(t, dummy, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testDummy(t, dummy, tx, key, value) +} + +func TestPersistentDummyInfo(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "tmsp-dummy-test") // TODO + if err != nil { + t.Fatal(err) + } + dummy := NewPersistentDummyApplication(dir) + height := uint64(0) + + _, _, lastBlockInfo, _ := dummy.Info() + if lastBlockInfo.BlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, lastBlockInfo.BlockHeight) + } + + // make and apply block + height = uint64(1) + hash := []byte("foo") + header := &types.Header{ + Height: uint64(height), + } + dummy.BeginBlock(hash, header) + dummy.EndBlock(height) + dummy.Commit() + + _, _, lastBlockInfo, _ = dummy.Info() + if lastBlockInfo.BlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, lastBlockInfo.BlockHeight) + } + +} + +// add a validator, remove a validator, update a validator +func TestValSetChanges(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "tmsp-dummy-test") // TODO + if err != nil { + t.Fatal(err) + } + dummy := NewPersistentDummyApplication(dir) + + // init with some validators + total := 10 + 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() + vals[i] = &types.Validator{pubkey, uint64(power)} + } + // iniitalize with the first nInit + dummy.InitChain(vals[:nInit]) + + vals1, vals2 := vals[:nInit], dummy.Validators() + valsEqual(t, vals1, vals2) + + var v1, v2, v3 *types.Validator + + // add some validators + v1, v2 = vals[nInit], vals[nInit+1] + diff := []*types.Validator{v1, v2} + tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power) + tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power) + + makeApplyBlock(t, dummy, 1, diff, tx1, tx2) + + vals1, vals2 = vals[:nInit+2], dummy.Validators() + valsEqual(t, vals1, vals2) + + // remove some validators + v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit] + v1.Power = 0 + v2.Power = 0 + v3.Power = 0 + diff = []*types.Validator{v1, v2, v3} + tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) + tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power) + tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power) + + makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3) + + vals1 = append(vals[:nInit-2], vals[nInit+1]) + vals2 = dummy.Validators() + valsEqual(t, vals1, vals2) + + // update some validators + v1 = vals[0] + if v1.Power == 5 { + v1.Power = 6 + } else { + v1.Power = 5 + } + diff = []*types.Validator{v1} + tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) + + makeApplyBlock(t, dummy, 3, diff, tx1) + + vals1 = append([]*types.Validator{v1}, vals1[1:len(vals1)]...) + vals2 = dummy.Validators() + valsEqual(t, vals1, vals2) + +} + +func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) { + // make and apply block + height := uint64(heightInt) + hash := []byte("foo") + header := &types.Header{ + Height: height, + } + + dummyChain := dummy.(types.BlockchainAware) // hmm... + dummyChain.BeginBlock(hash, header) + for _, tx := range txs { + if r := dummy.AppendTx(tx); r.IsErr() { + t.Fatal(r) + } + } + diff2 := dummyChain.EndBlock(height) + dummy.Commit() + + valsEqual(t, diff, diff2) + +} + +// order doesn't matter +func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { + if len(vals1) != len(vals2) { + t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1)) + } + sort.Sort(types.Validators(vals1)) + sort.Sort(types.Validators(vals2)) + for i, v1 := range vals1 { + v2 := vals2[i] + if !bytes.Equal(v1.PubKey, v2.PubKey) || + v1.Power != v2.Power { + t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power) + } + } +} diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index cb2171f5..7fdb0a24 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -2,6 +2,9 @@ package dummy import ( "bytes" + "encoding/hex" + "strconv" + "strings" . "github.com/tendermint/go-common" dbm "github.com/tendermint/go-db" @@ -10,6 +13,10 @@ import ( "github.com/tendermint/tmsp/types" ) +const ( + ValidatorSetChangePrefix string = "val:" +) + //----------------------------------------- type PersistentDummyApplication struct { @@ -17,8 +24,12 @@ type PersistentDummyApplication struct { db dbm.DB // latest received + // TODO: move to merkle tree? blockHash []byte blockHeader *types.Header + + // validator set + changes []*types.Validator } func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { @@ -51,6 +62,15 @@ func (app *PersistentDummyApplication) SetOption(key string, value string) (log // tx is either "key=value" or just arbitrary bytes func (app *PersistentDummyApplication) AppendTx(tx []byte) types.Result { + // if it starts with "val:", update the validator set + // format is "val:pubkey/power" + if isValidatorTx(tx) { + // update validators in the merkle tree + // and in app.changes + return app.execValidatorTx(tx) + } + + // otherwise, update the key-value store return app.app.AppendTx(tx) } @@ -76,17 +96,29 @@ func (app *PersistentDummyApplication) Query(query []byte) types.Result { return app.app.Query(query) } +// Save the validators in the merkle tree func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) { - return + for _, v := range validators { + r := app.updateValidator(v) + if r.IsErr() { + log.Error("Error updating validators", "r", r) + } + } } +// Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(hash []byte, header *types.Header) { + // update latest block info app.blockHash = hash app.blockHeader = header + + // reset valset changes + app.changes = make([]*types.Validator, 0) } +// Update the validator set func (app *PersistentDummyApplication) EndBlock(height uint64) (diffs []*types.Validator) { - return nil + return app.changes } //----------------------------------------- @@ -120,3 +152,77 @@ func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { } db.Set(lastBlockKey, buf.Bytes()) } + +//--------------------------------------------- +// update validators + +func (app *PersistentDummyApplication) Validators() (validators []*types.Validator) { + app.app.state.Iterate(func(key, value []byte) bool { + if isValidatorTx(key) { + validator := new(types.Validator) + err := types.ReadMessage(bytes.NewBuffer(value), validator) + if err != nil { + panic(err) + } + validators = append(validators, validator) + } + return false + }) + return +} + +func MakeValSetChangeTx(pubkey []byte, power uint64) []byte { + return []byte(Fmt("val:%X/%d", pubkey, power)) +} + +func isValidatorTx(tx []byte) bool { + if strings.HasPrefix(string(tx), ValidatorSetChangePrefix) { + return true + } + return false +} + +// format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx +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)) + } + 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)) + } + power, err := strconv.Atoi(powerS) + if err != nil { + return types.ErrEncodingError.SetLog(Fmt("Power (%s) is not an int", powerS)) + } + + // update + return app.updateValidator(&types.Validator{pubkey, uint64(power)}) +} + +// add, update, or remove a validator +func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.Result { + key := []byte("val:" + string(v.PubKey)) + if v.Power == 0 { + // remove validator + if !app.app.state.Has(key) { + return types.ErrUnauthorized.SetLog(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)) + } + app.app.state.Set(key, value.Bytes()) + } + + // we only update the changes array if we succesfully updated the tree + app.changes = append(app.changes, v) + + return types.OK +} diff --git a/types/validators.go b/types/validators.go new file mode 100644 index 00000000..6494394e --- /dev/null +++ b/types/validators.go @@ -0,0 +1,24 @@ +package types + +import ( + "bytes" +) + +// validators implements sort + +type Validators []*Validator + +func (v Validators) Len() int { + return len(v) +} + +// XXX: doesn't distinguish same validator with different power +func (v Validators) Less(i, j int) bool { + return bytes.Compare(v[i].PubKey, v[j].PubKey) <= 0 +} + +func (v Validators) Swap(i, j int) { + v1 := v[i] + v[i] = v[j] + v[j] = v1 +} From dc13ec05a1500651d6156d10f29a34099a41f5e2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 Nov 2016 20:44:41 -0500 Subject: [PATCH 150/545] NewIAVLTree takes waldir --- example/dummy/dummy.go | 5 +---- example/dummy/persistent_dummy.go | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 9bed4089..80c1ad9d 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -14,10 +14,7 @@ type DummyApplication struct { } func NewDummyApplication() *DummyApplication { - state := merkle.NewIAVLTree( - 0, - nil, - ) + state := merkle.NewIAVLTree(0, ".", nil) return &DummyApplication{state: state} } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 7fdb0a24..230e537a 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -36,10 +36,7 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { db := dbm.NewDB("dummy", "leveldb", dbDir) lastBlock := LoadLastBlock(db) - stateTree := merkle.NewIAVLTree( - 0, - db, - ) + stateTree := merkle.NewIAVLTree(0, ".", db) stateTree.Load(lastBlock.AppHash) log.Notice("Loaded state", "block", lastBlock.BlockHeight, "root", stateTree.Hash()) From ef3eb4a30e09713f87d041fa6110f4e1cc0a74a3 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 Nov 2016 21:06:39 -0500 Subject: [PATCH 151/545] update glide --- glide.lock | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/glide.lock b/glide.lock index 9171ff8d..e82a60d4 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ hash: 603c43870dfc63a3113a3d13ae799038206bd77889e2e9596a860d3644b8fb67 -updated: 2016-11-15T14:46:00.011667442-05:00 +updated: 2016-11-22T20:57:55.984772241-05:00 imports: - name: github.com/btcsuite/btcd - version: d9a674e1b7bc09d0830d6986c71cf5f535d753c3 + version: afec1bd1245a4a19e6dfe1306974b733e7cbb9b8 subpackages: - btcec - name: github.com/btcsuite/fastsha256 @@ -10,7 +10,7 @@ imports: - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: da116c3771bf4a398a43f44e069195ef1c9688ef + version: 8ee79997227bf9b34611aee7946ae64735e6fd93 subpackages: - proto - name: github.com/golang/snappy @@ -39,8 +39,10 @@ imports: subpackages: - edwards25519 - extra25519 +- name: github.com/tendermint/go-autofile + version: 63186e34b33d78ae47fb0d25e5717b307fdf3603 - name: github.com/tendermint/go-common - version: fa3daa7abc253264c916c12fecce3effa01a1287 + version: 6b4160f2a57487f277c42bf06fd280195dfdb278 - name: github.com/tendermint/go-crypto version: 4b11d62bdb324027ea01554e5767b71174680ba0 - name: github.com/tendermint/go-db @@ -48,7 +50,7 @@ imports: - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 05042c6ab9cad51d12e4cecf717ae68e3b1409a8 + version: bfc4afe28c7a50045d4d1eb043e67460f8a51a4f - name: github.com/tendermint/go-process version: ba01cfbb58d446673beff17e72883cb49c835fb9 - name: github.com/tendermint/go-wire @@ -58,9 +60,9 @@ imports: subpackages: - term - name: github.com/urfave/cli - version: b4f4786f378c0c1d3336b5bb798094b166edf5a9 + version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/crypto - version: 9477e0b78b9ac3d0b03822fd95422e2fe07627cd + version: ede567c8e044a5913dad1d1af3696d9da953104c subpackages: - nacl/secretbox - openpgp/armor @@ -69,7 +71,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: cac22060de4e495155959e69adcb4b45763ccb10 + version: 4971afdc2f162e82d185353533d3cf16188a9f4e subpackages: - context - http2 @@ -79,11 +81,11 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: b699b7032584f0953262cb2788a0ca19bb494703 + version: 30237cf4eefd639b184d1f2cb77a581ea0be8947 subpackages: - unix - name: google.golang.org/grpc - version: 0d9891286aca15aeb2b0a73be9f5946c3cfefa85 + version: 63bd55dfbf781b183216d2dd4433a659c947648a subpackages: - codes - credentials From 37b5cca87c37a8ac90bc8d369a6ed489442c29cb Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 Nov 2016 21:06:50 -0500 Subject: [PATCH 152/545] update cli example for new query result format --- tests/test_cli/ex1.tmsp.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.tmsp.out index 89bd61c2..836df8ae 100644 --- a/tests/test_cli/ex1.tmsp.out +++ b/tests/test_cli/ex1.tmsp.out @@ -17,7 +17,7 @@ > query abc -> code: OK --> data: {Index=0 value=abc exists=true} +-> data: {{"index":0,"value":"abc","exists":true}} > append_tx def=xyz -> code: OK @@ -27,5 +27,5 @@ > query def -> code: OK --> data: {Index=1 value=xyz exists=true} +-> data: {{"index":1,"value":"xyz","exists":true}} From e813b8c71d3953c0c77e50e877dc4891d1a52de9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 23 Nov 2016 18:22:22 -0500 Subject: [PATCH 153/545] counter: fix tx buffer overflow --- example/counter/counter.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/example/counter/counter.go b/example/counter/counter.go index 230556e1..ef57d840 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -30,6 +30,9 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) func (app *CounterApplication) AppendTx(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))) + } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) @@ -43,6 +46,9 @@ func (app *CounterApplication) AppendTx(tx []byte) types.Result { 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))) + } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) From 2dce41ad6a517548f2b7fc44c191df18b11c2e67 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 23 Nov 2016 18:22:44 -0500 Subject: [PATCH 154/545] types: pretty print validators --- types/validators.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/types/validators.go b/types/validators.go index 6494394e..185355d1 100644 --- a/types/validators.go +++ b/types/validators.go @@ -2,6 +2,8 @@ package types import ( "bytes" + + "github.com/tendermint/go-wire" ) // validators implements sort @@ -22,3 +24,18 @@ func (v Validators) Swap(i, j int) { v[i] = v[j] v[j] = v1 } + +//------------------------------------- + +type validatorPretty struct { + PubKey []byte `json:"pub_key"` + Power uint64 `json:"power"` +} + +func ValidatorsString(vs Validators) string { + s := make([]validatorPretty, len(vs)) + for i, v := range vs { + s[i] = validatorPretty{v.PubKey, v.Power} + } + return string(wire.JSONBytes(s)) +} From 40448a3897dc870cc8e57a41a1e2872e976de539 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 23 Nov 2016 18:23:35 -0500 Subject: [PATCH 155/545] types: update LastBlockInfo and ConfigInfo --- example/dummy/persistent_dummy.go | 5 +- types/types.pb.go | 254 ++++++++++++++++-------------- types/types.proto | 7 +- 3 files changed, 137 insertions(+), 129 deletions(-) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 230e537a..ed2326f1 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -25,7 +25,6 @@ type PersistentDummyApplication struct { // latest received // TODO: move to merkle tree? - blockHash []byte blockHeader *types.Header // validator set @@ -82,7 +81,6 @@ func (app *PersistentDummyApplication) Commit() types.Result { lastBlock := types.LastBlockInfo{ BlockHeight: app.blockHeader.Height, - BlockHash: app.blockHash, AppHash: appHash, // this hash will be in the next block header } SaveLastBlock(app.db, lastBlock) @@ -106,7 +104,6 @@ func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(hash []byte, header *types.Header) { // update latest block info - app.blockHash = hash app.blockHeader = header // reset valset changes @@ -140,7 +137,7 @@ func LoadLastBlock(db dbm.DB) (lastBlock types.LastBlockInfo) { } func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { - log.Notice("Saving block", "height", lastBlock.BlockHeight, "hash", lastBlock.BlockHash, "root", lastBlock.AppHash) + log.Notice("Saving block", "height", lastBlock.BlockHeight, "root", lastBlock.AppHash) buf, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(lastBlock, buf, n, err) if *err != nil { diff --git a/types/types.pb.go b/types/types.pb.go index 7204767e..5dc576d0 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1503,8 +1503,7 @@ func (m *TMSPInfo) GetVersion() string { type LastBlockInfo struct { BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` - BlockHash []byte `protobuf:"bytes,2,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + AppHash []byte `protobuf:"bytes,2,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } func (m *LastBlockInfo) Reset() { *m = LastBlockInfo{} } @@ -1519,13 +1518,6 @@ func (m *LastBlockInfo) GetBlockHeight() uint64 { return 0 } -func (m *LastBlockInfo) GetBlockHash() []byte { - if m != nil { - return m.BlockHash - } - return nil -} - func (m *LastBlockInfo) GetAppHash() []byte { if m != nil { return m.AppHash @@ -1534,7 +1526,9 @@ func (m *LastBlockInfo) GetAppHash() []byte { } type ConfigInfo struct { - MaxBlockSize uint64 `protobuf:"varint,1,opt,name=max_block_size,json=maxBlockSize" json:"max_block_size,omitempty"` + MaxBlockSizeBytes uint64 `protobuf:"varint,1,opt,name=max_block_size_bytes,json=maxBlockSizeBytes" json:"max_block_size_bytes,omitempty"` + MaxBlockSizeTxs uint64 `protobuf:"varint,2,opt,name=max_block_size_txs,json=maxBlockSizeTxs" json:"max_block_size_txs,omitempty"` + MaxTxSize uint64 `protobuf:"varint,3,opt,name=max_tx_size,json=maxTxSize" json:"max_tx_size,omitempty"` } func (m *ConfigInfo) Reset() { *m = ConfigInfo{} } @@ -1542,9 +1536,23 @@ func (m *ConfigInfo) String() string { return proto.CompactTextString func (*ConfigInfo) ProtoMessage() {} func (*ConfigInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } -func (m *ConfigInfo) GetMaxBlockSize() uint64 { +func (m *ConfigInfo) GetMaxBlockSizeBytes() uint64 { if m != nil { - return m.MaxBlockSize + return m.MaxBlockSizeBytes + } + return 0 +} + +func (m *ConfigInfo) GetMaxBlockSizeTxs() uint64 { + if m != nil { + return m.MaxBlockSizeTxs + } + return 0 +} + +func (m *ConfigInfo) GetMaxTxSize() uint64 { + if m != nil { + return m.MaxTxSize } return 0 } @@ -2143,114 +2151,116 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1743 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0xdb, 0xc8, - 0x15, 0x16, 0x29, 0x6e, 0x78, 0xa4, 0xa8, 0xd6, 0xd3, 0x46, 0x33, 0x49, 0x95, 0x07, 0xf1, 0x64, - 0x24, 0xc7, 0x65, 0xa7, 0xe4, 0x9a, 0x29, 0x3b, 0x93, 0x4a, 0x95, 0x65, 0x6b, 0x2c, 0xd5, 0xc4, - 0xb6, 0x02, 0x7b, 0x7c, 0xc8, 0x52, 0x2c, 0x88, 0x68, 0x92, 0x88, 0x40, 0x00, 0x06, 0x1a, 0x1a, - 0xca, 0xff, 0x60, 0x7e, 0x49, 0xae, 0xb9, 0xe4, 0x92, 0x6b, 0x4e, 0xd9, 0x97, 0x5f, 0x34, 0xf5, - 0xba, 0x1b, 0x00, 0x01, 0x81, 0x3e, 0xf9, 0xc2, 0xc2, 0x5b, 0xbb, 0xfb, 0x2d, 0x5f, 0xbf, 0x26, - 0x6c, 0x89, 0xeb, 0x90, 0xc7, 0x0f, 0xe4, 0xef, 0xfd, 0x30, 0x0a, 0x44, 0x80, 0x4d, 0x49, 0x98, - 0x7f, 0x6d, 0x40, 0xdb, 0xe2, 0xef, 0x12, 0x1e, 0x0b, 0x3c, 0x80, 0x06, 0x1f, 0xcf, 0x82, 0x41, - 0xed, 0x76, 0xed, 0xa0, 0x7b, 0x84, 0xf7, 0x95, 0xba, 0x96, 0x9e, 0x8c, 0x67, 0xc1, 0xe9, 0x9a, - 0x25, 0x35, 0xf0, 0xa7, 0xd0, 0x9c, 0x78, 0x49, 0x3c, 0x1b, 0xd4, 0xa5, 0xea, 0x76, 0x51, 0xf5, - 0x2b, 0x12, 0x9d, 0xae, 0x59, 0x4a, 0x87, 0xdc, 0xba, 0xfe, 0x24, 0x18, 0xac, 0x57, 0xb9, 0x3d, - 0xf3, 0x27, 0xd2, 0x2d, 0x69, 0xe0, 0x23, 0x80, 0x98, 0x8b, 0x51, 0x10, 0x0a, 0x37, 0xf0, 0x07, - 0x0d, 0xa9, 0xbf, 0x5f, 0xd4, 0x7f, 0xcd, 0xc5, 0x2b, 0x29, 0x3e, 0x5d, 0xb3, 0x8c, 0x38, 0x25, - 0xf0, 0x73, 0x30, 0xec, 0x30, 0xe4, 0xbe, 0x33, 0x12, 0x8b, 0x41, 0x53, 0x1a, 0xee, 0x15, 0x0d, - 0x9f, 0x48, 0xf1, 0x9b, 0xc5, 0xe9, 0x9a, 0xd5, 0xb1, 0xf5, 0x37, 0x1e, 0x41, 0x67, 0x3c, 0xe3, - 0xe3, 0x4b, 0xb2, 0x6a, 0x49, 0xab, 0xdd, 0xa2, 0xd5, 0x53, 0x92, 0x4a, 0xa3, 0xf6, 0x58, 0x7d, - 0xe2, 0x7d, 0x68, 0x8d, 0x83, 0xf9, 0xdc, 0x15, 0x83, 0xb6, 0xb4, 0xd8, 0x29, 0x59, 0x48, 0xd9, - 0xe9, 0x9a, 0xa5, 0xb5, 0x28, 0x56, 0xef, 0x12, 0x1e, 0x5d, 0x0f, 0x3a, 0x55, 0xb1, 0xfa, 0x35, - 0x89, 0x28, 0x56, 0x52, 0x87, 0x22, 0xe0, 0xfa, 0xae, 0x18, 0x8d, 0x67, 0xb6, 0xeb, 0x0f, 0x8c, - 0xaa, 0x08, 0x9c, 0xf9, 0xae, 0x78, 0x4a, 0x62, 0x8a, 0x80, 0x9b, 0x12, 0xf8, 0x25, 0x74, 0x2f, - 0xf8, 0xd4, 0xf5, 0x47, 0x17, 0x5e, 0x30, 0xbe, 0x1c, 0x80, 0x34, 0x1d, 0x14, 0x4d, 0x8f, 0x49, - 0xe1, 0x98, 0xe4, 0xa7, 0x6b, 0x16, 0x5c, 0x64, 0x14, 0x85, 0x8f, 0x62, 0xa7, 0x4c, 0xbb, 0x55, - 0xe1, 0x3b, 0xf1, 0x9d, 0xd4, 0xb0, 0xc3, 0xf5, 0xf7, 0x71, 0x1b, 0x9a, 0x57, 0xb6, 0x97, 0x70, - 0xf3, 0x33, 0xe8, 0x2e, 0x95, 0x09, 0x0e, 0xa0, 0x3d, 0xe7, 0x71, 0x6c, 0x4f, 0xb9, 0xac, 0x25, - 0xc3, 0x4a, 0x49, 0xb3, 0x0f, 0xbd, 0xe5, 0x22, 0x31, 0x37, 0x32, 0x43, 0x2a, 0x04, 0xf3, 0xe7, - 0xc0, 0xca, 0x79, 0x46, 0x06, 0xeb, 0x97, 0xfc, 0x5a, 0x3b, 0xa2, 0x4f, 0xdc, 0xd1, 0xcb, 0xca, - 0xea, 0x33, 0x2c, 0xbd, 0x87, 0x4f, 0x60, 0xb3, 0x94, 0x6a, 0xec, 0x43, 0x5d, 0x2c, 0xa4, 0x65, - 0xcf, 0xaa, 0x8b, 0x85, 0x79, 0x1b, 0xfa, 0xc5, 0xbc, 0xde, 0xd0, 0xb8, 0x93, 0xed, 0x4f, 0x26, - 0x86, 0x96, 0x52, 0xc9, 0x53, 0x2a, 0x8a, 0x30, 0x37, 0x61, 0xa3, 0x90, 0x6d, 0xf3, 0x59, 0xb6, - 0xef, 0x2c, 0x3b, 0xf8, 0x33, 0x80, 0x2b, 0xdb, 0x73, 0x1d, 0x5b, 0x04, 0x51, 0x3c, 0xa8, 0xdd, - 0x5e, 0x3f, 0xe8, 0x1e, 0x31, 0x1d, 0xd4, 0xb7, 0xa9, 0xc0, 0x5a, 0xd2, 0x31, 0x5f, 0xc2, 0xd6, - 0x8d, 0x44, 0x21, 0x42, 0x63, 0x66, 0xc7, 0x33, 0xbd, 0x01, 0xf9, 0x8d, 0x9f, 0x42, 0x6b, 0xc6, - 0x6d, 0x87, 0x47, 0xba, 0xff, 0x36, 0xb4, 0xdb, 0x53, 0xc9, 0xb4, 0xb4, 0xd0, 0x3c, 0xcc, 0x22, - 0x92, 0x66, 0x0f, 0xf7, 0xc8, 0xd2, 0x9d, 0xce, 0x84, 0xf4, 0xd7, 0xb0, 0x34, 0x65, 0x7e, 0xd7, - 0x84, 0x8e, 0xc5, 0xe3, 0x30, 0xf0, 0x63, 0x8e, 0x8f, 0xc0, 0xe0, 0x8b, 0x31, 0x57, 0x5d, 0x58, - 0x2b, 0x15, 0x92, 0xd2, 0x39, 0x49, 0xe5, 0x54, 0x84, 0x99, 0x32, 0x1e, 0x6a, 0x04, 0x29, 0xc3, - 0x82, 0x36, 0x5a, 0x86, 0x90, 0x7b, 0x29, 0x84, 0xac, 0x97, 0xba, 0x48, 0xe9, 0x96, 0x30, 0xe4, - 0x50, 0x63, 0x48, 0xa3, 0xd2, 0x71, 0x01, 0x44, 0x1e, 0x17, 0x40, 0xa4, 0x59, 0xb9, 0xfd, 0x15, - 0x28, 0xf2, 0xc5, 0x32, 0x8a, 0xb4, 0x4a, 0xcd, 0xa7, 0x2c, 0x2b, 0x61, 0xe4, 0xe1, 0x12, 0x8c, - 0xb4, 0x4b, 0xdd, 0xa3, 0xcc, 0x2a, 0x70, 0xe4, 0x41, 0x86, 0x23, 0x9d, 0x12, 0xf2, 0x68, 0x93, - 0x32, 0x90, 0xdc, 0x4b, 0x6b, 0xd1, 0xa8, 0x8c, 0x58, 0x09, 0x49, 0x1e, 0x17, 0x90, 0x04, 0x2a, - 0xc3, 0xb0, 0x02, 0x4a, 0x7e, 0x51, 0x84, 0x12, 0x85, 0x07, 0xb7, 0x4a, 0xb6, 0x2b, 0xb1, 0xe4, - 0x8b, 0x65, 0x2c, 0xe9, 0x55, 0x06, 0xf1, 0xc3, 0x60, 0x72, 0x48, 0x6d, 0x50, 0x2a, 0x33, 0x6a, - 0x44, 0x1e, 0x45, 0x41, 0xa4, 0x71, 0x40, 0x11, 0xe6, 0x01, 0xb5, 0x6b, 0x5e, 0x5c, 0x1f, 0x00, - 0x1e, 0xd9, 0xb2, 0x4b, 0xa5, 0x65, 0xfe, 0xa9, 0x96, 0xdb, 0x52, 0xfd, 0x50, 0xa3, 0xc9, 0x12, - 0x53, 0x86, 0xaa, 0x96, 0xee, 0x81, 0x21, 0xe6, 0x71, 0x38, 0x92, 0x02, 0x55, 0xd4, 0x9b, 0xfa, - 0x2c, 0x6f, 0x5e, 0xbc, 0x3e, 0x27, 0x3b, 0xab, 0x43, 0x1a, 0xd2, 0xc3, 0x43, 0x00, 0xcf, 0x8e, - 0x85, 0x3e, 0x7a, 0xb1, 0xae, 0x7f, 0x65, 0xc7, 0x42, 0x9e, 0x53, 0xda, 0x18, 0x5e, 0x4a, 0xe2, - 0x21, 0x95, 0x81, 0x3f, 0x71, 0xa7, 0xba, 0xb6, 0xb7, 0xb4, 0xc1, 0x53, 0xc9, 0x94, 0xda, 0x5a, - 0xc1, 0xfc, 0x34, 0x0f, 0x4c, 0x01, 0x1e, 0xbd, 0x60, 0x9a, 0xc2, 0xa3, 0x17, 0x4c, 0xcd, 0xdf, - 0x13, 0x18, 0x15, 0xab, 0x15, 0x7f, 0x0c, 0x8d, 0x71, 0xe0, 0xa8, 0xa8, 0xf4, 0xb3, 0x33, 0x3c, - 0x0d, 0x1c, 0xfe, 0xe6, 0x3a, 0xe4, 0x96, 0x14, 0x52, 0x04, 0x1c, 0x5b, 0xd8, 0xf2, 0xa0, 0x3d, - 0x4b, 0x7e, 0xa7, 0xee, 0xd7, 0x73, 0xf7, 0xbf, 0x23, 0x54, 0x29, 0x54, 0xf5, 0xc7, 0xf4, 0xfe, - 0x9b, 0x3c, 0x4f, 0x0a, 0x81, 0x3f, 0xa2, 0xef, 0xdf, 0x12, 0xfc, 0x2f, 0x37, 0xd7, 0xc7, 0x74, - 0xbe, 0x9d, 0x27, 0x27, 0x6b, 0x2b, 0x73, 0x07, 0xf0, 0x66, 0xbf, 0xa8, 0x5b, 0xae, 0xd8, 0x09, - 0xf8, 0x13, 0x68, 0x3a, 0xee, 0x64, 0x12, 0x0f, 0x1a, 0x2b, 0x2e, 0x0a, 0x25, 0x36, 0xef, 0x40, - 0x27, 0xad, 0x3c, 0xaa, 0xf6, 0xb7, 0x3c, 0x8a, 0x53, 0x94, 0x36, 0xac, 0x94, 0x34, 0x3d, 0xd8, - 0x28, 0x14, 0x1c, 0x7e, 0x02, 0x3d, 0x59, 0x95, 0xa3, 0x02, 0xfa, 0x77, 0x25, 0xef, 0x54, 0xb2, - 0xf0, 0x47, 0x00, 0x5a, 0xc5, 0xd6, 0x83, 0x5d, 0xcf, 0x32, 0x94, 0x02, 0xdd, 0x39, 0xb7, 0x80, - 0xf0, 0x4e, 0x09, 0xd7, 0xa5, 0xb0, 0x6d, 0x87, 0x21, 0x89, 0xcc, 0x23, 0x80, 0xbc, 0x5a, 0xf1, - 0x0e, 0xf4, 0xe7, 0xf6, 0x42, 0x35, 0xc1, 0x28, 0x76, 0xdf, 0x73, 0xbd, 0x58, 0x6f, 0x6e, 0x2f, - 0xe4, 0x86, 0x5e, 0xbb, 0xef, 0xb9, 0xf9, 0xc7, 0x3a, 0xb4, 0xd4, 0x75, 0x45, 0x9e, 0x25, 0x48, - 0x8d, 0x5c, 0x27, 0x3d, 0x87, 0xa4, 0xcf, 0x9c, 0xa5, 0xeb, 0xaa, 0xbe, 0x7c, 0x5d, 0x51, 0x4a, - 0x84, 0x3b, 0xe7, 0x72, 0x23, 0x0d, 0x4b, 0x7e, 0xe3, 0x3e, 0xb4, 0xfd, 0x64, 0x3e, 0x12, 0x8b, - 0x58, 0x76, 0x52, 0xc3, 0x6a, 0xf9, 0xc9, 0xfc, 0xcd, 0x22, 0xc6, 0x23, 0xd8, 0xc8, 0xdb, 0x92, - 0x16, 0x51, 0x77, 0x42, 0x5f, 0x87, 0x58, 0x05, 0xe9, 0x99, 0xd5, 0xcd, 0x7a, 0xf2, 0xcc, 0xc1, - 0x03, 0x60, 0xd2, 0x46, 0x41, 0xaf, 0x3a, 0x75, 0x4b, 0x9e, 0xba, 0x4f, 0x7c, 0x8d, 0xcd, 0x14, - 0x97, 0x1f, 0x80, 0x41, 0x15, 0xa1, 0x54, 0xda, 0x52, 0xa5, 0x43, 0x0c, 0x29, 0xfc, 0x0c, 0x36, - 0xf3, 0xfb, 0x5d, 0xa9, 0x74, 0x94, 0x97, 0x9c, 0x7d, 0x23, 0xba, 0x46, 0x31, 0xba, 0x67, 0xd0, - 0xd6, 0x5b, 0xac, 0x9c, 0x05, 0xee, 0x42, 0x33, 0xb4, 0x23, 0x11, 0x6b, 0x78, 0x4a, 0xf1, 0xe6, - 0xdc, 0x8e, 0x68, 0x86, 0xd2, 0x13, 0x81, 0x52, 0x31, 0x1f, 0xc3, 0x46, 0x81, 0x4f, 0xa8, 0x2a, - 0x02, 0x61, 0x7b, 0x3a, 0x45, 0x8a, 0xc8, 0x96, 0xa9, 0xe7, 0xcb, 0x98, 0x8f, 0xc1, 0xc8, 0x6a, - 0x91, 0xd2, 0x12, 0x26, 0x17, 0x5f, 0xf3, 0x74, 0x2c, 0xd2, 0x14, 0xb9, 0x0b, 0x83, 0x6f, 0xf5, - 0x58, 0xd2, 0xb0, 0x14, 0x71, 0xf7, 0x2f, 0x35, 0xe8, 0xbe, 0x50, 0x30, 0x4c, 0x5d, 0x85, 0x9b, - 0xd0, 0x7d, 0x99, 0x78, 0x9e, 0x66, 0xb1, 0x35, 0xec, 0x40, 0x83, 0xd0, 0x9b, 0xd5, 0xd0, 0x80, - 0xa6, 0x44, 0x67, 0x56, 0x27, 0x26, 0x95, 0x13, 0x5b, 0xc7, 0x0d, 0x30, 0x32, 0xb8, 0x63, 0x0d, - 0x22, 0xb3, 0x6b, 0x81, 0x35, 0xb1, 0x07, 0x9d, 0x14, 0xe5, 0xd8, 0x16, 0x76, 0xa1, 0xad, 0x41, - 0x89, 0x21, 0x02, 0xb4, 0x54, 0xa2, 0xd8, 0x36, 0x79, 0x96, 0x78, 0xc2, 0x76, 0xc8, 0x41, 0xd6, - 0xa1, 0x6c, 0x17, 0xfb, 0x00, 0x79, 0x6f, 0xb2, 0x3d, 0x72, 0x98, 0x76, 0x25, 0xdb, 0xbf, 0xfb, - 0xe7, 0x26, 0x74, 0x52, 0x3c, 0xc0, 0x16, 0xd4, 0x5f, 0x7d, 0xcd, 0xd6, 0x70, 0x0b, 0x36, 0xce, - 0x7c, 0xc1, 0x23, 0xdf, 0xf6, 0x4e, 0xe8, 0x1e, 0x62, 0x35, 0x62, 0x9d, 0xf8, 0xe3, 0xc0, 0x71, - 0xfd, 0xa9, 0x62, 0xd5, 0xc9, 0xd1, 0xb1, 0xed, 0xbc, 0x0c, 0xfc, 0x31, 0x67, 0xeb, 0xc8, 0xa0, - 0xf7, 0x8d, 0x6f, 0x27, 0x62, 0x16, 0x44, 0xee, 0x7b, 0xee, 0xb0, 0x06, 0xee, 0xc2, 0xd6, 0x99, - 0x1f, 0x27, 0x93, 0x89, 0x3b, 0x76, 0xb9, 0x2f, 0xbe, 0x4a, 0x7c, 0x27, 0x66, 0x4d, 0x44, 0xe8, - 0x7f, 0xe3, 0x5f, 0xfa, 0xc1, 0xb7, 0xbe, 0x1e, 0xde, 0x58, 0x0b, 0x07, 0xb0, 0x73, 0x6c, 0xc7, - 0xfc, 0x59, 0x12, 0x7a, 0xee, 0xd8, 0x16, 0xfc, 0x89, 0xe3, 0x44, 0x3c, 0x8e, 0x19, 0x27, 0x27, - 0x24, 0x29, 0xae, 0x3d, 0x49, 0x0d, 0x0a, 0xfe, 0x39, 0x8f, 0xd9, 0x14, 0x6f, 0xc1, 0xee, 0x0d, - 0x89, 0x5c, 0x79, 0x86, 0x3f, 0x84, 0x41, 0x59, 0xf4, 0xdc, 0x8e, 0xcf, 0x23, 0x77, 0xcc, 0x99, - 0x8b, 0x3b, 0xc0, 0x94, 0x54, 0x96, 0xee, 0x99, 0x1f, 0x26, 0x82, 0xfd, 0x21, 0x5d, 0x5f, 0x73, - 0x5f, 0x25, 0x82, 0xd8, 0x97, 0x25, 0xf6, 0xb9, 0x2c, 0x0f, 0xe6, 0xe1, 0x3e, 0x6c, 0x2f, 0xb1, - 0x5f, 0xd3, 0xf9, 0x28, 0x3a, 0xf3, 0x7c, 0xbf, 0x4a, 0xe0, 0x4e, 0x7d, 0x5b, 0x24, 0x11, 0x67, - 0x3e, 0xee, 0x01, 0x92, 0x44, 0x87, 0x24, 0x3d, 0x78, 0x90, 0xae, 0xa0, 0xf9, 0x7a, 0x85, 0xb0, - 0xcc, 0xf6, 0x92, 0xa9, 0xeb, 0xb3, 0x77, 0xb8, 0x0b, 0xec, 0x79, 0x70, 0xa5, 0xb9, 0x27, 0xbe, - 0x70, 0xc5, 0x35, 0xfb, 0x5b, 0x0d, 0x77, 0x60, 0x33, 0x67, 0x3f, 0x8f, 0x82, 0x24, 0x64, 0x7f, - 0xaf, 0xe1, 0x3e, 0x60, 0xce, 0x3d, 0x8f, 0x82, 0x30, 0x88, 0x6d, 0x8f, 0xfd, 0xa3, 0x86, 0x7b, - 0xb0, 0xf5, 0x3c, 0xb8, 0xca, 0xb2, 0xa0, 0x0c, 0xfe, 0x99, 0x1a, 0x64, 0xfc, 0x17, 0x7c, 0x7e, - 0xc1, 0x23, 0xf6, 0xaf, 0x1a, 0xde, 0x82, 0x9d, 0x65, 0x41, 0xe6, 0xeb, 0xdf, 0x35, 0xbd, 0xa3, - 0x4c, 0xf4, 0x36, 0x10, 0x9c, 0xfd, 0x27, 0x65, 0xeb, 0x38, 0x68, 0x47, 0xff, 0xad, 0xe1, 0x36, - 0xf4, 0x73, 0xb6, 0xd4, 0xfd, 0x5f, 0x0d, 0x87, 0xb0, 0x5b, 0x60, 0xba, 0xfe, 0xf4, 0x9c, 0x3a, - 0x8e, 0xfd, 0xbf, 0x76, 0xf4, 0x5d, 0x13, 0x36, 0xe9, 0xa2, 0x78, 0x12, 0xaa, 0x05, 0x68, 0x54, - 0x78, 0xa0, 0xfa, 0x0c, 0x2b, 0x5e, 0xf6, 0xc3, 0xaa, 0x59, 0x1d, 0x8f, 0x74, 0x3b, 0x62, 0xd5, - 0x03, 0x7f, 0x58, 0x39, 0xb2, 0xd3, 0x22, 0x6a, 0x9c, 0xba, 0xf9, 0xce, 0x1f, 0x56, 0xcd, 0xed, - 0xf8, 0xcb, 0xa5, 0xf6, 0xc6, 0x55, 0xaf, 0xfd, 0xe1, 0xca, 0x09, 0x1e, 0xbf, 0xcc, 0x01, 0x00, - 0x57, 0xbc, 0xf9, 0x87, 0xab, 0xa6, 0x78, 0x7c, 0x94, 0xe1, 0x05, 0x56, 0xbf, 0xfc, 0x87, 0x2b, - 0x26, 0x79, 0x8a, 0x8d, 0x1a, 0x50, 0xaa, 0x1e, 0xf4, 0xc3, 0xca, 0xe1, 0x1c, 0x3f, 0x4f, 0x01, - 0x09, 0x2b, 0xff, 0x34, 0x18, 0x56, 0x3f, 0x01, 0x28, 0x42, 0xf9, 0xb3, 0x72, 0xd5, 0xbf, 0x01, - 0xc3, 0x95, 0xc3, 0x3d, 0x3e, 0x59, 0x46, 0x38, 0x5c, 0xf9, 0x9f, 0xc0, 0x70, 0xf5, 0x88, 0x4f, - 0x41, 0xce, 0xdf, 0x90, 0xd5, 0xff, 0x0c, 0x0c, 0x57, 0x4d, 0xf9, 0x17, 0x2d, 0xf9, 0x8f, 0xd3, - 0xc3, 0xef, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa2, 0x81, 0xd5, 0x01, 0x86, 0x12, 0x00, 0x00, + // 1774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x73, 0xdb, 0xc8, + 0x11, 0x16, 0x24, 0x3e, 0x9b, 0x12, 0x35, 0x6a, 0x51, 0x12, 0xcd, 0xa4, 0x52, 0x5e, 0x64, 0x37, + 0x2b, 0x79, 0x5d, 0x76, 0x4a, 0xae, 0xdd, 0xb2, 0xb3, 0xa9, 0x54, 0x59, 0xb6, 0xd6, 0x54, 0x6d, + 0x6c, 0x2b, 0xb0, 0xd6, 0x87, 0x3c, 0x8a, 0x05, 0x11, 0x43, 0x12, 0x11, 0x09, 0xc0, 0xc0, 0xc0, + 0x4b, 0xf9, 0x1f, 0x6c, 0xfe, 0x48, 0xae, 0xb9, 0xe4, 0x92, 0x6b, 0x4e, 0x79, 0x3f, 0x7e, 0xd1, + 0x56, 0xcf, 0x0c, 0x9e, 0x02, 0x7d, 0xf2, 0x85, 0xc5, 0xe9, 0xd7, 0xcc, 0x74, 0x7f, 0xfd, 0xcd, + 0x60, 0x60, 0x47, 0x5c, 0x07, 0x3c, 0xba, 0x2f, 0x7f, 0xef, 0x05, 0xa1, 0x2f, 0x7c, 0xac, 0xcb, + 0x81, 0xf9, 0xd7, 0x1a, 0x34, 0x2d, 0xfe, 0x26, 0xe6, 0x91, 0xc0, 0x43, 0xa8, 0xf1, 0xf1, 0xcc, + 0xef, 0x1b, 0xb7, 0x8d, 0xc3, 0xce, 0x31, 0xde, 0x53, 0xe6, 0x5a, 0x7b, 0x3a, 0x9e, 0xf9, 0xc3, + 0x35, 0x4b, 0x5a, 0xe0, 0x67, 0x50, 0x9f, 0xcc, 0xe3, 0x68, 0xd6, 0x5f, 0x97, 0xa6, 0xbb, 0x45, + 0xd3, 0xaf, 0x48, 0x35, 0x5c, 0xb3, 0x94, 0x0d, 0x85, 0x75, 0xbd, 0x89, 0xdf, 0xdf, 0xa8, 0x0a, + 0x7b, 0xe6, 0x4d, 0x64, 0x58, 0xb2, 0xc0, 0x87, 0x00, 0x11, 0x17, 0x23, 0x3f, 0x10, 0xae, 0xef, + 0xf5, 0x6b, 0xd2, 0xfe, 0xa0, 0x68, 0xff, 0x8a, 0x8b, 0x97, 0x52, 0x3d, 0x5c, 0xb3, 0xda, 0x51, + 0x32, 0xc0, 0xcf, 0xa1, 0x6d, 0x07, 0x01, 0xf7, 0x9c, 0x91, 0x58, 0xf6, 0xeb, 0xd2, 0x71, 0xbf, + 0xe8, 0xf8, 0x58, 0xaa, 0x2f, 0x96, 0xc3, 0x35, 0xab, 0x65, 0xeb, 0xff, 0x78, 0x0c, 0xad, 0xf1, + 0x8c, 0x8f, 0xaf, 0xc8, 0xab, 0x21, 0xbd, 0xf6, 0x8a, 0x5e, 0x4f, 0x48, 0x2b, 0x9d, 0x9a, 0x63, + 0xf5, 0x17, 0xef, 0x41, 0x63, 0xec, 0x2f, 0x16, 0xae, 0xe8, 0x37, 0xa5, 0x47, 0xaf, 0xe4, 0x21, + 0x75, 0xc3, 0x35, 0x4b, 0x5b, 0x51, 0xae, 0xde, 0xc4, 0x3c, 0xbc, 0xee, 0xb7, 0xaa, 0x72, 0xf5, + 0x2b, 0x52, 0x51, 0xae, 0xa4, 0x0d, 0x65, 0xc0, 0xf5, 0x5c, 0x31, 0x1a, 0xcf, 0x6c, 0xd7, 0xeb, + 0xb7, 0xab, 0x32, 0x70, 0xe6, 0xb9, 0xe2, 0x09, 0xa9, 0x29, 0x03, 0x6e, 0x32, 0xc0, 0x2f, 0xa1, + 0x73, 0xc9, 0xa7, 0xae, 0x37, 0xba, 0x9c, 0xfb, 0xe3, 0xab, 0x3e, 0x48, 0xd7, 0x7e, 0xd1, 0xf5, + 0x84, 0x0c, 0x4e, 0x48, 0x3f, 0x5c, 0xb3, 0xe0, 0x32, 0x1d, 0x51, 0xfa, 0x28, 0x77, 0xca, 0xb5, + 0x53, 0x95, 0xbe, 0x53, 0xcf, 0x49, 0x1c, 0x5b, 0x5c, 0xff, 0x3f, 0x69, 0x42, 0xfd, 0xad, 0x3d, + 0x8f, 0xb9, 0xf9, 0x29, 0x74, 0x72, 0x30, 0xc1, 0x3e, 0x34, 0x17, 0x3c, 0x8a, 0xec, 0x29, 0x97, + 0x58, 0x6a, 0x5b, 0xc9, 0xd0, 0xec, 0xc2, 0x66, 0x1e, 0x24, 0xe6, 0x56, 0xea, 0x48, 0x40, 0x30, + 0x7f, 0x06, 0xac, 0x5c, 0x67, 0x64, 0xb0, 0x71, 0xc5, 0xaf, 0x75, 0x20, 0xfa, 0x8b, 0x3d, 0x3d, + 0xad, 0x44, 0x5f, 0xdb, 0xd2, 0x6b, 0xf8, 0x08, 0xb6, 0x4b, 0xa5, 0xc6, 0x2e, 0xac, 0x8b, 0xa5, + 0xf4, 0xdc, 0xb4, 0xd6, 0xc5, 0xd2, 0xbc, 0x0d, 0xdd, 0x62, 0x5d, 0x6f, 0x58, 0x7c, 0x9c, 0xae, + 0x4f, 0x16, 0x86, 0xa6, 0x52, 0xc5, 0x53, 0x26, 0x6a, 0x60, 0x6e, 0xc3, 0x56, 0xa1, 0xda, 0xe6, + 0xd3, 0x74, 0xdd, 0x69, 0x75, 0xf0, 0xa7, 0x00, 0x6f, 0xed, 0xb9, 0xeb, 0xd8, 0xc2, 0x0f, 0xa3, + 0xbe, 0x71, 0x7b, 0xe3, 0xb0, 0x73, 0xcc, 0x74, 0x52, 0x5f, 0x27, 0x0a, 0x2b, 0x67, 0x63, 0xbe, + 0x80, 0x9d, 0x1b, 0x85, 0x42, 0x84, 0xda, 0xcc, 0x8e, 0x66, 0x7a, 0x01, 0xf2, 0x3f, 0x7e, 0x02, + 0x8d, 0x19, 0xb7, 0x1d, 0x1e, 0xea, 0xfe, 0xdb, 0xd2, 0x61, 0x87, 0x52, 0x68, 0x69, 0xa5, 0x79, + 0x94, 0x66, 0x24, 0xa9, 0x1e, 0xee, 0x93, 0xa7, 0x3b, 0x9d, 0x09, 0x19, 0xaf, 0x66, 0xe9, 0x91, + 0xf9, 0x5d, 0x1d, 0x5a, 0x16, 0x8f, 0x02, 0xdf, 0x8b, 0x38, 0x3e, 0x84, 0x36, 0x5f, 0x8e, 0xb9, + 0xea, 0x42, 0xa3, 0x04, 0x24, 0x65, 0x73, 0x9a, 0xe8, 0x09, 0x84, 0xa9, 0x31, 0x1e, 0x69, 0x06, + 0x29, 0xd3, 0x82, 0x76, 0xca, 0x53, 0xc8, 0xdd, 0x84, 0x42, 0x36, 0x4a, 0x5d, 0xa4, 0x6c, 0x4b, + 0x1c, 0x72, 0xa4, 0x39, 0xa4, 0x56, 0x19, 0xb8, 0x40, 0x22, 0x8f, 0x0a, 0x24, 0x52, 0xaf, 0x5c, + 0xfe, 0x0a, 0x16, 0xf9, 0x22, 0xcf, 0x22, 0x8d, 0x52, 0xf3, 0x29, 0xcf, 0x4a, 0x1a, 0x79, 0x90, + 0xa3, 0x91, 0x66, 0xa9, 0x7b, 0x94, 0x5b, 0x05, 0x8f, 0xdc, 0x4f, 0x79, 0xa4, 0x55, 0x62, 0x1e, + 0xed, 0x52, 0x26, 0x92, 0xbb, 0x09, 0x16, 0xdb, 0x95, 0x19, 0x2b, 0x31, 0xc9, 0xa3, 0x02, 0x93, + 0x40, 0x65, 0x1a, 0x56, 0x50, 0xc9, 0xcf, 0x8b, 0x54, 0xa2, 0xf8, 0xe0, 0x56, 0xc9, 0x77, 0x25, + 0x97, 0x7c, 0x91, 0xe7, 0x92, 0xcd, 0xca, 0x24, 0xbe, 0x9f, 0x4c, 0x8e, 0xa8, 0x0d, 0x4a, 0x30, + 0xa3, 0x46, 0xe4, 0x61, 0xe8, 0x87, 0x9a, 0x07, 0xd4, 0xc0, 0x3c, 0xa4, 0x76, 0xcd, 0xc0, 0xf5, + 0x1e, 0xe2, 0x91, 0x2d, 0x9b, 0x83, 0x96, 0xf9, 0x27, 0x23, 0xf3, 0x25, 0xfc, 0x50, 0xa3, 0x49, + 0x88, 0x29, 0x47, 0x85, 0xa5, 0xbb, 0xd0, 0x16, 0x8b, 0x28, 0x18, 0x49, 0x85, 0x02, 0xf5, 0xb6, + 0xde, 0xcb, 0xc5, 0xf3, 0x57, 0xe7, 0xe4, 0x67, 0xb5, 0xc8, 0x42, 0x46, 0x78, 0x00, 0x30, 0xb7, + 0x23, 0xa1, 0xb7, 0x5e, 0xc4, 0xf5, 0x2f, 0xed, 0x48, 0xc8, 0x7d, 0x4a, 0x9f, 0xf6, 0x3c, 0x19, + 0xe2, 0x11, 0xc1, 0xc0, 0x9b, 0xb8, 0x53, 0x8d, 0xed, 0x1d, 0xed, 0xf0, 0x44, 0x0a, 0xa5, 0xb5, + 0x36, 0x30, 0x3f, 0xc9, 0x12, 0x53, 0xa0, 0xc7, 0xb9, 0x3f, 0x4d, 0xe8, 0x71, 0xee, 0x4f, 0xcd, + 0xdf, 0x11, 0x19, 0x15, 0xd1, 0x8a, 0x3f, 0x86, 0xda, 0xd8, 0x77, 0x54, 0x56, 0xba, 0xe9, 0x1e, + 0x9e, 0xf8, 0x0e, 0xbf, 0xb8, 0x0e, 0xb8, 0x25, 0x95, 0x94, 0x01, 0xc7, 0x16, 0xb6, 0xdc, 0xe8, + 0xa6, 0x25, 0xff, 0x27, 0xe1, 0x37, 0xb2, 0xf0, 0xbf, 0x25, 0x56, 0x29, 0xa0, 0xfa, 0x43, 0x46, + 0xff, 0x75, 0x56, 0x27, 0xc5, 0xc0, 0x1f, 0x30, 0xf6, 0x6f, 0x88, 0xfe, 0xf3, 0xcd, 0xf5, 0x21, + 0x83, 0xef, 0x66, 0xc5, 0x49, 0xdb, 0xca, 0xec, 0x01, 0xde, 0xec, 0x17, 0x75, 0xca, 0x15, 0x3b, + 0x01, 0x7f, 0x02, 0x75, 0xc7, 0x9d, 0x4c, 0xa2, 0x7e, 0x6d, 0xc5, 0x41, 0xa1, 0xd4, 0xe6, 0xc7, + 0xd0, 0x4a, 0x90, 0x47, 0x68, 0x7f, 0xcd, 0xc3, 0x28, 0x61, 0xe9, 0xb6, 0x95, 0x0c, 0xcd, 0xe7, + 0xb0, 0x55, 0x00, 0x1c, 0x7e, 0x04, 0x9b, 0x12, 0x95, 0xa3, 0x02, 0xfb, 0x77, 0xa4, 0x6c, 0x28, + 0x45, 0x78, 0x0b, 0x88, 0xd0, 0x46, 0xf2, 0xb0, 0x51, 0x5b, 0x6d, 0xda, 0x41, 0x30, 0xb4, 0xa3, + 0x99, 0xf9, 0x07, 0x03, 0x20, 0xc3, 0x23, 0xde, 0x87, 0xde, 0xc2, 0x5e, 0x2a, 0x98, 0x8f, 0x22, + 0xf7, 0x1d, 0x1f, 0x5d, 0x5e, 0x0b, 0x1e, 0xe9, 0xa0, 0x3b, 0x0b, 0x7b, 0x29, 0x27, 0x7e, 0xe5, + 0xbe, 0xe3, 0x27, 0xa4, 0xc0, 0xcf, 0x00, 0x4b, 0x0e, 0x62, 0x19, 0xc9, 0x49, 0x6a, 0xd6, 0x76, + 0xde, 0xfc, 0x62, 0x19, 0xe1, 0x8f, 0xa0, 0x43, 0xc6, 0x62, 0x29, 0x2d, 0x65, 0x8a, 0x6b, 0x56, + 0x7b, 0x61, 0x2f, 0x2f, 0x96, 0x64, 0x62, 0xfe, 0x71, 0x1d, 0x1a, 0xea, 0xa0, 0xa3, 0x25, 0x4b, + 0x7a, 0x1b, 0xb9, 0x4e, 0x92, 0x01, 0x39, 0x3e, 0x73, 0x72, 0x07, 0xdd, 0x7a, 0xfe, 0xa0, 0xa3, + 0x62, 0x0a, 0x77, 0x91, 0x84, 0x95, 0xff, 0xf1, 0x00, 0x9a, 0x5e, 0xbc, 0x90, 0x6b, 0xaa, 0x29, + 0x63, 0x2f, 0x5e, 0xd0, 0x52, 0x8e, 0x61, 0x2b, 0x6b, 0x68, 0x9a, 0x44, 0x9d, 0x26, 0x5d, 0x5d, + 0x1c, 0x95, 0xde, 0xa7, 0x56, 0x27, 0xed, 0xe6, 0x33, 0x07, 0x0f, 0x81, 0x49, 0x1f, 0x45, 0xda, + 0x2a, 0x9d, 0x0d, 0x99, 0xce, 0x2e, 0xc9, 0x35, 0xab, 0xd3, 0x29, 0xfe, 0x03, 0x68, 0x13, 0x96, + 0x94, 0x49, 0x53, 0x9a, 0xb4, 0x48, 0x20, 0x95, 0x9f, 0xc2, 0x76, 0x76, 0x33, 0x50, 0x26, 0x2d, + 0x15, 0x25, 0x13, 0x4b, 0xc3, 0x7c, 0xd9, 0xda, 0xc5, 0xb2, 0x9d, 0x41, 0x53, 0x2f, 0xb1, 0xf2, + 0x16, 0x71, 0x07, 0xea, 0x81, 0x1d, 0x8a, 0x48, 0x13, 0x5b, 0xc2, 0x54, 0xe7, 0x76, 0x48, 0xb7, + 0x2f, 0x7d, 0x97, 0x50, 0x26, 0xe6, 0x23, 0xd8, 0x2a, 0xc8, 0x89, 0x8f, 0x85, 0x2f, 0xec, 0xb9, + 0x2e, 0xba, 0x1a, 0xa4, 0xd3, 0xac, 0x67, 0xd3, 0x98, 0x8f, 0xa0, 0x9d, 0xa2, 0x98, 0xca, 0x12, + 0xc4, 0x97, 0x5f, 0xf3, 0xe4, 0x42, 0xa5, 0x47, 0x14, 0x2e, 0xf0, 0xbf, 0xd5, 0x17, 0x9a, 0x9a, + 0xa5, 0x06, 0x77, 0xfe, 0x62, 0x40, 0xe7, 0xb9, 0x22, 0x70, 0xea, 0x47, 0xdc, 0x86, 0xce, 0x8b, + 0x78, 0x3e, 0xd7, 0x22, 0xb6, 0x86, 0x2d, 0xa8, 0x11, 0xef, 0x33, 0x03, 0xdb, 0x50, 0x97, 0xbc, + 0xce, 0xd6, 0x49, 0x48, 0x30, 0x65, 0x1b, 0xb8, 0x05, 0xed, 0x94, 0x28, 0x59, 0x8d, 0x86, 0xe9, + 0x81, 0xc2, 0xea, 0xb8, 0x09, 0xad, 0x84, 0x1f, 0xd9, 0x0e, 0x76, 0xa0, 0xa9, 0xe9, 0x8c, 0x21, + 0x02, 0x34, 0x54, 0xa1, 0xd8, 0x2e, 0x45, 0x96, 0x4c, 0xc4, 0x7a, 0x14, 0x20, 0xed, 0x6d, 0xb6, + 0x87, 0x5d, 0x80, 0xac, 0xab, 0xd9, 0x3e, 0x05, 0x4c, 0xfa, 0x99, 0x1d, 0xdc, 0xf9, 0x73, 0x1d, + 0x5a, 0x09, 0x93, 0x60, 0x03, 0xd6, 0x5f, 0x7e, 0xcd, 0xd6, 0x70, 0x07, 0xb6, 0xce, 0x3c, 0xc1, + 0x43, 0xcf, 0x9e, 0x9f, 0xd2, 0x09, 0xc6, 0x0c, 0x12, 0x9d, 0x7a, 0x63, 0xdf, 0x71, 0xbd, 0xa9, + 0x12, 0xad, 0x53, 0xa0, 0x13, 0xdb, 0x79, 0xe1, 0x7b, 0x63, 0xce, 0x36, 0x90, 0xc1, 0xe6, 0x37, + 0x9e, 0x1d, 0x8b, 0x99, 0x1f, 0xba, 0xef, 0xb8, 0xc3, 0x6a, 0xb8, 0x07, 0x3b, 0x67, 0x5e, 0x14, + 0x4f, 0x26, 0xee, 0xd8, 0xe5, 0x9e, 0xf8, 0x2a, 0xf6, 0x9c, 0x88, 0xd5, 0x11, 0xa1, 0xfb, 0x8d, + 0x77, 0xe5, 0xf9, 0xdf, 0x7a, 0xfa, 0xda, 0xc7, 0x1a, 0xd8, 0x87, 0xde, 0x89, 0x1d, 0xf1, 0xa7, + 0x71, 0x30, 0x77, 0xc7, 0xb6, 0xe0, 0x8f, 0x1d, 0x27, 0xe4, 0x51, 0xc4, 0x38, 0x05, 0x21, 0x4d, + 0x71, 0xee, 0x49, 0xe2, 0x50, 0x88, 0xcf, 0x79, 0xc4, 0xa6, 0x78, 0x0b, 0xf6, 0x6e, 0x68, 0xe4, + 0xcc, 0x33, 0xfc, 0x21, 0xf4, 0xcb, 0xaa, 0x67, 0x76, 0x74, 0x1e, 0xba, 0x63, 0xce, 0x5c, 0xec, + 0x01, 0x53, 0x5a, 0x09, 0xdd, 0x33, 0x2f, 0x88, 0x05, 0xfb, 0x7d, 0x32, 0xbf, 0x96, 0xbe, 0x8c, + 0x05, 0x89, 0xaf, 0x4a, 0xe2, 0x73, 0x09, 0x0f, 0x36, 0xc7, 0x03, 0xd8, 0xcd, 0x89, 0x5f, 0xd1, + 0xfe, 0x28, 0x3b, 0x8b, 0x6c, 0xbd, 0x4a, 0xe1, 0x4e, 0x3d, 0x5b, 0xc4, 0x21, 0x67, 0x1e, 0xee, + 0x03, 0x92, 0x46, 0xa7, 0x24, 0xd9, 0xb8, 0x9f, 0xcc, 0xa0, 0xe5, 0x7a, 0x86, 0xa0, 0x2c, 0x9e, + 0xc7, 0x53, 0xd7, 0x63, 0x6f, 0x70, 0x0f, 0xd8, 0x33, 0xff, 0xad, 0x96, 0x9e, 0x7a, 0xc2, 0x15, + 0xd7, 0xec, 0x6f, 0x06, 0xf6, 0x60, 0x3b, 0x13, 0x3f, 0x0b, 0xfd, 0x38, 0x60, 0x7f, 0x37, 0xf0, + 0x00, 0x30, 0x93, 0x9e, 0x87, 0x7e, 0xe0, 0x47, 0xf6, 0x9c, 0xfd, 0xc3, 0xc0, 0x7d, 0xd8, 0x79, + 0xe6, 0xbf, 0x4d, 0xab, 0xa0, 0x1c, 0xfe, 0x99, 0x38, 0xa4, 0xf2, 0xe7, 0x7c, 0x71, 0xc9, 0x43, + 0xf6, 0x2f, 0x03, 0x6f, 0x41, 0x2f, 0xaf, 0x48, 0x63, 0xfd, 0xdb, 0xd0, 0x2b, 0x4a, 0x55, 0xaf, + 0x7d, 0xc1, 0xd9, 0x7f, 0x12, 0xb1, 0xce, 0x83, 0x0e, 0xf4, 0x5f, 0x03, 0x77, 0xa1, 0x9b, 0x89, + 0xa5, 0xed, 0xff, 0x0c, 0x1c, 0xc0, 0x5e, 0x41, 0xe8, 0x7a, 0xd3, 0x73, 0xea, 0x38, 0xf6, 0x7f, + 0xe3, 0xf8, 0xbb, 0x3a, 0x6c, 0xd3, 0x11, 0xf3, 0x38, 0x50, 0x13, 0xd0, 0x25, 0xe3, 0xbe, 0xea, + 0x33, 0xac, 0x78, 0x13, 0x18, 0x54, 0xdd, 0xf2, 0xf1, 0x58, 0xb7, 0x23, 0x56, 0x3d, 0x0d, 0x0c, + 0x2a, 0x2f, 0xfb, 0x34, 0x89, 0xba, 0x88, 0xdd, 0x7c, 0x21, 0x18, 0x54, 0xdd, 0xf8, 0xf1, 0x17, + 0xb9, 0xf6, 0xc6, 0x55, 0xef, 0x04, 0x83, 0x95, 0x77, 0x7f, 0xfc, 0x32, 0x23, 0x00, 0x5c, 0xf1, + 0x5a, 0x30, 0x58, 0x75, 0xff, 0xc7, 0x87, 0x29, 0x5f, 0x60, 0xf5, 0x9b, 0xc1, 0x60, 0xc5, 0x37, + 0x00, 0xe5, 0x46, 0x5d, 0x6d, 0xaa, 0x9e, 0x02, 0x06, 0x95, 0xd7, 0x7a, 0xfc, 0x3c, 0x21, 0x24, + 0xac, 0x7c, 0x6e, 0x18, 0x54, 0x7f, 0x3c, 0x50, 0x86, 0xb2, 0x0f, 0xd2, 0x55, 0xef, 0x08, 0x83, + 0x95, 0x9f, 0x05, 0xf8, 0x38, 0xcf, 0x70, 0xb8, 0xf2, 0x35, 0x61, 0xb0, 0xfa, 0xe3, 0x80, 0x92, + 0x9c, 0x7d, 0x7d, 0x56, 0xbf, 0x29, 0x0c, 0x56, 0x7d, 0x1f, 0x5c, 0x36, 0xe4, 0x5b, 0xd5, 0x83, + 0xef, 0x03, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xa9, 0x42, 0xf7, 0xc0, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 3e9ebfe5..f18391ee 100644 --- a/types/types.proto +++ b/types/types.proto @@ -220,12 +220,13 @@ message TMSPInfo { message LastBlockInfo { uint64 block_height = 1; - bytes block_hash = 2; - bytes app_hash = 3; + bytes app_hash = 2; } message ConfigInfo { - uint64 max_block_size = 1; + uint64 max_block_size_bytes = 1; + uint64 max_block_size_txs = 2; + uint64 max_tx_size = 3; } //---------------------------------------- From 5e83e481bf4583f432e89805bd7486ef63f3d08f Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 6 Dec 2016 02:15:32 -0800 Subject: [PATCH 156/545] Fix tests; Update go-merkle API --- example/dummy/dummy.go | 2 +- example/dummy/persistent_dummy.go | 2 +- tests/test_app/app.go | 1 + tests/test_cli/ex1.tmsp.out | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 80c1ad9d..daed7a93 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -14,7 +14,7 @@ type DummyApplication struct { } func NewDummyApplication() *DummyApplication { - state := merkle.NewIAVLTree(0, ".", nil) + state := merkle.NewIAVLTree(0, nil) return &DummyApplication{state: state} } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index ed2326f1..1fe40fc2 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -35,7 +35,7 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { db := dbm.NewDB("dummy", "leveldb", dbDir) lastBlock := LoadLastBlock(db) - stateTree := merkle.NewIAVLTree(0, ".", db) + stateTree := merkle.NewIAVLTree(0, db) stateTree.Load(lastBlock.AppHash) log.Notice("Loaded state", "block", lastBlock.BlockHeight, "root", stateTree.Hash()) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 2a1bf15a..44e36eeb 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -17,6 +17,7 @@ func StartApp(tmspApp string) *process.Process { // Start the app //outBuf := NewBufferCloser(nil) proc, err := process.StartProcess("tmsp_app", + "", "bash", []string{"-c", tmspApp}, nil, diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.tmsp.out index 836df8ae..89bd61c2 100644 --- a/tests/test_cli/ex1.tmsp.out +++ b/tests/test_cli/ex1.tmsp.out @@ -17,7 +17,7 @@ > query abc -> code: OK --> data: {{"index":0,"value":"abc","exists":true}} +-> data: {Index=0 value=abc exists=true} > append_tx def=xyz -> code: OK @@ -27,5 +27,5 @@ > query def -> code: OK --> data: {{"index":1,"value":"xyz","exists":true}} +-> data: {Index=1 value=xyz exists=true} From b3e5d0afa1dea4d4131cd4faba6491abe271f7da Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 6 Dec 2016 03:22:53 -0800 Subject: [PATCH 157/545] Update glide.* --- glide.lock | 16 ++++++++-------- glide.yaml | 5 +++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/glide.lock b/glide.lock index e82a60d4..15fbcd45 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 603c43870dfc63a3113a3d13ae799038206bd77889e2e9596a860d3644b8fb67 -updated: 2016-11-22T20:57:55.984772241-05:00 +hash: 0644029071e51c40b7b4f9b3b3c14fce59e6dadd42897ea20d7eaf049104969e +updated: 2016-12-06T03:21:00.488564175-08:00 imports: - name: github.com/btcsuite/btcd version: afec1bd1245a4a19e6dfe1306974b733e7cbb9b8 @@ -15,6 +15,8 @@ imports: - proto - name: github.com/golang/snappy version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 +- name: github.com/jmhodges/levigo + version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable version: d228849504861217f796da67fae4f6e347643f15 - name: github.com/mattn/go-isatty @@ -39,20 +41,18 @@ imports: subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/go-autofile - version: 63186e34b33d78ae47fb0d25e5717b307fdf3603 - name: github.com/tendermint/go-common - version: 6b4160f2a57487f277c42bf06fd280195dfdb278 + version: 70e694ee76f09058ea38c9ba81b4aa621bd54df1 - name: github.com/tendermint/go-crypto version: 4b11d62bdb324027ea01554e5767b71174680ba0 - name: github.com/tendermint/go-db - version: 31fdd21c7eaeed53e0ea7ca597fb1e960e2988a5 + version: 5e2a1d3e300743380a329499804dde6bfb0af7d5 - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: bfc4afe28c7a50045d4d1eb043e67460f8a51a4f + version: 8bbe6968f21c1c8a3dcdd2f1ca2a87009a9ec912 - name: github.com/tendermint/go-process - version: ba01cfbb58d446673beff17e72883cb49c835fb9 + version: 7f507d69fa4c13b34e7a17ff5c87d1eaaa759145 - name: github.com/tendermint/go-wire version: 287d8caeae91d21686340f5f87170560531681e6 - name: github.com/tendermint/log15 diff --git a/glide.yaml b/glide.yaml index bc1ad142..440d47cc 100644 --- a/glide.yaml +++ b/glide.yaml @@ -7,9 +7,14 @@ import: version: develop - package: github.com/tendermint/go-crypto - package: github.com/tendermint/go-logger +- package: github.com/tendermint/go-db + version: develop - package: github.com/tendermint/go-merkle + version: develop - package: github.com/tendermint/go-process + version: develop - package: github.com/tendermint/go-wire + version: develop - package: github.com/urfave/cli - package: golang.org/x/net subpackages: From c5f008d60fe9213482debdac4685e973c05b71fc Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 6 Dec 2016 03:57:09 -0800 Subject: [PATCH 158/545] Fix TMSP tutorial outputs --- cmd/tmsp-cli/tmsp-cli.go | 4 ++-- example/counter/counter.go | 2 +- example/dummy/dummy.go | 2 +- tests/test_cli/ex1.tmsp.out | 15 ++++++++------- tests/test_cli/ex2.tmsp.out | 4 ++-- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index fe6dbd45..219d89df 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -234,7 +234,7 @@ func cmdCheckTx(c *cli.Context) error { // Get application Merkle root hash func cmdCommit(c *cli.Context) error { res := client.CommitSync() - printResponse(c, res, Fmt("%X", res.Data), false) + printResponse(c, res, Fmt("0x%X", res.Data), false) return nil } @@ -264,7 +264,7 @@ func printResponse(c *cli.Context, res types.Result, s string, printCode bool) { fmt.Printf("-> error: %s\n", res.Error) }*/ if s != "" { - fmt.Printf("-> data: {%s}\n", s) + fmt.Printf("-> data: %s\n", s) } if res.Log != "" { fmt.Printf("-> log: %s\n", res.Log) diff --git a/example/counter/counter.go b/example/counter/counter.go index ef57d840..3252f943 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -18,7 +18,7 @@ func NewCounterApplication(serial bool) *CounterApplication { } func (app *CounterApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - return Fmt("hashes:%v, txs:%v", app.hashCount, app.txCount), nil, nil, nil + return Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount), nil, nil, nil } func (app *CounterApplication) SetOption(key string, value string) (log string) { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index daed7a93..438de6a4 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -19,7 +19,7 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - return Fmt("size:%v", app.state.Size()), nil, nil, nil + return Fmt("{\"size\":%v}", app.state.Size()), nil, nil, nil } func (app *DummyApplication) SetOption(key string, value string) (log string) { diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.tmsp.out index 89bd61c2..eabeabd1 100644 --- a/tests/test_cli/ex1.tmsp.out +++ b/tests/test_cli/ex1.tmsp.out @@ -1,31 +1,32 @@ > echo hello --> data: {hello} +-> data: hello > info --> data: {size:0} +-> data: {"size":0} > commit +-> data: 0x > append_tx abc -> code: OK > info --> data: {size:1} +-> data: {"size":1} > commit --> data: {750502FC7E84BBD788ED589624F06CFA871845D1} +-> data: 0x750502FC7E84BBD788ED589624F06CFA871845D1 > query abc -> code: OK --> data: {Index=0 value=abc exists=true} +-> data: {"index":0,"value":"abc","exists":true} > append_tx def=xyz -> code: OK > commit --> data: {76393B8A182E450286B0694C629ECB51B286EFD5} +-> data: 0x76393B8A182E450286B0694C629ECB51B286EFD5 > query def -> code: OK --> data: {Index=1 value=xyz exists=true} +-> data: {"index":1,"value":"xyz","exists":true} diff --git a/tests/test_cli/ex2.tmsp.out b/tests/test_cli/ex2.tmsp.out index 3aa7744b..84e4ad4f 100644 --- a/tests/test_cli/ex2.tmsp.out +++ b/tests/test_cli/ex2.tmsp.out @@ -1,5 +1,5 @@ > set_option serial on --> data: {serial=on} +-> data: serial=on > check_tx 0x00 -> code: OK @@ -22,5 +22,5 @@ -> log: Invalid nonce. Expected 2, got 4 > info --> data: {hashes:0, txs:2} +-> data: {"hashes":0,"txs":2} From 5f6ad831b05ae4b4f1bf9941f46c0a92719a0183 Mon Sep 17 00:00:00 2001 From: jac Date: Thu, 15 Dec 2016 14:47:31 +0100 Subject: [PATCH 159/545] link to TMSP Blog post --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6f1e53a..b4af06f0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Blockchains are a system for creating shared multi-master application state. **TMSP** is a socket protocol enabling a blockchain consensus engine, running in one process, to manage a blockchain application state, running in another. -For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/). +For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/blog/tmsp-the-tendermint-socket-protocol/). Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen From b0a17b18042cdc82a6a123fe44b68041f23f2282 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 2 Jan 2017 12:12:23 -0800 Subject: [PATCH 160/545] Fix blog link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d034a6b1..e50e3292 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Blockchains are a system for creating shared multi-master application state. **TMSP** is a socket protocol enabling a blockchain consensus engine, running in one process, to manage a blockchain application state, running in another. -For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/posts/tendermint-socket-protocol/). +For more information on TMSP, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/tmsp-the-tendermint-socket-protocol). Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen From 75ea378a6a5d3abd73e31c8e5a7f4e1c609c5474 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 2 Jan 2017 18:10:12 -0800 Subject: [PATCH 161/545] Encode dummy query values as hex strings --- example/dummy/dummy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 438de6a4..34ba63ec 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,6 +1,7 @@ package dummy import ( + "encoding/hex" "strings" . "github.com/tendermint/go-common" @@ -48,8 +49,7 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(query []byte) types.Result { index, value, exists := app.state.Get(query) - - queryResult := QueryResult{index, string(value), exists} + queryResult := QueryResult{index, hex.EncodeToString(value), exists} return types.NewResultOK(wire.JSONBytes(queryResult), "") } From ab211d2dbeab48bb3f5c064199b51cd64af28d24 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 2 Jan 2017 18:20:30 -0800 Subject: [PATCH 162/545] Include 'value' and 'valueHex' fields in dummy query response --- example/dummy/dummy.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 34ba63ec..086aee18 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -49,12 +49,13 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(query []byte) types.Result { index, value, exists := app.state.Get(query) - queryResult := QueryResult{index, hex.EncodeToString(value), exists} + 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"` - Exists bool `json:"exists"` + Index int `json:"index"` + Value string `json:"value"` + ValueHex string `json:"valueHex"` + Exists bool `json:"exists"` } From 115e6939d01909567f7f19b956b17cf9d313c246 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 2 Jan 2017 18:28:47 -0800 Subject: [PATCH 163/545] Require quotes or 0x for string args --- cmd/tmsp-cli/tmsp-cli.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 219d89df..5b74f8f9 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -285,5 +285,13 @@ func stringOrHexToBytes(s string) []byte { } return b } + + if !strings.HasPrefix(s, "\"") || !strings.HasSuffix(s, "\"") { + fmt.Printf("Invalid string arg: \"%s\". Must be quoted or a \"0x\"-prefixed hex string\n", s) + return []byte{} + } + + // TODO: return errors + return []byte(s) } From e748127b7f4a8ee489dec5228bbd083533af89b1 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 2 Jan 2017 18:49:10 -0800 Subject: [PATCH 164/545] Don't include quotes in quoted string args --- cmd/tmsp-cli/tmsp-cli.go | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 5b74f8f9..cfc56d1e 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -213,7 +213,11 @@ func cmdAppendTx(c *cli.Context) error { if len(args) != 1 { return errors.New("Command append_tx takes 1 argument") } - txBytes := stringOrHexToBytes(c.Args()[0]) + txBytes, err := stringOrHexToBytes(c.Args()[0]) + if err != nil { + fmt.Println(err.Error()) + return nil + } res := client.AppendTxSync(txBytes) printResponse(c, res, string(res.Data), true) return nil @@ -225,7 +229,11 @@ func cmdCheckTx(c *cli.Context) error { if len(args) != 1 { return errors.New("Command check_tx takes 1 argument") } - txBytes := stringOrHexToBytes(c.Args()[0]) + txBytes, err := stringOrHexToBytes(c.Args()[0]) + if err != nil { + fmt.Println(err.Error()) + return nil + } res := client.CheckTxSync(txBytes) printResponse(c, res, string(res.Data), true) return nil @@ -244,7 +252,11 @@ func cmdQuery(c *cli.Context) error { if len(args) != 1 { return errors.New("Command query takes 1 argument") } - queryBytes := stringOrHexToBytes(c.Args()[0]) + queryBytes, err := stringOrHexToBytes(c.Args()[0]) + if err != nil { + fmt.Println(err.Error()) + return nil + } res := client.QuerySync(queryBytes) printResponse(c, res, string(res.Data), true) return nil @@ -277,21 +289,22 @@ func printResponse(c *cli.Context, res types.Result, s string, printCode bool) { } // NOTE: s is interpreted as a string unless prefixed with 0x -func stringOrHexToBytes(s string) []byte { - if len(s) > 2 && s[:2] == "0x" { +func stringOrHexToBytes(s string) ([]byte, error) { + fmt.Printf("string: %s %x\n", s, []byte(s)) + + if len(s) > 2 && strings.ToLower(s[:2]) == "0x" { b, err := hex.DecodeString(s[2:]) if err != nil { - fmt.Println("Error decoding hex argument:", err.Error()) + err = fmt.Errorf("Error decoding hex argument: %s", err.Error()) + return nil, err } - return b + return b, nil } if !strings.HasPrefix(s, "\"") || !strings.HasSuffix(s, "\"") { - fmt.Printf("Invalid string arg: \"%s\". Must be quoted or a \"0x\"-prefixed hex string\n", s) - return []byte{} + err := fmt.Errorf("Invalid string arg: \"%s\". Must be quoted or a \"0x\"-prefixed hex string", s) + return nil, err } - // TODO: return errors - - return []byte(s) + return []byte(s[1 : len(s)-1]), nil } From 86a6deba3feef1c5c5df09ddc72979318450b2a4 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 2 Jan 2017 18:49:54 -0800 Subject: [PATCH 165/545] Remove debug printing --- cmd/tmsp-cli/tmsp-cli.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index cfc56d1e..2fab906a 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -290,8 +290,6 @@ func printResponse(c *cli.Context, res types.Result, s string, printCode bool) { // NOTE: s is interpreted as a string unless prefixed with 0x func stringOrHexToBytes(s string) ([]byte, error) { - fmt.Printf("string: %s %x\n", s, []byte(s)) - if len(s) > 2 && strings.ToLower(s[:2]) == "0x" { b, err := hex.DecodeString(s[2:]) if err != nil { From cd6fa3018c537f8145c490eab918b394443dd54a Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 3 Jan 2017 10:53:14 -0800 Subject: [PATCH 166/545] Return errors from cmd functions instead of printing --- cmd/tmsp-cli/tmsp-cli.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 2fab906a..50e954d9 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -215,8 +215,7 @@ func cmdAppendTx(c *cli.Context) error { } txBytes, err := stringOrHexToBytes(c.Args()[0]) if err != nil { - fmt.Println(err.Error()) - return nil + return err } res := client.AppendTxSync(txBytes) printResponse(c, res, string(res.Data), true) @@ -231,8 +230,7 @@ func cmdCheckTx(c *cli.Context) error { } txBytes, err := stringOrHexToBytes(c.Args()[0]) if err != nil { - fmt.Println(err.Error()) - return nil + return err } res := client.CheckTxSync(txBytes) printResponse(c, res, string(res.Data), true) @@ -254,8 +252,7 @@ func cmdQuery(c *cli.Context) error { } queryBytes, err := stringOrHexToBytes(c.Args()[0]) if err != nil { - fmt.Println(err.Error()) - return nil + return err } res := client.QuerySync(queryBytes) printResponse(c, res, string(res.Data), true) From 4bb65366f4cbc3442b82eeb99efe1f9f1242dc26 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 3 Jan 2017 19:26:20 -0800 Subject: [PATCH 167/545] Update CLI test string args --- tests/test_cli/ex1.tmsp | 8 ++++---- tests/test_cli/ex1.tmsp.out | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/test_cli/ex1.tmsp b/tests/test_cli/ex1.tmsp index de61c8b2..13251267 100644 --- a/tests/test_cli/ex1.tmsp +++ b/tests/test_cli/ex1.tmsp @@ -1,10 +1,10 @@ echo hello info commit -append_tx abc +append_tx "abc" info commit -query abc -append_tx def=xyz +query "abc" +append_tx "def=xyz" commit -query def +query "def" diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.tmsp.out index eabeabd1..51cee99f 100644 --- a/tests/test_cli/ex1.tmsp.out +++ b/tests/test_cli/ex1.tmsp.out @@ -7,7 +7,7 @@ > commit -> data: 0x -> append_tx abc +> append_tx "abc" -> code: OK > info @@ -16,17 +16,17 @@ > commit -> data: 0x750502FC7E84BBD788ED589624F06CFA871845D1 -> query abc +> query "abc" -> code: OK --> data: {"index":0,"value":"abc","exists":true} +-> data: {"index":0,"value":"abc","valueHex":"616263","exists":true} -> append_tx def=xyz +> append_tx "def=xyz" -> code: OK > commit -> data: 0x76393B8A182E450286B0694C629ECB51B286EFD5 -> query def +> query "def" -> code: OK --> data: {"index":1,"value":"xyz","exists":true} +-> data: {"index":1,"value":"xyz","valueHex":"78797a","exists":true} From c31df4081cd660d4e7485bb81594b8c3ab26b636 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 22 Dec 2016 18:24:45 -0500 Subject: [PATCH 168/545] added counter query support --- example/counter/counter.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/example/counter/counter.go b/example/counter/counter.go index 3252f943..58c37c85 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -72,5 +72,14 @@ func (app *CounterApplication) Commit() types.Result { } func (app *CounterApplication) Query(query []byte) types.Result { - return types.NewResultOK(nil, Fmt("Query is not supported")) + queryStr := string(query) + + switch queryStr { + case "hash": + return types.NewResultOK(nil, Fmt("%v", app.hashCount)) + case "tx": + return types.NewResultOK(nil, Fmt("%v", app.txCount)) + } + + return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) } From 81b2697ccefc345a7dca8f3dd2ec2e9f83f15930 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 22 Dec 2016 19:00:22 -0500 Subject: [PATCH 169/545] fix console exit, closes #35 --- cmd/tmsp-cli/tmsp-cli.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 50e954d9..cd9ae62e 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -19,6 +19,10 @@ import ( var client tmspcli.Client func main() { + + //workaround for the cli library (https://github.com/urfave/cli/issues/565) + cli.OsExiter = func(_ int) {} + app := cli.NewApp() app.Name = "tmsp-cli" app.Usage = "tmsp-cli [command] [args...]" @@ -171,10 +175,7 @@ func cmdConsole(app *cli.App, c *cli.Context) error { args := []string{"tmsp-cli"} args = append(args, strings.Split(string(line), " ")...) - if err := app.Run(args); err != nil { - // if the command doesn't succeed, inform the user without exiting - fmt.Println("Error:", err.Error()) - } + app.Run(args) //cli already prints error within its func call } } From e6b9a2b6aaa32d23c404400beb59277298ea66ca Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 12 Jan 2017 01:03:51 -0500 Subject: [PATCH 170/545] response struct and persistent args --- cmd/tmsp-cli/tmsp-cli.go | 107 ++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index cd9ae62e..7e7bd21e 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -15,6 +15,30 @@ import ( "github.com/urfave/cli" ) +//structure for data passed to print response +// variables must be exposed for JSON to read +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: "", + } + + if printCode { + rsp.Code = res.Code.String() + } + + return rsp +} + // client is a global variable so it can be reused by the console var client tmspcli.Client @@ -135,6 +159,20 @@ func badCmd(c *cli.Context, cmd string) { cli.DefaultAppComplete(c) } +//Generates new Args array based off of previous call args to maintain flag persistence +func persistentArgs(line []byte) []string { + + //generate the arguments to run from orginal os.Args + // to maintain flag arguments + args := os.Args + args = args[:len(args)-1] // remove the previous command argument + + if len(line) > 0 { //prevents introduction of extra space leading to argument parse errors + args = append(args, strings.Split(string(line), " ")...) + } + return args +} + //-------------------------------------------------------------------------------- func cmdBatch(app *cli.App, c *cli.Context) error { @@ -150,12 +188,9 @@ func cmdBatch(app *cli.App, c *cli.Context) error { } else if err != nil { return err } - args := []string{"tmsp-cli"} - if c.GlobalBool("verbose") { - args = append(args, "--verbose") - } - args = append(args, strings.Split(string(line), " ")...) - app.Run(args) + + args := persistentArgs(line) + app.Run(args) //cli prints error within its func call } return nil } @@ -163,6 +198,7 @@ func cmdBatch(app *cli.App, c *cli.Context) error { func cmdConsole(app *cli.App, c *cli.Context) error { // don't hard exit on mistyped commands (eg. check vs check_tx) app.CommandNotFound = badCmd + for { fmt.Printf("\n> ") bufReader := bufio.NewReader(os.Stdin) @@ -173,9 +209,8 @@ func cmdConsole(app *cli.App, c *cli.Context) error { return err } - args := []string{"tmsp-cli"} - args = append(args, strings.Split(string(line), " ")...) - app.Run(args) //cli already prints error within its func call + args := persistentArgs(line) + app.Run(args) //cli prints error within its func call } } @@ -186,14 +221,16 @@ func cmdEcho(c *cli.Context) error { return errors.New("Command echo takes 1 argument") } res := client.EchoSync(args[0]) - printResponse(c, res, string(res.Data), false) + rsp := newResponse(res, string(res.Data), false) + printResponse(c, rsp) return nil } // Get some info from the application func cmdInfo(c *cli.Context) error { res, _, _, _ := client.InfoSync() - printResponse(c, res, string(res.Data), false) + rsp := newResponse(res, string(res.Data), false) + printResponse(c, rsp) return nil } @@ -204,7 +241,8 @@ func cmdSetOption(c *cli.Context) error { return errors.New("Command set_option takes 2 arguments (key, value)") } res := client.SetOptionSync(args[0], args[1]) - printResponse(c, res, Fmt("%s=%s", args[0], args[1]), false) + rsp := newResponse(res, Fmt("%s=%s", args[0], args[1]), false) + printResponse(c, rsp) return nil } @@ -219,7 +257,8 @@ func cmdAppendTx(c *cli.Context) error { return err } res := client.AppendTxSync(txBytes) - printResponse(c, res, string(res.Data), true) + rsp := newResponse(res, string(res.Data), true) + printResponse(c, rsp) return nil } @@ -234,14 +273,16 @@ func cmdCheckTx(c *cli.Context) error { return err } res := client.CheckTxSync(txBytes) - printResponse(c, res, string(res.Data), true) + rsp := newResponse(res, string(res.Data), true) + printResponse(c, rsp) return nil } // Get application Merkle root hash func cmdCommit(c *cli.Context) error { res := client.CommitSync() - printResponse(c, res, Fmt("0x%X", res.Data), false) + rsp := newResponse(res, Fmt("0x%X", res.Data), false) + printResponse(c, rsp) return nil } @@ -256,31 +297,37 @@ func cmdQuery(c *cli.Context) error { return err } res := client.QuerySync(queryBytes) - printResponse(c, res, string(res.Data), true) + rsp := newResponse(res, string(res.Data), true) + printResponse(c, rsp) return nil } //-------------------------------------------------------------------------------- -func printResponse(c *cli.Context, res types.Result, s string, printCode bool) { - if c.GlobalBool("verbose") { +func printResponse(c *cli.Context, rsp *response) { + + verbose := c.GlobalBool("verbose") + + if verbose { fmt.Println(">", c.Command.Name, strings.Join(c.Args(), " ")) } - if printCode { - fmt.Printf("-> code: %s\n", res.Code.String()) - } - /*if res.Error != "" { - fmt.Printf("-> error: %s\n", res.Error) - }*/ - if s != "" { - fmt.Printf("-> data: %s\n", s) - } - if res.Log != "" { - fmt.Printf("-> log: %s\n", res.Log) + if rsp.PrintCode { + fmt.Printf("-> code: %s\n", rsp.Code) } - if c.GlobalBool("verbose") { + //if pr.res.Error != "" { + // fmt.Printf("-> error: %s\n", pr.res.Error) + //} + + if rsp.Data != "" { + fmt.Printf("-> data: %s\n", rsp.Data) + } + if rsp.Res.Log != "" { + fmt.Printf("-> log: %s\n", rsp.Res.Log) + } + + if verbose { fmt.Println("") } From 831cb4adcd3daa88451f3ea707f432fa269d5ed8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 12 Jan 2017 01:08:31 -0500 Subject: [PATCH 171/545] update glide --- glide.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index 15fbcd45..5a8a6c77 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 0644029071e51c40b7b4f9b3b3c14fce59e6dadd42897ea20d7eaf049104969e -updated: 2016-12-06T03:21:00.488564175-08:00 +updated: 2017-01-12T01:05:04.505700434-05:00 imports: - name: github.com/btcsuite/btcd version: afec1bd1245a4a19e6dfe1306974b733e7cbb9b8 @@ -46,15 +46,15 @@ imports: - name: github.com/tendermint/go-crypto version: 4b11d62bdb324027ea01554e5767b71174680ba0 - name: github.com/tendermint/go-db - version: 5e2a1d3e300743380a329499804dde6bfb0af7d5 + version: 2645626c33d8702739e52a61a55d705c2dfe4530 - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 8bbe6968f21c1c8a3dcdd2f1ca2a87009a9ec912 + version: c7a7ae88ca72bf030a7fb7d0d52ce8d1e62b4e16 - name: github.com/tendermint/go-process version: 7f507d69fa4c13b34e7a17ff5c87d1eaaa759145 - name: github.com/tendermint/go-wire - version: 287d8caeae91d21686340f5f87170560531681e6 + version: 37d5dd6530857a1abc1db50a48ba22c3459826a1 - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: From 0d82d26408e03eee7ea287aad3c169c0eeb27a35 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 26 Dec 2016 16:49:29 -0800 Subject: [PATCH 172/545] Frist commit on types.proto --- types/application.go | 2 +- types/types.proto | 27 ++++----------------------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/types/application.go b/types/application.go index 0137f1e1..b001bc3c 100644 --- a/types/application.go +++ b/types/application.go @@ -8,7 +8,7 @@ import ( type Application interface { // Return application info - Info() (string, *TMSPInfo, *LastBlockInfo, *ConfigInfo) + Info() ResponseInfo // Set application option (e.g. mode=mempool, mode=consensus) SetOption(key string, value string) (log string) diff --git a/types/types.proto b/types/types.proto index f18391ee..8d0860c9 100644 --- a/types/types.proto +++ b/types/types.proto @@ -165,11 +165,10 @@ message ResponseFlush{ } message ResponseInfo { - string info = 1; // backwards compatible - - TMSPInfo tmsp_info = 2; - LastBlockInfo last_block = 3; - ConfigInfo config = 4; + string info = 1; + string version = 2; + uint64 last_block_height = 3; + bytes last_block_app_hash = 4; } message ResponseSetOption{ @@ -211,24 +210,6 @@ message ResponseEndBlock{ repeated Validator diffs = 4; } -//---------------------------------------- -// Info types - -message TMSPInfo { - string Version = 1; -} - -message LastBlockInfo { - uint64 block_height = 1; - bytes app_hash = 2; -} - -message ConfigInfo { - uint64 max_block_size_bytes = 1; - uint64 max_block_size_txs = 2; - uint64 max_tx_size = 3; -} - //---------------------------------------- // Blockchain Types From 8b76f3dd0074b869166f7240f515ead90a8ef2bc Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 26 Dec 2016 17:44:36 -0800 Subject: [PATCH 173/545] Make fields in ResponseInfo be flat --- client/client.go | 2 +- client/grpc_client.go | 13 +- client/local_client.go | 10 +- client/socket_client.go | 11 +- cmd/tmsp-cli/tmsp-cli.go | 7 +- example/chain_aware/chain_aware_app.go | 4 +- example/counter/counter.go | 4 +- example/dummy/dummy.go | 4 +- example/dummy/dummy_test.go | 12 +- example/dummy/persistent_dummy.go | 27 +- example/nil/nil_app.go | 4 +- types/application.go | 4 +- types/messages.go | 5 +- types/types.pb.go | 331 +++++++++---------------- types/types.proto | 2 +- 15 files changed, 186 insertions(+), 254 deletions(-) diff --git a/client/client.go b/client/client.go index d1954e3f..c39357ba 100644 --- a/client/client.go +++ b/client/client.go @@ -25,7 +25,7 @@ type Client interface { FlushSync() error EchoSync(msg string) (res types.Result) - InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) + InfoSync() (resInfo types.ResponseInfo, err error) SetOptionSync(key string, value string) (res types.Result) AppendTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) diff --git a/client/grpc_client.go b/client/grpc_client.go index 1e016973..e72f31fb 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -262,13 +262,16 @@ func (cli *grpcClient) FlushSync() error { return nil } -func (cli *grpcClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { +func (cli *grpcClient) InfoSync() (resInfo types.ResponseInfo, err error) { reqres := cli.InfoAsync() - if res := cli.checkErrGetResult(); res.IsErr() { - return res, nil, nil, nil + if err = cli.Error(); err != nil { + return resInfo, err + } + if resInfo_ := reqres.Response.GetInfo(); resInfo_ != nil { + return *resInfo_, nil + } else { + return resInfo, nil } - resp := reqres.Response.GetInfo() - return types.NewResultOK([]byte(resp.Info), LOG), resp.TmspInfo, resp.LastBlock, resp.Config } func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { diff --git a/client/local_client.go b/client/local_client.go index e50763a8..0c363d0c 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -51,11 +51,11 @@ func (app *localClient) EchoAsync(msg string) *ReqRes { func (app *localClient) InfoAsync() *ReqRes { app.mtx.Lock() - info, tmspInfo, blockInfo, configInfo := app.Application.Info() + resInfo := app.Application.Info() app.mtx.Unlock() return app.callback( types.ToRequestInfo(), - types.ToResponseInfo(info, tmspInfo, blockInfo, configInfo), + types.ToResponseInfo(resInfo), ) } @@ -157,11 +157,11 @@ func (app *localClient) EchoSync(msg string) (res types.Result) { return types.OK.SetData([]byte(msg)) } -func (app *localClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { +func (app *localClient) InfoSync() (resInfo types.ResponseInfo, err error) { app.mtx.Lock() defer app.mtx.Unlock() - info, tmspInfo, blockInfo, configInfo := app.Application.Info() - return types.OK.SetData([]byte(info)), tmspInfo, blockInfo, configInfo + resInfo = app.Application.Info() + return resInfo, nil } func (app *localClient) SetOptionSync(key string, value string) (res types.Result) { diff --git a/client/socket_client.go b/client/socket_client.go index 01a33036..8c5c8428 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -292,14 +292,17 @@ func (cli *socketClient) FlushSync() error { return cli.Error() } -func (cli *socketClient) InfoSync() (types.Result, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { +func (cli *socketClient) InfoSync() (resInfo types.ResponseInfo, err error) { reqres := cli.queueRequest(types.ToRequestInfo()) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()), nil, nil, nil + return resInfo, err + } + if resInfo_ := reqres.Response.GetInfo(); resInfo_ != nil { + return *resInfo_, nil + } else { + return resInfo, nil } - resp := reqres.Response.GetInfo() - return types.Result{Code: OK, Data: []byte(resp.Info), Log: LOG}, resp.TmspInfo, resp.LastBlock, resp.Config } func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 7e7bd21e..2bf5b862 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -228,8 +228,11 @@ func cmdEcho(c *cli.Context) error { // Get some info from the application func cmdInfo(c *cli.Context) error { - res, _, _, _ := client.InfoSync() - rsp := newResponse(res, string(res.Data), false) + resInfo, err := client.InfoSync() + if err != nil { + return err + } + rsp := newResponse(types.Result{}, string(resInfo.Data), false) printResponse(c, rsp) return nil } diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index aec7fe1b..15d8f876 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -36,8 +36,8 @@ func NewChainAwareApplication() *ChainAwareApplication { return &ChainAwareApplication{} } -func (app *ChainAwareApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - return "nil", nil, nil, nil +func (app *ChainAwareApplication) Info() types.ResponseInfo { + return types.ResponseInfo{} } func (app *ChainAwareApplication) SetOption(key string, value string) (log string) { diff --git a/example/counter/counter.go b/example/counter/counter.go index 58c37c85..221ddf04 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -17,8 +17,8 @@ func NewCounterApplication(serial bool) *CounterApplication { return &CounterApplication{serial: serial} } -func (app *CounterApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - return Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount), nil, nil, nil +func (app *CounterApplication) Info() types.ResponseInfo { + return types.ResponseInfo{Data: Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } func (app *CounterApplication) SetOption(key string, value string) (log string) { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 086aee18..ca7bc525 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -19,8 +19,8 @@ func NewDummyApplication() *DummyApplication { return &DummyApplication{state: state} } -func (app *DummyApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - return Fmt("{\"size\":%v}", app.state.Size()), nil, nil, nil +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) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index e284f125..eea7f4a8 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -72,9 +72,9 @@ func TestPersistentDummyInfo(t *testing.T) { dummy := NewPersistentDummyApplication(dir) height := uint64(0) - _, _, lastBlockInfo, _ := dummy.Info() - if lastBlockInfo.BlockHeight != height { - t.Fatalf("expected height of %d, got %d", height, lastBlockInfo.BlockHeight) + resInfo := dummy.Info() + if resInfo.LastBlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) } // make and apply block @@ -87,9 +87,9 @@ func TestPersistentDummyInfo(t *testing.T) { dummy.EndBlock(height) dummy.Commit() - _, _, lastBlockInfo, _ = dummy.Info() - if lastBlockInfo.BlockHeight != height { - t.Fatalf("expected height of %d, got %d", height, lastBlockInfo.BlockHeight) + resInfo = dummy.Info() + if resInfo.LastBlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) } } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 1fe40fc2..fc2b38cd 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -38,7 +38,7 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { stateTree := merkle.NewIAVLTree(0, db) stateTree.Load(lastBlock.AppHash) - log.Notice("Loaded state", "block", lastBlock.BlockHeight, "root", stateTree.Hash()) + log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) return &PersistentDummyApplication{ app: &DummyApplication{state: stateTree}, @@ -46,10 +46,12 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { } } -func (app *PersistentDummyApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - s, _, _, _ := app.app.Info() +func (app *PersistentDummyApplication) Info() (resInfo types.ResponseInfo) { + resInfo = app.app.Info() lastBlock := LoadLastBlock(app.db) - return s, nil, &lastBlock, nil + resInfo.LastBlockHeight = lastBlock.Height + resInfo.LastBlockAppHash = lastBlock.AppHash + return resInfo } func (app *PersistentDummyApplication) SetOption(key string, value string) (log string) { @@ -79,9 +81,9 @@ func (app *PersistentDummyApplication) Commit() types.Result { appHash := app.app.state.Save() log.Info("Saved state", "root", appHash) - lastBlock := types.LastBlockInfo{ - BlockHeight: app.blockHeader.Height, - AppHash: appHash, // this hash will be in the next block header + lastBlock := LastBlockInfo{ + Height: app.blockHeader.Height, + AppHash: appHash, // this hash will be in the next block header } SaveLastBlock(app.db, lastBlock) return types.NewResultOK(appHash, "") @@ -120,8 +122,13 @@ func (app *PersistentDummyApplication) EndBlock(height uint64) (diffs []*types.V var lastBlockKey = []byte("lastblock") +type LastBlockInfo struct { + Height uint64 + AppHash []byte +} + // Get the last block from the db -func LoadLastBlock(db dbm.DB) (lastBlock types.LastBlockInfo) { +func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { buf := db.Get(lastBlockKey) if len(buf) != 0 { r, n, err := bytes.NewReader(buf), new(int), new(error) @@ -136,8 +143,8 @@ func LoadLastBlock(db dbm.DB) (lastBlock types.LastBlockInfo) { return lastBlock } -func SaveLastBlock(db dbm.DB, lastBlock types.LastBlockInfo) { - log.Notice("Saving block", "height", lastBlock.BlockHeight, "root", lastBlock.AppHash) +func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { + log.Notice("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) buf, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(lastBlock, buf, n, err) if *err != nil { diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 05b5c788..7cc01c05 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -11,8 +11,8 @@ func NewNilApplication() *NilApplication { return &NilApplication{} } -func (app *NilApplication) Info() (string, *types.TMSPInfo, *types.LastBlockInfo, *types.ConfigInfo) { - return "nil", nil, nil, nil +func (app *NilApplication) Info() (resInfo types.ResponseInfo) { + return } func (app *NilApplication) SetOption(key string, value string) (log string) { diff --git a/types/application.go b/types/application.go index b001bc3c..d124afd5 100644 --- a/types/application.go +++ b/types/application.go @@ -59,8 +59,8 @@ func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*Resp } func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { - info, tmspInfo, blockInfo, configInfo := app.app.Info() - return &ResponseInfo{info, tmspInfo, blockInfo, configInfo}, nil + resInfo := app.app.Info() + return &resInfo, nil } func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { diff --git a/types/messages.go b/types/messages.go index 16e4fbd2..afd4548e 100644 --- a/types/messages.go +++ b/types/messages.go @@ -93,9 +93,10 @@ func ToResponseFlush() *Response { } } -func ToResponseInfo(info string, tmspInfo *TMSPInfo, blockInfo *LastBlockInfo, configInfo *ConfigInfo) *Response { +func ToResponseInfo(resInfo ResponseInfo) *Response { + resInfoCopy := resInfo return &Response{ - Value: &Response_Info{&ResponseInfo{info, tmspInfo, blockInfo, configInfo}}, + Value: &Response_Info{&resInfoCopy}, } } diff --git a/types/types.pb.go b/types/types.pb.go index 5dc576d0..c9781779 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -34,9 +34,6 @@ It has these top-level messages: ResponseInitChain ResponseBeginBlock ResponseEndBlock - TMSPInfo - LastBlockInfo - ConfigInfo Header BlockID PartSetHeader @@ -1270,10 +1267,10 @@ func (*ResponseFlush) ProtoMessage() {} func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } type ResponseInfo struct { - Info string `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` - TmspInfo *TMSPInfo `protobuf:"bytes,2,opt,name=tmsp_info,json=tmspInfo" json:"tmsp_info,omitempty"` - LastBlock *LastBlockInfo `protobuf:"bytes,3,opt,name=last_block,json=lastBlock" json:"last_block,omitempty"` - Config *ConfigInfo `protobuf:"bytes,4,opt,name=config" json:"config,omitempty"` + Data string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` + LastBlockHeight uint64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight" json:"last_block_height,omitempty"` + LastBlockAppHash []byte `protobuf:"bytes,4,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` } func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } @@ -1281,30 +1278,30 @@ func (m *ResponseInfo) String() string { return proto.CompactTextStri func (*ResponseInfo) ProtoMessage() {} func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } -func (m *ResponseInfo) GetInfo() string { +func (m *ResponseInfo) GetData() string { if m != nil { - return m.Info + return m.Data } return "" } -func (m *ResponseInfo) GetTmspInfo() *TMSPInfo { +func (m *ResponseInfo) GetVersion() string { if m != nil { - return m.TmspInfo + return m.Version } - return nil + return "" } -func (m *ResponseInfo) GetLastBlock() *LastBlockInfo { +func (m *ResponseInfo) GetLastBlockHeight() uint64 { if m != nil { - return m.LastBlock + return m.LastBlockHeight } - return nil + return 0 } -func (m *ResponseInfo) GetConfig() *ConfigInfo { +func (m *ResponseInfo) GetLastBlockAppHash() []byte { if m != nil { - return m.Config + return m.LastBlockAppHash } return nil } @@ -1485,78 +1482,6 @@ func (m *ResponseEndBlock) GetDiffs() []*Validator { return nil } -type TMSPInfo struct { - Version string `protobuf:"bytes,1,opt,name=Version" json:"Version,omitempty"` -} - -func (m *TMSPInfo) Reset() { *m = TMSPInfo{} } -func (m *TMSPInfo) String() string { return proto.CompactTextString(m) } -func (*TMSPInfo) ProtoMessage() {} -func (*TMSPInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } - -func (m *TMSPInfo) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -type LastBlockInfo struct { - BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight" json:"block_height,omitempty"` - AppHash []byte `protobuf:"bytes,2,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` -} - -func (m *LastBlockInfo) Reset() { *m = LastBlockInfo{} } -func (m *LastBlockInfo) String() string { return proto.CompactTextString(m) } -func (*LastBlockInfo) ProtoMessage() {} -func (*LastBlockInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } - -func (m *LastBlockInfo) GetBlockHeight() uint64 { - if m != nil { - return m.BlockHeight - } - return 0 -} - -func (m *LastBlockInfo) GetAppHash() []byte { - if m != nil { - return m.AppHash - } - return nil -} - -type ConfigInfo struct { - MaxBlockSizeBytes uint64 `protobuf:"varint,1,opt,name=max_block_size_bytes,json=maxBlockSizeBytes" json:"max_block_size_bytes,omitempty"` - MaxBlockSizeTxs uint64 `protobuf:"varint,2,opt,name=max_block_size_txs,json=maxBlockSizeTxs" json:"max_block_size_txs,omitempty"` - MaxTxSize uint64 `protobuf:"varint,3,opt,name=max_tx_size,json=maxTxSize" json:"max_tx_size,omitempty"` -} - -func (m *ConfigInfo) Reset() { *m = ConfigInfo{} } -func (m *ConfigInfo) String() string { return proto.CompactTextString(m) } -func (*ConfigInfo) ProtoMessage() {} -func (*ConfigInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } - -func (m *ConfigInfo) GetMaxBlockSizeBytes() uint64 { - if m != nil { - return m.MaxBlockSizeBytes - } - return 0 -} - -func (m *ConfigInfo) GetMaxBlockSizeTxs() uint64 { - if m != nil { - return m.MaxBlockSizeTxs - } - return 0 -} - -func (m *ConfigInfo) GetMaxTxSize() uint64 { - if m != nil { - return m.MaxTxSize - } - return 0 -} - type Header struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` @@ -1572,7 +1497,7 @@ type Header struct { func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *Header) GetChainId() string { if m != nil { @@ -1645,7 +1570,7 @@ type BlockID struct { func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} -func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *BlockID) GetHash() []byte { if m != nil { @@ -1669,7 +1594,7 @@ type PartSetHeader struct { func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *PartSetHeader) GetTotal() uint64 { if m != nil { @@ -1693,7 +1618,7 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1735,9 +1660,6 @@ func init() { proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") - proto.RegisterType((*TMSPInfo)(nil), "types.TMSPInfo") - proto.RegisterType((*LastBlockInfo)(nil), "types.LastBlockInfo") - proto.RegisterType((*ConfigInfo)(nil), "types.ConfigInfo") proto.RegisterType((*Header)(nil), "types.Header") proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") @@ -2151,116 +2073,109 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1774 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x73, 0xdb, 0xc8, - 0x11, 0x16, 0x24, 0x3e, 0x9b, 0x12, 0x35, 0x6a, 0x51, 0x12, 0xcd, 0xa4, 0x52, 0x5e, 0x64, 0x37, - 0x2b, 0x79, 0x5d, 0x76, 0x4a, 0xae, 0xdd, 0xb2, 0xb3, 0xa9, 0x54, 0x59, 0xb6, 0xd6, 0x54, 0x6d, - 0x6c, 0x2b, 0xb0, 0xd6, 0x87, 0x3c, 0x8a, 0x05, 0x11, 0x43, 0x12, 0x11, 0x09, 0xc0, 0xc0, 0xc0, - 0x4b, 0xf9, 0x1f, 0x6c, 0xfe, 0x48, 0xae, 0xb9, 0xe4, 0x92, 0x6b, 0x4e, 0x79, 0x3f, 0x7e, 0xd1, - 0x56, 0xcf, 0x0c, 0x9e, 0x02, 0x7d, 0xf2, 0x85, 0xc5, 0xe9, 0xd7, 0xcc, 0x74, 0x7f, 0xfd, 0xcd, - 0x60, 0x60, 0x47, 0x5c, 0x07, 0x3c, 0xba, 0x2f, 0x7f, 0xef, 0x05, 0xa1, 0x2f, 0x7c, 0xac, 0xcb, - 0x81, 0xf9, 0xd7, 0x1a, 0x34, 0x2d, 0xfe, 0x26, 0xe6, 0x91, 0xc0, 0x43, 0xa8, 0xf1, 0xf1, 0xcc, - 0xef, 0x1b, 0xb7, 0x8d, 0xc3, 0xce, 0x31, 0xde, 0x53, 0xe6, 0x5a, 0x7b, 0x3a, 0x9e, 0xf9, 0xc3, - 0x35, 0x4b, 0x5a, 0xe0, 0x67, 0x50, 0x9f, 0xcc, 0xe3, 0x68, 0xd6, 0x5f, 0x97, 0xa6, 0xbb, 0x45, - 0xd3, 0xaf, 0x48, 0x35, 0x5c, 0xb3, 0x94, 0x0d, 0x85, 0x75, 0xbd, 0x89, 0xdf, 0xdf, 0xa8, 0x0a, - 0x7b, 0xe6, 0x4d, 0x64, 0x58, 0xb2, 0xc0, 0x87, 0x00, 0x11, 0x17, 0x23, 0x3f, 0x10, 0xae, 0xef, - 0xf5, 0x6b, 0xd2, 0xfe, 0xa0, 0x68, 0xff, 0x8a, 0x8b, 0x97, 0x52, 0x3d, 0x5c, 0xb3, 0xda, 0x51, - 0x32, 0xc0, 0xcf, 0xa1, 0x6d, 0x07, 0x01, 0xf7, 0x9c, 0x91, 0x58, 0xf6, 0xeb, 0xd2, 0x71, 0xbf, - 0xe8, 0xf8, 0x58, 0xaa, 0x2f, 0x96, 0xc3, 0x35, 0xab, 0x65, 0xeb, 0xff, 0x78, 0x0c, 0xad, 0xf1, - 0x8c, 0x8f, 0xaf, 0xc8, 0xab, 0x21, 0xbd, 0xf6, 0x8a, 0x5e, 0x4f, 0x48, 0x2b, 0x9d, 0x9a, 0x63, - 0xf5, 0x17, 0xef, 0x41, 0x63, 0xec, 0x2f, 0x16, 0xae, 0xe8, 0x37, 0xa5, 0x47, 0xaf, 0xe4, 0x21, - 0x75, 0xc3, 0x35, 0x4b, 0x5b, 0x51, 0xae, 0xde, 0xc4, 0x3c, 0xbc, 0xee, 0xb7, 0xaa, 0x72, 0xf5, - 0x2b, 0x52, 0x51, 0xae, 0xa4, 0x0d, 0x65, 0xc0, 0xf5, 0x5c, 0x31, 0x1a, 0xcf, 0x6c, 0xd7, 0xeb, - 0xb7, 0xab, 0x32, 0x70, 0xe6, 0xb9, 0xe2, 0x09, 0xa9, 0x29, 0x03, 0x6e, 0x32, 0xc0, 0x2f, 0xa1, - 0x73, 0xc9, 0xa7, 0xae, 0x37, 0xba, 0x9c, 0xfb, 0xe3, 0xab, 0x3e, 0x48, 0xd7, 0x7e, 0xd1, 0xf5, - 0x84, 0x0c, 0x4e, 0x48, 0x3f, 0x5c, 0xb3, 0xe0, 0x32, 0x1d, 0x51, 0xfa, 0x28, 0x77, 0xca, 0xb5, - 0x53, 0x95, 0xbe, 0x53, 0xcf, 0x49, 0x1c, 0x5b, 0x5c, 0xff, 0x3f, 0x69, 0x42, 0xfd, 0xad, 0x3d, - 0x8f, 0xb9, 0xf9, 0x29, 0x74, 0x72, 0x30, 0xc1, 0x3e, 0x34, 0x17, 0x3c, 0x8a, 0xec, 0x29, 0x97, - 0x58, 0x6a, 0x5b, 0xc9, 0xd0, 0xec, 0xc2, 0x66, 0x1e, 0x24, 0xe6, 0x56, 0xea, 0x48, 0x40, 0x30, - 0x7f, 0x06, 0xac, 0x5c, 0x67, 0x64, 0xb0, 0x71, 0xc5, 0xaf, 0x75, 0x20, 0xfa, 0x8b, 0x3d, 0x3d, - 0xad, 0x44, 0x5f, 0xdb, 0xd2, 0x6b, 0xf8, 0x08, 0xb6, 0x4b, 0xa5, 0xc6, 0x2e, 0xac, 0x8b, 0xa5, - 0xf4, 0xdc, 0xb4, 0xd6, 0xc5, 0xd2, 0xbc, 0x0d, 0xdd, 0x62, 0x5d, 0x6f, 0x58, 0x7c, 0x9c, 0xae, - 0x4f, 0x16, 0x86, 0xa6, 0x52, 0xc5, 0x53, 0x26, 0x6a, 0x60, 0x6e, 0xc3, 0x56, 0xa1, 0xda, 0xe6, - 0xd3, 0x74, 0xdd, 0x69, 0x75, 0xf0, 0xa7, 0x00, 0x6f, 0xed, 0xb9, 0xeb, 0xd8, 0xc2, 0x0f, 0xa3, - 0xbe, 0x71, 0x7b, 0xe3, 0xb0, 0x73, 0xcc, 0x74, 0x52, 0x5f, 0x27, 0x0a, 0x2b, 0x67, 0x63, 0xbe, - 0x80, 0x9d, 0x1b, 0x85, 0x42, 0x84, 0xda, 0xcc, 0x8e, 0x66, 0x7a, 0x01, 0xf2, 0x3f, 0x7e, 0x02, - 0x8d, 0x19, 0xb7, 0x1d, 0x1e, 0xea, 0xfe, 0xdb, 0xd2, 0x61, 0x87, 0x52, 0x68, 0x69, 0xa5, 0x79, - 0x94, 0x66, 0x24, 0xa9, 0x1e, 0xee, 0x93, 0xa7, 0x3b, 0x9d, 0x09, 0x19, 0xaf, 0x66, 0xe9, 0x91, - 0xf9, 0x5d, 0x1d, 0x5a, 0x16, 0x8f, 0x02, 0xdf, 0x8b, 0x38, 0x3e, 0x84, 0x36, 0x5f, 0x8e, 0xb9, - 0xea, 0x42, 0xa3, 0x04, 0x24, 0x65, 0x73, 0x9a, 0xe8, 0x09, 0x84, 0xa9, 0x31, 0x1e, 0x69, 0x06, - 0x29, 0xd3, 0x82, 0x76, 0xca, 0x53, 0xc8, 0xdd, 0x84, 0x42, 0x36, 0x4a, 0x5d, 0xa4, 0x6c, 0x4b, - 0x1c, 0x72, 0xa4, 0x39, 0xa4, 0x56, 0x19, 0xb8, 0x40, 0x22, 0x8f, 0x0a, 0x24, 0x52, 0xaf, 0x5c, - 0xfe, 0x0a, 0x16, 0xf9, 0x22, 0xcf, 0x22, 0x8d, 0x52, 0xf3, 0x29, 0xcf, 0x4a, 0x1a, 0x79, 0x90, - 0xa3, 0x91, 0x66, 0xa9, 0x7b, 0x94, 0x5b, 0x05, 0x8f, 0xdc, 0x4f, 0x79, 0xa4, 0x55, 0x62, 0x1e, - 0xed, 0x52, 0x26, 0x92, 0xbb, 0x09, 0x16, 0xdb, 0x95, 0x19, 0x2b, 0x31, 0xc9, 0xa3, 0x02, 0x93, - 0x40, 0x65, 0x1a, 0x56, 0x50, 0xc9, 0xcf, 0x8b, 0x54, 0xa2, 0xf8, 0xe0, 0x56, 0xc9, 0x77, 0x25, - 0x97, 0x7c, 0x91, 0xe7, 0x92, 0xcd, 0xca, 0x24, 0xbe, 0x9f, 0x4c, 0x8e, 0xa8, 0x0d, 0x4a, 0x30, - 0xa3, 0x46, 0xe4, 0x61, 0xe8, 0x87, 0x9a, 0x07, 0xd4, 0xc0, 0x3c, 0xa4, 0x76, 0xcd, 0xc0, 0xf5, - 0x1e, 0xe2, 0x91, 0x2d, 0x9b, 0x83, 0x96, 0xf9, 0x27, 0x23, 0xf3, 0x25, 0xfc, 0x50, 0xa3, 0x49, - 0x88, 0x29, 0x47, 0x85, 0xa5, 0xbb, 0xd0, 0x16, 0x8b, 0x28, 0x18, 0x49, 0x85, 0x02, 0xf5, 0xb6, - 0xde, 0xcb, 0xc5, 0xf3, 0x57, 0xe7, 0xe4, 0x67, 0xb5, 0xc8, 0x42, 0x46, 0x78, 0x00, 0x30, 0xb7, - 0x23, 0xa1, 0xb7, 0x5e, 0xc4, 0xf5, 0x2f, 0xed, 0x48, 0xc8, 0x7d, 0x4a, 0x9f, 0xf6, 0x3c, 0x19, - 0xe2, 0x11, 0xc1, 0xc0, 0x9b, 0xb8, 0x53, 0x8d, 0xed, 0x1d, 0xed, 0xf0, 0x44, 0x0a, 0xa5, 0xb5, - 0x36, 0x30, 0x3f, 0xc9, 0x12, 0x53, 0xa0, 0xc7, 0xb9, 0x3f, 0x4d, 0xe8, 0x71, 0xee, 0x4f, 0xcd, - 0xdf, 0x11, 0x19, 0x15, 0xd1, 0x8a, 0x3f, 0x86, 0xda, 0xd8, 0x77, 0x54, 0x56, 0xba, 0xe9, 0x1e, - 0x9e, 0xf8, 0x0e, 0xbf, 0xb8, 0x0e, 0xb8, 0x25, 0x95, 0x94, 0x01, 0xc7, 0x16, 0xb6, 0xdc, 0xe8, - 0xa6, 0x25, 0xff, 0x27, 0xe1, 0x37, 0xb2, 0xf0, 0xbf, 0x25, 0x56, 0x29, 0xa0, 0xfa, 0x43, 0x46, - 0xff, 0x75, 0x56, 0x27, 0xc5, 0xc0, 0x1f, 0x30, 0xf6, 0x6f, 0x88, 0xfe, 0xf3, 0xcd, 0xf5, 0x21, - 0x83, 0xef, 0x66, 0xc5, 0x49, 0xdb, 0xca, 0xec, 0x01, 0xde, 0xec, 0x17, 0x75, 0xca, 0x15, 0x3b, - 0x01, 0x7f, 0x02, 0x75, 0xc7, 0x9d, 0x4c, 0xa2, 0x7e, 0x6d, 0xc5, 0x41, 0xa1, 0xd4, 0xe6, 0xc7, - 0xd0, 0x4a, 0x90, 0x47, 0x68, 0x7f, 0xcd, 0xc3, 0x28, 0x61, 0xe9, 0xb6, 0x95, 0x0c, 0xcd, 0xe7, - 0xb0, 0x55, 0x00, 0x1c, 0x7e, 0x04, 0x9b, 0x12, 0x95, 0xa3, 0x02, 0xfb, 0x77, 0xa4, 0x6c, 0x28, - 0x45, 0x78, 0x0b, 0x88, 0xd0, 0x46, 0xf2, 0xb0, 0x51, 0x5b, 0x6d, 0xda, 0x41, 0x30, 0xb4, 0xa3, - 0x99, 0xf9, 0x07, 0x03, 0x20, 0xc3, 0x23, 0xde, 0x87, 0xde, 0xc2, 0x5e, 0x2a, 0x98, 0x8f, 0x22, - 0xf7, 0x1d, 0x1f, 0x5d, 0x5e, 0x0b, 0x1e, 0xe9, 0xa0, 0x3b, 0x0b, 0x7b, 0x29, 0x27, 0x7e, 0xe5, - 0xbe, 0xe3, 0x27, 0xa4, 0xc0, 0xcf, 0x00, 0x4b, 0x0e, 0x62, 0x19, 0xc9, 0x49, 0x6a, 0xd6, 0x76, - 0xde, 0xfc, 0x62, 0x19, 0xe1, 0x8f, 0xa0, 0x43, 0xc6, 0x62, 0x29, 0x2d, 0x65, 0x8a, 0x6b, 0x56, - 0x7b, 0x61, 0x2f, 0x2f, 0x96, 0x64, 0x62, 0xfe, 0x71, 0x1d, 0x1a, 0xea, 0xa0, 0xa3, 0x25, 0x4b, - 0x7a, 0x1b, 0xb9, 0x4e, 0x92, 0x01, 0x39, 0x3e, 0x73, 0x72, 0x07, 0xdd, 0x7a, 0xfe, 0xa0, 0xa3, - 0x62, 0x0a, 0x77, 0x91, 0x84, 0x95, 0xff, 0xf1, 0x00, 0x9a, 0x5e, 0xbc, 0x90, 0x6b, 0xaa, 0x29, - 0x63, 0x2f, 0x5e, 0xd0, 0x52, 0x8e, 0x61, 0x2b, 0x6b, 0x68, 0x9a, 0x44, 0x9d, 0x26, 0x5d, 0x5d, - 0x1c, 0x95, 0xde, 0xa7, 0x56, 0x27, 0xed, 0xe6, 0x33, 0x07, 0x0f, 0x81, 0x49, 0x1f, 0x45, 0xda, - 0x2a, 0x9d, 0x0d, 0x99, 0xce, 0x2e, 0xc9, 0x35, 0xab, 0xd3, 0x29, 0xfe, 0x03, 0x68, 0x13, 0x96, - 0x94, 0x49, 0x53, 0x9a, 0xb4, 0x48, 0x20, 0x95, 0x9f, 0xc2, 0x76, 0x76, 0x33, 0x50, 0x26, 0x2d, - 0x15, 0x25, 0x13, 0x4b, 0xc3, 0x7c, 0xd9, 0xda, 0xc5, 0xb2, 0x9d, 0x41, 0x53, 0x2f, 0xb1, 0xf2, - 0x16, 0x71, 0x07, 0xea, 0x81, 0x1d, 0x8a, 0x48, 0x13, 0x5b, 0xc2, 0x54, 0xe7, 0x76, 0x48, 0xb7, - 0x2f, 0x7d, 0x97, 0x50, 0x26, 0xe6, 0x23, 0xd8, 0x2a, 0xc8, 0x89, 0x8f, 0x85, 0x2f, 0xec, 0xb9, - 0x2e, 0xba, 0x1a, 0xa4, 0xd3, 0xac, 0x67, 0xd3, 0x98, 0x8f, 0xa0, 0x9d, 0xa2, 0x98, 0xca, 0x12, - 0xc4, 0x97, 0x5f, 0xf3, 0xe4, 0x42, 0xa5, 0x47, 0x14, 0x2e, 0xf0, 0xbf, 0xd5, 0x17, 0x9a, 0x9a, - 0xa5, 0x06, 0x77, 0xfe, 0x62, 0x40, 0xe7, 0xb9, 0x22, 0x70, 0xea, 0x47, 0xdc, 0x86, 0xce, 0x8b, - 0x78, 0x3e, 0xd7, 0x22, 0xb6, 0x86, 0x2d, 0xa8, 0x11, 0xef, 0x33, 0x03, 0xdb, 0x50, 0x97, 0xbc, - 0xce, 0xd6, 0x49, 0x48, 0x30, 0x65, 0x1b, 0xb8, 0x05, 0xed, 0x94, 0x28, 0x59, 0x8d, 0x86, 0xe9, - 0x81, 0xc2, 0xea, 0xb8, 0x09, 0xad, 0x84, 0x1f, 0xd9, 0x0e, 0x76, 0xa0, 0xa9, 0xe9, 0x8c, 0x21, - 0x02, 0x34, 0x54, 0xa1, 0xd8, 0x2e, 0x45, 0x96, 0x4c, 0xc4, 0x7a, 0x14, 0x20, 0xed, 0x6d, 0xb6, - 0x87, 0x5d, 0x80, 0xac, 0xab, 0xd9, 0x3e, 0x05, 0x4c, 0xfa, 0x99, 0x1d, 0xdc, 0xf9, 0x73, 0x1d, - 0x5a, 0x09, 0x93, 0x60, 0x03, 0xd6, 0x5f, 0x7e, 0xcd, 0xd6, 0x70, 0x07, 0xb6, 0xce, 0x3c, 0xc1, - 0x43, 0xcf, 0x9e, 0x9f, 0xd2, 0x09, 0xc6, 0x0c, 0x12, 0x9d, 0x7a, 0x63, 0xdf, 0x71, 0xbd, 0xa9, - 0x12, 0xad, 0x53, 0xa0, 0x13, 0xdb, 0x79, 0xe1, 0x7b, 0x63, 0xce, 0x36, 0x90, 0xc1, 0xe6, 0x37, - 0x9e, 0x1d, 0x8b, 0x99, 0x1f, 0xba, 0xef, 0xb8, 0xc3, 0x6a, 0xb8, 0x07, 0x3b, 0x67, 0x5e, 0x14, - 0x4f, 0x26, 0xee, 0xd8, 0xe5, 0x9e, 0xf8, 0x2a, 0xf6, 0x9c, 0x88, 0xd5, 0x11, 0xa1, 0xfb, 0x8d, - 0x77, 0xe5, 0xf9, 0xdf, 0x7a, 0xfa, 0xda, 0xc7, 0x1a, 0xd8, 0x87, 0xde, 0x89, 0x1d, 0xf1, 0xa7, - 0x71, 0x30, 0x77, 0xc7, 0xb6, 0xe0, 0x8f, 0x1d, 0x27, 0xe4, 0x51, 0xc4, 0x38, 0x05, 0x21, 0x4d, - 0x71, 0xee, 0x49, 0xe2, 0x50, 0x88, 0xcf, 0x79, 0xc4, 0xa6, 0x78, 0x0b, 0xf6, 0x6e, 0x68, 0xe4, - 0xcc, 0x33, 0xfc, 0x21, 0xf4, 0xcb, 0xaa, 0x67, 0x76, 0x74, 0x1e, 0xba, 0x63, 0xce, 0x5c, 0xec, - 0x01, 0x53, 0x5a, 0x09, 0xdd, 0x33, 0x2f, 0x88, 0x05, 0xfb, 0x7d, 0x32, 0xbf, 0x96, 0xbe, 0x8c, - 0x05, 0x89, 0xaf, 0x4a, 0xe2, 0x73, 0x09, 0x0f, 0x36, 0xc7, 0x03, 0xd8, 0xcd, 0x89, 0x5f, 0xd1, - 0xfe, 0x28, 0x3b, 0x8b, 0x6c, 0xbd, 0x4a, 0xe1, 0x4e, 0x3d, 0x5b, 0xc4, 0x21, 0x67, 0x1e, 0xee, - 0x03, 0x92, 0x46, 0xa7, 0x24, 0xd9, 0xb8, 0x9f, 0xcc, 0xa0, 0xe5, 0x7a, 0x86, 0xa0, 0x2c, 0x9e, - 0xc7, 0x53, 0xd7, 0x63, 0x6f, 0x70, 0x0f, 0xd8, 0x33, 0xff, 0xad, 0x96, 0x9e, 0x7a, 0xc2, 0x15, - 0xd7, 0xec, 0x6f, 0x06, 0xf6, 0x60, 0x3b, 0x13, 0x3f, 0x0b, 0xfd, 0x38, 0x60, 0x7f, 0x37, 0xf0, - 0x00, 0x30, 0x93, 0x9e, 0x87, 0x7e, 0xe0, 0x47, 0xf6, 0x9c, 0xfd, 0xc3, 0xc0, 0x7d, 0xd8, 0x79, - 0xe6, 0xbf, 0x4d, 0xab, 0xa0, 0x1c, 0xfe, 0x99, 0x38, 0xa4, 0xf2, 0xe7, 0x7c, 0x71, 0xc9, 0x43, - 0xf6, 0x2f, 0x03, 0x6f, 0x41, 0x2f, 0xaf, 0x48, 0x63, 0xfd, 0xdb, 0xd0, 0x2b, 0x4a, 0x55, 0xaf, - 0x7d, 0xc1, 0xd9, 0x7f, 0x12, 0xb1, 0xce, 0x83, 0x0e, 0xf4, 0x5f, 0x03, 0x77, 0xa1, 0x9b, 0x89, - 0xa5, 0xed, 0xff, 0x0c, 0x1c, 0xc0, 0x5e, 0x41, 0xe8, 0x7a, 0xd3, 0x73, 0xea, 0x38, 0xf6, 0x7f, - 0xe3, 0xf8, 0xbb, 0x3a, 0x6c, 0xd3, 0x11, 0xf3, 0x38, 0x50, 0x13, 0xd0, 0x25, 0xe3, 0xbe, 0xea, - 0x33, 0xac, 0x78, 0x13, 0x18, 0x54, 0xdd, 0xf2, 0xf1, 0x58, 0xb7, 0x23, 0x56, 0x3d, 0x0d, 0x0c, - 0x2a, 0x2f, 0xfb, 0x34, 0x89, 0xba, 0x88, 0xdd, 0x7c, 0x21, 0x18, 0x54, 0xdd, 0xf8, 0xf1, 0x17, - 0xb9, 0xf6, 0xc6, 0x55, 0xef, 0x04, 0x83, 0x95, 0x77, 0x7f, 0xfc, 0x32, 0x23, 0x00, 0x5c, 0xf1, - 0x5a, 0x30, 0x58, 0x75, 0xff, 0xc7, 0x87, 0x29, 0x5f, 0x60, 0xf5, 0x9b, 0xc1, 0x60, 0xc5, 0x37, - 0x00, 0xe5, 0x46, 0x5d, 0x6d, 0xaa, 0x9e, 0x02, 0x06, 0x95, 0xd7, 0x7a, 0xfc, 0x3c, 0x21, 0x24, - 0xac, 0x7c, 0x6e, 0x18, 0x54, 0x7f, 0x3c, 0x50, 0x86, 0xb2, 0x0f, 0xd2, 0x55, 0xef, 0x08, 0x83, - 0x95, 0x9f, 0x05, 0xf8, 0x38, 0xcf, 0x70, 0xb8, 0xf2, 0x35, 0x61, 0xb0, 0xfa, 0xe3, 0x80, 0x92, - 0x9c, 0x7d, 0x7d, 0x56, 0xbf, 0x29, 0x0c, 0x56, 0x7d, 0x1f, 0x5c, 0x36, 0xe4, 0x5b, 0xd5, 0x83, - 0xef, 0x03, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xa9, 0x42, 0xf7, 0xc0, 0x12, 0x00, 0x00, + // 1654 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0x1b, 0xc7, + 0x15, 0xc6, 0x60, 0xc7, 0x03, 0x09, 0x34, 0x1f, 0x41, 0x12, 0x44, 0x72, 0x50, 0x26, 0x71, 0x4c, + 0x29, 0x8e, 0x94, 0xa2, 0xcb, 0x2e, 0x31, 0x4e, 0xa5, 0x8a, 0x94, 0x68, 0x02, 0xe5, 0x92, 0xc4, + 0x8c, 0x68, 0x1f, 0xb2, 0x14, 0x6a, 0x88, 0x69, 0x00, 0x13, 0x02, 0x33, 0xa3, 0x59, 0x68, 0x32, + 0xff, 0xc0, 0xbf, 0x20, 0x3f, 0x21, 0xbf, 0x20, 0x97, 0x5c, 0x73, 0xca, 0xbe, 0xfc, 0x22, 0xd7, + 0xeb, 0xee, 0x59, 0x39, 0xf0, 0x49, 0x17, 0xd4, 0xf4, 0xdb, 0xba, 0xfb, 0xf5, 0xf7, 0xbe, 0x7e, + 0x0d, 0xd8, 0x09, 0xef, 0x3d, 0x1e, 0x3c, 0x13, 0xbf, 0x4f, 0x3d, 0xdf, 0x0d, 0x5d, 0x6c, 0x88, + 0x81, 0xfe, 0xd7, 0x3a, 0xb4, 0x0c, 0xfe, 0x2e, 0xe2, 0x41, 0x88, 0x47, 0x50, 0xe7, 0xb3, 0xa5, + 0x3b, 0xd4, 0x1e, 0x69, 0x47, 0xdd, 0x63, 0x7c, 0x2a, 0xcd, 0x95, 0xf6, 0x7c, 0xb6, 0x74, 0xc7, + 0x15, 0x43, 0x58, 0xe0, 0x4f, 0xa0, 0x31, 0x5f, 0x45, 0xc1, 0x72, 0x58, 0x15, 0xa6, 0xbb, 0x79, + 0xd3, 0xcf, 0x49, 0x35, 0xae, 0x18, 0xd2, 0x86, 0xc2, 0xda, 0xce, 0xdc, 0x1d, 0xd6, 0xca, 0xc2, + 0x4e, 0x9c, 0xb9, 0x08, 0x4b, 0x16, 0xf8, 0x1c, 0x20, 0xe0, 0xe1, 0xd4, 0xf5, 0x42, 0xdb, 0x75, + 0x86, 0x75, 0x61, 0x7f, 0x90, 0xb7, 0x7f, 0xcb, 0xc3, 0x37, 0x42, 0x3d, 0xae, 0x18, 0x9d, 0x20, + 0x1e, 0xe0, 0x27, 0xd0, 0x31, 0x3d, 0x8f, 0x3b, 0xd6, 0x34, 0xbc, 0x1b, 0x36, 0x84, 0xe3, 0x7e, + 0xde, 0xf1, 0x54, 0xa8, 0xaf, 0xee, 0xc6, 0x15, 0xa3, 0x6d, 0xaa, 0x6f, 0x3c, 0x86, 0xf6, 0x6c, + 0xc9, 0x67, 0x37, 0xe4, 0xd5, 0x14, 0x5e, 0x7b, 0x79, 0xaf, 0x17, 0xa4, 0x15, 0x4e, 0xad, 0x99, + 0xfc, 0xc4, 0xa7, 0xd0, 0x9c, 0xb9, 0xeb, 0xb5, 0x1d, 0x0e, 0x5b, 0xc2, 0x63, 0x50, 0xf0, 0x10, + 0xba, 0x71, 0xc5, 0x50, 0x56, 0x94, 0xab, 0x77, 0x11, 0xf7, 0xef, 0x87, 0xed, 0xb2, 0x5c, 0xfd, + 0x8a, 0x54, 0x94, 0x2b, 0x61, 0x43, 0x19, 0xb0, 0x1d, 0x3b, 0x9c, 0xce, 0x96, 0xa6, 0xed, 0x0c, + 0x3b, 0x65, 0x19, 0x98, 0x38, 0x76, 0xf8, 0x82, 0xd4, 0x94, 0x01, 0x3b, 0x1e, 0xe0, 0x67, 0xd0, + 0xbd, 0xe6, 0x0b, 0xdb, 0x99, 0x5e, 0xaf, 0xdc, 0xd9, 0xcd, 0x10, 0x84, 0xeb, 0x30, 0xef, 0x7a, + 0x46, 0x06, 0x67, 0xa4, 0x1f, 0x57, 0x0c, 0xb8, 0x4e, 0x46, 0x94, 0x3e, 0xca, 0x9d, 0x74, 0xed, + 0x96, 0xa5, 0xef, 0xdc, 0xb1, 0x62, 0xc7, 0x36, 0x57, 0xdf, 0x67, 0x2d, 0x68, 0xdc, 0x9a, 0xab, + 0x88, 0xeb, 0x1f, 0x42, 0x37, 0x03, 0x13, 0x1c, 0x42, 0x6b, 0xcd, 0x83, 0xc0, 0x5c, 0x70, 0x81, + 0xa5, 0x8e, 0x11, 0x0f, 0xf5, 0x1e, 0x6c, 0x65, 0x41, 0xa2, 0x6f, 0x27, 0x8e, 0x04, 0x04, 0xfd, + 0xe7, 0xc0, 0x8a, 0xe7, 0x8c, 0x0c, 0x6a, 0x37, 0xfc, 0x5e, 0x05, 0xa2, 0x4f, 0x1c, 0xa8, 0x69, + 0x05, 0xfa, 0x3a, 0x86, 0x5a, 0xc3, 0x0f, 0xa0, 0x5f, 0x38, 0x6a, 0xec, 0x41, 0x35, 0xbc, 0x13, + 0x9e, 0x5b, 0x46, 0x35, 0xbc, 0xd3, 0x1f, 0x41, 0x2f, 0x7f, 0xae, 0x0f, 0x2c, 0x7e, 0x94, 0xac, + 0x4f, 0x1c, 0x0c, 0x4d, 0x25, 0x0f, 0x4f, 0x9a, 0xc8, 0x81, 0xde, 0x87, 0xed, 0xdc, 0x69, 0xeb, + 0x2f, 0x93, 0x75, 0x27, 0xa7, 0x83, 0x3f, 0x03, 0xb8, 0x35, 0x57, 0xb6, 0x65, 0x86, 0xae, 0x1f, + 0x0c, 0xb5, 0x47, 0xb5, 0xa3, 0xee, 0x31, 0x53, 0x49, 0xfd, 0x2a, 0x56, 0x18, 0x19, 0x1b, 0xfd, + 0x35, 0xec, 0x3c, 0x38, 0x28, 0x44, 0xa8, 0x2f, 0xcd, 0x60, 0xa9, 0x16, 0x20, 0xbe, 0xf1, 0x03, + 0x68, 0x2e, 0xb9, 0x69, 0x71, 0x5f, 0xd5, 0xdf, 0xb6, 0x0a, 0x3b, 0x16, 0x42, 0x43, 0x29, 0xf5, + 0xc7, 0x49, 0x46, 0xe2, 0xd3, 0xc3, 0x7d, 0xf2, 0xb4, 0x17, 0xcb, 0x50, 0xc4, 0xab, 0x1b, 0x6a, + 0xa4, 0x7f, 0xd3, 0x80, 0xb6, 0xc1, 0x03, 0xcf, 0x75, 0x02, 0x8e, 0xcf, 0xa1, 0xc3, 0xef, 0x66, + 0x5c, 0x56, 0xa1, 0x56, 0x00, 0x92, 0xb4, 0x39, 0x8f, 0xf5, 0x04, 0xc2, 0xc4, 0x18, 0x1f, 0x2b, + 0x06, 0x29, 0xd2, 0x82, 0x72, 0xca, 0x52, 0xc8, 0x47, 0x31, 0x85, 0xd4, 0x0a, 0x55, 0x24, 0x6d, + 0x0b, 0x1c, 0xf2, 0x58, 0x71, 0x48, 0xbd, 0x34, 0x70, 0x8e, 0x44, 0x4e, 0x72, 0x24, 0xd2, 0x28, + 0x5d, 0xfe, 0x06, 0x16, 0xf9, 0x34, 0xcb, 0x22, 0xcd, 0x42, 0xf1, 0x49, 0xcf, 0x52, 0x1a, 0xf9, + 0x38, 0x43, 0x23, 0xad, 0x42, 0xf5, 0x48, 0xb7, 0x12, 0x1e, 0x79, 0x96, 0xf0, 0x48, 0xbb, 0xc0, + 0x3c, 0xca, 0xa5, 0x48, 0x24, 0x1f, 0xc5, 0x58, 0xec, 0x94, 0x66, 0xac, 0xc0, 0x24, 0x27, 0x39, + 0x26, 0x81, 0xd2, 0x34, 0x6c, 0xa0, 0x92, 0x5f, 0xe4, 0xa9, 0x44, 0xf2, 0xc1, 0x61, 0xc1, 0x77, + 0x23, 0x97, 0x7c, 0x9a, 0xe5, 0x92, 0xad, 0xd2, 0x24, 0x7e, 0x37, 0x99, 0x3c, 0xa6, 0x32, 0x28, + 0xc0, 0x8c, 0x0a, 0x91, 0xfb, 0xbe, 0xeb, 0x2b, 0x1e, 0x90, 0x03, 0xfd, 0x88, 0xca, 0x35, 0x05, + 0xd7, 0x77, 0x10, 0x8f, 0x28, 0xd9, 0x0c, 0xb4, 0xf4, 0x3f, 0x6a, 0xa9, 0x2f, 0xe1, 0x87, 0x0a, + 0xcd, 0x32, 0x43, 0x53, 0x39, 0x8a, 0x6f, 0x8a, 0x77, 0xcb, 0xfd, 0x80, 0x80, 0x24, 0xb9, 0x26, + 0x1e, 0xe2, 0x13, 0xd8, 0x59, 0x99, 0x41, 0x28, 0xb7, 0x39, 0x55, 0x35, 0x55, 0x13, 0x35, 0xd5, + 0x27, 0x85, 0xdc, 0x9f, 0x10, 0xe3, 0x4f, 0x61, 0x37, 0x63, 0x6b, 0x7a, 0xde, 0x54, 0x54, 0x74, + 0x5d, 0x54, 0x34, 0x4b, 0xac, 0x4f, 0x3d, 0x6f, 0x6c, 0x06, 0x4b, 0xfd, 0x83, 0x74, 0xff, 0x39, + 0x16, 0x5c, 0xb9, 0x8b, 0x98, 0x05, 0x57, 0xee, 0x42, 0xff, 0x1d, 0x71, 0x4e, 0x1e, 0x94, 0xf8, + 0x43, 0xa8, 0xcf, 0x5c, 0x4b, 0x6e, 0xbe, 0x77, 0xdc, 0x57, 0x69, 0x7f, 0xe1, 0x5a, 0xfc, 0xea, + 0xde, 0xe3, 0x86, 0x50, 0x26, 0x1b, 0xad, 0x4a, 0x46, 0x11, 0x1b, 0x55, 0xe1, 0x6b, 0x69, 0xf8, + 0xdf, 0x12, 0x79, 0xe4, 0xc0, 0xfb, 0x3e, 0xa3, 0xff, 0x3a, 0x3d, 0x0e, 0x49, 0xb4, 0xef, 0x31, + 0xf6, 0x6f, 0x88, 0xe5, 0xb3, 0x35, 0xf4, 0x3e, 0x83, 0xef, 0xa6, 0x87, 0x93, 0x54, 0x8f, 0x3e, + 0x00, 0x7c, 0x58, 0x16, 0xf2, 0x32, 0xcb, 0x03, 0x1e, 0x7f, 0x0c, 0x0d, 0xcb, 0x9e, 0xcf, 0x83, + 0x61, 0x7d, 0xc3, 0x7d, 0x20, 0xd5, 0xfa, 0x9f, 0xaa, 0xd0, 0x94, 0x6c, 0x8e, 0x87, 0x44, 0x2e, + 0xa6, 0xed, 0x4c, 0x6d, 0x2b, 0x06, 0xb5, 0x18, 0x4f, 0xac, 0x0c, 0x9b, 0x57, 0xb3, 0x6c, 0x4e, + 0x5b, 0x09, 0xed, 0x35, 0x57, 0x78, 0x14, 0xdf, 0x78, 0x00, 0x2d, 0x27, 0x5a, 0x4f, 0xc3, 0xbb, + 0x40, 0x00, 0xaf, 0x6e, 0x34, 0x9d, 0x68, 0x7d, 0x75, 0x17, 0xe0, 0x31, 0x6c, 0x67, 0xd0, 0x69, + 0x5b, 0x8a, 0x32, 0x7b, 0x6a, 0x69, 0x62, 0xdd, 0x93, 0x97, 0x46, 0x37, 0xc1, 0xe9, 0xc4, 0xc2, + 0x23, 0x10, 0xb0, 0x9d, 0x4a, 0x66, 0x92, 0x70, 0x6e, 0x8a, 0xbc, 0xf5, 0x48, 0xae, 0xa8, 0x8b, + 0xae, 0xaa, 0xef, 0x41, 0x87, 0x32, 0x29, 0x4d, 0x5a, 0xc2, 0xa4, 0x4d, 0x02, 0xa1, 0xfc, 0x10, + 0xfa, 0xe9, 0xf5, 0x27, 0x4d, 0xda, 0x32, 0x4a, 0x2a, 0x16, 0x86, 0x87, 0xd0, 0x4e, 0xca, 0xa6, + 0x23, 0x2c, 0x5a, 0xa6, 0xaa, 0x96, 0x09, 0xb4, 0xd4, 0x12, 0x4b, 0xaf, 0xca, 0x27, 0xd0, 0xf0, + 0x4c, 0x3f, 0x0c, 0xd4, 0x95, 0x14, 0x93, 0xe6, 0xa5, 0xe9, 0x53, 0x8b, 0xa1, 0x2e, 0x4c, 0x69, + 0xa2, 0x9f, 0xc0, 0x76, 0x4e, 0x4e, 0xa4, 0x13, 0xba, 0xa1, 0xb9, 0x52, 0x97, 0xa5, 0x1c, 0x24, + 0xd3, 0x54, 0xd3, 0x69, 0xf4, 0x13, 0xe8, 0x24, 0x67, 0x48, 0xc7, 0xe2, 0x45, 0xd7, 0x5f, 0xf0, + 0xb8, 0x6b, 0x50, 0x23, 0x0a, 0xe7, 0xb9, 0x5f, 0xab, 0x5b, 0xbb, 0x6e, 0xc8, 0xc1, 0x93, 0xbf, + 0x68, 0xd0, 0x7d, 0x25, 0x59, 0x8a, 0xd0, 0x88, 0x7d, 0xe8, 0xbe, 0x8e, 0x56, 0x2b, 0x25, 0x62, + 0x15, 0x6c, 0x43, 0x9d, 0xc8, 0x8d, 0x69, 0xd8, 0x81, 0x86, 0x20, 0x2f, 0x56, 0x25, 0x21, 0xb1, + 0x16, 0xab, 0xe1, 0x36, 0x74, 0x12, 0x9a, 0x60, 0x75, 0x1a, 0x26, 0xac, 0xc9, 0x1a, 0xb8, 0x05, + 0xed, 0x98, 0x1d, 0xd8, 0x0e, 0x76, 0xa1, 0xa5, 0x8a, 0x99, 0x21, 0x02, 0x34, 0xe5, 0x41, 0xb1, + 0x5d, 0x8a, 0x2c, 0xea, 0x90, 0x0d, 0x28, 0x40, 0x82, 0x6c, 0xb6, 0x87, 0x3d, 0x80, 0x14, 0xd3, + 0x6c, 0x9f, 0x02, 0xc6, 0x68, 0x66, 0x07, 0x4f, 0xfe, 0xdc, 0x80, 0x76, 0x5c, 0x47, 0xd8, 0x84, + 0xea, 0x9b, 0x2f, 0x58, 0x05, 0x77, 0x60, 0x7b, 0xe2, 0x84, 0xdc, 0x77, 0xcc, 0xd5, 0x39, 0xd1, + 0x34, 0xd3, 0x48, 0x74, 0xee, 0xcc, 0x5c, 0xcb, 0x76, 0x16, 0x52, 0x54, 0xa5, 0x40, 0x67, 0xa6, + 0xf5, 0xda, 0x75, 0x66, 0x9c, 0xd5, 0x90, 0xc1, 0xd6, 0x97, 0x8e, 0x19, 0x85, 0x4b, 0xd7, 0xb7, + 0xff, 0xc0, 0x2d, 0x56, 0xc7, 0x3d, 0xd8, 0x99, 0x38, 0x41, 0x34, 0x9f, 0xdb, 0x33, 0x9b, 0x3b, + 0xe1, 0xe7, 0x91, 0x63, 0x05, 0xac, 0x81, 0x08, 0xbd, 0x2f, 0x9d, 0x1b, 0xc7, 0xfd, 0xda, 0x51, + 0xbd, 0x0d, 0x6b, 0xe2, 0x10, 0x06, 0x67, 0x66, 0xc0, 0x5f, 0x46, 0xde, 0xca, 0x9e, 0x99, 0x21, + 0x3f, 0xb5, 0x2c, 0x9f, 0x07, 0x01, 0xe3, 0x14, 0x84, 0x34, 0xf9, 0xb9, 0xe7, 0xb1, 0x43, 0x2e, + 0x3e, 0xe7, 0x01, 0x5b, 0xe0, 0x21, 0xec, 0x3d, 0xd0, 0x88, 0x99, 0x97, 0xf8, 0x7d, 0x18, 0x16, + 0x55, 0x17, 0x66, 0x70, 0xe9, 0xdb, 0x33, 0xce, 0x6c, 0x1c, 0x00, 0x93, 0x5a, 0x01, 0xdd, 0x89, + 0xe3, 0x45, 0x21, 0xfb, 0x7d, 0x3c, 0xbf, 0x92, 0xbe, 0x89, 0x42, 0x12, 0xdf, 0x14, 0xc4, 0x97, + 0x02, 0x1e, 0x6c, 0x85, 0x07, 0xb0, 0x9b, 0x11, 0xbf, 0xa5, 0xfd, 0x51, 0x76, 0xd6, 0xe9, 0x7a, + 0xa5, 0xc2, 0x5e, 0x38, 0x66, 0x18, 0xf9, 0x9c, 0x39, 0xb8, 0x0f, 0x48, 0x1a, 0x95, 0x92, 0x78, + 0xe3, 0x6e, 0x3c, 0x83, 0x92, 0xab, 0x19, 0xbc, 0xa2, 0x78, 0x15, 0x2d, 0x6c, 0x87, 0xbd, 0xc3, + 0x3d, 0x60, 0x17, 0xee, 0xad, 0x92, 0x9e, 0x3b, 0xa1, 0x1d, 0xde, 0xb3, 0xbf, 0x69, 0x38, 0x80, + 0x7e, 0x2a, 0xbe, 0xf0, 0xdd, 0xc8, 0x63, 0x7f, 0xd7, 0xf0, 0x00, 0x30, 0x95, 0x5e, 0xfa, 0xae, + 0xe7, 0x06, 0xe6, 0x8a, 0xfd, 0x43, 0xc3, 0x7d, 0xd8, 0xb9, 0x70, 0x6f, 0x93, 0x53, 0x90, 0x0e, + 0xff, 0x8c, 0x1d, 0x12, 0xf9, 0x2b, 0xbe, 0xbe, 0xe6, 0x3e, 0xfb, 0x97, 0x86, 0x87, 0x30, 0xc8, + 0x2a, 0x92, 0x58, 0xff, 0xd6, 0xd4, 0x8a, 0x12, 0xd5, 0x57, 0x6e, 0xc8, 0xd9, 0x7f, 0x62, 0xb1, + 0xca, 0x83, 0x0a, 0xf4, 0x5f, 0x0d, 0x77, 0xa1, 0x97, 0x8a, 0x85, 0xed, 0xff, 0x34, 0x1c, 0xc1, + 0x5e, 0x4e, 0x68, 0x3b, 0x8b, 0x4b, 0xaa, 0x38, 0xf6, 0x7f, 0xed, 0xf8, 0x9b, 0x06, 0xf4, 0xaf, + 0x5e, 0xbd, 0xbd, 0x3c, 0xf5, 0xe4, 0x04, 0x74, 0xc5, 0x3e, 0x93, 0x75, 0x86, 0x25, 0x0f, 0xdf, + 0x51, 0x59, 0x2b, 0x8b, 0xc7, 0xaa, 0x1c, 0xb1, 0xec, 0xfd, 0x3b, 0x2a, 0xed, 0x68, 0x69, 0x12, + 0xd9, 0x6d, 0x3c, 0x7c, 0x06, 0x8f, 0xca, 0xda, 0x5a, 0xfc, 0x65, 0xa6, 0xbc, 0x71, 0xd3, 0x63, + 0x78, 0xb4, 0xb1, 0xc1, 0xc5, 0xcf, 0x52, 0x02, 0xc0, 0x0d, 0x4f, 0xe2, 0xd1, 0xa6, 0x26, 0x17, + 0x9f, 0x27, 0x7c, 0x81, 0xe5, 0x0f, 0xe3, 0xd1, 0x86, 0x46, 0x97, 0x72, 0x23, 0x2f, 0xf6, 0xb2, + 0xf7, 0xee, 0xa8, 0xb4, 0x77, 0xc5, 0x4f, 0x62, 0x42, 0xc2, 0xd2, 0x37, 0xf5, 0xa8, 0xbc, 0x43, + 0xa6, 0x0c, 0xa5, 0xaf, 0xae, 0x4d, 0x8f, 0xe5, 0xd1, 0xc6, 0xde, 0x17, 0x4f, 0xb3, 0x0c, 0x87, + 0x1b, 0x9f, 0xcc, 0xa3, 0xcd, 0x1d, 0x30, 0x25, 0x39, 0x7d, 0x62, 0x95, 0x3f, 0x9c, 0x47, 0x9b, + 0x9a, 0xe0, 0xeb, 0xa6, 0xf8, 0x43, 0xe6, 0xe3, 0x6f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf8, 0xa7, + 0x82, 0x8b, 0xa5, 0x11, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 8d0860c9..69f9a573 100644 --- a/types/types.proto +++ b/types/types.proto @@ -165,7 +165,7 @@ message ResponseFlush{ } message ResponseInfo { - string info = 1; + string data = 1; string version = 2; uint64 last_block_height = 3; bytes last_block_app_hash = 4; From f8167872d8ddd3a2362452ef1414991b5afa8862 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 26 Dec 2016 22:12:32 -0800 Subject: [PATCH 174/545] EndBlock also returns ResponseEndBlock --- client/client.go | 2 +- client/grpc_client.go | 10 +++++++--- client/local_client.go | 12 ++++++------ client/socket_client.go | 10 +++++++--- cmd/counter/main.go | 3 ++- cmd/dummy/main.go | 3 ++- example/chain_aware/chain_aware_app.go | 7 ++++--- example/chain_aware/chain_aware_test.go | 3 ++- example/dummy/dummy_test.go | 4 ++-- example/dummy/persistent_dummy.go | 4 ++-- server/socket_server.go | 9 +++++---- types/application.go | 6 +++--- types/messages.go | 5 +++-- 13 files changed, 46 insertions(+), 32 deletions(-) diff --git a/client/client.go b/client/client.go index c39357ba..c3c1e151 100644 --- a/client/client.go +++ b/client/client.go @@ -38,7 +38,7 @@ type Client interface { InitChainSync(validators []*types.Validator) (err error) BeginBlockSync(hash []byte, header *types.Header) (err error) - EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) + EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) } //---------------------------------------- diff --git a/client/grpc_client.go b/client/grpc_client.go index e72f31fb..15cda522 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -329,10 +329,14 @@ func (cli *grpcClient) BeginBlockSync(hash []byte, header *types.Header) (err er return cli.Error() } -func (cli *grpcClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { +func (cli *grpcClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { reqres := cli.EndBlockAsync(height) if err := cli.Error(); err != nil { - return nil, err + return resEndBlock, err + } + if resEndBlock_ := reqres.Response.GetEndBlock(); resEndBlock_ != nil { + return *resEndBlock_, nil + } else { + return resEndBlock, nil } - return reqres.Response.GetEndBlock().Diffs, nil } diff --git a/client/local_client.go b/client/local_client.go index 0c363d0c..ee5d6f28 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -136,14 +136,14 @@ func (app *localClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqR func (app *localClient) EndBlockAsync(height uint64) *ReqRes { app.mtx.Lock() - var validators []*types.Validator + var resEndBlock types.ResponseEndBlock if bcApp, ok := app.Application.(types.BlockchainAware); ok { - validators = bcApp.EndBlock(height) + resEndBlock = bcApp.EndBlock(height) } app.mtx.Unlock() return app.callback( types.ToRequestEndBlock(height), - types.ToResponseEndBlock(validators), + types.ToResponseEndBlock(resEndBlock), ) } @@ -217,13 +217,13 @@ func (app *localClient) BeginBlockSync(hash []byte, header *types.Header) (err e return nil } -func (app *localClient) EndBlockSync(height uint64) (changedValidators []*types.Validator, err error) { +func (app *localClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { app.mtx.Lock() if bcApp, ok := app.Application.(types.BlockchainAware); ok { - changedValidators = bcApp.EndBlock(height) + resEndBlock = bcApp.EndBlock(height) } app.mtx.Unlock() - return changedValidators, nil + return resEndBlock, nil } //------------------------------------------------------- diff --git a/client/socket_client.go b/client/socket_client.go index 8c5c8428..aecaeea5 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -373,13 +373,17 @@ func (cli *socketClient) BeginBlockSync(hash []byte, header *types.Header) (err return nil } -func (cli *socketClient) EndBlockSync(height uint64) (validators []*types.Validator, err error) { +func (cli *socketClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { reqres := cli.queueRequest(types.ToRequestEndBlock(height)) cli.FlushSync() if err := cli.Error(); err != nil { - return nil, err + return resEndBlock, err + } + if resEndBlock_ := reqres.Response.GetEndBlock(); resEndBlock_ != nil { + return *resEndBlock_, nil + } else { + return resEndBlock, nil } - return reqres.Response.GetEndBlock().Diffs, nil } //---------------------------------------- diff --git a/cmd/counter/main.go b/cmd/counter/main.go index c04a40e0..0f284af9 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -17,7 +17,7 @@ func main() { app := counter.NewCounterApplication(*serialPtr) // Start the listener - _, err := server.NewServer(*addrPtr, *tmspPtr, app) + srv, err := server.NewServer(*addrPtr, *tmspPtr, app) if err != nil { Exit(err.Error()) } @@ -25,6 +25,7 @@ func main() { // Wait forever TrapSignal(func() { // Cleanup + srv.Stop() }) } diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 8a1465c4..fe7ae750 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -25,7 +25,7 @@ func main() { } // Start the listener - _, err := server.NewServer(*addrPtr, *tmspPtr, app) + srv, err := server.NewServer(*addrPtr, *tmspPtr, app) if err != nil { Exit(err.Error()) } @@ -33,6 +33,7 @@ func main() { // Wait forever TrapSignal(func() { // Cleanup + srv.Stop() }) } diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 15d8f876..cd91c682 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -15,7 +15,7 @@ func main() { flag.Parse() // Start the listener - _, err := server.NewServer(*addrPtr, *tmspPtr, NewChainAwareApplication()) + srv, err := server.NewServer(*addrPtr, *tmspPtr, NewChainAwareApplication()) if err != nil { Exit(err.Error()) } @@ -23,6 +23,7 @@ func main() { // Wait forever TrapSignal(func() { // Cleanup + srv.Stop() }) } @@ -65,9 +66,9 @@ func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) return } -func (app *ChainAwareApplication) EndBlock(height uint64) []*types.Validator { +func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { app.endCount += 1 - return nil + return } func (app *ChainAwareApplication) InitChain(vals []*types.Validator) { diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index bad7c812..fd375470 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -16,10 +16,11 @@ func TestChainAware(t *testing.T) { app := NewChainAwareApplication() // Start the listener - _, err := server.NewServer("unix://test.sock", "socket", app) + srv, err := server.NewServer("unix://test.sock", "socket", app) if err != nil { t.Fatal(err) } + defer srv.Stop() // Connect to the socket client, err := tmspcli.NewSocketClient("unix://test.sock", false) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index eea7f4a8..f1287c9d 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -179,10 +179,10 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ t.Fatal(r) } } - diff2 := dummyChain.EndBlock(height) + resEndBlock := dummyChain.EndBlock(height) dummy.Commit() - valsEqual(t, diff, diff2) + valsEqual(t, diff, resEndBlock.Diffs) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index fc2b38cd..dc774ca3 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -113,8 +113,8 @@ func (app *PersistentDummyApplication) BeginBlock(hash []byte, header *types.Hea } // Update the validator set -func (app *PersistentDummyApplication) EndBlock(height uint64) (diffs []*types.Validator) { - return app.changes +func (app *PersistentDummyApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { + return types.ResponseEndBlock{Diffs: app.changes} } //----------------------------------------- diff --git a/server/socket_server.go b/server/socket_server.go index 43b4ed63..5a916ef4 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -168,7 +168,8 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Flush: responses <- types.ToResponseFlush() case *types.Request_Info: - responses <- types.ToResponseInfo(s.app.Info()) + resInfo := s.app.Info() + responses <- types.ToResponseInfo(resInfo) case *types.Request_SetOption: so := r.SetOption logStr := s.app.SetOption(so.Key, so.Value) @@ -197,10 +198,10 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types responses <- types.ToResponseBeginBlock() case *types.Request_EndBlock: if app, ok := s.app.(types.BlockchainAware); ok { - validators := app.EndBlock(r.EndBlock.Height) - responses <- types.ToResponseEndBlock(validators) + resEndBlock := app.EndBlock(r.EndBlock.Height) + responses <- types.ToResponseEndBlock(resEndBlock) } else { - responses <- types.ToResponseEndBlock(nil) + responses <- types.ToResponseEndBlock(types.ResponseEndBlock{}) } default: responses <- types.ToResponseException("Unknown request") diff --git a/types/application.go b/types/application.go index d124afd5..59b619e8 100644 --- a/types/application.go +++ b/types/application.go @@ -38,7 +38,7 @@ type BlockchainAware interface { // Signals the end of a block // diffs: changed validators from app to TendermintCore - EndBlock(height uint64) (diffs []*Validator) + EndBlock(height uint64) ResponseEndBlock } //------------------------------------ @@ -103,8 +103,8 @@ func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlo func (app *GRPCApplication) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { if chainAware, ok := app.app.(BlockchainAware); ok { - diffs := chainAware.EndBlock(req.Height) - return &ResponseEndBlock{diffs}, nil + resEndBlock := chainAware.EndBlock(req.Height) + return &resEndBlock, nil } return &ResponseEndBlock{}, nil } diff --git a/types/messages.go b/types/messages.go index afd4548e..428b05dc 100644 --- a/types/messages.go +++ b/types/messages.go @@ -142,9 +142,10 @@ func ToResponseBeginBlock() *Response { } } -func ToResponseEndBlock(validators []*Validator) *Response { +func ToResponseEndBlock(resEndBlock ResponseEndBlock) *Response { + resEndBlockCopy := resEndBlock return &Response{ - Value: &Response_EndBlock{&ResponseEndBlock{validators}}, + Value: &Response_EndBlock{&resEndBlockCopy}, } } From 490a96ef6697aa5ef3d170a8a88c0e0bd724ff2b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 12 Jan 2017 15:18:38 -0500 Subject: [PATCH 175/545] drop unneeded variable copy --- types/messages.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/types/messages.go b/types/messages.go index 428b05dc..2d256d8c 100644 --- a/types/messages.go +++ b/types/messages.go @@ -94,9 +94,8 @@ func ToResponseFlush() *Response { } func ToResponseInfo(resInfo ResponseInfo) *Response { - resInfoCopy := resInfo return &Response{ - Value: &Response_Info{&resInfoCopy}, + Value: &Response_Info{&resInfo}, } } @@ -143,9 +142,8 @@ func ToResponseBeginBlock() *Response { } func ToResponseEndBlock(resEndBlock ResponseEndBlock) *Response { - resEndBlockCopy := resEndBlock return &Response{ - Value: &Response_EndBlock{&resEndBlockCopy}, + Value: &Response_EndBlock{&resEndBlock}, } } From 80f377135b08c01deeed6d8b19eb896e5f159b96 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 12 Jan 2017 15:27:08 -0500 Subject: [PATCH 176/545] AppendTx -> DeliverTx --- README.md | 10 +- client/client.go | 4 +- client/grpc_client.go | 14 +-- client/local_client.go | 12 +-- client/socket_client.go | 14 +-- cmd/tmsp-cli/tmsp-cli.go | 12 +-- example/chain_aware/chain_aware_app.go | 2 +- example/counter/counter.go | 2 +- example/dummy/dummy.go | 2 +- example/dummy/dummy_test.go | 6 +- example/dummy/persistent_dummy.go | 4 +- example/example_test.go | 34 +++---- example/nil/nil_app.go | 2 +- example/python/app.py | 2 +- example/python/tmsp/msg.py | 4 +- example/python3/app.py | 2 +- example/python3/tmsp/msg.py | 4 +- server/socket_server.go | 6 +- tests/test_app/app.go | 8 +- tests/test_app/main.go | 16 ++-- tests/test_cli/ex1.tmsp | 4 +- tests/test_cli/ex1.tmsp.out | 4 +- tests/test_cli/ex2.tmsp | 6 +- tests/test_cli/ex2.tmsp.out | 6 +- types/application.go | 10 +- types/messages.go | 8 +- types/types.pb.go | 126 ++++++++++++------------- types/types.proto | 12 +-- 28 files changed, 168 insertions(+), 168 deletions(-) diff --git a/README.md b/README.md index b4af06f0..cb757695 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Note this prefixing does not apply for grpc. TMSP requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/tmsp/blob/master/types/types.proto). -#### AppendTx +#### DeliverTx * __Arguments__: * `Data ([]byte)`: The request transaction bytes * __Returns__: @@ -71,7 +71,7 @@ TMSP 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 AppendTx, but they happen on different connections - CheckTx from the mempool connection, and AppendTx 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 appendtxs, 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 stte 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`, @@ -122,7 +122,7 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil * __Arguments__: * `Height (uint64)`: The block height that is starting * __Usage__:
- Signals the beginning of a new block. Called prior to any AppendTxs. + Signals the beginning of a new block. Called prior to any DeliverTxs. #### EndBlock * __Arguments__: @@ -149,7 +149,7 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil ##### Jan 23th, 2016 * Added CheckTx/Query TMSP message types -* Added Result/Log fields to AppendTx/CheckTx/SetOption +* Added Result/Log fields to DeliverTx/CheckTx/SetOption * Removed Listener messages * Removed Code from ResponseSetOption and ResponseGetHash * Made examples BigEndian @@ -160,4 +160,4 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil ##### Jan 8th, 2016 -* Tendermint/TMSP now comes to consensus on the order first before AppendTx. +* Tendermint/TMSP now comes to consensus on the order first before DeliverTx. diff --git a/client/client.go b/client/client.go index c3c1e151..0305b29e 100644 --- a/client/client.go +++ b/client/client.go @@ -18,7 +18,7 @@ type Client interface { EchoAsync(msg string) *ReqRes InfoAsync() *ReqRes SetOptionAsync(key string, value string) *ReqRes - AppendTxAsync(tx []byte) *ReqRes + DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes QueryAsync(tx []byte) *ReqRes CommitAsync() *ReqRes @@ -27,7 +27,7 @@ type Client interface { EchoSync(msg string) (res types.Result) InfoSync() (resInfo types.ResponseInfo, err error) SetOptionSync(key string, value string) (res types.Result) - AppendTxSync(tx []byte) (res types.Result) + DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) QuerySync(tx []byte) (res types.Result) CommitSync() (res types.Result) diff --git a/client/grpc_client.go b/client/grpc_client.go index 15cda522..ac6beb06 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -155,13 +155,13 @@ func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_SetOption{res}}) } -func (cli *grpcClient) AppendTxAsync(tx []byte) *ReqRes { - req := types.ToRequestAppendTx(tx) - res, err := cli.client.AppendTx(context.Background(), req.GetAppendTx(), grpc.FailFast(true)) +func (cli *grpcClient) DeliverTxAsync(tx []byte) *ReqRes { + req := types.ToRequestDeliverTx(tx) + res, err := cli.client.DeliverTx(context.Background(), req.GetDeliverTx(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) } - return cli.finishAsyncCall(req, &types.Response{&types.Response_AppendTx{res}}) + return cli.finishAsyncCall(req, &types.Response{&types.Response_DeliverTx{res}}) } func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { @@ -283,12 +283,12 @@ func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result return types.Result{Code: OK, Data: nil, Log: resp.Log} } -func (cli *grpcClient) AppendTxSync(tx []byte) (res types.Result) { - reqres := cli.AppendTxAsync(tx) +func (cli *grpcClient) DeliverTxSync(tx []byte) (res types.Result) { + reqres := cli.DeliverTxAsync(tx) if res := cli.checkErrGetResult(); res.IsErr() { return res } - resp := reqres.Response.GetAppendTx() + resp := reqres.Response.GetDeliverTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } diff --git a/client/local_client.go b/client/local_client.go index ee5d6f28..9b0eeaf0 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -69,13 +69,13 @@ func (app *localClient) SetOptionAsync(key string, value string) *ReqRes { ) } -func (app *localClient) AppendTxAsync(tx []byte) *ReqRes { +func (app *localClient) DeliverTxAsync(tx []byte) *ReqRes { app.mtx.Lock() - res := app.Application.AppendTx(tx) + res := app.Application.DeliverTx(tx) app.mtx.Unlock() return app.callback( - types.ToRequestAppendTx(tx), - types.ToResponseAppendTx(res.Code, res.Data, res.Log), + types.ToRequestDeliverTx(tx), + types.ToResponseDeliverTx(res.Code, res.Data, res.Log), ) } @@ -171,9 +171,9 @@ func (app *localClient) SetOptionSync(key string, value string) (res types.Resul return types.OK.SetLog(log) } -func (app *localClient) AppendTxSync(tx []byte) (res types.Result) { +func (app *localClient) DeliverTxSync(tx []byte) (res types.Result) { app.mtx.Lock() - res = app.Application.AppendTx(tx) + res = app.Application.DeliverTx(tx) app.mtx.Unlock() return res } diff --git a/client/socket_client.go b/client/socket_client.go index aecaeea5..2a914f81 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -243,8 +243,8 @@ func (cli *socketClient) SetOptionAsync(key string, value string) *ReqRes { return cli.queueRequest(types.ToRequestSetOption(key, value)) } -func (cli *socketClient) AppendTxAsync(tx []byte) *ReqRes { - return cli.queueRequest(types.ToRequestAppendTx(tx)) +func (cli *socketClient) DeliverTxAsync(tx []byte) *ReqRes { + return cli.queueRequest(types.ToRequestDeliverTx(tx)) } func (cli *socketClient) CheckTxAsync(tx []byte) *ReqRes { @@ -315,13 +315,13 @@ func (cli *socketClient) SetOptionSync(key string, value string) (res types.Resu return types.Result{Code: OK, Data: nil, Log: resp.Log} } -func (cli *socketClient) AppendTxSync(tx []byte) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestAppendTx(tx)) +func (cli *socketClient) DeliverTxSync(tx []byte) (res types.Result) { + reqres := cli.queueRequest(types.ToRequestDeliverTx(tx)) cli.FlushSync() if err := cli.Error(); err != nil { return types.ErrInternalError.SetLog(err.Error()) } - resp := reqres.Response.GetAppendTx() + resp := reqres.Response.GetDeliverTx() return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } @@ -429,8 +429,8 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { _, ok = res.Value.(*types.Response_Info) case *types.Request_SetOption: _, ok = res.Value.(*types.Response_SetOption) - case *types.Request_AppendTx: - _, ok = res.Value.(*types.Response_AppendTx) + case *types.Request_DeliverTx: + _, ok = res.Value.(*types.Response_DeliverTx) case *types.Request_CheckTx: _, ok = res.Value.(*types.Response_CheckTx) case *types.Request_Commit: diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/tmsp-cli/tmsp-cli.go index 2bf5b862..b1d0d33e 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/tmsp-cli/tmsp-cli.go @@ -104,10 +104,10 @@ func main() { }, }, { - Name: "append_tx", - Usage: "Append a new tx to application", + Name: "deliver_tx", + Usage: "Deliver a new tx to application", Action: func(c *cli.Context) error { - return cmdAppendTx(c) + return cmdDeliverTx(c) }, }, { @@ -250,16 +250,16 @@ func cmdSetOption(c *cli.Context) error { } // Append a new tx to application -func cmdAppendTx(c *cli.Context) error { +func cmdDeliverTx(c *cli.Context) error { args := c.Args() if len(args) != 1 { - return errors.New("Command append_tx takes 1 argument") + return errors.New("Command deliver_tx takes 1 argument") } txBytes, err := stringOrHexToBytes(c.Args()[0]) if err != nil { return err } - res := client.AppendTxSync(txBytes) + res := client.DeliverTxSync(txBytes) rsp := newResponse(res, string(res.Data), true) printResponse(c, rsp) return nil diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index cd91c682..35774d66 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -45,7 +45,7 @@ func (app *ChainAwareApplication) SetOption(key string, value string) (log strin return "" } -func (app *ChainAwareApplication) AppendTx(tx []byte) types.Result { +func (app *ChainAwareApplication) DeliverTx(tx []byte) types.Result { return types.NewResultOK(nil, "") } diff --git a/example/counter/counter.go b/example/counter/counter.go index 221ddf04..663abcab 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -28,7 +28,7 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) return "" } -func (app *CounterApplication) AppendTx(tx []byte) types.Result { +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))) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index ca7bc525..7e0be585 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -28,7 +28,7 @@ func (app *DummyApplication) SetOption(key string, value string) (log string) { } // tx is either "key=value" or just arbitrary bytes -func (app *DummyApplication) AppendTx(tx []byte) types.Result { +func (app *DummyApplication) DeliverTx(tx []byte) types.Result { parts := strings.Split(string(tx), "=") if len(parts) == 2 { app.state.Set([]byte(parts[0]), []byte(parts[1])) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index f1287c9d..2f486aa5 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -13,10 +13,10 @@ import ( ) func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) { - if r := dummy.AppendTx(tx); r.IsErr() { + if r := dummy.DeliverTx(tx); r.IsErr() { t.Fatal(r) } - if r := dummy.AppendTx(tx); r.IsErr() { + if r := dummy.DeliverTx(tx); r.IsErr() { t.Fatal(r) } @@ -175,7 +175,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ dummyChain := dummy.(types.BlockchainAware) // hmm... dummyChain.BeginBlock(hash, header) for _, tx := range txs { - if r := dummy.AppendTx(tx); r.IsErr() { + if r := dummy.DeliverTx(tx); r.IsErr() { t.Fatal(r) } } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index dc774ca3..f4dbc6ee 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -59,7 +59,7 @@ func (app *PersistentDummyApplication) SetOption(key string, value string) (log } // tx is either "key=value" or just arbitrary bytes -func (app *PersistentDummyApplication) AppendTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { // if it starts with "val:", update the validator set // format is "val:pubkey/power" if isValidatorTx(tx) { @@ -69,7 +69,7 @@ func (app *PersistentDummyApplication) AppendTx(tx []byte) types.Result { } // otherwise, update the key-value store - return app.app.AppendTx(tx) + return app.app.DeliverTx(tx) } func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { diff --git a/example/example_test.go b/example/example_test.go index 3293be55..6ff334d3 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -35,7 +35,7 @@ func TestGRPC(t *testing.T) { func testStream(t *testing.T, app types.Application) { - numAppendTxs := 200000 + numDeliverTxs := 200000 // Start the listener server, err := server.NewSocketServer("unix://test.sock", app) @@ -57,15 +57,15 @@ func testStream(t *testing.T, app types.Application) { client.SetResponseCallback(func(req *types.Request, res *types.Response) { // Process response switch r := res.Value.(type) { - case *types.Response_AppendTx: + case *types.Response_DeliverTx: counter += 1 - if r.AppendTx.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", r.AppendTx.Code) + if r.DeliverTx.Code != types.CodeType_OK { + t.Error("DeliverTx failed with ret_code", r.DeliverTx.Code) } - if counter > numAppendTxs { - t.Fatalf("Too many AppendTx responses. Got %d, expected %d", counter, numAppendTxs) + if counter > numDeliverTxs { + t.Fatalf("Too many DeliverTx responses. Got %d, expected %d", counter, numDeliverTxs) } - if counter == numAppendTxs { + if counter == numDeliverTxs { go func() { time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow close(done) @@ -80,9 +80,9 @@ func testStream(t *testing.T, app types.Application) { }) // Write requests - for counter := 0; counter < numAppendTxs; counter++ { + for counter := 0; counter < numDeliverTxs; counter++ { // Send request - reqRes := client.AppendTxAsync([]byte("test")) + reqRes := client.DeliverTxAsync([]byte("test")) _ = reqRes // check err ? @@ -108,7 +108,7 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { func testGRPCSync(t *testing.T, app *types.GRPCApplication) { - numAppendTxs := 2000 + numDeliverTxs := 2000 // Start the listener server, err := server.NewGRPCServer("unix://test.sock", app) @@ -127,21 +127,21 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { client := types.NewTMSPApplicationClient(conn) // Write requests - for counter := 0; counter < numAppendTxs; counter++ { + for counter := 0; counter < numDeliverTxs; counter++ { // Send request - response, err := client.AppendTx(context.Background(), &types.RequestAppendTx{[]byte("test")}) + response, err := client.DeliverTx(context.Background(), &types.RequestDeliverTx{[]byte("test")}) if err != nil { - t.Fatalf("Error in GRPC AppendTx: %v", err.Error()) + t.Fatalf("Error in GRPC DeliverTx: %v", err.Error()) } counter += 1 if response.Code != types.CodeType_OK { - t.Error("AppendTx failed with ret_code", response.Code) + t.Error("DeliverTx failed with ret_code", response.Code) } - if counter > numAppendTxs { - t.Fatal("Too many AppendTx responses") + if counter > numDeliverTxs { + t.Fatal("Too many DeliverTx responses") } t.Log("response", counter) - if counter == numAppendTxs { + if counter == numDeliverTxs { go func() { time.Sleep(time.Second * 2) // Wait for a bit to allow counter overflow }() diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 7cc01c05..928395bc 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -19,7 +19,7 @@ func (app *NilApplication) SetOption(key string, value string) (log string) { return "" } -func (app *NilApplication) AppendTx(tx []byte) types.Result { +func (app *NilApplication) DeliverTx(tx []byte) types.Result { return types.NewResultOK(nil, "") } diff --git a/example/python/app.py b/example/python/app.py index b8cfcca8..335188fa 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -24,7 +24,7 @@ class CounterApplication(): self.serial = True return 0 - def append_tx(self, txBytes): + def deliver_tx(self, txBytes): if self.serial: txByteArray = bytearray(txBytes) if len(txBytes) >= 2 and txBytes[:2] == "0x": diff --git a/example/python/tmsp/msg.py b/example/python/tmsp/msg.py index a03c0a07..fcb85c1f 100644 --- a/example/python/tmsp/msg.py +++ b/example/python/tmsp/msg.py @@ -6,7 +6,7 @@ message_types = { 0x02: "flush", 0x03: "info", 0x04: "set_option", - 0x21: "append_tx", + 0x21: "deliver_tx", 0x22: "check_tx", 0x23: "commit", 0x24: "add_listener", @@ -32,7 +32,7 @@ class RequestDecoder(): def set_option(self): return decode_string(self.reader), decode_string(self.reader) - def append_tx(self): + def deliver_tx(self): return decode_string(self.reader) def check_tx(self): diff --git a/example/python3/app.py b/example/python3/app.py index c3d11490..a0b727b7 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -24,7 +24,7 @@ class CounterApplication(): self.serial = True return 0 - def append_tx(self, txBytes): + def deliver_tx(self, txBytes): if self.serial: txByteArray = bytearray(txBytes) if len(txBytes) >= 2 and txBytes[:2] == "0x": diff --git a/example/python3/tmsp/msg.py b/example/python3/tmsp/msg.py index ae30f88d..e8d69db9 100644 --- a/example/python3/tmsp/msg.py +++ b/example/python3/tmsp/msg.py @@ -6,7 +6,7 @@ message_types = { 0x02: "flush", 0x03: "info", 0x04: "set_option", - 0x21: "append_tx", + 0x21: "deliver_tx", 0x22: "check_tx", 0x23: "commit", 0x24: "add_listener", @@ -32,7 +32,7 @@ class RequestDecoder(): def set_option(self): return decode_string(self.reader), decode_string(self.reader) - def append_tx(self): + def deliver_tx(self): return decode_string(self.reader) def check_tx(self): diff --git a/server/socket_server.go b/server/socket_server.go index 5a916ef4..2be3bbb5 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -174,9 +174,9 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types so := r.SetOption logStr := s.app.SetOption(so.Key, so.Value) responses <- types.ToResponseSetOption(logStr) - case *types.Request_AppendTx: - res := s.app.AppendTx(r.AppendTx.Tx) - responses <- types.ToResponseAppendTx(res.Code, res.Data, res.Log) + case *types.Request_DeliverTx: + res := s.app.DeliverTx(r.DeliverTx.Tx) + responses <- types.ToResponseDeliverTx(res.Code, res.Data, res.Log) case *types.Request_CheckTx: res := s.app.CheckTx(r.CheckTx.Tx) responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 44e36eeb..b38d0737 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -62,15 +62,15 @@ func Commit(client tmspcli.Client, hashExp []byte) { } } -func AppendTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - res := client.AppendTxSync(txBytes) +func DeliverTx(client tmspcli.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("AppendTx response code was unexpected. Got %v expected %v. Log: %v", + panic(Fmt("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", code, codeExp, log)) } if !bytes.Equal(data, dataExp) { - panic(Fmt("AppendTx response data was unexpected. Got %X expected %X", + panic(Fmt("DeliverTx 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 ada63718..db627a3e 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -34,15 +34,15 @@ func testCounter() { SetOption(client, "serial", "on") Commit(client, nil) - AppendTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + DeliverTx(client, []byte("abc"), types.CodeType_BadNonce, nil) Commit(client, nil) - AppendTx(client, []byte{0x00}, types.CodeType_OK, nil) + DeliverTx(client, []byte{0x00}, types.CodeType_OK, nil) Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) - AppendTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) - AppendTx(client, []byte{0x01}, types.CodeType_OK, nil) - AppendTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) - AppendTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) - AppendTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) - AppendTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) + 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.tmsp b/tests/test_cli/ex1.tmsp index 13251267..e909266e 100644 --- a/tests/test_cli/ex1.tmsp +++ b/tests/test_cli/ex1.tmsp @@ -1,10 +1,10 @@ echo hello info commit -append_tx "abc" +deliver_tx "abc" info commit query "abc" -append_tx "def=xyz" +deliver_tx "def=xyz" commit query "def" diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.tmsp.out index 51cee99f..c8739758 100644 --- a/tests/test_cli/ex1.tmsp.out +++ b/tests/test_cli/ex1.tmsp.out @@ -7,7 +7,7 @@ > commit -> data: 0x -> append_tx "abc" +> deliver_tx "abc" -> code: OK > info @@ -20,7 +20,7 @@ -> code: OK -> data: {"index":0,"value":"abc","valueHex":"616263","exists":true} -> append_tx "def=xyz" +> deliver_tx "def=xyz" -> code: OK > commit diff --git a/tests/test_cli/ex2.tmsp b/tests/test_cli/ex2.tmsp index e9550db8..3b435f22 100644 --- a/tests/test_cli/ex2.tmsp +++ b/tests/test_cli/ex2.tmsp @@ -1,8 +1,8 @@ set_option serial on check_tx 0x00 check_tx 0xff -append_tx 0x00 +deliver_tx 0x00 check_tx 0x00 -append_tx 0x01 -append_tx 0x04 +deliver_tx 0x01 +deliver_tx 0x04 info diff --git a/tests/test_cli/ex2.tmsp.out b/tests/test_cli/ex2.tmsp.out index 84e4ad4f..1fab1e84 100644 --- a/tests/test_cli/ex2.tmsp.out +++ b/tests/test_cli/ex2.tmsp.out @@ -7,17 +7,17 @@ > check_tx 0xff -> code: OK -> append_tx 0x00 +> deliver_tx 0x00 -> code: OK > check_tx 0x00 -> code: BadNonce -> log: Invalid nonce. Expected >= 1, got 0 -> append_tx 0x01 +> deliver_tx 0x01 -> code: OK -> append_tx 0x04 +> deliver_tx 0x04 -> code: BadNonce -> log: Invalid nonce. Expected 2, got 4 diff --git a/types/application.go b/types/application.go index 59b619e8..4da5e6f7 100644 --- a/types/application.go +++ b/types/application.go @@ -13,8 +13,8 @@ type Application interface { // Set application option (e.g. mode=mempool, mode=consensus) SetOption(key string, value string) (log string) - // Append a tx - AppendTx(tx []byte) Result + // Deliver a tx + DeliverTx(tx []byte) Result // Validate a tx for the mempool CheckTx(tx []byte) Result @@ -67,9 +67,9 @@ func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption return &ResponseSetOption{app.app.SetOption(req.Key, req.Value)}, nil } -func (app *GRPCApplication) AppendTx(ctx context.Context, req *RequestAppendTx) (*ResponseAppendTx, error) { - r := app.app.AppendTx(req.Tx) - return &ResponseAppendTx{r.Code, r.Data, r.Log}, nil +func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { + r := app.app.DeliverTx(req.Tx) + return &ResponseDeliverTx{r.Code, r.Data, r.Log}, nil } func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { diff --git a/types/messages.go b/types/messages.go index 2d256d8c..84e6ee0b 100644 --- a/types/messages.go +++ b/types/messages.go @@ -31,9 +31,9 @@ func ToRequestSetOption(key string, value string) *Request { } } -func ToRequestAppendTx(txBytes []byte) *Request { +func ToRequestDeliverTx(txBytes []byte) *Request { return &Request{ - Value: &Request_AppendTx{&RequestAppendTx{txBytes}}, + Value: &Request_DeliverTx{&RequestDeliverTx{txBytes}}, } } @@ -105,9 +105,9 @@ func ToResponseSetOption(log string) *Response { } } -func ToResponseAppendTx(code CodeType, data []byte, log string) *Response { +func ToResponseDeliverTx(code CodeType, data []byte, log string) *Response { return &Response{ - Value: &Response_AppendTx{&ResponseAppendTx{code, data, log}}, + Value: &Response_DeliverTx{&ResponseDeliverTx{code, data, log}}, } } diff --git a/types/types.pb.go b/types/types.pb.go index c9781779..2c279bd2 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -14,7 +14,7 @@ It has these top-level messages: RequestFlush RequestInfo RequestSetOption - RequestAppendTx + RequestDeliverTx RequestCheckTx RequestQuery RequestCommit @@ -27,7 +27,7 @@ It has these top-level messages: ResponseFlush ResponseInfo ResponseSetOption - ResponseAppendTx + ResponseDeliverTx ResponseCheckTx ResponseQuery ResponseCommit @@ -74,7 +74,7 @@ const ( MessageType_Info MessageType = 3 MessageType_SetOption MessageType = 4 MessageType_Exception MessageType = 5 - MessageType_AppendTx MessageType = 17 + MessageType_DeliverTx MessageType = 17 MessageType_CheckTx MessageType = 18 MessageType_Commit MessageType = 19 MessageType_Query MessageType = 20 @@ -90,7 +90,7 @@ var MessageType_name = map[int32]string{ 3: "Info", 4: "SetOption", 5: "Exception", - 17: "AppendTx", + 17: "DeliverTx", 18: "CheckTx", 19: "Commit", 20: "Query", @@ -105,7 +105,7 @@ var MessageType_value = map[string]int32{ "Info": 3, "SetOption": 4, "Exception": 5, - "AppendTx": 17, + "DeliverTx": 17, "CheckTx": 18, "Commit": 19, "Query": 20, @@ -233,7 +233,7 @@ type Request struct { // *Request_Flush // *Request_Info // *Request_SetOption - // *Request_AppendTx + // *Request_DeliverTx // *Request_CheckTx // *Request_Commit // *Request_Query @@ -264,8 +264,8 @@ type Request_Info struct { type Request_SetOption struct { SetOption *RequestSetOption `protobuf:"bytes,4,opt,name=set_option,json=setOption,oneof"` } -type Request_AppendTx struct { - AppendTx *RequestAppendTx `protobuf:"bytes,5,opt,name=append_tx,json=appendTx,oneof"` +type Request_DeliverTx struct { + DeliverTx *RequestDeliverTx `protobuf:"bytes,5,opt,name=deliver_tx,json=deliverTx,oneof"` } type Request_CheckTx struct { CheckTx *RequestCheckTx `protobuf:"bytes,6,opt,name=check_tx,json=checkTx,oneof"` @@ -290,7 +290,7 @@ func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} func (*Request_Info) isRequest_Value() {} func (*Request_SetOption) isRequest_Value() {} -func (*Request_AppendTx) isRequest_Value() {} +func (*Request_DeliverTx) isRequest_Value() {} func (*Request_CheckTx) isRequest_Value() {} func (*Request_Commit) isRequest_Value() {} func (*Request_Query) isRequest_Value() {} @@ -333,9 +333,9 @@ func (m *Request) GetSetOption() *RequestSetOption { return nil } -func (m *Request) GetAppendTx() *RequestAppendTx { - if x, ok := m.GetValue().(*Request_AppendTx); ok { - return x.AppendTx +func (m *Request) GetDeliverTx() *RequestDeliverTx { + if x, ok := m.GetValue().(*Request_DeliverTx); ok { + return x.DeliverTx } return nil } @@ -389,7 +389,7 @@ func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error (*Request_Flush)(nil), (*Request_Info)(nil), (*Request_SetOption)(nil), - (*Request_AppendTx)(nil), + (*Request_DeliverTx)(nil), (*Request_CheckTx)(nil), (*Request_Commit)(nil), (*Request_Query)(nil), @@ -423,9 +423,9 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.SetOption); err != nil { return err } - case *Request_AppendTx: + case *Request_DeliverTx: b.EncodeVarint(5<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.AppendTx); err != nil { + if err := b.EncodeMessage(x.DeliverTx); err != nil { return err } case *Request_CheckTx: @@ -500,13 +500,13 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_SetOption{msg} return true, err - case 5: // value.append_tx + case 5: // value.deliver_tx if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } - msg := new(RequestAppendTx) + msg := new(RequestDeliverTx) err := b.DecodeMessage(msg) - m.Value = &Request_AppendTx{msg} + m.Value = &Request_DeliverTx{msg} return true, err case 6: // value.check_tx if wire != proto.WireBytes { @@ -585,8 +585,8 @@ func _Request_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(4<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Request_AppendTx: - s := proto.Size(x.AppendTx) + case *Request_DeliverTx: + s := proto.Size(x.DeliverTx) n += proto.SizeVarint(5<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s @@ -683,16 +683,16 @@ func (m *RequestSetOption) GetValue() string { return "" } -type RequestAppendTx struct { +type RequestDeliverTx struct { Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` } -func (m *RequestAppendTx) Reset() { *m = RequestAppendTx{} } -func (m *RequestAppendTx) String() string { return proto.CompactTextString(m) } -func (*RequestAppendTx) ProtoMessage() {} -func (*RequestAppendTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } +func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } +func (*RequestDeliverTx) ProtoMessage() {} +func (*RequestDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } -func (m *RequestAppendTx) GetTx() []byte { +func (m *RequestDeliverTx) GetTx() []byte { if m != nil { return m.Tx } @@ -802,7 +802,7 @@ type Response struct { // *Response_Flush // *Response_Info // *Response_SetOption - // *Response_AppendTx + // *Response_DeliverTx // *Response_CheckTx // *Response_Commit // *Response_Query @@ -836,8 +836,8 @@ type Response_Info struct { type Response_SetOption struct { SetOption *ResponseSetOption `protobuf:"bytes,5,opt,name=set_option,json=setOption,oneof"` } -type Response_AppendTx struct { - AppendTx *ResponseAppendTx `protobuf:"bytes,6,opt,name=append_tx,json=appendTx,oneof"` +type Response_DeliverTx struct { + DeliverTx *ResponseDeliverTx `protobuf:"bytes,6,opt,name=deliver_tx,json=deliverTx,oneof"` } type Response_CheckTx struct { CheckTx *ResponseCheckTx `protobuf:"bytes,7,opt,name=check_tx,json=checkTx,oneof"` @@ -863,7 +863,7 @@ func (*Response_Echo) isResponse_Value() {} func (*Response_Flush) isResponse_Value() {} func (*Response_Info) isResponse_Value() {} func (*Response_SetOption) isResponse_Value() {} -func (*Response_AppendTx) isResponse_Value() {} +func (*Response_DeliverTx) isResponse_Value() {} func (*Response_CheckTx) isResponse_Value() {} func (*Response_Commit) isResponse_Value() {} func (*Response_Query) isResponse_Value() {} @@ -913,9 +913,9 @@ func (m *Response) GetSetOption() *ResponseSetOption { return nil } -func (m *Response) GetAppendTx() *ResponseAppendTx { - if x, ok := m.GetValue().(*Response_AppendTx); ok { - return x.AppendTx +func (m *Response) GetDeliverTx() *ResponseDeliverTx { + if x, ok := m.GetValue().(*Response_DeliverTx); ok { + return x.DeliverTx } return nil } @@ -970,7 +970,7 @@ func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) erro (*Response_Flush)(nil), (*Response_Info)(nil), (*Response_SetOption)(nil), - (*Response_AppendTx)(nil), + (*Response_DeliverTx)(nil), (*Response_CheckTx)(nil), (*Response_Commit)(nil), (*Response_Query)(nil), @@ -1009,9 +1009,9 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.SetOption); err != nil { return err } - case *Response_AppendTx: + case *Response_DeliverTx: b.EncodeVarint(6<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.AppendTx); err != nil { + if err := b.EncodeMessage(x.DeliverTx); err != nil { return err } case *Response_CheckTx: @@ -1094,13 +1094,13 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_SetOption{msg} return true, err - case 6: // value.append_tx + case 6: // value.deliver_tx if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } - msg := new(ResponseAppendTx) + msg := new(ResponseDeliverTx) err := b.DecodeMessage(msg) - m.Value = &Response_AppendTx{msg} + m.Value = &Response_DeliverTx{msg} return true, err case 7: // value.check_tx if wire != proto.WireBytes { @@ -1184,8 +1184,8 @@ func _Response_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(5<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Response_AppendTx: - s := proto.Size(x.AppendTx) + case *Response_DeliverTx: + s := proto.Size(x.DeliverTx) n += proto.SizeVarint(6<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s @@ -1322,32 +1322,32 @@ func (m *ResponseSetOption) GetLog() string { return "" } -type ResponseAppendTx struct { +type ResponseDeliverTx struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` } -func (m *ResponseAppendTx) Reset() { *m = ResponseAppendTx{} } -func (m *ResponseAppendTx) String() string { return proto.CompactTextString(m) } -func (*ResponseAppendTx) ProtoMessage() {} -func (*ResponseAppendTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } +func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } +func (*ResponseDeliverTx) ProtoMessage() {} +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } -func (m *ResponseAppendTx) GetCode() CodeType { +func (m *ResponseDeliverTx) GetCode() CodeType { if m != nil { return m.Code } return CodeType_OK } -func (m *ResponseAppendTx) GetData() []byte { +func (m *ResponseDeliverTx) GetData() []byte { if m != nil { return m.Data } return nil } -func (m *ResponseAppendTx) GetLog() string { +func (m *ResponseDeliverTx) GetLog() string { if m != nil { return m.Log } @@ -1640,7 +1640,7 @@ func init() { proto.RegisterType((*RequestFlush)(nil), "types.RequestFlush") proto.RegisterType((*RequestInfo)(nil), "types.RequestInfo") proto.RegisterType((*RequestSetOption)(nil), "types.RequestSetOption") - proto.RegisterType((*RequestAppendTx)(nil), "types.RequestAppendTx") + proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") @@ -1653,7 +1653,7 @@ func init() { proto.RegisterType((*ResponseFlush)(nil), "types.ResponseFlush") proto.RegisterType((*ResponseInfo)(nil), "types.ResponseInfo") proto.RegisterType((*ResponseSetOption)(nil), "types.ResponseSetOption") - proto.RegisterType((*ResponseAppendTx)(nil), "types.ResponseAppendTx") + proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") @@ -1683,7 +1683,7 @@ type TMSPApplicationClient interface { Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) - AppendTx(ctx context.Context, in *RequestAppendTx, opts ...grpc.CallOption) (*ResponseAppendTx, error) + DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) @@ -1736,9 +1736,9 @@ func (c *tMSPApplicationClient) SetOption(ctx context.Context, in *RequestSetOpt return out, nil } -func (c *tMSPApplicationClient) AppendTx(ctx context.Context, in *RequestAppendTx, opts ...grpc.CallOption) (*ResponseAppendTx, error) { - out := new(ResponseAppendTx) - err := grpc.Invoke(ctx, "/types.TMSPApplication/AppendTx", in, out, c.cc, opts...) +func (c *tMSPApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { + out := new(ResponseDeliverTx) + err := grpc.Invoke(ctx, "/types.TMSPApplication/DeliverTx", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1806,7 +1806,7 @@ type TMSPApplicationServer interface { Flush(context.Context, *RequestFlush) (*ResponseFlush, error) Info(context.Context, *RequestInfo) (*ResponseInfo, error) SetOption(context.Context, *RequestSetOption) (*ResponseSetOption, error) - AppendTx(context.Context, *RequestAppendTx) (*ResponseAppendTx, error) + DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) Query(context.Context, *RequestQuery) (*ResponseQuery, error) Commit(context.Context, *RequestCommit) (*ResponseCommit, error) @@ -1891,20 +1891,20 @@ func _TMSPApplication_SetOption_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } -func _TMSPApplication_AppendTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestAppendTx) +func _TMSPApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestDeliverTx) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).AppendTx(ctx, in) + return srv.(TMSPApplicationServer).DeliverTx(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/AppendTx", + FullMethod: "/types.TMSPApplication/DeliverTx", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).AppendTx(ctx, req.(*RequestAppendTx)) + return srv.(TMSPApplicationServer).DeliverTx(ctx, req.(*RequestDeliverTx)) } return interceptor(ctx, in, info, handler) } @@ -2038,8 +2038,8 @@ var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ Handler: _TMSPApplication_SetOption_Handler, }, { - MethodName: "AppendTx", - Handler: _TMSPApplication_AppendTx_Handler, + MethodName: "DeliverTx", + Handler: _TMSPApplication_DeliverTx_Handler, }, { MethodName: "CheckTx", diff --git a/types/types.proto b/types/types.proto index 69f9a573..34e5450b 100644 --- a/types/types.proto +++ b/types/types.proto @@ -18,7 +18,7 @@ enum MessageType { Info = 0x03; SetOption = 0x04; Exception = 0x05; - AppendTx = 0x11; + DeliverTx = 0x11; CheckTx = 0x12; Commit = 0x13; Query = 0x14; @@ -79,7 +79,7 @@ message Request { RequestFlush flush = 2; RequestInfo info = 3; RequestSetOption set_option = 4; - RequestAppendTx append_tx = 5; + RequestDeliverTx deliver_tx = 5; RequestCheckTx check_tx = 6; RequestCommit commit = 7; RequestQuery query = 8; @@ -104,7 +104,7 @@ message RequestSetOption{ string value = 2; } -message RequestAppendTx{ +message RequestDeliverTx{ bytes tx = 1; } @@ -143,7 +143,7 @@ message Response { ResponseFlush flush = 3; ResponseInfo info = 4; ResponseSetOption set_option = 5; - ResponseAppendTx append_tx = 6; + ResponseDeliverTx deliver_tx = 6; ResponseCheckTx check_tx = 7; ResponseCommit commit = 8; ResponseQuery query = 9; @@ -175,7 +175,7 @@ message ResponseSetOption{ string log = 1; } -message ResponseAppendTx{ +message ResponseDeliverTx{ CodeType code = 1; bytes data = 2; string log = 3; @@ -248,7 +248,7 @@ service TMSPApplication { rpc Flush(RequestFlush) returns (ResponseFlush); rpc Info(RequestInfo) returns (ResponseInfo); rpc SetOption(RequestSetOption) returns (ResponseSetOption); - rpc AppendTx(RequestAppendTx) returns (ResponseAppendTx); + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); rpc Query(RequestQuery) returns (ResponseQuery); rpc Commit(RequestCommit) returns (ResponseCommit); From 5189a2248d5b4d952a40fc72a14c510af3aa10dc Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 12 Jan 2017 15:47:55 -0500 Subject: [PATCH 177/545] TMSP -> ABCI --- LICENSE | 2 +- Makefile | 4 +- README.md | 32 ++-- client/client.go | 6 +- client/grpc_client.go | 12 +- client/local_client.go | 4 +- client/log.go | 4 +- client/socket_client.go | 8 +- cmd/{tmsp-cli => abci-cli}/tmsp-cli.go | 18 +-- cmd/counter/main.go | 8 +- cmd/dummy/main.go | 10 +- example/chain_aware/chain_aware_app.go | 8 +- example/chain_aware/chain_aware_test.go | 8 +- example/counter/counter.go | 2 +- example/dummy/README.md | 2 +- example/dummy/dummy.go | 2 +- example/dummy/dummy_test.go | 8 +- example/dummy/persistent_dummy.go | 2 +- example/example_test.go | 14 +- example/js/README.md | 2 +- example/nil/nil_app.go | 2 +- example/python/{tmsp => abci}/__init__.py | 0 example/python/{tmsp => abci}/msg.py | 2 +- example/python/{tmsp => abci}/reader.py | 0 example/python/{tmsp => abci}/server.py | 4 +- example/python/{tmsp => abci}/wire.py | 0 example/python/app.py | 10 +- example/python3/{tmsp => abci}/__init__.py | 0 example/python3/{tmsp => abci}/msg.py | 2 +- example/python3/{tmsp => abci}/reader.py | 0 example/python3/{tmsp => abci}/server.py | 4 +- example/python3/{tmsp => abci}/wire.py | 0 example/python3/app.py | 10 +- glide.yaml | 2 +- server/grpc_server.go | 10 +- server/log.go | 2 +- server/server.go | 2 +- server/socket_server.go | 4 +- tests/benchmarks/parallel/parallel.go | 2 +- tests/benchmarks/simple/simple.go | 2 +- tests/test_app/app.go | 26 +-- tests/test_app/main.go | 22 +-- tests/test_app/test.sh | 10 +- tests/test_cli/{ex1.tmsp => ex1.abci} | 0 tests/test_cli/{ex1.tmsp.out => ex1.abci.out} | 0 tests/test_cli/{ex2.tmsp => ex2.abci} | 0 tests/test_cli/{ex2.tmsp.out => ex2.abci.out} | 0 tests/test_cli/test.sh | 8 +- testutil/messages.go | 2 +- types/result.go | 2 +- types/types.pb.go | 152 +++++++++--------- types/types.proto | 4 +- 52 files changed, 221 insertions(+), 219 deletions(-) rename cmd/{tmsp-cli => abci-cli}/tmsp-cli.go (95%) rename example/python/{tmsp => abci}/__init__.py (100%) rename example/python/{tmsp => abci}/msg.py (94%) rename example/python/{tmsp => abci}/reader.py (100%) rename example/python/{tmsp => abci}/server.py (98%) rename example/python/{tmsp => abci}/wire.py (100%) rename example/python3/{tmsp => abci}/__init__.py (100%) rename example/python3/{tmsp => abci}/msg.py (94%) rename example/python3/{tmsp => abci}/reader.py (100%) rename example/python3/{tmsp => abci}/server.py (98%) rename example/python3/{tmsp => abci}/wire.py (100%) rename tests/test_cli/{ex1.tmsp => ex1.abci} (100%) rename tests/test_cli/{ex1.tmsp.out => ex1.abci.out} (100%) rename tests/test_cli/{ex2.tmsp => ex2.abci} (100%) rename tests/test_cli/{ex2.tmsp.out => ex2.abci.out} (100%) diff --git a/LICENSE b/LICENSE index 3934a10f..57951bb8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Tendermint TMSP +Tendermint ABCI Copyright (C) 2015 Tendermint diff --git a/Makefile b/Makefile index b00c5a67..22fa6fdd 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,13 @@ all: protoc test install -NOVENDOR = go list github.com/tendermint/tmsp/... | grep -v /vendor/ +NOVENDOR = go list github.com/tendermint/abci/... | grep -v /vendor/ protoc: protoc --go_out=plugins=grpc:. types/*.proto install: - go install github.com/tendermint/tmsp/cmd/... + go install github.com/tendermint/abci/cmd/... test: go test `${NOVENDOR}` diff --git a/README.md b/README.md index cb757695..8672af92 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,37 @@ -# Tendermint Socket Protocol (TMSP) +# Tendermint Socket Protocol (ABCI) -[![CircleCI](https://circleci.com/gh/tendermint/tmsp.svg?style=svg)](https://circleci.com/gh/tendermint/tmsp) +[![CircleCI](https://circleci.com/gh/tendermint/abci.svg?style=svg)](https://circleci.com/gh/tendermint/abci) Blockchains are a system for creating shared multi-master application state. -**TMSP** is a socket protocol enabling a blockchain consensus engine, running in one process, +**ABCI** is a socket protocol enabling a blockchain consensus engine, running in one process, to manage a blockchain application state, running in another. -For more information on TMSP, motivations, and tutorials, please visit [our blog post](http://tendermint.com/blog/tmsp-the-tendermint-socket-protocol/). +For more information on ABCI, motivations, and tutorials, please visit [our blog post](http://tendermint.com/blog/abci-the-tendermint-socket-protocol/). Other implementations: -* [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen -* [js-tmsp](https://github.com/tendermint/js-tmsp) -* [jTMSP](https://github.com/jTMSP/) for Java +* [cpp-abci](https://github.com/mdyring/cpp-abci) by Martin Dyring-Andersen +* [js-abci](https://github.com/tendermint/js-abci) +* [jABCI](https://github.com/jABCI/) for Java ## Contents This repository holds a number of important pieces: - `types/types.proto` - - the protobuf file defining TMSP message types, and the optional grpc interface. + - 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 -- golang implementation of TMSP client and server +- golang implementation of ABCI client and server - two implementations: - asynchronous, ordered message passing over unix or tcp; - messages are serialized using protobuf and length prefixed - grpc - TendermintCore runs a client, and the application runs a server -- `cmd/tmsp-cli` - - command line tool wrapping the client for probing/testing a TMSP application - - use `tmsp-cli --version` to get the TMSP version +- `cmd/abci-cli` + - command line tool wrapping the client for probing/testing a ABCI application + - use `abci-cli --version` to get the ABCI version - examples: - the `cmd/counter` application, which illustrates nonce checking in txs @@ -42,13 +42,13 @@ This repository holds a number of important pieces: Since this is a streaming protocol, all messages are encoded with a length-prefix followed by the message encoded in Protobuf3. Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. -For example, if the Protobuf3 encoded TMSP message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded TMSP message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. +For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. Note this prefixing does not apply for grpc. ## Message types -TMSP requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/tmsp/blob/master/types/types.proto). +ABCI requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/abci/blob/master/types/types.proto). #### DeliverTx * __Arguments__: @@ -148,7 +148,7 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil ##### Jan 23th, 2016 -* Added CheckTx/Query TMSP message types +* Added CheckTx/Query ABCI message types * Added Result/Log fields to DeliverTx/CheckTx/SetOption * Removed Listener messages * Removed Code from ResponseSetOption and ResponseGetHash @@ -160,4 +160,4 @@ TMSP requests/responses are simple Protobuf messages. Check out the [schema fil ##### Jan 8th, 2016 -* Tendermint/TMSP now comes to consensus on the order first before DeliverTx. +* Tendermint/ABCI now comes to consensus on the order first before DeliverTx. diff --git a/client/client.go b/client/client.go index 0305b29e..8ea29593 100644 --- a/client/client.go +++ b/client/client.go @@ -1,11 +1,11 @@ -package tmspcli +package abcicli import ( "fmt" "sync" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) type Client interface { @@ -50,7 +50,7 @@ func NewClient(addr, transport string, mustConnect bool) (client Client, err err case "grpc": client, err = NewGRPCClient(addr, mustConnect) default: - err = fmt.Errorf("Unknown tmsp transport %s", transport) + err = fmt.Errorf("Unknown abci transport %s", transport) } return diff --git a/client/grpc_client.go b/client/grpc_client.go index ac6beb06..566ee183 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -1,4 +1,4 @@ -package tmspcli +package abcicli import ( "net" @@ -9,7 +9,7 @@ import ( grpc "google.golang.org/grpc" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) // A stripped copy of the remoteClient that makes @@ -18,7 +18,7 @@ type grpcClient struct { BaseService mustConnect bool - client types.TMSPApplicationClient + client types.ABCIApplicationClient mtx sync.Mutex addr string @@ -50,13 +50,13 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - log.Warn(Fmt("tmsp.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) + log.Warn(Fmt("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } } - client := types.NewTMSPApplicationClient(conn) + client := types.NewABCIApplicationClient(conn) ENSURE_CONNECTED: for { @@ -93,7 +93,7 @@ func (cli *grpcClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(Fmt("Stopping tmsp.grpcClient for error: %v", err.Error())) + log.Warn(Fmt("Stopping abci.grpcClient for error: %v", err.Error())) cli.Stop() } diff --git a/client/local_client.go b/client/local_client.go index 9b0eeaf0..b787eb36 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -1,10 +1,10 @@ -package tmspcli +package abcicli import ( "sync" . "github.com/tendermint/go-common" - types "github.com/tendermint/tmsp/types" + types "github.com/tendermint/abci/types" ) type localClient struct { diff --git a/client/log.go b/client/log.go index deadf6c3..944b05ba 100644 --- a/client/log.go +++ b/client/log.go @@ -1,7 +1,7 @@ -package tmspcli +package abcicli import ( "github.com/tendermint/go-logger" ) -var log = logger.New("module", "tmspcli") +var log = logger.New("module", "abcicli") diff --git a/client/socket_client.go b/client/socket_client.go index 2a914f81..9b4f9aed 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -1,4 +1,4 @@ -package tmspcli +package abcicli import ( "bufio" @@ -11,7 +11,7 @@ import ( "time" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) const ( @@ -70,7 +70,7 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - log.Warn(Fmt("tmsp.socketClient failed to connect to %v. Retrying...", cli.addr)) + log.Warn(Fmt("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -109,7 +109,7 @@ func (cli *socketClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(Fmt("Stopping tmsp.socketClient for error: %v", err.Error())) + log.Warn(Fmt("Stopping abci.socketClient for error: %v", err.Error())) cli.Stop() } diff --git a/cmd/tmsp-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go similarity index 95% rename from cmd/tmsp-cli/tmsp-cli.go rename to cmd/abci-cli/tmsp-cli.go index b1d0d33e..b8bc2937 100644 --- a/cmd/tmsp-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -10,8 +10,8 @@ import ( "strings" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/client" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/client" + "github.com/tendermint/abci/types" "github.com/urfave/cli" ) @@ -40,7 +40,7 @@ func newResponse(res types.Result, data string, printCode bool) *response { } // client is a global variable so it can be reused by the console -var client tmspcli.Client +var client abcicli.Client func main() { @@ -48,8 +48,8 @@ func main() { cli.OsExiter = func(_ int) {} app := cli.NewApp() - app.Name = "tmsp-cli" - app.Usage = "tmsp-cli [command] [args...]" + app.Name = "abci-cli" + app.Usage = "abci-cli [command] [args...]" app.Version = "0.2.1" // better error handling in console app.Flags = []cli.Flag{ cli.StringFlag{ @@ -58,7 +58,7 @@ func main() { Usage: "address of application socket", }, cli.StringFlag{ - Name: "tmsp", + Name: "abci", Value: "socket", Usage: "socket or grpc", }, @@ -70,14 +70,14 @@ func main() { app.Commands = []cli.Command{ { Name: "batch", - Usage: "Run a batch of tmsp commands against an application", + Usage: "Run a batch of abci commands against an application", Action: func(c *cli.Context) error { return cmdBatch(app, c) }, }, { Name: "console", - Usage: "Start an interactive tmsp console for multiple commands", + Usage: "Start an interactive abci console for multiple commands", Action: func(c *cli.Context) error { return cmdConsole(app, c) }, @@ -143,7 +143,7 @@ func main() { func before(c *cli.Context) error { if client == nil { var err error - client, err = tmspcli.NewClient(c.GlobalString("address"), c.GlobalString("tmsp"), false) + client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) if err != nil { Exit(err.Error()) } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 0f284af9..218224a0 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -4,20 +4,20 @@ import ( "flag" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/example/counter" - "github.com/tendermint/tmsp/server" + "github.com/tendermint/abci/example/counter" + "github.com/tendermint/abci/server" ) func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - tmspPtr := flag.String("tmsp", "socket", "TMSP server: socket | grpc") + abciPtr := flag.String("abci", "socket", "ABCI server: socket | grpc") serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") flag.Parse() app := counter.NewCounterApplication(*serialPtr) // Start the listener - srv, err := server.NewServer(*addrPtr, *tmspPtr, app) + srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { Exit(err.Error()) } diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index fe7ae750..aecb1138 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -4,15 +4,15 @@ import ( "flag" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/example/dummy" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/example/dummy" + "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" ) func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - tmspPtr := flag.String("tmsp", "socket", "socket | grpc") + abciPtr := flag.String("abci", "socket", "socket | grpc") persistencePtr := flag.String("persist", "", "directory to use for a database") flag.Parse() @@ -25,7 +25,7 @@ func main() { } // Start the listener - srv, err := server.NewServer(*addrPtr, *tmspPtr, app) + srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { Exit(err.Error()) } diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 35774d66..e3543f13 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -4,18 +4,18 @@ import ( "flag" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" ) func main() { addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - tmspPtr := flag.String("tmsp", "socket", "socket | grpc") + abciPtr := flag.String("abci", "socket", "socket | grpc") flag.Parse() // Start the listener - srv, err := server.NewServer(*addrPtr, *tmspPtr, NewChainAwareApplication()) + srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) if err != nil { Exit(err.Error()) } diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index fd375470..f5283a38 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -6,9 +6,9 @@ import ( "testing" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/client" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/client" + "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" ) func TestChainAware(t *testing.T) { @@ -23,7 +23,7 @@ func TestChainAware(t *testing.T) { defer srv.Stop() // Connect to the socket - client, err := tmspcli.NewSocketClient("unix://test.sock", false) + client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { Exit(Fmt("Error starting socket client: %v", err.Error())) } diff --git a/example/counter/counter.go b/example/counter/counter.go index 663abcab..90be6d92 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -4,7 +4,7 @@ import ( "encoding/binary" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) type CounterApplication struct { diff --git a/example/dummy/README.md b/example/dummy/README.md index 19f82fda..8c1f0f04 100644 --- a/example/dummy/README.md +++ b/example/dummy/README.md @@ -14,7 +14,7 @@ The app has no replay protection (other than what the mempool provides). The PersistentDummyApplication wraps the DummyApplication and provides two additional features: -1) persistence of state across app restarts (using Tendermint's TMSP-Handshake mechanism) +1) persistence of state across app restarts (using Tendermint's ABCI-Handshake mechanism) 2) validator set changes The state is persisted in leveldb along with the last block committed, diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 7e0be585..648ef07e 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -7,7 +7,7 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) type DummyApplication struct { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 2f486aa5..d2294347 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -9,7 +9,7 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) { @@ -49,7 +49,7 @@ func TestDummyKV(t *testing.T) { } func TestPersistentDummyKV(t *testing.T) { - dir, err := ioutil.TempDir("/tmp", "tmsp-dummy-test") // TODO + dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO if err != nil { t.Fatal(err) } @@ -65,7 +65,7 @@ func TestPersistentDummyKV(t *testing.T) { } func TestPersistentDummyInfo(t *testing.T) { - dir, err := ioutil.TempDir("/tmp", "tmsp-dummy-test") // TODO + dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO if err != nil { t.Fatal(err) } @@ -96,7 +96,7 @@ func TestPersistentDummyInfo(t *testing.T) { // add a validator, remove a validator, update a validator func TestValSetChanges(t *testing.T) { - dir, err := ioutil.TempDir("/tmp", "tmsp-dummy-test") // TODO + dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO if err != nil { t.Fatal(err) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index f4dbc6ee..fa730bcb 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -10,7 +10,7 @@ import ( dbm "github.com/tendermint/go-db" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) const ( diff --git a/example/example_test.go b/example/example_test.go index 6ff334d3..1ddefddb 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -11,11 +11,11 @@ import ( "google.golang.org/grpc" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/client" - "github.com/tendermint/tmsp/example/dummy" - nilapp "github.com/tendermint/tmsp/example/nil" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" + "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" ) func TestDummy(t *testing.T) { @@ -45,7 +45,7 @@ func testStream(t *testing.T, app types.Application) { defer server.Stop() // Connect to the socket - client, err := tmspcli.NewSocketClient("unix://test.sock", false) + client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { Exit(Fmt("Error starting socket client: %v", err.Error())) } @@ -124,7 +124,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { } defer conn.Close() - client := types.NewTMSPApplicationClient(conn) + client := types.NewABCIApplicationClient(conn) // Write requests for counter := 0; counter < numDeliverTxs; counter++ { diff --git a/example/js/README.md b/example/js/README.md index f1875506..1bef9cbf 100644 --- a/example/js/README.md +++ b/example/js/README.md @@ -1 +1 @@ -This example has been moved here: https://github.com/tendermint/js-tmsp/tree/master/example +This example has been moved here: https://github.com/tendermint/js-abci/tree/master/example diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 928395bc..cd57f0d9 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -1,7 +1,7 @@ package nilapp import ( - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) type NilApplication struct { diff --git a/example/python/tmsp/__init__.py b/example/python/abci/__init__.py similarity index 100% rename from example/python/tmsp/__init__.py rename to example/python/abci/__init__.py diff --git a/example/python/tmsp/msg.py b/example/python/abci/msg.py similarity index 94% rename from example/python/tmsp/msg.py rename to example/python/abci/msg.py index fcb85c1f..7329f585 100644 --- a/example/python/tmsp/msg.py +++ b/example/python/abci/msg.py @@ -13,7 +13,7 @@ message_types = { 0x25: "rm_listener", } -# return the decoded arguments of tmsp messages +# return the decoded arguments of abci messages class RequestDecoder(): diff --git a/example/python/tmsp/reader.py b/example/python/abci/reader.py similarity index 100% rename from example/python/tmsp/reader.py rename to example/python/abci/reader.py diff --git a/example/python/tmsp/server.py b/example/python/abci/server.py similarity index 98% rename from example/python/tmsp/server.py rename to example/python/abci/server.py index 60f76e3a..40d50896 100644 --- a/example/python/tmsp/server.py +++ b/example/python/abci/server.py @@ -26,9 +26,9 @@ class Connection(): raise IOError("dead connection") this.recBuf.write(data) -# TMSP server responds to messges by calling methods on the app +# ABCI server responds to messges by calling methods on the app -class TMSPServer(): +class ABCIServer(): def __init__(self, app, port=5410): self.app = app diff --git a/example/python/tmsp/wire.py b/example/python/abci/wire.py similarity index 100% rename from example/python/tmsp/wire.py rename to example/python/abci/wire.py diff --git a/example/python/app.py b/example/python/app.py index 335188fa..a44ff345 100644 --- a/example/python/app.py +++ b/example/python/app.py @@ -1,8 +1,8 @@ import sys -from tmsp.wire import hex2bytes, decode_big_endian, encode_big_endian -from tmsp.server import TMSPServer -from tmsp.reader import BytesBuffer +from abci.wire import hex2bytes, decode_big_endian, encode_big_endian +from abci.server import ABCIServer +from abci.reader import BytesBuffer class CounterApplication(): @@ -75,8 +75,8 @@ if __name__ == '__main__': print "too many arguments" quit() - print 'TMSP Demo APP (Python)' + print 'ABCI Demo APP (Python)' app = CounterApplication() - server = TMSPServer(app, port) + server = ABCIServer(app, port) server.main_loop() diff --git a/example/python3/tmsp/__init__.py b/example/python3/abci/__init__.py similarity index 100% rename from example/python3/tmsp/__init__.py rename to example/python3/abci/__init__.py diff --git a/example/python3/tmsp/msg.py b/example/python3/abci/msg.py similarity index 94% rename from example/python3/tmsp/msg.py rename to example/python3/abci/msg.py index e8d69db9..807c4b6b 100644 --- a/example/python3/tmsp/msg.py +++ b/example/python3/abci/msg.py @@ -13,7 +13,7 @@ message_types = { 0x25: "rm_listener", } -# return the decoded arguments of tmsp messages +# return the decoded arguments of abci messages class RequestDecoder(): diff --git a/example/python3/tmsp/reader.py b/example/python3/abci/reader.py similarity index 100% rename from example/python3/tmsp/reader.py rename to example/python3/abci/reader.py diff --git a/example/python3/tmsp/server.py b/example/python3/abci/server.py similarity index 98% rename from example/python3/tmsp/server.py rename to example/python3/abci/server.py index 03735bb3..04063262 100644 --- a/example/python3/tmsp/server.py +++ b/example/python3/abci/server.py @@ -29,9 +29,9 @@ class Connection(): raise IOError("dead connection") this.recBuf.write(data) -# TMSP server responds to messges by calling methods on the app +# ABCI server responds to messges by calling methods on the app -class TMSPServer(): +class ABCIServer(): def __init__(self, app, port=5410): self.app = app diff --git a/example/python3/tmsp/wire.py b/example/python3/abci/wire.py similarity index 100% rename from example/python3/tmsp/wire.py rename to example/python3/abci/wire.py diff --git a/example/python3/app.py b/example/python3/app.py index a0b727b7..b40041a4 100644 --- a/example/python3/app.py +++ b/example/python3/app.py @@ -1,8 +1,8 @@ import sys -from tmsp.wire import hex2bytes, decode_big_endian, encode_big_endian -from tmsp.server import TMSPServer -from tmsp.reader import BytesBuffer +from abci.wire import hex2bytes, decode_big_endian, encode_big_endian +from abci.server import ABCIServer +from abci.reader import BytesBuffer class CounterApplication(): @@ -75,8 +75,8 @@ if __name__ == '__main__': print("too many arguments") quit() - print('TMSP Demo APP (Python)') + print('ABCI Demo APP (Python)') app = CounterApplication() - server = TMSPServer(app, port) + server = ABCIServer(app, port) server.main_loop() diff --git a/glide.yaml b/glide.yaml index 440d47cc..fae5a984 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,4 +1,4 @@ -package: github.com/tendermint/tmsp +package: github.com/tendermint/abci import: - package: github.com/golang/protobuf subpackages: diff --git a/server/grpc_server.go b/server/grpc_server.go index 472da25d..1acd45a3 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -7,7 +7,7 @@ import ( "google.golang.org/grpc" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) // var maxNumberConnections = 2 @@ -20,10 +20,10 @@ type GRPCServer struct { listener net.Listener server *grpc.Server - app types.TMSPApplicationServer + app types.ABCIApplicationServer } -func NewGRPCServer(protoAddr string, app types.TMSPApplicationServer) (Service, error) { +func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (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.TMSPApplicationServer) (Service, listener: nil, app: app, } - s.BaseService = *NewBaseService(nil, "TMSPServer", s) + s.BaseService = *NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } @@ -45,7 +45,7 @@ func (s *GRPCServer) OnStart() error { } s.listener = ln s.server = grpc.NewServer() - types.RegisterTMSPApplicationServer(s.server, s.app) + types.RegisterABCIApplicationServer(s.server, s.app) go s.server.Serve(s.listener) return nil } diff --git a/server/log.go b/server/log.go index 8ac4092e..4b313d25 100644 --- a/server/log.go +++ b/server/log.go @@ -4,4 +4,4 @@ import ( "github.com/tendermint/go-logger" ) -var log = logger.New("module", "tmsp-server") +var log = logger.New("module", "abci-server") diff --git a/server/server.go b/server/server.go index f2b9d0af..49676747 100644 --- a/server/server.go +++ b/server/server.go @@ -4,7 +4,7 @@ import ( "fmt" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) func NewServer(protoAddr, transport string, app types.Application) (Service, error) { diff --git a/server/socket_server.go b/server/socket_server.go index 2be3bbb5..bd26a18a 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -9,7 +9,7 @@ import ( "sync" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) // var maxNumberConnections = 2 @@ -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, "TMSPServer", s) + s.BaseService = *NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index db57e19b..5960d529 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -6,7 +6,7 @@ import ( //"encoding/hex" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) func main() { diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 585ebd2b..fb536730 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -9,7 +9,7 @@ import ( //"encoding/hex" . "github.com/tendermint/go-common" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) func main() { diff --git a/tests/test_app/app.go b/tests/test_app/app.go index b38d0737..59d5b0e7 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -7,24 +7,24 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-process" - "github.com/tendermint/tmsp/client" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/client" + "github.com/tendermint/abci/types" ) //---------------------------------------- -func StartApp(tmspApp string) *process.Process { +func StartApp(abciApp string) *process.Process { // Start the app //outBuf := NewBufferCloser(nil) - proc, err := process.StartProcess("tmsp_app", + proc, err := process.StartProcess("abci_app", "", "bash", - []string{"-c", tmspApp}, + []string{"-c", abciApp}, nil, os.Stdout, ) if err != nil { - panic("running tmsp_app: " + err.Error()) + panic("running abci_app: " + err.Error()) } // TODO a better way to handle this? @@ -33,16 +33,16 @@ func StartApp(tmspApp string) *process.Process { return proc } -func StartClient(tmspType string) tmspcli.Client { +func StartClient(abciType string) abcicli.Client { // Start client - client, err := tmspcli.NewClient("tcp://127.0.0.1:46658", tmspType, true) + client, err := abcicli.NewClient("tcp://127.0.0.1:46658", abciType, true) if err != nil { - panic("connecting to tmsp_app: " + err.Error()) + panic("connecting to abci_app: " + err.Error()) } return client } -func SetOption(client tmspcli.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() { @@ -50,7 +50,7 @@ func SetOption(client tmspcli.Client, key, value string) { } } -func Commit(client tmspcli.Client, hashExp []byte) { +func Commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { @@ -62,7 +62,7 @@ func Commit(client tmspcli.Client, hashExp []byte) { } } -func DeliverTx(client tmspcli.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 { @@ -75,7 +75,7 @@ func DeliverTx(client tmspcli.Client, txBytes []byte, codeExp types.CodeType, da } } -func CheckTx(client tmspcli.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() { diff --git a/tests/test_app/main.go b/tests/test_app/main.go index db627a3e..05f66b07 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -4,15 +4,15 @@ import ( "fmt" "os" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) -var tmspType string +var abciType string func init() { - tmspType = os.Getenv("TMSP") - if tmspType == "" { - tmspType = "socket" + abciType = os.Getenv("ABCI") + if abciType == "" { + abciType = "socket" } } @@ -21,15 +21,15 @@ func main() { } func testCounter() { - tmspApp := os.Getenv("TMSP_APP") - if tmspApp == "" { - panic("No TMSP_APP specified") + abciApp := os.Getenv("ABCI_APP") + if abciApp == "" { + panic("No ABCI_APP specified") } - fmt.Printf("Running %s test with tmsp=%s\n", tmspApp, tmspType) - appProc := StartApp(tmspApp) + fmt.Printf("Running %s test with abci=%s\n", abciApp, abciType) + appProc := StartApp(abciApp) defer appProc.StopProcess(true) - client := StartClient(tmspType) + client := StartClient(abciType) defer client.Stop() SetOption(client, "serial", "on") diff --git a/tests/test_app/test.sh b/tests/test_app/test.sh index 4c28a831..a0f2c3ce 100755 --- a/tests/test_app/test.sh +++ b/tests/test_app/test.sh @@ -1,17 +1,17 @@ #! /bin/bash set -e -# These tests spawn the counter app and server by execing the TMSP_APP command and run some simple client tests against it +# These tests spawn the counter app and server by execing the ABCI_APP command and run some simple client tests against it -ROOT=$GOPATH/src/github.com/tendermint/tmsp/tests/test_app +ROOT=$GOPATH/src/github.com/tendermint/abci/tests/test_app cd $ROOT # test golang counter -TMSP_APP="counter" go run *.go +ABCI_APP="counter" go run *.go # test golang counter via grpc -TMSP_APP="counter -tmsp=grpc" TMSP="grpc" go run *.go +ABCI_APP="counter -abci=grpc" ABCI="grpc" go run *.go # test nodejs counter # TODO: fix node app -#TMSP_APP="node $GOPATH/src/github.com/tendermint/js-tmsp/example/app.js" go test -test.run TestCounter +#ABCI_APP="node $GOPATH/src/github.com/tendermint/js-abci/example/app.js" go test -test.run TestCounter diff --git a/tests/test_cli/ex1.tmsp b/tests/test_cli/ex1.abci similarity index 100% rename from tests/test_cli/ex1.tmsp rename to tests/test_cli/ex1.abci diff --git a/tests/test_cli/ex1.tmsp.out b/tests/test_cli/ex1.abci.out similarity index 100% rename from tests/test_cli/ex1.tmsp.out rename to tests/test_cli/ex1.abci.out diff --git a/tests/test_cli/ex2.tmsp b/tests/test_cli/ex2.abci similarity index 100% rename from tests/test_cli/ex2.tmsp rename to tests/test_cli/ex2.abci diff --git a/tests/test_cli/ex2.tmsp.out b/tests/test_cli/ex2.abci.out similarity index 100% rename from tests/test_cli/ex2.tmsp.out rename to tests/test_cli/ex2.abci.out diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 00446c45..a770730b 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -1,5 +1,7 @@ #! /bin/bash +cd $GOPATH/src/github.com/tendermint/abci + function testExample() { N=$1 INPUT=$2 @@ -8,7 +10,7 @@ function testExample() { echo "Example $N" $APP &> /dev/null & sleep 2 - tmsp-cli --verbose batch < $INPUT > "${INPUT}.out.new" + abci-cli --verbose batch < $INPUT > "${INPUT}.out.new" killall "$APP" pre=`shasum < "${INPUT}.out"` @@ -26,8 +28,8 @@ function testExample() { rm "${INPUT}".out.new } -testExample 1 tests/test_cli/ex1.tmsp dummy -testExample 2 tests/test_cli/ex2.tmsp counter +testExample 1 tests/test_cli/ex1.abci dummy +testExample 2 tests/test_cli/ex2.abci counter echo "" echo "PASS" diff --git a/testutil/messages.go b/testutil/messages.go index 2890fbd5..1036e48e 100644 --- a/testutil/messages.go +++ b/testutil/messages.go @@ -2,7 +2,7 @@ package testutil import ( "github.com/tendermint/go-crypto" - "github.com/tendermint/tmsp/types" + "github.com/tendermint/abci/types" ) //---------------------------------------- diff --git a/types/result.go b/types/result.go index 717ae2fa..571c5bf8 100644 --- a/types/result.go +++ b/types/result.go @@ -28,7 +28,7 @@ func (res Result) IsErr() bool { } func (res Result) Error() string { - return fmt.Sprintf("TMSP code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) + return fmt.Sprintf("ABCI code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) } func (res Result) PrependLog(log string) Result { diff --git a/types/types.pb.go b/types/types.pb.go index 2c279bd2..40c3441b 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1676,9 +1676,9 @@ var _ grpc.ClientConn // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion4 -// Client API for TMSPApplication service +// Client API for ABCIApplication service -type TMSPApplicationClient interface { +type ABCIApplicationClient interface { Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) @@ -1696,13 +1696,13 @@ type tMSPApplicationClient struct { cc *grpc.ClientConn } -func NewTMSPApplicationClient(cc *grpc.ClientConn) TMSPApplicationClient { +func NewABCIApplicationClient(cc *grpc.ClientConn) ABCIApplicationClient { return &tMSPApplicationClient{cc} } func (c *tMSPApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { out := new(ResponseEcho) - err := grpc.Invoke(ctx, "/types.TMSPApplication/Echo", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Echo", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1711,7 +1711,7 @@ func (c *tMSPApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts func (c *tMSPApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { out := new(ResponseFlush) - err := grpc.Invoke(ctx, "/types.TMSPApplication/Flush", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Flush", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1720,7 +1720,7 @@ func (c *tMSPApplicationClient) Flush(ctx context.Context, in *RequestFlush, opt func (c *tMSPApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { out := new(ResponseInfo) - err := grpc.Invoke(ctx, "/types.TMSPApplication/Info", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Info", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1729,7 +1729,7 @@ func (c *tMSPApplicationClient) Info(ctx context.Context, in *RequestInfo, opts func (c *tMSPApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { out := new(ResponseSetOption) - err := grpc.Invoke(ctx, "/types.TMSPApplication/SetOption", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/SetOption", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1738,7 +1738,7 @@ func (c *tMSPApplicationClient) SetOption(ctx context.Context, in *RequestSetOpt func (c *tMSPApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { out := new(ResponseDeliverTx) - err := grpc.Invoke(ctx, "/types.TMSPApplication/DeliverTx", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/DeliverTx", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1747,7 +1747,7 @@ func (c *tMSPApplicationClient) DeliverTx(ctx context.Context, in *RequestDelive func (c *tMSPApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { out := new(ResponseCheckTx) - err := grpc.Invoke(ctx, "/types.TMSPApplication/CheckTx", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/CheckTx", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1756,7 +1756,7 @@ func (c *tMSPApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, func (c *tMSPApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { out := new(ResponseQuery) - err := grpc.Invoke(ctx, "/types.TMSPApplication/Query", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Query", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1765,7 +1765,7 @@ func (c *tMSPApplicationClient) Query(ctx context.Context, in *RequestQuery, opt func (c *tMSPApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { out := new(ResponseCommit) - err := grpc.Invoke(ctx, "/types.TMSPApplication/Commit", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1774,7 +1774,7 @@ func (c *tMSPApplicationClient) Commit(ctx context.Context, in *RequestCommit, o func (c *tMSPApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { out := new(ResponseInitChain) - err := grpc.Invoke(ctx, "/types.TMSPApplication/InitChain", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/InitChain", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1783,7 +1783,7 @@ func (c *tMSPApplicationClient) InitChain(ctx context.Context, in *RequestInitCh func (c *tMSPApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { out := new(ResponseBeginBlock) - err := grpc.Invoke(ctx, "/types.TMSPApplication/BeginBlock", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/BeginBlock", in, out, c.cc, opts...) if err != nil { return nil, err } @@ -1792,16 +1792,16 @@ func (c *tMSPApplicationClient) BeginBlock(ctx context.Context, in *RequestBegin func (c *tMSPApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { out := new(ResponseEndBlock) - err := grpc.Invoke(ctx, "/types.TMSPApplication/EndBlock", in, out, c.cc, opts...) + err := grpc.Invoke(ctx, "/types.ABCIApplication/EndBlock", in, out, c.cc, opts...) if err != nil { return nil, err } return out, nil } -// Server API for TMSPApplication service +// Server API for ABCIApplication service -type TMSPApplicationServer interface { +type ABCIApplicationServer interface { Echo(context.Context, *RequestEcho) (*ResponseEcho, error) Flush(context.Context, *RequestFlush) (*ResponseFlush, error) Info(context.Context, *RequestInfo) (*ResponseInfo, error) @@ -1815,255 +1815,255 @@ type TMSPApplicationServer interface { EndBlock(context.Context, *RequestEndBlock) (*ResponseEndBlock, error) } -func RegisterTMSPApplicationServer(s *grpc.Server, srv TMSPApplicationServer) { - s.RegisterService(&_TMSPApplication_serviceDesc, srv) +func RegisterABCIApplicationServer(s *grpc.Server, srv ABCIApplicationServer) { + s.RegisterService(&_ABCIApplication_serviceDesc, srv) } -func _TMSPApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestEcho) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).Echo(ctx, in) + return srv.(ABCIApplicationServer).Echo(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/Echo", + FullMethod: "/types.ABCIApplication/Echo", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).Echo(ctx, req.(*RequestEcho)) + return srv.(ABCIApplicationServer).Echo(ctx, req.(*RequestEcho)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestFlush) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).Flush(ctx, in) + return srv.(ABCIApplicationServer).Flush(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/Flush", + FullMethod: "/types.ABCIApplication/Flush", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).Flush(ctx, req.(*RequestFlush)) + return srv.(ABCIApplicationServer).Flush(ctx, req.(*RequestFlush)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestInfo) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).Info(ctx, in) + return srv.(ABCIApplicationServer).Info(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/Info", + FullMethod: "/types.ABCIApplication/Info", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).Info(ctx, req.(*RequestInfo)) + return srv.(ABCIApplicationServer).Info(ctx, req.(*RequestInfo)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_SetOption_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_SetOption_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestSetOption) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).SetOption(ctx, in) + return srv.(ABCIApplicationServer).SetOption(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/SetOption", + FullMethod: "/types.ABCIApplication/SetOption", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).SetOption(ctx, req.(*RequestSetOption)) + return srv.(ABCIApplicationServer).SetOption(ctx, req.(*RequestSetOption)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestDeliverTx) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).DeliverTx(ctx, in) + return srv.(ABCIApplicationServer).DeliverTx(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/DeliverTx", + FullMethod: "/types.ABCIApplication/DeliverTx", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).DeliverTx(ctx, req.(*RequestDeliverTx)) + return srv.(ABCIApplicationServer).DeliverTx(ctx, req.(*RequestDeliverTx)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestCheckTx) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).CheckTx(ctx, in) + return srv.(ABCIApplicationServer).CheckTx(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/CheckTx", + FullMethod: "/types.ABCIApplication/CheckTx", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).CheckTx(ctx, req.(*RequestCheckTx)) + return srv.(ABCIApplicationServer).CheckTx(ctx, req.(*RequestCheckTx)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestQuery) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).Query(ctx, in) + return srv.(ABCIApplicationServer).Query(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/Query", + FullMethod: "/types.ABCIApplication/Query", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).Query(ctx, req.(*RequestQuery)) + return srv.(ABCIApplicationServer).Query(ctx, req.(*RequestQuery)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestCommit) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).Commit(ctx, in) + return srv.(ABCIApplicationServer).Commit(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/Commit", + FullMethod: "/types.ABCIApplication/Commit", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).Commit(ctx, req.(*RequestCommit)) + return srv.(ABCIApplicationServer).Commit(ctx, req.(*RequestCommit)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestInitChain) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).InitChain(ctx, in) + return srv.(ABCIApplicationServer).InitChain(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/InitChain", + FullMethod: "/types.ABCIApplication/InitChain", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).InitChain(ctx, req.(*RequestInitChain)) + return srv.(ABCIApplicationServer).InitChain(ctx, req.(*RequestInitChain)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestBeginBlock) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).BeginBlock(ctx, in) + return srv.(ABCIApplicationServer).BeginBlock(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/BeginBlock", + FullMethod: "/types.ABCIApplication/BeginBlock", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) + return srv.(ABCIApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) } return interceptor(ctx, in, info, handler) } -func _TMSPApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ABCIApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestEndBlock) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TMSPApplicationServer).EndBlock(ctx, in) + return srv.(ABCIApplicationServer).EndBlock(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/types.TMSPApplication/EndBlock", + FullMethod: "/types.ABCIApplication/EndBlock", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TMSPApplicationServer).EndBlock(ctx, req.(*RequestEndBlock)) + return srv.(ABCIApplicationServer).EndBlock(ctx, req.(*RequestEndBlock)) } return interceptor(ctx, in, info, handler) } -var _TMSPApplication_serviceDesc = grpc.ServiceDesc{ - ServiceName: "types.TMSPApplication", - HandlerType: (*TMSPApplicationServer)(nil), +var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ + ServiceName: "types.ABCIApplication", + HandlerType: (*ABCIApplicationServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "Echo", - Handler: _TMSPApplication_Echo_Handler, + Handler: _ABCIApplication_Echo_Handler, }, { MethodName: "Flush", - Handler: _TMSPApplication_Flush_Handler, + Handler: _ABCIApplication_Flush_Handler, }, { MethodName: "Info", - Handler: _TMSPApplication_Info_Handler, + Handler: _ABCIApplication_Info_Handler, }, { MethodName: "SetOption", - Handler: _TMSPApplication_SetOption_Handler, + Handler: _ABCIApplication_SetOption_Handler, }, { MethodName: "DeliverTx", - Handler: _TMSPApplication_DeliverTx_Handler, + Handler: _ABCIApplication_DeliverTx_Handler, }, { MethodName: "CheckTx", - Handler: _TMSPApplication_CheckTx_Handler, + Handler: _ABCIApplication_CheckTx_Handler, }, { MethodName: "Query", - Handler: _TMSPApplication_Query_Handler, + Handler: _ABCIApplication_Query_Handler, }, { MethodName: "Commit", - Handler: _TMSPApplication_Commit_Handler, + Handler: _ABCIApplication_Commit_Handler, }, { MethodName: "InitChain", - Handler: _TMSPApplication_InitChain_Handler, + Handler: _ABCIApplication_InitChain_Handler, }, { MethodName: "BeginBlock", - Handler: _TMSPApplication_BeginBlock_Handler, + Handler: _ABCIApplication_BeginBlock_Handler, }, { MethodName: "EndBlock", - Handler: _TMSPApplication_EndBlock_Handler, + Handler: _ABCIApplication_EndBlock_Handler, }, }, Streams: []grpc.StreamDesc{}, diff --git a/types/types.proto b/types/types.proto index 34e5450b..b3ff1655 100644 --- a/types/types.proto +++ b/types/types.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package types; -// This file is copied from http://github.com/tendermint/tmsp +// This file is copied from http://github.com/tendermint/abci //---------------------------------------- // Message types @@ -243,7 +243,7 @@ message Validator { //---------------------------------------- // Service Definition -service TMSPApplication { +service ABCIApplication { rpc Echo(RequestEcho) returns (ResponseEcho) ; rpc Flush(RequestFlush) returns (ResponseFlush); rpc Info(RequestInfo) returns (ResponseInfo); From 42b7bfbf0c5e760655321b0d25adabcb7428d08d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 12 Jan 2017 21:20:09 -0500 Subject: [PATCH 178/545] update version and glide --- cmd/abci-cli/tmsp-cli.go | 4 ++-- glide.lock | 33 +++++++++++++++++++-------------- glide.yaml | 1 - types/version.go | 7 +++++++ 4 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 types/version.go diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index b8bc2937..39dace9f 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -9,9 +9,9 @@ import ( "os" "strings" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" "github.com/urfave/cli" ) @@ -50,7 +50,7 @@ func main() { app := cli.NewApp() app.Name = "abci-cli" app.Usage = "abci-cli [command] [args...]" - app.Version = "0.2.1" // better error handling in console + app.Version = "0.3.0" // hex handling app.Flags = []cli.Flag{ cli.StringFlag{ Name: "address", diff --git a/glide.lock b/glide.lock index 5a8a6c77..27767606 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,10 @@ -hash: 0644029071e51c40b7b4f9b3b3c14fce59e6dadd42897ea20d7eaf049104969e -updated: 2017-01-12T01:05:04.505700434-05:00 +hash: c050dfd4a6af84ab490a78c1580ac74caf42ed00799de7017d2ee325b806f77e +updated: 2017-01-12T21:19:13.812049926-05:00 imports: - name: github.com/btcsuite/btcd - version: afec1bd1245a4a19e6dfe1306974b733e7cbb9b8 + version: 153dca5c1e4b5d1ea1523592495e5bedfa503391 subpackages: - btcec -- name: github.com/btcsuite/fastsha256 - version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf @@ -20,9 +18,9 @@ imports: - name: github.com/mattn/go-colorable version: d228849504861217f796da67fae4f6e347643f15 - name: github.com/mattn/go-isatty - version: 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8 + version: 30a891c33c7cde7b02a981314b4228ec99380cca - name: github.com/syndtr/goleveldb - version: 6b4daa5362b502898ddf367c5c11deb9e7a5c727 + version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 subpackages: - leveldb - leveldb/cache @@ -50,19 +48,19 @@ imports: - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: c7a7ae88ca72bf030a7fb7d0d52ce8d1e62b4e16 + version: 2979c7eb8aa020fa1cf203654907dbb889703888 - name: github.com/tendermint/go-process version: 7f507d69fa4c13b34e7a17ff5c87d1eaaa759145 - name: github.com/tendermint/go-wire - version: 37d5dd6530857a1abc1db50a48ba22c3459826a1 + version: 2f3b7aafe21c80b19b6ee3210ecb3e3d07c7a471 - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term - name: github.com/urfave/cli - version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 + version: 8ef3805c9de2519805c3f060524b695bba2cd715 - name: golang.org/x/crypto - version: ede567c8e044a5913dad1d1af3696d9da953104c + version: 7c6cc321c680f03b9ef0764448e780704f486b51 subpackages: - nacl/secretbox - openpgp/armor @@ -71,7 +69,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 4971afdc2f162e82d185353533d3cf16188a9f4e + version: 60c41d1de8da134c05b7b40154a9a82bf5b7edb9 subpackages: - context - http2 @@ -81,11 +79,18 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: 30237cf4eefd639b184d1f2cb77a581ea0be8947 + version: d75a52659825e75fff6158388dddc6a5b04f9ba5 subpackages: - unix +- name: golang.org/x/text + version: 44f4f658a783b0cee41fe0a23b8fc91d9c120558 + subpackages: + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm - name: google.golang.org/grpc - version: 63bd55dfbf781b183216d2dd4433a659c947648a + version: 50955793b0183f9de69bd78e2ec251cf20aab121 subpackages: - codes - credentials diff --git a/glide.yaml b/glide.yaml index fae5a984..91283045 100644 --- a/glide.yaml +++ b/glide.yaml @@ -14,7 +14,6 @@ import: - package: github.com/tendermint/go-process version: develop - package: github.com/tendermint/go-wire - version: develop - package: github.com/urfave/cli - package: golang.org/x/net subpackages: diff --git a/types/version.go b/types/version.go new file mode 100644 index 00000000..719c6c98 --- /dev/null +++ b/types/version.go @@ -0,0 +1,7 @@ +package types + +const Maj = "0" +const Min = "3" // ResponseInfo, ResponseEndBlock +const Fix = "0" // + +const Version = Maj + "." + Min + "." + Fix From 5626a1125a60f336bbc3a5599ad5e62b93a8d320 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 13 Jan 2017 00:24:38 -0500 Subject: [PATCH 179/545] move glide deps to master --- glide.lock | 12 ++++++------ glide.yaml | 4 ---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/glide.lock b/glide.lock index 27767606..42776a3a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c050dfd4a6af84ab490a78c1580ac74caf42ed00799de7017d2ee325b806f77e -updated: 2017-01-12T21:19:13.812049926-05:00 +hash: febff7f2646081f635b5dc2a0a672d9b8e42eb59241269e6658eec916cd2a5a4 +updated: 2017-01-13T00:24:02.377918976-05:00 imports: - name: github.com/btcsuite/btcd version: 153dca5c1e4b5d1ea1523592495e5bedfa503391 @@ -40,17 +40,17 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-common - version: 70e694ee76f09058ea38c9ba81b4aa621bd54df1 + version: e289af53b6bf6af28da129d9ef64389a4cf7987f - name: github.com/tendermint/go-crypto version: 4b11d62bdb324027ea01554e5767b71174680ba0 - name: github.com/tendermint/go-db - version: 2645626c33d8702739e52a61a55d705c2dfe4530 + version: 72f6dacd22a686cdf7fcd60286503e3aceda77ba - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 2979c7eb8aa020fa1cf203654907dbb889703888 + version: 7a86b4486f2cd84ac885c5bbc609fdee2905f5d1 - name: github.com/tendermint/go-process - version: 7f507d69fa4c13b34e7a17ff5c87d1eaaa759145 + version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire version: 2f3b7aafe21c80b19b6ee3210ecb3e3d07c7a471 - name: github.com/tendermint/log15 diff --git a/glide.yaml b/glide.yaml index 91283045..295b3d3e 100644 --- a/glide.yaml +++ b/glide.yaml @@ -4,15 +4,11 @@ import: subpackages: - proto - package: github.com/tendermint/go-common - version: develop - package: github.com/tendermint/go-crypto - package: github.com/tendermint/go-logger - package: github.com/tendermint/go-db - version: develop - package: github.com/tendermint/go-merkle - version: develop - package: github.com/tendermint/go-process - version: develop - package: github.com/tendermint/go-wire - package: github.com/urfave/cli - package: golang.org/x/net From 68ef6bc1bf16d49c94ab88703aa5229567fdcea9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 13 Jan 2017 03:09:28 -0500 Subject: [PATCH 180/545] update README --- README.md | 165 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index ea09fa7c..aec2d922 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,74 @@ -# Tendermint Socket Protocol (ABCI) +# Application BlockChain Interface (ABCI) [![CircleCI](https://circleci.com/gh/tendermint/abci.svg?style=svg)](https://circleci.com/gh/tendermint/abci) -Blockchains are a system for creating shared multi-master application state. -**ABCI** is a socket protocol enabling a blockchain consensus engine, running in one process, -to manage a blockchain application state, running in another. +Blockchains are a system for multi-master state machine replication. +**ABCI** is an interface that defines the boundary between the replication engine (the blockchain), +and the state machine (the application). It is most commonly implemented in the form of the Tendermint Socket Protocol (TSP), +also known as Teaspoon. +By using a socket protocol, we enable a consensus engine running in one process +to manage an application state running in another. -For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-tendermint-socket-protocol). +For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/tmsp-the-tendermint-socket-protocol). + +Previously, the ABCI was just referred to as TMSP. Other implementations: -* [cpp-abci](https://github.com/mdyring/cpp-abci) by Martin Dyring-Andersen -* [js-abci](https://github.com/tendermint/js-abci) -* [jABCI](https://github.com/jABCI/) for Java +* [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen +* [js-tmsp](https://github.com/tendermint/js-tmsp) +* [jTMSP](https://github.com/jTMSP/) for Java -## Contents +# Specification -This repository holds a number of important pieces: +The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers. -- `types/types.proto` - - 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 - -- golang implementation of ABCI client and server - - two implementations: - - asynchronous, ordered message passing over unix or tcp; - - messages are serialized using protobuf and length prefixed - - grpc - - TendermintCore runs a client, and the application runs a server - -- `cmd/abci-cli` - - command line tool wrapping the client for probing/testing a ABCI application - - use `abci-cli --version` to get the ABCI version - -- examples: - - the `cmd/counter` application, which illustrates nonce checking in txs - - the `cmd/dummy` application, which illustrates a simple key-value merkle tree +As a [Go interface](https://github.com/tendermint/abci/blob/master/types/application.go), it might look like: -## Message format +``` +// Applications +type Application interface { -Since this is a streaming protocol, all messages are encoded with a length-prefix followed by the message encoded in Protobuf3. Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. + // Latest state + Info() ResponseInfo -For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. + // Initialization + SetOption(key string, value string) (log string) + InitChain(validators []*Validator) -Note this prefixing does not apply for grpc. + // Apply a block + BeginBlock(hash []byte, header *Header) + DeliverTx(tx []byte) Result + EndBlock(height uint64) ResponseEndBlock + Commit() Result -## Message types + // Check validity + CheckTx(tx []byte) Result + + // Query for state + Query(query []byte) Result +} + +type Result struct { + Code CodeType + Data []byte + Log string // Can be non-deterministic +} + +type ResponseInfo struct { + Data string + Version string + LastBlockHeight uint64 + LastBlockAppHash []byte +} + +type ResponseEndBlock struct { + Diffs []*Validator +} + +``` + +## Message Types ABCI requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/abci/blob/master/types/types.proto). @@ -92,15 +114,15 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * `Data ([]byte)`: The query response bytes * `Log (string)`: Debug or error message -#### Flush - * __Usage__:
- Flush the response queue. Applications that implement `types.Application` need not implement this message -- it's handled by the project. - #### Info * __Returns__: - * `Data ([]byte)`: The info bytes + * `Data (string)`: Some arbitrary information + * `Version (Version)`: Version information + * `LastBlockHeight (uint64)`: Latest block for which the app has called Commit + * `LastBlockAppHash ([]byte)`: Latest result of Commit + * __Usage__:
- Return information about the application state. Application specific. + Return information about the application state. Used to sync the app with Tendermint on crash/restart. #### SetOption * __Arguments__: @@ -120,44 +142,63 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil #### BeginBlock * __Arguments__: - * `Height (uint64)`: The block height that is starting + * `Hash ([]byte)`: The block height that is starting + * `Header (struct{})`: The block header * __Usage__:
- Signals the beginning of a new block. Called prior to any DeliverTxs. + Signals the beginning of a new block. Called prior to any DeliverTxs. The header is expected to at least contain the Height. #### EndBlock * __Arguments__: * `Height (uint64)`: The block height that ended * __Returns__: - * `Validators ([]Validator)`: Changed validators with new voting powers (0 to remove) + * `Diffs ([]Validator)`: Changed validators with new voting powers (0 to remove) * __Usage__:
- Signals the end of a block. Called prior to each Commit after all transactions + Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. -## Changelog -##### Mar 26h, 2016 -* Introduce BeginBlock +# Implementations -##### Mar 6th, 2016 +The ABCI is a client/server interface where the replication engine (blockchain) forms the client +and the state machine (application) forms the server. +As blocks are committed in the blockchain, they are forwarded to the application. -* Added InitChain, EndBlock +This repository provides two implementations of an ABCI client & server: TSP (Tendermint Socket Protocol) and via GRPC. -##### Feb 14th, 2016 +## TSP -* s/GetHash/Commit/g -* Document Protobuf request/response fields +ABCI is best implemented as a streaming protocol. +The TSP provides for asynchronous, ordered message passing over unix or tcp. +Messages are serialized using Protobuf3 and length-prefixed. +Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. -##### Jan 23th, 2016 +For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. -* 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 +## GRPC -##### Jan 12th, 2016 +GRPC is an rpc framework native to Protocol Buffers with support in many languages. +Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than +the ordered, asynchronous TSP. -* Added "RetCodeBadNonce = 0x06" return code +Note the length-prefixing used in TSP does not apply for GRPC. -##### Jan 8th, 2016 +# Tools and Apps + +The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. +See the [tutorial](https://tendermint.com/intro/getting-started/first-tmsp) for more details. + +Multiple example apps are included: +- the `counter` application, which illustrates nonce checking in txs +- the `dummy` application, which illustrates a simple key-value merkle tree +- the `dummy --persistent` application, which augments the dummy with persistence and validator set changes + + +# Build + +To build the protobuf code: + +``` +make protoc +``` + +See `protoc --help` and [the grpc docs](https://www.grpc.io/docs) for examples and details of other languages -* Tendermint/ABCI now comes to consensus on the order first before DeliverTx. From b9d1465488fdcb3c4c7eff42d11cdbee00240d8c Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 13 Jan 2017 10:12:38 -0800 Subject: [PATCH 181/545] Make sure we install before test, since test relies on counter etc --- Makefile | 2 +- types/types.pb.go | 243 +++++++++++++++++++++++----------------------- 2 files changed, 122 insertions(+), 123 deletions(-) diff --git a/Makefile b/Makefile index 22fa6fdd..d80410ff 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all test get_deps -all: protoc test install +all: protoc install test NOVENDOR = go list github.com/tendermint/abci/... | grep -v /vendor/ diff --git a/types/types.pb.go b/types/types.pb.go index 40c3441b..6cae5433 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -74,7 +74,7 @@ const ( MessageType_Info MessageType = 3 MessageType_SetOption MessageType = 4 MessageType_Exception MessageType = 5 - MessageType_DeliverTx MessageType = 17 + MessageType_DeliverTx MessageType = 17 MessageType_CheckTx MessageType = 18 MessageType_Commit MessageType = 19 MessageType_Query MessageType = 20 @@ -105,7 +105,7 @@ var MessageType_value = map[string]int32{ "Info": 3, "SetOption": 4, "Exception": 5, - "DeliverTx": 17, + "DeliverTx": 17, "CheckTx": 18, "Commit": 19, "Query": 20, @@ -290,7 +290,7 @@ func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} func (*Request_Info) isRequest_Value() {} func (*Request_SetOption) isRequest_Value() {} -func (*Request_DeliverTx) isRequest_Value() {} +func (*Request_DeliverTx) isRequest_Value() {} func (*Request_CheckTx) isRequest_Value() {} func (*Request_Commit) isRequest_Value() {} func (*Request_Query) isRequest_Value() {} @@ -863,7 +863,7 @@ func (*Response_Echo) isResponse_Value() {} func (*Response_Flush) isResponse_Value() {} func (*Response_Info) isResponse_Value() {} func (*Response_SetOption) isResponse_Value() {} -func (*Response_DeliverTx) isResponse_Value() {} +func (*Response_DeliverTx) isResponse_Value() {} func (*Response_CheckTx) isResponse_Value() {} func (*Response_Commit) isResponse_Value() {} func (*Response_Query) isResponse_Value() {} @@ -1692,15 +1692,15 @@ type ABCIApplicationClient interface { EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) } -type tMSPApplicationClient struct { +type aBCIApplicationClient struct { cc *grpc.ClientConn } func NewABCIApplicationClient(cc *grpc.ClientConn) ABCIApplicationClient { - return &tMSPApplicationClient{cc} + return &aBCIApplicationClient{cc} } -func (c *tMSPApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { +func (c *aBCIApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { out := new(ResponseEcho) err := grpc.Invoke(ctx, "/types.ABCIApplication/Echo", in, out, c.cc, opts...) if err != nil { @@ -1709,7 +1709,7 @@ func (c *tMSPApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts return out, nil } -func (c *tMSPApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { +func (c *aBCIApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { out := new(ResponseFlush) err := grpc.Invoke(ctx, "/types.ABCIApplication/Flush", in, out, c.cc, opts...) if err != nil { @@ -1718,7 +1718,7 @@ func (c *tMSPApplicationClient) Flush(ctx context.Context, in *RequestFlush, opt return out, nil } -func (c *tMSPApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { +func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { out := new(ResponseInfo) err := grpc.Invoke(ctx, "/types.ABCIApplication/Info", in, out, c.cc, opts...) if err != nil { @@ -1727,7 +1727,7 @@ func (c *tMSPApplicationClient) Info(ctx context.Context, in *RequestInfo, opts return out, nil } -func (c *tMSPApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { +func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { out := new(ResponseSetOption) err := grpc.Invoke(ctx, "/types.ABCIApplication/SetOption", in, out, c.cc, opts...) if err != nil { @@ -1736,7 +1736,7 @@ func (c *tMSPApplicationClient) SetOption(ctx context.Context, in *RequestSetOpt return out, nil } -func (c *tMSPApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { +func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { out := new(ResponseDeliverTx) err := grpc.Invoke(ctx, "/types.ABCIApplication/DeliverTx", in, out, c.cc, opts...) if err != nil { @@ -1745,7 +1745,7 @@ func (c *tMSPApplicationClient) DeliverTx(ctx context.Context, in *RequestDelive return out, nil } -func (c *tMSPApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { +func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { out := new(ResponseCheckTx) err := grpc.Invoke(ctx, "/types.ABCIApplication/CheckTx", in, out, c.cc, opts...) if err != nil { @@ -1754,7 +1754,7 @@ func (c *tMSPApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, return out, nil } -func (c *tMSPApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { +func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { out := new(ResponseQuery) err := grpc.Invoke(ctx, "/types.ABCIApplication/Query", in, out, c.cc, opts...) if err != nil { @@ -1763,7 +1763,7 @@ func (c *tMSPApplicationClient) Query(ctx context.Context, in *RequestQuery, opt return out, nil } -func (c *tMSPApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { +func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { out := new(ResponseCommit) err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...) if err != nil { @@ -1772,7 +1772,7 @@ func (c *tMSPApplicationClient) Commit(ctx context.Context, in *RequestCommit, o return out, nil } -func (c *tMSPApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { +func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { out := new(ResponseInitChain) err := grpc.Invoke(ctx, "/types.ABCIApplication/InitChain", in, out, c.cc, opts...) if err != nil { @@ -1781,7 +1781,7 @@ func (c *tMSPApplicationClient) InitChain(ctx context.Context, in *RequestInitCh return out, nil } -func (c *tMSPApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { +func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { out := new(ResponseBeginBlock) err := grpc.Invoke(ctx, "/types.ABCIApplication/BeginBlock", in, out, c.cc, opts...) if err != nil { @@ -1790,7 +1790,7 @@ func (c *tMSPApplicationClient) BeginBlock(ctx context.Context, in *RequestBegin return out, nil } -func (c *tMSPApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { +func (c *aBCIApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { out := new(ResponseEndBlock) err := grpc.Invoke(ctx, "/types.ABCIApplication/EndBlock", in, out, c.cc, opts...) if err != nil { @@ -2073,109 +2073,108 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1654 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x49, 0x73, 0x1b, 0xc7, - 0x15, 0xc6, 0x60, 0xc7, 0x03, 0x09, 0x34, 0x1f, 0x41, 0x12, 0x44, 0x72, 0x50, 0x26, 0x71, 0x4c, - 0x29, 0x8e, 0x94, 0xa2, 0xcb, 0x2e, 0x31, 0x4e, 0xa5, 0x8a, 0x94, 0x68, 0x02, 0xe5, 0x92, 0xc4, - 0x8c, 0x68, 0x1f, 0xb2, 0x14, 0x6a, 0x88, 0x69, 0x00, 0x13, 0x02, 0x33, 0xa3, 0x59, 0x68, 0x32, - 0xff, 0xc0, 0xbf, 0x20, 0x3f, 0x21, 0xbf, 0x20, 0x97, 0x5c, 0x73, 0xca, 0xbe, 0xfc, 0x22, 0xd7, - 0xeb, 0xee, 0x59, 0x39, 0xf0, 0x49, 0x17, 0xd4, 0xf4, 0xdb, 0xba, 0xfb, 0xf5, 0xf7, 0xbe, 0x7e, - 0x0d, 0xd8, 0x09, 0xef, 0x3d, 0x1e, 0x3c, 0x13, 0xbf, 0x4f, 0x3d, 0xdf, 0x0d, 0x5d, 0x6c, 0x88, - 0x81, 0xfe, 0xd7, 0x3a, 0xb4, 0x0c, 0xfe, 0x2e, 0xe2, 0x41, 0x88, 0x47, 0x50, 0xe7, 0xb3, 0xa5, - 0x3b, 0xd4, 0x1e, 0x69, 0x47, 0xdd, 0x63, 0x7c, 0x2a, 0xcd, 0x95, 0xf6, 0x7c, 0xb6, 0x74, 0xc7, - 0x15, 0x43, 0x58, 0xe0, 0x4f, 0xa0, 0x31, 0x5f, 0x45, 0xc1, 0x72, 0x58, 0x15, 0xa6, 0xbb, 0x79, - 0xd3, 0xcf, 0x49, 0x35, 0xae, 0x18, 0xd2, 0x86, 0xc2, 0xda, 0xce, 0xdc, 0x1d, 0xd6, 0xca, 0xc2, - 0x4e, 0x9c, 0xb9, 0x08, 0x4b, 0x16, 0xf8, 0x1c, 0x20, 0xe0, 0xe1, 0xd4, 0xf5, 0x42, 0xdb, 0x75, - 0x86, 0x75, 0x61, 0x7f, 0x90, 0xb7, 0x7f, 0xcb, 0xc3, 0x37, 0x42, 0x3d, 0xae, 0x18, 0x9d, 0x20, - 0x1e, 0xe0, 0x27, 0xd0, 0x31, 0x3d, 0x8f, 0x3b, 0xd6, 0x34, 0xbc, 0x1b, 0x36, 0x84, 0xe3, 0x7e, - 0xde, 0xf1, 0x54, 0xa8, 0xaf, 0xee, 0xc6, 0x15, 0xa3, 0x6d, 0xaa, 0x6f, 0x3c, 0x86, 0xf6, 0x6c, - 0xc9, 0x67, 0x37, 0xe4, 0xd5, 0x14, 0x5e, 0x7b, 0x79, 0xaf, 0x17, 0xa4, 0x15, 0x4e, 0xad, 0x99, - 0xfc, 0xc4, 0xa7, 0xd0, 0x9c, 0xb9, 0xeb, 0xb5, 0x1d, 0x0e, 0x5b, 0xc2, 0x63, 0x50, 0xf0, 0x10, - 0xba, 0x71, 0xc5, 0x50, 0x56, 0x94, 0xab, 0x77, 0x11, 0xf7, 0xef, 0x87, 0xed, 0xb2, 0x5c, 0xfd, - 0x8a, 0x54, 0x94, 0x2b, 0x61, 0x43, 0x19, 0xb0, 0x1d, 0x3b, 0x9c, 0xce, 0x96, 0xa6, 0xed, 0x0c, - 0x3b, 0x65, 0x19, 0x98, 0x38, 0x76, 0xf8, 0x82, 0xd4, 0x94, 0x01, 0x3b, 0x1e, 0xe0, 0x67, 0xd0, - 0xbd, 0xe6, 0x0b, 0xdb, 0x99, 0x5e, 0xaf, 0xdc, 0xd9, 0xcd, 0x10, 0x84, 0xeb, 0x30, 0xef, 0x7a, - 0x46, 0x06, 0x67, 0xa4, 0x1f, 0x57, 0x0c, 0xb8, 0x4e, 0x46, 0x94, 0x3e, 0xca, 0x9d, 0x74, 0xed, - 0x96, 0xa5, 0xef, 0xdc, 0xb1, 0x62, 0xc7, 0x36, 0x57, 0xdf, 0x67, 0x2d, 0x68, 0xdc, 0x9a, 0xab, - 0x88, 0xeb, 0x1f, 0x42, 0x37, 0x03, 0x13, 0x1c, 0x42, 0x6b, 0xcd, 0x83, 0xc0, 0x5c, 0x70, 0x81, - 0xa5, 0x8e, 0x11, 0x0f, 0xf5, 0x1e, 0x6c, 0x65, 0x41, 0xa2, 0x6f, 0x27, 0x8e, 0x04, 0x04, 0xfd, - 0xe7, 0xc0, 0x8a, 0xe7, 0x8c, 0x0c, 0x6a, 0x37, 0xfc, 0x5e, 0x05, 0xa2, 0x4f, 0x1c, 0xa8, 0x69, - 0x05, 0xfa, 0x3a, 0x86, 0x5a, 0xc3, 0x0f, 0xa0, 0x5f, 0x38, 0x6a, 0xec, 0x41, 0x35, 0xbc, 0x13, - 0x9e, 0x5b, 0x46, 0x35, 0xbc, 0xd3, 0x1f, 0x41, 0x2f, 0x7f, 0xae, 0x0f, 0x2c, 0x7e, 0x94, 0xac, - 0x4f, 0x1c, 0x0c, 0x4d, 0x25, 0x0f, 0x4f, 0x9a, 0xc8, 0x81, 0xde, 0x87, 0xed, 0xdc, 0x69, 0xeb, - 0x2f, 0x93, 0x75, 0x27, 0xa7, 0x83, 0x3f, 0x03, 0xb8, 0x35, 0x57, 0xb6, 0x65, 0x86, 0xae, 0x1f, - 0x0c, 0xb5, 0x47, 0xb5, 0xa3, 0xee, 0x31, 0x53, 0x49, 0xfd, 0x2a, 0x56, 0x18, 0x19, 0x1b, 0xfd, - 0x35, 0xec, 0x3c, 0x38, 0x28, 0x44, 0xa8, 0x2f, 0xcd, 0x60, 0xa9, 0x16, 0x20, 0xbe, 0xf1, 0x03, - 0x68, 0x2e, 0xb9, 0x69, 0x71, 0x5f, 0xd5, 0xdf, 0xb6, 0x0a, 0x3b, 0x16, 0x42, 0x43, 0x29, 0xf5, - 0xc7, 0x49, 0x46, 0xe2, 0xd3, 0xc3, 0x7d, 0xf2, 0xb4, 0x17, 0xcb, 0x50, 0xc4, 0xab, 0x1b, 0x6a, - 0xa4, 0x7f, 0xd3, 0x80, 0xb6, 0xc1, 0x03, 0xcf, 0x75, 0x02, 0x8e, 0xcf, 0xa1, 0xc3, 0xef, 0x66, - 0x5c, 0x56, 0xa1, 0x56, 0x00, 0x92, 0xb4, 0x39, 0x8f, 0xf5, 0x04, 0xc2, 0xc4, 0x18, 0x1f, 0x2b, - 0x06, 0x29, 0xd2, 0x82, 0x72, 0xca, 0x52, 0xc8, 0x47, 0x31, 0x85, 0xd4, 0x0a, 0x55, 0x24, 0x6d, - 0x0b, 0x1c, 0xf2, 0x58, 0x71, 0x48, 0xbd, 0x34, 0x70, 0x8e, 0x44, 0x4e, 0x72, 0x24, 0xd2, 0x28, - 0x5d, 0xfe, 0x06, 0x16, 0xf9, 0x34, 0xcb, 0x22, 0xcd, 0x42, 0xf1, 0x49, 0xcf, 0x52, 0x1a, 0xf9, - 0x38, 0x43, 0x23, 0xad, 0x42, 0xf5, 0x48, 0xb7, 0x12, 0x1e, 0x79, 0x96, 0xf0, 0x48, 0xbb, 0xc0, - 0x3c, 0xca, 0xa5, 0x48, 0x24, 0x1f, 0xc5, 0x58, 0xec, 0x94, 0x66, 0xac, 0xc0, 0x24, 0x27, 0x39, - 0x26, 0x81, 0xd2, 0x34, 0x6c, 0xa0, 0x92, 0x5f, 0xe4, 0xa9, 0x44, 0xf2, 0xc1, 0x61, 0xc1, 0x77, - 0x23, 0x97, 0x7c, 0x9a, 0xe5, 0x92, 0xad, 0xd2, 0x24, 0x7e, 0x37, 0x99, 0x3c, 0xa6, 0x32, 0x28, - 0xc0, 0x8c, 0x0a, 0x91, 0xfb, 0xbe, 0xeb, 0x2b, 0x1e, 0x90, 0x03, 0xfd, 0x88, 0xca, 0x35, 0x05, - 0xd7, 0x77, 0x10, 0x8f, 0x28, 0xd9, 0x0c, 0xb4, 0xf4, 0x3f, 0x6a, 0xa9, 0x2f, 0xe1, 0x87, 0x0a, - 0xcd, 0x32, 0x43, 0x53, 0x39, 0x8a, 0x6f, 0x8a, 0x77, 0xcb, 0xfd, 0x80, 0x80, 0x24, 0xb9, 0x26, - 0x1e, 0xe2, 0x13, 0xd8, 0x59, 0x99, 0x41, 0x28, 0xb7, 0x39, 0x55, 0x35, 0x55, 0x13, 0x35, 0xd5, - 0x27, 0x85, 0xdc, 0x9f, 0x10, 0xe3, 0x4f, 0x61, 0x37, 0x63, 0x6b, 0x7a, 0xde, 0x54, 0x54, 0x74, - 0x5d, 0x54, 0x34, 0x4b, 0xac, 0x4f, 0x3d, 0x6f, 0x6c, 0x06, 0x4b, 0xfd, 0x83, 0x74, 0xff, 0x39, - 0x16, 0x5c, 0xb9, 0x8b, 0x98, 0x05, 0x57, 0xee, 0x42, 0xff, 0x1d, 0x71, 0x4e, 0x1e, 0x94, 0xf8, - 0x43, 0xa8, 0xcf, 0x5c, 0x4b, 0x6e, 0xbe, 0x77, 0xdc, 0x57, 0x69, 0x7f, 0xe1, 0x5a, 0xfc, 0xea, - 0xde, 0xe3, 0x86, 0x50, 0x26, 0x1b, 0xad, 0x4a, 0x46, 0x11, 0x1b, 0x55, 0xe1, 0x6b, 0x69, 0xf8, - 0xdf, 0x12, 0x79, 0xe4, 0xc0, 0xfb, 0x3e, 0xa3, 0xff, 0x3a, 0x3d, 0x0e, 0x49, 0xb4, 0xef, 0x31, - 0xf6, 0x6f, 0x88, 0xe5, 0xb3, 0x35, 0xf4, 0x3e, 0x83, 0xef, 0xa6, 0x87, 0x93, 0x54, 0x8f, 0x3e, - 0x00, 0x7c, 0x58, 0x16, 0xf2, 0x32, 0xcb, 0x03, 0x1e, 0x7f, 0x0c, 0x0d, 0xcb, 0x9e, 0xcf, 0x83, - 0x61, 0x7d, 0xc3, 0x7d, 0x20, 0xd5, 0xfa, 0x9f, 0xaa, 0xd0, 0x94, 0x6c, 0x8e, 0x87, 0x44, 0x2e, - 0xa6, 0xed, 0x4c, 0x6d, 0x2b, 0x06, 0xb5, 0x18, 0x4f, 0xac, 0x0c, 0x9b, 0x57, 0xb3, 0x6c, 0x4e, - 0x5b, 0x09, 0xed, 0x35, 0x57, 0x78, 0x14, 0xdf, 0x78, 0x00, 0x2d, 0x27, 0x5a, 0x4f, 0xc3, 0xbb, - 0x40, 0x00, 0xaf, 0x6e, 0x34, 0x9d, 0x68, 0x7d, 0x75, 0x17, 0xe0, 0x31, 0x6c, 0x67, 0xd0, 0x69, - 0x5b, 0x8a, 0x32, 0x7b, 0x6a, 0x69, 0x62, 0xdd, 0x93, 0x97, 0x46, 0x37, 0xc1, 0xe9, 0xc4, 0xc2, - 0x23, 0x10, 0xb0, 0x9d, 0x4a, 0x66, 0x92, 0x70, 0x6e, 0x8a, 0xbc, 0xf5, 0x48, 0xae, 0xa8, 0x8b, - 0xae, 0xaa, 0xef, 0x41, 0x87, 0x32, 0x29, 0x4d, 0x5a, 0xc2, 0xa4, 0x4d, 0x02, 0xa1, 0xfc, 0x10, - 0xfa, 0xe9, 0xf5, 0x27, 0x4d, 0xda, 0x32, 0x4a, 0x2a, 0x16, 0x86, 0x87, 0xd0, 0x4e, 0xca, 0xa6, - 0x23, 0x2c, 0x5a, 0xa6, 0xaa, 0x96, 0x09, 0xb4, 0xd4, 0x12, 0x4b, 0xaf, 0xca, 0x27, 0xd0, 0xf0, - 0x4c, 0x3f, 0x0c, 0xd4, 0x95, 0x14, 0x93, 0xe6, 0xa5, 0xe9, 0x53, 0x8b, 0xa1, 0x2e, 0x4c, 0x69, - 0xa2, 0x9f, 0xc0, 0x76, 0x4e, 0x4e, 0xa4, 0x13, 0xba, 0xa1, 0xb9, 0x52, 0x97, 0xa5, 0x1c, 0x24, - 0xd3, 0x54, 0xd3, 0x69, 0xf4, 0x13, 0xe8, 0x24, 0x67, 0x48, 0xc7, 0xe2, 0x45, 0xd7, 0x5f, 0xf0, - 0xb8, 0x6b, 0x50, 0x23, 0x0a, 0xe7, 0xb9, 0x5f, 0xab, 0x5b, 0xbb, 0x6e, 0xc8, 0xc1, 0x93, 0xbf, - 0x68, 0xd0, 0x7d, 0x25, 0x59, 0x8a, 0xd0, 0x88, 0x7d, 0xe8, 0xbe, 0x8e, 0x56, 0x2b, 0x25, 0x62, - 0x15, 0x6c, 0x43, 0x9d, 0xc8, 0x8d, 0x69, 0xd8, 0x81, 0x86, 0x20, 0x2f, 0x56, 0x25, 0x21, 0xb1, - 0x16, 0xab, 0xe1, 0x36, 0x74, 0x12, 0x9a, 0x60, 0x75, 0x1a, 0x26, 0xac, 0xc9, 0x1a, 0xb8, 0x05, - 0xed, 0x98, 0x1d, 0xd8, 0x0e, 0x76, 0xa1, 0xa5, 0x8a, 0x99, 0x21, 0x02, 0x34, 0xe5, 0x41, 0xb1, - 0x5d, 0x8a, 0x2c, 0xea, 0x90, 0x0d, 0x28, 0x40, 0x82, 0x6c, 0xb6, 0x87, 0x3d, 0x80, 0x14, 0xd3, - 0x6c, 0x9f, 0x02, 0xc6, 0x68, 0x66, 0x07, 0x4f, 0xfe, 0xdc, 0x80, 0x76, 0x5c, 0x47, 0xd8, 0x84, - 0xea, 0x9b, 0x2f, 0x58, 0x05, 0x77, 0x60, 0x7b, 0xe2, 0x84, 0xdc, 0x77, 0xcc, 0xd5, 0x39, 0xd1, - 0x34, 0xd3, 0x48, 0x74, 0xee, 0xcc, 0x5c, 0xcb, 0x76, 0x16, 0x52, 0x54, 0xa5, 0x40, 0x67, 0xa6, - 0xf5, 0xda, 0x75, 0x66, 0x9c, 0xd5, 0x90, 0xc1, 0xd6, 0x97, 0x8e, 0x19, 0x85, 0x4b, 0xd7, 0xb7, - 0xff, 0xc0, 0x2d, 0x56, 0xc7, 0x3d, 0xd8, 0x99, 0x38, 0x41, 0x34, 0x9f, 0xdb, 0x33, 0x9b, 0x3b, - 0xe1, 0xe7, 0x91, 0x63, 0x05, 0xac, 0x81, 0x08, 0xbd, 0x2f, 0x9d, 0x1b, 0xc7, 0xfd, 0xda, 0x51, - 0xbd, 0x0d, 0x6b, 0xe2, 0x10, 0x06, 0x67, 0x66, 0xc0, 0x5f, 0x46, 0xde, 0xca, 0x9e, 0x99, 0x21, - 0x3f, 0xb5, 0x2c, 0x9f, 0x07, 0x01, 0xe3, 0x14, 0x84, 0x34, 0xf9, 0xb9, 0xe7, 0xb1, 0x43, 0x2e, - 0x3e, 0xe7, 0x01, 0x5b, 0xe0, 0x21, 0xec, 0x3d, 0xd0, 0x88, 0x99, 0x97, 0xf8, 0x7d, 0x18, 0x16, - 0x55, 0x17, 0x66, 0x70, 0xe9, 0xdb, 0x33, 0xce, 0x6c, 0x1c, 0x00, 0x93, 0x5a, 0x01, 0xdd, 0x89, - 0xe3, 0x45, 0x21, 0xfb, 0x7d, 0x3c, 0xbf, 0x92, 0xbe, 0x89, 0x42, 0x12, 0xdf, 0x14, 0xc4, 0x97, - 0x02, 0x1e, 0x6c, 0x85, 0x07, 0xb0, 0x9b, 0x11, 0xbf, 0xa5, 0xfd, 0x51, 0x76, 0xd6, 0xe9, 0x7a, - 0xa5, 0xc2, 0x5e, 0x38, 0x66, 0x18, 0xf9, 0x9c, 0x39, 0xb8, 0x0f, 0x48, 0x1a, 0x95, 0x92, 0x78, - 0xe3, 0x6e, 0x3c, 0x83, 0x92, 0xab, 0x19, 0xbc, 0xa2, 0x78, 0x15, 0x2d, 0x6c, 0x87, 0xbd, 0xc3, - 0x3d, 0x60, 0x17, 0xee, 0xad, 0x92, 0x9e, 0x3b, 0xa1, 0x1d, 0xde, 0xb3, 0xbf, 0x69, 0x38, 0x80, - 0x7e, 0x2a, 0xbe, 0xf0, 0xdd, 0xc8, 0x63, 0x7f, 0xd7, 0xf0, 0x00, 0x30, 0x95, 0x5e, 0xfa, 0xae, - 0xe7, 0x06, 0xe6, 0x8a, 0xfd, 0x43, 0xc3, 0x7d, 0xd8, 0xb9, 0x70, 0x6f, 0x93, 0x53, 0x90, 0x0e, - 0xff, 0x8c, 0x1d, 0x12, 0xf9, 0x2b, 0xbe, 0xbe, 0xe6, 0x3e, 0xfb, 0x97, 0x86, 0x87, 0x30, 0xc8, - 0x2a, 0x92, 0x58, 0xff, 0xd6, 0xd4, 0x8a, 0x12, 0xd5, 0x57, 0x6e, 0xc8, 0xd9, 0x7f, 0x62, 0xb1, - 0xca, 0x83, 0x0a, 0xf4, 0x5f, 0x0d, 0x77, 0xa1, 0x97, 0x8a, 0x85, 0xed, 0xff, 0x34, 0x1c, 0xc1, - 0x5e, 0x4e, 0x68, 0x3b, 0x8b, 0x4b, 0xaa, 0x38, 0xf6, 0x7f, 0xed, 0xf8, 0x9b, 0x06, 0xf4, 0xaf, - 0x5e, 0xbd, 0xbd, 0x3c, 0xf5, 0xe4, 0x04, 0x74, 0xc5, 0x3e, 0x93, 0x75, 0x86, 0x25, 0x0f, 0xdf, - 0x51, 0x59, 0x2b, 0x8b, 0xc7, 0xaa, 0x1c, 0xb1, 0xec, 0xfd, 0x3b, 0x2a, 0xed, 0x68, 0x69, 0x12, - 0xd9, 0x6d, 0x3c, 0x7c, 0x06, 0x8f, 0xca, 0xda, 0x5a, 0xfc, 0x65, 0xa6, 0xbc, 0x71, 0xd3, 0x63, - 0x78, 0xb4, 0xb1, 0xc1, 0xc5, 0xcf, 0x52, 0x02, 0xc0, 0x0d, 0x4f, 0xe2, 0xd1, 0xa6, 0x26, 0x17, - 0x9f, 0x27, 0x7c, 0x81, 0xe5, 0x0f, 0xe3, 0xd1, 0x86, 0x46, 0x97, 0x72, 0x23, 0x2f, 0xf6, 0xb2, - 0xf7, 0xee, 0xa8, 0xb4, 0x77, 0xc5, 0x4f, 0x62, 0x42, 0xc2, 0xd2, 0x37, 0xf5, 0xa8, 0xbc, 0x43, - 0xa6, 0x0c, 0xa5, 0xaf, 0xae, 0x4d, 0x8f, 0xe5, 0xd1, 0xc6, 0xde, 0x17, 0x4f, 0xb3, 0x0c, 0x87, - 0x1b, 0x9f, 0xcc, 0xa3, 0xcd, 0x1d, 0x30, 0x25, 0x39, 0x7d, 0x62, 0x95, 0x3f, 0x9c, 0x47, 0x9b, - 0x9a, 0xe0, 0xeb, 0xa6, 0xf8, 0x43, 0xe6, 0xe3, 0x6f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf8, 0xa7, - 0x82, 0x8b, 0xa5, 0x11, 0x00, 0x00, + // 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, } From 05096de3687ac582bec63860b3dd384acd9149aa Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 15 Jan 2017 14:43:16 -0800 Subject: [PATCH 182/545] Add Result.String --- example/dummy/dummy.go | 2 +- types/result.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 648ef07e..6fdf8785 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,10 +4,10 @@ import ( "encoding/hex" "strings" + "github.com/tendermint/abci/types" . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" - "github.com/tendermint/abci/types" ) type DummyApplication struct { diff --git a/types/result.go b/types/result.go index 571c5bf8..af89058e 100644 --- a/types/result.go +++ b/types/result.go @@ -28,7 +28,11 @@ func (res Result) IsErr() bool { } func (res Result) Error() string { - return fmt.Sprintf("ABCI code:%v, data:%X, log:%v", res.Code, res.Data, res.Log) + return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) +} + +func (res Result) String() string { + return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) } func (res Result) PrependLog(log string) Result { From 235b18d694a0da9cd904c234b216861d14770cba Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 21:58:42 -0800 Subject: [PATCH 183/545] Makefile: add gmt and lint --- Makefile | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d80410ff..9e703971 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,33 @@ -.PHONY: all test get_deps +.PHONY: all test fmt lint get_deps all: protoc install test NOVENDOR = go list github.com/tendermint/abci/... | grep -v /vendor/ 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/... test: - go test `${NOVENDOR}` - bash tests/test.sh + @ go test `${NOVENDOR}` + @ bash tests/test.sh + +fmt: + @ go fmt ./... + +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 From aae3c91e88446f2b0244efefcd5a7ecb518eb877 Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 22:03:27 -0800 Subject: [PATCH 184/545] fmt: run 'make fmt' --- client/client.go | 2 +- client/grpc_client.go | 2 +- client/local_client.go | 2 +- client/socket_client.go | 2 +- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- example/chain_aware/chain_aware_app.go | 2 +- example/chain_aware/chain_aware_test.go | 2 +- example/counter/counter.go | 2 +- example/dummy/dummy_test.go | 2 +- example/dummy/persistent_dummy.go | 2 +- example/example_test.go | 2 +- server/grpc_server.go | 2 +- server/server.go | 2 +- server/socket_server.go | 2 +- tests/benchmarks/parallel/parallel.go | 2 +- tests/benchmarks/simple/simple.go | 2 +- tests/test_app/app.go | 4 ++-- testutil/messages.go | 2 +- 19 files changed, 20 insertions(+), 20 deletions(-) diff --git a/client/client.go b/client/client.go index 8ea29593..cdeb4db0 100644 --- a/client/client.go +++ b/client/client.go @@ -4,8 +4,8 @@ import ( "fmt" "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) type Client interface { diff --git a/client/grpc_client.go b/client/grpc_client.go index 566ee183..1a0e11d2 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -8,8 +8,8 @@ import ( context "golang.org/x/net/context" grpc "google.golang.org/grpc" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) // A stripped copy of the remoteClient that makes diff --git a/client/local_client.go b/client/local_client.go index b787eb36..33dd619b 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -3,8 +3,8 @@ package abcicli import ( "sync" - . "github.com/tendermint/go-common" types "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) type localClient struct { diff --git a/client/socket_client.go b/client/socket_client.go index 9b4f9aed..744b6c0c 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" + . "github.com/tendermint/go-common" ) const ( diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 218224a0..0714380b 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -3,9 +3,9 @@ package main import ( "flag" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" + . "github.com/tendermint/go-common" ) func main() { diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index aecb1138..8167c354 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -3,10 +3,10 @@ package main import ( "flag" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func main() { diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index e3543f13..85ea7129 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -3,9 +3,9 @@ package main import ( "flag" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func main() { diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index f5283a38..942c9ba9 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func TestChainAware(t *testing.T) { diff --git a/example/counter/counter.go b/example/counter/counter.go index 90be6d92..1249f667 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -3,8 +3,8 @@ package counter import ( "encoding/binary" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) type CounterApplication struct { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index d2294347..f745d2ea 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -6,10 +6,10 @@ import ( "sort" "testing" + "github.com/tendermint/abci/types" . "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" - "github.com/tendermint/abci/types" ) func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value string) { diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index fa730bcb..550c5969 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -6,11 +6,11 @@ import ( "strconv" "strings" + "github.com/tendermint/abci/types" . "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 ( diff --git a/example/example_test.go b/example/example_test.go index 1ddefddb..fb15f503 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -10,12 +10,12 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc" - . "github.com/tendermint/go-common" "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" + . "github.com/tendermint/go-common" ) func TestDummy(t *testing.T) { diff --git a/server/grpc_server.go b/server/grpc_server.go index 1acd45a3..07704c32 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -6,8 +6,8 @@ import ( "google.golang.org/grpc" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 diff --git a/server/server.go b/server/server.go index 49676747..6de8747b 100644 --- a/server/server.go +++ b/server/server.go @@ -3,8 +3,8 @@ package server import ( "fmt" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func NewServer(protoAddr, transport string, app types.Application) (Service, error) { diff --git a/server/socket_server.go b/server/socket_server.go index bd26a18a..1ef47859 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -8,8 +8,8 @@ import ( "strings" "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 5960d529..51d9a636 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -5,8 +5,8 @@ import ( "fmt" //"encoding/hex" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func main() { diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index fb536730..b1b71fb7 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -8,8 +8,8 @@ import ( "reflect" //"encoding/hex" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func main() { diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 59d5b0e7..b84b9386 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -5,10 +5,10 @@ import ( "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-common" + "github.com/tendermint/go-process" ) //---------------------------------------- diff --git a/testutil/messages.go b/testutil/messages.go index 1036e48e..0cdddb44 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" ) //---------------------------------------- From c65bb21a51c53bc2566a1eea95473e3c915c6c7b Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 22:33:48 -0800 Subject: [PATCH 185/545] Makefile: add 'build' target --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9e703971..45d0450a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all test fmt lint get_deps +.PHONY: all build test fmt lint get_deps all: protoc install test @@ -10,6 +10,9 @@ protoc: install: @ go install github.com/tendermint/abci/cmd/... +build: + @ go build -i github.com/tendermint/abci/cmd/... + test: @ go test `${NOVENDOR}` @ bash tests/test.sh From fcaa545e1ef4d68ae35dc064693da7df9b832204 Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 22:48:24 -0800 Subject: [PATCH 186/545] lint: remove dot import (go-common) Spell out the package explicitly. This commit is totally textual, and does not change any logic. The swiss-army knife package may serve a kick-start in early stage development. But as the codebase growing, we might want to retire it gradually: For simple wrapping functions, just inline it on the call site. For larger pice of code, make it an independent package. --- client/client.go | 4 ++-- client/grpc_client.go | 12 ++++++------ client/local_client.go | 6 +++--- client/socket_client.go | 16 ++++++++-------- cmd/abci-cli/tmsp-cli.go | 10 +++++----- cmd/counter/main.go | 6 +++--- cmd/dummy/main.go | 6 +++--- example/chain_aware/chain_aware_app.go | 8 ++++---- example/chain_aware/chain_aware_test.go | 4 ++-- example/counter/counter.go | 18 +++++++++--------- example/dummy/dummy.go | 4 ++-- example/dummy/dummy_test.go | 6 +++--- example/dummy/persistent_dummy.go | 18 +++++++++--------- example/example_test.go | 13 +++++++------ server/grpc_server.go | 8 ++++---- server/server.go | 6 +++--- server/socket_server.go | 10 +++++----- tests/benchmarks/parallel/parallel.go | 13 ++++++------- tests/benchmarks/simple/simple.go | 11 +++++------ tests/test_app/app.go | 18 +++++++++--------- 20 files changed, 98 insertions(+), 99 deletions(-) diff --git a/client/client.go b/client/client.go index cdeb4db0..dc70645e 100644 --- a/client/client.go +++ b/client/client.go @@ -5,11 +5,11 @@ import ( "sync" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) type Client interface { - Service + common.Service SetResponseCallback(Callback) Error() error diff --git a/client/grpc_client.go b/client/grpc_client.go index 1a0e11d2..c48ebbcb 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -9,13 +9,13 @@ import ( grpc "google.golang.org/grpc" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) // A stripped copy of the remoteClient that makes // synchronous calls using grpc type grpcClient struct { - BaseService + common.BaseService mustConnect bool client types.ABCIApplicationClient @@ -31,13 +31,13 @@ func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { addr: addr, mustConnect: mustConnect, } - cli.BaseService = *NewBaseService(nil, "grpcClient", cli) + cli.BaseService = *common.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 common.Connect(addr) } func (cli *grpcClient) OnStart() error { @@ -50,7 +50,7 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - log.Warn(Fmt("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) + log.Warn(common.Fmt("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -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(common.Fmt("Stopping abci.grpcClient for error: %v", err.Error())) cli.Stop() } diff --git a/client/local_client.go b/client/local_client.go index 33dd619b..235e3fce 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -4,11 +4,11 @@ import ( "sync" types "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) type localClient struct { - BaseService + common.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 = *common.NewBaseService(log, "localClient", cli) return cli } diff --git a/client/socket_client.go b/client/socket_client.go index 744b6c0c..9309b67a 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -11,7 +11,7 @@ import ( "time" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "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 + common.BaseService reqQueue chan *ReqRes - flushTimer *ThrottleTimer + flushTimer *common.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: common.NewThrottleTimer("socketClient", flushThrottleMS), mustConnect: mustConnect, addr: addr, reqSent: list.New(), resCb: nil, } - cli.BaseService = *NewBaseService(nil, "socketClient", cli) + cli.BaseService = *common.NewBaseService(nil, "socketClient", cli) _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err @@ -65,12 +65,12 @@ func (cli *socketClient) OnStart() error { var conn net.Conn RETRY_LOOP: for { - conn, err = Connect(cli.addr) + conn, err = common.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)) + log.Warn(common.Fmt("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -109,7 +109,7 @@ func (cli *socketClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(Fmt("Stopping abci.socketClient for error: %v", err.Error())) + log.Warn(common.Fmt("Stopping abci.socketClient for error: %v", err.Error())) cli.Stop() } diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index 39dace9f..99d22a08 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -11,7 +11,7 @@ import ( "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" "github.com/urfave/cli" ) @@ -135,7 +135,7 @@ func main() { app.Before = before err := app.Run(os.Args) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } } @@ -145,7 +145,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()) + common.Exit(err.Error()) } } return nil @@ -244,7 +244,7 @@ func cmdSetOption(c *cli.Context) error { 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) + rsp := newResponse(res, common.Fmt("%s=%s", args[0], args[1]), false) printResponse(c, rsp) return nil } @@ -284,7 +284,7 @@ func cmdCheckTx(c *cli.Context) error { // Get application Merkle root hash func cmdCommit(c *cli.Context) error { res := client.CommitSync() - rsp := newResponse(res, Fmt("0x%X", res.Data), false) + rsp := newResponse(res, common.Fmt("0x%X", res.Data), false) printResponse(c, rsp) return nil } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 0714380b..24abc5de 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -5,7 +5,7 @@ import ( "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func main() { @@ -19,11 +19,11 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } // Wait forever - TrapSignal(func() { + common.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 8167c354..503cf73b 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func main() { @@ -27,11 +27,11 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } // Wait forever - TrapSignal(func() { + common.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 85ea7129..c0dc0d6e 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -5,7 +5,7 @@ import ( "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func main() { @@ -17,11 +17,11 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } // Wait forever - TrapSignal(func() { + common.TrapSignal(func() { // Cleanup srv.Stop() }) @@ -58,7 +58,7 @@ func (app *ChainAwareApplication) Commit() types.Result { } func (app *ChainAwareApplication) Query(query []byte) types.Result { - return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "") + return types.NewResultOK([]byte(common.Fmt("%d,%d", app.beginCount, app.endCount)), "") } func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index 942c9ba9..a19dd781 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func TestChainAware(t *testing.T) { @@ -25,7 +25,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())) + common.Exit(Fmt("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() diff --git a/example/counter/counter.go b/example/counter/counter.go index 1249f667..02ff00ee 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) type CounterApplication struct { @@ -18,7 +18,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: common.Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } func (app *CounterApplication) SetOption(key string, value string) (log string) { @@ -31,13 +31,13 @@ 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(common.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(common.Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) } } app.txCount += 1 @@ -47,13 +47,13 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.Result { 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(common.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(common.Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) } } return types.OK @@ -76,10 +76,10 @@ func (app *CounterApplication) Query(query []byte) types.Result { switch queryStr { case "hash": - return types.NewResultOK(nil, Fmt("%v", app.hashCount)) + return types.NewResultOK(nil, common.Fmt("%v", app.hashCount)) case "tx": - return types.NewResultOK(nil, Fmt("%v", app.txCount)) + return types.NewResultOK(nil, common.Fmt("%v", app.txCount)) } - return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) + return types.ErrUnknownRequest.SetLog(common.Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 6fdf8785..c49353e1 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -5,7 +5,7 @@ import ( "strings" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" ) @@ -20,7 +20,7 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info() (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: Fmt("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: common.Fmt("{\"size\":%v}", app.state.Size())} } func (app *DummyApplication) SetOption(key string, value string) (log string) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index f745d2ea..9236068e 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" ) @@ -107,8 +107,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(common.Fmt("test%d", i))).PubKey().Bytes() + power := common.RandInt() vals[i] = &types.Validator{pubkey, uint64(power)} } // iniitalize with the first nInit diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 550c5969..b7c1eb4b 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" dbm "github.com/tendermint/go-db" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" @@ -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)) + common.Exit(common.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) + common.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(common.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(common.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(common.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(common.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(common.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(common.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 fb15f503..94549994 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -7,15 +7,16 @@ import ( "testing" "time" - "golang.org/x/net/context" "google.golang.org/grpc" + "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" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func TestDummy(t *testing.T) { @@ -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())) + common.Exit(common.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())) + common.Exit(common.Fmt("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() @@ -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())) + common.Exit(common.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())) + common.Exit(common.Fmt("Error dialing GRPC server: %v", err.Error())) } defer conn.Close() diff --git a/server/grpc_server.go b/server/grpc_server.go index 07704c32..3893b20b 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -7,13 +7,13 @@ import ( "google.golang.org/grpc" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 type GRPCServer struct { - BaseService + common.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) (common.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 = *common.NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } diff --git a/server/server.go b/server/server.go index 6de8747b..1d42e7d5 100644 --- a/server/server.go +++ b/server/server.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "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) (common.Service, error) { + var s common.Service var err error switch transport { case "socket": diff --git a/server/socket_server.go b/server/socket_server.go index 1ef47859..06bf0398 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -9,13 +9,13 @@ import ( "sync" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 type SocketServer struct { - BaseService + common.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) (common.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 = *common.NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } @@ -100,7 +100,7 @@ func (s *SocketServer) acceptConnectionsRoutine() { if !s.IsRunning() { return // Ignore error from listener closing. } - Exit("Failed to accept connection: " + err.Error()) + common.Exit("Failed to accept connection: " + err.Error()) } else { log.Notice("Accepted a new connection") } diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 51d9a636..9b7176f3 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -3,17 +3,16 @@ package main import ( "bufio" "fmt" - //"encoding/hex" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func main() { - conn, err := Connect("unix://test.sock") + conn, err := common.Connect("unix://test.sock") if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } // Read a bunch of responses @@ -23,7 +22,7 @@ func main() { var res = &types.Response{} err := types.ReadMessage(conn, res) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } counter += 1 if counter%1000 == 0 { @@ -40,11 +39,11 @@ func main() { err := types.WriteMessage(req, bufWriter) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } err = bufWriter.Flush() if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } counter += 1 diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index b1b71fb7..5076dc7a 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -6,17 +6,16 @@ import ( "fmt" "net" "reflect" - //"encoding/hex" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" ) func main() { - conn, err := Connect("unix://test.sock") + conn, err := common.Connect("unix://test.sock") if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } // Make a bunch of requests @@ -25,7 +24,7 @@ func main() { req := types.ToRequestEcho("foobar") _, err := makeRequest(conn, req) if err != nil { - Exit(err.Error()) + common.Exit(err.Error()) } counter += 1 if counter%1000 == 0 { @@ -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, errors.New(common.Fmt("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 b84b9386..ef932278 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + common "github.com/tendermint/go-common" "github.com/tendermint/go-process" ) @@ -46,7 +46,7 @@ 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(common.Fmt("setting %v=%v: \nlog: %v", key, value, log)) } } @@ -54,10 +54,10 @@ 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(common.Fmt("committing %v\nlog: %v", log)) } if !bytes.Equal(res.Data, hashExp) { - panic(Fmt("Commit hash was unexpected. Got %X expected %X", + panic(common.Fmt("Commit hash was unexpected. Got %X expected %X", data, hashExp)) } } @@ -66,11 +66,11 @@ func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da 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(common.Fmt("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(common.Fmt("DeliverTx response data was unexpected. Got %X expected %X", data, dataExp)) } } @@ -79,14 +79,14 @@ func CheckTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, data 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(common.Fmt("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(common.Fmt("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(common.Fmt("CheckTx response data was unexpected. Got %X expected %X", data, dataExp)) } } From 1150bbfe367cc4596e4fe4d15c8e7d2ff9c61670 Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 22:59:46 -0800 Subject: [PATCH 187/545] lint: s/common.Fmt/fmt.Sprintf --- client/grpc_client.go | 5 +++-- client/socket_client.go | 4 ++-- cmd/abci-cli/tmsp-cli.go | 4 ++-- example/chain_aware/chain_aware_app.go | 3 ++- example/counter/counter.go | 18 +++++++++--------- example/dummy/dummy.go | 4 ++-- example/dummy/dummy_test.go | 3 ++- example/dummy/persistent_dummy.go | 15 ++++++++------- example/example_test.go | 8 ++++---- tests/benchmarks/simple/simple.go | 2 +- tests/test_app/app.go | 16 ++++++++-------- 11 files changed, 43 insertions(+), 39 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index c48ebbcb..3f568ac2 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -1,6 +1,7 @@ package abcicli import ( + "fmt" "net" "sync" "time" @@ -50,7 +51,7 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - log.Warn(common.Fmt("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) + log.Warn(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -93,7 +94,7 @@ func (cli *grpcClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(common.Fmt("Stopping abci.grpcClient for error: %v", err.Error())) + log.Warn(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error())) cli.Stop() } diff --git a/client/socket_client.go b/client/socket_client.go index 9309b67a..2ed51ef4 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -70,7 +70,7 @@ RETRY_LOOP: if cli.mustConnect { return err } else { - log.Warn(common.Fmt("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) + log.Warn(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -109,7 +109,7 @@ func (cli *socketClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(common.Fmt("Stopping abci.socketClient for error: %v", err.Error())) + log.Warn(fmt.Sprintf("Stopping abci.socketClient for error: %v", err.Error())) cli.Stop() } diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index 99d22a08..d2227a68 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -244,7 +244,7 @@ func cmdSetOption(c *cli.Context) error { return errors.New("Command set_option takes 2 arguments (key, value)") } res := client.SetOptionSync(args[0], args[1]) - rsp := newResponse(res, common.Fmt("%s=%s", args[0], args[1]), false) + rsp := newResponse(res, fmt.Sprintf("%s=%s", args[0], args[1]), false) printResponse(c, rsp) return nil } @@ -284,7 +284,7 @@ func cmdCheckTx(c *cli.Context) error { // Get application Merkle root hash func cmdCommit(c *cli.Context) error { res := client.CommitSync() - rsp := newResponse(res, common.Fmt("0x%X", res.Data), false) + rsp := newResponse(res, fmt.Sprintf("0x%X", res.Data), false) printResponse(c, rsp) return nil } diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index c0dc0d6e..534135d1 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -2,6 +2,7 @@ package main import ( "flag" + "fmt" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" @@ -58,7 +59,7 @@ func (app *ChainAwareApplication) Commit() types.Result { } func (app *ChainAwareApplication) Query(query []byte) types.Result { - return types.NewResultOK([]byte(common.Fmt("%d,%d", app.beginCount, app.endCount)), "") + return types.NewResultOK([]byte(fmt.Sprintf("%d,%d", app.beginCount, app.endCount)), "") } func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { diff --git a/example/counter/counter.go b/example/counter/counter.go index 02ff00ee..03861d0f 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -2,9 +2,9 @@ package counter import ( "encoding/binary" + "fmt" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" ) type CounterApplication struct { @@ -18,7 +18,7 @@ func NewCounterApplication(serial bool) *CounterApplication { } func (app *CounterApplication) Info() types.ResponseInfo { - return types.ResponseInfo{Data: common.Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} + return types.ResponseInfo{Data: fmt.Sprintf("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } func (app *CounterApplication) SetOption(key string, value string) (log string) { @@ -31,13 +31,13 @@ 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(common.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ErrEncodingError.SetLog(fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))) } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.ErrBadNonce.SetLog(common.Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) + return types.ErrBadNonce.SetLog(fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) } } app.txCount += 1 @@ -47,13 +47,13 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.Result { func (app *CounterApplication) CheckTx(tx []byte) types.Result { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(common.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ErrEncodingError.SetLog(fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))) } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.ErrBadNonce.SetLog(common.Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) + return types.ErrBadNonce.SetLog(fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) } } return types.OK @@ -76,10 +76,10 @@ func (app *CounterApplication) Query(query []byte) types.Result { switch queryStr { case "hash": - return types.NewResultOK(nil, common.Fmt("%v", app.hashCount)) + return types.NewResultOK(nil, fmt.Sprintf("%v", app.hashCount)) case "tx": - return types.NewResultOK(nil, common.Fmt("%v", app.txCount)) + return types.NewResultOK(nil, fmt.Sprintf("%v", app.txCount)) } - return types.ErrUnknownRequest.SetLog(common.Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) + return types.ErrUnknownRequest.SetLog(fmt.Sprintf("Invalid nonce. Expected hash or tx, got %v", queryStr)) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index c49353e1..b514e43c 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -2,10 +2,10 @@ package dummy import ( "encoding/hex" + "fmt" "strings" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" ) @@ -20,7 +20,7 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info() (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: common.Fmt("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} } func (app *DummyApplication) SetOption(key string, value string) (log string) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 9236068e..ca1ec7f9 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -2,6 +2,7 @@ package dummy import ( "bytes" + "fmt" "io/ioutil" "sort" "testing" @@ -107,7 +108,7 @@ func TestValSetChanges(t *testing.T) { nInit := 5 vals := make([]*types.Validator, total) for i := 0; i < total; i++ { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(common.Fmt("test%d", i))).PubKey().Bytes() + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(fmt.Sprintf("test%d", i))).PubKey().Bytes() power := common.RandInt() vals[i] = &types.Validator{pubkey, uint64(power)} } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index b7c1eb4b..f7302b9d 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,6 +3,7 @@ package dummy import ( "bytes" "encoding/hex" + "fmt" "strconv" "strings" @@ -135,7 +136,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 - common.Exit(common.Fmt("Data has been corrupted or its spec has changed: %v\n", *err)) + common.Exit(fmt.Sprintf("Data has been corrupted or its spec has changed: %v\n", *err)) } // TODO: ensure that buf is completely read. } @@ -173,7 +174,7 @@ func (app *PersistentDummyApplication) Validators() (validators []*types.Validat } func MakeValSetChangeTx(pubkey []byte, power uint64) []byte { - return []byte(common.Fmt("val:%X/%d", pubkey, power)) + return []byte(fmt.Sprintf("val:%X/%d", pubkey, power)) } func isValidatorTx(tx []byte) bool { @@ -188,16 +189,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(common.Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) + return types.ErrEncodingError.SetLog(fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) } pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] pubkey, err := hex.DecodeString(pubkeyS) if err != nil { - return types.ErrEncodingError.SetLog(common.Fmt("Pubkey (%s) is invalid hex", pubkeyS)) + return types.ErrEncodingError.SetLog(fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)) } power, err := strconv.Atoi(powerS) if err != nil { - return types.ErrEncodingError.SetLog(common.Fmt("Power (%s) is not an int", powerS)) + return types.ErrEncodingError.SetLog(fmt.Sprintf("Power (%s) is not an int", powerS)) } // update @@ -210,14 +211,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(common.Fmt("Cannot remove non-existent validator %X", key)) + return types.ErrUnauthorized.SetLog(fmt.Sprintf("Cannot remove non-existent validator %X", key)) } app.app.state.Remove(key) } else { // add or update validator value := bytes.NewBuffer(make([]byte, 0)) if err := types.WriteMessage(v, value); err != nil { - return types.ErrInternalError.SetLog(common.Fmt("Error encoding validator: %v", err)) + return types.ErrInternalError.SetLog(fmt.Sprintf("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 94549994..f47962fb 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -41,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 { - common.Exit(common.Fmt("Error starting socket server: %v", err.Error())) + common.Exit(fmt.Sprintf("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 { - common.Exit(common.Fmt("Error starting socket client: %v", err.Error())) + common.Exit(fmt.Sprintf("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() @@ -114,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 { - common.Exit(common.Fmt("Error starting GRPC server: %v", err.Error())) + common.Exit(fmt.Sprintf("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 { - common.Exit(common.Fmt("Error dialing GRPC server: %v", err.Error())) + common.Exit(fmt.Sprintf("Error dialing GRPC server: %v", err.Error())) } defer conn.Close() diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 5076dc7a..d99c1b56 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -62,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(common.Fmt("Expected flush response but got something else: %v", reflect.TypeOf(resFlush))) + return nil, errors.New(fmt.Sprintf("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 ef932278..8651cd4b 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -46,7 +46,7 @@ func SetOption(client abcicli.Client, key, value string) { res := client.SetOptionSync(key, value) _, _, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(common.Fmt("setting %v=%v: \nlog: %v", key, value, log)) + panic(fmt.Sprintf("setting %v=%v: \nlog: %v", key, value, log)) } } @@ -54,10 +54,10 @@ func Commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(common.Fmt("committing %v\nlog: %v", log)) + panic(fmt.Sprintf("committing %v\nlog: %v", log)) } if !bytes.Equal(res.Data, hashExp) { - panic(common.Fmt("Commit hash was unexpected. Got %X expected %X", + panic(fmt.Sprintf("Commit hash was unexpected. Got %X expected %X", data, hashExp)) } } @@ -66,11 +66,11 @@ func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da res := client.DeliverTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if code != codeExp { - panic(common.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(common.Fmt("DeliverTx response data was unexpected. Got %X expected %X", + panic(fmt.Sprintf("DeliverTx response data was unexpected. Got %X expected %X", data, dataExp)) } } @@ -79,14 +79,14 @@ func CheckTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, data res := client.CheckTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(common.Fmt("checking tx %X: %v\nlog: %v", txBytes, log)) + panic(fmt.Sprintf("checking tx %X: %v\nlog: %v", txBytes, log)) } if code != codeExp { - panic(common.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(common.Fmt("CheckTx response data was unexpected. Got %X expected %X", + panic(fmt.Sprintf("CheckTx response data was unexpected. Got %X expected %X", data, dataExp)) } } From 9134905f42da8fd5829fbcfe33907b9f35d8fd43 Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 23:09:33 -0800 Subject: [PATCH 188/545] cleanup: replace common.Exit with log.Crit or log.Fatal Later we can pick another logger that has fatal, like zap? --- cmd/abci-cli/tmsp-cli.go | 6 +++--- cmd/counter/main.go | 3 ++- cmd/dummy/main.go | 3 ++- example/chain_aware/chain_aware_app.go | 3 ++- example/chain_aware/chain_aware_test.go | 5 +++-- example/dummy/persistent_dummy.go | 2 +- example/example_test.go | 11 ++++++----- server/socket_server.go | 2 +- tests/benchmarks/parallel/parallel.go | 9 +++++---- tests/benchmarks/simple/simple.go | 5 +++-- 10 files changed, 28 insertions(+), 21 deletions(-) diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index d2227a68..a5e32d0e 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -6,12 +6,12 @@ import ( "errors" "fmt" "io" + "log" "os" "strings" "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" "github.com/urfave/cli" ) @@ -135,7 +135,7 @@ func main() { app.Before = before err := app.Run(os.Args) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } } @@ -145,7 +145,7 @@ func before(c *cli.Context) error { var err error client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } } return nil diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 24abc5de..c547d372 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "log" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" @@ -19,7 +20,7 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } // Wait forever diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 503cf73b..71102e1a 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "log" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" @@ -27,7 +28,7 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } // Wait forever diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 534135d1..92fdad3d 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "log" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" @@ -18,7 +19,7 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } // Wait forever diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index a19dd781..d3ece608 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -1,6 +1,8 @@ package main import ( + "fmt" + "log" "strconv" "strings" "testing" @@ -8,7 +10,6 @@ import ( "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" ) func TestChainAware(t *testing.T) { @@ -25,7 +26,7 @@ func TestChainAware(t *testing.T) { // Connect to the socket client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { - common.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() diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index f7302b9d..40c85aea 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -136,7 +136,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 - common.Exit(fmt.Sprintf("Data has been corrupted or its spec has changed: %v\n", *err)) + log.Crit(fmt.Sprintf("Data has been corrupted or its spec has changed: %v\n", *err)) } // TODO: ensure that buf is completely read. } diff --git a/example/example_test.go b/example/example_test.go index f47962fb..f31b3974 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -2,6 +2,7 @@ package example import ( "fmt" + "log" "net" "reflect" "testing" @@ -41,14 +42,14 @@ func testStream(t *testing.T, app types.Application) { // Start the listener server, err := server.NewSocketServer("unix://test.sock", app) if err != nil { - common.Exit(fmt.Sprintf("Error starting socket server: %v", err.Error())) + log.Fatal(fmt.Sprintf("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 { - common.Exit(fmt.Sprintf("Error starting socket client: %v", err.Error())) + log.Fatal(fmt.Sprintf("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() @@ -104,7 +105,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 common.Connect(addr) } func testGRPCSync(t *testing.T, app *types.GRPCApplication) { @@ -114,14 +115,14 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { // Start the listener server, err := server.NewGRPCServer("unix://test.sock", app) if err != nil { - common.Exit(fmt.Sprintf("Error starting GRPC server: %v", err.Error())) + log.Fatal(fmt.Sprintf("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 { - common.Exit(fmt.Sprintf("Error dialing GRPC server: %v", err.Error())) + log.Fatal(fmt.Sprintf("Error dialing GRPC server: %v", err.Error())) } defer conn.Close() diff --git a/server/socket_server.go b/server/socket_server.go index 06bf0398..8fe445cd 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -100,7 +100,7 @@ func (s *SocketServer) acceptConnectionsRoutine() { if !s.IsRunning() { return // Ignore error from listener closing. } - common.Exit("Failed to accept connection: " + err.Error()) + log.Crit("Failed to accept connection: " + err.Error()) } else { log.Notice("Accepted a new connection") } diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 9b7176f3..88d19f32 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -3,6 +3,7 @@ package main import ( "bufio" "fmt" + "log" "github.com/tendermint/abci/types" common "github.com/tendermint/go-common" @@ -12,7 +13,7 @@ func main() { conn, err := common.Connect("unix://test.sock") if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } // Read a bunch of responses @@ -22,7 +23,7 @@ func main() { var res = &types.Response{} err := types.ReadMessage(conn, res) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } counter += 1 if counter%1000 == 0 { @@ -39,11 +40,11 @@ func main() { err := types.WriteMessage(req, bufWriter) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } err = bufWriter.Flush() if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } counter += 1 diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index d99c1b56..bd97567d 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" "fmt" + "log" "net" "reflect" @@ -15,7 +16,7 @@ func main() { conn, err := common.Connect("unix://test.sock") if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } // Make a bunch of requests @@ -24,7 +25,7 @@ func main() { req := types.ToRequestEcho("foobar") _, err := makeRequest(conn, req) if err != nil { - common.Exit(err.Error()) + log.Fatal(err.Error()) } counter += 1 if counter%1000 == 0 { From af2a66b2263425461fc955fe9cb3726a0693caef Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Mon, 16 Jan 2017 23:23:06 -0800 Subject: [PATCH 189/545] test_app: unexport internal function. This reverts commit 24c9b2761d7da5ab5084310f0cb3e51c7fc9738d. --- tests/test_app/app.go | 16 +++++++--------- tests/test_app/main.go | 30 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 8651cd4b..87b74ead 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/abci/client" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" "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,7 +40,7 @@ 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() { @@ -50,7 +48,7 @@ func SetOption(client abcicli.Client, key, value string) { } } -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() { @@ -62,7 +60,7 @@ func Commit(client abcicli.Client, hashExp []byte) { } } -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 { @@ -75,7 +73,7 @@ func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da } } -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() { diff --git a/tests/test_app/main.go b/tests/test_app/main.go index 05f66b07..376c02fe 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}) } From 55cb08722df2e06ecad6a66ddb0b43f3c791aa71 Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Tue, 17 Jan 2017 00:26:32 -0800 Subject: [PATCH 190/545] lint: s/+=1/++, remove else clauses --- client/grpc_client.go | 21 +++++++++------------ client/socket_client.go | 22 +++++++++------------- example/chain_aware/chain_aware_app.go | 4 ++-- example/counter/counter.go | 12 +++++------- example/example_test.go | 4 ++-- server/socket_server.go | 2 +- tests/benchmarks/parallel/parallel.go | 4 ++-- tests/benchmarks/simple/simple.go | 5 ++--- 8 files changed, 32 insertions(+), 42 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 3f568ac2..ec6dcdb7 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -50,11 +50,10 @@ RETRY_LOOP: if err != nil { if cli.mustConnect { return err - } else { - log.Warn(fmt.Sprintf("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) @@ -268,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) { @@ -335,9 +333,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/socket_client.go b/client/socket_client.go index 2ed51ef4..a0def235 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -69,11 +69,10 @@ RETRY_LOOP: if err != nil { if cli.mustConnect { return err - } else { - log.Warn(fmt.Sprintf("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() { @@ -298,11 +296,10 @@ func (cli *socketClient) 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 *socketClient) SetOptionSync(key string, value string) (res types.Result) { @@ -379,11 +376,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/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 92fdad3d..a9a23375 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -64,12 +64,12 @@ func (app *ChainAwareApplication) Query(query []byte) types.Result { } func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { - app.beginCount += 1 + app.beginCount++ return } func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { - app.endCount += 1 + app.endCount++ return } diff --git a/example/counter/counter.go b/example/counter/counter.go index 03861d0f..00e71f38 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -40,7 +40,7 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.Result { return types.ErrBadNonce.SetLog(fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) } } - app.txCount += 1 + app.txCount++ return types.OK } @@ -60,15 +60,13 @@ func (app *CounterApplication) CheckTx(tx []byte) types.Result { } 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 { diff --git a/example/example_test.go b/example/example_test.go index f31b3974..b60fc276 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -60,7 +60,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) } @@ -135,7 +135,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/server/socket_server.go b/server/socket_server.go index 8fe445cd..070fba8c 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -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 diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index 88d19f32..ac8d4e9e 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -25,7 +25,7 @@ func main() { if err != nil { log.Fatal(err.Error()) } - counter += 1 + counter++ if counter%1000 == 0 { fmt.Println("Read", counter) } @@ -47,7 +47,7 @@ func main() { 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 bd97567d..75b66923 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "errors" "fmt" "log" "net" @@ -27,7 +26,7 @@ func main() { if err != nil { 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.Sprintf("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 From 98c4679f39414a3ff7a1896aab6884f54f7d820b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 10 Jan 2017 15:29:47 +0100 Subject: [PATCH 191/545] Fixed Makefile to cleanup after run --- .gitignore | 1 + Makefile | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d2d414be..920af762 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.swo *.pyc +vendor diff --git a/Makefile b/Makefile index d80410ff..4db16ccd 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,8 @@ install: go install github.com/tendermint/abci/cmd/... test: - go test `${NOVENDOR}` + find . -name test.sock -exec rm {} \; + go test -p 1 `${NOVENDOR}` bash tests/test.sh test_integrations: get_vendor_deps install test From 58ea995032ccb4098fe56b904a41f34de879981e Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 10 Jan 2017 15:49:26 +0100 Subject: [PATCH 192/545] Begin adding proof calls --- client/client.go | 2 ++ client/grpc_client.go | 18 ++++++++++++++++++ client/local_client.go | 17 +++++++++++++++++ client/socket_client.go | 15 +++++++++++++++ cmd/abci-cli/tmsp-cli.go | 19 +++++++++++++++++++ example/chain_aware/chain_aware_app.go | 4 ++++ example/counter/counter.go | 4 ++++ example/dummy/dummy.go | 4 ++++ example/dummy/persistent_dummy.go | 4 ++++ example/nil/nil_app.go | 4 ++++ server/socket_server.go | 3 +++ types/application.go | 8 ++++++++ types/messages.go | 12 ++++++++++++ types/types.proto | 19 +++++++++++++++++-- 14 files changed, 131 insertions(+), 2 deletions(-) diff --git a/client/client.go b/client/client.go index 8ea29593..a8bc8ea8 100644 --- a/client/client.go +++ b/client/client.go @@ -21,6 +21,7 @@ type Client interface { DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes QueryAsync(tx []byte) *ReqRes + ProofAsync(tx []byte) *ReqRes CommitAsync() *ReqRes FlushSync() error @@ -30,6 +31,7 @@ type Client interface { DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) QuerySync(tx []byte) (res types.Result) + ProofSync(tx []byte) (res types.Result) CommitSync() (res types.Result) InitChainAsync(validators []*types.Validator) *ReqRes diff --git a/client/grpc_client.go b/client/grpc_client.go index 566ee183..740623c6 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -182,6 +182,15 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}}) } +func (cli *grpcClient) ProofAsync(key []byte) *ReqRes { + req := types.ToRequestProof(key) + res, err := cli.client.Proof(context.Background(), req.GetProof(), grpc.FailFast(true)) + if err != nil { + cli.StopForError(err) + } + return cli.finishAsyncCall(req, &types.Response{&types.Response_Proof{res}}) +} + func (cli *grpcClient) CommitAsync() *ReqRes { req := types.ToRequestCommit() res, err := cli.client.Commit(context.Background(), req.GetCommit(), grpc.FailFast(true)) @@ -301,6 +310,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) ProofSync(key []byte) (res types.Result) { + reqres := cli.ProofAsync(key) + if res := cli.checkErrGetResult(); res.IsErr() { + return res + } + resp := reqres.Response.GetProof() + 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() { diff --git a/client/local_client.go b/client/local_client.go index b787eb36..8c092cec 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -99,6 +99,16 @@ func (app *localClient) QueryAsync(tx []byte) *ReqRes { ) } +func (app *localClient) ProofAsync(key []byte) *ReqRes { + app.mtx.Lock() + res := app.Application.Proof(key) + app.mtx.Unlock() + return app.callback( + types.ToRequestProof(key), + types.ToResponseQuery(res.Code, res.Data, res.Log), + ) +} + func (app *localClient) CommitAsync() *ReqRes { app.mtx.Lock() res := app.Application.Commit() @@ -192,6 +202,13 @@ func (app *localClient) QuerySync(query []byte) (res types.Result) { return res } +func (app *localClient) ProofSync(key []byte) (res types.Result) { + app.mtx.Lock() + res = app.Application.Proof(key) + app.mtx.Unlock() + return res +} + func (app *localClient) CommitSync() (res types.Result) { app.mtx.Lock() res = app.Application.Commit() diff --git a/client/socket_client.go b/client/socket_client.go index 9b4f9aed..252c8777 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -255,6 +255,10 @@ func (cli *socketClient) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.ToRequestQuery(query)) } +func (cli *socketClient) ProofAsync(key []byte) *ReqRes { + return cli.queueRequest(types.ToRequestProof(key)) +} + func (cli *socketClient) CommitAsync() *ReqRes { return cli.queueRequest(types.ToRequestCommit()) } @@ -345,6 +349,15 @@ func (cli *socketClient) QuerySync(query []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } +func (cli *socketClient) ProofSync(key []byte) (res types.Result) { + reqres := cli.queueRequest(types.ToRequestProof(key)) + cli.FlushSync() + if err := cli.Error(); err != nil { + return types.ErrInternalError.SetLog(err.Error()) + } + resp := reqres.Response.GetProof() + return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} +} func (cli *socketClient) CommitSync() (res types.Result) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() @@ -437,6 +450,8 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { _, ok = res.Value.(*types.Response_Commit) case *types.Request_Query: _, ok = res.Value.(*types.Response_Query) + case *types.Request_Proof: + _, ok = res.Value.(*types.Response_Proof) case *types.Request_InitChain: _, ok = res.Value.(*types.Response_InitChain) case *types.Request_BeginBlock: diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index 39dace9f..d40b510b 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -131,6 +131,13 @@ func main() { return cmdQuery(c) }, }, + { + Name: "proof", + Usage: "Get proof for a key", + Action: func(c *cli.Context) error { + return cmdProof(c) + }, + }, } app.Before = before err := app.Run(os.Args) @@ -305,6 +312,18 @@ func cmdQuery(c *cli.Context) error { return nil } +// Prove application state +func cmdProof(c *cli.Context) error { + args := c.Args() + if len(args) != 1 { + return errors.New("Command proof takes 1 argument") + } + keyBytes := stringOrHexToBytes(c.Args()[0]) + res := client.ProofSync(keyBytes) + printResponse(c, res, string(res.Data), true) + return nil +} + //-------------------------------------------------------------------------------- func printResponse(c *cli.Context, rsp *response) { diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index e3543f13..387a88e8 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -61,6 +61,10 @@ func (app *ChainAwareApplication) Query(query []byte) types.Result { return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "") } +func (app *ChainAwareApplication) Proof(key []byte) types.Result { + return types.NewResultOK(nil, Fmt("Proof is not supported")) +} + func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { app.beginCount += 1 return diff --git a/example/counter/counter.go b/example/counter/counter.go index 90be6d92..e5b17992 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -83,3 +83,7 @@ func (app *CounterApplication) Query(query []byte) types.Result { return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) } + +func (app *CounterApplication) Proof(key []byte) types.Result { + return types.NewResultOK(nil, Fmt("Proof is not supported")) +} diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 6fdf8785..2336add8 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -53,6 +53,10 @@ func (app *DummyApplication) Query(query []byte) types.Result { return types.NewResultOK(wire.JSONBytes(queryResult), "") } +func (app *DummyApplication) Proof(key []byte) types.Result { + return types.NewResultOK(nil, Fmt("TODO: support proof!")) +} + type QueryResult struct { Index int `json:"index"` Value string `json:"value"` diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index fa730bcb..bb8783ee 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -93,6 +93,10 @@ func (app *PersistentDummyApplication) Query(query []byte) types.Result { return app.app.Query(query) } +func (app *PersistentDummyApplication) Proof(key []byte) types.Result { + return types.NewResultOK(nil, Fmt("TODO: support proof!")) +} + // Save the validators in the merkle tree func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) { for _, v := range validators { diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index cd57f0d9..a4d181c0 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -34,3 +34,7 @@ func (app *NilApplication) Commit() types.Result { func (app *NilApplication) Query(query []byte) types.Result { return types.NewResultOK(nil, "") } + +func (app *NilApplication) Proof(key []byte) types.Result { + return types.NewResultOK(nil, "") +} diff --git a/server/socket_server.go b/server/socket_server.go index bd26a18a..046b55ed 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -186,6 +186,9 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Query: res := s.app.Query(r.Query.Query) responses <- types.ToResponseQuery(res.Code, res.Data, res.Log) + case *types.Request_Proof: + res := s.app.Proof(r.Proof.Key, r.Proof.Height) + responses <- types.ToResponseProof(res.Code, res.Data, res.Log) case *types.Request_InitChain: if app, ok := s.app.(types.BlockchainAware); ok { app.InitChain(r.InitChain.Validators) diff --git a/types/application.go b/types/application.go index 4da5e6f7..95f35d4a 100644 --- a/types/application.go +++ b/types/application.go @@ -22,6 +22,9 @@ type Application interface { // Query for state Query(query []byte) Result + // Get proof for state + Proof(key []byte, blockHeight int) Result + // Return the application Merkle root hash Commit() Result } @@ -82,6 +85,11 @@ func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*Resp return &ResponseQuery{r.Code, r.Data, r.Log}, nil } +func (app *GRPCApplication) Proof(ctx context.Context, req *RequestProof) (*ResponseQuery, error) { + r := app.app.Proof(req.Key, req.Height) + return &ResponseProof{r.Code, r.Data, r.Log}, nil +} + func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { r := app.app.Commit() return &ResponseCommit{r.Code, r.Data, r.Log}, nil diff --git a/types/messages.go b/types/messages.go index 84e6ee0b..b445c535 100644 --- a/types/messages.go +++ b/types/messages.go @@ -55,6 +55,12 @@ func ToRequestQuery(queryBytes []byte) *Request { } } +func ToRequestProof(key []byte, blockHeight int) *Request { + return &Request{ + Value: &Request_Proof{&RequestProof{key, blockHeight}}, + } +} + func ToRequestInitChain(validators []*Validator) *Request { return &Request{ Value: &Request_InitChain{&RequestInitChain{validators}}, @@ -129,6 +135,12 @@ func ToResponseQuery(code CodeType, data []byte, log string) *Response { } } +func ToResponseProof(code CodeType, data []byte, log string) *Response { + return &Response{ + Value: &Response_Proof{&ResponseProof{code, data, log}}, + } +} + func ToResponseInitChain() *Response { return &Response{ Value: &Response_InitChain{&ResponseInitChain{}}, diff --git a/types/types.proto b/types/types.proto index b3ff1655..09a2af8f 100644 --- a/types/types.proto +++ b/types/types.proto @@ -6,7 +6,7 @@ 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) @@ -25,6 +25,7 @@ enum MessageType { InitChain = 0x15; BeginBlock = 0x16; EndBlock = 0x17; + Proof = 0x18; } //---------------------------------------- @@ -116,6 +117,12 @@ message RequestQuery{ bytes query = 1; } +message RequestProof{ + bytes key = 1; + int64 height = 2; +} + + message RequestCommit{ } @@ -150,6 +157,7 @@ message Response { ResponseInitChain init_chain = 10; ResponseBeginBlock begin_block = 11; ResponseEndBlock end_block = 12; + ResponseProof proof = 13; } } @@ -193,6 +201,12 @@ message ResponseQuery{ string log = 3; } +message ResponseProof{ + CodeType code = 1; + bytes data = 2; + string log = 3; +} + message ResponseCommit{ CodeType code = 1; bytes data = 2; @@ -222,7 +236,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 { @@ -251,6 +265,7 @@ service ABCIApplication { rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); rpc Query(RequestQuery) returns (ResponseQuery); + rpc Proof(RequestProof) returns (ResponseProof); rpc Commit(RequestCommit) returns (ResponseCommit); rpc InitChain(RequestInitChain) returns (ResponseInitChain); rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); From 7cd39dafea5e2d14d4f6bbab18dbb280f77629a7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 10 Jan 2017 15:59:29 +0100 Subject: [PATCH 193/545] Update protocol buffers --- Makefile | 4 + example/chain_aware/chain_aware_app.go | 2 +- example/counter/counter.go | 2 +- example/dummy/dummy.go | 2 +- example/dummy/persistent_dummy.go | 2 +- example/nil/nil_app.go | 2 +- types/application.go | 4 +- types/messages.go | 2 +- types/types.pb.go | 413 +++++++++++++++++-------- types/types.proto | 2 +- 10 files changed, 301 insertions(+), 134 deletions(-) diff --git a/Makefile b/Makefile index 4db16ccd..740bce9b 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,10 @@ 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 diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 387a88e8..f335e543 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -61,7 +61,7 @@ func (app *ChainAwareApplication) Query(query []byte) types.Result { return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "") } -func (app *ChainAwareApplication) Proof(key []byte) types.Result { +func (app *ChainAwareApplication) Proof(key []byte, blockHeight int64) types.Result { return types.NewResultOK(nil, Fmt("Proof is not supported")) } diff --git a/example/counter/counter.go b/example/counter/counter.go index e5b17992..9ffec400 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -84,6 +84,6 @@ func (app *CounterApplication) Query(query []byte) types.Result { return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) } -func (app *CounterApplication) Proof(key []byte) types.Result { +func (app *CounterApplication) Proof(key []byte, blockHeight int64) types.Result { return types.NewResultOK(nil, Fmt("Proof is not supported")) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 2336add8..ebce1099 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -53,7 +53,7 @@ func (app *DummyApplication) Query(query []byte) types.Result { return types.NewResultOK(wire.JSONBytes(queryResult), "") } -func (app *DummyApplication) Proof(key []byte) types.Result { +func (app *DummyApplication) Proof(key []byte, blockHeight int64) types.Result { return types.NewResultOK(nil, Fmt("TODO: support proof!")) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index bb8783ee..70c0e667 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -93,7 +93,7 @@ func (app *PersistentDummyApplication) Query(query []byte) types.Result { return app.app.Query(query) } -func (app *PersistentDummyApplication) Proof(key []byte) types.Result { +func (app *PersistentDummyApplication) Proof(key []byte, blockHeight int64) types.Result { return types.NewResultOK(nil, Fmt("TODO: support proof!")) } diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index a4d181c0..1088ac96 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -35,6 +35,6 @@ func (app *NilApplication) Query(query []byte) types.Result { return types.NewResultOK(nil, "") } -func (app *NilApplication) Proof(key []byte) types.Result { +func (app *NilApplication) Proof(key []byte, blockHeight int64) types.Result { return types.NewResultOK(nil, "") } diff --git a/types/application.go b/types/application.go index 95f35d4a..5ba440dd 100644 --- a/types/application.go +++ b/types/application.go @@ -23,7 +23,7 @@ type Application interface { Query(query []byte) Result // Get proof for state - Proof(key []byte, blockHeight int) Result + Proof(key []byte, blockHeight int64) Result // Return the application Merkle root hash Commit() Result @@ -85,7 +85,7 @@ func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*Resp return &ResponseQuery{r.Code, r.Data, r.Log}, nil } -func (app *GRPCApplication) Proof(ctx context.Context, req *RequestProof) (*ResponseQuery, error) { +func (app *GRPCApplication) Proof(ctx context.Context, req *RequestProof) (*ResponseProof, error) { r := app.app.Proof(req.Key, req.Height) return &ResponseProof{r.Code, r.Data, r.Log}, nil } diff --git a/types/messages.go b/types/messages.go index b445c535..9e303a71 100644 --- a/types/messages.go +++ b/types/messages.go @@ -55,7 +55,7 @@ func ToRequestQuery(queryBytes []byte) *Request { } } -func ToRequestProof(key []byte, blockHeight int) *Request { +func ToRequestProof(key []byte, blockHeight int64) *Request { return &Request{ Value: &Request_Proof{&RequestProof{key, blockHeight}}, } diff --git a/types/types.pb.go b/types/types.pb.go index 6cae5433..8467a78c 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -17,6 +17,7 @@ It has these top-level messages: RequestDeliverTx RequestCheckTx RequestQuery + RequestProof RequestCommit RequestInitChain RequestBeginBlock @@ -30,6 +31,7 @@ It has these top-level messages: ResponseDeliverTx ResponseCheckTx ResponseQuery + ResponseProof ResponseCommit ResponseInitChain ResponseBeginBlock @@ -81,6 +83,7 @@ const ( MessageType_InitChain MessageType = 21 MessageType_BeginBlock MessageType = 22 MessageType_EndBlock MessageType = 23 + MessageType_Proof MessageType = 24 ) var MessageType_name = map[int32]string{ @@ -97,6 +100,7 @@ var MessageType_name = map[int32]string{ 21: "InitChain", 22: "BeginBlock", 23: "EndBlock", + 24: "Proof", } var MessageType_value = map[string]int32{ "NullMessage": 0, @@ -112,6 +116,7 @@ var MessageType_value = map[string]int32{ "InitChain": 21, "BeginBlock": 22, "EndBlock": 23, + "Proof": 24, } func (x MessageType) String() string { @@ -240,6 +245,7 @@ type Request struct { // *Request_InitChain // *Request_BeginBlock // *Request_EndBlock + // *Request_Proof Value isRequest_Value `protobuf_oneof:"value"` } @@ -285,6 +291,9 @@ type Request_BeginBlock struct { type Request_EndBlock struct { EndBlock *RequestEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,oneof"` } +type Request_Proof struct { + Proof *RequestProof `protobuf:"bytes,12,opt,name=proof,oneof"` +} func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} @@ -297,6 +306,7 @@ func (*Request_Query) isRequest_Value() {} func (*Request_InitChain) isRequest_Value() {} func (*Request_BeginBlock) isRequest_Value() {} func (*Request_EndBlock) isRequest_Value() {} +func (*Request_Proof) isRequest_Value() {} func (m *Request) GetValue() isRequest_Value { if m != nil { @@ -382,6 +392,13 @@ func (m *Request) GetEndBlock() *RequestEndBlock { return nil } +func (m *Request) GetProof() *RequestProof { + if x, ok := m.GetValue().(*Request_Proof); ok { + return x.Proof + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Request_OneofMarshaler, _Request_OneofUnmarshaler, _Request_OneofSizer, []interface{}{ @@ -396,6 +413,7 @@ func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error (*Request_InitChain)(nil), (*Request_BeginBlock)(nil), (*Request_EndBlock)(nil), + (*Request_Proof)(nil), } } @@ -458,6 +476,11 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.EndBlock); err != nil { return err } + case *Request_Proof: + b.EncodeVarint(12<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Proof); err != nil { + return err + } case nil: default: return fmt.Errorf("Request.Value has unexpected type %T", x) @@ -556,6 +579,14 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_EndBlock{msg} return true, err + case 12: // value.proof + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestProof) + err := b.DecodeMessage(msg) + m.Value = &Request_Proof{msg} + return true, err default: return false, nil } @@ -620,6 +651,11 @@ func _Request_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(11<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s + case *Request_Proof: + s := proto.Size(x.Proof) + n += proto.SizeVarint(12<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -731,13 +767,37 @@ func (m *RequestQuery) GetQuery() []byte { return nil } +type RequestProof struct { + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` +} + +func (m *RequestProof) Reset() { *m = RequestProof{} } +func (m *RequestProof) String() string { return proto.CompactTextString(m) } +func (*RequestProof) ProtoMessage() {} +func (*RequestProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *RequestProof) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *RequestProof) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + type RequestCommit struct { } func (m *RequestCommit) Reset() { *m = RequestCommit{} } func (m *RequestCommit) String() string { return proto.CompactTextString(m) } func (*RequestCommit) ProtoMessage() {} -func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } type RequestInitChain struct { Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` @@ -746,7 +806,7 @@ type RequestInitChain struct { func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } func (*RequestInitChain) ProtoMessage() {} -func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *RequestInitChain) GetValidators() []*Validator { if m != nil { @@ -763,7 +823,7 @@ type RequestBeginBlock struct { func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} -func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *RequestBeginBlock) GetHash() []byte { if m != nil { @@ -786,7 +846,7 @@ type RequestEndBlock struct { func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} -func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *RequestEndBlock) GetHeight() uint64 { if m != nil { @@ -809,13 +869,14 @@ type Response struct { // *Response_InitChain // *Response_BeginBlock // *Response_EndBlock + // *Response_Proof Value isResponse_Value `protobuf_oneof:"value"` } func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} -func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } type isResponse_Value interface { isResponse_Value() @@ -857,6 +918,9 @@ type Response_BeginBlock struct { type Response_EndBlock struct { EndBlock *ResponseEndBlock `protobuf:"bytes,12,opt,name=end_block,json=endBlock,oneof"` } +type Response_Proof struct { + Proof *ResponseProof `protobuf:"bytes,13,opt,name=proof,oneof"` +} func (*Response_Exception) isResponse_Value() {} func (*Response_Echo) isResponse_Value() {} @@ -870,6 +934,7 @@ func (*Response_Query) isResponse_Value() {} func (*Response_InitChain) isResponse_Value() {} func (*Response_BeginBlock) isResponse_Value() {} func (*Response_EndBlock) isResponse_Value() {} +func (*Response_Proof) isResponse_Value() {} func (m *Response) GetValue() isResponse_Value { if m != nil { @@ -962,6 +1027,13 @@ func (m *Response) GetEndBlock() *ResponseEndBlock { return nil } +func (m *Response) GetProof() *ResponseProof { + if x, ok := m.GetValue().(*Response_Proof); ok { + return x.Proof + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Response_OneofMarshaler, _Response_OneofUnmarshaler, _Response_OneofSizer, []interface{}{ @@ -977,6 +1049,7 @@ func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) erro (*Response_InitChain)(nil), (*Response_BeginBlock)(nil), (*Response_EndBlock)(nil), + (*Response_Proof)(nil), } } @@ -1044,6 +1117,11 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.EndBlock); err != nil { return err } + case *Response_Proof: + b.EncodeVarint(13<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Proof); err != nil { + return err + } case nil: default: return fmt.Errorf("Response.Value has unexpected type %T", x) @@ -1150,6 +1228,14 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_EndBlock{msg} return true, err + case 13: // value.proof + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseProof) + err := b.DecodeMessage(msg) + m.Value = &Response_Proof{msg} + return true, err default: return false, nil } @@ -1219,6 +1305,11 @@ func _Response_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(12<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s + case *Response_Proof: + s := proto.Size(x.Proof) + n += proto.SizeVarint(13<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -1233,7 +1324,7 @@ type ResponseException struct { func (m *ResponseException) Reset() { *m = ResponseException{} } func (m *ResponseException) String() string { return proto.CompactTextString(m) } func (*ResponseException) ProtoMessage() {} -func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *ResponseException) GetError() string { if m != nil { @@ -1249,7 +1340,7 @@ type ResponseEcho struct { func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } func (*ResponseEcho) ProtoMessage() {} -func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *ResponseEcho) GetMessage() string { if m != nil { @@ -1264,7 +1355,7 @@ type ResponseFlush struct { func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } func (*ResponseFlush) ProtoMessage() {} -func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } type ResponseInfo struct { Data string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` @@ -1276,7 +1367,7 @@ type ResponseInfo struct { func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } func (*ResponseInfo) ProtoMessage() {} -func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *ResponseInfo) GetData() string { if m != nil { @@ -1313,7 +1404,7 @@ type ResponseSetOption struct { func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } func (*ResponseSetOption) ProtoMessage() {} -func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *ResponseSetOption) GetLog() string { if m != nil { @@ -1331,7 +1422,7 @@ type ResponseDeliverTx struct { func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } func (*ResponseDeliverTx) ProtoMessage() {} -func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *ResponseDeliverTx) GetCode() CodeType { if m != nil { @@ -1363,7 +1454,7 @@ type ResponseCheckTx struct { func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } func (*ResponseCheckTx) ProtoMessage() {} -func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *ResponseCheckTx) GetCode() CodeType { if m != nil { @@ -1395,7 +1486,7 @@ type ResponseQuery struct { func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} -func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *ResponseQuery) GetCode() CodeType { if m != nil { @@ -1418,6 +1509,38 @@ func (m *ResponseQuery) GetLog() string { return "" } +type ResponseProof 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"` +} + +func (m *ResponseProof) Reset() { *m = ResponseProof{} } +func (m *ResponseProof) String() string { return proto.CompactTextString(m) } +func (*ResponseProof) ProtoMessage() {} +func (*ResponseProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } + +func (m *ResponseProof) GetCode() CodeType { + if m != nil { + return m.Code + } + return CodeType_OK +} + +func (m *ResponseProof) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseProof) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + type ResponseCommit 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"` @@ -1427,7 +1550,7 @@ type ResponseCommit struct { func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} -func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *ResponseCommit) GetCode() CodeType { if m != nil { @@ -1456,7 +1579,7 @@ type ResponseInitChain struct { func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } func (*ResponseInitChain) ProtoMessage() {} -func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } type ResponseBeginBlock struct { } @@ -1464,7 +1587,7 @@ type ResponseBeginBlock struct { func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} -func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } type ResponseEndBlock struct { Diffs []*Validator `protobuf:"bytes,4,rep,name=diffs" json:"diffs,omitempty"` @@ -1473,7 +1596,7 @@ type ResponseEndBlock struct { func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} -func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *ResponseEndBlock) GetDiffs() []*Validator { if m != nil { @@ -1497,7 +1620,7 @@ type Header struct { func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *Header) GetChainId() string { if m != nil { @@ -1570,7 +1693,7 @@ type BlockID struct { func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} -func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *BlockID) GetHash() []byte { if m != nil { @@ -1594,7 +1717,7 @@ type PartSetHeader struct { func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } func (m *PartSetHeader) GetTotal() uint64 { if m != nil { @@ -1618,7 +1741,7 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1643,6 +1766,7 @@ func init() { proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") + proto.RegisterType((*RequestProof)(nil), "types.RequestProof") proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") proto.RegisterType((*RequestInitChain)(nil), "types.RequestInitChain") proto.RegisterType((*RequestBeginBlock)(nil), "types.RequestBeginBlock") @@ -1656,6 +1780,7 @@ func init() { proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") + proto.RegisterType((*ResponseProof)(nil), "types.ResponseProof") proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") @@ -1686,6 +1811,7 @@ type ABCIApplicationClient interface { DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) + Proof(ctx context.Context, in *RequestProof, opts ...grpc.CallOption) (*ResponseProof, error) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) @@ -1763,6 +1889,15 @@ func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opt return out, nil } +func (c *aBCIApplicationClient) Proof(ctx context.Context, in *RequestProof, opts ...grpc.CallOption) (*ResponseProof, error) { + out := new(ResponseProof) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Proof", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { out := new(ResponseCommit) err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...) @@ -1809,6 +1944,7 @@ type ABCIApplicationServer interface { DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) Query(context.Context, *RequestQuery) (*ResponseQuery, error) + Proof(context.Context, *RequestProof) (*ResponseProof, error) Commit(context.Context, *RequestCommit) (*ResponseCommit, error) InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) @@ -1945,6 +2081,24 @@ func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _ABCIApplication_Proof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestProof) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Proof(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/Proof", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Proof(ctx, req.(*RequestProof)) + } + return interceptor(ctx, in, info, handler) +} + func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestCommit) if err := dec(in); err != nil { @@ -2049,6 +2203,10 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ MethodName: "Query", Handler: _ABCIApplication_Query_Handler, }, + { + MethodName: "Proof", + Handler: _ABCIApplication_Proof_Handler, + }, { MethodName: "Commit", Handler: _ABCIApplication_Commit_Handler, @@ -2073,108 +2231,113 @@ 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, + // 1714 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x6f, 0xe4, 0x48, + 0x15, 0x8e, 0xfb, 0xde, 0xa7, 0x93, 0x4e, 0xe5, 0xe4, 0xe6, 0x34, 0x3c, 0x8c, 0x0c, 0xcb, 0x66, + 0x86, 0x61, 0x06, 0x65, 0xb5, 0x68, 0xc2, 0x22, 0xa4, 0x64, 0x26, 0x9b, 0xb4, 0x56, 0x3b, 0x13, + 0xbc, 0xb3, 0xfb, 0x00, 0x88, 0x96, 0xd3, 0xae, 0xee, 0x36, 0x71, 0x6c, 0x8f, 0x2f, 0xd9, 0x84, + 0x3f, 0xc2, 0x4f, 0xe0, 0x17, 0xf0, 0xc2, 0x13, 0x4f, 0x48, 0xdc, 0x2f, 0x7f, 0x85, 0x3f, 0x80, + 0x4e, 0x55, 0xf9, 0x1a, 0x9b, 0xa7, 0xd9, 0x97, 0x96, 0xeb, 0xdc, 0xaa, 0x4e, 0xd5, 0x77, 0xbe, + 0x3a, 0x5d, 0xb0, 0x15, 0xdf, 0x07, 0x3c, 0x7a, 0x2e, 0x7e, 0x9f, 0x05, 0xa1, 0x1f, 0xfb, 0xd8, + 0x15, 0x03, 0xe3, 0xbf, 0x1d, 0xe8, 0x9b, 0xfc, 0x5d, 0xc2, 0xa3, 0x18, 0x0f, 0xa1, 0xc3, 0xe7, + 0x2b, 0x5f, 0xd7, 0x1e, 0x69, 0x87, 0xa3, 0x23, 0x7c, 0x26, 0xcd, 0x95, 0xf6, 0x6c, 0xbe, 0xf2, + 0x2f, 0xd6, 0x4c, 0x61, 0x81, 0xdf, 0x87, 0xee, 0xc2, 0x4d, 0xa2, 0x95, 0xde, 0x12, 0xa6, 0xdb, + 0x65, 0xd3, 0x4f, 0x49, 0x75, 0xb1, 0x66, 0x4a, 0x1b, 0x0a, 0xeb, 0x78, 0x0b, 0x5f, 0x6f, 0xd7, + 0x85, 0x9d, 0x7a, 0x0b, 0x11, 0x96, 0x2c, 0xf0, 0x05, 0x40, 0xc4, 0xe3, 0x99, 0x1f, 0xc4, 0x8e, + 0xef, 0xe9, 0x1d, 0x61, 0xbf, 0x5f, 0xb6, 0xff, 0x82, 0xc7, 0x6f, 0x84, 0xfa, 0x62, 0xcd, 0x1c, + 0x46, 0xe9, 0x80, 0x3c, 0x6d, 0xee, 0x3a, 0xb7, 0x3c, 0x9c, 0xc5, 0x77, 0x7a, 0xb7, 0xce, 0xf3, + 0x95, 0xd4, 0xbf, 0xbd, 0x23, 0x4f, 0x3b, 0x1d, 0xe0, 0x11, 0x0c, 0xe6, 0x2b, 0x3e, 0xbf, 0x26, + 0xbf, 0x9e, 0xf0, 0xdb, 0x2d, 0xfb, 0xbd, 0x24, 0xad, 0xf0, 0xea, 0xcf, 0xe5, 0x27, 0x3e, 0x83, + 0xde, 0xdc, 0xbf, 0xb9, 0x71, 0x62, 0xbd, 0x2f, 0x3c, 0x76, 0x2a, 0x1e, 0x42, 0x77, 0xb1, 0x66, + 0x2a, 0x2b, 0xda, 0xae, 0x77, 0x09, 0x0f, 0xef, 0xf5, 0x41, 0xdd, 0x76, 0xfd, 0x8c, 0x54, 0xb4, + 0x5d, 0xc2, 0x86, 0x52, 0x71, 0x3c, 0x27, 0x9e, 0xcd, 0x57, 0x96, 0xe3, 0xe9, 0xc3, 0xba, 0x54, + 0xa6, 0x9e, 0x13, 0xbf, 0x24, 0x35, 0xa5, 0xe2, 0xa4, 0x03, 0xfc, 0x04, 0x46, 0x57, 0x7c, 0xe9, + 0x78, 0xb3, 0x2b, 0xd7, 0x9f, 0x5f, 0xeb, 0x20, 0x5c, 0xf5, 0xb2, 0xeb, 0x29, 0x19, 0x9c, 0x92, + 0xfe, 0x62, 0xcd, 0x84, 0xab, 0x6c, 0x84, 0x1f, 0xc3, 0x90, 0x7b, 0xb6, 0x72, 0x1d, 0x09, 0xd7, + 0xbd, 0x0a, 0x02, 0x3c, 0x3b, 0x75, 0x1c, 0x70, 0xf5, 0x4d, 0xa9, 0x05, 0xa1, 0xef, 0x2f, 0xf4, + 0xf5, 0xba, 0xd4, 0x2e, 0x49, 0x45, 0xa9, 0x09, 0x9b, 0xd3, 0x3e, 0x74, 0x6f, 0x2d, 0x37, 0xe1, + 0xc6, 0x87, 0x30, 0x2a, 0xc0, 0x0a, 0x75, 0xe8, 0xdf, 0xf0, 0x28, 0xb2, 0x96, 0x5c, 0x60, 0x6f, + 0x68, 0xa6, 0x43, 0x63, 0x0c, 0xeb, 0x45, 0x50, 0x19, 0x1b, 0x99, 0x23, 0x01, 0xc7, 0xf8, 0x31, + 0xb0, 0x2a, 0x2e, 0x90, 0x41, 0xfb, 0x9a, 0xdf, 0xab, 0x40, 0xf4, 0x89, 0x3b, 0x6a, 0x5a, 0x81, + 0xd6, 0xa1, 0xa9, 0xd6, 0x60, 0x64, 0xbe, 0x19, 0x32, 0x70, 0x0c, 0xad, 0xf8, 0x4e, 0xb8, 0xae, + 0x9b, 0xad, 0xf8, 0xce, 0x78, 0x04, 0xe3, 0x32, 0x0a, 0x1e, 0x58, 0x7c, 0x37, 0x5b, 0xa0, 0x38, + 0x46, 0x9a, 0x4b, 0x1e, 0xb5, 0x34, 0x91, 0x03, 0xe3, 0x45, 0x66, 0x25, 0x76, 0xa4, 0xb8, 0xc6, + 0x75, 0xb9, 0xc6, 0x3d, 0xe8, 0xad, 0xb8, 0xb3, 0x5c, 0xc5, 0x62, 0x91, 0x6d, 0x53, 0x8d, 0x8c, + 0x4d, 0xd8, 0x28, 0xa1, 0xca, 0x78, 0x95, 0x2d, 0x3b, 0x43, 0x01, 0xfe, 0x10, 0xe0, 0xd6, 0x72, + 0x1d, 0xdb, 0x8a, 0xfd, 0x30, 0xd2, 0xb5, 0x47, 0xed, 0xc3, 0xd1, 0x11, 0x53, 0x27, 0xf1, 0x55, + 0xaa, 0x30, 0x0b, 0x36, 0xc6, 0x6b, 0xd8, 0x7a, 0x00, 0x08, 0x44, 0xe8, 0xac, 0xac, 0x68, 0xa5, + 0x96, 0x25, 0xbe, 0xf1, 0x03, 0x5a, 0x97, 0x65, 0xf3, 0x50, 0x95, 0xfa, 0x86, 0x0a, 0x7b, 0x21, + 0x84, 0xa6, 0x52, 0x1a, 0x8f, 0x61, 0xb3, 0x82, 0x92, 0x42, 0x46, 0x14, 0xaf, 0x93, 0x65, 0xf4, + 0x87, 0x2e, 0x0c, 0x4c, 0x1e, 0x05, 0xbe, 0x17, 0x71, 0x7c, 0x01, 0x43, 0x7e, 0x37, 0xe7, 0xb2, + 0xe0, 0xb5, 0x0a, 0x60, 0xa5, 0xcd, 0x59, 0xaa, 0x27, 0xb0, 0x67, 0xc6, 0xf8, 0x58, 0x91, 0x55, + 0x95, 0x81, 0x94, 0x53, 0x91, 0xad, 0x9e, 0xa6, 0x6c, 0xd5, 0xae, 0x54, 0xab, 0xb4, 0xad, 0xd0, + 0xd5, 0x63, 0x45, 0x57, 0x9d, 0xda, 0xc0, 0x25, 0xbe, 0x3a, 0x2e, 0xf1, 0x55, 0xb7, 0x76, 0xf9, + 0x0d, 0x84, 0x75, 0x5c, 0x22, 0xac, 0x5e, 0xad, 0x6b, 0x03, 0x63, 0x7d, 0x54, 0x60, 0xac, 0x7e, + 0xa5, 0x50, 0xa5, 0x63, 0x0d, 0x65, 0x3d, 0xcf, 0x28, 0x6b, 0x50, 0x21, 0x39, 0xe5, 0x52, 0xe5, + 0xac, 0xa7, 0x29, 0x90, 0x87, 0xb5, 0x9b, 0x56, 0x21, 0xad, 0xe3, 0x12, 0x69, 0x41, 0x6d, 0x3a, + 0x0d, 0xac, 0xf5, 0x93, 0x32, 0x6b, 0x49, 0xea, 0x39, 0xa8, 0xf8, 0x36, 0xd2, 0xd6, 0x8f, 0x8a, + 0xb4, 0xb5, 0x5e, 0x21, 0x4b, 0x85, 0x85, 0x3a, 0xde, 0x7a, 0x9a, 0xf2, 0xd6, 0x46, 0x6d, 0x7a, + 0x4d, 0xc4, 0xf5, 0x98, 0xea, 0xa6, 0x82, 0x4b, 0xaa, 0x79, 0x1e, 0x86, 0x7e, 0xa8, 0x38, 0x47, + 0x0e, 0x8c, 0x43, 0xaa, 0xf9, 0x1c, 0x8d, 0xff, 0x87, 0xe4, 0x44, 0x8d, 0x17, 0xb0, 0x68, 0xfc, + 0x56, 0xcb, 0x7d, 0x09, 0x70, 0x54, 0x99, 0xb6, 0x15, 0x5b, 0xca, 0x51, 0x7c, 0x53, 0xbc, 0x5b, + 0x1e, 0x46, 0x84, 0x3c, 0xc9, 0x6b, 0xe9, 0x10, 0x9f, 0xc0, 0x96, 0x6b, 0x45, 0xb1, 0xdc, 0x94, + 0x99, 0x2a, 0xc2, 0xb6, 0x28, 0xc2, 0x4d, 0x52, 0xc8, 0xdd, 0x10, 0x62, 0xfc, 0x01, 0x6c, 0x17, + 0x6c, 0xad, 0x20, 0x98, 0x09, 0x0a, 0xe8, 0x08, 0x0a, 0x60, 0x99, 0xf5, 0x49, 0x10, 0x5c, 0x58, + 0xd1, 0xca, 0xf8, 0x20, 0xcf, 0xbf, 0xc4, 0xb8, 0xae, 0xbf, 0x4c, 0x19, 0xd7, 0xf5, 0x97, 0xc6, + 0xaf, 0x72, 0xb3, 0x9c, 0x5c, 0xbf, 0x03, 0x9d, 0xb9, 0x6f, 0xcb, 0xec, 0xc7, 0x47, 0x9b, 0x6a, + 0xc7, 0x5f, 0xfa, 0x36, 0x7f, 0x7b, 0x1f, 0x70, 0x53, 0x28, 0xb3, 0x4c, 0x5b, 0x92, 0x83, 0x44, + 0xa6, 0x2a, 0x7e, 0x3b, 0x8f, 0xff, 0x4b, 0xa2, 0x9b, 0x12, 0xd6, 0xdf, 0x67, 0xf4, 0x9f, 0xe7, + 0xe7, 0x21, 0x49, 0xfd, 0x9b, 0x89, 0x2d, 0xaf, 0x82, 0xf7, 0x18, 0xfb, 0x17, 0x74, 0x5b, 0x15, + 0xcb, 0xf9, 0x7d, 0x06, 0xdf, 0xce, 0x8f, 0x34, 0x2b, 0x64, 0x63, 0x07, 0xf0, 0x61, 0x85, 0xca, + 0x5b, 0xb9, 0x5c, 0x7b, 0xf8, 0x3d, 0xe8, 0xda, 0xce, 0x62, 0x11, 0xe9, 0x9d, 0x86, 0xdb, 0x49, + 0xaa, 0x8d, 0xdf, 0xb5, 0xa0, 0x27, 0xef, 0x16, 0x3c, 0x20, 0x9e, 0xb3, 0x1c, 0x6f, 0xe6, 0xd8, + 0x69, 0xc5, 0x88, 0xf1, 0xd4, 0xae, 0xdc, 0x96, 0xd9, 0xdd, 0x42, 0xa9, 0xc4, 0xce, 0x0d, 0x57, + 0x60, 0x17, 0xdf, 0xb8, 0x0f, 0x7d, 0x2f, 0xb9, 0x99, 0xc5, 0x77, 0x91, 0x40, 0x75, 0xc7, 0xec, + 0x79, 0xc9, 0xcd, 0xdb, 0xbb, 0x08, 0x8f, 0x60, 0xa3, 0x00, 0x7d, 0xc7, 0x56, 0x04, 0x3e, 0x56, + 0x4b, 0x13, 0xeb, 0x9e, 0xbe, 0x32, 0x47, 0x59, 0x11, 0x4c, 0x6d, 0x3c, 0x04, 0x51, 0x13, 0x33, + 0x49, 0x92, 0xb2, 0x56, 0x7a, 0x62, 0xdf, 0xc6, 0x24, 0x57, 0x2c, 0x4a, 0x17, 0xe7, 0xb7, 0x60, + 0x48, 0x3b, 0x29, 0x4d, 0xfa, 0xc2, 0x64, 0x40, 0x02, 0xa1, 0xfc, 0x10, 0x36, 0xf3, 0xcb, 0x58, + 0x9a, 0x0c, 0x64, 0x94, 0x5c, 0x2c, 0x0c, 0x0f, 0x60, 0x90, 0xd5, 0xe4, 0x50, 0x58, 0xf4, 0x2d, + 0x55, 0x8a, 0x53, 0xe8, 0xab, 0x25, 0xd6, 0x5e, 0xdc, 0x4f, 0xa0, 0x1b, 0x58, 0x61, 0x1c, 0xa9, + 0x0b, 0x32, 0x25, 0xb8, 0x4b, 0x2b, 0xa4, 0x5e, 0x49, 0x5d, 0xdf, 0xd2, 0xc4, 0x38, 0x86, 0x8d, + 0x92, 0x9c, 0x18, 0x2d, 0xf6, 0x63, 0xcb, 0x55, 0x57, 0xb7, 0x1c, 0x64, 0xd3, 0xb4, 0xf2, 0x69, + 0x8c, 0x63, 0x18, 0x66, 0x67, 0x48, 0xc7, 0x12, 0x24, 0x57, 0x9f, 0x65, 0x9d, 0x8d, 0x1a, 0x51, + 0xb8, 0xc0, 0xff, 0x5a, 0xf5, 0x10, 0x1d, 0x53, 0x0e, 0x9e, 0xfc, 0x49, 0x83, 0xd1, 0xe7, 0x92, + 0x02, 0x09, 0x8d, 0xb8, 0x09, 0xa3, 0xd7, 0x89, 0xeb, 0x2a, 0x11, 0x5b, 0xc3, 0x01, 0x74, 0x88, + 0x39, 0x99, 0x86, 0x43, 0xe8, 0x0a, 0x66, 0x64, 0x2d, 0x12, 0x12, 0x25, 0xb2, 0x36, 0x6e, 0xc0, + 0x30, 0xe3, 0x20, 0xd6, 0xa1, 0x61, 0x46, 0xc9, 0xac, 0x4b, 0xc3, 0x8c, 0x7a, 0xd8, 0x16, 0x8e, + 0xa0, 0xaf, 0x98, 0x82, 0x21, 0x02, 0xf4, 0xe4, 0x49, 0xb1, 0x6d, 0x0a, 0x2d, 0x8a, 0x9c, 0xed, + 0x90, 0x4b, 0x06, 0x6d, 0xb6, 0x8b, 0x63, 0x80, 0x1c, 0xd4, 0x6c, 0x0f, 0xd7, 0x61, 0x90, 0xc2, + 0x99, 0xed, 0x93, 0x9f, 0x28, 0x60, 0xa6, 0x3f, 0xf9, 0x7d, 0x17, 0x06, 0x69, 0x4d, 0x61, 0x0f, + 0x5a, 0x6f, 0x3e, 0x63, 0x6b, 0xb8, 0x05, 0x1b, 0x53, 0x2f, 0xe6, 0xa1, 0x67, 0xb9, 0x67, 0x74, + 0x1f, 0x30, 0x8d, 0x44, 0x67, 0xde, 0xdc, 0xb7, 0x1d, 0x6f, 0x29, 0x45, 0x2d, 0x8a, 0x79, 0x6a, + 0xd9, 0xaf, 0x7d, 0x6f, 0xce, 0x59, 0x1b, 0x19, 0xac, 0x7f, 0xe9, 0x59, 0x49, 0xbc, 0xf2, 0x43, + 0xe7, 0x37, 0xdc, 0x66, 0x1d, 0xdc, 0x85, 0xad, 0xa9, 0x17, 0x25, 0x8b, 0x85, 0x33, 0x77, 0xb8, + 0x17, 0x7f, 0x9a, 0x78, 0x76, 0xc4, 0xba, 0x88, 0x30, 0xfe, 0xd2, 0xbb, 0xf6, 0xfc, 0xaf, 0x3d, + 0xd5, 0x75, 0xb1, 0x1e, 0xea, 0xb0, 0x73, 0x6a, 0x45, 0xfc, 0x55, 0x12, 0xb8, 0xce, 0xdc, 0x8a, + 0xf9, 0x89, 0x6d, 0x87, 0x3c, 0x8a, 0x18, 0xa7, 0x20, 0xa4, 0x29, 0xcf, 0xbd, 0x48, 0x1d, 0x4a, + 0xf1, 0x39, 0x8f, 0xd8, 0x12, 0x0f, 0x60, 0xf7, 0x81, 0x46, 0xcc, 0xbc, 0xc2, 0x6f, 0x83, 0x5e, + 0x55, 0x9d, 0x5b, 0xd1, 0x65, 0xe8, 0xcc, 0x39, 0x73, 0x70, 0x07, 0x98, 0xd4, 0x0a, 0x18, 0x4f, + 0xbd, 0x20, 0x89, 0xd9, 0xaf, 0xd3, 0xf9, 0x95, 0xf4, 0x4d, 0x12, 0x93, 0xf8, 0xba, 0x22, 0xbe, + 0x14, 0x50, 0x61, 0x2e, 0xee, 0xc3, 0x76, 0x41, 0xfc, 0x05, 0xe5, 0x47, 0xbb, 0x73, 0x93, 0xaf, + 0x57, 0x2a, 0x9c, 0xa5, 0x67, 0xc5, 0x49, 0xc8, 0x99, 0x87, 0x7b, 0x80, 0xa4, 0x51, 0x5b, 0x92, + 0x26, 0xee, 0xa7, 0x33, 0x28, 0xb9, 0x9a, 0x21, 0xa8, 0x8a, 0xdd, 0x64, 0xe9, 0x78, 0xec, 0x1d, + 0xee, 0x02, 0x3b, 0xf7, 0x6f, 0x95, 0xf4, 0xcc, 0x8b, 0x9d, 0xf8, 0x9e, 0xfd, 0x59, 0xc3, 0x1d, + 0xd8, 0xcc, 0xc5, 0xe7, 0xa1, 0x9f, 0x04, 0xec, 0x2f, 0x1a, 0xee, 0x03, 0xe6, 0xd2, 0xcb, 0xd0, + 0x0f, 0xfc, 0xc8, 0x72, 0xd9, 0x5f, 0x35, 0xdc, 0x83, 0xad, 0x73, 0xff, 0x36, 0x3b, 0x05, 0xe9, + 0xf0, 0xb7, 0xd4, 0x21, 0x93, 0x7f, 0xce, 0x6f, 0xae, 0x78, 0xc8, 0xfe, 0xae, 0xe1, 0x01, 0xec, + 0x14, 0x15, 0x59, 0xac, 0x7f, 0x68, 0x6a, 0x45, 0x99, 0xea, 0x2b, 0x3f, 0xe6, 0xec, 0x9f, 0xa9, + 0x58, 0xed, 0x83, 0x0a, 0xf4, 0x2f, 0x0d, 0xb7, 0x61, 0x9c, 0x8b, 0x85, 0xed, 0xbf, 0x35, 0x9c, + 0xc0, 0x6e, 0x49, 0xe8, 0x78, 0xcb, 0x4b, 0xaa, 0x3e, 0xf6, 0x1f, 0xed, 0xe8, 0x8f, 0x5d, 0xd8, + 0x3c, 0x39, 0x7d, 0x39, 0x3d, 0x09, 0xe4, 0x04, 0x74, 0x97, 0x3f, 0x97, 0x35, 0x87, 0x35, 0xff, + 0xfe, 0x27, 0x75, 0x4d, 0x36, 0x1e, 0xa9, 0xd2, 0xc4, 0xba, 0x47, 0x80, 0x49, 0x6d, 0xaf, 0x4d, + 0x93, 0xc8, 0xb6, 0xe6, 0xe1, 0x5b, 0xc0, 0xa4, 0xae, 0xe1, 0xc6, 0x9f, 0x16, 0x4a, 0x1d, 0x9b, + 0x5e, 0x04, 0x26, 0x8d, 0xad, 0x37, 0xf9, 0xe7, 0x7d, 0x48, 0xd3, 0xbb, 0xc0, 0xa4, 0xb1, 0xff, + 0xc6, 0x17, 0x19, 0x7b, 0x60, 0xfd, 0xeb, 0xc0, 0xa4, 0xa1, 0x05, 0xa7, 0xed, 0x91, 0x3d, 0x44, + 0xdd, 0x9f, 0xfe, 0x49, 0x6d, 0x57, 0x4d, 0x3e, 0xb2, 0x37, 0xa8, 0xfb, 0x37, 0x3d, 0xa9, 0x6d, + 0x55, 0xf1, 0xe3, 0x94, 0xd2, 0xb0, 0xf6, 0x31, 0x62, 0x52, 0xdf, 0xef, 0xd3, 0xc6, 0xe4, 0x7f, + 0x23, 0x9b, 0x5e, 0x19, 0x26, 0x8d, 0x9d, 0x3c, 0x9e, 0x14, 0x39, 0x12, 0x1b, 0xdf, 0x1a, 0x26, + 0xcd, 0xfd, 0x3c, 0x7e, 0x92, 0xd3, 0x2a, 0x36, 0xbc, 0x38, 0x4c, 0x9a, 0x5a, 0xfa, 0xab, 0x9e, + 0x78, 0xcc, 0xfa, 0xe8, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xce, 0x8c, 0x71, 0x92, 0xe1, 0x12, + 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 09a2af8f..16dc2856 100644 --- a/types/types.proto +++ b/types/types.proto @@ -87,6 +87,7 @@ message Request { RequestInitChain init_chain = 9; RequestBeginBlock begin_block = 10; RequestEndBlock end_block = 11; + RequestProof proof = 12; } } @@ -122,7 +123,6 @@ message RequestProof{ int64 height = 2; } - message RequestCommit{ } From cfc3f247516574944f99e55a20544bbd81910a0d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 10 Jan 2017 17:06:51 +0100 Subject: [PATCH 194/545] Everything compiles, test proof in dummy app --- client/client.go | 4 ++-- client/grpc_client.go | 8 ++++---- client/local_client.go | 10 +++++----- client/socket_client.go | 8 ++++---- cmd/abci-cli/tmsp-cli.go | 20 +++++++++++++++----- example/dummy/dummy.go | 11 ++++++++++- example/dummy/dummy_test.go | 22 ++++++++++++++++++++++ example/dummy/persistent_dummy.go | 2 +- 8 files changed, 63 insertions(+), 22 deletions(-) diff --git a/client/client.go b/client/client.go index a8bc8ea8..fd31b21a 100644 --- a/client/client.go +++ b/client/client.go @@ -21,7 +21,7 @@ type Client interface { DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes QueryAsync(tx []byte) *ReqRes - ProofAsync(tx []byte) *ReqRes + ProofAsync(key []byte, blockHeight int64) *ReqRes CommitAsync() *ReqRes FlushSync() error @@ -31,7 +31,7 @@ type Client interface { DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) QuerySync(tx []byte) (res types.Result) - ProofSync(tx []byte) (res types.Result) + ProofSync(key []byte, blockHeight int64) (res types.Result) CommitSync() (res types.Result) InitChainAsync(validators []*types.Validator) *ReqRes diff --git a/client/grpc_client.go b/client/grpc_client.go index 740623c6..3654c47c 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -182,8 +182,8 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}}) } -func (cli *grpcClient) ProofAsync(key []byte) *ReqRes { - req := types.ToRequestProof(key) +func (cli *grpcClient) ProofAsync(key []byte, blockHeight int64) *ReqRes { + req := types.ToRequestProof(key, blockHeight) res, err := cli.client.Proof(context.Background(), req.GetProof(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -310,8 +310,8 @@ func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *grpcClient) ProofSync(key []byte) (res types.Result) { - reqres := cli.ProofAsync(key) +func (cli *grpcClient) ProofSync(key []byte, blockHeight int64) (res types.Result) { + reqres := cli.ProofAsync(key, blockHeight) if res := cli.checkErrGetResult(); res.IsErr() { return res } diff --git a/client/local_client.go b/client/local_client.go index 8c092cec..bdc59c5a 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -99,12 +99,12 @@ func (app *localClient) QueryAsync(tx []byte) *ReqRes { ) } -func (app *localClient) ProofAsync(key []byte) *ReqRes { +func (app *localClient) ProofAsync(key []byte, blockHeight int64) *ReqRes { app.mtx.Lock() - res := app.Application.Proof(key) + res := app.Application.Proof(key, blockHeight) app.mtx.Unlock() return app.callback( - types.ToRequestProof(key), + types.ToRequestProof(key, blockHeight), types.ToResponseQuery(res.Code, res.Data, res.Log), ) } @@ -202,9 +202,9 @@ func (app *localClient) QuerySync(query []byte) (res types.Result) { return res } -func (app *localClient) ProofSync(key []byte) (res types.Result) { +func (app *localClient) ProofSync(key []byte, blockHeight int64) (res types.Result) { app.mtx.Lock() - res = app.Application.Proof(key) + res = app.Application.Proof(key, blockHeight) app.mtx.Unlock() return res } diff --git a/client/socket_client.go b/client/socket_client.go index 252c8777..cacd67bf 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -255,8 +255,8 @@ func (cli *socketClient) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.ToRequestQuery(query)) } -func (cli *socketClient) ProofAsync(key []byte) *ReqRes { - return cli.queueRequest(types.ToRequestProof(key)) +func (cli *socketClient) ProofAsync(key []byte, blockHeight int64) *ReqRes { + return cli.queueRequest(types.ToRequestProof(key, blockHeight)) } func (cli *socketClient) CommitAsync() *ReqRes { @@ -349,8 +349,8 @@ func (cli *socketClient) QuerySync(query []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *socketClient) ProofSync(key []byte) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestProof(key)) +func (cli *socketClient) ProofSync(key []byte, blockHeight int64) (res types.Result) { + reqres := cli.queueRequest(types.ToRequestProof(key, blockHeight)) cli.FlushSync() if err := cli.Error(); err != nil { return types.ErrInternalError.SetLog(err.Error()) diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index d40b510b..0eae4d85 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "os" + "strconv" "strings" "github.com/tendermint/abci/client" @@ -315,12 +316,21 @@ func cmdQuery(c *cli.Context) error { // Prove application state func cmdProof(c *cli.Context) error { args := c.Args() - if len(args) != 1 { - return errors.New("Command proof takes 1 argument") + if len(args) < 1 { + return errors.New("Command proof takes 1 or 2 arguments") } - keyBytes := stringOrHexToBytes(c.Args()[0]) - res := client.ProofSync(keyBytes) - printResponse(c, res, string(res.Data), true) + keyBytes, err := stringOrHexToBytes(c.Args()[0]) + if err != nil { + return err + } + + var height int64 + if len(args) == 2 { + height, _ = strconv.ParseInt(args[1], 10, 0) + } + res := client.ProofSync(keyBytes, height) + rsp := newResponse(res, string(res.Data), true) + printResponse(c, rsp) return nil } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index ebce1099..fcf067dc 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -2,6 +2,7 @@ package dummy import ( "encoding/hex" + "fmt" "strings" "github.com/tendermint/abci/types" @@ -54,7 +55,15 @@ func (app *DummyApplication) Query(query []byte) types.Result { } func (app *DummyApplication) Proof(key []byte, blockHeight int64) types.Result { - return types.NewResultOK(nil, Fmt("TODO: support proof!")) + if blockHeight != 0 { + return types.ErrUnknownRequest + } + proof, exists := app.state.Proof(key) + if !exists { + fmt.Println("Didn't find nothing") + return types.NewResultOK(nil, "") + } + return types.NewResultOK(proof, "Found the key") } type QueryResult struct { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index d2294347..8cd999c0 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -8,6 +8,7 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" + merkle "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" "github.com/tendermint/abci/types" ) @@ -34,6 +35,27 @@ func testDummy(t *testing.T, dummy types.Application, tx []byte, key, value stri t.Fatalf("Got %s, expected %s", q.Value, value) } + rp := dummy.Proof([]byte(key), 0) + if rp.IsErr() { + t.Fatal(rp) + } + + p, err := merkle.LoadProof(rp.Data) + if err != nil { + t.Fatal(err) + } + + if !p.Valid() { + t.Fatal("Invalid proof") + } + + if !bytes.Equal([]byte(key), p.Key()) { + t.Fatalf("Invalid key: %s", p.Key()) + } + + if !bytes.Equal([]byte(value), p.Value()) { + t.Fatalf("Invalid key: %s", p.Value()) + } } func TestDummyKV(t *testing.T) { diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 70c0e667..3a1ce3b5 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -94,7 +94,7 @@ func (app *PersistentDummyApplication) Query(query []byte) types.Result { } func (app *PersistentDummyApplication) Proof(key []byte, blockHeight int64) types.Result { - return types.NewResultOK(nil, Fmt("TODO: support proof!")) + return app.app.Proof(key, blockHeight) } // Save the validators in the merkle tree From 732274b7f6ad695a5b02a537b97c852b92f34c69 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 10 Jan 2017 18:12:20 +0100 Subject: [PATCH 195/545] Add tests for client-server proofs over socket and grpc --- README.md | 22 ++- example/dummy/dummy_test.go | 158 +++++++++++---- example/dummy/dummy_test.go.orig | 321 +++++++++++++++++++++++++++++++ glide.lock | 15 +- glide.yaml | 4 + 5 files changed, 473 insertions(+), 47 deletions(-) create mode 100644 example/dummy/dummy_test.go.orig diff --git a/README.md b/README.md index ea09fa7c..3a9b27cb 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ [![CircleCI](https://circleci.com/gh/tendermint/abci.svg?style=svg)](https://circleci.com/gh/tendermint/abci) -Blockchains are a system for creating shared multi-master application state. +Blockchains are a system for creating shared multi-master application state. **ABCI** is a socket protocol enabling a blockchain consensus engine, running in one process, -to manage a blockchain application state, running in another. For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-tendermint-socket-protocol). @@ -18,15 +17,15 @@ Other implementations: This repository holds a number of important pieces: - `types/types.proto` - - the protobuf file defining ABCI message types, and the optional grpc interface. + - 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 - golang implementation of ABCI client and server - two implementations: - - asynchronous, ordered message passing over unix or tcp; + - asynchronous, ordered message passing over unix or tcp; - messages are serialized using protobuf and length prefixed - - grpc + - grpc - TendermintCore runs a client, and the application runs a server - `cmd/abci-cli` @@ -77,7 +76,7 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil 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 @@ -92,6 +91,17 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * `Data ([]byte)`: The query response bytes * `Log (string)`: Debug or error message +#### Proof + * __Arguments__: + * `Key ([]byte)`: The key whose data you want to verifiably query + * `Height (int64)`: The block height for which you want the proof (default=0 returns the proof for last committed block) + * __Returns__: + * `Code (uint32)`: Response code + * `Data ([]byte)`: The query response bytes + * `Log (string)`: Debug or error message + * __Usage__:
+ Return a Merkle proof from the key/value pair back to the application hash. + #### Flush * __Usage__:
Flush the response queue. Applications that implement `types.Application` need not implement this message -- it's handled by the project. diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 8cd999c0..aa6c837d 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -6,56 +6,40 @@ import ( "sort" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" . "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" merkle "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" - "github.com/tendermint/abci/types" ) -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) - } +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 + r := app.Query([]byte(key)) + require.False(t, r.IsErr(), 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) - } - - rp := dummy.Proof([]byte(key), 0) - if rp.IsErr() { - t.Fatal(rp) - } + err := wire.ReadJSONBytes(r.Data, q) + require.Nil(t, err) + require.Equal(t, value, q.Value) + // make sure proof is fine + rp := app.Proof([]byte(key), 0) + require.False(t, rp.IsErr(), rp) p, err := merkle.LoadProof(rp.Data) - if err != nil { - t.Fatal(err) - } - - if !p.Valid() { - t.Fatal("Invalid proof") - } - - if !bytes.Equal([]byte(key), p.Key()) { - t.Fatalf("Invalid key: %s", p.Key()) - } - - if !bytes.Equal([]byte(value), p.Value()) { - t.Fatalf("Invalid key: %s", p.Value()) - } + require.Nil(t, err) + require.True(t, p.Valid()) + assert.Equal(t, []byte(key), p.Key()) + assert.Equal(t, []byte(value), p.Value()) } func TestDummyKV(t *testing.T) { @@ -223,3 +207,97 @@ func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { } } } + +func makeSocketClientServer(app types.Application, name string) (abcicli.Client, Service, error) { + // Start the listener + socket := 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, Service, error) { + // Start the listener + socket := 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 + r := app.QuerySync([]byte(key)) + require.False(t, r.IsErr(), r) + q := new(QueryResult) + err := wire.ReadJSONBytes(r.Data, q) + require.Nil(t, err) + require.Equal(t, value, q.Value) + + // make sure proof is fine + rp := app.ProofSync([]byte(key), 0) + require.False(t, rp.IsErr(), rp) + p, err := merkle.LoadProof(rp.Data) + require.Nil(t, err) + require.True(t, p.Valid()) + assert.Equal(t, []byte(key), p.Key()) + assert.Equal(t, []byte(value), p.Value()) +} diff --git a/example/dummy/dummy_test.go.orig b/example/dummy/dummy_test.go.orig new file mode 100644 index 00000000..5cf7eee7 --- /dev/null +++ b/example/dummy/dummy_test.go.orig @@ -0,0 +1,321 @@ +package dummy + +import ( + "bytes" + "io/ioutil" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + . "github.com/tendermint/go-common" + "github.com/tendermint/go-crypto" + merkle "github.com/tendermint/go-merkle" + "github.com/tendermint/go-wire" +<<<<<<< HEAD + "github.com/tendermint/abci/types" +) + +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) + } +======= + tmspcli "github.com/tendermint/tmsp/client" + "github.com/tendermint/tmsp/server" + "github.com/tendermint/tmsp/types" +) + +func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { + ar := app.AppendTx(tx) + require.False(t, ar.IsErr(), ar) + // repeating tx doesn't raise error + ar = app.AppendTx(tx) + require.False(t, ar.IsErr(), ar) +>>>>>>> Add tests for client-server proofs over socket and grpc + + // make sure query is fine + r := app.Query([]byte(key)) + require.False(t, r.IsErr(), r) + q := new(QueryResult) + err := wire.ReadJSONBytes(r.Data, q) + require.Nil(t, err) + require.Equal(t, value, q.Value) + + // make sure proof is fine + rp := app.Proof([]byte(key), 0) + require.False(t, rp.IsErr(), rp) + p, err := merkle.LoadProof(rp.Data) + require.Nil(t, err) + require.True(t, p.Valid()) + assert.Equal(t, []byte(key), p.Key()) + assert.Equal(t, []byte(value), p.Value()) +} + +func TestDummyKV(t *testing.T) { + dummy := NewDummyApplication() + key := "abc" + value := key + tx := []byte(key) + testDummy(t, dummy, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testDummy(t, dummy, tx, key, value) +} + +func TestPersistentDummyKV(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO + if err != nil { + t.Fatal(err) + } + dummy := NewPersistentDummyApplication(dir) + key := "abc" + value := key + tx := []byte(key) + testDummy(t, dummy, tx, key, value) + + value = "def" + tx = []byte(key + "=" + value) + testDummy(t, dummy, tx, key, value) +} + +func TestPersistentDummyInfo(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO + if err != nil { + t.Fatal(err) + } + dummy := NewPersistentDummyApplication(dir) + height := uint64(0) + + resInfo := dummy.Info() + if resInfo.LastBlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) + } + + // make and apply block + height = uint64(1) + hash := []byte("foo") + header := &types.Header{ + Height: uint64(height), + } + dummy.BeginBlock(hash, header) + dummy.EndBlock(height) + dummy.Commit() + + resInfo = dummy.Info() + if resInfo.LastBlockHeight != height { + t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) + } + +} + +// add a validator, remove a validator, update a validator +func TestValSetChanges(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO + if err != nil { + t.Fatal(err) + } + dummy := NewPersistentDummyApplication(dir) + + // init with some validators + total := 10 + 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() + vals[i] = &types.Validator{pubkey, uint64(power)} + } + // iniitalize with the first nInit + dummy.InitChain(vals[:nInit]) + + vals1, vals2 := vals[:nInit], dummy.Validators() + valsEqual(t, vals1, vals2) + + var v1, v2, v3 *types.Validator + + // add some validators + v1, v2 = vals[nInit], vals[nInit+1] + diff := []*types.Validator{v1, v2} + tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power) + tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power) + + makeApplyBlock(t, dummy, 1, diff, tx1, tx2) + + vals1, vals2 = vals[:nInit+2], dummy.Validators() + valsEqual(t, vals1, vals2) + + // remove some validators + v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit] + v1.Power = 0 + v2.Power = 0 + v3.Power = 0 + diff = []*types.Validator{v1, v2, v3} + tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) + tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power) + tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power) + + makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3) + + vals1 = append(vals[:nInit-2], vals[nInit+1]) + vals2 = dummy.Validators() + valsEqual(t, vals1, vals2) + + // update some validators + v1 = vals[0] + if v1.Power == 5 { + v1.Power = 6 + } else { + v1.Power = 5 + } + diff = []*types.Validator{v1} + tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) + + makeApplyBlock(t, dummy, 3, diff, tx1) + + vals1 = append([]*types.Validator{v1}, vals1[1:len(vals1)]...) + vals2 = dummy.Validators() + valsEqual(t, vals1, vals2) + +} + +func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) { + // make and apply block + height := uint64(heightInt) + hash := []byte("foo") + header := &types.Header{ + Height: height, + } + + dummyChain := dummy.(types.BlockchainAware) // hmm... + dummyChain.BeginBlock(hash, header) + for _, tx := range txs { + if r := dummy.DeliverTx(tx); r.IsErr() { + t.Fatal(r) + } + } + resEndBlock := dummyChain.EndBlock(height) + dummy.Commit() + + valsEqual(t, diff, resEndBlock.Diffs) + +} + +// order doesn't matter +func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { + if len(vals1) != len(vals2) { + t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1)) + } + sort.Sort(types.Validators(vals1)) + sort.Sort(types.Validators(vals2)) + for i, v1 := range vals1 { + v2 := vals2[i] + if !bytes.Equal(v1.PubKey, v2.PubKey) || + v1.Power != v2.Power { + t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power) + } + } +} + +func makeSocketClientServer(app types.Application, name string) (tmspcli.Client, Service, error) { + // Start the listener + socket := Fmt("unix://%s.sock", name) + server, err := server.NewSocketServer(socket, app) + if err != nil { + return nil, nil, err + } + + // Connect to the socket + client, err := tmspcli.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) (tmspcli.Client, Service, error) { + // Start the listener + socket := Fmt("unix://%s.sock", name) + + gapp := types.NewGRPCApplication(app) + server, err := server.NewGRPCServer(socket, gapp) + if err != nil { + return nil, nil, err + } + + client, err := tmspcli.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 tmspcli.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 tmspcli.Client, tx []byte, key, value string) { + ar := app.AppendTxSync(tx) + require.False(t, ar.IsErr(), ar) + // repeating tx doesn't raise error + ar = app.AppendTxSync(tx) + require.False(t, ar.IsErr(), ar) + + // make sure query is fine + r := app.QuerySync([]byte(key)) + require.False(t, r.IsErr(), r) + q := new(QueryResult) + err := wire.ReadJSONBytes(r.Data, q) + require.Nil(t, err) + require.Equal(t, value, q.Value) + + // make sure proof is fine + rp := app.ProofSync([]byte(key), 0) + require.False(t, rp.IsErr(), rp) + p, err := merkle.LoadProof(rp.Data) + require.Nil(t, err) + require.True(t, p.Valid()) + assert.Equal(t, []byte(key), p.Key()) + assert.Equal(t, []byte(value), p.Value()) +} diff --git a/glide.lock b/glide.lock index 42776a3a..4829e672 100644 --- a/glide.lock +++ b/glide.lock @@ -19,6 +19,11 @@ imports: version: d228849504861217f796da67fae4f6e347643f15 - name: github.com/mattn/go-isatty version: 30a891c33c7cde7b02a981314b4228ec99380cca +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require - name: github.com/syndtr/goleveldb version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 subpackages: @@ -102,4 +107,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 295b3d3e..af174387 100644 --- a/glide.yaml +++ b/glide.yaml @@ -15,3 +15,7 @@ import: subpackages: - context - package: google.golang.org/grpc +- package: github.com/stretchr/testify + version: ^1.1.4 + subpackages: + - require From dde413d44bb0a3b718dda3c6918949243da008af Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 10 Jan 2017 19:14:35 +0100 Subject: [PATCH 196/545] Cleaned up text --- README.md | 3 ++- example/dummy/dummy.go | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a9b27cb..23c1ac65 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,8 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * `Data ([]byte)`: The query response bytes * `Log (string)`: Debug or error message * __Usage__:
- Return a Merkle proof from the key/value pair back to the application hash. + Return a Merkle proof from the key/value pair back to the application hash.
+ *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. Hopefully this will be improved soon(ish) #### Flush * __Usage__:
diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index fcf067dc..39f54fc2 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -2,7 +2,6 @@ package dummy import ( "encoding/hex" - "fmt" "strings" "github.com/tendermint/abci/types" @@ -50,18 +49,21 @@ func (app *DummyApplication) Commit() types.Result { 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), "") } func (app *DummyApplication) Proof(key []byte, blockHeight int64) types.Result { + // TODO: when go-merkle supports querying older blocks without possible panics, + // we should store a cache and allow a query. But for now it is impossible. + // And this is just a Dummy application anyway, what do you expect? ;) if blockHeight != 0 { return types.ErrUnknownRequest } proof, exists := app.state.Proof(key) if !exists { - fmt.Println("Didn't find nothing") - return types.NewResultOK(nil, "") + return types.NewResultOK(nil, Fmt("Cannot find key = %v", key)) } return types.NewResultOK(proof, "Found the key") } From e0309007ad431ddd126e2ec0d36bd2adbede1aed Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 12 Jan 2017 12:37:47 +0100 Subject: [PATCH 197/545] Improve Makefile --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 740bce9b..5cbe0b62 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,8 @@ protoc: install: go install github.com/tendermint/abci/cmd/... -test: +# 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 From fdc047ae7af0f0189dd9f21b932eb92ce455ffa5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 17 Jan 2017 17:22:34 +0100 Subject: [PATCH 198/545] Proof uses uint64 for blockHeight --- client/client.go | 6 +- client/grpc_client.go | 6 +- client/local_client.go | 6 +- client/socket_client.go | 6 +- cmd/abci-cli/tmsp-cli.go | 4 +- example/chain_aware/chain_aware_app.go | 4 +- example/counter/counter.go | 4 +- example/dummy/dummy.go | 2 +- example/dummy/persistent_dummy.go | 4 +- example/nil/nil_app.go | 2 +- types/application.go | 2 +- types/messages.go | 2 +- types/types.pb.go | 219 ++++++++++++------------- types/types.proto | 120 +++++++------- 14 files changed, 193 insertions(+), 194 deletions(-) diff --git a/client/client.go b/client/client.go index fd31b21a..bbd41398 100644 --- a/client/client.go +++ b/client/client.go @@ -4,8 +4,8 @@ import ( "fmt" "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) type Client interface { @@ -21,7 +21,7 @@ type Client interface { DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes QueryAsync(tx []byte) *ReqRes - ProofAsync(key []byte, blockHeight int64) *ReqRes + ProofAsync(key []byte, blockHeight uint64) *ReqRes CommitAsync() *ReqRes FlushSync() error @@ -31,7 +31,7 @@ type Client interface { DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) QuerySync(tx []byte) (res types.Result) - ProofSync(key []byte, blockHeight int64) (res types.Result) + ProofSync(key []byte, blockHeight uint64) (res types.Result) CommitSync() (res types.Result) InitChainAsync(validators []*types.Validator) *ReqRes diff --git a/client/grpc_client.go b/client/grpc_client.go index 3654c47c..63fb16a4 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -8,8 +8,8 @@ import ( context "golang.org/x/net/context" grpc "google.golang.org/grpc" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) // A stripped copy of the remoteClient that makes @@ -182,7 +182,7 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}}) } -func (cli *grpcClient) ProofAsync(key []byte, blockHeight int64) *ReqRes { +func (cli *grpcClient) ProofAsync(key []byte, blockHeight uint64) *ReqRes { req := types.ToRequestProof(key, blockHeight) res, err := cli.client.Proof(context.Background(), req.GetProof(), grpc.FailFast(true)) if err != nil { @@ -310,7 +310,7 @@ func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *grpcClient) ProofSync(key []byte, blockHeight int64) (res types.Result) { +func (cli *grpcClient) ProofSync(key []byte, blockHeight uint64) (res types.Result) { reqres := cli.ProofAsync(key, blockHeight) if res := cli.checkErrGetResult(); res.IsErr() { return res diff --git a/client/local_client.go b/client/local_client.go index bdc59c5a..7450573e 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -3,8 +3,8 @@ package abcicli import ( "sync" - . "github.com/tendermint/go-common" types "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) type localClient struct { @@ -99,7 +99,7 @@ func (app *localClient) QueryAsync(tx []byte) *ReqRes { ) } -func (app *localClient) ProofAsync(key []byte, blockHeight int64) *ReqRes { +func (app *localClient) ProofAsync(key []byte, blockHeight uint64) *ReqRes { app.mtx.Lock() res := app.Application.Proof(key, blockHeight) app.mtx.Unlock() @@ -202,7 +202,7 @@ func (app *localClient) QuerySync(query []byte) (res types.Result) { return res } -func (app *localClient) ProofSync(key []byte, blockHeight int64) (res types.Result) { +func (app *localClient) ProofSync(key []byte, blockHeight uint64) (res types.Result) { app.mtx.Lock() res = app.Application.Proof(key, blockHeight) app.mtx.Unlock() diff --git a/client/socket_client.go b/client/socket_client.go index cacd67bf..04d07a55 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" + . "github.com/tendermint/go-common" ) const ( @@ -255,7 +255,7 @@ func (cli *socketClient) QueryAsync(query []byte) *ReqRes { return cli.queueRequest(types.ToRequestQuery(query)) } -func (cli *socketClient) ProofAsync(key []byte, blockHeight int64) *ReqRes { +func (cli *socketClient) ProofAsync(key []byte, blockHeight uint64) *ReqRes { return cli.queueRequest(types.ToRequestProof(key, blockHeight)) } @@ -349,7 +349,7 @@ func (cli *socketClient) QuerySync(query []byte) (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *socketClient) ProofSync(key []byte, blockHeight int64) (res types.Result) { +func (cli *socketClient) ProofSync(key []byte, blockHeight uint64) (res types.Result) { reqres := cli.queueRequest(types.ToRequestProof(key, blockHeight)) cli.FlushSync() if err := cli.Error(); err != nil { diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/tmsp-cli.go index 0eae4d85..ccdd41d4 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/tmsp-cli.go @@ -324,9 +324,9 @@ func cmdProof(c *cli.Context) error { return err } - var height int64 + var height uint64 if len(args) == 2 { - height, _ = strconv.ParseInt(args[1], 10, 0) + height, _ = strconv.ParseUint(args[1], 10, 0) } res := client.ProofSync(keyBytes, height) rsp := newResponse(res, string(res.Data), true) diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index f335e543..361f2a07 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -3,9 +3,9 @@ package main import ( "flag" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func main() { @@ -61,7 +61,7 @@ func (app *ChainAwareApplication) Query(query []byte) types.Result { return types.NewResultOK([]byte(Fmt("%d,%d", app.beginCount, app.endCount)), "") } -func (app *ChainAwareApplication) Proof(key []byte, blockHeight int64) types.Result { +func (app *ChainAwareApplication) Proof(key []byte, blockHeight uint64) types.Result { return types.NewResultOK(nil, Fmt("Proof is not supported")) } diff --git a/example/counter/counter.go b/example/counter/counter.go index 9ffec400..62c10826 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -3,8 +3,8 @@ package counter import ( "encoding/binary" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) type CounterApplication struct { @@ -84,6 +84,6 @@ func (app *CounterApplication) Query(query []byte) types.Result { return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) } -func (app *CounterApplication) Proof(key []byte, blockHeight int64) types.Result { +func (app *CounterApplication) Proof(key []byte, blockHeight uint64) types.Result { return types.NewResultOK(nil, Fmt("Proof is not supported")) } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 39f54fc2..8f606f98 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -54,7 +54,7 @@ func (app *DummyApplication) Query(query []byte) types.Result { return types.NewResultOK(wire.JSONBytes(queryResult), "") } -func (app *DummyApplication) Proof(key []byte, blockHeight int64) types.Result { +func (app *DummyApplication) Proof(key []byte, blockHeight uint64) types.Result { // TODO: when go-merkle supports querying older blocks without possible panics, // we should store a cache and allow a query. But for now it is impossible. // And this is just a Dummy application anyway, what do you expect? ;) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 3a1ce3b5..781e1aae 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -6,11 +6,11 @@ import ( "strconv" "strings" + "github.com/tendermint/abci/types" . "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 ( @@ -93,7 +93,7 @@ func (app *PersistentDummyApplication) Query(query []byte) types.Result { return app.app.Query(query) } -func (app *PersistentDummyApplication) Proof(key []byte, blockHeight int64) types.Result { +func (app *PersistentDummyApplication) Proof(key []byte, blockHeight uint64) types.Result { return app.app.Proof(key, blockHeight) } diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 1088ac96..694184a2 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -35,6 +35,6 @@ func (app *NilApplication) Query(query []byte) types.Result { return types.NewResultOK(nil, "") } -func (app *NilApplication) Proof(key []byte, blockHeight int64) types.Result { +func (app *NilApplication) Proof(key []byte, blockHeight uint64) types.Result { return types.NewResultOK(nil, "") } diff --git a/types/application.go b/types/application.go index 5ba440dd..4cea52ff 100644 --- a/types/application.go +++ b/types/application.go @@ -23,7 +23,7 @@ type Application interface { Query(query []byte) Result // Get proof for state - Proof(key []byte, blockHeight int64) Result + Proof(key []byte, blockHeight uint64) Result // Return the application Merkle root hash Commit() Result diff --git a/types/messages.go b/types/messages.go index 9e303a71..af79f7eb 100644 --- a/types/messages.go +++ b/types/messages.go @@ -55,7 +55,7 @@ func ToRequestQuery(queryBytes []byte) *Request { } } -func ToRequestProof(key []byte, blockHeight int64) *Request { +func ToRequestProof(key []byte, blockHeight uint64) *Request { return &Request{ Value: &Request_Proof{&RequestProof{key, blockHeight}}, } diff --git a/types/types.pb.go b/types/types.pb.go index 8467a78c..e53f877e 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -769,7 +769,7 @@ func (m *RequestQuery) GetQuery() []byte { type RequestProof struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Height int64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` } func (m *RequestProof) Reset() { *m = RequestProof{} } @@ -784,7 +784,7 @@ func (m *RequestProof) GetKey() []byte { return nil } -func (m *RequestProof) GetHeight() int64 { +func (m *RequestProof) GetHeight() uint64 { if m != nil { return m.Height } @@ -2231,113 +2231,112 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1714 bytes of a gzipped FileDescriptorProto + // 1710 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x6f, 0xe4, 0x48, - 0x15, 0x8e, 0xfb, 0xde, 0xa7, 0x93, 0x4e, 0xe5, 0xe4, 0xe6, 0x34, 0x3c, 0x8c, 0x0c, 0xcb, 0x66, - 0x86, 0x61, 0x06, 0x65, 0xb5, 0x68, 0xc2, 0x22, 0xa4, 0x64, 0x26, 0x9b, 0xb4, 0x56, 0x3b, 0x13, - 0xbc, 0xb3, 0xfb, 0x00, 0x88, 0x96, 0xd3, 0xae, 0xee, 0x36, 0x71, 0x6c, 0x8f, 0x2f, 0xd9, 0x84, - 0x3f, 0xc2, 0x4f, 0xe0, 0x17, 0xf0, 0xc2, 0x13, 0x4f, 0x48, 0xdc, 0x2f, 0x7f, 0x85, 0x3f, 0x80, - 0x4e, 0x55, 0xf9, 0x1a, 0x9b, 0xa7, 0xd9, 0x97, 0x96, 0xeb, 0xdc, 0xaa, 0x4e, 0xd5, 0x77, 0xbe, - 0x3a, 0x5d, 0xb0, 0x15, 0xdf, 0x07, 0x3c, 0x7a, 0x2e, 0x7e, 0x9f, 0x05, 0xa1, 0x1f, 0xfb, 0xd8, - 0x15, 0x03, 0xe3, 0xbf, 0x1d, 0xe8, 0x9b, 0xfc, 0x5d, 0xc2, 0xa3, 0x18, 0x0f, 0xa1, 0xc3, 0xe7, - 0x2b, 0x5f, 0xd7, 0x1e, 0x69, 0x87, 0xa3, 0x23, 0x7c, 0x26, 0xcd, 0x95, 0xf6, 0x6c, 0xbe, 0xf2, - 0x2f, 0xd6, 0x4c, 0x61, 0x81, 0xdf, 0x87, 0xee, 0xc2, 0x4d, 0xa2, 0x95, 0xde, 0x12, 0xa6, 0xdb, - 0x65, 0xd3, 0x4f, 0x49, 0x75, 0xb1, 0x66, 0x4a, 0x1b, 0x0a, 0xeb, 0x78, 0x0b, 0x5f, 0x6f, 0xd7, - 0x85, 0x9d, 0x7a, 0x0b, 0x11, 0x96, 0x2c, 0xf0, 0x05, 0x40, 0xc4, 0xe3, 0x99, 0x1f, 0xc4, 0x8e, - 0xef, 0xe9, 0x1d, 0x61, 0xbf, 0x5f, 0xb6, 0xff, 0x82, 0xc7, 0x6f, 0x84, 0xfa, 0x62, 0xcd, 0x1c, - 0x46, 0xe9, 0x80, 0x3c, 0x6d, 0xee, 0x3a, 0xb7, 0x3c, 0x9c, 0xc5, 0x77, 0x7a, 0xb7, 0xce, 0xf3, - 0x95, 0xd4, 0xbf, 0xbd, 0x23, 0x4f, 0x3b, 0x1d, 0xe0, 0x11, 0x0c, 0xe6, 0x2b, 0x3e, 0xbf, 0x26, - 0xbf, 0x9e, 0xf0, 0xdb, 0x2d, 0xfb, 0xbd, 0x24, 0xad, 0xf0, 0xea, 0xcf, 0xe5, 0x27, 0x3e, 0x83, - 0xde, 0xdc, 0xbf, 0xb9, 0x71, 0x62, 0xbd, 0x2f, 0x3c, 0x76, 0x2a, 0x1e, 0x42, 0x77, 0xb1, 0x66, - 0x2a, 0x2b, 0xda, 0xae, 0x77, 0x09, 0x0f, 0xef, 0xf5, 0x41, 0xdd, 0x76, 0xfd, 0x8c, 0x54, 0xb4, - 0x5d, 0xc2, 0x86, 0x52, 0x71, 0x3c, 0x27, 0x9e, 0xcd, 0x57, 0x96, 0xe3, 0xe9, 0xc3, 0xba, 0x54, - 0xa6, 0x9e, 0x13, 0xbf, 0x24, 0x35, 0xa5, 0xe2, 0xa4, 0x03, 0xfc, 0x04, 0x46, 0x57, 0x7c, 0xe9, - 0x78, 0xb3, 0x2b, 0xd7, 0x9f, 0x5f, 0xeb, 0x20, 0x5c, 0xf5, 0xb2, 0xeb, 0x29, 0x19, 0x9c, 0x92, - 0xfe, 0x62, 0xcd, 0x84, 0xab, 0x6c, 0x84, 0x1f, 0xc3, 0x90, 0x7b, 0xb6, 0x72, 0x1d, 0x09, 0xd7, - 0xbd, 0x0a, 0x02, 0x3c, 0x3b, 0x75, 0x1c, 0x70, 0xf5, 0x4d, 0xa9, 0x05, 0xa1, 0xef, 0x2f, 0xf4, - 0xf5, 0xba, 0xd4, 0x2e, 0x49, 0x45, 0xa9, 0x09, 0x9b, 0xd3, 0x3e, 0x74, 0x6f, 0x2d, 0x37, 0xe1, - 0xc6, 0x87, 0x30, 0x2a, 0xc0, 0x0a, 0x75, 0xe8, 0xdf, 0xf0, 0x28, 0xb2, 0x96, 0x5c, 0x60, 0x6f, - 0x68, 0xa6, 0x43, 0x63, 0x0c, 0xeb, 0x45, 0x50, 0x19, 0x1b, 0x99, 0x23, 0x01, 0xc7, 0xf8, 0x31, - 0xb0, 0x2a, 0x2e, 0x90, 0x41, 0xfb, 0x9a, 0xdf, 0xab, 0x40, 0xf4, 0x89, 0x3b, 0x6a, 0x5a, 0x81, - 0xd6, 0xa1, 0xa9, 0xd6, 0x60, 0x64, 0xbe, 0x19, 0x32, 0x70, 0x0c, 0xad, 0xf8, 0x4e, 0xb8, 0xae, - 0x9b, 0xad, 0xf8, 0xce, 0x78, 0x04, 0xe3, 0x32, 0x0a, 0x1e, 0x58, 0x7c, 0x37, 0x5b, 0xa0, 0x38, - 0x46, 0x9a, 0x4b, 0x1e, 0xb5, 0x34, 0x91, 0x03, 0xe3, 0x45, 0x66, 0x25, 0x76, 0xa4, 0xb8, 0xc6, - 0x75, 0xb9, 0xc6, 0x3d, 0xe8, 0xad, 0xb8, 0xb3, 0x5c, 0xc5, 0x62, 0x91, 0x6d, 0x53, 0x8d, 0x8c, - 0x4d, 0xd8, 0x28, 0xa1, 0xca, 0x78, 0x95, 0x2d, 0x3b, 0x43, 0x01, 0xfe, 0x10, 0xe0, 0xd6, 0x72, - 0x1d, 0xdb, 0x8a, 0xfd, 0x30, 0xd2, 0xb5, 0x47, 0xed, 0xc3, 0xd1, 0x11, 0x53, 0x27, 0xf1, 0x55, - 0xaa, 0x30, 0x0b, 0x36, 0xc6, 0x6b, 0xd8, 0x7a, 0x00, 0x08, 0x44, 0xe8, 0xac, 0xac, 0x68, 0xa5, - 0x96, 0x25, 0xbe, 0xf1, 0x03, 0x5a, 0x97, 0x65, 0xf3, 0x50, 0x95, 0xfa, 0x86, 0x0a, 0x7b, 0x21, - 0x84, 0xa6, 0x52, 0x1a, 0x8f, 0x61, 0xb3, 0x82, 0x92, 0x42, 0x46, 0x14, 0xaf, 0x93, 0x65, 0xf4, - 0x87, 0x2e, 0x0c, 0x4c, 0x1e, 0x05, 0xbe, 0x17, 0x71, 0x7c, 0x01, 0x43, 0x7e, 0x37, 0xe7, 0xb2, - 0xe0, 0xb5, 0x0a, 0x60, 0xa5, 0xcd, 0x59, 0xaa, 0x27, 0xb0, 0x67, 0xc6, 0xf8, 0x58, 0x91, 0x55, - 0x95, 0x81, 0x94, 0x53, 0x91, 0xad, 0x9e, 0xa6, 0x6c, 0xd5, 0xae, 0x54, 0xab, 0xb4, 0xad, 0xd0, - 0xd5, 0x63, 0x45, 0x57, 0x9d, 0xda, 0xc0, 0x25, 0xbe, 0x3a, 0x2e, 0xf1, 0x55, 0xb7, 0x76, 0xf9, - 0x0d, 0x84, 0x75, 0x5c, 0x22, 0xac, 0x5e, 0xad, 0x6b, 0x03, 0x63, 0x7d, 0x54, 0x60, 0xac, 0x7e, - 0xa5, 0x50, 0xa5, 0x63, 0x0d, 0x65, 0x3d, 0xcf, 0x28, 0x6b, 0x50, 0x21, 0x39, 0xe5, 0x52, 0xe5, - 0xac, 0xa7, 0x29, 0x90, 0x87, 0xb5, 0x9b, 0x56, 0x21, 0xad, 0xe3, 0x12, 0x69, 0x41, 0x6d, 0x3a, - 0x0d, 0xac, 0xf5, 0x93, 0x32, 0x6b, 0x49, 0xea, 0x39, 0xa8, 0xf8, 0x36, 0xd2, 0xd6, 0x8f, 0x8a, - 0xb4, 0xb5, 0x5e, 0x21, 0x4b, 0x85, 0x85, 0x3a, 0xde, 0x7a, 0x9a, 0xf2, 0xd6, 0x46, 0x6d, 0x7a, - 0x4d, 0xc4, 0xf5, 0x98, 0xea, 0xa6, 0x82, 0x4b, 0xaa, 0x79, 0x1e, 0x86, 0x7e, 0xa8, 0x38, 0x47, - 0x0e, 0x8c, 0x43, 0xaa, 0xf9, 0x1c, 0x8d, 0xff, 0x87, 0xe4, 0x44, 0x8d, 0x17, 0xb0, 0x68, 0xfc, - 0x56, 0xcb, 0x7d, 0x09, 0x70, 0x54, 0x99, 0xb6, 0x15, 0x5b, 0xca, 0x51, 0x7c, 0x53, 0xbc, 0x5b, - 0x1e, 0x46, 0x84, 0x3c, 0xc9, 0x6b, 0xe9, 0x10, 0x9f, 0xc0, 0x96, 0x6b, 0x45, 0xb1, 0xdc, 0x94, - 0x99, 0x2a, 0xc2, 0xb6, 0x28, 0xc2, 0x4d, 0x52, 0xc8, 0xdd, 0x10, 0x62, 0xfc, 0x01, 0x6c, 0x17, - 0x6c, 0xad, 0x20, 0x98, 0x09, 0x0a, 0xe8, 0x08, 0x0a, 0x60, 0x99, 0xf5, 0x49, 0x10, 0x5c, 0x58, - 0xd1, 0xca, 0xf8, 0x20, 0xcf, 0xbf, 0xc4, 0xb8, 0xae, 0xbf, 0x4c, 0x19, 0xd7, 0xf5, 0x97, 0xc6, - 0xaf, 0x72, 0xb3, 0x9c, 0x5c, 0xbf, 0x03, 0x9d, 0xb9, 0x6f, 0xcb, 0xec, 0xc7, 0x47, 0x9b, 0x6a, - 0xc7, 0x5f, 0xfa, 0x36, 0x7f, 0x7b, 0x1f, 0x70, 0x53, 0x28, 0xb3, 0x4c, 0x5b, 0x92, 0x83, 0x44, - 0xa6, 0x2a, 0x7e, 0x3b, 0x8f, 0xff, 0x4b, 0xa2, 0x9b, 0x12, 0xd6, 0xdf, 0x67, 0xf4, 0x9f, 0xe7, - 0xe7, 0x21, 0x49, 0xfd, 0x9b, 0x89, 0x2d, 0xaf, 0x82, 0xf7, 0x18, 0xfb, 0x17, 0x74, 0x5b, 0x15, - 0xcb, 0xf9, 0x7d, 0x06, 0xdf, 0xce, 0x8f, 0x34, 0x2b, 0x64, 0x63, 0x07, 0xf0, 0x61, 0x85, 0xca, - 0x5b, 0xb9, 0x5c, 0x7b, 0xf8, 0x3d, 0xe8, 0xda, 0xce, 0x62, 0x11, 0xe9, 0x9d, 0x86, 0xdb, 0x49, - 0xaa, 0x8d, 0xdf, 0xb5, 0xa0, 0x27, 0xef, 0x16, 0x3c, 0x20, 0x9e, 0xb3, 0x1c, 0x6f, 0xe6, 0xd8, - 0x69, 0xc5, 0x88, 0xf1, 0xd4, 0xae, 0xdc, 0x96, 0xd9, 0xdd, 0x42, 0xa9, 0xc4, 0xce, 0x0d, 0x57, - 0x60, 0x17, 0xdf, 0xb8, 0x0f, 0x7d, 0x2f, 0xb9, 0x99, 0xc5, 0x77, 0x91, 0x40, 0x75, 0xc7, 0xec, - 0x79, 0xc9, 0xcd, 0xdb, 0xbb, 0x08, 0x8f, 0x60, 0xa3, 0x00, 0x7d, 0xc7, 0x56, 0x04, 0x3e, 0x56, - 0x4b, 0x13, 0xeb, 0x9e, 0xbe, 0x32, 0x47, 0x59, 0x11, 0x4c, 0x6d, 0x3c, 0x04, 0x51, 0x13, 0x33, - 0x49, 0x92, 0xb2, 0x56, 0x7a, 0x62, 0xdf, 0xc6, 0x24, 0x57, 0x2c, 0x4a, 0x17, 0xe7, 0xb7, 0x60, - 0x48, 0x3b, 0x29, 0x4d, 0xfa, 0xc2, 0x64, 0x40, 0x02, 0xa1, 0xfc, 0x10, 0x36, 0xf3, 0xcb, 0x58, - 0x9a, 0x0c, 0x64, 0x94, 0x5c, 0x2c, 0x0c, 0x0f, 0x60, 0x90, 0xd5, 0xe4, 0x50, 0x58, 0xf4, 0x2d, - 0x55, 0x8a, 0x53, 0xe8, 0xab, 0x25, 0xd6, 0x5e, 0xdc, 0x4f, 0xa0, 0x1b, 0x58, 0x61, 0x1c, 0xa9, - 0x0b, 0x32, 0x25, 0xb8, 0x4b, 0x2b, 0xa4, 0x5e, 0x49, 0x5d, 0xdf, 0xd2, 0xc4, 0x38, 0x86, 0x8d, - 0x92, 0x9c, 0x18, 0x2d, 0xf6, 0x63, 0xcb, 0x55, 0x57, 0xb7, 0x1c, 0x64, 0xd3, 0xb4, 0xf2, 0x69, - 0x8c, 0x63, 0x18, 0x66, 0x67, 0x48, 0xc7, 0x12, 0x24, 0x57, 0x9f, 0x65, 0x9d, 0x8d, 0x1a, 0x51, - 0xb8, 0xc0, 0xff, 0x5a, 0xf5, 0x10, 0x1d, 0x53, 0x0e, 0x9e, 0xfc, 0x49, 0x83, 0xd1, 0xe7, 0x92, - 0x02, 0x09, 0x8d, 0xb8, 0x09, 0xa3, 0xd7, 0x89, 0xeb, 0x2a, 0x11, 0x5b, 0xc3, 0x01, 0x74, 0x88, - 0x39, 0x99, 0x86, 0x43, 0xe8, 0x0a, 0x66, 0x64, 0x2d, 0x12, 0x12, 0x25, 0xb2, 0x36, 0x6e, 0xc0, - 0x30, 0xe3, 0x20, 0xd6, 0xa1, 0x61, 0x46, 0xc9, 0xac, 0x4b, 0xc3, 0x8c, 0x7a, 0xd8, 0x16, 0x8e, - 0xa0, 0xaf, 0x98, 0x82, 0x21, 0x02, 0xf4, 0xe4, 0x49, 0xb1, 0x6d, 0x0a, 0x2d, 0x8a, 0x9c, 0xed, - 0x90, 0x4b, 0x06, 0x6d, 0xb6, 0x8b, 0x63, 0x80, 0x1c, 0xd4, 0x6c, 0x0f, 0xd7, 0x61, 0x90, 0xc2, - 0x99, 0xed, 0x93, 0x9f, 0x28, 0x60, 0xa6, 0x3f, 0xf9, 0x7d, 0x17, 0x06, 0x69, 0x4d, 0x61, 0x0f, - 0x5a, 0x6f, 0x3e, 0x63, 0x6b, 0xb8, 0x05, 0x1b, 0x53, 0x2f, 0xe6, 0xa1, 0x67, 0xb9, 0x67, 0x74, - 0x1f, 0x30, 0x8d, 0x44, 0x67, 0xde, 0xdc, 0xb7, 0x1d, 0x6f, 0x29, 0x45, 0x2d, 0x8a, 0x79, 0x6a, - 0xd9, 0xaf, 0x7d, 0x6f, 0xce, 0x59, 0x1b, 0x19, 0xac, 0x7f, 0xe9, 0x59, 0x49, 0xbc, 0xf2, 0x43, - 0xe7, 0x37, 0xdc, 0x66, 0x1d, 0xdc, 0x85, 0xad, 0xa9, 0x17, 0x25, 0x8b, 0x85, 0x33, 0x77, 0xb8, - 0x17, 0x7f, 0x9a, 0x78, 0x76, 0xc4, 0xba, 0x88, 0x30, 0xfe, 0xd2, 0xbb, 0xf6, 0xfc, 0xaf, 0x3d, - 0xd5, 0x75, 0xb1, 0x1e, 0xea, 0xb0, 0x73, 0x6a, 0x45, 0xfc, 0x55, 0x12, 0xb8, 0xce, 0xdc, 0x8a, - 0xf9, 0x89, 0x6d, 0x87, 0x3c, 0x8a, 0x18, 0xa7, 0x20, 0xa4, 0x29, 0xcf, 0xbd, 0x48, 0x1d, 0x4a, - 0xf1, 0x39, 0x8f, 0xd8, 0x12, 0x0f, 0x60, 0xf7, 0x81, 0x46, 0xcc, 0xbc, 0xc2, 0x6f, 0x83, 0x5e, - 0x55, 0x9d, 0x5b, 0xd1, 0x65, 0xe8, 0xcc, 0x39, 0x73, 0x70, 0x07, 0x98, 0xd4, 0x0a, 0x18, 0x4f, - 0xbd, 0x20, 0x89, 0xd9, 0xaf, 0xd3, 0xf9, 0x95, 0xf4, 0x4d, 0x12, 0x93, 0xf8, 0xba, 0x22, 0xbe, - 0x14, 0x50, 0x61, 0x2e, 0xee, 0xc3, 0x76, 0x41, 0xfc, 0x05, 0xe5, 0x47, 0xbb, 0x73, 0x93, 0xaf, - 0x57, 0x2a, 0x9c, 0xa5, 0x67, 0xc5, 0x49, 0xc8, 0x99, 0x87, 0x7b, 0x80, 0xa4, 0x51, 0x5b, 0x92, - 0x26, 0xee, 0xa7, 0x33, 0x28, 0xb9, 0x9a, 0x21, 0xa8, 0x8a, 0xdd, 0x64, 0xe9, 0x78, 0xec, 0x1d, - 0xee, 0x02, 0x3b, 0xf7, 0x6f, 0x95, 0xf4, 0xcc, 0x8b, 0x9d, 0xf8, 0x9e, 0xfd, 0x59, 0xc3, 0x1d, - 0xd8, 0xcc, 0xc5, 0xe7, 0xa1, 0x9f, 0x04, 0xec, 0x2f, 0x1a, 0xee, 0x03, 0xe6, 0xd2, 0xcb, 0xd0, - 0x0f, 0xfc, 0xc8, 0x72, 0xd9, 0x5f, 0x35, 0xdc, 0x83, 0xad, 0x73, 0xff, 0x36, 0x3b, 0x05, 0xe9, - 0xf0, 0xb7, 0xd4, 0x21, 0x93, 0x7f, 0xce, 0x6f, 0xae, 0x78, 0xc8, 0xfe, 0xae, 0xe1, 0x01, 0xec, - 0x14, 0x15, 0x59, 0xac, 0x7f, 0x68, 0x6a, 0x45, 0x99, 0xea, 0x2b, 0x3f, 0xe6, 0xec, 0x9f, 0xa9, - 0x58, 0xed, 0x83, 0x0a, 0xf4, 0x2f, 0x0d, 0xb7, 0x61, 0x9c, 0x8b, 0x85, 0xed, 0xbf, 0x35, 0x9c, - 0xc0, 0x6e, 0x49, 0xe8, 0x78, 0xcb, 0x4b, 0xaa, 0x3e, 0xf6, 0x1f, 0xed, 0xe8, 0x8f, 0x5d, 0xd8, - 0x3c, 0x39, 0x7d, 0x39, 0x3d, 0x09, 0xe4, 0x04, 0x74, 0x97, 0x3f, 0x97, 0x35, 0x87, 0x35, 0xff, - 0xfe, 0x27, 0x75, 0x4d, 0x36, 0x1e, 0xa9, 0xd2, 0xc4, 0xba, 0x47, 0x80, 0x49, 0x6d, 0xaf, 0x4d, - 0x93, 0xc8, 0xb6, 0xe6, 0xe1, 0x5b, 0xc0, 0xa4, 0xae, 0xe1, 0xc6, 0x9f, 0x16, 0x4a, 0x1d, 0x9b, - 0x5e, 0x04, 0x26, 0x8d, 0xad, 0x37, 0xf9, 0xe7, 0x7d, 0x48, 0xd3, 0xbb, 0xc0, 0xa4, 0xb1, 0xff, - 0xc6, 0x17, 0x19, 0x7b, 0x60, 0xfd, 0xeb, 0xc0, 0xa4, 0xa1, 0x05, 0xa7, 0xed, 0x91, 0x3d, 0x44, - 0xdd, 0x9f, 0xfe, 0x49, 0x6d, 0x57, 0x4d, 0x3e, 0xb2, 0x37, 0xa8, 0xfb, 0x37, 0x3d, 0xa9, 0x6d, - 0x55, 0xf1, 0xe3, 0x94, 0xd2, 0xb0, 0xf6, 0x31, 0x62, 0x52, 0xdf, 0xef, 0xd3, 0xc6, 0xe4, 0x7f, - 0x23, 0x9b, 0x5e, 0x19, 0x26, 0x8d, 0x9d, 0x3c, 0x9e, 0x14, 0x39, 0x12, 0x1b, 0xdf, 0x1a, 0x26, - 0xcd, 0xfd, 0x3c, 0x7e, 0x92, 0xd3, 0x2a, 0x36, 0xbc, 0x38, 0x4c, 0x9a, 0x5a, 0xfa, 0xab, 0x9e, - 0x78, 0xcc, 0xfa, 0xe8, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xce, 0x8c, 0x71, 0x92, 0xe1, 0x12, - 0x00, 0x00, + 0x15, 0x8e, 0x3b, 0x7d, 0x3d, 0x9d, 0x74, 0x2a, 0x27, 0x37, 0xa7, 0xe1, 0x61, 0x64, 0x58, 0x36, + 0x33, 0x0c, 0x33, 0x28, 0xab, 0x45, 0x13, 0x16, 0x21, 0x25, 0x33, 0xd9, 0xa4, 0xb5, 0xda, 0x99, + 0xe0, 0x9d, 0xdd, 0x07, 0x40, 0xb4, 0x9c, 0x76, 0x75, 0xb7, 0x89, 0xdb, 0xf6, 0xf8, 0x92, 0x4d, + 0xf8, 0x23, 0xfc, 0x04, 0x7e, 0x01, 0x2f, 0x3c, 0xf1, 0x84, 0xc4, 0xfd, 0xf2, 0x57, 0xf8, 0x03, + 0xe8, 0x54, 0x95, 0xaf, 0xb1, 0x79, 0x9a, 0x7d, 0x69, 0xb9, 0xce, 0xad, 0xea, 0x54, 0x7d, 0xe7, + 0xab, 0xd3, 0x05, 0xdb, 0xf1, 0x7d, 0xc0, 0xa3, 0xe7, 0xe2, 0xf7, 0x59, 0x10, 0xfa, 0xb1, 0x8f, + 0x1d, 0x31, 0x30, 0xfe, 0xdb, 0x86, 0x9e, 0xc9, 0xdf, 0x25, 0x3c, 0x8a, 0xf1, 0x08, 0xda, 0x7c, + 0xb6, 0xf4, 0x75, 0xed, 0x91, 0x76, 0x34, 0x3c, 0xc6, 0x67, 0xd2, 0x5c, 0x69, 0xcf, 0x67, 0x4b, + 0xff, 0x72, 0xcd, 0x14, 0x16, 0xf8, 0x7d, 0xe8, 0xcc, 0xdd, 0x24, 0x5a, 0xea, 0x2d, 0x61, 0xba, + 0x53, 0x36, 0xfd, 0x94, 0x54, 0x97, 0x6b, 0xa6, 0xb4, 0xa1, 0xb0, 0x8e, 0x37, 0xf7, 0xf5, 0xf5, + 0xba, 0xb0, 0x13, 0x6f, 0x2e, 0xc2, 0x92, 0x05, 0xbe, 0x00, 0x88, 0x78, 0x3c, 0xf5, 0x83, 0xd8, + 0xf1, 0x3d, 0xbd, 0x2d, 0xec, 0x0f, 0xca, 0xf6, 0x5f, 0xf0, 0xf8, 0x8d, 0x50, 0x5f, 0xae, 0x99, + 0x83, 0x28, 0x1d, 0x90, 0xa7, 0xcd, 0x5d, 0xe7, 0x96, 0x87, 0xd3, 0xf8, 0x4e, 0xef, 0xd4, 0x79, + 0xbe, 0x92, 0xfa, 0xb7, 0x77, 0xe4, 0x69, 0xa7, 0x03, 0x3c, 0x86, 0xfe, 0x6c, 0xc9, 0x67, 0x37, + 0xe4, 0xd7, 0x15, 0x7e, 0x7b, 0x65, 0xbf, 0x97, 0xa4, 0x15, 0x5e, 0xbd, 0x99, 0xfc, 0xc4, 0x67, + 0xd0, 0x9d, 0xf9, 0xab, 0x95, 0x13, 0xeb, 0x3d, 0xe1, 0xb1, 0x5b, 0xf1, 0x10, 0xba, 0xcb, 0x35, + 0x53, 0x59, 0xd1, 0x76, 0xbd, 0x4b, 0x78, 0x78, 0xaf, 0xf7, 0xeb, 0xb6, 0xeb, 0x67, 0xa4, 0xa2, + 0xed, 0x12, 0x36, 0x94, 0x8a, 0xe3, 0x39, 0xf1, 0x74, 0xb6, 0xb4, 0x1c, 0x4f, 0x1f, 0xd4, 0xa5, + 0x32, 0xf1, 0x9c, 0xf8, 0x25, 0xa9, 0x29, 0x15, 0x27, 0x1d, 0xe0, 0x27, 0x30, 0xbc, 0xe6, 0x0b, + 0xc7, 0x9b, 0x5e, 0xbb, 0xfe, 0xec, 0x46, 0x07, 0xe1, 0xaa, 0x97, 0x5d, 0xcf, 0xc8, 0xe0, 0x8c, + 0xf4, 0x97, 0x6b, 0x26, 0x5c, 0x67, 0x23, 0xfc, 0x18, 0x06, 0xdc, 0xb3, 0x95, 0xeb, 0x50, 0xb8, + 0xee, 0x57, 0x10, 0xe0, 0xd9, 0xa9, 0x63, 0x9f, 0xab, 0x6f, 0x4a, 0x2d, 0x08, 0x7d, 0x7f, 0xae, + 0x6f, 0xd4, 0xa5, 0x76, 0x45, 0x2a, 0x4a, 0x4d, 0xd8, 0x9c, 0xf5, 0xa0, 0x73, 0x6b, 0xb9, 0x09, + 0x37, 0x3e, 0x84, 0x61, 0x01, 0x56, 0xa8, 0x43, 0x6f, 0xc5, 0xa3, 0xc8, 0x5a, 0x70, 0x81, 0xbd, + 0x81, 0x99, 0x0e, 0x8d, 0x11, 0x6c, 0x14, 0x41, 0x65, 0x6c, 0x66, 0x8e, 0x04, 0x1c, 0xe3, 0xc7, + 0xc0, 0xaa, 0xb8, 0x40, 0x06, 0xeb, 0x37, 0xfc, 0x5e, 0x05, 0xa2, 0x4f, 0xdc, 0x55, 0xd3, 0x0a, + 0xb4, 0x0e, 0x4c, 0xb5, 0x06, 0x23, 0xf3, 0xcd, 0x90, 0x81, 0x23, 0x68, 0xc5, 0x77, 0xc2, 0x75, + 0xc3, 0x6c, 0xc5, 0x77, 0xc6, 0x23, 0x18, 0x95, 0x51, 0xf0, 0xc0, 0xe2, 0xbb, 0xd9, 0x02, 0xc5, + 0x31, 0xd2, 0x5c, 0xf2, 0xa8, 0xa5, 0x89, 0x1c, 0x18, 0x2f, 0x32, 0x2b, 0xb1, 0x23, 0xc5, 0x35, + 0x6e, 0xc8, 0x35, 0xee, 0x43, 0x77, 0xc9, 0x9d, 0xc5, 0x32, 0x16, 0x8b, 0x6c, 0x9b, 0x6a, 0x64, + 0x6c, 0xc1, 0x66, 0x09, 0x55, 0xc6, 0xab, 0x6c, 0xd9, 0x19, 0x0a, 0xf0, 0x87, 0x00, 0xb7, 0x96, + 0xeb, 0xd8, 0x56, 0xec, 0x87, 0x91, 0xae, 0x3d, 0x5a, 0x3f, 0x1a, 0x1e, 0x33, 0x75, 0x12, 0x5f, + 0xa5, 0x0a, 0xb3, 0x60, 0x63, 0xbc, 0x86, 0xed, 0x07, 0x80, 0x40, 0x84, 0xf6, 0xd2, 0x8a, 0x96, + 0x6a, 0x59, 0xe2, 0x1b, 0x3f, 0xa0, 0x75, 0x59, 0x36, 0x0f, 0x55, 0xa9, 0x6f, 0xaa, 0xb0, 0x97, + 0x42, 0x68, 0x2a, 0xa5, 0xf1, 0x18, 0xb6, 0x2a, 0x28, 0x29, 0x64, 0xa4, 0x95, 0x32, 0xfa, 0x43, + 0x07, 0xfa, 0x26, 0x8f, 0x02, 0xdf, 0x8b, 0x38, 0xbe, 0x80, 0x01, 0xbf, 0x9b, 0x71, 0x59, 0xf0, + 0x5a, 0x05, 0xb0, 0xd2, 0xe6, 0x3c, 0xd5, 0x13, 0xd8, 0x33, 0x63, 0x7c, 0xac, 0xc8, 0xaa, 0xca, + 0x40, 0xca, 0xa9, 0xc8, 0x56, 0x4f, 0x53, 0xb6, 0x5a, 0xaf, 0x54, 0xab, 0xb4, 0xad, 0xd0, 0xd5, + 0x63, 0x45, 0x57, 0xed, 0xda, 0xc0, 0x25, 0xbe, 0x3a, 0x29, 0xf1, 0x55, 0xa7, 0x76, 0xf9, 0x0d, + 0x84, 0x75, 0x52, 0x22, 0xac, 0x6e, 0xad, 0x6b, 0x03, 0x63, 0x7d, 0x54, 0x60, 0xac, 0x5e, 0xa5, + 0x50, 0xa5, 0x63, 0x0d, 0x65, 0x3d, 0xcf, 0x28, 0xab, 0x5f, 0x21, 0x39, 0xe5, 0x52, 0xe5, 0xac, + 0xa7, 0x29, 0x90, 0x07, 0xb5, 0x9b, 0x56, 0x21, 0xad, 0x93, 0x12, 0x69, 0x41, 0x6d, 0x3a, 0x0d, + 0xac, 0xf5, 0x93, 0x32, 0x6b, 0x49, 0xea, 0x39, 0xac, 0xf8, 0x36, 0xd2, 0xd6, 0x8f, 0x8a, 0xb4, + 0xb5, 0x51, 0x21, 0x4b, 0x85, 0x85, 0x3a, 0xde, 0x7a, 0x9a, 0xf2, 0xd6, 0x66, 0x6d, 0x7a, 0x4d, + 0xc4, 0xf5, 0x98, 0xea, 0xa6, 0x82, 0x4b, 0xaa, 0x79, 0x1e, 0x86, 0x7e, 0xa8, 0x38, 0x47, 0x0e, + 0x8c, 0x23, 0xaa, 0xf9, 0x1c, 0x8d, 0xff, 0x87, 0xe4, 0x44, 0x8d, 0x17, 0xb0, 0x68, 0xfc, 0x56, + 0xcb, 0x7d, 0x09, 0x70, 0x54, 0x99, 0xb6, 0x15, 0x5b, 0xca, 0x51, 0x7c, 0x53, 0xbc, 0x5b, 0x1e, + 0x46, 0x84, 0x3c, 0xc9, 0x6b, 0xe9, 0x10, 0x9f, 0xc0, 0xb6, 0x6b, 0x45, 0xb1, 0xdc, 0x94, 0xa9, + 0x2a, 0xc2, 0x75, 0x51, 0x84, 0x5b, 0xa4, 0x90, 0xbb, 0x21, 0xc4, 0xf8, 0x03, 0xd8, 0x29, 0xd8, + 0x5a, 0x41, 0x30, 0x15, 0x14, 0xd0, 0x16, 0x14, 0xc0, 0x32, 0xeb, 0xd3, 0x20, 0xb8, 0xb4, 0xa2, + 0xa5, 0xf1, 0x41, 0x9e, 0x7f, 0x89, 0x71, 0x5d, 0x7f, 0x91, 0x32, 0xae, 0xeb, 0x2f, 0x8c, 0x5f, + 0xe5, 0x66, 0x39, 0xb9, 0x7e, 0x07, 0xda, 0x33, 0xdf, 0x96, 0xd9, 0x8f, 0x8e, 0xb7, 0xd4, 0x8e, + 0xbf, 0xf4, 0x6d, 0xfe, 0xf6, 0x3e, 0xe0, 0xa6, 0x50, 0x66, 0x99, 0xb6, 0x24, 0x07, 0x89, 0x4c, + 0x55, 0xfc, 0xf5, 0x3c, 0xfe, 0x2f, 0x89, 0x6e, 0x4a, 0x58, 0x7f, 0x9f, 0xd1, 0x7f, 0x9e, 0x9f, + 0x87, 0x24, 0xf5, 0x6f, 0x26, 0xb6, 0xbc, 0x0a, 0xde, 0x63, 0xec, 0x5f, 0xd0, 0x6d, 0x55, 0x2c, + 0xe7, 0xf7, 0x19, 0x7c, 0x27, 0x3f, 0xd2, 0xac, 0x90, 0x8d, 0x5d, 0xc0, 0x87, 0x15, 0x2a, 0x6f, + 0xe5, 0x72, 0xed, 0xe1, 0xf7, 0xa0, 0x63, 0x3b, 0xf3, 0x79, 0xa4, 0xb7, 0x1b, 0x6e, 0x27, 0xa9, + 0x36, 0x7e, 0xd7, 0x82, 0xae, 0xbc, 0x5b, 0xf0, 0x90, 0x78, 0xce, 0x72, 0xbc, 0xa9, 0x63, 0xa7, + 0x15, 0x23, 0xc6, 0x13, 0xbb, 0xe9, 0xb6, 0xa4, 0x54, 0x62, 0x67, 0xc5, 0x15, 0xd8, 0xc5, 0x37, + 0x1e, 0x40, 0xcf, 0x4b, 0x56, 0xd3, 0xf8, 0x2e, 0x12, 0xa8, 0x6e, 0x9b, 0x5d, 0x2f, 0x59, 0xbd, + 0xbd, 0x8b, 0xf0, 0x18, 0x36, 0x0b, 0xd0, 0x77, 0x6c, 0x45, 0xe0, 0x23, 0xb5, 0x34, 0xb1, 0xee, + 0xc9, 0x2b, 0x73, 0x98, 0x15, 0xc1, 0xc4, 0xc6, 0x23, 0x10, 0x35, 0x31, 0x95, 0x24, 0x29, 0x6b, + 0xa5, 0x2b, 0xf6, 0x6d, 0x44, 0x72, 0xc5, 0xa2, 0x74, 0x71, 0x7e, 0x0b, 0x06, 0xb4, 0x93, 0xd2, + 0xa4, 0x27, 0x4c, 0xfa, 0x24, 0x10, 0xca, 0x0f, 0x61, 0x2b, 0xbf, 0x8c, 0xa5, 0x49, 0x5f, 0x46, + 0xc9, 0xc5, 0xc2, 0xf0, 0x10, 0xfa, 0x59, 0x4d, 0x0e, 0x84, 0x45, 0xcf, 0x52, 0xa5, 0x38, 0x81, + 0x9e, 0x5a, 0x62, 0xed, 0xc5, 0xfd, 0x04, 0x3a, 0x81, 0x15, 0xc6, 0x91, 0xba, 0x20, 0x53, 0x82, + 0xbb, 0xb2, 0x42, 0xea, 0x95, 0xd4, 0xf5, 0x2d, 0x4d, 0x8c, 0x13, 0xd8, 0x2c, 0xc9, 0x89, 0xd1, + 0x62, 0x3f, 0xb6, 0x5c, 0x75, 0x75, 0xcb, 0x41, 0x36, 0x4d, 0x2b, 0x9f, 0xc6, 0x38, 0x81, 0x41, + 0x76, 0x86, 0x74, 0x2c, 0x41, 0x72, 0xfd, 0x59, 0xd6, 0xd9, 0xa8, 0x11, 0x85, 0x0b, 0xfc, 0xaf, + 0x55, 0x0f, 0xd1, 0x36, 0xe5, 0xe0, 0xc9, 0x9f, 0x34, 0x18, 0x7e, 0x2e, 0x29, 0x90, 0xd0, 0x88, + 0x5b, 0x30, 0x7c, 0x9d, 0xb8, 0xae, 0x12, 0xb1, 0x35, 0xec, 0x43, 0x9b, 0x98, 0x93, 0x69, 0x38, + 0x80, 0x8e, 0x60, 0x46, 0xd6, 0x22, 0x21, 0x51, 0x22, 0x5b, 0xc7, 0x4d, 0x18, 0x64, 0x1c, 0xc4, + 0xda, 0x34, 0xcc, 0x28, 0x99, 0x75, 0x68, 0x98, 0x51, 0x0f, 0xdb, 0xc6, 0x21, 0xf4, 0x14, 0x53, + 0x30, 0x44, 0x80, 0xae, 0x3c, 0x29, 0xb6, 0x43, 0xa1, 0x45, 0x91, 0xb3, 0x5d, 0x72, 0xc9, 0xa0, + 0xcd, 0xf6, 0x70, 0x04, 0x90, 0x83, 0x9a, 0xed, 0xe3, 0x06, 0xf4, 0x53, 0x38, 0xb3, 0x03, 0xf2, + 0x13, 0x05, 0xcc, 0xf4, 0x27, 0xbf, 0xef, 0x40, 0x3f, 0xad, 0x29, 0xec, 0x42, 0xeb, 0xcd, 0x67, + 0x6c, 0x0d, 0xb7, 0x61, 0x73, 0xe2, 0xc5, 0x3c, 0xf4, 0x2c, 0xf7, 0x9c, 0xee, 0x03, 0xa6, 0x91, + 0xe8, 0xdc, 0x9b, 0xf9, 0xb6, 0xe3, 0x2d, 0xa4, 0xa8, 0x45, 0x31, 0xcf, 0x2c, 0xfb, 0xb5, 0xef, + 0xcd, 0x38, 0x5b, 0x47, 0x06, 0x1b, 0x5f, 0x7a, 0x56, 0x12, 0x2f, 0xfd, 0xd0, 0xf9, 0x0d, 0xb7, + 0x59, 0x1b, 0xf7, 0x60, 0x7b, 0xe2, 0x45, 0xc9, 0x7c, 0xee, 0xcc, 0x1c, 0xee, 0xc5, 0x9f, 0x26, + 0x9e, 0x1d, 0xb1, 0x0e, 0x22, 0x8c, 0xbe, 0xf4, 0x6e, 0x3c, 0xff, 0x6b, 0x4f, 0x75, 0x5d, 0xac, + 0x8b, 0x3a, 0xec, 0x9e, 0x59, 0x11, 0x7f, 0x95, 0x04, 0xae, 0x33, 0xb3, 0x62, 0x7e, 0x6a, 0xdb, + 0x21, 0x8f, 0x22, 0xc6, 0x29, 0x08, 0x69, 0xca, 0x73, 0xcf, 0x53, 0x87, 0x52, 0x7c, 0xce, 0x23, + 0xb6, 0xc0, 0x43, 0xd8, 0x7b, 0xa0, 0x11, 0x33, 0x2f, 0xf1, 0xdb, 0xa0, 0x57, 0x55, 0x17, 0x56, + 0x74, 0x15, 0x3a, 0x33, 0xce, 0x1c, 0xdc, 0x05, 0x26, 0xb5, 0x02, 0xc6, 0x13, 0x2f, 0x48, 0x62, + 0xf6, 0xeb, 0x74, 0x7e, 0x25, 0x7d, 0x93, 0xc4, 0x24, 0xbe, 0xa9, 0x88, 0xaf, 0x04, 0x54, 0x98, + 0x8b, 0x07, 0xb0, 0x53, 0x10, 0x7f, 0x41, 0xf9, 0xd1, 0xee, 0xac, 0xf2, 0xf5, 0x4a, 0x85, 0xb3, + 0xf0, 0xac, 0x38, 0x09, 0x39, 0xf3, 0x70, 0x1f, 0x90, 0x34, 0x6a, 0x4b, 0xd2, 0xc4, 0xfd, 0x74, + 0x06, 0x25, 0x57, 0x33, 0x04, 0x55, 0xb1, 0x9b, 0x2c, 0x1c, 0x8f, 0xbd, 0xc3, 0x3d, 0x60, 0x17, + 0xfe, 0xad, 0x92, 0x9e, 0x7b, 0xb1, 0x13, 0xdf, 0xb3, 0x3f, 0x6b, 0xb8, 0x0b, 0x5b, 0xb9, 0xf8, + 0x22, 0xf4, 0x93, 0x80, 0xfd, 0x45, 0xc3, 0x03, 0xc0, 0x5c, 0x7a, 0x15, 0xfa, 0x81, 0x1f, 0x59, + 0x2e, 0xfb, 0xab, 0x86, 0xfb, 0xb0, 0x7d, 0xe1, 0xdf, 0x66, 0xa7, 0x20, 0x1d, 0xfe, 0x96, 0x3a, + 0x64, 0xf2, 0xcf, 0xf9, 0xea, 0x9a, 0x87, 0xec, 0xef, 0x1a, 0x1e, 0xc2, 0x6e, 0x51, 0x91, 0xc5, + 0xfa, 0x87, 0xa6, 0x56, 0x94, 0xa9, 0xbe, 0xf2, 0x63, 0xce, 0xfe, 0x99, 0x8a, 0xd5, 0x3e, 0xa8, + 0x40, 0xff, 0xd2, 0x70, 0x07, 0x46, 0xb9, 0x58, 0xd8, 0xfe, 0x5b, 0xc3, 0x31, 0xec, 0x95, 0x84, + 0x8e, 0xb7, 0xb8, 0xa2, 0xea, 0x63, 0xff, 0xd1, 0x8e, 0xff, 0xd8, 0x81, 0xad, 0xd3, 0xb3, 0x97, + 0x93, 0xd3, 0x40, 0x4e, 0x40, 0x77, 0xf9, 0x73, 0x59, 0x73, 0x58, 0xf3, 0xef, 0x7f, 0x5c, 0xd7, + 0x64, 0xe3, 0xb1, 0x2a, 0x4d, 0xac, 0x7b, 0x04, 0x18, 0xd7, 0xf6, 0xda, 0x34, 0x89, 0x6c, 0x6b, + 0x1e, 0xbe, 0x05, 0x8c, 0xeb, 0x1a, 0x6e, 0xfc, 0x69, 0xa1, 0xd4, 0xb1, 0xe9, 0x45, 0x60, 0xdc, + 0xd8, 0x7a, 0x93, 0x7f, 0xde, 0x87, 0x34, 0xbd, 0x0b, 0x8c, 0x1b, 0xfb, 0x6f, 0x7c, 0x91, 0xb1, + 0x07, 0xd6, 0xbf, 0x0e, 0x8c, 0x1b, 0x5a, 0x70, 0xda, 0x1e, 0xd9, 0x43, 0xd4, 0xfd, 0xe9, 0x1f, + 0xd7, 0x76, 0xd5, 0xe4, 0x23, 0x7b, 0x83, 0xba, 0x7f, 0xd3, 0xe3, 0xda, 0x56, 0x15, 0x3f, 0x4e, + 0x29, 0x0d, 0x6b, 0x1f, 0x23, 0xc6, 0xf5, 0xfd, 0x3e, 0x6d, 0x4c, 0xfe, 0x37, 0xb2, 0xe9, 0x95, + 0x61, 0xdc, 0xd8, 0xc9, 0xe3, 0x69, 0x91, 0x23, 0xb1, 0xf1, 0xad, 0x61, 0xdc, 0xdc, 0xcf, 0xe3, + 0x27, 0x39, 0xad, 0x62, 0xc3, 0x8b, 0xc3, 0xb8, 0xa9, 0xa5, 0xbf, 0xee, 0x8a, 0xc7, 0xac, 0x8f, + 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x1e, 0x2e, 0xe2, 0x17, 0xe1, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 16dc2856..045c2d68 100644 --- a/types/types.proto +++ b/types/types.proto @@ -11,63 +11,63 @@ package types; // so we don't have to type switch // (would be twice as fast, but we're talking about 15ns) enum MessageType { - NullMessage = 0x00; + 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; - Proof = 0x18; + Echo = 0x01; + Flush = 0x02; + Info = 0x03; + SetOption = 0x04; + Exception = 0x05; + DeliverTx = 0x11; + CheckTx = 0x12; + Commit = 0x13; + Query = 0x14; + InitChain = 0x15; + BeginBlock = 0x16; + EndBlock = 0x17; + Proof = 0x18; } //---------------------------------------- // Code types enum CodeType { - OK = 0; + OK = 0; - // General response codes, 0 ~ 99 - InternalError = 1; - EncodingError = 2; - BadNonce = 3; - Unauthorized = 4; - InsufficientFunds = 5; - UnknownRequest = 6; + // 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 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; + // 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; } @@ -87,7 +87,7 @@ message Request { RequestInitChain init_chain = 9; RequestBeginBlock begin_block = 10; RequestEndBlock end_block = 11; - RequestProof proof = 12; + RequestProof proof = 12; } } @@ -107,20 +107,20 @@ message RequestSetOption{ } message RequestDeliverTx{ - bytes tx = 1; + bytes tx = 1; } message RequestCheckTx{ - bytes tx = 1; + bytes tx = 1; } message RequestQuery{ - bytes query = 1; + bytes query = 1; } message RequestProof{ - bytes key = 1; - int64 height = 2; + bytes key = 1; + uint64 height = 2; } message RequestCommit{ @@ -157,7 +157,7 @@ message Response { ResponseInitChain init_chain = 10; ResponseBeginBlock begin_block = 11; ResponseEndBlock end_block = 12; - ResponseProof proof = 13; + ResponseProof proof = 13; } } @@ -202,9 +202,9 @@ message ResponseQuery{ } message ResponseProof{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } message ResponseCommit{ @@ -250,8 +250,8 @@ message PartSetHeader { } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; } //---------------------------------------- @@ -265,7 +265,7 @@ service ABCIApplication { rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); rpc Query(RequestQuery) returns (ResponseQuery); - rpc Proof(RequestProof) returns (ResponseProof); + rpc Proof(RequestProof) returns (ResponseProof); rpc Commit(RequestCommit) returns (ResponseCommit); rpc InitChain(RequestInitChain) returns (ResponseInitChain); rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); From f94ae5eeed7659a46a5d186cc706c31aa55edc66 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 23 Jan 2017 20:14:14 -0800 Subject: [PATCH 199/545] TSP -> Socket --- README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index aec2d922..b73724e6 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ Blockchains are a system for multi-master state machine replication. **ABCI** is an interface that defines the boundary between the replication engine (the blockchain), -and the state machine (the application). It is most commonly implemented in the form of the Tendermint Socket Protocol (TSP), -also known as Teaspoon. +and the state machine (the application). By using a socket protocol, we enable a consensus engine running in one process to manage an application state running in another. @@ -162,12 +161,12 @@ The ABCI is a client/server interface where the replication engine (blockchain) and the state machine (application) forms the server. As blocks are committed in the blockchain, they are forwarded to the application. -This repository provides two implementations of an ABCI client & server: TSP (Tendermint Socket Protocol) and via GRPC. +This repository provides two implementations of an ABCI client & server: via socket and via GRPC. -## TSP +## Socket ABCI is best implemented as a streaming protocol. -The TSP provides for asynchronous, ordered message passing over unix or tcp. +The socket implementation provides for asynchronous, ordered message passing over unix or tcp. Messages are serialized using Protobuf3 and length-prefixed. Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. @@ -177,9 +176,9 @@ For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), th GRPC is an rpc framework native to Protocol Buffers with support in many languages. Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than -the ordered, asynchronous TSP. +the ordered, asynchronous socket protocol. -Note the length-prefixing used in TSP does not apply for GRPC. +Note the length-prefixing used in the socket implementation does not apply for GRPC. # Tools and Apps From 9745f07beeb2cccd9047d0e7a5bdcf230f9fef24 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 23 Jan 2017 20:26:17 -0800 Subject: [PATCH 200/545] common -> cmn --- client/client.go | 4 ++-- client/grpc_client.go | 8 ++++---- client/local_client.go | 6 +++--- client/socket_client.go | 12 ++++++------ cmd/counter/main.go | 4 ++-- cmd/dummy/main.go | 4 ++-- example/chain_aware/chain_aware_app.go | 4 ++-- example/dummy/dummy_test.go | 4 ++-- example/dummy/persistent_dummy.go | 4 ++-- example/example_test.go | 4 ++-- server/grpc_server.go | 8 ++++---- server/server.go | 6 +++--- server/socket_server.go | 8 ++++---- tests/benchmarks/parallel/parallel.go | 4 ++-- tests/benchmarks/simple/simple.go | 4 ++-- 15 files changed, 42 insertions(+), 42 deletions(-) diff --git a/client/client.go b/client/client.go index dc70645e..9b3d1a75 100644 --- a/client/client.go +++ b/client/client.go @@ -5,11 +5,11 @@ import ( "sync" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) type Client interface { - common.Service + cmn.Service SetResponseCallback(Callback) Error() error diff --git a/client/grpc_client.go b/client/grpc_client.go index ec6dcdb7..fc67b8b9 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -10,13 +10,13 @@ import ( grpc "google.golang.org/grpc" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) // A stripped copy of the remoteClient that makes // synchronous calls using grpc type grpcClient struct { - common.BaseService + cmn.BaseService mustConnect bool client types.ABCIApplicationClient @@ -32,13 +32,13 @@ func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { addr: addr, mustConnect: mustConnect, } - cli.BaseService = *common.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 common.Connect(addr) + return cmn.Connect(addr) } func (cli *grpcClient) OnStart() error { diff --git a/client/local_client.go b/client/local_client.go index 235e3fce..459f4223 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -4,11 +4,11 @@ import ( "sync" types "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) type localClient struct { - common.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 = *common.NewBaseService(log, "localClient", cli) + cli.BaseService = *cmn.NewBaseService(log, "localClient", cli) return cli } diff --git a/client/socket_client.go b/client/socket_client.go index a0def235..d5335d8e 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -11,7 +11,7 @@ import ( "time" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + 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 { - common.BaseService + cmn.BaseService reqQueue chan *ReqRes - flushTimer *common.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: common.NewThrottleTimer("socketClient", flushThrottleMS), + flushTimer: cmn.NewThrottleTimer("socketClient", flushThrottleMS), mustConnect: mustConnect, addr: addr, reqSent: list.New(), resCb: nil, } - cli.BaseService = *common.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,7 +65,7 @@ func (cli *socketClient) OnStart() error { var conn net.Conn RETRY_LOOP: for { - conn, err = common.Connect(cli.addr) + conn, err = cmn.Connect(cli.addr) if err != nil { if cli.mustConnect { return err diff --git a/cmd/counter/main.go b/cmd/counter/main.go index c547d372..6858fc43 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) func main() { @@ -24,7 +24,7 @@ func main() { } // Wait forever - common.TrapSignal(func() { + cmn.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 71102e1a..b48a15c7 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) func main() { @@ -32,7 +32,7 @@ func main() { } // Wait forever - common.TrapSignal(func() { + cmn.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index a9a23375..766f570c 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) func main() { @@ -23,7 +23,7 @@ func main() { } // Wait forever - common.TrapSignal(func() { + cmn.TrapSignal(func() { // Cleanup srv.Stop() }) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index ca1ec7f9..49dce920 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" ) @@ -109,7 +109,7 @@ func TestValSetChanges(t *testing.T) { vals := make([]*types.Validator, total) for i := 0; i < total; i++ { pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(fmt.Sprintf("test%d", i))).PubKey().Bytes() - power := common.RandInt() + power := cmn.RandInt() vals[i] = &types.Validator{pubkey, uint64(power)} } // iniitalize with the first nInit diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 40c85aea..547fc1eb 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" dbm "github.com/tendermint/go-db" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" @@ -150,7 +150,7 @@ func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { wire.WriteBinary(lastBlock, buf, n, err) if *err != nil { // TODO - common.PanicCrisis(*err) + cmn.PanicCrisis(*err) } db.Set(lastBlockKey, buf.Bytes()) } diff --git a/example/example_test.go b/example/example_test.go index b60fc276..26921083 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -17,7 +17,7 @@ import ( nilapp "github.com/tendermint/abci/example/nil" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) func TestDummy(t *testing.T) { @@ -105,7 +105,7 @@ func testStream(t *testing.T, app types.Application) { // test grpc func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { - return common.Connect(addr) + return cmn.Connect(addr) } func testGRPCSync(t *testing.T, app *types.GRPCApplication) { diff --git a/server/grpc_server.go b/server/grpc_server.go index 3893b20b..944d4e42 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -7,13 +7,13 @@ import ( "google.golang.org/grpc" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 type GRPCServer struct { - common.BaseService + cmn.BaseService proto string addr string @@ -23,7 +23,7 @@ type GRPCServer struct { app types.ABCIApplicationServer } -func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (common.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) (common.Se listener: nil, app: app, } - s.BaseService = *common.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 1d42e7d5..eb71b132 100644 --- a/server/server.go +++ b/server/server.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) -func NewServer(protoAddr, transport string, app types.Application) (common.Service, error) { - var s common.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 070fba8c..76185505 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -9,13 +9,13 @@ import ( "sync" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 type SocketServer struct { - common.BaseService + cmn.BaseService proto string addr string @@ -29,7 +29,7 @@ type SocketServer struct { app types.Application } -func NewSocketServer(protoAddr string, app types.Application) (common.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) (common.Service, e app: app, conns: make(map[int]net.Conn), } - s.BaseService = *common.NewBaseService(nil, "ABCIServer", s) + s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) _, err := s.Start() // Just start it return s, err } diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index ac8d4e9e..f01fba4c 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -6,12 +6,12 @@ import ( "log" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) func main() { - conn, err := common.Connect("unix://test.sock") + conn, err := cmn.Connect("unix://test.sock") if err != nil { log.Fatal(err.Error()) } diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 75b66923..498aac34 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -8,12 +8,12 @@ import ( "reflect" "github.com/tendermint/abci/types" - common "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) func main() { - conn, err := common.Connect("unix://test.sock") + conn, err := cmn.Connect("unix://test.sock") if err != nil { log.Fatal(err.Error()) } From 4bdddf9829dce751b25b3166df604dd125cf4b80 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 23 Jan 2017 20:48:12 -0800 Subject: [PATCH 201/545] First commit to demonstrate change --- README.md | 10 +++++++--- types/types.proto | 33 +++++++++++---------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 23c1ac65..083b031c 100644 --- a/README.md +++ b/README.md @@ -85,16 +85,20 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil #### Query * __Arguments__: - * `Data ([]byte)`: The query request bytes + * `Query ([]byte)`: The query request bytes + * `Path (string)`: Path of request + * `Height (uint64)`: The block height for which you want the query (default=0 returns data for the latest committed block) + * `Prove (bool)`: Return Merkle proof with response * __Returns__: - * `Code (uint32)`: Response code * `Data ([]byte)`: The query response bytes * `Log (string)`: Debug or error message + * `Height (uint64)`: The block height from which data was derived + * `Proof ([]byte)`: Proof for the data, if requested #### Proof * __Arguments__: * `Key ([]byte)`: The key whose data you want to verifiably query - * `Height (int64)`: The block height for which you want the proof (default=0 returns the proof for last committed block) + * `Height (uint64)`: The block height for which you want the proof (default=0 returns the proof for last committed block) * __Returns__: * `Code (uint32)`: Response code * `Data ([]byte)`: The query response bytes diff --git a/types/types.proto b/types/types.proto index 045c2d68..14093476 100644 --- a/types/types.proto +++ b/types/types.proto @@ -18,14 +18,13 @@ enum MessageType { Info = 0x03; SetOption = 0x04; Exception = 0x05; - DeliverTx = 0x11; + DeliverTx = 0x11; CheckTx = 0x12; Commit = 0x13; Query = 0x14; InitChain = 0x15; BeginBlock = 0x16; EndBlock = 0x17; - Proof = 0x18; } //---------------------------------------- @@ -87,7 +86,6 @@ message Request { RequestInitChain init_chain = 9; RequestBeginBlock begin_block = 10; RequestEndBlock end_block = 11; - RequestProof proof = 12; } } @@ -107,20 +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; -} - -message RequestProof{ - bytes key = 1; - uint64 height = 2; + bytes query = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; } message RequestCommit{ @@ -157,7 +153,6 @@ message Response { ResponseInitChain init_chain = 10; ResponseBeginBlock begin_block = 11; ResponseEndBlock end_block = 12; - ResponseProof proof = 13; } } @@ -196,15 +191,10 @@ message ResponseCheckTx{ } message ResponseQuery{ - CodeType code = 1; - bytes data = 2; - string log = 3; -} - -message ResponseProof{ - CodeType code = 1; bytes data = 2; string log = 3; + uint64 height = 4; + bytes proof = 5; } message ResponseCommit{ @@ -250,8 +240,8 @@ message PartSetHeader { } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; } //---------------------------------------- @@ -265,7 +255,6 @@ service ABCIApplication { rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); rpc Query(RequestQuery) returns (ResponseQuery); - rpc Proof(RequestProof) returns (ResponseProof); rpc Commit(RequestCommit) returns (ResponseCommit); rpc InitChain(RequestInitChain) returns (ResponseInitChain); rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); From 2a4894310d5b0c8f69e99782d7d905f21236f947 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 23 Jan 2017 23:42:09 -0800 Subject: [PATCH 202/545] Remove Proof message, replace with more flexible Query --- README.md | 27 +- client/client.go | 6 +- client/grpc_client.go | 36 +- client/local_client.go | 31 +- client/socket_client.go | 36 +- cmd/abci-cli/{tmsp-cli.go => abci-cli.go} | 144 ++++--- cmd/counter/main.go | 2 +- example/chain_aware/chain_aware_app.go | 10 +- example/chain_aware/chain_aware_test.go | 8 +- example/counter/counter.go | 15 +- example/dummy/dummy.go | 50 ++- example/dummy/dummy_test.go | 56 +-- example/dummy/persistent_dummy.go | 8 +- example/nil/nil_app.go | 8 +- glide.lock | 2 +- server/socket_server.go | 9 +- tests/test_cli/ex1.abci.out.new | 44 ++ types/application.go | 14 +- types/code.go | 3 + types/messages.go | 20 +- types/types.pb.go | 468 +++++++++------------- types/types.proto | 11 +- 22 files changed, 429 insertions(+), 579 deletions(-) rename cmd/abci-cli/{tmsp-cli.go => abci-cli.go} (78%) create mode 100644 tests/test_cli/ex1.abci.out.new create mode 100644 types/code.go diff --git a/README.md b/README.md index 083b031c..ec6db985 100644 --- a/README.md +++ b/README.md @@ -85,27 +85,20 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil #### Query * __Arguments__: - * `Query ([]byte)`: The query request bytes - * `Path (string)`: Path of request + * `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) - * `Prove (bool)`: Return Merkle proof with response - * __Returns__: - * `Data ([]byte)`: The query response bytes - * `Log (string)`: Debug or error message - * `Height (uint64)`: The block height from which data was derived - * `Proof ([]byte)`: Proof for the data, if requested - -#### Proof - * __Arguments__: - * `Key ([]byte)`: The key whose data you want to verifiably query - * `Height (uint64)`: The block height for which you want the proof (default=0 returns the proof for last committed block) + * `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 * `Log (string)`: Debug or error message - * __Usage__:
- Return a Merkle proof from the key/value pair back to the application hash.
- *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. Hopefully this will be improved soon(ish) + *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. Hopefully this will be improved soon(ish) #### Flush * __Usage__:
diff --git a/client/client.go b/client/client.go index bbd41398..25bb23ec 100644 --- a/client/client.go +++ b/client/client.go @@ -20,8 +20,7 @@ type Client interface { SetOptionAsync(key string, value string) *ReqRes DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes - QueryAsync(tx []byte) *ReqRes - ProofAsync(key []byte, blockHeight uint64) *ReqRes + QueryAsync(reqQuery types.RequestQuery) *ReqRes CommitAsync() *ReqRes FlushSync() error @@ -30,8 +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) - ProofSync(key []byte, blockHeight uint64) (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 63fb16a4..1a48fed1 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -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) @@ -182,15 +182,6 @@ func (cli *grpcClient) QueryAsync(query []byte) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}}) } -func (cli *grpcClient) ProofAsync(key []byte, blockHeight uint64) *ReqRes { - req := types.ToRequestProof(key, blockHeight) - res, err := cli.client.Proof(context.Background(), req.GetProof(), grpc.FailFast(true)) - if err != nil { - cli.StopForError(err) - } - return cli.finishAsyncCall(req, &types.Response{&types.Response_Proof{res}}) -} - func (cli *grpcClient) CommitAsync() *ReqRes { req := types.ToRequestCommit() res, err := cli.client.Commit(context.Background(), req.GetCommit(), grpc.FailFast(true)) @@ -264,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 { @@ -310,22 +301,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) ProofSync(key []byte, blockHeight uint64) (res types.Result) { - reqres := cli.ProofAsync(key, blockHeight) - 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.GetProof() - 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 + if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { + return *resQuery_, nil } - resp := reqres.Response.GetQuery() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return resQuery, nil } func (cli *grpcClient) CommitSync() (res types.Result) { diff --git a/client/local_client.go b/client/local_client.go index 7450573e..f056289c 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -89,23 +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), - ) -} - -func (app *localClient) ProofAsync(key []byte, blockHeight uint64) *ReqRes { - app.mtx.Lock() - res := app.Application.Proof(key, blockHeight) - app.mtx.Unlock() - return app.callback( - types.ToRequestProof(key, blockHeight), - types.ToResponseQuery(res.Code, res.Data, res.Log), + types.ToRequestQuery(reqQuery), + types.ToResponseQuery(resQuery), ) } @@ -195,18 +185,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 -} - -func (app *localClient) ProofSync(key []byte, blockHeight uint64) (res types.Result) { - app.mtx.Lock() - res = app.Application.Proof(key, blockHeight) - app.mtx.Unlock() - return res + return resQuery, nil } func (app *localClient) CommitSync() (res types.Result) { diff --git a/client/socket_client.go b/client/socket_client.go index 04d07a55..733aff4a 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -251,12 +251,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) ProofAsync(key []byte, blockHeight uint64) *ReqRes { - return cli.queueRequest(types.ToRequestProof(key, blockHeight)) +func (cli *socketClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { + return cli.queueRequest(types.ToRequestQuery(reqQuery)) } func (cli *socketClient) CommitAsync() *ReqRes { @@ -284,7 +280,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 { @@ -304,9 +300,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) { @@ -339,25 +334,18 @@ 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) ProofSync(key []byte, blockHeight uint64) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestProof(key, blockHeight)) - cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetProof() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} -} func (cli *socketClient) CommitSync() (res types.Result) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() @@ -450,8 +438,6 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { _, ok = res.Value.(*types.Response_Commit) case *types.Request_Query: _, ok = res.Value.(*types.Response_Query) - case *types.Request_Proof: - _, ok = res.Value.(*types.Response_Proof) case *types.Request_InitChain: _, ok = res.Value.(*types.Response_InitChain) case *types.Request_BeginBlock: diff --git a/cmd/abci-cli/tmsp-cli.go b/cmd/abci-cli/abci-cli.go similarity index 78% rename from cmd/abci-cli/tmsp-cli.go rename to cmd/abci-cli/abci-cli.go index ccdd41d4..5c2b0051 100644 --- a/cmd/abci-cli/tmsp-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "os" - "strconv" "strings" "github.com/tendermint/abci/client" @@ -16,28 +15,15 @@ import ( "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: "", - } - - if printCode { - rsp.Code = res.Code.String() - } - - return rsp + Data []byte + Code types.CodeType + Key []byte + Value []byte + Log string + Height string + Proof []byte } // client is a global variable so it can be reused by the console @@ -132,13 +118,6 @@ func main() { return cmdQuery(c) }, }, - { - Name: "proof", - Usage: "Get proof for a key", - Action: func(c *cli.Context) error { - return cmdProof(c) - }, - }, } app.Before = before err := app.Run(os.Args) @@ -228,9 +207,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 } @@ -240,8 +220,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 } @@ -251,9 +232,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 } @@ -268,8 +250,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 } @@ -284,20 +269,26 @@ 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{ + 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 { @@ -307,36 +298,29 @@ 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) - return nil -} - -// Prove application state -func cmdProof(c *cli.Context) error { - args := c.Args() - if len(args) < 1 { - return errors.New("Command proof takes 1 or 2 arguments") - } - keyBytes, err := stringOrHexToBytes(c.Args()[0]) + 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 } - - var height uint64 - if len(args) == 2 { - height, _ = strconv.ParseUint(args[1], 10, 0) - } - res := client.ProofSync(keyBytes, height) - rsp := newResponse(res, string(res.Data), true) - printResponse(c, rsp) + printResponse(c, response{ + Code: resQuery.Code, + Key: resQuery.Key, + Value: resQuery.Value, + Log: resQuery.Log, + Height: fmt.Sprintf("%v", 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") @@ -344,19 +328,29 @@ 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 != types.CodeType_OK { + 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.Res.Log != "" { - fmt.Printf("-> log: %s\n", rsp.Res.Log) + if len(rsp.Key) != 0 { + fmt.Printf("-> key: %s\n", rsp.Key) + fmt.Printf("-> key.hex: %X\n", rsp.Key) + } + if len(rsp.Value) != 0 { + fmt.Printf("-> value: %s\n", rsp.Value) + fmt.Printf("-> value.hex: %X\n", rsp.Value) + } + if rsp.Log != "" { + fmt.Printf("-> log: %s\n", rsp.Log) + } + if rsp.Height != "" { + fmt.Printf("-> height: %s\n", rsp.Height) + } + if rsp.Proof != nil { + fmt.Printf("-> proof: %X\n", rsp.Proof) } if verbose { diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 218224a0..0714380b 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -3,9 +3,9 @@ package main import ( "flag" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" + . "github.com/tendermint/go-common" ) func main() { diff --git a/example/chain_aware/chain_aware_app.go b/example/chain_aware/chain_aware_app.go index 361f2a07..8bedfc61 100644 --- a/example/chain_aware/chain_aware_app.go +++ b/example/chain_aware/chain_aware_app.go @@ -57,12 +57,10 @@ 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) Proof(key []byte, blockHeight uint64) types.Result { - return types.NewResultOK(nil, Fmt("Proof is not supported")) +func (app *ChainAwareApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { + return types.ResponseQuery{ + Value: []byte(Fmt("%d,%d", app.beginCount, app.endCount)), + } } func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { diff --git a/example/chain_aware/chain_aware_test.go b/example/chain_aware/chain_aware_test.go index f5283a38..18fa8ea9 100644 --- a/example/chain_aware/chain_aware_test.go +++ b/example/chain_aware/chain_aware_test.go @@ -5,10 +5,10 @@ import ( "strings" "testing" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) func TestChainAware(t *testing.T) { @@ -39,10 +39,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/counter/counter.go b/example/counter/counter.go index 62c10826..2f929c3e 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -71,19 +71,14 @@ func (app *CounterApplication) Commit() types.Result { } } -func (app *CounterApplication) Query(query []byte) types.Result { - queryStr := string(query) +func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { - switch queryStr { + switch reqQuery.Path { case "hash": - return types.NewResultOK(nil, Fmt("%v", app.hashCount)) + return types.ResponseQuery{Value: []byte(Fmt("%v", app.hashCount))} case "tx": - return types.NewResultOK(nil, Fmt("%v", app.txCount)) + return types.ResponseQuery{Value: []byte(Fmt("%v", app.txCount))} } - return types.ErrUnknownRequest.SetLog(Fmt("Invalid nonce. Expected hash or tx, got %v", queryStr)) -} - -func (app *CounterApplication) Proof(key []byte, blockHeight uint64) types.Result { - return types.NewResultOK(nil, Fmt("Proof is not supported")) + return types.ResponseQuery{Log: Fmt("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 8f606f98..d37a1f76 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,13 +1,11 @@ package dummy import ( - "encoding/hex" "strings" "github.com/tendermint/abci/types" . "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" ) type DummyApplication struct { @@ -47,30 +45,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), "") -} - -func (app *DummyApplication) Proof(key []byte, blockHeight uint64) types.Result { - // TODO: when go-merkle supports querying older blocks without possible panics, - // we should store a cache and allow a query. But for now it is impossible. - // And this is just a Dummy application anyway, what do you expect? ;) - if blockHeight != 0 { - return types.ErrUnknownRequest +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 } - proof, exists := app.state.Proof(key) - if !exists { - return types.NewResultOK(nil, Fmt("Cannot find key = %v", key)) - } - return types.NewResultOK(proof, "Found the key") -} - -type QueryResult struct { - Index int `json:"index"` - Value string `json:"value"` - ValueHex string `json:"valueHex"` - Exists bool `json:"exists"` } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index aa6c837d..b17192b4 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -6,7 +6,6 @@ import ( "sort" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" @@ -14,7 +13,6 @@ import ( . "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" merkle "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" ) func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { @@ -25,21 +23,24 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string require.False(t, ar.IsErr(), ar) // make sure query is fine - r := app.Query([]byte(key)) - require.False(t, r.IsErr(), r) - q := new(QueryResult) - err := wire.ReadJSONBytes(r.Data, q) - require.Nil(t, err) - require.Equal(t, value, q.Value) + 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 - rp := app.Proof([]byte(key), 0) - require.False(t, rp.IsErr(), rp) - p, err := merkle.LoadProof(rp.Data) + 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, p.Valid()) - assert.Equal(t, []byte(key), p.Key()) - assert.Equal(t, []byte(value), p.Value()) + 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) { @@ -285,19 +286,24 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) require.False(t, ar.IsErr(), ar) // make sure query is fine - r := app.QuerySync([]byte(key)) - require.False(t, r.IsErr(), r) - q := new(QueryResult) - err := wire.ReadJSONBytes(r.Data, q) + resQuery, err := app.QuerySync(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + }) require.Nil(t, err) - require.Equal(t, value, q.Value) + require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, value, string(resQuery.Value)) // make sure proof is fine - rp := app.ProofSync([]byte(key), 0) - require.False(t, rp.IsErr(), rp) - p, err := merkle.LoadProof(rp.Data) + resQuery, err = app.QuerySync(types.RequestQuery{ + Path: "/store", + Data: []byte(key), + Prove: true, + }) require.Nil(t, err) - require.True(t, p.Valid()) - assert.Equal(t, []byte(key), p.Key()) - assert.Equal(t, []byte(value), p.Value()) + 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 781e1aae..2afb6c12 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -89,12 +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) Proof(key []byte, blockHeight uint64) types.Result { - return app.app.Proof(key, blockHeight) +func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { + return app.app.Query(reqQuery) } // Save the validators in the merkle tree diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 694184a2..95ac8d59 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -31,10 +31,6 @@ func (app *NilApplication) Commit() types.Result { return types.NewResultOK([]byte("nil"), "") } -func (app *NilApplication) Query(query []byte) types.Result { - return types.NewResultOK(nil, "") -} - -func (app *NilApplication) Proof(key []byte, blockHeight uint64) types.Result { - return types.NewResultOK(nil, "") +func (app *NilApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { + return resQuery } diff --git a/glide.lock b/glide.lock index 4829e672..c67e08b3 100644 --- a/glide.lock +++ b/glide.lock @@ -53,7 +53,7 @@ imports: - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 7a86b4486f2cd84ac885c5bbc609fdee2905f5d1 + version: 653cb1f631528351ddbc359b994eb0c96f0341cd - name: github.com/tendermint/go-process version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire diff --git a/server/socket_server.go b/server/socket_server.go index 046b55ed..7832a900 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -8,8 +8,8 @@ import ( "strings" "sync" - . "github.com/tendermint/go-common" "github.com/tendermint/abci/types" + . "github.com/tendermint/go-common" ) // var maxNumberConnections = 2 @@ -184,11 +184,8 @@ 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) - case *types.Request_Proof: - res := s.app.Proof(r.Proof.Key, r.Proof.Height) - responses <- types.ToResponseProof(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) diff --git a/tests/test_cli/ex1.abci.out.new b/tests/test_cli/ex1.abci.out.new new file mode 100644 index 00000000..aa8c5ae0 --- /dev/null +++ b/tests/test_cli/ex1.abci.out.new @@ -0,0 +1,44 @@ +> echo hello +-> data: hello +-> data.hex: 68656C6C6F + +> info +-> data: {"size":0} +-> data.hex: 7B2273697A65223A307D + +> commit + +> deliver_tx "abc" + +> info +-> data: {"size":1} +-> data.hex: 7B2273697A65223A317D + +> commit +-> data: uü~„»×ˆíX–$ðlú‡EÑ +-> data.hex: 750502FC7E84BBD788ED589624F06CFA871845D1 + +> query "abc" +-> key: abc +-> key.hex: 616263 +-> value: abc +-> value.hex: 616263 +-> log: exists +-> height: 0 +-> proof: 010114750502FC7E84BBD788ED589624F06CFA871845D1000114750502FC7E84BBD788ED589624F06CFA871845D1 + +> deliver_tx "def=xyz" + +> commit +-> data: v9;Š.E†°iLbžËQ²†ïÕ +-> data.hex: 76393B8A182E450286B0694C629ECB51B286EFD5 + +> query "def" +-> key: def +-> key.hex: 646566 +-> value: xyz +-> value.hex: 78797A +-> log: exists +-> height: 0 +-> proof: 010114C08027141879A7B95E1339565CE60D7DB7A115EB01010101020114750502FC7E84BBD788ED589624F06CFA871845D100011476393B8A182E450286B0694C629ECB51B286EFD5 + diff --git a/types/application.go b/types/application.go index 4cea52ff..404437fe 100644 --- a/types/application.go +++ b/types/application.go @@ -20,10 +20,7 @@ type Application interface { CheckTx(tx []byte) Result // Query for state - Query(query []byte) Result - - // Get proof for state - Proof(key []byte, blockHeight uint64) Result + Query(reqQuery RequestQuery) ResponseQuery // Return the application Merkle root hash Commit() Result @@ -81,13 +78,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 -} - -func (app *GRPCApplication) Proof(ctx context.Context, req *RequestProof) (*ResponseProof, error) { - r := app.app.Proof(req.Key, req.Height) - return &ResponseProof{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) { diff --git a/types/code.go b/types/code.go new file mode 100644 index 00000000..c99a0bbe --- /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 af79f7eb..fe2d310a 100644 --- a/types/messages.go +++ b/types/messages.go @@ -49,15 +49,9 @@ func ToRequestCommit() *Request { } } -func ToRequestQuery(queryBytes []byte) *Request { +func ToRequestQuery(reqQuery RequestQuery) *Request { return &Request{ - Value: &Request_Query{&RequestQuery{queryBytes}}, - } -} - -func ToRequestProof(key []byte, blockHeight uint64) *Request { - return &Request{ - Value: &Request_Proof{&RequestProof{key, blockHeight}}, + Value: &Request_Query{&reqQuery}, } } @@ -129,15 +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}}, - } -} - -func ToResponseProof(code CodeType, data []byte, log string) *Response { - return &Response{ - Value: &Response_Proof{&ResponseProof{code, data, log}}, + Value: &Response_Query{&resQuery}, } } diff --git a/types/types.pb.go b/types/types.pb.go index e53f877e..e0ae1076 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -17,7 +17,6 @@ It has these top-level messages: RequestDeliverTx RequestCheckTx RequestQuery - RequestProof RequestCommit RequestInitChain RequestBeginBlock @@ -31,7 +30,6 @@ It has these top-level messages: ResponseDeliverTx ResponseCheckTx ResponseQuery - ResponseProof ResponseCommit ResponseInitChain ResponseBeginBlock @@ -83,7 +81,6 @@ const ( MessageType_InitChain MessageType = 21 MessageType_BeginBlock MessageType = 22 MessageType_EndBlock MessageType = 23 - MessageType_Proof MessageType = 24 ) var MessageType_name = map[int32]string{ @@ -100,7 +97,6 @@ var MessageType_name = map[int32]string{ 21: "InitChain", 22: "BeginBlock", 23: "EndBlock", - 24: "Proof", } var MessageType_value = map[string]int32{ "NullMessage": 0, @@ -116,7 +112,6 @@ var MessageType_value = map[string]int32{ "InitChain": 21, "BeginBlock": 22, "EndBlock": 23, - "Proof": 24, } func (x MessageType) String() string { @@ -245,7 +240,6 @@ type Request struct { // *Request_InitChain // *Request_BeginBlock // *Request_EndBlock - // *Request_Proof Value isRequest_Value `protobuf_oneof:"value"` } @@ -291,9 +285,6 @@ type Request_BeginBlock struct { type Request_EndBlock struct { EndBlock *RequestEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,oneof"` } -type Request_Proof struct { - Proof *RequestProof `protobuf:"bytes,12,opt,name=proof,oneof"` -} func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} @@ -306,7 +297,6 @@ func (*Request_Query) isRequest_Value() {} func (*Request_InitChain) isRequest_Value() {} func (*Request_BeginBlock) isRequest_Value() {} func (*Request_EndBlock) isRequest_Value() {} -func (*Request_Proof) isRequest_Value() {} func (m *Request) GetValue() isRequest_Value { if m != nil { @@ -392,13 +382,6 @@ func (m *Request) GetEndBlock() *RequestEndBlock { return nil } -func (m *Request) GetProof() *RequestProof { - if x, ok := m.GetValue().(*Request_Proof); ok { - return x.Proof - } - return nil -} - // XXX_OneofFuncs is for the internal use of the proto package. func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Request_OneofMarshaler, _Request_OneofUnmarshaler, _Request_OneofSizer, []interface{}{ @@ -413,7 +396,6 @@ func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error (*Request_InitChain)(nil), (*Request_BeginBlock)(nil), (*Request_EndBlock)(nil), - (*Request_Proof)(nil), } } @@ -476,11 +458,6 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.EndBlock); err != nil { return err } - case *Request_Proof: - b.EncodeVarint(12<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Proof); err != nil { - return err - } case nil: default: return fmt.Errorf("Request.Value has unexpected type %T", x) @@ -579,14 +556,6 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_EndBlock{msg} return true, err - case 12: // value.proof - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(RequestProof) - err := b.DecodeMessage(msg) - m.Value = &Request_Proof{msg} - return true, err default: return false, nil } @@ -651,11 +620,6 @@ func _Request_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(11<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Request_Proof: - s := proto.Size(x.Proof) - n += proto.SizeVarint(12<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -752,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{} } @@ -760,44 +727,41 @@ 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 } -type RequestProof struct { - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` -} - -func (m *RequestProof) Reset() { *m = RequestProof{} } -func (m *RequestProof) String() string { return proto.CompactTextString(m) } -func (*RequestProof) ProtoMessage() {} -func (*RequestProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } - -func (m *RequestProof) GetKey() []byte { +func (m *RequestQuery) GetPath() string { if m != nil { - return m.Key + return m.Path } - return nil + return "" } -func (m *RequestProof) GetHeight() uint64 { +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 { } func (m *RequestCommit) Reset() { *m = RequestCommit{} } func (m *RequestCommit) String() string { return proto.CompactTextString(m) } func (*RequestCommit) ProtoMessage() {} -func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } type RequestInitChain struct { Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` @@ -806,7 +770,7 @@ type RequestInitChain struct { func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } func (*RequestInitChain) ProtoMessage() {} -func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *RequestInitChain) GetValidators() []*Validator { if m != nil { @@ -823,7 +787,7 @@ type RequestBeginBlock struct { func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} -func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *RequestBeginBlock) GetHash() []byte { if m != nil { @@ -846,7 +810,7 @@ type RequestEndBlock struct { func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} -func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *RequestEndBlock) GetHeight() uint64 { if m != nil { @@ -869,14 +833,13 @@ type Response struct { // *Response_InitChain // *Response_BeginBlock // *Response_EndBlock - // *Response_Proof Value isResponse_Value `protobuf_oneof:"value"` } func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} -func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } type isResponse_Value interface { isResponse_Value() @@ -918,9 +881,6 @@ type Response_BeginBlock struct { type Response_EndBlock struct { EndBlock *ResponseEndBlock `protobuf:"bytes,12,opt,name=end_block,json=endBlock,oneof"` } -type Response_Proof struct { - Proof *ResponseProof `protobuf:"bytes,13,opt,name=proof,oneof"` -} func (*Response_Exception) isResponse_Value() {} func (*Response_Echo) isResponse_Value() {} @@ -934,7 +894,6 @@ func (*Response_Query) isResponse_Value() {} func (*Response_InitChain) isResponse_Value() {} func (*Response_BeginBlock) isResponse_Value() {} func (*Response_EndBlock) isResponse_Value() {} -func (*Response_Proof) isResponse_Value() {} func (m *Response) GetValue() isResponse_Value { if m != nil { @@ -1027,13 +986,6 @@ func (m *Response) GetEndBlock() *ResponseEndBlock { return nil } -func (m *Response) GetProof() *ResponseProof { - if x, ok := m.GetValue().(*Response_Proof); ok { - return x.Proof - } - return nil -} - // XXX_OneofFuncs is for the internal use of the proto package. func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Response_OneofMarshaler, _Response_OneofUnmarshaler, _Response_OneofSizer, []interface{}{ @@ -1049,7 +1001,6 @@ func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) erro (*Response_InitChain)(nil), (*Response_BeginBlock)(nil), (*Response_EndBlock)(nil), - (*Response_Proof)(nil), } } @@ -1117,11 +1068,6 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.EndBlock); err != nil { return err } - case *Response_Proof: - b.EncodeVarint(13<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Proof); err != nil { - return err - } case nil: default: return fmt.Errorf("Response.Value has unexpected type %T", x) @@ -1228,14 +1174,6 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_EndBlock{msg} return true, err - case 13: // value.proof - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(ResponseProof) - err := b.DecodeMessage(msg) - m.Value = &Response_Proof{msg} - return true, err default: return false, nil } @@ -1305,11 +1243,6 @@ func _Response_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(12<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Response_Proof: - s := proto.Size(x.Proof) - n += proto.SizeVarint(13<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -1324,7 +1257,7 @@ type ResponseException struct { func (m *ResponseException) Reset() { *m = ResponseException{} } func (m *ResponseException) String() string { return proto.CompactTextString(m) } func (*ResponseException) ProtoMessage() {} -func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *ResponseException) GetError() string { if m != nil { @@ -1340,7 +1273,7 @@ type ResponseEcho struct { func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } func (*ResponseEcho) ProtoMessage() {} -func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *ResponseEcho) GetMessage() string { if m != nil { @@ -1355,7 +1288,7 @@ type ResponseFlush struct { func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } func (*ResponseFlush) ProtoMessage() {} -func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } type ResponseInfo struct { Data string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` @@ -1367,7 +1300,7 @@ type ResponseInfo struct { func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } func (*ResponseInfo) ProtoMessage() {} -func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *ResponseInfo) GetData() string { if m != nil { @@ -1404,7 +1337,7 @@ type ResponseSetOption struct { func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } func (*ResponseSetOption) ProtoMessage() {} -func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *ResponseSetOption) GetLog() string { if m != nil { @@ -1422,7 +1355,7 @@ type ResponseDeliverTx struct { func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } func (*ResponseDeliverTx) ProtoMessage() {} -func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *ResponseDeliverTx) GetCode() CodeType { if m != nil { @@ -1454,7 +1387,7 @@ type ResponseCheckTx struct { func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } func (*ResponseCheckTx) ProtoMessage() {} -func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *ResponseCheckTx) GetCode() CodeType { if m != nil { @@ -1478,15 +1411,19 @@ 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{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} -func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *ResponseQuery) GetCode() CodeType { if m != nil { @@ -1495,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 @@ -1509,38 +1474,6 @@ func (m *ResponseQuery) GetLog() string { return "" } -type ResponseProof 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"` -} - -func (m *ResponseProof) Reset() { *m = ResponseProof{} } -func (m *ResponseProof) String() string { return proto.CompactTextString(m) } -func (*ResponseProof) ProtoMessage() {} -func (*ResponseProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } - -func (m *ResponseProof) GetCode() CodeType { - if m != nil { - return m.Code - } - return CodeType_OK -} - -func (m *ResponseProof) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - -func (m *ResponseProof) GetLog() string { - if m != nil { - return m.Log - } - return "" -} - type ResponseCommit 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"` @@ -1550,7 +1483,7 @@ type ResponseCommit struct { func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} -func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *ResponseCommit) GetCode() CodeType { if m != nil { @@ -1579,7 +1512,7 @@ type ResponseInitChain struct { func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } func (*ResponseInitChain) ProtoMessage() {} -func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } type ResponseBeginBlock struct { } @@ -1587,7 +1520,7 @@ type ResponseBeginBlock struct { func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} -func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } type ResponseEndBlock struct { Diffs []*Validator `protobuf:"bytes,4,rep,name=diffs" json:"diffs,omitempty"` @@ -1596,7 +1529,7 @@ type ResponseEndBlock struct { func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} -func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *ResponseEndBlock) GetDiffs() []*Validator { if m != nil { @@ -1620,7 +1553,7 @@ type Header struct { func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *Header) GetChainId() string { if m != nil { @@ -1693,7 +1626,7 @@ type BlockID struct { func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} -func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *BlockID) GetHash() []byte { if m != nil { @@ -1717,7 +1650,7 @@ type PartSetHeader struct { func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *PartSetHeader) GetTotal() uint64 { if m != nil { @@ -1741,7 +1674,7 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1766,7 +1699,6 @@ func init() { proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") - proto.RegisterType((*RequestProof)(nil), "types.RequestProof") proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") proto.RegisterType((*RequestInitChain)(nil), "types.RequestInitChain") proto.RegisterType((*RequestBeginBlock)(nil), "types.RequestBeginBlock") @@ -1780,7 +1712,6 @@ func init() { proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") - proto.RegisterType((*ResponseProof)(nil), "types.ResponseProof") proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") @@ -1811,7 +1742,6 @@ type ABCIApplicationClient interface { DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) - Proof(ctx context.Context, in *RequestProof, opts ...grpc.CallOption) (*ResponseProof, error) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) @@ -1889,15 +1819,6 @@ func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opt return out, nil } -func (c *aBCIApplicationClient) Proof(ctx context.Context, in *RequestProof, opts ...grpc.CallOption) (*ResponseProof, error) { - out := new(ResponseProof) - err := grpc.Invoke(ctx, "/types.ABCIApplication/Proof", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { out := new(ResponseCommit) err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...) @@ -1944,7 +1865,6 @@ type ABCIApplicationServer interface { DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) Query(context.Context, *RequestQuery) (*ResponseQuery, error) - Proof(context.Context, *RequestProof) (*ResponseProof, error) Commit(context.Context, *RequestCommit) (*ResponseCommit, error) InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) @@ -2081,24 +2001,6 @@ func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } -func _ABCIApplication_Proof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestProof) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIApplicationServer).Proof(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/Proof", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).Proof(ctx, req.(*RequestProof)) - } - return interceptor(ctx, in, info, handler) -} - func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RequestCommit) if err := dec(in); err != nil { @@ -2203,10 +2105,6 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ MethodName: "Query", Handler: _ABCIApplication_Query_Handler, }, - { - MethodName: "Proof", - Handler: _ABCIApplication_Proof_Handler, - }, { MethodName: "Commit", Handler: _ABCIApplication_Commit_Handler, @@ -2231,112 +2129,112 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1710 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x6f, 0xe4, 0x48, - 0x15, 0x8e, 0x3b, 0x7d, 0x3d, 0x9d, 0x74, 0x2a, 0x27, 0x37, 0xa7, 0xe1, 0x61, 0x64, 0x58, 0x36, - 0x33, 0x0c, 0x33, 0x28, 0xab, 0x45, 0x13, 0x16, 0x21, 0x25, 0x33, 0xd9, 0xa4, 0xb5, 0xda, 0x99, - 0xe0, 0x9d, 0xdd, 0x07, 0x40, 0xb4, 0x9c, 0x76, 0x75, 0xb7, 0x89, 0xdb, 0xf6, 0xf8, 0x92, 0x4d, - 0xf8, 0x23, 0xfc, 0x04, 0x7e, 0x01, 0x2f, 0x3c, 0xf1, 0x84, 0xc4, 0xfd, 0xf2, 0x57, 0xf8, 0x03, - 0xe8, 0x54, 0x95, 0xaf, 0xb1, 0x79, 0x9a, 0x7d, 0x69, 0xb9, 0xce, 0xad, 0xea, 0x54, 0x7d, 0xe7, - 0xab, 0xd3, 0x05, 0xdb, 0xf1, 0x7d, 0xc0, 0xa3, 0xe7, 0xe2, 0xf7, 0x59, 0x10, 0xfa, 0xb1, 0x8f, - 0x1d, 0x31, 0x30, 0xfe, 0xdb, 0x86, 0x9e, 0xc9, 0xdf, 0x25, 0x3c, 0x8a, 0xf1, 0x08, 0xda, 0x7c, - 0xb6, 0xf4, 0x75, 0xed, 0x91, 0x76, 0x34, 0x3c, 0xc6, 0x67, 0xd2, 0x5c, 0x69, 0xcf, 0x67, 0x4b, - 0xff, 0x72, 0xcd, 0x14, 0x16, 0xf8, 0x7d, 0xe8, 0xcc, 0xdd, 0x24, 0x5a, 0xea, 0x2d, 0x61, 0xba, - 0x53, 0x36, 0xfd, 0x94, 0x54, 0x97, 0x6b, 0xa6, 0xb4, 0xa1, 0xb0, 0x8e, 0x37, 0xf7, 0xf5, 0xf5, - 0xba, 0xb0, 0x13, 0x6f, 0x2e, 0xc2, 0x92, 0x05, 0xbe, 0x00, 0x88, 0x78, 0x3c, 0xf5, 0x83, 0xd8, - 0xf1, 0x3d, 0xbd, 0x2d, 0xec, 0x0f, 0xca, 0xf6, 0x5f, 0xf0, 0xf8, 0x8d, 0x50, 0x5f, 0xae, 0x99, - 0x83, 0x28, 0x1d, 0x90, 0xa7, 0xcd, 0x5d, 0xe7, 0x96, 0x87, 0xd3, 0xf8, 0x4e, 0xef, 0xd4, 0x79, - 0xbe, 0x92, 0xfa, 0xb7, 0x77, 0xe4, 0x69, 0xa7, 0x03, 0x3c, 0x86, 0xfe, 0x6c, 0xc9, 0x67, 0x37, - 0xe4, 0xd7, 0x15, 0x7e, 0x7b, 0x65, 0xbf, 0x97, 0xa4, 0x15, 0x5e, 0xbd, 0x99, 0xfc, 0xc4, 0x67, - 0xd0, 0x9d, 0xf9, 0xab, 0x95, 0x13, 0xeb, 0x3d, 0xe1, 0xb1, 0x5b, 0xf1, 0x10, 0xba, 0xcb, 0x35, - 0x53, 0x59, 0xd1, 0x76, 0xbd, 0x4b, 0x78, 0x78, 0xaf, 0xf7, 0xeb, 0xb6, 0xeb, 0x67, 0xa4, 0xa2, - 0xed, 0x12, 0x36, 0x94, 0x8a, 0xe3, 0x39, 0xf1, 0x74, 0xb6, 0xb4, 0x1c, 0x4f, 0x1f, 0xd4, 0xa5, - 0x32, 0xf1, 0x9c, 0xf8, 0x25, 0xa9, 0x29, 0x15, 0x27, 0x1d, 0xe0, 0x27, 0x30, 0xbc, 0xe6, 0x0b, - 0xc7, 0x9b, 0x5e, 0xbb, 0xfe, 0xec, 0x46, 0x07, 0xe1, 0xaa, 0x97, 0x5d, 0xcf, 0xc8, 0xe0, 0x8c, - 0xf4, 0x97, 0x6b, 0x26, 0x5c, 0x67, 0x23, 0xfc, 0x18, 0x06, 0xdc, 0xb3, 0x95, 0xeb, 0x50, 0xb8, - 0xee, 0x57, 0x10, 0xe0, 0xd9, 0xa9, 0x63, 0x9f, 0xab, 0x6f, 0x4a, 0x2d, 0x08, 0x7d, 0x7f, 0xae, - 0x6f, 0xd4, 0xa5, 0x76, 0x45, 0x2a, 0x4a, 0x4d, 0xd8, 0x9c, 0xf5, 0xa0, 0x73, 0x6b, 0xb9, 0x09, - 0x37, 0x3e, 0x84, 0x61, 0x01, 0x56, 0xa8, 0x43, 0x6f, 0xc5, 0xa3, 0xc8, 0x5a, 0x70, 0x81, 0xbd, - 0x81, 0x99, 0x0e, 0x8d, 0x11, 0x6c, 0x14, 0x41, 0x65, 0x6c, 0x66, 0x8e, 0x04, 0x1c, 0xe3, 0xc7, - 0xc0, 0xaa, 0xb8, 0x40, 0x06, 0xeb, 0x37, 0xfc, 0x5e, 0x05, 0xa2, 0x4f, 0xdc, 0x55, 0xd3, 0x0a, - 0xb4, 0x0e, 0x4c, 0xb5, 0x06, 0x23, 0xf3, 0xcd, 0x90, 0x81, 0x23, 0x68, 0xc5, 0x77, 0xc2, 0x75, - 0xc3, 0x6c, 0xc5, 0x77, 0xc6, 0x23, 0x18, 0x95, 0x51, 0xf0, 0xc0, 0xe2, 0xbb, 0xd9, 0x02, 0xc5, - 0x31, 0xd2, 0x5c, 0xf2, 0xa8, 0xa5, 0x89, 0x1c, 0x18, 0x2f, 0x32, 0x2b, 0xb1, 0x23, 0xc5, 0x35, - 0x6e, 0xc8, 0x35, 0xee, 0x43, 0x77, 0xc9, 0x9d, 0xc5, 0x32, 0x16, 0x8b, 0x6c, 0x9b, 0x6a, 0x64, - 0x6c, 0xc1, 0x66, 0x09, 0x55, 0xc6, 0xab, 0x6c, 0xd9, 0x19, 0x0a, 0xf0, 0x87, 0x00, 0xb7, 0x96, - 0xeb, 0xd8, 0x56, 0xec, 0x87, 0x91, 0xae, 0x3d, 0x5a, 0x3f, 0x1a, 0x1e, 0x33, 0x75, 0x12, 0x5f, - 0xa5, 0x0a, 0xb3, 0x60, 0x63, 0xbc, 0x86, 0xed, 0x07, 0x80, 0x40, 0x84, 0xf6, 0xd2, 0x8a, 0x96, - 0x6a, 0x59, 0xe2, 0x1b, 0x3f, 0xa0, 0x75, 0x59, 0x36, 0x0f, 0x55, 0xa9, 0x6f, 0xaa, 0xb0, 0x97, - 0x42, 0x68, 0x2a, 0xa5, 0xf1, 0x18, 0xb6, 0x2a, 0x28, 0x29, 0x64, 0xa4, 0x95, 0x32, 0xfa, 0x43, - 0x07, 0xfa, 0x26, 0x8f, 0x02, 0xdf, 0x8b, 0x38, 0xbe, 0x80, 0x01, 0xbf, 0x9b, 0x71, 0x59, 0xf0, - 0x5a, 0x05, 0xb0, 0xd2, 0xe6, 0x3c, 0xd5, 0x13, 0xd8, 0x33, 0x63, 0x7c, 0xac, 0xc8, 0xaa, 0xca, - 0x40, 0xca, 0xa9, 0xc8, 0x56, 0x4f, 0x53, 0xb6, 0x5a, 0xaf, 0x54, 0xab, 0xb4, 0xad, 0xd0, 0xd5, - 0x63, 0x45, 0x57, 0xed, 0xda, 0xc0, 0x25, 0xbe, 0x3a, 0x29, 0xf1, 0x55, 0xa7, 0x76, 0xf9, 0x0d, - 0x84, 0x75, 0x52, 0x22, 0xac, 0x6e, 0xad, 0x6b, 0x03, 0x63, 0x7d, 0x54, 0x60, 0xac, 0x5e, 0xa5, - 0x50, 0xa5, 0x63, 0x0d, 0x65, 0x3d, 0xcf, 0x28, 0xab, 0x5f, 0x21, 0x39, 0xe5, 0x52, 0xe5, 0xac, - 0xa7, 0x29, 0x90, 0x07, 0xb5, 0x9b, 0x56, 0x21, 0xad, 0x93, 0x12, 0x69, 0x41, 0x6d, 0x3a, 0x0d, - 0xac, 0xf5, 0x93, 0x32, 0x6b, 0x49, 0xea, 0x39, 0xac, 0xf8, 0x36, 0xd2, 0xd6, 0x8f, 0x8a, 0xb4, - 0xb5, 0x51, 0x21, 0x4b, 0x85, 0x85, 0x3a, 0xde, 0x7a, 0x9a, 0xf2, 0xd6, 0x66, 0x6d, 0x7a, 0x4d, - 0xc4, 0xf5, 0x98, 0xea, 0xa6, 0x82, 0x4b, 0xaa, 0x79, 0x1e, 0x86, 0x7e, 0xa8, 0x38, 0x47, 0x0e, - 0x8c, 0x23, 0xaa, 0xf9, 0x1c, 0x8d, 0xff, 0x87, 0xe4, 0x44, 0x8d, 0x17, 0xb0, 0x68, 0xfc, 0x56, - 0xcb, 0x7d, 0x09, 0x70, 0x54, 0x99, 0xb6, 0x15, 0x5b, 0xca, 0x51, 0x7c, 0x53, 0xbc, 0x5b, 0x1e, - 0x46, 0x84, 0x3c, 0xc9, 0x6b, 0xe9, 0x10, 0x9f, 0xc0, 0xb6, 0x6b, 0x45, 0xb1, 0xdc, 0x94, 0xa9, - 0x2a, 0xc2, 0x75, 0x51, 0x84, 0x5b, 0xa4, 0x90, 0xbb, 0x21, 0xc4, 0xf8, 0x03, 0xd8, 0x29, 0xd8, - 0x5a, 0x41, 0x30, 0x15, 0x14, 0xd0, 0x16, 0x14, 0xc0, 0x32, 0xeb, 0xd3, 0x20, 0xb8, 0xb4, 0xa2, - 0xa5, 0xf1, 0x41, 0x9e, 0x7f, 0x89, 0x71, 0x5d, 0x7f, 0x91, 0x32, 0xae, 0xeb, 0x2f, 0x8c, 0x5f, - 0xe5, 0x66, 0x39, 0xb9, 0x7e, 0x07, 0xda, 0x33, 0xdf, 0x96, 0xd9, 0x8f, 0x8e, 0xb7, 0xd4, 0x8e, - 0xbf, 0xf4, 0x6d, 0xfe, 0xf6, 0x3e, 0xe0, 0xa6, 0x50, 0x66, 0x99, 0xb6, 0x24, 0x07, 0x89, 0x4c, - 0x55, 0xfc, 0xf5, 0x3c, 0xfe, 0x2f, 0x89, 0x6e, 0x4a, 0x58, 0x7f, 0x9f, 0xd1, 0x7f, 0x9e, 0x9f, - 0x87, 0x24, 0xf5, 0x6f, 0x26, 0xb6, 0xbc, 0x0a, 0xde, 0x63, 0xec, 0x5f, 0xd0, 0x6d, 0x55, 0x2c, - 0xe7, 0xf7, 0x19, 0x7c, 0x27, 0x3f, 0xd2, 0xac, 0x90, 0x8d, 0x5d, 0xc0, 0x87, 0x15, 0x2a, 0x6f, - 0xe5, 0x72, 0xed, 0xe1, 0xf7, 0xa0, 0x63, 0x3b, 0xf3, 0x79, 0xa4, 0xb7, 0x1b, 0x6e, 0x27, 0xa9, - 0x36, 0x7e, 0xd7, 0x82, 0xae, 0xbc, 0x5b, 0xf0, 0x90, 0x78, 0xce, 0x72, 0xbc, 0xa9, 0x63, 0xa7, - 0x15, 0x23, 0xc6, 0x13, 0xbb, 0xe9, 0xb6, 0xa4, 0x54, 0x62, 0x67, 0xc5, 0x15, 0xd8, 0xc5, 0x37, - 0x1e, 0x40, 0xcf, 0x4b, 0x56, 0xd3, 0xf8, 0x2e, 0x12, 0xa8, 0x6e, 0x9b, 0x5d, 0x2f, 0x59, 0xbd, - 0xbd, 0x8b, 0xf0, 0x18, 0x36, 0x0b, 0xd0, 0x77, 0x6c, 0x45, 0xe0, 0x23, 0xb5, 0x34, 0xb1, 0xee, - 0xc9, 0x2b, 0x73, 0x98, 0x15, 0xc1, 0xc4, 0xc6, 0x23, 0x10, 0x35, 0x31, 0x95, 0x24, 0x29, 0x6b, - 0xa5, 0x2b, 0xf6, 0x6d, 0x44, 0x72, 0xc5, 0xa2, 0x74, 0x71, 0x7e, 0x0b, 0x06, 0xb4, 0x93, 0xd2, - 0xa4, 0x27, 0x4c, 0xfa, 0x24, 0x10, 0xca, 0x0f, 0x61, 0x2b, 0xbf, 0x8c, 0xa5, 0x49, 0x5f, 0x46, - 0xc9, 0xc5, 0xc2, 0xf0, 0x10, 0xfa, 0x59, 0x4d, 0x0e, 0x84, 0x45, 0xcf, 0x52, 0xa5, 0x38, 0x81, - 0x9e, 0x5a, 0x62, 0xed, 0xc5, 0xfd, 0x04, 0x3a, 0x81, 0x15, 0xc6, 0x91, 0xba, 0x20, 0x53, 0x82, - 0xbb, 0xb2, 0x42, 0xea, 0x95, 0xd4, 0xf5, 0x2d, 0x4d, 0x8c, 0x13, 0xd8, 0x2c, 0xc9, 0x89, 0xd1, - 0x62, 0x3f, 0xb6, 0x5c, 0x75, 0x75, 0xcb, 0x41, 0x36, 0x4d, 0x2b, 0x9f, 0xc6, 0x38, 0x81, 0x41, - 0x76, 0x86, 0x74, 0x2c, 0x41, 0x72, 0xfd, 0x59, 0xd6, 0xd9, 0xa8, 0x11, 0x85, 0x0b, 0xfc, 0xaf, - 0x55, 0x0f, 0xd1, 0x36, 0xe5, 0xe0, 0xc9, 0x9f, 0x34, 0x18, 0x7e, 0x2e, 0x29, 0x90, 0xd0, 0x88, - 0x5b, 0x30, 0x7c, 0x9d, 0xb8, 0xae, 0x12, 0xb1, 0x35, 0xec, 0x43, 0x9b, 0x98, 0x93, 0x69, 0x38, - 0x80, 0x8e, 0x60, 0x46, 0xd6, 0x22, 0x21, 0x51, 0x22, 0x5b, 0xc7, 0x4d, 0x18, 0x64, 0x1c, 0xc4, - 0xda, 0x34, 0xcc, 0x28, 0x99, 0x75, 0x68, 0x98, 0x51, 0x0f, 0xdb, 0xc6, 0x21, 0xf4, 0x14, 0x53, - 0x30, 0x44, 0x80, 0xae, 0x3c, 0x29, 0xb6, 0x43, 0xa1, 0x45, 0x91, 0xb3, 0x5d, 0x72, 0xc9, 0xa0, - 0xcd, 0xf6, 0x70, 0x04, 0x90, 0x83, 0x9a, 0xed, 0xe3, 0x06, 0xf4, 0x53, 0x38, 0xb3, 0x03, 0xf2, - 0x13, 0x05, 0xcc, 0xf4, 0x27, 0xbf, 0xef, 0x40, 0x3f, 0xad, 0x29, 0xec, 0x42, 0xeb, 0xcd, 0x67, - 0x6c, 0x0d, 0xb7, 0x61, 0x73, 0xe2, 0xc5, 0x3c, 0xf4, 0x2c, 0xf7, 0x9c, 0xee, 0x03, 0xa6, 0x91, - 0xe8, 0xdc, 0x9b, 0xf9, 0xb6, 0xe3, 0x2d, 0xa4, 0xa8, 0x45, 0x31, 0xcf, 0x2c, 0xfb, 0xb5, 0xef, - 0xcd, 0x38, 0x5b, 0x47, 0x06, 0x1b, 0x5f, 0x7a, 0x56, 0x12, 0x2f, 0xfd, 0xd0, 0xf9, 0x0d, 0xb7, - 0x59, 0x1b, 0xf7, 0x60, 0x7b, 0xe2, 0x45, 0xc9, 0x7c, 0xee, 0xcc, 0x1c, 0xee, 0xc5, 0x9f, 0x26, - 0x9e, 0x1d, 0xb1, 0x0e, 0x22, 0x8c, 0xbe, 0xf4, 0x6e, 0x3c, 0xff, 0x6b, 0x4f, 0x75, 0x5d, 0xac, - 0x8b, 0x3a, 0xec, 0x9e, 0x59, 0x11, 0x7f, 0x95, 0x04, 0xae, 0x33, 0xb3, 0x62, 0x7e, 0x6a, 0xdb, - 0x21, 0x8f, 0x22, 0xc6, 0x29, 0x08, 0x69, 0xca, 0x73, 0xcf, 0x53, 0x87, 0x52, 0x7c, 0xce, 0x23, - 0xb6, 0xc0, 0x43, 0xd8, 0x7b, 0xa0, 0x11, 0x33, 0x2f, 0xf1, 0xdb, 0xa0, 0x57, 0x55, 0x17, 0x56, - 0x74, 0x15, 0x3a, 0x33, 0xce, 0x1c, 0xdc, 0x05, 0x26, 0xb5, 0x02, 0xc6, 0x13, 0x2f, 0x48, 0x62, - 0xf6, 0xeb, 0x74, 0x7e, 0x25, 0x7d, 0x93, 0xc4, 0x24, 0xbe, 0xa9, 0x88, 0xaf, 0x04, 0x54, 0x98, - 0x8b, 0x07, 0xb0, 0x53, 0x10, 0x7f, 0x41, 0xf9, 0xd1, 0xee, 0xac, 0xf2, 0xf5, 0x4a, 0x85, 0xb3, - 0xf0, 0xac, 0x38, 0x09, 0x39, 0xf3, 0x70, 0x1f, 0x90, 0x34, 0x6a, 0x4b, 0xd2, 0xc4, 0xfd, 0x74, - 0x06, 0x25, 0x57, 0x33, 0x04, 0x55, 0xb1, 0x9b, 0x2c, 0x1c, 0x8f, 0xbd, 0xc3, 0x3d, 0x60, 0x17, - 0xfe, 0xad, 0x92, 0x9e, 0x7b, 0xb1, 0x13, 0xdf, 0xb3, 0x3f, 0x6b, 0xb8, 0x0b, 0x5b, 0xb9, 0xf8, - 0x22, 0xf4, 0x93, 0x80, 0xfd, 0x45, 0xc3, 0x03, 0xc0, 0x5c, 0x7a, 0x15, 0xfa, 0x81, 0x1f, 0x59, - 0x2e, 0xfb, 0xab, 0x86, 0xfb, 0xb0, 0x7d, 0xe1, 0xdf, 0x66, 0xa7, 0x20, 0x1d, 0xfe, 0x96, 0x3a, - 0x64, 0xf2, 0xcf, 0xf9, 0xea, 0x9a, 0x87, 0xec, 0xef, 0x1a, 0x1e, 0xc2, 0x6e, 0x51, 0x91, 0xc5, - 0xfa, 0x87, 0xa6, 0x56, 0x94, 0xa9, 0xbe, 0xf2, 0x63, 0xce, 0xfe, 0x99, 0x8a, 0xd5, 0x3e, 0xa8, - 0x40, 0xff, 0xd2, 0x70, 0x07, 0x46, 0xb9, 0x58, 0xd8, 0xfe, 0x5b, 0xc3, 0x31, 0xec, 0x95, 0x84, - 0x8e, 0xb7, 0xb8, 0xa2, 0xea, 0x63, 0xff, 0xd1, 0x8e, 0xff, 0xd8, 0x81, 0xad, 0xd3, 0xb3, 0x97, - 0x93, 0xd3, 0x40, 0x4e, 0x40, 0x77, 0xf9, 0x73, 0x59, 0x73, 0x58, 0xf3, 0xef, 0x7f, 0x5c, 0xd7, - 0x64, 0xe3, 0xb1, 0x2a, 0x4d, 0xac, 0x7b, 0x04, 0x18, 0xd7, 0xf6, 0xda, 0x34, 0x89, 0x6c, 0x6b, - 0x1e, 0xbe, 0x05, 0x8c, 0xeb, 0x1a, 0x6e, 0xfc, 0x69, 0xa1, 0xd4, 0xb1, 0xe9, 0x45, 0x60, 0xdc, - 0xd8, 0x7a, 0x93, 0x7f, 0xde, 0x87, 0x34, 0xbd, 0x0b, 0x8c, 0x1b, 0xfb, 0x6f, 0x7c, 0x91, 0xb1, - 0x07, 0xd6, 0xbf, 0x0e, 0x8c, 0x1b, 0x5a, 0x70, 0xda, 0x1e, 0xd9, 0x43, 0xd4, 0xfd, 0xe9, 0x1f, - 0xd7, 0x76, 0xd5, 0xe4, 0x23, 0x7b, 0x83, 0xba, 0x7f, 0xd3, 0xe3, 0xda, 0x56, 0x15, 0x3f, 0x4e, - 0x29, 0x0d, 0x6b, 0x1f, 0x23, 0xc6, 0xf5, 0xfd, 0x3e, 0x6d, 0x4c, 0xfe, 0x37, 0xb2, 0xe9, 0x95, - 0x61, 0xdc, 0xd8, 0xc9, 0xe3, 0x69, 0x91, 0x23, 0xb1, 0xf1, 0xad, 0x61, 0xdc, 0xdc, 0xcf, 0xe3, - 0x27, 0x39, 0xad, 0x62, 0xc3, 0x8b, 0xc3, 0xb8, 0xa9, 0xa5, 0xbf, 0xee, 0x8a, 0xc7, 0xac, 0x8f, - 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x1e, 0x2e, 0xe2, 0x17, 0xe1, 0x12, 0x00, 0x00, + // 1711 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x6f, 0xe4, 0xc6, + 0x11, 0x16, 0xe7, 0x3d, 0x35, 0xd2, 0xa8, 0x55, 0x1a, 0x49, 0xd4, 0x24, 0x87, 0x05, 0x03, 0xc7, + 0xda, 0x8d, 0xb3, 0x1b, 0xc8, 0x70, 0xb0, 0x8a, 0x83, 0x00, 0xd2, 0xae, 0xbc, 0x1a, 0x18, 0xde, + 0x55, 0xe8, 0xb5, 0x2f, 0x09, 0x32, 0xa0, 0x86, 0x3d, 0x33, 0x8c, 0xa8, 0x26, 0x97, 0x6c, 0xca, + 0x52, 0x7e, 0x83, 0xef, 0xf9, 0x09, 0xb9, 0x07, 0xc8, 0x29, 0xf7, 0x00, 0x79, 0x3f, 0x7e, 0x51, + 0xd0, 0x0f, 0x3e, 0x45, 0x1a, 0x3e, 0xf8, 0x32, 0x60, 0x3d, 0xbb, 0xab, 0xba, 0xea, 0xeb, 0xea, + 0x81, 0x1d, 0x7e, 0x1f, 0xd2, 0xf8, 0x99, 0xfc, 0x7d, 0x1a, 0x46, 0x01, 0x0f, 0xb0, 0x2b, 0x09, + 0xeb, 0x2f, 0x1d, 0xe8, 0xdb, 0xf4, 0x5d, 0x42, 0x63, 0x8e, 0x47, 0xd0, 0xa1, 0x8b, 0x75, 0x60, + 0x1a, 0x8f, 0x8c, 0xa3, 0xd1, 0x31, 0x3e, 0x55, 0xea, 0x5a, 0x7a, 0xbe, 0x58, 0x07, 0x17, 0x1b, + 0xb6, 0xd4, 0xc0, 0x1f, 0x41, 0x77, 0xe9, 0x27, 0xf1, 0xda, 0x6c, 0x49, 0xd5, 0xdd, 0xb2, 0xea, + 0x27, 0x42, 0x74, 0xb1, 0x61, 0x2b, 0x1d, 0xe1, 0xd6, 0x63, 0xcb, 0xc0, 0x6c, 0xd7, 0xb9, 0x9d, + 0xb1, 0xa5, 0x74, 0x2b, 0x34, 0xf0, 0x39, 0x40, 0x4c, 0xf9, 0x3c, 0x08, 0xb9, 0x17, 0x30, 0xb3, + 0x23, 0xf5, 0x0f, 0xca, 0xfa, 0x9f, 0x53, 0xfe, 0x46, 0x8a, 0x2f, 0x36, 0xec, 0x61, 0x9c, 0x12, + 0xc2, 0xd2, 0xa5, 0xbe, 0x77, 0x4b, 0xa3, 0x39, 0xbf, 0x33, 0xbb, 0x75, 0x96, 0x2f, 0x95, 0xfc, + 0xed, 0x9d, 0xb0, 0x74, 0x53, 0x02, 0x8f, 0x61, 0xb0, 0x58, 0xd3, 0xc5, 0xb5, 0xb0, 0xeb, 0x49, + 0xbb, 0xbd, 0xb2, 0xdd, 0x0b, 0x21, 0x95, 0x56, 0xfd, 0x85, 0xfa, 0xc4, 0xa7, 0xd0, 0x5b, 0x04, + 0x37, 0x37, 0x1e, 0x37, 0xfb, 0xd2, 0x62, 0x52, 0xb1, 0x90, 0xb2, 0x8b, 0x0d, 0x5b, 0x6b, 0x89, + 0x74, 0xbd, 0x4b, 0x68, 0x74, 0x6f, 0x0e, 0xea, 0xd2, 0xf5, 0x4b, 0x21, 0x12, 0xe9, 0x92, 0x3a, + 0x22, 0x14, 0x8f, 0x79, 0x7c, 0xbe, 0x58, 0x3b, 0x1e, 0x33, 0x87, 0x75, 0xa1, 0xcc, 0x98, 0xc7, + 0x5f, 0x08, 0xb1, 0x08, 0xc5, 0x4b, 0x09, 0xfc, 0x18, 0x46, 0x57, 0x74, 0xe5, 0xb1, 0xf9, 0x95, + 0x1f, 0x2c, 0xae, 0x4d, 0x90, 0xa6, 0x66, 0xd9, 0xf4, 0x4c, 0x28, 0x9c, 0x09, 0xf9, 0xc5, 0x86, + 0x0d, 0x57, 0x19, 0x85, 0x1f, 0xc1, 0x90, 0x32, 0x57, 0x9b, 0x8e, 0xa4, 0xe9, 0x7e, 0xa5, 0x02, + 0x98, 0x9b, 0x1a, 0x0e, 0xa8, 0xfe, 0x3e, 0xeb, 0x43, 0xf7, 0xd6, 0xf1, 0x13, 0x6a, 0xbd, 0x0f, + 0xa3, 0x42, 0xa5, 0xa0, 0x09, 0xfd, 0x1b, 0x1a, 0xc7, 0xce, 0x8a, 0xca, 0x72, 0x1a, 0xda, 0x29, + 0x69, 0x8d, 0x61, 0xb3, 0x58, 0x27, 0xd6, 0x56, 0x66, 0x28, 0x6a, 0xc1, 0xfa, 0x19, 0x90, 0xea, + 0x51, 0x23, 0x81, 0xf6, 0x35, 0xbd, 0xd7, 0x8e, 0xc4, 0x27, 0x4e, 0xf4, 0xb2, 0xb2, 0x00, 0x87, + 0xb6, 0xde, 0x83, 0x95, 0xd9, 0x66, 0x87, 0x8d, 0x63, 0x68, 0xf1, 0x3b, 0x69, 0xba, 0x69, 0xb7, + 0xf8, 0x9d, 0xf5, 0x08, 0xc6, 0xe5, 0x83, 0x7d, 0xa0, 0xe1, 0x66, 0x1b, 0x94, 0x27, 0x83, 0x08, + 0x1d, 0xd7, 0xe1, 0x8e, 0xd6, 0x90, 0xdf, 0x82, 0x17, 0x3a, 0x7c, 0xad, 0x97, 0x97, 0xdf, 0xb8, + 0x0f, 0xbd, 0x35, 0xf5, 0x56, 0x6b, 0x2e, 0x2b, 0xbd, 0x63, 0x6b, 0x4a, 0xec, 0x35, 0x8c, 0x82, + 0x5b, 0x2a, 0x0b, 0x7a, 0x60, 0x2b, 0xc2, 0xda, 0x86, 0xad, 0x52, 0xb9, 0x58, 0x2f, 0xb3, 0xcd, + 0x67, 0xc7, 0x8b, 0x3f, 0x01, 0xb8, 0x75, 0x7c, 0xcf, 0x75, 0x78, 0x10, 0xc5, 0xa6, 0xf1, 0xa8, + 0x7d, 0x34, 0x3a, 0x26, 0xfa, 0x54, 0xbe, 0x4c, 0x05, 0x76, 0x41, 0xc7, 0x7a, 0x0d, 0x3b, 0x0f, + 0x4e, 0x5a, 0xec, 0x76, 0xed, 0xc4, 0xeb, 0x34, 0x02, 0xf1, 0x8d, 0xef, 0x89, 0xdd, 0x3a, 0x2e, + 0x8d, 0x74, 0x0f, 0x6f, 0x69, 0xb7, 0x17, 0x92, 0x69, 0x6b, 0xa1, 0xf5, 0x18, 0xb6, 0x2b, 0xc7, + 0x5f, 0x88, 0xd3, 0x28, 0xc6, 0x69, 0x7d, 0xdd, 0x85, 0x81, 0x4d, 0xe3, 0x30, 0x60, 0x31, 0xc5, + 0xe7, 0x30, 0xa4, 0x77, 0x0b, 0xaa, 0x3a, 0xd9, 0xa8, 0x54, 0xa2, 0xd2, 0x39, 0x4f, 0xe5, 0xa2, + 0x8a, 0x33, 0x65, 0x7c, 0xac, 0x51, 0xa8, 0x0a, 0x2d, 0xda, 0xa8, 0x08, 0x43, 0x1f, 0xa4, 0x30, + 0xd4, 0xae, 0xb4, 0xa1, 0xd2, 0xad, 0xe0, 0xd0, 0x63, 0x8d, 0x43, 0x9d, 0x5a, 0xc7, 0x25, 0x20, + 0x3a, 0x29, 0x01, 0x51, 0xb7, 0x76, 0xfb, 0x0d, 0x48, 0x74, 0x52, 0x42, 0xa2, 0x5e, 0xad, 0x69, + 0x03, 0x14, 0x7d, 0x58, 0x80, 0xa2, 0x7e, 0xa5, 0x03, 0x95, 0x61, 0x0d, 0x16, 0x3d, 0xcb, 0xb0, + 0x68, 0x50, 0x41, 0x2f, 0x6d, 0x52, 0x05, 0xa3, 0x0f, 0x52, 0x30, 0x1a, 0xd6, 0x26, 0xad, 0x82, + 0x46, 0x27, 0x25, 0x34, 0x82, 0xda, 0x70, 0x1a, 0xe0, 0xe8, 0xe7, 0x65, 0x38, 0x52, 0x98, 0x72, + 0x58, 0xb1, 0x6d, 0xc4, 0xa3, 0x9f, 0x16, 0xf1, 0x68, 0xb3, 0x82, 0x82, 0xba, 0x16, 0xbe, 0x11, + 0x90, 0x1e, 0x8b, 0x4e, 0xa8, 0x54, 0x9a, 0xe8, 0x45, 0x1a, 0x45, 0x41, 0xa4, 0xb1, 0x44, 0x11, + 0xd6, 0x91, 0xe8, 0xf8, 0xbc, 0xbe, 0xbe, 0x01, 0xbc, 0x64, 0xd7, 0x16, 0xaa, 0xcb, 0xfa, 0xbd, + 0x91, 0xdb, 0x8a, 0x12, 0x2a, 0xa1, 0xc5, 0x50, 0xa3, 0x85, 0x09, 0xfd, 0x5b, 0x1a, 0xc5, 0xa2, + 0x96, 0x14, 0x60, 0xa4, 0x24, 0x3e, 0x81, 0x1d, 0xdf, 0x89, 0xb9, 0x0a, 0x73, 0x5e, 0x82, 0x8f, + 0x6d, 0x21, 0x50, 0xf1, 0x29, 0x1c, 0xf9, 0x31, 0xec, 0x16, 0x74, 0x9d, 0x30, 0x9c, 0xcb, 0xa6, + 0xee, 0xc8, 0xa6, 0x26, 0x99, 0xf6, 0x69, 0x18, 0x5e, 0x38, 0xf1, 0xda, 0x7a, 0x2f, 0x8f, 0xbf, + 0x84, 0xa4, 0x7e, 0xb0, 0x4a, 0x91, 0xd4, 0x0f, 0x56, 0xd6, 0x6f, 0x72, 0xb5, 0x1c, 0x34, 0x7f, + 0x00, 0x9d, 0x45, 0xe0, 0xaa, 0xe8, 0xc7, 0xc7, 0xdb, 0x3a, 0xef, 0x2f, 0x02, 0x97, 0xbe, 0xbd, + 0x0f, 0xa9, 0x2d, 0x85, 0x59, 0xa4, 0xad, 0x02, 0x2e, 0x6a, 0xff, 0xed, 0xdc, 0xff, 0xaf, 0x05, + 0x80, 0x94, 0xaa, 0xf7, 0xbb, 0xf4, 0xfe, 0x47, 0x23, 0x3f, 0x10, 0x85, 0xd6, 0xdf, 0xca, 0xf9, + 0x04, 0xba, 0x1e, 0x73, 0xe9, 0x9d, 0xf4, 0xde, 0xb6, 0x15, 0x91, 0x5e, 0x33, 0x6d, 0xb9, 0x62, + 0xf9, 0x9a, 0x51, 0x49, 0x56, 0x84, 0x06, 0xf4, 0x60, 0x29, 0x81, 0x61, 0xd3, 0x56, 0x44, 0x01, + 0x16, 0x7b, 0x25, 0xf8, 0xd7, 0x9b, 0xee, 0xe7, 0x9b, 0xfe, 0x95, 0xb8, 0x82, 0x8a, 0xdd, 0xf9, + 0x5d, 0x66, 0x64, 0x37, 0x3f, 0xcf, 0xac, 0x2f, 0xad, 0x09, 0xe0, 0xc3, 0x86, 0x53, 0x57, 0x6d, + 0xb9, 0x95, 0xf0, 0x87, 0xd0, 0x75, 0xbd, 0xe5, 0x32, 0x36, 0x3b, 0x0d, 0x97, 0x8d, 0x12, 0x5b, + 0x7f, 0x68, 0x41, 0x4f, 0x5d, 0x15, 0x78, 0x28, 0x60, 0xcb, 0xf1, 0xd8, 0xdc, 0x73, 0xd3, 0x76, + 0x91, 0xf4, 0xcc, 0x2d, 0xe4, 0xa4, 0x55, 0xca, 0x09, 0x42, 0x87, 0x7b, 0x37, 0x54, 0x57, 0xba, + 0xfc, 0xc6, 0x03, 0xe8, 0xb3, 0xe4, 0x66, 0xce, 0xef, 0x62, 0x99, 0xed, 0x8e, 0xdd, 0x63, 0xc9, + 0xcd, 0xdb, 0xbb, 0x18, 0x8f, 0x61, 0xab, 0x50, 0xf7, 0x9e, 0xab, 0xf1, 0x78, 0xac, 0xb7, 0x26, + 0xf7, 0x3d, 0x7b, 0x69, 0x8f, 0xb2, 0x0e, 0x98, 0xb9, 0x78, 0x04, 0xb2, 0x21, 0xe6, 0x0a, 0xf3, + 0x54, 0xa3, 0xf4, 0x64, 0xde, 0xc6, 0x82, 0xaf, 0x41, 0x51, 0xdc, 0x83, 0xdf, 0x83, 0xa1, 0xc8, + 0xa4, 0x52, 0xe9, 0x4b, 0x95, 0x81, 0x60, 0x48, 0xe1, 0xfb, 0xb0, 0x9d, 0xdf, 0xad, 0x4a, 0x65, + 0xa0, 0xbc, 0xe4, 0x6c, 0xa9, 0x78, 0x08, 0x83, 0xac, 0x21, 0x87, 0x52, 0xa3, 0xef, 0xe8, 0x3e, + 0x9c, 0x41, 0x5f, 0x6f, 0xb1, 0xf6, 0x1e, 0x7e, 0x02, 0xdd, 0xd0, 0x89, 0x78, 0xac, 0xef, 0xbb, + 0x14, 0x8e, 0x2f, 0x9d, 0x48, 0x0c, 0x40, 0xfa, 0x36, 0x56, 0x2a, 0xd6, 0x09, 0x6c, 0x95, 0xf8, + 0xa2, 0x12, 0x79, 0xc0, 0x1d, 0x5f, 0xdf, 0xc4, 0x8a, 0xc8, 0x96, 0x69, 0xe5, 0xcb, 0x58, 0x27, + 0x30, 0xcc, 0xce, 0x50, 0x1c, 0x4b, 0x98, 0x5c, 0x7d, 0xaa, 0x47, 0xaa, 0x4d, 0x5b, 0x53, 0xb2, + 0xb0, 0x83, 0xaf, 0xf4, 0x48, 0xd0, 0xb1, 0x15, 0xf1, 0xe4, 0xcf, 0x06, 0x8c, 0x3e, 0x53, 0xf8, + 0x27, 0xaa, 0x11, 0xb7, 0x61, 0xf4, 0x3a, 0xf1, 0x7d, 0xcd, 0x22, 0x1b, 0x38, 0x80, 0x8e, 0x80, + 0x4d, 0x62, 0xe0, 0x10, 0xba, 0x12, 0x16, 0x49, 0x4b, 0x30, 0x05, 0x1e, 0x92, 0x36, 0x6e, 0xc1, + 0x30, 0x03, 0x20, 0xd2, 0x11, 0x64, 0x86, 0xc7, 0xa4, 0x2b, 0xc8, 0x0c, 0x77, 0xc8, 0x0e, 0x8e, + 0xa0, 0xaf, 0x61, 0x82, 0x20, 0x02, 0xf4, 0xd4, 0x49, 0x91, 0x5d, 0xe1, 0x5a, 0x36, 0x38, 0x99, + 0x08, 0x93, 0xac, 0xb4, 0xc9, 0x1e, 0x8e, 0x01, 0xf2, 0xa2, 0x26, 0xfb, 0xb8, 0x09, 0x83, 0xb4, + 0x9c, 0xc9, 0xc1, 0x93, 0x3f, 0x75, 0x61, 0x90, 0x36, 0x12, 0xf6, 0xa0, 0xf5, 0xe6, 0x53, 0xb2, + 0x81, 0x3b, 0xb0, 0x35, 0x63, 0x9c, 0x46, 0xcc, 0xf1, 0xcf, 0xc5, 0x0d, 0x40, 0x0c, 0xc1, 0x3a, + 0x67, 0x8b, 0xc0, 0xf5, 0xd8, 0x4a, 0xb1, 0x5a, 0xc2, 0xd1, 0x99, 0xe3, 0xbe, 0x0e, 0xd8, 0x82, + 0x92, 0x36, 0x12, 0xd8, 0xfc, 0x82, 0x39, 0x09, 0x5f, 0x07, 0x91, 0xf7, 0x3b, 0xea, 0x92, 0x0e, + 0xee, 0xc1, 0xce, 0x8c, 0xc5, 0xc9, 0x72, 0xe9, 0x2d, 0x3c, 0xca, 0xf8, 0x27, 0x09, 0x73, 0x63, + 0xd2, 0x45, 0x84, 0xf1, 0x17, 0xec, 0x9a, 0x05, 0x5f, 0x31, 0x3d, 0x39, 0x91, 0x1e, 0x9a, 0x30, + 0x39, 0x73, 0x62, 0xfa, 0x32, 0x09, 0x7d, 0x6f, 0xe1, 0x70, 0x7a, 0xea, 0xba, 0x11, 0x8d, 0x63, + 0x42, 0x85, 0x13, 0x21, 0x29, 0xaf, 0xbd, 0x4c, 0x0d, 0x4a, 0xfe, 0x29, 0x8d, 0xc9, 0x0a, 0x0f, + 0x61, 0xef, 0x81, 0x44, 0xae, 0xbc, 0xc6, 0xef, 0x83, 0x59, 0x15, 0xbd, 0x72, 0xe2, 0xcb, 0xc8, + 0x5b, 0x50, 0xe2, 0xe1, 0x04, 0x88, 0x92, 0xca, 0xda, 0x9d, 0xb1, 0x30, 0xe1, 0xe4, 0xb7, 0xe9, + 0xfa, 0x9a, 0xfb, 0x26, 0xe1, 0x82, 0x7d, 0x5d, 0x61, 0x5f, 0xca, 0xfa, 0x20, 0x3e, 0x1e, 0xc0, + 0x6e, 0x81, 0xfd, 0xb9, 0x88, 0x4f, 0x64, 0xe7, 0x26, 0xdf, 0xaf, 0x12, 0x78, 0x2b, 0xe6, 0xf0, + 0x24, 0xa2, 0x84, 0xe1, 0x3e, 0xa0, 0x90, 0xe8, 0x94, 0xa4, 0x81, 0x07, 0xe9, 0x0a, 0x9a, 0xaf, + 0x57, 0x08, 0xab, 0x6c, 0x3f, 0x59, 0x79, 0x8c, 0xbc, 0xc3, 0x3d, 0x20, 0xaf, 0x82, 0x5b, 0xcd, + 0x3d, 0x67, 0xdc, 0xe3, 0xf7, 0xe4, 0xaf, 0x06, 0x4e, 0x60, 0x3b, 0x67, 0xbf, 0x8a, 0x82, 0x24, + 0x24, 0x7f, 0x33, 0xf0, 0x00, 0x30, 0xe7, 0x5e, 0x46, 0x41, 0x18, 0xc4, 0x8e, 0x4f, 0xfe, 0x6e, + 0xe0, 0x3e, 0xec, 0xbc, 0x0a, 0x6e, 0xb3, 0x53, 0x50, 0x06, 0xff, 0x48, 0x0d, 0x32, 0xfe, 0x67, + 0xf4, 0xe6, 0x8a, 0x46, 0xe4, 0x9f, 0x06, 0x1e, 0xc2, 0xa4, 0x28, 0xc8, 0x7c, 0xfd, 0xcb, 0xd0, + 0x3b, 0xca, 0x44, 0x5f, 0x06, 0x9c, 0x92, 0x7f, 0xa7, 0x6c, 0x9d, 0x07, 0xed, 0xe8, 0x3f, 0x06, + 0xee, 0xc2, 0x38, 0x67, 0x4b, 0xdd, 0xff, 0x1a, 0x38, 0x85, 0xbd, 0x12, 0xd3, 0x63, 0xab, 0x4b, + 0xd1, 0x72, 0xe4, 0x7f, 0xc6, 0xf1, 0xd7, 0x5d, 0xd8, 0x3e, 0x3d, 0x7b, 0x31, 0x3b, 0x0d, 0xd5, + 0x02, 0xe2, 0xf6, 0x7e, 0xa6, 0x1a, 0x0d, 0x6b, 0x9e, 0xe6, 0xd3, 0xba, 0x41, 0x19, 0x8f, 0x75, + 0x3f, 0x62, 0xdd, 0x0b, 0x7d, 0x5a, 0x3b, 0x2f, 0x8b, 0x45, 0xd4, 0x20, 0xf3, 0xf0, 0xa1, 0x3e, + 0xad, 0x1b, 0x9a, 0xf1, 0x17, 0x85, 0xfe, 0xc6, 0xa6, 0xe7, 0xfa, 0xb4, 0x71, 0x7c, 0x16, 0xf6, + 0xf9, 0xe4, 0xd1, 0xf4, 0x68, 0x9f, 0x36, 0xce, 0xd0, 0xf8, 0x3c, 0x83, 0x0c, 0xac, 0x7f, 0xba, + 0x4f, 0x1b, 0xc6, 0x68, 0x91, 0x1e, 0x35, 0x34, 0xd4, 0xbd, 0xc8, 0xa7, 0xb5, 0x93, 0x31, 0x7e, + 0x94, 0x62, 0x12, 0xd6, 0xbe, 0xfa, 0xa7, 0xf5, 0xf3, 0xb7, 0x08, 0x32, 0x7f, 0xd6, 0x35, 0x3d, + 0xe7, 0xa7, 0x8d, 0x93, 0x35, 0x9e, 0x16, 0x41, 0x0e, 0x1b, 0x1f, 0xf5, 0xd3, 0xe6, 0xf9, 0x1a, + 0x3f, 0xce, 0x71, 0x11, 0x1b, 0x9e, 0xf6, 0xd3, 0xa6, 0x11, 0xfb, 0xaa, 0x27, 0xff, 0x35, 0xfa, + 0xf0, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x73, 0x34, 0x90, 0x2d, 0x4a, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 14093476..3eea82ea 100644 --- a/types/types.proto +++ b/types/types.proto @@ -113,7 +113,7 @@ message RequestCheckTx{ } message RequestQuery{ - bytes query = 1; + bytes data = 1; string path = 2; uint64 height = 3; bool prove = 4; @@ -191,10 +191,13 @@ message ResponseCheckTx{ } message ResponseQuery{ - bytes data = 2; - string log = 3; - uint64 height = 4; + CodeType code = 1; + int64 index = 2; + bytes key = 3; + bytes value = 4; bytes proof = 5; + uint64 height = 6; + string log = 7; } message ResponseCommit{ From dafcc3d3e38c34840a274f9ba96321449a81a7b8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 6 Feb 2017 18:10:20 -0500 Subject: [PATCH 203/545] fixes #38 and #59 --- README.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b73724e6..a0b4707f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ and the state machine (the application). By using a socket protocol, we enable a consensus engine running in one process to manage an application state running in another. -For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/tmsp-the-tendermint-socket-protocol). +For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-application-blockchain-interface), +and the more detailed [application developer's guide](https://tendermint.com/docs/guides/app-development). Previously, the ABCI was just referred to as TMSP. @@ -154,6 +155,19 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. +#### Echo + * __Arguments__: + * `Message (string)`: A string to echo back + * __Returns__: + * `Message (string)`: The input string + * __Usage__:
+ * Echo a string to test an abci client/server implementation + + +#### Flush + * __Usage__:
+ * Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. + # Implementations @@ -183,7 +197,7 @@ Note the length-prefixing used in the socket implementation does not apply for G # Tools and Apps The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. -See the [tutorial](https://tendermint.com/intro/getting-started/first-tmsp) for more details. +See the [tutorial](https://tendermint.com/intro/getting-started/first-abci) for more details. Multiple example apps are included: - the `counter` application, which illustrates nonce checking in txs From b025c13f67cb3c26d015d8f8dc0bac910855a39d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 6 Feb 2017 19:08:37 -0500 Subject: [PATCH 204/545] drop BlockchainAware --- client/local_client.go | 25 ++------ .../block_aware_app.go} | 0 .../block_aware_test.go} | 0 example/counter/counter.go | 10 +++ example/dummy/dummy.go | 10 +++ example/dummy/dummy_test.go | 5 +- example/nil/nil_app.go | 10 +++ server/socket_server.go | 16 ++--- types/application.go | 64 ++++++------------- 9 files changed, 62 insertions(+), 78 deletions(-) rename example/{chain_aware/chain_aware_app.go => block_aware/block_aware_app.go} (100%) rename example/{chain_aware/chain_aware_test.go => block_aware/block_aware_test.go} (100%) diff --git a/client/local_client.go b/client/local_client.go index a34fde10..1150db4a 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -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), @@ -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/example/chain_aware/chain_aware_app.go b/example/block_aware/block_aware_app.go similarity index 100% rename from example/chain_aware/chain_aware_app.go rename to example/block_aware/block_aware_app.go diff --git a/example/chain_aware/chain_aware_test.go b/example/block_aware/block_aware_test.go similarity index 100% rename from example/chain_aware/chain_aware_test.go rename to example/block_aware/block_aware_test.go diff --git a/example/counter/counter.go b/example/counter/counter.go index a55a1fd1..8fce72e2 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -80,3 +80,13 @@ func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.Response return types.ResponseQuery{Log: Fmt("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} } } + +func (app *CounterApplication) InitChain(validators []*types.Validator) { +} + +func (app *CounterApplication) BeginBlock(hash []byte, header *types.Header) { +} + +func (app *CounterApplication) EndBlock(height uint64) types.ResponseEndBlock { + return types.ResponseEndBlock{} +} diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index ac2bd462..73c938e7 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -70,3 +70,13 @@ func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types. return } } + +func (app *DummyApplication) InitChain(validators []*types.Validator) { +} + +func (app *DummyApplication) BeginBlock(hash []byte, header *types.Header) { +} + +func (app *DummyApplication) EndBlock(height uint64) types.ResponseEndBlock { + return types.ResponseEndBlock{} +} diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 7ca12a6e..fbbf97a5 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -180,14 +180,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) diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go index 95ac8d59..5285cc39 100644 --- a/example/nil/nil_app.go +++ b/example/nil/nil_app.go @@ -34,3 +34,13 @@ func (app *NilApplication) Commit() types.Result { func (app *NilApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { return resQuery } + +func (app *NilApplication) InitChain(validators []*types.Validator) { +} + +func (app *NilApplication) BeginBlock(hash []byte, header *types.Header) { +} + +func (app *NilApplication) EndBlock(height uint64) types.ResponseEndBlock { + return types.ResponseEndBlock{} +} diff --git a/server/socket_server.go b/server/socket_server.go index 46114027..bc1980e2 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -187,22 +187,14 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types 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/types/application.go b/types/application.go index 404437fe..b45305f8 100644 --- a/types/application.go +++ b/types/application.go @@ -6,42 +6,25 @@ import ( // Applications type Application interface { + // 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 - // Return application info - Info() ResponseInfo + // Mempool Connection + CheckTx(tx []byte) Result // Validate a tx for the mempool - // 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(reqQuery RequestQuery) ResponseQuery - - // 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 + // 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 } @@ -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 } From 5d673ecf314e27c57b69e7882921914a2eb5749a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 12 Feb 2017 18:38:10 -0800 Subject: [PATCH 205/545] Fix comment for BeginBlock hash --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c002b141..11d790f4 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,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. From b6afa8d85bab43b65c628d5416a48905e7450396 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 6 Feb 2017 19:20:33 -0500 Subject: [PATCH 206/545] Query: Height -> LastHeight --- README.md | 6 +- cmd/abci-cli/abci-cli.go | 34 +++--- types/types.pb.go | 247 ++++++++++++++++++++------------------- types/types.proto | 6 +- 4 files changed, 147 insertions(+), 146 deletions(-) diff --git a/README.md b/README.md index c002b141..af66fecc 100644 --- a/README.md +++ b/README.md @@ -76,16 +76,16 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * `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) + * `LastHeight (uint64)`: The block height for which you want the query (default=0 returns data for the latest committed block). Note that the corresponding Merkle root hash will only be included in the header of the next block (ie. `LastHeight + 1`) * `Prove (bool)`: Return Merkle proof with response if possible * __Returns__: * `Code (uint32)`: Response code * `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 + * `LastHeight (uint64)`: The block height from which data was derived. The Merkle root for the proof is included in block `LastHeight + 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. Hopefully this will be improved soon(ish) + *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__: diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 0168bea4..e4fd50be 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -17,13 +17,13 @@ import ( // Structure for data passed to print response. type response struct { - Data []byte - Code types.CodeType - Key []byte - Value []byte - Log string - Height string - Proof []byte + Data []byte + Code types.CodeType + Key []byte + Value []byte + Log string + LastHeight string + Proof []byte } // client is a global variable so it can be reused by the console @@ -299,20 +299,20 @@ func cmdQuery(c *cli.Context) error { return err } resQuery, err := client.QuerySync(types.RequestQuery{ - Data: queryBytes, - Path: "/store", // TOOD expose - Height: 0, // TODO expose + Data: queryBytes, + Path: "/store", // TOOD expose + LastHeight: 0, // TODO expose //Prove: true, // TODO expose }) if err != nil { return err } printResponse(c, response{ - Code: resQuery.Code, - Key: resQuery.Key, - Value: resQuery.Value, - Log: resQuery.Log, - Height: fmt.Sprintf("%v", resQuery.Height), + Code: resQuery.Code, + Key: resQuery.Key, + Value: resQuery.Value, + Log: resQuery.Log, + LastHeight: fmt.Sprintf("%v", resQuery.LastHeight), //Proof: resQuery.Proof, }) return nil @@ -346,8 +346,8 @@ func printResponse(c *cli.Context, rsp response) { if rsp.Log != "" { fmt.Printf("-> log: %s\n", rsp.Log) } - if rsp.Height != "" { - fmt.Printf("-> height: %s\n", rsp.Height) + if rsp.LastHeight != "" { + fmt.Printf("-> height: %s\n", rsp.LastHeight) } if rsp.Proof != nil { fmt.Printf("-> proof: %X\n", rsp.Proof) diff --git a/types/types.pb.go b/types/types.pb.go index e0ae1076..3458c27c 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -716,10 +716,10 @@ func (m *RequestCheckTx) GetTx() []byte { } type RequestQuery struct { - 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"` + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + LastHeight uint64 `protobuf:"varint,3,opt,name=last_height,json=lastHeight" json:"last_height,omitempty"` + Prove bool `protobuf:"varint,4,opt,name=prove" json:"prove,omitempty"` } func (m *RequestQuery) Reset() { *m = RequestQuery{} } @@ -741,9 +741,9 @@ func (m *RequestQuery) GetPath() string { return "" } -func (m *RequestQuery) GetHeight() uint64 { +func (m *RequestQuery) GetLastHeight() uint64 { if m != nil { - return m.Height + return m.LastHeight } return 0 } @@ -1411,13 +1411,13 @@ func (m *ResponseCheckTx) GetLog() string { } type ResponseQuery struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` - 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"` + 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"` + LastHeight uint64 `protobuf:"varint,6,opt,name=last_height,json=lastHeight" json:"last_height,omitempty"` + Log string `protobuf:"bytes,7,opt,name=log" json:"log,omitempty"` } func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } @@ -1460,9 +1460,9 @@ func (m *ResponseQuery) GetProof() []byte { return nil } -func (m *ResponseQuery) GetHeight() uint64 { +func (m *ResponseQuery) GetLastHeight() uint64 { if m != nil { - return m.Height + return m.LastHeight } return 0 } @@ -2129,112 +2129,113 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1711 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x4b, 0x6f, 0xe4, 0xc6, - 0x11, 0x16, 0xe7, 0x3d, 0x35, 0xd2, 0xa8, 0x55, 0x1a, 0x49, 0xd4, 0x24, 0x87, 0x05, 0x03, 0xc7, - 0xda, 0x8d, 0xb3, 0x1b, 0xc8, 0x70, 0xb0, 0x8a, 0x83, 0x00, 0xd2, 0xae, 0xbc, 0x1a, 0x18, 0xde, - 0x55, 0xe8, 0xb5, 0x2f, 0x09, 0x32, 0xa0, 0x86, 0x3d, 0x33, 0x8c, 0xa8, 0x26, 0x97, 0x6c, 0xca, - 0x52, 0x7e, 0x83, 0xef, 0xf9, 0x09, 0xb9, 0x07, 0xc8, 0x29, 0xf7, 0x00, 0x79, 0x3f, 0x7e, 0x51, - 0xd0, 0x0f, 0x3e, 0x45, 0x1a, 0x3e, 0xf8, 0x32, 0x60, 0x3d, 0xbb, 0xab, 0xba, 0xea, 0xeb, 0xea, - 0x81, 0x1d, 0x7e, 0x1f, 0xd2, 0xf8, 0x99, 0xfc, 0x7d, 0x1a, 0x46, 0x01, 0x0f, 0xb0, 0x2b, 0x09, - 0xeb, 0x2f, 0x1d, 0xe8, 0xdb, 0xf4, 0x5d, 0x42, 0x63, 0x8e, 0x47, 0xd0, 0xa1, 0x8b, 0x75, 0x60, - 0x1a, 0x8f, 0x8c, 0xa3, 0xd1, 0x31, 0x3e, 0x55, 0xea, 0x5a, 0x7a, 0xbe, 0x58, 0x07, 0x17, 0x1b, - 0xb6, 0xd4, 0xc0, 0x1f, 0x41, 0x77, 0xe9, 0x27, 0xf1, 0xda, 0x6c, 0x49, 0xd5, 0xdd, 0xb2, 0xea, - 0x27, 0x42, 0x74, 0xb1, 0x61, 0x2b, 0x1d, 0xe1, 0xd6, 0x63, 0xcb, 0xc0, 0x6c, 0xd7, 0xb9, 0x9d, - 0xb1, 0xa5, 0x74, 0x2b, 0x34, 0xf0, 0x39, 0x40, 0x4c, 0xf9, 0x3c, 0x08, 0xb9, 0x17, 0x30, 0xb3, - 0x23, 0xf5, 0x0f, 0xca, 0xfa, 0x9f, 0x53, 0xfe, 0x46, 0x8a, 0x2f, 0x36, 0xec, 0x61, 0x9c, 0x12, - 0xc2, 0xd2, 0xa5, 0xbe, 0x77, 0x4b, 0xa3, 0x39, 0xbf, 0x33, 0xbb, 0x75, 0x96, 0x2f, 0x95, 0xfc, - 0xed, 0x9d, 0xb0, 0x74, 0x53, 0x02, 0x8f, 0x61, 0xb0, 0x58, 0xd3, 0xc5, 0xb5, 0xb0, 0xeb, 0x49, - 0xbb, 0xbd, 0xb2, 0xdd, 0x0b, 0x21, 0x95, 0x56, 0xfd, 0x85, 0xfa, 0xc4, 0xa7, 0xd0, 0x5b, 0x04, - 0x37, 0x37, 0x1e, 0x37, 0xfb, 0xd2, 0x62, 0x52, 0xb1, 0x90, 0xb2, 0x8b, 0x0d, 0x5b, 0x6b, 0x89, - 0x74, 0xbd, 0x4b, 0x68, 0x74, 0x6f, 0x0e, 0xea, 0xd2, 0xf5, 0x4b, 0x21, 0x12, 0xe9, 0x92, 0x3a, - 0x22, 0x14, 0x8f, 0x79, 0x7c, 0xbe, 0x58, 0x3b, 0x1e, 0x33, 0x87, 0x75, 0xa1, 0xcc, 0x98, 0xc7, - 0x5f, 0x08, 0xb1, 0x08, 0xc5, 0x4b, 0x09, 0xfc, 0x18, 0x46, 0x57, 0x74, 0xe5, 0xb1, 0xf9, 0x95, - 0x1f, 0x2c, 0xae, 0x4d, 0x90, 0xa6, 0x66, 0xd9, 0xf4, 0x4c, 0x28, 0x9c, 0x09, 0xf9, 0xc5, 0x86, - 0x0d, 0x57, 0x19, 0x85, 0x1f, 0xc1, 0x90, 0x32, 0x57, 0x9b, 0x8e, 0xa4, 0xe9, 0x7e, 0xa5, 0x02, - 0x98, 0x9b, 0x1a, 0x0e, 0xa8, 0xfe, 0x3e, 0xeb, 0x43, 0xf7, 0xd6, 0xf1, 0x13, 0x6a, 0xbd, 0x0f, - 0xa3, 0x42, 0xa5, 0xa0, 0x09, 0xfd, 0x1b, 0x1a, 0xc7, 0xce, 0x8a, 0xca, 0x72, 0x1a, 0xda, 0x29, - 0x69, 0x8d, 0x61, 0xb3, 0x58, 0x27, 0xd6, 0x56, 0x66, 0x28, 0x6a, 0xc1, 0xfa, 0x19, 0x90, 0xea, - 0x51, 0x23, 0x81, 0xf6, 0x35, 0xbd, 0xd7, 0x8e, 0xc4, 0x27, 0x4e, 0xf4, 0xb2, 0xb2, 0x00, 0x87, - 0xb6, 0xde, 0x83, 0x95, 0xd9, 0x66, 0x87, 0x8d, 0x63, 0x68, 0xf1, 0x3b, 0x69, 0xba, 0x69, 0xb7, - 0xf8, 0x9d, 0xf5, 0x08, 0xc6, 0xe5, 0x83, 0x7d, 0xa0, 0xe1, 0x66, 0x1b, 0x94, 0x27, 0x83, 0x08, - 0x1d, 0xd7, 0xe1, 0x8e, 0xd6, 0x90, 0xdf, 0x82, 0x17, 0x3a, 0x7c, 0xad, 0x97, 0x97, 0xdf, 0xb8, - 0x0f, 0xbd, 0x35, 0xf5, 0x56, 0x6b, 0x2e, 0x2b, 0xbd, 0x63, 0x6b, 0x4a, 0xec, 0x35, 0x8c, 0x82, - 0x5b, 0x2a, 0x0b, 0x7a, 0x60, 0x2b, 0xc2, 0xda, 0x86, 0xad, 0x52, 0xb9, 0x58, 0x2f, 0xb3, 0xcd, - 0x67, 0xc7, 0x8b, 0x3f, 0x01, 0xb8, 0x75, 0x7c, 0xcf, 0x75, 0x78, 0x10, 0xc5, 0xa6, 0xf1, 0xa8, - 0x7d, 0x34, 0x3a, 0x26, 0xfa, 0x54, 0xbe, 0x4c, 0x05, 0x76, 0x41, 0xc7, 0x7a, 0x0d, 0x3b, 0x0f, - 0x4e, 0x5a, 0xec, 0x76, 0xed, 0xc4, 0xeb, 0x34, 0x02, 0xf1, 0x8d, 0xef, 0x89, 0xdd, 0x3a, 0x2e, - 0x8d, 0x74, 0x0f, 0x6f, 0x69, 0xb7, 0x17, 0x92, 0x69, 0x6b, 0xa1, 0xf5, 0x18, 0xb6, 0x2b, 0xc7, - 0x5f, 0x88, 0xd3, 0x28, 0xc6, 0x69, 0x7d, 0xdd, 0x85, 0x81, 0x4d, 0xe3, 0x30, 0x60, 0x31, 0xc5, - 0xe7, 0x30, 0xa4, 0x77, 0x0b, 0xaa, 0x3a, 0xd9, 0xa8, 0x54, 0xa2, 0xd2, 0x39, 0x4f, 0xe5, 0xa2, - 0x8a, 0x33, 0x65, 0x7c, 0xac, 0x51, 0xa8, 0x0a, 0x2d, 0xda, 0xa8, 0x08, 0x43, 0x1f, 0xa4, 0x30, - 0xd4, 0xae, 0xb4, 0xa1, 0xd2, 0xad, 0xe0, 0xd0, 0x63, 0x8d, 0x43, 0x9d, 0x5a, 0xc7, 0x25, 0x20, - 0x3a, 0x29, 0x01, 0x51, 0xb7, 0x76, 0xfb, 0x0d, 0x48, 0x74, 0x52, 0x42, 0xa2, 0x5e, 0xad, 0x69, - 0x03, 0x14, 0x7d, 0x58, 0x80, 0xa2, 0x7e, 0xa5, 0x03, 0x95, 0x61, 0x0d, 0x16, 0x3d, 0xcb, 0xb0, - 0x68, 0x50, 0x41, 0x2f, 0x6d, 0x52, 0x05, 0xa3, 0x0f, 0x52, 0x30, 0x1a, 0xd6, 0x26, 0xad, 0x82, - 0x46, 0x27, 0x25, 0x34, 0x82, 0xda, 0x70, 0x1a, 0xe0, 0xe8, 0xe7, 0x65, 0x38, 0x52, 0x98, 0x72, - 0x58, 0xb1, 0x6d, 0xc4, 0xa3, 0x9f, 0x16, 0xf1, 0x68, 0xb3, 0x82, 0x82, 0xba, 0x16, 0xbe, 0x11, - 0x90, 0x1e, 0x8b, 0x4e, 0xa8, 0x54, 0x9a, 0xe8, 0x45, 0x1a, 0x45, 0x41, 0xa4, 0xb1, 0x44, 0x11, - 0xd6, 0x91, 0xe8, 0xf8, 0xbc, 0xbe, 0xbe, 0x01, 0xbc, 0x64, 0xd7, 0x16, 0xaa, 0xcb, 0xfa, 0xbd, - 0x91, 0xdb, 0x8a, 0x12, 0x2a, 0xa1, 0xc5, 0x50, 0xa3, 0x85, 0x09, 0xfd, 0x5b, 0x1a, 0xc5, 0xa2, - 0x96, 0x14, 0x60, 0xa4, 0x24, 0x3e, 0x81, 0x1d, 0xdf, 0x89, 0xb9, 0x0a, 0x73, 0x5e, 0x82, 0x8f, - 0x6d, 0x21, 0x50, 0xf1, 0x29, 0x1c, 0xf9, 0x31, 0xec, 0x16, 0x74, 0x9d, 0x30, 0x9c, 0xcb, 0xa6, - 0xee, 0xc8, 0xa6, 0x26, 0x99, 0xf6, 0x69, 0x18, 0x5e, 0x38, 0xf1, 0xda, 0x7a, 0x2f, 0x8f, 0xbf, - 0x84, 0xa4, 0x7e, 0xb0, 0x4a, 0x91, 0xd4, 0x0f, 0x56, 0xd6, 0x6f, 0x72, 0xb5, 0x1c, 0x34, 0x7f, - 0x00, 0x9d, 0x45, 0xe0, 0xaa, 0xe8, 0xc7, 0xc7, 0xdb, 0x3a, 0xef, 0x2f, 0x02, 0x97, 0xbe, 0xbd, - 0x0f, 0xa9, 0x2d, 0x85, 0x59, 0xa4, 0xad, 0x02, 0x2e, 0x6a, 0xff, 0xed, 0xdc, 0xff, 0xaf, 0x05, - 0x80, 0x94, 0xaa, 0xf7, 0xbb, 0xf4, 0xfe, 0x47, 0x23, 0x3f, 0x10, 0x85, 0xd6, 0xdf, 0xca, 0xf9, - 0x04, 0xba, 0x1e, 0x73, 0xe9, 0x9d, 0xf4, 0xde, 0xb6, 0x15, 0x91, 0x5e, 0x33, 0x6d, 0xb9, 0x62, - 0xf9, 0x9a, 0x51, 0x49, 0x56, 0x84, 0x06, 0xf4, 0x60, 0x29, 0x81, 0x61, 0xd3, 0x56, 0x44, 0x01, - 0x16, 0x7b, 0x25, 0xf8, 0xd7, 0x9b, 0xee, 0xe7, 0x9b, 0xfe, 0x95, 0xb8, 0x82, 0x8a, 0xdd, 0xf9, - 0x5d, 0x66, 0x64, 0x37, 0x3f, 0xcf, 0xac, 0x2f, 0xad, 0x09, 0xe0, 0xc3, 0x86, 0x53, 0x57, 0x6d, - 0xb9, 0x95, 0xf0, 0x87, 0xd0, 0x75, 0xbd, 0xe5, 0x32, 0x36, 0x3b, 0x0d, 0x97, 0x8d, 0x12, 0x5b, - 0x7f, 0x68, 0x41, 0x4f, 0x5d, 0x15, 0x78, 0x28, 0x60, 0xcb, 0xf1, 0xd8, 0xdc, 0x73, 0xd3, 0x76, - 0x91, 0xf4, 0xcc, 0x2d, 0xe4, 0xa4, 0x55, 0xca, 0x09, 0x42, 0x87, 0x7b, 0x37, 0x54, 0x57, 0xba, - 0xfc, 0xc6, 0x03, 0xe8, 0xb3, 0xe4, 0x66, 0xce, 0xef, 0x62, 0x99, 0xed, 0x8e, 0xdd, 0x63, 0xc9, - 0xcd, 0xdb, 0xbb, 0x18, 0x8f, 0x61, 0xab, 0x50, 0xf7, 0x9e, 0xab, 0xf1, 0x78, 0xac, 0xb7, 0x26, - 0xf7, 0x3d, 0x7b, 0x69, 0x8f, 0xb2, 0x0e, 0x98, 0xb9, 0x78, 0x04, 0xb2, 0x21, 0xe6, 0x0a, 0xf3, - 0x54, 0xa3, 0xf4, 0x64, 0xde, 0xc6, 0x82, 0xaf, 0x41, 0x51, 0xdc, 0x83, 0xdf, 0x83, 0xa1, 0xc8, - 0xa4, 0x52, 0xe9, 0x4b, 0x95, 0x81, 0x60, 0x48, 0xe1, 0xfb, 0xb0, 0x9d, 0xdf, 0xad, 0x4a, 0x65, - 0xa0, 0xbc, 0xe4, 0x6c, 0xa9, 0x78, 0x08, 0x83, 0xac, 0x21, 0x87, 0x52, 0xa3, 0xef, 0xe8, 0x3e, - 0x9c, 0x41, 0x5f, 0x6f, 0xb1, 0xf6, 0x1e, 0x7e, 0x02, 0xdd, 0xd0, 0x89, 0x78, 0xac, 0xef, 0xbb, - 0x14, 0x8e, 0x2f, 0x9d, 0x48, 0x0c, 0x40, 0xfa, 0x36, 0x56, 0x2a, 0xd6, 0x09, 0x6c, 0x95, 0xf8, - 0xa2, 0x12, 0x79, 0xc0, 0x1d, 0x5f, 0xdf, 0xc4, 0x8a, 0xc8, 0x96, 0x69, 0xe5, 0xcb, 0x58, 0x27, - 0x30, 0xcc, 0xce, 0x50, 0x1c, 0x4b, 0x98, 0x5c, 0x7d, 0xaa, 0x47, 0xaa, 0x4d, 0x5b, 0x53, 0xb2, - 0xb0, 0x83, 0xaf, 0xf4, 0x48, 0xd0, 0xb1, 0x15, 0xf1, 0xe4, 0xcf, 0x06, 0x8c, 0x3e, 0x53, 0xf8, - 0x27, 0xaa, 0x11, 0xb7, 0x61, 0xf4, 0x3a, 0xf1, 0x7d, 0xcd, 0x22, 0x1b, 0x38, 0x80, 0x8e, 0x80, - 0x4d, 0x62, 0xe0, 0x10, 0xba, 0x12, 0x16, 0x49, 0x4b, 0x30, 0x05, 0x1e, 0x92, 0x36, 0x6e, 0xc1, - 0x30, 0x03, 0x20, 0xd2, 0x11, 0x64, 0x86, 0xc7, 0xa4, 0x2b, 0xc8, 0x0c, 0x77, 0xc8, 0x0e, 0x8e, - 0xa0, 0xaf, 0x61, 0x82, 0x20, 0x02, 0xf4, 0xd4, 0x49, 0x91, 0x5d, 0xe1, 0x5a, 0x36, 0x38, 0x99, - 0x08, 0x93, 0xac, 0xb4, 0xc9, 0x1e, 0x8e, 0x01, 0xf2, 0xa2, 0x26, 0xfb, 0xb8, 0x09, 0x83, 0xb4, - 0x9c, 0xc9, 0xc1, 0x93, 0x3f, 0x75, 0x61, 0x90, 0x36, 0x12, 0xf6, 0xa0, 0xf5, 0xe6, 0x53, 0xb2, - 0x81, 0x3b, 0xb0, 0x35, 0x63, 0x9c, 0x46, 0xcc, 0xf1, 0xcf, 0xc5, 0x0d, 0x40, 0x0c, 0xc1, 0x3a, - 0x67, 0x8b, 0xc0, 0xf5, 0xd8, 0x4a, 0xb1, 0x5a, 0xc2, 0xd1, 0x99, 0xe3, 0xbe, 0x0e, 0xd8, 0x82, - 0x92, 0x36, 0x12, 0xd8, 0xfc, 0x82, 0x39, 0x09, 0x5f, 0x07, 0x91, 0xf7, 0x3b, 0xea, 0x92, 0x0e, - 0xee, 0xc1, 0xce, 0x8c, 0xc5, 0xc9, 0x72, 0xe9, 0x2d, 0x3c, 0xca, 0xf8, 0x27, 0x09, 0x73, 0x63, - 0xd2, 0x45, 0x84, 0xf1, 0x17, 0xec, 0x9a, 0x05, 0x5f, 0x31, 0x3d, 0x39, 0x91, 0x1e, 0x9a, 0x30, - 0x39, 0x73, 0x62, 0xfa, 0x32, 0x09, 0x7d, 0x6f, 0xe1, 0x70, 0x7a, 0xea, 0xba, 0x11, 0x8d, 0x63, - 0x42, 0x85, 0x13, 0x21, 0x29, 0xaf, 0xbd, 0x4c, 0x0d, 0x4a, 0xfe, 0x29, 0x8d, 0xc9, 0x0a, 0x0f, - 0x61, 0xef, 0x81, 0x44, 0xae, 0xbc, 0xc6, 0xef, 0x83, 0x59, 0x15, 0xbd, 0x72, 0xe2, 0xcb, 0xc8, - 0x5b, 0x50, 0xe2, 0xe1, 0x04, 0x88, 0x92, 0xca, 0xda, 0x9d, 0xb1, 0x30, 0xe1, 0xe4, 0xb7, 0xe9, - 0xfa, 0x9a, 0xfb, 0x26, 0xe1, 0x82, 0x7d, 0x5d, 0x61, 0x5f, 0xca, 0xfa, 0x20, 0x3e, 0x1e, 0xc0, - 0x6e, 0x81, 0xfd, 0xb9, 0x88, 0x4f, 0x64, 0xe7, 0x26, 0xdf, 0xaf, 0x12, 0x78, 0x2b, 0xe6, 0xf0, - 0x24, 0xa2, 0x84, 0xe1, 0x3e, 0xa0, 0x90, 0xe8, 0x94, 0xa4, 0x81, 0x07, 0xe9, 0x0a, 0x9a, 0xaf, - 0x57, 0x08, 0xab, 0x6c, 0x3f, 0x59, 0x79, 0x8c, 0xbc, 0xc3, 0x3d, 0x20, 0xaf, 0x82, 0x5b, 0xcd, - 0x3d, 0x67, 0xdc, 0xe3, 0xf7, 0xe4, 0xaf, 0x06, 0x4e, 0x60, 0x3b, 0x67, 0xbf, 0x8a, 0x82, 0x24, - 0x24, 0x7f, 0x33, 0xf0, 0x00, 0x30, 0xe7, 0x5e, 0x46, 0x41, 0x18, 0xc4, 0x8e, 0x4f, 0xfe, 0x6e, - 0xe0, 0x3e, 0xec, 0xbc, 0x0a, 0x6e, 0xb3, 0x53, 0x50, 0x06, 0xff, 0x48, 0x0d, 0x32, 0xfe, 0x67, - 0xf4, 0xe6, 0x8a, 0x46, 0xe4, 0x9f, 0x06, 0x1e, 0xc2, 0xa4, 0x28, 0xc8, 0x7c, 0xfd, 0xcb, 0xd0, - 0x3b, 0xca, 0x44, 0x5f, 0x06, 0x9c, 0x92, 0x7f, 0xa7, 0x6c, 0x9d, 0x07, 0xed, 0xe8, 0x3f, 0x06, - 0xee, 0xc2, 0x38, 0x67, 0x4b, 0xdd, 0xff, 0x1a, 0x38, 0x85, 0xbd, 0x12, 0xd3, 0x63, 0xab, 0x4b, - 0xd1, 0x72, 0xe4, 0x7f, 0xc6, 0xf1, 0xd7, 0x5d, 0xd8, 0x3e, 0x3d, 0x7b, 0x31, 0x3b, 0x0d, 0xd5, - 0x02, 0xe2, 0xf6, 0x7e, 0xa6, 0x1a, 0x0d, 0x6b, 0x9e, 0xe6, 0xd3, 0xba, 0x41, 0x19, 0x8f, 0x75, - 0x3f, 0x62, 0xdd, 0x0b, 0x7d, 0x5a, 0x3b, 0x2f, 0x8b, 0x45, 0xd4, 0x20, 0xf3, 0xf0, 0xa1, 0x3e, - 0xad, 0x1b, 0x9a, 0xf1, 0x17, 0x85, 0xfe, 0xc6, 0xa6, 0xe7, 0xfa, 0xb4, 0x71, 0x7c, 0x16, 0xf6, - 0xf9, 0xe4, 0xd1, 0xf4, 0x68, 0x9f, 0x36, 0xce, 0xd0, 0xf8, 0x3c, 0x83, 0x0c, 0xac, 0x7f, 0xba, - 0x4f, 0x1b, 0xc6, 0x68, 0x91, 0x1e, 0x35, 0x34, 0xd4, 0xbd, 0xc8, 0xa7, 0xb5, 0x93, 0x31, 0x7e, - 0x94, 0x62, 0x12, 0xd6, 0xbe, 0xfa, 0xa7, 0xf5, 0xf3, 0xb7, 0x08, 0x32, 0x7f, 0xd6, 0x35, 0x3d, - 0xe7, 0xa7, 0x8d, 0x93, 0x35, 0x9e, 0x16, 0x41, 0x0e, 0x1b, 0x1f, 0xf5, 0xd3, 0xe6, 0xf9, 0x1a, - 0x3f, 0xce, 0x71, 0x11, 0x1b, 0x9e, 0xf6, 0xd3, 0xa6, 0x11, 0xfb, 0xaa, 0x27, 0xff, 0x35, 0xfa, - 0xf0, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x73, 0x34, 0x90, 0x2d, 0x4a, 0x12, 0x00, 0x00, + // 1723 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x6f, 0xe3, 0xc6, + 0x15, 0x36, 0x75, 0xd7, 0x91, 0x2d, 0x8f, 0x8f, 0x65, 0x5b, 0x56, 0x0b, 0x74, 0xc1, 0x22, 0x8d, + 0x77, 0x9b, 0xee, 0x16, 0x0e, 0x52, 0xac, 0x9b, 0xa2, 0x80, 0xbd, 0xeb, 0xac, 0x85, 0x20, 0xbb, + 0x2e, 0xb3, 0xc9, 0x4b, 0x8b, 0x0a, 0xb4, 0x38, 0x92, 0x58, 0x4b, 0x24, 0x97, 0x1c, 0x3a, 0x72, + 0x7f, 0x43, 0xde, 0xfb, 0x13, 0xfa, 0x0b, 0xfa, 0x94, 0xf7, 0x02, 0xbd, 0x5f, 0x7e, 0x51, 0x71, + 0x66, 0x86, 0x57, 0x53, 0x41, 0x1f, 0xf2, 0x22, 0xf0, 0x5c, 0x67, 0xce, 0xcc, 0x39, 0xdf, 0x39, + 0x23, 0xd8, 0x13, 0xf7, 0x01, 0x8f, 0x9e, 0xc9, 0xdf, 0xa7, 0x41, 0xe8, 0x0b, 0x1f, 0x9b, 0x92, + 0x30, 0xff, 0xdc, 0x80, 0xb6, 0xc5, 0xdf, 0xc5, 0x3c, 0x12, 0x78, 0x02, 0x0d, 0x3e, 0x5d, 0xf8, + 0x43, 0xe3, 0x91, 0x71, 0xd2, 0x3b, 0xc5, 0xa7, 0x4a, 0x5d, 0x4b, 0x2f, 0xa7, 0x0b, 0xff, 0x6a, + 0xcb, 0x92, 0x1a, 0xf8, 0x63, 0x68, 0xce, 0x96, 0x71, 0xb4, 0x18, 0xd6, 0xa4, 0xea, 0x7e, 0x51, + 0xf5, 0x13, 0x12, 0x5d, 0x6d, 0x59, 0x4a, 0x87, 0xdc, 0xba, 0xde, 0xcc, 0x1f, 0xd6, 0xab, 0xdc, + 0x8e, 0xbd, 0x99, 0x74, 0x4b, 0x1a, 0xf8, 0x1c, 0x20, 0xe2, 0x62, 0xe2, 0x07, 0xc2, 0xf5, 0xbd, + 0x61, 0x43, 0xea, 0x1f, 0x15, 0xf5, 0x3f, 0xe7, 0xe2, 0x8d, 0x14, 0x5f, 0x6d, 0x59, 0xdd, 0x28, + 0x21, 0xc8, 0xd2, 0xe1, 0x4b, 0xf7, 0x8e, 0x87, 0x13, 0xb1, 0x1e, 0x36, 0xab, 0x2c, 0x5f, 0x2a, + 0xf9, 0xdb, 0x35, 0x59, 0x3a, 0x09, 0x81, 0xa7, 0xd0, 0x99, 0x2e, 0xf8, 0xf4, 0x96, 0xec, 0x5a, + 0xd2, 0xee, 0xa0, 0x68, 0xf7, 0x82, 0xa4, 0xd2, 0xaa, 0x3d, 0x55, 0x9f, 0xf8, 0x14, 0x5a, 0x53, + 0x7f, 0xb5, 0x72, 0xc5, 0xb0, 0x2d, 0x2d, 0x06, 0x25, 0x0b, 0x29, 0xbb, 0xda, 0xb2, 0xb4, 0x16, + 0x1d, 0xd7, 0xbb, 0x98, 0x87, 0xf7, 0xc3, 0x4e, 0xd5, 0x71, 0xfd, 0x8a, 0x44, 0x74, 0x5c, 0x52, + 0x87, 0x42, 0x71, 0x3d, 0x57, 0x4c, 0xa6, 0x0b, 0xdb, 0xf5, 0x86, 0xdd, 0xaa, 0x50, 0xc6, 0x9e, + 0x2b, 0x5e, 0x90, 0x98, 0x42, 0x71, 0x13, 0x02, 0x3f, 0x86, 0xde, 0x0d, 0x9f, 0xbb, 0xde, 0xe4, + 0x66, 0xe9, 0x4f, 0x6f, 0x87, 0x20, 0x4d, 0x87, 0x45, 0xd3, 0x0b, 0x52, 0xb8, 0x20, 0xf9, 0xd5, + 0x96, 0x05, 0x37, 0x29, 0x85, 0x1f, 0x41, 0x97, 0x7b, 0x8e, 0x36, 0xed, 0x49, 0xd3, 0xc3, 0x52, + 0x06, 0x78, 0x4e, 0x62, 0xd8, 0xe1, 0xfa, 0xfb, 0xa2, 0x0d, 0xcd, 0x3b, 0x7b, 0x19, 0x73, 0xf3, + 0x7d, 0xe8, 0xe5, 0x32, 0x05, 0x87, 0xd0, 0x5e, 0xf1, 0x28, 0xb2, 0xe7, 0x5c, 0xa6, 0x53, 0xd7, + 0x4a, 0x48, 0xb3, 0x0f, 0xdb, 0xf9, 0x3c, 0x31, 0x77, 0x52, 0x43, 0xca, 0x05, 0xf3, 0xe7, 0xc0, + 0xca, 0x57, 0x8d, 0x0c, 0xea, 0xb7, 0xfc, 0x5e, 0x3b, 0xa2, 0x4f, 0x1c, 0xe8, 0x65, 0x65, 0x02, + 0x76, 0x2d, 0xbd, 0x07, 0x33, 0xb5, 0x4d, 0x2f, 0x1b, 0xfb, 0x50, 0x13, 0x6b, 0x69, 0xba, 0x6d, + 0xd5, 0xc4, 0xda, 0x7c, 0x04, 0xfd, 0xe2, 0xc5, 0x3e, 0xd0, 0x58, 0xa5, 0x1b, 0x94, 0x37, 0x83, + 0x08, 0x0d, 0xc7, 0x16, 0xb6, 0xd6, 0x90, 0xdf, 0xc4, 0x0b, 0x6c, 0xb1, 0xd0, 0xcb, 0xcb, 0x6f, + 0xfc, 0x01, 0xf4, 0x96, 0x76, 0x24, 0x26, 0x0b, 0xee, 0xce, 0x17, 0x42, 0xa6, 0x7b, 0xc3, 0x02, + 0x62, 0x5d, 0x49, 0x0e, 0x6d, 0x3a, 0x08, 0xfd, 0x3b, 0x2e, 0x33, 0xbb, 0x63, 0x29, 0xc2, 0xdc, + 0x85, 0x9d, 0x42, 0xde, 0x98, 0x2f, 0xd3, 0x28, 0xd2, 0x7b, 0xc6, 0x9f, 0x02, 0xdc, 0xd9, 0x4b, + 0xd7, 0xb1, 0x85, 0x1f, 0x46, 0x43, 0xe3, 0x51, 0xfd, 0xa4, 0x77, 0xca, 0xf4, 0xf5, 0x7c, 0x99, + 0x08, 0xac, 0x9c, 0x8e, 0xf9, 0x1a, 0xf6, 0x1e, 0x5c, 0x39, 0x6d, 0x7b, 0x61, 0x47, 0x8b, 0x24, + 0x14, 0xfa, 0xc6, 0xf7, 0xa0, 0xb5, 0xe0, 0xb6, 0xc3, 0x43, 0x5d, 0xcc, 0x3b, 0xda, 0xed, 0x95, + 0x64, 0x5a, 0x5a, 0x68, 0x3e, 0x86, 0xdd, 0x52, 0x1e, 0xe0, 0x21, 0x59, 0xca, 0x58, 0x0d, 0x19, + 0xab, 0xa6, 0xcc, 0xaf, 0x9b, 0xd0, 0xb1, 0x78, 0x14, 0xf8, 0x5e, 0xc4, 0xf1, 0x39, 0x74, 0xf9, + 0x7a, 0xca, 0x55, 0x49, 0x1b, 0xa5, 0x94, 0x54, 0x3a, 0x97, 0x89, 0x9c, 0xd2, 0x39, 0x55, 0xc6, + 0xc7, 0x1a, 0x8e, 0xca, 0x18, 0xa3, 0x8d, 0xf2, 0x78, 0xf4, 0x41, 0x82, 0x47, 0xf5, 0x52, 0x3d, + 0x2a, 0xdd, 0x12, 0x20, 0x3d, 0xd6, 0x80, 0xd4, 0xa8, 0x74, 0x5c, 0x40, 0xa4, 0xb3, 0x02, 0x22, + 0x35, 0x2b, 0xb7, 0xbf, 0x01, 0x92, 0xce, 0x0a, 0x90, 0xd4, 0xaa, 0x34, 0xdd, 0x80, 0x49, 0x1f, + 0xe6, 0x30, 0xa9, 0x5d, 0x2a, 0x45, 0x65, 0x58, 0x01, 0x4a, 0xcf, 0x52, 0x50, 0xea, 0x94, 0x60, + 0x4c, 0x9b, 0x94, 0x51, 0xe9, 0x83, 0x04, 0x95, 0xba, 0x95, 0x87, 0x56, 0x82, 0xa5, 0xb3, 0x02, + 0x2c, 0x41, 0x65, 0x38, 0x1b, 0x70, 0xe9, 0x17, 0x45, 0x5c, 0x52, 0xe0, 0x72, 0x5c, 0xb2, 0xdd, + 0x08, 0x4c, 0x3f, 0xcb, 0x03, 0xd3, 0x76, 0x09, 0x0e, 0x75, 0x2e, 0x7c, 0x2b, 0x32, 0x3d, 0xa6, + 0x4a, 0x28, 0x65, 0x1a, 0xd5, 0x22, 0x0f, 0x43, 0x3f, 0xd4, 0xa0, 0xa2, 0x08, 0xf3, 0x84, 0x4a, + 0x3f, 0xcb, 0xaf, 0x6f, 0x41, 0x31, 0x59, 0xb5, 0xb9, 0xec, 0x32, 0xff, 0x60, 0x64, 0xb6, 0x94, + 0x42, 0x05, 0xd8, 0xe8, 0x6a, 0xd8, 0x18, 0x42, 0xfb, 0x8e, 0x87, 0x11, 0xe5, 0x92, 0x42, 0x8e, + 0x84, 0xc4, 0x27, 0xb0, 0x27, 0xc1, 0x43, 0x86, 0x59, 0x84, 0x90, 0x5d, 0x12, 0xa8, 0xf8, 0x14, + 0x8e, 0xfc, 0x04, 0xf6, 0x73, 0xba, 0x76, 0x10, 0x4c, 0x64, 0x51, 0x37, 0x64, 0x51, 0xb3, 0x54, + 0xfb, 0x3c, 0x08, 0xae, 0xec, 0x68, 0x61, 0xbe, 0x97, 0xc5, 0x5f, 0x80, 0xd4, 0xa5, 0x3f, 0x4f, + 0x20, 0x75, 0xe9, 0xcf, 0xcd, 0xdf, 0x66, 0x6a, 0x19, 0x7a, 0xfe, 0x10, 0x1a, 0x53, 0xdf, 0x51, + 0xd1, 0xf7, 0x4f, 0x77, 0xf5, 0xb9, 0xbf, 0xf0, 0x1d, 0xfe, 0xf6, 0x3e, 0xe0, 0x96, 0x14, 0xa6, + 0x91, 0xd6, 0x72, 0x00, 0xa9, 0xfd, 0xd7, 0x33, 0xff, 0xbf, 0x21, 0x00, 0x29, 0x64, 0xef, 0x77, + 0xe9, 0xfd, 0x1b, 0x23, 0xbb, 0x10, 0x05, 0xdb, 0xff, 0x97, 0xf3, 0x01, 0x34, 0x5d, 0xcf, 0xe1, + 0x6b, 0xe9, 0xbd, 0x6e, 0x29, 0x22, 0xe9, 0x37, 0x75, 0xb9, 0x62, 0xb1, 0xdf, 0xa8, 0x43, 0x56, + 0x84, 0x06, 0x74, 0x7f, 0x26, 0x81, 0x61, 0xdb, 0x52, 0x44, 0xb9, 0x0f, 0xb4, 0x1e, 0xf4, 0x01, + 0xbd, 0xfb, 0x76, 0xb6, 0xfb, 0x5f, 0x53, 0x53, 0xca, 0x97, 0xe9, 0x77, 0x79, 0x34, 0xfb, 0xd9, + 0xc5, 0xa6, 0x05, 0x6a, 0x0e, 0x00, 0x1f, 0x56, 0x9e, 0x6a, 0xbe, 0xc5, 0x9a, 0xc2, 0x1f, 0x41, + 0xd3, 0x71, 0x67, 0xb3, 0x68, 0xd8, 0xd8, 0xd0, 0x75, 0x94, 0xd8, 0xfc, 0x63, 0x0d, 0x5a, 0xaa, + 0x67, 0xe0, 0x31, 0xe1, 0x97, 0xed, 0x7a, 0x13, 0xd7, 0x49, 0xea, 0x46, 0xd2, 0x63, 0x27, 0xd7, + 0x33, 0x6a, 0xf9, 0x9e, 0x41, 0xa1, 0x08, 0x77, 0xc5, 0x75, 0xca, 0xcb, 0x6f, 0x3c, 0x82, 0xb6, + 0x17, 0xaf, 0x26, 0x62, 0x1d, 0xc9, 0x63, 0x6f, 0x58, 0x2d, 0x2f, 0x5e, 0xbd, 0x5d, 0x47, 0x78, + 0x0a, 0x3b, 0xb9, 0x02, 0x70, 0x1d, 0x0d, 0xcc, 0x7d, 0xbd, 0x35, 0xb9, 0xef, 0xf1, 0x4b, 0xab, + 0x97, 0x96, 0xc2, 0xd8, 0xc1, 0x13, 0x90, 0x95, 0x31, 0x51, 0xe0, 0xa7, 0x2a, 0xa6, 0x25, 0xcf, + 0xad, 0x4f, 0x7c, 0x8d, 0x8e, 0xd4, 0x10, 0xbf, 0x07, 0x5d, 0x3a, 0x49, 0xa5, 0xd2, 0x96, 0x2a, + 0x1d, 0x62, 0x48, 0xe1, 0xfb, 0xb0, 0x9b, 0x35, 0x59, 0xa5, 0xd2, 0x51, 0x5e, 0x32, 0xb6, 0x54, + 0x3c, 0x86, 0x4e, 0x5a, 0x99, 0x5d, 0xa9, 0xd1, 0xb6, 0x75, 0x41, 0x8e, 0xa1, 0xad, 0xb7, 0x58, + 0xd9, 0x90, 0x9f, 0x40, 0x33, 0xb0, 0x43, 0x11, 0xe9, 0xc6, 0x97, 0xe0, 0xf2, 0xb5, 0x1d, 0xd2, + 0x48, 0xa4, 0xdb, 0xb2, 0x52, 0x31, 0xcf, 0x60, 0xa7, 0xc0, 0xa7, 0x94, 0x14, 0xbe, 0xb0, 0x97, + 0xba, 0x25, 0x2b, 0x22, 0x5d, 0xa6, 0x96, 0x2d, 0x63, 0x9e, 0x41, 0x37, 0xbd, 0x43, 0xba, 0x96, + 0x20, 0xbe, 0xf9, 0x54, 0x0f, 0x59, 0xdb, 0x96, 0xa6, 0x64, 0x86, 0xfb, 0x5f, 0xe9, 0xd9, 0xa0, + 0x61, 0x29, 0xe2, 0xc9, 0x37, 0x06, 0xf4, 0x3e, 0x53, 0x40, 0x48, 0xd9, 0x88, 0xbb, 0xd0, 0x7b, + 0x1d, 0x2f, 0x97, 0x9a, 0xc5, 0xb6, 0xb0, 0x03, 0x0d, 0xc2, 0x4f, 0x66, 0x60, 0x17, 0x9a, 0x12, + 0x1f, 0x59, 0x8d, 0x98, 0x04, 0x8c, 0xac, 0x8e, 0x3b, 0xd0, 0x4d, 0x91, 0x88, 0x35, 0x88, 0x4c, + 0x81, 0x99, 0x35, 0x89, 0x4c, 0x01, 0x88, 0xed, 0x61, 0x0f, 0xda, 0x1a, 0x2f, 0x18, 0x22, 0x40, + 0x4b, 0xdd, 0x14, 0xdb, 0x27, 0xd7, 0xb2, 0xd2, 0xd9, 0x80, 0x4c, 0xd2, 0xd4, 0x66, 0x07, 0xd8, + 0x07, 0xc8, 0x92, 0x9a, 0x1d, 0xe2, 0x36, 0x74, 0x92, 0x74, 0x66, 0x47, 0x4f, 0xfe, 0xd4, 0x84, + 0x4e, 0x52, 0x48, 0xd8, 0x82, 0xda, 0x9b, 0x4f, 0xd9, 0x16, 0xee, 0xc1, 0xce, 0xd8, 0x13, 0x3c, + 0xf4, 0xec, 0xe5, 0x25, 0xb5, 0x02, 0x66, 0x10, 0xeb, 0xd2, 0x9b, 0xfa, 0x8e, 0xeb, 0xcd, 0x15, + 0xab, 0x46, 0x8e, 0x2e, 0x6c, 0xe7, 0xb5, 0xef, 0x4d, 0x39, 0xab, 0x23, 0x83, 0xed, 0x2f, 0x3c, + 0x3b, 0x16, 0x0b, 0x3f, 0x74, 0x7f, 0xcf, 0x1d, 0xd6, 0xc0, 0x03, 0xd8, 0x1b, 0x7b, 0x51, 0x3c, + 0x9b, 0xb9, 0x53, 0x97, 0x7b, 0xe2, 0x93, 0xd8, 0x73, 0x22, 0xd6, 0x44, 0x84, 0xfe, 0x17, 0xde, + 0xad, 0xe7, 0x7f, 0xe5, 0xe9, 0x11, 0x8a, 0xb5, 0x70, 0x08, 0x83, 0x0b, 0x3b, 0xe2, 0x2f, 0xe3, + 0x60, 0xe9, 0x4e, 0x6d, 0xc1, 0xcf, 0x1d, 0x27, 0xe4, 0x51, 0xc4, 0x38, 0x39, 0x21, 0x49, 0x71, + 0xed, 0x59, 0x62, 0x50, 0xf0, 0xcf, 0x79, 0xc4, 0xe6, 0x78, 0x0c, 0x07, 0x0f, 0x24, 0x72, 0xe5, + 0x05, 0x7e, 0x1f, 0x86, 0x65, 0xd1, 0x2b, 0x3b, 0xba, 0x0e, 0xdd, 0x29, 0x67, 0x2e, 0x0e, 0x80, + 0x29, 0xa9, 0xcc, 0xdd, 0xb1, 0x17, 0xc4, 0x82, 0xfd, 0x2e, 0x59, 0x5f, 0x73, 0xdf, 0xc4, 0x82, + 0xd8, 0xb7, 0x25, 0xf6, 0xb5, 0xcc, 0x0f, 0xb6, 0xc4, 0x23, 0xd8, 0xcf, 0xb1, 0x3f, 0xa7, 0xf8, + 0xe8, 0x74, 0x56, 0xd9, 0x7e, 0x95, 0xc0, 0x9d, 0x7b, 0xb6, 0x88, 0x43, 0xce, 0x3c, 0x3c, 0x04, + 0x24, 0x89, 0x3e, 0x92, 0x24, 0x70, 0x3f, 0x59, 0x41, 0xf3, 0xf5, 0x0a, 0x41, 0x99, 0xbd, 0x8c, + 0xe7, 0xae, 0xc7, 0xde, 0xe1, 0x01, 0xb0, 0x57, 0xfe, 0x9d, 0xe6, 0x5e, 0x7a, 0xc2, 0x15, 0xf7, + 0xec, 0x2f, 0x06, 0x0e, 0x60, 0x37, 0x63, 0xbf, 0x0a, 0xfd, 0x38, 0x60, 0x7f, 0x35, 0xf0, 0x08, + 0x30, 0xe3, 0x5e, 0x87, 0x7e, 0xe0, 0x47, 0xf6, 0x92, 0xfd, 0xcd, 0xc0, 0x43, 0xd8, 0x7b, 0xe5, + 0xdf, 0xa5, 0xb7, 0xa0, 0x0c, 0xfe, 0x9e, 0x18, 0xa4, 0xfc, 0xcf, 0xf8, 0xea, 0x86, 0x87, 0xec, + 0x1f, 0x06, 0x1e, 0xc3, 0x20, 0x2f, 0x48, 0x7d, 0xfd, 0xd3, 0xd0, 0x3b, 0x4a, 0x45, 0x5f, 0xfa, + 0x82, 0xb3, 0x7f, 0x25, 0x6c, 0x7d, 0x0e, 0xda, 0xd1, 0xbf, 0x0d, 0xdc, 0x87, 0x7e, 0xc6, 0x96, + 0xba, 0xff, 0x31, 0x70, 0x04, 0x07, 0x05, 0xa6, 0xeb, 0xcd, 0xaf, 0xa9, 0xe4, 0xd8, 0x7f, 0x8d, + 0xd3, 0xaf, 0x9b, 0xb0, 0x7b, 0x7e, 0xf1, 0x62, 0x7c, 0x1e, 0xa8, 0x05, 0xa8, 0x8d, 0x3f, 0x53, + 0x85, 0x86, 0x15, 0x8f, 0xf5, 0x51, 0xd5, 0xc4, 0x8c, 0xa7, 0xba, 0x1e, 0xb1, 0xea, 0xcd, 0x3e, + 0xaa, 0x1c, 0x9c, 0x69, 0x11, 0x35, 0xd1, 0x3c, 0x7c, 0xba, 0x8f, 0xaa, 0xa6, 0x67, 0xfc, 0x65, + 0xae, 0xbe, 0x71, 0xd3, 0x03, 0x7e, 0xb4, 0x71, 0x8e, 0x26, 0xfb, 0x6c, 0x04, 0xd9, 0xf4, 0x8c, + 0x1f, 0x6d, 0x1c, 0xa6, 0xf1, 0x79, 0x0a, 0x19, 0x58, 0xfd, 0x98, 0x1f, 0x6d, 0x98, 0xa7, 0xe9, + 0x78, 0xd4, 0xf4, 0x50, 0xf5, 0x46, 0x1f, 0x55, 0x8e, 0xc8, 0xf8, 0x51, 0x82, 0x49, 0x58, 0xf9, + 0x3f, 0xc0, 0xa8, 0x7a, 0x10, 0xa7, 0x20, 0xb3, 0xf7, 0xdd, 0xa6, 0x07, 0xfe, 0x68, 0xe3, 0x88, + 0x8d, 0xe7, 0x79, 0x90, 0xc3, 0x8d, 0xcf, 0xfc, 0xd1, 0xe6, 0x41, 0x1b, 0x3f, 0xce, 0x70, 0x11, + 0x37, 0x3c, 0xf6, 0x47, 0x9b, 0x66, 0xed, 0x9b, 0x96, 0xfc, 0x1f, 0xe9, 0xc3, 0xff, 0x05, 0x00, + 0x00, 0xff, 0xff, 0x3a, 0x61, 0xc1, 0xbf, 0x5c, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 3eea82ea..67cd3249 100644 --- a/types/types.proto +++ b/types/types.proto @@ -115,7 +115,7 @@ message RequestCheckTx{ message RequestQuery{ bytes data = 1; string path = 2; - uint64 height = 3; + uint64 last_height = 3; bool prove = 4; } @@ -192,11 +192,11 @@ message ResponseCheckTx{ message ResponseQuery{ CodeType code = 1; - int64 index = 2; + int64 index = 2; bytes key = 3; bytes value = 4; bytes proof = 5; - uint64 height = 6; + uint64 last_height = 6; string log = 7; } From e909cafa0bc208a9bc14d599c955d1bb6e8ff94e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Feb 2017 18:48:59 -0500 Subject: [PATCH 207/545] BaseApplication --- example/block_aware/block_aware_app.go | 26 ++------------- example/counter/counter.go | 12 ++----- example/dummy/dummy.go | 16 ++------- example/example_test.go | 9 +++-- example/nil/nil_app.go | 46 -------------------------- types/base_app.go | 42 +++++++++++++++++++++++ 6 files changed, 52 insertions(+), 99 deletions(-) delete mode 100644 example/nil/nil_app.go create mode 100644 types/base_app.go diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index 90a7a440..454c3560 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -30,6 +30,8 @@ func main() { } type ChainAwareApplication struct { + types.BaseApplication + beginCount int endCount int } @@ -38,26 +40,6 @@ 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(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { return types.ResponseQuery{ Value: []byte(cmn.Fmt("%d,%d", app.beginCount, app.endCount)), @@ -73,7 +55,3 @@ func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.Res app.endCount++ return } - -func (app *ChainAwareApplication) InitChain(vals []*types.Validator) { - return -} diff --git a/example/counter/counter.go b/example/counter/counter.go index 8fce72e2..fa0bab58 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -9,6 +9,8 @@ import ( ) type CounterApplication struct { + types.BaseApplication + hashCount int txCount int serial bool @@ -80,13 +82,3 @@ func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.Response return types.ResponseQuery{Log: Fmt("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} } } - -func (app *CounterApplication) InitChain(validators []*types.Validator) { -} - -func (app *CounterApplication) BeginBlock(hash []byte, header *types.Header) { -} - -func (app *CounterApplication) EndBlock(height uint64) types.ResponseEndBlock { - return types.ResponseEndBlock{} -} diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 73c938e7..fd66250b 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -9,6 +9,8 @@ import ( ) type DummyApplication struct { + types.BaseApplication + state merkle.Tree } @@ -21,10 +23,6 @@ func (app *DummyApplication) Info() (resInfo types.ResponseInfo) { return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} } -func (app *DummyApplication) SetOption(key string, value string) (log string) { - return "" -} - // tx is either "key=value" or just arbitrary bytes func (app *DummyApplication) DeliverTx(tx []byte) types.Result { parts := strings.Split(string(tx), "=") @@ -70,13 +68,3 @@ func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types. return } } - -func (app *DummyApplication) InitChain(validators []*types.Validator) { -} - -func (app *DummyApplication) BeginBlock(hash []byte, header *types.Header) { -} - -func (app *DummyApplication) EndBlock(height uint64) types.ResponseEndBlock { - return types.ResponseEndBlock{} -} diff --git a/example/example_test.go b/example/example_test.go index 26921083..9f18c421 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -14,7 +14,6 @@ import ( "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" @@ -25,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) { diff --git a/example/nil/nil_app.go b/example/nil/nil_app.go deleted file mode 100644 index 5285cc39..00000000 --- a/example/nil/nil_app.go +++ /dev/null @@ -1,46 +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(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { - return resQuery -} - -func (app *NilApplication) InitChain(validators []*types.Validator) { -} - -func (app *NilApplication) BeginBlock(hash []byte, header *types.Header) { -} - -func (app *NilApplication) EndBlock(height uint64) types.ResponseEndBlock { - return types.ResponseEndBlock{} -} diff --git a/types/base_app.go b/types/base_app.go new file mode 100644 index 00000000..1d4f84b8 --- /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 +} From 31bdda27ad80e47d372e4b9e4acfd4c0ef81d3e4 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 14 Feb 2017 16:53:21 -0500 Subject: [PATCH 208/545] Query: LastHeight -> Height :) --- README.md | 4 +- cmd/abci-cli/abci-cli.go | 34 +++--- glide.lock | 35 +++--- glide.yaml | 3 + types/types.pb.go | 247 +++++++++++++++++++-------------------- types/types.proto | 4 +- 6 files changed, 161 insertions(+), 166 deletions(-) diff --git a/README.md b/README.md index 43b19f13..f732b82c 100644 --- a/README.md +++ b/README.md @@ -76,14 +76,14 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * `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/...' - * `LastHeight (uint64)`: The block height for which you want the query (default=0 returns data for the latest committed block). Note that the corresponding Merkle root hash will only be included in the header of the next block (ie. `LastHeight + 1`) + * `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 * `Key ([]byte)`: The key of the matching data * `Value ([]byte)`: The value of the matching data * `Proof ([]byte)`: Proof for the data, if requested - * `LastHeight (uint64)`: The block height from which data was derived. The Merkle root for the proof is included in block `LastHeight + 1` + * `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) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index e4fd50be..0168bea4 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -17,13 +17,13 @@ import ( // Structure for data passed to print response. type response struct { - Data []byte - Code types.CodeType - Key []byte - Value []byte - Log string - LastHeight string - Proof []byte + Data []byte + Code types.CodeType + Key []byte + Value []byte + Log string + Height string + Proof []byte } // client is a global variable so it can be reused by the console @@ -299,20 +299,20 @@ func cmdQuery(c *cli.Context) error { return err } resQuery, err := client.QuerySync(types.RequestQuery{ - Data: queryBytes, - Path: "/store", // TOOD expose - LastHeight: 0, // TODO expose + 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, - Key: resQuery.Key, - Value: resQuery.Value, - Log: resQuery.Log, - LastHeight: fmt.Sprintf("%v", resQuery.LastHeight), + Code: resQuery.Code, + Key: resQuery.Key, + Value: resQuery.Value, + Log: resQuery.Log, + Height: fmt.Sprintf("%v", resQuery.Height), //Proof: resQuery.Proof, }) return nil @@ -346,8 +346,8 @@ func printResponse(c *cli.Context, rsp response) { if rsp.Log != "" { fmt.Printf("-> log: %s\n", rsp.Log) } - if rsp.LastHeight != "" { - fmt.Printf("-> height: %s\n", rsp.LastHeight) + if rsp.Height != "" { + fmt.Printf("-> height: %s\n", rsp.Height) } if rsp.Proof != nil { fmt.Printf("-> proof: %X\n", rsp.Proof) diff --git a/glide.lock b/glide.lock index c67e08b3..5e06cad2 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,13 @@ 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: @@ -45,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 @@ -53,19 +53,19 @@ imports: - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 653cb1f631528351ddbc359b994eb0c96f0341cd + 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 @@ -74,7 +74,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 60c41d1de8da134c05b7b40154a9a82bf5b7edb9 + version: 61557ac0112b576429a0df080e1c2cef5dfbb642 subpackages: - context - http2 @@ -84,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 diff --git a/glide.yaml b/glide.yaml index af174387..2b19d872 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 diff --git a/types/types.pb.go b/types/types.pb.go index 3458c27c..f5966453 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -716,10 +716,10 @@ func (m *RequestCheckTx) GetTx() []byte { } type RequestQuery struct { - Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` - Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` - LastHeight uint64 `protobuf:"varint,3,opt,name=last_height,json=lastHeight" json:"last_height,omitempty"` - Prove bool `protobuf:"varint,4,opt,name=prove" json:"prove,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{} } @@ -741,9 +741,9 @@ func (m *RequestQuery) GetPath() string { return "" } -func (m *RequestQuery) GetLastHeight() uint64 { +func (m *RequestQuery) GetHeight() uint64 { if m != nil { - return m.LastHeight + return m.Height } return 0 } @@ -1411,13 +1411,13 @@ func (m *ResponseCheckTx) GetLog() string { } type ResponseQuery struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` - 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"` - LastHeight uint64 `protobuf:"varint,6,opt,name=last_height,json=lastHeight" json:"last_height,omitempty"` - Log string `protobuf:"bytes,7,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{} } @@ -1460,9 +1460,9 @@ func (m *ResponseQuery) GetProof() []byte { return nil } -func (m *ResponseQuery) GetLastHeight() uint64 { +func (m *ResponseQuery) GetHeight() uint64 { if m != nil { - return m.LastHeight + return m.Height } return 0 } @@ -2129,113 +2129,112 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1723 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x6f, 0xe3, 0xc6, - 0x15, 0x36, 0x75, 0xd7, 0x91, 0x2d, 0x8f, 0x8f, 0x65, 0x5b, 0x56, 0x0b, 0x74, 0xc1, 0x22, 0x8d, - 0x77, 0x9b, 0xee, 0x16, 0x0e, 0x52, 0xac, 0x9b, 0xa2, 0x80, 0xbd, 0xeb, 0xac, 0x85, 0x20, 0xbb, - 0x2e, 0xb3, 0xc9, 0x4b, 0x8b, 0x0a, 0xb4, 0x38, 0x92, 0x58, 0x4b, 0x24, 0x97, 0x1c, 0x3a, 0x72, - 0x7f, 0x43, 0xde, 0xfb, 0x13, 0xfa, 0x0b, 0xfa, 0x94, 0xf7, 0x02, 0xbd, 0x5f, 0x7e, 0x51, 0x71, - 0x66, 0x86, 0x57, 0x53, 0x41, 0x1f, 0xf2, 0x22, 0xf0, 0x5c, 0x67, 0xce, 0xcc, 0x39, 0xdf, 0x39, - 0x23, 0xd8, 0x13, 0xf7, 0x01, 0x8f, 0x9e, 0xc9, 0xdf, 0xa7, 0x41, 0xe8, 0x0b, 0x1f, 0x9b, 0x92, - 0x30, 0xff, 0xdc, 0x80, 0xb6, 0xc5, 0xdf, 0xc5, 0x3c, 0x12, 0x78, 0x02, 0x0d, 0x3e, 0x5d, 0xf8, - 0x43, 0xe3, 0x91, 0x71, 0xd2, 0x3b, 0xc5, 0xa7, 0x4a, 0x5d, 0x4b, 0x2f, 0xa7, 0x0b, 0xff, 0x6a, - 0xcb, 0x92, 0x1a, 0xf8, 0x63, 0x68, 0xce, 0x96, 0x71, 0xb4, 0x18, 0xd6, 0xa4, 0xea, 0x7e, 0x51, - 0xf5, 0x13, 0x12, 0x5d, 0x6d, 0x59, 0x4a, 0x87, 0xdc, 0xba, 0xde, 0xcc, 0x1f, 0xd6, 0xab, 0xdc, - 0x8e, 0xbd, 0x99, 0x74, 0x4b, 0x1a, 0xf8, 0x1c, 0x20, 0xe2, 0x62, 0xe2, 0x07, 0xc2, 0xf5, 0xbd, - 0x61, 0x43, 0xea, 0x1f, 0x15, 0xf5, 0x3f, 0xe7, 0xe2, 0x8d, 0x14, 0x5f, 0x6d, 0x59, 0xdd, 0x28, - 0x21, 0xc8, 0xd2, 0xe1, 0x4b, 0xf7, 0x8e, 0x87, 0x13, 0xb1, 0x1e, 0x36, 0xab, 0x2c, 0x5f, 0x2a, - 0xf9, 0xdb, 0x35, 0x59, 0x3a, 0x09, 0x81, 0xa7, 0xd0, 0x99, 0x2e, 0xf8, 0xf4, 0x96, 0xec, 0x5a, - 0xd2, 0xee, 0xa0, 0x68, 0xf7, 0x82, 0xa4, 0xd2, 0xaa, 0x3d, 0x55, 0x9f, 0xf8, 0x14, 0x5a, 0x53, - 0x7f, 0xb5, 0x72, 0xc5, 0xb0, 0x2d, 0x2d, 0x06, 0x25, 0x0b, 0x29, 0xbb, 0xda, 0xb2, 0xb4, 0x16, - 0x1d, 0xd7, 0xbb, 0x98, 0x87, 0xf7, 0xc3, 0x4e, 0xd5, 0x71, 0xfd, 0x8a, 0x44, 0x74, 0x5c, 0x52, - 0x87, 0x42, 0x71, 0x3d, 0x57, 0x4c, 0xa6, 0x0b, 0xdb, 0xf5, 0x86, 0xdd, 0xaa, 0x50, 0xc6, 0x9e, - 0x2b, 0x5e, 0x90, 0x98, 0x42, 0x71, 0x13, 0x02, 0x3f, 0x86, 0xde, 0x0d, 0x9f, 0xbb, 0xde, 0xe4, - 0x66, 0xe9, 0x4f, 0x6f, 0x87, 0x20, 0x4d, 0x87, 0x45, 0xd3, 0x0b, 0x52, 0xb8, 0x20, 0xf9, 0xd5, - 0x96, 0x05, 0x37, 0x29, 0x85, 0x1f, 0x41, 0x97, 0x7b, 0x8e, 0x36, 0xed, 0x49, 0xd3, 0xc3, 0x52, - 0x06, 0x78, 0x4e, 0x62, 0xd8, 0xe1, 0xfa, 0xfb, 0xa2, 0x0d, 0xcd, 0x3b, 0x7b, 0x19, 0x73, 0xf3, - 0x7d, 0xe8, 0xe5, 0x32, 0x05, 0x87, 0xd0, 0x5e, 0xf1, 0x28, 0xb2, 0xe7, 0x5c, 0xa6, 0x53, 0xd7, - 0x4a, 0x48, 0xb3, 0x0f, 0xdb, 0xf9, 0x3c, 0x31, 0x77, 0x52, 0x43, 0xca, 0x05, 0xf3, 0xe7, 0xc0, - 0xca, 0x57, 0x8d, 0x0c, 0xea, 0xb7, 0xfc, 0x5e, 0x3b, 0xa2, 0x4f, 0x1c, 0xe8, 0x65, 0x65, 0x02, - 0x76, 0x2d, 0xbd, 0x07, 0x33, 0xb5, 0x4d, 0x2f, 0x1b, 0xfb, 0x50, 0x13, 0x6b, 0x69, 0xba, 0x6d, - 0xd5, 0xc4, 0xda, 0x7c, 0x04, 0xfd, 0xe2, 0xc5, 0x3e, 0xd0, 0x58, 0xa5, 0x1b, 0x94, 0x37, 0x83, - 0x08, 0x0d, 0xc7, 0x16, 0xb6, 0xd6, 0x90, 0xdf, 0xc4, 0x0b, 0x6c, 0xb1, 0xd0, 0xcb, 0xcb, 0x6f, - 0xfc, 0x01, 0xf4, 0x96, 0x76, 0x24, 0x26, 0x0b, 0xee, 0xce, 0x17, 0x42, 0xa6, 0x7b, 0xc3, 0x02, - 0x62, 0x5d, 0x49, 0x0e, 0x6d, 0x3a, 0x08, 0xfd, 0x3b, 0x2e, 0x33, 0xbb, 0x63, 0x29, 0xc2, 0xdc, - 0x85, 0x9d, 0x42, 0xde, 0x98, 0x2f, 0xd3, 0x28, 0xd2, 0x7b, 0xc6, 0x9f, 0x02, 0xdc, 0xd9, 0x4b, - 0xd7, 0xb1, 0x85, 0x1f, 0x46, 0x43, 0xe3, 0x51, 0xfd, 0xa4, 0x77, 0xca, 0xf4, 0xf5, 0x7c, 0x99, - 0x08, 0xac, 0x9c, 0x8e, 0xf9, 0x1a, 0xf6, 0x1e, 0x5c, 0x39, 0x6d, 0x7b, 0x61, 0x47, 0x8b, 0x24, - 0x14, 0xfa, 0xc6, 0xf7, 0xa0, 0xb5, 0xe0, 0xb6, 0xc3, 0x43, 0x5d, 0xcc, 0x3b, 0xda, 0xed, 0x95, - 0x64, 0x5a, 0x5a, 0x68, 0x3e, 0x86, 0xdd, 0x52, 0x1e, 0xe0, 0x21, 0x59, 0xca, 0x58, 0x0d, 0x19, - 0xab, 0xa6, 0xcc, 0xaf, 0x9b, 0xd0, 0xb1, 0x78, 0x14, 0xf8, 0x5e, 0xc4, 0xf1, 0x39, 0x74, 0xf9, - 0x7a, 0xca, 0x55, 0x49, 0x1b, 0xa5, 0x94, 0x54, 0x3a, 0x97, 0x89, 0x9c, 0xd2, 0x39, 0x55, 0xc6, - 0xc7, 0x1a, 0x8e, 0xca, 0x18, 0xa3, 0x8d, 0xf2, 0x78, 0xf4, 0x41, 0x82, 0x47, 0xf5, 0x52, 0x3d, - 0x2a, 0xdd, 0x12, 0x20, 0x3d, 0xd6, 0x80, 0xd4, 0xa8, 0x74, 0x5c, 0x40, 0xa4, 0xb3, 0x02, 0x22, - 0x35, 0x2b, 0xb7, 0xbf, 0x01, 0x92, 0xce, 0x0a, 0x90, 0xd4, 0xaa, 0x34, 0xdd, 0x80, 0x49, 0x1f, - 0xe6, 0x30, 0xa9, 0x5d, 0x2a, 0x45, 0x65, 0x58, 0x01, 0x4a, 0xcf, 0x52, 0x50, 0xea, 0x94, 0x60, - 0x4c, 0x9b, 0x94, 0x51, 0xe9, 0x83, 0x04, 0x95, 0xba, 0x95, 0x87, 0x56, 0x82, 0xa5, 0xb3, 0x02, - 0x2c, 0x41, 0x65, 0x38, 0x1b, 0x70, 0xe9, 0x17, 0x45, 0x5c, 0x52, 0xe0, 0x72, 0x5c, 0xb2, 0xdd, - 0x08, 0x4c, 0x3f, 0xcb, 0x03, 0xd3, 0x76, 0x09, 0x0e, 0x75, 0x2e, 0x7c, 0x2b, 0x32, 0x3d, 0xa6, - 0x4a, 0x28, 0x65, 0x1a, 0xd5, 0x22, 0x0f, 0x43, 0x3f, 0xd4, 0xa0, 0xa2, 0x08, 0xf3, 0x84, 0x4a, - 0x3f, 0xcb, 0xaf, 0x6f, 0x41, 0x31, 0x59, 0xb5, 0xb9, 0xec, 0x32, 0xff, 0x60, 0x64, 0xb6, 0x94, - 0x42, 0x05, 0xd8, 0xe8, 0x6a, 0xd8, 0x18, 0x42, 0xfb, 0x8e, 0x87, 0x11, 0xe5, 0x92, 0x42, 0x8e, - 0x84, 0xc4, 0x27, 0xb0, 0x27, 0xc1, 0x43, 0x86, 0x59, 0x84, 0x90, 0x5d, 0x12, 0xa8, 0xf8, 0x14, - 0x8e, 0xfc, 0x04, 0xf6, 0x73, 0xba, 0x76, 0x10, 0x4c, 0x64, 0x51, 0x37, 0x64, 0x51, 0xb3, 0x54, - 0xfb, 0x3c, 0x08, 0xae, 0xec, 0x68, 0x61, 0xbe, 0x97, 0xc5, 0x5f, 0x80, 0xd4, 0xa5, 0x3f, 0x4f, - 0x20, 0x75, 0xe9, 0xcf, 0xcd, 0xdf, 0x66, 0x6a, 0x19, 0x7a, 0xfe, 0x10, 0x1a, 0x53, 0xdf, 0x51, - 0xd1, 0xf7, 0x4f, 0x77, 0xf5, 0xb9, 0xbf, 0xf0, 0x1d, 0xfe, 0xf6, 0x3e, 0xe0, 0x96, 0x14, 0xa6, - 0x91, 0xd6, 0x72, 0x00, 0xa9, 0xfd, 0xd7, 0x33, 0xff, 0xbf, 0x21, 0x00, 0x29, 0x64, 0xef, 0x77, - 0xe9, 0xfd, 0x1b, 0x23, 0xbb, 0x10, 0x05, 0xdb, 0xff, 0x97, 0xf3, 0x01, 0x34, 0x5d, 0xcf, 0xe1, - 0x6b, 0xe9, 0xbd, 0x6e, 0x29, 0x22, 0xe9, 0x37, 0x75, 0xb9, 0x62, 0xb1, 0xdf, 0xa8, 0x43, 0x56, - 0x84, 0x06, 0x74, 0x7f, 0x26, 0x81, 0x61, 0xdb, 0x52, 0x44, 0xb9, 0x0f, 0xb4, 0x1e, 0xf4, 0x01, - 0xbd, 0xfb, 0x76, 0xb6, 0xfb, 0x5f, 0x53, 0x53, 0xca, 0x97, 0xe9, 0x77, 0x79, 0x34, 0xfb, 0xd9, - 0xc5, 0xa6, 0x05, 0x6a, 0x0e, 0x00, 0x1f, 0x56, 0x9e, 0x6a, 0xbe, 0xc5, 0x9a, 0xc2, 0x1f, 0x41, - 0xd3, 0x71, 0x67, 0xb3, 0x68, 0xd8, 0xd8, 0xd0, 0x75, 0x94, 0xd8, 0xfc, 0x63, 0x0d, 0x5a, 0xaa, - 0x67, 0xe0, 0x31, 0xe1, 0x97, 0xed, 0x7a, 0x13, 0xd7, 0x49, 0xea, 0x46, 0xd2, 0x63, 0x27, 0xd7, - 0x33, 0x6a, 0xf9, 0x9e, 0x41, 0xa1, 0x08, 0x77, 0xc5, 0x75, 0xca, 0xcb, 0x6f, 0x3c, 0x82, 0xb6, - 0x17, 0xaf, 0x26, 0x62, 0x1d, 0xc9, 0x63, 0x6f, 0x58, 0x2d, 0x2f, 0x5e, 0xbd, 0x5d, 0x47, 0x78, - 0x0a, 0x3b, 0xb9, 0x02, 0x70, 0x1d, 0x0d, 0xcc, 0x7d, 0xbd, 0x35, 0xb9, 0xef, 0xf1, 0x4b, 0xab, - 0x97, 0x96, 0xc2, 0xd8, 0xc1, 0x13, 0x90, 0x95, 0x31, 0x51, 0xe0, 0xa7, 0x2a, 0xa6, 0x25, 0xcf, - 0xad, 0x4f, 0x7c, 0x8d, 0x8e, 0xd4, 0x10, 0xbf, 0x07, 0x5d, 0x3a, 0x49, 0xa5, 0xd2, 0x96, 0x2a, - 0x1d, 0x62, 0x48, 0xe1, 0xfb, 0xb0, 0x9b, 0x35, 0x59, 0xa5, 0xd2, 0x51, 0x5e, 0x32, 0xb6, 0x54, - 0x3c, 0x86, 0x4e, 0x5a, 0x99, 0x5d, 0xa9, 0xd1, 0xb6, 0x75, 0x41, 0x8e, 0xa1, 0xad, 0xb7, 0x58, - 0xd9, 0x90, 0x9f, 0x40, 0x33, 0xb0, 0x43, 0x11, 0xe9, 0xc6, 0x97, 0xe0, 0xf2, 0xb5, 0x1d, 0xd2, - 0x48, 0xa4, 0xdb, 0xb2, 0x52, 0x31, 0xcf, 0x60, 0xa7, 0xc0, 0xa7, 0x94, 0x14, 0xbe, 0xb0, 0x97, - 0xba, 0x25, 0x2b, 0x22, 0x5d, 0xa6, 0x96, 0x2d, 0x63, 0x9e, 0x41, 0x37, 0xbd, 0x43, 0xba, 0x96, - 0x20, 0xbe, 0xf9, 0x54, 0x0f, 0x59, 0xdb, 0x96, 0xa6, 0x64, 0x86, 0xfb, 0x5f, 0xe9, 0xd9, 0xa0, - 0x61, 0x29, 0xe2, 0xc9, 0x37, 0x06, 0xf4, 0x3e, 0x53, 0x40, 0x48, 0xd9, 0x88, 0xbb, 0xd0, 0x7b, - 0x1d, 0x2f, 0x97, 0x9a, 0xc5, 0xb6, 0xb0, 0x03, 0x0d, 0xc2, 0x4f, 0x66, 0x60, 0x17, 0x9a, 0x12, - 0x1f, 0x59, 0x8d, 0x98, 0x04, 0x8c, 0xac, 0x8e, 0x3b, 0xd0, 0x4d, 0x91, 0x88, 0x35, 0x88, 0x4c, - 0x81, 0x99, 0x35, 0x89, 0x4c, 0x01, 0x88, 0xed, 0x61, 0x0f, 0xda, 0x1a, 0x2f, 0x18, 0x22, 0x40, - 0x4b, 0xdd, 0x14, 0xdb, 0x27, 0xd7, 0xb2, 0xd2, 0xd9, 0x80, 0x4c, 0xd2, 0xd4, 0x66, 0x07, 0xd8, - 0x07, 0xc8, 0x92, 0x9a, 0x1d, 0xe2, 0x36, 0x74, 0x92, 0x74, 0x66, 0x47, 0x4f, 0xfe, 0xd4, 0x84, - 0x4e, 0x52, 0x48, 0xd8, 0x82, 0xda, 0x9b, 0x4f, 0xd9, 0x16, 0xee, 0xc1, 0xce, 0xd8, 0x13, 0x3c, - 0xf4, 0xec, 0xe5, 0x25, 0xb5, 0x02, 0x66, 0x10, 0xeb, 0xd2, 0x9b, 0xfa, 0x8e, 0xeb, 0xcd, 0x15, - 0xab, 0x46, 0x8e, 0x2e, 0x6c, 0xe7, 0xb5, 0xef, 0x4d, 0x39, 0xab, 0x23, 0x83, 0xed, 0x2f, 0x3c, - 0x3b, 0x16, 0x0b, 0x3f, 0x74, 0x7f, 0xcf, 0x1d, 0xd6, 0xc0, 0x03, 0xd8, 0x1b, 0x7b, 0x51, 0x3c, - 0x9b, 0xb9, 0x53, 0x97, 0x7b, 0xe2, 0x93, 0xd8, 0x73, 0x22, 0xd6, 0x44, 0x84, 0xfe, 0x17, 0xde, - 0xad, 0xe7, 0x7f, 0xe5, 0xe9, 0x11, 0x8a, 0xb5, 0x70, 0x08, 0x83, 0x0b, 0x3b, 0xe2, 0x2f, 0xe3, - 0x60, 0xe9, 0x4e, 0x6d, 0xc1, 0xcf, 0x1d, 0x27, 0xe4, 0x51, 0xc4, 0x38, 0x39, 0x21, 0x49, 0x71, - 0xed, 0x59, 0x62, 0x50, 0xf0, 0xcf, 0x79, 0xc4, 0xe6, 0x78, 0x0c, 0x07, 0x0f, 0x24, 0x72, 0xe5, - 0x05, 0x7e, 0x1f, 0x86, 0x65, 0xd1, 0x2b, 0x3b, 0xba, 0x0e, 0xdd, 0x29, 0x67, 0x2e, 0x0e, 0x80, - 0x29, 0xa9, 0xcc, 0xdd, 0xb1, 0x17, 0xc4, 0x82, 0xfd, 0x2e, 0x59, 0x5f, 0x73, 0xdf, 0xc4, 0x82, - 0xd8, 0xb7, 0x25, 0xf6, 0xb5, 0xcc, 0x0f, 0xb6, 0xc4, 0x23, 0xd8, 0xcf, 0xb1, 0x3f, 0xa7, 0xf8, - 0xe8, 0x74, 0x56, 0xd9, 0x7e, 0x95, 0xc0, 0x9d, 0x7b, 0xb6, 0x88, 0x43, 0xce, 0x3c, 0x3c, 0x04, - 0x24, 0x89, 0x3e, 0x92, 0x24, 0x70, 0x3f, 0x59, 0x41, 0xf3, 0xf5, 0x0a, 0x41, 0x99, 0xbd, 0x8c, - 0xe7, 0xae, 0xc7, 0xde, 0xe1, 0x01, 0xb0, 0x57, 0xfe, 0x9d, 0xe6, 0x5e, 0x7a, 0xc2, 0x15, 0xf7, - 0xec, 0x2f, 0x06, 0x0e, 0x60, 0x37, 0x63, 0xbf, 0x0a, 0xfd, 0x38, 0x60, 0x7f, 0x35, 0xf0, 0x08, - 0x30, 0xe3, 0x5e, 0x87, 0x7e, 0xe0, 0x47, 0xf6, 0x92, 0xfd, 0xcd, 0xc0, 0x43, 0xd8, 0x7b, 0xe5, - 0xdf, 0xa5, 0xb7, 0xa0, 0x0c, 0xfe, 0x9e, 0x18, 0xa4, 0xfc, 0xcf, 0xf8, 0xea, 0x86, 0x87, 0xec, - 0x1f, 0x06, 0x1e, 0xc3, 0x20, 0x2f, 0x48, 0x7d, 0xfd, 0xd3, 0xd0, 0x3b, 0x4a, 0x45, 0x5f, 0xfa, - 0x82, 0xb3, 0x7f, 0x25, 0x6c, 0x7d, 0x0e, 0xda, 0xd1, 0xbf, 0x0d, 0xdc, 0x87, 0x7e, 0xc6, 0x96, - 0xba, 0xff, 0x31, 0x70, 0x04, 0x07, 0x05, 0xa6, 0xeb, 0xcd, 0xaf, 0xa9, 0xe4, 0xd8, 0x7f, 0x8d, - 0xd3, 0xaf, 0x9b, 0xb0, 0x7b, 0x7e, 0xf1, 0x62, 0x7c, 0x1e, 0xa8, 0x05, 0xa8, 0x8d, 0x3f, 0x53, - 0x85, 0x86, 0x15, 0x8f, 0xf5, 0x51, 0xd5, 0xc4, 0x8c, 0xa7, 0xba, 0x1e, 0xb1, 0xea, 0xcd, 0x3e, - 0xaa, 0x1c, 0x9c, 0x69, 0x11, 0x35, 0xd1, 0x3c, 0x7c, 0xba, 0x8f, 0xaa, 0xa6, 0x67, 0xfc, 0x65, - 0xae, 0xbe, 0x71, 0xd3, 0x03, 0x7e, 0xb4, 0x71, 0x8e, 0x26, 0xfb, 0x6c, 0x04, 0xd9, 0xf4, 0x8c, - 0x1f, 0x6d, 0x1c, 0xa6, 0xf1, 0x79, 0x0a, 0x19, 0x58, 0xfd, 0x98, 0x1f, 0x6d, 0x98, 0xa7, 0xe9, - 0x78, 0xd4, 0xf4, 0x50, 0xf5, 0x46, 0x1f, 0x55, 0x8e, 0xc8, 0xf8, 0x51, 0x82, 0x49, 0x58, 0xf9, - 0x3f, 0xc0, 0xa8, 0x7a, 0x10, 0xa7, 0x20, 0xb3, 0xf7, 0xdd, 0xa6, 0x07, 0xfe, 0x68, 0xe3, 0x88, - 0x8d, 0xe7, 0x79, 0x90, 0xc3, 0x8d, 0xcf, 0xfc, 0xd1, 0xe6, 0x41, 0x1b, 0x3f, 0xce, 0x70, 0x11, - 0x37, 0x3c, 0xf6, 0x47, 0x9b, 0x66, 0xed, 0x9b, 0x96, 0xfc, 0x1f, 0xe9, 0xc3, 0xff, 0x05, 0x00, - 0x00, 0xff, 0xff, 0x3a, 0x61, 0xc1, 0xbf, 0x5c, 0x12, 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 67cd3249..85ec434d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -115,7 +115,7 @@ message RequestCheckTx{ message RequestQuery{ bytes data = 1; string path = 2; - uint64 last_height = 3; + uint64 height = 3; bool prove = 4; } @@ -196,7 +196,7 @@ message ResponseQuery{ bytes key = 3; bytes value = 4; bytes proof = 5; - uint64 last_height = 6; + uint64 height = 6; string log = 7; } From f81a9c647d18b4a54b541c4c1e069e55bc9be61b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 18 Feb 2017 07:36:14 +0100 Subject: [PATCH 209/545] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0b4707f..bc4a2bcc 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The [primary specification](https://github.com/tendermint/abci/blob/master/types As a [Go interface](https://github.com/tendermint/abci/blob/master/types/application.go), it might look like: -``` +```golang // Applications type Application interface { From d299afe630932b327b596f2608d958d25da55b8c Mon Sep 17 00:00:00 2001 From: Wolf Date: Sun, 19 Feb 2017 16:46:57 +0100 Subject: [PATCH 210/545] Update: jTMSP -> jABCI --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc4a2bcc..40efc50c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Previously, the ABCI was just referred to as TMSP. Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen * [js-tmsp](https://github.com/tendermint/js-tmsp) -* [jTMSP](https://github.com/jTMSP/) for Java +* [jABCI](https://github.com/jTendermint/jabci) for Java # Specification From b350b08021d3f51a9a45b84629fcead0e51ca0ac Mon Sep 17 00:00:00 2001 From: Agnieszka Kramarek <4gn3s@users.noreply.github.com> Date: Mon, 20 Feb 2017 13:49:52 +0100 Subject: [PATCH 211/545] Update README.md Typo fixed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f732b82c..96c95826 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ 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`, From eaeb2658ea7cb14c643707dccce6db41d1d37e58 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 3 Mar 2017 18:39:10 -0500 Subject: [PATCH 212/545] fixes from review --- cmd/abci-cli/abci-cli.go | 58 +++--- example/counter/counter.go | 19 +- example/dummy/dummy.go | 4 +- example/dummy/dummy_test.go | 5 +- example/dummy/dummy_test.go.orig | 321 ------------------------------ example/dummy/persistent_dummy.go | 15 +- example/example_test.go | 8 +- tests/test_cli/ex1.abci.out | 8 +- 8 files changed, 62 insertions(+), 376 deletions(-) delete mode 100644 example/dummy/dummy_test.go.orig diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 0168bea4..1b08b76a 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -17,12 +17,18 @@ import ( // Structure for data passed to print response. type response struct { - Data []byte - Code types.CodeType + // generic abci response + Data []byte + Code types.CodeType + Log string + + Query *queryResponse +} + +type queryResponse struct { Key []byte Value []byte - Log string - Height string + Height uint64 Proof []byte } @@ -281,6 +287,7 @@ func cmdCheckTx(c *cli.Context) error { func cmdCommit(c *cli.Context) error { res := client.CommitSync() printResponse(c, response{ + Code: res.Code, Data: res.Data, Log: res.Log, }) @@ -308,12 +315,14 @@ func cmdQuery(c *cli.Context) error { return err } printResponse(c, response{ - Code: resQuery.Code, - Key: resQuery.Key, - Value: resQuery.Value, - Log: resQuery.Log, - Height: fmt.Sprintf("%v", resQuery.Height), - //Proof: resQuery.Proof, + Code: resQuery.Code, + Log: resQuery.Log, + Query: &queryResponse{ + Key: resQuery.Key, + Value: resQuery.Value, + Height: resQuery.Height, + Proof: resQuery.Proof, + }, }) return nil } @@ -328,29 +337,30 @@ func printResponse(c *cli.Context, rsp response) { fmt.Println(">", c.Command.Name, strings.Join(c.Args(), " ")) } - if rsp.Code != types.CodeType_OK { + if !rsp.Code.IsOK() { fmt.Printf("-> code: %s\n", rsp.Code.String()) } if len(rsp.Data) != 0 { fmt.Printf("-> data: %s\n", rsp.Data) fmt.Printf("-> data.hex: %X\n", rsp.Data) } - if len(rsp.Key) != 0 { - fmt.Printf("-> key: %s\n", rsp.Key) - fmt.Printf("-> key.hex: %X\n", rsp.Key) - } - if len(rsp.Value) != 0 { - fmt.Printf("-> value: %s\n", rsp.Value) - fmt.Printf("-> value.hex: %X\n", rsp.Value) - } if rsp.Log != "" { fmt.Printf("-> log: %s\n", rsp.Log) } - if rsp.Height != "" { - fmt.Printf("-> height: %s\n", rsp.Height) - } - if rsp.Proof != nil { - fmt.Printf("-> proof: %X\n", rsp.Proof) + + 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/example/counter/counter.go b/example/counter/counter.go index fa0bab58..c40541ed 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -2,10 +2,9 @@ package counter import ( "encoding/binary" - "fmt" "github.com/tendermint/abci/types" - . "github.com/tendermint/go-common" + cmn "github.com/tendermint/go-common" ) type CounterApplication struct { @@ -21,7 +20,7 @@ func NewCounterApplication(serial bool) *CounterApplication { } func (app *CounterApplication) Info() types.ResponseInfo { - return types.ResponseInfo{Data: fmt.Sprintf("{\"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) { @@ -34,13 +33,13 @@ 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.Sprintf("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.Sprintf("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++ @@ -50,13 +49,13 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.Result { func (app *CounterApplication) CheckTx(tx []byte) types.Result { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(fmt.Sprintf("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.Sprintf("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 @@ -75,10 +74,10 @@ func (app *CounterApplication) Commit() types.Result { func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { switch reqQuery.Path { case "hash": - return types.ResponseQuery{Value: []byte(Fmt("%v", app.hashCount))} + return types.ResponseQuery{Value: []byte(cmn.Fmt("%v", app.hashCount))} case "tx": - return types.ResponseQuery{Value: []byte(Fmt("%v", app.txCount))} + return types.ResponseQuery{Value: []byte(cmn.Fmt("%v", app.txCount))} default: - return types.ResponseQuery{Log: Fmt("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} + return types.ResponseQuery{Log: cmn.Fmt("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)} } } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index fd66250b..f88b1b20 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,10 +1,10 @@ package dummy import ( - "fmt" "strings" "github.com/tendermint/abci/types" + cmn "github.com/tendermint/go-common" "github.com/tendermint/go-merkle" ) @@ -20,7 +20,7 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info() (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} } // tx is either "key=value" or just arbitrary bytes diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index fbbf97a5..879cf3c4 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -2,7 +2,6 @@ package dummy import ( "bytes" - "fmt" "io/ioutil" "sort" "testing" @@ -13,7 +12,7 @@ import ( "github.com/tendermint/abci/types" cmn "github.com/tendermint/go-common" "github.com/tendermint/go-crypto" - merkle "github.com/tendermint/go-merkle" + "github.com/tendermint/go-merkle" ) func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { @@ -115,7 +114,7 @@ func TestValSetChanges(t *testing.T) { nInit := 5 vals := make([]*types.Validator, total) for i := 0; i < total; i++ { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(fmt.Sprintf("test%d", i))).PubKey().Bytes() + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() power := cmn.RandInt() vals[i] = &types.Validator{pubkey, uint64(power)} } diff --git a/example/dummy/dummy_test.go.orig b/example/dummy/dummy_test.go.orig deleted file mode 100644 index 5cf7eee7..00000000 --- a/example/dummy/dummy_test.go.orig +++ /dev/null @@ -1,321 +0,0 @@ -package dummy - -import ( - "bytes" - "io/ioutil" - "sort" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - . "github.com/tendermint/go-common" - "github.com/tendermint/go-crypto" - merkle "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" -<<<<<<< HEAD - "github.com/tendermint/abci/types" -) - -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) - } -======= - tmspcli "github.com/tendermint/tmsp/client" - "github.com/tendermint/tmsp/server" - "github.com/tendermint/tmsp/types" -) - -func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { - ar := app.AppendTx(tx) - require.False(t, ar.IsErr(), ar) - // repeating tx doesn't raise error - ar = app.AppendTx(tx) - require.False(t, ar.IsErr(), ar) ->>>>>>> Add tests for client-server proofs over socket and grpc - - // make sure query is fine - r := app.Query([]byte(key)) - require.False(t, r.IsErr(), r) - q := new(QueryResult) - err := wire.ReadJSONBytes(r.Data, q) - require.Nil(t, err) - require.Equal(t, value, q.Value) - - // make sure proof is fine - rp := app.Proof([]byte(key), 0) - require.False(t, rp.IsErr(), rp) - p, err := merkle.LoadProof(rp.Data) - require.Nil(t, err) - require.True(t, p.Valid()) - assert.Equal(t, []byte(key), p.Key()) - assert.Equal(t, []byte(value), p.Value()) -} - -func TestDummyKV(t *testing.T) { - dummy := NewDummyApplication() - key := "abc" - value := key - tx := []byte(key) - testDummy(t, dummy, tx, key, value) - - value = "def" - tx = []byte(key + "=" + value) - testDummy(t, dummy, tx, key, value) -} - -func TestPersistentDummyKV(t *testing.T) { - dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO - if err != nil { - t.Fatal(err) - } - dummy := NewPersistentDummyApplication(dir) - key := "abc" - value := key - tx := []byte(key) - testDummy(t, dummy, tx, key, value) - - value = "def" - tx = []byte(key + "=" + value) - testDummy(t, dummy, tx, key, value) -} - -func TestPersistentDummyInfo(t *testing.T) { - dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO - if err != nil { - t.Fatal(err) - } - dummy := NewPersistentDummyApplication(dir) - height := uint64(0) - - resInfo := dummy.Info() - if resInfo.LastBlockHeight != height { - t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) - } - - // make and apply block - height = uint64(1) - hash := []byte("foo") - header := &types.Header{ - Height: uint64(height), - } - dummy.BeginBlock(hash, header) - dummy.EndBlock(height) - dummy.Commit() - - resInfo = dummy.Info() - if resInfo.LastBlockHeight != height { - t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) - } - -} - -// add a validator, remove a validator, update a validator -func TestValSetChanges(t *testing.T) { - dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO - if err != nil { - t.Fatal(err) - } - dummy := NewPersistentDummyApplication(dir) - - // init with some validators - total := 10 - 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() - vals[i] = &types.Validator{pubkey, uint64(power)} - } - // iniitalize with the first nInit - dummy.InitChain(vals[:nInit]) - - vals1, vals2 := vals[:nInit], dummy.Validators() - valsEqual(t, vals1, vals2) - - var v1, v2, v3 *types.Validator - - // add some validators - v1, v2 = vals[nInit], vals[nInit+1] - diff := []*types.Validator{v1, v2} - tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power) - tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power) - - makeApplyBlock(t, dummy, 1, diff, tx1, tx2) - - vals1, vals2 = vals[:nInit+2], dummy.Validators() - valsEqual(t, vals1, vals2) - - // remove some validators - v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit] - v1.Power = 0 - v2.Power = 0 - v3.Power = 0 - diff = []*types.Validator{v1, v2, v3} - tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) - tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power) - tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power) - - makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3) - - vals1 = append(vals[:nInit-2], vals[nInit+1]) - vals2 = dummy.Validators() - valsEqual(t, vals1, vals2) - - // update some validators - v1 = vals[0] - if v1.Power == 5 { - v1.Power = 6 - } else { - v1.Power = 5 - } - diff = []*types.Validator{v1} - tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) - - makeApplyBlock(t, dummy, 3, diff, tx1) - - vals1 = append([]*types.Validator{v1}, vals1[1:len(vals1)]...) - vals2 = dummy.Validators() - valsEqual(t, vals1, vals2) - -} - -func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) { - // make and apply block - height := uint64(heightInt) - hash := []byte("foo") - header := &types.Header{ - Height: height, - } - - dummyChain := dummy.(types.BlockchainAware) // hmm... - dummyChain.BeginBlock(hash, header) - for _, tx := range txs { - if r := dummy.DeliverTx(tx); r.IsErr() { - t.Fatal(r) - } - } - resEndBlock := dummyChain.EndBlock(height) - dummy.Commit() - - valsEqual(t, diff, resEndBlock.Diffs) - -} - -// order doesn't matter -func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { - if len(vals1) != len(vals2) { - t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1)) - } - sort.Sort(types.Validators(vals1)) - sort.Sort(types.Validators(vals2)) - for i, v1 := range vals1 { - v2 := vals2[i] - if !bytes.Equal(v1.PubKey, v2.PubKey) || - v1.Power != v2.Power { - t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power) - } - } -} - -func makeSocketClientServer(app types.Application, name string) (tmspcli.Client, Service, error) { - // Start the listener - socket := Fmt("unix://%s.sock", name) - server, err := server.NewSocketServer(socket, app) - if err != nil { - return nil, nil, err - } - - // Connect to the socket - client, err := tmspcli.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) (tmspcli.Client, Service, error) { - // Start the listener - socket := Fmt("unix://%s.sock", name) - - gapp := types.NewGRPCApplication(app) - server, err := server.NewGRPCServer(socket, gapp) - if err != nil { - return nil, nil, err - } - - client, err := tmspcli.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 tmspcli.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 tmspcli.Client, tx []byte, key, value string) { - ar := app.AppendTxSync(tx) - require.False(t, ar.IsErr(), ar) - // repeating tx doesn't raise error - ar = app.AppendTxSync(tx) - require.False(t, ar.IsErr(), ar) - - // make sure query is fine - r := app.QuerySync([]byte(key)) - require.False(t, r.IsErr(), r) - q := new(QueryResult) - err := wire.ReadJSONBytes(r.Data, q) - require.Nil(t, err) - require.Equal(t, value, q.Value) - - // make sure proof is fine - rp := app.ProofSync([]byte(key), 0) - require.False(t, rp.IsErr(), rp) - p, err := merkle.LoadProof(rp.Data) - require.Nil(t, err) - require.True(t, p.Valid()) - assert.Equal(t, []byte(key), p.Key()) - assert.Equal(t, []byte(value), p.Value()) -} diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 73366c7e..48eff420 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,7 +3,6 @@ package dummy import ( "bytes" "encoding/hex" - "fmt" "strconv" "strings" @@ -136,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 - log.Crit(fmt.Sprintf("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. } @@ -174,7 +173,7 @@ func (app *PersistentDummyApplication) Validators() (validators []*types.Validat } func MakeValSetChangeTx(pubkey []byte, power uint64) []byte { - return []byte(fmt.Sprintf("val:%X/%d", pubkey, power)) + return []byte(cmn.Fmt("val:%X/%d", pubkey, power)) } func isValidatorTx(tx []byte) bool { @@ -189,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.Sprintf("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.Sprintf("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.Sprintf("Power (%s) is not an int", powerS)) + return types.ErrEncodingError.SetLog(cmn.Fmt("Power (%s) is not an int", powerS)) } // update @@ -211,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.Sprintf("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.Sprintf("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 9f18c421..034331d6 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -41,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 { - log.Fatal(fmt.Sprintf("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 { - log.Fatal(fmt.Sprintf("Error starting socket client: %v", err.Error())) + log.Fatal(cmn.Fmt("Error starting socket client: %v", err.Error())) } client.Start() defer client.Stop() @@ -114,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 { - log.Fatal(fmt.Sprintf("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 { - log.Fatal(fmt.Sprintf("Error dialing GRPC server: %v", err.Error())) + log.Fatal(cmn.Fmt("Error dialing GRPC server: %v", err.Error())) } defer conn.Close() diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index e1e21d24..e434944a 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -19,10 +19,10 @@ -> data.hex: 750502FC7E84BBD788ED589624F06CFA871845D1 > query "abc" --> value: abc --> value.hex: 616263 -> log: exists -> height: 0 +-> value: abc +-> value.hex: 616263 > deliver_tx "def=xyz" @@ -31,8 +31,8 @@ -> data.hex: 76393B8A182E450286B0694C629ECB51B286EFD5 > query "def" --> value: xyz --> value.hex: 78797A -> log: exists -> height: 0 +-> value: xyz +-> value.hex: 78797A From 0b1ee4b67318047d20a90bc6a8b0119a15c7c771 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 3 Mar 2017 18:43:05 -0500 Subject: [PATCH 213/545] version bump to 0.4.0 --- cmd/abci-cli/abci-cli.go | 3 ++- version/version.go | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 version/version.go diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 1b08b76a..accae9d1 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" + "github.com/tendermint/abci/version" "github.com/urfave/cli" ) @@ -43,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", diff --git a/version/version.go b/version/version.go new file mode 100644 index 00000000..04695d9b --- /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!) From 700a62c22e5868e6075eb97a57b6d69ab6346f26 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 6 Mar 2017 02:53:15 -0500 Subject: [PATCH 214/545] CHANGELOG --- CHANGELOG.md | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..7586c906 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,169 @@ +# Changelog + +## 0.4.0 (March 6, 2017) + +BREAKING CHANGES: + +- Query takes RequestQuery and returns ResponseQuery, with more specificity over keys, paths, and proofs: + +``` +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:o + +``` +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. + + + From be5a4345a3283450f57451912be0f390f4286128 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 6 Mar 2017 02:58:26 -0500 Subject: [PATCH 215/545] formatting and update CHANGELOG --- CHANGELOG.md | 8 +++++--- types/types.proto | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7586c906..6f5cf42c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,9 @@ BREAKING CHANGES: -- Query takes RequestQuery and returns ResponseQuery, with more specificity over keys, paths, and proofs: +- 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{ @@ -20,7 +22,7 @@ message ResponseQuery{ bytes key = 3; bytes value = 4; bytes proof = 5; - uint64 height = 6; + uint64 height = 6; string log = 7; } ``` @@ -47,7 +49,7 @@ message RequestBeginBlock{ } ``` -- Info returns a ResponseInfo, containing last block height and app hash:o +- Info returns a ResponseInfo, containing last block height and app hash: ``` message ResponseInfo { diff --git a/types/types.proto b/types/types.proto index 85ec434d..0c741d3d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -196,7 +196,7 @@ message ResponseQuery{ bytes key = 3; bytes value = 4; bytes proof = 5; - uint64 height = 6; + uint64 height = 6; string log = 7; } @@ -214,7 +214,7 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 4; + repeated Validator diffs = 1; } //---------------------------------------- From e6a5b060f9308310943ec9c7e13876d16cc06723 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Mar 2017 16:36:41 -0400 Subject: [PATCH 216/545] update readme --- README.md | 94 ++++++++++++++----------------------------------------- 1 file changed, 24 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 2159f3cb..4b94c97c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ to manage an application state running in another. For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-application-blockchain-interface), and the more detailed [application developer's guide](https://tendermint.com/docs/guides/app-development). -Previously, the ABCI was just referred to as TMSP. +Previously, the ABCI was referred to as TMSP. Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen @@ -21,62 +21,22 @@ Other implementations: # Specification The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers. +To build it, run - - 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. +``` +make protoc +``` -TendermintCore runs a client, and the ABCI application runs a server. There are three Golang implementation of ABCI client and server. +See `protoc --help` and [the Protocol Buffers site](https://developers.google.com/protocol-buffers/) for details on compiling for other languages. +Note we also include a [GRPC](https://www.grpc.io/docs) service definition. -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 -type Application interface { - - // Latest state - Info() ResponseInfo - - // Initialization - SetOption(key string, value string) (log string) - InitChain(validators []*Validator) - - // Apply a block - BeginBlock(hash []byte, header *Header) - DeliverTx(tx []byte) Result - EndBlock(height uint64) ResponseEndBlock - Commit() Result - - // Check validity - CheckTx(tx []byte) Result - - // Query for state - Query(query []byte) Result -} - -type Result struct { - Code CodeType - Data []byte - Log string // Can be non-deterministic -} - -type ResponseInfo struct { - Data string - Version string - LastBlockHeight uint64 - LastBlockAppHash []byte -} - -type ResponseEndBlock struct { - Diffs []*Validator -} - -_TODO: merge information from https://tendermint.com/blog/tendermint-0-8-release_ +For the specification as an interface in Go, see the [types/application.go file](https://github.com/tendermint/abci/blob/master/types/application.go). ## Message Types -ABCI requests/responses are simple Protobuf messages. Check out the [schema file](https://github.com/tendermint/abci/blob/master/types/types.proto). +ABCI requests/responses are defined as simple Protobuf messages in [this schema file](https://github.com/tendermint/abci/blob/master/types/types.proto). +TendermintCore sends the requests, and the ABCI application sends the responses. +Here, we describe the requests and responses as function arguments and return values, and make some notes about usage: #### DeliverTx * __Arguments__: @@ -99,7 +59,7 @@ 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 state. + CheckTx can happen interspersed with DeliverTx, but they happen on different ABCI connections - CheckTx from the mempool connection, and DeliverTx from the consensus connection. During Commit, the mempool is locked, so you can reset the mempool state to the latest state after running all those DeliverTxs, and then the mempool will re-run whatever txs it has against that latest mempool state. Transactions are first run through CheckTx before broadcast to peers in the mempool layer. You can make CheckTx semi-stateful and clear the state upon `Commit` or `BeginBlock`, @@ -184,13 +144,13 @@ ABCI requests/responses are simple Protobuf messages. Check out the [schema fil * Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. -# Implementations +# Implementation -The ABCI is a client/server interface where the replication engine (blockchain) forms the client -and the state machine (application) forms the server. -As blocks are committed in the blockchain, they are forwarded to the application. +We provide three implementations of the ABCI in Go: -This repository provides two implementations of an ABCI client & server: via socket and via GRPC. +1. ABCI-socket +2. GRPC +3. Golang in-process ## Socket @@ -209,24 +169,18 @@ the ordered, asynchronous socket protocol. Note the length-prefixing used in the socket implementation does not apply for GRPC. +## In Process + +The simplest implementation just uses function calls within Go. +This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. + + # Tools and Apps The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. -See the [tutorial](https://tendermint.com/intro/getting-started/first-abci) for more details. +See the [guide](htutoria://tendermint.com/docs/guides/abci-cli) for more details. Multiple example apps are included: - the `counter` application, which illustrates nonce checking in txs - the `dummy` application, which illustrates a simple key-value merkle tree - the `dummy --persistent` application, which augments the dummy with persistence and validator set changes - - -# Build - -To build the protobuf code: - -``` -make protoc -``` - -See `protoc --help` and [the grpc docs](https://www.grpc.io/docs) for examples and details of other languages - From 1a565b83ec227a7b9f146008c0dc299fc6e7ecc5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Mar 2017 17:17:41 -0400 Subject: [PATCH 217/545] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b94c97c..e6aafa6b 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ This means ABCI applications written in Golang can be compiled with TendermintCo # Tools and Apps The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. -See the [guide](htutoria://tendermint.com/docs/guides/abci-cli) for more details. +See the [guide](https://tendermint.com/docs/guides/abci-cli) for more details. Multiple example apps are included: - the `counter` application, which illustrates nonce checking in txs From af792eac777de757cd496349a5f6b5313738fcbc Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Mar 2017 17:20:31 -0400 Subject: [PATCH 218/545] readme: js-tmsp -> js-abci --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e6aafa6b..df0045d4 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Previously, the ABCI was referred to as TMSP. Other implementations: * [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen -* [js-tmsp](https://github.com/tendermint/js-tmsp) +* [js-abci](https://github.com/tendermint/js-abci) * [jABCI](https://github.com/jTendermint/jabci) for Java # Specification @@ -28,7 +28,7 @@ make protoc ``` See `protoc --help` and [the Protocol Buffers site](https://developers.google.com/protocol-buffers/) for details on compiling for other languages. -Note we also include a [GRPC](https://www.grpc.io/docs) service definition. +Note we also include a [GRPC](http://www.grpc.io/docs) service definition. For the specification as an interface in Go, see the [types/application.go file](https://github.com/tendermint/abci/blob/master/types/application.go). From 31eafe8f8eba6b8817edd74df399f508540da528 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 10 Apr 2017 22:24:54 +0200 Subject: [PATCH 219/545] Update dependencies to newest develop branches --- glide.lock | 18 +++++++++++------- glide.yaml | 5 +++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/glide.lock b/glide.lock index 5e06cad2..d3375535 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 54e49c7cb920a3390f631de12e38226494920bbc5e0c369514df18fe0ab5b693 -updated: 2017-02-14T16:51:55.592202262-05:00 +hash: a0dd8fe3cb061f9e4f3b3b6f0e6e7fb91982d7c3deb422e53e144a3bdcde216a +updated: 2017-04-10T22:08:48.85177017+02:00 imports: - name: github.com/btcsuite/btcd version: d06c0bb181529331be8f8d9350288c420d9e60e4 @@ -19,6 +19,8 @@ imports: version: 5411d3eea5978e6cdc258b30de592b60df6aba96 - name: github.com/mattn/go-isatty version: 281032e84ae07510239465db46bf442aa44b953a +- name: github.com/pkg/errors + version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/stretchr/testify version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: @@ -45,19 +47,21 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-common - version: 339e135776142939d82bc8e699db0bf391fd938d + version: 6af2364fa91ef2f3afc8ba0db33b66d9d3ae006c - name: github.com/tendermint/go-crypto - version: 4b11d62bdb324027ea01554e5767b71174680ba0 + version: 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 +- name: github.com/tendermint/go-data + version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db - version: 72f6dacd22a686cdf7fcd60286503e3aceda77ba + version: eac3f2bc147023957c8bf69432a4e6c4dc5c3f72 - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle - version: 9f20e80cb188d07860caa70196dd7700659ec4a4 + version: 714d4d04557fd068a7c2a1748241ce8428015a96 - name: github.com/tendermint/go-process version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire - version: 3216ec9d47bbdf8d4fc27d22169ea86a6688bc15 + version: f530b7af7a8b06e612c2063bff6ace49060a085e - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: diff --git a/glide.yaml b/glide.yaml index 2b19d872..4d035802 100644 --- a/glide.yaml +++ b/glide.yaml @@ -7,12 +7,17 @@ import: version: develop - package: github.com/tendermint/go-crypto version: develop +- package: github.com/tendermint/go-data + version: develop - package: github.com/tendermint/go-logger + version: develop - package: github.com/tendermint/go-db + version: develop - package: github.com/tendermint/go-merkle version: develop - package: github.com/tendermint/go-process - package: github.com/tendermint/go-wire + version: develop - package: github.com/urfave/cli - package: golang.org/x/net subpackages: From f2851145792559491cf5a3f8fc412a91594deaf2 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Sat, 15 Apr 2017 11:00:47 +0400 Subject: [PATCH 220/545] add Erlang implementation to readme [ci skip] [circleci skip] --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index df0045d4..2efb234d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![CircleCI](https://circleci.com/gh/tendermint/abci.svg?style=svg)](https://circleci.com/gh/tendermint/abci) -Blockchains are a system for multi-master state machine replication. +Blockchains are a system for multi-master state machine replication. **ABCI** is an interface that defines the boundary between the replication engine (the blockchain), and the state machine (the application). By using a socket protocol, we enable a consensus engine running in one process @@ -14,14 +14,15 @@ and the more detailed [application developer's guide](https://tendermint.com/doc Previously, the ABCI was referred to as TMSP. Other implementations: -* [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen -* [js-abci](https://github.com/tendermint/js-abci) -* [jABCI](https://github.com/jTendermint/jabci) for Java +* C++ [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen +* JavaScript [js-abci](https://github.com/tendermint/js-abci) +* Java [jABCI](https://github.com/jTendermint/jabci) +* Erlang [abci_server](https://github.com/KrzysiekJ/abci_server) by Krzysztof Jurewicz # Specification The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers. -To build it, run +To build it, run ``` make protoc @@ -154,7 +155,7 @@ We provide three implementations of the ABCI in Go: ## Socket -ABCI is best implemented as a streaming protocol. +ABCI is best implemented as a streaming protocol. The socket implementation provides for asynchronous, ordered message passing over unix or tcp. Messages are serialized using Protobuf3 and length-prefixed. Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. @@ -164,7 +165,7 @@ For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), th ## GRPC GRPC is an rpc framework native to Protocol Buffers with support in many languages. -Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than +Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than the ordered, asynchronous socket protocol. Note the length-prefixing used in the socket implementation does not apply for GRPC. From 1aa663d907fde7df4c92215db5641f28031faf3a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 18 Apr 2017 23:31:12 -0400 Subject: [PATCH 221/545] update glide --- glide.lock | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/glide.lock b/glide.lock index d3375535..eea3410c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,24 +1,26 @@ hash: a0dd8fe3cb061f9e4f3b3b6f0e6e7fb91982d7c3deb422e53e144a3bdcde216a -updated: 2017-04-10T22:08:48.85177017+02:00 +updated: 2017-04-18T23:28:11.182163777-04:00 imports: - name: github.com/btcsuite/btcd - version: d06c0bb181529331be8f8d9350288c420d9e60e4 + version: b8df516b4b267acf2de46be593a9d948d1d2c420 subpackages: - btcec +- name: github.com/btcsuite/fastsha256 + version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 8ee79997227bf9b34611aee7946ae64735e6fd93 + version: 69b215d01a5606c843240eab4937eab3acee6530 subpackages: - proto - name: github.com/golang/snappy - version: 7db9049039a047d955fe8c19b83c8ff5abd765c7 + version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable - version: 5411d3eea5978e6cdc258b30de592b60df6aba96 + version: 9fdad7c47650b7d2e1da50644c1f4ba7f172f252 - name: github.com/mattn/go-isatty - version: 281032e84ae07510239465db46bf442aa44b953a + version: 56b76bdf51f7708750eac80fa38b952bb9f32639 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/stretchr/testify @@ -27,7 +29,7 @@ imports: - assert - require - name: github.com/syndtr/goleveldb - version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 + version: 3c5717caf1475fd25964109a0fc640bd150fce43 subpackages: - leveldb - leveldb/cache @@ -47,13 +49,13 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-common - version: 6af2364fa91ef2f3afc8ba0db33b66d9d3ae006c + version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto version: 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db - version: eac3f2bc147023957c8bf69432a4e6c4dc5c3f72 + version: 9643f60bc2578693844aacf380a7c32e4c029fee - name: github.com/tendermint/go-logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle @@ -61,15 +63,15 @@ imports: - name: github.com/tendermint/go-process version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire - version: f530b7af7a8b06e612c2063bff6ace49060a085e + version: c1c9a57ab8038448ddea1714c0698f8051e5748c - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term - name: github.com/urfave/cli - version: 347a9884a87374d000eec7e6445a34487c1f4a2b + version: 8ef3805c9de2519805c3f060524b695bba2cd715 - name: golang.org/x/crypto - version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8 + version: 1f22c0103821b9390939b6776727195525381532 subpackages: - nacl/secretbox - openpgp/armor @@ -78,7 +80,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 61557ac0112b576429a0df080e1c2cef5dfbb642 + version: d379faa25cbdc04d653984913a2ceb43b0bc46d7 subpackages: - context - http2 @@ -88,11 +90,11 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: e24f485414aeafb646f6fca458b0bf869c0880a1 + version: 50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e subpackages: - unix - name: google.golang.org/grpc - version: cbcceb2942a489498cf22b2f918536e819d33f0a + version: 7b399ed358736bc5522021cdc7d79a8ee9ac6f98 subpackages: - codes - credentials From 1002a8c5d0a0a4e4855d343fc9402f772c6e4211 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 18 Apr 2017 23:31:30 -0400 Subject: [PATCH 222/545] bump version --- CHANGELOG.md | 6 ++++++ version/version.go | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f5cf42c..b7115552 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.4.1 (April 18, 2017) + +IMPROVEMENTS: + +- Update dependencies + ## 0.4.0 (March 6, 2017) BREAKING CHANGES: diff --git a/version/version.go b/version/version.go index 04695d9b..7b02c593 100644 --- a/version/version.go +++ b/version/version.go @@ -4,6 +4,6 @@ package version const Maj = "0" const Min = "4" -const Fix = "0" +const Fix = "1" -const Version = "0.4.0" // new Query args and response (with proof!) +const Version = "0.4.1" From 03012a05329b3e6fedc8a6a97f34768aac46c714 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 18:24:18 -0400 Subject: [PATCH 223/545] update glide --- glide.lock | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/glide.lock b/glide.lock index eea3410c..f9d043fa 100644 --- a/glide.lock +++ b/glide.lock @@ -1,26 +1,24 @@ hash: a0dd8fe3cb061f9e4f3b3b6f0e6e7fb91982d7c3deb422e53e144a3bdcde216a -updated: 2017-04-18T23:28:11.182163777-04:00 +updated: 2017-04-21T18:24:13.217717865-04:00 imports: - name: github.com/btcsuite/btcd - version: b8df516b4b267acf2de46be593a9d948d1d2c420 + version: 583684b21bfbde9b5fc4403916fd7c807feb0289 subpackages: - btcec -- name: github.com/btcsuite/fastsha256 - version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 69b215d01a5606c843240eab4937eab3acee6530 + version: 8ee79997227bf9b34611aee7946ae64735e6fd93 subpackages: - proto - name: github.com/golang/snappy - version: 553a641470496b2327abcac10b36396bd98e45c9 + version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/mattn/go-colorable - version: 9fdad7c47650b7d2e1da50644c1f4ba7f172f252 + version: d228849504861217f796da67fae4f6e347643f15 - name: github.com/mattn/go-isatty - version: 56b76bdf51f7708750eac80fa38b952bb9f32639 + version: 30a891c33c7cde7b02a981314b4228ec99380cca - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/stretchr/testify @@ -29,7 +27,7 @@ imports: - assert - require - name: github.com/syndtr/goleveldb - version: 3c5717caf1475fd25964109a0fc640bd150fce43 + version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 subpackages: - leveldb - leveldb/cache @@ -51,7 +49,7 @@ imports: - name: github.com/tendermint/go-common version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto - version: 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 + version: 9b95da8fa4187f6799558d89b271dc8ab6485615 - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/go-db @@ -63,15 +61,22 @@ imports: - name: github.com/tendermint/go-process version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire - version: c1c9a57ab8038448ddea1714c0698f8051e5748c + version: 334005c236d19c632fb5f073f9de3b0fab6a522b + subpackages: + - data - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term +- name: github.com/tendermint/tmlibs + version: df250b69416a35a943a6e2a92118667e9ef031d4 + subpackages: + - common + - logger - name: github.com/urfave/cli - version: 8ef3805c9de2519805c3f060524b695bba2cd715 + version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/crypto - version: 1f22c0103821b9390939b6776727195525381532 + version: 7c6cc321c680f03b9ef0764448e780704f486b51 subpackages: - nacl/secretbox - openpgp/armor @@ -80,7 +85,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: d379faa25cbdc04d653984913a2ceb43b0bc46d7 + version: 61557ac0112b576429a0df080e1c2cef5dfbb642 subpackages: - context - http2 @@ -90,11 +95,11 @@ imports: - lex/httplex - trace - name: golang.org/x/sys - version: 50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e + version: d75a52659825e75fff6158388dddc6a5b04f9ba5 subpackages: - unix - name: google.golang.org/grpc - version: 7b399ed358736bc5522021cdc7d79a8ee9ac6f98 + version: cbcceb2942a489498cf22b2f918536e819d33f0a subpackages: - codes - credentials From 28d042fdae2c2e7d32a8d7bc3dba459d368dee69 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 18:25:13 -0400 Subject: [PATCH 224/545] use tmlibs --- client/client.go | 2 +- client/grpc_client.go | 2 +- client/local_client.go | 2 +- client/log.go | 2 +- client/socket_client.go | 2 +- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- example/block_aware/block_aware_app.go | 2 +- example/counter/counter.go | 2 +- example/dummy/dummy.go | 2 +- example/dummy/dummy_test.go | 2 +- example/dummy/log.go | 2 +- example/dummy/persistent_dummy.go | 4 ++-- example/example_test.go | 2 +- glide.lock | 8 ++++---- glide.yaml | 8 ++++---- server/grpc_server.go | 2 +- server/log.go | 2 +- server/server.go | 2 +- server/socket_server.go | 2 +- tests/benchmarks/parallel/parallel.go | 2 +- tests/benchmarks/simple/simple.go | 2 +- tests/test_app/app.go | 2 +- 23 files changed, 30 insertions(+), 30 deletions(-) diff --git a/client/client.go b/client/client.go index 38fff486..a54978fc 100644 --- a/client/client.go +++ b/client/client.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) type Client interface { diff --git a/client/grpc_client.go b/client/grpc_client.go index 7cca5079..42393669 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -10,7 +10,7 @@ import ( grpc "google.golang.org/grpc" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) // A stripped copy of the remoteClient that makes diff --git a/client/local_client.go b/client/local_client.go index 1150db4a..4bdcffad 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -4,7 +4,7 @@ import ( "sync" types "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) type localClient struct { diff --git a/client/log.go b/client/log.go index 944b05ba..146bf127 100644 --- a/client/log.go +++ b/client/log.go @@ -1,7 +1,7 @@ package abcicli import ( - "github.com/tendermint/go-logger" + "github.com/tendermint/tmlibs/logger" ) var log = logger.New("module", "abcicli") diff --git a/client/socket_client.go b/client/socket_client.go index 5aeeac7a..ebcfb44b 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -11,7 +11,7 @@ import ( "time" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) const ( diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 6858fc43..e7b777a8 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index b48a15c7..a1cc68ae 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index 454c3560..e1afee96 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/example/counter/counter.go b/example/counter/counter.go index c40541ed..c4e4e267 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) type CounterApplication struct { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index f88b1b20..f384cc98 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,7 +4,7 @@ import ( "strings" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/go-merkle" ) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 879cf3c4..aa040948 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -10,7 +10,7 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/go-crypto" "github.com/tendermint/go-merkle" ) diff --git a/example/dummy/log.go b/example/dummy/log.go index 8571fa01..5607ca55 100644 --- a/example/dummy/log.go +++ b/example/dummy/log.go @@ -1,7 +1,7 @@ package dummy import ( - "github.com/tendermint/go-logger" + "github.com/tendermint/tmlibs/logger" ) var log = logger.New("module", "dummy") diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 48eff420..258cb301 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" - dbm "github.com/tendermint/go-db" + cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/go-merkle" "github.com/tendermint/go-wire" ) diff --git a/example/example_test.go b/example/example_test.go index 034331d6..e6edef36 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -16,7 +16,7 @@ import ( "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func TestDummy(t *testing.T) { diff --git a/glide.lock b/glide.lock index f9d043fa..cd453aa0 100644 --- a/glide.lock +++ b/glide.lock @@ -46,19 +46,19 @@ imports: subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/go-common +- name: github.com/tendermint/tmlibs/common version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto version: 9b95da8fa4187f6799558d89b271dc8ab6485615 - name: github.com/tendermint/go-data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 -- name: github.com/tendermint/go-db +- name: github.com/tendermint/tmlibs/db version: 9643f60bc2578693844aacf380a7c32e4c029fee -- name: github.com/tendermint/go-logger +- name: github.com/tendermint/tmlibs/logger version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-merkle version: 714d4d04557fd068a7c2a1748241ce8428015a96 -- name: github.com/tendermint/go-process +- name: github.com/tendermint/tmlibs/process version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire version: 334005c236d19c632fb5f073f9de3b0fab6a522b diff --git a/glide.yaml b/glide.yaml index 4d035802..542d2df0 100644 --- a/glide.yaml +++ b/glide.yaml @@ -3,19 +3,19 @@ import: - package: github.com/golang/protobuf subpackages: - proto -- package: github.com/tendermint/go-common +- package: github.com/tendermint/tmlibs/common version: develop - package: github.com/tendermint/go-crypto version: develop - package: github.com/tendermint/go-data version: develop -- package: github.com/tendermint/go-logger +- package: github.com/tendermint/tmlibs/logger version: develop -- package: github.com/tendermint/go-db +- package: github.com/tendermint/tmlibs/db version: develop - package: github.com/tendermint/go-merkle version: develop -- package: github.com/tendermint/go-process +- package: github.com/tendermint/tmlibs/process - package: github.com/tendermint/go-wire version: develop - package: github.com/urfave/cli diff --git a/server/grpc_server.go b/server/grpc_server.go index 944d4e42..003a7661 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -7,7 +7,7 @@ import ( "google.golang.org/grpc" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) // var maxNumberConnections = 2 diff --git a/server/log.go b/server/log.go index 4b313d25..887c9ed6 100644 --- a/server/log.go +++ b/server/log.go @@ -1,7 +1,7 @@ package server import ( - "github.com/tendermint/go-logger" + "github.com/tendermint/tmlibs/logger" ) var log = logger.New("module", "abci-server") diff --git a/server/server.go b/server/server.go index eb71b132..d18df820 100644 --- a/server/server.go +++ b/server/server.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func NewServer(protoAddr, transport string, app types.Application) (cmn.Service, error) { diff --git a/server/socket_server.go b/server/socket_server.go index bc1980e2..9933829c 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -9,7 +9,7 @@ import ( "sync" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) // var maxNumberConnections = 2 diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index f01fba4c..cc68cead 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -6,7 +6,7 @@ import ( "log" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 498aac34..ef5bab86 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -8,7 +8,7 @@ import ( "reflect" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 87b74ead..7cff5710 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - "github.com/tendermint/go-process" + "github.com/tendermint/tmlibs/process" ) func startApp(abciApp string) *process.Process { From dd303dc119b130a81391324a5782368279ad9817 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 18:25:30 -0400 Subject: [PATCH 225/545] go-data -> go-wire/data --- glide.lock | 2 +- glide.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index cd453aa0..7a39a3b4 100644 --- a/glide.lock +++ b/glide.lock @@ -50,7 +50,7 @@ imports: version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto version: 9b95da8fa4187f6799558d89b271dc8ab6485615 -- name: github.com/tendermint/go-data +- name: github.com/tendermint/go-wire/data version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - name: github.com/tendermint/tmlibs/db version: 9643f60bc2578693844aacf380a7c32e4c029fee diff --git a/glide.yaml b/glide.yaml index 542d2df0..cf909175 100644 --- a/glide.yaml +++ b/glide.yaml @@ -7,7 +7,7 @@ import: version: develop - package: github.com/tendermint/go-crypto version: develop -- package: github.com/tendermint/go-data +- package: github.com/tendermint/go-wire/data version: develop - package: github.com/tendermint/tmlibs/logger version: develop From 078e617d1c107e39b756ef278e4c867d6befdcd9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 18:28:49 -0400 Subject: [PATCH 226/545] go-merkle -> merkleeyes/iavl and tmlibs/merkle --- example/dummy/dummy.go | 5 +++-- example/dummy/dummy_test.go | 8 ++++---- example/dummy/persistent_dummy.go | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index f384cc98..4485deac 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,8 +4,9 @@ import ( "strings" "github.com/tendermint/abci/types" + "github.com/tendermint/merkleeyes/iavl" cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/go-merkle" + "github.com/tendermint/tmlibs/merkle" ) type DummyApplication struct { @@ -15,7 +16,7 @@ type DummyApplication struct { } func NewDummyApplication() *DummyApplication { - state := merkle.NewIAVLTree(0, nil) + state := iavl.NewIAVLTree(0, nil) return &DummyApplication{state: state} } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index aa040948..57aac4ef 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -10,9 +10,9 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/go-crypto" - "github.com/tendermint/go-merkle" + "github.com/tendermint/merkleeyes/iavl" + cmn "github.com/tendermint/tmlibs/common" ) func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { @@ -38,7 +38,7 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string }) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := merkle.ReadProof(resQuery.Proof) + proof, err := iavl.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 } @@ -302,7 +302,7 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) 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) + proof, err := iavl.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 258cb301..84793bc9 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -7,10 +7,10 @@ import ( "strings" "github.com/tendermint/abci/types" + "github.com/tendermint/go-wire" + "github.com/tendermint/merkleeyes/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" - "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" ) const ( @@ -35,7 +35,7 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { db := dbm.NewDB("dummy", "leveldb", dbDir) lastBlock := LoadLastBlock(db) - stateTree := merkle.NewIAVLTree(0, db) + stateTree := iavl.NewIAVLTree(0, db) stateTree.Load(lastBlock.AppHash) log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) From be61e273cebeb64866a83c578f92b22cf2169cdd Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 18:32:46 -0400 Subject: [PATCH 227/545] update glide --- glide.lock | 33 ++++++++++++++------------------- glide.yaml | 25 +++++++++++++------------ 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/glide.lock b/glide.lock index 7a39a3b4..8aa89aba 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: a0dd8fe3cb061f9e4f3b3b6f0e6e7fb91982d7c3deb422e53e144a3bdcde216a -updated: 2017-04-21T18:24:13.217717865-04:00 +hash: 13c7dac029851e5177bf78ff26ce6ccd047360111795a9a65af4ba6a0b87f4b3 +updated: 2017-04-21T18:31:57.13123527-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -21,11 +21,6 @@ imports: version: 30a891c33c7cde7b02a981314b4228ec99380cca - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert - - require - name: github.com/syndtr/goleveldb version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 subpackages: @@ -46,20 +41,8 @@ imports: subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/tmlibs/common - version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto version: 9b95da8fa4187f6799558d89b271dc8ab6485615 -- name: github.com/tendermint/go-wire/data - version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 -- name: github.com/tendermint/tmlibs/db - version: 9643f60bc2578693844aacf380a7c32e4c029fee -- name: github.com/tendermint/tmlibs/logger - version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 -- name: github.com/tendermint/go-merkle - version: 714d4d04557fd068a7c2a1748241ce8428015a96 -- name: github.com/tendermint/tmlibs/process - version: b27edfd189b1a01a0b099f7e9f8263589cf04909 - name: github.com/tendermint/go-wire version: 334005c236d19c632fb5f073f9de3b0fab6a522b subpackages: @@ -68,11 +51,18 @@ imports: version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term +- name: github.com/tendermint/merkleeyes + version: 41fe51f4a6d3f1abc45fd4684e1351e084860ca4 + subpackages: + - iavl - name: github.com/tendermint/tmlibs version: df250b69416a35a943a6e2a92118667e9ef031d4 subpackages: - common + - db - logger + - merkle + - process - name: github.com/urfave/cli version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/crypto @@ -120,3 +110,8 @@ testImports: version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: - difflib +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require diff --git a/glide.yaml b/glide.yaml index cf909175..2876b0e5 100644 --- a/glide.yaml +++ b/glide.yaml @@ -3,27 +3,28 @@ import: - package: github.com/golang/protobuf subpackages: - proto -- package: github.com/tendermint/tmlibs/common - version: develop - package: github.com/tendermint/go-crypto version: develop -- package: github.com/tendermint/go-wire/data - version: develop -- package: github.com/tendermint/tmlibs/logger - version: develop -- package: github.com/tendermint/tmlibs/db - version: develop -- package: github.com/tendermint/go-merkle - version: develop -- package: github.com/tendermint/tmlibs/process - package: github.com/tendermint/go-wire version: develop +- package: github.com/tendermint/merkleeyes + version: develop + subpackages: + - iavl +- package: github.com/tendermint/tmlibs + version: develop + subpackages: + - common + - db + - logger + - merkle + - process - package: github.com/urfave/cli - package: golang.org/x/net subpackages: - context - package: google.golang.org/grpc +testImport: - package: github.com/stretchr/testify - version: ^1.1.4 subpackages: - require From c709d3cc857929a8dd36a90da3640122d7e75770 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 18:39:18 -0400 Subject: [PATCH 228/545] update merkleeyes --- glide.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 8aa89aba..614ce5a1 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 13c7dac029851e5177bf78ff26ce6ccd047360111795a9a65af4ba6a0b87f4b3 -updated: 2017-04-21T18:31:57.13123527-04:00 +updated: 2017-04-21T18:38:50.4243289-04:00 imports: - name: github.com/btcsuite/btcd version: 583684b21bfbde9b5fc4403916fd7c807feb0289 @@ -52,7 +52,7 @@ imports: subpackages: - term - name: github.com/tendermint/merkleeyes - version: 41fe51f4a6d3f1abc45fd4684e1351e084860ca4 + version: 6fd69aa0871a4e685a5570aa7ab3d12e4068a722 subpackages: - iavl - name: github.com/tendermint/tmlibs From 8339dc3b1a389ced232573c46e106de2fce9f112 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 27 Apr 2017 19:18:53 -0400 Subject: [PATCH 229/545] types: Result and Validator use data.Bytes --- types/result.go | 4 +++- types/validators.go | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/types/result.go b/types/result.go index af89058e..d7e231d8 100644 --- a/types/result.go +++ b/types/result.go @@ -2,12 +2,14 @@ package types import ( "fmt" + + "github.com/tendermint/go-wire/data" ) // CONTRACT: a zero Result is OK. type Result struct { Code CodeType - Data []byte + Data data.Bytes Log string // Can be non-deterministic } diff --git a/types/validators.go b/types/validators.go index 185355d1..a83c6d40 100644 --- a/types/validators.go +++ b/types/validators.go @@ -2,8 +2,9 @@ package types import ( "bytes" + "encoding/json" - "github.com/tendermint/go-wire" + "github.com/tendermint/go-wire/data" ) // validators implements sort @@ -28,8 +29,8 @@ func (v Validators) Swap(i, j int) { //------------------------------------- type validatorPretty struct { - PubKey []byte `json:"pub_key"` - Power uint64 `json:"power"` + PubKey data.Bytes `json:"pub_key"` + Power uint64 `json:"power"` } func ValidatorsString(vs Validators) string { @@ -37,5 +38,6 @@ func ValidatorsString(vs Validators) string { for i, v := range vs { s[i] = validatorPretty{v.PubKey, v.Power} } - return string(wire.JSONBytes(s)) + b, _ := json.Marshal(s) + return string(b) } From 8d8e35ae537538c9cf6808be3ca9dd7dab81b7f6 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 27 Apr 2017 19:53:22 -0400 Subject: [PATCH 230/545] types: methods convert pb types to use data.Bytes --- types/result.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/types/result.go b/types/result.go index d7e231d8..c7f2d565 100644 --- a/types/result.go +++ b/types/result.go @@ -8,9 +8,9 @@ import ( // CONTRACT: a zero Result is OK. type Result struct { - Code CodeType - Data data.Bytes - Log string // Can be non-deterministic + Code CodeType `json:"code"` + Data data.Bytes `json:"data"` + Log string `json:"log"` // Can be non-deterministic } func NewResult(code CodeType, data []byte, log string) Result { @@ -86,3 +86,47 @@ func NewError(code CodeType, log string) Result { Log: log, } } + +//---------------------------------------- +// Convenience methods for turning the +// pb type into one using data.Bytes + +// Convert ResponseCheckTx to standard Result +func (r *ResponseCheckTx) Result() Result { + return Result{ + Code: r.Code, + Data: r.Data, + Log: r.Log, + } +} + +// Convert ResponseDeliverTx to standard Result +func (r *ResponseDeliverTx) Result() Result { + return Result{ + Code: r.Code, + Data: r.Data, + Log: r.Log, + } +} + +type ResultQuery struct { + Code CodeType `json:"code"` + Index int64 `json:"index"` + Key data.Bytes `json:"key"` + Value data.Bytes `json:"value"` + Proof data.Bytes `json:"proof"` + Height uint64 `json:"height"` + Log string `json:"log"` +} + +func (r *ResponseQuery) Result() *ResultQuery { + return &ResultQuery{ + Code: r.Code, + Index: r.Index, + Key: r.Key, + Value: r.Value, + Proof: r.Proof, + Height: r.Height, + Log: r.Log, + } +} From 986bdd00a585bbbcd41cfb8fb3ef6dbdca55baf9 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 28 Apr 2017 00:37:18 +0400 Subject: [PATCH 231/545] new logging --- .gitignore | 4 +- client/grpc_client.go | 4 +- client/local_client.go | 2 +- client/log.go | 7 --- client/socket_client.go | 8 +-- cmd/abci-cli/abci-cli.go | 11 ++-- cmd/counter/main.go | 8 ++- cmd/dummy/main.go | 10 +++- example/block_aware/block_aware_app.go | 8 ++- example/block_aware/block_aware_test.go | 12 +++-- example/dummy/dummy_test.go | 11 +++- example/dummy/log.go | 7 --- example/dummy/persistent_dummy.go | 30 +++++++---- example/example_test.go | 19 ++++--- glide.lock | 71 +++++++++++++++---------- glide.yaml | 5 +- server/log.go | 7 --- server/socket_server.go | 14 ++--- tests/test.sh | 0 tests/test_app/app.go | 5 +- 20 files changed, 141 insertions(+), 102 deletions(-) delete mode 100644 client/log.go delete mode 100644 example/dummy/log.go delete mode 100644 server/log.go mode change 100644 => 100755 tests/test.sh diff --git a/.gitignore b/.gitignore index 920af762..62f28681 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -*.swp -*.swo -*.pyc vendor +.glide diff --git a/client/grpc_client.go b/client/grpc_client.go index 42393669..25783101 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -51,7 +51,7 @@ RETRY_LOOP: if cli.mustConnect { return err } - log.Warn(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) + cli.Logger.Error(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -93,7 +93,7 @@ func (cli *grpcClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error())) + cli.Logger.Error(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error())) cli.Stop() } diff --git a/client/local_client.go b/client/local_client.go index 4bdcffad..37f76abb 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -22,7 +22,7 @@ func NewLocalClient(mtx *sync.Mutex, app types.Application) *localClient { mtx: mtx, Application: app, } - cli.BaseService = *cmn.NewBaseService(log, "localClient", cli) + cli.BaseService = *cmn.NewBaseService(nil, "localClient", cli) return cli } diff --git a/client/log.go b/client/log.go deleted file mode 100644 index 146bf127..00000000 --- a/client/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package abcicli - -import ( - "github.com/tendermint/tmlibs/logger" -) - -var log = logger.New("module", "abcicli") diff --git a/client/socket_client.go b/client/socket_client.go index ebcfb44b..76f150c0 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -70,7 +70,7 @@ RETRY_LOOP: if cli.mustConnect { return err } - log.Warn(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) + cli.Logger.Error(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -107,7 +107,7 @@ func (cli *socketClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(fmt.Sprintf("Stopping abci.socketClient for error: %v", err.Error())) + cli.Logger.Error(fmt.Sprintf("Stopping abci.socketClient for error: %v", err.Error())) cli.Stop() } @@ -147,7 +147,7 @@ func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { cli.StopForError(fmt.Errorf("Error writing msg: %v", err)) return } - // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) + // cli.Logger.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) if _, ok := reqres.Request.Value.(*types.Request_Flush); ok { err = w.Flush() if err != nil { @@ -175,7 +175,7 @@ func (cli *socketClient) recvResponseRoutine(conn net.Conn) { cli.StopForError(errors.New(r.Exception.Error)) return default: - // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) + // cli.Logger.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) err := cli.didRecvResponse(res) if err != nil { cli.StopForError(err) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index accae9d1..02fa32f0 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -6,13 +6,14 @@ import ( "errors" "fmt" "io" - "log" + stdlog "log" "os" "strings" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" "github.com/tendermint/abci/version" + "github.com/tendermint/tmlibs/log" "github.com/urfave/cli" ) @@ -129,7 +130,7 @@ func main() { app.Before = before err := app.Run(os.Args) if err != nil { - log.Fatal(err.Error()) + stdlog.Fatal(err.Error()) } } @@ -139,8 +140,10 @@ func before(c *cli.Context) error { var err error client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) if err != nil { - log.Fatal(err.Error()) + stdlog.Fatal(err.Error()) } + logger := log.NewTmLogger(os.Stdout) + client.SetLogger(log.With(logger, "module", "abci-client")) } return nil } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index e7b777a8..19fc0b8c 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -2,11 +2,13 @@ package main import ( "flag" - "log" + stdlog "log" + "os" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func main() { @@ -20,8 +22,10 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - log.Fatal(err.Error()) + stdlog.Fatal(err.Error()) } + logger := log.NewTmLogger(os.Stdout) + srv.SetLogger(log.With(logger, "module", "abci-server")) // Wait forever cmn.TrapSignal(func() { diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index a1cc68ae..f462a34e 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -2,12 +2,14 @@ package main import ( "flag" - "log" + stdlog "log" + "os" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func main() { @@ -17,19 +19,23 @@ func main() { persistencePtr := flag.String("persist", "", "directory to use for a database") flag.Parse() + logger := log.NewTmLogger(os.Stdout) + // Create the application - in memory or persisted to disk var app types.Application if *persistencePtr == "" { app = dummy.NewDummyApplication() } else { app = dummy.NewPersistentDummyApplication(*persistencePtr) + app.(*dummy.PersistentDummyApplication).SetLogger(log.With(logger, "module", "dummy")) } // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - log.Fatal(err.Error()) + stdlog.Fatal(err.Error()) } + srv.SetLogger(log.With(logger, "module", "abci-server")) // Wait forever cmn.TrapSignal(func() { diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index e1afee96..c77052b3 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -2,11 +2,13 @@ package main import ( "flag" - "log" + stdlog "log" + "os" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func main() { @@ -18,8 +20,10 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) if err != nil { - log.Fatal(err.Error()) + stdlog.Fatal(err.Error()) } + logger := log.NewTmLogger(os.Stdout) + srv.SetLogger(log.With(logger, "module", "abci-server")) // Wait forever cmn.TrapSignal(func() { diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 2ce6aacf..c251de6a 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -1,33 +1,35 @@ package main import ( - "fmt" - "log" + "os" "strconv" "strings" "testing" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + "github.com/tendermint/tmlibs/log" ) func TestChainAware(t *testing.T) { - app := NewChainAwareApplication() + logger := log.NewTmLogger(os.Stdout) // Start the listener srv, err := server.NewServer("unix://test.sock", "socket", app) if err != nil { t.Fatal(err) } + srv.SetLogger(log.With(logger, "module", "abci-server")) defer srv.Stop() // Connect to the socket client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { - log.Fatal(fmt.Sprintf("Error starting socket client: %v", err.Error())) + t.Fatalf("Error starting socket client: %v", err.Error()) } + client.SetLogger(log.With(logger, "module", "abci-client")) client.Start() defer client.Stop() diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 57aac4ef..fe569306 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -3,6 +3,7 @@ package dummy import ( "bytes" "io/ioutil" + "os" "sort" "testing" @@ -10,9 +11,10 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - "github.com/tendermint/go-crypto" + crypto "github.com/tendermint/go-crypto" "github.com/tendermint/merkleeyes/iavl" cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { @@ -211,10 +213,13 @@ 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) + logger := log.NewTmLogger(os.Stdout) + server, err := server.NewSocketServer(socket, app) if err != nil { return nil, nil, err } + server.SetLogger(log.With(logger, "module", "abci-server")) // Connect to the socket client, err := abcicli.NewSocketClient(socket, false) @@ -222,6 +227,7 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, server.Stop() return nil, nil, err } + client.SetLogger(log.With(logger, "module", "abci-client")) client.Start() return client, server, err @@ -230,18 +236,21 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { // Start the listener socket := cmn.Fmt("unix://%s.sock", name) + logger := log.NewTmLogger(os.Stdout) gapp := types.NewGRPCApplication(app) server, err := server.NewGRPCServer(socket, gapp) if err != nil { return nil, nil, err } + server.SetLogger(log.With(logger, "module", "abci-server")) client, err := abcicli.NewGRPCClient(socket, true) if err != nil { server.Stop() return nil, nil, err } + client.SetLogger(log.With(logger, "module", "abci-client")) return client, server, err } diff --git a/example/dummy/log.go b/example/dummy/log.go deleted file mode 100644 index 5607ca55..00000000 --- a/example/dummy/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package dummy - -import ( - "github.com/tendermint/tmlibs/logger" -) - -var log = logger.New("module", "dummy") diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 84793bc9..fb59a272 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -6,11 +6,13 @@ import ( "strconv" "strings" + "github.com/pkg/errors" "github.com/tendermint/abci/types" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" "github.com/tendermint/merkleeyes/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" ) const ( @@ -29,6 +31,8 @@ type PersistentDummyApplication struct { // validator set changes []*types.Validator + + logger log.Logger } func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { @@ -38,14 +42,19 @@ func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { stateTree := iavl.NewIAVLTree(0, db) stateTree.Load(lastBlock.AppHash) - log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) + // log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) return &PersistentDummyApplication{ - app: &DummyApplication{state: stateTree}, - db: db, + app: &DummyApplication{state: stateTree}, + db: db, + logger: log.NewNopLogger(), } } +func (app *PersistentDummyApplication) SetLogger(l log.Logger) { + app.logger = l +} + func (app *PersistentDummyApplication) Info() (resInfo types.ResponseInfo) { resInfo = app.app.Info() lastBlock := LoadLastBlock(app.db) @@ -79,13 +88,16 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { func (app *PersistentDummyApplication) Commit() types.Result { // Save appHash := app.app.state.Save() - log.Info("Saved state", "root", appHash) + app.logger.Info("Saved state", "root", appHash) lastBlock := LastBlockInfo{ Height: app.blockHeader.Height, AppHash: appHash, // this hash will be in the next block header } + + app.logger.Info("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) SaveLastBlock(app.db, lastBlock) + return types.NewResultOK(appHash, "") } @@ -98,7 +110,7 @@ func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) for _, v := range validators { r := app.updateValidator(v) if r.IsErr() { - log.Error("Error updating validators", "r", r) + app.logger.Error("Error updating validators", "r", r) } } } @@ -134,8 +146,7 @@ func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { r, n, err := bytes.NewReader(buf), new(int), new(error) wire.ReadBinaryPtr(&lastBlock, r, 0, n, err) if *err != nil { - // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - log.Crit(cmn.Fmt("Data has been corrupted or its spec has changed: %v\n", *err)) + cmn.PanicCrisis(errors.Wrap(*err, "cannot load last block (data has been corrupted or its spec has changed)")) } // TODO: ensure that buf is completely read. } @@ -144,12 +155,11 @@ func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { } func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { - log.Notice("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) buf, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(lastBlock, buf, n, err) if *err != nil { // TODO - cmn.PanicCrisis(*err) + cmn.PanicCrisis(errors.Wrap(*err, "cannot save last block")) } db.Set(lastBlockKey, buf.Bytes()) } diff --git a/example/example_test.go b/example/example_test.go index e6edef36..d71a44e6 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -2,8 +2,9 @@ package example import ( "fmt" - "log" + stdlog "log" "net" + "os" "reflect" "testing" "time" @@ -12,11 +13,12 @@ import ( "golang.org/x/net/context" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func TestDummy(t *testing.T) { @@ -37,19 +39,22 @@ func TestGRPC(t *testing.T) { func testStream(t *testing.T, app types.Application) { numDeliverTxs := 200000 + logger := log.NewTmLogger(os.Stdout) // Start the listener server, err := server.NewSocketServer("unix://test.sock", app) if err != nil { - log.Fatal(cmn.Fmt("Error starting socket server: %v", err.Error())) + stdlog.Fatal(cmn.Fmt("Error starting socket server: %v", err.Error())) } + server.SetLogger(log.With(logger, "module", "abci-server")) defer server.Stop() // Connect to the socket client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { - log.Fatal(cmn.Fmt("Error starting socket client: %v", err.Error())) + stdlog.Fatal(cmn.Fmt("Error starting socket client: %v", err.Error())) } + client.SetLogger(log.With(logger, "module", "abci-client")) client.Start() defer client.Stop() @@ -110,18 +115,20 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { func testGRPCSync(t *testing.T, app *types.GRPCApplication) { numDeliverTxs := 2000 + logger := log.NewTmLogger(os.Stdout) // Start the listener server, err := server.NewGRPCServer("unix://test.sock", app) if err != nil { - log.Fatal(cmn.Fmt("Error starting GRPC server: %v", err.Error())) + stdlog.Fatal(cmn.Fmt("Error starting GRPC server: %v", err.Error())) } + server.SetLogger(log.With(logger, "module", "abci-server")) defer server.Stop() // Connect to the socket conn, err := grpc.Dial("unix://test.sock", grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) if err != nil { - log.Fatal(cmn.Fmt("Error dialing GRPC server: %v", err.Error())) + stdlog.Fatal(cmn.Fmt("Error dialing GRPC server: %v", err.Error())) } defer conn.Close() diff --git a/glide.lock b/glide.lock index 614ce5a1..9b574b52 100644 --- a/glide.lock +++ b/glide.lock @@ -1,28 +1,35 @@ -hash: 13c7dac029851e5177bf78ff26ce6ccd047360111795a9a65af4ba6a0b87f4b3 -updated: 2017-04-21T18:38:50.4243289-04:00 +hash: 3918a6fe902116fbac5ac474580edf246bee125df6e63e3bd8378f068fa8f819 +updated: 2017-05-01T08:59:45.550273823Z imports: - name: github.com/btcsuite/btcd - version: 583684b21bfbde9b5fc4403916fd7c807feb0289 + version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec +- name: github.com/go-kit/kit + version: 8a2988aa81f699fc1e647c3c9dddce0113ef1bfb + subpackages: + - log + - log/level + - log/term +- name: github.com/go-logfmt/logfmt + version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 8ee79997227bf9b34611aee7946ae64735e6fd93 + version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 subpackages: - proto + - ptypes/any - name: github.com/golang/snappy - version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 + version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/mattn/go-colorable - version: d228849504861217f796da67fae4f6e347643f15 -- name: github.com/mattn/go-isatty - version: 30a891c33c7cde7b02a981314b4228ec99380cca +- name: github.com/kr/logfmt + version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: ff09b135c25aae272398c51a07235b90a75aa4f0 - name: github.com/syndtr/goleveldb - version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65 + version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: - leveldb - leveldb/cache @@ -42,31 +49,27 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 9b95da8fa4187f6799558d89b271dc8ab6485615 + version: 197a2b270fd94ee03824b158e738fce62862d0b8 - name: github.com/tendermint/go-wire - version: 334005c236d19c632fb5f073f9de3b0fab6a522b + version: b53add0b622662731985485f3a19be7f684660b8 subpackages: - data -- name: github.com/tendermint/log15 - version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 - subpackages: - - term - name: github.com/tendermint/merkleeyes - version: 6fd69aa0871a4e685a5570aa7ab3d12e4068a722 + version: d0aa363fd4e015e509038c3a0ec493bc62ee0b8a subpackages: - iavl - name: github.com/tendermint/tmlibs - version: df250b69416a35a943a6e2a92118667e9ef031d4 + version: dc50d7d3c19771377fb4aa6e703354205050053a subpackages: - common - db - - logger + - log - merkle - process - name: github.com/urfave/cli - version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 + version: ab403a54a148f2d857920810291539e1f817ee7b - name: golang.org/x/crypto - version: 7c6cc321c680f03b9ef0764448e780704f486b51 + version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: - nacl/secretbox - openpgp/armor @@ -75,7 +78,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 61557ac0112b576429a0df080e1c2cef5dfbb642 + version: da118f7b8e5954f39d0d2130ab35d4bf0e3cb344 subpackages: - context - http2 @@ -84,26 +87,36 @@ imports: - internal/timeseries - lex/httplex - trace -- name: golang.org/x/sys - version: d75a52659825e75fff6158388dddc6a5b04f9ba5 +- name: golang.org/x/text + version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 subpackages: - - unix + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm +- name: google.golang.org/genproto + version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + subpackages: + - googleapis/rpc/status - name: google.golang.org/grpc - version: cbcceb2942a489498cf22b2f918536e819d33f0a + version: 0eb507a2ca07f13baf499f89d66cc566bf644643 subpackages: - codes - credentials + - grpclb/grpc_lb_v1 - grpclog - internal + - keepalive - metadata - naming - peer - stats + - status - tap - transport testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -111,7 +124,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 4d4bfba8f1d1027c4fdbe371823030df51419987 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index 2876b0e5..95fd9ce3 100644 --- a/glide.yaml +++ b/glide.yaml @@ -3,6 +3,7 @@ import: - package: github.com/golang/protobuf subpackages: - proto +- package: github.com/pkg/errors - package: github.com/tendermint/go-crypto version: develop - package: github.com/tendermint/go-wire @@ -12,11 +13,11 @@ import: subpackages: - iavl - package: github.com/tendermint/tmlibs - version: develop + version: feature/new-logging subpackages: - common - db - - logger + - log - merkle - process - package: github.com/urfave/cli diff --git a/server/log.go b/server/log.go deleted file mode 100644 index 887c9ed6..00000000 --- a/server/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package server - -import ( - "github.com/tendermint/tmlibs/logger" -) - -var log = logger.New("module", "abci-server") diff --git a/server/socket_server.go b/server/socket_server.go index 9933829c..3d83c3f7 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -94,15 +94,15 @@ func (s *SocketServer) acceptConnectionsRoutine() { // semaphore <- struct{}{} // Accept a connection - log.Notice("Waiting for new connection...") + s.Logger.Info("Waiting for new connection...") conn, err := s.listener.Accept() if err != nil { if !s.IsRunning() { return // Ignore error from listener closing. } - log.Crit("Failed to accept connection: " + err.Error()) + s.Logger.Error("Failed to accept connection: " + err.Error()) } else { - log.Notice("Accepted a new connection") + s.Logger.Info("Accepted a new connection") } connID := s.addConn(conn) @@ -119,18 +119,18 @@ func (s *SocketServer) acceptConnectionsRoutine() { // Wait until signal to close connection errClose := <-closeConn if err == io.EOF { - log.Warn("Connection was closed by client") + s.Logger.Error("Connection was closed by client") } else if errClose != nil { - log.Warn("Connection error", "error", errClose) + s.Logger.Error("Connection error", "error", errClose) } else { // never happens - log.Warn("Connection was closed.") + s.Logger.Error("Connection was closed.") } // Close the connection err := s.rmConn(connID, conn) if err != nil { - log.Warn("Error in closing connection", "error", err) + s.Logger.Error("Error in closing connection", "error", err) } // <-semaphore diff --git a/tests/test.sh b/tests/test.sh old mode 100644 new mode 100755 diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 7cff5710..879a7400 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -6,8 +6,9 @@ import ( "os" "time" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" + "github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/process" ) @@ -37,6 +38,8 @@ func startClient(abciType string) abcicli.Client { if err != nil { panic("connecting to abci_app: " + err.Error()) } + logger := log.NewTmLogger(os.Stdout) + client.SetLogger(log.With(logger, "module", "abcicli")) return client } From 9a6d19028277f84b1c8cf57cac1e50180a397f3f Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 1 May 2017 16:43:52 +0400 Subject: [PATCH 232/545] remove stdlog --- cmd/abci-cli/abci-cli.go | 13 +++++++++---- cmd/counter/main.go | 7 ++++--- cmd/dummy/main.go | 4 ++-- example/block_aware/block_aware_app.go | 7 ++++--- example/example_test.go | 9 ++++----- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 02fa32f0..8a1ee2d1 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - stdlog "log" "os" "strings" @@ -37,6 +36,8 @@ type queryResponse struct { // client is a global variable so it can be reused by the console var client abcicli.Client +var logger log.Logger + func main() { //workaround for the cli library (https://github.com/urfave/cli/issues/565) @@ -130,19 +131,23 @@ func main() { app.Before = before err := app.Run(os.Args) if err != nil { - stdlog.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) } } func before(c *cli.Context) error { + if logger == nil { + logger = log.NewTmLogger(os.Stdout) + } if client == nil { var err error client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) if err != nil { - stdlog.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) } - logger := log.NewTmLogger(os.Stdout) client.SetLogger(log.With(logger, "module", "abci-client")) } return nil diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 19fc0b8c..8fd5b4cc 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -2,7 +2,6 @@ package main import ( "flag" - stdlog "log" "os" "github.com/tendermint/abci/example/counter" @@ -19,12 +18,14 @@ func main() { flag.Parse() app := counter.NewCounterApplication(*serialPtr) + logger := log.NewTmLogger(os.Stdout) + // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - stdlog.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) } - logger := log.NewTmLogger(os.Stdout) srv.SetLogger(log.With(logger, "module", "abci-server")) // Wait forever diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index f462a34e..92249a9b 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -2,7 +2,6 @@ package main import ( "flag" - stdlog "log" "os" "github.com/tendermint/abci/example/dummy" @@ -33,7 +32,8 @@ func main() { // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - stdlog.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) } srv.SetLogger(log.With(logger, "module", "abci-server")) diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index c77052b3..8f4e3393 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -2,7 +2,6 @@ package main import ( "flag" - stdlog "log" "os" "github.com/tendermint/abci/server" @@ -17,12 +16,14 @@ func main() { abciPtr := flag.String("abci", "socket", "socket | grpc") flag.Parse() + logger := log.NewTmLogger(os.Stdout) + // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) if err != nil { - stdlog.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) } - logger := log.NewTmLogger(os.Stdout) srv.SetLogger(log.With(logger, "module", "abci-server")) // Wait forever diff --git a/example/example_test.go b/example/example_test.go index d71a44e6..ca2bf063 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -2,7 +2,6 @@ package example import ( "fmt" - stdlog "log" "net" "os" "reflect" @@ -44,7 +43,7 @@ func testStream(t *testing.T, app types.Application) { // Start the listener server, err := server.NewSocketServer("unix://test.sock", app) if err != nil { - stdlog.Fatal(cmn.Fmt("Error starting socket server: %v", err.Error())) + t.Fatalf("Error starting socket server: %v", err.Error()) } server.SetLogger(log.With(logger, "module", "abci-server")) defer server.Stop() @@ -52,7 +51,7 @@ func testStream(t *testing.T, app types.Application) { // Connect to the socket client, err := abcicli.NewSocketClient("unix://test.sock", false) if err != nil { - stdlog.Fatal(cmn.Fmt("Error starting socket client: %v", err.Error())) + t.Fatalf("Error starting socket client: %v", err.Error()) } client.SetLogger(log.With(logger, "module", "abci-client")) client.Start() @@ -120,7 +119,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { // Start the listener server, err := server.NewGRPCServer("unix://test.sock", app) if err != nil { - stdlog.Fatal(cmn.Fmt("Error starting GRPC server: %v", err.Error())) + t.Fatalf("Error starting GRPC server: %v", err.Error()) } server.SetLogger(log.With(logger, "module", "abci-server")) defer server.Stop() @@ -128,7 +127,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { // Connect to the socket conn, err := grpc.Dial("unix://test.sock", grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) if err != nil { - stdlog.Fatal(cmn.Fmt("Error dialing GRPC server: %v", err.Error())) + t.Fatalf("Error dialing GRPC server: %v", err.Error()) } defer conn.Close() From ce124c4aebb8b1e0137f15cd3b236ee91304d909 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 1 May 2017 16:45:51 +0400 Subject: [PATCH 233/545] modify test scripts to use relative paths --- .editorconfig | 15 +++++++++++++++ Makefile | 2 +- tests/test_app/test.sh | 13 +++++++++---- tests/test_cli/test.sh | 20 +++++++++++++------- 4 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d587999e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[Makefile] +indent_style = tab + +[*.sh] +indent_style = tab diff --git a/Makefile b/Makefile index 31236551..5d1a0428 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ 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; + done; test_integrations: get_vendor_deps install test diff --git a/tests/test_app/test.sh b/tests/test_app/test.sh index a0f2c3ce..0620b476 100755 --- a/tests/test_app/test.sh +++ b/tests/test_app/test.sh @@ -3,14 +3,19 @@ set -e # These tests spawn the counter app and server by execing the ABCI_APP command and run some simple client tests against it -ROOT=$GOPATH/src/github.com/tendermint/abci/tests/test_app -cd $ROOT +# Get the directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +# Change into that dir because we expect that. +cd "$DIR" # test golang counter -ABCI_APP="counter" go run *.go +ABCI_APP="counter" go run ./*.go # test golang counter via grpc -ABCI_APP="counter -abci=grpc" ABCI="grpc" go run *.go +ABCI_APP="counter -abci=grpc" ABCI="grpc" go run ./*.go # test nodejs counter # TODO: fix node app diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index a770730b..4266dd16 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -1,6 +1,12 @@ #! /bin/bash -cd $GOPATH/src/github.com/tendermint/abci +# Get the root directory. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )/../.." && pwd )" + +# Change into that dir because we expect that. +cd "$DIR" || exit function testExample() { N=$1 @@ -10,17 +16,17 @@ function testExample() { echo "Example $N" $APP &> /dev/null & sleep 2 - abci-cli --verbose batch < $INPUT > "${INPUT}.out.new" - killall "$APP" + abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" + killall "$APP" - pre=`shasum < "${INPUT}.out"` - post=`shasum < "${INPUT}.out.new"` + pre=$(shasum < "${INPUT}.out") + post=$(shasum < "${INPUT}.out.new") if [[ "$pre" != "$post" ]]; then echo "You broke the tutorial" - echo "Got:" + echo "Got:" cat "${INPUT}.out.new" - echo "Expected:" + echo "Expected:" cat "${INPUT}.out" exit 1 fi From 6baaad997512c6ef1b20556da6fecfea10f63f95 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 1 May 2017 17:11:40 +0400 Subject: [PATCH 234/545] update glide --- glide.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 9b574b52..c98e45a8 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 3918a6fe902116fbac5ac474580edf246bee125df6e63e3bd8378f068fa8f819 -updated: 2017-05-01T08:59:45.550273823Z +updated: 2017-05-01T12:52:56.770980963Z imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 @@ -59,7 +59,7 @@ imports: subpackages: - iavl - name: github.com/tendermint/tmlibs - version: dc50d7d3c19771377fb4aa6e703354205050053a + version: ee90b71eb94d05958875fb9cd756b301b691ea27 subpackages: - common - db From d2a4b16b287656a7b7cf200edc7fc49fc1a5fa49 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 3 May 2017 11:39:15 +0400 Subject: [PATCH 235/545] introduce testing logger --- cmd/abci-cli/abci-cli.go | 2 +- cmd/counter/main.go | 2 +- cmd/dummy/main.go | 2 +- example/block_aware/block_aware_app.go | 2 +- example/block_aware/block_aware_test.go | 6 ++---- example/dummy/dummy_test.go | 4 ++-- example/example_test.go | 11 +++-------- glide.lock | 16 ++++++++-------- glide.yaml | 2 +- tests/test_app/app.go | 2 +- 10 files changed, 21 insertions(+), 28 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 8a1ee2d1..260f0405 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -139,7 +139,7 @@ func main() { func before(c *cli.Context) error { if logger == nil { - logger = log.NewTmLogger(os.Stdout) + logger = log.NewTMLogger(os.Stdout) } if client == nil { var err error diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 8fd5b4cc..9ec6fdcc 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -18,7 +18,7 @@ func main() { flag.Parse() app := counter.NewCounterApplication(*serialPtr) - logger := log.NewTmLogger(os.Stdout) + logger := log.NewTMLogger(os.Stdout) // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 92249a9b..311f774e 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -18,7 +18,7 @@ func main() { persistencePtr := flag.String("persist", "", "directory to use for a database") flag.Parse() - logger := log.NewTmLogger(os.Stdout) + logger := log.NewTMLogger(os.Stdout) // Create the application - in memory or persisted to disk var app types.Application diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index 8f4e3393..ae9c1047 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -16,7 +16,7 @@ func main() { abciPtr := flag.String("abci", "socket", "socket | grpc") flag.Parse() - logger := log.NewTmLogger(os.Stdout) + logger := log.NewTMLogger(os.Stdout) // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index c251de6a..7d1ddc2b 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -1,7 +1,6 @@ package main import ( - "os" "strconv" "strings" "testing" @@ -14,14 +13,13 @@ import ( func TestChainAware(t *testing.T) { app := NewChainAwareApplication() - logger := log.NewTmLogger(os.Stdout) // Start the listener srv, err := server.NewServer("unix://test.sock", "socket", app) if err != nil { t.Fatal(err) } - srv.SetLogger(log.With(logger, "module", "abci-server")) + srv.SetLogger(log.With(log.TestingLogger(), "module", "abci-server")) defer srv.Stop() // Connect to the socket @@ -29,7 +27,7 @@ func TestChainAware(t *testing.T) { if err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } - client.SetLogger(log.With(logger, "module", "abci-client")) + client.SetLogger(log.With(log.TestingLogger(), "module", "abci-client")) client.Start() defer client.Stop() diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index fe569306..cb4e5cad 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -213,7 +213,7 @@ 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) - logger := log.NewTmLogger(os.Stdout) + logger := log.NewTMLogger(os.Stdout) server, err := server.NewSocketServer(socket, app) if err != nil { @@ -236,7 +236,7 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { // Start the listener socket := cmn.Fmt("unix://%s.sock", name) - logger := log.NewTmLogger(os.Stdout) + logger := log.NewTMLogger(os.Stdout) gapp := types.NewGRPCApplication(app) server, err := server.NewGRPCServer(socket, gapp) diff --git a/example/example_test.go b/example/example_test.go index ca2bf063..a96d17ab 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -3,7 +3,6 @@ package example import ( "fmt" "net" - "os" "reflect" "testing" "time" @@ -36,16 +35,14 @@ func TestGRPC(t *testing.T) { } func testStream(t *testing.T, app types.Application) { - numDeliverTxs := 200000 - logger := log.NewTmLogger(os.Stdout) // Start the listener server, err := server.NewSocketServer("unix://test.sock", app) if err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) } - server.SetLogger(log.With(logger, "module", "abci-server")) + server.SetLogger(log.With(log.TestingLogger(), "module", "abci-server")) defer server.Stop() // Connect to the socket @@ -53,7 +50,7 @@ func testStream(t *testing.T, app types.Application) { if err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } - client.SetLogger(log.With(logger, "module", "abci-client")) + client.SetLogger(log.With(log.TestingLogger(), "module", "abci-client")) client.Start() defer client.Stop() @@ -112,16 +109,14 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { } func testGRPCSync(t *testing.T, app *types.GRPCApplication) { - numDeliverTxs := 2000 - logger := log.NewTmLogger(os.Stdout) // Start the listener server, err := server.NewGRPCServer("unix://test.sock", app) if err != nil { t.Fatalf("Error starting GRPC server: %v", err.Error()) } - server.SetLogger(log.With(logger, "module", "abci-server")) + server.SetLogger(log.With(log.TestingLogger(), "module", "abci-server")) defer server.Stop() // Connect to the socket diff --git a/glide.lock b/glide.lock index c98e45a8..14abafc5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ -hash: 3918a6fe902116fbac5ac474580edf246bee125df6e63e3bd8378f068fa8f819 -updated: 2017-05-01T12:52:56.770980963Z +hash: c29114af0ddcb75dd9093d4006dd6b9039640a35540d5f44f9c19261b5730781 +updated: 2017-05-03T07:33:18.832551385Z imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - name: github.com/go-kit/kit - version: 8a2988aa81f699fc1e647c3c9dddce0113ef1bfb + version: 0873e56b0faeae3a1d661b10d629135508ea5504 subpackages: - log - log/level @@ -49,7 +49,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 197a2b270fd94ee03824b158e738fce62862d0b8 + version: 524ba917a3a1636f21ab2c0bf76b6526903ab879 - name: github.com/tendermint/go-wire version: b53add0b622662731985485f3a19be7f684660b8 subpackages: @@ -59,7 +59,7 @@ imports: subpackages: - iavl - name: github.com/tendermint/tmlibs - version: ee90b71eb94d05958875fb9cd756b301b691ea27 + version: 8fc36b0097e1dfcfbba793d4b4cc87e96a03096f subpackages: - common - db @@ -69,7 +69,7 @@ imports: - name: github.com/urfave/cli version: ab403a54a148f2d857920810291539e1f817ee7b - name: golang.org/x/crypto - version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e + version: d1464577745bc7f4e74f65be9cfbd09436a729d6 subpackages: - nacl/secretbox - openpgp/armor @@ -78,7 +78,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: da118f7b8e5954f39d0d2130ab35d4bf0e3cb344 + version: 0819898fb4973868bba6de59b6aaad75beea9a6a subpackages: - context - http2 @@ -99,7 +99,7 @@ imports: subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: 0eb507a2ca07f13baf499f89d66cc566bf644643 + version: 68a5d50f4517bae2b44b18092410fe248d153f1e subpackages: - codes - credentials diff --git a/glide.yaml b/glide.yaml index 95fd9ce3..aa98c8a6 100644 --- a/glide.yaml +++ b/glide.yaml @@ -13,7 +13,7 @@ import: subpackages: - iavl - package: github.com/tendermint/tmlibs - version: feature/new-logging + version: feature/testing-logger subpackages: - common - db diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 879a7400..14aa9c1d 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -38,7 +38,7 @@ func startClient(abciType string) abcicli.Client { if err != nil { panic("connecting to abci_app: " + err.Error()) } - logger := log.NewTmLogger(os.Stdout) + logger := log.NewTMLogger(os.Stdout) client.SetLogger(log.With(logger, "module", "abcicli")) return client } From 1dc3629b1a53935f2aca6794dfe3bcfb2e582d46 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 4 May 2017 22:43:54 +0400 Subject: [PATCH 236/545] update log interface --- client/socket_client.go | 3 ++- cmd/abci-cli/abci-cli.go | 4 ++-- cmd/counter/main.go | 4 ++-- cmd/dummy/main.go | 6 +++--- example/block_aware/block_aware_app.go | 4 ++-- example/block_aware/block_aware_test.go | 4 ++-- example/dummy/dummy_test.go | 13 ++++++------- example/example_test.go | 6 +++--- glide.lock | 10 +++++----- server/socket_server.go | 2 ++ tests/test_app/app.go | 4 ++-- 11 files changed, 31 insertions(+), 29 deletions(-) diff --git a/client/socket_client.go b/client/socket_client.go index 76f150c0..dd3e2903 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -53,7 +53,8 @@ func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { resCb: nil, } cli.BaseService = *cmn.NewBaseService(nil, "socketClient", cli) - + // FIXME we are loosing "Starting socketClient" message here + // add logger to params? _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. return cli, err } diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 260f0405..f4fe45fe 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -139,7 +139,7 @@ func main() { func before(c *cli.Context) error { if logger == nil { - logger = log.NewTMLogger(os.Stdout) + logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) } if client == nil { var err error @@ -148,7 +148,7 @@ func before(c *cli.Context) error { logger.Error(err.Error()) os.Exit(1) } - client.SetLogger(log.With(logger, "module", "abci-client")) + client.SetLogger(logger.With("module", "abci-client")) } return nil } diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 9ec6fdcc..351e0886 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -18,7 +18,7 @@ func main() { flag.Parse() app := counter.NewCounterApplication(*serialPtr) - logger := log.NewTMLogger(os.Stdout) + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) @@ -26,7 +26,7 @@ func main() { logger.Error(err.Error()) os.Exit(1) } - srv.SetLogger(log.With(logger, "module", "abci-server")) + srv.SetLogger(logger.With("module", "abci-server")) // Wait forever cmn.TrapSignal(func() { diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 311f774e..9e1a8112 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -18,7 +18,7 @@ func main() { persistencePtr := flag.String("persist", "", "directory to use for a database") flag.Parse() - logger := log.NewTMLogger(os.Stdout) + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Create the application - in memory or persisted to disk var app types.Application @@ -26,7 +26,7 @@ func main() { app = dummy.NewDummyApplication() } else { app = dummy.NewPersistentDummyApplication(*persistencePtr) - app.(*dummy.PersistentDummyApplication).SetLogger(log.With(logger, "module", "dummy")) + app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) } // Start the listener @@ -35,7 +35,7 @@ func main() { logger.Error(err.Error()) os.Exit(1) } - srv.SetLogger(log.With(logger, "module", "abci-server")) + srv.SetLogger(logger.With("module", "abci-server")) // Wait forever cmn.TrapSignal(func() { diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index ae9c1047..30e115ac 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -16,7 +16,7 @@ func main() { abciPtr := flag.String("abci", "socket", "socket | grpc") flag.Parse() - logger := log.NewTMLogger(os.Stdout) + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) @@ -24,7 +24,7 @@ func main() { logger.Error(err.Error()) os.Exit(1) } - srv.SetLogger(log.With(logger, "module", "abci-server")) + srv.SetLogger(logger.With("module", "abci-server")) // Wait forever cmn.TrapSignal(func() { diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 7d1ddc2b..6d42b876 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -19,7 +19,7 @@ func TestChainAware(t *testing.T) { if err != nil { t.Fatal(err) } - srv.SetLogger(log.With(log.TestingLogger(), "module", "abci-server")) + srv.SetLogger(log.TestingLogger().With("module", "abci-server")) defer srv.Stop() // Connect to the socket @@ -27,7 +27,7 @@ func TestChainAware(t *testing.T) { if err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } - client.SetLogger(log.With(log.TestingLogger(), "module", "abci-client")) + client.SetLogger(log.TestingLogger().With("module", "abci-client")) client.Start() defer client.Stop() diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index cb4e5cad..f805dd73 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -3,7 +3,6 @@ package dummy import ( "bytes" "io/ioutil" - "os" "sort" "testing" @@ -213,13 +212,13 @@ 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) - logger := log.NewTMLogger(os.Stdout) + logger := log.TestingLogger() server, err := server.NewSocketServer(socket, app) if err != nil { return nil, nil, err } - server.SetLogger(log.With(logger, "module", "abci-server")) + server.SetLogger(logger.With("module", "abci-server")) // Connect to the socket client, err := abcicli.NewSocketClient(socket, false) @@ -227,7 +226,7 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, server.Stop() return nil, nil, err } - client.SetLogger(log.With(logger, "module", "abci-client")) + client.SetLogger(logger.With("module", "abci-client")) client.Start() return client, server, err @@ -236,21 +235,21 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { // Start the listener socket := cmn.Fmt("unix://%s.sock", name) - logger := log.NewTMLogger(os.Stdout) + logger := log.TestingLogger() gapp := types.NewGRPCApplication(app) server, err := server.NewGRPCServer(socket, gapp) if err != nil { return nil, nil, err } - server.SetLogger(log.With(logger, "module", "abci-server")) + server.SetLogger(logger.With("module", "abci-server")) client, err := abcicli.NewGRPCClient(socket, true) if err != nil { server.Stop() return nil, nil, err } - client.SetLogger(log.With(logger, "module", "abci-client")) + client.SetLogger(logger.With("module", "abci-client")) return client, server, err } diff --git a/example/example_test.go b/example/example_test.go index a96d17ab..85c13d7d 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -42,7 +42,7 @@ func testStream(t *testing.T, app types.Application) { if err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) } - server.SetLogger(log.With(log.TestingLogger(), "module", "abci-server")) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) defer server.Stop() // Connect to the socket @@ -50,7 +50,7 @@ func testStream(t *testing.T, app types.Application) { if err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } - client.SetLogger(log.With(log.TestingLogger(), "module", "abci-client")) + client.SetLogger(log.TestingLogger().With("module", "abci-client")) client.Start() defer client.Stop() @@ -116,7 +116,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { if err != nil { t.Fatalf("Error starting GRPC server: %v", err.Error()) } - server.SetLogger(log.With(log.TestingLogger(), "module", "abci-server")) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) defer server.Stop() // Connect to the socket diff --git a/glide.lock b/glide.lock index 14abafc5..39d654aa 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: c29114af0ddcb75dd9093d4006dd6b9039640a35540d5f44f9c19261b5730781 -updated: 2017-05-03T07:33:18.832551385Z +updated: 2017-05-04T17:47:52.109070369Z imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 @@ -14,7 +14,7 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 7a2f19628aabfe68f0766b59e74d6315f8347d22 - name: github.com/golang/protobuf version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 subpackages: @@ -59,7 +59,7 @@ imports: subpackages: - iavl - name: github.com/tendermint/tmlibs - version: 8fc36b0097e1dfcfbba793d4b4cc87e96a03096f + version: a9a96064a0a494ef6a13c38b4395c20abee64996 subpackages: - common - db @@ -69,7 +69,7 @@ imports: - name: github.com/urfave/cli version: ab403a54a148f2d857920810291539e1f817ee7b - name: golang.org/x/crypto - version: d1464577745bc7f4e74f65be9cfbd09436a729d6 + version: 5a033cc77e57eca05bdb50522851d29e03569cbe subpackages: - nacl/secretbox - openpgp/armor @@ -78,7 +78,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 0819898fb4973868bba6de59b6aaad75beea9a6a + version: feeb485667d1fdabe727840fe00adc22431bc86e subpackages: - context - http2 diff --git a/server/socket_server.go b/server/socket_server.go index 3d83c3f7..f8d6f54a 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -40,6 +40,8 @@ func NewSocketServer(protoAddr string, app types.Application) (cmn.Service, erro conns: make(map[int]net.Conn), } s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) + // FIXME we are loosing "Starting ABCIServer" message here + // add logger to params? _, err := s.Start() // Just start it return s, err } diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 14aa9c1d..a88a05fd 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -38,8 +38,8 @@ func startClient(abciType string) abcicli.Client { if err != nil { panic("connecting to abci_app: " + err.Error()) } - logger := log.NewTMLogger(os.Stdout) - client.SetLogger(log.With(logger, "module", "abcicli")) + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + client.SetLogger(logger.With("module", "abcicli")) return client } From 317e91748ffd8c4c683d80a31ab1681beb2a5202 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 4 May 2017 23:24:58 +0400 Subject: [PATCH 237/545] remove all .sock files! --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5d1a0428..19ae4260 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ build: # test.sh requires that we run the installed cmds, must not be out of date test: install - find . -name test.sock -exec rm {} \; + find . -path ./vendor -prune -o -name *.sock -exec rm {} \; @ go test -p 1 `${NOVENDOR}` @ bash tests/test.sh From 50a9967c79d89742151c7f1a981678df8c21f9dc Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 5 May 2017 16:32:23 +0400 Subject: [PATCH 238/545] change tmlibs package version to "log" --- glide.lock | 8 ++++---- glide.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glide.lock b/glide.lock index 39d654aa..43375f1e 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c29114af0ddcb75dd9093d4006dd6b9039640a35540d5f44f9c19261b5730781 -updated: 2017-05-04T17:47:52.109070369Z +hash: 8038c78e65a8b5ad4bc6ff8e74c40bd02be23e2c3c4245aff8b354e3dbdec1e2 +updated: 2017-05-05T12:30:23.699400925Z imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 @@ -27,7 +27,7 @@ imports: - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: ff09b135c25aae272398c51a07235b90a75aa4f0 + version: c605e284fe17294bda444b34710735b29d1a9d90 - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -99,7 +99,7 @@ imports: subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: 68a5d50f4517bae2b44b18092410fe248d153f1e + version: 844f573616520565fdc6fb4db242321b5456fd6d subpackages: - codes - credentials diff --git a/glide.yaml b/glide.yaml index aa98c8a6..bd97a4a8 100644 --- a/glide.yaml +++ b/glide.yaml @@ -13,7 +13,7 @@ import: subpackages: - iavl - package: github.com/tendermint/tmlibs - version: feature/testing-logger + version: log subpackages: - common - db From d3e3eca3fed6dad4e56612ce55b29509e0bee318 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 5 May 2017 14:57:33 -0400 Subject: [PATCH 239/545] update glide --- glide.lock | 6 +++--- glide.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index 43375f1e..76fa6c5f 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 8038c78e65a8b5ad4bc6ff8e74c40bd02be23e2c3c4245aff8b354e3dbdec1e2 -updated: 2017-05-05T12:30:23.699400925Z +hash: f9c2ddad16bf8652076a93bd9f398bb498eefb2f5bd2c89a77d966ebd12feec8 +updated: 2017-05-05T14:57:21.118338652-04:00 imports: - name: github.com/btcsuite/btcd version: 4b348c1d33373d672edd83fc576892d0e46686d2 @@ -59,7 +59,7 @@ imports: subpackages: - iavl - name: github.com/tendermint/tmlibs - version: a9a96064a0a494ef6a13c38b4395c20abee64996 + version: d72136da0df105944199c9e04035147fc6a4befa subpackages: - common - db diff --git a/glide.yaml b/glide.yaml index bd97a4a8..11379aad 100644 --- a/glide.yaml +++ b/glide.yaml @@ -13,7 +13,7 @@ import: subpackages: - iavl - package: github.com/tendermint/tmlibs - version: log + version: develop subpackages: - common - db From a3d4e5797d84514c3a95e2a0f70a078eb543dba9 Mon Sep 17 00:00:00 2001 From: Krzysztof Jurewicz Date: Wed, 5 Apr 2017 14:56:28 +0200 Subject: [PATCH 240/545] Comment out MessageType As it is an unused enum, leaving it uncommented causes dead Protocol Buffers code to be generated. --- types/types.proto | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/types/types.proto b/types/types.proto index 0c741d3d..242c72f5 100644 --- a/types/types.proto +++ b/types/types.proto @@ -10,22 +10,22 @@ package types; // 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; +// 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; -} +// 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 From 322b4e54def8df4929007b21495c63310cfd00cd Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Tue, 9 May 2017 12:13:28 +0200 Subject: [PATCH 241/545] Remove unused enum MessageTypes --- types/types.proto | 270 +++++++++++++++++++++------------------------- 1 file changed, 123 insertions(+), 147 deletions(-) diff --git a/types/types.proto b/types/types.proto index 242c72f5..1d66df9d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -3,70 +3,46 @@ package types; // This file is copied from http://github.com/tendermint/abci -//---------------------------------------- -// Message types - -// 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; -// } - //---------------------------------------- // Code types enum CodeType { - OK = 0; + OK = 0; - // General response codes, 0 ~ 99 - InternalError = 1; - EncodingError = 2; - BadNonce = 3; - Unauthorized = 4; - InsufficientFunds = 5; - UnknownRequest = 6; + // 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 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; + // 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; } @@ -74,23 +50,23 @@ enum CodeType { // Request types message Request { - oneof value{ - RequestEcho echo = 1; - RequestFlush flush = 2; - RequestInfo info = 3; - RequestSetOption set_option = 4; - RequestDeliverTx deliver_tx = 5; - RequestCheckTx check_tx = 6; - RequestCommit commit = 7; - RequestQuery query = 8; - RequestInitChain init_chain = 9; - RequestBeginBlock begin_block = 10; - RequestEndBlock end_block = 11; - } + oneof value{ + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestDeliverTx deliver_tx = 5; + RequestCheckTx check_tx = 6; + RequestCommit commit = 7; + RequestQuery query = 8; + RequestInitChain init_chain = 9; + RequestBeginBlock begin_block = 10; + RequestEndBlock end_block = 11; + } } message RequestEcho { - string message = 1; + string message = 1; } message RequestFlush { @@ -100,39 +76,39 @@ message RequestInfo { } message RequestSetOption{ - string key = 1; - string value = 2; + string key = 1; + string value = 2; } message RequestDeliverTx{ - bytes tx = 1; + bytes tx = 1; } message RequestCheckTx{ - bytes tx = 1; + bytes tx = 1; } message RequestQuery{ - bytes data = 1; - string path = 2; - uint64 height = 3; - bool prove = 4; + bytes data = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; } message RequestCommit{ } message RequestInitChain{ - repeated Validator validators = 1; + repeated Validator validators = 1; } message RequestBeginBlock{ - bytes hash = 1; - Header header = 2; + bytes hash = 1; + Header header = 2; } message RequestEndBlock{ - uint64 height = 1; + uint64 height = 1; } //---------------------------------------- @@ -140,70 +116,70 @@ message RequestEndBlock{ message Response { - oneof value{ - ResponseException exception = 1; - ResponseEcho echo = 2; - ResponseFlush flush = 3; - ResponseInfo info = 4; - ResponseSetOption set_option = 5; - ResponseDeliverTx deliver_tx = 6; - ResponseCheckTx check_tx = 7; - ResponseCommit commit = 8; - ResponseQuery query = 9; - ResponseInitChain init_chain = 10; - ResponseBeginBlock begin_block = 11; - ResponseEndBlock end_block = 12; - } + oneof value{ + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseDeliverTx deliver_tx = 6; + ResponseCheckTx check_tx = 7; + ResponseCommit commit = 8; + ResponseQuery query = 9; + ResponseInitChain init_chain = 10; + ResponseBeginBlock begin_block = 11; + ResponseEndBlock end_block = 12; + } } message ResponseException{ - string error = 1; + string error = 1; } message ResponseEcho { - string message = 1; + string message = 1; } message ResponseFlush{ } message ResponseInfo { - string data = 1; - string version = 2; - uint64 last_block_height = 3; - bytes last_block_app_hash = 4; + string data = 1; + string version = 2; + uint64 last_block_height = 3; + bytes last_block_app_hash = 4; } message ResponseSetOption{ - string log = 1; + string log = 1; } message ResponseDeliverTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } message ResponseCheckTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } message ResponseQuery{ - CodeType code = 1; - int64 index = 2; - bytes key = 3; - bytes value = 4; - bytes proof = 5; - uint64 height = 6; - string log = 7; + CodeType code = 1; + int64 index = 2; + bytes key = 3; + bytes value = 4; + bytes proof = 5; + uint64 height = 6; + string log = 7; } message ResponseCommit{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } @@ -214,52 +190,52 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 1; + repeated Validator diffs = 1; } //---------------------------------------- // Blockchain Types message Header { - string chain_id = 1; - uint64 height = 2; - uint64 time = 3; - uint64 num_txs = 4; - BlockID last_block_id = 5; - bytes last_commit_hash = 6; - bytes data_hash = 7; - bytes validators_hash = 8; - bytes app_hash = 9; + string chain_id = 1; + uint64 height = 2; + uint64 time = 3; + uint64 num_txs = 4; + BlockID last_block_id = 5; + bytes last_commit_hash = 6; + bytes data_hash = 7; + bytes validators_hash = 8; + bytes app_hash = 9; } message BlockID { - bytes hash = 1; - PartSetHeader parts = 2; + bytes hash = 1; + PartSetHeader parts = 2; } message PartSetHeader { - uint64 total = 1; - bytes hash = 2; + uint64 total = 1; + bytes hash = 2; } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; } //---------------------------------------- // Service Definition service ABCIApplication { - rpc Echo(RequestEcho) returns (ResponseEcho) ; - rpc Flush(RequestFlush) returns (ResponseFlush); - rpc Info(RequestInfo) returns (ResponseInfo); - rpc SetOption(RequestSetOption) returns (ResponseSetOption); - rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); - rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); - rpc Query(RequestQuery) returns (ResponseQuery); - rpc Commit(RequestCommit) returns (ResponseCommit); - rpc InitChain(RequestInitChain) returns (ResponseInitChain); - rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); - rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); + rpc Echo(RequestEcho) returns (ResponseEcho) ; + rpc Flush(RequestFlush) returns (ResponseFlush); + rpc Info(RequestInfo) returns (ResponseInfo); + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + rpc Query(RequestQuery) returns (ResponseQuery); + rpc Commit(RequestCommit) returns (ResponseCommit); + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); } From 577ec5452f92a39b1d02ac5774cdd963ab545b47 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Tue, 9 May 2017 12:33:38 +0200 Subject: [PATCH 242/545] Fix indentation --- types/types.proto | 246 +++++++++++++++++++++++----------------------- 1 file changed, 123 insertions(+), 123 deletions(-) diff --git a/types/types.proto b/types/types.proto index 1d66df9d..7abc354d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -7,42 +7,42 @@ package types; // Code types enum CodeType { - OK = 0; + OK = 0; - // General response codes, 0 ~ 99 - InternalError = 1; - EncodingError = 2; - BadNonce = 3; - Unauthorized = 4; - InsufficientFunds = 5; - UnknownRequest = 6; + // 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 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; + // Reserved for governance, 200 ~ 299 + GovUnknownEntity = 201; + GovUnknownGroup = 202; + GovUnknownProposal = 203; + GovDuplicateGroup = 204; + GovDuplicateMember = 205; + GovDuplicateProposal = 206; + GovDuplicateVote = 207; + GovInvalidMember = 208; + GovInvalidVote = 209; + GovInvalidVotingPower = 210; } @@ -50,23 +50,23 @@ enum CodeType { // Request types message Request { - oneof value{ - RequestEcho echo = 1; - RequestFlush flush = 2; - RequestInfo info = 3; - RequestSetOption set_option = 4; - RequestDeliverTx deliver_tx = 5; - RequestCheckTx check_tx = 6; - RequestCommit commit = 7; - RequestQuery query = 8; - RequestInitChain init_chain = 9; - RequestBeginBlock begin_block = 10; - RequestEndBlock end_block = 11; - } + oneof value{ + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestDeliverTx deliver_tx = 5; + RequestCheckTx check_tx = 6; + RequestCommit commit = 7; + RequestQuery query = 8; + RequestInitChain init_chain = 9; + RequestBeginBlock begin_block = 10; + RequestEndBlock end_block = 11; + } } message RequestEcho { - string message = 1; + string message = 1; } message RequestFlush { @@ -76,39 +76,39 @@ message RequestInfo { } message RequestSetOption{ - string key = 1; - string value = 2; + string key = 1; + string value = 2; } message RequestDeliverTx{ - bytes tx = 1; + bytes tx = 1; } message RequestCheckTx{ - bytes tx = 1; + bytes tx = 1; } message RequestQuery{ - bytes data = 1; - string path = 2; - uint64 height = 3; - bool prove = 4; + bytes data = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; } message RequestCommit{ } message RequestInitChain{ - repeated Validator validators = 1; + repeated Validator validators = 1; } message RequestBeginBlock{ - bytes hash = 1; - Header header = 2; + bytes hash = 1; + Header header = 2; } message RequestEndBlock{ - uint64 height = 1; + uint64 height = 1; } //---------------------------------------- @@ -116,70 +116,70 @@ message RequestEndBlock{ message Response { - oneof value{ - ResponseException exception = 1; - ResponseEcho echo = 2; - ResponseFlush flush = 3; - ResponseInfo info = 4; - ResponseSetOption set_option = 5; - ResponseDeliverTx deliver_tx = 6; - ResponseCheckTx check_tx = 7; - ResponseCommit commit = 8; - ResponseQuery query = 9; - ResponseInitChain init_chain = 10; - ResponseBeginBlock begin_block = 11; - ResponseEndBlock end_block = 12; - } + oneof value{ + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseDeliverTx deliver_tx = 6; + ResponseCheckTx check_tx = 7; + ResponseCommit commit = 8; + ResponseQuery query = 9; + ResponseInitChain init_chain = 10; + ResponseBeginBlock begin_block = 11; + ResponseEndBlock end_block = 12; + } } message ResponseException{ - string error = 1; + string error = 1; } message ResponseEcho { - string message = 1; + string message = 1; } message ResponseFlush{ } message ResponseInfo { - string data = 1; - string version = 2; - uint64 last_block_height = 3; - bytes last_block_app_hash = 4; + string data = 1; + string version = 2; + uint64 last_block_height = 3; + bytes last_block_app_hash = 4; } message ResponseSetOption{ - string log = 1; + string log = 1; } message ResponseDeliverTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } message ResponseCheckTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } message ResponseQuery{ - CodeType code = 1; - int64 index = 2; - bytes key = 3; - bytes value = 4; - bytes proof = 5; - uint64 height = 6; - string log = 7; + CodeType code = 1; + int64 index = 2; + bytes key = 3; + bytes value = 4; + bytes proof = 5; + uint64 height = 6; + string log = 7; } message ResponseCommit{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } @@ -190,52 +190,52 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 1; + repeated Validator diffs = 1; } //---------------------------------------- // Blockchain Types message Header { - string chain_id = 1; - uint64 height = 2; - uint64 time = 3; - uint64 num_txs = 4; - BlockID last_block_id = 5; - bytes last_commit_hash = 6; - bytes data_hash = 7; - bytes validators_hash = 8; - bytes app_hash = 9; + string chain_id = 1; + uint64 height = 2; + uint64 time = 3; + uint64 num_txs = 4; + BlockID last_block_id = 5; + bytes last_commit_hash = 6; + bytes data_hash = 7; + bytes validators_hash = 8; + bytes app_hash = 9; } message BlockID { - bytes hash = 1; - PartSetHeader parts = 2; + bytes hash = 1; + PartSetHeader parts = 2; } message PartSetHeader { - uint64 total = 1; - bytes hash = 2; + uint64 total = 1; + bytes hash = 2; } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; } //---------------------------------------- // Service Definition service ABCIApplication { - rpc Echo(RequestEcho) returns (ResponseEcho) ; - rpc Flush(RequestFlush) returns (ResponseFlush); - rpc Info(RequestInfo) returns (ResponseInfo); - rpc SetOption(RequestSetOption) returns (ResponseSetOption); - rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); - rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); - rpc Query(RequestQuery) returns (ResponseQuery); - rpc Commit(RequestCommit) returns (ResponseCommit); - rpc InitChain(RequestInitChain) returns (ResponseInitChain); - rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); - rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); + rpc Echo(RequestEcho) returns (ResponseEcho) ; + rpc Flush(RequestFlush) returns (ResponseFlush); + rpc Info(RequestInfo) returns (ResponseInfo); + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + rpc Query(RequestQuery) returns (ResponseQuery); + rpc Commit(RequestCommit) returns (ResponseCommit); + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); } From 840e658ec01829aed2cf47cdae216a03d9609300 Mon Sep 17 00:00:00 2001 From: Jacob Gadikian Date: Mon, 1 May 2017 22:53:51 +0700 Subject: [PATCH 243/545] Update grpc_server.go --- server/grpc_server.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/grpc_server.go b/server/grpc_server.go index 003a7661..37ef20a8 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -1,3 +1,13 @@ +/* +Package server is used to start a new ABCI server. + +It defines the struct for gRPC server settings, and functions for: + +* Starting a new gRPC server +* Stopping a gRPC server + +*/ + package server import ( @@ -12,6 +22,7 @@ import ( // var maxNumberConnections = 2 +//GRPCServer is used to set the protocol and address for gRPC. type GRPCServer struct { cmn.BaseService @@ -23,6 +34,7 @@ type GRPCServer struct { app types.ABCIApplicationServer } +//NewGRPCServer allows setting up a new gRPC ABCI server. func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Service, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] @@ -37,6 +49,7 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Servi return s, err } +//Onstart registers a new gRPC service and tells that service to listen on the port that is set in NewGRPCServer. func (s *GRPCServer) OnStart() error { s.BaseService.OnStart() ln, err := net.Listen(s.proto, s.addr) @@ -50,6 +63,7 @@ func (s *GRPCServer) OnStart() error { return nil } +//OnStop is called when a gRPC server is stopped. func (s *GRPCServer) OnStop() { s.BaseService.OnStop() s.server.Stop() From e43bcf3f2615770eb08a70d3c62569f7b823c935 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Tue, 9 May 2017 12:40:18 +0200 Subject: [PATCH 244/545] Move package comment --- server/grpc_server.go | 16 +++------------- server/server.go | 9 +++++++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/server/grpc_server.go b/server/grpc_server.go index 37ef20a8..1d8dd1ef 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -1,13 +1,3 @@ -/* -Package server is used to start a new ABCI server. - -It defines the struct for gRPC server settings, and functions for: - -* Starting a new gRPC server -* Stopping a gRPC server - -*/ - package server import ( @@ -22,7 +12,7 @@ import ( // var maxNumberConnections = 2 -//GRPCServer is used to set the protocol and address for gRPC. +//GRPCServer is used to set the protocol and address for gRPC. type GRPCServer struct { cmn.BaseService @@ -49,7 +39,7 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Servi return s, err } -//Onstart registers a new gRPC service and tells that service to listen on the port that is set in NewGRPCServer. +//Onstart registers a new gRPC service and tells that service to listen on the port that is set in NewGRPCServer. func (s *GRPCServer) OnStart() error { s.BaseService.OnStart() ln, err := net.Listen(s.proto, s.addr) @@ -63,7 +53,7 @@ func (s *GRPCServer) OnStart() error { return nil } -//OnStop is called when a gRPC server is stopped. +//OnStop is called when a gRPC server is stopped. func (s *GRPCServer) OnStop() { s.BaseService.OnStop() s.server.Stop() diff --git a/server/server.go b/server/server.go index d18df820..45d9ac1f 100644 --- a/server/server.go +++ b/server/server.go @@ -1,3 +1,12 @@ +/* +Package server is used to start a new ABCI server. + +It contains two server implementation: + * gRPC server + * socket server + +*/ + package server import ( From ea2d83e513a99b90f96099a2e04fbc5b935c73a9 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Sat, 13 May 2017 10:01:16 +0200 Subject: [PATCH 245/545] Clean up comments --- server/grpc_server.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/server/grpc_server.go b/server/grpc_server.go index 1d8dd1ef..ae2a481d 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -10,9 +10,6 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -// var maxNumberConnections = 2 - -//GRPCServer is used to set the protocol and address for gRPC. type GRPCServer struct { cmn.BaseService @@ -24,7 +21,7 @@ type GRPCServer struct { app types.ABCIApplicationServer } -//NewGRPCServer allows setting up a new gRPC ABCI server. +// NewGRPCServer returns a new gRPC ABCI server func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Service, error) { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] @@ -39,7 +36,7 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Servi return s, err } -//Onstart registers a new gRPC service and tells that service to listen on the port that is set in NewGRPCServer. +// OnStart starts the gRPC service func (s *GRPCServer) OnStart() error { s.BaseService.OnStart() ln, err := net.Listen(s.proto, s.addr) @@ -53,7 +50,7 @@ func (s *GRPCServer) OnStart() error { return nil } -//OnStop is called when a gRPC server is stopped. +// OnStop stops the gRPC server func (s *GRPCServer) OnStop() { s.BaseService.OnStop() s.server.Stop() From 4674bf96b036ec64f70f836593a68388f3d12ae5 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Sat, 13 May 2017 18:37:00 +0200 Subject: [PATCH 246/545] Extend the query command --- cmd/abci-cli/abci-cli.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index f4fe45fe..9327a3f1 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "os" + "strconv" "strings" abcicli "github.com/tendermint/abci/client" @@ -307,18 +308,36 @@ func cmdCommit(c *cli.Context) error { // TODO: Make request and response support all fields. func cmdQuery(c *cli.Context) error { args := c.Args() - if len(args) != 1 { - return errors.New("Command query takes 1 argument") + fmt.Println(len(args)) + if len(args) == 0 { + return errors.New("Command query takes 1 or more arguments") } - queryBytes, err := stringOrHexToBytes(c.Args()[0]) + + queryBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err } + + var path = "/store" + if len(args) > 1 { + path = args[1] + } + + var height uint64 + if len(args) > 2 { + height, _ = strconv.ParseUint(args[2], 10, 64) + } + + var prove = true + if len(args) > 3 { + prove, _ = strconv.ParseBool(args[3]) + } + resQuery, err := client.QuerySync(types.RequestQuery{ Data: queryBytes, - Path: "/store", // TOOD expose - Height: 0, // TODO expose - //Prove: true, // TODO expose + Path: path, + Height: height, + Prove: prove, }) if err != nil { return err From b55e695d3d33d87c2ab1335669c597fd746ca384 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Sat, 13 May 2017 21:08:34 +0200 Subject: [PATCH 247/545] Remove debug statement --- cmd/abci-cli/abci-cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 9327a3f1..de157832 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -308,7 +308,7 @@ func cmdCommit(c *cli.Context) error { // TODO: Make request and response support all fields. func cmdQuery(c *cli.Context) error { args := c.Args() - fmt.Println(len(args)) + if len(args) == 0 { return errors.New("Command query takes 1 or more arguments") } From 05dc4d12dd00f72bc0d57971c0da47f8da252d45 Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Sat, 13 May 2017 19:08:04 -0400 Subject: [PATCH 248/545] result.IsSameCode --- types/result.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/types/result.go b/types/result.go index c7f2d565..7bf52c90 100644 --- a/types/result.go +++ b/types/result.go @@ -29,6 +29,10 @@ func (res Result) IsErr() bool { return res.Code != CodeType_OK } +func (res Result) IsSameCode(compare Result) bool { + return res.Code == compare.Code +} + func (res Result) Error() string { return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) } From eda4f2dddcb68ca515711660efdd023541c90194 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 11:29:34 -0400 Subject: [PATCH 249/545] NewXXXClient doesnt run Start or return error --- client/client.go | 7 ++--- client/grpc_client.go | 5 ++-- client/socket_client.go | 7 ++--- cmd/abci-cli/abci-cli.go | 5 +++- example/block_aware/block_aware_test.go | 4 +-- example/dummy/dummy_test.go | 8 +++--- example/example_test.go | 4 +-- glide.lock | 35 ++++++++++++++++--------- tests/test_app/app.go | 4 +++ 9 files changed, 46 insertions(+), 33 deletions(-) diff --git a/client/client.go b/client/client.go index a54978fc..c911dd87 100644 --- a/client/client.go +++ b/client/client.go @@ -43,15 +43,16 @@ type Client interface { //---------------------------------------- +// NewClient returns a new ABCI client of the specified transport type. +// It returns an error if the transport is not "socket" or "grpc" func NewClient(addr, transport string, mustConnect bool) (client Client, err error) { switch transport { case "socket": - client, err = NewSocketClient(addr, mustConnect) + client = NewSocketClient(addr, mustConnect) case "grpc": - client, err = NewGRPCClient(addr, mustConnect) + client = NewGRPCClient(addr, mustConnect) default: err = fmt.Errorf("Unknown abci transport %s", transport) - } return } diff --git a/client/grpc_client.go b/client/grpc_client.go index 25783101..9743cdf6 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -27,14 +27,13 @@ type grpcClient struct { resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { +func NewGRPCClient(addr string, mustConnect bool) *grpcClient { cli := &grpcClient{ addr: addr, mustConnect: mustConnect, } 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 + return cli } func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { diff --git a/client/socket_client.go b/client/socket_client.go index dd3e2903..f95eac5c 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -42,7 +42,7 @@ type socketClient struct { } -func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { +func NewSocketClient(addr string, mustConnect bool) *socketClient { cli := &socketClient{ reqQueue: make(chan *ReqRes, reqQueueSize), flushTimer: cmn.NewThrottleTimer("socketClient", flushThrottleMS), @@ -53,10 +53,7 @@ func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { resCb: nil, } cli.BaseService = *cmn.NewBaseService(nil, "socketClient", cli) - // FIXME we are loosing "Starting socketClient" message here - // add logger to params? - _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. - return cli, err + return cli } func (cli *socketClient) OnStart() error { diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index f4fe45fe..3cf6ab89 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -139,7 +139,7 @@ func main() { func before(c *cli.Context) error { if logger == nil { - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), log.AllowError()) } if client == nil { var err error @@ -149,6 +149,9 @@ func before(c *cli.Context) error { os.Exit(1) } client.SetLogger(logger.With("module", "abci-client")) + if _, err := client.Start(); err != nil { + return err + } } return nil } diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 6d42b876..817deec6 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -23,8 +23,8 @@ func TestChainAware(t *testing.T) { defer srv.Stop() // Connect to the socket - client, err := abcicli.NewSocketClient("unix://test.sock", false) - if err != nil { + client := abcicli.NewSocketClient("unix://test.sock", false) + if _, err := client.Start(); err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } client.SetLogger(log.TestingLogger().With("module", "abci-client")) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index f805dd73..8ef36d07 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -221,8 +221,8 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, server.SetLogger(logger.With("module", "abci-server")) // Connect to the socket - client, err := abcicli.NewSocketClient(socket, false) - if err != nil { + client := abcicli.NewSocketClient(socket, false) + if _, err := client.Start(); err != nil { server.Stop() return nil, nil, err } @@ -244,8 +244,8 @@ func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, c } server.SetLogger(logger.With("module", "abci-server")) - client, err := abcicli.NewGRPCClient(socket, true) - if err != nil { + client := abcicli.NewGRPCClient(socket, true) + if _, err := client.Start(); err != nil { server.Stop() return nil, nil, err } diff --git a/example/example_test.go b/example/example_test.go index 85c13d7d..cdb44082 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -46,8 +46,8 @@ func testStream(t *testing.T, app types.Application) { defer server.Stop() // Connect to the socket - client, err := abcicli.NewSocketClient("unix://test.sock", false) - if err != nil { + client := abcicli.NewSocketClient("unix://test.sock", false) + if _, err := client.Start(); err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } client.SetLogger(log.TestingLogger().With("module", "abci-client")) diff --git a/glide.lock b/glide.lock index 76fa6c5f..55c5cdb3 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,16 @@ hash: f9c2ddad16bf8652076a93bd9f398bb498eefb2f5bd2c89a77d966ebd12feec8 -updated: 2017-05-05T14:57:21.118338652-04:00 +updated: 2017-05-15T10:11:42.094564957-04:00 imports: - name: github.com/btcsuite/btcd - version: 4b348c1d33373d672edd83fc576892d0e46686d2 + version: b8df516b4b267acf2de46be593a9d948d1d2c420 subpackages: - btcec +- name: github.com/btcsuite/fastsha256 + version: 637e656429416087660c84436a2a035d69d54e2e +- name: github.com/clipperhouse/typewriter + version: c1a48da378ebb7db1db9f35981b5cc24bf2e5b85 - name: github.com/go-kit/kit - version: 0873e56b0faeae3a1d661b10d629135508ea5504 + version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 subpackages: - log - log/level @@ -14,7 +18,7 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack - version: 7a2f19628aabfe68f0766b59e74d6315f8347d22 + version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 subpackages: @@ -27,7 +31,7 @@ imports: - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: c605e284fe17294bda444b34710735b29d1a9d90 + version: ff09b135c25aae272398c51a07235b90a75aa4f0 - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -49,17 +53,17 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 524ba917a3a1636f21ab2c0bf76b6526903ab879 + version: a42b10e0feb465eb56fbc6bb5b71d57ef646ec57 - name: github.com/tendermint/go-wire - version: b53add0b622662731985485f3a19be7f684660b8 + version: 301a758c9d28e9f3900ff5d545403cf4e5f6e73f subpackages: - data - name: github.com/tendermint/merkleeyes - version: d0aa363fd4e015e509038c3a0ec493bc62ee0b8a + version: c722818b460381bc5b82e38c73ff6e22a9df624d subpackages: - iavl - name: github.com/tendermint/tmlibs - version: d72136da0df105944199c9e04035147fc6a4befa + version: 812d9f9b84d1dfe4cb46ce021b3a2d97b48d1292 subpackages: - common - db @@ -67,9 +71,9 @@ imports: - merkle - process - name: github.com/urfave/cli - version: ab403a54a148f2d857920810291539e1f817ee7b + version: d70f47eeca3afd795160003bc6e28b001d60c67c - name: golang.org/x/crypto - version: 5a033cc77e57eca05bdb50522851d29e03569cbe + version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: - nacl/secretbox - openpgp/armor @@ -94,6 +98,11 @@ imports: - transform - unicode/bidi - unicode/norm +- name: golang.org/x/tools + version: 144c6642b5d832d6c44a53dad6ee61665dd432ce + subpackages: + - go/ast/astutil + - imports - name: google.golang.org/genproto version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 subpackages: @@ -116,7 +125,7 @@ imports: - transport testImports: - name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -124,7 +133,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 4d4bfba8f1d1027c4fdbe371823030df51419987 + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 subpackages: - assert - require diff --git a/tests/test_app/app.go b/tests/test_app/app.go index a88a05fd..3930957d 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -36,8 +36,12 @@ func startClient(abciType string) abcicli.Client { // Start client client, err := abcicli.NewClient("tcp://127.0.0.1:46658", abciType, true) if err != nil { + panic(err.Error()) + } + if _, err := client.Start(); err != nil { panic("connecting to abci_app: " + err.Error()) } + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) client.SetLogger(logger.With("module", "abcicli")) return client From 894f3fca73b2dacca5fe99bda50c128d5cbef8e5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 12:28:37 -0400 Subject: [PATCH 250/545] cmd: query params are flags --- cmd/abci-cli/abci-cli.go | 41 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index de157832..1b3d2dc5 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "os" - "strconv" "strings" abcicli "github.com/tendermint/abci/client" @@ -127,6 +126,22 @@ func main() { Action: func(c *cli.Context) error { return cmdQuery(c) }, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "path", + Value: "/store", + Usage: "Path to prefix the query with", + }, + cli.IntFlag{ + Name: "height", + Value: 0, + Usage: "Height to query the blockchain at", + }, + cli.BoolFlag{ + Name: "prove", + Usage: "Whether or not to return a merkle proof of the query result", + }, + }, }, } app.Before = before @@ -305,12 +320,11 @@ func cmdCommit(c *cli.Context) error { } // Query application state -// TODO: Make request and response support all fields. func cmdQuery(c *cli.Context) error { args := c.Args() - if len(args) == 0 { - return errors.New("Command query takes 1 or more arguments") + if len(args) != 1 { + return errors.New("Command query takes 1 argument, the query bytes") } queryBytes, err := stringOrHexToBytes(args[0]) @@ -318,25 +332,14 @@ func cmdQuery(c *cli.Context) error { return err } - var path = "/store" - if len(args) > 1 { - path = args[1] - } - - var height uint64 - if len(args) > 2 { - height, _ = strconv.ParseUint(args[2], 10, 64) - } - - var prove = true - if len(args) > 3 { - prove, _ = strconv.ParseBool(args[3]) - } + path := c.String("path") + height := c.Int("height") + prove := c.Bool("prove") resQuery, err := client.QuerySync(types.RequestQuery{ Data: queryBytes, Path: path, - Height: height, + Height: uint64(height), Prove: prove, }) if err != nil { From d07b2352ad1c914d5b7f85a444ee2b977779b6e0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 12:51:24 -0400 Subject: [PATCH 251/545] NewXXXServer doesnt run Start or return error --- cmd/counter/main.go | 4 ++++ cmd/dummy/main.go | 4 ++++ example/block_aware/block_aware_app.go | 4 ++++ example/block_aware/block_aware_test.go | 3 +++ example/dummy/dummy_test.go | 21 ++++++++++----------- example/example_test.go | 8 ++++---- server/grpc_server.go | 5 ++--- server/server.go | 4 ++-- server/socket_server.go | 7 ++----- 9 files changed, 35 insertions(+), 25 deletions(-) diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 351e0886..aa55778c 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -27,6 +27,10 @@ func main() { os.Exit(1) } srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) + } // Wait forever cmn.TrapSignal(func() { diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index 9e1a8112..85bbca18 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -36,6 +36,10 @@ func main() { os.Exit(1) } srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) + } // Wait forever cmn.TrapSignal(func() { diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index 30e115ac..8bacecd1 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -25,6 +25,10 @@ func main() { os.Exit(1) } srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) + } // Wait forever cmn.TrapSignal(func() { diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 817deec6..38acdd51 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -20,6 +20,9 @@ func TestChainAware(t *testing.T) { t.Fatal(err) } srv.SetLogger(log.TestingLogger().With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + t.Fatal(err.Error()) + } defer srv.Stop() // Connect to the socket diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 8ef36d07..e180af3e 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -214,22 +214,21 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, socket := cmn.Fmt("unix://%s.sock", name) logger := log.TestingLogger() - server, err := server.NewSocketServer(socket, app) - if err != nil { + server := server.NewSocketServer(socket, app) + server.SetLogger(logger.With("module", "abci-server")) + if _, err := server.Start(); err != nil { return nil, nil, err } - server.SetLogger(logger.With("module", "abci-server")) // Connect to the socket client := abcicli.NewSocketClient(socket, false) + client.SetLogger(logger.With("module", "abci-client")) if _, err := client.Start(); err != nil { server.Stop() return nil, nil, err } - client.SetLogger(logger.With("module", "abci-client")) - client.Start() - return client, server, err + return client, server, nil } func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { @@ -238,19 +237,19 @@ func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, c logger := log.TestingLogger() gapp := types.NewGRPCApplication(app) - server, err := server.NewGRPCServer(socket, gapp) - if err != nil { + server := server.NewGRPCServer(socket, gapp) + server.SetLogger(logger.With("module", "abci-server")) + if _, err := server.Start(); err != nil { return nil, nil, err } - server.SetLogger(logger.With("module", "abci-server")) client := abcicli.NewGRPCClient(socket, true) + client.SetLogger(logger.With("module", "abci-client")) if _, err := client.Start(); err != nil { server.Stop() return nil, nil, err } - client.SetLogger(logger.With("module", "abci-client")) - return client, server, err + return client, server, nil } func TestClientServer(t *testing.T) { diff --git a/example/example_test.go b/example/example_test.go index cdb44082..7e116c59 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -38,8 +38,8 @@ func testStream(t *testing.T, app types.Application) { numDeliverTxs := 200000 // Start the listener - server, err := server.NewSocketServer("unix://test.sock", app) - if err != nil { + server := server.NewSocketServer("unix://test.sock", app) + if _, err := server.Start(); err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) } server.SetLogger(log.TestingLogger().With("module", "abci-server")) @@ -112,8 +112,8 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { numDeliverTxs := 2000 // Start the listener - server, err := server.NewGRPCServer("unix://test.sock", app) - if err != nil { + server := server.NewGRPCServer("unix://test.sock", app) + if _, err := server.Start(); err != nil { t.Fatalf("Error starting GRPC server: %v", err.Error()) } server.SetLogger(log.TestingLogger().With("module", "abci-server")) diff --git a/server/grpc_server.go b/server/grpc_server.go index ae2a481d..90346d69 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -22,7 +22,7 @@ type GRPCServer struct { } // NewGRPCServer returns a new gRPC ABCI server -func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Service, error) { +func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) cmn.Service { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &GRPCServer{ @@ -32,8 +32,7 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Servi app: app, } s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) - _, err := s.Start() // Just start it - return s, err + return s } // OnStart starts the gRPC service diff --git a/server/server.go b/server/server.go index 45d9ac1f..0bbd65e3 100644 --- a/server/server.go +++ b/server/server.go @@ -21,9 +21,9 @@ func NewServer(protoAddr, transport string, app types.Application) (cmn.Service, var err error switch transport { case "socket": - s, err = NewSocketServer(protoAddr, app) + s = NewSocketServer(protoAddr, app) case "grpc": - s, err = NewGRPCServer(protoAddr, types.NewGRPCApplication(app)) + s = NewGRPCServer(protoAddr, types.NewGRPCApplication(app)) default: err = fmt.Errorf("Unknown server type %s", transport) } diff --git a/server/socket_server.go b/server/socket_server.go index f8d6f54a..2b01dbd7 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -29,7 +29,7 @@ type SocketServer struct { app types.Application } -func NewSocketServer(protoAddr string, app types.Application) (cmn.Service, error) { +func NewSocketServer(protoAddr string, app types.Application) cmn.Service { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &SocketServer{ @@ -40,10 +40,7 @@ func NewSocketServer(protoAddr string, app types.Application) (cmn.Service, erro conns: make(map[int]net.Conn), } s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) - // FIXME we are loosing "Starting ABCIServer" message here - // add logger to params? - _, err := s.Start() // Just start it - return s, err + return s } func (s *SocketServer) OnStart() error { From d82c7edf3aca25d762f282f0508160cf7620f645 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 12:52:33 -0400 Subject: [PATCH 252/545] update changelog and bump version --- CHANGELOG.md | 23 +++++++++++++++++++++++ version/version.go | 6 +++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7115552..29b5dcf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.5.0 (May 15, 2017) + +BREAKING CHANGES: + +- `NewSocketClient` and `NewGRPCClient` no longer start the client automatically, and don't return errors. The caller is responsible for running `client.Start()` and checking the error. +- `NewSocketServer` and `NewGRPCServer` no longer start the server automatically, and don't return errors. The caller is responsible for running `server.Start()` and checking the error. + + +FEATURES: + +- [types] new method `func (res Result) IsSameCode(compare Result) bool` checks whether two results have the same code +- [types] new methods `func (r *ResponseCheckTx) Result() Result` and `func (r *ResponseDeliverTx) Result() Result` to convert from protobuf types (for control over json serialization) +- [types] new method `func (r *ResponseQuery) Result() *ResultQuery` and struct `ResultQuery` to convert from protobuf types (for control over json serializtion) + +IMPROVEMENTS: + +- Update imports for new `tmlibs` repository +- Use the new logger +- [abci-cli] Add flags to the query command for `path`, `height`, and `prove` +- [types] use `data.Bytes` and `json` tags in the `Result` struct + +BUG FIXES: + ## 0.4.1 (April 18, 2017) IMPROVEMENTS: diff --git a/version/version.go b/version/version.go index 7b02c593..6687721f 100644 --- a/version/version.go +++ b/version/version.go @@ -3,7 +3,7 @@ package version // NOTE: we should probably be versioning the ABCI and the abci-cli separately const Maj = "0" -const Min = "4" -const Fix = "1" +const Min = "5" +const Fix = "0" -const Version = "0.4.1" +const Version = "0.5.0" From 5dabeffb35c027d7087a12149685daa68989168b Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 12:59:44 -0400 Subject: [PATCH 253/545] fixes from review --- example/block_aware/block_aware_test.go | 3 +-- example/example_test.go | 7 +++---- tests/test_app/app.go | 4 ++-- types/validators.go | 6 +++++- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 38acdd51..05a5c05c 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -27,11 +27,10 @@ func TestChainAware(t *testing.T) { // Connect to the socket client := abcicli.NewSocketClient("unix://test.sock", false) + client.SetLogger(log.TestingLogger().With("module", "abci-client")) if _, err := client.Start(); err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } - client.SetLogger(log.TestingLogger().With("module", "abci-client")) - client.Start() defer client.Stop() n := uint64(5) diff --git a/example/example_test.go b/example/example_test.go index 7e116c59..e9505f22 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -39,19 +39,18 @@ func testStream(t *testing.T, app types.Application) { // Start the listener server := server.NewSocketServer("unix://test.sock", app) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) if _, err := server.Start(); err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) } - server.SetLogger(log.TestingLogger().With("module", "abci-server")) defer server.Stop() // Connect to the socket client := abcicli.NewSocketClient("unix://test.sock", false) + client.SetLogger(log.TestingLogger().With("module", "abci-client")) if _, err := client.Start(); err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } - client.SetLogger(log.TestingLogger().With("module", "abci-client")) - client.Start() defer client.Stop() done := make(chan struct{}) @@ -113,10 +112,10 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { // Start the listener server := server.NewGRPCServer("unix://test.sock", app) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) if _, err := server.Start(); err != nil { t.Fatalf("Error starting GRPC server: %v", err.Error()) } - server.SetLogger(log.TestingLogger().With("module", "abci-server")) defer server.Stop() // Connect to the socket diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 3930957d..281c9dcb 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -38,12 +38,12 @@ func startClient(abciType string) abcicli.Client { if err != nil { panic(err.Error()) } + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + client.SetLogger(logger.With("module", "abcicli")) if _, err := client.Start(); err != nil { panic("connecting to abci_app: " + err.Error()) } - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - client.SetLogger(logger.With("module", "abcicli")) return client } diff --git a/types/validators.go b/types/validators.go index a83c6d40..95258aa2 100644 --- a/types/validators.go +++ b/types/validators.go @@ -5,6 +5,7 @@ import ( "encoding/json" "github.com/tendermint/go-wire/data" + cmn "github.com/tendermint/tmlibs/common" ) // validators implements sort @@ -38,6 +39,9 @@ func ValidatorsString(vs Validators) string { for i, v := range vs { s[i] = validatorPretty{v.PubKey, v.Power} } - b, _ := json.Marshal(s) + b, err := json.Marshal(s) + if err != nil { + cmn.PanicSanity(err.Error()) + } return string(b) } From 609c0dbc3ef549a7885d63d5bfef98691642da32 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 18 May 2017 11:39:12 +0200 Subject: [PATCH 254/545] CHANGELOG update release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b5dcf3..09d7bf5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.5.0 (May 15, 2017) +## 0.5.0 (May 18, 2017) BREAKING CHANGES: From b86da575718079396af1f7fe3609ea34be6f855d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 1 Jun 2017 23:32:55 -0400 Subject: [PATCH 256/545] scripts for building --- Makefile | 13 ++++++- scripts/abci-builder/Dockerfile | 12 +++++++ scripts/dist.sh | 53 +++++++++++++++++++++++++++++ scripts/dist_build.sh | 60 +++++++++++++++++++++++++++++++++ scripts/publish.sh | 7 ++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 scripts/abci-builder/Dockerfile create mode 100755 scripts/dist.sh create mode 100755 scripts/dist_build.sh create mode 100644 scripts/publish.sh diff --git a/Makefile b/Makefile index 19ae4260..41b8f6b6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -.PHONY: all build test fmt lint get_deps +GOTOOLS = \ + github.com/mitchellh/gox \ + github.com/Masterminds/glide all: protoc install test @@ -17,6 +19,10 @@ install: build: @ go build -i github.com/tendermint/abci/cmd/... +dist: + @ sudo bash scripts/dist.sh + @ bash scripts/publish.sh + # test.sh requires that we run the installed cmds, must not be out of date test: install find . -path ./vendor -prune -o -name *.sock -exec rm {} \; @@ -37,6 +43,11 @@ test_integrations: get_vendor_deps install test get_deps: @ go get -d `${NOVENDOR}` +tools: + go get -u -v $(GOTOOLS) + get_vendor_deps: @ go get github.com/Masterminds/glide @ glide install + +.PHONY: all build test fmt lint get_deps tools diff --git a/scripts/abci-builder/Dockerfile b/scripts/abci-builder/Dockerfile new file mode 100644 index 00000000..c56fb2ea --- /dev/null +++ b/scripts/abci-builder/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.7.4 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + zip \ + && rm -rf /var/lib/apt/lists/* + +# We want to ensure that release builds never have any cgo dependencies so we +# switch that off at the highest level. +ENV CGO_ENABLED 0 + +RUN mkdir -p $GOPATH/src/github.com/tendermint/abci +WORKDIR $GOPATH/src/github.com/tendermint/abci diff --git a/scripts/dist.sh b/scripts/dist.sh new file mode 100755 index 00000000..86884c25 --- /dev/null +++ b/scripts/dist.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -e + +REPO_NAME="abci" + +# Get the version from the environment, or try to figure it out. +if [ -z $VERSION ]; then + VERSION=$(awk -F\" '/Version =/ { print $2; exit }' < version/version.go) +fi +if [ -z "$VERSION" ]; then + echo "Please specify a version." + exit 1 +fi +echo "==> Building version $VERSION..." + +# Get the parent directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" + +# Change into that dir because we expect that. +cd "$DIR" + +## Generate the tag. +#if [ -z "$NOTAG" ]; then +# echo "==> Tagging..." +# git commit --allow-empty -a -m "Release v$VERSION" +# git tag -a -m "Version $VERSION" "v${VERSION}" master +#fi + +# Do a hermetic build inside a Docker container. +docker build -t tendermint/${REPO_NAME}-builder scripts/${REPO_NAME}-builder/ +docker run --rm -e "BUILD_TAGS=$BUILD_TAGS" -v "$(pwd)":/go/src/github.com/tendermint/${REPO_NAME} tendermint/${REPO_NAME}-builder ./scripts/dist_build.sh + +# Add $REPO_NAME and $VERSION prefix to package name. +rm -rf ./build/dist +mkdir -p ./build/dist +for FILENAME in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type f); do + FILENAME=$(basename "$FILENAME") + cp "./build/pkg/${FILENAME}" "./build/dist/${REPO_NAME}_${VERSION}_${FILENAME}" +done + +# Make the checksums. +pushd ./build/dist +shasum -a256 ./* > "./${REPO_NAME}_${VERSION}_SHA256SUMS" +popd + +# Done +echo +echo "==> Results:" +ls -hl ./build/dist + +exit 0 diff --git a/scripts/dist_build.sh b/scripts/dist_build.sh new file mode 100755 index 00000000..94fabe1b --- /dev/null +++ b/scripts/dist_build.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -e + +# Get the parent directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" + +# Change into that dir because we expect that. +cd "$DIR" + +# Get the git commit +GIT_COMMIT="$(git rev-parse --short HEAD)" +GIT_DESCRIBE="$(git describe --tags --always)" +GIT_IMPORT="github.com/tendermint/abci/version" + +# Determine the arch/os combos we're building for +XC_ARCH=${XC_ARCH:-"386 amd64 arm"} +XC_OS=${XC_OS:-"solaris darwin freebsd linux windows"} + +# Delete the old dir +echo "==> Removing old directory..." +rm -rf build/pkg +mkdir -p build/pkg + +# Make sure build tools are available. +make tools + +# Get VENDORED dependencies +make get_vendor_deps + +BINARIES=( "abci-cli" "dummy" "counter" ) + +for binary in ${BINARIES[@]}; do + # Build! + echo "==> Building..." + "$(which gox)" \ + -os="${XC_OS}" \ + -arch="${XC_ARCH}" \ + -osarch="!darwin/arm !solaris/amd64 !freebsd/amd64" \ + -ldflags "-X ${GIT_IMPORT}.GitCommit='${GIT_COMMIT}' -X ${GIT_IMPORT}.GitDescribe='${GIT_DESCRIBE}'" \ + -output "build/pkg/{{.OS}}_{{.Arch}}/$binary" \ + -tags="${BUILD_TAGS}" \ + github.com/tendermint/abci/cmd/$binary + + # Zip all the files. + echo "==> Packaging..." + for PLATFORM in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type d); do + OSARCH=$(basename "${PLATFORM}") + echo "--> ${OSARCH}" + + pushd "$PLATFORM" >/dev/null 2>&1 + zip "../${OSARCH}.zip" ./* + popd >/dev/null 2>&1 + done +done + + + +exit 0 diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100644 index 00000000..715f6c11 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,7 @@ +#! /bin/bash + +# Get the version from the environment, or try to figure it out. +if [ -z $VERSION ]; then + VERSION=$(awk -F\" '/Version =/ { print $2; exit }' < version/version.go) +fi +aws s3 cp --recursive build/dist s3://tendermint/binaries/abci/v${VERSION} --acl public-read From 7f5f48b6b9ec3964de4b07b6c3cd05d7c91aeee5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Jun 2017 12:44:00 -0400 Subject: [PATCH 257/545] dist: dont mkdir in container --- Makefile | 2 +- scripts/dist.sh | 11 +++++------ scripts/dist_build.sh | 5 ----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 41b8f6b6..9c9a7c57 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ build: @ go build -i github.com/tendermint/abci/cmd/... dist: - @ sudo bash scripts/dist.sh + @ bash scripts/dist.sh @ bash scripts/publish.sh # test.sh requires that we run the installed cmds, must not be out of date diff --git a/scripts/dist.sh b/scripts/dist.sh index 86884c25..d94ce20f 100755 --- a/scripts/dist.sh +++ b/scripts/dist.sh @@ -21,12 +21,11 @@ DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" # Change into that dir because we expect that. cd "$DIR" -## Generate the tag. -#if [ -z "$NOTAG" ]; then -# echo "==> Tagging..." -# git commit --allow-empty -a -m "Release v$VERSION" -# git tag -a -m "Version $VERSION" "v${VERSION}" master -#fi +# Delete the old dir +echo "==> Removing old directory..." +rm -rf build/pkg +mkdir -p build/pkg + # Do a hermetic build inside a Docker container. docker build -t tendermint/${REPO_NAME}-builder scripts/${REPO_NAME}-builder/ diff --git a/scripts/dist_build.sh b/scripts/dist_build.sh index 94fabe1b..0f5e3e3b 100755 --- a/scripts/dist_build.sh +++ b/scripts/dist_build.sh @@ -18,11 +18,6 @@ GIT_IMPORT="github.com/tendermint/abci/version" XC_ARCH=${XC_ARCH:-"386 amd64 arm"} XC_OS=${XC_OS:-"solaris darwin freebsd linux windows"} -# Delete the old dir -echo "==> Removing old directory..." -rm -rf build/pkg -mkdir -p build/pkg - # Make sure build tools are available. make tools From 01181721adca98ff9015ad8956a9e5cdc17d87d2 Mon Sep 17 00:00:00 2001 From: Zach Date: Thu, 24 Aug 2017 11:02:14 -0400 Subject: [PATCH 258/545] readme: update install instruction (#100) --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 2efb234d..3f2a8c05 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,15 @@ and the state machine (the application). By using a socket protocol, we enable a consensus engine running in one process to manage an application state running in another. +# Install + +``` +go get github.com/tendermint/abci +cd $GOPATH/src/github.com/tendermint/abci +glide install +go install ./cmd/... +``` + For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-application-blockchain-interface), and the more detailed [application developer's guide](https://tendermint.com/docs/guides/app-development). From f1094f760b80ed35d709ed446646b716ded7a6f2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 4 Sep 2017 15:32:03 -0400 Subject: [PATCH 259/545] types: remove redundant version file --- types/version.go | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 types/version.go diff --git a/types/version.go b/types/version.go deleted file mode 100644 index 719c6c98..00000000 --- a/types/version.go +++ /dev/null @@ -1,7 +0,0 @@ -package types - -const Maj = "0" -const Min = "3" // ResponseInfo, ResponseEndBlock -const Fix = "0" // - -const Version = Maj + "." + Min + "." + Fix From a0724296592f63c0b7fdbc4eec1a7e53b6f4eb55 Mon Sep 17 00:00:00 2001 From: Peng Zhong Date: Thu, 7 Sep 2017 13:32:56 +0800 Subject: [PATCH 260/545] Fix blog post link for ABCI We moved our blog to Medium. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f2a8c05..56d1ce29 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ glide install go install ./cmd/... ``` -For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://tendermint.com/blog/abci-the-application-blockchain-interface), +For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://blog.cosmos.network/abci-the-application-blockchain-interface-f1bd8278cdd7), and the more detailed [application developer's guide](https://tendermint.com/docs/guides/app-development). Previously, the ABCI was referred to as TMSP. From f279171a2888adf20293d3c6e8ff4f4bf2c80655 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 18 Sep 2017 15:51:48 -0400 Subject: [PATCH 261/545] use request structs for InitChain and BeginBlock --- client/client.go | 12 ++++++------ client/grpc_client.go | 16 ++++++++-------- client/local_client.go | 20 ++++++++++---------- client/socket_client.go | 16 ++++++++-------- example/block_aware/block_aware_app.go | 2 +- example/block_aware/block_aware_test.go | 2 +- example/dummy/persistent_dummy.go | 8 ++++---- server/socket_server.go | 4 ++-- types/application.go | 17 +++++++++-------- types/base_app.go | 4 ++-- types/messages.go | 8 ++++---- types/result.go | 1 + 12 files changed, 56 insertions(+), 54 deletions(-) diff --git a/client/client.go b/client/client.go index c911dd87..3cc5df36 100644 --- a/client/client.go +++ b/client/client.go @@ -20,7 +20,7 @@ type Client interface { SetOptionAsync(key string, value string) *ReqRes DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes - QueryAsync(reqQuery types.RequestQuery) *ReqRes + QueryAsync(types.RequestQuery) *ReqRes CommitAsync() *ReqRes FlushSync() error @@ -29,15 +29,15 @@ type Client interface { SetOptionSync(key string, value string) (res types.Result) DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) - QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) + QuerySync(types.RequestQuery) (resQuery types.ResponseQuery, err error) CommitSync() (res types.Result) - InitChainAsync(validators []*types.Validator) *ReqRes - BeginBlockAsync(hash []byte, header *types.Header) *ReqRes + InitChainAsync(types.RequestInitChain) *ReqRes + BeginBlockAsync(types.RequestBeginBlock) *ReqRes EndBlockAsync(height uint64) *ReqRes - InitChainSync(validators []*types.Validator) (err error) - BeginBlockSync(hash []byte, header *types.Header) (err error) + InitChainSync(types.RequestInitChain) (err error) + BeginBlockSync(types.RequestBeginBlock) (err error) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) } diff --git a/client/grpc_client.go b/client/grpc_client.go index 9743cdf6..a990455f 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -190,8 +190,8 @@ func (cli *grpcClient) CommitAsync() *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Commit{res}}) } -func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { - req := types.ToRequestInitChain(validators) +func (cli *grpcClient) InitChainAsync(params types.RequestInitChain) *ReqRes { + req := types.ToRequestInitChain(params) res, err := cli.client.InitChain(context.Background(), req.GetInitChain(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -199,8 +199,8 @@ func (cli *grpcClient) InitChainAsync(validators []*types.Validator) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_InitChain{res}}) } -func (cli *grpcClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { - req := types.ToRequestBeginBlock(hash, header) +func (cli *grpcClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { + req := types.ToRequestBeginBlock(params) res, err := cli.client.BeginBlock(context.Background(), req.GetBeginBlock(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -319,13 +319,13 @@ func (cli *grpcClient) CommitSync() (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *grpcClient) InitChainSync(validators []*types.Validator) (err error) { - cli.InitChainAsync(validators) +func (cli *grpcClient) InitChainSync(params types.RequestInitChain) (err error) { + cli.InitChainAsync(params) return cli.Error() } -func (cli *grpcClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { - cli.BeginBlockAsync(hash, header) +func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { + cli.BeginBlockAsync(params) return cli.Error() } diff --git a/client/local_client.go b/client/local_client.go index 37f76abb..6bf455c6 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -109,23 +109,23 @@ func (app *localClient) CommitAsync() *ReqRes { ) } -func (app *localClient) InitChainAsync(validators []*types.Validator) *ReqRes { +func (app *localClient) InitChainAsync(params types.RequestInitChain) *ReqRes { app.mtx.Lock() - app.Application.InitChain(validators) + app.Application.InitChain(params) reqRes := app.callback( - types.ToRequestInitChain(validators), + types.ToRequestInitChain(params), types.ToResponseInitChain(), ) app.mtx.Unlock() return reqRes } -func (app *localClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { +func (app *localClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { app.mtx.Lock() - app.Application.BeginBlock(hash, header) + app.Application.BeginBlock(params) app.mtx.Unlock() return app.callback( - types.ToRequestBeginBlock(hash, header), + types.ToRequestBeginBlock(params), types.ToResponseBeginBlock(), ) } @@ -192,16 +192,16 @@ func (app *localClient) CommitSync() (res types.Result) { return res } -func (app *localClient) InitChainSync(validators []*types.Validator) (err error) { +func (app *localClient) InitChainSync(params types.RequestInitChain) (err error) { app.mtx.Lock() - app.Application.InitChain(validators) + app.Application.InitChain(params) app.mtx.Unlock() return nil } -func (app *localClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { +func (app *localClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { app.mtx.Lock() - app.Application.BeginBlock(hash, header) + app.Application.BeginBlock(params) app.mtx.Unlock() return nil } diff --git a/client/socket_client.go b/client/socket_client.go index f95eac5c..1da93494 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -255,12 +255,12 @@ func (cli *socketClient) CommitAsync() *ReqRes { return cli.queueRequest(types.ToRequestCommit()) } -func (cli *socketClient) InitChainAsync(validators []*types.Validator) *ReqRes { - return cli.queueRequest(types.ToRequestInitChain(validators)) +func (cli *socketClient) InitChainAsync(params types.RequestInitChain) *ReqRes { + return cli.queueRequest(types.ToRequestInitChain(params)) } -func (cli *socketClient) BeginBlockAsync(hash []byte, header *types.Header) *ReqRes { - return cli.queueRequest(types.ToRequestBeginBlock(hash, header)) +func (cli *socketClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { + return cli.queueRequest(types.ToRequestBeginBlock(params)) } func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { @@ -352,8 +352,8 @@ func (cli *socketClient) CommitSync() (res types.Result) { return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} } -func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error) { - cli.queueRequest(types.ToRequestInitChain(validators)) +func (cli *socketClient) InitChainSync(params types.RequestInitChain) (err error) { + cli.queueRequest(types.ToRequestInitChain(params)) cli.FlushSync() if err := cli.Error(); err != nil { return err @@ -361,8 +361,8 @@ func (cli *socketClient) InitChainSync(validators []*types.Validator) (err error return nil } -func (cli *socketClient) BeginBlockSync(hash []byte, header *types.Header) (err error) { - cli.queueRequest(types.ToRequestBeginBlock(hash, header)) +func (cli *socketClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { + cli.queueRequest(types.ToRequestBeginBlock(params)) cli.FlushSync() if err := cli.Error(); err != nil { return err diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index 8bacecd1..c88f2289 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -55,7 +55,7 @@ func (app *ChainAwareApplication) Query(reqQuery types.RequestQuery) (resQuery t } } -func (app *ChainAwareApplication) BeginBlock(hash []byte, header *types.Header) { +func (app *ChainAwareApplication) BeginBlock(reqBeginBlock types.RequestBeginBlock) { app.beginCount++ return } diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 05a5c05c..64b6755e 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -37,7 +37,7 @@ func TestChainAware(t *testing.T) { hash := []byte("fake block hash") header := &types.Header{} for i := uint64(0); i < n; i++ { - client.BeginBlockSync(hash, header) + client.BeginBlockSync(&types.RequestBeginBlock{hash, header}) client.EndBlockSync(i) client.CommitSync() } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index fb59a272..303876e8 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -106,8 +106,8 @@ func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types. } // Save the validators in the merkle tree -func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) { - for _, v := range validators { +func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) { + for _, v := range params.Validators { r := app.updateValidator(v) if r.IsErr() { app.logger.Error("Error updating validators", "r", r) @@ -116,9 +116,9 @@ func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) } // Track the block hash and header information -func (app *PersistentDummyApplication) BeginBlock(hash []byte, header *types.Header) { +func (app *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { // update latest block info - app.blockHeader = header + app.blockHeader = params.Header // reset valset changes app.changes = make([]*types.Validator, 0) diff --git a/server/socket_server.go b/server/socket_server.go index 2b01dbd7..88011a05 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -186,10 +186,10 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types resQuery := s.app.Query(*r.Query) responses <- types.ToResponseQuery(resQuery) case *types.Request_InitChain: - s.app.InitChain(r.InitChain.Validators) + s.app.InitChain(*r.InitChain) responses <- types.ToResponseInitChain() case *types.Request_BeginBlock: - s.app.BeginBlock(r.BeginBlock.Hash, r.BeginBlock.Header) + s.app.BeginBlock(*r.BeginBlock) responses <- types.ToResponseBeginBlock() case *types.Request_EndBlock: resEndBlock := s.app.EndBlock(r.EndBlock.Height) diff --git a/types/application.go b/types/application.go index b45305f8..8f17bf50 100644 --- a/types/application.go +++ b/types/application.go @@ -4,27 +4,28 @@ import ( context "golang.org/x/net/context" ) -// Applications +// Application is an interface that enables any finite, deterministic state machine +// to be driven by a blockchain-based replication engine via the ABCI type Application interface { // 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 + Query(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 + InitChain(RequestInitChain) // Initialize blockchain with validators and other info from TendermintCore + BeginBlock(RequestBeginBlock) // Signals the beginning of a block + DeliverTx(tx []byte) Result // Deliver a tx for full processing EndBlock(height uint64) ResponseEndBlock // Signals the end of a block, returns changes to the validator set Commit() Result // Commit the state and return the application Merkle root hash } //------------------------------------ -// GRPC wrapper for application +// GRPCApplication is a GRPC wrapper for Application type GRPCApplication struct { app Application } @@ -71,12 +72,12 @@ func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*Re } func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - app.app.InitChain(req.Validators) + app.app.InitChain(*req) return &ResponseInitChain{}, nil // NOTE: empty return } func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { - app.app.BeginBlock(req.Hash, req.Header) + app.app.BeginBlock(*req) return &ResponseBeginBlock{}, nil // NOTE: empty return } diff --git a/types/base_app.go b/types/base_app.go index 1d4f84b8..71c99cc2 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -31,10 +31,10 @@ func (app *BaseApplication) Query(reqQuery RequestQuery) (resQuery ResponseQuery return } -func (app *BaseApplication) InitChain(validators []*Validator) { +func (app *BaseApplication) InitChain(reqInitChain RequestInitChain) { } -func (app *BaseApplication) BeginBlock(hash []byte, header *Header) { +func (app *BaseApplication) BeginBlock(reqBeginBlock RequestBeginBlock) { } func (app *BaseApplication) EndBlock(height uint64) (resEndBlock ResponseEndBlock) { diff --git a/types/messages.go b/types/messages.go index fe2d310a..c7f24a13 100644 --- a/types/messages.go +++ b/types/messages.go @@ -55,15 +55,15 @@ func ToRequestQuery(reqQuery RequestQuery) *Request { } } -func ToRequestInitChain(validators []*Validator) *Request { +func ToRequestInitChain(reqInitChain RequestInitChain) *Request { return &Request{ - Value: &Request_InitChain{&RequestInitChain{validators}}, + Value: &Request_InitChain{&reqInitChain}, } } -func ToRequestBeginBlock(hash []byte, header *Header) *Request { +func ToRequestBeginBlock(reqBeginBlock RequestBeginBlock) *Request { return &Request{ - Value: &Request_BeginBlock{&RequestBeginBlock{hash, header}}, + Value: &Request_BeginBlock{&reqBeginBlock}, } } diff --git a/types/result.go b/types/result.go index 7bf52c90..abf1e964 100644 --- a/types/result.go +++ b/types/result.go @@ -6,6 +6,7 @@ import ( "github.com/tendermint/go-wire/data" ) +// Result is a common result object for ABCI calls. // CONTRACT: a zero Result is OK. type Result struct { Code CodeType `json:"code"` From 318345f9969ac28e3a2006182bc0e3b6462ba66e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Sep 2017 00:10:13 -0400 Subject: [PATCH 262/545] fix tests --- example/block_aware/block_aware_test.go | 2 +- example/dummy/dummy_test.go | 6 +++--- types/messages.go | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 64b6755e..2777ce1a 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -37,7 +37,7 @@ func TestChainAware(t *testing.T) { hash := []byte("fake block hash") header := &types.Header{} for i := uint64(0); i < n; i++ { - client.BeginBlockSync(&types.RequestBeginBlock{hash, header}) + client.BeginBlockSync(types.RequestBeginBlock{hash, header}) client.EndBlockSync(i) client.CommitSync() } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index e180af3e..495e7858 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -91,7 +91,7 @@ func TestPersistentDummyInfo(t *testing.T) { header := &types.Header{ Height: uint64(height), } - dummy.BeginBlock(hash, header) + dummy.BeginBlock(types.RequestBeginBlock{hash, header}) dummy.EndBlock(height) dummy.Commit() @@ -120,7 +120,7 @@ func TestValSetChanges(t *testing.T) { vals[i] = &types.Validator{pubkey, uint64(power)} } // iniitalize with the first nInit - dummy.InitChain(vals[:nInit]) + dummy.InitChain(types.RequestInitChain{vals[:nInit]}) vals1, vals2 := vals[:nInit], dummy.Validators() valsEqual(t, vals1, vals2) @@ -180,7 +180,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ Height: height, } - dummy.BeginBlock(hash, header) + dummy.BeginBlock(types.RequestBeginBlock{hash, header}) for _, tx := range txs { if r := dummy.DeliverTx(tx); r.IsErr() { t.Fatal(r) diff --git a/types/messages.go b/types/messages.go index c7f24a13..7918e0ef 100644 --- a/types/messages.go +++ b/types/messages.go @@ -49,21 +49,21 @@ func ToRequestCommit() *Request { } } -func ToRequestQuery(reqQuery RequestQuery) *Request { +func ToRequestQuery(req RequestQuery) *Request { return &Request{ - Value: &Request_Query{&reqQuery}, + Value: &Request_Query{&req}, } } -func ToRequestInitChain(reqInitChain RequestInitChain) *Request { +func ToRequestInitChain(req RequestInitChain) *Request { return &Request{ - Value: &Request_InitChain{&reqInitChain}, + Value: &Request_InitChain{&req}, } } -func ToRequestBeginBlock(reqBeginBlock RequestBeginBlock) *Request { +func ToRequestBeginBlock(req RequestBeginBlock) *Request { return &Request{ - Value: &Request_BeginBlock{&reqBeginBlock}, + Value: &Request_BeginBlock{&req}, } } From bd9f1d0d4c9ae1ceb689581c8c10ea4995e4cfc7 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 21 Sep 2017 15:21:08 -0400 Subject: [PATCH 263/545] metalinter: add linter to Makefile like tendermint --- Makefile | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9c9a7c57..cbdc66e1 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ GOTOOLS = \ github.com/mitchellh/gox \ - github.com/Masterminds/glide + github.com/Masterminds/glide \ + github.com/alecthomas/gometalinter all: protoc install test @@ -50,4 +51,38 @@ get_vendor_deps: @ go get github.com/Masterminds/glide @ glide install +metalinter: tools + @gometalinter --install + gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... + +metalinter_test: tools + @gometalinter --install + gometalinter --vendor --deadline=600s --disable-all \ + --enable=deadcode \ + --enable=gas \ + --enable=goimports \ + --enable=gosimple \ + --enable=gotype \ + --enable=ineffassign \ + --enable=misspell \ + --enable=safesql \ + --enable=structcheck \ + --enable=varcheck \ + ./... + + #--enable=aligncheck \ + #--enable=dupl \ + #--enable=errcheck \ + #--enable=goconst \ + #--enable=gocyclo \ + #--enable=golint \ <== comments on anything exported + #--enable=interfacer \ + #--enable=megacheck \ + #--enable=staticcheck \ + #--enable=unconvert \ + #--enable=unparam \ + #--enable=unused \ + #--enable=vet \ + #--enable=vetshadow \ + .PHONY: all build test fmt lint get_deps tools From 6a378d30f3d1eb962144a5b585d177335b0f4868 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 21 Sep 2017 15:26:43 -0400 Subject: [PATCH 264/545] linting: cover the basics --- client/grpc_client.go | 2 +- client/socket_client.go | 16 +++++----------- cmd/abci-cli/abci-cli.go | 4 ++-- example/block_aware/block_aware_app.go | 1 - example/dummy/dummy_test.go | 2 +- example/dummy/persistent_dummy.go | 7 ++----- tests/test_app/app.go | 4 ++-- 7 files changed, 13 insertions(+), 23 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index a990455f..e9a74026 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -113,7 +113,7 @@ func (cli *grpcClient) SetResponseCallback(resCb Callback) { //---------------------------------------- // GRPC calls are synchronous, but some callbacks expect to be called asynchronously // (eg. the mempool expects to be able to lock to remove bad txs from cache). -// To accomodate, we finish each call in its own go-routine, +// To accommodate, we finish each call in its own go-routine, // which is expensive, but easy - if you want something better, use the socket protocol! // maybe one day, if people really want it, we use grpc streams, // but hopefully not :D diff --git a/client/socket_client.go b/client/socket_client.go index 1da93494..74df9326 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -19,9 +19,9 @@ const ( LOG = "" ) -const reqQueueSize = 256 // TODO make configurable -const maxResponseSize = 1048576 // 1MB TODO make configurable -const flushThrottleMS = 20 // Don't wait longer than... +const reqQueueSize = 256 // TODO make configurable +// const maxResponseSize = 1048576 // 1MB TODO make configurable +const flushThrottleMS = 20 // Don't wait longer than... // This is goroutine-safe, but users should beware that // the application in general is not meant to be interfaced @@ -355,19 +355,13 @@ func (cli *socketClient) CommitSync() (res types.Result) { func (cli *socketClient) InitChainSync(params types.RequestInitChain) (err error) { cli.queueRequest(types.ToRequestInitChain(params)) cli.FlushSync() - if err := cli.Error(); err != nil { - return err - } - return nil + return cli.Error() } func (cli *socketClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { cli.queueRequest(types.ToRequestBeginBlock(params)) cli.FlushSync() - if err := cli.Error(); err != nil { - return err - } - return nil + return cli.Error() } func (cli *socketClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 0f1dd82d..b96c0346 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -183,12 +183,12 @@ func badCmd(c *cli.Context, cmd string) { //Generates new Args array based off of previous call args to maintain flag persistence func persistentArgs(line []byte) []string { - //generate the arguments to run from orginal os.Args + // generate the arguments to run from original os.Args // to maintain flag arguments args := os.Args args = args[:len(args)-1] // remove the previous command argument - if len(line) > 0 { //prevents introduction of extra space leading to argument parse errors + if len(line) > 0 { // prevents introduction of extra space leading to argument parse errors args = append(args, strings.Split(string(line), " ")...) } return args diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index c88f2289..8a031da2 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -57,7 +57,6 @@ func (app *ChainAwareApplication) Query(reqQuery types.RequestQuery) (resQuery t func (app *ChainAwareApplication) BeginBlock(reqBeginBlock types.RequestBeginBlock) { app.beginCount++ - return } func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 495e7858..a616025e 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -166,7 +166,7 @@ func TestValSetChanges(t *testing.T) { makeApplyBlock(t, dummy, 3, diff, tx1) - vals1 = append([]*types.Validator{v1}, vals1[1:len(vals1)]...) + vals1 = append([]*types.Validator{v1}, vals1[1:]...) vals2 = dummy.Validators() valsEqual(t, vals1, vals2) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 303876e8..371cf4ce 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -187,10 +187,7 @@ func MakeValSetChangeTx(pubkey []byte, power uint64) []byte { } func isValidatorTx(tx []byte) bool { - if strings.HasPrefix(string(tx), ValidatorSetChangePrefix) { - return true - } - return false + return strings.HasPrefix(string(tx), ValidatorSetChangePrefix) } // format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx @@ -232,7 +229,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types app.app.state.Set(key, value.Bytes()) } - // we only update the changes array if we succesfully updated the tree + // we only update the changes array if we successfully updated the tree app.changes = append(app.changes, v) return types.OK diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 281c9dcb..30202b6a 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -80,7 +80,7 @@ func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da } } -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() { @@ -94,4 +94,4 @@ func checkTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, data panic(fmt.Sprintf("CheckTx response data was unexpected. Got %X expected %X", data, dataExp)) } -} +}*/ From 36e96c5bf1b104650bd2a43c7e7d7995964df933 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 21 Sep 2017 15:32:06 -0400 Subject: [PATCH 265/545] linting: catch some errors --- Makefile | 2 +- client/grpc_client.go | 4 +++- client/socket_client.go | 4 +++- server/grpc_server.go | 4 +++- server/socket_server.go | 4 +++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index cbdc66e1..13f5dae7 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ metalinter: tools metalinter_test: tools @gometalinter --install gometalinter --vendor --deadline=600s --disable-all \ + --enable=aligncheck \ --enable=deadcode \ --enable=gas \ --enable=goimports \ @@ -70,7 +71,6 @@ metalinter_test: tools --enable=varcheck \ ./... - #--enable=aligncheck \ #--enable=dupl \ #--enable=errcheck \ #--enable=goconst \ diff --git a/client/grpc_client.go b/client/grpc_client.go index e9a74026..31ca3db2 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -41,7 +41,9 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { } func (cli *grpcClient) OnStart() error { - cli.BaseService.OnStart() + if err := cli.BaseService.OnStart(); err != nil { + return err + } RETRY_LOOP: for { diff --git a/client/socket_client.go b/client/socket_client.go index 74df9326..4c7265cd 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -57,7 +57,9 @@ func NewSocketClient(addr string, mustConnect bool) *socketClient { } func (cli *socketClient) OnStart() error { - cli.BaseService.OnStart() + if err := cli.BaseService.OnStart(); err != nil { + return err + } var err error var conn net.Conn diff --git a/server/grpc_server.go b/server/grpc_server.go index 90346d69..ac3d728a 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -37,7 +37,9 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) cmn.Servic // OnStart starts the gRPC service func (s *GRPCServer) OnStart() error { - s.BaseService.OnStart() + if err := s.BaseService.OnStart(); err != nil { + return err + } ln, err := net.Listen(s.proto, s.addr) if err != nil { return err diff --git a/server/socket_server.go b/server/socket_server.go index 88011a05..4b64a5f0 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -44,7 +44,9 @@ func NewSocketServer(protoAddr string, app types.Application) cmn.Service { } func (s *SocketServer) OnStart() error { - s.BaseService.OnStart() + if err := s.BaseService.OnStart(); err != nil { + return err + } ln, err := net.Listen(s.proto, s.addr) if err != nil { return err From 65eb7e89745205aa30c3bba38c377fea0f233056 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 21 Sep 2017 15:46:51 -0400 Subject: [PATCH 266/545] linted, somewhat --- Makefile | 12 ++++++------ circle.yml | 1 + tests/test_app/app.go | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 13f5dae7..418ba3ee 100644 --- a/Makefile +++ b/Makefile @@ -61,28 +61,28 @@ metalinter_test: tools --enable=aligncheck \ --enable=deadcode \ --enable=gas \ + --enable=goconst \ --enable=goimports \ --enable=gosimple \ --enable=gotype \ --enable=ineffassign \ + --enable=megacheck \ --enable=misspell \ + --enable=staticcheck \ --enable=safesql \ --enable=structcheck \ + --enable=unconvert \ + --enable=unused \ --enable=varcheck \ + --enable=vetshadow \ ./... #--enable=dupl \ #--enable=errcheck \ - #--enable=goconst \ #--enable=gocyclo \ #--enable=golint \ <== comments on anything exported #--enable=interfacer \ - #--enable=megacheck \ - #--enable=staticcheck \ - #--enable=unconvert \ #--enable=unparam \ - #--enable=unused \ #--enable=vet \ - #--enable=vetshadow \ .PHONY: all build test fmt lint get_deps tools diff --git a/circle.yml b/circle.yml index 6355bc04..ab89e13d 100644 --- a/circle.yml +++ b/circle.yml @@ -18,4 +18,5 @@ checkout: test: override: - "go version" + - "cd $REPO && make metalinter_test" - "cd $REPO && make test_integrations" diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 30202b6a..11ade88c 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -59,7 +59,7 @@ func commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(fmt.Sprintf("committing %v\nlog: %v", log)) + panic(fmt.Sprintf("committing %v\nlog: %v", log, res.Log)) } if !bytes.Equal(res.Data, hashExp) { panic(fmt.Sprintf("Commit hash was unexpected. Got %X expected %X", From 0e7d974410cbb67eefa227de0fc3be8cc7ff604a Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 21 Sep 2017 16:02:01 -0400 Subject: [PATCH 267/545] install --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index ab89e13d..daa4218e 100644 --- a/circle.yml +++ b/circle.yml @@ -18,5 +18,5 @@ checkout: test: override: - "go version" - - "cd $REPO && make metalinter_test" + - "cd $REPO && make get_vendor_deps && make metalinter_test" - "cd $REPO && make test_integrations" From a3ac8254900d7ab7a36ae38f30b8d113e485f106 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Sep 2017 09:14:20 -0400 Subject: [PATCH 268/545] small fix --- tests/test_app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 11ade88c..ab794769 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -59,7 +59,7 @@ func commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() _, data, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(fmt.Sprintf("committing %v\nlog: %v", log, res.Log)) + panic(fmt.Sprintf("committing err %v\n", res)) } if !bytes.Equal(res.Data, hashExp) { panic(fmt.Sprintf("Commit hash was unexpected. Got %X expected %X", From fe426de5d47af1593448fded9f8e9ef07ead7762 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 22 Sep 2017 09:45:50 -0400 Subject: [PATCH 269/545] lint: couple more fixes --- tests/test_app/app.go | 2 +- types/application.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index ab794769..7fc3ace0 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -57,7 +57,7 @@ func setOption(client abcicli.Client, key, value string) { func commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() - _, data, log := res.Code, res.Data, res.Log + _, data, _ := res.Code, res.Data, res.Log if res.IsErr() { panic(fmt.Sprintf("committing err %v\n", res)) } diff --git a/types/application.go b/types/application.go index 8f17bf50..b596685c 100644 --- a/types/application.go +++ b/types/application.go @@ -1,4 +1,4 @@ -package types +package types // nolint: goimports import ( context "golang.org/x/net/context" @@ -18,7 +18,7 @@ type Application interface { // Consensus Connection InitChain(RequestInitChain) // Initialize blockchain with validators and other info from TendermintCore BeginBlock(RequestBeginBlock) // Signals the beginning of a block - DeliverTx(tx []byte) Result // Deliver a tx for full processing + 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 } From 96d2a2c92fef7acc5b8bbd7fddd72e4234f6c461 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 22 Sep 2017 09:38:14 -0400 Subject: [PATCH 270/545] readme: re-organize & update docs links --- README.md | 99 ++++++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 56d1ce29..f1b2ebb3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ and the state machine (the application). By using a socket protocol, we enable a consensus engine running in one process to manage an application state running in another. -# Install +## Install ``` go get github.com/tendermint/abci @@ -17,18 +17,54 @@ glide install go install ./cmd/... ``` -For more information on ABCI, motivations, and tutorials, please visit [our blog post](https://blog.cosmos.network/abci-the-application-blockchain-interface-f1bd8278cdd7), -and the more detailed [application developer's guide](https://tendermint.com/docs/guides/app-development). +For background information on ABCI, motivations, and tendermint, please visit [the documentation](http://tendermint.readthedocs.io/en/master/). +The two guides to focus on are the `Application Development Guide` and `Using ABCI-CLI`. Previously, the ABCI was referred to as TMSP. -Other implementations: -* C++ [cpp-tmsp](https://github.com/mdyring/cpp-tmsp) by Martin Dyring-Andersen -* JavaScript [js-abci](https://github.com/tendermint/js-abci) -* Java [jABCI](https://github.com/jTendermint/jabci) -* Erlang [abci_server](https://github.com/KrzysiekJ/abci_server) by Krzysztof Jurewicz +The community has provided a number of addtional implementations, see the `Tendermint Ecosystem` in [the documentation](http://tendermint.readthedocs.io/en/master/). -# Specification +## Implementation + +We provide three implementations of the ABCI in Go: + +- ABCI-socket +- GRPC +- Golang in-process + +### Socket + +ABCI is best implemented as a streaming protocol. +The socket implementation provides for asynchronous, ordered message passing over unix or tcp. +Messages are serialized using Protobuf3 and length-prefixed. +Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. + +For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. + +### GRPC + +GRPC is an rpc framework native to Protocol Buffers with support in many languages. +Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than +the ordered, asynchronous socket protocol. + +Note the length-prefixing used in the socket implementation does not apply for GRPC. + +### In Process + +The simplest implementation just uses function calls within Go. +This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. + +## Example Apps + +The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. +See [the documentation](http://tendermint.readthedocs.io/en/master/) for more details. + +Multiple example apps are included: +- the `counter` application, which illustrates nonce checking in txs +- the `dummy` application, which illustrates a simple key-value merkle tree +- the `dummy --persistent` application, which augments the dummy with persistence and validator set changes + +## Specification The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers. To build it, run @@ -42,7 +78,7 @@ Note we also include a [GRPC](http://www.grpc.io/docs) service definition. For the specification as an interface in Go, see the [types/application.go file](https://github.com/tendermint/abci/blob/master/types/application.go). -## Message Types +### Message Types ABCI requests/responses are defined as simple Protobuf messages in [this schema file](https://github.com/tendermint/abci/blob/master/types/types.proto). TendermintCore sends the requests, and the ABCI application sends the responses. @@ -148,49 +184,6 @@ Here, we describe the requests and responses as function arguments and return va * __Usage__:
* Echo a string to test an abci client/server implementation - #### Flush * __Usage__:
* Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. - - -# Implementation - -We provide three implementations of the ABCI in Go: - -1. ABCI-socket -2. GRPC -3. Golang in-process - -## Socket - -ABCI is best implemented as a streaming protocol. -The socket implementation provides for asynchronous, ordered message passing over unix or tcp. -Messages are serialized using Protobuf3 and length-prefixed. -Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. - -For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. - -## GRPC - -GRPC is an rpc framework native to Protocol Buffers with support in many languages. -Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than -the ordered, asynchronous socket protocol. - -Note the length-prefixing used in the socket implementation does not apply for GRPC. - -## In Process - -The simplest implementation just uses function calls within Go. -This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. - - -# Tools and Apps - -The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. -See the [guide](https://tendermint.com/docs/guides/abci-cli) for more details. - -Multiple example apps are included: -- the `counter` application, which illustrates nonce checking in txs -- the `dummy` application, which illustrates a simple key-value merkle tree -- the `dummy --persistent` application, which augments the dummy with persistence and validator set changes From 47d6f71e5a7c7adad77c15783e0ea127f5a81df6 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 22 Sep 2017 10:09:05 -0400 Subject: [PATCH 271/545] Makefile: remove redundant lint --- Makefile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 418ba3ee..d097ae72 100644 --- a/Makefile +++ b/Makefile @@ -33,12 +33,6 @@ test: install fmt: @ go fmt ./... -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: @@ -85,4 +79,4 @@ metalinter_test: tools #--enable=unparam \ #--enable=vet \ -.PHONY: all build test fmt lint get_deps tools +.PHONY: all build test fmt get_deps tools From 39b206f2c13dcc8423f4fb18c930c3b455a51eaa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Sep 2017 10:38:45 -0400 Subject: [PATCH 272/545] version bump, changelog, glide --- CHANGELOG.md | 11 +++++++++++ glide.lock | 27 ++++++++++++++------------- version/version.go | 4 ++-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09d7bf5e..fa9236db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 0.6.0 (September 22, 2017) + +BREAKING CHANGES: + +- [types/client] app.BeginBlock takes RequestBeginBlock +- [types/client] app.InitChain takes RequestInitChain + +IMPROVEMENTS: + +- various linting + ## 0.5.0 (May 18, 2017) BREAKING CHANGES: diff --git a/glide.lock b/glide.lock index 55c5cdb3..7b79f0e5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: f9c2ddad16bf8652076a93bd9f398bb498eefb2f5bd2c89a77d966ebd12feec8 -updated: 2017-05-15T10:11:42.094564957-04:00 +updated: 2017-09-22T10:34:17.228026799-04:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -7,8 +7,6 @@ imports: - btcec - name: github.com/btcsuite/fastsha256 version: 637e656429416087660c84436a2a035d69d54e2e -- name: github.com/clipperhouse/typewriter - version: c1a48da378ebb7db1db9f35981b5cc24bf2e5b85 - name: github.com/go-kit/kit version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 subpackages: @@ -17,6 +15,12 @@ imports: - log/term - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 +- name: github.com/go-playground/locales + version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 + subpackages: + - currency +- name: github.com/go-playground/universal-translator + version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf @@ -31,7 +35,7 @@ imports: - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: ff09b135c25aae272398c51a07235b90a75aa4f0 + version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -53,17 +57,17 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: a42b10e0feb465eb56fbc6bb5b71d57ef646ec57 + version: e6ea9499ff958479e4a921850d2382eb599f204c - name: github.com/tendermint/go-wire - version: 301a758c9d28e9f3900ff5d545403cf4e5f6e73f + version: 5f88da3dbc1a72844e6dfaf274ce87f851d488eb subpackages: - data - name: github.com/tendermint/merkleeyes - version: c722818b460381bc5b82e38c73ff6e22a9df624d + version: 2f6e5d31e7a35045d8d0a5895cb1fec33dd4d32b subpackages: - iavl - name: github.com/tendermint/tmlibs - version: 812d9f9b84d1dfe4cb46ce021b3a2d97b48d1292 + version: bffe6744ec277d60f707ab442e25513617842f8e subpackages: - common - db @@ -98,11 +102,6 @@ imports: - transform - unicode/bidi - unicode/norm -- name: golang.org/x/tools - version: 144c6642b5d832d6c44a53dad6ee61665dd432ce - subpackages: - - go/ast/astutil - - imports - name: google.golang.org/genproto version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 subpackages: @@ -123,6 +122,8 @@ imports: - status - tap - transport +- name: gopkg.in/go-playground/validator.v9 + version: d529ee1b0f30352444f507cc6cdac96bfd12decc testImports: - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 diff --git a/version/version.go b/version/version.go index 6687721f..34b1230e 100644 --- a/version/version.go +++ b/version/version.go @@ -3,7 +3,7 @@ package version // NOTE: we should probably be versioning the ABCI and the abci-cli separately const Maj = "0" -const Min = "5" +const Min = "6" const Fix = "0" -const Version = "0.5.0" +const Version = "0.6.0" From 667c2543eaf634792155bf29b829fdee3a6d0e1f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Sep 2017 11:10:39 -0400 Subject: [PATCH 273/545] use request struct for Info --- client/client.go | 4 +- client/grpc_client.go | 12 +- client/local_client.go | 10 +- client/socket_client.go | 8 +- cmd/abci-cli/abci-cli.go | 7 +- example/counter/counter.go | 2 +- example/dummy/dummy.go | 2 +- example/dummy/dummy_test.go | 4 +- example/dummy/persistent_dummy.go | 4 +- server/socket_server.go | 2 +- types/application.go | 4 +- types/base_app.go | 8 +- types/messages.go | 4 +- types/types.pb.go | 282 ++++++++++++------------------ types/types.proto | 1 + 15 files changed, 152 insertions(+), 202 deletions(-) diff --git a/client/client.go b/client/client.go index 3cc5df36..51d04124 100644 --- a/client/client.go +++ b/client/client.go @@ -16,7 +16,7 @@ type Client interface { FlushAsync() *ReqRes EchoAsync(msg string) *ReqRes - InfoAsync() *ReqRes + InfoAsync(types.RequestInfo) *ReqRes SetOptionAsync(key string, value string) *ReqRes DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes @@ -25,7 +25,7 @@ type Client interface { FlushSync() error EchoSync(msg string) (res types.Result) - InfoSync() (resInfo types.ResponseInfo, err error) + InfoSync(types.RequestInfo) (resInfo types.ResponseInfo, err error) SetOptionSync(key string, value string) (res types.Result) DeliverTxSync(tx []byte) (res types.Result) CheckTxSync(tx []byte) (res types.Result) diff --git a/client/grpc_client.go b/client/grpc_client.go index 31ca3db2..30f5d088 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -138,8 +138,8 @@ func (cli *grpcClient) FlushAsync() *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Flush{res}}) } -func (cli *grpcClient) InfoAsync() *ReqRes { - req := types.ToRequestInfo() +func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes { + req := types.ToRequestInfo(params) res, err := cli.client.Info(context.Background(), req.GetInfo(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -174,8 +174,8 @@ func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_CheckTx{res}}) } -func (cli *grpcClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { - req := types.ToRequestQuery(reqQuery) +func (cli *grpcClient) QueryAsync(params types.RequestQuery) *ReqRes { + req := types.ToRequestQuery(params) res, err := cli.client.Query(context.Background(), req.GetQuery(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -263,8 +263,8 @@ func (cli *grpcClient) FlushSync() error { return nil } -func (cli *grpcClient) InfoSync() (resInfo types.ResponseInfo, err error) { - reqres := cli.InfoAsync() +func (cli *grpcClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { + reqres := cli.InfoAsync(req) if err = cli.Error(); err != nil { return resInfo, err } diff --git a/client/local_client.go b/client/local_client.go index 6bf455c6..8494a468 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -49,12 +49,12 @@ func (app *localClient) EchoAsync(msg string) *ReqRes { ) } -func (app *localClient) InfoAsync() *ReqRes { +func (app *localClient) InfoAsync(req types.RequestInfo) *ReqRes { app.mtx.Lock() - resInfo := app.Application.Info() + resInfo := app.Application.Info(req) app.mtx.Unlock() return app.callback( - types.ToRequestInfo(), + types.ToRequestInfo(req), types.ToResponseInfo(resInfo), ) } @@ -150,10 +150,10 @@ func (app *localClient) EchoSync(msg string) (res types.Result) { return types.OK.SetData([]byte(msg)) } -func (app *localClient) InfoSync() (resInfo types.ResponseInfo, err error) { +func (app *localClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { app.mtx.Lock() defer app.mtx.Unlock() - resInfo = app.Application.Info() + resInfo = app.Application.Info(req) return resInfo, nil } diff --git a/client/socket_client.go b/client/socket_client.go index 4c7265cd..fd9d0ae9 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -233,8 +233,8 @@ func (cli *socketClient) FlushAsync() *ReqRes { return cli.queueRequest(types.ToRequestFlush()) } -func (cli *socketClient) InfoAsync() *ReqRes { - return cli.queueRequest(types.ToRequestInfo()) +func (cli *socketClient) InfoAsync(req types.RequestInfo) *ReqRes { + return cli.queueRequest(types.ToRequestInfo(req)) } func (cli *socketClient) SetOptionAsync(key string, value string) *ReqRes { @@ -290,8 +290,8 @@ func (cli *socketClient) FlushSync() error { return cli.Error() } -func (cli *socketClient) InfoSync() (resInfo types.ResponseInfo, err error) { - reqres := cli.queueRequest(types.ToRequestInfo()) +func (cli *socketClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { + reqres := cli.queueRequest(types.ToRequestInfo(req)) cli.FlushSync() if err := cli.Error(); err != nil { return resInfo, err diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index b96c0346..c7316949 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -250,7 +250,12 @@ func cmdEcho(c *cli.Context) error { // Get some info from the application func cmdInfo(c *cli.Context) error { - resInfo, err := client.InfoSync() + args := c.Args() + var version string + if len(args) == 1 { + version = args[0] + } + resInfo, err := client.InfoSync(types.RequestInfo{version}) if err != nil { return err } diff --git a/example/counter/counter.go b/example/counter/counter.go index c4e4e267..d2478ae2 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -19,7 +19,7 @@ func NewCounterApplication(serial bool) *CounterApplication { return &CounterApplication{serial: serial} } -func (app *CounterApplication) Info() types.ResponseInfo { +func (app *CounterApplication) Info(req types.RequestInfo) types.ResponseInfo { return types.ResponseInfo{Data: cmn.Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 4485deac..5db71f96 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -20,7 +20,7 @@ func NewDummyApplication() *DummyApplication { return &DummyApplication{state: state} } -func (app *DummyApplication) Info() (resInfo types.ResponseInfo) { +func (app *DummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index a616025e..fa9d531b 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -80,7 +80,7 @@ func TestPersistentDummyInfo(t *testing.T) { dummy := NewPersistentDummyApplication(dir) height := uint64(0) - resInfo := dummy.Info() + resInfo := dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) } @@ -95,7 +95,7 @@ func TestPersistentDummyInfo(t *testing.T) { dummy.EndBlock(height) dummy.Commit() - resInfo = dummy.Info() + resInfo = dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 371cf4ce..d392be53 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -55,8 +55,8 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { app.logger = l } -func (app *PersistentDummyApplication) Info() (resInfo types.ResponseInfo) { - resInfo = app.app.Info() +func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { + resInfo = app.app.Info(req) lastBlock := LoadLastBlock(app.db) resInfo.LastBlockHeight = lastBlock.Height resInfo.LastBlockAppHash = lastBlock.AppHash diff --git a/server/socket_server.go b/server/socket_server.go index 4b64a5f0..304a2c7f 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -169,7 +169,7 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Flush: responses <- types.ToResponseFlush() case *types.Request_Info: - resInfo := s.app.Info() + resInfo := s.app.Info(*r.Info) responses <- types.ToResponseInfo(resInfo) case *types.Request_SetOption: so := r.SetOption diff --git a/types/application.go b/types/application.go index b596685c..3d9716b7 100644 --- a/types/application.go +++ b/types/application.go @@ -8,7 +8,7 @@ import ( // to be driven by a blockchain-based replication engine via the ABCI type Application interface { // Info/Query Connection - Info() ResponseInfo // Return application info + Info(RequestInfo) ResponseInfo // Return application info SetOption(key string, value string) (log string) // Set application option Query(RequestQuery) ResponseQuery // Query for state @@ -43,7 +43,7 @@ func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*Resp } func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { - resInfo := app.app.Info() + resInfo := app.app.Info(*req) return &resInfo, nil } diff --git a/types/base_app.go b/types/base_app.go index 71c99cc2..94607e9a 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -7,7 +7,7 @@ func NewBaseApplication() *BaseApplication { return &BaseApplication{} } -func (app *BaseApplication) Info() (resInfo ResponseInfo) { +func (app *BaseApplication) Info(req RequestInfo) (resInfo ResponseInfo) { return } @@ -27,14 +27,14 @@ func (app *BaseApplication) Commit() Result { return NewResultOK([]byte("nil"), "") } -func (app *BaseApplication) Query(reqQuery RequestQuery) (resQuery ResponseQuery) { +func (app *BaseApplication) Query(req RequestQuery) (resQuery ResponseQuery) { return } -func (app *BaseApplication) InitChain(reqInitChain RequestInitChain) { +func (app *BaseApplication) InitChain(req RequestInitChain) { } -func (app *BaseApplication) BeginBlock(reqBeginBlock RequestBeginBlock) { +func (app *BaseApplication) BeginBlock(req RequestBeginBlock) { } func (app *BaseApplication) EndBlock(height uint64) (resEndBlock ResponseEndBlock) { diff --git a/types/messages.go b/types/messages.go index 7918e0ef..be272c38 100644 --- a/types/messages.go +++ b/types/messages.go @@ -19,9 +19,9 @@ func ToRequestFlush() *Request { } } -func ToRequestInfo() *Request { +func ToRequestInfo(req RequestInfo) *Request { return &Request{ - Value: &Request_Info{&RequestInfo{}}, + Value: &Request_Info{&req}, } } diff --git a/types/types.pb.go b/types/types.pb.go index f5966453..4ca304ac 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -61,64 +61,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package -// 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) -type MessageType int32 - -const ( - MessageType_NullMessage MessageType = 0 - MessageType_Echo MessageType = 1 - MessageType_Flush MessageType = 2 - MessageType_Info MessageType = 3 - MessageType_SetOption MessageType = 4 - MessageType_Exception MessageType = 5 - MessageType_DeliverTx MessageType = 17 - MessageType_CheckTx MessageType = 18 - MessageType_Commit MessageType = 19 - MessageType_Query MessageType = 20 - MessageType_InitChain MessageType = 21 - MessageType_BeginBlock MessageType = 22 - MessageType_EndBlock MessageType = 23 -) - -var MessageType_name = map[int32]string{ - 0: "NullMessage", - 1: "Echo", - 2: "Flush", - 3: "Info", - 4: "SetOption", - 5: "Exception", - 17: "DeliverTx", - 18: "CheckTx", - 19: "Commit", - 20: "Query", - 21: "InitChain", - 22: "BeginBlock", - 23: "EndBlock", -} -var MessageType_value = map[string]int32{ - "NullMessage": 0, - "Echo": 1, - "Flush": 2, - "Info": 3, - "SetOption": 4, - "Exception": 5, - "DeliverTx": 17, - "CheckTx": 18, - "Commit": 19, - "Query": 20, - "InitChain": 21, - "BeginBlock": 22, - "EndBlock": 23, -} - -func (x MessageType) String() string { - return proto.EnumName(MessageType_name, int32(x)) -} -func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - type CodeType int32 const ( @@ -225,7 +167,7 @@ var CodeType_value = map[string]int32{ func (x CodeType) String() string { return proto.EnumName(CodeType_name, int32(x)) } -func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } type Request struct { // Types that are valid to be assigned to Value: @@ -652,6 +594,7 @@ func (*RequestFlush) ProtoMessage() {} func (*RequestFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } type RequestInfo struct { + Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` } func (m *RequestInfo) Reset() { *m = RequestInfo{} } @@ -659,6 +602,13 @@ func (m *RequestInfo) String() string { return proto.CompactTextStrin func (*RequestInfo) ProtoMessage() {} func (*RequestInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (m *RequestInfo) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + type RequestSetOption struct { Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` @@ -1523,7 +1473,7 @@ func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } type ResponseEndBlock struct { - Diffs []*Validator `protobuf:"bytes,4,rep,name=diffs" json:"diffs,omitempty"` + Diffs []*Validator `protobuf:"bytes,1,rep,name=diffs" json:"diffs,omitempty"` } func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } @@ -1720,7 +1670,6 @@ func init() { proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") - proto.RegisterEnum("types.MessageType", MessageType_name, MessageType_value) proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) } @@ -2129,112 +2078,107 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 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, + // 1625 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x59, 0x6f, 0xdb, 0xc6, + 0x16, 0x36, 0xb5, 0xeb, 0xd8, 0x96, 0xe9, 0xb1, 0x6c, 0xcb, 0xba, 0xf7, 0x21, 0xe0, 0x45, 0x6e, + 0xec, 0xdc, 0xdc, 0xa4, 0x70, 0x90, 0x22, 0x6e, 0x8a, 0x02, 0xde, 0x62, 0x0b, 0x41, 0x13, 0x97, + 0x59, 0x5e, 0x5a, 0x54, 0xa0, 0xc9, 0x91, 0xc4, 0x5a, 0x9a, 0x61, 0xc8, 0xa1, 0x23, 0xf7, 0x37, + 0xe4, 0xbd, 0x3f, 0xa1, 0xef, 0x05, 0xfa, 0x17, 0x0a, 0x74, 0x5f, 0x7e, 0x51, 0x31, 0x0b, 0x57, + 0x93, 0x41, 0x1f, 0xf2, 0x22, 0xf0, 0x6c, 0x33, 0x73, 0xce, 0x9c, 0xf3, 0x9d, 0x33, 0x82, 0x55, + 0x76, 0xe5, 0xe1, 0xe0, 0x9e, 0xf8, 0xbd, 0xeb, 0xf9, 0x94, 0x51, 0x54, 0x17, 0x84, 0xf1, 0x43, + 0x0d, 0x9a, 0x26, 0x7e, 0x1d, 0xe2, 0x80, 0xa1, 0x6d, 0xa8, 0x61, 0x7b, 0x42, 0x7b, 0xda, 0x0d, + 0x6d, 0x7b, 0x71, 0x17, 0xdd, 0x95, 0xea, 0x4a, 0x7a, 0x6c, 0x4f, 0xe8, 0xe9, 0x82, 0x29, 0x34, + 0xd0, 0xff, 0xa0, 0x3e, 0x9a, 0x86, 0xc1, 0xa4, 0x57, 0x11, 0xaa, 0x6b, 0x59, 0xd5, 0xc7, 0x5c, + 0x74, 0xba, 0x60, 0x4a, 0x1d, 0xbe, 0xac, 0x4b, 0x46, 0xb4, 0x57, 0x2d, 0x5a, 0x76, 0x40, 0x46, + 0x62, 0x59, 0xae, 0x81, 0x1e, 0x02, 0x04, 0x98, 0x0d, 0xa9, 0xc7, 0x5c, 0x4a, 0x7a, 0x35, 0xa1, + 0xbf, 0x99, 0xd5, 0x7f, 0x8e, 0xd9, 0x33, 0x21, 0x3e, 0x5d, 0x30, 0xdb, 0x41, 0x44, 0x70, 0x4b, + 0x07, 0x4f, 0xdd, 0x4b, 0xec, 0x0f, 0xd9, 0xbc, 0x57, 0x2f, 0xb2, 0x3c, 0x92, 0xf2, 0x17, 0x73, + 0x6e, 0xe9, 0x44, 0x04, 0xda, 0x85, 0x96, 0x3d, 0xc1, 0xf6, 0x05, 0xb7, 0x6b, 0x08, 0xbb, 0xf5, + 0xac, 0xdd, 0x21, 0x97, 0x0a, 0xab, 0xa6, 0x2d, 0x3f, 0xd1, 0x5d, 0x68, 0xd8, 0x74, 0x36, 0x73, + 0x59, 0xaf, 0x29, 0x2c, 0xba, 0x39, 0x0b, 0x21, 0x3b, 0x5d, 0x30, 0x95, 0x16, 0x0f, 0xd7, 0xeb, + 0x10, 0xfb, 0x57, 0xbd, 0x56, 0x51, 0xb8, 0x3e, 0xe3, 0x22, 0x1e, 0x2e, 0xa1, 0xc3, 0x5d, 0x71, + 0x89, 0xcb, 0x86, 0xf6, 0xc4, 0x72, 0x49, 0xaf, 0x5d, 0xe4, 0xca, 0x80, 0xb8, 0xec, 0x90, 0x8b, + 0xb9, 0x2b, 0x6e, 0x44, 0xa0, 0x47, 0xb0, 0x78, 0x8e, 0xc7, 0x2e, 0x19, 0x9e, 0x4f, 0xa9, 0x7d, + 0xd1, 0x03, 0x61, 0xda, 0xcb, 0x9a, 0x1e, 0x70, 0x85, 0x03, 0x2e, 0x3f, 0x5d, 0x30, 0xe1, 0x3c, + 0xa6, 0xd0, 0x03, 0x68, 0x63, 0xe2, 0x28, 0xd3, 0x45, 0x61, 0xba, 0x91, 0xcb, 0x00, 0xe2, 0x44, + 0x86, 0x2d, 0xac, 0xbe, 0x0f, 0x9a, 0x50, 0xbf, 0xb4, 0xa6, 0x21, 0x36, 0x6e, 0xc1, 0x62, 0x2a, + 0x53, 0x50, 0x0f, 0x9a, 0x33, 0x1c, 0x04, 0xd6, 0x18, 0x8b, 0x74, 0x6a, 0x9b, 0x11, 0x69, 0x74, + 0x60, 0x29, 0x9d, 0x27, 0x29, 0x43, 0x9e, 0x0b, 0xdc, 0xf0, 0x12, 0xfb, 0x01, 0x4f, 0x00, 0x65, + 0xa8, 0x48, 0xe3, 0x23, 0xd0, 0xf3, 0x49, 0x80, 0x74, 0xa8, 0x5e, 0xe0, 0x2b, 0xa5, 0xc9, 0x3f, + 0x51, 0x57, 0x1d, 0x48, 0xa4, 0x66, 0xdb, 0x54, 0xa7, 0x33, 0x62, 0xdb, 0x38, 0x0d, 0x50, 0x07, + 0x2a, 0x6c, 0x2e, 0x4c, 0x97, 0xcc, 0x0a, 0x9b, 0x1b, 0x37, 0xa0, 0x93, 0xbd, 0xf2, 0x6b, 0x1a, + 0x4e, 0x7c, 0x74, 0x71, 0x67, 0x08, 0x41, 0xcd, 0xb1, 0x98, 0xa5, 0x34, 0xc4, 0x37, 0xe7, 0x79, + 0x16, 0x9b, 0xa8, 0xed, 0xc5, 0x37, 0xda, 0x80, 0xc6, 0x04, 0xbb, 0xe3, 0x09, 0x13, 0x35, 0x50, + 0x33, 0x15, 0xc5, 0xcf, 0xea, 0xf9, 0xf4, 0x12, 0x8b, 0x54, 0x6f, 0x99, 0x92, 0x30, 0x56, 0x60, + 0x39, 0x93, 0x48, 0xc6, 0x51, 0x7c, 0xf8, 0xf8, 0xe2, 0xd1, 0x07, 0x00, 0x97, 0xd6, 0xd4, 0x75, + 0x2c, 0x46, 0xfd, 0xa0, 0xa7, 0xdd, 0xa8, 0x6e, 0x2f, 0xee, 0xea, 0xea, 0xbe, 0x5e, 0x45, 0x02, + 0x33, 0xa5, 0x63, 0x3c, 0x85, 0xd5, 0x6b, 0x39, 0xc0, 0x4f, 0x3b, 0xb1, 0x82, 0x49, 0xe4, 0x01, + 0xff, 0x46, 0x37, 0xf9, 0x69, 0x2d, 0x07, 0xfb, 0xaa, 0xba, 0x97, 0xd5, 0xb2, 0xa7, 0x82, 0x69, + 0x2a, 0xa1, 0xb1, 0x03, 0x2b, 0xb9, 0xc4, 0x48, 0xf9, 0xa9, 0xa5, 0xfd, 0x34, 0xde, 0xd6, 0xa1, + 0x65, 0xe2, 0xc0, 0xa3, 0x24, 0xc0, 0xe8, 0x21, 0xb4, 0xf1, 0xdc, 0xc6, 0xb2, 0xc6, 0xb5, 0x5c, + 0x8e, 0x4a, 0x9d, 0xe3, 0x48, 0xce, 0xf3, 0x3b, 0x56, 0x46, 0x3b, 0x0a, 0x9f, 0xf2, 0xa0, 0xa3, + 0x8c, 0xd2, 0x00, 0x75, 0x27, 0x02, 0xa8, 0x6a, 0xae, 0x40, 0xa5, 0x6e, 0x0e, 0xa1, 0x76, 0x14, + 0x42, 0xd5, 0x0a, 0x17, 0xce, 0x40, 0xd4, 0x5e, 0x06, 0xa2, 0xea, 0x85, 0xc7, 0x2f, 0xc1, 0xa8, + 0xbd, 0x0c, 0x46, 0x35, 0x0a, 0x4d, 0x4b, 0x40, 0xea, 0x7e, 0x0a, 0xa4, 0x9a, 0xb9, 0xda, 0x94, + 0x86, 0x05, 0x28, 0x75, 0x2f, 0x46, 0xa9, 0x56, 0x0e, 0xd7, 0x94, 0x49, 0x1e, 0xa6, 0xee, 0x44, + 0x30, 0xd5, 0x2e, 0x0c, 0x5a, 0x0e, 0xa7, 0xf6, 0x32, 0x38, 0x05, 0x85, 0xee, 0x94, 0x00, 0xd5, + 0xc7, 0x59, 0xa0, 0x92, 0x68, 0xb3, 0x95, 0xb3, 0x2d, 0x45, 0xaa, 0x0f, 0xd3, 0x48, 0xb5, 0x94, + 0xc3, 0x47, 0x95, 0x0b, 0xef, 0x84, 0xaa, 0x1d, 0x5e, 0x09, 0xb9, 0x4c, 0xe3, 0xb5, 0x88, 0x7d, + 0x9f, 0xfa, 0x0a, 0x4b, 0x24, 0x61, 0x6c, 0xf3, 0x8a, 0x4f, 0xf2, 0xeb, 0x1d, 0xb0, 0x26, 0xaa, + 0x36, 0x95, 0x5d, 0xc6, 0x37, 0x5a, 0x62, 0x2b, 0x90, 0x2d, 0x8d, 0x16, 0x6d, 0x85, 0x16, 0x29, + 0xb4, 0xab, 0x64, 0xd0, 0x0e, 0xdd, 0x86, 0xd5, 0xa9, 0x15, 0x30, 0xe9, 0xe6, 0x30, 0x03, 0x1f, + 0x2b, 0x5c, 0x20, 0xfd, 0x93, 0x38, 0xf2, 0x7f, 0x58, 0x4b, 0xe9, 0x5a, 0x9e, 0x37, 0x14, 0x45, + 0x5d, 0x13, 0x45, 0xad, 0xc7, 0xda, 0xfb, 0x9e, 0x77, 0x6a, 0x05, 0x13, 0xe3, 0x66, 0xe2, 0x7f, + 0x06, 0x49, 0xa7, 0x74, 0x1c, 0x21, 0xe9, 0x94, 0x8e, 0x8d, 0x2f, 0x13, 0xb5, 0x04, 0x34, 0xff, + 0x03, 0x35, 0x9b, 0x3a, 0xd2, 0xfb, 0xce, 0xee, 0x8a, 0x8a, 0xfb, 0x21, 0x75, 0xf0, 0x8b, 0x2b, + 0x0f, 0x9b, 0x42, 0x18, 0x7b, 0x5a, 0x49, 0xe1, 0xa2, 0x5a, 0xbf, 0x9a, 0xac, 0xff, 0x05, 0x07, + 0x90, 0x4c, 0xf6, 0xbe, 0xcf, 0xd5, 0xbf, 0xd3, 0x92, 0x0b, 0x91, 0x68, 0xfd, 0x8f, 0x16, 0xef, + 0x42, 0xdd, 0x25, 0x0e, 0x9e, 0x8b, 0xd5, 0xab, 0xa6, 0x24, 0xa2, 0x36, 0x53, 0x15, 0x3b, 0x66, + 0xdb, 0x8c, 0x0c, 0xb2, 0x24, 0x14, 0xa0, 0xd3, 0x91, 0x00, 0x86, 0x25, 0x53, 0x12, 0x29, 0x58, + 0x6c, 0x64, 0xe0, 0x5f, 0x1d, 0xba, 0x99, 0x1c, 0xfa, 0x73, 0xde, 0x82, 0xd2, 0xd5, 0xf9, 0x3e, + 0x23, 0xb2, 0x96, 0xdc, 0x67, 0x5c, 0x97, 0x46, 0x17, 0xd0, 0xf5, 0x82, 0x93, 0xad, 0x36, 0x5b, + 0x4a, 0xe8, 0xbf, 0x50, 0x77, 0xdc, 0xd1, 0xa8, 0xbc, 0xd9, 0x48, 0xb1, 0xf1, 0x6d, 0x05, 0x1a, + 0xb2, 0x55, 0xa0, 0x2d, 0x0e, 0x5b, 0x96, 0x4b, 0x86, 0xae, 0x13, 0x95, 0x8b, 0xa0, 0x07, 0x4e, + 0x2a, 0x26, 0x95, 0x4c, 0x4c, 0x10, 0xd4, 0x98, 0x3b, 0xc3, 0x2a, 0xd3, 0xc5, 0x37, 0xda, 0x84, + 0x26, 0x09, 0x67, 0x43, 0x36, 0x0f, 0x44, 0xb4, 0x6b, 0x66, 0x83, 0x84, 0xb3, 0x17, 0xf3, 0x00, + 0xed, 0xc2, 0x72, 0x2a, 0xef, 0x5d, 0x47, 0xe1, 0x71, 0x47, 0x1d, 0x4d, 0x9c, 0x7b, 0x70, 0x64, + 0x2e, 0xc6, 0x15, 0x30, 0x70, 0xd0, 0x36, 0x88, 0x82, 0x18, 0x4a, 0xcc, 0x93, 0x85, 0xd2, 0x10, + 0x71, 0xeb, 0x70, 0xbe, 0x02, 0x45, 0xde, 0x07, 0xff, 0x05, 0x6d, 0x1e, 0x49, 0xa9, 0xd2, 0x14, + 0x2a, 0x2d, 0xce, 0x10, 0xc2, 0x5b, 0xb0, 0x92, 0xf4, 0x56, 0xa9, 0xd2, 0x92, 0xab, 0x24, 0x6c, + 0xa1, 0xb8, 0x05, 0xad, 0xb8, 0x20, 0xdb, 0x42, 0xa3, 0x69, 0xa9, 0x3a, 0x1c, 0x40, 0x53, 0x1d, + 0xb1, 0xb0, 0x0f, 0xdf, 0x86, 0xba, 0x67, 0xf9, 0x2c, 0x50, 0xfd, 0x2e, 0x82, 0xe3, 0x33, 0xcb, + 0xe7, 0x03, 0x90, 0xea, 0xc6, 0x52, 0xc5, 0xd8, 0x83, 0xe5, 0x0c, 0x9f, 0x67, 0x22, 0xa3, 0xcc, + 0x9a, 0xaa, 0x4e, 0x2c, 0x89, 0x78, 0x9b, 0x4a, 0xb2, 0x8d, 0xb1, 0x07, 0xed, 0xf8, 0x0e, 0xf9, + 0xb5, 0x78, 0xe1, 0xf9, 0x13, 0x35, 0x52, 0x2d, 0x99, 0x8a, 0x12, 0x89, 0x4d, 0xdf, 0xa8, 0x91, + 0xa0, 0x66, 0x4a, 0xe2, 0xf6, 0xf7, 0x75, 0x68, 0x45, 0xa9, 0x88, 0x1a, 0x50, 0x79, 0xf6, 0x44, + 0x5f, 0x40, 0xab, 0xb0, 0x3c, 0x20, 0x0c, 0xfb, 0xc4, 0x9a, 0x1e, 0x73, 0x0c, 0xd5, 0x35, 0xce, + 0x3a, 0x26, 0x36, 0x75, 0x5c, 0x32, 0x96, 0xac, 0x0a, 0x5a, 0x82, 0xd6, 0x81, 0xe5, 0x3c, 0xa5, + 0xc4, 0xc6, 0x7a, 0x15, 0xe9, 0xb0, 0xf4, 0x92, 0x58, 0x21, 0x9b, 0x50, 0xdf, 0xfd, 0x1a, 0x3b, + 0x7a, 0x0d, 0xad, 0xc3, 0xea, 0x80, 0x04, 0xe1, 0x68, 0xe4, 0xda, 0x2e, 0x26, 0xec, 0x71, 0x48, + 0x9c, 0x40, 0xaf, 0x23, 0x04, 0x9d, 0x97, 0xe4, 0x82, 0xd0, 0x37, 0x44, 0xcd, 0x1e, 0x7a, 0x03, + 0xf5, 0xa0, 0x7b, 0x60, 0x05, 0xf8, 0x28, 0xf4, 0xa6, 0xae, 0x6d, 0x31, 0xbc, 0xef, 0x38, 0x3e, + 0x0e, 0x02, 0x1d, 0xf3, 0x45, 0xb8, 0x24, 0xbb, 0xf7, 0x28, 0x32, 0xc8, 0xac, 0x8f, 0x71, 0xa0, + 0x8f, 0xd1, 0x16, 0xac, 0x5f, 0x93, 0x88, 0x9d, 0x27, 0xe8, 0xdf, 0xd0, 0xcb, 0x8b, 0x4e, 0xac, + 0xe0, 0xcc, 0x77, 0x6d, 0xac, 0xbb, 0xa8, 0x0b, 0xba, 0x94, 0x8a, 0xdb, 0x1f, 0x10, 0x2f, 0x64, + 0xfa, 0x57, 0xd1, 0xfe, 0x8a, 0xfb, 0x2c, 0x64, 0x9c, 0x7d, 0x91, 0x63, 0x9f, 0x89, 0x08, 0xeb, + 0x53, 0xb4, 0x09, 0x6b, 0x29, 0xf6, 0x73, 0xee, 0x1f, 0x8f, 0xce, 0x2c, 0x39, 0xaf, 0x14, 0xb8, + 0x63, 0x62, 0xb1, 0xd0, 0xc7, 0x3a, 0x41, 0x1b, 0x80, 0xb8, 0x44, 0x85, 0x24, 0x72, 0x9c, 0x46, + 0x3b, 0x28, 0xbe, 0xda, 0xc1, 0xcb, 0xb3, 0xa7, 0xe1, 0xd8, 0x25, 0xfa, 0x6b, 0xb4, 0x0e, 0xfa, + 0x09, 0xbd, 0x54, 0xdc, 0x63, 0xc2, 0x5c, 0x76, 0xa5, 0xff, 0xa8, 0xa1, 0x2e, 0xac, 0x24, 0xec, + 0x13, 0x9f, 0x86, 0x9e, 0xfe, 0x93, 0x86, 0x36, 0x01, 0x25, 0xdc, 0x33, 0x9f, 0x7a, 0x34, 0xb0, + 0xa6, 0xfa, 0xcf, 0x1a, 0xda, 0x80, 0xd5, 0x13, 0x7a, 0x19, 0xdf, 0x82, 0x34, 0xf8, 0x25, 0x32, + 0x88, 0xf9, 0x9f, 0xe2, 0xd9, 0x39, 0xf6, 0xf5, 0x5f, 0x35, 0xb4, 0x05, 0xdd, 0xb4, 0x20, 0x5e, + 0xeb, 0x37, 0x4d, 0x9d, 0x28, 0x16, 0xbd, 0xa2, 0x0c, 0xeb, 0xbf, 0x47, 0x6c, 0x15, 0x07, 0xb5, + 0xd0, 0x1f, 0x1a, 0x5a, 0x83, 0x4e, 0xc2, 0x16, 0xba, 0x7f, 0x6a, 0xa8, 0x0f, 0xeb, 0x19, 0xa6, + 0x4b, 0xc6, 0x67, 0x3c, 0x69, 0xf5, 0xbf, 0xb4, 0xdd, 0xb7, 0x75, 0x58, 0xd9, 0x3f, 0x38, 0x1c, + 0xec, 0x7b, 0x72, 0x03, 0xde, 0xff, 0xee, 0x41, 0x4d, 0x74, 0xf8, 0x82, 0x67, 0x6f, 0xbf, 0x68, + 0xd4, 0x44, 0xbb, 0x50, 0x17, 0x8d, 0x1e, 0x15, 0xbd, 0x7e, 0xfb, 0x85, 0x13, 0x27, 0xdf, 0x44, + 0x8e, 0x02, 0xd7, 0x1f, 0xc1, 0xfd, 0xa2, 0xb1, 0x13, 0x7d, 0x02, 0xed, 0xa4, 0x45, 0x97, 0x3d, + 0x85, 0xfb, 0xa5, 0x03, 0x28, 0xb7, 0x4f, 0x7a, 0x77, 0xd9, 0x83, 0xb8, 0x5f, 0x3a, 0x85, 0xa2, + 0x87, 0xd0, 0x8c, 0x7a, 0x73, 0xf1, 0xb3, 0xb8, 0x5f, 0x32, 0x88, 0xf2, 0xf0, 0xc8, 0xb6, 0x5b, + 0xf4, 0xda, 0xed, 0x17, 0xce, 0x96, 0xe8, 0x01, 0x34, 0x54, 0xdb, 0x2b, 0x7c, 0x51, 0xf7, 0x8b, + 0x27, 0x58, 0xee, 0x64, 0xf2, 0x30, 0x2a, 0x7b, 0x2a, 0xf7, 0x4b, 0x67, 0x53, 0xb4, 0x0f, 0x90, + 0x7a, 0x12, 0x95, 0x3e, 0x98, 0xfb, 0xe5, 0x13, 0x2a, 0x7a, 0x04, 0xad, 0xe4, 0x15, 0x54, 0xfc, + 0x6c, 0xee, 0x97, 0x0d, 0xa9, 0xe7, 0x0d, 0xf1, 0x8f, 0xcc, 0xfd, 0xbf, 0x03, 0x00, 0x00, 0xff, + 0xff, 0xbd, 0xb6, 0xa5, 0xad, 0xa6, 0x11, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 7abc354d..802d8fc5 100644 --- a/types/types.proto +++ b/types/types.proto @@ -73,6 +73,7 @@ message RequestFlush { } message RequestInfo { + string version = 1; } message RequestSetOption{ From 88cb73d95a1df0cfdacb352f9c7a911ab5bd22c0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Sep 2017 11:16:09 -0400 Subject: [PATCH 274/545] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa9236db..91bd0649 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ BREAKING CHANGES: - [types/client] app.BeginBlock takes RequestBeginBlock - [types/client] app.InitChain takes RequestInitChain +- [types/client] app.Info takes RequestInfo IMPROVEMENTS: From 15cd7fb1e3b75c436b6dee89a44db35f3d265bd0 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 4 Oct 2017 00:06:46 +0400 Subject: [PATCH 275/545] fix comment [ci skip] --- example/dummy/persistent_dummy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index d392be53..a8bfbcf0 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -67,7 +67,7 @@ func (app *PersistentDummyApplication) SetOption(key string, value string) (log return app.app.SetOption(key, value) } -// tx is either "key=value" or just arbitrary bytes +// tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { // if it starts with "val:", update the validator set // format is "val:pubkey/power" From 46d94f83259b5a3985a1c001a96276c1a901902d Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Tue, 17 Oct 2017 22:08:17 -0600 Subject: [PATCH 276/545] socketClient: fix and test for StopForError deadlock Fixes https://github.com/tendermint/abci/issues/114. Fix and test for StopForError deadlock due to accidental Mutex misuse. The test should return instantenously if StopForError works without erraneous contention, lest it regressed. --- client/socket_client.go | 2 +- client/socket_client_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 client/socket_client_test.go diff --git a/client/socket_client.go b/client/socket_client.go index fd9d0ae9..1045dea7 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -97,11 +97,11 @@ func (cli *socketClient) OnStop() { // Stop the client and set the error func (cli *socketClient) StopForError(err error) { - cli.mtx.Lock() if !cli.IsRunning() { return } + cli.mtx.Lock() if cli.err == nil { cli.err = err } diff --git a/client/socket_client_test.go b/client/socket_client_test.go new file mode 100644 index 00000000..814d5a68 --- /dev/null +++ b/client/socket_client_test.go @@ -0,0 +1,28 @@ +package abcicli_test + +import ( + "errors" + "testing" + "time" + + "github.com/tendermint/abci/client" +) + +func TestSocketClientStopForErrorDeadlock(t *testing.T) { + c := abcicli.NewSocketClient(":80", false) + err := errors.New("foo-tendermint") + + // See Issue https://github.com/tendermint/abci/issues/114 + doneChan := make(chan bool) + go func() { + defer close(doneChan) + c.StopForError(err) + c.StopForError(err) + }() + + select { + case <-doneChan: + case <-time.After(time.Second * 4): + t.Fatalf("Test took too long, potential deadlock still exists") + } +} From 9aff9f94dde85528686856815405d92f47b8fbb3 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 12:46:51 +0200 Subject: [PATCH 277/545] dummy app now uses iavl --- example/dummy/dummy.go | 23 ++++++---- example/dummy/dummy_test.go | 12 ++--- example/dummy/persistent_dummy.go | 74 +++++++++++++------------------ glide.lock | 16 +++---- glide.yaml | 4 +- 5 files changed, 59 insertions(+), 70 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 5db71f96..82927ca6 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,19 +4,20 @@ import ( "strings" "github.com/tendermint/abci/types" - "github.com/tendermint/merkleeyes/iavl" + wire "github.com/tendermint/go-wire" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/merkle" + dbm "github.com/tendermint/tmlibs/db" ) type DummyApplication struct { types.BaseApplication - state merkle.Tree + state *iavl.VersionedTree } func NewDummyApplication() *DummyApplication { - state := iavl.NewIAVLTree(0, nil) + state := iavl.NewVersionedTree(0, dbm.NewMemDB()) return &DummyApplication{state: state} } @@ -46,22 +47,26 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { if reqQuery.Prove { - value, proof, exists := app.state.Proof(reqQuery.Data) + value, proof, err := app.state.GetWithProof(reqQuery.Data) + // be stupid here + if err != nil { + panic(err) + } resQuery.Index = -1 // TODO make Proof return index resQuery.Key = reqQuery.Data resQuery.Value = value - resQuery.Proof = proof - if exists { + resQuery.Proof = wire.BinaryBytes(proof) + if value == nil { resQuery.Log = "exists" } else { resQuery.Log = "does not exist" } return } else { - index, value, exists := app.state.Get(reqQuery.Data) + index, value := app.state.Get(reqQuery.Data) resQuery.Index = int64(index) resQuery.Value = value - if exists { + if value != nil { resQuery.Log = "exists" } else { resQuery.Log = "does not exist" diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index fa9d531b..41e033bc 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -11,7 +11,7 @@ import ( "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/merkleeyes/iavl" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" ) @@ -39,9 +39,10 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string }) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := iavl.ReadProof(resQuery.Proof) + proof, err := iavl.ReadKeyExistsProof(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 + err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash) + require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash } func TestDummyKV(t *testing.T) { @@ -309,7 +310,8 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) require.Nil(t, err) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := iavl.ReadProof(resQuery.Proof) + proof, err := iavl.ReadKeyExistsProof(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 + err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash) + require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index a8bfbcf0..89bc6e72 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,13 +3,12 @@ package dummy import ( "bytes" "encoding/hex" + "path" "strconv" "strings" - "github.com/pkg/errors" "github.com/tendermint/abci/types" - wire "github.com/tendermint/go-wire" - "github.com/tendermint/merkleeyes/iavl" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" @@ -23,11 +22,11 @@ const ( type PersistentDummyApplication struct { app *DummyApplication - db dbm.DB // latest received // TODO: move to merkle tree? blockHeader *types.Header + height uint64 // validator set changes []*types.Validator @@ -36,17 +35,22 @@ type PersistentDummyApplication struct { } func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { - db := dbm.NewDB("dummy", "leveldb", dbDir) - lastBlock := LoadLastBlock(db) + name := "dummy" + dbPath := path.Join(dbDir, name+".db") + empty, _ := cmn.IsDirEmpty(dbPath) - stateTree := iavl.NewIAVLTree(0, db) - stateTree.Load(lastBlock.AppHash) + db, err := dbm.NewGoLevelDB(name, dbDir) + if err != nil { + panic(err) + } - // log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) + stateTree := iavl.NewVersionedTree(500, db) + if !empty { + stateTree.Load() + } return &PersistentDummyApplication{ app: &DummyApplication{state: stateTree}, - db: db, logger: log.NewNopLogger(), } } @@ -57,9 +61,8 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { resInfo = app.app.Info(req) - lastBlock := LoadLastBlock(app.db) - resInfo.LastBlockHeight = lastBlock.Height - resInfo.LastBlockAppHash = lastBlock.AppHash + resInfo.LastBlockHeight = app.height + resInfo.LastBlockAppHash = app.app.state.Hash() return resInfo } @@ -86,18 +89,26 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { } func (app *PersistentDummyApplication) Commit() types.Result { - // Save - appHash := app.app.state.Save() - app.logger.Info("Saved state", "root", appHash) + app.height = app.blockHeader.Height + + // Save a new version + var appHash []byte + var err error + if app.app.state.Size() > 0 { + appHash, err = app.app.state.SaveVersion(app.height) + if err != nil { + // if this wasn't a dummy app, we'd do something smarter + panic(err) + } + app.logger.Info("Saved state", "root", appHash) + } lastBlock := LastBlockInfo{ - Height: app.blockHeader.Height, + Height: app.height, AppHash: appHash, // this hash will be in the next block header } app.logger.Info("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) - SaveLastBlock(app.db, lastBlock) - return types.NewResultOK(appHash, "") } @@ -139,31 +150,6 @@ type LastBlockInfo struct { AppHash []byte } -// Get the last block from the db -func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { - buf := db.Get(lastBlockKey) - if len(buf) != 0 { - r, n, err := bytes.NewReader(buf), new(int), new(error) - wire.ReadBinaryPtr(&lastBlock, r, 0, n, err) - if *err != nil { - cmn.PanicCrisis(errors.Wrap(*err, "cannot load last block (data has been corrupted or its spec has changed)")) - } - // TODO: ensure that buf is completely read. - } - - return lastBlock -} - -func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(lastBlock, buf, n, err) - if *err != nil { - // TODO - cmn.PanicCrisis(errors.Wrap(*err, "cannot save last block")) - } - db.Set(lastBlockKey, buf.Bytes()) -} - //--------------------------------------------- // update validators diff --git a/glide.lock b/glide.lock index 7b79f0e5..d2dfc9a6 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: f9c2ddad16bf8652076a93bd9f398bb498eefb2f5bd2c89a77d966ebd12feec8 -updated: 2017-09-22T10:34:17.228026799-04:00 +hash: 876bc65024f66612325ebafcedeb3e4d5014d46b339cf7583f1c00c6bac6e32c +updated: 2017-10-18T11:59:44.724549502+02:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -57,17 +57,15 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: e6ea9499ff958479e4a921850d2382eb599f204c + version: 8e7f0e7701f92206679ad093d013b9b162427631 - name: github.com/tendermint/go-wire - version: 5f88da3dbc1a72844e6dfaf274ce87f851d488eb + version: 26ee079df7fca1958da8995c727b59759b197534 subpackages: - data -- name: github.com/tendermint/merkleeyes - version: 2f6e5d31e7a35045d8d0a5895cb1fec33dd4d32b - subpackages: - - iavl +- name: github.com/tendermint/iavl + version: ff4ffa531df48509d51f0c16c2432f986eed9fcc - name: github.com/tendermint/tmlibs - version: bffe6744ec277d60f707ab442e25513617842f8e + version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: - common - db diff --git a/glide.yaml b/glide.yaml index 11379aad..e8cf8302 100644 --- a/glide.yaml +++ b/glide.yaml @@ -8,10 +8,8 @@ import: version: develop - package: github.com/tendermint/go-wire version: develop -- package: github.com/tendermint/merkleeyes +- package: github.com/tendermint/iavl version: develop - subpackages: - - iavl - package: github.com/tendermint/tmlibs version: develop subpackages: From bae4e4acce1c364c76c95663788f9fa8c2abc312 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 13:13:18 +0200 Subject: [PATCH 278/545] Fix up commits, debug cli tests --- example/dummy/dummy.go | 17 ++++++++++++++++- example/dummy/persistent_dummy.go | 8 ++------ tests/test_cli/ex1.abci.out | 18 +++++++++--------- tests/test_cli/test.sh | 1 + 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 82927ca6..89f997a4 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,6 +1,7 @@ package dummy import ( + "fmt" "strings" "github.com/tendermint/abci/types" @@ -33,6 +34,7 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.Result { } else { app.state.Set(tx, tx) } + fmt.Println("set data") return types.OK } @@ -41,7 +43,20 @@ func (app *DummyApplication) CheckTx(tx []byte) types.Result { } func (app *DummyApplication) Commit() types.Result { - hash := app.state.Hash() + // Save a new version + var hash []byte + var err error + + if app.state.Size() > 0 { + // just add one more to height (kind of arbitrarily stupid) + height := app.state.LatestVersion() + 1 + hash, err = app.state.SaveVersion(height) + if err != nil { + // if this wasn't a dummy app, we'd do something smarter + panic(err) + } + } + return types.NewResultOK(hash, "") } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 89bc6e72..cc2d2d40 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -94,6 +94,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { // Save a new version var appHash []byte var err error + if app.app.state.Size() > 0 { appHash, err = app.app.state.SaveVersion(app.height) if err != nil { @@ -103,12 +104,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { app.logger.Info("Saved state", "root", appHash) } - lastBlock := LastBlockInfo{ - Height: app.height, - AppHash: appHash, // this hash will be in the next block header - } - - app.logger.Info("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) + app.logger.Info("Commit block", "height", app.height, "root", appHash) return types.NewResultOK(appHash, "") } diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index e434944a..c3a62d55 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -2,21 +2,21 @@ -> data: hello -> data.hex: 68656C6C6F -> info +> info -> data: {"size":0} -> data.hex: 7B2273697A65223A307D -> commit +> commit > deliver_tx "abc" -> info +> info -> data: {"size":1} -> data.hex: 7B2273697A65223A317D -> commit --> data: uü~„»×ˆíX–$ðlú‡EÑ --> data.hex: 750502FC7E84BBD788ED589624F06CFA871845D1 +> commit +-> data: IßÑ\ͬޮ—(ËûµèhŒ¥‹‘ +-> data.hex: 49DFD15CCDACDEAE9728CB01FBB5E8688CA58B91 > query "abc" -> log: exists @@ -26,9 +26,9 @@ > deliver_tx "def=xyz" -> commit --> data: v9;Š.E†°iLbžËQ²†ïÕ --> data.hex: 76393B8A182E450286B0694C629ECB51B286EFD5 +> commit +-> data: p-³"€7?¿?Ÿ‰Ú* Î,Ö+ +-> data.hex: 70102DB32280373FBF3F9F89DA2A20CE2CD62B0B > query "def" -> log: exists diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 4266dd16..8ea8d545 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -15,6 +15,7 @@ function testExample() { echo "Example $N" $APP &> /dev/null & + # $APP &> ./app.out & sleep 2 abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" killall "$APP" From d236e0eef9a6ecc12a736fdae85f635238053e24 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 18 Oct 2017 13:28:24 +0200 Subject: [PATCH 279/545] Fix trailing whitespace in tutorial test --- tests/test_cli/ex1.abci.out | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index c3a62d55..21c778c7 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -2,19 +2,19 @@ -> data: hello -> data.hex: 68656C6C6F -> info +> info -> data: {"size":0} -> data.hex: 7B2273697A65223A307D -> commit +> commit > deliver_tx "abc" -> info +> info -> data: {"size":1} -> data.hex: 7B2273697A65223A317D -> commit +> commit -> data: IßÑ\ͬޮ—(ËûµèhŒ¥‹‘ -> data.hex: 49DFD15CCDACDEAE9728CB01FBB5E8688CA58B91 @@ -26,7 +26,7 @@ > deliver_tx "def=xyz" -> commit +> commit -> data: p-³"€7?¿?Ÿ‰Ú* Î,Ö+ -> data.hex: 70102DB32280373FBF3F9F89DA2A20CE2CD62B0B From 46e1f1ae653a49f18ae813fc3a441edf219f0ce5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 14:43:34 +0200 Subject: [PATCH 280/545] Cleaup based on Antons PR comments --- example/dummy/dummy.go | 6 ++---- example/dummy/persistent_dummy.go | 7 ++++--- tests/test_cli/test.sh | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 89f997a4..7e95c859 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,7 +1,6 @@ package dummy import ( - "fmt" "strings" "github.com/tendermint/abci/types" @@ -34,7 +33,6 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.Result { } else { app.state.Set(tx, tx) } - fmt.Println("set data") return types.OK } @@ -63,7 +61,7 @@ func (app *DummyApplication) Commit() types.Result { func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { if reqQuery.Prove { value, proof, err := app.state.GetWithProof(reqQuery.Data) - // be stupid here + // if this wasn't a dummy app, we'd do something smarter if err != nil { panic(err) } @@ -71,7 +69,7 @@ func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types. resQuery.Key = reqQuery.Data resQuery.Value = value resQuery.Proof = wire.BinaryBytes(proof) - if value == nil { + if value != nil { resQuery.Log = "exists" } else { resQuery.Log = "does not exist" diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index cc2d2d40..94ce85ad 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -89,14 +89,14 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { } func (app *PersistentDummyApplication) Commit() types.Result { - app.height = app.blockHeader.Height + h := app.blockHeader.Height // Save a new version var appHash []byte var err error if app.app.state.Size() > 0 { - appHash, err = app.app.state.SaveVersion(app.height) + appHash, err = app.app.state.SaveVersion(h) if err != nil { // if this wasn't a dummy app, we'd do something smarter panic(err) @@ -104,7 +104,8 @@ func (app *PersistentDummyApplication) Commit() types.Result { app.logger.Info("Saved state", "root", appHash) } - app.logger.Info("Commit block", "height", app.height, "root", appHash) + app.height = h + app.logger.Info("Commit block", "height", h, "root", appHash) return types.NewResultOK(appHash, "") } diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 8ea8d545..4266dd16 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -15,7 +15,6 @@ function testExample() { echo "Example $N" $APP &> /dev/null & - # $APP &> ./app.out & sleep 2 abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" killall "$APP" From 7aa00e9ddd0ecb7e5dc3f003d61a834795c532d8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 14:48:07 +0200 Subject: [PATCH 281/545] Fix metalinter errors --- Makefile | 2 +- example/dummy/persistent_dummy.go | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/Makefile b/Makefile index d097ae72..8b621a9a 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,6 @@ metalinter: tools metalinter_test: tools @gometalinter --install gometalinter --vendor --deadline=600s --disable-all \ - --enable=aligncheck \ --enable=deadcode \ --enable=gas \ --enable=goconst \ @@ -71,6 +70,7 @@ metalinter_test: tools --enable=vetshadow \ ./... + # --enable=aligncheck \ <== disabled as not installed #--enable=dupl \ #--enable=errcheck \ #--enable=gocyclo \ diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 94ce85ad..20b68b9a 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -137,16 +137,6 @@ func (app *PersistentDummyApplication) EndBlock(height uint64) (resEndBlock type return types.ResponseEndBlock{Diffs: app.changes} } -//----------------------------------------- -// persist the last block info - -var lastBlockKey = []byte("lastblock") - -type LastBlockInfo struct { - Height uint64 - AppHash []byte -} - //--------------------------------------------- // update validators From 5162ed1b2b4e7c0cea98be442210b43a0b6b94b9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 19 Oct 2017 15:12:27 +0200 Subject: [PATCH 282/545] Remove gotype from metalinter so it passes (need newer go on circleci) --- Makefile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 8b621a9a..6c72d063 100644 --- a/Makefile +++ b/Makefile @@ -52,12 +52,12 @@ metalinter: tools metalinter_test: tools @gometalinter --install gometalinter --vendor --deadline=600s --disable-all \ + --enable=maligned \ --enable=deadcode \ --enable=gas \ --enable=goconst \ --enable=goimports \ --enable=gosimple \ - --enable=gotype \ --enable=ineffassign \ --enable=megacheck \ --enable=misspell \ @@ -70,13 +70,13 @@ metalinter_test: tools --enable=vetshadow \ ./... - # --enable=aligncheck \ <== disabled as not installed - #--enable=dupl \ - #--enable=errcheck \ - #--enable=gocyclo \ - #--enable=golint \ <== comments on anything exported - #--enable=interfacer \ - #--enable=unparam \ - #--enable=vet \ + #--enable=dupl \ + #--enable=errcheck \ + #--enable=gocyclo \ + #--enable=golint \ <== comments on anything exported + #--enable=gotype \ + #--enable=interfacer \ + #--enable=unparam \ + #--enable=vet \ .PHONY: all build test fmt get_deps tools From a4443ddb0c29227c619c03c660acc4b4bdf2ec38 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 23 Oct 2017 00:06:50 -0400 Subject: [PATCH 283/545] update persistent dummy for versioned iavl --- example/dummy/dummy_test.go | 12 +++++++++--- example/dummy/persistent_dummy.go | 28 +++++++++------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 41e033bc..fbc095e6 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -81,6 +81,8 @@ func TestPersistentDummyInfo(t *testing.T) { dummy := NewPersistentDummyApplication(dir) height := uint64(0) + dummy.InitChain(types.RequestInitChain{[]*types.Validator{randVal(0)}}) + resInfo := dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) @@ -103,6 +105,12 @@ func TestPersistentDummyInfo(t *testing.T) { } +func randVal(i int) *types.Validator { + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() + power := cmn.RandInt() + return &types.Validator{pubkey, uint64(power)} +} + // add a validator, remove a validator, update a validator func TestValSetChanges(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO @@ -116,9 +124,7 @@ func TestValSetChanges(t *testing.T) { nInit := 5 vals := make([]*types.Validator, total) for i := 0; i < total; i++ { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() - power := cmn.RandInt() - vals[i] = &types.Validator{pubkey, uint64(power)} + vals[i] = randVal(i) } // iniitalize with the first nInit dummy.InitChain(types.RequestInitChain{vals[:nInit]}) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 20b68b9a..de4aaa56 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -23,11 +23,6 @@ const ( type PersistentDummyApplication struct { app *DummyApplication - // latest received - // TODO: move to merkle tree? - blockHeader *types.Header - height uint64 - // validator set changes []*types.Validator @@ -61,7 +56,7 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { resInfo = app.app.Info(req) - resInfo.LastBlockHeight = app.height + resInfo.LastBlockHeight = app.app.state.LatestVersion() resInfo.LastBlockAppHash = app.app.state.Hash() return resInfo } @@ -88,24 +83,21 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { return app.app.CheckTx(tx) } +// Commit will panic if InitChain was not called func (app *PersistentDummyApplication) Commit() types.Result { - h := app.blockHeader.Height - // Save a new version + // Save a new version for next height + height := app.app.state.LatestVersion() + 1 var appHash []byte var err error - if app.app.state.Size() > 0 { - appHash, err = app.app.state.SaveVersion(h) - if err != nil { - // if this wasn't a dummy app, we'd do something smarter - panic(err) - } - app.logger.Info("Saved state", "root", appHash) + appHash, err = app.app.state.SaveVersion(height) + if err != nil { + // if this wasn't a dummy app, we'd do something smarter + panic(err) } - app.height = h - app.logger.Info("Commit block", "height", h, "root", appHash) + app.logger.Info("Commit block", "height", height, "root", appHash) return types.NewResultOK(appHash, "") } @@ -125,8 +117,6 @@ func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { - // update latest block info - app.blockHeader = params.Header // reset valset changes app.changes = make([]*types.Validator, 0) From e7ebf62092705e144a05882f7622622153333848 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 14:08:36 +0200 Subject: [PATCH 284/545] Remove empty check after iavl fixup --- example/dummy/persistent_dummy.go | 9 +-------- glide.lock | 8 ++++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index de4aaa56..15fe150d 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,7 +3,6 @@ package dummy import ( "bytes" "encoding/hex" - "path" "strconv" "strings" @@ -31,18 +30,13 @@ type PersistentDummyApplication struct { func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { name := "dummy" - dbPath := path.Join(dbDir, name+".db") - empty, _ := cmn.IsDirEmpty(dbPath) - db, err := dbm.NewGoLevelDB(name, dbDir) if err != nil { panic(err) } stateTree := iavl.NewVersionedTree(500, db) - if !empty { - stateTree.Load() - } + stateTree.Load() return &PersistentDummyApplication{ app: &DummyApplication{state: stateTree}, @@ -117,7 +111,6 @@ func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { - // reset valset changes app.changes = make([]*types.Validator, 0) } diff --git a/glide.lock b/glide.lock index d2dfc9a6..cc94dbd5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 876bc65024f66612325ebafcedeb3e4d5014d46b339cf7583f1c00c6bac6e32c -updated: 2017-10-18T11:59:44.724549502+02:00 +updated: 2017-10-23T14:04:02.596189966+02:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -63,7 +63,7 @@ imports: subpackages: - data - name: github.com/tendermint/iavl - version: ff4ffa531df48509d51f0c16c2432f986eed9fcc + version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 - name: github.com/tendermint/tmlibs version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: @@ -73,7 +73,7 @@ imports: - merkle - process - name: github.com/urfave/cli - version: d70f47eeca3afd795160003bc6e28b001d60c67c + version: 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c - name: golang.org/x/crypto version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: @@ -121,7 +121,7 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: d529ee1b0f30352444f507cc6cdac96bfd12decc + version: 6d8c18553ea1ac493d049edd6f102f52e618f085 testImports: - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 From 446e50ca9ee8ed3fbea9e5418282acf8b5842dbf Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 14:20:15 +0200 Subject: [PATCH 285/545] Moved RandVal into test helper functions, as needed in other repos for testing --- example/dummy/dummy_test.go | 15 ++------------- example/dummy/helpers.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 example/dummy/helpers.go diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index fbc095e6..751a2e91 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -10,7 +10,6 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - crypto "github.com/tendermint/go-crypto" "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" @@ -79,10 +78,9 @@ func TestPersistentDummyInfo(t *testing.T) { t.Fatal(err) } dummy := NewPersistentDummyApplication(dir) + InitDummy(dummy) height := uint64(0) - dummy.InitChain(types.RequestInitChain{[]*types.Validator{randVal(0)}}) - resInfo := dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) @@ -105,12 +103,6 @@ func TestPersistentDummyInfo(t *testing.T) { } -func randVal(i int) *types.Validator { - pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() - power := cmn.RandInt() - return &types.Validator{pubkey, uint64(power)} -} - // add a validator, remove a validator, update a validator func TestValSetChanges(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO @@ -122,10 +114,7 @@ func TestValSetChanges(t *testing.T) { // init with some validators total := 10 nInit := 5 - vals := make([]*types.Validator, total) - for i := 0; i < total; i++ { - vals[i] = randVal(i) - } + vals := RandVals(total) // iniitalize with the first nInit dummy.InitChain(types.RequestInitChain{vals[:nInit]}) diff --git a/example/dummy/helpers.go b/example/dummy/helpers.go new file mode 100644 index 00000000..55c464de --- /dev/null +++ b/example/dummy/helpers.go @@ -0,0 +1,34 @@ +package dummy + +import ( + "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" + cmn "github.com/tendermint/tmlibs/common" +) + +// RandVal creates one random validator, with a key derived +// from the input value +func RandVal(i int) *types.Validator { + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() + power := cmn.RandUint16() + 1 + return &types.Validator{pubkey, uint64(power)} +} + +// RandVals returns a list of cnt validators for initializing +// the application. Note that the keys are deterministically +// derived from the index in the array, while the power is +// random (Change this if not desired) +func RandVals(cnt int) []*types.Validator { + res := make([]*types.Validator, cnt) + for i := 0; i < cnt; i++ { + res[i] = RandVal(i) + } + return res +} + +// InitDummy initializes the dummy app with some data, +// which allows tests to pass and is fine as long as you +// don't make any tx that modify the validator state +func InitDummy(app *PersistentDummyApplication) { + app.InitChain(types.RequestInitChain{RandVals(1)}) +} From 9883013adf78a4d07d1f79224bc308d52603d063 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 18 Oct 2017 12:48:19 -0400 Subject: [PATCH 286/545] use cobra, closes #101 --- cmd/abci-cli/abci-cli.go | 381 ++++++++++++++++++--------------------- cmd/abci-cli/main.go | 5 + glide.yaml | 2 +- 3 files changed, 184 insertions(+), 204 deletions(-) create mode 100644 cmd/abci-cli/main.go diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index c7316949..acee3ea6 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -7,13 +7,15 @@ import ( "fmt" "io" "os" + "os/exec" "strings" abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - "github.com/tendermint/abci/version" + //"github.com/tendermint/abci/version" "github.com/tendermint/tmlibs/log" - "github.com/urfave/cli" + + "github.com/spf13/cobra" ) // Structure for data passed to print response. @@ -38,149 +40,135 @@ var client abcicli.Client var logger log.Logger -func main() { +// flags +var ( + address string + abci string + verbose bool - //workaround for the cli library (https://github.com/urfave/cli/issues/565) - cli.OsExiter = func(_ int) {} + path string + height int + prove bool +) - app := cli.NewApp() - app.Name = "abci-cli" - app.Usage = "abci-cli [command] [args...]" - app.Version = version.Version - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "address", - Value: "tcp://127.0.0.1:46658", - Usage: "address of application socket", - }, - cli.StringFlag{ - Name: "abci", - Value: "socket", - Usage: "socket or grpc", - }, - cli.BoolFlag{ - Name: "verbose", - Usage: "print the command and results as if it were a console session", - }, - } - app.Commands = []cli.Command{ - { - Name: "batch", - Usage: "Run a batch of abci commands against an application", - Action: func(c *cli.Context) error { - return cmdBatch(app, c) - }, - }, - { - Name: "console", - Usage: "Start an interactive abci console for multiple commands", - Action: func(c *cli.Context) error { - return cmdConsole(app, c) - }, - }, - { - Name: "echo", - Usage: "Have the application echo a message", - Action: func(c *cli.Context) error { - return cmdEcho(c) - }, - }, - { - Name: "info", - Usage: "Get some info about the application", - Action: func(c *cli.Context) error { - return cmdInfo(c) - }, - }, - { - Name: "set_option", - Usage: "Set an option on the application", - Action: func(c *cli.Context) error { - return cmdSetOption(c) - }, - }, - { - Name: "deliver_tx", - Usage: "Deliver a new tx to application", - Action: func(c *cli.Context) error { - return cmdDeliverTx(c) - }, - }, - { - Name: "check_tx", - Usage: "Validate a tx", - Action: func(c *cli.Context) error { - return cmdCheckTx(c) - }, - }, - { - Name: "commit", - Usage: "Commit the application state and return the Merkle root hash", - Action: func(c *cli.Context) error { - return cmdCommit(c) - }, - }, - { - Name: "query", - Usage: "Query application state", - Action: func(c *cli.Context) error { - return cmdQuery(c) - }, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "path", - Value: "/store", - Usage: "Path to prefix the query with", - }, - cli.IntFlag{ - Name: "height", - Value: 0, - Usage: "Height to query the blockchain at", - }, - cli.BoolFlag{ - Name: "prove", - Usage: "Whether or not to return a merkle proof of the query result", - }, - }, - }, - } - app.Before = before - err := app.Run(os.Args) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - -} - -func before(c *cli.Context) error { - if logger == nil { - logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), log.AllowError()) - } - if client == nil { - var err error - client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) +var RootCmd = &cobra.Command{ + Use: "abci-cli", + Short: "", + Long: "", + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + if logger == nil { + logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), log.AllowError()) } - client.SetLogger(logger.With("module", "abci-client")) - if _, err := client.Start(); err != nil { - return err + if client == nil { + var err error + client, err = abcicli.NewClient(address, abci, false) + if err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + client.SetLogger(logger.With("module", "abci-client")) + if _, err := client.Start(); err != nil { + return err + } } - } - return nil + return nil + }, } -// badCmd is called when we invoke with an invalid first argument (just for console for now) -func badCmd(c *cli.Context, cmd string) { - fmt.Println("Unknown command:", cmd) - fmt.Println("Please try one of the following:") - fmt.Println("") - cli.DefaultAppComplete(c) +func Execute() { + addGlobalFlags() + addCommands() + RootCmd.Execute() //err? } -//Generates new Args array based off of previous call args to maintain flag persistence +func addGlobalFlags() { + RootCmd.PersistentFlags().StringVarP(&address, "address", "", "tcp://127.0.0.1:46658", "address of application socket") + RootCmd.PersistentFlags().StringVarP(&abci, "abci", "", "socket", "socket or grpc") + RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "print the command and results as if it were a console session") +} + +func addQueryFlags() { + queryCmd.PersistentFlags().StringVarP(&path, "path", "", "/store", "Path to prefix query with") + queryCmd.PersistentFlags().IntVarP(&height, "height", "", 0, "Height to query the blockchain at") + queryCmd.PersistentFlags().BoolVarP(&prove, "prove", "", false, "Whether or not to return a merkle proof of the query result") +} + +func addCommands() { + RootCmd.AddCommand(batchCmd) + RootCmd.AddCommand(consoleCmd) + RootCmd.AddCommand(echoCmd) + RootCmd.AddCommand(infoCmd) + RootCmd.AddCommand(setOptionCmd) + RootCmd.AddCommand(deliverTxCmd) + RootCmd.AddCommand(checkTxCmd) + RootCmd.AddCommand(commitCmd) + addQueryFlags() + RootCmd.AddCommand(queryCmd) +} + +var batchCmd = &cobra.Command{ + Use: "batch", + Short: "Run a batch of abci commands against an application", + Long: "", + Run: cmdBatch, +} + +var consoleCmd = &cobra.Command{ + Use: "console", + Short: "Start an interactive abci console for multiple commands", + Long: "", + ValidArgs: []string{"batch", "echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"}, + Run: cmdConsole, +} + +var echoCmd = &cobra.Command{ + Use: "echo", + Short: "", + Long: "Have the application echo a message", + Run: cmdEcho, +} +var infoCmd = &cobra.Command{ + Use: "info", + Short: "Get some info about the application", + Long: "", + Run: cmdInfo, +} +var setOptionCmd = &cobra.Command{ + Use: "set_option", + Short: "Set an options on the application", + Long: "", + Run: cmdSetOption, +} + +var deliverTxCmd = &cobra.Command{ + Use: "deliver_tx", + Short: "Deliver a new tx to the application", + Long: "", + Run: cmdDeliverTx, +} + +var checkTxCmd = &cobra.Command{ + Use: "check_tx", + Short: "Validate a tx", + Long: "", + Run: cmdCheckTx, +} + +var commitCmd = &cobra.Command{ + Use: "commit", + Short: "Commit the application state and return the Merkle root hash", + Long: "", + Run: cmdCommit, +} + +var queryCmd = &cobra.Command{ + Use: "query", + Short: "Query the application state", + Long: "", + Run: cmdQuery, +} + +// Generates new Args array based off of previous call args to maintain flag persistence func persistentArgs(line []byte) []string { // generate the arguments to run from original os.Args @@ -196,154 +184,142 @@ func persistentArgs(line []byte) []string { //-------------------------------------------------------------------------------- -func cmdBatch(app *cli.App, c *cli.Context) error { +func cmdBatch(cmd *cobra.Command, args []string) { bufReader := bufio.NewReader(os.Stdin) for { line, more, err := bufReader.ReadLine() if more { - return errors.New("Input line is too long") + ifExit(errors.New("Input line is too long")) } else if err == io.EOF { break } else if len(line) == 0 { continue } else if err != nil { - return err + ifExit(err) } - args := persistentArgs(line) - app.Run(args) //cli prints error within its func call + pArgs := persistentArgs(line) + out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() + if err != nil { + panic(err) + } + fmt.Println(string(out)) } - return nil } -func cmdConsole(app *cli.App, c *cli.Context) error { - // don't hard exit on mistyped commands (eg. check vs check_tx) - app.CommandNotFound = badCmd +func cmdConsole(cmd *cobra.Command, args []string) { for { fmt.Printf("\n> ") bufReader := bufio.NewReader(os.Stdin) line, more, err := bufReader.ReadLine() if more { - return errors.New("Input is too long") + ifExit(errors.New("Input is too long")) } else if err != nil { - return err + ifExit(err) } - args := persistentArgs(line) - app.Run(args) //cli prints error within its func call + pArgs := persistentArgs(line) + out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() + if err != nil { + panic(err) + } + fmt.Println(string(out)) } } // Have the application echo a message -func cmdEcho(c *cli.Context) error { - args := c.Args() +func cmdEcho(cmd *cobra.Command, args []string) { if len(args) != 1 { - return errors.New("Command echo takes 1 argument") + ifExit(errors.New("Command echo takes 1 argument")) } resEcho := client.EchoSync(args[0]) - printResponse(c, response{ + printResponse(cmd, args, response{ Data: resEcho.Data, }) - return nil } // Get some info from the application -func cmdInfo(c *cli.Context) error { - args := c.Args() +func cmdInfo(cmd *cobra.Command, args []string) { var version string if len(args) == 1 { version = args[0] } resInfo, err := client.InfoSync(types.RequestInfo{version}) if err != nil { - return err + ifExit(err) } - printResponse(c, response{ + printResponse(cmd, args, response{ Data: []byte(resInfo.Data), }) - return nil } // Set an option on the application -func cmdSetOption(c *cli.Context) error { - args := c.Args() +func cmdSetOption(cmd *cobra.Command, args []string) { if len(args) != 2 { - return errors.New("Command set_option takes 2 arguments (key, value)") + ifExit(errors.New("Command set_option takes 2 arguments (key, value)")) } resSetOption := client.SetOptionSync(args[0], args[1]) - printResponse(c, response{ + printResponse(cmd, args, response{ Log: resSetOption.Log, }) - return nil } // Append a new tx to application -func cmdDeliverTx(c *cli.Context) error { - args := c.Args() +func cmdDeliverTx(cmd *cobra.Command, args []string) { if len(args) != 1 { - return errors.New("Command deliver_tx takes 1 argument") + ifExit(errors.New("Command deliver_tx takes 1 argument")) } - txBytes, err := stringOrHexToBytes(c.Args()[0]) + txBytes, err := stringOrHexToBytes(args[0]) if err != nil { - return err + ifExit(err) } res := client.DeliverTxSync(txBytes) - printResponse(c, response{ + printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, Log: res.Log, }) - return nil } // Validate a tx -func cmdCheckTx(c *cli.Context) error { - args := c.Args() +func cmdCheckTx(cmd *cobra.Command, args []string) { if len(args) != 1 { - return errors.New("Command check_tx takes 1 argument") + ifExit(errors.New("Command check_tx takes 1 argument")) } - txBytes, err := stringOrHexToBytes(c.Args()[0]) + txBytes, err := stringOrHexToBytes(args[0]) if err != nil { - return err + ifExit(err) } res := client.CheckTxSync(txBytes) - printResponse(c, response{ + printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, Log: res.Log, }) - return nil } // Get application Merkle root hash -func cmdCommit(c *cli.Context) error { +func cmdCommit(cmd *cobra.Command, args []string) { res := client.CommitSync() - printResponse(c, response{ + printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, Log: res.Log, }) - return nil } // Query application state -func cmdQuery(c *cli.Context) error { - args := c.Args() - +func cmdQuery(cmd *cobra.Command, args []string) { if len(args) != 1 { - return errors.New("Command query takes 1 argument, the query bytes") + ifExit(errors.New("Command query takes 1 argument, the query bytes")) } queryBytes, err := stringOrHexToBytes(args[0]) if err != nil { - return err + ifExit(err) } - path := c.String("path") - height := c.Int("height") - prove := c.Bool("prove") - resQuery, err := client.QuerySync(types.RequestQuery{ Data: queryBytes, Path: path, @@ -351,9 +327,9 @@ func cmdQuery(c *cli.Context) error { Prove: prove, }) if err != nil { - return err + ifExit(err) } - printResponse(c, response{ + printResponse(cmd, args, response{ Code: resQuery.Code, Log: resQuery.Log, Query: &queryResponse{ @@ -363,17 +339,14 @@ func cmdQuery(c *cli.Context) error { Proof: resQuery.Proof, }, }) - return nil } //-------------------------------------------------------------------------------- -func printResponse(c *cli.Context, rsp response) { - - verbose := c.GlobalBool("verbose") +func printResponse(cmd *cobra.Command, args []string, rsp response) { if verbose { - fmt.Println(">", c.Command.Name, strings.Join(c.Args(), " ")) + fmt.Println(">", cmd.Use, strings.Join(args, " ")) } if !rsp.Code.IsOK() { @@ -401,11 +374,6 @@ func printResponse(c *cli.Context, rsp response) { fmt.Printf("-> proof: %X\n", rsp.Query.Proof) } } - - if verbose { - fmt.Println("") - } - } // NOTE: s is interpreted as a string unless prefixed with 0x @@ -426,3 +394,10 @@ func stringOrHexToBytes(s string) ([]byte, error) { return []byte(s[1 : len(s)-1]), nil } + +func ifExit(err error) { + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cmd/abci-cli/main.go b/cmd/abci-cli/main.go new file mode 100644 index 00000000..736ef310 --- /dev/null +++ b/cmd/abci-cli/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + Execute() +} diff --git a/glide.yaml b/glide.yaml index e8cf8302..cd8c994c 100644 --- a/glide.yaml +++ b/glide.yaml @@ -18,7 +18,7 @@ import: - log - merkle - process -- package: github.com/urfave/cli +- package: github.com/spf13/cobra - package: golang.org/x/net subpackages: - context From f67e43625bf524e044bfb1d3a37dce68ccb53c71 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 18 Oct 2017 14:21:16 -0400 Subject: [PATCH 287/545] Makefile: fix linter --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 6c72d063..588e12df 100644 --- a/Makefile +++ b/Makefile @@ -70,13 +70,13 @@ metalinter_test: tools --enable=vetshadow \ ./... - #--enable=dupl \ - #--enable=errcheck \ - #--enable=gocyclo \ - #--enable=golint \ <== comments on anything exported - #--enable=gotype \ - #--enable=interfacer \ - #--enable=unparam \ - #--enable=vet \ + #--enable=dupl \ + #--enable=errcheck \ + #--enable=gocyclo \ + #--enable=golint \ <== comments on anything exported + #--enable=gotype \ + #--enable=interfacer \ + #--enable=unparam \ + #--enable=vet \ .PHONY: all build test fmt get_deps tools From 56f7d9627f82f5c767ed968641a3d56aff9d99ad Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 18 Oct 2017 14:27:39 -0400 Subject: [PATCH 288/545] update deps --- glide.lock | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index cc94dbd5..49795959 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 876bc65024f66612325ebafcedeb3e4d5014d46b339cf7583f1c00c6bac6e32c -updated: 2017-10-23T14:04:02.596189966+02:00 +hash: 1530ad93695fa2861f1572e3e1eef1b6604beb548fd4832985f6c6350260c2b3 +updated: 2017-10-18T14:27:16.428209213-04:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -30,12 +30,18 @@ imports: - ptypes/any - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 +- name: github.com/inconshreveable/mousetrap + version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d +- name: github.com/spf13/cobra + version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 +- name: github.com/spf13/pflag + version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -72,8 +78,6 @@ imports: - log - merkle - process -- name: github.com/urfave/cli - version: 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c - name: golang.org/x/crypto version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: From df5d9ac1bbf08439367fc5fc002162ae5903dc4b Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 18 Oct 2017 15:00:23 -0400 Subject: [PATCH 289/545] consolidate counter/dummy into the binary, #95 --- cmd/abci-cli/abci-cli.go | 99 ++++++++++++++++++++++++++++++++++++++++ cmd/counter/main.go | 41 ----------------- cmd/dummy/main.go | 50 -------------------- 3 files changed, 99 insertions(+), 91 deletions(-) delete mode 100644 cmd/counter/main.go delete mode 100644 cmd/dummy/main.go diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index acee3ea6..93b00543 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -11,8 +11,12 @@ import ( "strings" abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/example/counter" + "github.com/tendermint/abci/example/dummy" + "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" //"github.com/tendermint/abci/version" + cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" "github.com/spf13/cobra" @@ -42,13 +46,23 @@ var logger log.Logger // flags var ( + // global address string abci string verbose bool + // query path string height int prove bool + + // counter + addrC string + serial bool + + // dummy + addrD string + persist string ) var RootCmd = &cobra.Command{ @@ -93,6 +107,15 @@ func addQueryFlags() { queryCmd.PersistentFlags().BoolVarP(&prove, "prove", "", false, "Whether or not to return a merkle proof of the query result") } +func addCounterFlags() { + counterCmd.PersistentFlags().StringVarP(&addrC, "addr", "", "tcp://0.0.0.0:46658", "Listen address") + counterCmd.PersistentFlags().BoolVarP(&serial, "serial", "", false, "Enforce incrementing (serial) transactions") +} + +func addDummyFlags() { + dummyCmd.PersistentFlags().StringVarP(&addrD, "addr", "", "tcp://0.0.0.0:46658", "Listen address") + dummyCmd.PersistentFlags().StringVarP(&persist, "persist", "", "", "Directory to use for a database") +} func addCommands() { RootCmd.AddCommand(batchCmd) RootCmd.AddCommand(consoleCmd) @@ -104,6 +127,12 @@ func addCommands() { RootCmd.AddCommand(commitCmd) addQueryFlags() RootCmd.AddCommand(queryCmd) + + // examples + addCounterFlags() + RootCmd.AddCommand(counterCmd) + addDummyFlags() + RootCmd.AddCommand(dummyCmd) } var batchCmd = &cobra.Command{ @@ -168,6 +197,20 @@ var queryCmd = &cobra.Command{ Run: cmdQuery, } +var counterCmd = &cobra.Command{ + Use: "counter", + Short: "ABCI demo example", + Long: "", + Run: cmdCounter, +} + +var dummyCmd = &cobra.Command{ + Use: "dummy", + Short: "ABCI demo example", + Long: "", + Run: cmdDummy, +} + // Generates new Args array based off of previous call args to maintain flag persistence func persistentArgs(line []byte) []string { @@ -341,6 +384,62 @@ func cmdQuery(cmd *cobra.Command, args []string) { }) } +func cmdCounter(cmd *cobra.Command, args []string) { + + app := counter.NewCounterApplication(serial) + + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + + // Start the listener + srv, err := server.NewServer(addrC, abci, app) + if err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) +} + +func cmdDummy(cmd *cobra.Command, args []string) { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + + // Create the application - in memory or persisted to disk + var app types.Application + if persist == "" { + app = dummy.NewDummyApplication() + } else { + app = dummy.NewPersistentDummyApplication(persist) + app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) + } + + // Start the listener + srv, err := server.NewServer(addrD, abci, app) + if err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) +} + //-------------------------------------------------------------------------------- func printResponse(cmd *cobra.Command, args []string, rsp response) { diff --git a/cmd/counter/main.go b/cmd/counter/main.go deleted file mode 100644 index aa55778c..00000000 --- a/cmd/counter/main.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "flag" - "os" - - "github.com/tendermint/abci/example/counter" - "github.com/tendermint/abci/server" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" -) - -func main() { - - addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - abciPtr := flag.String("abci", "socket", "ABCI server: socket | grpc") - serialPtr := flag.Bool("serial", false, "Enforce incrementing (serial) txs") - flag.Parse() - app := counter.NewCounterApplication(*serialPtr) - - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Start the listener - srv, err := server.NewServer(*addrPtr, *abciPtr, app) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - srv.SetLogger(logger.With("module", "abci-server")) - if _, err := srv.Start(); err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - -} diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go deleted file mode 100644 index 85bbca18..00000000 --- a/cmd/dummy/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "flag" - "os" - - "github.com/tendermint/abci/example/dummy" - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" -) - -func main() { - - addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - abciPtr := flag.String("abci", "socket", "socket | grpc") - persistencePtr := flag.String("persist", "", "directory to use for a database") - flag.Parse() - - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Create the application - in memory or persisted to disk - var app types.Application - if *persistencePtr == "" { - app = dummy.NewDummyApplication() - } else { - app = dummy.NewPersistentDummyApplication(*persistencePtr) - app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) - } - - // Start the listener - srv, err := server.NewServer(*addrPtr, *abciPtr, app) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - srv.SetLogger(logger.With("module", "abci-server")) - if _, err := srv.Start(); err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - -} From f9e14ad61be9b56147d65b40dcf53ffc9cad41d2 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 18 Oct 2017 15:23:39 -0400 Subject: [PATCH 290/545] disable PersistenPreRun for counter/dummy --- cmd/abci-cli/abci-cli.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 93b00543..11a64432 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -15,7 +15,6 @@ import ( "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - //"github.com/tendermint/abci/version" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" @@ -70,6 +69,13 @@ var RootCmd = &cobra.Command{ Short: "", Long: "", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + + switch cmd.Use { + // for the examples apps, don't pre-run + case "counter", "dummy": + return nil + } + if logger == nil { logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), log.AllowError()) } From 631844895ff8a69c17cc21f8b197afe5527c02df Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 18 Oct 2017 15:32:34 -0400 Subject: [PATCH 291/545] fixes --- README.md | 6 +++--- scripts/dist_build.sh | 40 +++++++++++++++++++--------------------- tests/test_cli/test.sh | 10 +++++----- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index f1b2ebb3..33b037da 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,9 @@ The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an See [the documentation](http://tendermint.readthedocs.io/en/master/) for more details. Multiple example apps are included: -- the `counter` application, which illustrates nonce checking in txs -- the `dummy` application, which illustrates a simple key-value merkle tree -- the `dummy --persistent` application, which augments the dummy with persistence and validator set changes +- the `abci-cli counter` application, which illustrates nonce checking in txs +- the `abci-cli dummy` application, which illustrates a simple key-value merkle tree +- the `abci-cli dummy --persistent` application, which augments the dummy with persistence and validator set changes ## Specification diff --git a/scripts/dist_build.sh b/scripts/dist_build.sh index 0f5e3e3b..adaca24a 100755 --- a/scripts/dist_build.sh +++ b/scripts/dist_build.sh @@ -24,30 +24,28 @@ make tools # Get VENDORED dependencies make get_vendor_deps -BINARIES=( "abci-cli" "dummy" "counter" ) +BINARY="abci-cli" -for binary in ${BINARIES[@]}; do - # Build! - echo "==> Building..." - "$(which gox)" \ - -os="${XC_OS}" \ - -arch="${XC_ARCH}" \ - -osarch="!darwin/arm !solaris/amd64 !freebsd/amd64" \ - -ldflags "-X ${GIT_IMPORT}.GitCommit='${GIT_COMMIT}' -X ${GIT_IMPORT}.GitDescribe='${GIT_DESCRIBE}'" \ - -output "build/pkg/{{.OS}}_{{.Arch}}/$binary" \ - -tags="${BUILD_TAGS}" \ - github.com/tendermint/abci/cmd/$binary +# Build! +echo "==> Building..." +"$(which gox)" \ + -os="${XC_OS}" \ + -arch="${XC_ARCH}" \ + -osarch="!darwin/arm !solaris/amd64 !freebsd/amd64" \ + -ldflags "-X ${GIT_IMPORT}.GitCommit='${GIT_COMMIT}' -X ${GIT_IMPORT}.GitDescribe='${GIT_DESCRIBE}'" \ + -output "build/pkg/{{.OS}}_{{.Arch}}/$BINARY" \ + -tags="${BUILD_TAGS}" \ + github.com/tendermint/abci/cmd/$BINARY - # Zip all the files. - echo "==> Packaging..." - for PLATFORM in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type d); do - OSARCH=$(basename "${PLATFORM}") - echo "--> ${OSARCH}" +# Zip all the files. +echo "==> Packaging..." +for PLATFORM in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type d); do + OSARCH=$(basename "${PLATFORM}") + echo "--> ${OSARCH}" - pushd "$PLATFORM" >/dev/null 2>&1 - zip "../${OSARCH}.zip" ./* - popd >/dev/null 2>&1 - done + pushd "$PLATFORM" >/dev/null 2>&1 + zip "../${OSARCH}.zip" ./* + popd >/dev/null 2>&1 done diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 4266dd16..81b06a0e 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -11,13 +11,13 @@ cd "$DIR" || exit function testExample() { N=$1 INPUT=$2 - APP=$3 + APP="$3 $4" - echo "Example $N" + echo "Example $N: $APP" $APP &> /dev/null & sleep 2 abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" - killall "$APP" + killall $3 pre=$(shasum < "${INPUT}.out") post=$(shasum < "${INPUT}.out.new") @@ -34,8 +34,8 @@ function testExample() { rm "${INPUT}".out.new } -testExample 1 tests/test_cli/ex1.abci dummy -testExample 2 tests/test_cli/ex2.abci counter +testExample 1 tests/test_cli/ex1.abci abci-cli dummy +testExample 2 tests/test_cli/ex2.abci abci-cli counter echo "" echo "PASS" From 3330cb4856fe6e33ccf07a9fa44fb2b33d4c9516 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 23 Oct 2017 17:16:49 -0400 Subject: [PATCH 292/545] cleanup --- cmd/abci-cli/abci-cli.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 11a64432..906520f0 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -102,9 +102,9 @@ func Execute() { } func addGlobalFlags() { - RootCmd.PersistentFlags().StringVarP(&address, "address", "", "tcp://127.0.0.1:46658", "address of application socket") - RootCmd.PersistentFlags().StringVarP(&abci, "abci", "", "socket", "socket or grpc") - RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "print the command and results as if it were a console session") + RootCmd.PersistentFlags().StringVarP(&address, "address", "", "tcp://127.0.0.1:46658", "Address of application socket") + RootCmd.PersistentFlags().StringVarP(&abci, "abci", "", "socket", "Either socket or grpc") + RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print the command and results as if it were a console session") } func addQueryFlags() { @@ -158,8 +158,8 @@ var consoleCmd = &cobra.Command{ var echoCmd = &cobra.Command{ Use: "echo", - Short: "", - Long: "Have the application echo a message", + Short: "Have the application echo a message", + Long: "", Run: cmdEcho, } var infoCmd = &cobra.Command{ @@ -170,21 +170,21 @@ var infoCmd = &cobra.Command{ } var setOptionCmd = &cobra.Command{ Use: "set_option", - Short: "Set an options on the application", + Short: "Set an option on the application", Long: "", Run: cmdSetOption, } var deliverTxCmd = &cobra.Command{ Use: "deliver_tx", - Short: "Deliver a new tx to the application", + Short: "Deliver a new transaction to the application", Long: "", Run: cmdDeliverTx, } var checkTxCmd = &cobra.Command{ Use: "check_tx", - Short: "Validate a tx", + Short: "Validate a transaction", Long: "", Run: cmdCheckTx, } @@ -250,7 +250,7 @@ func cmdBatch(cmd *cobra.Command, args []string) { pArgs := persistentArgs(line) out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() if err != nil { - panic(err) + ifExit(err) } fmt.Println(string(out)) } @@ -271,7 +271,7 @@ func cmdConsole(cmd *cobra.Command, args []string) { pArgs := persistentArgs(line) out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() if err != nil { - panic(err) + ifExit(err) } fmt.Println(string(out)) } @@ -280,7 +280,7 @@ func cmdConsole(cmd *cobra.Command, args []string) { // Have the application echo a message func cmdEcho(cmd *cobra.Command, args []string) { if len(args) != 1 { - ifExit(errors.New("Command echo takes 1 argument")) + ifExit(errors.New("Command echo takes only 1 argument")) } resEcho := client.EchoSync(args[0]) printResponse(cmd, args, response{ @@ -306,7 +306,7 @@ func cmdInfo(cmd *cobra.Command, args []string) { // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) { if len(args) != 2 { - ifExit(errors.New("Command set_option takes 2 arguments (key, value)")) + ifExit(errors.New("Command set_option takes exactly 2 arguments (key, value)")) } resSetOption := client.SetOptionSync(args[0], args[1]) printResponse(cmd, args, response{ @@ -317,7 +317,7 @@ func cmdSetOption(cmd *cobra.Command, args []string) { // Append a new tx to application func cmdDeliverTx(cmd *cobra.Command, args []string) { if len(args) != 1 { - ifExit(errors.New("Command deliver_tx takes 1 argument")) + ifExit(errors.New("Command deliver_tx takes only 1 argument")) } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { @@ -334,7 +334,7 @@ func cmdDeliverTx(cmd *cobra.Command, args []string) { // Validate a tx func cmdCheckTx(cmd *cobra.Command, args []string) { if len(args) != 1 { - ifExit(errors.New("Command check_tx takes 1 argument")) + ifExit(errors.New("Command check_tx takes only 1 argument")) } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { @@ -361,7 +361,7 @@ func cmdCommit(cmd *cobra.Command, args []string) { // Query application state func cmdQuery(cmd *cobra.Command, args []string) { if len(args) != 1 { - ifExit(errors.New("Command query takes 1 argument, the query bytes")) + ifExit(errors.New("Command query takes only 1 argument, the query bytes")) } queryBytes, err := stringOrHexToBytes(args[0]) From 36de70be10867da3737c8b3388d94e778cf7ceee Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 23 Oct 2017 19:35:02 -0400 Subject: [PATCH 293/545] console: fix output, closes #93 --- cmd/abci-cli/abci-cli.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 906520f0..e098b9a3 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -259,7 +259,7 @@ func cmdBatch(cmd *cobra.Command, args []string) { func cmdConsole(cmd *cobra.Command, args []string) { for { - fmt.Printf("\n> ") + fmt.Printf("> ") bufReader := bufio.NewReader(os.Stdin) line, more, err := bufReader.ReadLine() if more { @@ -454,12 +454,16 @@ func printResponse(cmd *cobra.Command, args []string, rsp response) { fmt.Println(">", cmd.Use, strings.Join(args, " ")) } - if !rsp.Code.IsOK() { - fmt.Printf("-> code: %s\n", rsp.Code.String()) - } + // Always print the status code. + fmt.Printf("-> code: %s\n", rsp.Code.String()) + if len(rsp.Data) != 0 { - fmt.Printf("-> data: %s\n", rsp.Data) - fmt.Printf("-> data.hex: %X\n", rsp.Data) + // Do no print this line when using the commit command + // because the string comes out as gibberish + if cmd.Use != "commit" { + fmt.Printf("-> data: %s\n", rsp.Data) + } + fmt.Printf("-> data.hex: 0x%X\n", rsp.Data) } if rsp.Log != "" { fmt.Printf("-> log: %s\n", rsp.Log) From 4479e957095fb4616a86be325c6ee4e568ff624e Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 23 Oct 2017 19:54:38 -0400 Subject: [PATCH 294/545] console: fix tests --- tests/test_cli/ex1.abci.out | 22 +++++++++++++++------- tests/test_cli/ex2.abci.out | 8 +++++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/test_cli/ex1.abci.out b/tests/test_cli/ex1.abci.out index 21c778c7..6e344071 100644 --- a/tests/test_cli/ex1.abci.out +++ b/tests/test_cli/ex1.abci.out @@ -1,36 +1,44 @@ > echo hello +-> code: OK -> data: hello --> data.hex: 68656C6C6F +-> data.hex: 0x68656C6C6F > info +-> code: OK -> data: {"size":0} --> data.hex: 7B2273697A65223A307D +-> data.hex: 0x7B2273697A65223A307D > commit +-> code: OK > deliver_tx "abc" +-> code: OK > info +-> code: OK -> data: {"size":1} --> data.hex: 7B2273697A65223A317D +-> data.hex: 0x7B2273697A65223A317D > commit --> data: IßÑ\ͬޮ—(ËûµèhŒ¥‹‘ --> data.hex: 49DFD15CCDACDEAE9728CB01FBB5E8688CA58B91 +-> code: OK +-> data.hex: 0x49DFD15CCDACDEAE9728CB01FBB5E8688CA58B91 > query "abc" +-> code: OK -> log: exists -> height: 0 -> value: abc -> value.hex: 616263 > deliver_tx "def=xyz" +-> code: OK > commit --> data: p-³"€7?¿?Ÿ‰Ú* Î,Ö+ --> data.hex: 70102DB32280373FBF3F9F89DA2A20CE2CD62B0B +-> code: OK +-> data.hex: 0x70102DB32280373FBF3F9F89DA2A20CE2CD62B0B > query "def" +-> code: OK -> log: exists -> height: 0 -> value: xyz diff --git a/tests/test_cli/ex2.abci.out b/tests/test_cli/ex2.abci.out index 202861cf..40e10f83 100644 --- a/tests/test_cli/ex2.abci.out +++ b/tests/test_cli/ex2.abci.out @@ -1,22 +1,28 @@ > set_option serial on +-> code: OK > 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 -> log: Invalid nonce. Expected 2, got 4 > info +-> code: OK -> data: {"hashes":0,"txs":2} --> data.hex: 7B22686173686573223A302C22747873223A327D +-> data.hex: 0x7B22686173686573223A302C22747873223A327D From 6c41ec65bcd86489041fb3bf3a7c56cbe9e70dcf Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 25 Oct 2017 23:04:20 -0400 Subject: [PATCH 295/545] server: use cmn.ProtocolAndAddress --- server/grpc_server.go | 4 +--- server/socket_server.go | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/server/grpc_server.go b/server/grpc_server.go index ac3d728a..077f0e52 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -2,7 +2,6 @@ package server import ( "net" - "strings" "google.golang.org/grpc" @@ -23,8 +22,7 @@ type GRPCServer struct { // NewGRPCServer returns a new gRPC ABCI server func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) cmn.Service { - parts := strings.SplitN(protoAddr, "://", 2) - proto, addr := parts[0], parts[1] + proto, addr := cmn.ProtocolAndAddress(protoAddr) s := &GRPCServer{ proto: proto, addr: addr, diff --git a/server/socket_server.go b/server/socket_server.go index 304a2c7f..adc7516c 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "net" - "strings" "sync" "github.com/tendermint/abci/types" @@ -30,8 +29,7 @@ type SocketServer struct { } func NewSocketServer(protoAddr string, app types.Application) cmn.Service { - parts := strings.SplitN(protoAddr, "://", 2) - proto, addr := parts[0], parts[1] + proto, addr := cmn.ProtocolAndAddress(protoAddr) s := &SocketServer{ proto: proto, addr: addr, From b6a4ca6b3c4203802f0143b2cb407c10baf75a0e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 25 Oct 2017 23:15:57 -0400 Subject: [PATCH 296/545] remove testutil --- testutil/messages.go | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 testutil/messages.go diff --git a/testutil/messages.go b/testutil/messages.go deleted file mode 100644 index 0cdddb44..00000000 --- a/testutil/messages.go +++ /dev/null @@ -1,17 +0,0 @@ -package testutil - -import ( - "github.com/tendermint/abci/types" - "github.com/tendermint/go-crypto" -) - -//---------------------------------------- - -// UTILITY -func Validator(secret string, power uint64) *types.Validator { - privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret)) - return &types.Validator{ - PubKey: privKey.PubKey().Bytes(), - Power: power, - } -} From 4884747eb76608ee799f5d0bf51694c441cf9f62 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 25 Oct 2017 23:23:10 -0400 Subject: [PATCH 297/545] tests: add simple client/server test with no addr prefix --- tests/client_server_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/client_server_test.go diff --git a/tests/client_server_test.go b/tests/client_server_test.go new file mode 100644 index 00000000..cc946fce --- /dev/null +++ b/tests/client_server_test.go @@ -0,0 +1,27 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + abciclient "github.com/tendermint/abci/client" + "github.com/tendermint/abci/example/dummy" + abciserver "github.com/tendermint/abci/server" +) + +func TestClientServerNoAddrPrefix(t *testing.T) { + addr := "localhost:46658" + transport := "socket" + app := dummy.NewDummyApplication() + + server, err := abciserver.NewServer(addr, transport, app) + assert.NoError(t, err, "expected no error on NewServer") + _, err = server.Start() + assert.NoError(t, err, "expected no error on server.Start") + + client, err := abciclient.NewClient(addr, transport, true) + assert.NoError(t, err, "expected no error on NewClient") + _, err = client.Start() + assert.NoError(t, err, "expected no error on client.Start") +} From a0e38dc58374f485481ea07b23659d85f670a694 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 25 Oct 2017 23:34:37 -0400 Subject: [PATCH 298/545] dummy: verify pubkey is go-crypto encoded in DeliverTx. closes #51 --- example/dummy/persistent_dummy.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 15fe150d..4c480175 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" @@ -149,15 +150,25 @@ func isValidatorTx(tx []byte) bool { // format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { tx = tx[len(ValidatorSetChangePrefix):] + + //get the pubkey and power pubKeyAndPower := strings.Split(string(tx), "/") if len(pubKeyAndPower) != 2 { return types.ErrEncodingError.SetLog(cmn.Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) } pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] + + // decode the pubkey, ensuring its go-crypto encoded pubkey, err := hex.DecodeString(pubkeyS) if err != nil { return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%s) is invalid hex", pubkeyS)) } + _, err = crypto.PubKeyFromBytes(pubkey) + if err != nil { + return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%X) is invalid go-crypto encoded", pubkey)) + } + + // decode the power power, err := strconv.Atoi(powerS) if err != nil { return types.ErrEncodingError.SetLog(cmn.Fmt("Power (%s) is not an int", powerS)) From 461191d2f7b60b98e2705363cacf9651334cfeb0 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 26 Oct 2017 08:37:42 -0400 Subject: [PATCH 299/545] cli: clean up error handling --- cmd/abci-cli/abci-cli.go | 133 ++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 56 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index e098b9a3..294c88cf 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -83,8 +83,7 @@ var RootCmd = &cobra.Command{ var err error client, err = abcicli.NewClient(address, abci, false) if err != nil { - logger.Error(err.Error()) - os.Exit(1) + return err } client.SetLogger(logger.With("module", "abci-client")) if _, err := client.Start(); err != nil { @@ -98,7 +97,7 @@ var RootCmd = &cobra.Command{ func Execute() { addGlobalFlags() addCommands() - RootCmd.Execute() //err? + RootCmd.Execute() } func addGlobalFlags() { @@ -145,7 +144,9 @@ var batchCmd = &cobra.Command{ Use: "batch", Short: "Run a batch of abci commands against an application", Long: "", - Run: cmdBatch, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdBatch(cmd, args) + }, } var consoleCmd = &cobra.Command{ @@ -153,68 +154,88 @@ var consoleCmd = &cobra.Command{ Short: "Start an interactive abci console for multiple commands", Long: "", ValidArgs: []string{"batch", "echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"}, - Run: cmdConsole, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdConsole(cmd, args) + }, } var echoCmd = &cobra.Command{ Use: "echo", Short: "Have the application echo a message", Long: "", - Run: cmdEcho, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdEcho(cmd, args) + }, } var infoCmd = &cobra.Command{ Use: "info", Short: "Get some info about the application", Long: "", - Run: cmdInfo, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdInfo(cmd, args) + }, } var setOptionCmd = &cobra.Command{ Use: "set_option", Short: "Set an option on the application", Long: "", - Run: cmdSetOption, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdSetOption(cmd, args) + }, } var deliverTxCmd = &cobra.Command{ Use: "deliver_tx", Short: "Deliver a new transaction to the application", Long: "", - Run: cmdDeliverTx, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdDeliverTx(cmd, args) + }, } var checkTxCmd = &cobra.Command{ Use: "check_tx", Short: "Validate a transaction", Long: "", - Run: cmdCheckTx, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdCheckTx(cmd, args) + }, } var commitCmd = &cobra.Command{ Use: "commit", Short: "Commit the application state and return the Merkle root hash", Long: "", - Run: cmdCommit, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdCommit(cmd, args) + }, } var queryCmd = &cobra.Command{ Use: "query", Short: "Query the application state", Long: "", - Run: cmdQuery, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdQuery(cmd, args) + }, } var counterCmd = &cobra.Command{ Use: "counter", Short: "ABCI demo example", Long: "", - Run: cmdCounter, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdCounter(cmd, args) + }, } var dummyCmd = &cobra.Command{ Use: "dummy", Short: "ABCI demo example", Long: "", - Run: cmdDummy, + RunE: func(cmd *cobra.Command, args []string) error { + return cmdDummy(cmd, args) + }, } // Generates new Args array based off of previous call args to maintain flag persistence @@ -233,95 +254,100 @@ func persistentArgs(line []byte) []string { //-------------------------------------------------------------------------------- -func cmdBatch(cmd *cobra.Command, args []string) { +func cmdBatch(cmd *cobra.Command, args []string) error { bufReader := bufio.NewReader(os.Stdin) for { line, more, err := bufReader.ReadLine() if more { - ifExit(errors.New("Input line is too long")) + return errors.New("Input line is too long") } else if err == io.EOF { break } else if len(line) == 0 { continue } else if err != nil { - ifExit(err) + return err } pArgs := persistentArgs(line) out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() if err != nil { - ifExit(err) + return err } fmt.Println(string(out)) } + return nil } -func cmdConsole(cmd *cobra.Command, args []string) { +func cmdConsole(cmd *cobra.Command, args []string) error { for { fmt.Printf("> ") bufReader := bufio.NewReader(os.Stdin) line, more, err := bufReader.ReadLine() if more { - ifExit(errors.New("Input is too long")) + return errors.New("Input is too long") } else if err != nil { - ifExit(err) + return err } pArgs := persistentArgs(line) out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() if err != nil { - ifExit(err) + return err } fmt.Println(string(out)) } + return nil } // Have the application echo a message -func cmdEcho(cmd *cobra.Command, args []string) { +func cmdEcho(cmd *cobra.Command, args []string) error { if len(args) != 1 { - ifExit(errors.New("Command echo takes only 1 argument")) + return errors.New("Command echo takes only 1 argument") } resEcho := client.EchoSync(args[0]) printResponse(cmd, args, response{ Data: resEcho.Data, }) + return nil } // Get some info from the application -func cmdInfo(cmd *cobra.Command, args []string) { +func cmdInfo(cmd *cobra.Command, args []string) error { var version string if len(args) == 1 { version = args[0] } resInfo, err := client.InfoSync(types.RequestInfo{version}) if err != nil { - ifExit(err) + return err } printResponse(cmd, args, response{ Data: []byte(resInfo.Data), }) + return nil } // Set an option on the application -func cmdSetOption(cmd *cobra.Command, args []string) { +func cmdSetOption(cmd *cobra.Command, args []string) error { if len(args) != 2 { - ifExit(errors.New("Command set_option takes exactly 2 arguments (key, value)")) + return errors.New("Command set_option takes exactly 2 arguments (key, value)") } resSetOption := client.SetOptionSync(args[0], args[1]) printResponse(cmd, args, response{ Log: resSetOption.Log, }) + return nil } // Append a new tx to application -func cmdDeliverTx(cmd *cobra.Command, args []string) { +func cmdDeliverTx(cmd *cobra.Command, args []string) error { if len(args) != 1 { - ifExit(errors.New("Command deliver_tx takes only 1 argument")) + return errors.New("Command deliver_tx takes only 1 argument") } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { - ifExit(err) + return err } res := client.DeliverTxSync(txBytes) printResponse(cmd, args, response{ @@ -329,16 +355,17 @@ func cmdDeliverTx(cmd *cobra.Command, args []string) { Data: res.Data, Log: res.Log, }) + return nil } // Validate a tx -func cmdCheckTx(cmd *cobra.Command, args []string) { +func cmdCheckTx(cmd *cobra.Command, args []string) error { if len(args) != 1 { - ifExit(errors.New("Command check_tx takes only 1 argument")) + return errors.New("Command check_tx takes only 1 argument") } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { - ifExit(err) + return err } res := client.CheckTxSync(txBytes) printResponse(cmd, args, response{ @@ -346,27 +373,29 @@ func cmdCheckTx(cmd *cobra.Command, args []string) { Data: res.Data, Log: res.Log, }) + return nil } // Get application Merkle root hash -func cmdCommit(cmd *cobra.Command, args []string) { +func cmdCommit(cmd *cobra.Command, args []string) error { res := client.CommitSync() printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, Log: res.Log, }) + return nil } // Query application state -func cmdQuery(cmd *cobra.Command, args []string) { +func cmdQuery(cmd *cobra.Command, args []string) error { if len(args) != 1 { - ifExit(errors.New("Command query takes only 1 argument, the query bytes")) + return errors.New("Command query takes only 1 argument, the query bytes") } queryBytes, err := stringOrHexToBytes(args[0]) if err != nil { - ifExit(err) + return err } resQuery, err := client.QuerySync(types.RequestQuery{ @@ -376,7 +405,7 @@ func cmdQuery(cmd *cobra.Command, args []string) { Prove: prove, }) if err != nil { - ifExit(err) + return err } printResponse(cmd, args, response{ Code: resQuery.Code, @@ -388,9 +417,10 @@ func cmdQuery(cmd *cobra.Command, args []string) { Proof: resQuery.Proof, }, }) + return nil } -func cmdCounter(cmd *cobra.Command, args []string) { +func cmdCounter(cmd *cobra.Command, args []string) error { app := counter.NewCounterApplication(serial) @@ -399,13 +429,11 @@ func cmdCounter(cmd *cobra.Command, args []string) { // Start the listener srv, err := server.NewServer(addrC, abci, app) if err != nil { - logger.Error(err.Error()) - os.Exit(1) + return err } srv.SetLogger(logger.With("module", "abci-server")) if _, err := srv.Start(); err != nil { - logger.Error(err.Error()) - os.Exit(1) + return err } // Wait forever @@ -413,9 +441,10 @@ func cmdCounter(cmd *cobra.Command, args []string) { // Cleanup srv.Stop() }) + return nil } -func cmdDummy(cmd *cobra.Command, args []string) { +func cmdDummy(cmd *cobra.Command, args []string) error { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Create the application - in memory or persisted to disk @@ -430,13 +459,11 @@ func cmdDummy(cmd *cobra.Command, args []string) { // Start the listener srv, err := server.NewServer(addrD, abci, app) if err != nil { - logger.Error(err.Error()) - os.Exit(1) + return err } srv.SetLogger(logger.With("module", "abci-server")) if _, err := srv.Start(); err != nil { - logger.Error(err.Error()) - os.Exit(1) + return err } // Wait forever @@ -444,6 +471,7 @@ func cmdDummy(cmd *cobra.Command, args []string) { // Cleanup srv.Stop() }) + return nil } //-------------------------------------------------------------------------------- @@ -503,10 +531,3 @@ func stringOrHexToBytes(s string) ([]byte, error) { return []byte(s[1 : len(s)-1]), nil } - -func ifExit(err error) { - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} From f013ee5cf99ee74c0dad568cd0668fa14031f213 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Thu, 26 Oct 2017 08:51:43 -0400 Subject: [PATCH 300/545] cli: use cobra's new ExactArgs() feature --- cmd/abci-cli/abci-cli.go | 27 +++++++++++---------------- glide.lock | 8 ++++---- glide.yaml | 1 + 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 294c88cf..1beb0850 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -144,6 +144,7 @@ var batchCmd = &cobra.Command{ Use: "batch", Short: "Run a batch of abci commands against an application", Long: "", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return cmdBatch(cmd, args) }, @@ -153,6 +154,7 @@ var consoleCmd = &cobra.Command{ Use: "console", Short: "Start an interactive abci console for multiple commands", Long: "", + Args: cobra.ExactArgs(0), ValidArgs: []string{"batch", "echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"}, RunE: func(cmd *cobra.Command, args []string) error { return cmdConsole(cmd, args) @@ -163,6 +165,7 @@ var echoCmd = &cobra.Command{ Use: "echo", Short: "Have the application echo a message", Long: "", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return cmdEcho(cmd, args) }, @@ -171,6 +174,7 @@ var infoCmd = &cobra.Command{ Use: "info", Short: "Get some info about the application", Long: "", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return cmdInfo(cmd, args) }, @@ -179,6 +183,7 @@ var setOptionCmd = &cobra.Command{ Use: "set_option", Short: "Set an option on the application", Long: "", + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { return cmdSetOption(cmd, args) }, @@ -188,6 +193,7 @@ var deliverTxCmd = &cobra.Command{ Use: "deliver_tx", Short: "Deliver a new transaction to the application", Long: "", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return cmdDeliverTx(cmd, args) }, @@ -197,6 +203,7 @@ var checkTxCmd = &cobra.Command{ Use: "check_tx", Short: "Validate a transaction", Long: "", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return cmdCheckTx(cmd, args) }, @@ -206,6 +213,7 @@ var commitCmd = &cobra.Command{ Use: "commit", Short: "Commit the application state and return the Merkle root hash", Long: "", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return cmdCommit(cmd, args) }, @@ -215,6 +223,7 @@ var queryCmd = &cobra.Command{ Use: "query", Short: "Query the application state", Long: "", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return cmdQuery(cmd, args) }, @@ -224,6 +233,7 @@ var counterCmd = &cobra.Command{ Use: "counter", Short: "ABCI demo example", Long: "", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return cmdCounter(cmd, args) }, @@ -233,6 +243,7 @@ var dummyCmd = &cobra.Command{ Use: "dummy", Short: "ABCI demo example", Long: "", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return cmdDummy(cmd, args) }, @@ -302,9 +313,6 @@ func cmdConsole(cmd *cobra.Command, args []string) error { // Have the application echo a message func cmdEcho(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return errors.New("Command echo takes only 1 argument") - } resEcho := client.EchoSync(args[0]) printResponse(cmd, args, response{ Data: resEcho.Data, @@ -330,9 +338,6 @@ func cmdInfo(cmd *cobra.Command, args []string) error { // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) error { - if len(args) != 2 { - return errors.New("Command set_option takes exactly 2 arguments (key, value)") - } resSetOption := client.SetOptionSync(args[0], args[1]) printResponse(cmd, args, response{ Log: resSetOption.Log, @@ -342,9 +347,6 @@ func cmdSetOption(cmd *cobra.Command, args []string) error { // Append a new tx to application func cmdDeliverTx(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return errors.New("Command deliver_tx takes only 1 argument") - } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err @@ -360,9 +362,6 @@ func cmdDeliverTx(cmd *cobra.Command, args []string) error { // Validate a tx func cmdCheckTx(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return errors.New("Command check_tx takes only 1 argument") - } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err @@ -389,10 +388,6 @@ func cmdCommit(cmd *cobra.Command, args []string) error { // Query application state func cmdQuery(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return errors.New("Command query takes only 1 argument, the query bytes") - } - queryBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err diff --git a/glide.lock b/glide.lock index 49795959..8ee12dc7 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 1530ad93695fa2861f1572e3e1eef1b6604beb548fd4832985f6c6350260c2b3 -updated: 2017-10-18T14:27:16.428209213-04:00 +hash: 3c8680f0a289567a29f737be5f1d5f242c7e2afd84bdd023dd74596b88508fc2 +updated: 2017-10-26T08:45:51.300025559-04:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -39,7 +39,7 @@ imports: - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/spf13/cobra - version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 + version: 2df9a531813370438a4d79bfc33e21f58063ed87 - name: github.com/spf13/pflag version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 - name: github.com/syndtr/goleveldb @@ -69,7 +69,7 @@ imports: subpackages: - data - name: github.com/tendermint/iavl - version: 721710e7aa59f61dbfbf558943a207ba3fe6b926 + version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tmlibs version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: diff --git a/glide.yaml b/glide.yaml index cd8c994c..ccd41cdc 100644 --- a/glide.yaml +++ b/glide.yaml @@ -19,6 +19,7 @@ import: - merkle - process - package: github.com/spf13/cobra + version: master - package: golang.org/x/net subpackages: - context From d973cb5df983bf2c7ed780bc111e3bb8c25c422e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 12:12:07 -0400 Subject: [PATCH 301/545] changelog and version --- CHANGELOG.md | 12 ++++++++++++ version/version.go | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91bd0649..5ed93b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 0.7.0 (October 27, 2017) + +BREAKING CHANGES: + - [cli] consolidate example apps under a single `abci-cli` binary + +IMPROVEMENTS: + - [cli] use spf13/cobra instead of urfave/cli + - [dummy] use iavl instead of merkleeyes, and add support for historical queries + +BUG FIXES: + - [client] fix deadlock on StopForError + ## 0.6.0 (September 22, 2017) BREAKING CHANGES: diff --git a/version/version.go b/version/version.go index 34b1230e..bbea51bc 100644 --- a/version/version.go +++ b/version/version.go @@ -3,7 +3,7 @@ package version // NOTE: we should probably be versioning the ABCI and the abci-cli separately const Maj = "0" -const Min = "6" +const Min = "7" const Fix = "0" -const Version = "0.6.0" +const Version = "0.7.0" From c9612f094b8181c3986a07f85cd8a8a07c9676c8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 12:13:16 -0400 Subject: [PATCH 302/545] glide --- glide.lock | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/glide.lock b/glide.lock index 8ee12dc7..2a992d72 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 3c8680f0a289567a29f737be5f1d5f242c7e2afd84bdd023dd74596b88508fc2 -updated: 2017-10-26T08:45:51.300025559-04:00 +updated: 2017-10-27T12:12:58.940745472-04:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -24,10 +24,13 @@ imports: - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 + version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 subpackages: - proto + - ptypes - ptypes/any + - ptypes/duration + - ptypes/timestamp - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/inconshreveable/mousetrap @@ -39,9 +42,9 @@ imports: - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/spf13/cobra - version: 2df9a531813370438a4d79bfc33e21f58063ed87 + version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b - name: github.com/spf13/pflag - version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 + version: 80fe0fb4eba54167e2ccae1c6c950e72abf61b73 - name: github.com/syndtr/goleveldb version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: @@ -63,15 +66,15 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: 8e7f0e7701f92206679ad093d013b9b162427631 + version: db5603e37435933c13665a708055fadd18222f5f - name: github.com/tendermint/go-wire - version: 26ee079df7fca1958da8995c727b59759b197534 + version: 8ee84b5b2581530168daf66fc89c548d27403c57 subpackages: - data - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tmlibs - version: 8e5266a9ef2527e68a1571f932db8228a331b556 + version: 092eb701c7276907cdbed258750e22ce895b6735 subpackages: - common - db @@ -88,7 +91,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: feeb485667d1fdabe727840fe00adc22431bc86e + version: cd69bc3fc700721b709c3a59e16e24c67b58f6ff subpackages: - context - http2 @@ -105,21 +108,24 @@ imports: - unicode/bidi - unicode/norm - name: google.golang.org/genproto - version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + version: f676e0f3ac6395ff1a529ae59a6670878a8371a6 subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: 844f573616520565fdc6fb4db242321b5456fd6d + version: f7bf885db0b7479a537ec317c6e48ce53145f3db subpackages: + - balancer - codes + - connectivity - credentials - - grpclb/grpc_lb_v1 + - grpclb/grpc_lb_v1/messages - grpclog - internal - keepalive - metadata - naming - peer + - resolver - stats - status - tap From ecb1f02f770eeb52bb85e16998f66e552296bf86 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 8 Nov 2017 17:18:42 -0500 Subject: [PATCH 303/545] add version cmd (Refs #124) --- cmd/abci-cli/abci-cli.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 1beb0850..9962380b 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -15,6 +15,7 @@ import ( "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + "github.com/tendermint/abci/version" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" @@ -71,8 +72,9 @@ var RootCmd = &cobra.Command{ PersistentPreRunE: func(cmd *cobra.Command, args []string) error { switch cmd.Use { - // for the examples apps, don't pre-run - case "counter", "dummy": + case "counter", "dummy": // for the examples apps, don't pre-run + return nil + case "version": // skip running for version command return nil } @@ -130,6 +132,7 @@ func addCommands() { RootCmd.AddCommand(deliverTxCmd) RootCmd.AddCommand(checkTxCmd) RootCmd.AddCommand(commitCmd) + RootCmd.AddCommand(versionCmd) addQueryFlags() RootCmd.AddCommand(queryCmd) @@ -219,6 +222,17 @@ var commitCmd = &cobra.Command{ }, } +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print abci console version", + Long: "", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println(version.Version) + return nil + }, +} + var queryCmd = &cobra.Command{ Use: "query", Short: "Query the application state", From 5efe88cd107080d032ba8c73dd4e857e13cc2bd2 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 8 Nov 2017 17:18:52 -0500 Subject: [PATCH 304/545] simplify Makefile install and build commands --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 588e12df..a22a2e90 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,10 @@ protoc: @ protoc --go_out=plugins=grpc:. types/*.proto install: - @ go install github.com/tendermint/abci/cmd/... + @ go install ./cmd/... build: - @ go build -i github.com/tendermint/abci/cmd/... + @ go build -i ./cmd/... dist: @ bash scripts/dist.sh From 430c49ea143b76cc419b2f2c6c0779ea715db823 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 8 Nov 2017 17:19:35 -0500 Subject: [PATCH 305/545] update deps --- glide.lock | 11 +++++------ glide.yaml | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/glide.lock b/glide.lock index 2a992d72..75552186 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 3c8680f0a289567a29f737be5f1d5f242c7e2afd84bdd023dd74596b88508fc2 -updated: 2017-10-27T12:12:58.940745472-04:00 +hash: 5501ab3d7136aa8fb425c995d45221849b33aefab76c5d2c192e721dad28da38 +updated: 2017-11-08T22:19:19.433856551Z imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -66,20 +66,19 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto - version: db5603e37435933c13665a708055fadd18222f5f + version: b4f04f196cd719660e43b91202cd60d9a95b1837 - name: github.com/tendermint/go-wire - version: 8ee84b5b2581530168daf66fc89c548d27403c57 + version: 2baffcb6b690057568bc90ef1d457efb150b979a subpackages: - data - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tmlibs - version: 092eb701c7276907cdbed258750e22ce895b6735 + version: 176c2ceed611d7735e39131e312bd973afb41b7b subpackages: - common - db - log - - merkle - process - name: golang.org/x/crypto version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e diff --git a/glide.yaml b/glide.yaml index ccd41cdc..ce805723 100644 --- a/glide.yaml +++ b/glide.yaml @@ -3,11 +3,13 @@ import: - package: github.com/golang/protobuf subpackages: - proto -- package: github.com/pkg/errors +- package: github.com/spf13/cobra - package: github.com/tendermint/go-crypto version: develop - package: github.com/tendermint/go-wire version: develop + subpackages: + - data - package: github.com/tendermint/iavl version: develop - package: github.com/tendermint/tmlibs @@ -16,10 +18,7 @@ import: - common - db - log - - merkle - process -- package: github.com/spf13/cobra - version: master - package: golang.org/x/net subpackages: - context @@ -27,4 +26,5 @@ import: testImport: - package: github.com/stretchr/testify subpackages: + - assert - require From 10e1233f1420e6b244ee1366485e18d58ef981fb Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 8 Nov 2017 17:29:15 -0500 Subject: [PATCH 306/545] fix megacheck issues --- example/dummy/dummy_test.go | 6 +++--- example/example_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 751a2e91..efbc5af7 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" abcicli "github.com/tendermint/abci/client" - "github.com/tendermint/abci/server" + abciserver "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" @@ -210,7 +210,7 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, socket := cmn.Fmt("unix://%s.sock", name) logger := log.TestingLogger() - server := server.NewSocketServer(socket, app) + server := abciserver.NewSocketServer(socket, app) server.SetLogger(logger.With("module", "abci-server")) if _, err := server.Start(); err != nil { return nil, nil, err @@ -233,7 +233,7 @@ func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, c logger := log.TestingLogger() gapp := types.NewGRPCApplication(app) - server := server.NewGRPCServer(socket, gapp) + server := abciserver.NewGRPCServer(socket, gapp) server.SetLogger(logger.With("module", "abci-server")) if _, err := server.Start(); err != nil { return nil, nil, err diff --git a/example/example_test.go b/example/example_test.go index e9505f22..496ed3d3 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -13,7 +13,7 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/dummy" - "github.com/tendermint/abci/server" + abciserver "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" @@ -38,7 +38,7 @@ func testStream(t *testing.T, app types.Application) { numDeliverTxs := 200000 // Start the listener - server := server.NewSocketServer("unix://test.sock", app) + server := abciserver.NewSocketServer("unix://test.sock", app) server.SetLogger(log.TestingLogger().With("module", "abci-server")) if _, err := server.Start(); err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) @@ -111,7 +111,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { numDeliverTxs := 2000 // Start the listener - server := server.NewGRPCServer("unix://test.sock", app) + server := abciserver.NewGRPCServer("unix://test.sock", app) server.SetLogger(log.TestingLogger().With("module", "abci-server")) if _, err := server.Start(); err != nil { t.Fatalf("Error starting GRPC server: %v", err.Error()) From 43c64163d8f97d7db49dea353782ff51d49b83c1 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 9 Nov 2017 13:16:35 -0400 Subject: [PATCH 307/545] Update socket_server.go This is likely related to #125 --- server/socket_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/socket_server.go b/server/socket_server.go index adc7516c..55227e7d 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -117,7 +117,7 @@ func (s *SocketServer) acceptConnectionsRoutine() { go func() { // Wait until signal to close connection errClose := <-closeConn - if err == io.EOF { + if errClose == io.EOF { s.Logger.Error("Connection was closed by client") } else if errClose != nil { s.Logger.Error("Connection error", "error", errClose) From 64c756de477b33ddecf4bdcbe776f5ebc1615066 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Sun, 12 Nov 2017 22:30:41 -0500 Subject: [PATCH 308/545] use Makefile commands in readme [ci skip] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 33b037da..aedebee6 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ to manage an application state running in another. ``` go get github.com/tendermint/abci cd $GOPATH/src/github.com/tendermint/abci -glide install -go install ./cmd/... +make get_vendor_deps +make install ``` For background information on ABCI, motivations, and tendermint, please visit [the documentation](http://tendermint.readthedocs.io/en/master/). From 3bd8782ab211f2fec1f7302b9d931f8e3d56e7be Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 14 Nov 2017 17:03:23 +0000 Subject: [PATCH 309/545] server: minor refactor --- server/socket_server.go | 57 +++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/server/socket_server.go b/server/socket_server.go index 55227e7d..2396c556 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -59,11 +59,11 @@ func (s *SocketServer) OnStop() { s.listener.Close() s.connsMtx.Lock() + defer s.connsMtx.Unlock() for id, conn := range s.conns { delete(s.conns, id) conn.Close() } - s.connsMtx.Unlock() } func (s *SocketServer) addConn(conn net.Conn) int { @@ -78,20 +78,21 @@ func (s *SocketServer) addConn(conn net.Conn) int { } // deletes conn even if close errs -func (s *SocketServer) rmConn(connID int, conn net.Conn) error { +func (s *SocketServer) rmConn(connID int) error { s.connsMtx.Lock() defer s.connsMtx.Unlock() + conn, ok := s.conns[connID] + if !ok { + return fmt.Errorf("Connection %d does not exist", connID) + } + delete(s.conns, connID) return conn.Close() } func (s *SocketServer) acceptConnectionsRoutine() { - // semaphore := make(chan struct{}, maxNumberConnections) - for { - // semaphore <- struct{}{} - // Accept a connection s.Logger.Info("Waiting for new connection...") conn, err := s.listener.Accept() @@ -100,10 +101,11 @@ func (s *SocketServer) acceptConnectionsRoutine() { return // Ignore error from listener closing. } s.Logger.Error("Failed to accept connection: " + err.Error()) - } else { - s.Logger.Info("Accepted a new connection") + continue } + s.Logger.Info("Accepted a new connection") + connID := s.addConn(conn) closeConn := make(chan error, 2) // Push to signal connection closed @@ -112,28 +114,27 @@ func (s *SocketServer) acceptConnectionsRoutine() { // Read requests from conn and deal with them go s.handleRequests(closeConn, conn, responses) // Pull responses from 'responses' and write them to conn. - go s.handleResponses(closeConn, responses, conn) + go s.handleResponses(closeConn, conn, responses) - go func() { - // Wait until signal to close connection - errClose := <-closeConn - if errClose == io.EOF { - s.Logger.Error("Connection was closed by client") - } else if errClose != nil { - s.Logger.Error("Connection error", "error", errClose) - } else { - // never happens - s.Logger.Error("Connection was closed.") - } + // Wait until signal to close connection + go s.waitForClose(closeConn, connID) + } +} - // Close the connection - err := s.rmConn(connID, conn) - if err != nil { - s.Logger.Error("Error in closing connection", "error", err) - } +func (s *SocketServer) waitForClose(closeConn chan error, connID int) { + err := <-closeConn + if err == io.EOF { + s.Logger.Error("Connection was closed by client") + } else if err != nil { + s.Logger.Error("Connection error", "error", err) + } else { + // never happens + s.Logger.Error("Connection was closed.") + } - // <-semaphore - }() + // Close the connection + if err := s.rmConn(connID); err != nil { + s.Logger.Error("Error in closing connection", "error", err) } } @@ -200,7 +201,7 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types } // Pull responses from 'responses' and write them to conn. -func (s *SocketServer) handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) { +func (s *SocketServer) handleResponses(closeConn chan error, conn net.Conn, responses <-chan *types.Response) { var count int var bufWriter = bufio.NewWriter(conn) for { From a52b98c70e84b3fee37e6b0122e3283a8e7d603f Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 14 Nov 2017 12:25:52 -0600 Subject: [PATCH 310/545] update deps --- glide.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glide.lock b/glide.lock index 75552186..80dbc483 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 5501ab3d7136aa8fb425c995d45221849b33aefab76c5d2c192e721dad28da38 -updated: 2017-11-08T22:19:19.433856551Z +updated: 2017-11-14T18:23:41.2024073Z imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -68,13 +68,13 @@ imports: - name: github.com/tendermint/go-crypto version: b4f04f196cd719660e43b91202cd60d9a95b1837 - name: github.com/tendermint/go-wire - version: 2baffcb6b690057568bc90ef1d457efb150b979a + version: 1c96861c03231361546944d883d99593b2e6b408 subpackages: - data - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tmlibs - version: 176c2ceed611d7735e39131e312bd973afb41b7b + version: 2442a0a698d271d5cf5d6a8e7c1db20335e959c1 subpackages: - common - db From f2bf7d1b2d2552391ad1ea999346e7772d5d6cff Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 14 Nov 2017 12:26:01 -0600 Subject: [PATCH 311/545] update go version to 1.9.2 --- scripts/abci-builder/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/abci-builder/Dockerfile b/scripts/abci-builder/Dockerfile index c56fb2ea..1182085b 100644 --- a/scripts/abci-builder/Dockerfile +++ b/scripts/abci-builder/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.7.4 +FROM golang:1.9.2 RUN apt-get update && apt-get install -y --no-install-recommends \ zip \ From 1d49453ffb63dab9568d8333b75b8fd8b0f4b177 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 14 Nov 2017 12:53:40 -0600 Subject: [PATCH 312/545] fix integration tests (Fixes #131) --- Makefile | 6 +++--- tests/test_app/app.go | 2 +- tests/test_app/test.sh | 2 +- tests/test_cli/test.sh | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index a22a2e90..6c99e363 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ GOTOOLS = \ all: protoc install test -NOVENDOR = go list github.com/tendermint/abci/... | grep -v /vendor/ +PACKAGES=$(shell go list ./... | grep -v '/vendor/') install-protoc: # Download: https://github.com/google/protobuf/releases @@ -27,7 +27,7 @@ dist: # test.sh requires that we run the installed cmds, must not be out of date test: install find . -path ./vendor -prune -o -name *.sock -exec rm {} \; - @ go test -p 1 `${NOVENDOR}` + @ go test $(PACKAGES) @ bash tests/test.sh fmt: @@ -36,7 +36,7 @@ fmt: test_integrations: get_vendor_deps install test get_deps: - @ go get -d `${NOVENDOR}` + @ go get -d $(PACKAGES) tools: go get -u -v $(GOTOOLS) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 7fc3ace0..127ba78f 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -18,7 +18,7 @@ func startApp(abciApp string) *process.Process { proc, err := process.StartProcess("abci_app", "", "bash", - []string{"-c", abciApp}, + []string{"-c", fmt.Sprintf("abci-cli %s", abciApp)}, nil, os.Stdout, ) diff --git a/tests/test_app/test.sh b/tests/test_app/test.sh index 0620b476..5b523fef 100755 --- a/tests/test_app/test.sh +++ b/tests/test_app/test.sh @@ -15,7 +15,7 @@ cd "$DIR" ABCI_APP="counter" go run ./*.go # test golang counter via grpc -ABCI_APP="counter -abci=grpc" ABCI="grpc" go run ./*.go +ABCI_APP="counter --abci=grpc" ABCI="grpc" go run ./*.go # test nodejs counter # TODO: fix node app diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index 81b06a0e..ea4ea4fa 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -17,7 +17,7 @@ function testExample() { $APP &> /dev/null & sleep 2 abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" - killall $3 + killall "$3" pre=$(shasum < "${INPUT}.out") post=$(shasum < "${INPUT}.out.new") From f808dd55966831b345089c57a6b7fc1772c983ec Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 14 Nov 2017 13:09:19 -0600 Subject: [PATCH 313/545] update CHANGELOG --- CHANGELOG.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ed93b91..0cd5046c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.7.1 (November 14, 2017) + +IMPROVEMENTS: + - [cli] added version command + +BUG FIXES: + - [server] fix "Connection error module=abci-server error=EOF" + ## 0.7.0 (October 27, 2017) BREAKING CHANGES: @@ -43,7 +51,7 @@ IMPROVEMENTS: - Update imports for new `tmlibs` repository - Use the new logger - [abci-cli] Add flags to the query command for `path`, `height`, and `prove` -- [types] use `data.Bytes` and `json` tags in the `Result` struct +- [types] use `data.Bytes` and `json` tags in the `Result` struct BUG FIXES: @@ -55,9 +63,9 @@ IMPROVEMENTS: ## 0.4.0 (March 6, 2017) -BREAKING CHANGES: +BREAKING CHANGES: -- Query takes RequestQuery and returns ResponseQuery. The request is split into `data` and `path`, +- 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. @@ -66,7 +74,7 @@ message RequestQuery{ bytes data = 1; string path = 2; uint64 height = 3; - bool prove = 4; + bool prove = 4; } message ResponseQuery{ @@ -142,7 +150,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 { From bac924e3990fe9f769b813771ee1e4d9e7cb60f7 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 14 Nov 2017 13:09:27 -0600 Subject: [PATCH 314/545] update version --- version/version.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version/version.go b/version/version.go index bbea51bc..e02653d8 100644 --- a/version/version.go +++ b/version/version.go @@ -4,6 +4,6 @@ package version const Maj = "0" const Min = "7" -const Fix = "0" +const Fix = "1" -const Version = "0.7.0" +const Version = "0.7.1" From 480e4e4444842a4709c38e80729afe96f47df1ac Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 16:19:59 -0500 Subject: [PATCH 315/545] install protoc --- Makefile | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6c99e363..b9ef0b33 100644 --- a/Makefile +++ b/Makefile @@ -7,12 +7,22 @@ all: protoc install test PACKAGES=$(shell go list ./... | grep -v '/vendor/') -install-protoc: - # Download: https://github.com/google/protobuf/releases +install_protoc: + # https://github.com/google/protobuf/releases + curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ + cd protobuf-cpp-3.4.1 && \ + DIST_LANG=cpp ./configure && \ + make && \ + make install && \ + cd .. && \ + rm -rf protobuf-cpp-3.4.1 go get github.com/golang/protobuf/protoc-gen-go protoc: - @ protoc --go_out=plugins=grpc:. types/*.proto + ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" + ## ldconfig (may require sudo) + ## https://stackoverflow.com/a/25518702 + protoc --go_out=plugins=grpc:. types/*.proto install: @ go install ./cmd/... @@ -79,4 +89,4 @@ metalinter_test: tools #--enable=unparam \ #--enable=vet \ -.PHONY: all build test fmt get_deps tools +.PHONY: all build test fmt get_deps tools protoc install_protoc From 87072d3810e2c69588ff646746654d3161656dde Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 16:19:29 -0500 Subject: [PATCH 316/545] add Dockerfile for development --- Dockerfile.develop | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Dockerfile.develop diff --git a/Dockerfile.develop b/Dockerfile.develop new file mode 100644 index 00000000..daf6cb61 --- /dev/null +++ b/Dockerfile.develop @@ -0,0 +1,15 @@ +FROM golang:latest + +RUN mkdir -p /go/src/github.com/tendermint/abci +WORKDIR /go/src/github.com/tendermint/abci + +COPY Makefile /go/src/github.com/tendermint/abci/ + +RUN make install_protoc + +COPY glide.yaml /go/src/github.com/tendermint/abci/ +COPY glide.lock /go/src/github.com/tendermint/abci/ + +RUN make get_vendor_deps + +COPY . /go/src/github.com/tendermint/abci From f07c300c148ddad93a541e7b753b094ee26614e9 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 16:49:06 -0500 Subject: [PATCH 317/545] add proto section to .editorconfig --- .editorconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.editorconfig b/.editorconfig index d587999e..82f77436 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,3 +13,7 @@ indent_style = tab [*.sh] indent_style = tab + +[*.proto] +indent_style = space +indent_size = 2 From bb0d7e95261243336cb2114dcf447d307a2edfb8 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 16:52:52 -0500 Subject: [PATCH 318/545] add tags field to DeliverTx and CheckTx --- client/local_client.go | 4 +- server/socket_server.go | 4 +- types/application.go | 4 +- types/messages.go | 10 +- types/result.go | 3 + types/types.pb.go | 275 ++++++++++++++++++++++++---------------- types/types.proto | 17 ++- 7 files changed, 192 insertions(+), 125 deletions(-) diff --git a/client/local_client.go b/client/local_client.go index 8494a468..13ebc090 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -75,7 +75,7 @@ func (app *localClient) DeliverTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestDeliverTx(tx), - types.ToResponseDeliverTx(res.Code, res.Data, res.Log), + types.ToResponseDeliverTx(res.Code, res.Data, res.Log, res.Tags), ) } @@ -85,7 +85,7 @@ func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestCheckTx(tx), - types.ToResponseCheckTx(res.Code, res.Data, res.Log), + types.ToResponseCheckTx(res.Code, res.Data, res.Log, res.Tags), ) } diff --git a/server/socket_server.go b/server/socket_server.go index 2396c556..3e8ef942 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -176,10 +176,10 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types responses <- types.ToResponseSetOption(logStr) case *types.Request_DeliverTx: res := s.app.DeliverTx(r.DeliverTx.Tx) - responses <- types.ToResponseDeliverTx(res.Code, res.Data, res.Log) + responses <- types.ToResponseDeliverTx(res.Code, res.Data, res.Log, res.Tags) case *types.Request_CheckTx: res := s.app.CheckTx(r.CheckTx.Tx) - responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) + responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log, res.Tags) case *types.Request_Commit: res := s.app.Commit() responses <- types.ToResponseCommit(res.Code, res.Data, res.Log) diff --git a/types/application.go b/types/application.go index 3d9716b7..fcda5d95 100644 --- a/types/application.go +++ b/types/application.go @@ -53,12 +53,12 @@ func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { r := app.app.DeliverTx(req.Tx) - return &ResponseDeliverTx{r.Code, r.Data, r.Log}, nil + return &ResponseDeliverTx{r.Code, r.Data, r.Log, r.Tags}, nil } func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { r := app.app.CheckTx(req.Tx) - return &ResponseCheckTx{r.Code, r.Data, r.Log}, nil + return &ResponseCheckTx{r.Code, r.Data, r.Log, r.Tags}, nil } func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { diff --git a/types/messages.go b/types/messages.go index be272c38..d4a58296 100644 --- a/types/messages.go +++ b/types/messages.go @@ -4,7 +4,7 @@ import ( "io" "github.com/golang/protobuf/proto" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" ) func ToRequestEcho(message string) *Request { @@ -105,15 +105,15 @@ func ToResponseSetOption(log string) *Response { } } -func ToResponseDeliverTx(code CodeType, data []byte, log string) *Response { +func ToResponseDeliverTx(code CodeType, data []byte, log string, tags []*KVPair) *Response { return &Response{ - Value: &Response_DeliverTx{&ResponseDeliverTx{code, data, log}}, + Value: &Response_DeliverTx{&ResponseDeliverTx{code, data, log, tags}}, } } -func ToResponseCheckTx(code CodeType, data []byte, log string) *Response { +func ToResponseCheckTx(code CodeType, data []byte, log string, tags []*KVPair) *Response { return &Response{ - Value: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, + Value: &Response_CheckTx{&ResponseCheckTx{code, data, log, tags}}, } } diff --git a/types/result.go b/types/result.go index abf1e964..84f877dc 100644 --- a/types/result.go +++ b/types/result.go @@ -12,6 +12,7 @@ type Result struct { Code CodeType `json:"code"` Data data.Bytes `json:"data"` Log string `json:"log"` // Can be non-deterministic + Tags []*KVPair `json:"tags"` } func NewResult(code CodeType, data []byte, log string) Result { @@ -102,6 +103,7 @@ func (r *ResponseCheckTx) Result() Result { Code: r.Code, Data: r.Data, Log: r.Log, + Tags: r.Tags, } } @@ -111,6 +113,7 @@ func (r *ResponseDeliverTx) Result() Result { Code: r.Code, Data: r.Data, Log: r.Log, + Tags: r.Tags, } } diff --git a/types/types.pb.go b/types/types.pb.go index 4ca304ac..99396259 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: types/types.proto -// DO NOT EDIT! /* Package types is a generated protocol buffer package. @@ -38,6 +37,7 @@ It has these top-level messages: BlockID PartSetHeader Validator + KVPair */ package types @@ -1297,9 +1297,10 @@ func (m *ResponseSetOption) GetLog() string { } type ResponseDeliverTx struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` } func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } @@ -1328,10 +1329,18 @@ func (m *ResponseDeliverTx) GetLog() string { return "" } +func (m *ResponseDeliverTx) GetTags() []*KVPair { + if m != nil { + return m.Tags + } + return nil +} + type ResponseCheckTx struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1360,6 +1369,13 @@ func (m *ResponseCheckTx) GetLog() string { return "" } +func (m *ResponseCheckTx) GetTags() []*KVPair { + if m != nil { + return m.Tags + } + return nil +} + type ResponseQuery struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` @@ -1640,6 +1656,38 @@ func (m *Validator) GetPower() uint64 { return 0 } +type KVPair struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + ValueString string `protobuf:"bytes,2,opt,name=value_string,json=valueString" json:"value_string,omitempty"` + ValueInt int64 `protobuf:"varint,3,opt,name=value_int,json=valueInt" json:"value_int,omitempty"` +} + +func (m *KVPair) Reset() { *m = KVPair{} } +func (m *KVPair) String() string { return proto.CompactTextString(m) } +func (*KVPair) ProtoMessage() {} +func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *KVPair) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *KVPair) GetValueString() string { + if m != nil { + return m.ValueString + } + return "" +} + +func (m *KVPair) GetValueInt() int64 { + if m != nil { + return m.ValueInt + } + return 0 +} + func init() { proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*RequestEcho)(nil), "types.RequestEcho") @@ -1670,6 +1718,7 @@ func init() { proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") + proto.RegisterType((*KVPair)(nil), "types.KVPair") proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) } @@ -2078,107 +2127,111 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1625 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x59, 0x6f, 0xdb, 0xc6, - 0x16, 0x36, 0xb5, 0xeb, 0xd8, 0x96, 0xe9, 0xb1, 0x6c, 0xcb, 0xba, 0xf7, 0x21, 0xe0, 0x45, 0x6e, - 0xec, 0xdc, 0xdc, 0xa4, 0x70, 0x90, 0x22, 0x6e, 0x8a, 0x02, 0xde, 0x62, 0x0b, 0x41, 0x13, 0x97, - 0x59, 0x5e, 0x5a, 0x54, 0xa0, 0xc9, 0x91, 0xc4, 0x5a, 0x9a, 0x61, 0xc8, 0xa1, 0x23, 0xf7, 0x37, - 0xe4, 0xbd, 0x3f, 0xa1, 0xef, 0x05, 0xfa, 0x17, 0x0a, 0x74, 0x5f, 0x7e, 0x51, 0x31, 0x0b, 0x57, - 0x93, 0x41, 0x1f, 0xf2, 0x22, 0xf0, 0x6c, 0x33, 0x73, 0xce, 0x9c, 0xf3, 0x9d, 0x33, 0x82, 0x55, - 0x76, 0xe5, 0xe1, 0xe0, 0x9e, 0xf8, 0xbd, 0xeb, 0xf9, 0x94, 0x51, 0x54, 0x17, 0x84, 0xf1, 0x43, - 0x0d, 0x9a, 0x26, 0x7e, 0x1d, 0xe2, 0x80, 0xa1, 0x6d, 0xa8, 0x61, 0x7b, 0x42, 0x7b, 0xda, 0x0d, - 0x6d, 0x7b, 0x71, 0x17, 0xdd, 0x95, 0xea, 0x4a, 0x7a, 0x6c, 0x4f, 0xe8, 0xe9, 0x82, 0x29, 0x34, - 0xd0, 0xff, 0xa0, 0x3e, 0x9a, 0x86, 0xc1, 0xa4, 0x57, 0x11, 0xaa, 0x6b, 0x59, 0xd5, 0xc7, 0x5c, - 0x74, 0xba, 0x60, 0x4a, 0x1d, 0xbe, 0xac, 0x4b, 0x46, 0xb4, 0x57, 0x2d, 0x5a, 0x76, 0x40, 0x46, - 0x62, 0x59, 0xae, 0x81, 0x1e, 0x02, 0x04, 0x98, 0x0d, 0xa9, 0xc7, 0x5c, 0x4a, 0x7a, 0x35, 0xa1, - 0xbf, 0x99, 0xd5, 0x7f, 0x8e, 0xd9, 0x33, 0x21, 0x3e, 0x5d, 0x30, 0xdb, 0x41, 0x44, 0x70, 0x4b, - 0x07, 0x4f, 0xdd, 0x4b, 0xec, 0x0f, 0xd9, 0xbc, 0x57, 0x2f, 0xb2, 0x3c, 0x92, 0xf2, 0x17, 0x73, - 0x6e, 0xe9, 0x44, 0x04, 0xda, 0x85, 0x96, 0x3d, 0xc1, 0xf6, 0x05, 0xb7, 0x6b, 0x08, 0xbb, 0xf5, - 0xac, 0xdd, 0x21, 0x97, 0x0a, 0xab, 0xa6, 0x2d, 0x3f, 0xd1, 0x5d, 0x68, 0xd8, 0x74, 0x36, 0x73, - 0x59, 0xaf, 0x29, 0x2c, 0xba, 0x39, 0x0b, 0x21, 0x3b, 0x5d, 0x30, 0x95, 0x16, 0x0f, 0xd7, 0xeb, - 0x10, 0xfb, 0x57, 0xbd, 0x56, 0x51, 0xb8, 0x3e, 0xe3, 0x22, 0x1e, 0x2e, 0xa1, 0xc3, 0x5d, 0x71, - 0x89, 0xcb, 0x86, 0xf6, 0xc4, 0x72, 0x49, 0xaf, 0x5d, 0xe4, 0xca, 0x80, 0xb8, 0xec, 0x90, 0x8b, - 0xb9, 0x2b, 0x6e, 0x44, 0xa0, 0x47, 0xb0, 0x78, 0x8e, 0xc7, 0x2e, 0x19, 0x9e, 0x4f, 0xa9, 0x7d, - 0xd1, 0x03, 0x61, 0xda, 0xcb, 0x9a, 0x1e, 0x70, 0x85, 0x03, 0x2e, 0x3f, 0x5d, 0x30, 0xe1, 0x3c, - 0xa6, 0xd0, 0x03, 0x68, 0x63, 0xe2, 0x28, 0xd3, 0x45, 0x61, 0xba, 0x91, 0xcb, 0x00, 0xe2, 0x44, - 0x86, 0x2d, 0xac, 0xbe, 0x0f, 0x9a, 0x50, 0xbf, 0xb4, 0xa6, 0x21, 0x36, 0x6e, 0xc1, 0x62, 0x2a, - 0x53, 0x50, 0x0f, 0x9a, 0x33, 0x1c, 0x04, 0xd6, 0x18, 0x8b, 0x74, 0x6a, 0x9b, 0x11, 0x69, 0x74, - 0x60, 0x29, 0x9d, 0x27, 0x29, 0x43, 0x9e, 0x0b, 0xdc, 0xf0, 0x12, 0xfb, 0x01, 0x4f, 0x00, 0x65, - 0xa8, 0x48, 0xe3, 0x23, 0xd0, 0xf3, 0x49, 0x80, 0x74, 0xa8, 0x5e, 0xe0, 0x2b, 0xa5, 0xc9, 0x3f, - 0x51, 0x57, 0x1d, 0x48, 0xa4, 0x66, 0xdb, 0x54, 0xa7, 0x33, 0x62, 0xdb, 0x38, 0x0d, 0x50, 0x07, - 0x2a, 0x6c, 0x2e, 0x4c, 0x97, 0xcc, 0x0a, 0x9b, 0x1b, 0x37, 0xa0, 0x93, 0xbd, 0xf2, 0x6b, 0x1a, - 0x4e, 0x7c, 0x74, 0x71, 0x67, 0x08, 0x41, 0xcd, 0xb1, 0x98, 0xa5, 0x34, 0xc4, 0x37, 0xe7, 0x79, - 0x16, 0x9b, 0xa8, 0xed, 0xc5, 0x37, 0xda, 0x80, 0xc6, 0x04, 0xbb, 0xe3, 0x09, 0x13, 0x35, 0x50, - 0x33, 0x15, 0xc5, 0xcf, 0xea, 0xf9, 0xf4, 0x12, 0x8b, 0x54, 0x6f, 0x99, 0x92, 0x30, 0x56, 0x60, - 0x39, 0x93, 0x48, 0xc6, 0x51, 0x7c, 0xf8, 0xf8, 0xe2, 0xd1, 0x07, 0x00, 0x97, 0xd6, 0xd4, 0x75, - 0x2c, 0x46, 0xfd, 0xa0, 0xa7, 0xdd, 0xa8, 0x6e, 0x2f, 0xee, 0xea, 0xea, 0xbe, 0x5e, 0x45, 0x02, - 0x33, 0xa5, 0x63, 0x3c, 0x85, 0xd5, 0x6b, 0x39, 0xc0, 0x4f, 0x3b, 0xb1, 0x82, 0x49, 0xe4, 0x01, - 0xff, 0x46, 0x37, 0xf9, 0x69, 0x2d, 0x07, 0xfb, 0xaa, 0xba, 0x97, 0xd5, 0xb2, 0xa7, 0x82, 0x69, - 0x2a, 0xa1, 0xb1, 0x03, 0x2b, 0xb9, 0xc4, 0x48, 0xf9, 0xa9, 0xa5, 0xfd, 0x34, 0xde, 0xd6, 0xa1, - 0x65, 0xe2, 0xc0, 0xa3, 0x24, 0xc0, 0xe8, 0x21, 0xb4, 0xf1, 0xdc, 0xc6, 0xb2, 0xc6, 0xb5, 0x5c, - 0x8e, 0x4a, 0x9d, 0xe3, 0x48, 0xce, 0xf3, 0x3b, 0x56, 0x46, 0x3b, 0x0a, 0x9f, 0xf2, 0xa0, 0xa3, - 0x8c, 0xd2, 0x00, 0x75, 0x27, 0x02, 0xa8, 0x6a, 0xae, 0x40, 0xa5, 0x6e, 0x0e, 0xa1, 0x76, 0x14, - 0x42, 0xd5, 0x0a, 0x17, 0xce, 0x40, 0xd4, 0x5e, 0x06, 0xa2, 0xea, 0x85, 0xc7, 0x2f, 0xc1, 0xa8, - 0xbd, 0x0c, 0x46, 0x35, 0x0a, 0x4d, 0x4b, 0x40, 0xea, 0x7e, 0x0a, 0xa4, 0x9a, 0xb9, 0xda, 0x94, - 0x86, 0x05, 0x28, 0x75, 0x2f, 0x46, 0xa9, 0x56, 0x0e, 0xd7, 0x94, 0x49, 0x1e, 0xa6, 0xee, 0x44, - 0x30, 0xd5, 0x2e, 0x0c, 0x5a, 0x0e, 0xa7, 0xf6, 0x32, 0x38, 0x05, 0x85, 0xee, 0x94, 0x00, 0xd5, - 0xc7, 0x59, 0xa0, 0x92, 0x68, 0xb3, 0x95, 0xb3, 0x2d, 0x45, 0xaa, 0x0f, 0xd3, 0x48, 0xb5, 0x94, - 0xc3, 0x47, 0x95, 0x0b, 0xef, 0x84, 0xaa, 0x1d, 0x5e, 0x09, 0xb9, 0x4c, 0xe3, 0xb5, 0x88, 0x7d, - 0x9f, 0xfa, 0x0a, 0x4b, 0x24, 0x61, 0x6c, 0xf3, 0x8a, 0x4f, 0xf2, 0xeb, 0x1d, 0xb0, 0x26, 0xaa, - 0x36, 0x95, 0x5d, 0xc6, 0x37, 0x5a, 0x62, 0x2b, 0x90, 0x2d, 0x8d, 0x16, 0x6d, 0x85, 0x16, 0x29, - 0xb4, 0xab, 0x64, 0xd0, 0x0e, 0xdd, 0x86, 0xd5, 0xa9, 0x15, 0x30, 0xe9, 0xe6, 0x30, 0x03, 0x1f, - 0x2b, 0x5c, 0x20, 0xfd, 0x93, 0x38, 0xf2, 0x7f, 0x58, 0x4b, 0xe9, 0x5a, 0x9e, 0x37, 0x14, 0x45, - 0x5d, 0x13, 0x45, 0xad, 0xc7, 0xda, 0xfb, 0x9e, 0x77, 0x6a, 0x05, 0x13, 0xe3, 0x66, 0xe2, 0x7f, - 0x06, 0x49, 0xa7, 0x74, 0x1c, 0x21, 0xe9, 0x94, 0x8e, 0x8d, 0x2f, 0x13, 0xb5, 0x04, 0x34, 0xff, - 0x03, 0x35, 0x9b, 0x3a, 0xd2, 0xfb, 0xce, 0xee, 0x8a, 0x8a, 0xfb, 0x21, 0x75, 0xf0, 0x8b, 0x2b, - 0x0f, 0x9b, 0x42, 0x18, 0x7b, 0x5a, 0x49, 0xe1, 0xa2, 0x5a, 0xbf, 0x9a, 0xac, 0xff, 0x05, 0x07, - 0x90, 0x4c, 0xf6, 0xbe, 0xcf, 0xd5, 0xbf, 0xd3, 0x92, 0x0b, 0x91, 0x68, 0xfd, 0x8f, 0x16, 0xef, - 0x42, 0xdd, 0x25, 0x0e, 0x9e, 0x8b, 0xd5, 0xab, 0xa6, 0x24, 0xa2, 0x36, 0x53, 0x15, 0x3b, 0x66, - 0xdb, 0x8c, 0x0c, 0xb2, 0x24, 0x14, 0xa0, 0xd3, 0x91, 0x00, 0x86, 0x25, 0x53, 0x12, 0x29, 0x58, - 0x6c, 0x64, 0xe0, 0x5f, 0x1d, 0xba, 0x99, 0x1c, 0xfa, 0x73, 0xde, 0x82, 0xd2, 0xd5, 0xf9, 0x3e, - 0x23, 0xb2, 0x96, 0xdc, 0x67, 0x5c, 0x97, 0x46, 0x17, 0xd0, 0xf5, 0x82, 0x93, 0xad, 0x36, 0x5b, - 0x4a, 0xe8, 0xbf, 0x50, 0x77, 0xdc, 0xd1, 0xa8, 0xbc, 0xd9, 0x48, 0xb1, 0xf1, 0x6d, 0x05, 0x1a, - 0xb2, 0x55, 0xa0, 0x2d, 0x0e, 0x5b, 0x96, 0x4b, 0x86, 0xae, 0x13, 0x95, 0x8b, 0xa0, 0x07, 0x4e, - 0x2a, 0x26, 0x95, 0x4c, 0x4c, 0x10, 0xd4, 0x98, 0x3b, 0xc3, 0x2a, 0xd3, 0xc5, 0x37, 0xda, 0x84, - 0x26, 0x09, 0x67, 0x43, 0x36, 0x0f, 0x44, 0xb4, 0x6b, 0x66, 0x83, 0x84, 0xb3, 0x17, 0xf3, 0x00, - 0xed, 0xc2, 0x72, 0x2a, 0xef, 0x5d, 0x47, 0xe1, 0x71, 0x47, 0x1d, 0x4d, 0x9c, 0x7b, 0x70, 0x64, - 0x2e, 0xc6, 0x15, 0x30, 0x70, 0xd0, 0x36, 0x88, 0x82, 0x18, 0x4a, 0xcc, 0x93, 0x85, 0xd2, 0x10, - 0x71, 0xeb, 0x70, 0xbe, 0x02, 0x45, 0xde, 0x07, 0xff, 0x05, 0x6d, 0x1e, 0x49, 0xa9, 0xd2, 0x14, - 0x2a, 0x2d, 0xce, 0x10, 0xc2, 0x5b, 0xb0, 0x92, 0xf4, 0x56, 0xa9, 0xd2, 0x92, 0xab, 0x24, 0x6c, - 0xa1, 0xb8, 0x05, 0xad, 0xb8, 0x20, 0xdb, 0x42, 0xa3, 0x69, 0xa9, 0x3a, 0x1c, 0x40, 0x53, 0x1d, - 0xb1, 0xb0, 0x0f, 0xdf, 0x86, 0xba, 0x67, 0xf9, 0x2c, 0x50, 0xfd, 0x2e, 0x82, 0xe3, 0x33, 0xcb, - 0xe7, 0x03, 0x90, 0xea, 0xc6, 0x52, 0xc5, 0xd8, 0x83, 0xe5, 0x0c, 0x9f, 0x67, 0x22, 0xa3, 0xcc, - 0x9a, 0xaa, 0x4e, 0x2c, 0x89, 0x78, 0x9b, 0x4a, 0xb2, 0x8d, 0xb1, 0x07, 0xed, 0xf8, 0x0e, 0xf9, - 0xb5, 0x78, 0xe1, 0xf9, 0x13, 0x35, 0x52, 0x2d, 0x99, 0x8a, 0x12, 0x89, 0x4d, 0xdf, 0xa8, 0x91, - 0xa0, 0x66, 0x4a, 0xe2, 0xf6, 0xf7, 0x75, 0x68, 0x45, 0xa9, 0x88, 0x1a, 0x50, 0x79, 0xf6, 0x44, - 0x5f, 0x40, 0xab, 0xb0, 0x3c, 0x20, 0x0c, 0xfb, 0xc4, 0x9a, 0x1e, 0x73, 0x0c, 0xd5, 0x35, 0xce, - 0x3a, 0x26, 0x36, 0x75, 0x5c, 0x32, 0x96, 0xac, 0x0a, 0x5a, 0x82, 0xd6, 0x81, 0xe5, 0x3c, 0xa5, - 0xc4, 0xc6, 0x7a, 0x15, 0xe9, 0xb0, 0xf4, 0x92, 0x58, 0x21, 0x9b, 0x50, 0xdf, 0xfd, 0x1a, 0x3b, - 0x7a, 0x0d, 0xad, 0xc3, 0xea, 0x80, 0x04, 0xe1, 0x68, 0xe4, 0xda, 0x2e, 0x26, 0xec, 0x71, 0x48, - 0x9c, 0x40, 0xaf, 0x23, 0x04, 0x9d, 0x97, 0xe4, 0x82, 0xd0, 0x37, 0x44, 0xcd, 0x1e, 0x7a, 0x03, - 0xf5, 0xa0, 0x7b, 0x60, 0x05, 0xf8, 0x28, 0xf4, 0xa6, 0xae, 0x6d, 0x31, 0xbc, 0xef, 0x38, 0x3e, - 0x0e, 0x02, 0x1d, 0xf3, 0x45, 0xb8, 0x24, 0xbb, 0xf7, 0x28, 0x32, 0xc8, 0xac, 0x8f, 0x71, 0xa0, - 0x8f, 0xd1, 0x16, 0xac, 0x5f, 0x93, 0x88, 0x9d, 0x27, 0xe8, 0xdf, 0xd0, 0xcb, 0x8b, 0x4e, 0xac, - 0xe0, 0xcc, 0x77, 0x6d, 0xac, 0xbb, 0xa8, 0x0b, 0xba, 0x94, 0x8a, 0xdb, 0x1f, 0x10, 0x2f, 0x64, - 0xfa, 0x57, 0xd1, 0xfe, 0x8a, 0xfb, 0x2c, 0x64, 0x9c, 0x7d, 0x91, 0x63, 0x9f, 0x89, 0x08, 0xeb, - 0x53, 0xb4, 0x09, 0x6b, 0x29, 0xf6, 0x73, 0xee, 0x1f, 0x8f, 0xce, 0x2c, 0x39, 0xaf, 0x14, 0xb8, - 0x63, 0x62, 0xb1, 0xd0, 0xc7, 0x3a, 0x41, 0x1b, 0x80, 0xb8, 0x44, 0x85, 0x24, 0x72, 0x9c, 0x46, - 0x3b, 0x28, 0xbe, 0xda, 0xc1, 0xcb, 0xb3, 0xa7, 0xe1, 0xd8, 0x25, 0xfa, 0x6b, 0xb4, 0x0e, 0xfa, - 0x09, 0xbd, 0x54, 0xdc, 0x63, 0xc2, 0x5c, 0x76, 0xa5, 0xff, 0xa8, 0xa1, 0x2e, 0xac, 0x24, 0xec, - 0x13, 0x9f, 0x86, 0x9e, 0xfe, 0x93, 0x86, 0x36, 0x01, 0x25, 0xdc, 0x33, 0x9f, 0x7a, 0x34, 0xb0, - 0xa6, 0xfa, 0xcf, 0x1a, 0xda, 0x80, 0xd5, 0x13, 0x7a, 0x19, 0xdf, 0x82, 0x34, 0xf8, 0x25, 0x32, - 0x88, 0xf9, 0x9f, 0xe2, 0xd9, 0x39, 0xf6, 0xf5, 0x5f, 0x35, 0xb4, 0x05, 0xdd, 0xb4, 0x20, 0x5e, - 0xeb, 0x37, 0x4d, 0x9d, 0x28, 0x16, 0xbd, 0xa2, 0x0c, 0xeb, 0xbf, 0x47, 0x6c, 0x15, 0x07, 0xb5, - 0xd0, 0x1f, 0x1a, 0x5a, 0x83, 0x4e, 0xc2, 0x16, 0xba, 0x7f, 0x6a, 0xa8, 0x0f, 0xeb, 0x19, 0xa6, - 0x4b, 0xc6, 0x67, 0x3c, 0x69, 0xf5, 0xbf, 0xb4, 0xdd, 0xb7, 0x75, 0x58, 0xd9, 0x3f, 0x38, 0x1c, - 0xec, 0x7b, 0x72, 0x03, 0xde, 0xff, 0xee, 0x41, 0x4d, 0x74, 0xf8, 0x82, 0x67, 0x6f, 0xbf, 0x68, - 0xd4, 0x44, 0xbb, 0x50, 0x17, 0x8d, 0x1e, 0x15, 0xbd, 0x7e, 0xfb, 0x85, 0x13, 0x27, 0xdf, 0x44, - 0x8e, 0x02, 0xd7, 0x1f, 0xc1, 0xfd, 0xa2, 0xb1, 0x13, 0x7d, 0x02, 0xed, 0xa4, 0x45, 0x97, 0x3d, - 0x85, 0xfb, 0xa5, 0x03, 0x28, 0xb7, 0x4f, 0x7a, 0x77, 0xd9, 0x83, 0xb8, 0x5f, 0x3a, 0x85, 0xa2, - 0x87, 0xd0, 0x8c, 0x7a, 0x73, 0xf1, 0xb3, 0xb8, 0x5f, 0x32, 0x88, 0xf2, 0xf0, 0xc8, 0xb6, 0x5b, - 0xf4, 0xda, 0xed, 0x17, 0xce, 0x96, 0xe8, 0x01, 0x34, 0x54, 0xdb, 0x2b, 0x7c, 0x51, 0xf7, 0x8b, - 0x27, 0x58, 0xee, 0x64, 0xf2, 0x30, 0x2a, 0x7b, 0x2a, 0xf7, 0x4b, 0x67, 0x53, 0xb4, 0x0f, 0x90, - 0x7a, 0x12, 0x95, 0x3e, 0x98, 0xfb, 0xe5, 0x13, 0x2a, 0x7a, 0x04, 0xad, 0xe4, 0x15, 0x54, 0xfc, - 0x6c, 0xee, 0x97, 0x0d, 0xa9, 0xe7, 0x0d, 0xf1, 0x8f, 0xcc, 0xfd, 0xbf, 0x03, 0x00, 0x00, 0xff, - 0xff, 0xbd, 0xb6, 0xa5, 0xad, 0xa6, 0x11, 0x00, 0x00, + // 1691 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x49, 0x6f, 0x1b, 0xc9, + 0x15, 0x56, 0x73, 0xe7, 0x13, 0x45, 0xb5, 0x4a, 0x94, 0x44, 0x31, 0x39, 0xd8, 0x1d, 0x38, 0x96, + 0x1c, 0xc7, 0x0e, 0x64, 0x38, 0xb0, 0xe2, 0x20, 0x80, 0x36, 0x4b, 0x84, 0x11, 0x5b, 0x69, 0x2f, + 0x87, 0xe4, 0x40, 0xb4, 0xd8, 0x45, 0xb2, 0x22, 0xb2, 0xaa, 0xdd, 0x5d, 0x2d, 0x53, 0xb9, 0x04, + 0xb9, 0xfb, 0x9e, 0x9f, 0x30, 0xf7, 0x01, 0xe6, 0x2f, 0x0c, 0x30, 0xfb, 0xf2, 0x8b, 0x06, 0xb5, + 0xf4, 0xaa, 0xa6, 0x31, 0x87, 0xc1, 0x5c, 0x88, 0x7e, 0x5b, 0x55, 0xbd, 0x57, 0xef, 0x7d, 0xef, + 0x15, 0x61, 0x8d, 0x5f, 0x7b, 0x38, 0x78, 0x28, 0x7f, 0x1f, 0x78, 0x3e, 0xe3, 0x0c, 0x55, 0x25, + 0x61, 0x7d, 0x5e, 0x81, 0xba, 0x8d, 0xdf, 0x85, 0x38, 0xe0, 0x68, 0x07, 0x2a, 0x78, 0x38, 0x61, + 0x5d, 0xe3, 0x96, 0xb1, 0xb3, 0xbc, 0x87, 0x1e, 0x28, 0x75, 0x2d, 0x3d, 0x19, 0x4e, 0xd8, 0xd9, + 0x92, 0x2d, 0x35, 0xd0, 0x1f, 0xa0, 0x3a, 0x9a, 0x86, 0xc1, 0xa4, 0x5b, 0x92, 0xaa, 0xeb, 0x59, + 0xd5, 0x67, 0x42, 0x74, 0xb6, 0x64, 0x2b, 0x1d, 0xb1, 0x2c, 0xa1, 0x23, 0xd6, 0x2d, 0x17, 0x2d, + 0xdb, 0xa7, 0x23, 0xb9, 0xac, 0xd0, 0x40, 0x4f, 0x00, 0x02, 0xcc, 0x07, 0xcc, 0xe3, 0x84, 0xd1, + 0x6e, 0x45, 0xea, 0x6f, 0x65, 0xf5, 0x5f, 0x61, 0xfe, 0x52, 0x8a, 0xcf, 0x96, 0xec, 0x66, 0x10, + 0x11, 0xc2, 0xd2, 0xc5, 0x53, 0x72, 0x85, 0xfd, 0x01, 0x9f, 0x77, 0xab, 0x45, 0x96, 0xc7, 0x4a, + 0xfe, 0x7a, 0x2e, 0x2c, 0xdd, 0x88, 0x40, 0x7b, 0xd0, 0x18, 0x4e, 0xf0, 0xf0, 0x52, 0xd8, 0xd5, + 0xa4, 0xdd, 0x46, 0xd6, 0xee, 0x48, 0x48, 0xa5, 0x55, 0x7d, 0xa8, 0x3e, 0xd1, 0x03, 0xa8, 0x0d, + 0xd9, 0x6c, 0x46, 0x78, 0xb7, 0x2e, 0x2d, 0x3a, 0x39, 0x0b, 0x29, 0x3b, 0x5b, 0xb2, 0xb5, 0x96, + 0x08, 0xd7, 0xbb, 0x10, 0xfb, 0xd7, 0xdd, 0x46, 0x51, 0xb8, 0xfe, 0x21, 0x44, 0x22, 0x5c, 0x52, + 0x47, 0xb8, 0x42, 0x28, 0xe1, 0x83, 0xe1, 0xc4, 0x21, 0xb4, 0xdb, 0x2c, 0x72, 0xa5, 0x4f, 0x09, + 0x3f, 0x12, 0x62, 0xe1, 0x0a, 0x89, 0x08, 0xf4, 0x14, 0x96, 0x2f, 0xf0, 0x98, 0xd0, 0xc1, 0xc5, + 0x94, 0x0d, 0x2f, 0xbb, 0x20, 0x4d, 0xbb, 0x59, 0xd3, 0x43, 0xa1, 0x70, 0x28, 0xe4, 0x67, 0x4b, + 0x36, 0x5c, 0xc4, 0x14, 0x7a, 0x0c, 0x4d, 0x4c, 0x5d, 0x6d, 0xba, 0x2c, 0x4d, 0x37, 0x73, 0x19, + 0x40, 0xdd, 0xc8, 0xb0, 0x81, 0xf5, 0xf7, 0x61, 0x1d, 0xaa, 0x57, 0xce, 0x34, 0xc4, 0xd6, 0x5d, + 0x58, 0x4e, 0x65, 0x0a, 0xea, 0x42, 0x7d, 0x86, 0x83, 0xc0, 0x19, 0x63, 0x99, 0x4e, 0x4d, 0x3b, + 0x22, 0xad, 0x36, 0xb4, 0xd2, 0x79, 0x92, 0x32, 0x14, 0xb9, 0x20, 0x0c, 0xaf, 0xb0, 0x1f, 0x88, + 0x04, 0xd0, 0x86, 0x9a, 0xb4, 0xfe, 0x02, 0x66, 0x3e, 0x09, 0x90, 0x09, 0xe5, 0x4b, 0x7c, 0xad, + 0x35, 0xc5, 0x27, 0xea, 0xe8, 0x03, 0xc9, 0xd4, 0x6c, 0xda, 0xfa, 0x74, 0x56, 0x6c, 0x1b, 0xa7, + 0x01, 0x6a, 0x43, 0x89, 0xcf, 0xa5, 0x69, 0xcb, 0x2e, 0xf1, 0xb9, 0x75, 0x0b, 0xda, 0xd9, 0x2b, + 0xbf, 0xa1, 0xe1, 0xc6, 0x47, 0x97, 0x77, 0x86, 0x10, 0x54, 0x5c, 0x87, 0x3b, 0x5a, 0x43, 0x7e, + 0x0b, 0x9e, 0xe7, 0xf0, 0x89, 0xde, 0x5e, 0x7e, 0xa3, 0x4d, 0xa8, 0x4d, 0x30, 0x19, 0x4f, 0xb8, + 0xac, 0x81, 0x8a, 0xad, 0x29, 0x71, 0x56, 0xcf, 0x67, 0x57, 0x58, 0xa6, 0x7a, 0xc3, 0x56, 0x84, + 0xb5, 0x0a, 0x2b, 0x99, 0x44, 0xb2, 0x8e, 0xe3, 0xc3, 0xc7, 0x17, 0x8f, 0xfe, 0x04, 0x70, 0xe5, + 0x4c, 0x89, 0xeb, 0x70, 0xe6, 0x07, 0x5d, 0xe3, 0x56, 0x79, 0x67, 0x79, 0xcf, 0xd4, 0xf7, 0xf5, + 0x36, 0x12, 0xd8, 0x29, 0x1d, 0xeb, 0x05, 0xac, 0xdd, 0xc8, 0x01, 0x71, 0xda, 0x89, 0x13, 0x4c, + 0x22, 0x0f, 0xc4, 0x37, 0xba, 0x23, 0x4e, 0xeb, 0xb8, 0xd8, 0xd7, 0xd5, 0xbd, 0xa2, 0x97, 0x3d, + 0x93, 0x4c, 0x5b, 0x0b, 0xad, 0x5d, 0x58, 0xcd, 0x25, 0x46, 0xca, 0x4f, 0x23, 0xed, 0xa7, 0xf5, + 0xa1, 0x0a, 0x0d, 0x1b, 0x07, 0x1e, 0xa3, 0x01, 0x46, 0x4f, 0xa0, 0x89, 0xe7, 0x43, 0xac, 0x6a, + 0xdc, 0xc8, 0xe5, 0xa8, 0xd2, 0x39, 0x89, 0xe4, 0x22, 0xbf, 0x63, 0x65, 0xb4, 0xab, 0xf1, 0x29, + 0x0f, 0x3a, 0xda, 0x28, 0x0d, 0x50, 0xf7, 0x23, 0x80, 0x2a, 0xe7, 0x0a, 0x54, 0xe9, 0xe6, 0x10, + 0x6a, 0x57, 0x23, 0x54, 0xa5, 0x70, 0xe1, 0x0c, 0x44, 0xed, 0x67, 0x20, 0xaa, 0x5a, 0x78, 0xfc, + 0x05, 0x18, 0xb5, 0x9f, 0xc1, 0xa8, 0x5a, 0xa1, 0xe9, 0x02, 0x90, 0x7a, 0x94, 0x02, 0xa9, 0x7a, + 0xae, 0x36, 0x95, 0x61, 0x01, 0x4a, 0x3d, 0x8c, 0x51, 0xaa, 0x91, 0xc3, 0x35, 0x6d, 0x92, 0x87, + 0xa9, 0xfb, 0x11, 0x4c, 0x35, 0x0b, 0x83, 0x96, 0xc3, 0xa9, 0xfd, 0x0c, 0x4e, 0x41, 0xa1, 0x3b, + 0x0b, 0x80, 0xea, 0xaf, 0x59, 0xa0, 0x52, 0x68, 0xb3, 0x9d, 0xb3, 0x5d, 0x88, 0x54, 0x7f, 0x4e, + 0x23, 0x55, 0x2b, 0x87, 0x8f, 0x3a, 0x17, 0x3e, 0x0a, 0x55, 0xbb, 0xa2, 0x12, 0x72, 0x99, 0x26, + 0x6a, 0x11, 0xfb, 0x3e, 0xf3, 0x35, 0x96, 0x28, 0xc2, 0xda, 0x11, 0x15, 0x9f, 0xe4, 0xd7, 0x47, + 0x60, 0x4d, 0x56, 0x6d, 0x2a, 0xbb, 0xac, 0xff, 0x1b, 0x89, 0xad, 0x44, 0xb6, 0x34, 0x5a, 0x34, + 0x35, 0x5a, 0xa4, 0xd0, 0xae, 0x94, 0x41, 0x3b, 0x74, 0x0f, 0xd6, 0xa6, 0x4e, 0xc0, 0x95, 0x9b, + 0x83, 0x0c, 0x7c, 0xac, 0x0a, 0x81, 0xf2, 0x4f, 0xe1, 0xc8, 0x1f, 0x61, 0x3d, 0xa5, 0xeb, 0x78, + 0xde, 0x40, 0x16, 0x75, 0x45, 0x16, 0xb5, 0x19, 0x6b, 0x1f, 0x78, 0xde, 0x99, 0x13, 0x4c, 0xac, + 0x3b, 0x89, 0xff, 0x19, 0x24, 0x9d, 0xb2, 0x71, 0x84, 0xa4, 0x53, 0x36, 0xb6, 0xfe, 0x67, 0x24, + 0x7a, 0x09, 0x6a, 0xfe, 0x0e, 0x2a, 0x43, 0xe6, 0x2a, 0xf7, 0xdb, 0x7b, 0xab, 0x3a, 0xf0, 0x47, + 0xcc, 0xc5, 0xaf, 0xaf, 0x3d, 0x6c, 0x4b, 0x61, 0xec, 0x6a, 0x29, 0x05, 0x8c, 0x7a, 0x83, 0x72, + 0xbc, 0x01, 0xba, 0x0d, 0x15, 0xee, 0x8c, 0x83, 0x6e, 0x45, 0xa2, 0x57, 0x04, 0x33, 0xcf, 0xdf, + 0x9e, 0x3b, 0xc4, 0xb7, 0xa5, 0xc8, 0xfa, 0xaf, 0x00, 0x99, 0x4c, 0x86, 0xff, 0xca, 0x07, 0xf8, + 0xd4, 0x48, 0xee, 0x55, 0x81, 0xfe, 0xcf, 0xda, 0xbf, 0x03, 0x55, 0x42, 0x5d, 0x3c, 0x97, 0x07, + 0x28, 0xdb, 0x8a, 0x88, 0xba, 0x55, 0x59, 0x1e, 0x2a, 0xdb, 0xad, 0xd4, 0x5d, 0x29, 0x42, 0xf7, + 0x05, 0x36, 0x92, 0xf8, 0xd2, 0xb2, 0x15, 0x91, 0x42, 0xd7, 0x5a, 0xa6, 0x8b, 0x68, 0xbf, 0xea, + 0xc9, 0xcd, 0xfd, 0x4b, 0x74, 0xb2, 0x74, 0x91, 0xff, 0x82, 0x41, 0xb3, 0xd6, 0x93, 0xac, 0x88, + 0xcb, 0xdb, 0xea, 0x00, 0xba, 0x59, 0xb7, 0xaa, 0x63, 0x67, 0x2b, 0x12, 0xfd, 0x1e, 0xaa, 0x2e, + 0x19, 0x8d, 0x16, 0xf7, 0x2c, 0x25, 0xb6, 0x3e, 0x29, 0x41, 0x4d, 0x75, 0x1c, 0xb4, 0x2d, 0xd0, + 0xcf, 0x21, 0x74, 0x40, 0xdc, 0xa8, 0xea, 0x24, 0xdd, 0x77, 0x53, 0x31, 0x29, 0x65, 0x62, 0x82, + 0xa0, 0xc2, 0xc9, 0x0c, 0xeb, 0x82, 0x91, 0xdf, 0x68, 0x0b, 0xea, 0x34, 0x9c, 0x0d, 0xf8, 0x3c, + 0x90, 0xd1, 0xae, 0xd8, 0x35, 0x1a, 0xce, 0x5e, 0xcf, 0x03, 0xb4, 0x07, 0x2b, 0xa9, 0xf2, 0x21, + 0xae, 0x86, 0xf5, 0xb6, 0x3e, 0x9a, 0x3c, 0x77, 0xff, 0xd8, 0x5e, 0x8e, 0x0b, 0xa9, 0xef, 0xa2, + 0x1d, 0x90, 0x75, 0x35, 0x50, 0xd0, 0xa9, 0xea, 0xad, 0x26, 0xe3, 0xd6, 0x16, 0x7c, 0x8d, 0xad, + 0xa2, 0x9d, 0xfe, 0x06, 0x9a, 0x22, 0x92, 0x4a, 0xa5, 0x2e, 0x55, 0x1a, 0x82, 0x21, 0x85, 0x77, + 0x61, 0x35, 0x69, 0xd1, 0x4a, 0xa5, 0xa1, 0x56, 0x49, 0xd8, 0x52, 0x71, 0x1b, 0x1a, 0x71, 0x5d, + 0x37, 0xa5, 0x46, 0xdd, 0xd1, 0xe5, 0xdc, 0x87, 0xba, 0x3e, 0x62, 0x61, 0x3b, 0xbf, 0x07, 0x55, + 0xcf, 0xf1, 0x79, 0xa0, 0xdb, 0x66, 0x84, 0xea, 0xe7, 0x8e, 0x2f, 0xe6, 0x28, 0xdd, 0xd4, 0x95, + 0x8a, 0xb5, 0x0f, 0x2b, 0x19, 0xbe, 0xc8, 0x44, 0xce, 0xb8, 0x33, 0xd5, 0x0d, 0x5d, 0x11, 0xf1, + 0x36, 0xa5, 0x64, 0x1b, 0x6b, 0x1f, 0x9a, 0xf1, 0x1d, 0x8a, 0x6b, 0xf1, 0xc2, 0x8b, 0xe7, 0x7a, + 0x32, 0x6b, 0xd9, 0x9a, 0x92, 0x89, 0xcd, 0xde, 0xeb, 0xc9, 0xa2, 0x62, 0x2b, 0xc2, 0xfa, 0x27, + 0xd4, 0x54, 0xcd, 0x15, 0x8c, 0x73, 0xb7, 0xa1, 0x25, 0x6b, 0x62, 0x10, 0x70, 0x9f, 0xd0, 0xb1, + 0x46, 0xc9, 0x65, 0xc9, 0x7b, 0x25, 0x59, 0x22, 0xc0, 0x4a, 0x85, 0x50, 0x85, 0x90, 0x65, 0xbb, + 0x21, 0x19, 0x7d, 0xca, 0xef, 0x7d, 0x56, 0x85, 0x46, 0x94, 0xe6, 0xa8, 0x06, 0xa5, 0x97, 0xcf, + 0xcd, 0x25, 0xb4, 0x06, 0x2b, 0x7d, 0xca, 0xb1, 0x4f, 0x9d, 0xe9, 0x89, 0x80, 0x79, 0xd3, 0x10, + 0xac, 0x13, 0x3a, 0x64, 0x2e, 0xa1, 0x63, 0xc5, 0x2a, 0xa1, 0x16, 0x34, 0x0e, 0x1d, 0xf7, 0x05, + 0xa3, 0x43, 0x6c, 0x96, 0x91, 0x09, 0xad, 0x37, 0xd4, 0x09, 0xf9, 0x84, 0xf9, 0xe4, 0x3f, 0xd8, + 0x35, 0x2b, 0x68, 0x03, 0xd6, 0xfa, 0x34, 0x08, 0x47, 0x23, 0x32, 0x24, 0x98, 0xf2, 0x67, 0x21, + 0x75, 0x03, 0xb3, 0x8a, 0x10, 0xb4, 0xdf, 0xd0, 0x4b, 0xca, 0xde, 0x53, 0x3d, 0x1e, 0x99, 0x35, + 0xd4, 0x85, 0xce, 0xa1, 0x13, 0xe0, 0xe3, 0xd0, 0x9b, 0x92, 0xa1, 0xc3, 0xf1, 0x81, 0xeb, 0xfa, + 0x38, 0x08, 0x4c, 0x2c, 0x16, 0x11, 0x92, 0xec, 0xde, 0xa3, 0xc8, 0x20, 0xb3, 0x3e, 0xc6, 0x81, + 0x39, 0x46, 0xdb, 0xb0, 0x71, 0x43, 0x22, 0x77, 0x9e, 0xa0, 0xdf, 0x42, 0x37, 0x2f, 0x3a, 0x75, + 0x82, 0x73, 0x9f, 0x0c, 0xb1, 0x49, 0x50, 0x07, 0x4c, 0x25, 0x95, 0x99, 0xd5, 0xa7, 0x5e, 0xc8, + 0xcd, 0x7f, 0x47, 0xfb, 0x6b, 0xee, 0xcb, 0x90, 0x0b, 0xf6, 0x65, 0x8e, 0x7d, 0x2e, 0x6f, 0xcf, + 0x9c, 0xa2, 0x2d, 0x58, 0x4f, 0xb1, 0x5f, 0x09, 0xff, 0x44, 0x74, 0x66, 0xc9, 0x79, 0x95, 0x80, + 0x8c, 0xa9, 0xc3, 0x43, 0x1f, 0x9b, 0x14, 0x6d, 0x02, 0x12, 0x12, 0x1d, 0x92, 0xc8, 0x71, 0x16, + 0xed, 0xa0, 0xf9, 0x7a, 0x07, 0x2f, 0xcf, 0x9e, 0x86, 0x63, 0x42, 0xcd, 0x77, 0x68, 0x03, 0xcc, + 0x53, 0x76, 0xa5, 0xb9, 0x27, 0x94, 0x13, 0x7e, 0x6d, 0x7e, 0x61, 0xa0, 0x0e, 0xac, 0x26, 0xec, + 0x53, 0x9f, 0x85, 0x9e, 0xf9, 0xa5, 0x81, 0xb6, 0x00, 0x25, 0xdc, 0x73, 0x9f, 0x79, 0x2c, 0x70, + 0xa6, 0xe6, 0x57, 0x06, 0xda, 0x84, 0xb5, 0x53, 0x76, 0x15, 0xdf, 0x82, 0x32, 0xf8, 0x3a, 0x32, + 0x88, 0xf9, 0x7f, 0xc7, 0xb3, 0x0b, 0xec, 0x9b, 0xdf, 0x18, 0x68, 0x1b, 0x3a, 0x69, 0x41, 0xbc, + 0xd6, 0xb7, 0x86, 0x3e, 0x51, 0x2c, 0x7a, 0xcb, 0x38, 0x36, 0xbf, 0x8b, 0xd8, 0x3a, 0x0e, 0x7a, + 0xa1, 0xef, 0x0d, 0xb4, 0x0e, 0xed, 0x84, 0x2d, 0x75, 0x7f, 0x30, 0x50, 0x0f, 0x36, 0x32, 0x4c, + 0x42, 0xc7, 0xe7, 0xa2, 0x20, 0xcc, 0x1f, 0x8d, 0xbd, 0x0f, 0x55, 0x58, 0x3d, 0x38, 0x3c, 0xea, + 0x1f, 0x78, 0x6a, 0x03, 0xd1, 0xa2, 0x1f, 0x42, 0x45, 0x0e, 0x21, 0x05, 0x2f, 0xf3, 0x5e, 0xd1, + 0x34, 0x8c, 0xf6, 0xa0, 0x2a, 0x67, 0x11, 0x54, 0xf4, 0x40, 0xef, 0x15, 0x0e, 0xc5, 0x62, 0x13, + 0x35, 0xad, 0xdc, 0x7c, 0xa7, 0xf7, 0x8a, 0x26, 0x63, 0xf4, 0x37, 0x68, 0x26, 0x53, 0xc4, 0xa2, + 0xd7, 0x7a, 0x6f, 0xe1, 0x8c, 0x2c, 0xec, 0x93, 0xe9, 0x62, 0xd1, 0x9b, 0xbd, 0xb7, 0x70, 0x50, + 0x46, 0x4f, 0xa0, 0x1e, 0x8d, 0x06, 0xc5, 0x2f, 0xf7, 0xde, 0x82, 0x59, 0x59, 0x84, 0x47, 0xb5, + 0xf4, 0xa2, 0x07, 0x79, 0xaf, 0x70, 0xfc, 0x45, 0x8f, 0xa1, 0xa6, 0x5b, 0x6a, 0xe1, 0xa3, 0xbf, + 0x57, 0x3c, 0x64, 0x0b, 0x27, 0x93, 0xb7, 0xdb, 0xa2, 0xd7, 0x7c, 0x6f, 0xe1, 0xf8, 0x8c, 0x0e, + 0x00, 0x52, 0xaf, 0xb6, 0x85, 0x6f, 0xfa, 0xde, 0xe2, 0x21, 0x1a, 0x3d, 0x85, 0x46, 0xf2, 0x50, + 0x2b, 0x7e, 0xd9, 0xf7, 0x16, 0xcd, 0xd1, 0x17, 0x35, 0xf9, 0xa7, 0xd1, 0xa3, 0x9f, 0x02, 0x00, + 0x00, 0xff, 0xff, 0x37, 0x8d, 0xa7, 0x8f, 0x49, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 802d8fc5..6d19a8ed 100644 --- a/types/types.proto +++ b/types/types.proto @@ -156,15 +156,17 @@ message ResponseSetOption{ } message ResponseDeliverTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; + repeated KVPair tags = 4; } message ResponseCheckTx{ CodeType code = 1; bytes data = 2; string log = 3; + repeated KVPair tags = 4; } message ResponseQuery{ @@ -224,6 +226,15 @@ message Validator { uint64 power = 2; } +//---------------------------------------- +// Abstract types + +message KVPair { + string key = 1; + string value_string = 2; + int64 value_int = 3; +} + //---------------------------------------- // Service Definition From 33b51378f27c4aa8015c960f109295cd286f28a8 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 16:56:24 -0500 Subject: [PATCH 319/545] reformat types.proto --- types/types.proto | 242 +++++++++++++++++++++++----------------------- 1 file changed, 121 insertions(+), 121 deletions(-) diff --git a/types/types.proto b/types/types.proto index 6d19a8ed..09dcb1bd 100644 --- a/types/types.proto +++ b/types/types.proto @@ -7,42 +7,42 @@ package types; // Code types enum CodeType { - OK = 0; + OK = 0; - // General response codes, 0 ~ 99 - InternalError = 1; - EncodingError = 2; - BadNonce = 3; - Unauthorized = 4; - InsufficientFunds = 5; - UnknownRequest = 6; + // 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 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; + // Reserved for governance, 200 ~ 299 + GovUnknownEntity = 201; + GovUnknownGroup = 202; + GovUnknownProposal = 203; + GovDuplicateGroup = 204; + GovDuplicateMember = 205; + GovDuplicateProposal = 206; + GovDuplicateVote = 207; + GovInvalidMember = 208; + GovInvalidVote = 209; + GovInvalidVotingPower = 210; } @@ -50,66 +50,66 @@ enum CodeType { // Request types message Request { - oneof value{ - RequestEcho echo = 1; - RequestFlush flush = 2; - RequestInfo info = 3; - RequestSetOption set_option = 4; - RequestDeliverTx deliver_tx = 5; - RequestCheckTx check_tx = 6; - RequestCommit commit = 7; - RequestQuery query = 8; - RequestInitChain init_chain = 9; - RequestBeginBlock begin_block = 10; - RequestEndBlock end_block = 11; - } + oneof value{ + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestDeliverTx deliver_tx = 5; + RequestCheckTx check_tx = 6; + RequestCommit commit = 7; + RequestQuery query = 8; + RequestInitChain init_chain = 9; + RequestBeginBlock begin_block = 10; + RequestEndBlock end_block = 11; + } } message RequestEcho { - string message = 1; + string message = 1; } message RequestFlush { } message RequestInfo { - string version = 1; + string version = 1; } message RequestSetOption{ - string key = 1; - string value = 2; + string key = 1; + string value = 2; } message RequestDeliverTx{ - bytes tx = 1; + bytes tx = 1; } message RequestCheckTx{ - bytes tx = 1; + bytes tx = 1; } message RequestQuery{ - bytes data = 1; - string path = 2; - uint64 height = 3; - bool prove = 4; + bytes data = 1; + string path = 2; + uint64 height = 3; + bool prove = 4; } message RequestCommit{ } message RequestInitChain{ - repeated Validator validators = 1; + repeated Validator validators = 1; } message RequestBeginBlock{ - bytes hash = 1; - Header header = 2; + bytes hash = 1; + Header header = 2; } message RequestEndBlock{ - uint64 height = 1; + uint64 height = 1; } //---------------------------------------- @@ -117,42 +117,42 @@ message RequestEndBlock{ message Response { - oneof value{ - ResponseException exception = 1; - ResponseEcho echo = 2; - ResponseFlush flush = 3; - ResponseInfo info = 4; - ResponseSetOption set_option = 5; - ResponseDeliverTx deliver_tx = 6; - ResponseCheckTx check_tx = 7; - ResponseCommit commit = 8; - ResponseQuery query = 9; - ResponseInitChain init_chain = 10; - ResponseBeginBlock begin_block = 11; - ResponseEndBlock end_block = 12; - } + oneof value{ + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseDeliverTx deliver_tx = 6; + ResponseCheckTx check_tx = 7; + ResponseCommit commit = 8; + ResponseQuery query = 9; + ResponseInitChain init_chain = 10; + ResponseBeginBlock begin_block = 11; + ResponseEndBlock end_block = 12; + } } message ResponseException{ - string error = 1; + string error = 1; } message ResponseEcho { - string message = 1; + string message = 1; } message ResponseFlush{ } message ResponseInfo { - string data = 1; - string version = 2; - uint64 last_block_height = 3; - bytes last_block_app_hash = 4; + string data = 1; + string version = 2; + uint64 last_block_height = 3; + bytes last_block_app_hash = 4; } message ResponseSetOption{ - string log = 1; + string log = 1; } message ResponseDeliverTx{ @@ -163,26 +163,26 @@ message ResponseDeliverTx{ } message ResponseCheckTx{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; repeated KVPair tags = 4; } message ResponseQuery{ - CodeType code = 1; - int64 index = 2; - bytes key = 3; - bytes value = 4; - bytes proof = 5; - uint64 height = 6; - string log = 7; + CodeType code = 1; + int64 index = 2; + bytes key = 3; + bytes value = 4; + bytes proof = 5; + uint64 height = 6; + string log = 7; } message ResponseCommit{ - CodeType code = 1; - bytes data = 2; - string log = 3; + CodeType code = 1; + bytes data = 2; + string log = 3; } @@ -193,37 +193,37 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 1; + repeated Validator diffs = 1; } //---------------------------------------- // Blockchain Types message Header { - string chain_id = 1; - uint64 height = 2; - uint64 time = 3; - uint64 num_txs = 4; - BlockID last_block_id = 5; - bytes last_commit_hash = 6; - bytes data_hash = 7; - bytes validators_hash = 8; - bytes app_hash = 9; + string chain_id = 1; + uint64 height = 2; + uint64 time = 3; + uint64 num_txs = 4; + BlockID last_block_id = 5; + bytes last_commit_hash = 6; + bytes data_hash = 7; + bytes validators_hash = 8; + bytes app_hash = 9; } message BlockID { - bytes hash = 1; - PartSetHeader parts = 2; + bytes hash = 1; + PartSetHeader parts = 2; } message PartSetHeader { - uint64 total = 1; - bytes hash = 2; + uint64 total = 1; + bytes hash = 2; } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pubKey = 1; + uint64 power = 2; } //---------------------------------------- @@ -239,15 +239,15 @@ message KVPair { // Service Definition service ABCIApplication { - rpc Echo(RequestEcho) returns (ResponseEcho) ; - rpc Flush(RequestFlush) returns (ResponseFlush); - rpc Info(RequestInfo) returns (ResponseInfo); - rpc SetOption(RequestSetOption) returns (ResponseSetOption); - rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); - rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); - rpc Query(RequestQuery) returns (ResponseQuery); - rpc Commit(RequestCommit) returns (ResponseCommit); - rpc InitChain(RequestInitChain) returns (ResponseInitChain); - rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); - rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); + rpc Echo(RequestEcho) returns (ResponseEcho) ; + rpc Flush(RequestFlush) returns (ResponseFlush); + rpc Info(RequestInfo) returns (ResponseInfo); + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + rpc Query(RequestQuery) returns (ResponseQuery); + rpc Commit(RequestCommit) returns (ResponseCommit); + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); } From 76bd68f881af267ed31c85e6df8bea9575b4d2f9 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 16:59:09 -0500 Subject: [PATCH 320/545] add docker commands to Makefile --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b9ef0b33..33553a28 100644 --- a/Makefile +++ b/Makefile @@ -89,4 +89,10 @@ metalinter_test: tools #--enable=unparam \ #--enable=vet \ -.PHONY: all build test fmt get_deps tools protoc install_protoc +build-docker: + docker build -t "tendermint/abci-dev" -f Dockerfile.develop . + +run-docker: + docker run -it --rm -v "$PWD:/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash + +.PHONY: all build test fmt get_deps tools protoc install_protoc build-docker run-docker From 8b71e47002311241b6a47b9680d573d1bec63d6b Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 17:15:09 -0500 Subject: [PATCH 321/545] add linter for proto files (Fixes #128) --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 33553a28..c82e8854 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ GOTOOLS = \ github.com/mitchellh/gox \ github.com/Masterminds/glide \ - github.com/alecthomas/gometalinter + github.com/alecthomas/gometalinter \ + github.com/ckaznocha/protoc-gen-lint all: protoc install test @@ -57,10 +58,12 @@ get_vendor_deps: metalinter: tools @gometalinter --install + protoc --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... metalinter_test: tools @gometalinter --install + # protoc --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ From 3cbf44058db3a6f74b01db217937edd9a18c884f Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 9 Nov 2017 17:16:06 -0500 Subject: [PATCH 322/545] no need for protoc in make all since we have types.pb.go generated --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c82e8854..06efbf34 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ GOTOOLS = \ github.com/alecthomas/gometalinter \ github.com/ckaznocha/protoc-gen-lint -all: protoc install test +all: install test PACKAGES=$(shell go list ./... | grep -v '/vendor/') From 29c1cd03ea5402d3515d302b867b0e2b5d92d714 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 20 Nov 2017 17:09:18 -0600 Subject: [PATCH 323/545] [make install_protoc] fix folder name --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 06efbf34..aeb6d716 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,12 @@ PACKAGES=$(shell go list ./... | grep -v '/vendor/') install_protoc: # https://github.com/google/protobuf/releases curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ - cd protobuf-cpp-3.4.1 && \ + cd protobuf-3.4.1 && \ DIST_LANG=cpp ./configure && \ make && \ make install && \ cd .. && \ - rm -rf protobuf-cpp-3.4.1 + rm -rf protobuf-3.4.1 go get github.com/golang/protobuf/protoc-gen-go protoc: From 02399071ff8fa443a600c75b36baa5ef8b517282 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 20 Nov 2017 18:17:56 -0600 Subject: [PATCH 324/545] add ldconfig cmd to Dockerfile --- Dockerfile.develop | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile.develop b/Dockerfile.develop index daf6cb61..e21350ce 100644 --- a/Dockerfile.develop +++ b/Dockerfile.develop @@ -6,6 +6,8 @@ WORKDIR /go/src/github.com/tendermint/abci COPY Makefile /go/src/github.com/tendermint/abci/ RUN make install_protoc +# see make protoc for details +RUN ldconfig COPY glide.yaml /go/src/github.com/tendermint/abci/ COPY glide.lock /go/src/github.com/tendermint/abci/ From fc7db13fa8cf929a277843f7868089ea2237b0fe Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 20 Nov 2017 18:21:59 -0600 Subject: [PATCH 325/545] remove tags from CheckTx add value_type field to KVPair --- client/local_client.go | 2 +- server/socket_server.go | 2 +- types/application.go | 2 +- types/base_app.go | 24 ++-- types/messages.go | 4 +- types/result.go | 1 - types/types.pb.go | 267 ++++++++++++++++++++++------------------ types/types.proto | 10 +- 8 files changed, 170 insertions(+), 142 deletions(-) diff --git a/client/local_client.go b/client/local_client.go index 13ebc090..539c1eef 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -85,7 +85,7 @@ func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestCheckTx(tx), - types.ToResponseCheckTx(res.Code, res.Data, res.Log, res.Tags), + types.ToResponseCheckTx(res.Code, res.Data, res.Log), ) } diff --git a/server/socket_server.go b/server/socket_server.go index 3e8ef942..68a21322 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -179,7 +179,7 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types responses <- types.ToResponseDeliverTx(res.Code, res.Data, res.Log, res.Tags) case *types.Request_CheckTx: res := s.app.CheckTx(r.CheckTx.Tx) - responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log, res.Tags) + responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) case *types.Request_Commit: res := s.app.Commit() responses <- types.ToResponseCommit(res.Code, res.Data, res.Log) diff --git a/types/application.go b/types/application.go index fcda5d95..51a1869b 100644 --- a/types/application.go +++ b/types/application.go @@ -58,7 +58,7 @@ func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { r := app.app.CheckTx(req.Tx) - return &ResponseCheckTx{r.Code, r.Data, r.Log, r.Tags}, nil + return &ResponseCheckTx{r.Code, r.Data, r.Log}, nil } func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { diff --git a/types/base_app.go b/types/base_app.go index 94607e9a..60bf4388 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -7,36 +7,36 @@ func NewBaseApplication() *BaseApplication { return &BaseApplication{} } -func (app *BaseApplication) Info(req RequestInfo) (resInfo ResponseInfo) { - return +func (BaseApplication) Info(req RequestInfo) ResponseInfo { + return ResponseInfo{} } -func (app *BaseApplication) SetOption(key string, value string) (log string) { +func (BaseApplication) SetOption(key string, value string) (log string) { return "" } -func (app *BaseApplication) DeliverTx(tx []byte) Result { +func (BaseApplication) DeliverTx(tx []byte) Result { return NewResultOK(nil, "") } -func (app *BaseApplication) CheckTx(tx []byte) Result { +func (BaseApplication) CheckTx(tx []byte) Result { return NewResultOK(nil, "") } -func (app *BaseApplication) Commit() Result { +func (BaseApplication) Commit() Result { return NewResultOK([]byte("nil"), "") } -func (app *BaseApplication) Query(req RequestQuery) (resQuery ResponseQuery) { - return +func (BaseApplication) Query(req RequestQuery) ResponseQuery { + return ResponseQuery{} } -func (app *BaseApplication) InitChain(req RequestInitChain) { +func (BaseApplication) InitChain(req RequestInitChain) { } -func (app *BaseApplication) BeginBlock(req RequestBeginBlock) { +func (BaseApplication) BeginBlock(req RequestBeginBlock) { } -func (app *BaseApplication) EndBlock(height uint64) (resEndBlock ResponseEndBlock) { - return +func (BaseApplication) EndBlock(height uint64) ResponseEndBlock { + return ResponseEndBlock{} } diff --git a/types/messages.go b/types/messages.go index d4a58296..298f17ba 100644 --- a/types/messages.go +++ b/types/messages.go @@ -111,9 +111,9 @@ func ToResponseDeliverTx(code CodeType, data []byte, log string, tags []*KVPair) } } -func ToResponseCheckTx(code CodeType, data []byte, log string, tags []*KVPair) *Response { +func ToResponseCheckTx(code CodeType, data []byte, log string) *Response { return &Response{ - Value: &Response_CheckTx{&ResponseCheckTx{code, data, log, tags}}, + Value: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, } } diff --git a/types/result.go b/types/result.go index 84f877dc..96dd4e79 100644 --- a/types/result.go +++ b/types/result.go @@ -103,7 +103,6 @@ func (r *ResponseCheckTx) Result() Result { Code: r.Code, Data: r.Data, Log: r.Log, - Tags: r.Tags, } } diff --git a/types/types.pb.go b/types/types.pb.go index 99396259..0cd97679 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -169,6 +169,27 @@ func (x CodeType) String() string { } func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +type KVPair_Type int32 + +const ( + KVPair_STRING KVPair_Type = 0 + KVPair_INT KVPair_Type = 1 +) + +var KVPair_Type_name = map[int32]string{ + 0: "STRING", + 1: "INT", +} +var KVPair_Type_value = map[string]int32{ + "STRING": 0, + "INT": 1, +} + +func (x KVPair_Type) String() string { + return proto.EnumName(KVPair_Type_name, int32(x)) +} +func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{29, 0} } + type Request struct { // Types that are valid to be assigned to Value: // *Request_Echo @@ -1337,10 +1358,9 @@ func (m *ResponseDeliverTx) GetTags() []*KVPair { } type ResponseCheckTx struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` - Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` + Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1369,13 +1389,6 @@ func (m *ResponseCheckTx) GetLog() string { return "" } -func (m *ResponseCheckTx) GetTags() []*KVPair { - if m != nil { - return m.Tags - } - return nil -} - type ResponseQuery struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` @@ -1657,9 +1670,10 @@ func (m *Validator) GetPower() uint64 { } type KVPair struct { - Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` - ValueString string `protobuf:"bytes,2,opt,name=value_string,json=valueString" json:"value_string,omitempty"` - ValueInt int64 `protobuf:"varint,3,opt,name=value_int,json=valueInt" json:"value_int,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + ValueType KVPair_Type `protobuf:"varint,2,opt,name=value_type,json=valueType,enum=types.KVPair_Type" json:"value_type,omitempty"` + ValueString string `protobuf:"bytes,3,opt,name=value_string,json=valueString" json:"value_string,omitempty"` + ValueInt int64 `protobuf:"varint,4,opt,name=value_int,json=valueInt" json:"value_int,omitempty"` } func (m *KVPair) Reset() { *m = KVPair{} } @@ -1674,6 +1688,13 @@ func (m *KVPair) GetKey() string { return "" } +func (m *KVPair) GetValueType() KVPair_Type { + if m != nil { + return m.ValueType + } + return KVPair_STRING +} + func (m *KVPair) GetValueString() string { if m != nil { return m.ValueString @@ -1720,6 +1741,7 @@ func init() { proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterType((*KVPair)(nil), "types.KVPair") proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) + proto.RegisterEnum("types.KVPair_Type", KVPair_Type_name, KVPair_Type_value) } // Reference imports to suppress errors if they are not otherwise used. @@ -2127,111 +2149,114 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1691 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x49, 0x6f, 0x1b, 0xc9, - 0x15, 0x56, 0x73, 0xe7, 0x13, 0x45, 0xb5, 0x4a, 0x94, 0x44, 0x31, 0x39, 0xd8, 0x1d, 0x38, 0x96, - 0x1c, 0xc7, 0x0e, 0x64, 0x38, 0xb0, 0xe2, 0x20, 0x80, 0x36, 0x4b, 0x84, 0x11, 0x5b, 0x69, 0x2f, - 0x87, 0xe4, 0x40, 0xb4, 0xd8, 0x45, 0xb2, 0x22, 0xb2, 0xaa, 0xdd, 0x5d, 0x2d, 0x53, 0xb9, 0x04, - 0xb9, 0xfb, 0x9e, 0x9f, 0x30, 0xf7, 0x01, 0xe6, 0x2f, 0x0c, 0x30, 0xfb, 0xf2, 0x8b, 0x06, 0xb5, - 0xf4, 0xaa, 0xa6, 0x31, 0x87, 0xc1, 0x5c, 0x88, 0x7e, 0x5b, 0x55, 0xbd, 0x57, 0xef, 0x7d, 0xef, - 0x15, 0x61, 0x8d, 0x5f, 0x7b, 0x38, 0x78, 0x28, 0x7f, 0x1f, 0x78, 0x3e, 0xe3, 0x0c, 0x55, 0x25, - 0x61, 0x7d, 0x5e, 0x81, 0xba, 0x8d, 0xdf, 0x85, 0x38, 0xe0, 0x68, 0x07, 0x2a, 0x78, 0x38, 0x61, - 0x5d, 0xe3, 0x96, 0xb1, 0xb3, 0xbc, 0x87, 0x1e, 0x28, 0x75, 0x2d, 0x3d, 0x19, 0x4e, 0xd8, 0xd9, - 0x92, 0x2d, 0x35, 0xd0, 0x1f, 0xa0, 0x3a, 0x9a, 0x86, 0xc1, 0xa4, 0x5b, 0x92, 0xaa, 0xeb, 0x59, - 0xd5, 0x67, 0x42, 0x74, 0xb6, 0x64, 0x2b, 0x1d, 0xb1, 0x2c, 0xa1, 0x23, 0xd6, 0x2d, 0x17, 0x2d, - 0xdb, 0xa7, 0x23, 0xb9, 0xac, 0xd0, 0x40, 0x4f, 0x00, 0x02, 0xcc, 0x07, 0xcc, 0xe3, 0x84, 0xd1, - 0x6e, 0x45, 0xea, 0x6f, 0x65, 0xf5, 0x5f, 0x61, 0xfe, 0x52, 0x8a, 0xcf, 0x96, 0xec, 0x66, 0x10, - 0x11, 0xc2, 0xd2, 0xc5, 0x53, 0x72, 0x85, 0xfd, 0x01, 0x9f, 0x77, 0xab, 0x45, 0x96, 0xc7, 0x4a, - 0xfe, 0x7a, 0x2e, 0x2c, 0xdd, 0x88, 0x40, 0x7b, 0xd0, 0x18, 0x4e, 0xf0, 0xf0, 0x52, 0xd8, 0xd5, - 0xa4, 0xdd, 0x46, 0xd6, 0xee, 0x48, 0x48, 0xa5, 0x55, 0x7d, 0xa8, 0x3e, 0xd1, 0x03, 0xa8, 0x0d, - 0xd9, 0x6c, 0x46, 0x78, 0xb7, 0x2e, 0x2d, 0x3a, 0x39, 0x0b, 0x29, 0x3b, 0x5b, 0xb2, 0xb5, 0x96, - 0x08, 0xd7, 0xbb, 0x10, 0xfb, 0xd7, 0xdd, 0x46, 0x51, 0xb8, 0xfe, 0x21, 0x44, 0x22, 0x5c, 0x52, - 0x47, 0xb8, 0x42, 0x28, 0xe1, 0x83, 0xe1, 0xc4, 0x21, 0xb4, 0xdb, 0x2c, 0x72, 0xa5, 0x4f, 0x09, - 0x3f, 0x12, 0x62, 0xe1, 0x0a, 0x89, 0x08, 0xf4, 0x14, 0x96, 0x2f, 0xf0, 0x98, 0xd0, 0xc1, 0xc5, - 0x94, 0x0d, 0x2f, 0xbb, 0x20, 0x4d, 0xbb, 0x59, 0xd3, 0x43, 0xa1, 0x70, 0x28, 0xe4, 0x67, 0x4b, - 0x36, 0x5c, 0xc4, 0x14, 0x7a, 0x0c, 0x4d, 0x4c, 0x5d, 0x6d, 0xba, 0x2c, 0x4d, 0x37, 0x73, 0x19, - 0x40, 0xdd, 0xc8, 0xb0, 0x81, 0xf5, 0xf7, 0x61, 0x1d, 0xaa, 0x57, 0xce, 0x34, 0xc4, 0xd6, 0x5d, - 0x58, 0x4e, 0x65, 0x0a, 0xea, 0x42, 0x7d, 0x86, 0x83, 0xc0, 0x19, 0x63, 0x99, 0x4e, 0x4d, 0x3b, - 0x22, 0xad, 0x36, 0xb4, 0xd2, 0x79, 0x92, 0x32, 0x14, 0xb9, 0x20, 0x0c, 0xaf, 0xb0, 0x1f, 0x88, - 0x04, 0xd0, 0x86, 0x9a, 0xb4, 0xfe, 0x02, 0x66, 0x3e, 0x09, 0x90, 0x09, 0xe5, 0x4b, 0x7c, 0xad, - 0x35, 0xc5, 0x27, 0xea, 0xe8, 0x03, 0xc9, 0xd4, 0x6c, 0xda, 0xfa, 0x74, 0x56, 0x6c, 0x1b, 0xa7, - 0x01, 0x6a, 0x43, 0x89, 0xcf, 0xa5, 0x69, 0xcb, 0x2e, 0xf1, 0xb9, 0x75, 0x0b, 0xda, 0xd9, 0x2b, - 0xbf, 0xa1, 0xe1, 0xc6, 0x47, 0x97, 0x77, 0x86, 0x10, 0x54, 0x5c, 0x87, 0x3b, 0x5a, 0x43, 0x7e, - 0x0b, 0x9e, 0xe7, 0xf0, 0x89, 0xde, 0x5e, 0x7e, 0xa3, 0x4d, 0xa8, 0x4d, 0x30, 0x19, 0x4f, 0xb8, - 0xac, 0x81, 0x8a, 0xad, 0x29, 0x71, 0x56, 0xcf, 0x67, 0x57, 0x58, 0xa6, 0x7a, 0xc3, 0x56, 0x84, - 0xb5, 0x0a, 0x2b, 0x99, 0x44, 0xb2, 0x8e, 0xe3, 0xc3, 0xc7, 0x17, 0x8f, 0xfe, 0x04, 0x70, 0xe5, - 0x4c, 0x89, 0xeb, 0x70, 0xe6, 0x07, 0x5d, 0xe3, 0x56, 0x79, 0x67, 0x79, 0xcf, 0xd4, 0xf7, 0xf5, - 0x36, 0x12, 0xd8, 0x29, 0x1d, 0xeb, 0x05, 0xac, 0xdd, 0xc8, 0x01, 0x71, 0xda, 0x89, 0x13, 0x4c, - 0x22, 0x0f, 0xc4, 0x37, 0xba, 0x23, 0x4e, 0xeb, 0xb8, 0xd8, 0xd7, 0xd5, 0xbd, 0xa2, 0x97, 0x3d, - 0x93, 0x4c, 0x5b, 0x0b, 0xad, 0x5d, 0x58, 0xcd, 0x25, 0x46, 0xca, 0x4f, 0x23, 0xed, 0xa7, 0xf5, - 0xa1, 0x0a, 0x0d, 0x1b, 0x07, 0x1e, 0xa3, 0x01, 0x46, 0x4f, 0xa0, 0x89, 0xe7, 0x43, 0xac, 0x6a, - 0xdc, 0xc8, 0xe5, 0xa8, 0xd2, 0x39, 0x89, 0xe4, 0x22, 0xbf, 0x63, 0x65, 0xb4, 0xab, 0xf1, 0x29, - 0x0f, 0x3a, 0xda, 0x28, 0x0d, 0x50, 0xf7, 0x23, 0x80, 0x2a, 0xe7, 0x0a, 0x54, 0xe9, 0xe6, 0x10, - 0x6a, 0x57, 0x23, 0x54, 0xa5, 0x70, 0xe1, 0x0c, 0x44, 0xed, 0x67, 0x20, 0xaa, 0x5a, 0x78, 0xfc, - 0x05, 0x18, 0xb5, 0x9f, 0xc1, 0xa8, 0x5a, 0xa1, 0xe9, 0x02, 0x90, 0x7a, 0x94, 0x02, 0xa9, 0x7a, - 0xae, 0x36, 0x95, 0x61, 0x01, 0x4a, 0x3d, 0x8c, 0x51, 0xaa, 0x91, 0xc3, 0x35, 0x6d, 0x92, 0x87, - 0xa9, 0xfb, 0x11, 0x4c, 0x35, 0x0b, 0x83, 0x96, 0xc3, 0xa9, 0xfd, 0x0c, 0x4e, 0x41, 0xa1, 0x3b, - 0x0b, 0x80, 0xea, 0xaf, 0x59, 0xa0, 0x52, 0x68, 0xb3, 0x9d, 0xb3, 0x5d, 0x88, 0x54, 0x7f, 0x4e, - 0x23, 0x55, 0x2b, 0x87, 0x8f, 0x3a, 0x17, 0x3e, 0x0a, 0x55, 0xbb, 0xa2, 0x12, 0x72, 0x99, 0x26, - 0x6a, 0x11, 0xfb, 0x3e, 0xf3, 0x35, 0x96, 0x28, 0xc2, 0xda, 0x11, 0x15, 0x9f, 0xe4, 0xd7, 0x47, - 0x60, 0x4d, 0x56, 0x6d, 0x2a, 0xbb, 0xac, 0xff, 0x1b, 0x89, 0xad, 0x44, 0xb6, 0x34, 0x5a, 0x34, - 0x35, 0x5a, 0xa4, 0xd0, 0xae, 0x94, 0x41, 0x3b, 0x74, 0x0f, 0xd6, 0xa6, 0x4e, 0xc0, 0x95, 0x9b, - 0x83, 0x0c, 0x7c, 0xac, 0x0a, 0x81, 0xf2, 0x4f, 0xe1, 0xc8, 0x1f, 0x61, 0x3d, 0xa5, 0xeb, 0x78, - 0xde, 0x40, 0x16, 0x75, 0x45, 0x16, 0xb5, 0x19, 0x6b, 0x1f, 0x78, 0xde, 0x99, 0x13, 0x4c, 0xac, - 0x3b, 0x89, 0xff, 0x19, 0x24, 0x9d, 0xb2, 0x71, 0x84, 0xa4, 0x53, 0x36, 0xb6, 0xfe, 0x67, 0x24, - 0x7a, 0x09, 0x6a, 0xfe, 0x0e, 0x2a, 0x43, 0xe6, 0x2a, 0xf7, 0xdb, 0x7b, 0xab, 0x3a, 0xf0, 0x47, - 0xcc, 0xc5, 0xaf, 0xaf, 0x3d, 0x6c, 0x4b, 0x61, 0xec, 0x6a, 0x29, 0x05, 0x8c, 0x7a, 0x83, 0x72, - 0xbc, 0x01, 0xba, 0x0d, 0x15, 0xee, 0x8c, 0x83, 0x6e, 0x45, 0xa2, 0x57, 0x04, 0x33, 0xcf, 0xdf, - 0x9e, 0x3b, 0xc4, 0xb7, 0xa5, 0xc8, 0xfa, 0xaf, 0x00, 0x99, 0x4c, 0x86, 0xff, 0xca, 0x07, 0xf8, - 0xd4, 0x48, 0xee, 0x55, 0x81, 0xfe, 0xcf, 0xda, 0xbf, 0x03, 0x55, 0x42, 0x5d, 0x3c, 0x97, 0x07, - 0x28, 0xdb, 0x8a, 0x88, 0xba, 0x55, 0x59, 0x1e, 0x2a, 0xdb, 0xad, 0xd4, 0x5d, 0x29, 0x42, 0xf7, - 0x05, 0x36, 0x92, 0xf8, 0xd2, 0xb2, 0x15, 0x91, 0x42, 0xd7, 0x5a, 0xa6, 0x8b, 0x68, 0xbf, 0xea, - 0xc9, 0xcd, 0xfd, 0x4b, 0x74, 0xb2, 0x74, 0x91, 0xff, 0x82, 0x41, 0xb3, 0xd6, 0x93, 0xac, 0x88, - 0xcb, 0xdb, 0xea, 0x00, 0xba, 0x59, 0xb7, 0xaa, 0x63, 0x67, 0x2b, 0x12, 0xfd, 0x1e, 0xaa, 0x2e, - 0x19, 0x8d, 0x16, 0xf7, 0x2c, 0x25, 0xb6, 0x3e, 0x29, 0x41, 0x4d, 0x75, 0x1c, 0xb4, 0x2d, 0xd0, - 0xcf, 0x21, 0x74, 0x40, 0xdc, 0xa8, 0xea, 0x24, 0xdd, 0x77, 0x53, 0x31, 0x29, 0x65, 0x62, 0x82, - 0xa0, 0xc2, 0xc9, 0x0c, 0xeb, 0x82, 0x91, 0xdf, 0x68, 0x0b, 0xea, 0x34, 0x9c, 0x0d, 0xf8, 0x3c, - 0x90, 0xd1, 0xae, 0xd8, 0x35, 0x1a, 0xce, 0x5e, 0xcf, 0x03, 0xb4, 0x07, 0x2b, 0xa9, 0xf2, 0x21, - 0xae, 0x86, 0xf5, 0xb6, 0x3e, 0x9a, 0x3c, 0x77, 0xff, 0xd8, 0x5e, 0x8e, 0x0b, 0xa9, 0xef, 0xa2, - 0x1d, 0x90, 0x75, 0x35, 0x50, 0xd0, 0xa9, 0xea, 0xad, 0x26, 0xe3, 0xd6, 0x16, 0x7c, 0x8d, 0xad, - 0xa2, 0x9d, 0xfe, 0x06, 0x9a, 0x22, 0x92, 0x4a, 0xa5, 0x2e, 0x55, 0x1a, 0x82, 0x21, 0x85, 0x77, - 0x61, 0x35, 0x69, 0xd1, 0x4a, 0xa5, 0xa1, 0x56, 0x49, 0xd8, 0x52, 0x71, 0x1b, 0x1a, 0x71, 0x5d, - 0x37, 0xa5, 0x46, 0xdd, 0xd1, 0xe5, 0xdc, 0x87, 0xba, 0x3e, 0x62, 0x61, 0x3b, 0xbf, 0x07, 0x55, - 0xcf, 0xf1, 0x79, 0xa0, 0xdb, 0x66, 0x84, 0xea, 0xe7, 0x8e, 0x2f, 0xe6, 0x28, 0xdd, 0xd4, 0x95, - 0x8a, 0xb5, 0x0f, 0x2b, 0x19, 0xbe, 0xc8, 0x44, 0xce, 0xb8, 0x33, 0xd5, 0x0d, 0x5d, 0x11, 0xf1, - 0x36, 0xa5, 0x64, 0x1b, 0x6b, 0x1f, 0x9a, 0xf1, 0x1d, 0x8a, 0x6b, 0xf1, 0xc2, 0x8b, 0xe7, 0x7a, - 0x32, 0x6b, 0xd9, 0x9a, 0x92, 0x89, 0xcd, 0xde, 0xeb, 0xc9, 0xa2, 0x62, 0x2b, 0xc2, 0xfa, 0x27, - 0xd4, 0x54, 0xcd, 0x15, 0x8c, 0x73, 0xb7, 0xa1, 0x25, 0x6b, 0x62, 0x10, 0x70, 0x9f, 0xd0, 0xb1, - 0x46, 0xc9, 0x65, 0xc9, 0x7b, 0x25, 0x59, 0x22, 0xc0, 0x4a, 0x85, 0x50, 0x85, 0x90, 0x65, 0xbb, - 0x21, 0x19, 0x7d, 0xca, 0xef, 0x7d, 0x56, 0x85, 0x46, 0x94, 0xe6, 0xa8, 0x06, 0xa5, 0x97, 0xcf, - 0xcd, 0x25, 0xb4, 0x06, 0x2b, 0x7d, 0xca, 0xb1, 0x4f, 0x9d, 0xe9, 0x89, 0x80, 0x79, 0xd3, 0x10, - 0xac, 0x13, 0x3a, 0x64, 0x2e, 0xa1, 0x63, 0xc5, 0x2a, 0xa1, 0x16, 0x34, 0x0e, 0x1d, 0xf7, 0x05, - 0xa3, 0x43, 0x6c, 0x96, 0x91, 0x09, 0xad, 0x37, 0xd4, 0x09, 0xf9, 0x84, 0xf9, 0xe4, 0x3f, 0xd8, - 0x35, 0x2b, 0x68, 0x03, 0xd6, 0xfa, 0x34, 0x08, 0x47, 0x23, 0x32, 0x24, 0x98, 0xf2, 0x67, 0x21, - 0x75, 0x03, 0xb3, 0x8a, 0x10, 0xb4, 0xdf, 0xd0, 0x4b, 0xca, 0xde, 0x53, 0x3d, 0x1e, 0x99, 0x35, - 0xd4, 0x85, 0xce, 0xa1, 0x13, 0xe0, 0xe3, 0xd0, 0x9b, 0x92, 0xa1, 0xc3, 0xf1, 0x81, 0xeb, 0xfa, - 0x38, 0x08, 0x4c, 0x2c, 0x16, 0x11, 0x92, 0xec, 0xde, 0xa3, 0xc8, 0x20, 0xb3, 0x3e, 0xc6, 0x81, - 0x39, 0x46, 0xdb, 0xb0, 0x71, 0x43, 0x22, 0x77, 0x9e, 0xa0, 0xdf, 0x42, 0x37, 0x2f, 0x3a, 0x75, - 0x82, 0x73, 0x9f, 0x0c, 0xb1, 0x49, 0x50, 0x07, 0x4c, 0x25, 0x95, 0x99, 0xd5, 0xa7, 0x5e, 0xc8, - 0xcd, 0x7f, 0x47, 0xfb, 0x6b, 0xee, 0xcb, 0x90, 0x0b, 0xf6, 0x65, 0x8e, 0x7d, 0x2e, 0x6f, 0xcf, - 0x9c, 0xa2, 0x2d, 0x58, 0x4f, 0xb1, 0x5f, 0x09, 0xff, 0x44, 0x74, 0x66, 0xc9, 0x79, 0x95, 0x80, - 0x8c, 0xa9, 0xc3, 0x43, 0x1f, 0x9b, 0x14, 0x6d, 0x02, 0x12, 0x12, 0x1d, 0x92, 0xc8, 0x71, 0x16, - 0xed, 0xa0, 0xf9, 0x7a, 0x07, 0x2f, 0xcf, 0x9e, 0x86, 0x63, 0x42, 0xcd, 0x77, 0x68, 0x03, 0xcc, - 0x53, 0x76, 0xa5, 0xb9, 0x27, 0x94, 0x13, 0x7e, 0x6d, 0x7e, 0x61, 0xa0, 0x0e, 0xac, 0x26, 0xec, - 0x53, 0x9f, 0x85, 0x9e, 0xf9, 0xa5, 0x81, 0xb6, 0x00, 0x25, 0xdc, 0x73, 0x9f, 0x79, 0x2c, 0x70, - 0xa6, 0xe6, 0x57, 0x06, 0xda, 0x84, 0xb5, 0x53, 0x76, 0x15, 0xdf, 0x82, 0x32, 0xf8, 0x3a, 0x32, - 0x88, 0xf9, 0x7f, 0xc7, 0xb3, 0x0b, 0xec, 0x9b, 0xdf, 0x18, 0x68, 0x1b, 0x3a, 0x69, 0x41, 0xbc, - 0xd6, 0xb7, 0x86, 0x3e, 0x51, 0x2c, 0x7a, 0xcb, 0x38, 0x36, 0xbf, 0x8b, 0xd8, 0x3a, 0x0e, 0x7a, - 0xa1, 0xef, 0x0d, 0xb4, 0x0e, 0xed, 0x84, 0x2d, 0x75, 0x7f, 0x30, 0x50, 0x0f, 0x36, 0x32, 0x4c, - 0x42, 0xc7, 0xe7, 0xa2, 0x20, 0xcc, 0x1f, 0x8d, 0xbd, 0x0f, 0x55, 0x58, 0x3d, 0x38, 0x3c, 0xea, - 0x1f, 0x78, 0x6a, 0x03, 0xd1, 0xa2, 0x1f, 0x42, 0x45, 0x0e, 0x21, 0x05, 0x2f, 0xf3, 0x5e, 0xd1, - 0x34, 0x8c, 0xf6, 0xa0, 0x2a, 0x67, 0x11, 0x54, 0xf4, 0x40, 0xef, 0x15, 0x0e, 0xc5, 0x62, 0x13, - 0x35, 0xad, 0xdc, 0x7c, 0xa7, 0xf7, 0x8a, 0x26, 0x63, 0xf4, 0x37, 0x68, 0x26, 0x53, 0xc4, 0xa2, - 0xd7, 0x7a, 0x6f, 0xe1, 0x8c, 0x2c, 0xec, 0x93, 0xe9, 0x62, 0xd1, 0x9b, 0xbd, 0xb7, 0x70, 0x50, - 0x46, 0x4f, 0xa0, 0x1e, 0x8d, 0x06, 0xc5, 0x2f, 0xf7, 0xde, 0x82, 0x59, 0x59, 0x84, 0x47, 0xb5, - 0xf4, 0xa2, 0x07, 0x79, 0xaf, 0x70, 0xfc, 0x45, 0x8f, 0xa1, 0xa6, 0x5b, 0x6a, 0xe1, 0xa3, 0xbf, - 0x57, 0x3c, 0x64, 0x0b, 0x27, 0x93, 0xb7, 0xdb, 0xa2, 0xd7, 0x7c, 0x6f, 0xe1, 0xf8, 0x8c, 0x0e, - 0x00, 0x52, 0xaf, 0xb6, 0x85, 0x6f, 0xfa, 0xde, 0xe2, 0x21, 0x1a, 0x3d, 0x85, 0x46, 0xf2, 0x50, - 0x2b, 0x7e, 0xd9, 0xf7, 0x16, 0xcd, 0xd1, 0x17, 0x35, 0xf9, 0xa7, 0xd1, 0xa3, 0x9f, 0x02, 0x00, - 0x00, 0xff, 0xff, 0x37, 0x8d, 0xa7, 0x8f, 0x49, 0x12, 0x00, 0x00, + // 1736 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcb, 0x6e, 0xdb, 0xcc, + 0x15, 0x36, 0x25, 0xea, 0x76, 0x2c, 0xcb, 0xf4, 0x58, 0xb6, 0x65, 0xa5, 0x8b, 0x84, 0x45, 0x1a, + 0x3b, 0x4d, 0x9d, 0xd6, 0x41, 0x8a, 0xb8, 0x29, 0x0a, 0xf8, 0x16, 0x5b, 0x08, 0xea, 0xb8, 0xb4, + 0x93, 0x4d, 0x0b, 0x08, 0xb4, 0x38, 0x92, 0xa6, 0x96, 0x86, 0x0c, 0x39, 0x74, 0xe4, 0xee, 0xba, + 0xcf, 0xbe, 0x8f, 0x50, 0xa0, 0xcb, 0x02, 0x7d, 0x85, 0x02, 0xff, 0xfd, 0xf2, 0x44, 0x3f, 0xe6, + 0xc2, 0xab, 0xa9, 0xe0, 0x5f, 0x64, 0x23, 0xf0, 0x5c, 0xbe, 0x99, 0x33, 0x33, 0xe7, 0x7c, 0x73, + 0x46, 0xb0, 0xc2, 0x6e, 0x3d, 0x1c, 0x3c, 0x15, 0xbf, 0x3b, 0x9e, 0xef, 0x32, 0x17, 0x55, 0x84, + 0x60, 0xfe, 0x5f, 0x87, 0x9a, 0x85, 0xdf, 0x87, 0x38, 0x60, 0x68, 0x0b, 0x74, 0x3c, 0x18, 0xbb, + 0x1d, 0xed, 0xbe, 0xb6, 0xb5, 0xb8, 0x8b, 0x76, 0xa4, 0xbb, 0xb2, 0x1e, 0x0f, 0xc6, 0xee, 0xe9, + 0x82, 0x25, 0x3c, 0xd0, 0xaf, 0xa1, 0x32, 0x9c, 0x84, 0xc1, 0xb8, 0x53, 0x12, 0xae, 0xab, 0x59, + 0xd7, 0x57, 0xdc, 0x74, 0xba, 0x60, 0x49, 0x1f, 0x3e, 0x2c, 0xa1, 0x43, 0xb7, 0x53, 0x2e, 0x1a, + 0xb6, 0x47, 0x87, 0x62, 0x58, 0xee, 0x81, 0x5e, 0x00, 0x04, 0x98, 0xf5, 0x5d, 0x8f, 0x11, 0x97, + 0x76, 0x74, 0xe1, 0xbf, 0x91, 0xf5, 0xbf, 0xc0, 0xec, 0x8d, 0x30, 0x9f, 0x2e, 0x58, 0x8d, 0x20, + 0x12, 0x38, 0xd2, 0xc1, 0x13, 0x72, 0x83, 0xfd, 0x3e, 0x9b, 0x75, 0x2a, 0x45, 0xc8, 0x23, 0x69, + 0xbf, 0x9c, 0x71, 0xa4, 0x13, 0x09, 0x68, 0x17, 0xea, 0x83, 0x31, 0x1e, 0x5c, 0x73, 0x5c, 0x55, + 0xe0, 0xd6, 0xb2, 0xb8, 0x43, 0x6e, 0x15, 0xa8, 0xda, 0x40, 0x7e, 0xa2, 0x1d, 0xa8, 0x0e, 0xdc, + 0xe9, 0x94, 0xb0, 0x4e, 0x4d, 0x20, 0xda, 0x39, 0x84, 0xb0, 0x9d, 0x2e, 0x58, 0xca, 0x8b, 0x6f, + 0xd7, 0xfb, 0x10, 0xfb, 0xb7, 0x9d, 0x7a, 0xd1, 0x76, 0xfd, 0x85, 0x9b, 0xf8, 0x76, 0x09, 0x1f, + 0xbe, 0x14, 0x42, 0x09, 0xeb, 0x0f, 0xc6, 0x36, 0xa1, 0x9d, 0x46, 0xd1, 0x52, 0x7a, 0x94, 0xb0, + 0x43, 0x6e, 0xe6, 0x4b, 0x21, 0x91, 0x80, 0x5e, 0xc2, 0xe2, 0x15, 0x1e, 0x11, 0xda, 0xbf, 0x9a, + 0xb8, 0x83, 0xeb, 0x0e, 0x08, 0x68, 0x27, 0x0b, 0x3d, 0xe0, 0x0e, 0x07, 0xdc, 0x7e, 0xba, 0x60, + 0xc1, 0x55, 0x2c, 0xa1, 0xe7, 0xd0, 0xc0, 0xd4, 0x51, 0xd0, 0x45, 0x01, 0x5d, 0xcf, 0x65, 0x00, + 0x75, 0x22, 0x60, 0x1d, 0xab, 0xef, 0x83, 0x1a, 0x54, 0x6e, 0xec, 0x49, 0x88, 0xcd, 0x47, 0xb0, + 0x98, 0xca, 0x14, 0xd4, 0x81, 0xda, 0x14, 0x07, 0x81, 0x3d, 0xc2, 0x22, 0x9d, 0x1a, 0x56, 0x24, + 0x9a, 0x2d, 0x68, 0xa6, 0xf3, 0x24, 0x05, 0xe4, 0xb9, 0xc0, 0x81, 0x37, 0xd8, 0x0f, 0x78, 0x02, + 0x28, 0xa0, 0x12, 0xcd, 0x3f, 0x80, 0x91, 0x4f, 0x02, 0x64, 0x40, 0xf9, 0x1a, 0xdf, 0x2a, 0x4f, + 0xfe, 0x89, 0xda, 0x2a, 0x20, 0x91, 0x9a, 0x0d, 0x4b, 0x45, 0x67, 0xc6, 0xd8, 0x38, 0x0d, 0x50, + 0x0b, 0x4a, 0x6c, 0x26, 0xa0, 0x4d, 0xab, 0xc4, 0x66, 0xe6, 0x7d, 0x68, 0x65, 0x8f, 0xfc, 0x8e, + 0x87, 0x13, 0x87, 0x2e, 0xce, 0x0c, 0x21, 0xd0, 0x1d, 0x9b, 0xd9, 0xca, 0x43, 0x7c, 0x73, 0x9d, + 0x67, 0xb3, 0xb1, 0x9a, 0x5e, 0x7c, 0xa3, 0x75, 0xa8, 0x8e, 0x31, 0x19, 0x8d, 0x99, 0xa8, 0x01, + 0xdd, 0x52, 0x12, 0x8f, 0xd5, 0xf3, 0xdd, 0x1b, 0x2c, 0x52, 0xbd, 0x6e, 0x49, 0xc1, 0x5c, 0x86, + 0xa5, 0x4c, 0x22, 0x99, 0x47, 0x71, 0xf0, 0xf1, 0xc1, 0xa3, 0xdf, 0x02, 0xdc, 0xd8, 0x13, 0xe2, + 0xd8, 0xcc, 0xf5, 0x83, 0x8e, 0x76, 0xbf, 0xbc, 0xb5, 0xb8, 0x6b, 0xa8, 0xf3, 0x7a, 0x17, 0x19, + 0xac, 0x94, 0x8f, 0x79, 0x06, 0x2b, 0x77, 0x72, 0x80, 0x47, 0x3b, 0xb6, 0x83, 0x71, 0xb4, 0x02, + 0xfe, 0x8d, 0x1e, 0xf2, 0x68, 0x6d, 0x07, 0xfb, 0xaa, 0xba, 0x97, 0xd4, 0xb0, 0xa7, 0x42, 0x69, + 0x29, 0xa3, 0xb9, 0x0d, 0xcb, 0xb9, 0xc4, 0x48, 0xad, 0x53, 0x4b, 0xaf, 0xd3, 0xfc, 0x58, 0x81, + 0xba, 0x85, 0x03, 0xcf, 0xa5, 0x01, 0x46, 0x2f, 0xa0, 0x81, 0x67, 0x03, 0x2c, 0x6b, 0x5c, 0xcb, + 0xe5, 0xa8, 0xf4, 0x39, 0x8e, 0xec, 0x3c, 0xbf, 0x63, 0x67, 0xb4, 0xad, 0xf8, 0x29, 0x4f, 0x3a, + 0x0a, 0x94, 0x26, 0xa8, 0x27, 0x11, 0x41, 0x95, 0x73, 0x05, 0x2a, 0x7d, 0x73, 0x0c, 0xb5, 0xad, + 0x18, 0x4a, 0x2f, 0x1c, 0x38, 0x43, 0x51, 0x7b, 0x19, 0x8a, 0xaa, 0x14, 0x86, 0x3f, 0x87, 0xa3, + 0xf6, 0x32, 0x1c, 0x55, 0x2d, 0x84, 0xce, 0x21, 0xa9, 0x67, 0x29, 0x92, 0xaa, 0xe5, 0x6a, 0x53, + 0x02, 0x0b, 0x58, 0xea, 0x69, 0xcc, 0x52, 0xf5, 0x1c, 0xaf, 0x29, 0x48, 0x9e, 0xa6, 0x9e, 0x44, + 0x34, 0xd5, 0x28, 0xdc, 0xb4, 0x1c, 0x4f, 0xed, 0x65, 0x78, 0x0a, 0x0a, 0x97, 0x33, 0x87, 0xa8, + 0xfe, 0x98, 0x25, 0x2a, 0xc9, 0x36, 0x9b, 0x39, 0xec, 0x5c, 0xa6, 0xfa, 0x7d, 0x9a, 0xa9, 0x9a, + 0x39, 0x7e, 0x54, 0xb9, 0xf0, 0x49, 0xaa, 0xda, 0xe6, 0x95, 0x90, 0xcb, 0x34, 0x5e, 0x8b, 0xd8, + 0xf7, 0x5d, 0x5f, 0x71, 0x89, 0x14, 0xcc, 0x2d, 0x5e, 0xf1, 0x49, 0x7e, 0x7d, 0x82, 0xd6, 0x44, + 0xd5, 0xa6, 0xb2, 0xcb, 0xfc, 0x97, 0x96, 0x60, 0x05, 0xb3, 0xa5, 0xd9, 0xa2, 0xa1, 0xd8, 0x22, + 0xc5, 0x76, 0xa5, 0x0c, 0xdb, 0xa1, 0xc7, 0xb0, 0x32, 0xb1, 0x03, 0x26, 0x97, 0xd9, 0xcf, 0xd0, + 0xc7, 0x32, 0x37, 0xc8, 0xf5, 0x49, 0x1e, 0xf9, 0x0d, 0xac, 0xa6, 0x7c, 0x6d, 0xcf, 0xeb, 0x8b, + 0xa2, 0xd6, 0x45, 0x51, 0x1b, 0xb1, 0xf7, 0xbe, 0xe7, 0x9d, 0xda, 0xc1, 0xd8, 0x7c, 0x98, 0xac, + 0x3f, 0xc3, 0xa4, 0x13, 0x77, 0x14, 0x31, 0xe9, 0xc4, 0x1d, 0x99, 0xff, 0xd4, 0x12, 0xbf, 0x84, + 0x35, 0x7f, 0x09, 0xfa, 0xc0, 0x75, 0xe4, 0xf2, 0x5b, 0xbb, 0xcb, 0x6a, 0xe3, 0x0f, 0x5d, 0x07, + 0x5f, 0xde, 0x7a, 0xd8, 0x12, 0xc6, 0x78, 0xa9, 0xa5, 0x14, 0x31, 0xaa, 0x09, 0xca, 0xf1, 0x04, + 0xe8, 0x01, 0xe8, 0xcc, 0x1e, 0x05, 0x1d, 0x5d, 0xb0, 0x57, 0x44, 0x33, 0xaf, 0xdf, 0x9d, 0xdb, + 0xc4, 0xb7, 0x84, 0xc9, 0xfc, 0x1b, 0x27, 0x99, 0x4c, 0x86, 0x7f, 0xc6, 0x00, 0xcc, 0xff, 0x6a, + 0xc9, 0xa1, 0x49, 0x46, 0xff, 0x59, 0x83, 0xb7, 0xa1, 0x42, 0xa8, 0x83, 0x67, 0x62, 0xf4, 0xb2, + 0x25, 0x85, 0xe8, 0x2a, 0x2a, 0x8b, 0x19, 0xb3, 0x57, 0x91, 0x3c, 0x08, 0x29, 0x28, 0xd2, 0x77, + 0x87, 0x82, 0x3c, 0x9a, 0x96, 0x14, 0x52, 0xd4, 0x59, 0xcd, 0x5c, 0x11, 0x2a, 0xe8, 0x5a, 0x12, + 0xf4, 0x5f, 0xf9, 0x35, 0x95, 0xae, 0xe0, 0xcf, 0xb9, 0x23, 0xab, 0xc9, 0x91, 0xc7, 0xb5, 0x6b, + 0xb6, 0x01, 0xdd, 0x2d, 0x4a, 0x79, 0x1d, 0x67, 0xcb, 0x0d, 0xfd, 0x0a, 0x2a, 0x0e, 0x19, 0x0e, + 0xe7, 0x5f, 0x48, 0xd2, 0x6c, 0xfe, 0xbb, 0x04, 0x55, 0x79, 0x9d, 0xa0, 0x4d, 0x4e, 0x6d, 0x36, + 0xa1, 0x7d, 0xe2, 0x44, 0x25, 0x25, 0xe4, 0x9e, 0x93, 0xda, 0x93, 0x52, 0x66, 0x4f, 0x10, 0xe8, + 0x8c, 0x4c, 0xb1, 0xaa, 0x06, 0xf1, 0x8d, 0x36, 0xa0, 0x46, 0xc3, 0x69, 0x9f, 0xcd, 0x02, 0xb1, + 0xdb, 0xba, 0x55, 0xa5, 0xe1, 0xf4, 0x72, 0x16, 0xa0, 0x5d, 0x58, 0x4a, 0xd5, 0x06, 0x71, 0x14, + 0x67, 0xb7, 0x54, 0x68, 0x22, 0xee, 0xde, 0x91, 0xb5, 0x18, 0x57, 0x49, 0xcf, 0x41, 0x5b, 0x20, + 0x8a, 0xa6, 0x2f, 0x79, 0x51, 0x16, 0x53, 0x55, 0xec, 0x5b, 0x8b, 0xeb, 0x15, 0x71, 0xf2, 0xbb, + 0xf2, 0x1e, 0x34, 0xf8, 0x4e, 0x4a, 0x97, 0x9a, 0x70, 0xa9, 0x73, 0x85, 0x30, 0x3e, 0x82, 0xe5, + 0xe4, 0xfe, 0x95, 0x2e, 0x75, 0x39, 0x4a, 0xa2, 0x16, 0x8e, 0x9b, 0x50, 0x8f, 0x8b, 0xb6, 0x21, + 0x3c, 0x6a, 0xb6, 0xaa, 0xd5, 0x1e, 0xd4, 0x54, 0x88, 0x85, 0x77, 0xf5, 0x63, 0xa8, 0x78, 0xb6, + 0xcf, 0x02, 0x75, 0x27, 0x46, 0x94, 0x7d, 0x6e, 0xfb, 0xbc, 0x49, 0x52, 0x37, 0xb6, 0x74, 0x31, + 0xf7, 0x60, 0x29, 0xa3, 0xe7, 0x99, 0xc8, 0x5c, 0x66, 0x4f, 0xd4, 0x6d, 0x2d, 0x85, 0x78, 0x9a, + 0x52, 0x32, 0x8d, 0xb9, 0x07, 0x8d, 0xf8, 0x0c, 0xf9, 0xb1, 0x78, 0xe1, 0xd5, 0x6b, 0xd5, 0x76, + 0x35, 0x2d, 0x25, 0x89, 0xc4, 0x76, 0x3f, 0xa8, 0xb6, 0x41, 0xb7, 0xa4, 0x60, 0xfe, 0x47, 0x83, + 0xaa, 0x2c, 0xe9, 0x82, 0x66, 0xed, 0x77, 0xa2, 0x8b, 0x09, 0x71, 0x9f, 0x87, 0x2d, 0x70, 0xad, + 0xf8, 0x81, 0x20, 0x41, 0x3b, 0x22, 0x85, 0x1b, 0xc2, 0x8b, 0x7f, 0xa2, 0x07, 0xd0, 0x94, 0x90, + 0x80, 0xf9, 0x84, 0x46, 0xc9, 0xbb, 0x28, 0x74, 0x17, 0x42, 0xc5, 0x0f, 0x45, 0xba, 0x10, 0xca, + 0x44, 0x36, 0x94, 0xad, 0xba, 0x50, 0xf4, 0x28, 0x33, 0xef, 0x81, 0x2e, 0xc6, 0x01, 0xa8, 0x5e, + 0x5c, 0x5a, 0xbd, 0xb3, 0x13, 0x63, 0x01, 0xd5, 0xa0, 0xdc, 0x3b, 0xbb, 0x34, 0xb4, 0xc7, 0xff, + 0xab, 0x40, 0x3d, 0xaa, 0x1b, 0x54, 0x85, 0xd2, 0x9b, 0xd7, 0xc6, 0x02, 0x5a, 0x81, 0xa5, 0x1e, + 0x65, 0xd8, 0xa7, 0xf6, 0xe4, 0x98, 0x5f, 0x0a, 0x86, 0xc6, 0x55, 0xc7, 0x74, 0xe0, 0x3a, 0x84, + 0x8e, 0xa4, 0xaa, 0x84, 0x9a, 0x50, 0x3f, 0xb0, 0x9d, 0x33, 0x97, 0x0e, 0xb0, 0x51, 0x46, 0x06, + 0x34, 0xdf, 0x52, 0x3b, 0x64, 0x63, 0xd7, 0x27, 0xff, 0xc0, 0x8e, 0xa1, 0xa3, 0x35, 0x58, 0xe9, + 0xd1, 0x20, 0x1c, 0x0e, 0xc9, 0x80, 0x60, 0xca, 0x5e, 0x85, 0xd4, 0x09, 0x8c, 0x0a, 0x42, 0xd0, + 0x7a, 0x4b, 0xaf, 0xa9, 0xfb, 0x81, 0xaa, 0x66, 0xca, 0xa8, 0xa2, 0x0e, 0xb4, 0x0f, 0xec, 0x00, + 0x1f, 0x85, 0xde, 0x84, 0x0c, 0x6c, 0x86, 0xf7, 0x1d, 0xc7, 0xc7, 0x41, 0x60, 0x60, 0x3e, 0x08, + 0xb7, 0x64, 0xe7, 0x1e, 0x46, 0x80, 0xcc, 0xf8, 0x18, 0x07, 0xc6, 0x08, 0x6d, 0xc2, 0xda, 0x1d, + 0x8b, 0x98, 0x79, 0x8c, 0x7e, 0x01, 0x9d, 0xbc, 0xe9, 0xc4, 0x0e, 0xce, 0x7d, 0x32, 0xc0, 0x06, + 0x41, 0x6d, 0x30, 0xa4, 0x55, 0xa4, 0x6a, 0x8f, 0x7a, 0x21, 0x33, 0xfe, 0x1e, 0xcd, 0xaf, 0xb4, + 0x6f, 0x42, 0xc6, 0xd5, 0xd7, 0x39, 0xf5, 0xb9, 0x48, 0x07, 0x63, 0x82, 0x36, 0x60, 0x35, 0xa5, + 0xbe, 0xe0, 0xeb, 0xe3, 0xbb, 0x33, 0x4d, 0xe2, 0x95, 0x06, 0x32, 0xa2, 0x36, 0x0b, 0x7d, 0x6c, + 0x50, 0xb4, 0x0e, 0x88, 0x5b, 0xd4, 0x96, 0x44, 0x0b, 0x77, 0xa3, 0x19, 0x94, 0x5e, 0xcd, 0xe0, + 0xe5, 0xd5, 0x93, 0x70, 0x44, 0xa8, 0xf1, 0x1e, 0xad, 0x81, 0x71, 0xe2, 0xde, 0x28, 0xed, 0x31, + 0x65, 0x84, 0xdd, 0x1a, 0x5f, 0x68, 0xa8, 0x0d, 0xcb, 0x89, 0xfa, 0xc4, 0x77, 0x43, 0xcf, 0xf8, + 0x52, 0x43, 0x1b, 0x80, 0x12, 0xed, 0xb9, 0xef, 0x7a, 0x6e, 0x60, 0x4f, 0x8c, 0xaf, 0x34, 0xb4, + 0x0e, 0x2b, 0x27, 0xee, 0x4d, 0x7c, 0x0a, 0x12, 0xf0, 0x75, 0x04, 0x88, 0xf5, 0x7f, 0xc6, 0xd3, + 0x2b, 0xec, 0x1b, 0xdf, 0x68, 0x68, 0x13, 0xda, 0x69, 0x43, 0x3c, 0xd6, 0xb7, 0x9a, 0x8a, 0x28, + 0x36, 0xbd, 0x73, 0x19, 0x36, 0xbe, 0x8b, 0xd4, 0x6a, 0x1f, 0xd4, 0x40, 0xdf, 0x6b, 0x68, 0x15, + 0x5a, 0x89, 0x5a, 0xf8, 0xfe, 0xa0, 0xa1, 0x2e, 0xac, 0x65, 0x94, 0x84, 0x8e, 0xce, 0x79, 0x85, + 0x19, 0x3f, 0x6a, 0xbb, 0x1f, 0x2b, 0xb0, 0xbc, 0x7f, 0x70, 0xd8, 0xdb, 0xf7, 0xe4, 0x04, 0xfc, + 0x42, 0x7f, 0x0a, 0xba, 0x68, 0x59, 0x0a, 0xde, 0xf1, 0xdd, 0xa2, 0xde, 0x19, 0xed, 0x42, 0x45, + 0x74, 0x2e, 0xa8, 0xe8, 0x39, 0xdf, 0x2d, 0x6c, 0xa1, 0xf9, 0x24, 0xb2, 0xb7, 0xb9, 0xfb, 0xaa, + 0xef, 0x16, 0xf5, 0xd1, 0xe8, 0x4f, 0xd0, 0x48, 0x7a, 0x8e, 0x79, 0x6f, 0xfb, 0xee, 0xdc, 0x8e, + 0x9a, 0xe3, 0x93, 0x5e, 0x64, 0xde, 0x0b, 0xbf, 0x3b, 0xb7, 0xad, 0x46, 0x2f, 0xa0, 0x16, 0x35, + 0x12, 0xc5, 0xef, 0xfc, 0xee, 0x9c, 0xce, 0x9a, 0x6f, 0x8f, 0xec, 0x11, 0x8a, 0x9e, 0xef, 0xdd, + 0xc2, 0x66, 0x19, 0x3d, 0x87, 0xaa, 0xba, 0xa3, 0x0b, 0xff, 0x22, 0xe8, 0x16, 0xb7, 0xe4, 0x7c, + 0x91, 0xc9, 0x4b, 0x6f, 0xde, 0xdb, 0xbf, 0x3b, 0xb7, 0xd9, 0x46, 0xfb, 0x00, 0xa9, 0x37, 0xde, + 0xdc, 0x7f, 0x00, 0xba, 0xf3, 0x5b, 0x6e, 0xf4, 0x12, 0xea, 0xc9, 0xb3, 0xae, 0xf8, 0x7f, 0x80, + 0xee, 0xbc, 0xae, 0xfb, 0xaa, 0x2a, 0xfe, 0x62, 0x7a, 0xf6, 0x53, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x59, 0xf7, 0xaf, 0xdb, 0x77, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 09dcb1bd..e83df985 100644 --- a/types/types.proto +++ b/types/types.proto @@ -166,7 +166,6 @@ message ResponseCheckTx{ CodeType code = 1; bytes data = 2; string log = 3; - repeated KVPair tags = 4; } message ResponseQuery{ @@ -231,8 +230,13 @@ message Validator { message KVPair { string key = 1; - string value_string = 2; - int64 value_int = 3; + enum Type { + STRING = 0; + INT = 1; + } + Type value_type = 2; + string value_string = 3; + int64 value_int = 4; } //---------------------------------------- From 92801dbd72fddc0521575f8666aa4582710157f0 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 20 Nov 2017 18:30:10 -0600 Subject: [PATCH 326/545] [dockerfile] install psmisc for tests --- Dockerfile.develop | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Dockerfile.develop b/Dockerfile.develop index e21350ce..d4643155 100644 --- a/Dockerfile.develop +++ b/Dockerfile.develop @@ -5,9 +5,13 @@ WORKDIR /go/src/github.com/tendermint/abci COPY Makefile /go/src/github.com/tendermint/abci/ -RUN make install_protoc -# see make protoc for details -RUN ldconfig +# see make protoc for details on ldconfig +RUN make install_protoc && ldconfig + +# killall is used in tests +RUN apt-get update && apt-get install -y \ + psmisc \ + && rm -rf /var/lib/apt/lists/* COPY glide.yaml /go/src/github.com/tendermint/abci/ COPY glide.lock /go/src/github.com/tendermint/abci/ From 3a3d508e5c57112977e387d21106a9c601d93b3c Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 20 Nov 2017 20:26:37 -0600 Subject: [PATCH 327/545] CheckTx and DeliverTx return ResponseCheckTx and ResponseDeliverTx respectively Commit now returns ResponseCommit --- client/local_client.go | 6 ++--- example/counter/counter.go | 31 +++++++++++++++--------- example/dummy/dummy.go | 16 ++++++------- example/dummy/persistent_dummy.go | 39 ++++++++++++++++++++----------- types/application.go | 6 ++--- types/base_app.go | 12 +++++----- types/result.go | 8 +++++++ 7 files changed, 74 insertions(+), 44 deletions(-) diff --git a/client/local_client.go b/client/local_client.go index 539c1eef..89f98418 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -164,14 +164,14 @@ func (app *localClient) SetOptionSync(key string, value string) (res types.Resul return types.OK.SetLog(log) } -func (app *localClient) DeliverTxSync(tx []byte) (res types.Result) { +func (app *localClient) DeliverTxSync(tx []byte) (res types.ResponseDeliverTx) { app.mtx.Lock() res = app.Application.DeliverTx(tx) app.mtx.Unlock() return res } -func (app *localClient) CheckTxSync(tx []byte) (res types.Result) { +func (app *localClient) CheckTxSync(tx []byte) (res types.ResponseCheckTx) { app.mtx.Lock() res = app.Application.CheckTx(tx) app.mtx.Unlock() @@ -185,7 +185,7 @@ func (app *localClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.R return resQuery, nil } -func (app *localClient) CommitSync() (res types.Result) { +func (app *localClient) CommitSync() (res types.ResponseCommit) { app.mtx.Lock() res = app.Application.Commit() app.mtx.Unlock() diff --git a/example/counter/counter.go b/example/counter/counter.go index d2478ae2..65cac4a0 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -2,6 +2,7 @@ package counter import ( "encoding/binary" + "fmt" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" @@ -30,45 +31,53 @@ func (app *CounterApplication) SetOption(key string, value string) (log string) return "" } -func (app *CounterApplication) DeliverTx(tx []byte) types.Result { +func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { - return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected %v, got %v", app.txCount, txValue)) + return types.ResponseDeliverTx{ + Code: types.CodeType_BadNonce, + Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)} } } app.txCount++ - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } -func (app *CounterApplication) CheckTx(tx []byte) types.Result { +func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { if app.serial { if len(tx) > 8 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Max tx size is 8 bytes, got %d", len(tx))) + return types.ResponseCheckTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) copy(tx8[len(tx8)-len(tx):], tx) txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { - return types.ErrBadNonce.SetLog(cmn.Fmt("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)) + return types.ResponseCheckTx{ + Code: types.CodeType_BadNonce, + Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} } } - return types.OK + return types.ResponseCheckTx{Code: types.CodeType_OK} } -func (app *CounterApplication) Commit() types.Result { +func (app *CounterApplication) Commit() (resp types.ResponseCommit) { app.hashCount++ if app.txCount == 0 { - return types.OK + return types.ResponseCommit{Code: types.CodeType_OK} } hash := make([]byte, 8) binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return types.NewResultOK(hash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} } func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 7e95c859..a4edacac 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,12 +1,12 @@ package dummy import ( + "fmt" "strings" "github.com/tendermint/abci/types" wire "github.com/tendermint/go-wire" "github.com/tendermint/iavl" - cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" ) @@ -22,25 +22,25 @@ func NewDummyApplication() *DummyApplication { } func (app *DummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} + return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())} } // tx is either "key=value" or just arbitrary bytes -func (app *DummyApplication) DeliverTx(tx []byte) types.Result { +func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { parts := strings.Split(string(tx), "=") if len(parts) == 2 { app.state.Set([]byte(parts[0]), []byte(parts[1])) } else { app.state.Set(tx, tx) } - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } -func (app *DummyApplication) CheckTx(tx []byte) types.Result { - return types.OK +func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { + return types.ResponseCheckTx{Code: types.CodeType_OK} } -func (app *DummyApplication) Commit() types.Result { +func (app *DummyApplication) Commit() types.ResponseCommit { // Save a new version var hash []byte var err error @@ -55,7 +55,7 @@ func (app *DummyApplication) Commit() types.Result { } } - return types.NewResultOK(hash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} } func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 4c480175..8fa11282 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -3,6 +3,7 @@ package dummy import ( "bytes" "encoding/hex" + "fmt" "strconv" "strings" @@ -61,7 +62,7 @@ func (app *PersistentDummyApplication) SetOption(key string, value string) (log } // tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes -func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { // if it starts with "val:", update the validator set // format is "val:pubkey/power" if isValidatorTx(tx) { @@ -74,12 +75,12 @@ func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.Result { return app.app.DeliverTx(tx) } -func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { return app.app.CheckTx(tx) } // Commit will panic if InitChain was not called -func (app *PersistentDummyApplication) Commit() types.Result { +func (app *PersistentDummyApplication) Commit() types.ResponseCommit { // Save a new version for next height height := app.app.state.LatestVersion() + 1 @@ -93,7 +94,7 @@ func (app *PersistentDummyApplication) Commit() types.Result { } app.logger.Info("Commit block", "height", height, "root", appHash) - return types.NewResultOK(appHash, "") + return types.ResponseCommit{Code: types.CodeType_OK, Data: appHash} } func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { @@ -148,30 +149,38 @@ func isValidatorTx(tx []byte) bool { } // format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx -func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { +func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx { tx = tx[len(ValidatorSetChangePrefix):] //get the pubkey and power pubKeyAndPower := strings.Split(string(tx), "/") if len(pubKeyAndPower) != 2 { - return types.ErrEncodingError.SetLog(cmn.Fmt("Expected 'pubkey/power'. Got %v", pubKeyAndPower)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)} } pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] // decode the pubkey, ensuring its go-crypto encoded pubkey, err := hex.DecodeString(pubkeyS) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%s) is invalid hex", pubkeyS)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)} } _, err = crypto.PubKeyFromBytes(pubkey) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Pubkey (%X) is invalid go-crypto encoded", pubkey)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Pubkey (%X) is invalid go-crypto encoded", pubkey)} } // decode the power power, err := strconv.Atoi(powerS) if err != nil { - return types.ErrEncodingError.SetLog(cmn.Fmt("Power (%s) is not an int", powerS)) + return types.ResponseDeliverTx{ + Code: types.CodeType_EncodingError, + Log: fmt.Sprintf("Power (%s) is not an int", powerS)} } // update @@ -179,19 +188,23 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Result { } // add, update, or remove a validator -func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.Result { +func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.ResponseDeliverTx { key := []byte("val:" + string(v.PubKey)) if v.Power == 0 { // remove validator if !app.app.state.Has(key) { - return types.ErrUnauthorized.SetLog(cmn.Fmt("Cannot remove non-existent validator %X", key)) + return types.ResponseDeliverTx{ + Code: types.CodeType_Unauthorized, + Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)} } app.app.state.Remove(key) } else { // add or update validator value := bytes.NewBuffer(make([]byte, 0)) if err := types.WriteMessage(v, value); err != nil { - return types.ErrInternalError.SetLog(cmn.Fmt("Error encoding validator: %v", err)) + return types.ResponseDeliverTx{ + Code: types.CodeType_InternalError, + Log: fmt.Sprintf("Error encoding validator: %v", err)} } app.app.state.Set(key, value.Bytes()) } @@ -199,5 +212,5 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types // we only update the changes array if we successfully updated the tree app.changes = append(app.changes, v) - return types.OK + return types.ResponseDeliverTx{Code: types.CodeType_OK} } diff --git a/types/application.go b/types/application.go index 51a1869b..ed9b0d20 100644 --- a/types/application.go +++ b/types/application.go @@ -13,14 +13,14 @@ type Application interface { Query(RequestQuery) ResponseQuery // Query for state // Mempool Connection - CheckTx(tx []byte) Result // Validate a tx for the mempool + CheckTx(tx []byte) ResponseCheckTx // Validate a tx for the mempool // Consensus Connection InitChain(RequestInitChain) // Initialize blockchain with validators and other info from TendermintCore BeginBlock(RequestBeginBlock) // Signals the beginning of a block - DeliverTx(tx []byte) Result // Deliver a tx for full processing + DeliverTx(tx []byte) ResponseDeliverTx // 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 + Commit() ResponseCommit // Commit the state and return the application Merkle root hash } //------------------------------------ diff --git a/types/base_app.go b/types/base_app.go index 60bf4388..75fdae8d 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -15,16 +15,16 @@ func (BaseApplication) SetOption(key string, value string) (log string) { return "" } -func (BaseApplication) DeliverTx(tx []byte) Result { - return NewResultOK(nil, "") +func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { + return ResponseDeliverTx{} } -func (BaseApplication) CheckTx(tx []byte) Result { - return NewResultOK(nil, "") +func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { + return ResponseCheckTx{} } -func (BaseApplication) Commit() Result { - return NewResultOK([]byte("nil"), "") +func (BaseApplication) Commit() ResponseCommit { + return ResponseCommit{Code: CodeType_OK, Data: []byte("nil")} } func (BaseApplication) Query(req RequestQuery) ResponseQuery { diff --git a/types/result.go b/types/result.go index 96dd4e79..ffd8966a 100644 --- a/types/result.go +++ b/types/result.go @@ -106,6 +106,10 @@ func (r *ResponseCheckTx) Result() Result { } } +func (r ResponseCheckTx) IsErr() bool { + return r.Code != CodeType_OK +} + // Convert ResponseDeliverTx to standard Result func (r *ResponseDeliverTx) Result() Result { return Result{ @@ -116,6 +120,10 @@ func (r *ResponseDeliverTx) Result() Result { } } +func (r ResponseDeliverTx) IsErr() bool { + return r.Code != CodeType_OK +} + type ResultQuery struct { Code CodeType `json:"code"` Index int64 `json:"index"` From 8e6269ce930f785cb8987cea3498ca7cff104ae5 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 15:24:29 -0600 Subject: [PATCH 328/545] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index aedebee6..4cfcce74 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ Here, we describe the requests and responses as function arguments and return va * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message + * `Tags ([]*KVPair)`: Optional tags for indexing * __Usage__:
Append and run a transaction. If the transaction is valid, returns CodeType.OK From fbe7234639d411ddd15aea039dc9532adaaa3f21 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 17:33:34 -0600 Subject: [PATCH 329/545] remove Result from the client package plus make Client interface more consistent. All *Sync functions now return an error as a second return param. Deliver/Check/Commit use Code to indicate errors and have IsErr() func defined on ResponseXYZ structs. --- client/client.go | 20 ++++----- client/grpc_client.go | 95 +++++++++++++--------------------------- client/local_client.go | 58 ++++++++++++------------ client/socket_client.go | 84 ++++++++++++----------------------- cmd/abci-cli/abci-cli.go | 18 +++++--- tests/test_app/app.go | 47 ++++++++++---------- types/result.go | 7 +++ 7 files changed, 140 insertions(+), 189 deletions(-) diff --git a/client/client.go b/client/client.go index 51d04124..b550dc92 100644 --- a/client/client.go +++ b/client/client.go @@ -24,21 +24,21 @@ type Client interface { CommitAsync() *ReqRes FlushSync() error - EchoSync(msg string) (res types.Result) - InfoSync(types.RequestInfo) (resInfo types.ResponseInfo, err error) - SetOptionSync(key string, value string) (res types.Result) - DeliverTxSync(tx []byte) (res types.Result) - CheckTxSync(tx []byte) (res types.Result) - QuerySync(types.RequestQuery) (resQuery types.ResponseQuery, err error) - CommitSync() (res types.Result) + EchoSync(msg string) (*types.ResponseEcho, error) + InfoSync(types.RequestInfo) (*types.ResponseInfo, error) + SetOptionSync(key string, value string) (log string, err error) + DeliverTxSync(tx []byte) *types.ResponseDeliverTx + CheckTxSync(tx []byte) *types.ResponseCheckTx + QuerySync(types.RequestQuery) (*types.ResponseQuery, error) + CommitSync() *types.ResponseCommit InitChainAsync(types.RequestInitChain) *ReqRes BeginBlockAsync(types.RequestBeginBlock) *ReqRes EndBlockAsync(height uint64) *ReqRes - InitChainSync(types.RequestInitChain) (err error) - BeginBlockSync(types.RequestBeginBlock) (err error) - EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) + InitChainSync(types.RequestInitChain) error + BeginBlockSync(types.RequestBeginBlock) error + EndBlockSync(height uint64) (*types.ResponseEndBlock, error) } //---------------------------------------- diff --git a/client/grpc_client.go b/client/grpc_client.go index 30f5d088..524f1f7f 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -240,104 +240,71 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) return reqres } -func (cli *grpcClient) checkErrGetResult() types.Result { - if err := cli.Error(); err != nil { - // StopForError should already have been called if error is set - return types.ErrInternalError.SetLog(err.Error()) - } - return types.Result{} -} - //---------------------------------------- -func (cli *grpcClient) EchoSync(msg string) (res types.Result) { - reqres := cli.EchoAsync(msg) - if res := cli.checkErrGetResult(); res.IsErr() { - return res - } - resp := reqres.Response.GetEcho() - return types.NewResultOK([]byte(resp.Message), "") -} - func (cli *grpcClient) FlushSync() error { return nil } -func (cli *grpcClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { +func (cli *grpcClient) EchoSync(msg string) (*types.ResponseEcho, error) { + reqres := cli.EchoAsync(msg) + // StopForError should already have been called if error is set + return reqres.Response.GetEcho(), cli.Error() +} + +func (cli *grpcClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { reqres := cli.InfoAsync(req) - if err = cli.Error(); err != nil { - return resInfo, err - } - if info := reqres.Response.GetInfo(); info != nil { - return *info, nil - } - return resInfo, nil + return reqres.Response.GetInfo(), cli.Error() } -func (cli *grpcClient) SetOptionSync(key string, value string) (res types.Result) { +func (cli *grpcClient) SetOptionSync(key string, value string) (log string, err error) { reqres := cli.SetOptionAsync(key, value) - if res := cli.checkErrGetResult(); res.IsErr() { - return res + if err := cli.Error(); err != nil { + return "", err } - resp := reqres.Response.GetSetOption() - return types.Result{Code: OK, Data: nil, Log: resp.Log} + return reqres.Response.GetSetOption().Log, nil } -func (cli *grpcClient) DeliverTxSync(tx []byte) (res types.Result) { +func (cli *grpcClient) DeliverTxSync(tx []byte) *types.ResponseDeliverTx { reqres := cli.DeliverTxAsync(tx) - if res := cli.checkErrGetResult(); res.IsErr() { - return res + if err := cli.Error(); err != nil { + return &types.ResponseDeliverTx{Code: types.CodeType_InternalError, Log: err.Error()} } - resp := reqres.Response.GetDeliverTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetDeliverTx() } -func (cli *grpcClient) CheckTxSync(tx []byte) (res types.Result) { +func (cli *grpcClient) CheckTxSync(tx []byte) *types.ResponseCheckTx { reqres := cli.CheckTxAsync(tx) - if res := cli.checkErrGetResult(); res.IsErr() { - return res + if err := cli.Error(); err != nil { + return &types.ResponseCheckTx{Code: types.CodeType_InternalError, Log: err.Error()} } - resp := reqres.Response.GetCheckTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCheckTx() } -func (cli *grpcClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { - reqres := cli.QueryAsync(reqQuery) - if err = cli.Error(); err != nil { - return resQuery, err - } - if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { - return *resQuery_, nil - } - return resQuery, nil +func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { + reqres := cli.QueryAsync(req) + return reqres.Response.GetQuery(), cli.Error() } -func (cli *grpcClient) CommitSync() (res types.Result) { +func (cli *grpcClient) CommitSync() *types.ResponseCommit { reqres := cli.CommitAsync() - if res := cli.checkErrGetResult(); res.IsErr() { - return res + if err := cli.Error(); err != nil { + return &types.ResponseCommit{Code: types.CodeType_InternalError, Log: err.Error()} } - resp := reqres.Response.GetCommit() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCommit() } -func (cli *grpcClient) InitChainSync(params types.RequestInitChain) (err error) { +func (cli *grpcClient) InitChainSync(params types.RequestInitChain) error { cli.InitChainAsync(params) return cli.Error() } -func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { +func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) error { cli.BeginBlockAsync(params) return cli.Error() } -func (cli *grpcClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { +func (cli *grpcClient) EndBlockSync(height uint64) (*types.ResponseEndBlock, error) { reqres := cli.EndBlockAsync(height) - if err := cli.Error(); err != nil { - return resEndBlock, err - } - if blk := reqres.Response.GetEndBlock(); blk != nil { - return *blk, nil - } - return resEndBlock, nil + return reqres.Response.GetEndBlock(), cli.Error() } diff --git a/client/local_client.go b/client/local_client.go index 89f98418..9081406a 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -146,71 +146,71 @@ func (app *localClient) FlushSync() error { return nil } -func (app *localClient) EchoSync(msg string) (res types.Result) { - return types.OK.SetData([]byte(msg)) +func (app *localClient) EchoSync(msg string) (*types.ResponseEcho, error) { + return &types.ResponseEcho{msg}, nil } -func (app *localClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { +func (app *localClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { app.mtx.Lock() - defer app.mtx.Unlock() - resInfo = app.Application.Info(req) - return resInfo, nil -} - -func (app *localClient) SetOptionSync(key string, value string) (res types.Result) { - app.mtx.Lock() - log := app.Application.SetOption(key, value) + res := app.Application.Info(req) app.mtx.Unlock() - return types.OK.SetLog(log) + return &res, nil } -func (app *localClient) DeliverTxSync(tx []byte) (res types.ResponseDeliverTx) { +func (app *localClient) SetOptionSync(key string, value string) (log string, err error) { app.mtx.Lock() - res = app.Application.DeliverTx(tx) + log = app.Application.SetOption(key, value) app.mtx.Unlock() - return res + return log, nil } -func (app *localClient) CheckTxSync(tx []byte) (res types.ResponseCheckTx) { +func (app *localClient) DeliverTxSync(tx []byte) *types.ResponseDeliverTx { app.mtx.Lock() - res = app.Application.CheckTx(tx) + res := app.Application.DeliverTx(tx) app.mtx.Unlock() - return res + return &res } -func (app *localClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { +func (app *localClient) CheckTxSync(tx []byte) *types.ResponseCheckTx { app.mtx.Lock() - resQuery = app.Application.Query(reqQuery) + res := app.Application.CheckTx(tx) app.mtx.Unlock() - return resQuery, nil + return &res } -func (app *localClient) CommitSync() (res types.ResponseCommit) { +func (app *localClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { app.mtx.Lock() - res = app.Application.Commit() + res := app.Application.Query(req) app.mtx.Unlock() - return res + return &res, nil } -func (app *localClient) InitChainSync(params types.RequestInitChain) (err error) { +func (app *localClient) CommitSync() *types.ResponseCommit { + app.mtx.Lock() + res := app.Application.Commit() + app.mtx.Unlock() + return &res +} + +func (app *localClient) InitChainSync(params types.RequestInitChain) error { app.mtx.Lock() app.Application.InitChain(params) app.mtx.Unlock() return nil } -func (app *localClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { +func (app *localClient) BeginBlockSync(params types.RequestBeginBlock) error { app.mtx.Lock() app.Application.BeginBlock(params) app.mtx.Unlock() return nil } -func (app *localClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { +func (app *localClient) EndBlockSync(height uint64) (*types.ResponseEndBlock, error) { app.mtx.Lock() - resEndBlock = app.Application.EndBlock(height) + res := app.Application.EndBlock(height) app.mtx.Unlock() - return resEndBlock, nil + return &res, nil } //------------------------------------------------------- diff --git a/client/socket_client.go b/client/socket_client.go index 1045dea7..ef0a6ece 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -271,111 +271,85 @@ func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { //---------------------------------------- -func (cli *socketClient) EchoSync(msg string) (res types.Result) { - reqres := cli.queueRequest(types.ToRequestEcho(msg)) - cli.FlushSync() - if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) - } - resp := reqres.Response.GetEcho() - return types.Result{Code: OK, Data: []byte(resp.Message)} -} - func (cli *socketClient) FlushSync() error { reqRes := cli.queueRequest(types.ToRequestFlush()) if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return err } reqRes.Wait() // NOTE: if we don't flush the queue, its possible to get stuck here return cli.Error() } -func (cli *socketClient) InfoSync(req types.RequestInfo) (resInfo types.ResponseInfo, err error) { - reqres := cli.queueRequest(types.ToRequestInfo(req)) +func (cli *socketClient) EchoSync(msg string) (*types.ResponseEcho, error) { + reqres := cli.queueRequest(types.ToRequestEcho(msg)) cli.FlushSync() - if err := cli.Error(); err != nil { - return resInfo, err - } - if resInfo_ := reqres.Response.GetInfo(); resInfo_ != nil { - return *resInfo_, nil - } - return resInfo, nil + return reqres.Response.GetEcho(), cli.Error() } -func (cli *socketClient) SetOptionSync(key string, value string) (res types.Result) { +func (cli *socketClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) { + reqres := cli.queueRequest(types.ToRequestInfo(req)) + cli.FlushSync() + return reqres.Response.GetInfo(), cli.Error() +} + +func (cli *socketClient) SetOptionSync(key string, value string) (log string, err error) { reqres := cli.queueRequest(types.ToRequestSetOption(key, value)) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return "", err } - resp := reqres.Response.GetSetOption() - return types.Result{Code: OK, Data: nil, Log: resp.Log} + return reqres.Response.GetSetOption().Log, nil } -func (cli *socketClient) DeliverTxSync(tx []byte) (res types.Result) { +func (cli *socketClient) DeliverTxSync(tx []byte) *types.ResponseDeliverTx { reqres := cli.queueRequest(types.ToRequestDeliverTx(tx)) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return &types.ResponseDeliverTx{Code: types.CodeType_InternalError, Log: err.Error()} } - resp := reqres.Response.GetDeliverTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetDeliverTx() } -func (cli *socketClient) CheckTxSync(tx []byte) (res types.Result) { +func (cli *socketClient) CheckTxSync(tx []byte) *types.ResponseCheckTx { reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return &types.ResponseCheckTx{Code: types.CodeType_InternalError, Log: err.Error()} } - resp := reqres.Response.GetCheckTx() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCheckTx() } -func (cli *socketClient) QuerySync(reqQuery types.RequestQuery) (resQuery types.ResponseQuery, err error) { - reqres := cli.queueRequest(types.ToRequestQuery(reqQuery)) +func (cli *socketClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { + reqres := cli.queueRequest(types.ToRequestQuery(req)) cli.FlushSync() - if err := cli.Error(); err != nil { - return resQuery, err - } - if resQuery_ := reqres.Response.GetQuery(); resQuery_ != nil { - return *resQuery_, nil - } - return resQuery, nil + return reqres.Response.GetQuery(), cli.Error() } -func (cli *socketClient) CommitSync() (res types.Result) { +func (cli *socketClient) CommitSync() *types.ResponseCommit { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() if err := cli.Error(); err != nil { - return types.ErrInternalError.SetLog(err.Error()) + return &types.ResponseCommit{Code: types.CodeType_InternalError, Log: err.Error()} } - resp := reqres.Response.GetCommit() - return types.Result{Code: resp.Code, Data: resp.Data, Log: resp.Log} + return reqres.Response.GetCommit() } -func (cli *socketClient) InitChainSync(params types.RequestInitChain) (err error) { +func (cli *socketClient) InitChainSync(params types.RequestInitChain) error { cli.queueRequest(types.ToRequestInitChain(params)) cli.FlushSync() return cli.Error() } -func (cli *socketClient) BeginBlockSync(params types.RequestBeginBlock) (err error) { +func (cli *socketClient) BeginBlockSync(params types.RequestBeginBlock) error { cli.queueRequest(types.ToRequestBeginBlock(params)) cli.FlushSync() return cli.Error() } -func (cli *socketClient) EndBlockSync(height uint64) (resEndBlock types.ResponseEndBlock, err error) { +func (cli *socketClient) EndBlockSync(height uint64) (*types.ResponseEndBlock, error) { reqres := cli.queueRequest(types.ToRequestEndBlock(height)) cli.FlushSync() - if err := cli.Error(); err != nil { - return resEndBlock, err - } - if blk := reqres.Response.GetEndBlock(); blk != nil { - return *blk, nil - } - return resEndBlock, nil + return reqres.Response.GetEndBlock(), cli.Error() } //---------------------------------------- diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 9962380b..9c14aa4d 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -327,9 +327,12 @@ func cmdConsole(cmd *cobra.Command, args []string) error { // Have the application echo a message func cmdEcho(cmd *cobra.Command, args []string) error { - resEcho := client.EchoSync(args[0]) + res, err := client.EchoSync(args[0]) + if err != nil { + return err + } printResponse(cmd, args, response{ - Data: resEcho.Data, + Data: []byte(res.Message), }) return nil } @@ -340,21 +343,24 @@ func cmdInfo(cmd *cobra.Command, args []string) error { if len(args) == 1 { version = args[0] } - resInfo, err := client.InfoSync(types.RequestInfo{version}) + res, err := client.InfoSync(types.RequestInfo{version}) if err != nil { return err } printResponse(cmd, args, response{ - Data: []byte(resInfo.Data), + Data: []byte(res.Data), }) return nil } // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) error { - resSetOption := client.SetOptionSync(args[0], args[1]) + log, err := client.SetOptionSync(args[0], args[1]) + if err != nil { + return err + } printResponse(cmd, args, response{ - Log: resSetOption.Log, + Log: log, }) return nil } diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 127ba78f..67742b38 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -23,7 +23,7 @@ func startApp(abciApp string) *process.Process { os.Stdout, ) if err != nil { - panic("running abci_app: " + err.Error()) + panicf("running abci_app: %v", err) } // TODO a better way to handle this? @@ -41,57 +41,54 @@ func startClient(abciType string) abcicli.Client { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) client.SetLogger(logger.With("module", "abcicli")) if _, err := client.Start(); err != nil { - panic("connecting to abci_app: " + err.Error()) + panicf("connecting to abci_app: %v", err.Error()) } return client } func setOption(client abcicli.Client, key, value string) { - res := client.SetOptionSync(key, value) - _, _, log := res.Code, res.Data, res.Log - if res.IsErr() { - panic(fmt.Sprintf("setting %v=%v: \nlog: %v", key, value, log)) + _, err := client.SetOptionSync(key, value) + if err != nil { + panicf("setting %v=%v: \nerr: %v", key, value, err) } } func commit(client abcicli.Client, hashExp []byte) { res := client.CommitSync() - _, data, _ := res.Code, res.Data, res.Log if res.IsErr() { - panic(fmt.Sprintf("committing err %v\n", res)) + panicf("committing err %v\n", res) } if !bytes.Equal(res.Data, hashExp) { - panic(fmt.Sprintf("Commit hash was unexpected. Got %X expected %X", - data, hashExp)) + panicf("Commit hash was unexpected. Got %X expected %X", res.Data, hashExp) } } func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.DeliverTxSync(txBytes) - code, data, log := res.Code, res.Data, res.Log - if code != codeExp { - panic(fmt.Sprintf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", - code, codeExp, log)) + if res.Code != codeExp { + panicf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", res.Code, codeExp, res.Log) } - if !bytes.Equal(data, dataExp) { - panic(fmt.Sprintf("DeliverTx response data was unexpected. Got %X expected %X", - data, dataExp)) + if !bytes.Equal(res.Data, dataExp) { + panicf("DeliverTx response data was unexpected. Got %X expected %X", res.Data, dataExp) } } /*func checkTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { res := client.CheckTxSync(txBytes) - code, data, log := res.Code, res.Data, res.Log if res.IsErr() { - panic(fmt.Sprintf("checking tx %X: %v\nlog: %v", txBytes, log)) + panicf("checking tx %X: %v\nlog: %v", txBytes, res.Log) } - if code != codeExp { - panic(fmt.Sprintf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", - code, codeExp, log)) + if res.Code != codeExp { + panicf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", + res.Code, codeExp, res.Log) } - if !bytes.Equal(data, dataExp) { - panic(fmt.Sprintf("CheckTx response data was unexpected. Got %X expected %X", - data, dataExp)) + if !bytes.Equal(res.Data, dataExp) { + panicf("CheckTx response data was unexpected. Got %X expected %X", + res.Data, dataExp) } }*/ + +func panicf(format string, a ...interface{}) { + panic(fmt.Sprintf(format, a)) +} diff --git a/types/result.go b/types/result.go index ffd8966a..1cb96879 100644 --- a/types/result.go +++ b/types/result.go @@ -106,6 +106,7 @@ func (r *ResponseCheckTx) Result() Result { } } +// IsErr returns true if Code is something other than OK. func (r ResponseCheckTx) IsErr() bool { return r.Code != CodeType_OK } @@ -120,6 +121,7 @@ func (r *ResponseDeliverTx) Result() Result { } } +// IsErr returns true if Code is something other than OK. func (r ResponseDeliverTx) IsErr() bool { return r.Code != CodeType_OK } @@ -145,3 +147,8 @@ func (r *ResponseQuery) Result() *ResultQuery { Log: r.Log, } } + +// IsErr returns true if Code is something other than OK. +func (r ResponseCommit) IsErr() bool { + return r.Code != CodeType_OK +} From e6fdc98aeb40421cde26d7f0a5fda1099f6aa80f Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 17:44:22 -0600 Subject: [PATCH 330/545] update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cd5046c..4f944d9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.8.0 (TBD) + +BREAKING CHANGES: + - [client] more consistent interface + +IMPROVEMENTS: + - [types] added Tags field to ResponseDeliverTx + ## 0.7.1 (November 14, 2017) IMPROVEMENTS: From f6a79dd7c50c49a3e9ae39bde76af6d1ae773985 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 17:50:06 -0600 Subject: [PATCH 331/545] add interface assertions for all clients --- client/grpc_client.go | 2 ++ client/local_client.go | 2 ++ client/socket_client.go | 2 ++ 3 files changed, 6 insertions(+) diff --git a/client/grpc_client.go b/client/grpc_client.go index 524f1f7f..c7a4c2ae 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -13,6 +13,8 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +var _ Client = (*grpcClient)(nil) + // A stripped copy of the remoteClient that makes // synchronous calls using grpc type grpcClient struct { diff --git a/client/local_client.go b/client/local_client.go index 9081406a..2a294f48 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -7,6 +7,8 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +var _ Client = (*localClient)(nil) + type localClient struct { cmn.BaseService mtx *sync.Mutex diff --git a/client/socket_client.go b/client/socket_client.go index ef0a6ece..64211979 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -23,6 +23,8 @@ const reqQueueSize = 256 // TODO make configurable // const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... +var _ Client = (*socketClient)(nil) + // This is goroutine-safe, but users should beware that // the application in general is not meant to be interfaced // with concurrent callers. From 5be9c50b47d93a977c3eec19dd49e7c486d7e008 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 17:53:48 -0600 Subject: [PATCH 332/545] fix megacheck warning --- cmd/abci-cli/abci-cli.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 9c14aa4d..cd6f05f4 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -355,12 +355,12 @@ func cmdInfo(cmd *cobra.Command, args []string) error { // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) error { - log, err := client.SetOptionSync(args[0], args[1]) + resLog, err := client.SetOptionSync(args[0], args[1]) if err != nil { return err } printResponse(cmd, args, response{ - Log: log, + Log: resLog, }) return nil } From 52ec4efe275ec96d01d741415996d473c748b19e Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 18:11:23 -0600 Subject: [PATCH 333/545] retire test_integrations in favor of just make test --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index aeb6d716..57ab4052 100644 --- a/Makefile +++ b/Makefile @@ -37,15 +37,15 @@ dist: # test.sh requires that we run the installed cmds, must not be out of date test: install - find . -path ./vendor -prune -o -name *.sock -exec rm {} \; + @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @ echo "==> Running unit tests" @ go test $(PACKAGES) + @ echo "==> Running integration tests (./tests)" @ bash tests/test.sh fmt: @ go fmt ./... -test_integrations: get_vendor_deps install test - get_deps: @ go get -d $(PACKAGES) From 7868a3358f8b31b090e2a60ce3d27145ca93bc5c Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 21 Nov 2017 18:12:12 -0600 Subject: [PATCH 334/545] gather test coverage --- circle.yml | 10 +++++----- test.sh | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100755 test.sh diff --git a/circle.yml b/circle.yml index daa4218e..45987363 100644 --- a/circle.yml +++ b/circle.yml @@ -12,11 +12,11 @@ checkout: - rm -rf $REPO - mkdir -p $HOME/.go_workspace/src/github.com/$CIRCLE_PROJECT_USERNAME - mv $HOME/$CIRCLE_PROJECT_REPONAME $REPO - # - git submodule sync - # - git submodule update --init # use submodules + - go version test: override: - - "go version" - - "cd $REPO && make get_vendor_deps && make metalinter_test" - - "cd $REPO && make test_integrations" + - cd $REPO && make get_vendor_deps && make metalinter_test && bash ./test.sh + post: + - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt + - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" diff --git a/test.sh b/test.sh new file mode 100755 index 00000000..136f60e2 --- /dev/null +++ b/test.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e +echo "" > coverage.txt + +echo "==> Running unit tests" +for d in $(go list ./... | grep -v vendor); do + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done + +echo "==> Running integration tests (./tests)" +find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; +make install +bash tests/test.sh From 5fd83b3eeec162b7f1b34795a5a9ca19a9cca76a Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 16:17:34 -0600 Subject: [PATCH 335/545] implement error interface for ResponseDeliverTx/CheckTx/Commit --- types/errors.go | 23 +++++++++++++++++++++++ types/result.go | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/types/errors.go b/types/errors.go index 7fa1f009..03d14578 100644 --- a/types/errors.go +++ b/types/errors.go @@ -23,4 +23,27 @@ var ( ErrBaseUnknownAddress = NewError(CodeType_BaseUnknownAddress, "Error (base) unknown address") ErrBaseUnknownPlugin = NewError(CodeType_BaseUnknownPlugin, "Error (base) unknown plugin") ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error (base) unknown pubkey") + + code2string = map[CodeType]string{ + CodeType_InternalError: "Internal error", + CodeType_EncodingError: "Encoding error", + CodeType_BadNonce: "Error bad nonce", + CodeType_Unauthorized: "Unauthorized", + CodeType_InsufficientFunds: "Insufficient funds", + CodeType_UnknownRequest: "Unknown request", + + CodeType_BaseDuplicateAddress: "Error (base) duplicate address", + CodeType_BaseEncodingError: "Error (base) encoding error", + CodeType_BaseInsufficientFees: "Error (base) insufficient fees", + CodeType_BaseInsufficientFunds: "Error (base) insufficient funds", + CodeType_BaseInsufficientGasPrice: "Error (base) insufficient gas price", + CodeType_BaseInvalidInput: "Error (base) invalid input", + CodeType_BaseInvalidOutput: "Error (base) invalid output", + CodeType_BaseInvalidPubKey: "Error (base) invalid pubkey", + CodeType_BaseInvalidSequence: "Error (base) invalid sequence", + CodeType_BaseInvalidSignature: "Error (base) invalid signature", + CodeType_BaseUnknownAddress: "Error (base) unknown address", + CodeType_BaseUnknownPlugin: "Error (base) unknown plugin", + CodeType_BaseUnknownPubKey: "Error (base) unknown pubkey", + } ) diff --git a/types/result.go b/types/result.go index 1cb96879..8dba2448 100644 --- a/types/result.go +++ b/types/result.go @@ -111,6 +111,11 @@ func (r ResponseCheckTx) IsErr() bool { return r.Code != CodeType_OK } +// Error implements error interface by formatting response as string. +func (r ResponseCheckTx) Error() string { + return fmtError(r.Code, r.Log) +} + // Convert ResponseDeliverTx to standard Result func (r *ResponseDeliverTx) Result() Result { return Result{ @@ -126,6 +131,11 @@ func (r ResponseDeliverTx) IsErr() bool { return r.Code != CodeType_OK } +// Error implements error interface by formatting response as string. +func (r ResponseDeliverTx) Error() string { + return fmtError(r.Code, r.Log) +} + type ResultQuery struct { Code CodeType `json:"code"` Index int64 `json:"index"` @@ -152,3 +162,17 @@ func (r *ResponseQuery) Result() *ResultQuery { func (r ResponseCommit) IsErr() bool { return r.Code != CodeType_OK } + +// Error implements error interface by formatting response as string. +func (r ResponseCommit) Error() string { + return fmtError(r.Code, r.Log) +} + +func fmtError(code CodeType, log string) string { + codeAsStr, ok := code2string[code] + if ok { + return fmt.Sprintf("%s (%v): %s", codeAsStr, code, log) + } else { + return fmt.Sprintf("Unknown error (%v): %s", code, log) + } +} From 01252e8cc84229ad0f47921e1b2a74592de72ffc Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 16:18:06 -0600 Subject: [PATCH 336/545] mark Result as deprecated --- types/result.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/result.go b/types/result.go index 8dba2448..e37f6f49 100644 --- a/types/result.go +++ b/types/result.go @@ -8,6 +8,7 @@ import ( // Result is a common result object for ABCI calls. // CONTRACT: a zero Result is OK. +// DEPRECATED: prefer raw types instead. type Result struct { Code CodeType `json:"code"` Data data.Bytes `json:"data"` From f01f2bbf3a52c395c22a96c5cff442cd433bcb84 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 17:34:00 -0600 Subject: [PATCH 337/545] DeliverTxSync/CheckTxSync/CommitSync now return error as well --- client/client.go | 6 +++--- client/grpc_client.go | 19 ++++++++++--------- client/local_client.go | 12 ++++++------ client/socket_client.go | 20 ++++++++++---------- cmd/abci-cli/abci-cli.go | 15 ++++++++++++--- example/dummy/dummy_test.go | 6 ++++-- tests/test_app/app.go | 15 ++++++++++++--- types/errors.go | 9 +++++++++ 8 files changed, 66 insertions(+), 36 deletions(-) diff --git a/client/client.go b/client/client.go index b550dc92..5878b619 100644 --- a/client/client.go +++ b/client/client.go @@ -27,10 +27,10 @@ type Client interface { EchoSync(msg string) (*types.ResponseEcho, error) InfoSync(types.RequestInfo) (*types.ResponseInfo, error) SetOptionSync(key string, value string) (log string, err error) - DeliverTxSync(tx []byte) *types.ResponseDeliverTx - CheckTxSync(tx []byte) *types.ResponseCheckTx + DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) + CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) QuerySync(types.RequestQuery) (*types.ResponseQuery, error) - CommitSync() *types.ResponseCommit + CommitSync() (*types.ResponseCommit, error) InitChainAsync(types.RequestInitChain) *ReqRes BeginBlockAsync(types.RequestBeginBlock) *ReqRes diff --git a/client/grpc_client.go b/client/grpc_client.go index c7a4c2ae..6a53cb21 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "github.com/pkg/errors" context "golang.org/x/net/context" grpc "google.golang.org/grpc" @@ -267,20 +268,20 @@ func (cli *grpcClient) SetOptionSync(key string, value string) (log string, err return reqres.Response.GetSetOption().Log, nil } -func (cli *grpcClient) DeliverTxSync(tx []byte) *types.ResponseDeliverTx { +func (cli *grpcClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { reqres := cli.DeliverTxAsync(tx) if err := cli.Error(); err != nil { - return &types.ResponseDeliverTx{Code: types.CodeType_InternalError, Log: err.Error()} + return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) } - return reqres.Response.GetDeliverTx() + return reqres.Response.GetDeliverTx(), nil } -func (cli *grpcClient) CheckTxSync(tx []byte) *types.ResponseCheckTx { +func (cli *grpcClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { reqres := cli.CheckTxAsync(tx) if err := cli.Error(); err != nil { - return &types.ResponseCheckTx{Code: types.CodeType_InternalError, Log: err.Error()} + return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) } - return reqres.Response.GetCheckTx() + return reqres.Response.GetCheckTx(), nil } func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { @@ -288,12 +289,12 @@ func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, return reqres.Response.GetQuery(), cli.Error() } -func (cli *grpcClient) CommitSync() *types.ResponseCommit { +func (cli *grpcClient) CommitSync() (*types.ResponseCommit, error) { reqres := cli.CommitAsync() if err := cli.Error(); err != nil { - return &types.ResponseCommit{Code: types.CodeType_InternalError, Log: err.Error()} + return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) } - return reqres.Response.GetCommit() + return reqres.Response.GetCommit(), nil } func (cli *grpcClient) InitChainSync(params types.RequestInitChain) error { diff --git a/client/local_client.go b/client/local_client.go index 2a294f48..15dda8e6 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -166,18 +166,18 @@ func (app *localClient) SetOptionSync(key string, value string) (log string, err return log, nil } -func (app *localClient) DeliverTxSync(tx []byte) *types.ResponseDeliverTx { +func (app *localClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { app.mtx.Lock() res := app.Application.DeliverTx(tx) app.mtx.Unlock() - return &res + return &res, nil } -func (app *localClient) CheckTxSync(tx []byte) *types.ResponseCheckTx { +func (app *localClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { app.mtx.Lock() res := app.Application.CheckTx(tx) app.mtx.Unlock() - return &res + return &res, nil } func (app *localClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { @@ -187,11 +187,11 @@ func (app *localClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, return &res, nil } -func (app *localClient) CommitSync() *types.ResponseCommit { +func (app *localClient) CommitSync() (*types.ResponseCommit, error) { app.mtx.Lock() res := app.Application.Commit() app.mtx.Unlock() - return &res + return &res, nil } func (app *localClient) InitChainSync(params types.RequestInitChain) error { diff --git a/client/socket_client.go b/client/socket_client.go index 64211979..7e117d22 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -3,13 +3,13 @@ package abcicli import ( "bufio" "container/list" - "errors" "fmt" "net" "reflect" "sync" "time" + "github.com/pkg/errors" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -303,22 +303,22 @@ func (cli *socketClient) SetOptionSync(key string, value string) (log string, er return reqres.Response.GetSetOption().Log, nil } -func (cli *socketClient) DeliverTxSync(tx []byte) *types.ResponseDeliverTx { +func (cli *socketClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { reqres := cli.queueRequest(types.ToRequestDeliverTx(tx)) cli.FlushSync() if err := cli.Error(); err != nil { - return &types.ResponseDeliverTx{Code: types.CodeType_InternalError, Log: err.Error()} + return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) } - return reqres.Response.GetDeliverTx() + return reqres.Response.GetDeliverTx(), nil } -func (cli *socketClient) CheckTxSync(tx []byte) *types.ResponseCheckTx { +func (cli *socketClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() if err := cli.Error(); err != nil { - return &types.ResponseCheckTx{Code: types.CodeType_InternalError, Log: err.Error()} + return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) } - return reqres.Response.GetCheckTx() + return reqres.Response.GetCheckTx(), nil } func (cli *socketClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { @@ -327,13 +327,13 @@ func (cli *socketClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery return reqres.Response.GetQuery(), cli.Error() } -func (cli *socketClient) CommitSync() *types.ResponseCommit { +func (cli *socketClient) CommitSync() (*types.ResponseCommit, error) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() if err := cli.Error(); err != nil { - return &types.ResponseCommit{Code: types.CodeType_InternalError, Log: err.Error()} + return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) } - return reqres.Response.GetCommit() + return reqres.Response.GetCommit(), nil } func (cli *socketClient) InitChainSync(params types.RequestInitChain) error { diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index cd6f05f4..e3f0daec 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -371,7 +371,10 @@ func cmdDeliverTx(cmd *cobra.Command, args []string) error { if err != nil { return err } - res := client.DeliverTxSync(txBytes) + res, err := client.DeliverTxSync(txBytes) + if err != nil { + return err + } printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, @@ -386,7 +389,10 @@ func cmdCheckTx(cmd *cobra.Command, args []string) error { if err != nil { return err } - res := client.CheckTxSync(txBytes) + res, err := client.CheckTxSync(txBytes) + if err != nil { + return err + } printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, @@ -397,7 +403,10 @@ func cmdCheckTx(cmd *cobra.Command, args []string) error { // Get application Merkle root hash func cmdCommit(cmd *cobra.Command, args []string) error { - res := client.CommitSync() + res, err := client.CommitSync() + if err != nil { + return err + } printResponse(cmd, args, response{ Code: res.Code, Data: res.Data, diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index efbc5af7..798da720 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -281,10 +281,12 @@ func runClientTests(t *testing.T, client abcicli.Client) { } func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) { - ar := app.DeliverTxSync(tx) + ar, err := app.DeliverTxSync(tx) + require.NoError(t, err) require.False(t, ar.IsErr(), ar) // repeating tx doesn't raise error - ar = app.DeliverTxSync(tx) + ar, err = app.DeliverTxSync(tx) + require.NoError(t, err) require.False(t, ar.IsErr(), ar) // make sure query is fine diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 67742b38..c3e9d14f 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -55,7 +55,10 @@ func setOption(client abcicli.Client, key, value string) { } func commit(client abcicli.Client, hashExp []byte) { - res := client.CommitSync() + res, err := client.CommitSync() + if err != nil { + panicf("client error: %v", err) + } if res.IsErr() { panicf("committing err %v\n", res) } @@ -65,7 +68,10 @@ func commit(client abcicli.Client, hashExp []byte) { } func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - res := client.DeliverTxSync(txBytes) + res, err := client.DeliverTxSync(txBytes) + if err != nil { + panicf("client error: %v", err) + } if res.Code != codeExp { panicf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", res.Code, codeExp, res.Log) } @@ -75,7 +81,10 @@ func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da } /*func checkTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { - res := client.CheckTxSync(txBytes) + res, err := client.CheckTxSync(txBytes) + if err != nil { + panicf("client error: %v", err) + } if res.IsErr() { panicf("checking tx %X: %v\nlog: %v", txBytes, res.Log) } diff --git a/types/errors.go b/types/errors.go index 03d14578..f63d2470 100644 --- a/types/errors.go +++ b/types/errors.go @@ -47,3 +47,12 @@ var ( CodeType_BaseUnknownPubKey: "Error (base) unknown pubkey", } ) + +// HumanCode transforms code into a more humane format, such as "Internal error" instead of 0. +func HumanCode(code CodeType) string { + s, ok := code2string[code] + if !ok { + return "Unknown code" + } + return s +} From 91efacfabc086f14a9d4fe4f2d661a0e647915c2 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 17:44:39 -0600 Subject: [PATCH 338/545] remove types.Result --- types/code.go | 34 +++++++++++ types/errors.go | 58 ------------------ types/result.go | 158 ++++++++---------------------------------------- 3 files changed, 59 insertions(+), 191 deletions(-) delete mode 100644 types/errors.go diff --git a/types/code.go b/types/code.go index c99a0bbe..613c4cda 100644 --- a/types/code.go +++ b/types/code.go @@ -1,3 +1,37 @@ package types +var ( + code2string = map[CodeType]string{ + CodeType_InternalError: "Internal error", + CodeType_EncodingError: "Encoding error", + CodeType_BadNonce: "Error bad nonce", + CodeType_Unauthorized: "Unauthorized", + CodeType_InsufficientFunds: "Insufficient funds", + CodeType_UnknownRequest: "Unknown request", + + CodeType_BaseDuplicateAddress: "Error (base) duplicate address", + CodeType_BaseEncodingError: "Error (base) encoding error", + CodeType_BaseInsufficientFees: "Error (base) insufficient fees", + CodeType_BaseInsufficientFunds: "Error (base) insufficient funds", + CodeType_BaseInsufficientGasPrice: "Error (base) insufficient gas price", + CodeType_BaseInvalidInput: "Error (base) invalid input", + CodeType_BaseInvalidOutput: "Error (base) invalid output", + CodeType_BaseInvalidPubKey: "Error (base) invalid pubkey", + CodeType_BaseInvalidSequence: "Error (base) invalid sequence", + CodeType_BaseInvalidSignature: "Error (base) invalid signature", + CodeType_BaseUnknownAddress: "Error (base) unknown address", + CodeType_BaseUnknownPlugin: "Error (base) unknown plugin", + CodeType_BaseUnknownPubKey: "Error (base) unknown pubkey", + } +) + func (c CodeType) IsOK() bool { return c == CodeType_OK } + +// HumanCode transforms code into a more humane format, such as "Internal error" instead of 0. +func HumanCode(code CodeType) string { + s, ok := code2string[code] + if !ok { + return "Unknown code" + } + return s +} diff --git a/types/errors.go b/types/errors.go deleted file mode 100644 index f63d2470..00000000 --- a/types/errors.go +++ /dev/null @@ -1,58 +0,0 @@ -package types - -var ( - OK = NewResultOK(nil, "") - - ErrInternalError = NewError(CodeType_InternalError, "Internal error") - ErrEncodingError = NewError(CodeType_EncodingError, "Encoding error") - ErrBadNonce = NewError(CodeType_BadNonce, "Error bad nonce") - ErrUnauthorized = NewError(CodeType_Unauthorized, "Unauthorized") - ErrInsufficientFunds = NewError(CodeType_InsufficientFunds, "Insufficient funds") - ErrUnknownRequest = NewError(CodeType_UnknownRequest, "Unknown request") - - ErrBaseDuplicateAddress = NewError(CodeType_BaseDuplicateAddress, "Error (base) duplicate address") - ErrBaseEncodingError = NewError(CodeType_BaseEncodingError, "Error (base) encoding error") - ErrBaseInsufficientFees = NewError(CodeType_BaseInsufficientFees, "Error (base) insufficient fees") - ErrBaseInsufficientFunds = NewError(CodeType_BaseInsufficientFunds, "Error (base) insufficient funds") - ErrBaseInsufficientGasPrice = NewError(CodeType_BaseInsufficientGasPrice, "Error (base) insufficient gas price") - ErrBaseInvalidInput = NewError(CodeType_BaseInvalidInput, "Error (base) invalid input") - ErrBaseInvalidOutput = NewError(CodeType_BaseInvalidOutput, "Error (base) invalid output") - ErrBaseInvalidPubKey = NewError(CodeType_BaseInvalidPubKey, "Error (base) invalid pubkey") - ErrBaseInvalidSequence = NewError(CodeType_BaseInvalidSequence, "Error (base) invalid sequence") - ErrBaseInvalidSignature = NewError(CodeType_BaseInvalidSignature, "Error (base) invalid signature") - ErrBaseUnknownAddress = NewError(CodeType_BaseUnknownAddress, "Error (base) unknown address") - ErrBaseUnknownPlugin = NewError(CodeType_BaseUnknownPlugin, "Error (base) unknown plugin") - ErrBaseUnknownPubKey = NewError(CodeType_BaseUnknownPubKey, "Error (base) unknown pubkey") - - code2string = map[CodeType]string{ - CodeType_InternalError: "Internal error", - CodeType_EncodingError: "Encoding error", - CodeType_BadNonce: "Error bad nonce", - CodeType_Unauthorized: "Unauthorized", - CodeType_InsufficientFunds: "Insufficient funds", - CodeType_UnknownRequest: "Unknown request", - - CodeType_BaseDuplicateAddress: "Error (base) duplicate address", - CodeType_BaseEncodingError: "Error (base) encoding error", - CodeType_BaseInsufficientFees: "Error (base) insufficient fees", - CodeType_BaseInsufficientFunds: "Error (base) insufficient funds", - CodeType_BaseInsufficientGasPrice: "Error (base) insufficient gas price", - CodeType_BaseInvalidInput: "Error (base) invalid input", - CodeType_BaseInvalidOutput: "Error (base) invalid output", - CodeType_BaseInvalidPubKey: "Error (base) invalid pubkey", - CodeType_BaseInvalidSequence: "Error (base) invalid sequence", - CodeType_BaseInvalidSignature: "Error (base) invalid signature", - CodeType_BaseUnknownAddress: "Error (base) unknown address", - CodeType_BaseUnknownPlugin: "Error (base) unknown plugin", - CodeType_BaseUnknownPubKey: "Error (base) unknown pubkey", - } -) - -// HumanCode transforms code into a more humane format, such as "Internal error" instead of 0. -func HumanCode(code CodeType) string { - s, ok := code2string[code] - if !ok { - return "Unknown code" - } - return s -} diff --git a/types/result.go b/types/result.go index e37f6f49..78cea710 100644 --- a/types/result.go +++ b/types/result.go @@ -6,107 +6,6 @@ import ( "github.com/tendermint/go-wire/data" ) -// Result is a common result object for ABCI calls. -// CONTRACT: a zero Result is OK. -// DEPRECATED: prefer raw types instead. -type Result struct { - Code CodeType `json:"code"` - Data data.Bytes `json:"data"` - Log string `json:"log"` // Can be non-deterministic - Tags []*KVPair `json:"tags"` -} - -func NewResult(code CodeType, data []byte, log string) Result { - return Result{ - Code: code, - Data: data, - Log: log, - } -} - -func (res Result) IsOK() bool { - return res.Code == CodeType_OK -} - -func (res Result) IsErr() bool { - return res.Code != CodeType_OK -} - -func (res Result) IsSameCode(compare Result) bool { - return res.Code == compare.Code -} - -func (res Result) Error() string { - return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) -} - -func (res Result) String() string { - return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) -} - -func (res Result) PrependLog(log string) Result { - return Result{ - Code: res.Code, - Data: res.Data, - Log: log + ";" + res.Log, - } -} - -func (res Result) AppendLog(log string) Result { - return Result{ - Code: res.Code, - Data: res.Data, - Log: res.Log + ";" + log, - } -} - -func (res Result) SetLog(log string) Result { - return Result{ - Code: res.Code, - Data: res.Data, - Log: log, - } -} - -func (res Result) SetData(data []byte) Result { - return Result{ - Code: res.Code, - Data: data, - Log: res.Log, - } -} - -//---------------------------------------- - -// NOTE: if data == nil and log == "", same as zero Result. -func NewResultOK(data []byte, log string) Result { - return Result{ - Code: CodeType_OK, - Data: data, - Log: log, - } -} - -func NewError(code CodeType, log string) Result { - return Result{ - Code: code, - Log: log, - } -} - -//---------------------------------------- -// Convenience methods for turning the -// pb type into one using data.Bytes - -// Convert ResponseCheckTx to standard Result -func (r *ResponseCheckTx) Result() Result { - return Result{ - Code: r.Code, - Data: r.Data, - Log: r.Log, - } -} - // IsErr returns true if Code is something other than OK. func (r ResponseCheckTx) IsErr() bool { return r.Code != CodeType_OK @@ -117,16 +16,6 @@ func (r ResponseCheckTx) Error() string { return fmtError(r.Code, r.Log) } -// Convert ResponseDeliverTx to standard Result -func (r *ResponseDeliverTx) Result() Result { - return Result{ - Code: r.Code, - Data: r.Data, - Log: r.Log, - Tags: r.Tags, - } -} - // IsErr returns true if Code is something other than OK. func (r ResponseDeliverTx) IsErr() bool { return r.Code != CodeType_OK @@ -137,28 +26,6 @@ func (r ResponseDeliverTx) Error() string { return fmtError(r.Code, r.Log) } -type ResultQuery struct { - Code CodeType `json:"code"` - Index int64 `json:"index"` - Key data.Bytes `json:"key"` - Value data.Bytes `json:"value"` - Proof data.Bytes `json:"proof"` - Height uint64 `json:"height"` - Log string `json:"log"` -} - -func (r *ResponseQuery) Result() *ResultQuery { - return &ResultQuery{ - Code: r.Code, - Index: r.Index, - Key: r.Key, - Value: r.Value, - Proof: r.Proof, - Height: r.Height, - Log: r.Log, - } -} - // IsErr returns true if Code is something other than OK. func (r ResponseCommit) IsErr() bool { return r.Code != CodeType_OK @@ -177,3 +44,28 @@ func fmtError(code CodeType, log string) string { return fmt.Sprintf("Unknown error (%v): %s", code, log) } } + +// ResultQuery is a wrapper around ResponseQuery using data.Bytes instead of +// raw byte slices. +type ResultQuery struct { + Code CodeType `json:"code"` + Index int64 `json:"index"` + Key data.Bytes `json:"key"` + Value data.Bytes `json:"value"` + Proof data.Bytes `json:"proof"` + Height uint64 `json:"height"` + Log string `json:"log"` +} + +// Result converts response query to ResultQuery. +func (r *ResponseQuery) Result() *ResultQuery { + return &ResultQuery{ + Code: r.Code, + Index: r.Index, + Key: r.Key, + Value: r.Value, + Proof: r.Proof, + Height: r.Height, + Log: r.Log, + } +} From afb7feeea20b2255be7f808caa227e67dfb1fe8e Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 17:51:36 -0600 Subject: [PATCH 339/545] update CHANGELOG --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f944d9f..9db1817c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ ## 0.8.0 (TBD) BREAKING CHANGES: - - [client] more consistent interface + - [client] all {X}Sync methods now return an error + - [types] removed Result + - [client] all {X}Sync methods now return Response{X} as first return value IMPROVEMENTS: - [types] added Tags field to ResponseDeliverTx From 1726e828655000f09804046e8a2e1cab5799c8a9 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 18:19:41 -0600 Subject: [PATCH 340/545] add IsErr and Error method for ResultQuery --- types/result.go | 14 ++++++-- types/result_test.go | 76 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 types/result_test.go diff --git a/types/result.go b/types/result.go index 78cea710..6ebad8ab 100644 --- a/types/result.go +++ b/types/result.go @@ -39,9 +39,9 @@ func (r ResponseCommit) Error() string { func fmtError(code CodeType, log string) string { codeAsStr, ok := code2string[code] if ok { - return fmt.Sprintf("%s (%v): %s", codeAsStr, code, log) + return fmt.Sprintf("%s (%d): %s", codeAsStr, code, log) } else { - return fmt.Sprintf("Unknown error (%v): %s", code, log) + return fmt.Sprintf("Unknown error (%d): %s", code, log) } } @@ -69,3 +69,13 @@ func (r *ResponseQuery) Result() *ResultQuery { Log: r.Log, } } + +// IsErr returns true if Code is something other than OK. +func (r *ResultQuery) IsErr() bool { + return r.Code != CodeType_OK +} + +// Error implements error interface by formatting result as string. +func (r *ResultQuery) Error() string { + return fmtError(r.Code, r.Log) +} diff --git a/types/result_test.go b/types/result_test.go new file mode 100644 index 00000000..14f334c4 --- /dev/null +++ b/types/result_test.go @@ -0,0 +1,76 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResultQuery(t *testing.T) { + orig := &ResponseQuery{ + Code: CodeType_OK, + Index: 0, + Key: []byte("hello"), + Value: []byte("world"), + Height: 1, + } + res := orig.Result() + assert.False(t, res.IsErr()) + + orig = &ResponseQuery{ + Code: CodeType_BadNonce, + Index: 0, + Key: []byte("hello"), + Value: []byte("world"), + Height: 1, + Log: "bad", + } + res = orig.Result() + assert.True(t, res.IsErr()) + assert.Equal(t, "Error bad nonce (3): bad", res.Error()) +} + +func TestResponseDeliverTx(t *testing.T) { + res := ResponseDeliverTx{ + Code: CodeType_OK, + Data: []byte("Victor Mancha"), + } + assert.False(t, res.IsErr()) + + res = ResponseDeliverTx{ + Code: CodeType_InternalError, + Log: "bad", + } + assert.True(t, res.IsErr()) + assert.Equal(t, "Internal error (1): bad", res.Error()) +} + +func TestResponseCheckTx(t *testing.T) { + res := ResponseCheckTx{ + Code: CodeType_OK, + Data: []byte("Talos"), + } + assert.False(t, res.IsErr()) + + res = ResponseCheckTx{ + Code: CodeType_InternalError, + Log: "bad", + } + assert.True(t, res.IsErr()) + assert.Equal(t, "Internal error (1): bad", res.Error()) +} + +func TestResponseCommit(t *testing.T) { + res := ResponseCommit{ + Code: CodeType_OK, + Data: []byte("Old Lace"), + } + assert.False(t, res.IsErr()) + + res = ResponseCommit{ + Code: CodeType_Unauthorized, + Log: "bad", + } + assert.True(t, res.IsErr()) + assert.Equal(t, "Unauthorized (4): bad", res.Error()) +} From 2cfad8523a54d64271d7cbc69a39433eab918aa0 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 18:24:53 -0600 Subject: [PATCH 341/545] test HumanCode --- types/code_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 types/code_test.go diff --git a/types/code_test.go b/types/code_test.go new file mode 100644 index 00000000..d9032d3c --- /dev/null +++ b/types/code_test.go @@ -0,0 +1,12 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestHumanCode(t *testing.T) { + assert.Equal(t, "Internal error", HumanCode(CodeType_InternalError)) + assert.Equal(t, "Unknown code", HumanCode(-1)) +} From cbf347e2aabbb06e84eba7f0debcc92dedce4aa0 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 19:07:36 -0600 Subject: [PATCH 342/545] add comment for Client interface [ci skip] --- client/client.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/client.go b/client/client.go index 5878b619..092c479a 100644 --- a/client/client.go +++ b/client/client.go @@ -8,6 +8,10 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +// Client defines an interface for an ABCI client. Client-related errors (e.g. +// network errors) are returned as a second return value for most calls +// (sometimes there is no response). Application-related errors are reflected +// in response via ABCI error codes and logs. type Client interface { cmn.Service From 0176a834d197a3718808cd04e6407fee1631298a Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 19:37:51 -0600 Subject: [PATCH 343/545] refactor code --- client/grpc_client.go | 17 ++++------------- client/socket_client.go | 17 ++++------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 6a53cb21..f7889d69 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -104,7 +104,7 @@ func (cli *grpcClient) StopForError(err error) { func (cli *grpcClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return cli.err + return errors.Wrap(cli.err, types.HumanCode(types.CodeType_InternalError)) } // Set listener for all responses @@ -270,18 +270,12 @@ func (cli *grpcClient) SetOptionSync(key string, value string) (log string, err func (cli *grpcClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { reqres := cli.DeliverTxAsync(tx) - if err := cli.Error(); err != nil { - return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) - } - return reqres.Response.GetDeliverTx(), nil + return reqres.Response.GetDeliverTx(), cli.Error() } func (cli *grpcClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { reqres := cli.CheckTxAsync(tx) - if err := cli.Error(); err != nil { - return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) - } - return reqres.Response.GetCheckTx(), nil + return reqres.Response.GetCheckTx(), cli.Error() } func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { @@ -291,10 +285,7 @@ func (cli *grpcClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, func (cli *grpcClient) CommitSync() (*types.ResponseCommit, error) { reqres := cli.CommitAsync() - if err := cli.Error(); err != nil { - return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) - } - return reqres.Response.GetCommit(), nil + return reqres.Response.GetCommit(), cli.Error() } func (cli *grpcClient) InitChainSync(params types.RequestInitChain) error { diff --git a/client/socket_client.go b/client/socket_client.go index 7e117d22..716ef451 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -116,7 +116,7 @@ func (cli *socketClient) StopForError(err error) { func (cli *socketClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return cli.err + return errors.Wrap(cli.err, types.HumanCode(types.CodeType_InternalError)) } // Set listener for all responses @@ -306,19 +306,13 @@ func (cli *socketClient) SetOptionSync(key string, value string) (log string, er func (cli *socketClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { reqres := cli.queueRequest(types.ToRequestDeliverTx(tx)) cli.FlushSync() - if err := cli.Error(); err != nil { - return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) - } - return reqres.Response.GetDeliverTx(), nil + return reqres.Response.GetDeliverTx(), cli.Error() } func (cli *socketClient) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) { reqres := cli.queueRequest(types.ToRequestCheckTx(tx)) cli.FlushSync() - if err := cli.Error(); err != nil { - return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) - } - return reqres.Response.GetCheckTx(), nil + return reqres.Response.GetCheckTx(), cli.Error() } func (cli *socketClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery, error) { @@ -330,10 +324,7 @@ func (cli *socketClient) QuerySync(req types.RequestQuery) (*types.ResponseQuery func (cli *socketClient) CommitSync() (*types.ResponseCommit, error) { reqres := cli.queueRequest(types.ToRequestCommit()) cli.FlushSync() - if err := cli.Error(); err != nil { - return nil, errors.Wrap(err, types.HumanCode(types.CodeType_InternalError)) - } - return reqres.Response.GetCommit(), nil + return reqres.Response.GetCommit(), cli.Error() } func (cli *socketClient) InitChainSync(params types.RequestInitChain) error { From 03fafeec2fc8fd95e30f4a9af31472b4a5e5718b Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 19:38:04 -0600 Subject: [PATCH 344/545] fix formatting of panicf function --- tests/test_app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index c3e9d14f..c869fe83 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -99,5 +99,5 @@ func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da }*/ func panicf(format string, a ...interface{}) { - panic(fmt.Sprintf(format, a)) + panic(fmt.Sprintf(format, a...)) } From 9b30fab4fc5ab59f34fc8ad72b7288178246bd27 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Nov 2017 19:38:28 -0600 Subject: [PATCH 345/545] preserve behaviour of BaseApplication --- types/base_app.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/base_app.go b/types/base_app.go index 75fdae8d..5432a531 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -16,11 +16,11 @@ func (BaseApplication) SetOption(key string, value string) (log string) { } func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { - return ResponseDeliverTx{} + return ResponseDeliverTx{Code: CodeType_OK} } func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { - return ResponseCheckTx{} + return ResponseCheckTx{Code: CodeType_OK} } func (BaseApplication) Commit() ResponseCommit { From 67d2a5f66d958f881ca6957eb4b3a9268dc00b41 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 24 Nov 2017 16:45:36 -0600 Subject: [PATCH 346/545] set Code to OK in ResponseQuery in BaseApplication See https://github.com/tendermint/abci/pull/130#discussion_r152713220 --- types/base_app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/base_app.go b/types/base_app.go index 5432a531..0086685b 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -28,7 +28,7 @@ func (BaseApplication) Commit() ResponseCommit { } func (BaseApplication) Query(req RequestQuery) ResponseQuery { - return ResponseQuery{} + return ResponseQuery{Code: CodeType_OK} } func (BaseApplication) InitChain(req RequestInitChain) { From c7f54fb56cbc2f896e24f2f25d54aeccbb1e2dcd Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 19:04:21 +0000 Subject: [PATCH 347/545] everything takes Request, returns Response; expect DeliverTx/CheckTx/Commit --- client/client.go | 27 +++++----- client/grpc_client.go | 33 ++++++------ client/local_client.go | 72 ++++++++++++------------- client/socket_client.go | 41 +++++++------- cmd/abci-cli/abci-cli.go | 5 +- example/block_aware/block_aware_app.go | 65 ---------------------- example/block_aware/block_aware_test.go | 57 -------------------- example/counter/counter.go | 5 +- example/dummy/dummy.go | 2 + example/dummy/dummy_test.go | 4 +- example/dummy/persistent_dummy.go | 26 +++++---- server/socket_server.go | 31 ++++++----- types/application.go | 33 ++++++------ types/base_app.go | 12 +++-- types/messages.go | 52 +++++++++--------- 15 files changed, 174 insertions(+), 291 deletions(-) delete mode 100644 example/block_aware/block_aware_app.go delete mode 100644 example/block_aware/block_aware_test.go diff --git a/client/client.go b/client/client.go index 092c479a..ddb589a4 100644 --- a/client/client.go +++ b/client/client.go @@ -8,10 +8,11 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -// Client defines an interface for an ABCI client. Client-related errors (e.g. -// network errors) are returned as a second return value for most calls -// (sometimes there is no response). Application-related errors are reflected -// in response via ABCI error codes and logs. +// Client defines an interface for an ABCI client. +// All `Async` methods return a `ReqRes` object. +// All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error. +// Note these are client errors, eg. ABCI socket connectivity issues. +// Application-related errors are reflected in response via ABCI error codes and logs. type Client interface { cmn.Service @@ -21,28 +22,26 @@ type Client interface { FlushAsync() *ReqRes EchoAsync(msg string) *ReqRes InfoAsync(types.RequestInfo) *ReqRes - SetOptionAsync(key string, value string) *ReqRes + SetOptionAsync(types.RequestSetOption) *ReqRes DeliverTxAsync(tx []byte) *ReqRes CheckTxAsync(tx []byte) *ReqRes QueryAsync(types.RequestQuery) *ReqRes CommitAsync() *ReqRes + InitChainAsync(types.RequestInitChain) *ReqRes + BeginBlockAsync(types.RequestBeginBlock) *ReqRes + EndBlockAsync(types.RequestEndBlock) *ReqRes FlushSync() error EchoSync(msg string) (*types.ResponseEcho, error) InfoSync(types.RequestInfo) (*types.ResponseInfo, error) - SetOptionSync(key string, value string) (log string, err error) + SetOptionSync(types.RequestSetOption) (*types.ResponseSetOption, error) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) CheckTxSync(tx []byte) (*types.ResponseCheckTx, error) QuerySync(types.RequestQuery) (*types.ResponseQuery, error) CommitSync() (*types.ResponseCommit, error) - - InitChainAsync(types.RequestInitChain) *ReqRes - BeginBlockAsync(types.RequestBeginBlock) *ReqRes - EndBlockAsync(height uint64) *ReqRes - - InitChainSync(types.RequestInitChain) error - BeginBlockSync(types.RequestBeginBlock) error - EndBlockSync(height uint64) (*types.ResponseEndBlock, error) + InitChainSync(types.RequestInitChain) (*types.ResponseInitChain, error) + BeginBlockSync(types.RequestBeginBlock) (*types.ResponseBeginBlock, error) + EndBlockSync(types.RequestEndBlock) (*types.ResponseEndBlock, error) } //---------------------------------------- diff --git a/client/grpc_client.go b/client/grpc_client.go index f7889d69..6079c90c 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -150,8 +150,8 @@ func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_Info{res}}) } -func (cli *grpcClient) SetOptionAsync(key string, value string) *ReqRes { - req := types.ToRequestSetOption(key, value) +func (cli *grpcClient) SetOptionAsync(params types.RequestSetOption) *ReqRes { + req := types.ToRequestSetOption(params) res, err := cli.client.SetOption(context.Background(), req.GetSetOption(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -213,8 +213,8 @@ func (cli *grpcClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { return cli.finishAsyncCall(req, &types.Response{&types.Response_BeginBlock{res}}) } -func (cli *grpcClient) EndBlockAsync(height uint64) *ReqRes { - req := types.ToRequestEndBlock(height) +func (cli *grpcClient) EndBlockAsync(params types.RequestEndBlock) *ReqRes { + req := types.ToRequestEndBlock(params) res, err := cli.client.EndBlock(context.Background(), req.GetEndBlock(), grpc.FailFast(true)) if err != nil { cli.StopForError(err) @@ -260,12 +260,9 @@ func (cli *grpcClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, err return reqres.Response.GetInfo(), cli.Error() } -func (cli *grpcClient) SetOptionSync(key string, value string) (log string, err error) { - reqres := cli.SetOptionAsync(key, value) - if err := cli.Error(); err != nil { - return "", err - } - return reqres.Response.GetSetOption().Log, nil +func (cli *grpcClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { + reqres := cli.SetOptionAsync(req) + return reqres.Response.GetSetOption(), cli.Error() } func (cli *grpcClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { @@ -288,17 +285,17 @@ func (cli *grpcClient) CommitSync() (*types.ResponseCommit, error) { return reqres.Response.GetCommit(), cli.Error() } -func (cli *grpcClient) InitChainSync(params types.RequestInitChain) error { - cli.InitChainAsync(params) - return cli.Error() +func (cli *grpcClient) InitChainSync(params types.RequestInitChain) (*types.ResponseInitChain, error) { + reqres := cli.InitChainAsync(params) + return reqres.Response.GetInitChain(), cli.Error() } -func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) error { - cli.BeginBlockAsync(params) - return cli.Error() +func (cli *grpcClient) BeginBlockSync(params types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { + reqres := cli.BeginBlockAsync(params) + return reqres.Response.GetBeginBlock(), cli.Error() } -func (cli *grpcClient) EndBlockSync(height uint64) (*types.ResponseEndBlock, error) { - reqres := cli.EndBlockAsync(height) +func (cli *grpcClient) EndBlockSync(params types.RequestEndBlock) (*types.ResponseEndBlock, error) { + reqres := cli.EndBlockAsync(params) return reqres.Response.GetEndBlock(), cli.Error() } diff --git a/client/local_client.go b/client/local_client.go index 15dda8e6..64bf5fe0 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -53,21 +53,21 @@ func (app *localClient) EchoAsync(msg string) *ReqRes { func (app *localClient) InfoAsync(req types.RequestInfo) *ReqRes { app.mtx.Lock() - resInfo := app.Application.Info(req) + res := app.Application.Info(req) app.mtx.Unlock() return app.callback( types.ToRequestInfo(req), - types.ToResponseInfo(resInfo), + types.ToResponseInfo(res), ) } -func (app *localClient) SetOptionAsync(key string, value string) *ReqRes { +func (app *localClient) SetOptionAsync(req types.RequestSetOption) *ReqRes { app.mtx.Lock() - log := app.Application.SetOption(key, value) + res := app.Application.SetOption(req) app.mtx.Unlock() return app.callback( - types.ToRequestSetOption(key, value), - types.ToResponseSetOption(log), + types.ToRequestSetOption(req), + types.ToResponseSetOption(res), ) } @@ -77,7 +77,7 @@ func (app *localClient) DeliverTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestDeliverTx(tx), - types.ToResponseDeliverTx(res.Code, res.Data, res.Log, res.Tags), + types.ToResponseDeliverTx(res), ) } @@ -87,17 +87,17 @@ func (app *localClient) CheckTxAsync(tx []byte) *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestCheckTx(tx), - types.ToResponseCheckTx(res.Code, res.Data, res.Log), + types.ToResponseCheckTx(res), ) } -func (app *localClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { +func (app *localClient) QueryAsync(req types.RequestQuery) *ReqRes { app.mtx.Lock() - resQuery := app.Application.Query(reqQuery) + res := app.Application.Query(req) app.mtx.Unlock() return app.callback( - types.ToRequestQuery(reqQuery), - types.ToResponseQuery(resQuery), + types.ToRequestQuery(req), + types.ToResponseQuery(res), ) } @@ -107,38 +107,38 @@ func (app *localClient) CommitAsync() *ReqRes { app.mtx.Unlock() return app.callback( types.ToRequestCommit(), - types.ToResponseCommit(res.Code, res.Data, res.Log), + types.ToResponseCommit(res), ) } -func (app *localClient) InitChainAsync(params types.RequestInitChain) *ReqRes { +func (app *localClient) InitChainAsync(req types.RequestInitChain) *ReqRes { app.mtx.Lock() - app.Application.InitChain(params) + res := app.Application.InitChain(req) reqRes := app.callback( - types.ToRequestInitChain(params), - types.ToResponseInitChain(), + types.ToRequestInitChain(req), + types.ToResponseInitChain(res), ) app.mtx.Unlock() return reqRes } -func (app *localClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { +func (app *localClient) BeginBlockAsync(req types.RequestBeginBlock) *ReqRes { app.mtx.Lock() - app.Application.BeginBlock(params) + res := app.Application.BeginBlock(req) app.mtx.Unlock() return app.callback( - types.ToRequestBeginBlock(params), - types.ToResponseBeginBlock(), + types.ToRequestBeginBlock(req), + types.ToResponseBeginBlock(res), ) } -func (app *localClient) EndBlockAsync(height uint64) *ReqRes { +func (app *localClient) EndBlockAsync(req types.RequestEndBlock) *ReqRes { app.mtx.Lock() - resEndBlock := app.Application.EndBlock(height) + res := app.Application.EndBlock(req) app.mtx.Unlock() return app.callback( - types.ToRequestEndBlock(height), - types.ToResponseEndBlock(resEndBlock), + types.ToRequestEndBlock(req), + types.ToResponseEndBlock(res), ) } @@ -159,11 +159,11 @@ func (app *localClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, er return &res, nil } -func (app *localClient) SetOptionSync(key string, value string) (log string, err error) { +func (app *localClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { app.mtx.Lock() - log = app.Application.SetOption(key, value) + res := app.Application.SetOption(req) app.mtx.Unlock() - return log, nil + return &res, nil } func (app *localClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { @@ -194,23 +194,23 @@ func (app *localClient) CommitSync() (*types.ResponseCommit, error) { return &res, nil } -func (app *localClient) InitChainSync(params types.RequestInitChain) error { +func (app *localClient) InitChainSync(req types.RequestInitChain) (*types.ResponseInitChain, error) { app.mtx.Lock() - app.Application.InitChain(params) + res := app.Application.InitChain(req) app.mtx.Unlock() - return nil + return &res, nil } -func (app *localClient) BeginBlockSync(params types.RequestBeginBlock) error { +func (app *localClient) BeginBlockSync(req types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { app.mtx.Lock() - app.Application.BeginBlock(params) + res := app.Application.BeginBlock(req) app.mtx.Unlock() - return nil + return &res, nil } -func (app *localClient) EndBlockSync(height uint64) (*types.ResponseEndBlock, error) { +func (app *localClient) EndBlockSync(req types.RequestEndBlock) (*types.ResponseEndBlock, error) { app.mtx.Lock() - res := app.Application.EndBlock(height) + res := app.Application.EndBlock(req) app.mtx.Unlock() return &res, nil } diff --git a/client/socket_client.go b/client/socket_client.go index 716ef451..84377a05 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -239,8 +239,8 @@ func (cli *socketClient) InfoAsync(req types.RequestInfo) *ReqRes { return cli.queueRequest(types.ToRequestInfo(req)) } -func (cli *socketClient) SetOptionAsync(key string, value string) *ReqRes { - return cli.queueRequest(types.ToRequestSetOption(key, value)) +func (cli *socketClient) SetOptionAsync(req types.RequestSetOption) *ReqRes { + return cli.queueRequest(types.ToRequestSetOption(req)) } func (cli *socketClient) DeliverTxAsync(tx []byte) *ReqRes { @@ -259,16 +259,16 @@ func (cli *socketClient) CommitAsync() *ReqRes { return cli.queueRequest(types.ToRequestCommit()) } -func (cli *socketClient) InitChainAsync(params types.RequestInitChain) *ReqRes { - return cli.queueRequest(types.ToRequestInitChain(params)) +func (cli *socketClient) InitChainAsync(req types.RequestInitChain) *ReqRes { + return cli.queueRequest(types.ToRequestInitChain(req)) } -func (cli *socketClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes { - return cli.queueRequest(types.ToRequestBeginBlock(params)) +func (cli *socketClient) BeginBlockAsync(req types.RequestBeginBlock) *ReqRes { + return cli.queueRequest(types.ToRequestBeginBlock(req)) } -func (cli *socketClient) EndBlockAsync(height uint64) *ReqRes { - return cli.queueRequest(types.ToRequestEndBlock(height)) +func (cli *socketClient) EndBlockAsync(req types.RequestEndBlock) *ReqRes { + return cli.queueRequest(types.ToRequestEndBlock(req)) } //---------------------------------------- @@ -294,13 +294,10 @@ func (cli *socketClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, e return reqres.Response.GetInfo(), cli.Error() } -func (cli *socketClient) SetOptionSync(key string, value string) (log string, err error) { - reqres := cli.queueRequest(types.ToRequestSetOption(key, value)) +func (cli *socketClient) SetOptionSync(req types.RequestSetOption) (*types.ResponseSetOption, error) { + reqres := cli.queueRequest(types.ToRequestSetOption(req)) cli.FlushSync() - if err := cli.Error(); err != nil { - return "", err - } - return reqres.Response.GetSetOption().Log, nil + return reqres.Response.GetSetOption(), cli.Error() } func (cli *socketClient) DeliverTxSync(tx []byte) (*types.ResponseDeliverTx, error) { @@ -327,20 +324,20 @@ func (cli *socketClient) CommitSync() (*types.ResponseCommit, error) { return reqres.Response.GetCommit(), cli.Error() } -func (cli *socketClient) InitChainSync(params types.RequestInitChain) error { - cli.queueRequest(types.ToRequestInitChain(params)) +func (cli *socketClient) InitChainSync(req types.RequestInitChain) (*types.ResponseInitChain, error) { + reqres := cli.queueRequest(types.ToRequestInitChain(req)) cli.FlushSync() - return cli.Error() + return reqres.Response.GetInitChain(), cli.Error() } -func (cli *socketClient) BeginBlockSync(params types.RequestBeginBlock) error { - cli.queueRequest(types.ToRequestBeginBlock(params)) +func (cli *socketClient) BeginBlockSync(req types.RequestBeginBlock) (*types.ResponseBeginBlock, error) { + reqres := cli.queueRequest(types.ToRequestBeginBlock(req)) cli.FlushSync() - return cli.Error() + return reqres.Response.GetBeginBlock(), cli.Error() } -func (cli *socketClient) EndBlockSync(height uint64) (*types.ResponseEndBlock, error) { - reqres := cli.queueRequest(types.ToRequestEndBlock(height)) +func (cli *socketClient) EndBlockSync(req types.RequestEndBlock) (*types.ResponseEndBlock, error) { + reqres := cli.queueRequest(types.ToRequestEndBlock(req)) cli.FlushSync() return reqres.Response.GetEndBlock(), cli.Error() } diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index e3f0daec..d27bf24b 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -355,12 +355,13 @@ func cmdInfo(cmd *cobra.Command, args []string) error { // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) error { - resLog, err := client.SetOptionSync(args[0], args[1]) + key, val := args[0], args[1] + res, err := client.SetOptionSync(types.RequestSetOption{key, val}) if err != nil { return err } printResponse(cmd, args, response{ - Log: resLog, + Log: res.Log, }) return nil } diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go deleted file mode 100644 index 8a031da2..00000000 --- a/example/block_aware/block_aware_app.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "flag" - "os" - - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" -) - -func main() { - - addrPtr := flag.String("addr", "tcp://0.0.0.0:46658", "Listen address") - abciPtr := flag.String("abci", "socket", "socket | grpc") - flag.Parse() - - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Start the listener - srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - srv.SetLogger(logger.With("module", "abci-server")) - if _, err := srv.Start(); err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - -} - -type ChainAwareApplication struct { - types.BaseApplication - - beginCount int - endCount int -} - -func NewChainAwareApplication() *ChainAwareApplication { - return &ChainAwareApplication{} -} - -func (app *ChainAwareApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { - return types.ResponseQuery{ - Value: []byte(cmn.Fmt("%d,%d", app.beginCount, app.endCount)), - } -} - -func (app *ChainAwareApplication) BeginBlock(reqBeginBlock types.RequestBeginBlock) { - app.beginCount++ -} - -func (app *ChainAwareApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { - app.endCount++ - return -} diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go deleted file mode 100644 index 2777ce1a..00000000 --- a/example/block_aware/block_aware_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -import ( - "strconv" - "strings" - "testing" - - abcicli "github.com/tendermint/abci/client" - "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" - "github.com/tendermint/tmlibs/log" -) - -func TestChainAware(t *testing.T) { - app := NewChainAwareApplication() - - // Start the listener - srv, err := server.NewServer("unix://test.sock", "socket", app) - if err != nil { - t.Fatal(err) - } - srv.SetLogger(log.TestingLogger().With("module", "abci-server")) - if _, err := srv.Start(); err != nil { - t.Fatal(err.Error()) - } - defer srv.Stop() - - // Connect to the socket - client := abcicli.NewSocketClient("unix://test.sock", false) - client.SetLogger(log.TestingLogger().With("module", "abci-client")) - if _, err := client.Start(); err != nil { - t.Fatalf("Error starting socket client: %v", err.Error()) - } - defer client.Stop() - - n := uint64(5) - hash := []byte("fake block hash") - header := &types.Header{} - for i := uint64(0); i < n; i++ { - client.BeginBlockSync(types.RequestBeginBlock{hash, header}) - client.EndBlockSync(i) - client.CommitSync() - } - - r := app.Query(types.RequestQuery{}) - spl := strings.Split(string(r.Value), ",") - if len(spl) != 2 { - t.Fatal("expected %d,%d ; got %s", n, n, string(r.Value)) - } - beginCount, _ := strconv.Atoi(spl[0]) - endCount, _ := strconv.Atoi(spl[1]) - if uint64(beginCount) != n { - t.Fatalf("expected beginCount of %d, got %d", n, beginCount) - } else if uint64(endCount) != n { - t.Fatalf("expected endCount of %d, got %d", n, endCount) - } -} diff --git a/example/counter/counter.go b/example/counter/counter.go index 65cac4a0..a7b09027 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -24,11 +24,12 @@ func (app *CounterApplication) Info(req types.RequestInfo) types.ResponseInfo { return types.ResponseInfo{Data: cmn.Fmt("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)} } -func (app *CounterApplication) SetOption(key string, value string) (log string) { +func (app *CounterApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption { + key, value := req.Key, req.Value if key == "serial" && value == "on" { app.serial = true } - return "" + return types.ResponseSetOption{} } func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index a4edacac..65d524cf 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -10,6 +10,8 @@ import ( dbm "github.com/tendermint/tmlibs/db" ) +var _ types.Application = (*DummyApplication)(nil) + type DummyApplication struct { types.BaseApplication diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 798da720..b7aef6a8 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -93,7 +93,7 @@ func TestPersistentDummyInfo(t *testing.T) { Height: uint64(height), } dummy.BeginBlock(types.RequestBeginBlock{hash, header}) - dummy.EndBlock(height) + dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() resInfo = dummy.Info(types.RequestInfo{}) @@ -182,7 +182,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ t.Fatal(r) } } - resEndBlock := dummy.EndBlock(height) + resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() valsEqual(t, diff, resEndBlock.Diffs) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 8fa11282..ed284529 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -21,6 +21,8 @@ const ( //----------------------------------------- +var _ types.Application = (*PersistentDummyApplication)(nil) + type PersistentDummyApplication struct { app *DummyApplication @@ -50,15 +52,15 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { app.logger = l } -func (app *PersistentDummyApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - resInfo = app.app.Info(req) - resInfo.LastBlockHeight = app.app.state.LatestVersion() - resInfo.LastBlockAppHash = app.app.state.Hash() - return resInfo +func (app *PersistentDummyApplication) Info(req types.RequestInfo) types.ResponseInfo { + res := app.app.Info(req) + res.LastBlockHeight = app.app.state.LatestVersion() + res.LastBlockAppHash = app.app.state.Hash() + return res } -func (app *PersistentDummyApplication) SetOption(key string, value string) (log string) { - return app.app.SetOption(key, value) +func (app *PersistentDummyApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption { + return app.app.SetOption(req) } // tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes @@ -102,23 +104,25 @@ func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types. } // Save the validators in the merkle tree -func (app *PersistentDummyApplication) InitChain(params types.RequestInitChain) { - for _, v := range params.Validators { +func (app *PersistentDummyApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain { + for _, v := range req.Validators { r := app.updateValidator(v) if r.IsErr() { app.logger.Error("Error updating validators", "r", r) } } + return types.ResponseInitChain{} } // Track the block hash and header information -func (app *PersistentDummyApplication) BeginBlock(params types.RequestBeginBlock) { +func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { // reset valset changes app.changes = make([]*types.Validator, 0) + return types.ResponseBeginBlock{} } // Update the validator set -func (app *PersistentDummyApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) { +func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { return types.ResponseEndBlock{Diffs: app.changes} } diff --git a/server/socket_server.go b/server/socket_server.go index 68a21322..c88180d4 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -168,33 +168,32 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types case *types.Request_Flush: responses <- types.ToResponseFlush() case *types.Request_Info: - resInfo := s.app.Info(*r.Info) - responses <- types.ToResponseInfo(resInfo) + res := s.app.Info(*r.Info) + responses <- types.ToResponseInfo(res) case *types.Request_SetOption: - so := r.SetOption - logStr := s.app.SetOption(so.Key, so.Value) - responses <- types.ToResponseSetOption(logStr) + res := s.app.SetOption(*r.SetOption) + responses <- types.ToResponseSetOption(res) case *types.Request_DeliverTx: res := s.app.DeliverTx(r.DeliverTx.Tx) - responses <- types.ToResponseDeliverTx(res.Code, res.Data, res.Log, res.Tags) + responses <- types.ToResponseDeliverTx(res) case *types.Request_CheckTx: res := s.app.CheckTx(r.CheckTx.Tx) - responses <- types.ToResponseCheckTx(res.Code, res.Data, res.Log) + responses <- types.ToResponseCheckTx(res) case *types.Request_Commit: res := s.app.Commit() - responses <- types.ToResponseCommit(res.Code, res.Data, res.Log) + responses <- types.ToResponseCommit(res) case *types.Request_Query: - resQuery := s.app.Query(*r.Query) - responses <- types.ToResponseQuery(resQuery) + res := s.app.Query(*r.Query) + responses <- types.ToResponseQuery(res) case *types.Request_InitChain: - s.app.InitChain(*r.InitChain) - responses <- types.ToResponseInitChain() + res := s.app.InitChain(*r.InitChain) + responses <- types.ToResponseInitChain(res) case *types.Request_BeginBlock: - s.app.BeginBlock(*r.BeginBlock) - responses <- types.ToResponseBeginBlock() + res := s.app.BeginBlock(*r.BeginBlock) + responses <- types.ToResponseBeginBlock(res) case *types.Request_EndBlock: - resEndBlock := s.app.EndBlock(r.EndBlock.Height) - responses <- types.ToResponseEndBlock(resEndBlock) + res := s.app.EndBlock(*r.EndBlock) + responses <- types.ToResponseEndBlock(res) default: responses <- types.ToResponseException("Unknown request") } diff --git a/types/application.go b/types/application.go index ed9b0d20..c36e58f0 100644 --- a/types/application.go +++ b/types/application.go @@ -5,22 +5,24 @@ import ( ) // Application is an interface that enables any finite, deterministic state machine -// to be driven by a blockchain-based replication engine via the ABCI +// to be driven by a blockchain-based replication engine via the ABCI. +// All methods take a RequestXxx argument and return a ResponseXxx argument, +// except CheckTx/DeliverTx, which take `tx []byte`, and `Commit`, which takes nothing. type Application interface { // Info/Query Connection - Info(RequestInfo) ResponseInfo // Return application info - SetOption(key string, value string) (log string) // Set application option - Query(RequestQuery) ResponseQuery // Query for state + Info(RequestInfo) ResponseInfo // Return application info + SetOption(RequestSetOption) ResponseSetOption // Set application option + Query(RequestQuery) ResponseQuery // Query for state // Mempool Connection CheckTx(tx []byte) ResponseCheckTx // Validate a tx for the mempool // Consensus Connection - InitChain(RequestInitChain) // Initialize blockchain with validators and other info from TendermintCore - BeginBlock(RequestBeginBlock) // Signals the beginning of a block - DeliverTx(tx []byte) ResponseDeliverTx // Deliver a tx for full processing - EndBlock(height uint64) ResponseEndBlock // Signals the end of a block, returns changes to the validator set - Commit() ResponseCommit // Commit the state and return the application Merkle root hash + InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain with validators and other info from TendermintCore + BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block + DeliverTx(tx []byte) ResponseDeliverTx // Deliver a tx for full processing + EndBlock(RequestEndBlock) ResponseEndBlock // Signals the end of a block, returns changes to the validator set + Commit() ResponseCommit // Commit the state and return the application Merkle root hash } //------------------------------------ @@ -48,7 +50,8 @@ func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*Respon } func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { - return &ResponseSetOption{app.app.SetOption(req.Key, req.Value)}, nil + resSetOption := app.app.SetOption(*req) + return &resSetOption, nil } func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { @@ -72,16 +75,16 @@ func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*Re } func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - app.app.InitChain(*req) - return &ResponseInitChain{}, nil // NOTE: empty return + resInitChain := app.app.InitChain(*req) + return &resInitChain, nil } func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { - app.app.BeginBlock(*req) - return &ResponseBeginBlock{}, nil // NOTE: empty return + resBeginBlock := app.app.BeginBlock(*req) + return &resBeginBlock, nil } func (app *GRPCApplication) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { - resEndBlock := app.app.EndBlock(req.Height) + resEndBlock := app.app.EndBlock(*req) return &resEndBlock, nil } diff --git a/types/base_app.go b/types/base_app.go index 0086685b..404678e9 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -11,8 +11,8 @@ func (BaseApplication) Info(req RequestInfo) ResponseInfo { return ResponseInfo{} } -func (BaseApplication) SetOption(key string, value string) (log string) { - return "" +func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { + return ResponseSetOption{} } func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { @@ -31,12 +31,14 @@ func (BaseApplication) Query(req RequestQuery) ResponseQuery { return ResponseQuery{Code: CodeType_OK} } -func (BaseApplication) InitChain(req RequestInitChain) { +func (BaseApplication) InitChain(req RequestInitChain) ResponseInitChain { + return ResponseInitChain{} } -func (BaseApplication) BeginBlock(req RequestBeginBlock) { +func (BaseApplication) BeginBlock(req RequestBeginBlock) ResponseBeginBlock { + return ResponseBeginBlock{} } -func (BaseApplication) EndBlock(height uint64) ResponseEndBlock { +func (BaseApplication) EndBlock(req RequestEndBlock) ResponseEndBlock { return ResponseEndBlock{} } diff --git a/types/messages.go b/types/messages.go index 298f17ba..77ad538e 100644 --- a/types/messages.go +++ b/types/messages.go @@ -25,21 +25,21 @@ func ToRequestInfo(req RequestInfo) *Request { } } -func ToRequestSetOption(key string, value string) *Request { +func ToRequestSetOption(req RequestSetOption) *Request { return &Request{ - Value: &Request_SetOption{&RequestSetOption{key, value}}, + Value: &Request_SetOption{&req}, } } -func ToRequestDeliverTx(txBytes []byte) *Request { +func ToRequestDeliverTx(tx []byte) *Request { return &Request{ - Value: &Request_DeliverTx{&RequestDeliverTx{txBytes}}, + Value: &Request_DeliverTx{&RequestDeliverTx{tx}}, } } -func ToRequestCheckTx(txBytes []byte) *Request { +func ToRequestCheckTx(tx []byte) *Request { return &Request{ - Value: &Request_CheckTx{&RequestCheckTx{txBytes}}, + Value: &Request_CheckTx{&RequestCheckTx{tx}}, } } @@ -67,9 +67,9 @@ func ToRequestBeginBlock(req RequestBeginBlock) *Request { } } -func ToRequestEndBlock(height uint64) *Request { +func ToRequestEndBlock(req RequestEndBlock) *Request { return &Request{ - Value: &Request_EndBlock{&RequestEndBlock{height}}, + Value: &Request_EndBlock{&req}, } } @@ -93,57 +93,57 @@ func ToResponseFlush() *Response { } } -func ToResponseInfo(resInfo ResponseInfo) *Response { +func ToResponseInfo(res ResponseInfo) *Response { return &Response{ - Value: &Response_Info{&resInfo}, + Value: &Response_Info{&res}, } } -func ToResponseSetOption(log string) *Response { +func ToResponseSetOption(res ResponseSetOption) *Response { return &Response{ - Value: &Response_SetOption{&ResponseSetOption{log}}, + Value: &Response_SetOption{&res}, } } -func ToResponseDeliverTx(code CodeType, data []byte, log string, tags []*KVPair) *Response { +func ToResponseDeliverTx(res ResponseDeliverTx) *Response { return &Response{ - Value: &Response_DeliverTx{&ResponseDeliverTx{code, data, log, tags}}, + Value: &Response_DeliverTx{&res}, } } -func ToResponseCheckTx(code CodeType, data []byte, log string) *Response { +func ToResponseCheckTx(res ResponseCheckTx) *Response { return &Response{ - Value: &Response_CheckTx{&ResponseCheckTx{code, data, log}}, + Value: &Response_CheckTx{&res}, } } -func ToResponseCommit(code CodeType, data []byte, log string) *Response { +func ToResponseCommit(res ResponseCommit) *Response { return &Response{ - Value: &Response_Commit{&ResponseCommit{code, data, log}}, + Value: &Response_Commit{&res}, } } -func ToResponseQuery(resQuery ResponseQuery) *Response { +func ToResponseQuery(res ResponseQuery) *Response { return &Response{ - Value: &Response_Query{&resQuery}, + Value: &Response_Query{&res}, } } -func ToResponseInitChain() *Response { +func ToResponseInitChain(res ResponseInitChain) *Response { return &Response{ - Value: &Response_InitChain{&ResponseInitChain{}}, + Value: &Response_InitChain{&res}, } } -func ToResponseBeginBlock() *Response { +func ToResponseBeginBlock(res ResponseBeginBlock) *Response { return &Response{ - Value: &Response_BeginBlock{&ResponseBeginBlock{}}, + Value: &Response_BeginBlock{&res}, } } -func ToResponseEndBlock(resEndBlock ResponseEndBlock) *Response { +func ToResponseEndBlock(res ResponseEndBlock) *Response { return &Response{ - Value: &Response_EndBlock{&resEndBlock}, + Value: &Response_EndBlock{&res}, } } From fb612e5a7b83b8a008ed813974c452726b4a1da9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 19:52:06 +0000 Subject: [PATCH 348/545] fixup tests --- Makefile | 14 ++++++++++---- circle.yml | 2 +- cmd/abci-cli/abci-cli.go | 4 ++-- cmd/abci-cli/main.go | 11 ++++++++++- test.sh | 10 +++++----- tests/test_app/app.go | 2 +- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 57ab4052..ab9223f6 100644 --- a/Makefile +++ b/Makefile @@ -36,12 +36,18 @@ dist: @ bash scripts/publish.sh # test.sh requires that we run the installed cmds, must not be out of date -test: install +test: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; - @ echo "==> Running unit tests" + @ echo "==> Running go test" @ go test $(PACKAGES) - @ echo "==> Running integration tests (./tests)" - @ bash tests/test.sh + +test_race: + @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @ echo "==> Running go test --race" + @go test -v -race $(PACKAGES) + +test_integrations: + @ bash test.sh fmt: @ go fmt ./... diff --git a/circle.yml b/circle.yml index 45987363..c6904fae 100644 --- a/circle.yml +++ b/circle.yml @@ -16,7 +16,7 @@ checkout: test: override: - - cd $REPO && make get_vendor_deps && make metalinter_test && bash ./test.sh + - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations post: - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index d27bf24b..d6e95d96 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -96,10 +96,10 @@ var RootCmd = &cobra.Command{ }, } -func Execute() { +func Execute() error { addGlobalFlags() addCommands() - RootCmd.Execute() + return RootCmd.Execute() } func addGlobalFlags() { diff --git a/cmd/abci-cli/main.go b/cmd/abci-cli/main.go index 736ef310..a927e7ed 100644 --- a/cmd/abci-cli/main.go +++ b/cmd/abci-cli/main.go @@ -1,5 +1,14 @@ package main +import ( + "fmt" + "os" +) + func main() { - Execute() + err := Execute() + if err != nil { + fmt.Print(err) + os.Exit(1) + } } diff --git a/test.sh b/test.sh index 136f60e2..33839c06 100755 --- a/test.sh +++ b/test.sh @@ -5,11 +5,11 @@ echo "" > coverage.txt echo "==> Running unit tests" for d in $(go list ./... | grep -v vendor); do - go test -race -coverprofile=profile.out -covermode=atomic "$d" - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi done echo "==> Running integration tests (./tests)" diff --git a/tests/test_app/app.go b/tests/test_app/app.go index c869fe83..59d7aec4 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -48,7 +48,7 @@ func startClient(abciType string) abcicli.Client { } func setOption(client abcicli.Client, key, value string) { - _, err := client.SetOptionSync(key, value) + _, err := client.SetOptionSync(types.RequestSetOption{key, value}) if err != nil { panicf("setting %v=%v: \nerr: %v", key, value, err) } From 7dc5b746ac7bf18d49c61154de81fc99909ef81c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 20:10:11 +0000 Subject: [PATCH 349/545] types: add gas and fee fields to CheckTx --- types/types.pb.go | 240 +++++++++++++++++++++++++--------------------- types/types.proto | 2 + 2 files changed, 131 insertions(+), 111 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index 0cd97679..7b278ea2 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1,5 +1,6 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. +// Code generated by protoc-gen-go. // source: types/types.proto +// DO NOT EDIT! /* Package types is a generated protocol buffer package. @@ -1361,6 +1362,8 @@ type ResponseCheckTx struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Gas uint64 `protobuf:"varint,4,opt,name=gas" json:"gas,omitempty"` + Fee uint64 `protobuf:"varint,5,opt,name=fee" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1389,6 +1392,20 @@ func (m *ResponseCheckTx) GetLog() string { return "" } +func (m *ResponseCheckTx) GetGas() uint64 { + if m != nil { + return m.Gas + } + return 0 +} + +func (m *ResponseCheckTx) GetFee() uint64 { + if m != nil { + return m.Fee + } + return 0 +} + type ResponseQuery struct { Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` @@ -2149,114 +2166,115 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1736 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcb, 0x6e, 0xdb, 0xcc, - 0x15, 0x36, 0x25, 0xea, 0x76, 0x2c, 0xcb, 0xf4, 0x58, 0xb6, 0x65, 0xa5, 0x8b, 0x84, 0x45, 0x1a, - 0x3b, 0x4d, 0x9d, 0xd6, 0x41, 0x8a, 0xb8, 0x29, 0x0a, 0xf8, 0x16, 0x5b, 0x08, 0xea, 0xb8, 0xb4, - 0x93, 0x4d, 0x0b, 0x08, 0xb4, 0x38, 0x92, 0xa6, 0x96, 0x86, 0x0c, 0x39, 0x74, 0xe4, 0xee, 0xba, - 0xcf, 0xbe, 0x8f, 0x50, 0xa0, 0xcb, 0x02, 0x7d, 0x85, 0x02, 0xff, 0xfd, 0xf2, 0x44, 0x3f, 0xe6, - 0xc2, 0xab, 0xa9, 0xe0, 0x5f, 0x64, 0x23, 0xf0, 0x5c, 0xbe, 0x99, 0x33, 0x33, 0xe7, 0x7c, 0x73, - 0x46, 0xb0, 0xc2, 0x6e, 0x3d, 0x1c, 0x3c, 0x15, 0xbf, 0x3b, 0x9e, 0xef, 0x32, 0x17, 0x55, 0x84, - 0x60, 0xfe, 0x5f, 0x87, 0x9a, 0x85, 0xdf, 0x87, 0x38, 0x60, 0x68, 0x0b, 0x74, 0x3c, 0x18, 0xbb, - 0x1d, 0xed, 0xbe, 0xb6, 0xb5, 0xb8, 0x8b, 0x76, 0xa4, 0xbb, 0xb2, 0x1e, 0x0f, 0xc6, 0xee, 0xe9, - 0x82, 0x25, 0x3c, 0xd0, 0xaf, 0xa1, 0x32, 0x9c, 0x84, 0xc1, 0xb8, 0x53, 0x12, 0xae, 0xab, 0x59, - 0xd7, 0x57, 0xdc, 0x74, 0xba, 0x60, 0x49, 0x1f, 0x3e, 0x2c, 0xa1, 0x43, 0xb7, 0x53, 0x2e, 0x1a, - 0xb6, 0x47, 0x87, 0x62, 0x58, 0xee, 0x81, 0x5e, 0x00, 0x04, 0x98, 0xf5, 0x5d, 0x8f, 0x11, 0x97, - 0x76, 0x74, 0xe1, 0xbf, 0x91, 0xf5, 0xbf, 0xc0, 0xec, 0x8d, 0x30, 0x9f, 0x2e, 0x58, 0x8d, 0x20, - 0x12, 0x38, 0xd2, 0xc1, 0x13, 0x72, 0x83, 0xfd, 0x3e, 0x9b, 0x75, 0x2a, 0x45, 0xc8, 0x23, 0x69, - 0xbf, 0x9c, 0x71, 0xa4, 0x13, 0x09, 0x68, 0x17, 0xea, 0x83, 0x31, 0x1e, 0x5c, 0x73, 0x5c, 0x55, - 0xe0, 0xd6, 0xb2, 0xb8, 0x43, 0x6e, 0x15, 0xa8, 0xda, 0x40, 0x7e, 0xa2, 0x1d, 0xa8, 0x0e, 0xdc, - 0xe9, 0x94, 0xb0, 0x4e, 0x4d, 0x20, 0xda, 0x39, 0x84, 0xb0, 0x9d, 0x2e, 0x58, 0xca, 0x8b, 0x6f, - 0xd7, 0xfb, 0x10, 0xfb, 0xb7, 0x9d, 0x7a, 0xd1, 0x76, 0xfd, 0x85, 0x9b, 0xf8, 0x76, 0x09, 0x1f, - 0xbe, 0x14, 0x42, 0x09, 0xeb, 0x0f, 0xc6, 0x36, 0xa1, 0x9d, 0x46, 0xd1, 0x52, 0x7a, 0x94, 0xb0, - 0x43, 0x6e, 0xe6, 0x4b, 0x21, 0x91, 0x80, 0x5e, 0xc2, 0xe2, 0x15, 0x1e, 0x11, 0xda, 0xbf, 0x9a, - 0xb8, 0x83, 0xeb, 0x0e, 0x08, 0x68, 0x27, 0x0b, 0x3d, 0xe0, 0x0e, 0x07, 0xdc, 0x7e, 0xba, 0x60, - 0xc1, 0x55, 0x2c, 0xa1, 0xe7, 0xd0, 0xc0, 0xd4, 0x51, 0xd0, 0x45, 0x01, 0x5d, 0xcf, 0x65, 0x00, - 0x75, 0x22, 0x60, 0x1d, 0xab, 0xef, 0x83, 0x1a, 0x54, 0x6e, 0xec, 0x49, 0x88, 0xcd, 0x47, 0xb0, - 0x98, 0xca, 0x14, 0xd4, 0x81, 0xda, 0x14, 0x07, 0x81, 0x3d, 0xc2, 0x22, 0x9d, 0x1a, 0x56, 0x24, - 0x9a, 0x2d, 0x68, 0xa6, 0xf3, 0x24, 0x05, 0xe4, 0xb9, 0xc0, 0x81, 0x37, 0xd8, 0x0f, 0x78, 0x02, - 0x28, 0xa0, 0x12, 0xcd, 0x3f, 0x80, 0x91, 0x4f, 0x02, 0x64, 0x40, 0xf9, 0x1a, 0xdf, 0x2a, 0x4f, - 0xfe, 0x89, 0xda, 0x2a, 0x20, 0x91, 0x9a, 0x0d, 0x4b, 0x45, 0x67, 0xc6, 0xd8, 0x38, 0x0d, 0x50, - 0x0b, 0x4a, 0x6c, 0x26, 0xa0, 0x4d, 0xab, 0xc4, 0x66, 0xe6, 0x7d, 0x68, 0x65, 0x8f, 0xfc, 0x8e, - 0x87, 0x13, 0x87, 0x2e, 0xce, 0x0c, 0x21, 0xd0, 0x1d, 0x9b, 0xd9, 0xca, 0x43, 0x7c, 0x73, 0x9d, - 0x67, 0xb3, 0xb1, 0x9a, 0x5e, 0x7c, 0xa3, 0x75, 0xa8, 0x8e, 0x31, 0x19, 0x8d, 0x99, 0xa8, 0x01, - 0xdd, 0x52, 0x12, 0x8f, 0xd5, 0xf3, 0xdd, 0x1b, 0x2c, 0x52, 0xbd, 0x6e, 0x49, 0xc1, 0x5c, 0x86, - 0xa5, 0x4c, 0x22, 0x99, 0x47, 0x71, 0xf0, 0xf1, 0xc1, 0xa3, 0xdf, 0x02, 0xdc, 0xd8, 0x13, 0xe2, - 0xd8, 0xcc, 0xf5, 0x83, 0x8e, 0x76, 0xbf, 0xbc, 0xb5, 0xb8, 0x6b, 0xa8, 0xf3, 0x7a, 0x17, 0x19, - 0xac, 0x94, 0x8f, 0x79, 0x06, 0x2b, 0x77, 0x72, 0x80, 0x47, 0x3b, 0xb6, 0x83, 0x71, 0xb4, 0x02, - 0xfe, 0x8d, 0x1e, 0xf2, 0x68, 0x6d, 0x07, 0xfb, 0xaa, 0xba, 0x97, 0xd4, 0xb0, 0xa7, 0x42, 0x69, - 0x29, 0xa3, 0xb9, 0x0d, 0xcb, 0xb9, 0xc4, 0x48, 0xad, 0x53, 0x4b, 0xaf, 0xd3, 0xfc, 0x58, 0x81, - 0xba, 0x85, 0x03, 0xcf, 0xa5, 0x01, 0x46, 0x2f, 0xa0, 0x81, 0x67, 0x03, 0x2c, 0x6b, 0x5c, 0xcb, - 0xe5, 0xa8, 0xf4, 0x39, 0x8e, 0xec, 0x3c, 0xbf, 0x63, 0x67, 0xb4, 0xad, 0xf8, 0x29, 0x4f, 0x3a, - 0x0a, 0x94, 0x26, 0xa8, 0x27, 0x11, 0x41, 0x95, 0x73, 0x05, 0x2a, 0x7d, 0x73, 0x0c, 0xb5, 0xad, - 0x18, 0x4a, 0x2f, 0x1c, 0x38, 0x43, 0x51, 0x7b, 0x19, 0x8a, 0xaa, 0x14, 0x86, 0x3f, 0x87, 0xa3, - 0xf6, 0x32, 0x1c, 0x55, 0x2d, 0x84, 0xce, 0x21, 0xa9, 0x67, 0x29, 0x92, 0xaa, 0xe5, 0x6a, 0x53, - 0x02, 0x0b, 0x58, 0xea, 0x69, 0xcc, 0x52, 0xf5, 0x1c, 0xaf, 0x29, 0x48, 0x9e, 0xa6, 0x9e, 0x44, - 0x34, 0xd5, 0x28, 0xdc, 0xb4, 0x1c, 0x4f, 0xed, 0x65, 0x78, 0x0a, 0x0a, 0x97, 0x33, 0x87, 0xa8, - 0xfe, 0x98, 0x25, 0x2a, 0xc9, 0x36, 0x9b, 0x39, 0xec, 0x5c, 0xa6, 0xfa, 0x7d, 0x9a, 0xa9, 0x9a, - 0x39, 0x7e, 0x54, 0xb9, 0xf0, 0x49, 0xaa, 0xda, 0xe6, 0x95, 0x90, 0xcb, 0x34, 0x5e, 0x8b, 0xd8, - 0xf7, 0x5d, 0x5f, 0x71, 0x89, 0x14, 0xcc, 0x2d, 0x5e, 0xf1, 0x49, 0x7e, 0x7d, 0x82, 0xd6, 0x44, - 0xd5, 0xa6, 0xb2, 0xcb, 0xfc, 0x97, 0x96, 0x60, 0x05, 0xb3, 0xa5, 0xd9, 0xa2, 0xa1, 0xd8, 0x22, - 0xc5, 0x76, 0xa5, 0x0c, 0xdb, 0xa1, 0xc7, 0xb0, 0x32, 0xb1, 0x03, 0x26, 0x97, 0xd9, 0xcf, 0xd0, - 0xc7, 0x32, 0x37, 0xc8, 0xf5, 0x49, 0x1e, 0xf9, 0x0d, 0xac, 0xa6, 0x7c, 0x6d, 0xcf, 0xeb, 0x8b, - 0xa2, 0xd6, 0x45, 0x51, 0x1b, 0xb1, 0xf7, 0xbe, 0xe7, 0x9d, 0xda, 0xc1, 0xd8, 0x7c, 0x98, 0xac, - 0x3f, 0xc3, 0xa4, 0x13, 0x77, 0x14, 0x31, 0xe9, 0xc4, 0x1d, 0x99, 0xff, 0xd4, 0x12, 0xbf, 0x84, - 0x35, 0x7f, 0x09, 0xfa, 0xc0, 0x75, 0xe4, 0xf2, 0x5b, 0xbb, 0xcb, 0x6a, 0xe3, 0x0f, 0x5d, 0x07, - 0x5f, 0xde, 0x7a, 0xd8, 0x12, 0xc6, 0x78, 0xa9, 0xa5, 0x14, 0x31, 0xaa, 0x09, 0xca, 0xf1, 0x04, - 0xe8, 0x01, 0xe8, 0xcc, 0x1e, 0x05, 0x1d, 0x5d, 0xb0, 0x57, 0x44, 0x33, 0xaf, 0xdf, 0x9d, 0xdb, - 0xc4, 0xb7, 0x84, 0xc9, 0xfc, 0x1b, 0x27, 0x99, 0x4c, 0x86, 0x7f, 0xc6, 0x00, 0xcc, 0xff, 0x6a, - 0xc9, 0xa1, 0x49, 0x46, 0xff, 0x59, 0x83, 0xb7, 0xa1, 0x42, 0xa8, 0x83, 0x67, 0x62, 0xf4, 0xb2, - 0x25, 0x85, 0xe8, 0x2a, 0x2a, 0x8b, 0x19, 0xb3, 0x57, 0x91, 0x3c, 0x08, 0x29, 0x28, 0xd2, 0x77, - 0x87, 0x82, 0x3c, 0x9a, 0x96, 0x14, 0x52, 0xd4, 0x59, 0xcd, 0x5c, 0x11, 0x2a, 0xe8, 0x5a, 0x12, - 0xf4, 0x5f, 0xf9, 0x35, 0x95, 0xae, 0xe0, 0xcf, 0xb9, 0x23, 0xab, 0xc9, 0x91, 0xc7, 0xb5, 0x6b, - 0xb6, 0x01, 0xdd, 0x2d, 0x4a, 0x79, 0x1d, 0x67, 0xcb, 0x0d, 0xfd, 0x0a, 0x2a, 0x0e, 0x19, 0x0e, - 0xe7, 0x5f, 0x48, 0xd2, 0x6c, 0xfe, 0xbb, 0x04, 0x55, 0x79, 0x9d, 0xa0, 0x4d, 0x4e, 0x6d, 0x36, - 0xa1, 0x7d, 0xe2, 0x44, 0x25, 0x25, 0xe4, 0x9e, 0x93, 0xda, 0x93, 0x52, 0x66, 0x4f, 0x10, 0xe8, - 0x8c, 0x4c, 0xb1, 0xaa, 0x06, 0xf1, 0x8d, 0x36, 0xa0, 0x46, 0xc3, 0x69, 0x9f, 0xcd, 0x02, 0xb1, - 0xdb, 0xba, 0x55, 0xa5, 0xe1, 0xf4, 0x72, 0x16, 0xa0, 0x5d, 0x58, 0x4a, 0xd5, 0x06, 0x71, 0x14, - 0x67, 0xb7, 0x54, 0x68, 0x22, 0xee, 0xde, 0x91, 0xb5, 0x18, 0x57, 0x49, 0xcf, 0x41, 0x5b, 0x20, - 0x8a, 0xa6, 0x2f, 0x79, 0x51, 0x16, 0x53, 0x55, 0xec, 0x5b, 0x8b, 0xeb, 0x15, 0x71, 0xf2, 0xbb, - 0xf2, 0x1e, 0x34, 0xf8, 0x4e, 0x4a, 0x97, 0x9a, 0x70, 0xa9, 0x73, 0x85, 0x30, 0x3e, 0x82, 0xe5, - 0xe4, 0xfe, 0x95, 0x2e, 0x75, 0x39, 0x4a, 0xa2, 0x16, 0x8e, 0x9b, 0x50, 0x8f, 0x8b, 0xb6, 0x21, - 0x3c, 0x6a, 0xb6, 0xaa, 0xd5, 0x1e, 0xd4, 0x54, 0x88, 0x85, 0x77, 0xf5, 0x63, 0xa8, 0x78, 0xb6, - 0xcf, 0x02, 0x75, 0x27, 0x46, 0x94, 0x7d, 0x6e, 0xfb, 0xbc, 0x49, 0x52, 0x37, 0xb6, 0x74, 0x31, - 0xf7, 0x60, 0x29, 0xa3, 0xe7, 0x99, 0xc8, 0x5c, 0x66, 0x4f, 0xd4, 0x6d, 0x2d, 0x85, 0x78, 0x9a, - 0x52, 0x32, 0x8d, 0xb9, 0x07, 0x8d, 0xf8, 0x0c, 0xf9, 0xb1, 0x78, 0xe1, 0xd5, 0x6b, 0xd5, 0x76, - 0x35, 0x2d, 0x25, 0x89, 0xc4, 0x76, 0x3f, 0xa8, 0xb6, 0x41, 0xb7, 0xa4, 0x60, 0xfe, 0x47, 0x83, - 0xaa, 0x2c, 0xe9, 0x82, 0x66, 0xed, 0x77, 0xa2, 0x8b, 0x09, 0x71, 0x9f, 0x87, 0x2d, 0x70, 0xad, - 0xf8, 0x81, 0x20, 0x41, 0x3b, 0x22, 0x85, 0x1b, 0xc2, 0x8b, 0x7f, 0xa2, 0x07, 0xd0, 0x94, 0x90, - 0x80, 0xf9, 0x84, 0x46, 0xc9, 0xbb, 0x28, 0x74, 0x17, 0x42, 0xc5, 0x0f, 0x45, 0xba, 0x10, 0xca, - 0x44, 0x36, 0x94, 0xad, 0xba, 0x50, 0xf4, 0x28, 0x33, 0xef, 0x81, 0x2e, 0xc6, 0x01, 0xa8, 0x5e, - 0x5c, 0x5a, 0xbd, 0xb3, 0x13, 0x63, 0x01, 0xd5, 0xa0, 0xdc, 0x3b, 0xbb, 0x34, 0xb4, 0xc7, 0xff, - 0xab, 0x40, 0x3d, 0xaa, 0x1b, 0x54, 0x85, 0xd2, 0x9b, 0xd7, 0xc6, 0x02, 0x5a, 0x81, 0xa5, 0x1e, - 0x65, 0xd8, 0xa7, 0xf6, 0xe4, 0x98, 0x5f, 0x0a, 0x86, 0xc6, 0x55, 0xc7, 0x74, 0xe0, 0x3a, 0x84, - 0x8e, 0xa4, 0xaa, 0x84, 0x9a, 0x50, 0x3f, 0xb0, 0x9d, 0x33, 0x97, 0x0e, 0xb0, 0x51, 0x46, 0x06, - 0x34, 0xdf, 0x52, 0x3b, 0x64, 0x63, 0xd7, 0x27, 0xff, 0xc0, 0x8e, 0xa1, 0xa3, 0x35, 0x58, 0xe9, - 0xd1, 0x20, 0x1c, 0x0e, 0xc9, 0x80, 0x60, 0xca, 0x5e, 0x85, 0xd4, 0x09, 0x8c, 0x0a, 0x42, 0xd0, - 0x7a, 0x4b, 0xaf, 0xa9, 0xfb, 0x81, 0xaa, 0x66, 0xca, 0xa8, 0xa2, 0x0e, 0xb4, 0x0f, 0xec, 0x00, - 0x1f, 0x85, 0xde, 0x84, 0x0c, 0x6c, 0x86, 0xf7, 0x1d, 0xc7, 0xc7, 0x41, 0x60, 0x60, 0x3e, 0x08, - 0xb7, 0x64, 0xe7, 0x1e, 0x46, 0x80, 0xcc, 0xf8, 0x18, 0x07, 0xc6, 0x08, 0x6d, 0xc2, 0xda, 0x1d, - 0x8b, 0x98, 0x79, 0x8c, 0x7e, 0x01, 0x9d, 0xbc, 0xe9, 0xc4, 0x0e, 0xce, 0x7d, 0x32, 0xc0, 0x06, - 0x41, 0x6d, 0x30, 0xa4, 0x55, 0xa4, 0x6a, 0x8f, 0x7a, 0x21, 0x33, 0xfe, 0x1e, 0xcd, 0xaf, 0xb4, - 0x6f, 0x42, 0xc6, 0xd5, 0xd7, 0x39, 0xf5, 0xb9, 0x48, 0x07, 0x63, 0x82, 0x36, 0x60, 0x35, 0xa5, - 0xbe, 0xe0, 0xeb, 0xe3, 0xbb, 0x33, 0x4d, 0xe2, 0x95, 0x06, 0x32, 0xa2, 0x36, 0x0b, 0x7d, 0x6c, - 0x50, 0xb4, 0x0e, 0x88, 0x5b, 0xd4, 0x96, 0x44, 0x0b, 0x77, 0xa3, 0x19, 0x94, 0x5e, 0xcd, 0xe0, - 0xe5, 0xd5, 0x93, 0x70, 0x44, 0xa8, 0xf1, 0x1e, 0xad, 0x81, 0x71, 0xe2, 0xde, 0x28, 0xed, 0x31, - 0x65, 0x84, 0xdd, 0x1a, 0x5f, 0x68, 0xa8, 0x0d, 0xcb, 0x89, 0xfa, 0xc4, 0x77, 0x43, 0xcf, 0xf8, - 0x52, 0x43, 0x1b, 0x80, 0x12, 0xed, 0xb9, 0xef, 0x7a, 0x6e, 0x60, 0x4f, 0x8c, 0xaf, 0x34, 0xb4, - 0x0e, 0x2b, 0x27, 0xee, 0x4d, 0x7c, 0x0a, 0x12, 0xf0, 0x75, 0x04, 0x88, 0xf5, 0x7f, 0xc6, 0xd3, - 0x2b, 0xec, 0x1b, 0xdf, 0x68, 0x68, 0x13, 0xda, 0x69, 0x43, 0x3c, 0xd6, 0xb7, 0x9a, 0x8a, 0x28, - 0x36, 0xbd, 0x73, 0x19, 0x36, 0xbe, 0x8b, 0xd4, 0x6a, 0x1f, 0xd4, 0x40, 0xdf, 0x6b, 0x68, 0x15, - 0x5a, 0x89, 0x5a, 0xf8, 0xfe, 0xa0, 0xa1, 0x2e, 0xac, 0x65, 0x94, 0x84, 0x8e, 0xce, 0x79, 0x85, - 0x19, 0x3f, 0x6a, 0xbb, 0x1f, 0x2b, 0xb0, 0xbc, 0x7f, 0x70, 0xd8, 0xdb, 0xf7, 0xe4, 0x04, 0xfc, - 0x42, 0x7f, 0x0a, 0xba, 0x68, 0x59, 0x0a, 0xde, 0xf1, 0xdd, 0xa2, 0xde, 0x19, 0xed, 0x42, 0x45, - 0x74, 0x2e, 0xa8, 0xe8, 0x39, 0xdf, 0x2d, 0x6c, 0xa1, 0xf9, 0x24, 0xb2, 0xb7, 0xb9, 0xfb, 0xaa, - 0xef, 0x16, 0xf5, 0xd1, 0xe8, 0x4f, 0xd0, 0x48, 0x7a, 0x8e, 0x79, 0x6f, 0xfb, 0xee, 0xdc, 0x8e, - 0x9a, 0xe3, 0x93, 0x5e, 0x64, 0xde, 0x0b, 0xbf, 0x3b, 0xb7, 0xad, 0x46, 0x2f, 0xa0, 0x16, 0x35, - 0x12, 0xc5, 0xef, 0xfc, 0xee, 0x9c, 0xce, 0x9a, 0x6f, 0x8f, 0xec, 0x11, 0x8a, 0x9e, 0xef, 0xdd, - 0xc2, 0x66, 0x19, 0x3d, 0x87, 0xaa, 0xba, 0xa3, 0x0b, 0xff, 0x22, 0xe8, 0x16, 0xb7, 0xe4, 0x7c, - 0x91, 0xc9, 0x4b, 0x6f, 0xde, 0xdb, 0xbf, 0x3b, 0xb7, 0xd9, 0x46, 0xfb, 0x00, 0xa9, 0x37, 0xde, - 0xdc, 0x7f, 0x00, 0xba, 0xf3, 0x5b, 0x6e, 0xf4, 0x12, 0xea, 0xc9, 0xb3, 0xae, 0xf8, 0x7f, 0x80, - 0xee, 0xbc, 0xae, 0xfb, 0xaa, 0x2a, 0xfe, 0x62, 0x7a, 0xf6, 0x53, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x59, 0xf7, 0xaf, 0xdb, 0x77, 0x12, 0x00, 0x00, + // 1755 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x49, 0x6f, 0xdb, 0xce, + 0x15, 0x37, 0x25, 0x6a, 0x7b, 0x96, 0x65, 0x7a, 0x2c, 0xdb, 0xb2, 0xd2, 0x43, 0xc2, 0x22, 0x8d, + 0x9d, 0xa6, 0x4e, 0xeb, 0x20, 0x45, 0xdc, 0x14, 0x05, 0xbc, 0xc5, 0x16, 0x82, 0x3a, 0x2e, 0xed, + 0xe4, 0xd2, 0x83, 0x40, 0x8b, 0x23, 0x69, 0x6a, 0x69, 0xc8, 0x90, 0x43, 0x47, 0xee, 0xa9, 0xbd, + 0xe7, 0xde, 0x8f, 0x50, 0xa0, 0xc7, 0x02, 0xfd, 0x0a, 0x05, 0xfe, 0xfb, 0xf2, 0x89, 0xfe, 0x98, + 0x85, 0xab, 0xa9, 0xe0, 0x7f, 0xc8, 0x85, 0x98, 0xb7, 0xcd, 0xbc, 0x99, 0x79, 0xef, 0xf7, 0x1e, + 0x07, 0x56, 0xd8, 0xad, 0x87, 0x83, 0xa7, 0xe2, 0xbb, 0xe3, 0xf9, 0x2e, 0x73, 0x51, 0x45, 0x10, + 0xe6, 0xff, 0x75, 0xa8, 0x59, 0xf8, 0x7d, 0x88, 0x03, 0x86, 0xb6, 0x40, 0xc7, 0x83, 0xb1, 0xdb, + 0xd1, 0xee, 0x6b, 0x5b, 0x8b, 0xbb, 0x68, 0x47, 0xaa, 0x2b, 0xe9, 0xf1, 0x60, 0xec, 0x9e, 0x2e, + 0x58, 0x42, 0x03, 0xfd, 0x1a, 0x2a, 0xc3, 0x49, 0x18, 0x8c, 0x3b, 0x25, 0xa1, 0xba, 0x9a, 0x55, + 0x7d, 0xc5, 0x45, 0xa7, 0x0b, 0x96, 0xd4, 0xe1, 0xd3, 0x12, 0x3a, 0x74, 0x3b, 0xe5, 0xa2, 0x69, + 0x7b, 0x74, 0x28, 0xa6, 0xe5, 0x1a, 0xe8, 0x05, 0x40, 0x80, 0x59, 0xdf, 0xf5, 0x18, 0x71, 0x69, + 0x47, 0x17, 0xfa, 0x1b, 0x59, 0xfd, 0x0b, 0xcc, 0xde, 0x08, 0xf1, 0xe9, 0x82, 0xd5, 0x08, 0x22, + 0x82, 0x5b, 0x3a, 0x78, 0x42, 0x6e, 0xb0, 0xdf, 0x67, 0xb3, 0x4e, 0xa5, 0xc8, 0xf2, 0x48, 0xca, + 0x2f, 0x67, 0xdc, 0xd2, 0x89, 0x08, 0xb4, 0x0b, 0xf5, 0xc1, 0x18, 0x0f, 0xae, 0xb9, 0x5d, 0x55, + 0xd8, 0xad, 0x65, 0xed, 0x0e, 0xb9, 0x54, 0x58, 0xd5, 0x06, 0x72, 0x88, 0x76, 0xa0, 0x3a, 0x70, + 0xa7, 0x53, 0xc2, 0x3a, 0x35, 0x61, 0xd1, 0xce, 0x59, 0x08, 0xd9, 0xe9, 0x82, 0xa5, 0xb4, 0xf8, + 0x71, 0xbd, 0x0f, 0xb1, 0x7f, 0xdb, 0xa9, 0x17, 0x1d, 0xd7, 0x5f, 0xb8, 0x88, 0x1f, 0x97, 0xd0, + 0xe1, 0x5b, 0x21, 0x94, 0xb0, 0xfe, 0x60, 0x6c, 0x13, 0xda, 0x69, 0x14, 0x6d, 0xa5, 0x47, 0x09, + 0x3b, 0xe4, 0x62, 0xbe, 0x15, 0x12, 0x11, 0xe8, 0x25, 0x2c, 0x5e, 0xe1, 0x11, 0xa1, 0xfd, 0xab, + 0x89, 0x3b, 0xb8, 0xee, 0x80, 0x30, 0xed, 0x64, 0x4d, 0x0f, 0xb8, 0xc2, 0x01, 0x97, 0x9f, 0x2e, + 0x58, 0x70, 0x15, 0x53, 0xe8, 0x39, 0x34, 0x30, 0x75, 0x94, 0xe9, 0xa2, 0x30, 0x5d, 0xcf, 0x45, + 0x00, 0x75, 0x22, 0xc3, 0x3a, 0x56, 0xe3, 0x83, 0x1a, 0x54, 0x6e, 0xec, 0x49, 0x88, 0xcd, 0x47, + 0xb0, 0x98, 0x8a, 0x14, 0xd4, 0x81, 0xda, 0x14, 0x07, 0x81, 0x3d, 0xc2, 0x22, 0x9c, 0x1a, 0x56, + 0x44, 0x9a, 0x2d, 0x68, 0xa6, 0xe3, 0x24, 0x65, 0xc8, 0x63, 0x81, 0x1b, 0xde, 0x60, 0x3f, 0xe0, + 0x01, 0xa0, 0x0c, 0x15, 0x69, 0xfe, 0x01, 0x8c, 0x7c, 0x10, 0x20, 0x03, 0xca, 0xd7, 0xf8, 0x56, + 0x69, 0xf2, 0x21, 0x6a, 0x2b, 0x87, 0x44, 0x68, 0x36, 0x2c, 0xe5, 0x9d, 0x19, 0xdb, 0xc6, 0x61, + 0x80, 0x5a, 0x50, 0x62, 0x33, 0x61, 0xda, 0xb4, 0x4a, 0x6c, 0x66, 0xde, 0x87, 0x56, 0xf6, 0xca, + 0xef, 0x68, 0x38, 0xb1, 0xeb, 0xe2, 0xce, 0x10, 0x02, 0xdd, 0xb1, 0x99, 0xad, 0x34, 0xc4, 0x98, + 0xf3, 0x3c, 0x9b, 0x8d, 0xd5, 0xf2, 0x62, 0x8c, 0xd6, 0xa1, 0x3a, 0xc6, 0x64, 0x34, 0x66, 0x22, + 0x07, 0x74, 0x4b, 0x51, 0xdc, 0x57, 0xcf, 0x77, 0x6f, 0xb0, 0x08, 0xf5, 0xba, 0x25, 0x09, 0x73, + 0x19, 0x96, 0x32, 0x81, 0x64, 0x1e, 0xc5, 0xce, 0xc7, 0x17, 0x8f, 0x7e, 0x0b, 0x70, 0x63, 0x4f, + 0x88, 0x63, 0x33, 0xd7, 0x0f, 0x3a, 0xda, 0xfd, 0xf2, 0xd6, 0xe2, 0xae, 0xa1, 0xee, 0xeb, 0x5d, + 0x24, 0xb0, 0x52, 0x3a, 0xe6, 0x19, 0xac, 0xdc, 0x89, 0x01, 0xee, 0xed, 0xd8, 0x0e, 0xc6, 0xd1, + 0x0e, 0xf8, 0x18, 0x3d, 0xe4, 0xde, 0xda, 0x0e, 0xf6, 0x55, 0x76, 0x2f, 0xa9, 0x69, 0x4f, 0x05, + 0xd3, 0x52, 0x42, 0x73, 0x1b, 0x96, 0x73, 0x81, 0x91, 0xda, 0xa7, 0x96, 0xde, 0xa7, 0xf9, 0xb1, + 0x02, 0x75, 0x0b, 0x07, 0x9e, 0x4b, 0x03, 0x8c, 0x5e, 0x40, 0x03, 0xcf, 0x06, 0x58, 0xe6, 0xb8, + 0x96, 0x8b, 0x51, 0xa9, 0x73, 0x1c, 0xc9, 0x79, 0x7c, 0xc7, 0xca, 0x68, 0x5b, 0xe1, 0x53, 0x1e, + 0x74, 0x94, 0x51, 0x1a, 0xa0, 0x9e, 0x44, 0x00, 0x55, 0xce, 0x25, 0xa8, 0xd4, 0xcd, 0x21, 0xd4, + 0xb6, 0x42, 0x28, 0xbd, 0x70, 0xe2, 0x0c, 0x44, 0xed, 0x65, 0x20, 0xaa, 0x52, 0xe8, 0xfe, 0x1c, + 0x8c, 0xda, 0xcb, 0x60, 0x54, 0xb5, 0xd0, 0x74, 0x0e, 0x48, 0x3d, 0x4b, 0x81, 0x54, 0x2d, 0x97, + 0x9b, 0xd2, 0xb0, 0x00, 0xa5, 0x9e, 0xc6, 0x28, 0x55, 0xcf, 0xe1, 0x9a, 0x32, 0xc9, 0xc3, 0xd4, + 0x93, 0x08, 0xa6, 0x1a, 0x85, 0x87, 0x96, 0xc3, 0xa9, 0xbd, 0x0c, 0x4e, 0x41, 0xe1, 0x76, 0xe6, + 0x00, 0xd5, 0x1f, 0xb3, 0x40, 0x25, 0xd1, 0x66, 0x33, 0x67, 0x3b, 0x17, 0xa9, 0x7e, 0x9f, 0x46, + 0xaa, 0x66, 0x0e, 0x1f, 0x55, 0x2c, 0x7c, 0x12, 0xaa, 0xb6, 0x79, 0x26, 0xe4, 0x22, 0x8d, 0xe7, + 0x22, 0xf6, 0x7d, 0xd7, 0x57, 0x58, 0x22, 0x09, 0x73, 0x8b, 0x67, 0x7c, 0x12, 0x5f, 0x9f, 0x80, + 0x35, 0x91, 0xb5, 0xa9, 0xe8, 0x32, 0xff, 0xa5, 0x25, 0xb6, 0x02, 0xd9, 0xd2, 0x68, 0xd1, 0x50, + 0x68, 0x91, 0x42, 0xbb, 0x52, 0x06, 0xed, 0xd0, 0x63, 0x58, 0x99, 0xd8, 0x01, 0x93, 0xdb, 0xec, + 0x67, 0xe0, 0x63, 0x99, 0x0b, 0xe4, 0xfe, 0x24, 0x8e, 0xfc, 0x06, 0x56, 0x53, 0xba, 0xb6, 0xe7, + 0xf5, 0x45, 0x52, 0xeb, 0x22, 0xa9, 0x8d, 0x58, 0x7b, 0xdf, 0xf3, 0x4e, 0xed, 0x60, 0x6c, 0x3e, + 0x4c, 0xf6, 0x9f, 0x41, 0xd2, 0x89, 0x3b, 0x8a, 0x90, 0x74, 0xe2, 0x8e, 0xcc, 0x7f, 0x6a, 0x89, + 0x5e, 0x82, 0x9a, 0xbf, 0x04, 0x7d, 0xe0, 0x3a, 0x72, 0xfb, 0xad, 0xdd, 0x65, 0x75, 0xf0, 0x87, + 0xae, 0x83, 0x2f, 0x6f, 0x3d, 0x6c, 0x09, 0x61, 0xbc, 0xd5, 0x52, 0x0a, 0x18, 0xd5, 0x02, 0xe5, + 0x78, 0x01, 0xf4, 0x00, 0x74, 0x66, 0x8f, 0x82, 0x8e, 0x2e, 0xd0, 0x2b, 0x82, 0x99, 0xd7, 0xef, + 0xce, 0x6d, 0xe2, 0x5b, 0x42, 0x64, 0xfe, 0x43, 0xe3, 0x28, 0x93, 0x09, 0xf1, 0xcf, 0xe9, 0x81, + 0x01, 0xe5, 0x91, 0x1d, 0x88, 0x83, 0xd2, 0x2d, 0x3e, 0xe4, 0x9c, 0x21, 0xc6, 0x22, 0xb1, 0x75, + 0x8b, 0x0f, 0xcd, 0xff, 0x6a, 0xc9, 0xcd, 0x4a, 0xd8, 0xff, 0x59, 0x0e, 0xb4, 0xa1, 0x42, 0xa8, + 0x83, 0x67, 0xc2, 0x83, 0xb2, 0x25, 0x89, 0xa8, 0x5e, 0x95, 0x85, 0x57, 0xd9, 0x7a, 0x25, 0x6f, + 0x4b, 0x12, 0xaa, 0x32, 0xb8, 0x43, 0xe1, 0x48, 0xd3, 0x92, 0x44, 0x0a, 0x5f, 0xab, 0x99, 0x3a, + 0xa2, 0x36, 0x56, 0x4b, 0xee, 0xee, 0xaf, 0xbc, 0x96, 0xa5, 0xd3, 0xfc, 0x33, 0x9e, 0x9a, 0xb9, + 0x9a, 0xc4, 0x45, 0x9c, 0xe0, 0x66, 0x1b, 0xd0, 0xdd, 0xcc, 0x95, 0x35, 0x3b, 0x9b, 0x93, 0xe8, + 0x57, 0x50, 0x71, 0xc8, 0x70, 0x38, 0xbf, 0x6a, 0x49, 0xb1, 0xf9, 0xef, 0x12, 0x54, 0x65, 0xcd, + 0x41, 0x9b, 0x1c, 0xff, 0x6c, 0x42, 0xfb, 0xc4, 0x89, 0xf2, 0x4e, 0xd0, 0x3d, 0x27, 0x75, 0x26, + 0xa5, 0xcc, 0x99, 0x20, 0xd0, 0x19, 0x99, 0x62, 0x95, 0x32, 0x62, 0x8c, 0x36, 0xa0, 0x46, 0xc3, + 0x69, 0x9f, 0xcd, 0xa2, 0x2b, 0xaf, 0xd2, 0x70, 0x7a, 0x39, 0x0b, 0xd0, 0x2e, 0x2c, 0xa5, 0x12, + 0x88, 0x38, 0x0a, 0xd8, 0x5b, 0xca, 0x35, 0xe1, 0x77, 0xef, 0xc8, 0x5a, 0x8c, 0x53, 0xa9, 0xe7, + 0xa0, 0x2d, 0x10, 0x99, 0xd5, 0x97, 0xe0, 0x29, 0x33, 0xae, 0x2a, 0xce, 0xad, 0xc5, 0xf9, 0x0a, + 0x5d, 0x79, 0x41, 0xbd, 0x07, 0x0d, 0x7e, 0x92, 0x52, 0xa5, 0x26, 0x54, 0xea, 0x9c, 0x21, 0x84, + 0x8f, 0x60, 0x39, 0x29, 0xd2, 0x52, 0xa5, 0x2e, 0x67, 0x49, 0xd8, 0x42, 0x71, 0x13, 0xea, 0x71, + 0x66, 0x37, 0x84, 0x46, 0xcd, 0x56, 0x09, 0xdd, 0x83, 0x9a, 0x72, 0xb1, 0xb0, 0xa0, 0x3f, 0x86, + 0x8a, 0x67, 0xfb, 0x2c, 0x50, 0x85, 0x33, 0xc2, 0xf5, 0x73, 0xdb, 0xe7, 0x9d, 0x94, 0x2a, 0xeb, + 0x52, 0xc5, 0xdc, 0x83, 0xa5, 0x0c, 0x9f, 0x47, 0x22, 0x73, 0x99, 0x3d, 0x51, 0x25, 0x5d, 0x12, + 0xf1, 0x32, 0xa5, 0x64, 0x19, 0x73, 0x0f, 0x1a, 0xf1, 0x1d, 0xf2, 0x6b, 0xf1, 0xc2, 0xab, 0xd7, + 0xaa, 0x37, 0x6b, 0x5a, 0x8a, 0x12, 0x81, 0xed, 0x7e, 0x50, 0xbd, 0x85, 0x6e, 0x49, 0xc2, 0xfc, + 0x8f, 0x06, 0x55, 0x99, 0xf7, 0x05, 0x1d, 0xdd, 0xef, 0x44, 0xab, 0x13, 0xe2, 0x3e, 0x77, 0x5b, + 0xd8, 0xb5, 0xe2, 0xbf, 0x08, 0x69, 0xb4, 0x23, 0x42, 0xb8, 0x21, 0xb4, 0xf8, 0x10, 0x3d, 0x80, + 0xa6, 0x34, 0x09, 0x98, 0x4f, 0x68, 0x14, 0xbc, 0x8b, 0x82, 0x77, 0x21, 0x58, 0xfc, 0x52, 0xa4, + 0x0a, 0xa1, 0x4c, 0x44, 0x43, 0xd9, 0xaa, 0x0b, 0x46, 0x8f, 0x32, 0xf3, 0x1e, 0xe8, 0x62, 0x1e, + 0x80, 0xea, 0xc5, 0xa5, 0xd5, 0x3b, 0x3b, 0x31, 0x16, 0x50, 0x0d, 0xca, 0xbd, 0xb3, 0x4b, 0x43, + 0x7b, 0xfc, 0xbf, 0x0a, 0xd4, 0xa3, 0xbc, 0x41, 0x55, 0x28, 0xbd, 0x79, 0x6d, 0x2c, 0xa0, 0x15, + 0x58, 0xea, 0x51, 0x86, 0x7d, 0x6a, 0x4f, 0x8e, 0x79, 0xe5, 0x30, 0x34, 0xce, 0x3a, 0xa6, 0x03, + 0xd7, 0x21, 0x74, 0x24, 0x59, 0x25, 0xd4, 0x84, 0xfa, 0x81, 0xed, 0x9c, 0xb9, 0x74, 0x80, 0x8d, + 0x32, 0x32, 0xa0, 0xf9, 0x96, 0xda, 0x21, 0x1b, 0xbb, 0x3e, 0xf9, 0x3b, 0x76, 0x0c, 0x1d, 0xad, + 0xc1, 0x4a, 0x8f, 0x06, 0xe1, 0x70, 0x48, 0x06, 0x04, 0x53, 0xf6, 0x2a, 0xa4, 0x4e, 0x60, 0x54, + 0x10, 0x82, 0xd6, 0x5b, 0x7a, 0x4d, 0xdd, 0x0f, 0x54, 0x75, 0x5c, 0x46, 0x15, 0x75, 0xa0, 0x7d, + 0x60, 0x07, 0xf8, 0x28, 0xf4, 0x26, 0x64, 0x60, 0x33, 0xbc, 0xef, 0x38, 0x3e, 0x0e, 0x02, 0x03, + 0xf3, 0x49, 0xb8, 0x24, 0xbb, 0xf6, 0x30, 0x32, 0xc8, 0xcc, 0x8f, 0x71, 0x60, 0x8c, 0xd0, 0x26, + 0xac, 0xdd, 0x91, 0x88, 0x95, 0xc7, 0xe8, 0x17, 0xd0, 0xc9, 0x8b, 0x4e, 0xec, 0xe0, 0xdc, 0x27, + 0x03, 0x6c, 0x10, 0xd4, 0x06, 0x43, 0x4a, 0x45, 0xa8, 0xf6, 0xa8, 0x17, 0x32, 0xe3, 0x6f, 0xd1, + 0xfa, 0x8a, 0xfb, 0x26, 0x64, 0x9c, 0x7d, 0x9d, 0x63, 0x9f, 0x8b, 0x70, 0x30, 0x26, 0x68, 0x03, + 0x56, 0x53, 0xec, 0x0b, 0xbe, 0x3f, 0x7e, 0x3a, 0xd3, 0xc4, 0x5f, 0x29, 0x20, 0x23, 0x6a, 0xb3, + 0xd0, 0xc7, 0x06, 0x45, 0xeb, 0x80, 0xb8, 0x44, 0x1d, 0x49, 0xb4, 0x71, 0x37, 0x5a, 0x41, 0xf1, + 0xd5, 0x0a, 0x5e, 0x9e, 0x3d, 0x09, 0x47, 0x84, 0x1a, 0xef, 0xd1, 0x1a, 0x18, 0x27, 0xee, 0x8d, + 0xe2, 0x1e, 0x53, 0x46, 0xd8, 0xad, 0xf1, 0x85, 0x86, 0xda, 0xb0, 0x9c, 0xb0, 0x4f, 0x7c, 0x37, + 0xf4, 0x8c, 0x2f, 0x35, 0xb4, 0x01, 0x28, 0xe1, 0x9e, 0xfb, 0xae, 0xe7, 0x06, 0xf6, 0xc4, 0xf8, + 0x4a, 0x43, 0xeb, 0xb0, 0x72, 0xe2, 0xde, 0xc4, 0xb7, 0x20, 0x0d, 0xbe, 0x8e, 0x0c, 0x62, 0xfe, + 0x9f, 0xf1, 0xf4, 0x0a, 0xfb, 0xc6, 0x37, 0x1a, 0xda, 0x84, 0x76, 0x5a, 0x10, 0xcf, 0xf5, 0xad, + 0xa6, 0x3c, 0x8a, 0x45, 0xef, 0x5c, 0x86, 0x8d, 0xef, 0x22, 0xb6, 0x3a, 0x07, 0x35, 0xd1, 0xf7, + 0x1a, 0x5a, 0x85, 0x56, 0xc2, 0x16, 0xba, 0x3f, 0x68, 0xa8, 0x0b, 0x6b, 0x19, 0x26, 0xa1, 0xa3, + 0x73, 0x9e, 0x61, 0xc6, 0x8f, 0xda, 0xee, 0xc7, 0x0a, 0x2c, 0xef, 0x1f, 0x1c, 0xf6, 0xf6, 0x3d, + 0xb9, 0x00, 0xaf, 0xfa, 0x4f, 0x41, 0x17, 0x7d, 0x4d, 0xc1, 0xcf, 0x7e, 0xb7, 0xa8, 0xc1, 0x46, + 0xbb, 0x50, 0x11, 0xed, 0x0d, 0x2a, 0xfa, 0xe7, 0xef, 0x16, 0xf6, 0xd9, 0x7c, 0x11, 0xd9, 0x00, + 0xdd, 0xfd, 0xf5, 0xef, 0x16, 0x35, 0xdb, 0xe8, 0x4f, 0xd0, 0x48, 0x1a, 0x93, 0x79, 0x0f, 0x00, + 0xdd, 0xb9, 0x6d, 0x37, 0xb7, 0x4f, 0x1a, 0x96, 0x79, 0xcf, 0x00, 0xdd, 0xb9, 0xbd, 0x37, 0x7a, + 0x01, 0xb5, 0xa8, 0xd9, 0x28, 0x7e, 0x0c, 0xe8, 0xce, 0x69, 0xbf, 0xf9, 0xf1, 0xc8, 0x1e, 0xa1, + 0xe8, 0x1f, 0xbf, 0x5b, 0xd8, 0x51, 0xa3, 0xe7, 0x50, 0x55, 0x35, 0xba, 0xf0, 0x1d, 0xa1, 0x5b, + 0xdc, 0xb7, 0xf3, 0x4d, 0x26, 0xbf, 0x83, 0xf3, 0x1e, 0x08, 0xba, 0x73, 0x3b, 0x72, 0xb4, 0x0f, + 0x90, 0xfa, 0x11, 0x9c, 0xfb, 0x4c, 0xd0, 0x9d, 0xdf, 0x97, 0xa3, 0x97, 0x50, 0x4f, 0xfe, 0xfd, + 0x8a, 0x1f, 0x0b, 0xba, 0xf3, 0x5a, 0xf3, 0xab, 0xaa, 0x78, 0x87, 0x7a, 0xf6, 0x53, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x3c, 0xa1, 0xc6, 0x00, 0x9c, 0x12, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index e83df985..7b2c75e3 100644 --- a/types/types.proto +++ b/types/types.proto @@ -166,6 +166,8 @@ message ResponseCheckTx{ CodeType code = 1; bytes data = 2; string log = 3; + uint64 gas = 4; + uint64 fee = 5; } message ResponseQuery{ From e08885e3cdf3163c2bbc81ddef9471ee15943cd8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 20:16:35 +0000 Subject: [PATCH 350/545] minor fix --- types/application.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/types/application.go b/types/application.go index c36e58f0..bb9a0030 100644 --- a/types/application.go +++ b/types/application.go @@ -45,46 +45,46 @@ func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*Resp } func (app *GRPCApplication) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { - resInfo := app.app.Info(*req) - return &resInfo, nil + res := app.app.Info(*req) + return &res, nil } func (app *GRPCApplication) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { - resSetOption := app.app.SetOption(*req) - return &resSetOption, nil + res := app.app.SetOption(*req) + return &res, nil } func (app *GRPCApplication) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { - r := app.app.DeliverTx(req.Tx) - return &ResponseDeliverTx{r.Code, r.Data, r.Log, r.Tags}, nil + res := app.app.DeliverTx(req.Tx) + return &res, nil } func (app *GRPCApplication) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { - r := app.app.CheckTx(req.Tx) - return &ResponseCheckTx{r.Code, r.Data, r.Log}, nil + res := app.app.CheckTx(req.Tx) + return &res, nil } func (app *GRPCApplication) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { - resQuery := app.app.Query(*req) - return &resQuery, nil + res := app.app.Query(*req) + return &res, nil } func (app *GRPCApplication) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { - r := app.app.Commit() - return &ResponseCommit{r.Code, r.Data, r.Log}, nil + res := app.app.Commit() + return &res, nil } func (app *GRPCApplication) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - resInitChain := app.app.InitChain(*req) - return &resInitChain, nil + res := app.app.InitChain(*req) + return &res, nil } func (app *GRPCApplication) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { - resBeginBlock := app.app.BeginBlock(*req) - return &resBeginBlock, nil + res := app.app.BeginBlock(*req) + return &res, nil } func (app *GRPCApplication) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { - resEndBlock := app.app.EndBlock(*req) - return &resEndBlock, nil + res := app.app.EndBlock(*req) + return &res, nil } From e9094fbee3001db87f495fb8b6387cdc7deab75d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 20:19:04 +0000 Subject: [PATCH 351/545] update changelog --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db1817c..3c6956cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,14 @@ ## 0.8.0 (TBD) BREAKING CHANGES: - - [client] all {X}Sync methods now return an error + - [client] all XxxSync methods now return (ResponseXxx, error) + - [types] Application: all methods take RequestXxx and return (ResponseXxx, error), + except CheckTx/DeliverTx, which take `tx []byte`, and `Commit`, which takes nothing. - [types] removed Result - - [client] all {X}Sync methods now return Response{X} as first return value -IMPROVEMENTS: +FEATURES: - [types] added Tags field to ResponseDeliverTx + - [types] added Gas and Fee fields to ResponseCheckTx ## 0.7.1 (November 14, 2017) From 5a46675185d2bd76b79819075703a32b1cc175be Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 20:27:18 +0000 Subject: [PATCH 352/545] minor things --- CHANGELOG.md | 5 +++-- client/socket_client.go | 9 ++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6956cf..44db318b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,9 @@ BREAKING CHANGES: - [client] all XxxSync methods now return (ResponseXxx, error) - - [types] Application: all methods take RequestXxx and return (ResponseXxx, error), - except CheckTx/DeliverTx, which take `tx []byte`, and `Commit`, which takes nothing. + - [types] Application: all methods now take RequestXxx and return (ResponseXxx, error). + - Except `CheckTx`/`DeliverTx`, which takes a `tx []byte` argument. + - Except `Commit`, which takes no arguments. - [types] removed Result FEATURES: diff --git a/client/socket_client.go b/client/socket_client.go index 84377a05..7e5a1f30 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -14,11 +14,6 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -const ( - OK = types.CodeType_OK - LOG = "" -) - const reqQueueSize = 256 // TODO make configurable // const maxResponseSize = 1048576 // 1MB TODO make configurable const flushThrottleMS = 20 // Don't wait longer than... @@ -251,8 +246,8 @@ func (cli *socketClient) CheckTxAsync(tx []byte) *ReqRes { return cli.queueRequest(types.ToRequestCheckTx(tx)) } -func (cli *socketClient) QueryAsync(reqQuery types.RequestQuery) *ReqRes { - return cli.queueRequest(types.ToRequestQuery(reqQuery)) +func (cli *socketClient) QueryAsync(req types.RequestQuery) *ReqRes { + return cli.queueRequest(types.ToRequestQuery(req)) } func (cli *socketClient) CommitAsync() *ReqRes { From 26d967af7e5d348a5c072f121f931925258d29e9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 20:42:30 +0000 Subject: [PATCH 353/545] linter --- cmd/abci-cli/abci-cli.go | 4 ++-- server/socket_server.go | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index d6e95d96..78983250 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -294,7 +294,7 @@ func cmdBatch(cmd *cobra.Command, args []string) error { } pArgs := persistentArgs(line) - out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() + out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() // nolint: gas if err != nil { return err } @@ -316,7 +316,7 @@ func cmdConsole(cmd *cobra.Command, args []string) error { } pArgs := persistentArgs(line) - out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() + out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() // nolint: gas if err != nil { return err } diff --git a/server/socket_server.go b/server/socket_server.go index c88180d4..eb26dc35 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -56,13 +56,17 @@ func (s *SocketServer) OnStart() error { func (s *SocketServer) OnStop() { s.BaseService.OnStop() - s.listener.Close() + if err := s.listener.Close(); err != nil { + s.Logger.Error("Error closing listener", "err", err) + } s.connsMtx.Lock() defer s.connsMtx.Unlock() for id, conn := range s.conns { delete(s.conns, id) - conn.Close() + if err := conn.Close(); err != nil { + s.Logger.Error("Error closing connection", "id", id, "conn", conn, "err", err) + } } } From ab51bdef994946d5bf24c5808d730b493c8e923e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 20:53:03 +0000 Subject: [PATCH 354/545] types.pb.go isnt linted. use nolint :( --- types/types.pb.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/types.pb.go b/types/types.pb.go index 7b278ea2..e433d198 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -40,6 +40,7 @@ It has these top-level messages: Validator KVPair */ +//nolint: gas package types import proto "github.com/golang/protobuf/proto" From 0981c174ccc3f5ea7dea40f1e2b7d7cabfdc8b14 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 27 Nov 2017 22:28:41 +0000 Subject: [PATCH 355/545] update README for CheckTx Gas and Fee --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4cfcce74..f2546c00 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,8 @@ Here, we describe the requests and responses as function arguments and return va * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message + * `Gas (uint64)`: Amount of gas consumed by transaction + * `Fee (uint64)`: Fee paid by transaction * __Usage__:
Validate a mempool transaction, prior to broadcasting or proposing. This message should not mutate the main state, but application developers may want to keep a separate CheckTx state that gets reset upon Commit. From a0bf6dc1a136bbd79785649c2d678a75ed491ee5 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 27 Nov 2017 16:27:18 -0600 Subject: [PATCH 356/545] move comment --- Makefile | 1 - test.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ab9223f6..11a75664 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,6 @@ dist: @ bash scripts/dist.sh @ bash scripts/publish.sh -# test.sh requires that we run the installed cmds, must not be out of date test: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; @ echo "==> Running go test" diff --git a/test.sh b/test.sh index 33839c06..978b26e1 100755 --- a/test.sh +++ b/test.sh @@ -14,5 +14,6 @@ done echo "==> Running integration tests (./tests)" find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; +# tests/test.sh requires that we run the installed cmds, must not be out of date make install bash tests/test.sh From 6231652e87097dffcdc0115e470fd478ddae39de Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Mon, 27 Nov 2017 21:12:00 -0700 Subject: [PATCH 357/545] tests: sunset tmlibs/process.Process Updates https://github.com/tendermint/tmlibs/issues/81 No longer using tmlibs/process.Process as we deemed it racy and would incur a maintenance cost yet not used anywhere else but in these tests and not in actual code. --- tests/test_app/app.go | 22 ---------------------- tests/test_app/main.go | 30 ++++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 59d7aec4..f7ecbef5 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -4,34 +4,12 @@ import ( "bytes" "fmt" "os" - "time" abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" "github.com/tendermint/tmlibs/log" - "github.com/tendermint/tmlibs/process" ) -func startApp(abciApp string) *process.Process { - // Start the app - //outBuf := NewBufferCloser(nil) - proc, err := process.StartProcess("abci_app", - "", - "bash", - []string{"-c", fmt.Sprintf("abci-cli %s", abciApp)}, - nil, - os.Stdout, - ) - if err != nil { - panicf("running abci_app: %v", err) - } - - // TODO a better way to handle this? - time.Sleep(time.Second) - - return proc -} - func startClient(abciType string) abcicli.Client { // Start client client, err := abcicli.NewClient("tcp://127.0.0.1:46658", abciType, true) diff --git a/tests/test_app/main.go b/tests/test_app/main.go index 376c02fe..e6b11616 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -2,7 +2,10 @@ package main import ( "fmt" + "log" "os" + "os/exec" + "time" "github.com/tendermint/abci/types" ) @@ -20,6 +23,19 @@ func main() { testCounter() } +func ensureABCIIsUp(subCommand string, n int) error { + var err error + for i := 0; i < n; i++ { + cmd := exec.Command("bash", "-c", "abci-cli", subCommand) + _, err = cmd.CombinedOutput() + if err == nil { + break + } + <-time.After(500 * time.Second) + } + return err +} + func testCounter() { abciApp := os.Getenv("ABCI_APP") if abciApp == "" { @@ -27,8 +43,18 @@ func testCounter() { } fmt.Printf("Running %s test with abci=%s\n", abciApp, abciType) - appProc := startApp(abciApp) - defer appProc.StopProcess(true) + cmd := exec.Command("bash", "-c", fmt.Sprintf("abci-cli %s", abciApp)) + cmd.Stdout = os.Stdout + if err := cmd.Start(); err != nil { + log.Fatalf("starting %q err: %v", abciApp, err) + } + defer cmd.Wait() + defer cmd.Process.Kill() + + if err := ensureABCIIsUp("echo", 5); err != nil { + log.Fatalf("echo failed: %v", err) + } + client := startClient(abciType) defer client.Stop() From 9ed5787b6afe4435942b2ec2af895072dc157722 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 28 Nov 2017 07:24:17 +0000 Subject: [PATCH 358/545] tests: fix ensureABCIIsUp --- tests/test.sh | 1 + tests/test_app/main.go | 17 +++++++++++++---- tests/test_cli/test.sh | 39 ++++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/tests/test.sh b/tests/test.sh index 4087cdce..c005c0de 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,4 +1,5 @@ #! /bin/bash +set -e # test the counter using a go test script bash tests/test_app/test.sh diff --git a/tests/test_app/main.go b/tests/test_app/main.go index e6b11616..6c75a37e 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -23,15 +23,24 @@ func main() { testCounter() } -func ensureABCIIsUp(subCommand string, n int) error { +const ( + maxABCIConnectTries = 10 +) + +func ensureABCIIsUp(typ string, n int) error { var err error + cmdString := "abci-cli echo hello" + if typ == "grpc" { + cmdString = "abci-cli --abci grpc echo hello" + } + for i := 0; i < n; i++ { - cmd := exec.Command("bash", "-c", "abci-cli", subCommand) + cmd := exec.Command("bash", "-c", cmdString) _, err = cmd.CombinedOutput() if err == nil { break } - <-time.After(500 * time.Second) + <-time.After(500 * time.Millisecond) } return err } @@ -51,7 +60,7 @@ func testCounter() { defer cmd.Wait() defer cmd.Process.Kill() - if err := ensureABCIIsUp("echo", 5); err != nil { + if err := ensureABCIIsUp(abciType, maxABCIConnectTries); err != nil { log.Fatalf("echo failed: %v", err) } diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index ea4ea4fa..f6259148 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -1,4 +1,5 @@ #! /bin/bash +set -e # Get the root directory. SOURCE="${BASH_SOURCE[0]}" @@ -9,29 +10,29 @@ DIR="$( cd -P "$( dirname "$SOURCE" )/../.." && pwd )" cd "$DIR" || exit function testExample() { - N=$1 - INPUT=$2 - APP="$3 $4" + N=$1 + INPUT=$2 + APP="$3 $4" - echo "Example $N: $APP" - $APP &> /dev/null & - sleep 2 - abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" - killall "$3" + echo "Example $N: $APP" + $APP &> /dev/null & + sleep 2 + abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" + killall "$3" - pre=$(shasum < "${INPUT}.out") - post=$(shasum < "${INPUT}.out.new") + pre=$(shasum < "${INPUT}.out") + post=$(shasum < "${INPUT}.out.new") - if [[ "$pre" != "$post" ]]; then - echo "You broke the tutorial" - echo "Got:" - cat "${INPUT}.out.new" - echo "Expected:" - cat "${INPUT}.out" - exit 1 - fi + if [[ "$pre" != "$post" ]]; then + echo "You broke the tutorial" + echo "Got:" + cat "${INPUT}.out.new" + echo "Expected:" + cat "${INPUT}.out" + exit 1 + fi - rm "${INPUT}".out.new + rm "${INPUT}".out.new } testExample 1 tests/test_cli/ex1.abci abci-cli dummy From bb141794c8a499feab1f5cb02a91b03ce5f1b444 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 28 Nov 2017 07:47:51 +0000 Subject: [PATCH 359/545] client: use vars for retry intervals --- client/client.go | 5 +++++ client/grpc_client.go | 4 ++-- client/socket_client.go | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/client/client.go b/client/client.go index ddb589a4..ad0e5a7a 100644 --- a/client/client.go +++ b/client/client.go @@ -8,6 +8,11 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +const ( + dialRetryIntervalSeconds = 3 + echoRetryIntervalSeconds = 1 +) + // Client defines an interface for an ABCI client. // All `Async` methods return a `ReqRes` object. // All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error. diff --git a/client/grpc_client.go b/client/grpc_client.go index 6079c90c..f65d27e6 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -56,7 +56,7 @@ RETRY_LOOP: return err } cli.Logger.Error(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) - time.Sleep(time.Second * 3) + time.Sleep(time.Second * dialRetryIntervalSeconds) continue RETRY_LOOP } @@ -68,7 +68,7 @@ RETRY_LOOP: if err == nil { break ENSURE_CONNECTED } - time.Sleep(time.Second) + time.Sleep(time.Second * echoRetryIntervalSeconds) } cli.client = client diff --git a/client/socket_client.go b/client/socket_client.go index 7e5a1f30..a5d90dbe 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -68,7 +68,7 @@ RETRY_LOOP: return err } cli.Logger.Error(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) - time.Sleep(time.Second * 3) + time.Sleep(time.Second * dialRetryIntervalSeconds) continue RETRY_LOOP } cli.conn = conn From 67a81c13e2be6ee282bed7563008ac86482c1520 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 28 Nov 2017 07:48:00 +0000 Subject: [PATCH 360/545] run linter on make test --- Makefile | 18 ++++++++++-------- tests/test_app/main.go | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 11a75664..cdee195d 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,8 @@ dist: test: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @ echo "==> Running linter" + @ make metalinter_test @ echo "==> Running go test" @ go test $(PACKAGES) @@ -54,20 +56,20 @@ fmt: get_deps: @ go get -d $(PACKAGES) -tools: +ensure_tools: go get -u -v $(GOTOOLS) + @gometalinter --install -get_vendor_deps: - @ go get github.com/Masterminds/glide +get_vendor_deps: ensure_tools + @rm -rf vendor/ + @echo "--> Running glide install" @ glide install -metalinter: tools - @gometalinter --install +metalinter: protoc --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... -metalinter_test: tools - @gometalinter --install +metalinter_test: # protoc --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --disable-all \ --enable=maligned \ @@ -103,4 +105,4 @@ build-docker: run-docker: docker run -it --rm -v "$PWD:/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash -.PHONY: all build test fmt get_deps tools protoc install_protoc build-docker run-docker +.PHONY: all build test fmt get_deps ensure_tools protoc install_protoc build-docker run-docker diff --git a/tests/test_app/main.go b/tests/test_app/main.go index 6c75a37e..a21918f5 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -35,7 +35,7 @@ func ensureABCIIsUp(typ string, n int) error { } for i := 0; i < n; i++ { - cmd := exec.Command("bash", "-c", cmdString) + cmd := exec.Command("bash", "-c", cmdString) // nolint: gas _, err = cmd.CombinedOutput() if err == nil { break @@ -52,7 +52,7 @@ func testCounter() { } fmt.Printf("Running %s test with abci=%s\n", abciApp, abciType) - cmd := exec.Command("bash", "-c", fmt.Sprintf("abci-cli %s", abciApp)) + cmd := exec.Command("bash", "-c", fmt.Sprintf("abci-cli %s", abciApp)) // nolint: gas cmd.Stdout = os.Stdout if err := cmd.Start(); err != nil { log.Fatalf("starting %q err: %v", abciApp, err) From 72c3ea3872424fba6b564de9d722acd74e6ecedc Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 29 Nov 2017 20:13:59 -0600 Subject: [PATCH 361/545] include tags into dummy application DeliverTx response Refs https://github.com/tendermint/tendermint/pull/835 --- example/dummy/dummy.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 65d524cf..45462c53 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -35,7 +35,8 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { } else { app.state.Set(tx, tx) } - return types.ResponseDeliverTx{Code: types.CodeType_OK} + tags := []*types.KVPair{{Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}} + return types.ResponseDeliverTx{Code: types.CodeType_OK, Tags: tags} } func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { From 3b994b4e8a824d69b6973ae6154c274b382c9d9e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 02:45:40 +0000 Subject: [PATCH 362/545] dummy: include app.key tag --- example/dummy/dummy.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 45462c53..30eaff28 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -1,8 +1,8 @@ package dummy import ( + "bytes" "fmt" - "strings" "github.com/tendermint/abci/types" wire "github.com/tendermint/go-wire" @@ -29,13 +29,19 @@ func (app *DummyApplication) Info(req types.RequestInfo) (resInfo types.Response // tx is either "key=value" or just arbitrary bytes func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { - parts := strings.Split(string(tx), "=") + var key, value []byte + parts := bytes.Split(tx, []byte("=")) if len(parts) == 2 { - app.state.Set([]byte(parts[0]), []byte(parts[1])) + key, value = parts[0], parts[1] } else { - app.state.Set(tx, tx) + key, value = tx, tx + } + app.state.Set(key, value) + + tags := []*types.KVPair{ + {Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}, + {Key: "app.key", ValueType: types.KVPair_STRING, ValueString: string(key)}, } - tags := []*types.KVPair{{Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}} return types.ResponseDeliverTx{Code: types.CodeType_OK, Tags: tags} } From 32a6545604367681017fc91c1866f987518f8e88 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 03:02:48 +0000 Subject: [PATCH 363/545] changelog [ci skip] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44db318b..6937eaeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ BREAKING CHANGES: FEATURES: - [types] added Tags field to ResponseDeliverTx - [types] added Gas and Fee fields to ResponseCheckTx + - [dummy] DeliverTx returns tags ## 0.7.1 (November 14, 2017) From 20befcf6d6ba75b8de40e9fb5b6f74affb94a805 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 30 Nov 2017 11:17:35 -0600 Subject: [PATCH 364/545] add 2 helper methods for building KVPair(s) --- types/kvpair.go | 19 +++++++++++++++++++ types/kvpair_test.go | 15 +++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 types/kvpair.go create mode 100644 types/kvpair_test.go diff --git a/types/kvpair.go b/types/kvpair.go new file mode 100644 index 00000000..c7aad440 --- /dev/null +++ b/types/kvpair.go @@ -0,0 +1,19 @@ +package types + +// KVPairInt is a helper method to build KV pair with an integer value. +func KVPairInt(key string, val int64) *KVPair { + return &KVPair{ + Key: key, + ValueInt: val, + ValueType: KVPair_INT, + } +} + +// KVPairString is a helper method to build KV pair with a string value. +func KVPairString(key, val string) *KVPair { + return &KVPair{ + Key: key, + ValueString: val, + ValueType: KVPair_STRING, + } +} diff --git a/types/kvpair_test.go b/types/kvpair_test.go new file mode 100644 index 00000000..d006d56b --- /dev/null +++ b/types/kvpair_test.go @@ -0,0 +1,15 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKVPairInt(t *testing.T) { + assert.Equal(t, KVPairInt("a", 1), &KVPair{Key: "a", ValueType: KVPair_INT, ValueInt: 1}) +} + +func TestKVPairString(t *testing.T) { + assert.Equal(t, KVPairString("a", "b"), &KVPair{Key: "a", ValueType: KVPair_STRING, ValueString: "b"}) +} From 42a8e3240c92e9dddda1e2dd2ca26e155a3d5025 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 14:29:12 -0500 Subject: [PATCH 365/545] remove CodeType --- Makefile | 2 +- client/grpc_client.go | 2 +- client/socket_client.go | 2 +- cmd/abci-cli/abci-cli.go | 4 +- example/counter/counter.go | 17 +- example/dummy/dummy.go | 6 +- example/dummy/dummy_test.go | 8 +- example/dummy/persistent_dummy.go | 17 +- example/example.go | 2 +- example/example_test.go | 4 +- tests/test_app/app.go | 4 +- tests/test_app/main.go | 17 +- types/base_app.go | 8 +- types/code.go | 37 --- types/code_test.go | 12 - types/result.go | 25 ++- types/result_test.go | 24 +- types/types.pb.go | 358 ++++++++++-------------------- types/types.proto | 51 +---- 19 files changed, 190 insertions(+), 410 deletions(-) delete mode 100644 types/code.go delete mode 100644 types/code_test.go diff --git a/Makefile b/Makefile index cdee195d..e9d23900 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,6 @@ metalinter_test: gometalinter --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ - --enable=gas \ --enable=goconst \ --enable=goimports \ --enable=gosimple \ @@ -90,6 +89,7 @@ metalinter_test: --enable=vetshadow \ ./... + #--enable=gas \ #--enable=dupl \ #--enable=errcheck \ #--enable=gocyclo \ diff --git a/client/grpc_client.go b/client/grpc_client.go index f65d27e6..0afadc72 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -104,7 +104,7 @@ func (cli *grpcClient) StopForError(err error) { func (cli *grpcClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return errors.Wrap(cli.err, types.HumanCode(types.CodeType_InternalError)) + return errors.Wrap(cli.err, "grpc client error") } // Set listener for all responses diff --git a/client/socket_client.go b/client/socket_client.go index a5d90dbe..ecdc3694 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -111,7 +111,7 @@ func (cli *socketClient) StopForError(err error) { func (cli *socketClient) Error() error { cli.mtx.Lock() defer cli.mtx.Unlock() - return errors.Wrap(cli.err, types.HumanCode(types.CodeType_InternalError)) + return errors.Wrap(cli.err, "socket client error") } // Set listener for all responses diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 78983250..c0dbbfaf 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -26,7 +26,7 @@ import ( type response struct { // generic abci response Data []byte - Code types.CodeType + Code uint32 Log string Query *queryResponse @@ -508,7 +508,7 @@ func printResponse(cmd *cobra.Command, args []string, rsp response) { } // Always print the status code. - fmt.Printf("-> code: %s\n", rsp.Code.String()) + fmt.Printf("-> code: %d\n", rsp.Code) if len(rsp.Data) != 0 { // Do no print this line when using the commit command diff --git a/example/counter/counter.go b/example/counter/counter.go index a7b09027..67fa06e3 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "fmt" + "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -36,7 +37,7 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { if app.serial { if len(tx) > 8 { return types.ResponseDeliverTx{ - Code: types.CodeType_EncodingError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) @@ -44,19 +45,19 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { txValue := binary.BigEndian.Uint64(tx8) if txValue != uint64(app.txCount) { return types.ResponseDeliverTx{ - Code: types.CodeType_BadNonce, + Code: code.CodeTypeBadNonce, Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)} } } app.txCount++ - return types.ResponseDeliverTx{Code: types.CodeType_OK} + return types.ResponseDeliverTx{Code: types.CodeTypeOK} } func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { if app.serial { if len(tx) > 8 { return types.ResponseCheckTx{ - Code: types.CodeType_EncodingError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(tx))} } tx8 := make([]byte, 8) @@ -64,21 +65,21 @@ func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { txValue := binary.BigEndian.Uint64(tx8) if txValue < uint64(app.txCount) { return types.ResponseCheckTx{ - Code: types.CodeType_BadNonce, + Code: code.CodeTypeBadNonce, Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} } } - return types.ResponseCheckTx{Code: types.CodeType_OK} + return types.ResponseCheckTx{Code: types.CodeTypeOK} } func (app *CounterApplication) Commit() (resp types.ResponseCommit) { app.hashCount++ if app.txCount == 0 { - return types.ResponseCommit{Code: types.CodeType_OK} + return types.ResponseCommit{Code: types.CodeTypeOK} } hash := make([]byte, 8) binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} + return types.ResponseCommit{Code: types.CodeTypeOK, Data: hash} } func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 30eaff28..8329ef03 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -42,11 +42,11 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { {Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}, {Key: "app.key", ValueType: types.KVPair_STRING, ValueString: string(key)}, } - return types.ResponseDeliverTx{Code: types.CodeType_OK, Tags: tags} + return types.ResponseDeliverTx{Code: types.CodeTypeOK, Tags: tags} } func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { - return types.ResponseCheckTx{Code: types.CodeType_OK} + return types.ResponseCheckTx{Code: types.CodeTypeOK} } func (app *DummyApplication) Commit() types.ResponseCommit { @@ -64,7 +64,7 @@ func (app *DummyApplication) Commit() types.ResponseCommit { } } - return types.ResponseCommit{Code: types.CodeType_OK, Data: hash} + return types.ResponseCommit{Code: types.CodeTypeOK, Data: hash} } func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index b7aef6a8..bbb35dbe 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -27,7 +27,7 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string Path: "/store", Data: []byte(key), }) - require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, types.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) // make sure proof is fine @@ -36,7 +36,7 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string Data: []byte(key), Prove: true, }) - require.Equal(t, types.CodeType_OK, resQuery.Code) + require.EqualValues(t, types.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) proof, err := iavl.ReadKeyExistsProof(resQuery.Proof) require.Nil(t, err) @@ -295,7 +295,7 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) Data: []byte(key), }) require.Nil(t, err) - require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, types.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) // make sure proof is fine @@ -305,7 +305,7 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) Prove: true, }) require.Nil(t, err) - require.Equal(t, types.CodeType_OK, resQuery.Code) + require.Equal(t, types.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) proof, err := iavl.ReadKeyExistsProof(resQuery.Proof) require.Nil(t, err) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index ed284529..51da8b30 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/iavl" @@ -96,7 +97,7 @@ func (app *PersistentDummyApplication) Commit() types.ResponseCommit { } app.logger.Info("Commit block", "height", height, "root", appHash) - return types.ResponseCommit{Code: types.CodeType_OK, Data: appHash} + return types.ResponseCommit{Code: types.CodeTypeOK, Data: appHash} } func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { @@ -160,7 +161,7 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Response pubKeyAndPower := strings.Split(string(tx), "/") if len(pubKeyAndPower) != 2 { return types.ResponseDeliverTx{ - Code: types.CodeType_EncodingError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)} } pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] @@ -169,13 +170,13 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Response pubkey, err := hex.DecodeString(pubkeyS) if err != nil { return types.ResponseDeliverTx{ - Code: types.CodeType_EncodingError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)} } _, err = crypto.PubKeyFromBytes(pubkey) if err != nil { return types.ResponseDeliverTx{ - Code: types.CodeType_EncodingError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Pubkey (%X) is invalid go-crypto encoded", pubkey)} } @@ -183,7 +184,7 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Response power, err := strconv.Atoi(powerS) if err != nil { return types.ResponseDeliverTx{ - Code: types.CodeType_EncodingError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Power (%s) is not an int", powerS)} } @@ -198,7 +199,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types // remove validator if !app.app.state.Has(key) { return types.ResponseDeliverTx{ - Code: types.CodeType_Unauthorized, + Code: code.CodeTypeUnauthorized, Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)} } app.app.state.Remove(key) @@ -207,7 +208,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types value := bytes.NewBuffer(make([]byte, 0)) if err := types.WriteMessage(v, value); err != nil { return types.ResponseDeliverTx{ - Code: types.CodeType_InternalError, + Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Error encoding validator: %v", err)} } app.app.state.Set(key, value.Bytes()) @@ -216,5 +217,5 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types // we only update the changes array if we successfully updated the tree app.changes = append(app.changes, v) - return types.ResponseDeliverTx{Code: types.CodeType_OK} + return types.ResponseDeliverTx{Code: types.CodeTypeOK} } diff --git a/example/example.go b/example/example.go index ee491c1b..5a2b2449 100644 --- a/example/example.go +++ b/example/example.go @@ -1,3 +1,3 @@ package example -// so the go tool doesn't return errors about no buildable go files ... +// so go get doesnt complain diff --git a/example/example_test.go b/example/example_test.go index 496ed3d3..952f8cb2 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -60,7 +60,7 @@ func testStream(t *testing.T, app types.Application) { switch r := res.Value.(type) { case *types.Response_DeliverTx: counter++ - if r.DeliverTx.Code != types.CodeType_OK { + if r.DeliverTx.Code != types.CodeTypeOK { t.Error("DeliverTx failed with ret_code", r.DeliverTx.Code) } if counter > numDeliverTxs { @@ -135,7 +135,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { t.Fatalf("Error in GRPC DeliverTx: %v", err.Error()) } counter++ - if response.Code != types.CodeType_OK { + if response.Code != types.CodeTypeOK { t.Error("DeliverTx failed with ret_code", response.Code) } if counter > numDeliverTxs { diff --git a/tests/test_app/app.go b/tests/test_app/app.go index f7ecbef5..d55fb160 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -45,7 +45,7 @@ func commit(client abcicli.Client, hashExp []byte) { } } -func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +func deliverTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) { res, err := client.DeliverTxSync(txBytes) if err != nil { panicf("client error: %v", err) @@ -58,7 +58,7 @@ func deliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da } } -/*func checkTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) { +/*func checkTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) { res, err := client.CheckTxSync(txBytes) if err != nil { panicf("client error: %v", err) diff --git a/tests/test_app/main.go b/tests/test_app/main.go index a21918f5..95a7515d 100644 --- a/tests/test_app/main.go +++ b/tests/test_app/main.go @@ -7,6 +7,7 @@ import ( "os/exec" "time" + "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/types" ) @@ -69,15 +70,15 @@ func testCounter() { setOption(client, "serial", "on") commit(client, nil) - deliverTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + deliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil) commit(client, nil) - deliverTx(client, []byte{0x00}, types.CodeType_OK, nil) + deliverTx(client, []byte{0x00}, types.CodeTypeOK, 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) + deliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil) + deliverTx(client, []byte{0x01}, types.CodeTypeOK, nil) + deliverTx(client, []byte{0x00, 0x02}, types.CodeTypeOK, nil) + deliverTx(client, []byte{0x00, 0x03}, types.CodeTypeOK, nil) + deliverTx(client, []byte{0x00, 0x00, 0x04}, types.CodeTypeOK, nil) + deliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil) commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) } diff --git a/types/base_app.go b/types/base_app.go index 404678e9..f8d1946a 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -16,19 +16,19 @@ func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { } func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { - return ResponseDeliverTx{Code: CodeType_OK} + return ResponseDeliverTx{Code: CodeTypeOK} } func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { - return ResponseCheckTx{Code: CodeType_OK} + return ResponseCheckTx{Code: CodeTypeOK} } func (BaseApplication) Commit() ResponseCommit { - return ResponseCommit{Code: CodeType_OK, Data: []byte("nil")} + return ResponseCommit{Code: CodeTypeOK, Data: []byte("nil")} } func (BaseApplication) Query(req RequestQuery) ResponseQuery { - return ResponseQuery{Code: CodeType_OK} + return ResponseQuery{Code: CodeTypeOK} } func (BaseApplication) InitChain(req RequestInitChain) ResponseInitChain { diff --git a/types/code.go b/types/code.go deleted file mode 100644 index 613c4cda..00000000 --- a/types/code.go +++ /dev/null @@ -1,37 +0,0 @@ -package types - -var ( - code2string = map[CodeType]string{ - CodeType_InternalError: "Internal error", - CodeType_EncodingError: "Encoding error", - CodeType_BadNonce: "Error bad nonce", - CodeType_Unauthorized: "Unauthorized", - CodeType_InsufficientFunds: "Insufficient funds", - CodeType_UnknownRequest: "Unknown request", - - CodeType_BaseDuplicateAddress: "Error (base) duplicate address", - CodeType_BaseEncodingError: "Error (base) encoding error", - CodeType_BaseInsufficientFees: "Error (base) insufficient fees", - CodeType_BaseInsufficientFunds: "Error (base) insufficient funds", - CodeType_BaseInsufficientGasPrice: "Error (base) insufficient gas price", - CodeType_BaseInvalidInput: "Error (base) invalid input", - CodeType_BaseInvalidOutput: "Error (base) invalid output", - CodeType_BaseInvalidPubKey: "Error (base) invalid pubkey", - CodeType_BaseInvalidSequence: "Error (base) invalid sequence", - CodeType_BaseInvalidSignature: "Error (base) invalid signature", - CodeType_BaseUnknownAddress: "Error (base) unknown address", - CodeType_BaseUnknownPlugin: "Error (base) unknown plugin", - CodeType_BaseUnknownPubKey: "Error (base) unknown pubkey", - } -) - -func (c CodeType) IsOK() bool { return c == CodeType_OK } - -// HumanCode transforms code into a more humane format, such as "Internal error" instead of 0. -func HumanCode(code CodeType) string { - s, ok := code2string[code] - if !ok { - return "Unknown code" - } - return s -} diff --git a/types/code_test.go b/types/code_test.go deleted file mode 100644 index d9032d3c..00000000 --- a/types/code_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestHumanCode(t *testing.T) { - assert.Equal(t, "Internal error", HumanCode(CodeType_InternalError)) - assert.Equal(t, "Unknown code", HumanCode(-1)) -} diff --git a/types/result.go b/types/result.go index 6ebad8ab..59d82ffc 100644 --- a/types/result.go +++ b/types/result.go @@ -6,9 +6,15 @@ import ( "github.com/tendermint/go-wire/data" ) +// type CodeType uint32 + +const ( + CodeTypeOK uint32 = 0 +) + // IsErr returns true if Code is something other than OK. func (r ResponseCheckTx) IsErr() bool { - return r.Code != CodeType_OK + return r.Code != CodeTypeOK } // Error implements error interface by formatting response as string. @@ -18,7 +24,7 @@ func (r ResponseCheckTx) Error() string { // IsErr returns true if Code is something other than OK. func (r ResponseDeliverTx) IsErr() bool { - return r.Code != CodeType_OK + return r.Code != CodeTypeOK } // Error implements error interface by formatting response as string. @@ -28,7 +34,7 @@ func (r ResponseDeliverTx) Error() string { // IsErr returns true if Code is something other than OK. func (r ResponseCommit) IsErr() bool { - return r.Code != CodeType_OK + return r.Code != CodeTypeOK } // Error implements error interface by formatting response as string. @@ -36,19 +42,14 @@ func (r ResponseCommit) Error() string { return fmtError(r.Code, r.Log) } -func fmtError(code CodeType, log string) string { - codeAsStr, ok := code2string[code] - if ok { - return fmt.Sprintf("%s (%d): %s", codeAsStr, code, log) - } else { - return fmt.Sprintf("Unknown error (%d): %s", code, log) - } +func fmtError(code uint32, log string) string { + return fmt.Sprintf("Error code (%d): %s", code, log) } // ResultQuery is a wrapper around ResponseQuery using data.Bytes instead of // raw byte slices. type ResultQuery struct { - Code CodeType `json:"code"` + Code uint32 `json:"code"` Index int64 `json:"index"` Key data.Bytes `json:"key"` Value data.Bytes `json:"value"` @@ -72,7 +73,7 @@ func (r *ResponseQuery) Result() *ResultQuery { // IsErr returns true if Code is something other than OK. func (r *ResultQuery) IsErr() bool { - return r.Code != CodeType_OK + return r.Code != CodeTypeOK } // Error implements error interface by formatting result as string. diff --git a/types/result_test.go b/types/result_test.go index 14f334c4..7791cf52 100644 --- a/types/result_test.go +++ b/types/result_test.go @@ -8,7 +8,7 @@ import ( func TestResultQuery(t *testing.T) { orig := &ResponseQuery{ - Code: CodeType_OK, + Code: CodeTypeOK, Index: 0, Key: []byte("hello"), Value: []byte("world"), @@ -18,7 +18,7 @@ func TestResultQuery(t *testing.T) { assert.False(t, res.IsErr()) orig = &ResponseQuery{ - Code: CodeType_BadNonce, + Code: 1, Index: 0, Key: []byte("hello"), Value: []byte("world"), @@ -27,50 +27,50 @@ func TestResultQuery(t *testing.T) { } res = orig.Result() assert.True(t, res.IsErr()) - assert.Equal(t, "Error bad nonce (3): bad", res.Error()) + assert.Equal(t, "Error code (1): bad", res.Error()) } func TestResponseDeliverTx(t *testing.T) { res := ResponseDeliverTx{ - Code: CodeType_OK, + Code: CodeTypeOK, Data: []byte("Victor Mancha"), } assert.False(t, res.IsErr()) res = ResponseDeliverTx{ - Code: CodeType_InternalError, + Code: 1, Log: "bad", } assert.True(t, res.IsErr()) - assert.Equal(t, "Internal error (1): bad", res.Error()) + assert.Equal(t, "Error code (1): bad", res.Error()) } func TestResponseCheckTx(t *testing.T) { res := ResponseCheckTx{ - Code: CodeType_OK, + Code: CodeTypeOK, Data: []byte("Talos"), } assert.False(t, res.IsErr()) res = ResponseCheckTx{ - Code: CodeType_InternalError, + Code: 1, Log: "bad", } assert.True(t, res.IsErr()) - assert.Equal(t, "Internal error (1): bad", res.Error()) + assert.Equal(t, "Error code (1): bad", res.Error()) } func TestResponseCommit(t *testing.T) { res := ResponseCommit{ - Code: CodeType_OK, + Code: CodeTypeOK, Data: []byte("Old Lace"), } assert.False(t, res.IsErr()) res = ResponseCommit{ - Code: CodeType_Unauthorized, + Code: 1, Log: "bad", } assert.True(t, res.IsErr()) - assert.Equal(t, "Unauthorized (4): bad", res.Error()) + assert.Equal(t, "Error code (1): bad", res.Error()) } diff --git a/types/types.pb.go b/types/types.pb.go index e433d198..454f8dd7 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -40,7 +40,6 @@ It has these top-level messages: Validator KVPair */ -//nolint: gas package types import proto "github.com/golang/protobuf/proto" @@ -63,114 +62,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package -type CodeType int32 - -const ( - CodeType_OK CodeType = 0 - // General response codes, 0 ~ 99 - CodeType_InternalError CodeType = 1 - CodeType_EncodingError CodeType = 2 - CodeType_BadNonce CodeType = 3 - CodeType_Unauthorized CodeType = 4 - CodeType_InsufficientFunds CodeType = 5 - CodeType_UnknownRequest CodeType = 6 - // Reserved for basecoin, 100 ~ 199 - CodeType_BaseDuplicateAddress CodeType = 101 - CodeType_BaseEncodingError CodeType = 102 - CodeType_BaseInsufficientFees CodeType = 103 - CodeType_BaseInsufficientFunds CodeType = 104 - CodeType_BaseInsufficientGasPrice CodeType = 105 - CodeType_BaseInvalidInput CodeType = 106 - CodeType_BaseInvalidOutput CodeType = 107 - CodeType_BaseInvalidPubKey CodeType = 108 - CodeType_BaseInvalidSequence CodeType = 109 - CodeType_BaseInvalidSignature CodeType = 110 - CodeType_BaseUnknownAddress CodeType = 111 - CodeType_BaseUnknownPubKey CodeType = 112 - CodeType_BaseUnknownPlugin CodeType = 113 - // Reserved for governance, 200 ~ 299 - CodeType_GovUnknownEntity CodeType = 201 - CodeType_GovUnknownGroup CodeType = 202 - CodeType_GovUnknownProposal CodeType = 203 - CodeType_GovDuplicateGroup CodeType = 204 - CodeType_GovDuplicateMember CodeType = 205 - CodeType_GovDuplicateProposal CodeType = 206 - CodeType_GovDuplicateVote CodeType = 207 - CodeType_GovInvalidMember CodeType = 208 - CodeType_GovInvalidVote CodeType = 209 - CodeType_GovInvalidVotingPower CodeType = 210 -) - -var CodeType_name = map[int32]string{ - 0: "OK", - 1: "InternalError", - 2: "EncodingError", - 3: "BadNonce", - 4: "Unauthorized", - 5: "InsufficientFunds", - 6: "UnknownRequest", - 101: "BaseDuplicateAddress", - 102: "BaseEncodingError", - 103: "BaseInsufficientFees", - 104: "BaseInsufficientFunds", - 105: "BaseInsufficientGasPrice", - 106: "BaseInvalidInput", - 107: "BaseInvalidOutput", - 108: "BaseInvalidPubKey", - 109: "BaseInvalidSequence", - 110: "BaseInvalidSignature", - 111: "BaseUnknownAddress", - 112: "BaseUnknownPubKey", - 113: "BaseUnknownPlugin", - 201: "GovUnknownEntity", - 202: "GovUnknownGroup", - 203: "GovUnknownProposal", - 204: "GovDuplicateGroup", - 205: "GovDuplicateMember", - 206: "GovDuplicateProposal", - 207: "GovDuplicateVote", - 208: "GovInvalidMember", - 209: "GovInvalidVote", - 210: "GovInvalidVotingPower", -} -var CodeType_value = map[string]int32{ - "OK": 0, - "InternalError": 1, - "EncodingError": 2, - "BadNonce": 3, - "Unauthorized": 4, - "InsufficientFunds": 5, - "UnknownRequest": 6, - "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, - "GovUnknownEntity": 201, - "GovUnknownGroup": 202, - "GovUnknownProposal": 203, - "GovDuplicateGroup": 204, - "GovDuplicateMember": 205, - "GovDuplicateProposal": 206, - "GovDuplicateVote": 207, - "GovInvalidMember": 208, - "GovInvalidVote": 209, - "GovInvalidVotingPower": 210, -} - -func (x CodeType) String() string { - return proto.EnumName(CodeType_name, int32(x)) -} -func (CodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - type KVPair_Type int32 const ( @@ -1320,7 +1211,7 @@ func (m *ResponseSetOption) GetLog() string { } type ResponseDeliverTx struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` @@ -1331,11 +1222,11 @@ func (m *ResponseDeliverTx) String() string { return proto.CompactTex func (*ResponseDeliverTx) ProtoMessage() {} func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } -func (m *ResponseDeliverTx) GetCode() CodeType { +func (m *ResponseDeliverTx) GetCode() uint32 { if m != nil { return m.Code } - return CodeType_OK + return 0 } func (m *ResponseDeliverTx) GetData() []byte { @@ -1360,11 +1251,11 @@ func (m *ResponseDeliverTx) GetTags() []*KVPair { } type ResponseCheckTx struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` - Gas uint64 `protobuf:"varint,4,opt,name=gas" json:"gas,omitempty"` - Fee uint64 `protobuf:"varint,5,opt,name=fee" json:"fee,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Gas uint64 `protobuf:"varint,4,opt,name=gas" json:"gas,omitempty"` + Fee uint64 `protobuf:"varint,5,opt,name=fee" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1372,11 +1263,11 @@ func (m *ResponseCheckTx) String() string { return proto.CompactTextS func (*ResponseCheckTx) ProtoMessage() {} func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } -func (m *ResponseCheckTx) GetCode() CodeType { +func (m *ResponseCheckTx) GetCode() uint32 { if m != nil { return m.Code } - return CodeType_OK + return 0 } func (m *ResponseCheckTx) GetData() []byte { @@ -1408,13 +1299,13 @@ func (m *ResponseCheckTx) GetFee() uint64 { } type ResponseQuery struct { - Code CodeType `protobuf:"varint,1,opt,name=code,enum=types.CodeType" json:"code,omitempty"` - Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` - 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"` + Code uint32 `protobuf:"varint,1,opt,name=code" 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{} } @@ -1422,11 +1313,11 @@ func (m *ResponseQuery) String() string { return proto.CompactTextStr func (*ResponseQuery) ProtoMessage() {} func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } -func (m *ResponseQuery) GetCode() CodeType { +func (m *ResponseQuery) GetCode() uint32 { if m != nil { return m.Code } - return CodeType_OK + return 0 } func (m *ResponseQuery) GetIndex() int64 { @@ -1472,9 +1363,9 @@ func (m *ResponseQuery) GetLog() string { } type ResponseCommit 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 uint32 `protobuf:"varint,1,opt,name=code" 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"` } func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } @@ -1482,11 +1373,11 @@ func (m *ResponseCommit) String() string { return proto.CompactTextSt func (*ResponseCommit) ProtoMessage() {} func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } -func (m *ResponseCommit) GetCode() CodeType { +func (m *ResponseCommit) GetCode() uint32 { if m != nil { return m.Code } - return CodeType_OK + return 0 } func (m *ResponseCommit) GetData() []byte { @@ -1758,7 +1649,6 @@ func init() { proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterType((*KVPair)(nil), "types.KVPair") - proto.RegisterEnum("types.CodeType", CodeType_name, CodeType_value) proto.RegisterEnum("types.KVPair_Type", KVPair_Type_name, KVPair_Type_value) } @@ -2167,115 +2057,93 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1755 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x49, 0x6f, 0xdb, 0xce, - 0x15, 0x37, 0x25, 0x6a, 0x7b, 0x96, 0x65, 0x7a, 0x2c, 0xdb, 0xb2, 0xd2, 0x43, 0xc2, 0x22, 0x8d, - 0x9d, 0xa6, 0x4e, 0xeb, 0x20, 0x45, 0xdc, 0x14, 0x05, 0xbc, 0xc5, 0x16, 0x82, 0x3a, 0x2e, 0xed, - 0xe4, 0xd2, 0x83, 0x40, 0x8b, 0x23, 0x69, 0x6a, 0x69, 0xc8, 0x90, 0x43, 0x47, 0xee, 0xa9, 0xbd, - 0xe7, 0xde, 0x8f, 0x50, 0xa0, 0xc7, 0x02, 0xfd, 0x0a, 0x05, 0xfe, 0xfb, 0xf2, 0x89, 0xfe, 0x98, - 0x85, 0xab, 0xa9, 0xe0, 0x7f, 0xc8, 0x85, 0x98, 0xb7, 0xcd, 0xbc, 0x99, 0x79, 0xef, 0xf7, 0x1e, - 0x07, 0x56, 0xd8, 0xad, 0x87, 0x83, 0xa7, 0xe2, 0xbb, 0xe3, 0xf9, 0x2e, 0x73, 0x51, 0x45, 0x10, - 0xe6, 0xff, 0x75, 0xa8, 0x59, 0xf8, 0x7d, 0x88, 0x03, 0x86, 0xb6, 0x40, 0xc7, 0x83, 0xb1, 0xdb, - 0xd1, 0xee, 0x6b, 0x5b, 0x8b, 0xbb, 0x68, 0x47, 0xaa, 0x2b, 0xe9, 0xf1, 0x60, 0xec, 0x9e, 0x2e, - 0x58, 0x42, 0x03, 0xfd, 0x1a, 0x2a, 0xc3, 0x49, 0x18, 0x8c, 0x3b, 0x25, 0xa1, 0xba, 0x9a, 0x55, - 0x7d, 0xc5, 0x45, 0xa7, 0x0b, 0x96, 0xd4, 0xe1, 0xd3, 0x12, 0x3a, 0x74, 0x3b, 0xe5, 0xa2, 0x69, - 0x7b, 0x74, 0x28, 0xa6, 0xe5, 0x1a, 0xe8, 0x05, 0x40, 0x80, 0x59, 0xdf, 0xf5, 0x18, 0x71, 0x69, - 0x47, 0x17, 0xfa, 0x1b, 0x59, 0xfd, 0x0b, 0xcc, 0xde, 0x08, 0xf1, 0xe9, 0x82, 0xd5, 0x08, 0x22, - 0x82, 0x5b, 0x3a, 0x78, 0x42, 0x6e, 0xb0, 0xdf, 0x67, 0xb3, 0x4e, 0xa5, 0xc8, 0xf2, 0x48, 0xca, - 0x2f, 0x67, 0xdc, 0xd2, 0x89, 0x08, 0xb4, 0x0b, 0xf5, 0xc1, 0x18, 0x0f, 0xae, 0xb9, 0x5d, 0x55, - 0xd8, 0xad, 0x65, 0xed, 0x0e, 0xb9, 0x54, 0x58, 0xd5, 0x06, 0x72, 0x88, 0x76, 0xa0, 0x3a, 0x70, - 0xa7, 0x53, 0xc2, 0x3a, 0x35, 0x61, 0xd1, 0xce, 0x59, 0x08, 0xd9, 0xe9, 0x82, 0xa5, 0xb4, 0xf8, - 0x71, 0xbd, 0x0f, 0xb1, 0x7f, 0xdb, 0xa9, 0x17, 0x1d, 0xd7, 0x5f, 0xb8, 0x88, 0x1f, 0x97, 0xd0, - 0xe1, 0x5b, 0x21, 0x94, 0xb0, 0xfe, 0x60, 0x6c, 0x13, 0xda, 0x69, 0x14, 0x6d, 0xa5, 0x47, 0x09, - 0x3b, 0xe4, 0x62, 0xbe, 0x15, 0x12, 0x11, 0xe8, 0x25, 0x2c, 0x5e, 0xe1, 0x11, 0xa1, 0xfd, 0xab, - 0x89, 0x3b, 0xb8, 0xee, 0x80, 0x30, 0xed, 0x64, 0x4d, 0x0f, 0xb8, 0xc2, 0x01, 0x97, 0x9f, 0x2e, - 0x58, 0x70, 0x15, 0x53, 0xe8, 0x39, 0x34, 0x30, 0x75, 0x94, 0xe9, 0xa2, 0x30, 0x5d, 0xcf, 0x45, - 0x00, 0x75, 0x22, 0xc3, 0x3a, 0x56, 0xe3, 0x83, 0x1a, 0x54, 0x6e, 0xec, 0x49, 0x88, 0xcd, 0x47, - 0xb0, 0x98, 0x8a, 0x14, 0xd4, 0x81, 0xda, 0x14, 0x07, 0x81, 0x3d, 0xc2, 0x22, 0x9c, 0x1a, 0x56, - 0x44, 0x9a, 0x2d, 0x68, 0xa6, 0xe3, 0x24, 0x65, 0xc8, 0x63, 0x81, 0x1b, 0xde, 0x60, 0x3f, 0xe0, - 0x01, 0xa0, 0x0c, 0x15, 0x69, 0xfe, 0x01, 0x8c, 0x7c, 0x10, 0x20, 0x03, 0xca, 0xd7, 0xf8, 0x56, - 0x69, 0xf2, 0x21, 0x6a, 0x2b, 0x87, 0x44, 0x68, 0x36, 0x2c, 0xe5, 0x9d, 0x19, 0xdb, 0xc6, 0x61, - 0x80, 0x5a, 0x50, 0x62, 0x33, 0x61, 0xda, 0xb4, 0x4a, 0x6c, 0x66, 0xde, 0x87, 0x56, 0xf6, 0xca, - 0xef, 0x68, 0x38, 0xb1, 0xeb, 0xe2, 0xce, 0x10, 0x02, 0xdd, 0xb1, 0x99, 0xad, 0x34, 0xc4, 0x98, - 0xf3, 0x3c, 0x9b, 0x8d, 0xd5, 0xf2, 0x62, 0x8c, 0xd6, 0xa1, 0x3a, 0xc6, 0x64, 0x34, 0x66, 0x22, - 0x07, 0x74, 0x4b, 0x51, 0xdc, 0x57, 0xcf, 0x77, 0x6f, 0xb0, 0x08, 0xf5, 0xba, 0x25, 0x09, 0x73, - 0x19, 0x96, 0x32, 0x81, 0x64, 0x1e, 0xc5, 0xce, 0xc7, 0x17, 0x8f, 0x7e, 0x0b, 0x70, 0x63, 0x4f, - 0x88, 0x63, 0x33, 0xd7, 0x0f, 0x3a, 0xda, 0xfd, 0xf2, 0xd6, 0xe2, 0xae, 0xa1, 0xee, 0xeb, 0x5d, - 0x24, 0xb0, 0x52, 0x3a, 0xe6, 0x19, 0xac, 0xdc, 0x89, 0x01, 0xee, 0xed, 0xd8, 0x0e, 0xc6, 0xd1, - 0x0e, 0xf8, 0x18, 0x3d, 0xe4, 0xde, 0xda, 0x0e, 0xf6, 0x55, 0x76, 0x2f, 0xa9, 0x69, 0x4f, 0x05, - 0xd3, 0x52, 0x42, 0x73, 0x1b, 0x96, 0x73, 0x81, 0x91, 0xda, 0xa7, 0x96, 0xde, 0xa7, 0xf9, 0xb1, - 0x02, 0x75, 0x0b, 0x07, 0x9e, 0x4b, 0x03, 0x8c, 0x5e, 0x40, 0x03, 0xcf, 0x06, 0x58, 0xe6, 0xb8, - 0x96, 0x8b, 0x51, 0xa9, 0x73, 0x1c, 0xc9, 0x79, 0x7c, 0xc7, 0xca, 0x68, 0x5b, 0xe1, 0x53, 0x1e, - 0x74, 0x94, 0x51, 0x1a, 0xa0, 0x9e, 0x44, 0x00, 0x55, 0xce, 0x25, 0xa8, 0xd4, 0xcd, 0x21, 0xd4, - 0xb6, 0x42, 0x28, 0xbd, 0x70, 0xe2, 0x0c, 0x44, 0xed, 0x65, 0x20, 0xaa, 0x52, 0xe8, 0xfe, 0x1c, - 0x8c, 0xda, 0xcb, 0x60, 0x54, 0xb5, 0xd0, 0x74, 0x0e, 0x48, 0x3d, 0x4b, 0x81, 0x54, 0x2d, 0x97, - 0x9b, 0xd2, 0xb0, 0x00, 0xa5, 0x9e, 0xc6, 0x28, 0x55, 0xcf, 0xe1, 0x9a, 0x32, 0xc9, 0xc3, 0xd4, - 0x93, 0x08, 0xa6, 0x1a, 0x85, 0x87, 0x96, 0xc3, 0xa9, 0xbd, 0x0c, 0x4e, 0x41, 0xe1, 0x76, 0xe6, - 0x00, 0xd5, 0x1f, 0xb3, 0x40, 0x25, 0xd1, 0x66, 0x33, 0x67, 0x3b, 0x17, 0xa9, 0x7e, 0x9f, 0x46, - 0xaa, 0x66, 0x0e, 0x1f, 0x55, 0x2c, 0x7c, 0x12, 0xaa, 0xb6, 0x79, 0x26, 0xe4, 0x22, 0x8d, 0xe7, - 0x22, 0xf6, 0x7d, 0xd7, 0x57, 0x58, 0x22, 0x09, 0x73, 0x8b, 0x67, 0x7c, 0x12, 0x5f, 0x9f, 0x80, - 0x35, 0x91, 0xb5, 0xa9, 0xe8, 0x32, 0xff, 0xa5, 0x25, 0xb6, 0x02, 0xd9, 0xd2, 0x68, 0xd1, 0x50, - 0x68, 0x91, 0x42, 0xbb, 0x52, 0x06, 0xed, 0xd0, 0x63, 0x58, 0x99, 0xd8, 0x01, 0x93, 0xdb, 0xec, - 0x67, 0xe0, 0x63, 0x99, 0x0b, 0xe4, 0xfe, 0x24, 0x8e, 0xfc, 0x06, 0x56, 0x53, 0xba, 0xb6, 0xe7, - 0xf5, 0x45, 0x52, 0xeb, 0x22, 0xa9, 0x8d, 0x58, 0x7b, 0xdf, 0xf3, 0x4e, 0xed, 0x60, 0x6c, 0x3e, - 0x4c, 0xf6, 0x9f, 0x41, 0xd2, 0x89, 0x3b, 0x8a, 0x90, 0x74, 0xe2, 0x8e, 0xcc, 0x7f, 0x6a, 0x89, - 0x5e, 0x82, 0x9a, 0xbf, 0x04, 0x7d, 0xe0, 0x3a, 0x72, 0xfb, 0xad, 0xdd, 0x65, 0x75, 0xf0, 0x87, - 0xae, 0x83, 0x2f, 0x6f, 0x3d, 0x6c, 0x09, 0x61, 0xbc, 0xd5, 0x52, 0x0a, 0x18, 0xd5, 0x02, 0xe5, - 0x78, 0x01, 0xf4, 0x00, 0x74, 0x66, 0x8f, 0x82, 0x8e, 0x2e, 0xd0, 0x2b, 0x82, 0x99, 0xd7, 0xef, - 0xce, 0x6d, 0xe2, 0x5b, 0x42, 0x64, 0xfe, 0x43, 0xe3, 0x28, 0x93, 0x09, 0xf1, 0xcf, 0xe9, 0x81, - 0x01, 0xe5, 0x91, 0x1d, 0x88, 0x83, 0xd2, 0x2d, 0x3e, 0xe4, 0x9c, 0x21, 0xc6, 0x22, 0xb1, 0x75, - 0x8b, 0x0f, 0xcd, 0xff, 0x6a, 0xc9, 0xcd, 0x4a, 0xd8, 0xff, 0x59, 0x0e, 0xb4, 0xa1, 0x42, 0xa8, - 0x83, 0x67, 0xc2, 0x83, 0xb2, 0x25, 0x89, 0xa8, 0x5e, 0x95, 0x85, 0x57, 0xd9, 0x7a, 0x25, 0x6f, - 0x4b, 0x12, 0xaa, 0x32, 0xb8, 0x43, 0xe1, 0x48, 0xd3, 0x92, 0x44, 0x0a, 0x5f, 0xab, 0x99, 0x3a, - 0xa2, 0x36, 0x56, 0x4b, 0xee, 0xee, 0xaf, 0xbc, 0x96, 0xa5, 0xd3, 0xfc, 0x33, 0x9e, 0x9a, 0xb9, - 0x9a, 0xc4, 0x45, 0x9c, 0xe0, 0x66, 0x1b, 0xd0, 0xdd, 0xcc, 0x95, 0x35, 0x3b, 0x9b, 0x93, 0xe8, - 0x57, 0x50, 0x71, 0xc8, 0x70, 0x38, 0xbf, 0x6a, 0x49, 0xb1, 0xf9, 0xef, 0x12, 0x54, 0x65, 0xcd, - 0x41, 0x9b, 0x1c, 0xff, 0x6c, 0x42, 0xfb, 0xc4, 0x89, 0xf2, 0x4e, 0xd0, 0x3d, 0x27, 0x75, 0x26, - 0xa5, 0xcc, 0x99, 0x20, 0xd0, 0x19, 0x99, 0x62, 0x95, 0x32, 0x62, 0x8c, 0x36, 0xa0, 0x46, 0xc3, - 0x69, 0x9f, 0xcd, 0xa2, 0x2b, 0xaf, 0xd2, 0x70, 0x7a, 0x39, 0x0b, 0xd0, 0x2e, 0x2c, 0xa5, 0x12, - 0x88, 0x38, 0x0a, 0xd8, 0x5b, 0xca, 0x35, 0xe1, 0x77, 0xef, 0xc8, 0x5a, 0x8c, 0x53, 0xa9, 0xe7, - 0xa0, 0x2d, 0x10, 0x99, 0xd5, 0x97, 0xe0, 0x29, 0x33, 0xae, 0x2a, 0xce, 0xad, 0xc5, 0xf9, 0x0a, - 0x5d, 0x79, 0x41, 0xbd, 0x07, 0x0d, 0x7e, 0x92, 0x52, 0xa5, 0x26, 0x54, 0xea, 0x9c, 0x21, 0x84, - 0x8f, 0x60, 0x39, 0x29, 0xd2, 0x52, 0xa5, 0x2e, 0x67, 0x49, 0xd8, 0x42, 0x71, 0x13, 0xea, 0x71, - 0x66, 0x37, 0x84, 0x46, 0xcd, 0x56, 0x09, 0xdd, 0x83, 0x9a, 0x72, 0xb1, 0xb0, 0xa0, 0x3f, 0x86, - 0x8a, 0x67, 0xfb, 0x2c, 0x50, 0x85, 0x33, 0xc2, 0xf5, 0x73, 0xdb, 0xe7, 0x9d, 0x94, 0x2a, 0xeb, - 0x52, 0xc5, 0xdc, 0x83, 0xa5, 0x0c, 0x9f, 0x47, 0x22, 0x73, 0x99, 0x3d, 0x51, 0x25, 0x5d, 0x12, - 0xf1, 0x32, 0xa5, 0x64, 0x19, 0x73, 0x0f, 0x1a, 0xf1, 0x1d, 0xf2, 0x6b, 0xf1, 0xc2, 0xab, 0xd7, - 0xaa, 0x37, 0x6b, 0x5a, 0x8a, 0x12, 0x81, 0xed, 0x7e, 0x50, 0xbd, 0x85, 0x6e, 0x49, 0xc2, 0xfc, - 0x8f, 0x06, 0x55, 0x99, 0xf7, 0x05, 0x1d, 0xdd, 0xef, 0x44, 0xab, 0x13, 0xe2, 0x3e, 0x77, 0x5b, - 0xd8, 0xb5, 0xe2, 0xbf, 0x08, 0x69, 0xb4, 0x23, 0x42, 0xb8, 0x21, 0xb4, 0xf8, 0x10, 0x3d, 0x80, - 0xa6, 0x34, 0x09, 0x98, 0x4f, 0x68, 0x14, 0xbc, 0x8b, 0x82, 0x77, 0x21, 0x58, 0xfc, 0x52, 0xa4, - 0x0a, 0xa1, 0x4c, 0x44, 0x43, 0xd9, 0xaa, 0x0b, 0x46, 0x8f, 0x32, 0xf3, 0x1e, 0xe8, 0x62, 0x1e, - 0x80, 0xea, 0xc5, 0xa5, 0xd5, 0x3b, 0x3b, 0x31, 0x16, 0x50, 0x0d, 0xca, 0xbd, 0xb3, 0x4b, 0x43, - 0x7b, 0xfc, 0xbf, 0x0a, 0xd4, 0xa3, 0xbc, 0x41, 0x55, 0x28, 0xbd, 0x79, 0x6d, 0x2c, 0xa0, 0x15, - 0x58, 0xea, 0x51, 0x86, 0x7d, 0x6a, 0x4f, 0x8e, 0x79, 0xe5, 0x30, 0x34, 0xce, 0x3a, 0xa6, 0x03, - 0xd7, 0x21, 0x74, 0x24, 0x59, 0x25, 0xd4, 0x84, 0xfa, 0x81, 0xed, 0x9c, 0xb9, 0x74, 0x80, 0x8d, - 0x32, 0x32, 0xa0, 0xf9, 0x96, 0xda, 0x21, 0x1b, 0xbb, 0x3e, 0xf9, 0x3b, 0x76, 0x0c, 0x1d, 0xad, - 0xc1, 0x4a, 0x8f, 0x06, 0xe1, 0x70, 0x48, 0x06, 0x04, 0x53, 0xf6, 0x2a, 0xa4, 0x4e, 0x60, 0x54, - 0x10, 0x82, 0xd6, 0x5b, 0x7a, 0x4d, 0xdd, 0x0f, 0x54, 0x75, 0x5c, 0x46, 0x15, 0x75, 0xa0, 0x7d, - 0x60, 0x07, 0xf8, 0x28, 0xf4, 0x26, 0x64, 0x60, 0x33, 0xbc, 0xef, 0x38, 0x3e, 0x0e, 0x02, 0x03, - 0xf3, 0x49, 0xb8, 0x24, 0xbb, 0xf6, 0x30, 0x32, 0xc8, 0xcc, 0x8f, 0x71, 0x60, 0x8c, 0xd0, 0x26, - 0xac, 0xdd, 0x91, 0x88, 0x95, 0xc7, 0xe8, 0x17, 0xd0, 0xc9, 0x8b, 0x4e, 0xec, 0xe0, 0xdc, 0x27, - 0x03, 0x6c, 0x10, 0xd4, 0x06, 0x43, 0x4a, 0x45, 0xa8, 0xf6, 0xa8, 0x17, 0x32, 0xe3, 0x6f, 0xd1, - 0xfa, 0x8a, 0xfb, 0x26, 0x64, 0x9c, 0x7d, 0x9d, 0x63, 0x9f, 0x8b, 0x70, 0x30, 0x26, 0x68, 0x03, - 0x56, 0x53, 0xec, 0x0b, 0xbe, 0x3f, 0x7e, 0x3a, 0xd3, 0xc4, 0x5f, 0x29, 0x20, 0x23, 0x6a, 0xb3, - 0xd0, 0xc7, 0x06, 0x45, 0xeb, 0x80, 0xb8, 0x44, 0x1d, 0x49, 0xb4, 0x71, 0x37, 0x5a, 0x41, 0xf1, - 0xd5, 0x0a, 0x5e, 0x9e, 0x3d, 0x09, 0x47, 0x84, 0x1a, 0xef, 0xd1, 0x1a, 0x18, 0x27, 0xee, 0x8d, - 0xe2, 0x1e, 0x53, 0x46, 0xd8, 0xad, 0xf1, 0x85, 0x86, 0xda, 0xb0, 0x9c, 0xb0, 0x4f, 0x7c, 0x37, - 0xf4, 0x8c, 0x2f, 0x35, 0xb4, 0x01, 0x28, 0xe1, 0x9e, 0xfb, 0xae, 0xe7, 0x06, 0xf6, 0xc4, 0xf8, - 0x4a, 0x43, 0xeb, 0xb0, 0x72, 0xe2, 0xde, 0xc4, 0xb7, 0x20, 0x0d, 0xbe, 0x8e, 0x0c, 0x62, 0xfe, - 0x9f, 0xf1, 0xf4, 0x0a, 0xfb, 0xc6, 0x37, 0x1a, 0xda, 0x84, 0x76, 0x5a, 0x10, 0xcf, 0xf5, 0xad, - 0xa6, 0x3c, 0x8a, 0x45, 0xef, 0x5c, 0x86, 0x8d, 0xef, 0x22, 0xb6, 0x3a, 0x07, 0x35, 0xd1, 0xf7, - 0x1a, 0x5a, 0x85, 0x56, 0xc2, 0x16, 0xba, 0x3f, 0x68, 0xa8, 0x0b, 0x6b, 0x19, 0x26, 0xa1, 0xa3, - 0x73, 0x9e, 0x61, 0xc6, 0x8f, 0xda, 0xee, 0xc7, 0x0a, 0x2c, 0xef, 0x1f, 0x1c, 0xf6, 0xf6, 0x3d, - 0xb9, 0x00, 0xaf, 0xfa, 0x4f, 0x41, 0x17, 0x7d, 0x4d, 0xc1, 0xcf, 0x7e, 0xb7, 0xa8, 0xc1, 0x46, - 0xbb, 0x50, 0x11, 0xed, 0x0d, 0x2a, 0xfa, 0xe7, 0xef, 0x16, 0xf6, 0xd9, 0x7c, 0x11, 0xd9, 0x00, - 0xdd, 0xfd, 0xf5, 0xef, 0x16, 0x35, 0xdb, 0xe8, 0x4f, 0xd0, 0x48, 0x1a, 0x93, 0x79, 0x0f, 0x00, - 0xdd, 0xb9, 0x6d, 0x37, 0xb7, 0x4f, 0x1a, 0x96, 0x79, 0xcf, 0x00, 0xdd, 0xb9, 0xbd, 0x37, 0x7a, - 0x01, 0xb5, 0xa8, 0xd9, 0x28, 0x7e, 0x0c, 0xe8, 0xce, 0x69, 0xbf, 0xf9, 0xf1, 0xc8, 0x1e, 0xa1, - 0xe8, 0x1f, 0xbf, 0x5b, 0xd8, 0x51, 0xa3, 0xe7, 0x50, 0x55, 0x35, 0xba, 0xf0, 0x1d, 0xa1, 0x5b, - 0xdc, 0xb7, 0xf3, 0x4d, 0x26, 0xbf, 0x83, 0xf3, 0x1e, 0x08, 0xba, 0x73, 0x3b, 0x72, 0xb4, 0x0f, - 0x90, 0xfa, 0x11, 0x9c, 0xfb, 0x4c, 0xd0, 0x9d, 0xdf, 0x97, 0xa3, 0x97, 0x50, 0x4f, 0xfe, 0xfd, - 0x8a, 0x1f, 0x0b, 0xba, 0xf3, 0x5a, 0xf3, 0xab, 0xaa, 0x78, 0x87, 0x7a, 0xf6, 0x53, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x3c, 0xa1, 0xc6, 0x00, 0x9c, 0x12, 0x00, 0x00, + // 1395 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x97, 0x4b, 0x6f, 0xdb, 0x46, + 0x10, 0x80, 0x2d, 0x89, 0x7a, 0x70, 0xe4, 0x87, 0xb2, 0x71, 0x13, 0x46, 0xb9, 0x24, 0x04, 0xd2, + 0xd8, 0x69, 0xea, 0xb4, 0x0e, 0x52, 0xc4, 0x4d, 0x51, 0xc0, 0x4e, 0xd2, 0x4a, 0x0d, 0x90, 0xa6, + 0x1b, 0x23, 0x57, 0x81, 0x16, 0x57, 0x12, 0x61, 0x99, 0x64, 0xc8, 0x95, 0x2b, 0xff, 0x87, 0xdc, + 0x7b, 0xee, 0xa9, 0x40, 0x7f, 0x48, 0x7f, 0x57, 0x31, 0xb3, 0xcb, 0xa7, 0xc9, 0x1c, 0xda, 0x0b, + 0xb1, 0xb3, 0x33, 0xb3, 0xdc, 0xc7, 0xcc, 0xb7, 0xb3, 0x70, 0x43, 0x5e, 0x85, 0x22, 0x7e, 0x42, + 0xdf, 0x83, 0x30, 0x0a, 0x64, 0xc0, 0xda, 0x24, 0xd8, 0xff, 0x18, 0xd0, 0xe5, 0xe2, 0xe3, 0x4a, + 0xc4, 0x92, 0xed, 0x81, 0x21, 0xa6, 0x8b, 0xc0, 0x6a, 0xdc, 0x6b, 0xec, 0xf5, 0x0f, 0xd9, 0x81, + 0x32, 0xd7, 0xda, 0xd7, 0xd3, 0x45, 0x30, 0xda, 0xe0, 0x64, 0xc1, 0xbe, 0x82, 0xf6, 0x6c, 0xb9, + 0x8a, 0x17, 0x56, 0x93, 0x4c, 0x6f, 0x16, 0x4d, 0x7f, 0x42, 0xd5, 0x68, 0x83, 0x2b, 0x1b, 0x1c, + 0xd6, 0xf3, 0x67, 0x81, 0xd5, 0xaa, 0x1a, 0x76, 0xec, 0xcf, 0x68, 0x58, 0xb4, 0x60, 0xcf, 0x01, + 0x62, 0x21, 0x27, 0x41, 0x28, 0xbd, 0xc0, 0xb7, 0x0c, 0xb2, 0xbf, 0x5d, 0xb4, 0x7f, 0x2f, 0xe4, + 0xaf, 0xa4, 0x1e, 0x6d, 0x70, 0x33, 0x4e, 0x04, 0xf4, 0x74, 0xc5, 0xd2, 0xbb, 0x14, 0xd1, 0x44, + 0xae, 0xad, 0x76, 0x95, 0xe7, 0x2b, 0xa5, 0x3f, 0x5d, 0xa3, 0xa7, 0x9b, 0x08, 0xec, 0x10, 0x7a, + 0xd3, 0x85, 0x98, 0x9e, 0xa3, 0x5f, 0x87, 0xfc, 0xbe, 0x28, 0xfa, 0xbd, 0x44, 0x2d, 0x79, 0x75, + 0xa7, 0xaa, 0xc9, 0x0e, 0xa0, 0x33, 0x0d, 0x2e, 0x2e, 0x3c, 0x69, 0x75, 0xc9, 0x63, 0xb7, 0xe4, + 0x41, 0xba, 0xd1, 0x06, 0xd7, 0x56, 0xb8, 0x5d, 0x1f, 0x57, 0x22, 0xba, 0xb2, 0x7a, 0x55, 0xdb, + 0xf5, 0x1b, 0xaa, 0x70, 0xbb, 0xc8, 0x06, 0x97, 0xe2, 0xf9, 0x9e, 0x9c, 0x4c, 0x17, 0x8e, 0xe7, + 0x5b, 0x66, 0xd5, 0x52, 0xc6, 0xbe, 0x27, 0x5f, 0xa2, 0x1a, 0x97, 0xe2, 0x25, 0x02, 0x7b, 0x01, + 0xfd, 0x33, 0x31, 0xf7, 0xfc, 0xc9, 0xd9, 0x32, 0x98, 0x9e, 0x5b, 0x40, 0xae, 0x56, 0xd1, 0xf5, + 0x04, 0x0d, 0x4e, 0x50, 0x3f, 0xda, 0xe0, 0x70, 0x96, 0x4a, 0xec, 0x19, 0x98, 0xc2, 0x77, 0xb5, + 0x6b, 0x9f, 0x5c, 0x6f, 0x95, 0x22, 0xc0, 0x77, 0x13, 0xc7, 0x9e, 0xd0, 0xed, 0x93, 0x2e, 0xb4, + 0x2f, 0x9d, 0xe5, 0x4a, 0xd8, 0x0f, 0xa1, 0x9f, 0x8b, 0x14, 0x66, 0x41, 0xf7, 0x42, 0xc4, 0xb1, + 0x33, 0x17, 0x14, 0x4e, 0x26, 0x4f, 0x44, 0x7b, 0x1b, 0x36, 0xf3, 0x71, 0x92, 0x73, 0xc4, 0x58, + 0x40, 0xc7, 0x4b, 0x11, 0xc5, 0x18, 0x00, 0xda, 0x51, 0x8b, 0xf6, 0xf7, 0x30, 0x28, 0x07, 0x01, + 0x1b, 0x40, 0xeb, 0x5c, 0x5c, 0x69, 0x4b, 0x6c, 0xb2, 0x5d, 0x3d, 0x21, 0x0a, 0x4d, 0x93, 0xeb, + 0xd9, 0xd9, 0xa9, 0x6f, 0x1a, 0x06, 0x6c, 0x1b, 0x9a, 0x72, 0x4d, 0xae, 0x9b, 0xbc, 0x29, 0xd7, + 0xf6, 0x3d, 0xd8, 0x2e, 0x1e, 0xf9, 0x35, 0x0b, 0x37, 0x9d, 0x3a, 0x9d, 0x19, 0x63, 0x60, 0xb8, + 0x8e, 0x74, 0xb4, 0x05, 0xb5, 0xb1, 0x2f, 0x74, 0xe4, 0x42, 0xff, 0x9e, 0xda, 0xec, 0x16, 0x74, + 0x16, 0xc2, 0x9b, 0x2f, 0x24, 0xe5, 0x80, 0xc1, 0xb5, 0x84, 0x73, 0x0d, 0xa3, 0xe0, 0x52, 0x50, + 0xa8, 0xf7, 0xb8, 0x12, 0xec, 0x1d, 0xd8, 0x2a, 0x04, 0x92, 0xfd, 0x2a, 0x9d, 0x7c, 0x7a, 0xf0, + 0xec, 0x1b, 0x80, 0x4b, 0x67, 0xe9, 0xb9, 0x8e, 0x0c, 0xa2, 0xd8, 0x6a, 0xdc, 0x6b, 0xed, 0xf5, + 0x0f, 0x07, 0xfa, 0xbc, 0x3e, 0x24, 0x0a, 0x9e, 0xb3, 0xb1, 0xdf, 0xc2, 0x8d, 0x6b, 0x31, 0x80, + 0xb3, 0x5d, 0x38, 0xf1, 0x22, 0x59, 0x01, 0xb6, 0xd9, 0x03, 0x9c, 0xad, 0xe3, 0x8a, 0x48, 0x67, + 0xf7, 0x96, 0x1e, 0x76, 0x44, 0x9d, 0x5c, 0x2b, 0xed, 0x7d, 0xd8, 0x29, 0x05, 0x46, 0x6e, 0x9d, + 0x8d, 0xfc, 0x3a, 0xed, 0x4f, 0x6d, 0xe8, 0x71, 0x11, 0x87, 0x81, 0x1f, 0x0b, 0xf6, 0x1c, 0x4c, + 0xb1, 0x9e, 0x0a, 0x95, 0xe3, 0x8d, 0x52, 0x8c, 0x2a, 0x9b, 0xd7, 0x89, 0x1e, 0xe3, 0x3b, 0x35, + 0x66, 0xfb, 0x9a, 0x4f, 0x65, 0xe8, 0x68, 0xa7, 0x3c, 0xa0, 0x1e, 0x27, 0x80, 0x6a, 0x95, 0x12, + 0x54, 0xd9, 0x96, 0x08, 0xb5, 0xaf, 0x09, 0x65, 0x54, 0x0e, 0x5c, 0x40, 0xd4, 0x51, 0x01, 0x51, + 0xed, 0xca, 0xe9, 0xd7, 0x30, 0xea, 0xa8, 0xc0, 0xa8, 0x4e, 0xa5, 0x6b, 0x0d, 0xa4, 0x9e, 0xe6, + 0x20, 0xd5, 0x2d, 0xe5, 0xa6, 0x72, 0xac, 0xa0, 0xd4, 0x93, 0x94, 0x52, 0xbd, 0x12, 0xd7, 0xb4, + 0x4b, 0x19, 0x53, 0x8f, 0x13, 0x4c, 0x99, 0x95, 0x9b, 0x56, 0xe2, 0xd4, 0x51, 0x81, 0x53, 0x50, + 0xb9, 0x9c, 0x1a, 0x50, 0xfd, 0x50, 0x04, 0x95, 0xa2, 0xcd, 0x9d, 0x92, 0x6f, 0x2d, 0xa9, 0xbe, + 0xcb, 0x93, 0x6a, 0xb3, 0xc4, 0x47, 0x1d, 0x0b, 0x9f, 0x45, 0xd5, 0x3e, 0x66, 0x42, 0x29, 0xd2, + 0x30, 0x17, 0x45, 0x14, 0x05, 0x91, 0x66, 0x89, 0x12, 0xec, 0x3d, 0xcc, 0xf8, 0x2c, 0xbe, 0x3e, + 0x83, 0x35, 0xca, 0xda, 0x5c, 0x74, 0xd9, 0x7f, 0x34, 0x32, 0x5f, 0x22, 0x5b, 0x9e, 0x16, 0xa6, + 0xa6, 0x45, 0x8e, 0x76, 0xcd, 0x02, 0xed, 0xd8, 0x23, 0xb8, 0xb1, 0x74, 0x62, 0xa9, 0x96, 0x39, + 0x29, 0xe0, 0x63, 0x07, 0x15, 0x6a, 0x7d, 0x8a, 0x23, 0x5f, 0xc3, 0xcd, 0x9c, 0xad, 0x13, 0x86, + 0x13, 0x4a, 0x6a, 0x83, 0x92, 0x7a, 0x90, 0x5a, 0x1f, 0x87, 0xe1, 0xc8, 0x89, 0x17, 0xf6, 0x83, + 0x6c, 0xfd, 0x05, 0x92, 0x2e, 0x83, 0x79, 0x42, 0xd2, 0x65, 0x30, 0xb7, 0xc3, 0xcc, 0x2c, 0x83, + 0x26, 0x03, 0x63, 0x1a, 0xb8, 0x6a, 0xf5, 0x5b, 0x9c, 0xda, 0xe9, 0xc2, 0x9a, 0x39, 0x0c, 0xea, + 0xe1, 0x5a, 0xe9, 0x70, 0xec, 0x3e, 0x18, 0xd2, 0x99, 0xc7, 0x96, 0x41, 0xac, 0x4a, 0xa0, 0xf2, + 0xe6, 0xc3, 0x3b, 0xc7, 0x8b, 0x38, 0xa9, 0xec, 0x00, 0x91, 0x52, 0x88, 0xe7, 0xff, 0xf1, 0xbf, + 0x01, 0xb4, 0xe6, 0x4e, 0x4c, 0x9b, 0x60, 0x70, 0x6c, 0x62, 0xcf, 0x4c, 0x08, 0x4a, 0x5a, 0x83, + 0x63, 0xd3, 0xfe, 0xb3, 0x91, 0x9d, 0x5a, 0x8a, 0xf4, 0x6b, 0xff, 0xdb, 0x85, 0xb6, 0xe7, 0xbb, + 0x62, 0x4d, 0x3f, 0x6c, 0x71, 0x25, 0x24, 0x57, 0x4f, 0x8b, 0x26, 0x51, 0xbc, 0x7a, 0xd4, 0xc6, + 0x2b, 0x41, 0x43, 0x3e, 0x98, 0xd1, 0x7f, 0x37, 0xb9, 0x12, 0x72, 0xa8, 0xec, 0x14, 0xae, 0x04, + 0xbd, 0x8e, 0x6e, 0x76, 0x0c, 0xbf, 0xe0, 0xb5, 0x94, 0xcf, 0xd8, 0xff, 0xbe, 0x27, 0xf6, 0xcd, + 0xec, 0x48, 0xd3, 0xd4, 0xb4, 0x77, 0x81, 0x5d, 0xcf, 0x39, 0x75, 0xdb, 0x16, 0xb3, 0x89, 0x7d, + 0x09, 0x6d, 0xd7, 0x9b, 0xcd, 0xea, 0xef, 0x1b, 0xa5, 0xb6, 0xff, 0x6a, 0x42, 0x47, 0xdd, 0x16, + 0xec, 0x0e, 0x92, 0xcb, 0xf1, 0xfc, 0x89, 0xe7, 0x26, 0x19, 0x43, 0xf2, 0xd8, 0xcd, 0x6d, 0x41, + 0xb3, 0xb0, 0x05, 0x0c, 0x0c, 0xe9, 0x5d, 0x08, 0x1d, 0xec, 0xd4, 0x66, 0xb7, 0xa1, 0xeb, 0xaf, + 0x2e, 0x26, 0x72, 0x9d, 0x1c, 0x68, 0xc7, 0x5f, 0x5d, 0x9c, 0xae, 0x63, 0x76, 0x08, 0x5b, 0xb9, + 0xd0, 0xf7, 0x5c, 0x8d, 0xe4, 0x6d, 0x3d, 0x35, 0x9a, 0xf7, 0xf8, 0x15, 0xef, 0xa7, 0x49, 0x30, + 0x76, 0xd9, 0x1e, 0x50, 0x4e, 0x4c, 0x14, 0xf6, 0x54, 0xae, 0x74, 0x68, 0xdf, 0xb6, 0xb1, 0x5f, + 0x73, 0x11, 0xaf, 0xc2, 0xbb, 0x60, 0xe2, 0x4e, 0x2a, 0x93, 0x2e, 0x99, 0xf4, 0xb0, 0x83, 0x94, + 0x0f, 0x61, 0x27, 0xbb, 0x5e, 0x95, 0x49, 0x4f, 0x8d, 0x92, 0x75, 0x93, 0xe1, 0x1d, 0xe8, 0xa5, + 0x39, 0x69, 0x92, 0x45, 0xd7, 0xd1, 0xa9, 0x38, 0x86, 0xae, 0x9e, 0x62, 0xe5, 0x55, 0xfc, 0x08, + 0xda, 0xa1, 0x13, 0xc9, 0x58, 0x5f, 0x79, 0x09, 0x91, 0xdf, 0x39, 0x11, 0xd6, 0x40, 0xfa, 0x42, + 0x56, 0x26, 0xf6, 0x11, 0x6c, 0x15, 0xfa, 0x31, 0xf0, 0x64, 0x20, 0x9d, 0xa5, 0xbe, 0x8c, 0x95, + 0x90, 0xfe, 0xa6, 0x99, 0xfd, 0xc6, 0x3e, 0x02, 0x33, 0x3d, 0x43, 0x3c, 0x96, 0x70, 0x75, 0xf6, + 0x46, 0x57, 0x55, 0x9b, 0x5c, 0x4b, 0x14, 0xc7, 0xc1, 0xef, 0xba, 0x2a, 0x30, 0xb8, 0x12, 0xec, + 0xbf, 0x1b, 0xd0, 0x51, 0x39, 0x5c, 0x51, 0x8b, 0x7d, 0x4b, 0x45, 0xca, 0x4a, 0x4c, 0x70, 0xda, + 0xe4, 0xb7, 0x9d, 0xd6, 0xff, 0xca, 0xe9, 0xe0, 0xf4, 0x2a, 0x14, 0xdc, 0x24, 0x2b, 0x6c, 0xb2, + 0xfb, 0xb0, 0xa9, 0x5c, 0x62, 0x19, 0x79, 0x7e, 0x12, 0xbc, 0x7d, 0xea, 0x7b, 0x4f, 0x5d, 0x78, + 0x28, 0xca, 0xc4, 0xf3, 0x25, 0x45, 0x43, 0x8b, 0xf7, 0xa8, 0x63, 0xec, 0x4b, 0xfb, 0x2e, 0x18, + 0x34, 0x0e, 0x40, 0xe7, 0xfd, 0x29, 0x1f, 0xbf, 0xfd, 0x79, 0xb0, 0xc1, 0xba, 0xd0, 0x1a, 0xbf, + 0x3d, 0x1d, 0x34, 0x0e, 0x3f, 0xb5, 0x61, 0xe7, 0xf8, 0xe4, 0xe5, 0xf8, 0x38, 0x0c, 0x97, 0xde, + 0xd4, 0x21, 0xee, 0x3d, 0x01, 0x83, 0xc8, 0x5e, 0xf1, 0xdc, 0x19, 0x56, 0x95, 0x18, 0xec, 0x10, + 0xda, 0x04, 0x78, 0x56, 0xf5, 0xea, 0x19, 0x56, 0x56, 0x1a, 0xf8, 0x13, 0x75, 0x05, 0x5c, 0x7f, + 0xfc, 0x0c, 0xab, 0xca, 0x0d, 0xf6, 0x23, 0x98, 0x19, 0x9a, 0xeb, 0x9e, 0x40, 0xc3, 0xda, 0xc2, + 0x03, 0xfd, 0x33, 0x66, 0xd7, 0x3d, 0x84, 0x86, 0xb5, 0xd5, 0x07, 0x7b, 0x0e, 0xdd, 0x84, 0xc0, + 0xd5, 0xcf, 0xa1, 0x61, 0x4d, 0x01, 0x82, 0xdb, 0xa3, 0x48, 0x5a, 0xf5, 0xca, 0x19, 0x56, 0xd6, + 0x14, 0xec, 0x19, 0x74, 0x34, 0xda, 0x2a, 0x5f, 0x52, 0xc3, 0xea, 0xca, 0x05, 0x17, 0x99, 0x15, + 0xc4, 0x75, 0x4f, 0xa4, 0x61, 0x6d, 0x4d, 0xc2, 0x8e, 0x01, 0x72, 0xa5, 0x70, 0xed, 0x43, 0x69, + 0x58, 0x5f, 0x99, 0xb0, 0x17, 0xd0, 0xcb, 0xaa, 0xdf, 0xea, 0xe7, 0xd2, 0xb0, 0xae, 0x38, 0x39, + 0xeb, 0xd0, 0x4b, 0xfc, 0xe9, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x90, 0x66, 0x37, 0xca, 0x9e, + 0x0f, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 7b2c75e3..48608cd4 100644 --- a/types/types.proto +++ b/types/types.proto @@ -3,49 +3,6 @@ package types; // This file is copied from http://github.com/tendermint/abci -//---------------------------------------- -// 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; - -} - //---------------------------------------- // Request types @@ -156,14 +113,14 @@ message ResponseSetOption{ } message ResponseDeliverTx{ - CodeType code = 1; + uint32 code = 1; bytes data = 2; string log = 3; repeated KVPair tags = 4; } message ResponseCheckTx{ - CodeType code = 1; + uint32 code = 1; bytes data = 2; string log = 3; uint64 gas = 4; @@ -171,7 +128,7 @@ message ResponseCheckTx{ } message ResponseQuery{ - CodeType code = 1; + uint32 code = 1; int64 index = 2; bytes key = 3; bytes value = 4; @@ -181,7 +138,7 @@ message ResponseQuery{ } message ResponseCommit{ - CodeType code = 1; + uint32 code = 1; bytes data = 2; string log = 3; } From 308cb8e4547ba31aef96e45a46b24f6399bc5d74 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 14:30:21 -0500 Subject: [PATCH 366/545] use gogo/protobuf --- Makefile | 6 +- types/messages.go | 2 +- types/types.pb.go | 197 +++++++++++++++++++++++----------------------- 3 files changed, 101 insertions(+), 104 deletions(-) diff --git a/Makefile b/Makefile index e9d23900..32e8df4e 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ GOTOOLS = \ github.com/mitchellh/gox \ github.com/Masterminds/glide \ github.com/alecthomas/gometalinter \ - github.com/ckaznocha/protoc-gen-lint + github.com/ckaznocha/protoc-gen-lint \ + github.com/gogo/protobuf/protoc-gen-gogo all: install test @@ -17,13 +18,12 @@ install_protoc: make install && \ cd .. && \ rm -rf protobuf-3.4.1 - go get github.com/golang/protobuf/protoc-gen-go protoc: ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 - protoc --go_out=plugins=grpc:. types/*.proto + protoc --gogo_out=plugins=grpc:. types/*.proto install: @ go install ./cmd/... diff --git a/types/messages.go b/types/messages.go index 77ad538e..7b9c81f9 100644 --- a/types/messages.go +++ b/types/messages.go @@ -3,7 +3,7 @@ package types import ( "io" - "github.com/golang/protobuf/proto" + "github.com/gogo/protobuf/proto" wire "github.com/tendermint/go-wire" ) diff --git a/types/types.pb.go b/types/types.pb.go index 454f8dd7..149c060a 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-gogo. DO NOT EDIT. // source: types/types.proto -// DO NOT EDIT! /* Package types is a generated protocol buffer package. @@ -42,14 +41,12 @@ It has these top-level messages: */ package types -import proto "github.com/golang/protobuf/proto" +import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" -import ( - context "golang.org/x/net/context" - grpc "google.golang.org/grpc" -) +import context "golang.org/x/net/context" +import grpc "google.golang.org/grpc" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -60,7 +57,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type KVPair_Type int32 @@ -81,7 +78,7 @@ var KVPair_Type_value = map[string]int32{ func (x KVPair_Type) String() string { return proto.EnumName(KVPair_Type_name, int32(x)) } -func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{29, 0} } +func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29, 0} } type Request struct { // Types that are valid to be assigned to Value: @@ -102,7 +99,7 @@ type Request struct { func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} -func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Request) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{0} } type isRequest_Value interface { isRequest_Value() @@ -260,57 +257,57 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { // value switch x := m.Value.(type) { case *Request_Echo: - b.EncodeVarint(1<<3 | proto.WireBytes) + _ = b.EncodeVarint(1<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Echo); err != nil { return err } case *Request_Flush: - b.EncodeVarint(2<<3 | proto.WireBytes) + _ = b.EncodeVarint(2<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Flush); err != nil { return err } case *Request_Info: - b.EncodeVarint(3<<3 | proto.WireBytes) + _ = b.EncodeVarint(3<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Info); err != nil { return err } case *Request_SetOption: - b.EncodeVarint(4<<3 | proto.WireBytes) + _ = b.EncodeVarint(4<<3 | proto.WireBytes) if err := b.EncodeMessage(x.SetOption); err != nil { return err } case *Request_DeliverTx: - b.EncodeVarint(5<<3 | proto.WireBytes) + _ = b.EncodeVarint(5<<3 | proto.WireBytes) if err := b.EncodeMessage(x.DeliverTx); err != nil { return err } case *Request_CheckTx: - b.EncodeVarint(6<<3 | proto.WireBytes) + _ = b.EncodeVarint(6<<3 | proto.WireBytes) if err := b.EncodeMessage(x.CheckTx); err != nil { return err } case *Request_Commit: - b.EncodeVarint(7<<3 | proto.WireBytes) + _ = b.EncodeVarint(7<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Commit); err != nil { return err } case *Request_Query: - b.EncodeVarint(8<<3 | proto.WireBytes) + _ = b.EncodeVarint(8<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Query); err != nil { return err } case *Request_InitChain: - b.EncodeVarint(9<<3 | proto.WireBytes) + _ = b.EncodeVarint(9<<3 | proto.WireBytes) if err := b.EncodeMessage(x.InitChain); err != nil { return err } case *Request_BeginBlock: - b.EncodeVarint(10<<3 | proto.WireBytes) + _ = b.EncodeVarint(10<<3 | proto.WireBytes) if err := b.EncodeMessage(x.BeginBlock); err != nil { return err } case *Request_EndBlock: - b.EncodeVarint(11<<3 | proto.WireBytes) + _ = b.EncodeVarint(11<<3 | proto.WireBytes) if err := b.EncodeMessage(x.EndBlock); err != nil { return err } @@ -484,13 +481,13 @@ func _Request_OneofSizer(msg proto.Message) (n int) { } type RequestEcho struct { - Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` } func (m *RequestEcho) Reset() { *m = RequestEcho{} } func (m *RequestEcho) String() string { return proto.CompactTextString(m) } func (*RequestEcho) ProtoMessage() {} -func (*RequestEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*RequestEcho) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1} } func (m *RequestEcho) GetMessage() string { if m != nil { @@ -505,16 +502,16 @@ type RequestFlush struct { func (m *RequestFlush) Reset() { *m = RequestFlush{} } func (m *RequestFlush) String() string { return proto.CompactTextString(m) } func (*RequestFlush) ProtoMessage() {} -func (*RequestFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*RequestFlush) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{2} } type RequestInfo struct { - Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` } func (m *RequestInfo) Reset() { *m = RequestInfo{} } func (m *RequestInfo) String() string { return proto.CompactTextString(m) } func (*RequestInfo) ProtoMessage() {} -func (*RequestInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*RequestInfo) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{3} } func (m *RequestInfo) GetVersion() string { if m != nil { @@ -524,14 +521,14 @@ func (m *RequestInfo) GetVersion() string { } type RequestSetOption struct { - Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` } func (m *RequestSetOption) Reset() { *m = RequestSetOption{} } func (m *RequestSetOption) String() string { return proto.CompactTextString(m) } func (*RequestSetOption) ProtoMessage() {} -func (*RequestSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*RequestSetOption) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{4} } func (m *RequestSetOption) GetKey() string { if m != nil { @@ -554,7 +551,7 @@ type RequestDeliverTx struct { func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } func (*RequestDeliverTx) ProtoMessage() {} -func (*RequestDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*RequestDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} } func (m *RequestDeliverTx) GetTx() []byte { if m != nil { @@ -570,7 +567,7 @@ type RequestCheckTx struct { func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } func (*RequestCheckTx) ProtoMessage() {} -func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} } func (m *RequestCheckTx) GetTx() []byte { if m != nil { @@ -581,15 +578,15 @@ func (m *RequestCheckTx) GetTx() []byte { type RequestQuery struct { 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"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + Prove bool `protobuf:"varint,4,opt,name=prove,proto3" json:"prove,omitempty"` } func (m *RequestQuery) Reset() { *m = RequestQuery{} } func (m *RequestQuery) String() string { return proto.CompactTextString(m) } func (*RequestQuery) ProtoMessage() {} -func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{7} } func (m *RequestQuery) GetData() []byte { if m != nil { @@ -625,7 +622,7 @@ type RequestCommit struct { func (m *RequestCommit) Reset() { *m = RequestCommit{} } func (m *RequestCommit) String() string { return proto.CompactTextString(m) } func (*RequestCommit) ProtoMessage() {} -func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{8} } type RequestInitChain struct { Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` @@ -634,7 +631,7 @@ type RequestInitChain struct { func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } func (*RequestInitChain) ProtoMessage() {} -func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9} } func (m *RequestInitChain) GetValidators() []*Validator { if m != nil { @@ -651,7 +648,7 @@ type RequestBeginBlock struct { func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} -func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10} } func (m *RequestBeginBlock) GetHash() []byte { if m != nil { @@ -668,13 +665,13 @@ func (m *RequestBeginBlock) GetHeader() *Header { } type RequestEndBlock struct { - Height uint64 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"` + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` } func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} -func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} } func (m *RequestEndBlock) GetHeight() uint64 { if m != nil { @@ -703,7 +700,7 @@ type Response struct { func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} -func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*Response) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12} } type isResponse_Value interface { isResponse_Value() @@ -873,62 +870,62 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { // value switch x := m.Value.(type) { case *Response_Exception: - b.EncodeVarint(1<<3 | proto.WireBytes) + _ = b.EncodeVarint(1<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Exception); err != nil { return err } case *Response_Echo: - b.EncodeVarint(2<<3 | proto.WireBytes) + _ = b.EncodeVarint(2<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Echo); err != nil { return err } case *Response_Flush: - b.EncodeVarint(3<<3 | proto.WireBytes) + _ = b.EncodeVarint(3<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Flush); err != nil { return err } case *Response_Info: - b.EncodeVarint(4<<3 | proto.WireBytes) + _ = b.EncodeVarint(4<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Info); err != nil { return err } case *Response_SetOption: - b.EncodeVarint(5<<3 | proto.WireBytes) + _ = b.EncodeVarint(5<<3 | proto.WireBytes) if err := b.EncodeMessage(x.SetOption); err != nil { return err } case *Response_DeliverTx: - b.EncodeVarint(6<<3 | proto.WireBytes) + _ = b.EncodeVarint(6<<3 | proto.WireBytes) if err := b.EncodeMessage(x.DeliverTx); err != nil { return err } case *Response_CheckTx: - b.EncodeVarint(7<<3 | proto.WireBytes) + _ = b.EncodeVarint(7<<3 | proto.WireBytes) if err := b.EncodeMessage(x.CheckTx); err != nil { return err } case *Response_Commit: - b.EncodeVarint(8<<3 | proto.WireBytes) + _ = b.EncodeVarint(8<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Commit); err != nil { return err } case *Response_Query: - b.EncodeVarint(9<<3 | proto.WireBytes) + _ = b.EncodeVarint(9<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Query); err != nil { return err } case *Response_InitChain: - b.EncodeVarint(10<<3 | proto.WireBytes) + _ = b.EncodeVarint(10<<3 | proto.WireBytes) if err := b.EncodeMessage(x.InitChain); err != nil { return err } case *Response_BeginBlock: - b.EncodeVarint(11<<3 | proto.WireBytes) + _ = b.EncodeVarint(11<<3 | proto.WireBytes) if err := b.EncodeMessage(x.BeginBlock); err != nil { return err } case *Response_EndBlock: - b.EncodeVarint(12<<3 | proto.WireBytes) + _ = b.EncodeVarint(12<<3 | proto.WireBytes) if err := b.EncodeMessage(x.EndBlock); err != nil { return err } @@ -1115,13 +1112,13 @@ func _Response_OneofSizer(msg proto.Message) (n int) { } type ResponseException struct { - Error string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` } func (m *ResponseException) Reset() { *m = ResponseException{} } func (m *ResponseException) String() string { return proto.CompactTextString(m) } func (*ResponseException) ProtoMessage() {} -func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{13} } func (m *ResponseException) GetError() string { if m != nil { @@ -1131,13 +1128,13 @@ func (m *ResponseException) GetError() string { } type ResponseEcho struct { - Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` } func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } func (*ResponseEcho) ProtoMessage() {} -func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{14} } func (m *ResponseEcho) GetMessage() string { if m != nil { @@ -1152,19 +1149,19 @@ type ResponseFlush struct { func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } func (*ResponseFlush) ProtoMessage() {} -func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{15} } type ResponseInfo struct { - Data string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"` - LastBlockHeight uint64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight" json:"last_block_height,omitempty"` + Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + LastBlockHeight uint64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` LastBlockAppHash []byte `protobuf:"bytes,4,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` } func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } func (*ResponseInfo) ProtoMessage() {} -func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{16} } func (m *ResponseInfo) GetData() string { if m != nil { @@ -1195,13 +1192,13 @@ func (m *ResponseInfo) GetLastBlockAppHash() []byte { } type ResponseSetOption struct { - Log string `protobuf:"bytes,1,opt,name=log" json:"log,omitempty"` + Log string `protobuf:"bytes,1,opt,name=log,proto3" json:"log,omitempty"` } func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } func (*ResponseSetOption) ProtoMessage() {} -func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} } func (m *ResponseSetOption) GetLog() string { if m != nil { @@ -1211,16 +1208,16 @@ func (m *ResponseSetOption) GetLog() string { } type ResponseDeliverTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` } func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } func (*ResponseDeliverTx) ProtoMessage() {} -func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} } func (m *ResponseDeliverTx) GetCode() uint32 { if m != nil { @@ -1251,17 +1248,17 @@ func (m *ResponseDeliverTx) GetTags() []*KVPair { } type ResponseCheckTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` - Gas uint64 `protobuf:"varint,4,opt,name=gas" json:"gas,omitempty"` - Fee uint64 `protobuf:"varint,5,opt,name=fee" json:"fee,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Gas uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` + Fee uint64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } func (*ResponseCheckTx) ProtoMessage() {} -func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} } func (m *ResponseCheckTx) GetCode() uint32 { if m != nil { @@ -1299,19 +1296,19 @@ func (m *ResponseCheckTx) GetFee() uint64 { } type ResponseQuery struct { - Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` - Index int64 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Index int64 `protobuf:"varint,2,opt,name=index,proto3" 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"` + Height uint64 `protobuf:"varint,6,opt,name=height,proto3" json:"height,omitempty"` + Log string `protobuf:"bytes,7,opt,name=log,proto3" json:"log,omitempty"` } func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} -func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} } func (m *ResponseQuery) GetCode() uint32 { if m != nil { @@ -1363,15 +1360,15 @@ func (m *ResponseQuery) GetLog() string { } type ResponseCommit struct { - Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` } func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} -func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} } func (m *ResponseCommit) GetCode() uint32 { if m != nil { @@ -1400,7 +1397,7 @@ type ResponseInitChain struct { func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } func (*ResponseInitChain) ProtoMessage() {} -func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} } type ResponseBeginBlock struct { } @@ -1408,7 +1405,7 @@ type ResponseBeginBlock struct { func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} -func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } type ResponseEndBlock struct { Diffs []*Validator `protobuf:"bytes,1,rep,name=diffs" json:"diffs,omitempty"` @@ -1417,7 +1414,7 @@ type ResponseEndBlock struct { func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} -func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} } func (m *ResponseEndBlock) GetDiffs() []*Validator { if m != nil { @@ -1427,10 +1424,10 @@ func (m *ResponseEndBlock) GetDiffs() []*Validator { } type Header struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` - Height uint64 `protobuf:"varint,2,opt,name=height" json:"height,omitempty"` - Time uint64 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"` - NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs" json:"num_txs,omitempty"` + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Time uint64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` + NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` @@ -1441,7 +1438,7 @@ type Header struct { func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} } func (m *Header) GetChainId() string { if m != nil { @@ -1514,7 +1511,7 @@ type BlockID struct { func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} -func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} } func (m *BlockID) GetHash() []byte { if m != nil { @@ -1531,14 +1528,14 @@ func (m *BlockID) GetParts() *PartSetHeader { } type PartSetHeader struct { - Total uint64 `protobuf:"varint,1,opt,name=total" json:"total,omitempty"` + Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` } func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } func (m *PartSetHeader) GetTotal() uint64 { if m != nil { @@ -1556,13 +1553,13 @@ func (m *PartSetHeader) GetHash() []byte { type Validator struct { PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` - Power uint64 `protobuf:"varint,2,opt,name=power" json:"power,omitempty"` + Power uint64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` } func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1579,16 +1576,16 @@ func (m *Validator) GetPower() uint64 { } type KVPair struct { - Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` - ValueType KVPair_Type `protobuf:"varint,2,opt,name=value_type,json=valueType,enum=types.KVPair_Type" json:"value_type,omitempty"` - ValueString string `protobuf:"bytes,3,opt,name=value_string,json=valueString" json:"value_string,omitempty"` - ValueInt int64 `protobuf:"varint,4,opt,name=value_int,json=valueInt" json:"value_int,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + ValueType KVPair_Type `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=types.KVPair_Type" json:"value_type,omitempty"` + ValueString string `protobuf:"bytes,3,opt,name=value_string,json=valueString,proto3" json:"value_string,omitempty"` + ValueInt int64 `protobuf:"varint,4,opt,name=value_int,json=valueInt,proto3" json:"value_int,omitempty"` } func (m *KVPair) Reset() { *m = KVPair{} } func (m *KVPair) String() string { return proto.CompactTextString(m) } func (*KVPair) ProtoMessage() {} -func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} } func (m *KVPair) GetKey() string { if m != nil { @@ -2054,9 +2051,9 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ Metadata: "types/types.proto", } -func init() { proto.RegisterFile("types/types.proto", fileDescriptor0) } +func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } -var fileDescriptor0 = []byte{ +var fileDescriptorTypes = []byte{ // 1395 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x97, 0x4b, 0x6f, 0xdb, 0x46, 0x10, 0x80, 0x2d, 0x89, 0x7a, 0x70, 0xe4, 0x87, 0xb2, 0x71, 0x13, 0x46, 0xb9, 0x24, 0x04, 0xd2, From 24fbe291ab2d1b6d562b133b3c7251323888c1a6 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 15:17:54 -0500 Subject: [PATCH 367/545] update glide; update services for new signature --- cmd/abci-cli/abci-cli.go | 6 ++--- example/dummy/dummy_test.go | 8 +++---- example/example_test.go | 6 ++--- glide.lock | 46 ++++++++++++++++++++----------------- glide.yaml | 2 +- tests/client_server_test.go | 4 ++-- tests/test_app/app.go | 2 +- 7 files changed, 39 insertions(+), 35 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index c0dbbfaf..cc60a4bc 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -88,7 +88,7 @@ var RootCmd = &cobra.Command{ return err } client.SetLogger(logger.With("module", "abci-client")) - if _, err := client.Start(); err != nil { + if err := client.Start(); err != nil { return err } } @@ -457,7 +457,7 @@ func cmdCounter(cmd *cobra.Command, args []string) error { return err } srv.SetLogger(logger.With("module", "abci-server")) - if _, err := srv.Start(); err != nil { + if err := srv.Start(); err != nil { return err } @@ -487,7 +487,7 @@ func cmdDummy(cmd *cobra.Command, args []string) error { return err } srv.SetLogger(logger.With("module", "abci-server")) - if _, err := srv.Start(); err != nil { + if err := srv.Start(); err != nil { return err } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index bbb35dbe..65970ecd 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -212,14 +212,14 @@ func makeSocketClientServer(app types.Application, name string) (abcicli.Client, server := abciserver.NewSocketServer(socket, app) server.SetLogger(logger.With("module", "abci-server")) - if _, err := server.Start(); err != nil { + if err := server.Start(); err != nil { return nil, nil, err } // Connect to the socket client := abcicli.NewSocketClient(socket, false) client.SetLogger(logger.With("module", "abci-client")) - if _, err := client.Start(); err != nil { + if err := client.Start(); err != nil { server.Stop() return nil, nil, err } @@ -235,13 +235,13 @@ func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, c gapp := types.NewGRPCApplication(app) server := abciserver.NewGRPCServer(socket, gapp) server.SetLogger(logger.With("module", "abci-server")) - if _, err := server.Start(); err != nil { + if err := server.Start(); err != nil { return nil, nil, err } client := abcicli.NewGRPCClient(socket, true) client.SetLogger(logger.With("module", "abci-client")) - if _, err := client.Start(); err != nil { + if err := client.Start(); err != nil { server.Stop() return nil, nil, err } diff --git a/example/example_test.go b/example/example_test.go index 952f8cb2..7fd3bb52 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -40,7 +40,7 @@ func testStream(t *testing.T, app types.Application) { // Start the listener server := abciserver.NewSocketServer("unix://test.sock", app) server.SetLogger(log.TestingLogger().With("module", "abci-server")) - if _, err := server.Start(); err != nil { + if err := server.Start(); err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) } defer server.Stop() @@ -48,7 +48,7 @@ func testStream(t *testing.T, app types.Application) { // Connect to the socket client := abcicli.NewSocketClient("unix://test.sock", false) client.SetLogger(log.TestingLogger().With("module", "abci-client")) - if _, err := client.Start(); err != nil { + if err := client.Start(); err != nil { t.Fatalf("Error starting socket client: %v", err.Error()) } defer client.Stop() @@ -113,7 +113,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { // Start the listener server := abciserver.NewGRPCServer("unix://test.sock", app) server.SetLogger(log.TestingLogger().With("module", "abci-server")) - if _, err := server.Start(); err != nil { + if err := server.Start(); err != nil { t.Fatalf("Error starting GRPC server: %v", err.Error()) } defer server.Stop() diff --git a/glide.lock b/glide.lock index 80dbc483..b4a2125e 100644 --- a/glide.lock +++ b/glide.lock @@ -1,14 +1,12 @@ -hash: 5501ab3d7136aa8fb425c995d45221849b33aefab76c5d2c192e721dad28da38 -updated: 2017-11-14T18:23:41.2024073Z +hash: eb1802c17bab227061f9198f2a738ad6e2bb676cefdd5729dc2ac90d5d10e610 +updated: 2017-11-30T15:00:40.216000076-05:00 imports: - name: github.com/btcsuite/btcd - version: b8df516b4b267acf2de46be593a9d948d1d2c420 + version: 8cea3866d0f7fb12d567a20744942c0d078c7d15 subpackages: - btcec -- name: github.com/btcsuite/fastsha256 - version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/go-kit/kit - version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 + version: e3b2152e0063c5f05efea89ecbe297852af2a92d subpackages: - log - log/level @@ -16,15 +14,21 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-playground/locales - version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 + version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6 subpackages: - currency - name: github.com/go-playground/universal-translator version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc +- name: github.com/gogo/protobuf + version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 + subpackages: + - gogoproto + - proto + - protoc-gen-gogo/descriptor - name: github.com/golang/protobuf - version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 + version: 1e59b77b52bf8e4b449a57e6f79f21226d571845 subpackages: - proto - ptypes @@ -44,9 +48,9 @@ imports: - name: github.com/spf13/cobra version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b - name: github.com/spf13/pflag - version: 80fe0fb4eba54167e2ccae1c6c950e72abf61b73 + version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea - name: github.com/syndtr/goleveldb - version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 + version: adf24ef3f94bd13ec4163060b21a5678f22b429b subpackages: - leveldb - leveldb/cache @@ -61,27 +65,27 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-crypto version: b4f04f196cd719660e43b91202cd60d9a95b1837 - name: github.com/tendermint/go-wire - version: 1c96861c03231361546944d883d99593b2e6b408 + version: 7d50b38b3815efe313728de77e2995c8813ce13f subpackages: - data - name: github.com/tendermint/iavl version: 595f3dcd5b6cd4a292e90757ae6d367fd7a6e653 - name: github.com/tendermint/tmlibs - version: 2442a0a698d271d5cf5d6a8e7c1db20335e959c1 + version: 21fb7819891997c96838308b4eba5a50b07ff03f subpackages: - common - db - log - process - name: golang.org/x/crypto - version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e + version: 9f005a07e0d31d45e6656d241bb5c0f2efd4bc94 subpackages: - nacl/secretbox - openpgp/armor @@ -90,7 +94,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: cd69bc3fc700721b709c3a59e16e24c67b58f6ff + version: 9dfe39835686865bff950a07b394c12a98ddc811 subpackages: - context - http2 @@ -100,14 +104,14 @@ imports: - lex/httplex - trace - name: golang.org/x/text - version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 + version: 88f656faf3f37f690df1a32515b479415e1a6769 subpackages: - secure/bidirule - transform - unicode/bidi - unicode/norm - name: google.golang.org/genproto - version: f676e0f3ac6395ff1a529ae59a6670878a8371a6 + version: 891aceb7c239e72692819142dfca057bdcbfcb96 subpackages: - googleapis/rpc/status - name: google.golang.org/grpc @@ -130,10 +134,10 @@ imports: - tap - transport - name: gopkg.in/go-playground/validator.v9 - version: 6d8c18553ea1ac493d049edd6f102f52e618f085 + version: 61caf9d3038e1af346dbf5c2e16f6678e1548364 testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 subpackages: - spew - name: github.com/pmezard/go-difflib @@ -141,7 +145,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 2aa2c176b9dab406a6970f6a55f513e8a8c8b18f subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index ce805723..f4a796cf 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,6 +1,6 @@ package: github.com/tendermint/abci import: -- package: github.com/golang/protobuf +- package: github.com/gogo/protobuf subpackages: - proto - package: github.com/spf13/cobra diff --git a/tests/client_server_test.go b/tests/client_server_test.go index cc946fce..646c8b60 100644 --- a/tests/client_server_test.go +++ b/tests/client_server_test.go @@ -17,11 +17,11 @@ func TestClientServerNoAddrPrefix(t *testing.T) { server, err := abciserver.NewServer(addr, transport, app) assert.NoError(t, err, "expected no error on NewServer") - _, err = server.Start() + err = server.Start() assert.NoError(t, err, "expected no error on server.Start") client, err := abciclient.NewClient(addr, transport, true) assert.NoError(t, err, "expected no error on NewClient") - _, err = client.Start() + err = client.Start() assert.NoError(t, err, "expected no error on client.Start") } diff --git a/tests/test_app/app.go b/tests/test_app/app.go index d55fb160..f0403621 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -18,7 +18,7 @@ func startClient(abciType string) abcicli.Client { } logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) client.SetLogger(logger.With("module", "abcicli")) - if _, err := client.Start(); err != nil { + if err := client.Start(); err != nil { panicf("connecting to abci_app: %v", err.Error()) } From 81e4effbdb8f42ebd4806c17936fc07efce04148 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 15:31:10 -0500 Subject: [PATCH 368/545] types: use data.Bytes directly in type.proto via gogo/protobuf. wow --- Makefile | 5 +- glide.lock | 6 +- glide.yaml | 2 +- types/base_app.go | 2 +- types/result.go | 41 ++----- types/result_test.go | 8 +- types/types.pb.go | 266 +++++++++++++++++++------------------------ types/types.proto | 15 ++- 8 files changed, 143 insertions(+), 202 deletions(-) diff --git a/Makefile b/Makefile index 32e8df4e..e6a7af36 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ GOTOOLS = \ github.com/Masterminds/glide \ github.com/alecthomas/gometalinter \ github.com/ckaznocha/protoc-gen-lint \ - github.com/gogo/protobuf/protoc-gen-gogo + github.com/gogo/protobuf/protoc-gen-gogo \ + github.com/gogo/protobuf/gogoproto all: install test @@ -23,7 +24,7 @@ protoc: ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 - protoc --gogo_out=plugins=grpc:. types/*.proto + protoc -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf --gogo_out=plugins=grpc:. types/*.proto install: @ go install ./cmd/... diff --git a/glide.lock b/glide.lock index b4a2125e..d52acc7b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: eb1802c17bab227061f9198f2a738ad6e2bb676cefdd5729dc2ac90d5d10e610 -updated: 2017-11-30T15:00:40.216000076-05:00 +hash: 971ad090f3190ffd759deecf118a0eaefe7eceb4b1a8057800e332712fc1a7c2 +updated: 2017-11-30T15:29:31.740172292-05:00 imports: - name: github.com/btcsuite/btcd version: 8cea3866d0f7fb12d567a20744942c0d078c7d15 @@ -72,7 +72,7 @@ imports: - name: github.com/tendermint/go-crypto version: b4f04f196cd719660e43b91202cd60d9a95b1837 - name: github.com/tendermint/go-wire - version: 7d50b38b3815efe313728de77e2995c8813ce13f + version: 3f073b1a9c841d9b88d03ca8181f61278188adca subpackages: - data - name: github.com/tendermint/iavl diff --git a/glide.yaml b/glide.yaml index f4a796cf..aeb6b674 100644 --- a/glide.yaml +++ b/glide.yaml @@ -7,7 +7,7 @@ import: - package: github.com/tendermint/go-crypto version: develop - package: github.com/tendermint/go-wire - version: develop + version: data-bytes-marshal-unmarshal subpackages: - data - package: github.com/tendermint/iavl diff --git a/types/base_app.go b/types/base_app.go index f8d1946a..1998e9dc 100644 --- a/types/base_app.go +++ b/types/base_app.go @@ -24,7 +24,7 @@ func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { } func (BaseApplication) Commit() ResponseCommit { - return ResponseCommit{Code: CodeTypeOK, Data: []byte("nil")} + return ResponseCommit{Code: CodeTypeOK} } func (BaseApplication) Query(req RequestQuery) ResponseQuery { diff --git a/types/result.go b/types/result.go index 59d82ffc..3344b27c 100644 --- a/types/result.go +++ b/types/result.go @@ -2,8 +2,6 @@ package types import ( "fmt" - - "github.com/tendermint/go-wire/data" ) // type CodeType uint32 @@ -42,41 +40,16 @@ func (r ResponseCommit) Error() string { return fmtError(r.Code, r.Log) } -func fmtError(code uint32, log string) string { - return fmt.Sprintf("Error code (%d): %s", code, log) -} - -// ResultQuery is a wrapper around ResponseQuery using data.Bytes instead of -// raw byte slices. -type ResultQuery struct { - Code uint32 `json:"code"` - Index int64 `json:"index"` - Key data.Bytes `json:"key"` - Value data.Bytes `json:"value"` - Proof data.Bytes `json:"proof"` - Height uint64 `json:"height"` - Log string `json:"log"` -} - -// Result converts response query to ResultQuery. -func (r *ResponseQuery) Result() *ResultQuery { - return &ResultQuery{ - Code: r.Code, - Index: r.Index, - Key: r.Key, - Value: r.Value, - Proof: r.Proof, - Height: r.Height, - Log: r.Log, - } -} - // IsErr returns true if Code is something other than OK. -func (r *ResultQuery) IsErr() bool { +func (r ResponseQuery) IsErr() bool { return r.Code != CodeTypeOK } -// Error implements error interface by formatting result as string. -func (r *ResultQuery) Error() string { +// Error implements error interface by formatting response as string. +func (r ResponseQuery) Error() string { return fmtError(r.Code, r.Log) } + +func fmtError(code uint32, log string) string { + return fmt.Sprintf("Error code (%d): %s", code, log) +} diff --git a/types/result_test.go b/types/result_test.go index 7791cf52..b7da838c 100644 --- a/types/result_test.go +++ b/types/result_test.go @@ -6,18 +6,17 @@ import ( "github.com/stretchr/testify/assert" ) -func TestResultQuery(t *testing.T) { - orig := &ResponseQuery{ +func TestResponseQuery(t *testing.T) { + res := ResponseQuery{ Code: CodeTypeOK, Index: 0, Key: []byte("hello"), Value: []byte("world"), Height: 1, } - res := orig.Result() assert.False(t, res.IsErr()) - orig = &ResponseQuery{ + res = ResponseQuery{ Code: 1, Index: 0, Key: []byte("hello"), @@ -25,7 +24,6 @@ func TestResultQuery(t *testing.T) { Height: 1, Log: "bad", } - res = orig.Result() assert.True(t, res.IsErr()) assert.Equal(t, "Error code (1): bad", res.Error()) } diff --git a/types/types.pb.go b/types/types.pb.go index 149c060a..61a56cac 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -44,6 +44,9 @@ package types import proto "github.com/gogo/protobuf/proto" import fmt "fmt" import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import github_com_tendermint_go_wire_data "github.com/tendermint/go-wire/data" import context "golang.org/x/net/context" import grpc "google.golang.org/grpc" @@ -1208,10 +1211,10 @@ func (m *ResponseSetOption) GetLog() string { } type ResponseDeliverTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` } func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } @@ -1226,13 +1229,6 @@ func (m *ResponseDeliverTx) GetCode() uint32 { return 0 } -func (m *ResponseDeliverTx) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - func (m *ResponseDeliverTx) GetLog() string { if m != nil { return m.Log @@ -1248,11 +1244,11 @@ func (m *ResponseDeliverTx) GetTags() []*KVPair { } type ResponseCheckTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Gas uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` - Fee uint64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Gas uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` + Fee uint64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1267,13 +1263,6 @@ func (m *ResponseCheckTx) GetCode() uint32 { return 0 } -func (m *ResponseCheckTx) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - func (m *ResponseCheckTx) GetLog() string { if m != nil { return m.Log @@ -1296,13 +1285,13 @@ func (m *ResponseCheckTx) GetFee() uint64 { } type ResponseQuery struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Index int64 `protobuf:"varint,2,opt,name=index,proto3" 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,proto3" json:"height,omitempty"` - Log string `protobuf:"bytes,7,opt,name=log,proto3" json:"log,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Index int64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + Key github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,3,opt,name=key,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"key"` + Value github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,4,opt,name=value,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"value"` + Proof github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,5,opt,name=proof,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"proof"` + Height uint64 `protobuf:"varint,6,opt,name=height,proto3" json:"height,omitempty"` + Log string `protobuf:"bytes,7,opt,name=log,proto3" json:"log,omitempty"` } func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } @@ -1324,27 +1313,6 @@ func (m *ResponseQuery) GetIndex() int64 { 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 @@ -1360,9 +1328,9 @@ func (m *ResponseQuery) GetLog() string { } type ResponseCommit struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` } func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } @@ -1377,13 +1345,6 @@ func (m *ResponseCommit) GetCode() uint32 { return 0 } -func (m *ResponseCommit) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - func (m *ResponseCommit) GetLog() string { if m != nil { return m.Log @@ -2054,93 +2015,98 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1395 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x97, 0x4b, 0x6f, 0xdb, 0x46, - 0x10, 0x80, 0x2d, 0x89, 0x7a, 0x70, 0xe4, 0x87, 0xb2, 0x71, 0x13, 0x46, 0xb9, 0x24, 0x04, 0xd2, - 0xd8, 0x69, 0xea, 0xb4, 0x0e, 0x52, 0xc4, 0x4d, 0x51, 0xc0, 0x4e, 0xd2, 0x4a, 0x0d, 0x90, 0xa6, - 0x1b, 0x23, 0x57, 0x81, 0x16, 0x57, 0x12, 0x61, 0x99, 0x64, 0xc8, 0x95, 0x2b, 0xff, 0x87, 0xdc, - 0x7b, 0xee, 0xa9, 0x40, 0x7f, 0x48, 0x7f, 0x57, 0x31, 0xb3, 0xcb, 0xa7, 0xc9, 0x1c, 0xda, 0x0b, - 0xb1, 0xb3, 0x33, 0xb3, 0xdc, 0xc7, 0xcc, 0xb7, 0xb3, 0x70, 0x43, 0x5e, 0x85, 0x22, 0x7e, 0x42, - 0xdf, 0x83, 0x30, 0x0a, 0x64, 0xc0, 0xda, 0x24, 0xd8, 0xff, 0x18, 0xd0, 0xe5, 0xe2, 0xe3, 0x4a, - 0xc4, 0x92, 0xed, 0x81, 0x21, 0xa6, 0x8b, 0xc0, 0x6a, 0xdc, 0x6b, 0xec, 0xf5, 0x0f, 0xd9, 0x81, - 0x32, 0xd7, 0xda, 0xd7, 0xd3, 0x45, 0x30, 0xda, 0xe0, 0x64, 0xc1, 0xbe, 0x82, 0xf6, 0x6c, 0xb9, - 0x8a, 0x17, 0x56, 0x93, 0x4c, 0x6f, 0x16, 0x4d, 0x7f, 0x42, 0xd5, 0x68, 0x83, 0x2b, 0x1b, 0x1c, - 0xd6, 0xf3, 0x67, 0x81, 0xd5, 0xaa, 0x1a, 0x76, 0xec, 0xcf, 0x68, 0x58, 0xb4, 0x60, 0xcf, 0x01, - 0x62, 0x21, 0x27, 0x41, 0x28, 0xbd, 0xc0, 0xb7, 0x0c, 0xb2, 0xbf, 0x5d, 0xb4, 0x7f, 0x2f, 0xe4, - 0xaf, 0xa4, 0x1e, 0x6d, 0x70, 0x33, 0x4e, 0x04, 0xf4, 0x74, 0xc5, 0xd2, 0xbb, 0x14, 0xd1, 0x44, - 0xae, 0xad, 0x76, 0x95, 0xe7, 0x2b, 0xa5, 0x3f, 0x5d, 0xa3, 0xa7, 0x9b, 0x08, 0xec, 0x10, 0x7a, - 0xd3, 0x85, 0x98, 0x9e, 0xa3, 0x5f, 0x87, 0xfc, 0xbe, 0x28, 0xfa, 0xbd, 0x44, 0x2d, 0x79, 0x75, - 0xa7, 0xaa, 0xc9, 0x0e, 0xa0, 0x33, 0x0d, 0x2e, 0x2e, 0x3c, 0x69, 0x75, 0xc9, 0x63, 0xb7, 0xe4, - 0x41, 0xba, 0xd1, 0x06, 0xd7, 0x56, 0xb8, 0x5d, 0x1f, 0x57, 0x22, 0xba, 0xb2, 0x7a, 0x55, 0xdb, - 0xf5, 0x1b, 0xaa, 0x70, 0xbb, 0xc8, 0x06, 0x97, 0xe2, 0xf9, 0x9e, 0x9c, 0x4c, 0x17, 0x8e, 0xe7, - 0x5b, 0x66, 0xd5, 0x52, 0xc6, 0xbe, 0x27, 0x5f, 0xa2, 0x1a, 0x97, 0xe2, 0x25, 0x02, 0x7b, 0x01, - 0xfd, 0x33, 0x31, 0xf7, 0xfc, 0xc9, 0xd9, 0x32, 0x98, 0x9e, 0x5b, 0x40, 0xae, 0x56, 0xd1, 0xf5, - 0x04, 0x0d, 0x4e, 0x50, 0x3f, 0xda, 0xe0, 0x70, 0x96, 0x4a, 0xec, 0x19, 0x98, 0xc2, 0x77, 0xb5, - 0x6b, 0x9f, 0x5c, 0x6f, 0x95, 0x22, 0xc0, 0x77, 0x13, 0xc7, 0x9e, 0xd0, 0xed, 0x93, 0x2e, 0xb4, - 0x2f, 0x9d, 0xe5, 0x4a, 0xd8, 0x0f, 0xa1, 0x9f, 0x8b, 0x14, 0x66, 0x41, 0xf7, 0x42, 0xc4, 0xb1, - 0x33, 0x17, 0x14, 0x4e, 0x26, 0x4f, 0x44, 0x7b, 0x1b, 0x36, 0xf3, 0x71, 0x92, 0x73, 0xc4, 0x58, - 0x40, 0xc7, 0x4b, 0x11, 0xc5, 0x18, 0x00, 0xda, 0x51, 0x8b, 0xf6, 0xf7, 0x30, 0x28, 0x07, 0x01, - 0x1b, 0x40, 0xeb, 0x5c, 0x5c, 0x69, 0x4b, 0x6c, 0xb2, 0x5d, 0x3d, 0x21, 0x0a, 0x4d, 0x93, 0xeb, - 0xd9, 0xd9, 0xa9, 0x6f, 0x1a, 0x06, 0x6c, 0x1b, 0x9a, 0x72, 0x4d, 0xae, 0x9b, 0xbc, 0x29, 0xd7, - 0xf6, 0x3d, 0xd8, 0x2e, 0x1e, 0xf9, 0x35, 0x0b, 0x37, 0x9d, 0x3a, 0x9d, 0x19, 0x63, 0x60, 0xb8, - 0x8e, 0x74, 0xb4, 0x05, 0xb5, 0xb1, 0x2f, 0x74, 0xe4, 0x42, 0xff, 0x9e, 0xda, 0xec, 0x16, 0x74, - 0x16, 0xc2, 0x9b, 0x2f, 0x24, 0xe5, 0x80, 0xc1, 0xb5, 0x84, 0x73, 0x0d, 0xa3, 0xe0, 0x52, 0x50, - 0xa8, 0xf7, 0xb8, 0x12, 0xec, 0x1d, 0xd8, 0x2a, 0x04, 0x92, 0xfd, 0x2a, 0x9d, 0x7c, 0x7a, 0xf0, - 0xec, 0x1b, 0x80, 0x4b, 0x67, 0xe9, 0xb9, 0x8e, 0x0c, 0xa2, 0xd8, 0x6a, 0xdc, 0x6b, 0xed, 0xf5, - 0x0f, 0x07, 0xfa, 0xbc, 0x3e, 0x24, 0x0a, 0x9e, 0xb3, 0xb1, 0xdf, 0xc2, 0x8d, 0x6b, 0x31, 0x80, - 0xb3, 0x5d, 0x38, 0xf1, 0x22, 0x59, 0x01, 0xb6, 0xd9, 0x03, 0x9c, 0xad, 0xe3, 0x8a, 0x48, 0x67, - 0xf7, 0x96, 0x1e, 0x76, 0x44, 0x9d, 0x5c, 0x2b, 0xed, 0x7d, 0xd8, 0x29, 0x05, 0x46, 0x6e, 0x9d, - 0x8d, 0xfc, 0x3a, 0xed, 0x4f, 0x6d, 0xe8, 0x71, 0x11, 0x87, 0x81, 0x1f, 0x0b, 0xf6, 0x1c, 0x4c, - 0xb1, 0x9e, 0x0a, 0x95, 0xe3, 0x8d, 0x52, 0x8c, 0x2a, 0x9b, 0xd7, 0x89, 0x1e, 0xe3, 0x3b, 0x35, - 0x66, 0xfb, 0x9a, 0x4f, 0x65, 0xe8, 0x68, 0xa7, 0x3c, 0xa0, 0x1e, 0x27, 0x80, 0x6a, 0x95, 0x12, - 0x54, 0xd9, 0x96, 0x08, 0xb5, 0xaf, 0x09, 0x65, 0x54, 0x0e, 0x5c, 0x40, 0xd4, 0x51, 0x01, 0x51, - 0xed, 0xca, 0xe9, 0xd7, 0x30, 0xea, 0xa8, 0xc0, 0xa8, 0x4e, 0xa5, 0x6b, 0x0d, 0xa4, 0x9e, 0xe6, - 0x20, 0xd5, 0x2d, 0xe5, 0xa6, 0x72, 0xac, 0xa0, 0xd4, 0x93, 0x94, 0x52, 0xbd, 0x12, 0xd7, 0xb4, - 0x4b, 0x19, 0x53, 0x8f, 0x13, 0x4c, 0x99, 0x95, 0x9b, 0x56, 0xe2, 0xd4, 0x51, 0x81, 0x53, 0x50, - 0xb9, 0x9c, 0x1a, 0x50, 0xfd, 0x50, 0x04, 0x95, 0xa2, 0xcd, 0x9d, 0x92, 0x6f, 0x2d, 0xa9, 0xbe, - 0xcb, 0x93, 0x6a, 0xb3, 0xc4, 0x47, 0x1d, 0x0b, 0x9f, 0x45, 0xd5, 0x3e, 0x66, 0x42, 0x29, 0xd2, - 0x30, 0x17, 0x45, 0x14, 0x05, 0x91, 0x66, 0x89, 0x12, 0xec, 0x3d, 0xcc, 0xf8, 0x2c, 0xbe, 0x3e, - 0x83, 0x35, 0xca, 0xda, 0x5c, 0x74, 0xd9, 0x7f, 0x34, 0x32, 0x5f, 0x22, 0x5b, 0x9e, 0x16, 0xa6, - 0xa6, 0x45, 0x8e, 0x76, 0xcd, 0x02, 0xed, 0xd8, 0x23, 0xb8, 0xb1, 0x74, 0x62, 0xa9, 0x96, 0x39, - 0x29, 0xe0, 0x63, 0x07, 0x15, 0x6a, 0x7d, 0x8a, 0x23, 0x5f, 0xc3, 0xcd, 0x9c, 0xad, 0x13, 0x86, - 0x13, 0x4a, 0x6a, 0x83, 0x92, 0x7a, 0x90, 0x5a, 0x1f, 0x87, 0xe1, 0xc8, 0x89, 0x17, 0xf6, 0x83, - 0x6c, 0xfd, 0x05, 0x92, 0x2e, 0x83, 0x79, 0x42, 0xd2, 0x65, 0x30, 0xb7, 0xc3, 0xcc, 0x2c, 0x83, - 0x26, 0x03, 0x63, 0x1a, 0xb8, 0x6a, 0xf5, 0x5b, 0x9c, 0xda, 0xe9, 0xc2, 0x9a, 0x39, 0x0c, 0xea, - 0xe1, 0x5a, 0xe9, 0x70, 0xec, 0x3e, 0x18, 0xd2, 0x99, 0xc7, 0x96, 0x41, 0xac, 0x4a, 0xa0, 0xf2, - 0xe6, 0xc3, 0x3b, 0xc7, 0x8b, 0x38, 0xa9, 0xec, 0x00, 0x91, 0x52, 0x88, 0xe7, 0xff, 0xf1, 0xbf, - 0x01, 0xb4, 0xe6, 0x4e, 0x4c, 0x9b, 0x60, 0x70, 0x6c, 0x62, 0xcf, 0x4c, 0x08, 0x4a, 0x5a, 0x83, - 0x63, 0xd3, 0xfe, 0xb3, 0x91, 0x9d, 0x5a, 0x8a, 0xf4, 0x6b, 0xff, 0xdb, 0x85, 0xb6, 0xe7, 0xbb, - 0x62, 0x4d, 0x3f, 0x6c, 0x71, 0x25, 0x24, 0x57, 0x4f, 0x8b, 0x26, 0x51, 0xbc, 0x7a, 0xd4, 0xc6, - 0x2b, 0x41, 0x43, 0x3e, 0x98, 0xd1, 0x7f, 0x37, 0xb9, 0x12, 0x72, 0xa8, 0xec, 0x14, 0xae, 0x04, - 0xbd, 0x8e, 0x6e, 0x76, 0x0c, 0xbf, 0xe0, 0xb5, 0x94, 0xcf, 0xd8, 0xff, 0xbe, 0x27, 0xf6, 0xcd, - 0xec, 0x48, 0xd3, 0xd4, 0xb4, 0x77, 0x81, 0x5d, 0xcf, 0x39, 0x75, 0xdb, 0x16, 0xb3, 0x89, 0x7d, - 0x09, 0x6d, 0xd7, 0x9b, 0xcd, 0xea, 0xef, 0x1b, 0xa5, 0xb6, 0xff, 0x6a, 0x42, 0x47, 0xdd, 0x16, - 0xec, 0x0e, 0x92, 0xcb, 0xf1, 0xfc, 0x89, 0xe7, 0x26, 0x19, 0x43, 0xf2, 0xd8, 0xcd, 0x6d, 0x41, - 0xb3, 0xb0, 0x05, 0x0c, 0x0c, 0xe9, 0x5d, 0x08, 0x1d, 0xec, 0xd4, 0x66, 0xb7, 0xa1, 0xeb, 0xaf, - 0x2e, 0x26, 0x72, 0x9d, 0x1c, 0x68, 0xc7, 0x5f, 0x5d, 0x9c, 0xae, 0x63, 0x76, 0x08, 0x5b, 0xb9, - 0xd0, 0xf7, 0x5c, 0x8d, 0xe4, 0x6d, 0x3d, 0x35, 0x9a, 0xf7, 0xf8, 0x15, 0xef, 0xa7, 0x49, 0x30, - 0x76, 0xd9, 0x1e, 0x50, 0x4e, 0x4c, 0x14, 0xf6, 0x54, 0xae, 0x74, 0x68, 0xdf, 0xb6, 0xb1, 0x5f, - 0x73, 0x11, 0xaf, 0xc2, 0xbb, 0x60, 0xe2, 0x4e, 0x2a, 0x93, 0x2e, 0x99, 0xf4, 0xb0, 0x83, 0x94, - 0x0f, 0x61, 0x27, 0xbb, 0x5e, 0x95, 0x49, 0x4f, 0x8d, 0x92, 0x75, 0x93, 0xe1, 0x1d, 0xe8, 0xa5, - 0x39, 0x69, 0x92, 0x45, 0xd7, 0xd1, 0xa9, 0x38, 0x86, 0xae, 0x9e, 0x62, 0xe5, 0x55, 0xfc, 0x08, - 0xda, 0xa1, 0x13, 0xc9, 0x58, 0x5f, 0x79, 0x09, 0x91, 0xdf, 0x39, 0x11, 0xd6, 0x40, 0xfa, 0x42, - 0x56, 0x26, 0xf6, 0x11, 0x6c, 0x15, 0xfa, 0x31, 0xf0, 0x64, 0x20, 0x9d, 0xa5, 0xbe, 0x8c, 0x95, - 0x90, 0xfe, 0xa6, 0x99, 0xfd, 0xc6, 0x3e, 0x02, 0x33, 0x3d, 0x43, 0x3c, 0x96, 0x70, 0x75, 0xf6, - 0x46, 0x57, 0x55, 0x9b, 0x5c, 0x4b, 0x14, 0xc7, 0xc1, 0xef, 0xba, 0x2a, 0x30, 0xb8, 0x12, 0xec, - 0xbf, 0x1b, 0xd0, 0x51, 0x39, 0x5c, 0x51, 0x8b, 0x7d, 0x4b, 0x45, 0xca, 0x4a, 0x4c, 0x70, 0xda, - 0xe4, 0xb7, 0x9d, 0xd6, 0xff, 0xca, 0xe9, 0xe0, 0xf4, 0x2a, 0x14, 0xdc, 0x24, 0x2b, 0x6c, 0xb2, - 0xfb, 0xb0, 0xa9, 0x5c, 0x62, 0x19, 0x79, 0x7e, 0x12, 0xbc, 0x7d, 0xea, 0x7b, 0x4f, 0x5d, 0x78, - 0x28, 0xca, 0xc4, 0xf3, 0x25, 0x45, 0x43, 0x8b, 0xf7, 0xa8, 0x63, 0xec, 0x4b, 0xfb, 0x2e, 0x18, - 0x34, 0x0e, 0x40, 0xe7, 0xfd, 0x29, 0x1f, 0xbf, 0xfd, 0x79, 0xb0, 0xc1, 0xba, 0xd0, 0x1a, 0xbf, - 0x3d, 0x1d, 0x34, 0x0e, 0x3f, 0xb5, 0x61, 0xe7, 0xf8, 0xe4, 0xe5, 0xf8, 0x38, 0x0c, 0x97, 0xde, - 0xd4, 0x21, 0xee, 0x3d, 0x01, 0x83, 0xc8, 0x5e, 0xf1, 0xdc, 0x19, 0x56, 0x95, 0x18, 0xec, 0x10, - 0xda, 0x04, 0x78, 0x56, 0xf5, 0xea, 0x19, 0x56, 0x56, 0x1a, 0xf8, 0x13, 0x75, 0x05, 0x5c, 0x7f, - 0xfc, 0x0c, 0xab, 0xca, 0x0d, 0xf6, 0x23, 0x98, 0x19, 0x9a, 0xeb, 0x9e, 0x40, 0xc3, 0xda, 0xc2, - 0x03, 0xfd, 0x33, 0x66, 0xd7, 0x3d, 0x84, 0x86, 0xb5, 0xd5, 0x07, 0x7b, 0x0e, 0xdd, 0x84, 0xc0, - 0xd5, 0xcf, 0xa1, 0x61, 0x4d, 0x01, 0x82, 0xdb, 0xa3, 0x48, 0x5a, 0xf5, 0xca, 0x19, 0x56, 0xd6, - 0x14, 0xec, 0x19, 0x74, 0x34, 0xda, 0x2a, 0x5f, 0x52, 0xc3, 0xea, 0xca, 0x05, 0x17, 0x99, 0x15, - 0xc4, 0x75, 0x4f, 0xa4, 0x61, 0x6d, 0x4d, 0xc2, 0x8e, 0x01, 0x72, 0xa5, 0x70, 0xed, 0x43, 0x69, - 0x58, 0x5f, 0x99, 0xb0, 0x17, 0xd0, 0xcb, 0xaa, 0xdf, 0xea, 0xe7, 0xd2, 0xb0, 0xae, 0x38, 0x39, - 0xeb, 0xd0, 0x4b, 0xfc, 0xe9, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x90, 0x66, 0x37, 0xca, 0x9e, - 0x0f, 0x00, 0x00, + // 1485 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x8e, 0x13, 0x47, + 0x10, 0x5e, 0xdb, 0xe3, 0xbf, 0xf2, 0xfe, 0x98, 0x66, 0x03, 0xc6, 0x1c, 0x80, 0x91, 0x08, 0xbb, + 0x04, 0xd6, 0x64, 0x11, 0x11, 0x1b, 0xa2, 0x48, 0x6b, 0x16, 0x62, 0x0b, 0x89, 0x90, 0x61, 0xc5, + 0xd5, 0x1a, 0x7b, 0xda, 0xf6, 0x08, 0x7b, 0x66, 0x98, 0x69, 0x2f, 0x5e, 0x29, 0x8f, 0xc0, 0x3d, + 0xe7, 0xe4, 0x12, 0x29, 0x2f, 0x90, 0x37, 0x88, 0xf2, 0x0c, 0x39, 0xf0, 0x2c, 0x51, 0x55, 0xf7, + 0xfc, 0xee, 0x0c, 0x07, 0x0e, 0x5c, 0x56, 0x5d, 0x5d, 0xf5, 0xb5, 0xab, 0x7a, 0xaa, 0xbf, 0xaa, + 0x5a, 0xb8, 0x24, 0xce, 0x3d, 0x1e, 0xf4, 0xe8, 0xef, 0x81, 0xe7, 0xbb, 0xc2, 0x65, 0x55, 0x12, + 0xba, 0xf7, 0x67, 0xb6, 0x98, 0xaf, 0xc6, 0x07, 0x13, 0x77, 0xd9, 0x9b, 0xb9, 0x33, 0xb7, 0x47, + 0xda, 0xf1, 0x6a, 0x4a, 0x12, 0x09, 0xb4, 0x92, 0x28, 0xfd, 0x1f, 0x0d, 0xea, 0x06, 0x7f, 0xb7, + 0xe2, 0x81, 0x60, 0x7b, 0xa0, 0xf1, 0xc9, 0xdc, 0xed, 0x94, 0x6e, 0x96, 0xf6, 0x5a, 0x87, 0xec, + 0x40, 0x9e, 0xae, 0xb4, 0xcf, 0x26, 0x73, 0x77, 0xb0, 0x61, 0x90, 0x05, 0xfb, 0x06, 0xaa, 0xd3, + 0xc5, 0x2a, 0x98, 0x77, 0xca, 0x64, 0x7a, 0x39, 0x6d, 0xfa, 0x1c, 0x55, 0x83, 0x0d, 0x43, 0xda, + 0xe0, 0xb1, 0xb6, 0x33, 0x75, 0x3b, 0x95, 0xbc, 0x63, 0x87, 0xce, 0x94, 0x8e, 0x45, 0x0b, 0xf6, + 0x18, 0x20, 0xe0, 0x62, 0xe4, 0x7a, 0xc2, 0x76, 0x9d, 0x8e, 0x46, 0xf6, 0x57, 0xd3, 0xf6, 0xaf, + 0xb9, 0xf8, 0x99, 0xd4, 0x83, 0x0d, 0xa3, 0x19, 0x84, 0x02, 0x22, 0x2d, 0xbe, 0xb0, 0xcf, 0xb8, + 0x3f, 0x12, 0xeb, 0x4e, 0x35, 0x0f, 0x79, 0x22, 0xf5, 0xa7, 0x6b, 0x44, 0x5a, 0xa1, 0xc0, 0x0e, + 0xa1, 0x31, 0x99, 0xf3, 0xc9, 0x5b, 0xc4, 0xd5, 0x08, 0xf7, 0x55, 0x1a, 0xf7, 0x14, 0xb5, 0x84, + 0xaa, 0x4f, 0xe4, 0x92, 0x1d, 0x40, 0x6d, 0xe2, 0x2e, 0x97, 0xb6, 0xe8, 0xd4, 0x09, 0xb1, 0x9b, + 0x41, 0x90, 0x6e, 0xb0, 0x61, 0x28, 0x2b, 0xbc, 0xae, 0x77, 0x2b, 0xee, 0x9f, 0x77, 0x1a, 0x79, + 0xd7, 0xf5, 0x0b, 0xaa, 0xf0, 0xba, 0xc8, 0x06, 0x43, 0xb1, 0x1d, 0x5b, 0x8c, 0x26, 0x73, 0xd3, + 0x76, 0x3a, 0xcd, 0xbc, 0x50, 0x86, 0x8e, 0x2d, 0x9e, 0xa2, 0x1a, 0x43, 0xb1, 0x43, 0x81, 0x3d, + 0x81, 0xd6, 0x98, 0xcf, 0x6c, 0x67, 0x34, 0x5e, 0xb8, 0x93, 0xb7, 0x1d, 0x20, 0x68, 0x27, 0x0d, + 0xed, 0xa3, 0x41, 0x1f, 0xf5, 0x83, 0x0d, 0x03, 0xc6, 0x91, 0xc4, 0x1e, 0x41, 0x93, 0x3b, 0x96, + 0x82, 0xb6, 0x08, 0x7a, 0x25, 0x93, 0x01, 0x8e, 0x15, 0x02, 0x1b, 0x5c, 0xad, 0xfb, 0x75, 0xa8, + 0x9e, 0x99, 0x8b, 0x15, 0xd7, 0xef, 0x40, 0x2b, 0x91, 0x29, 0xac, 0x03, 0xf5, 0x25, 0x0f, 0x02, + 0x73, 0xc6, 0x29, 0x9d, 0x9a, 0x46, 0x28, 0xea, 0xdb, 0xb0, 0x99, 0xcc, 0x93, 0x04, 0x10, 0x73, + 0x01, 0x81, 0x67, 0xdc, 0x0f, 0x30, 0x01, 0x14, 0x50, 0x89, 0xfa, 0xf7, 0xd0, 0xce, 0x26, 0x01, + 0x6b, 0x43, 0xe5, 0x2d, 0x3f, 0x57, 0x96, 0xb8, 0x64, 0xbb, 0xca, 0x21, 0x4a, 0xcd, 0xa6, 0xa1, + 0xbc, 0xd3, 0x23, 0x6c, 0x94, 0x06, 0x6c, 0x1b, 0xca, 0x62, 0x4d, 0xd0, 0x4d, 0xa3, 0x2c, 0xd6, + 0xfa, 0x4d, 0xd8, 0x4e, 0x7f, 0xf2, 0x0b, 0x16, 0x56, 0xe4, 0x3a, 0x7d, 0x33, 0xc6, 0x40, 0xb3, + 0x4c, 0x61, 0x2a, 0x0b, 0x5a, 0xe3, 0x9e, 0x67, 0x8a, 0xb9, 0xfa, 0x79, 0x5a, 0xb3, 0x2b, 0x50, + 0x9b, 0x73, 0x7b, 0x36, 0x17, 0xf4, 0x06, 0x34, 0x43, 0x49, 0xe8, 0xab, 0xe7, 0xbb, 0x67, 0x9c, + 0x52, 0xbd, 0x61, 0x48, 0x41, 0xdf, 0x81, 0xad, 0x54, 0x22, 0xe9, 0x27, 0x91, 0xf3, 0xd1, 0x87, + 0x67, 0x0f, 0x00, 0xce, 0xcc, 0x85, 0x6d, 0x99, 0xc2, 0xf5, 0x83, 0x4e, 0xe9, 0x66, 0x65, 0xaf, + 0x75, 0xd8, 0x56, 0xdf, 0xeb, 0x4d, 0xa8, 0x30, 0x12, 0x36, 0xfa, 0x4b, 0xb8, 0x74, 0x21, 0x07, + 0xd0, 0xdb, 0xb9, 0x19, 0xcc, 0xc3, 0x08, 0x70, 0xcd, 0x6e, 0xa3, 0xb7, 0xa6, 0xc5, 0x7d, 0xf5, + 0xba, 0xb7, 0xd4, 0xb1, 0x03, 0xda, 0x34, 0x94, 0x52, 0xdf, 0x87, 0x9d, 0x4c, 0x62, 0x24, 0xe2, + 0x2c, 0x25, 0xe3, 0xd4, 0x3f, 0x54, 0xa1, 0x61, 0xf0, 0xc0, 0x73, 0x9d, 0x80, 0xb3, 0xc7, 0xd0, + 0xe4, 0xeb, 0x09, 0x97, 0x6f, 0xbc, 0x94, 0xc9, 0x51, 0x69, 0xf3, 0x2c, 0xd4, 0x63, 0x7e, 0x47, + 0xc6, 0x6c, 0x5f, 0xf1, 0x53, 0x96, 0x74, 0x14, 0x28, 0x49, 0x50, 0xf7, 0x42, 0x82, 0xaa, 0x64, + 0x1e, 0xa8, 0xb4, 0xcd, 0x30, 0xd4, 0xbe, 0x62, 0x28, 0x2d, 0xf7, 0xe0, 0x14, 0x45, 0x1d, 0xa5, + 0x28, 0xaa, 0x9a, 0xeb, 0x7e, 0x01, 0x47, 0x1d, 0xa5, 0x38, 0xaa, 0x96, 0x0b, 0x2d, 0x20, 0xa9, + 0x87, 0x09, 0x92, 0xaa, 0x67, 0xde, 0xa6, 0x04, 0xe6, 0xb0, 0x54, 0x2f, 0x62, 0xa9, 0x46, 0x86, + 0xd7, 0x14, 0x24, 0x4b, 0x53, 0xf7, 0x42, 0x9a, 0x6a, 0xe6, 0x5e, 0x5a, 0x86, 0xa7, 0x8e, 0x52, + 0x3c, 0x05, 0xb9, 0xe1, 0x14, 0x10, 0xd5, 0x0f, 0x69, 0xa2, 0x92, 0x6c, 0x73, 0x2d, 0x83, 0x2d, + 0x64, 0xaa, 0xef, 0x92, 0x4c, 0xb5, 0x99, 0xe1, 0x47, 0x95, 0x0b, 0x9f, 0xa4, 0xaa, 0x7d, 0x7c, + 0x09, 0x99, 0x4c, 0xc3, 0xb7, 0xc8, 0x7d, 0xdf, 0xf5, 0x15, 0x97, 0x48, 0x41, 0xdf, 0xc3, 0x17, + 0x1f, 0xe7, 0xd7, 0x27, 0x68, 0x8d, 0x5e, 0x6d, 0x22, 0xbb, 0xf4, 0xdf, 0x4a, 0x31, 0x96, 0x98, + 0x2d, 0xc9, 0x16, 0x4d, 0xc5, 0x16, 0x09, 0xb6, 0x2b, 0xa7, 0xd8, 0x8e, 0xdd, 0x85, 0x4b, 0x0b, + 0x33, 0x10, 0x32, 0xcc, 0x51, 0x8a, 0x3e, 0x76, 0x50, 0x21, 0xe3, 0x93, 0x3c, 0x72, 0x1f, 0x2e, + 0x27, 0x6c, 0x4d, 0xcf, 0x1b, 0xd1, 0xa3, 0xd6, 0xe8, 0x51, 0xb7, 0x23, 0xeb, 0x63, 0xcf, 0x1b, + 0x98, 0xc1, 0x5c, 0xbf, 0x1d, 0xc7, 0x9f, 0x62, 0xd2, 0x85, 0x3b, 0x0b, 0x99, 0x74, 0xe1, 0xce, + 0xf4, 0x3f, 0x4a, 0xb1, 0x5d, 0xcc, 0x9a, 0x0c, 0xb4, 0x89, 0x6b, 0xc9, 0xf0, 0xb7, 0x0c, 0x5a, + 0xb3, 0x13, 0x15, 0x19, 0x86, 0xb0, 0xd9, 0x7f, 0xf0, 0xef, 0xc7, 0x1b, 0x1b, 0xff, 0x7d, 0xbc, + 0xb1, 0x97, 0xe8, 0x44, 0x04, 0x77, 0x2c, 0xee, 0x2f, 0x6d, 0x47, 0xf4, 0x66, 0xee, 0xfd, 0xf7, + 0xb6, 0xcf, 0x7b, 0x88, 0x38, 0xe8, 0x9f, 0x0b, 0x1e, 0xa8, 0xbb, 0x50, 0x1e, 0x54, 0x22, 0x0f, + 0xd8, 0x2d, 0xd0, 0x84, 0x39, 0x0b, 0x3a, 0x1a, 0xd1, 0x5b, 0xc8, 0x43, 0x2f, 0xde, 0xbc, 0x32, + 0x6d, 0xdf, 0x20, 0x95, 0xfe, 0x7b, 0x09, 0x69, 0x28, 0xf5, 0x06, 0xbe, 0xa8, 0x8b, 0x6d, 0xa8, + 0xcc, 0xcc, 0x80, 0xae, 0x5a, 0x33, 0x70, 0x89, 0x3b, 0x53, 0xce, 0x89, 0x1a, 0x34, 0x03, 0x97, + 0xfa, 0xdf, 0xe5, 0x38, 0x37, 0xa2, 0xc2, 0x71, 0xc1, 0xc3, 0x5d, 0xa8, 0xda, 0x8e, 0xc5, 0xd7, + 0xe4, 0x62, 0xc5, 0x90, 0x02, 0xeb, 0xcb, 0x02, 0x57, 0xf9, 0x4c, 0xb7, 0xa9, 0x24, 0x3e, 0x0f, + 0x4b, 0xa2, 0xf6, 0x99, 0xa7, 0x48, 0x38, 0x9e, 0xe3, 0xf9, 0xae, 0x3b, 0xa5, 0xd8, 0x3e, 0xeb, + 0x1c, 0x82, 0x27, 0xca, 0x44, 0x2d, 0x55, 0x0e, 0xd5, 0xed, 0xd6, 0xe3, 0x14, 0xfc, 0x15, 0x4b, + 0x72, 0x92, 0xad, 0xbe, 0xe4, 0xb7, 0xd5, 0x2f, 0xc7, 0xf9, 0x1f, 0x11, 0x99, 0xbe, 0x0b, 0xec, + 0x22, 0x43, 0xc9, 0xde, 0x24, 0xcd, 0x3d, 0xec, 0x6b, 0xa8, 0x5a, 0xf6, 0x74, 0x5a, 0x5c, 0x9d, + 0xa5, 0x5a, 0xff, 0xb3, 0x0c, 0x35, 0x59, 0x5b, 0xd9, 0x35, 0xe4, 0x79, 0xd3, 0x76, 0x46, 0xb6, + 0x15, 0xf2, 0x0b, 0xc9, 0x43, 0x2b, 0x71, 0x69, 0xe5, 0xd4, 0xa5, 0x31, 0xd0, 0x84, 0xbd, 0xe4, + 0x8a, 0x1a, 0x68, 0xcd, 0xae, 0x42, 0xdd, 0x59, 0x2d, 0x47, 0x62, 0x1d, 0x26, 0x66, 0xcd, 0x59, + 0x2d, 0x4f, 0xd7, 0x01, 0x3b, 0x84, 0xad, 0x04, 0x51, 0xd8, 0x96, 0x2a, 0x60, 0xdb, 0xca, 0x35, + 0xf2, 0x7b, 0x78, 0x62, 0xb4, 0x22, 0xca, 0x18, 0x5a, 0x6c, 0x0f, 0x88, 0x41, 0x46, 0xb2, 0x48, + 0x48, 0x66, 0xa9, 0x11, 0xb3, 0x6c, 0xe3, 0xbe, 0xaa, 0x22, 0xd8, 0x38, 0x5c, 0x87, 0x26, 0xde, + 0xa4, 0x34, 0xa9, 0x93, 0x49, 0x03, 0x37, 0x48, 0x79, 0x07, 0x76, 0xe2, 0x66, 0x44, 0x9a, 0x34, + 0xe4, 0x29, 0xf1, 0x36, 0x19, 0x5e, 0x83, 0x46, 0xc4, 0x60, 0x4d, 0xb2, 0xa8, 0x9b, 0x8a, 0xb8, + 0x86, 0x50, 0x57, 0x2e, 0xe6, 0x36, 0x2e, 0x77, 0xa1, 0xea, 0x99, 0xbe, 0x08, 0x54, 0x83, 0x10, + 0xd6, 0xaf, 0x57, 0xa6, 0x8f, 0x1d, 0xa3, 0x6a, 0x5f, 0xa4, 0x89, 0x7e, 0x04, 0x5b, 0xa9, 0x7d, + 0x7c, 0x7e, 0xc2, 0x15, 0xe6, 0x42, 0xb5, 0x2e, 0x52, 0x88, 0x7e, 0xa6, 0x1c, 0xff, 0x8c, 0x7e, + 0x04, 0xcd, 0xe8, 0x1b, 0xe2, 0x67, 0xf1, 0x56, 0xe3, 0x17, 0xaa, 0x07, 0xdd, 0x34, 0x94, 0x44, + 0xad, 0x9d, 0xfb, 0x5e, 0xf5, 0x50, 0x9a, 0x21, 0x05, 0xfd, 0xaf, 0x12, 0xd4, 0x24, 0x7d, 0xe5, + 0x74, 0xae, 0xdf, 0x52, 0x4b, 0xb7, 0xe2, 0x23, 0x74, 0x9b, 0x70, 0xdb, 0xd1, 0xb4, 0x24, 0x41, + 0x07, 0xa7, 0xe7, 0x1e, 0x37, 0x9a, 0x64, 0x85, 0x4b, 0x76, 0x0b, 0x36, 0x25, 0x24, 0x10, 0xbe, + 0xed, 0x84, 0xc9, 0xdb, 0xa2, 0xbd, 0xd7, 0xb4, 0x85, 0x1f, 0x45, 0x9a, 0xd8, 0x8e, 0xa0, 0x6c, + 0xa8, 0x18, 0x0d, 0xda, 0x18, 0x3a, 0x42, 0xbf, 0x0e, 0x1a, 0x9d, 0x03, 0x50, 0x7b, 0x7d, 0x6a, + 0x0c, 0x5f, 0xfe, 0xd4, 0xde, 0x60, 0x75, 0xa8, 0x0c, 0x5f, 0x9e, 0xb6, 0x4b, 0x87, 0x1f, 0xaa, + 0xb0, 0x73, 0xdc, 0x7f, 0x3a, 0x3c, 0xf6, 0xbc, 0x85, 0x3d, 0x31, 0xa9, 0x4a, 0xf4, 0x40, 0xa3, + 0x3a, 0x98, 0x33, 0x1c, 0x76, 0xf3, 0x1a, 0x32, 0x76, 0x08, 0x55, 0x2a, 0x87, 0x2c, 0x6f, 0x46, + 0xec, 0xe6, 0xf6, 0x65, 0xf8, 0x23, 0xb2, 0x60, 0x5e, 0x1c, 0x15, 0xbb, 0x79, 0xcd, 0x19, 0xfb, + 0x11, 0x9a, 0x71, 0x21, 0x2b, 0x1a, 0x18, 0xbb, 0x85, 0x6d, 0x1a, 0xe2, 0xe3, 0x02, 0x57, 0x34, + 0x36, 0x76, 0x0b, 0x7b, 0x35, 0xf6, 0x18, 0xea, 0x61, 0xed, 0xc9, 0x1f, 0x1e, 0xbb, 0x05, 0xed, + 0x1a, 0x5e, 0x8f, 0xac, 0x08, 0x79, 0x33, 0x61, 0x37, 0xb7, 0x03, 0x63, 0x8f, 0xa0, 0xa6, 0xc8, + 0x30, 0x77, 0xee, 0xec, 0xe6, 0xf7, 0x79, 0x18, 0x64, 0x3c, 0x3e, 0x14, 0x0d, 0x94, 0xdd, 0xc2, + 0x0e, 0x8e, 0x1d, 0x03, 0x24, 0x06, 0x87, 0xc2, 0xb1, 0xb2, 0x5b, 0xdc, 0xc7, 0xb1, 0x27, 0xd0, + 0x88, 0x67, 0x85, 0xfc, 0xe1, 0xb2, 0x5b, 0xd4, 0xca, 0x8d, 0x6b, 0xf4, 0x0f, 0x8b, 0x87, 0xff, + 0x07, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xbb, 0x93, 0x98, 0xfb, 0x10, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 48608cd4..2754a362 100644 --- a/types/types.proto +++ b/types/types.proto @@ -1,6 +1,9 @@ syntax = "proto3"; package types; +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + + // This file is copied from http://github.com/tendermint/abci //---------------------------------------- @@ -114,14 +117,14 @@ message ResponseSetOption{ message ResponseDeliverTx{ uint32 code = 1; - bytes data = 2; + bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; string log = 3; repeated KVPair tags = 4; } message ResponseCheckTx{ uint32 code = 1; - bytes data = 2; + bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; string log = 3; uint64 gas = 4; uint64 fee = 5; @@ -130,16 +133,16 @@ message ResponseCheckTx{ message ResponseQuery{ uint32 code = 1; int64 index = 2; - bytes key = 3; - bytes value = 4; - bytes proof = 5; + bytes key = 3 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + bytes value = 4 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + bytes proof = 5 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; uint64 height = 6; string log = 7; } message ResponseCommit{ uint32 code = 1; - bytes data = 2; + bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; string log = 3; } From 550d6a6081dbdc0c4acee7f101f1828852ddca8f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 15:37:31 -0500 Subject: [PATCH 369/545] shame: forgot to add new code pkg --- example/code/code.go | 9 +++++++++ example/counter/counter.go | 8 ++++---- example/dummy/dummy.go | 7 ++++--- example/dummy/dummy_test.go | 17 ++++++++++------- example/dummy/persistent_dummy.go | 4 ++-- example/example_test.go | 10 ++++++---- 6 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 example/code/code.go diff --git a/example/code/code.go b/example/code/code.go new file mode 100644 index 00000000..94e9d015 --- /dev/null +++ b/example/code/code.go @@ -0,0 +1,9 @@ +package code + +// Return codes for the examples +const ( + CodeTypeOK uint32 = 0 + CodeTypeEncodingError uint32 = 1 + CodeTypeBadNonce uint32 = 2 + CodeTypeUnauthorized uint32 = 3 +) diff --git a/example/counter/counter.go b/example/counter/counter.go index 67fa06e3..0978799e 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -50,7 +50,7 @@ func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { } } app.txCount++ - return types.ResponseDeliverTx{Code: types.CodeTypeOK} + return types.ResponseDeliverTx{Code: code.CodeTypeOK} } func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { @@ -69,17 +69,17 @@ func (app *CounterApplication) CheckTx(tx []byte) types.ResponseCheckTx { Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)} } } - return types.ResponseCheckTx{Code: types.CodeTypeOK} + return types.ResponseCheckTx{Code: code.CodeTypeOK} } func (app *CounterApplication) Commit() (resp types.ResponseCommit) { app.hashCount++ if app.txCount == 0 { - return types.ResponseCommit{Code: types.CodeTypeOK} + return types.ResponseCommit{Code: code.CodeTypeOK} } hash := make([]byte, 8) binary.BigEndian.PutUint64(hash, uint64(app.txCount)) - return types.ResponseCommit{Code: types.CodeTypeOK, Data: hash} + return types.ResponseCommit{Code: code.CodeTypeOK, Data: hash} } func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 8329ef03..fdb4851c 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" + "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/types" wire "github.com/tendermint/go-wire" "github.com/tendermint/iavl" @@ -42,11 +43,11 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { {Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}, {Key: "app.key", ValueType: types.KVPair_STRING, ValueString: string(key)}, } - return types.ResponseDeliverTx{Code: types.CodeTypeOK, Tags: tags} + return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags} } func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx { - return types.ResponseCheckTx{Code: types.CodeTypeOK} + return types.ResponseCheckTx{Code: code.CodeTypeOK} } func (app *DummyApplication) Commit() types.ResponseCommit { @@ -64,7 +65,7 @@ func (app *DummyApplication) Commit() types.ResponseCommit { } } - return types.ResponseCommit{Code: types.CodeTypeOK, Data: hash} + return types.ResponseCommit{Code: code.CodeTypeOK, Data: hash} } func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 65970ecd..738da6e8 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -7,12 +7,15 @@ import ( "testing" "github.com/stretchr/testify/require" - abcicli "github.com/tendermint/abci/client" - abciserver "github.com/tendermint/abci/server" - "github.com/tendermint/abci/types" + "github.com/tendermint/iavl" cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/tmlibs/log" + + abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/example/code" + abciserver "github.com/tendermint/abci/server" + "github.com/tendermint/abci/types" ) func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { @@ -27,7 +30,7 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string Path: "/store", Data: []byte(key), }) - require.Equal(t, types.CodeTypeOK, resQuery.Code) + require.Equal(t, code.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) // make sure proof is fine @@ -36,7 +39,7 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string Data: []byte(key), Prove: true, }) - require.EqualValues(t, types.CodeTypeOK, resQuery.Code) + require.EqualValues(t, code.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) proof, err := iavl.ReadKeyExistsProof(resQuery.Proof) require.Nil(t, err) @@ -295,7 +298,7 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) Data: []byte(key), }) require.Nil(t, err) - require.Equal(t, types.CodeTypeOK, resQuery.Code) + require.Equal(t, code.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) // make sure proof is fine @@ -305,7 +308,7 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) Prove: true, }) require.Nil(t, err) - require.Equal(t, types.CodeTypeOK, resQuery.Code) + require.Equal(t, code.CodeTypeOK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) proof, err := iavl.ReadKeyExistsProof(resQuery.Proof) require.Nil(t, err) diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 51da8b30..1d72bea1 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -97,7 +97,7 @@ func (app *PersistentDummyApplication) Commit() types.ResponseCommit { } app.logger.Info("Commit block", "height", height, "root", appHash) - return types.ResponseCommit{Code: types.CodeTypeOK, Data: appHash} + return types.ResponseCommit{Code: code.CodeTypeOK, Data: appHash} } func (app *PersistentDummyApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery { @@ -217,5 +217,5 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types // we only update the changes array if we successfully updated the tree app.changes = append(app.changes, v) - return types.ResponseDeliverTx{Code: types.CodeTypeOK} + return types.ResponseDeliverTx{Code: code.CodeTypeOK} } diff --git a/example/example_test.go b/example/example_test.go index 7fd3bb52..dfa38a39 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -11,12 +11,14 @@ import ( "golang.org/x/net/context" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" + abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/example/dummy" abciserver "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" ) func TestDummy(t *testing.T) { @@ -60,7 +62,7 @@ func testStream(t *testing.T, app types.Application) { switch r := res.Value.(type) { case *types.Response_DeliverTx: counter++ - if r.DeliverTx.Code != types.CodeTypeOK { + if r.DeliverTx.Code != code.CodeTypeOK { t.Error("DeliverTx failed with ret_code", r.DeliverTx.Code) } if counter > numDeliverTxs { @@ -135,7 +137,7 @@ func testGRPCSync(t *testing.T, app *types.GRPCApplication) { t.Fatalf("Error in GRPC DeliverTx: %v", err.Error()) } counter++ - if response.Code != types.CodeTypeOK { + if response.Code != code.CodeTypeOK { t.Error("DeliverTx failed with ret_code", response.Code) } if counter > numDeliverTxs { From 10031f57d5ae773f5d2013e94f03d9c35a785b1f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 17:20:36 -0500 Subject: [PATCH 370/545] fix grpc version; add log_level and some logging --- client/grpc_client.go | 2 ++ cmd/abci-cli/abci-cli.go | 66 ++++++++++++++++++++++------------------ glide.lock | 20 ++++++------ glide.yaml | 5 ++- server/grpc_server.go | 1 + tests/test_app/test.sh | 5 +++ tests/test_cli/test.sh | 2 +- 7 files changed, 60 insertions(+), 41 deletions(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 0afadc72..308a9e13 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -60,6 +60,7 @@ RETRY_LOOP: continue RETRY_LOOP } + cli.Logger.Info("Dialed server. Waiting for echo.", "addr", cli.addr) client := types.NewABCIApplicationClient(conn) ENSURE_CONNECTED: @@ -68,6 +69,7 @@ RETRY_LOOP: if err == nil { break ENSURE_CONNECTED } + cli.Logger.Info("Echo failed", "err", err) time.Sleep(time.Second * echoRetryIntervalSeconds) } diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index cc60a4bc..25786b37 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -10,46 +10,32 @@ import ( "os/exec" "strings" + "github.com/spf13/cobra" + + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" "github.com/tendermint/abci/version" - cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" - - "github.com/spf13/cobra" ) -// Structure for data passed to print response. -type response struct { - // generic abci response - Data []byte - Code uint32 - Log string - - Query *queryResponse -} - -type queryResponse struct { - Key []byte - Value []byte - Height uint64 - Proof []byte -} - // client is a global variable so it can be reused by the console -var client abcicli.Client - -var logger log.Logger +var ( + client abcicli.Client + logger log.Logger +) // flags var ( // global - address string - abci string - verbose bool + address string + abci string + verbose bool // for the println output + logLevel string // for the logger // query path string @@ -79,7 +65,11 @@ var RootCmd = &cobra.Command{ } if logger == nil { - logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), log.AllowError()) + allowLevel, err := log.AllowLevel(logLevel) + if err != nil { + return err + } + logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), allowLevel) } if client == nil { var err error @@ -96,6 +86,23 @@ var RootCmd = &cobra.Command{ }, } +// Structure for data passed to print response. +type response struct { + // generic abci response + Data []byte + Code uint32 + Log string + + Query *queryResponse +} + +type queryResponse struct { + Key []byte + Value []byte + Height uint64 + Proof []byte +} + func Execute() error { addGlobalFlags() addCommands() @@ -103,9 +110,10 @@ func Execute() error { } func addGlobalFlags() { - RootCmd.PersistentFlags().StringVarP(&address, "address", "", "tcp://127.0.0.1:46658", "Address of application socket") + RootCmd.PersistentFlags().StringVarP(&address, "address", "", "tcp://0.0.0.0:46658", "Address of application socket") RootCmd.PersistentFlags().StringVarP(&abci, "abci", "", "socket", "Either socket or grpc") RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print the command and results as if it were a console session") + RootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "debug", "Set the logger level") } func addQueryFlags() { diff --git a/glide.lock b/glide.lock index d52acc7b..f96fd1c0 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: 971ad090f3190ffd759deecf118a0eaefe7eceb4b1a8057800e332712fc1a7c2 -updated: 2017-11-30T15:29:31.740172292-05:00 +hash: 6cb2c869c8ce7d9e43b1e8930b9b1bc974ebb3d36d4b704fc78b77efba956a13 +updated: 2017-11-30T17:08:29.176515576-05:00 imports: - name: github.com/btcsuite/btcd - version: 8cea3866d0f7fb12d567a20744942c0d078c7d15 + version: 2e60448ffcc6bf78332d1fe590260095f554dd78 subpackages: - btcec - name: github.com/go-kit/kit @@ -44,7 +44,7 @@ imports: - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: f15c970de5b76fac0b59abb32d62c17cc7bed265 - name: github.com/spf13/cobra version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b - name: github.com/spf13/pflag @@ -72,7 +72,7 @@ imports: - name: github.com/tendermint/go-crypto version: b4f04f196cd719660e43b91202cd60d9a95b1837 - name: github.com/tendermint/go-wire - version: 3f073b1a9c841d9b88d03ca8181f61278188adca + version: 5ab49b4c6ad674da6b81442911cf713ef0afb544 subpackages: - data - name: github.com/tendermint/iavl @@ -85,7 +85,7 @@ imports: - log - process - name: golang.org/x/crypto - version: 9f005a07e0d31d45e6656d241bb5c0f2efd4bc94 + version: 94eea52f7b742c7cbe0b03b22f0c4c8631ece122 subpackages: - nacl/secretbox - openpgp/armor @@ -94,7 +94,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: 9dfe39835686865bff950a07b394c12a98ddc811 + version: a8b9294777976932365dabb6640cf1468d95c70f subpackages: - context - http2 @@ -104,18 +104,18 @@ imports: - lex/httplex - trace - name: golang.org/x/text - version: 88f656faf3f37f690df1a32515b479415e1a6769 + version: 75cc3cad82b5f47d3fb229ddda8c5167da14f294 subpackages: - secure/bidirule - transform - unicode/bidi - unicode/norm - name: google.golang.org/genproto - version: 891aceb7c239e72692819142dfca057bdcbfcb96 + version: 7f0da29060c682909f650ad8ed4e515bd74fa12a subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: f7bf885db0b7479a537ec317c6e48ce53145f3db + version: 401e0e00e4bb830a10496d64cd95e068c5bf50de subpackages: - balancer - codes diff --git a/glide.yaml b/glide.yaml index aeb6b674..88f49dde 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,13 +1,15 @@ package: github.com/tendermint/abci import: - package: github.com/gogo/protobuf + version: v0.5 subpackages: - proto - package: github.com/spf13/cobra + version: v0.0.1 - package: github.com/tendermint/go-crypto version: develop - package: github.com/tendermint/go-wire - version: data-bytes-marshal-unmarshal + version: develop subpackages: - data - package: github.com/tendermint/iavl @@ -23,6 +25,7 @@ import: subpackages: - context - package: google.golang.org/grpc + version: v1.7.3 testImport: - package: github.com/stretchr/testify subpackages: diff --git a/server/grpc_server.go b/server/grpc_server.go index 077f0e52..e7dad15c 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -42,6 +42,7 @@ func (s *GRPCServer) OnStart() error { if err != nil { return err } + s.Logger.Info("Listening", "proto", s.proto, "addr", s.addr) s.listener = ln s.server = grpc.NewServer() types.RegisterABCIApplicationServer(s.server, s.app) diff --git a/tests/test_app/test.sh b/tests/test_app/test.sh index 5b523fef..230c9416 100755 --- a/tests/test_app/test.sh +++ b/tests/test_app/test.sh @@ -11,11 +11,16 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" # Change into that dir because we expect that. cd "$DIR" +echo "RUN COUNTER OVER SOCKET" # test golang counter ABCI_APP="counter" go run ./*.go +echo "----------------------" + +echo "RUN COUNTER OVER GRPC" # test golang counter via grpc ABCI_APP="counter --abci=grpc" ABCI="grpc" go run ./*.go +echo "----------------------" # test nodejs counter # TODO: fix node app diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index f6259148..ed00b9d7 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -17,7 +17,7 @@ function testExample() { echo "Example $N: $APP" $APP &> /dev/null & sleep 2 - abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" + abci-cli --log_level=error --verbose batch < "$INPUT" > "${INPUT}.out.new" killall "$3" pre=$(shasum < "${INPUT}.out") From f00a19eaad06917edd719e935d81780d0f9c2ed9 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 17:36:16 -0500 Subject: [PATCH 371/545] fix tutorial output to remove code msg --- tests/test_cli/ex2.abci.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cli/ex2.abci.out b/tests/test_cli/ex2.abci.out index 40e10f83..741dd7b7 100644 --- a/tests/test_cli/ex2.abci.out +++ b/tests/test_cli/ex2.abci.out @@ -11,14 +11,14 @@ -> code: OK > check_tx 0x00 --> code: BadNonce +-> code: 2 -> log: Invalid nonce. Expected >= 1, got 0 > deliver_tx 0x01 -> code: OK > deliver_tx 0x04 --> code: BadNonce +-> code: 2 -> log: Invalid nonce. Expected 2, got 4 > info From e3f6666ecc83aa5bbc22cb6d19b1fcb9455b5440 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 17:48:05 -0500 Subject: [PATCH 372/545] update changelog; add rudis script for safe keeping --- .gitignore | 1 + CHANGELOG.md | 9 +++-- example/example.go | 2 +- types/protoreplace/protoreplace.go | 55 ++++++++++++++++++++++++++++++ types/result.go | 2 -- 5 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 types/protoreplace/protoreplace.go diff --git a/.gitignore b/.gitignore index 62f28681..ea27eda1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ vendor .glide +types/types.pb.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6937eaeb..28dd2947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,20 @@ BREAKING CHANGES: - [client] all XxxSync methods now return (ResponseXxx, error) - - [types] Application: all methods now take RequestXxx and return (ResponseXxx, error). + - [types] all methods on Application interface now take RequestXxx and return (ResponseXxx, error). - Except `CheckTx`/`DeliverTx`, which takes a `tx []byte` argument. - Except `Commit`, which takes no arguments. - - [types] removed Result + - [types] removed Result and ResultQuery + - [types] removed CodeType - only `0 == OK` is defined here, everything else is left to convention at the application level + - [types] switched to using `gogo/protobuf` for code generation + - [types] use `customtype` feature of `gogo/protobuf` to replace `[]byte` with `data.Bytes` in all generated types :) + - this eliminates the need for additional types like ResultQuery FEATURES: - [types] added Tags field to ResponseDeliverTx - [types] added Gas and Fee fields to ResponseCheckTx - [dummy] DeliverTx returns tags + - [abci-cli] added `log_level` flag to control the logger ## 0.7.1 (November 14, 2017) diff --git a/example/example.go b/example/example.go index 5a2b2449..ee491c1b 100644 --- a/example/example.go +++ b/example/example.go @@ -1,3 +1,3 @@ package example -// so go get doesnt complain +// so the go tool doesn't return errors about no buildable go files ... diff --git a/types/protoreplace/protoreplace.go b/types/protoreplace/protoreplace.go new file mode 100644 index 00000000..c859098f --- /dev/null +++ b/types/protoreplace/protoreplace.go @@ -0,0 +1,55 @@ +package main + +// +build ignore + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "regexp" + "strings" +) + +// This script replaces most `[]byte` with `data.Bytes` in a `.pb.go` file. +// It was written before we realized we could use `gogo/protobuf` to achieve +// this more natively. So it's here for safe keeping in case we ever need to +// abandon `gogo/protobuf`. + +func main() { + bytePattern := regexp.MustCompile("[[][]]byte") + const oldPath = "types/types.pb.go" + const tmpPath = "types/types.pb.new" + content, err := ioutil.ReadFile(oldPath) + if err != nil { + panic("cannot read " + oldPath) + os.Exit(1) + } + lines := bytes.Split(content, []byte("\n")) + outFile, _ := os.Create(tmpPath) + wroteImport := false + for _, line_bytes := range lines { + line := string(line_bytes) + gotPackageLine := strings.HasPrefix(line, "package ") + writeImportTime := strings.HasPrefix(line, "import ") + containsDescriptor := strings.Contains(line, "Descriptor") + containsByteArray := strings.Contains(line, "[]byte") + if containsByteArray && !containsDescriptor { + line = string(bytePattern.ReplaceAll([]byte(line), []byte("data.Bytes"))) + } + if writeImportTime && !wroteImport { + wroteImport = true + fmt.Fprintf(outFile, "import \"github.com/tendermint/go-wire/data\"\n") + + } + if gotPackageLine { + fmt.Fprintf(outFile, "%s\n", "//nolint: gas") + } + fmt.Fprintf(outFile, "%s\n", line) + } + outFile.Close() + os.Remove(oldPath) + os.Rename(tmpPath, oldPath) + exec.Command("goimports", "-w", oldPath) +} diff --git a/types/result.go b/types/result.go index 3344b27c..3f3fdd82 100644 --- a/types/result.go +++ b/types/result.go @@ -4,8 +4,6 @@ import ( "fmt" ) -// type CodeType uint32 - const ( CodeTypeOK uint32 = 0 ) From ed393f9934c0c78d098b4935814582370a1efd4f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 17:49:53 -0500 Subject: [PATCH 373/545] abci-cli: print OK if code is 0 --- CHANGELOG.md | 1 + cmd/abci-cli/abci-cli.go | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28dd2947..8dba7032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ BREAKING CHANGES: - [types] switched to using `gogo/protobuf` for code generation - [types] use `customtype` feature of `gogo/protobuf` to replace `[]byte` with `data.Bytes` in all generated types :) - this eliminates the need for additional types like ResultQuery + - [abci-cli] codes are printed as their number instead of a message, except for `code == 0`, which is still printed as `OK` FEATURES: - [types] added Tags field to ResponseDeliverTx diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 25786b37..ef8b9063 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -516,7 +516,12 @@ func printResponse(cmd *cobra.Command, args []string, rsp response) { } // Always print the status code. - fmt.Printf("-> code: %d\n", rsp.Code) + if rsp.Code == types.CodeTypeOK { + fmt.Printf("-> code: OK\n") + } else { + fmt.Printf("-> code: %d\n", rsp.Code) + + } if len(rsp.Data) != 0 { // Do no print this line when using the commit command From 5d2838ebab9d81e6c888922ab11fb4c894e8b827 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 30 Nov 2017 20:17:06 -0500 Subject: [PATCH 374/545] fix from review --- client/grpc_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/grpc_client.go b/client/grpc_client.go index 308a9e13..9328fa32 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -69,7 +69,7 @@ RETRY_LOOP: if err == nil { break ENSURE_CONNECTED } - cli.Logger.Info("Echo failed", "err", err) + cli.Logger.Error("Echo failed", "err", err) time.Sleep(time.Second * echoRetryIntervalSeconds) } From b59fe60e65e5f8e51b20c4bba4b9b564001d478e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 00:35:14 -0500 Subject: [PATCH 375/545] abci-cli: prefix flag variables with flag --- cmd/abci-cli/abci-cli.go | 68 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index ef8b9063..e7fae52e 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -32,23 +32,23 @@ var ( // flags var ( // global - address string - abci string - verbose bool // for the println output - logLevel string // for the logger + flagAddress string + flagAbci string + flagVerbose bool // for the println output + flagLogLevel string // for the logger // query - path string - height int - prove bool + flagPath string + flagHeight int + flagProve bool // counter - addrC string - serial bool + flagAddrC string + flagSerial bool // dummy - addrD string - persist string + flagAddrD string + flagPersist string ) var RootCmd = &cobra.Command{ @@ -65,7 +65,7 @@ var RootCmd = &cobra.Command{ } if logger == nil { - allowLevel, err := log.AllowLevel(logLevel) + allowLevel, err := log.AllowLevel(flagLogLevel) if err != nil { return err } @@ -73,7 +73,7 @@ var RootCmd = &cobra.Command{ } if client == nil { var err error - client, err = abcicli.NewClient(address, abci, false) + client, err = abcicli.NewClient(flagAddress, flagAbci, false) if err != nil { return err } @@ -99,7 +99,7 @@ type response struct { type queryResponse struct { Key []byte Value []byte - Height uint64 + Height int64 Proof []byte } @@ -110,26 +110,26 @@ func Execute() error { } func addGlobalFlags() { - RootCmd.PersistentFlags().StringVarP(&address, "address", "", "tcp://0.0.0.0:46658", "Address of application socket") - RootCmd.PersistentFlags().StringVarP(&abci, "abci", "", "socket", "Either socket or grpc") - RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print the command and results as if it were a console session") - RootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "debug", "Set the logger level") + RootCmd.PersistentFlags().StringVarP(&flagAddress, "address", "", "tcp://0.0.0.0:46658", "Address of application socket") + RootCmd.PersistentFlags().StringVarP(&flagAbci, "abci", "", "socket", "Either socket or grpc") + RootCmd.PersistentFlags().BoolVarP(&flagVerbose, "verbose", "v", false, "Print the command and results as if it were a console session") + RootCmd.PersistentFlags().StringVarP(&flagLogLevel, "log_level", "", "debug", "Set the logger level") } func addQueryFlags() { - queryCmd.PersistentFlags().StringVarP(&path, "path", "", "/store", "Path to prefix query with") - queryCmd.PersistentFlags().IntVarP(&height, "height", "", 0, "Height to query the blockchain at") - queryCmd.PersistentFlags().BoolVarP(&prove, "prove", "", false, "Whether or not to return a merkle proof of the query result") + queryCmd.PersistentFlags().StringVarP(&flagPath, "path", "", "/store", "Path to prefix query with") + queryCmd.PersistentFlags().IntVarP(&flagHeight, "height", "", 0, "Height to query the blockchain at") + queryCmd.PersistentFlags().BoolVarP(&flagProve, "prove", "", false, "Whether or not to return a merkle proof of the query result") } func addCounterFlags() { - counterCmd.PersistentFlags().StringVarP(&addrC, "addr", "", "tcp://0.0.0.0:46658", "Listen address") - counterCmd.PersistentFlags().BoolVarP(&serial, "serial", "", false, "Enforce incrementing (serial) transactions") + counterCmd.PersistentFlags().StringVarP(&flagAddrC, "addr", "", "tcp://0.0.0.0:46658", "Listen address") + counterCmd.PersistentFlags().BoolVarP(&flagSerial, "serial", "", false, "Enforce incrementing (serial) transactions") } func addDummyFlags() { - dummyCmd.PersistentFlags().StringVarP(&addrD, "addr", "", "tcp://0.0.0.0:46658", "Listen address") - dummyCmd.PersistentFlags().StringVarP(&persist, "persist", "", "", "Directory to use for a database") + dummyCmd.PersistentFlags().StringVarP(&flagAddrD, "addr", "", "tcp://0.0.0.0:46658", "Listen address") + dummyCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "Directory to use for a database") } func addCommands() { RootCmd.AddCommand(batchCmd) @@ -433,9 +433,9 @@ func cmdQuery(cmd *cobra.Command, args []string) error { resQuery, err := client.QuerySync(types.RequestQuery{ Data: queryBytes, - Path: path, - Height: uint64(height), - Prove: prove, + Path: flagPath, + Height: int64(flagHeight), + Prove: flagProve, }) if err != nil { return err @@ -455,12 +455,12 @@ func cmdQuery(cmd *cobra.Command, args []string) error { func cmdCounter(cmd *cobra.Command, args []string) error { - app := counter.NewCounterApplication(serial) + app := counter.NewCounterApplication(flagSerial) logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Start the listener - srv, err := server.NewServer(addrC, abci, app) + srv, err := server.NewServer(flagAddrC, flagAbci, app) if err != nil { return err } @@ -482,15 +482,15 @@ func cmdDummy(cmd *cobra.Command, args []string) error { // Create the application - in memory or persisted to disk var app types.Application - if persist == "" { + if flagPersist == "" { app = dummy.NewDummyApplication() } else { - app = dummy.NewPersistentDummyApplication(persist) + app = dummy.NewPersistentDummyApplication(flagPersist) app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) } // Start the listener - srv, err := server.NewServer(addrD, abci, app) + srv, err := server.NewServer(flagAddrD, flagAbci, app) if err != nil { return err } @@ -511,7 +511,7 @@ func cmdDummy(cmd *cobra.Command, args []string) error { func printResponse(cmd *cobra.Command, args []string, rsp response) { - if verbose { + if flagVerbose { fmt.Println(">", cmd.Use, strings.Join(args, " ")) } From 0ad7dea71fb9cf188e057a41e78175ae765fef04 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 00:41:07 -0500 Subject: [PATCH 376/545] uint64 -> int64 --- CHANGELOG.md | 2 + Makefile | 8 +- example/dummy/dummy_test.go | 8 +- example/dummy/helpers.go | 2 +- example/dummy/persistent_dummy.go | 9 +- types/types.pb.go | 234 +++++++++++++++--------------- types/types.proto | 24 +-- types/validators.go | 5 +- 8 files changed, 148 insertions(+), 144 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dba7032..b1449a43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ BREAKING CHANGES: - [types] switched to using `gogo/protobuf` for code generation - [types] use `customtype` feature of `gogo/protobuf` to replace `[]byte` with `data.Bytes` in all generated types :) - this eliminates the need for additional types like ResultQuery + - [types] `pubKey` -> `pub_key` + - [types] `uint64` -> `int64` - [abci-cli] codes are printed as their number instead of a message, except for `code == 0`, which is still printed as `OK` FEATURES: diff --git a/Makefile b/Makefile index e6a7af36..ebe8f3a9 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,8 @@ GOTOOLS = \ github.com/gogo/protobuf/protoc-gen-gogo \ github.com/gogo/protobuf/gogoproto +INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf + all: install test PACKAGES=$(shell go list ./... | grep -v '/vendor/') @@ -24,7 +26,7 @@ protoc: ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 - protoc -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf --gogo_out=plugins=grpc:. types/*.proto + protoc $(INCLUDE) --gogo_out=plugins=grpc:. types/*.proto install: @ go install ./cmd/... @@ -67,11 +69,11 @@ get_vendor_deps: ensure_tools @ glide install metalinter: - protoc --lint_out=. types/*.proto + protoc $(INCLUDE) --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... metalinter_test: - # protoc --lint_out=. types/*.proto + protoc $(INCLUDE) --lint_out=. types/*.proto gometalinter --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 738da6e8..ec4d2e33 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -82,7 +82,7 @@ func TestPersistentDummyInfo(t *testing.T) { } dummy := NewPersistentDummyApplication(dir) InitDummy(dummy) - height := uint64(0) + height := int64(0) resInfo := dummy.Info(types.RequestInfo{}) if resInfo.LastBlockHeight != height { @@ -90,10 +90,10 @@ func TestPersistentDummyInfo(t *testing.T) { } // make and apply block - height = uint64(1) + height = int64(1) hash := []byte("foo") header := &types.Header{ - Height: uint64(height), + Height: int64(height), } dummy.BeginBlock(types.RequestBeginBlock{hash, header}) dummy.EndBlock(types.RequestEndBlock{header.Height}) @@ -173,7 +173,7 @@ func TestValSetChanges(t *testing.T) { func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) { // make and apply block - height := uint64(heightInt) + height := int64(heightInt) hash := []byte("foo") header := &types.Header{ Height: height, diff --git a/example/dummy/helpers.go b/example/dummy/helpers.go index 55c464de..d6b4338c 100644 --- a/example/dummy/helpers.go +++ b/example/dummy/helpers.go @@ -11,7 +11,7 @@ import ( func RandVal(i int) *types.Validator { pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() power := cmn.RandUint16() + 1 - return &types.Validator{pubkey, uint64(power)} + return &types.Validator{pubkey, int64(power)} } // RandVals returns a list of cnt validators for initializing diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 1d72bea1..6f389c50 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -55,7 +55,8 @@ func (app *PersistentDummyApplication) SetLogger(l log.Logger) { func (app *PersistentDummyApplication) Info(req types.RequestInfo) types.ResponseInfo { res := app.app.Info(req) - res.LastBlockHeight = app.app.state.LatestVersion() + var latestVersion uint64 = app.app.state.LatestVersion() // TODO: change to int64 + res.LastBlockHeight = int64(latestVersion) res.LastBlockAppHash = app.app.state.Hash() return res } @@ -145,7 +146,7 @@ func (app *PersistentDummyApplication) Validators() (validators []*types.Validat return } -func MakeValSetChangeTx(pubkey []byte, power uint64) []byte { +func MakeValSetChangeTx(pubkey []byte, power int64) []byte { return []byte(cmn.Fmt("val:%X/%d", pubkey, power)) } @@ -181,7 +182,7 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Response } // decode the power - power, err := strconv.Atoi(powerS) + power, err := strconv.ParseInt(powerS, 10, 64) if err != nil { return types.ResponseDeliverTx{ Code: code.CodeTypeEncodingError, @@ -189,7 +190,7 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Response } // update - return app.updateValidator(&types.Validator{pubkey, uint64(power)}) + return app.updateValidator(&types.Validator{pubkey, power}) } // add, update, or remove a validator diff --git a/types/types.pb.go b/types/types.pb.go index 61a56cac..094f3012 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -582,7 +582,7 @@ func (m *RequestCheckTx) GetTx() []byte { type RequestQuery struct { Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` - Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` Prove bool `protobuf:"varint,4,opt,name=prove,proto3" json:"prove,omitempty"` } @@ -605,7 +605,7 @@ func (m *RequestQuery) GetPath() string { return "" } -func (m *RequestQuery) GetHeight() uint64 { +func (m *RequestQuery) GetHeight() int64 { if m != nil { return m.Height } @@ -668,7 +668,7 @@ func (m *RequestBeginBlock) GetHeader() *Header { } type RequestEndBlock struct { - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` } func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } @@ -676,7 +676,7 @@ func (m *RequestEndBlock) String() string { return proto.CompactTextS func (*RequestEndBlock) ProtoMessage() {} func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} } -func (m *RequestEndBlock) GetHeight() uint64 { +func (m *RequestEndBlock) GetHeight() int64 { if m != nil { return m.Height } @@ -1157,7 +1157,7 @@ func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptorTypes, type ResponseInfo struct { Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - LastBlockHeight uint64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` LastBlockAppHash []byte `protobuf:"bytes,4,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` } @@ -1180,7 +1180,7 @@ func (m *ResponseInfo) GetVersion() string { return "" } -func (m *ResponseInfo) GetLastBlockHeight() uint64 { +func (m *ResponseInfo) GetLastBlockHeight() int64 { if m != nil { return m.LastBlockHeight } @@ -1247,8 +1247,8 @@ type ResponseCheckTx struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Gas uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` - Fee uint64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` + Gas int64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` + Fee int64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1270,14 +1270,14 @@ func (m *ResponseCheckTx) GetLog() string { return "" } -func (m *ResponseCheckTx) GetGas() uint64 { +func (m *ResponseCheckTx) GetGas() int64 { if m != nil { return m.Gas } return 0 } -func (m *ResponseCheckTx) GetFee() uint64 { +func (m *ResponseCheckTx) GetFee() int64 { if m != nil { return m.Fee } @@ -1290,7 +1290,7 @@ type ResponseQuery struct { Key github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,3,opt,name=key,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"key"` Value github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,4,opt,name=value,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"value"` Proof github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,5,opt,name=proof,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"proof"` - Height uint64 `protobuf:"varint,6,opt,name=height,proto3" json:"height,omitempty"` + Height int64 `protobuf:"varint,6,opt,name=height,proto3" json:"height,omitempty"` Log string `protobuf:"bytes,7,opt,name=log,proto3" json:"log,omitempty"` } @@ -1313,7 +1313,7 @@ func (m *ResponseQuery) GetIndex() int64 { return 0 } -func (m *ResponseQuery) GetHeight() uint64 { +func (m *ResponseQuery) GetHeight() int64 { if m != nil { return m.Height } @@ -1386,9 +1386,9 @@ func (m *ResponseEndBlock) GetDiffs() []*Validator { type Header struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - Time uint64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` - NumTxs uint64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Time int64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` + NumTxs int64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` @@ -1408,21 +1408,21 @@ func (m *Header) GetChainId() string { return "" } -func (m *Header) GetHeight() uint64 { +func (m *Header) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *Header) GetTime() uint64 { +func (m *Header) GetTime() int64 { if m != nil { return m.Time } return 0 } -func (m *Header) GetNumTxs() uint64 { +func (m *Header) GetNumTxs() int64 { if m != nil { return m.NumTxs } @@ -1489,7 +1489,7 @@ func (m *BlockID) GetParts() *PartSetHeader { } type PartSetHeader struct { - Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` } @@ -1498,7 +1498,7 @@ func (m *PartSetHeader) String() string { return proto.CompactTextStr func (*PartSetHeader) ProtoMessage() {} func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } -func (m *PartSetHeader) GetTotal() uint64 { +func (m *PartSetHeader) GetTotal() int64 { if m != nil { return m.Total } @@ -1513,8 +1513,8 @@ func (m *PartSetHeader) GetHash() []byte { } type Validator struct { - PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` - Power uint64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` + PubKey []byte `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` } func (m *Validator) Reset() { *m = Validator{} } @@ -1529,7 +1529,7 @@ func (m *Validator) GetPubKey() []byte { return nil } -func (m *Validator) GetPower() uint64 { +func (m *Validator) GetPower() int64 { if m != nil { return m.Power } @@ -2015,98 +2015,98 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1485 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x8e, 0x13, 0x47, - 0x10, 0x5e, 0xdb, 0xe3, 0xbf, 0xf2, 0xfe, 0x98, 0x66, 0x03, 0xc6, 0x1c, 0x80, 0x91, 0x08, 0xbb, - 0x04, 0xd6, 0x64, 0x11, 0x11, 0x1b, 0xa2, 0x48, 0x6b, 0x16, 0x62, 0x0b, 0x89, 0x90, 0x61, 0xc5, - 0xd5, 0x1a, 0x7b, 0xda, 0xf6, 0x08, 0x7b, 0x66, 0x98, 0x69, 0x2f, 0x5e, 0x29, 0x8f, 0xc0, 0x3d, - 0xe7, 0xe4, 0x12, 0x29, 0x2f, 0x90, 0x37, 0x88, 0xf2, 0x0c, 0x39, 0xf0, 0x2c, 0x51, 0x55, 0xf7, - 0xfc, 0xee, 0x0c, 0x07, 0x0e, 0x5c, 0x56, 0x5d, 0x5d, 0xf5, 0xb5, 0xab, 0x7a, 0xaa, 0xbf, 0xaa, - 0x5a, 0xb8, 0x24, 0xce, 0x3d, 0x1e, 0xf4, 0xe8, 0xef, 0x81, 0xe7, 0xbb, 0xc2, 0x65, 0x55, 0x12, - 0xba, 0xf7, 0x67, 0xb6, 0x98, 0xaf, 0xc6, 0x07, 0x13, 0x77, 0xd9, 0x9b, 0xb9, 0x33, 0xb7, 0x47, - 0xda, 0xf1, 0x6a, 0x4a, 0x12, 0x09, 0xb4, 0x92, 0x28, 0xfd, 0x1f, 0x0d, 0xea, 0x06, 0x7f, 0xb7, - 0xe2, 0x81, 0x60, 0x7b, 0xa0, 0xf1, 0xc9, 0xdc, 0xed, 0x94, 0x6e, 0x96, 0xf6, 0x5a, 0x87, 0xec, - 0x40, 0x9e, 0xae, 0xb4, 0xcf, 0x26, 0x73, 0x77, 0xb0, 0x61, 0x90, 0x05, 0xfb, 0x06, 0xaa, 0xd3, - 0xc5, 0x2a, 0x98, 0x77, 0xca, 0x64, 0x7a, 0x39, 0x6d, 0xfa, 0x1c, 0x55, 0x83, 0x0d, 0x43, 0xda, - 0xe0, 0xb1, 0xb6, 0x33, 0x75, 0x3b, 0x95, 0xbc, 0x63, 0x87, 0xce, 0x94, 0x8e, 0x45, 0x0b, 0xf6, - 0x18, 0x20, 0xe0, 0x62, 0xe4, 0x7a, 0xc2, 0x76, 0x9d, 0x8e, 0x46, 0xf6, 0x57, 0xd3, 0xf6, 0xaf, - 0xb9, 0xf8, 0x99, 0xd4, 0x83, 0x0d, 0xa3, 0x19, 0x84, 0x02, 0x22, 0x2d, 0xbe, 0xb0, 0xcf, 0xb8, - 0x3f, 0x12, 0xeb, 0x4e, 0x35, 0x0f, 0x79, 0x22, 0xf5, 0xa7, 0x6b, 0x44, 0x5a, 0xa1, 0xc0, 0x0e, - 0xa1, 0x31, 0x99, 0xf3, 0xc9, 0x5b, 0xc4, 0xd5, 0x08, 0xf7, 0x55, 0x1a, 0xf7, 0x14, 0xb5, 0x84, - 0xaa, 0x4f, 0xe4, 0x92, 0x1d, 0x40, 0x6d, 0xe2, 0x2e, 0x97, 0xb6, 0xe8, 0xd4, 0x09, 0xb1, 0x9b, - 0x41, 0x90, 0x6e, 0xb0, 0x61, 0x28, 0x2b, 0xbc, 0xae, 0x77, 0x2b, 0xee, 0x9f, 0x77, 0x1a, 0x79, - 0xd7, 0xf5, 0x0b, 0xaa, 0xf0, 0xba, 0xc8, 0x06, 0x43, 0xb1, 0x1d, 0x5b, 0x8c, 0x26, 0x73, 0xd3, - 0x76, 0x3a, 0xcd, 0xbc, 0x50, 0x86, 0x8e, 0x2d, 0x9e, 0xa2, 0x1a, 0x43, 0xb1, 0x43, 0x81, 0x3d, - 0x81, 0xd6, 0x98, 0xcf, 0x6c, 0x67, 0x34, 0x5e, 0xb8, 0x93, 0xb7, 0x1d, 0x20, 0x68, 0x27, 0x0d, - 0xed, 0xa3, 0x41, 0x1f, 0xf5, 0x83, 0x0d, 0x03, 0xc6, 0x91, 0xc4, 0x1e, 0x41, 0x93, 0x3b, 0x96, - 0x82, 0xb6, 0x08, 0x7a, 0x25, 0x93, 0x01, 0x8e, 0x15, 0x02, 0x1b, 0x5c, 0xad, 0xfb, 0x75, 0xa8, - 0x9e, 0x99, 0x8b, 0x15, 0xd7, 0xef, 0x40, 0x2b, 0x91, 0x29, 0xac, 0x03, 0xf5, 0x25, 0x0f, 0x02, - 0x73, 0xc6, 0x29, 0x9d, 0x9a, 0x46, 0x28, 0xea, 0xdb, 0xb0, 0x99, 0xcc, 0x93, 0x04, 0x10, 0x73, - 0x01, 0x81, 0x67, 0xdc, 0x0f, 0x30, 0x01, 0x14, 0x50, 0x89, 0xfa, 0xf7, 0xd0, 0xce, 0x26, 0x01, - 0x6b, 0x43, 0xe5, 0x2d, 0x3f, 0x57, 0x96, 0xb8, 0x64, 0xbb, 0xca, 0x21, 0x4a, 0xcd, 0xa6, 0xa1, - 0xbc, 0xd3, 0x23, 0x6c, 0x94, 0x06, 0x6c, 0x1b, 0xca, 0x62, 0x4d, 0xd0, 0x4d, 0xa3, 0x2c, 0xd6, - 0xfa, 0x4d, 0xd8, 0x4e, 0x7f, 0xf2, 0x0b, 0x16, 0x56, 0xe4, 0x3a, 0x7d, 0x33, 0xc6, 0x40, 0xb3, - 0x4c, 0x61, 0x2a, 0x0b, 0x5a, 0xe3, 0x9e, 0x67, 0x8a, 0xb9, 0xfa, 0x79, 0x5a, 0xb3, 0x2b, 0x50, - 0x9b, 0x73, 0x7b, 0x36, 0x17, 0xf4, 0x06, 0x34, 0x43, 0x49, 0xe8, 0xab, 0xe7, 0xbb, 0x67, 0x9c, - 0x52, 0xbd, 0x61, 0x48, 0x41, 0xdf, 0x81, 0xad, 0x54, 0x22, 0xe9, 0x27, 0x91, 0xf3, 0xd1, 0x87, - 0x67, 0x0f, 0x00, 0xce, 0xcc, 0x85, 0x6d, 0x99, 0xc2, 0xf5, 0x83, 0x4e, 0xe9, 0x66, 0x65, 0xaf, - 0x75, 0xd8, 0x56, 0xdf, 0xeb, 0x4d, 0xa8, 0x30, 0x12, 0x36, 0xfa, 0x4b, 0xb8, 0x74, 0x21, 0x07, - 0xd0, 0xdb, 0xb9, 0x19, 0xcc, 0xc3, 0x08, 0x70, 0xcd, 0x6e, 0xa3, 0xb7, 0xa6, 0xc5, 0x7d, 0xf5, - 0xba, 0xb7, 0xd4, 0xb1, 0x03, 0xda, 0x34, 0x94, 0x52, 0xdf, 0x87, 0x9d, 0x4c, 0x62, 0x24, 0xe2, - 0x2c, 0x25, 0xe3, 0xd4, 0x3f, 0x54, 0xa1, 0x61, 0xf0, 0xc0, 0x73, 0x9d, 0x80, 0xb3, 0xc7, 0xd0, - 0xe4, 0xeb, 0x09, 0x97, 0x6f, 0xbc, 0x94, 0xc9, 0x51, 0x69, 0xf3, 0x2c, 0xd4, 0x63, 0x7e, 0x47, - 0xc6, 0x6c, 0x5f, 0xf1, 0x53, 0x96, 0x74, 0x14, 0x28, 0x49, 0x50, 0xf7, 0x42, 0x82, 0xaa, 0x64, - 0x1e, 0xa8, 0xb4, 0xcd, 0x30, 0xd4, 0xbe, 0x62, 0x28, 0x2d, 0xf7, 0xe0, 0x14, 0x45, 0x1d, 0xa5, - 0x28, 0xaa, 0x9a, 0xeb, 0x7e, 0x01, 0x47, 0x1d, 0xa5, 0x38, 0xaa, 0x96, 0x0b, 0x2d, 0x20, 0xa9, - 0x87, 0x09, 0x92, 0xaa, 0x67, 0xde, 0xa6, 0x04, 0xe6, 0xb0, 0x54, 0x2f, 0x62, 0xa9, 0x46, 0x86, - 0xd7, 0x14, 0x24, 0x4b, 0x53, 0xf7, 0x42, 0x9a, 0x6a, 0xe6, 0x5e, 0x5a, 0x86, 0xa7, 0x8e, 0x52, - 0x3c, 0x05, 0xb9, 0xe1, 0x14, 0x10, 0xd5, 0x0f, 0x69, 0xa2, 0x92, 0x6c, 0x73, 0x2d, 0x83, 0x2d, - 0x64, 0xaa, 0xef, 0x92, 0x4c, 0xb5, 0x99, 0xe1, 0x47, 0x95, 0x0b, 0x9f, 0xa4, 0xaa, 0x7d, 0x7c, - 0x09, 0x99, 0x4c, 0xc3, 0xb7, 0xc8, 0x7d, 0xdf, 0xf5, 0x15, 0x97, 0x48, 0x41, 0xdf, 0xc3, 0x17, - 0x1f, 0xe7, 0xd7, 0x27, 0x68, 0x8d, 0x5e, 0x6d, 0x22, 0xbb, 0xf4, 0xdf, 0x4a, 0x31, 0x96, 0x98, - 0x2d, 0xc9, 0x16, 0x4d, 0xc5, 0x16, 0x09, 0xb6, 0x2b, 0xa7, 0xd8, 0x8e, 0xdd, 0x85, 0x4b, 0x0b, - 0x33, 0x10, 0x32, 0xcc, 0x51, 0x8a, 0x3e, 0x76, 0x50, 0x21, 0xe3, 0x93, 0x3c, 0x72, 0x1f, 0x2e, - 0x27, 0x6c, 0x4d, 0xcf, 0x1b, 0xd1, 0xa3, 0xd6, 0xe8, 0x51, 0xb7, 0x23, 0xeb, 0x63, 0xcf, 0x1b, - 0x98, 0xc1, 0x5c, 0xbf, 0x1d, 0xc7, 0x9f, 0x62, 0xd2, 0x85, 0x3b, 0x0b, 0x99, 0x74, 0xe1, 0xce, - 0xf4, 0x3f, 0x4a, 0xb1, 0x5d, 0xcc, 0x9a, 0x0c, 0xb4, 0x89, 0x6b, 0xc9, 0xf0, 0xb7, 0x0c, 0x5a, - 0xb3, 0x13, 0x15, 0x19, 0x86, 0xb0, 0xd9, 0x7f, 0xf0, 0xef, 0xc7, 0x1b, 0x1b, 0xff, 0x7d, 0xbc, - 0xb1, 0x97, 0xe8, 0x44, 0x04, 0x77, 0x2c, 0xee, 0x2f, 0x6d, 0x47, 0xf4, 0x66, 0xee, 0xfd, 0xf7, - 0xb6, 0xcf, 0x7b, 0x88, 0x38, 0xe8, 0x9f, 0x0b, 0x1e, 0xa8, 0xbb, 0x50, 0x1e, 0x54, 0x22, 0x0f, - 0xd8, 0x2d, 0xd0, 0x84, 0x39, 0x0b, 0x3a, 0x1a, 0xd1, 0x5b, 0xc8, 0x43, 0x2f, 0xde, 0xbc, 0x32, - 0x6d, 0xdf, 0x20, 0x95, 0xfe, 0x7b, 0x09, 0x69, 0x28, 0xf5, 0x06, 0xbe, 0xa8, 0x8b, 0x6d, 0xa8, - 0xcc, 0xcc, 0x80, 0xae, 0x5a, 0x33, 0x70, 0x89, 0x3b, 0x53, 0xce, 0x89, 0x1a, 0x34, 0x03, 0x97, - 0xfa, 0xdf, 0xe5, 0x38, 0x37, 0xa2, 0xc2, 0x71, 0xc1, 0xc3, 0x5d, 0xa8, 0xda, 0x8e, 0xc5, 0xd7, - 0xe4, 0x62, 0xc5, 0x90, 0x02, 0xeb, 0xcb, 0x02, 0x57, 0xf9, 0x4c, 0xb7, 0xa9, 0x24, 0x3e, 0x0f, - 0x4b, 0xa2, 0xf6, 0x99, 0xa7, 0x48, 0x38, 0x9e, 0xe3, 0xf9, 0xae, 0x3b, 0xa5, 0xd8, 0x3e, 0xeb, - 0x1c, 0x82, 0x27, 0xca, 0x44, 0x2d, 0x55, 0x0e, 0xd5, 0xed, 0xd6, 0xe3, 0x14, 0xfc, 0x15, 0x4b, - 0x72, 0x92, 0xad, 0xbe, 0xe4, 0xb7, 0xd5, 0x2f, 0xc7, 0xf9, 0x1f, 0x11, 0x99, 0xbe, 0x0b, 0xec, - 0x22, 0x43, 0xc9, 0xde, 0x24, 0xcd, 0x3d, 0xec, 0x6b, 0xa8, 0x5a, 0xf6, 0x74, 0x5a, 0x5c, 0x9d, - 0xa5, 0x5a, 0xff, 0xb3, 0x0c, 0x35, 0x59, 0x5b, 0xd9, 0x35, 0xe4, 0x79, 0xd3, 0x76, 0x46, 0xb6, - 0x15, 0xf2, 0x0b, 0xc9, 0x43, 0x2b, 0x71, 0x69, 0xe5, 0xd4, 0xa5, 0x31, 0xd0, 0x84, 0xbd, 0xe4, - 0x8a, 0x1a, 0x68, 0xcd, 0xae, 0x42, 0xdd, 0x59, 0x2d, 0x47, 0x62, 0x1d, 0x26, 0x66, 0xcd, 0x59, - 0x2d, 0x4f, 0xd7, 0x01, 0x3b, 0x84, 0xad, 0x04, 0x51, 0xd8, 0x96, 0x2a, 0x60, 0xdb, 0xca, 0x35, - 0xf2, 0x7b, 0x78, 0x62, 0xb4, 0x22, 0xca, 0x18, 0x5a, 0x6c, 0x0f, 0x88, 0x41, 0x46, 0xb2, 0x48, - 0x48, 0x66, 0xa9, 0x11, 0xb3, 0x6c, 0xe3, 0xbe, 0xaa, 0x22, 0xd8, 0x38, 0x5c, 0x87, 0x26, 0xde, - 0xa4, 0x34, 0xa9, 0x93, 0x49, 0x03, 0x37, 0x48, 0x79, 0x07, 0x76, 0xe2, 0x66, 0x44, 0x9a, 0x34, - 0xe4, 0x29, 0xf1, 0x36, 0x19, 0x5e, 0x83, 0x46, 0xc4, 0x60, 0x4d, 0xb2, 0xa8, 0x9b, 0x8a, 0xb8, - 0x86, 0x50, 0x57, 0x2e, 0xe6, 0x36, 0x2e, 0x77, 0xa1, 0xea, 0x99, 0xbe, 0x08, 0x54, 0x83, 0x10, - 0xd6, 0xaf, 0x57, 0xa6, 0x8f, 0x1d, 0xa3, 0x6a, 0x5f, 0xa4, 0x89, 0x7e, 0x04, 0x5b, 0xa9, 0x7d, - 0x7c, 0x7e, 0xc2, 0x15, 0xe6, 0x42, 0xb5, 0x2e, 0x52, 0x88, 0x7e, 0xa6, 0x1c, 0xff, 0x8c, 0x7e, - 0x04, 0xcd, 0xe8, 0x1b, 0xe2, 0x67, 0xf1, 0x56, 0xe3, 0x17, 0xaa, 0x07, 0xdd, 0x34, 0x94, 0x44, - 0xad, 0x9d, 0xfb, 0x5e, 0xf5, 0x50, 0x9a, 0x21, 0x05, 0xfd, 0xaf, 0x12, 0xd4, 0x24, 0x7d, 0xe5, - 0x74, 0xae, 0xdf, 0x52, 0x4b, 0xb7, 0xe2, 0x23, 0x74, 0x9b, 0x70, 0xdb, 0xd1, 0xb4, 0x24, 0x41, - 0x07, 0xa7, 0xe7, 0x1e, 0x37, 0x9a, 0x64, 0x85, 0x4b, 0x76, 0x0b, 0x36, 0x25, 0x24, 0x10, 0xbe, - 0xed, 0x84, 0xc9, 0xdb, 0xa2, 0xbd, 0xd7, 0xb4, 0x85, 0x1f, 0x45, 0x9a, 0xd8, 0x8e, 0xa0, 0x6c, - 0xa8, 0x18, 0x0d, 0xda, 0x18, 0x3a, 0x42, 0xbf, 0x0e, 0x1a, 0x9d, 0x03, 0x50, 0x7b, 0x7d, 0x6a, - 0x0c, 0x5f, 0xfe, 0xd4, 0xde, 0x60, 0x75, 0xa8, 0x0c, 0x5f, 0x9e, 0xb6, 0x4b, 0x87, 0x1f, 0xaa, - 0xb0, 0x73, 0xdc, 0x7f, 0x3a, 0x3c, 0xf6, 0xbc, 0x85, 0x3d, 0x31, 0xa9, 0x4a, 0xf4, 0x40, 0xa3, - 0x3a, 0x98, 0x33, 0x1c, 0x76, 0xf3, 0x1a, 0x32, 0x76, 0x08, 0x55, 0x2a, 0x87, 0x2c, 0x6f, 0x46, - 0xec, 0xe6, 0xf6, 0x65, 0xf8, 0x23, 0xb2, 0x60, 0x5e, 0x1c, 0x15, 0xbb, 0x79, 0xcd, 0x19, 0xfb, - 0x11, 0x9a, 0x71, 0x21, 0x2b, 0x1a, 0x18, 0xbb, 0x85, 0x6d, 0x1a, 0xe2, 0xe3, 0x02, 0x57, 0x34, - 0x36, 0x76, 0x0b, 0x7b, 0x35, 0xf6, 0x18, 0xea, 0x61, 0xed, 0xc9, 0x1f, 0x1e, 0xbb, 0x05, 0xed, - 0x1a, 0x5e, 0x8f, 0xac, 0x08, 0x79, 0x33, 0x61, 0x37, 0xb7, 0x03, 0x63, 0x8f, 0xa0, 0xa6, 0xc8, - 0x30, 0x77, 0xee, 0xec, 0xe6, 0xf7, 0x79, 0x18, 0x64, 0x3c, 0x3e, 0x14, 0x0d, 0x94, 0xdd, 0xc2, - 0x0e, 0x8e, 0x1d, 0x03, 0x24, 0x06, 0x87, 0xc2, 0xb1, 0xb2, 0x5b, 0xdc, 0xc7, 0xb1, 0x27, 0xd0, - 0x88, 0x67, 0x85, 0xfc, 0xe1, 0xb2, 0x5b, 0xd4, 0xca, 0x8d, 0x6b, 0xf4, 0x0f, 0x8b, 0x87, 0xff, - 0x07, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xbb, 0x93, 0x98, 0xfb, 0x10, 0x00, 0x00, + // 1488 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x8e, 0x13, 0xc7, + 0x13, 0x5f, 0x7f, 0xdb, 0xe5, 0xfd, 0x30, 0xcd, 0xfe, 0x61, 0x30, 0x07, 0x60, 0x24, 0xfe, 0xec, + 0x12, 0x58, 0x93, 0x45, 0x44, 0x2c, 0x44, 0x91, 0xd6, 0x2c, 0xc4, 0x16, 0x12, 0x21, 0xc3, 0x8a, + 0xab, 0x35, 0xf6, 0xb4, 0xed, 0x11, 0xf6, 0xcc, 0x30, 0xd3, 0x5e, 0xbc, 0x52, 0x1e, 0x81, 0x7b, + 0xce, 0xc9, 0x25, 0x52, 0x5e, 0x20, 0x6f, 0x10, 0xe5, 0x19, 0x72, 0xe0, 0x59, 0xa2, 0xaa, 0xee, + 0xf9, 0xdc, 0x19, 0x0e, 0x1c, 0xb8, 0xac, 0xba, 0xba, 0xea, 0xd7, 0xae, 0xea, 0xa9, 0xfe, 0x55, + 0xd5, 0xc2, 0x25, 0x71, 0xee, 0xf1, 0xa0, 0x47, 0x7f, 0x0f, 0x3c, 0xdf, 0x15, 0x2e, 0xab, 0x91, + 0xd0, 0xbd, 0x3f, 0xb3, 0xc5, 0x7c, 0x35, 0x3e, 0x98, 0xb8, 0xcb, 0xde, 0xcc, 0x9d, 0xb9, 0x3d, + 0xd2, 0x8e, 0x57, 0x53, 0x92, 0x48, 0xa0, 0x95, 0x44, 0xe9, 0x7f, 0x57, 0xa1, 0x61, 0xf0, 0xf7, + 0x2b, 0x1e, 0x08, 0xb6, 0x07, 0x55, 0x3e, 0x99, 0xbb, 0x5a, 0xe9, 0x66, 0x69, 0xaf, 0x7d, 0xc8, + 0x0e, 0xe4, 0xe9, 0x4a, 0xfb, 0x7c, 0x32, 0x77, 0x07, 0x1b, 0x06, 0x59, 0xb0, 0x6f, 0xa0, 0x36, + 0x5d, 0xac, 0x82, 0xb9, 0x56, 0x26, 0xd3, 0xcb, 0x69, 0xd3, 0x17, 0xa8, 0x1a, 0x6c, 0x18, 0xd2, + 0x06, 0x8f, 0xb5, 0x9d, 0xa9, 0xab, 0x55, 0xf2, 0x8e, 0x1d, 0x3a, 0x53, 0x3a, 0x16, 0x2d, 0xd8, + 0x63, 0x80, 0x80, 0x8b, 0x91, 0xeb, 0x09, 0xdb, 0x75, 0xb4, 0x2a, 0xd9, 0x5f, 0x4d, 0xdb, 0xbf, + 0xe1, 0xe2, 0x27, 0x52, 0x0f, 0x36, 0x8c, 0x56, 0x10, 0x0a, 0x88, 0xb4, 0xf8, 0xc2, 0x3e, 0xe3, + 0xfe, 0x48, 0xac, 0xb5, 0x5a, 0x1e, 0xf2, 0x44, 0xea, 0x4f, 0xd7, 0x88, 0xb4, 0x42, 0x81, 0x1d, + 0x42, 0x73, 0x32, 0xe7, 0x93, 0x77, 0x88, 0xab, 0x13, 0xee, 0x7f, 0x69, 0xdc, 0x33, 0xd4, 0x12, + 0xaa, 0x31, 0x91, 0x4b, 0x76, 0x00, 0xf5, 0x89, 0xbb, 0x5c, 0xda, 0x42, 0x6b, 0x10, 0x62, 0x37, + 0x83, 0x20, 0xdd, 0x60, 0xc3, 0x50, 0x56, 0x78, 0x5d, 0xef, 0x57, 0xdc, 0x3f, 0xd7, 0x9a, 0x79, + 0xd7, 0xf5, 0x33, 0xaa, 0xf0, 0xba, 0xc8, 0x06, 0x43, 0xb1, 0x1d, 0x5b, 0x8c, 0x26, 0x73, 0xd3, + 0x76, 0xb4, 0x56, 0x5e, 0x28, 0x43, 0xc7, 0x16, 0xcf, 0x50, 0x8d, 0xa1, 0xd8, 0xa1, 0xc0, 0x9e, + 0x42, 0x7b, 0xcc, 0x67, 0xb6, 0x33, 0x1a, 0x2f, 0xdc, 0xc9, 0x3b, 0x0d, 0x08, 0xaa, 0xa5, 0xa1, + 0x7d, 0x34, 0xe8, 0xa3, 0x7e, 0xb0, 0x61, 0xc0, 0x38, 0x92, 0xd8, 0x23, 0x68, 0x71, 0xc7, 0x52, + 0xd0, 0x36, 0x41, 0xaf, 0x64, 0x32, 0xc0, 0xb1, 0x42, 0x60, 0x93, 0xab, 0x75, 0xbf, 0x01, 0xb5, + 0x33, 0x73, 0xb1, 0xe2, 0xfa, 0x1d, 0x68, 0x27, 0x32, 0x85, 0x69, 0xd0, 0x58, 0xf2, 0x20, 0x30, + 0x67, 0x9c, 0xd2, 0xa9, 0x65, 0x84, 0xa2, 0xbe, 0x0d, 0x9b, 0xc9, 0x3c, 0x49, 0x00, 0x31, 0x17, + 0x10, 0x78, 0xc6, 0xfd, 0x00, 0x13, 0x40, 0x01, 0x95, 0xa8, 0x3f, 0x81, 0x4e, 0x36, 0x09, 0x58, + 0x07, 0x2a, 0xef, 0xf8, 0xb9, 0xb2, 0xc4, 0x25, 0xdb, 0x55, 0x0e, 0x51, 0x6a, 0xb6, 0x0c, 0xe5, + 0x9d, 0x1e, 0x61, 0xa3, 0x34, 0x60, 0xdb, 0x50, 0x16, 0x6b, 0x82, 0x6e, 0x1a, 0x65, 0xb1, 0xd6, + 0x6f, 0xc2, 0x76, 0xfa, 0x93, 0x5f, 0xb0, 0xb0, 0x22, 0xd7, 0xe9, 0x9b, 0x31, 0x06, 0x55, 0xcb, + 0x14, 0xa6, 0xb2, 0xa0, 0x35, 0xee, 0x79, 0xa6, 0x98, 0xab, 0x9f, 0xa7, 0x35, 0xbb, 0x02, 0xf5, + 0x39, 0xb7, 0x67, 0x73, 0x41, 0x6f, 0xa0, 0x62, 0x28, 0x09, 0x7d, 0xf5, 0x7c, 0xf7, 0x8c, 0x53, + 0xaa, 0x37, 0x0d, 0x29, 0xe8, 0x3b, 0xb0, 0x95, 0x4a, 0x24, 0xfd, 0x24, 0x72, 0x3e, 0xfa, 0xf0, + 0xec, 0x01, 0xc0, 0x99, 0xb9, 0xb0, 0x2d, 0x53, 0xb8, 0x7e, 0xa0, 0x95, 0x6e, 0x56, 0xf6, 0xda, + 0x87, 0x1d, 0xf5, 0xbd, 0xde, 0x86, 0x0a, 0x23, 0x61, 0xa3, 0xbf, 0x82, 0x4b, 0x17, 0x72, 0x00, + 0xbd, 0x9d, 0x9b, 0xc1, 0x3c, 0x8c, 0x00, 0xd7, 0xec, 0x36, 0x7a, 0x6b, 0x5a, 0xdc, 0x57, 0xaf, + 0x7b, 0x4b, 0x1d, 0x3b, 0xa0, 0x4d, 0x43, 0x29, 0xf5, 0x7d, 0xd8, 0xc9, 0x24, 0x46, 0x22, 0xce, + 0x52, 0x32, 0x4e, 0xfd, 0x63, 0x0d, 0x9a, 0x06, 0x0f, 0x3c, 0xd7, 0x09, 0x38, 0x7b, 0x0c, 0x2d, + 0xbe, 0x9e, 0x70, 0xf9, 0xc6, 0x4b, 0x99, 0x1c, 0x95, 0x36, 0xcf, 0x43, 0x3d, 0xe6, 0x77, 0x64, + 0xcc, 0xf6, 0x15, 0x3f, 0x65, 0x49, 0x47, 0x81, 0x92, 0x04, 0x75, 0x2f, 0x24, 0xa8, 0x4a, 0xe6, + 0x81, 0x4a, 0xdb, 0x0c, 0x43, 0xed, 0x2b, 0x86, 0xaa, 0xe6, 0x1e, 0x9c, 0xa2, 0xa8, 0xa3, 0x14, + 0x45, 0xd5, 0x72, 0xdd, 0x2f, 0xe0, 0xa8, 0xa3, 0x14, 0x47, 0xd5, 0x73, 0xa1, 0x05, 0x24, 0xf5, + 0x30, 0x41, 0x52, 0x8d, 0xcc, 0xdb, 0x94, 0xc0, 0x1c, 0x96, 0xea, 0x45, 0x2c, 0xd5, 0xcc, 0xf0, + 0x9a, 0x82, 0x64, 0x69, 0xea, 0x5e, 0x48, 0x53, 0xad, 0xdc, 0x4b, 0xcb, 0xf0, 0xd4, 0x51, 0x8a, + 0xa7, 0x20, 0x37, 0x9c, 0x02, 0xa2, 0xfa, 0x3e, 0x4d, 0x54, 0x92, 0x6d, 0xae, 0x65, 0xb0, 0x85, + 0x4c, 0xf5, 0x5d, 0x92, 0xa9, 0x36, 0x33, 0xfc, 0xa8, 0x72, 0xe1, 0xb3, 0x54, 0xb5, 0x8f, 0x2f, + 0x21, 0x93, 0x69, 0xf8, 0x16, 0xb9, 0xef, 0xbb, 0xbe, 0xe2, 0x12, 0x29, 0xe8, 0x7b, 0xf8, 0xe2, + 0xe3, 0xfc, 0xfa, 0x0c, 0xad, 0xd1, 0xab, 0x4d, 0x64, 0x97, 0xfe, 0x6b, 0x29, 0xc6, 0x12, 0xb3, + 0x25, 0xd9, 0xa2, 0xa5, 0xd8, 0x22, 0xc1, 0x76, 0xe5, 0x14, 0xdb, 0xb1, 0xbb, 0x70, 0x69, 0x61, + 0x06, 0x42, 0x86, 0x39, 0x4a, 0xd1, 0xc7, 0x0e, 0x2a, 0x64, 0x7c, 0x92, 0x47, 0xee, 0xc3, 0xe5, + 0x84, 0xad, 0xe9, 0x79, 0x23, 0x7a, 0xd4, 0x55, 0x7a, 0xd4, 0x9d, 0xc8, 0xfa, 0xd8, 0xf3, 0x06, + 0x66, 0x30, 0xd7, 0x6f, 0xc7, 0xf1, 0xa7, 0x98, 0x74, 0xe1, 0xce, 0x42, 0x26, 0x5d, 0xb8, 0x33, + 0xfd, 0xf7, 0x52, 0x6c, 0x17, 0xb3, 0x26, 0x83, 0xea, 0xc4, 0xb5, 0x64, 0xf8, 0x5b, 0x06, 0xad, + 0xd9, 0x89, 0x8a, 0x0c, 0x43, 0xd8, 0xec, 0x3f, 0xf8, 0xe7, 0xd3, 0x8d, 0x8d, 0x7f, 0x3f, 0xdd, + 0xd8, 0x4b, 0x74, 0x22, 0x82, 0x3b, 0x16, 0xf7, 0x97, 0xb6, 0x23, 0x7a, 0x33, 0xf7, 0xfe, 0x07, + 0xdb, 0xe7, 0x3d, 0x44, 0x1c, 0xf4, 0xcf, 0x05, 0x0f, 0xd4, 0x5d, 0x28, 0x0f, 0x2a, 0x91, 0x07, + 0xec, 0x16, 0x54, 0x85, 0x39, 0x0b, 0xb4, 0x2a, 0xd1, 0x5b, 0xc8, 0x43, 0x2f, 0xdf, 0xbe, 0x36, + 0x6d, 0xdf, 0x20, 0x95, 0xfe, 0x5b, 0x09, 0x69, 0x28, 0xf5, 0x06, 0xbe, 0xaa, 0x8b, 0x1d, 0xa8, + 0xcc, 0xcc, 0x80, 0xae, 0xba, 0x62, 0xe0, 0x12, 0x77, 0xa6, 0x9c, 0x13, 0x35, 0x54, 0x0c, 0x5c, + 0xea, 0x7f, 0x95, 0xe3, 0xdc, 0x88, 0x0a, 0xc7, 0x05, 0x0f, 0x77, 0xa1, 0x66, 0x3b, 0x16, 0x5f, + 0x93, 0x8b, 0x15, 0x43, 0x0a, 0xac, 0x2f, 0x0b, 0x5c, 0xe5, 0x0b, 0xdd, 0xa6, 0x92, 0xf8, 0x22, + 0x2c, 0x89, 0xd5, 0x2f, 0x3c, 0x45, 0xc2, 0xf1, 0x1c, 0xcf, 0x77, 0xdd, 0x29, 0xc5, 0xf6, 0x45, + 0xe7, 0x10, 0x3c, 0x51, 0x26, 0xea, 0xa9, 0x72, 0xa8, 0x6e, 0xb7, 0x11, 0xa7, 0xe0, 0x2f, 0x58, + 0x92, 0x93, 0x6c, 0xf5, 0x35, 0xbf, 0xad, 0x7e, 0x39, 0xce, 0xff, 0x88, 0xc8, 0xf4, 0x5d, 0x60, + 0x17, 0x19, 0x4a, 0xf6, 0x26, 0x69, 0xee, 0x61, 0xff, 0x87, 0x9a, 0x65, 0x4f, 0xa7, 0xc5, 0xd5, + 0x59, 0xaa, 0xf5, 0x3f, 0xca, 0x50, 0x97, 0xb5, 0x95, 0x5d, 0x43, 0x9e, 0x37, 0x6d, 0x67, 0x64, + 0x5b, 0x21, 0xbf, 0x90, 0x3c, 0xb4, 0x12, 0x97, 0x56, 0x4e, 0x5d, 0x1a, 0x83, 0xaa, 0xb0, 0x97, + 0x5c, 0x51, 0x03, 0xad, 0xd9, 0x55, 0x68, 0x38, 0xab, 0xe5, 0x48, 0xac, 0xc3, 0xc4, 0xac, 0x3b, + 0xab, 0xe5, 0xe9, 0x3a, 0x60, 0x87, 0xb0, 0x95, 0x20, 0x0a, 0xdb, 0x52, 0x05, 0x6c, 0x5b, 0xb9, + 0x46, 0x7e, 0x0f, 0x4f, 0x8c, 0x76, 0x44, 0x19, 0x43, 0x8b, 0xed, 0x01, 0x31, 0xc8, 0x48, 0x16, + 0x09, 0xc9, 0x2c, 0x75, 0x62, 0x96, 0x6d, 0xdc, 0x57, 0x55, 0x04, 0x1b, 0x87, 0xeb, 0xd0, 0xc2, + 0x9b, 0x94, 0x26, 0x0d, 0x32, 0x69, 0xe2, 0x06, 0x29, 0xef, 0xc0, 0x4e, 0xdc, 0x8c, 0x48, 0x93, + 0xa6, 0x3c, 0x25, 0xde, 0x26, 0xc3, 0x6b, 0xd0, 0x8c, 0x18, 0xac, 0x45, 0x16, 0x0d, 0x53, 0x11, + 0xd7, 0x10, 0x1a, 0xca, 0xc5, 0xdc, 0xc6, 0xe5, 0x2e, 0xd4, 0x3c, 0xd3, 0x17, 0x81, 0x6a, 0x10, + 0xc2, 0xfa, 0xf5, 0xda, 0xf4, 0xb1, 0x63, 0x54, 0xed, 0x8b, 0x34, 0xd1, 0x8f, 0x60, 0x2b, 0xb5, + 0x8f, 0xcf, 0x4f, 0xb8, 0xc2, 0x5c, 0xa8, 0xd6, 0x45, 0x0a, 0xd1, 0xcf, 0x94, 0xe3, 0x9f, 0xd1, + 0x9f, 0x40, 0x2b, 0xfa, 0x86, 0x78, 0xd5, 0xde, 0x6a, 0x3c, 0x0a, 0x9b, 0xd0, 0x4d, 0xa3, 0xee, + 0xad, 0xc6, 0x2f, 0x65, 0x1f, 0xea, 0xb9, 0x1f, 0x54, 0x13, 0x55, 0x31, 0xa4, 0xa0, 0xff, 0x59, + 0x82, 0xba, 0xe4, 0xaf, 0x9c, 0xd6, 0xf5, 0x5b, 0xea, 0xe9, 0x56, 0x7c, 0x84, 0x7e, 0x13, 0x6e, + 0x3b, 0x1a, 0x97, 0x24, 0xe8, 0xe0, 0xf4, 0xdc, 0xe3, 0x46, 0x8b, 0xac, 0x70, 0xc9, 0x6e, 0xc1, + 0xa6, 0x84, 0x04, 0xc2, 0xb7, 0x9d, 0x30, 0x7b, 0xdb, 0xb4, 0xf7, 0x86, 0xb6, 0xf0, 0xab, 0x48, + 0x13, 0xdb, 0x11, 0x2a, 0x1d, 0x9a, 0xb4, 0x31, 0x74, 0x84, 0x7e, 0x1d, 0xaa, 0x74, 0x0e, 0x40, + 0xfd, 0xcd, 0xa9, 0x31, 0x7c, 0xf5, 0x63, 0x67, 0x83, 0x35, 0xa0, 0x32, 0x7c, 0x75, 0xda, 0x29, + 0x1d, 0x7e, 0xac, 0xc1, 0xce, 0x71, 0xff, 0xd9, 0xf0, 0xd8, 0xf3, 0x16, 0xf6, 0xc4, 0xa4, 0x32, + 0xd1, 0x83, 0x2a, 0x15, 0xc2, 0x9c, 0xe9, 0xb0, 0x9b, 0xd7, 0x91, 0xb1, 0x43, 0xa8, 0x51, 0x3d, + 0x64, 0x79, 0x43, 0x62, 0x37, 0xb7, 0x31, 0xc3, 0x1f, 0x91, 0x15, 0xf3, 0xe2, 0xac, 0xd8, 0xcd, + 0xeb, 0xce, 0xd8, 0x0f, 0xd0, 0x8a, 0x2b, 0x59, 0xd1, 0xc4, 0xd8, 0x2d, 0xec, 0xd3, 0x10, 0x1f, + 0x57, 0xb8, 0xa2, 0xb9, 0xb1, 0x5b, 0xd8, 0xac, 0xb1, 0xc7, 0xd0, 0x08, 0x8b, 0x4f, 0xfe, 0xf4, + 0xd8, 0x2d, 0xe8, 0xd7, 0xf0, 0x7a, 0x64, 0x49, 0xc8, 0x1b, 0x0a, 0xbb, 0xb9, 0x2d, 0x18, 0x7b, + 0x04, 0x75, 0xc5, 0x86, 0xb9, 0x83, 0x67, 0x37, 0xbf, 0xd1, 0xc3, 0x20, 0xe3, 0xf9, 0xa1, 0x68, + 0xa2, 0xec, 0x16, 0xb6, 0x70, 0xec, 0x18, 0x20, 0x31, 0x39, 0x14, 0xce, 0x95, 0xdd, 0xe2, 0x46, + 0x8e, 0x3d, 0x85, 0x66, 0x3c, 0x2c, 0xe4, 0x4f, 0x97, 0xdd, 0xa2, 0x5e, 0x6e, 0x5c, 0xa7, 0xff, + 0x58, 0x3c, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x34, 0x61, 0x21, 0x91, 0xfc, 0x10, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 2754a362..d40e8885 100644 --- a/types/types.proto +++ b/types/types.proto @@ -52,7 +52,7 @@ message RequestCheckTx{ message RequestQuery{ bytes data = 1; string path = 2; - uint64 height = 3; + int64 height = 3; bool prove = 4; } @@ -69,7 +69,7 @@ message RequestBeginBlock{ } message RequestEndBlock{ - uint64 height = 1; + int64 height = 1; } //---------------------------------------- @@ -107,7 +107,7 @@ message ResponseFlush{ message ResponseInfo { string data = 1; string version = 2; - uint64 last_block_height = 3; + int64 last_block_height = 3; bytes last_block_app_hash = 4; } @@ -126,8 +126,8 @@ message ResponseCheckTx{ uint32 code = 1; bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; string log = 3; - uint64 gas = 4; - uint64 fee = 5; + int64 gas = 4; + int64 fee = 5; } message ResponseQuery{ @@ -136,7 +136,7 @@ message ResponseQuery{ bytes key = 3 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; bytes value = 4 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; bytes proof = 5 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - uint64 height = 6; + int64 height = 6; string log = 7; } @@ -162,9 +162,9 @@ message ResponseEndBlock{ message Header { string chain_id = 1; - uint64 height = 2; - uint64 time = 3; - uint64 num_txs = 4; + int64 height = 2; + int64 time = 3; + int64 num_txs = 4; BlockID last_block_id = 5; bytes last_commit_hash = 6; bytes data_hash = 7; @@ -178,13 +178,13 @@ message BlockID { } message PartSetHeader { - uint64 total = 1; + int64 total = 1; bytes hash = 2; } message Validator { - bytes pubKey = 1; - uint64 power = 2; + bytes pub_key = 1; + int64 power = 2; } //---------------------------------------- diff --git a/types/validators.go b/types/validators.go index 95258aa2..6bbe3f84 100644 --- a/types/validators.go +++ b/types/validators.go @@ -8,8 +8,7 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -// validators implements sort - +// Validators is a list of validators that implements the Sort interface type Validators []*Validator func (v Validators) Len() int { @@ -31,7 +30,7 @@ func (v Validators) Swap(i, j int) { type validatorPretty struct { PubKey data.Bytes `json:"pub_key"` - Power uint64 `json:"power"` + Power int64 `json:"power"` } func ValidatorsString(vs Validators) string { From b7a75ce8c31f19730e64c1485b4b2f53f038f9e7 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 01:16:00 -0500 Subject: [PATCH 377/545] update readme --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f2546c00..0deec181 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,8 @@ Here, we describe the requests and responses as function arguments and return va * `Code (uint32)`: Response code * `Data ([]byte)`: Result bytes, if any * `Log (string)`: Debug or error message - * `Gas (uint64)`: Amount of gas consumed by transaction - * `Fee (uint64)`: Fee paid by transaction + * `Gas (int64)`: Amount of gas consumed by transaction + * `Fee (int64)`: Fee paid by transaction * __Usage__:
Validate a mempool transaction, prior to broadcasting or proposing. This message should not mutate the main state, but application developers may want to keep a separate CheckTx state that gets reset upon Commit. @@ -127,14 +127,14 @@ Here, we describe the requests and responses as function arguments and return va * `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 + * `Height (int64)`: 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 * `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 + * `Height (int64)`: 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) @@ -142,7 +142,7 @@ Here, we describe the requests and responses as function arguments and return va * __Returns__: * `Data (string)`: Some arbitrary information * `Version (Version)`: Version information - * `LastBlockHeight (uint64)`: Latest block for which the app has called Commit + * `LastBlockHeight (int64)`: Latest block for which the app has called Commit * `LastBlockAppHash ([]byte)`: Latest result of Commit * __Usage__:
@@ -173,7 +173,7 @@ Here, we describe the requests and responses as function arguments and return va #### EndBlock * __Arguments__: - * `Height (uint64)`: The block height that ended + * `Height (int64)`: The block height that ended * __Returns__: * `Diffs ([]Validator)`: Changed validators with new voting powers (0 to remove) * __Usage__:
From b39e768a1af4ece98e60de2ae3ba480a4ce041d5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 02:50:17 -0500 Subject: [PATCH 378/545] disable metalinter on CI --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index c6904fae..7d4545e5 100644 --- a/circle.yml +++ b/circle.yml @@ -16,7 +16,7 @@ checkout: test: override: - - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations + - cd $REPO && make get_vendor_deps && make test_integrations post: - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" From 3d3d1288d1bdd2255fd9002b00b1615deef1b0b5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 00:51:20 -0500 Subject: [PATCH 379/545] types: consolidate some file --- types/application.go | 52 +++++++++++++++++++++++++- types/base_app.go | 44 ---------------------- types/kvpair.go | 19 ---------- types/{validators.go => util.go} | 34 +++++++++++++---- types/{kvpair_test.go => util_test.go} | 0 5 files changed, 78 insertions(+), 71 deletions(-) delete mode 100644 types/base_app.go delete mode 100644 types/kvpair.go rename types/{validators.go => util.go} (60%) rename types/{kvpair_test.go => util_test.go} (100%) diff --git a/types/application.go b/types/application.go index bb9a0030..f0ce1895 100644 --- a/types/application.go +++ b/types/application.go @@ -25,7 +25,57 @@ type Application interface { Commit() ResponseCommit // Commit the state and return the application Merkle root hash } -//------------------------------------ +//------------------------------------------------------- +// BaseApplication is a base form of Application + +var _ Application = (*BaseApplication)(nil) + +type BaseApplication struct { +} + +func NewBaseApplication() *BaseApplication { + return &BaseApplication{} +} + +func (BaseApplication) Info(req RequestInfo) ResponseInfo { + return ResponseInfo{} +} + +func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { + return ResponseSetOption{} +} + +func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { + return ResponseDeliverTx{Code: CodeTypeOK} +} + +func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { + return ResponseCheckTx{Code: CodeTypeOK} +} + +func (BaseApplication) Commit() ResponseCommit { + return ResponseCommit{Code: CodeTypeOK} +} + +func (BaseApplication) Query(req RequestQuery) ResponseQuery { + return ResponseQuery{Code: CodeTypeOK} +} + +func (BaseApplication) InitChain(req RequestInitChain) ResponseInitChain { + return ResponseInitChain{} +} + +func (BaseApplication) BeginBlock(req RequestBeginBlock) ResponseBeginBlock { + return ResponseBeginBlock{} +} + +func (BaseApplication) EndBlock(req RequestEndBlock) ResponseEndBlock { + return ResponseEndBlock{} +} + +//------------------------------------------------------- + +var _ Application = (*GRPCApplication)(nil) // GRPCApplication is a GRPC wrapper for Application type GRPCApplication struct { diff --git a/types/base_app.go b/types/base_app.go deleted file mode 100644 index 1998e9dc..00000000 --- a/types/base_app.go +++ /dev/null @@ -1,44 +0,0 @@ -package types - -type BaseApplication struct { -} - -func NewBaseApplication() *BaseApplication { - return &BaseApplication{} -} - -func (BaseApplication) Info(req RequestInfo) ResponseInfo { - return ResponseInfo{} -} - -func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { - return ResponseSetOption{} -} - -func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { - return ResponseDeliverTx{Code: CodeTypeOK} -} - -func (BaseApplication) CheckTx(tx []byte) ResponseCheckTx { - return ResponseCheckTx{Code: CodeTypeOK} -} - -func (BaseApplication) Commit() ResponseCommit { - return ResponseCommit{Code: CodeTypeOK} -} - -func (BaseApplication) Query(req RequestQuery) ResponseQuery { - return ResponseQuery{Code: CodeTypeOK} -} - -func (BaseApplication) InitChain(req RequestInitChain) ResponseInitChain { - return ResponseInitChain{} -} - -func (BaseApplication) BeginBlock(req RequestBeginBlock) ResponseBeginBlock { - return ResponseBeginBlock{} -} - -func (BaseApplication) EndBlock(req RequestEndBlock) ResponseEndBlock { - return ResponseEndBlock{} -} diff --git a/types/kvpair.go b/types/kvpair.go deleted file mode 100644 index c7aad440..00000000 --- a/types/kvpair.go +++ /dev/null @@ -1,19 +0,0 @@ -package types - -// KVPairInt is a helper method to build KV pair with an integer value. -func KVPairInt(key string, val int64) *KVPair { - return &KVPair{ - Key: key, - ValueInt: val, - ValueType: KVPair_INT, - } -} - -// KVPairString is a helper method to build KV pair with a string value. -func KVPairString(key, val string) *KVPair { - return &KVPair{ - Key: key, - ValueString: val, - ValueType: KVPair_STRING, - } -} diff --git a/types/validators.go b/types/util.go similarity index 60% rename from types/validators.go rename to types/util.go index 6bbe3f84..17c53f65 100644 --- a/types/validators.go +++ b/types/util.go @@ -8,6 +8,8 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +//------------------------------------------------------------------------------ + // Validators is a list of validators that implements the Sort interface type Validators []*Validator @@ -26,13 +28,6 @@ func (v Validators) Swap(i, j int) { v[j] = v1 } -//------------------------------------- - -type validatorPretty struct { - PubKey data.Bytes `json:"pub_key"` - Power int64 `json:"power"` -} - func ValidatorsString(vs Validators) string { s := make([]validatorPretty, len(vs)) for i, v := range vs { @@ -44,3 +39,28 @@ func ValidatorsString(vs Validators) string { } return string(b) } + +type validatorPretty struct { + PubKey data.Bytes `json:"pub_key"` + Power int64 `json:"power"` +} + +//------------------------------------------------------------------------------ + +// KVPairInt is a helper method to build KV pair with an integer value. +func KVPairInt(key string, val int64) *KVPair { + return &KVPair{ + Key: key, + ValueInt: val, + ValueType: KVPair_INT, + } +} + +// KVPairString is a helper method to build KV pair with a string value. +func KVPairString(key, val string) *KVPair { + return &KVPair{ + Key: key, + ValueString: val, + ValueType: KVPair_STRING, + } +} diff --git a/types/kvpair_test.go b/types/util_test.go similarity index 100% rename from types/kvpair_test.go rename to types/util_test.go From 9272756c498e524273baff0ec5c6578e5fae5de4 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 01:05:13 -0500 Subject: [PATCH 380/545] types: add note about ReadMessage having no cap --- types/application.go | 2 -- types/messages.go | 50 +++++++++++++++++++++--------------------- types/messages_test.go | 28 +++++++++++++++++++++++ 3 files changed, 53 insertions(+), 27 deletions(-) create mode 100644 types/messages_test.go diff --git a/types/application.go b/types/application.go index f0ce1895..6c0b8bd0 100644 --- a/types/application.go +++ b/types/application.go @@ -75,8 +75,6 @@ func (BaseApplication) EndBlock(req RequestEndBlock) ResponseEndBlock { //------------------------------------------------------- -var _ Application = (*GRPCApplication)(nil) - // GRPCApplication is a GRPC wrapper for Application type GRPCApplication struct { app Application diff --git a/types/messages.go b/types/messages.go index 7b9c81f9..5ce234cf 100644 --- a/types/messages.go +++ b/types/messages.go @@ -7,6 +7,31 @@ import ( wire "github.com/tendermint/go-wire" ) +// WriteMessage writes a length-delimited protobuf message. +func WriteMessage(msg proto.Message, w io.Writer) error { + bz, err := proto.Marshal(msg) + if err != nil { + return err + } + var n int + wire.WriteByteSlice(bz, w, &n, &err) + return err +} + +// ReadMessage reads a length delimited protobuf message. +func ReadMessage(r io.Reader, msg proto.Message) error { + var n int + var err error + bz := wire.ReadByteSlice(r, 0, &n, &err) //XXX: no max + if err != nil { + return err + } + err = proto.Unmarshal(bz, msg) + return err +} + +//---------------------------------------- + func ToRequestEcho(message string) *Request { return &Request{ Value: &Request_Echo{&RequestEcho{message}}, @@ -146,28 +171,3 @@ func ToResponseEndBlock(res ResponseEndBlock) *Response { Value: &Response_EndBlock{&res}, } } - -//---------------------------------------- - -// Write proto message, length delimited -func WriteMessage(msg proto.Message, w io.Writer) error { - bz, err := proto.Marshal(msg) - if err != nil { - return err - } - var n int - wire.WriteByteSlice(bz, w, &n, &err) - return err -} - -// Read proto message, length delimited -func ReadMessage(r io.Reader, msg proto.Message) error { - var n int - var err error - bz := wire.ReadByteSlice(r, 0, &n, &err) - if err != nil { - return err - } - err = proto.Unmarshal(bz, msg) - return err -} diff --git a/types/messages_test.go b/types/messages_test.go new file mode 100644 index 00000000..7f078979 --- /dev/null +++ b/types/messages_test.go @@ -0,0 +1,28 @@ +package types + +import ( + "bytes" + "testing" + + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/assert" +) + +func TestWriteReadMessage(t *testing.T) { + cases := []proto.Message{ + &RequestEcho{"hello"}, + // TODO: add the rest + } + + for _, c := range cases { + buf := new(bytes.Buffer) + err := WriteMessage(c, buf) + assert.Nil(t, err) + + msg := new(RequestEcho) + err = ReadMessage(buf, msg) + assert.Nil(t, err) + + assert.Equal(t, c, msg) + } +} From b20273439de2d532f8480c6557f2ebff0854ac69 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 01:09:16 -0500 Subject: [PATCH 381/545] types: RequestBeginBlock includes absent and byzantine validators --- CHANGELOG.md | 7 +- Makefile | 6 +- README.md | 4 +- types/types.pb.go | 242 +++++++++++++++++++++++++++------------------- types/types.proto | 7 ++ 5 files changed, 161 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1449a43..5395989f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,9 +17,10 @@ BREAKING CHANGES: - [abci-cli] codes are printed as their number instead of a message, except for `code == 0`, which is still printed as `OK` FEATURES: - - [types] added Tags field to ResponseDeliverTx - - [types] added Gas and Fee fields to ResponseCheckTx - - [dummy] DeliverTx returns tags + - [types] ResponseDeliverTx: added `tags` field + - [types] ResponseCheckTx: added `gas` and `fee` fields + - [types] RequestBeginBlock: added `absent_validators` and `byzantine_validators` fields + - [dummy] DeliverTx returns an owner tag and a key tag - [abci-cli] added `log_level` flag to control the logger ## 0.7.1 (November 14, 2017) diff --git a/Makefile b/Makefile index ebe8f3a9..d2384ae4 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ protoc: ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 - protoc $(INCLUDE) --gogo_out=plugins=grpc:. types/*.proto + protoc $(INCLUDE) --gogo_out=plugins=grpc:. --lint_out=. types/*.proto install: @ go install ./cmd/... @@ -38,14 +38,14 @@ dist: @ bash scripts/dist.sh @ bash scripts/publish.sh -test: +test: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; @ echo "==> Running linter" @ make metalinter_test @ echo "==> Running go test" @ go test $(PACKAGES) -test_race: +test_race: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; @ echo "==> Running go test --race" @go test -v -race $(PACKAGES) diff --git a/README.md b/README.md index 0deec181..1b7f8900 100644 --- a/README.md +++ b/README.md @@ -168,8 +168,10 @@ Here, we describe the requests and responses as function arguments and return va * __Arguments__: * `Hash ([]byte)`: The block's hash. This can be derived from the block header. * `Header (struct{})`: The block header + * `AbsentValidators ([]int32)`: List of indices of validators not included in the LastCommit + * `ByzantineValidators ([]Evidence)`: List of evidence of validators that acted maliciously * __Usage__:
- Signals the beginning of a new block. Called prior to any DeliverTxs. The header is expected to at least contain the Height. + Signals the beginning of a new block. Called prior to any DeliverTxs. The header is expected to at least contain the Height. The `AbsentValidators` and `ByzantineValidators` can be used to determine rewards and punishments for the validators. #### EndBlock * __Arguments__: diff --git a/types/types.pb.go b/types/types.pb.go index 094f3012..02d63e61 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -37,6 +37,7 @@ It has these top-level messages: BlockID PartSetHeader Validator + Evidence KVPair */ package types @@ -81,7 +82,7 @@ var KVPair_Type_value = map[string]int32{ func (x KVPair_Type) String() string { return proto.EnumName(KVPair_Type_name, int32(x)) } -func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29, 0} } +func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30, 0} } type Request struct { // Types that are valid to be assigned to Value: @@ -644,8 +645,10 @@ func (m *RequestInitChain) GetValidators() []*Validator { } type RequestBeginBlock struct { - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` + AbsentValidators []int32 `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators" json:"absent_validators,omitempty"` + ByzantineValidators []*Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators,omitempty"` } func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } @@ -667,6 +670,20 @@ func (m *RequestBeginBlock) GetHeader() *Header { return nil } +func (m *RequestBeginBlock) GetAbsentValidators() []int32 { + if m != nil { + return m.AbsentValidators + } + return nil +} + +func (m *RequestBeginBlock) GetByzantineValidators() []*Evidence { + if m != nil { + return m.ByzantineValidators + } + return nil +} + type RequestEndBlock struct { Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` } @@ -1536,6 +1553,30 @@ func (m *Validator) GetPower() int64 { return 0 } +type Evidence struct { + PubKey []byte `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *Evidence) Reset() { *m = Evidence{} } +func (m *Evidence) String() string { return proto.CompactTextString(m) } +func (*Evidence) ProtoMessage() {} +func (*Evidence) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} } + +func (m *Evidence) GetPubKey() []byte { + if m != nil { + return m.PubKey + } + return nil +} + +func (m *Evidence) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + type KVPair struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` ValueType KVPair_Type `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=types.KVPair_Type" json:"value_type,omitempty"` @@ -1546,7 +1587,7 @@ type KVPair struct { func (m *KVPair) Reset() { *m = KVPair{} } func (m *KVPair) String() string { return proto.CompactTextString(m) } func (*KVPair) ProtoMessage() {} -func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} } +func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} } func (m *KVPair) GetKey() string { if m != nil { @@ -1606,6 +1647,7 @@ func init() { proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") proto.RegisterType((*Validator)(nil), "types.Validator") + proto.RegisterType((*Evidence)(nil), "types.Evidence") proto.RegisterType((*KVPair)(nil), "types.KVPair") proto.RegisterEnum("types.KVPair_Type", KVPair_Type_name, KVPair_Type_value) } @@ -2015,98 +2057,102 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1488 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x8e, 0x13, 0xc7, - 0x13, 0x5f, 0x7f, 0xdb, 0xe5, 0xfd, 0x30, 0xcd, 0xfe, 0x61, 0x30, 0x07, 0x60, 0x24, 0xfe, 0xec, - 0x12, 0x58, 0x93, 0x45, 0x44, 0x2c, 0x44, 0x91, 0xd6, 0x2c, 0xc4, 0x16, 0x12, 0x21, 0xc3, 0x8a, - 0xab, 0x35, 0xf6, 0xb4, 0xed, 0x11, 0xf6, 0xcc, 0x30, 0xd3, 0x5e, 0xbc, 0x52, 0x1e, 0x81, 0x7b, - 0xce, 0xc9, 0x25, 0x52, 0x5e, 0x20, 0x6f, 0x10, 0xe5, 0x19, 0x72, 0xe0, 0x59, 0xa2, 0xaa, 0xee, - 0xf9, 0xdc, 0x19, 0x0e, 0x1c, 0xb8, 0xac, 0xba, 0xba, 0xea, 0xd7, 0xae, 0xea, 0xa9, 0xfe, 0x55, - 0xd5, 0xc2, 0x25, 0x71, 0xee, 0xf1, 0xa0, 0x47, 0x7f, 0x0f, 0x3c, 0xdf, 0x15, 0x2e, 0xab, 0x91, - 0xd0, 0xbd, 0x3f, 0xb3, 0xc5, 0x7c, 0x35, 0x3e, 0x98, 0xb8, 0xcb, 0xde, 0xcc, 0x9d, 0xb9, 0x3d, - 0xd2, 0x8e, 0x57, 0x53, 0x92, 0x48, 0xa0, 0x95, 0x44, 0xe9, 0x7f, 0x57, 0xa1, 0x61, 0xf0, 0xf7, - 0x2b, 0x1e, 0x08, 0xb6, 0x07, 0x55, 0x3e, 0x99, 0xbb, 0x5a, 0xe9, 0x66, 0x69, 0xaf, 0x7d, 0xc8, - 0x0e, 0xe4, 0xe9, 0x4a, 0xfb, 0x7c, 0x32, 0x77, 0x07, 0x1b, 0x06, 0x59, 0xb0, 0x6f, 0xa0, 0x36, - 0x5d, 0xac, 0x82, 0xb9, 0x56, 0x26, 0xd3, 0xcb, 0x69, 0xd3, 0x17, 0xa8, 0x1a, 0x6c, 0x18, 0xd2, - 0x06, 0x8f, 0xb5, 0x9d, 0xa9, 0xab, 0x55, 0xf2, 0x8e, 0x1d, 0x3a, 0x53, 0x3a, 0x16, 0x2d, 0xd8, - 0x63, 0x80, 0x80, 0x8b, 0x91, 0xeb, 0x09, 0xdb, 0x75, 0xb4, 0x2a, 0xd9, 0x5f, 0x4d, 0xdb, 0xbf, - 0xe1, 0xe2, 0x27, 0x52, 0x0f, 0x36, 0x8c, 0x56, 0x10, 0x0a, 0x88, 0xb4, 0xf8, 0xc2, 0x3e, 0xe3, - 0xfe, 0x48, 0xac, 0xb5, 0x5a, 0x1e, 0xf2, 0x44, 0xea, 0x4f, 0xd7, 0x88, 0xb4, 0x42, 0x81, 0x1d, - 0x42, 0x73, 0x32, 0xe7, 0x93, 0x77, 0x88, 0xab, 0x13, 0xee, 0x7f, 0x69, 0xdc, 0x33, 0xd4, 0x12, - 0xaa, 0x31, 0x91, 0x4b, 0x76, 0x00, 0xf5, 0x89, 0xbb, 0x5c, 0xda, 0x42, 0x6b, 0x10, 0x62, 0x37, - 0x83, 0x20, 0xdd, 0x60, 0xc3, 0x50, 0x56, 0x78, 0x5d, 0xef, 0x57, 0xdc, 0x3f, 0xd7, 0x9a, 0x79, - 0xd7, 0xf5, 0x33, 0xaa, 0xf0, 0xba, 0xc8, 0x06, 0x43, 0xb1, 0x1d, 0x5b, 0x8c, 0x26, 0x73, 0xd3, - 0x76, 0xb4, 0x56, 0x5e, 0x28, 0x43, 0xc7, 0x16, 0xcf, 0x50, 0x8d, 0xa1, 0xd8, 0xa1, 0xc0, 0x9e, - 0x42, 0x7b, 0xcc, 0x67, 0xb6, 0x33, 0x1a, 0x2f, 0xdc, 0xc9, 0x3b, 0x0d, 0x08, 0xaa, 0xa5, 0xa1, - 0x7d, 0x34, 0xe8, 0xa3, 0x7e, 0xb0, 0x61, 0xc0, 0x38, 0x92, 0xd8, 0x23, 0x68, 0x71, 0xc7, 0x52, - 0xd0, 0x36, 0x41, 0xaf, 0x64, 0x32, 0xc0, 0xb1, 0x42, 0x60, 0x93, 0xab, 0x75, 0xbf, 0x01, 0xb5, - 0x33, 0x73, 0xb1, 0xe2, 0xfa, 0x1d, 0x68, 0x27, 0x32, 0x85, 0x69, 0xd0, 0x58, 0xf2, 0x20, 0x30, - 0x67, 0x9c, 0xd2, 0xa9, 0x65, 0x84, 0xa2, 0xbe, 0x0d, 0x9b, 0xc9, 0x3c, 0x49, 0x00, 0x31, 0x17, - 0x10, 0x78, 0xc6, 0xfd, 0x00, 0x13, 0x40, 0x01, 0x95, 0xa8, 0x3f, 0x81, 0x4e, 0x36, 0x09, 0x58, - 0x07, 0x2a, 0xef, 0xf8, 0xb9, 0xb2, 0xc4, 0x25, 0xdb, 0x55, 0x0e, 0x51, 0x6a, 0xb6, 0x0c, 0xe5, - 0x9d, 0x1e, 0x61, 0xa3, 0x34, 0x60, 0xdb, 0x50, 0x16, 0x6b, 0x82, 0x6e, 0x1a, 0x65, 0xb1, 0xd6, - 0x6f, 0xc2, 0x76, 0xfa, 0x93, 0x5f, 0xb0, 0xb0, 0x22, 0xd7, 0xe9, 0x9b, 0x31, 0x06, 0x55, 0xcb, - 0x14, 0xa6, 0xb2, 0xa0, 0x35, 0xee, 0x79, 0xa6, 0x98, 0xab, 0x9f, 0xa7, 0x35, 0xbb, 0x02, 0xf5, - 0x39, 0xb7, 0x67, 0x73, 0x41, 0x6f, 0xa0, 0x62, 0x28, 0x09, 0x7d, 0xf5, 0x7c, 0xf7, 0x8c, 0x53, - 0xaa, 0x37, 0x0d, 0x29, 0xe8, 0x3b, 0xb0, 0x95, 0x4a, 0x24, 0xfd, 0x24, 0x72, 0x3e, 0xfa, 0xf0, - 0xec, 0x01, 0xc0, 0x99, 0xb9, 0xb0, 0x2d, 0x53, 0xb8, 0x7e, 0xa0, 0x95, 0x6e, 0x56, 0xf6, 0xda, - 0x87, 0x1d, 0xf5, 0xbd, 0xde, 0x86, 0x0a, 0x23, 0x61, 0xa3, 0xbf, 0x82, 0x4b, 0x17, 0x72, 0x00, - 0xbd, 0x9d, 0x9b, 0xc1, 0x3c, 0x8c, 0x00, 0xd7, 0xec, 0x36, 0x7a, 0x6b, 0x5a, 0xdc, 0x57, 0xaf, - 0x7b, 0x4b, 0x1d, 0x3b, 0xa0, 0x4d, 0x43, 0x29, 0xf5, 0x7d, 0xd8, 0xc9, 0x24, 0x46, 0x22, 0xce, - 0x52, 0x32, 0x4e, 0xfd, 0x63, 0x0d, 0x9a, 0x06, 0x0f, 0x3c, 0xd7, 0x09, 0x38, 0x7b, 0x0c, 0x2d, - 0xbe, 0x9e, 0x70, 0xf9, 0xc6, 0x4b, 0x99, 0x1c, 0x95, 0x36, 0xcf, 0x43, 0x3d, 0xe6, 0x77, 0x64, - 0xcc, 0xf6, 0x15, 0x3f, 0x65, 0x49, 0x47, 0x81, 0x92, 0x04, 0x75, 0x2f, 0x24, 0xa8, 0x4a, 0xe6, - 0x81, 0x4a, 0xdb, 0x0c, 0x43, 0xed, 0x2b, 0x86, 0xaa, 0xe6, 0x1e, 0x9c, 0xa2, 0xa8, 0xa3, 0x14, - 0x45, 0xd5, 0x72, 0xdd, 0x2f, 0xe0, 0xa8, 0xa3, 0x14, 0x47, 0xd5, 0x73, 0xa1, 0x05, 0x24, 0xf5, - 0x30, 0x41, 0x52, 0x8d, 0xcc, 0xdb, 0x94, 0xc0, 0x1c, 0x96, 0xea, 0x45, 0x2c, 0xd5, 0xcc, 0xf0, - 0x9a, 0x82, 0x64, 0x69, 0xea, 0x5e, 0x48, 0x53, 0xad, 0xdc, 0x4b, 0xcb, 0xf0, 0xd4, 0x51, 0x8a, - 0xa7, 0x20, 0x37, 0x9c, 0x02, 0xa2, 0xfa, 0x3e, 0x4d, 0x54, 0x92, 0x6d, 0xae, 0x65, 0xb0, 0x85, - 0x4c, 0xf5, 0x5d, 0x92, 0xa9, 0x36, 0x33, 0xfc, 0xa8, 0x72, 0xe1, 0xb3, 0x54, 0xb5, 0x8f, 0x2f, - 0x21, 0x93, 0x69, 0xf8, 0x16, 0xb9, 0xef, 0xbb, 0xbe, 0xe2, 0x12, 0x29, 0xe8, 0x7b, 0xf8, 0xe2, - 0xe3, 0xfc, 0xfa, 0x0c, 0xad, 0xd1, 0xab, 0x4d, 0x64, 0x97, 0xfe, 0x6b, 0x29, 0xc6, 0x12, 0xb3, - 0x25, 0xd9, 0xa2, 0xa5, 0xd8, 0x22, 0xc1, 0x76, 0xe5, 0x14, 0xdb, 0xb1, 0xbb, 0x70, 0x69, 0x61, - 0x06, 0x42, 0x86, 0x39, 0x4a, 0xd1, 0xc7, 0x0e, 0x2a, 0x64, 0x7c, 0x92, 0x47, 0xee, 0xc3, 0xe5, - 0x84, 0xad, 0xe9, 0x79, 0x23, 0x7a, 0xd4, 0x55, 0x7a, 0xd4, 0x9d, 0xc8, 0xfa, 0xd8, 0xf3, 0x06, - 0x66, 0x30, 0xd7, 0x6f, 0xc7, 0xf1, 0xa7, 0x98, 0x74, 0xe1, 0xce, 0x42, 0x26, 0x5d, 0xb8, 0x33, - 0xfd, 0xf7, 0x52, 0x6c, 0x17, 0xb3, 0x26, 0x83, 0xea, 0xc4, 0xb5, 0x64, 0xf8, 0x5b, 0x06, 0xad, - 0xd9, 0x89, 0x8a, 0x0c, 0x43, 0xd8, 0xec, 0x3f, 0xf8, 0xe7, 0xd3, 0x8d, 0x8d, 0x7f, 0x3f, 0xdd, - 0xd8, 0x4b, 0x74, 0x22, 0x82, 0x3b, 0x16, 0xf7, 0x97, 0xb6, 0x23, 0x7a, 0x33, 0xf7, 0xfe, 0x07, - 0xdb, 0xe7, 0x3d, 0x44, 0x1c, 0xf4, 0xcf, 0x05, 0x0f, 0xd4, 0x5d, 0x28, 0x0f, 0x2a, 0x91, 0x07, - 0xec, 0x16, 0x54, 0x85, 0x39, 0x0b, 0xb4, 0x2a, 0xd1, 0x5b, 0xc8, 0x43, 0x2f, 0xdf, 0xbe, 0x36, - 0x6d, 0xdf, 0x20, 0x95, 0xfe, 0x5b, 0x09, 0x69, 0x28, 0xf5, 0x06, 0xbe, 0xaa, 0x8b, 0x1d, 0xa8, - 0xcc, 0xcc, 0x80, 0xae, 0xba, 0x62, 0xe0, 0x12, 0x77, 0xa6, 0x9c, 0x13, 0x35, 0x54, 0x0c, 0x5c, - 0xea, 0x7f, 0x95, 0xe3, 0xdc, 0x88, 0x0a, 0xc7, 0x05, 0x0f, 0x77, 0xa1, 0x66, 0x3b, 0x16, 0x5f, - 0x93, 0x8b, 0x15, 0x43, 0x0a, 0xac, 0x2f, 0x0b, 0x5c, 0xe5, 0x0b, 0xdd, 0xa6, 0x92, 0xf8, 0x22, - 0x2c, 0x89, 0xd5, 0x2f, 0x3c, 0x45, 0xc2, 0xf1, 0x1c, 0xcf, 0x77, 0xdd, 0x29, 0xc5, 0xf6, 0x45, - 0xe7, 0x10, 0x3c, 0x51, 0x26, 0xea, 0xa9, 0x72, 0xa8, 0x6e, 0xb7, 0x11, 0xa7, 0xe0, 0x2f, 0x58, - 0x92, 0x93, 0x6c, 0xf5, 0x35, 0xbf, 0xad, 0x7e, 0x39, 0xce, 0xff, 0x88, 0xc8, 0xf4, 0x5d, 0x60, - 0x17, 0x19, 0x4a, 0xf6, 0x26, 0x69, 0xee, 0x61, 0xff, 0x87, 0x9a, 0x65, 0x4f, 0xa7, 0xc5, 0xd5, - 0x59, 0xaa, 0xf5, 0x3f, 0xca, 0x50, 0x97, 0xb5, 0x95, 0x5d, 0x43, 0x9e, 0x37, 0x6d, 0x67, 0x64, - 0x5b, 0x21, 0xbf, 0x90, 0x3c, 0xb4, 0x12, 0x97, 0x56, 0x4e, 0x5d, 0x1a, 0x83, 0xaa, 0xb0, 0x97, - 0x5c, 0x51, 0x03, 0xad, 0xd9, 0x55, 0x68, 0x38, 0xab, 0xe5, 0x48, 0xac, 0xc3, 0xc4, 0xac, 0x3b, - 0xab, 0xe5, 0xe9, 0x3a, 0x60, 0x87, 0xb0, 0x95, 0x20, 0x0a, 0xdb, 0x52, 0x05, 0x6c, 0x5b, 0xb9, - 0x46, 0x7e, 0x0f, 0x4f, 0x8c, 0x76, 0x44, 0x19, 0x43, 0x8b, 0xed, 0x01, 0x31, 0xc8, 0x48, 0x16, - 0x09, 0xc9, 0x2c, 0x75, 0x62, 0x96, 0x6d, 0xdc, 0x57, 0x55, 0x04, 0x1b, 0x87, 0xeb, 0xd0, 0xc2, - 0x9b, 0x94, 0x26, 0x0d, 0x32, 0x69, 0xe2, 0x06, 0x29, 0xef, 0xc0, 0x4e, 0xdc, 0x8c, 0x48, 0x93, - 0xa6, 0x3c, 0x25, 0xde, 0x26, 0xc3, 0x6b, 0xd0, 0x8c, 0x18, 0xac, 0x45, 0x16, 0x0d, 0x53, 0x11, - 0xd7, 0x10, 0x1a, 0xca, 0xc5, 0xdc, 0xc6, 0xe5, 0x2e, 0xd4, 0x3c, 0xd3, 0x17, 0x81, 0x6a, 0x10, - 0xc2, 0xfa, 0xf5, 0xda, 0xf4, 0xb1, 0x63, 0x54, 0xed, 0x8b, 0x34, 0xd1, 0x8f, 0x60, 0x2b, 0xb5, - 0x8f, 0xcf, 0x4f, 0xb8, 0xc2, 0x5c, 0xa8, 0xd6, 0x45, 0x0a, 0xd1, 0xcf, 0x94, 0xe3, 0x9f, 0xd1, - 0x9f, 0x40, 0x2b, 0xfa, 0x86, 0x78, 0xd5, 0xde, 0x6a, 0x3c, 0x0a, 0x9b, 0xd0, 0x4d, 0xa3, 0xee, - 0xad, 0xc6, 0x2f, 0x65, 0x1f, 0xea, 0xb9, 0x1f, 0x54, 0x13, 0x55, 0x31, 0xa4, 0xa0, 0xff, 0x59, - 0x82, 0xba, 0xe4, 0xaf, 0x9c, 0xd6, 0xf5, 0x5b, 0xea, 0xe9, 0x56, 0x7c, 0x84, 0x7e, 0x13, 0x6e, - 0x3b, 0x1a, 0x97, 0x24, 0xe8, 0xe0, 0xf4, 0xdc, 0xe3, 0x46, 0x8b, 0xac, 0x70, 0xc9, 0x6e, 0xc1, - 0xa6, 0x84, 0x04, 0xc2, 0xb7, 0x9d, 0x30, 0x7b, 0xdb, 0xb4, 0xf7, 0x86, 0xb6, 0xf0, 0xab, 0x48, - 0x13, 0xdb, 0x11, 0x2a, 0x1d, 0x9a, 0xb4, 0x31, 0x74, 0x84, 0x7e, 0x1d, 0xaa, 0x74, 0x0e, 0x40, - 0xfd, 0xcd, 0xa9, 0x31, 0x7c, 0xf5, 0x63, 0x67, 0x83, 0x35, 0xa0, 0x32, 0x7c, 0x75, 0xda, 0x29, - 0x1d, 0x7e, 0xac, 0xc1, 0xce, 0x71, 0xff, 0xd9, 0xf0, 0xd8, 0xf3, 0x16, 0xf6, 0xc4, 0xa4, 0x32, - 0xd1, 0x83, 0x2a, 0x15, 0xc2, 0x9c, 0xe9, 0xb0, 0x9b, 0xd7, 0x91, 0xb1, 0x43, 0xa8, 0x51, 0x3d, - 0x64, 0x79, 0x43, 0x62, 0x37, 0xb7, 0x31, 0xc3, 0x1f, 0x91, 0x15, 0xf3, 0xe2, 0xac, 0xd8, 0xcd, - 0xeb, 0xce, 0xd8, 0x0f, 0xd0, 0x8a, 0x2b, 0x59, 0xd1, 0xc4, 0xd8, 0x2d, 0xec, 0xd3, 0x10, 0x1f, - 0x57, 0xb8, 0xa2, 0xb9, 0xb1, 0x5b, 0xd8, 0xac, 0xb1, 0xc7, 0xd0, 0x08, 0x8b, 0x4f, 0xfe, 0xf4, - 0xd8, 0x2d, 0xe8, 0xd7, 0xf0, 0x7a, 0x64, 0x49, 0xc8, 0x1b, 0x0a, 0xbb, 0xb9, 0x2d, 0x18, 0x7b, - 0x04, 0x75, 0xc5, 0x86, 0xb9, 0x83, 0x67, 0x37, 0xbf, 0xd1, 0xc3, 0x20, 0xe3, 0xf9, 0xa1, 0x68, - 0xa2, 0xec, 0x16, 0xb6, 0x70, 0xec, 0x18, 0x20, 0x31, 0x39, 0x14, 0xce, 0x95, 0xdd, 0xe2, 0x46, - 0x8e, 0x3d, 0x85, 0x66, 0x3c, 0x2c, 0xe4, 0x4f, 0x97, 0xdd, 0xa2, 0x5e, 0x6e, 0x5c, 0xa7, 0xff, - 0x58, 0x3c, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x34, 0x61, 0x21, 0x91, 0xfc, 0x10, 0x00, 0x00, + // 1551 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0xcb, 0x8e, 0x13, 0x47, + 0x17, 0xc7, 0x6d, 0xb7, 0xaf, 0xc7, 0x73, 0xf1, 0xd4, 0xcc, 0x07, 0xc6, 0x2c, 0x18, 0x5a, 0xe2, + 0xc3, 0xc3, 0x65, 0xcc, 0x37, 0x88, 0x4f, 0x0c, 0x44, 0x91, 0xc6, 0x0c, 0xc4, 0x16, 0x12, 0x21, + 0xcd, 0x88, 0xad, 0xd5, 0x76, 0x97, 0xed, 0x12, 0x76, 0x77, 0xd3, 0x5d, 0x1e, 0x3c, 0x51, 0x1e, + 0x81, 0x7d, 0xd6, 0xc9, 0x26, 0x52, 0x5e, 0x20, 0xcb, 0xec, 0xa2, 0x3c, 0x43, 0x16, 0x3c, 0x4b, + 0x54, 0xa7, 0xaa, 0xaf, 0xd3, 0xcd, 0x82, 0x05, 0x9b, 0x51, 0x5d, 0xce, 0xbf, 0x7c, 0xaa, 0xfa, + 0xd4, 0xef, 0x9c, 0x1a, 0xd8, 0xe1, 0x17, 0x2e, 0xf5, 0x7b, 0xf8, 0xf7, 0xd0, 0xf5, 0x1c, 0xee, + 0x90, 0x0a, 0x76, 0x3a, 0xf7, 0x67, 0x8c, 0xcf, 0x57, 0xe3, 0xc3, 0x89, 0xb3, 0xec, 0xcd, 0x9c, + 0x99, 0xd3, 0xc3, 0xd9, 0xf1, 0x6a, 0x8a, 0x3d, 0xec, 0x60, 0x4b, 0xaa, 0xf4, 0xbf, 0xca, 0x50, + 0x33, 0xe8, 0xfb, 0x15, 0xf5, 0x39, 0xe9, 0x42, 0x99, 0x4e, 0xe6, 0x4e, 0xbb, 0xb8, 0x5f, 0xec, + 0x36, 0x8f, 0xc8, 0xa1, 0x5c, 0x5d, 0xcd, 0x3e, 0x9f, 0xcc, 0x9d, 0x41, 0xc1, 0x40, 0x0b, 0x72, + 0x17, 0x2a, 0xd3, 0xc5, 0xca, 0x9f, 0xb7, 0x4b, 0x68, 0xba, 0x9b, 0x34, 0x7d, 0x21, 0xa6, 0x06, + 0x05, 0x43, 0xda, 0x88, 0x65, 0x99, 0x3d, 0x75, 0xda, 0x5a, 0xd6, 0xb2, 0x43, 0x7b, 0x8a, 0xcb, + 0x0a, 0x0b, 0xf2, 0x18, 0xc0, 0xa7, 0x7c, 0xe4, 0xb8, 0x9c, 0x39, 0x76, 0xbb, 0x8c, 0xf6, 0x57, + 0x93, 0xf6, 0x6f, 0x28, 0xff, 0x1e, 0xa7, 0x07, 0x05, 0xa3, 0xe1, 0x07, 0x1d, 0xa1, 0xb4, 0xe8, + 0x82, 0x9d, 0x53, 0x6f, 0xc4, 0xd7, 0xed, 0x4a, 0x96, 0xf2, 0x54, 0xce, 0x9f, 0xad, 0x85, 0xd2, + 0x0a, 0x3a, 0xe4, 0x08, 0xea, 0x93, 0x39, 0x9d, 0xbc, 0x13, 0xba, 0x2a, 0xea, 0xfe, 0x93, 0xd4, + 0x3d, 0x13, 0xb3, 0xa8, 0xaa, 0x4d, 0x64, 0x93, 0x1c, 0x42, 0x75, 0xe2, 0x2c, 0x97, 0x8c, 0xb7, + 0x6b, 0xa8, 0xd8, 0x4b, 0x29, 0x70, 0x6e, 0x50, 0x30, 0x94, 0x95, 0x38, 0xae, 0xf7, 0x2b, 0xea, + 0x5d, 0xb4, 0xeb, 0x59, 0xc7, 0xf5, 0x83, 0x98, 0x12, 0xc7, 0x85, 0x36, 0x62, 0x2b, 0xcc, 0x66, + 0x7c, 0x34, 0x99, 0x9b, 0xcc, 0x6e, 0x37, 0xb2, 0xb6, 0x32, 0xb4, 0x19, 0x7f, 0x26, 0xa6, 0xc5, + 0x56, 0x58, 0xd0, 0x21, 0x4f, 0xa1, 0x39, 0xa6, 0x33, 0x66, 0x8f, 0xc6, 0x0b, 0x67, 0xf2, 0xae, + 0x0d, 0x28, 0x6d, 0x27, 0xa5, 0x7d, 0x61, 0xd0, 0x17, 0xf3, 0x83, 0x82, 0x01, 0xe3, 0xb0, 0x47, + 0x1e, 0x41, 0x83, 0xda, 0x96, 0x92, 0x36, 0x51, 0x7a, 0x25, 0x15, 0x01, 0xb6, 0x15, 0x08, 0xeb, + 0x54, 0xb5, 0xfb, 0x35, 0xa8, 0x9c, 0x9b, 0x8b, 0x15, 0xd5, 0x6f, 0x43, 0x33, 0x16, 0x29, 0xa4, + 0x0d, 0xb5, 0x25, 0xf5, 0x7d, 0x73, 0x46, 0x31, 0x9c, 0x1a, 0x46, 0xd0, 0xd5, 0xb7, 0x60, 0x23, + 0x1e, 0x27, 0x31, 0xa1, 0x88, 0x05, 0x21, 0x3c, 0xa7, 0x9e, 0x2f, 0x02, 0x40, 0x09, 0x55, 0x57, + 0x7f, 0x02, 0xad, 0x74, 0x10, 0x90, 0x16, 0x68, 0xef, 0xe8, 0x85, 0xb2, 0x14, 0x4d, 0xb2, 0xa7, + 0x1c, 0xc2, 0xd0, 0x6c, 0x18, 0xca, 0x3b, 0x3d, 0xd4, 0x86, 0x61, 0x40, 0xb6, 0xa0, 0xc4, 0xd7, + 0x28, 0xdd, 0x30, 0x4a, 0x7c, 0xad, 0xef, 0xc3, 0x56, 0xf2, 0x93, 0x5f, 0xb2, 0xb0, 0x42, 0xd7, + 0xf1, 0x9b, 0x11, 0x02, 0x65, 0xcb, 0xe4, 0xa6, 0xb2, 0xc0, 0xb6, 0x18, 0x73, 0x4d, 0x3e, 0x57, + 0x3f, 0x8f, 0x6d, 0x72, 0x05, 0xaa, 0x73, 0xca, 0x66, 0x73, 0x8e, 0x77, 0x40, 0x33, 0x54, 0x4f, + 0xf8, 0xea, 0x7a, 0xce, 0x39, 0xc5, 0x50, 0xaf, 0x1b, 0xb2, 0xa3, 0x6f, 0xc3, 0x66, 0x22, 0x90, + 0xf4, 0xd3, 0xd0, 0xf9, 0xf0, 0xc3, 0x93, 0x07, 0x00, 0xe7, 0xe6, 0x82, 0x59, 0x26, 0x77, 0x3c, + 0xbf, 0x5d, 0xdc, 0xd7, 0xba, 0xcd, 0xa3, 0x96, 0xfa, 0x5e, 0x6f, 0x83, 0x09, 0x23, 0x66, 0xa3, + 0xff, 0x59, 0x84, 0x9d, 0x4b, 0x41, 0x20, 0xdc, 0x9d, 0x9b, 0xfe, 0x3c, 0xd8, 0x82, 0x68, 0x93, + 0x5b, 0xc2, 0x5d, 0xd3, 0xa2, 0x9e, 0xba, 0xde, 0x9b, 0x6a, 0xdd, 0x01, 0x0e, 0x1a, 0x6a, 0x92, + 0xdc, 0x85, 0x1d, 0x73, 0xec, 0x53, 0x9b, 0x8f, 0x62, 0x9e, 0x68, 0xfb, 0x5a, 0xb7, 0x62, 0xb4, + 0xe4, 0x44, 0xe8, 0x88, 0x4f, 0xfa, 0xb0, 0x37, 0xbe, 0xf8, 0xd1, 0xb4, 0x39, 0xb3, 0x69, 0xdc, + 0xbe, 0x8c, 0x9e, 0x6f, 0xab, 0x5f, 0x78, 0x7e, 0xce, 0x2c, 0x6a, 0x4f, 0xa8, 0xb1, 0x1b, 0x1a, + 0x47, 0x6b, 0xe8, 0x07, 0xb0, 0x9d, 0x0a, 0xc5, 0xd8, 0xc9, 0x16, 0xe3, 0x27, 0xab, 0x7f, 0xac, + 0x40, 0xdd, 0xa0, 0xbe, 0xeb, 0xd8, 0x3e, 0x25, 0x8f, 0xa1, 0x41, 0xd7, 0x13, 0x2a, 0xa9, 0x52, + 0x4c, 0xdd, 0x0a, 0x69, 0xf3, 0x3c, 0x98, 0x17, 0x37, 0x2a, 0x34, 0x26, 0x07, 0x8a, 0x88, 0x69, + 0xcc, 0x29, 0x51, 0x1c, 0x89, 0xf7, 0x02, 0x24, 0x6a, 0x29, 0x24, 0x48, 0xdb, 0x14, 0x13, 0x0f, + 0x14, 0x13, 0xcb, 0x99, 0x0b, 0x27, 0xa0, 0x78, 0x9c, 0x80, 0x62, 0x25, 0xd3, 0xfd, 0x1c, 0x2a, + 0x1e, 0x27, 0xa8, 0x58, 0xcd, 0x94, 0xe6, 0x60, 0xf1, 0x61, 0x0c, 0x8b, 0xb5, 0x14, 0x0d, 0xa4, + 0x30, 0x83, 0x8b, 0xbd, 0x90, 0x8b, 0xf5, 0x14, 0x49, 0x95, 0x24, 0x0d, 0xc6, 0x7b, 0x01, 0x18, + 0x1b, 0x99, 0x87, 0x96, 0x22, 0xe3, 0x71, 0x82, 0x8c, 0x90, 0xb9, 0x9d, 0x1c, 0x34, 0x7e, 0x93, + 0x44, 0xa3, 0xe4, 0xdb, 0xb5, 0x94, 0x36, 0x97, 0x8d, 0xff, 0x8f, 0xb3, 0x71, 0x23, 0x45, 0x64, + 0x15, 0x0b, 0x9f, 0x85, 0xe3, 0x81, 0xb8, 0x7a, 0xa9, 0x48, 0x13, 0xb7, 0x9f, 0x7a, 0x9e, 0xe3, + 0x29, 0x7a, 0xc9, 0x8e, 0xde, 0x15, 0x8c, 0x89, 0xe2, 0xeb, 0x33, 0x20, 0x45, 0x4e, 0xc4, 0xa2, + 0x4b, 0xff, 0xb9, 0x18, 0x69, 0x91, 0xa5, 0x71, 0x3e, 0x35, 0x14, 0x9f, 0x62, 0x7c, 0x2d, 0x25, + 0xf8, 0x4a, 0xee, 0xc0, 0xce, 0xc2, 0xf4, 0xb9, 0xdc, 0xe6, 0x28, 0x01, 0xac, 0x6d, 0x31, 0x21, + 0xf7, 0x27, 0xc9, 0x75, 0x1f, 0x76, 0x63, 0xb6, 0xa6, 0xeb, 0x8e, 0x90, 0x22, 0x65, 0xa4, 0x48, + 0x2b, 0xb4, 0x3e, 0x71, 0xdd, 0x81, 0xe9, 0xcf, 0xf5, 0x5b, 0xd1, 0xfe, 0x13, 0xec, 0x5e, 0x38, + 0xb3, 0x80, 0xdd, 0x0b, 0x67, 0xa6, 0xff, 0x5a, 0x8c, 0xec, 0x22, 0x4e, 0x13, 0x28, 0x4f, 0x1c, + 0x4b, 0x6e, 0x7f, 0xd3, 0xc0, 0x36, 0x39, 0x55, 0x3b, 0x13, 0x5b, 0xd8, 0xe8, 0x3f, 0xf8, 0xfb, + 0xd3, 0x8d, 0xc2, 0x3f, 0x9f, 0x6e, 0x74, 0x63, 0xb5, 0x0f, 0xa7, 0xb6, 0x45, 0xbd, 0x25, 0xb3, + 0x79, 0x6f, 0xe6, 0xdc, 0xff, 0xc0, 0x3c, 0xda, 0x13, 0x8a, 0xc3, 0xfe, 0x05, 0xa7, 0xbe, 0x3a, + 0x0b, 0xe5, 0x81, 0x16, 0x7a, 0x40, 0x6e, 0x42, 0x99, 0x9b, 0xb3, 0x00, 0x4b, 0x01, 0xf8, 0x5e, + 0xbe, 0x7d, 0x6d, 0x32, 0xcf, 0xc0, 0x29, 0xfd, 0x97, 0xa2, 0xc0, 0x50, 0xe2, 0x0e, 0x7c, 0x55, + 0x17, 0x5b, 0xa0, 0xcd, 0x4c, 0x1f, 0x8f, 0x5a, 0x33, 0x44, 0x53, 0x8c, 0x4c, 0x29, 0x45, 0x34, + 0x68, 0x86, 0x68, 0xea, 0x7f, 0x94, 0xa2, 0xd8, 0x08, 0x53, 0xd5, 0x25, 0x0f, 0xf7, 0xa0, 0xc2, + 0x6c, 0x8b, 0xae, 0xd1, 0x45, 0xcd, 0x90, 0x1d, 0xd2, 0x97, 0x29, 0x55, 0xfb, 0x42, 0xb7, 0x31, + 0x09, 0xbf, 0x08, 0x92, 0x70, 0xf9, 0x0b, 0x57, 0x91, 0x72, 0xb1, 0x8e, 0xeb, 0x39, 0xce, 0x14, + 0xf7, 0xf6, 0x45, 0xeb, 0xa0, 0x3c, 0x96, 0x26, 0xaa, 0x89, 0x04, 0xac, 0x4e, 0xb7, 0x16, 0x85, + 0xe0, 0x4f, 0xa2, 0x08, 0x88, 0xd3, 0xea, 0x6b, 0x7e, 0x5b, 0x7d, 0x37, 0x8a, 0xff, 0x10, 0x64, + 0xfa, 0x1e, 0x90, 0xcb, 0x84, 0x92, 0xd5, 0x50, 0x92, 0x3d, 0xe4, 0xbf, 0x50, 0xb1, 0xd8, 0x74, + 0x9a, 0x5f, 0x0f, 0xc8, 0x69, 0xfd, 0xb7, 0x12, 0x54, 0x65, 0x32, 0x27, 0xd7, 0x04, 0xe7, 0x4d, + 0x66, 0x8f, 0x98, 0x15, 0xf0, 0x05, 0xfb, 0x43, 0x2b, 0x76, 0x68, 0xa5, 0xc4, 0xa1, 0x11, 0x28, + 0x73, 0xb6, 0xa4, 0x0a, 0x0d, 0xd8, 0x26, 0x57, 0xa1, 0x66, 0xaf, 0x96, 0x23, 0xbe, 0x0e, 0x02, + 0xb3, 0x6a, 0xaf, 0x96, 0x67, 0x6b, 0x9f, 0x1c, 0xc1, 0x66, 0x0c, 0x14, 0xcc, 0x52, 0x09, 0x6c, + 0x4b, 0xb9, 0x86, 0x7e, 0x0f, 0x4f, 0x8d, 0x66, 0x88, 0x8c, 0xa1, 0x45, 0xba, 0x80, 0x04, 0x19, + 0xc9, 0x24, 0x21, 0xc9, 0x52, 0x45, 0xb2, 0x6c, 0x89, 0x71, 0x95, 0x45, 0x44, 0xa5, 0x72, 0x1d, + 0x1a, 0xe2, 0x24, 0xa5, 0x49, 0x0d, 0x4d, 0xea, 0x62, 0x00, 0x27, 0x6f, 0xc3, 0x76, 0x54, 0x68, + 0x48, 0x93, 0xba, 0x5c, 0x25, 0x1a, 0x46, 0xc3, 0x6b, 0x50, 0x0f, 0x09, 0xd6, 0x40, 0x8b, 0x9a, + 0xa9, 0xc0, 0x35, 0x84, 0x9a, 0x72, 0x31, 0xb3, 0x52, 0xba, 0x03, 0x15, 0xd7, 0xf4, 0xb8, 0xaf, + 0x0a, 0x84, 0x20, 0x7f, 0xbd, 0x36, 0x3d, 0x51, 0xa3, 0xaa, 0x7a, 0x49, 0x9a, 0xe8, 0xc7, 0xb0, + 0x99, 0x18, 0x17, 0xd7, 0x8f, 0x3b, 0xdc, 0x5c, 0xa8, 0xd2, 0x45, 0x76, 0xc2, 0x9f, 0x29, 0x45, + 0x3f, 0xa3, 0x3f, 0x81, 0x46, 0xf8, 0x0d, 0xc5, 0x51, 0xbb, 0xab, 0xf1, 0x28, 0x28, 0x7b, 0x37, + 0x8c, 0xaa, 0xbb, 0x1a, 0xbf, 0x94, 0x95, 0xaf, 0xeb, 0x7c, 0x50, 0x55, 0x9b, 0x66, 0xc8, 0x8e, + 0xfe, 0x14, 0xea, 0x41, 0x55, 0x95, 0x2f, 0xcd, 0xf9, 0xd4, 0xfa, 0xef, 0x45, 0xa8, 0x4a, 0xf8, + 0x65, 0x54, 0xda, 0xff, 0xc3, 0x12, 0x74, 0x45, 0x47, 0x62, 0xd3, 0x28, 0xdc, 0x0a, 0x5f, 0x77, + 0x52, 0x74, 0x78, 0x76, 0xe1, 0x52, 0xa3, 0x81, 0x56, 0xa2, 0x49, 0x6e, 0xc2, 0x86, 0x94, 0xf8, + 0xdc, 0x63, 0x76, 0x10, 0xfa, 0x4d, 0x1c, 0x7b, 0x83, 0x43, 0xe2, 0x93, 0x4a, 0x13, 0x66, 0x73, + 0x15, 0x4b, 0x75, 0x1c, 0x18, 0xda, 0x5c, 0xbf, 0x0e, 0x65, 0x5c, 0x07, 0xa0, 0xfa, 0xe6, 0xcc, + 0x18, 0xbe, 0xfa, 0xae, 0x55, 0x20, 0x35, 0xd0, 0x86, 0xaf, 0xce, 0x5a, 0xc5, 0xa3, 0x8f, 0x15, + 0xd8, 0x3e, 0xe9, 0x3f, 0x1b, 0x9e, 0xb8, 0xee, 0x82, 0x4d, 0x4c, 0xcc, 0x31, 0x3d, 0x28, 0x63, + 0x16, 0xcd, 0x78, 0xcc, 0x76, 0xb2, 0xca, 0x39, 0x72, 0x04, 0x15, 0x4c, 0xa6, 0x24, 0xeb, 0x4d, + 0xdb, 0xc9, 0xac, 0xea, 0xc4, 0x8f, 0xc8, 0x74, 0x7b, 0xf9, 0x69, 0xdb, 0xc9, 0x2a, 0xed, 0xc8, + 0xb7, 0xd0, 0x88, 0xd2, 0x60, 0xde, 0x03, 0xb7, 0x93, 0x5b, 0xe4, 0x09, 0x7d, 0x94, 0x1e, 0xf3, + 0x9e, 0xb9, 0x9d, 0xdc, 0x4a, 0x8f, 0x3c, 0x86, 0x5a, 0x90, 0xb9, 0xb2, 0x1f, 0xbb, 0x9d, 0x9c, + 0x62, 0x4f, 0x1c, 0x8f, 0xcc, 0x27, 0x59, 0x6f, 0xd8, 0x4e, 0x66, 0xfd, 0x46, 0x1e, 0x41, 0x55, + 0xa1, 0x34, 0xf3, 0x9d, 0xdc, 0xc9, 0xae, 0x12, 0xc5, 0x26, 0xa3, 0xe7, 0x4e, 0xde, 0x03, 0xb8, + 0x93, 0x5b, 0xff, 0x91, 0x13, 0x80, 0xd8, 0x3b, 0x27, 0xf7, 0x19, 0xdc, 0xc9, 0xaf, 0x02, 0x89, + 0xb8, 0x3b, 0xe1, 0x4b, 0x23, 0xfb, 0x31, 0xdc, 0xc9, 0x2b, 0x04, 0xc7, 0x55, 0xfc, 0x07, 0xcb, + 0xc3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x39, 0xd6, 0x39, 0x74, 0xab, 0x11, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index d40e8885..6538ba2d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -66,6 +66,8 @@ message RequestInitChain{ message RequestBeginBlock{ bytes hash = 1; Header header = 2; + repeated int32 absent_validators = 3; + repeated Evidence byzantine_validators = 4; } message RequestEndBlock{ @@ -187,6 +189,11 @@ message Validator { int64 power = 2; } +message Evidence { + bytes pub_key = 1; + int64 height = 2; +} + //---------------------------------------- // Abstract types From fc90b2de1c3b257291ccdfef346614aa2a08ac54 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 1 Dec 2017 11:33:07 -0500 Subject: [PATCH 382/545] fix dummy test --- example/dummy/dummy_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index ec4d2e33..bfe9ef7a 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -95,7 +95,7 @@ func TestPersistentDummyInfo(t *testing.T) { header := &types.Header{ Height: int64(height), } - dummy.BeginBlock(types.RequestBeginBlock{hash, header}) + dummy.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil}) dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() @@ -179,7 +179,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ Height: height, } - dummy.BeginBlock(types.RequestBeginBlock{hash, header}) + dummy.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil}) for _, tx := range txs { if r := dummy.DeliverTx(tx); r.IsErr() { t.Fatal(r) From 3890a2058f723c2a6b106e6e65d89666bb9691c8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 2 Dec 2017 01:48:37 -0500 Subject: [PATCH 383/545] types: IsOK() --- types/result.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/types/result.go b/types/result.go index 3f3fdd82..cb2fb7a3 100644 --- a/types/result.go +++ b/types/result.go @@ -8,6 +8,11 @@ const ( CodeTypeOK uint32 = 0 ) +// IsOK returns true if Code is OK. +func (r ResponseCheckTx) IsOK() bool { + return r.Code == CodeTypeOK +} + // IsErr returns true if Code is something other than OK. func (r ResponseCheckTx) IsErr() bool { return r.Code != CodeTypeOK @@ -18,6 +23,11 @@ func (r ResponseCheckTx) Error() string { return fmtError(r.Code, r.Log) } +// IsOK returns true if Code is OK. +func (r ResponseDeliverTx) IsOK() bool { + return r.Code == CodeTypeOK +} + // IsErr returns true if Code is something other than OK. func (r ResponseDeliverTx) IsErr() bool { return r.Code != CodeTypeOK @@ -28,6 +38,11 @@ func (r ResponseDeliverTx) Error() string { return fmtError(r.Code, r.Log) } +// IsOK returns true if Code is OK. +func (r ResponseCommit) IsOK() bool { + return r.Code == CodeTypeOK +} + // IsErr returns true if Code is something other than OK. func (r ResponseCommit) IsErr() bool { return r.Code != CodeTypeOK @@ -38,6 +53,11 @@ func (r ResponseCommit) Error() string { return fmtError(r.Code, r.Log) } +// IsOK returns true if Code is OK. +func (r ResponseQuery) IsOK() bool { + return r.Code == CodeTypeOK +} + // IsErr returns true if Code is something other than OK. func (r ResponseQuery) IsErr() bool { return r.Code != CodeTypeOK From 82d56571b54f95f2015a33969382b56d2a059ff5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 2 Dec 2017 01:48:46 -0500 Subject: [PATCH 384/545] types: int32 with gogo int --- types/types.pb.go | 224 +++++++++++++++++++++------------------------- types/types.proto | 6 +- 2 files changed, 105 insertions(+), 125 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index 02d63e61..ec42f252 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -647,7 +647,7 @@ func (m *RequestInitChain) GetValidators() []*Validator { type RequestBeginBlock struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` - AbsentValidators []int32 `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators" json:"absent_validators,omitempty"` + AbsentValidators []int `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators,customtype=int" json:"absent_validators"` ByzantineValidators []*Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators,omitempty"` } @@ -670,13 +670,6 @@ func (m *RequestBeginBlock) GetHeader() *Header { return nil } -func (m *RequestBeginBlock) GetAbsentValidators() []int32 { - if m != nil { - return m.AbsentValidators - } - return nil -} - func (m *RequestBeginBlock) GetByzantineValidators() []*Evidence { if m != nil { return m.ByzantineValidators @@ -1405,7 +1398,7 @@ type Header struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` Time int64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` - NumTxs int64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` + NumTxs int `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3,customtype=int" json:"num_txs"` LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` @@ -1439,13 +1432,6 @@ func (m *Header) GetTime() int64 { return 0 } -func (m *Header) GetNumTxs() int64 { - if m != nil { - return m.NumTxs - } - return 0 -} - func (m *Header) GetLastBlockId() *BlockID { if m != nil { return m.LastBlockId @@ -1506,7 +1492,7 @@ func (m *BlockID) GetParts() *PartSetHeader { } type PartSetHeader struct { - Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Total int `protobuf:"varint,1,opt,name=total,proto3,customtype=int" json:"total"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` } @@ -1515,13 +1501,6 @@ func (m *PartSetHeader) String() string { return proto.CompactTextStr func (*PartSetHeader) ProtoMessage() {} func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } -func (m *PartSetHeader) GetTotal() int64 { - if m != nil { - return m.Total - } - return 0 -} - func (m *PartSetHeader) GetHash() []byte { if m != nil { return m.Hash @@ -2057,102 +2036,103 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1551 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0xcb, 0x8e, 0x13, 0x47, - 0x17, 0xc7, 0x6d, 0xb7, 0xaf, 0xc7, 0x73, 0xf1, 0xd4, 0xcc, 0x07, 0xc6, 0x2c, 0x18, 0x5a, 0xe2, - 0xc3, 0xc3, 0x65, 0xcc, 0x37, 0x88, 0x4f, 0x0c, 0x44, 0x91, 0xc6, 0x0c, 0xc4, 0x16, 0x12, 0x21, - 0xcd, 0x88, 0xad, 0xd5, 0x76, 0x97, 0xed, 0x12, 0x76, 0x77, 0xd3, 0x5d, 0x1e, 0x3c, 0x51, 0x1e, - 0x81, 0x7d, 0xd6, 0xc9, 0x26, 0x52, 0x5e, 0x20, 0xcb, 0xec, 0xa2, 0x3c, 0x43, 0x16, 0x3c, 0x4b, - 0x54, 0xa7, 0xaa, 0xaf, 0xd3, 0xcd, 0x82, 0x05, 0x9b, 0x51, 0x5d, 0xce, 0xbf, 0x7c, 0xaa, 0xfa, - 0xd4, 0xef, 0x9c, 0x1a, 0xd8, 0xe1, 0x17, 0x2e, 0xf5, 0x7b, 0xf8, 0xf7, 0xd0, 0xf5, 0x1c, 0xee, - 0x90, 0x0a, 0x76, 0x3a, 0xf7, 0x67, 0x8c, 0xcf, 0x57, 0xe3, 0xc3, 0x89, 0xb3, 0xec, 0xcd, 0x9c, - 0x99, 0xd3, 0xc3, 0xd9, 0xf1, 0x6a, 0x8a, 0x3d, 0xec, 0x60, 0x4b, 0xaa, 0xf4, 0xbf, 0xca, 0x50, - 0x33, 0xe8, 0xfb, 0x15, 0xf5, 0x39, 0xe9, 0x42, 0x99, 0x4e, 0xe6, 0x4e, 0xbb, 0xb8, 0x5f, 0xec, - 0x36, 0x8f, 0xc8, 0xa1, 0x5c, 0x5d, 0xcd, 0x3e, 0x9f, 0xcc, 0x9d, 0x41, 0xc1, 0x40, 0x0b, 0x72, - 0x17, 0x2a, 0xd3, 0xc5, 0xca, 0x9f, 0xb7, 0x4b, 0x68, 0xba, 0x9b, 0x34, 0x7d, 0x21, 0xa6, 0x06, - 0x05, 0x43, 0xda, 0x88, 0x65, 0x99, 0x3d, 0x75, 0xda, 0x5a, 0xd6, 0xb2, 0x43, 0x7b, 0x8a, 0xcb, - 0x0a, 0x0b, 0xf2, 0x18, 0xc0, 0xa7, 0x7c, 0xe4, 0xb8, 0x9c, 0x39, 0x76, 0xbb, 0x8c, 0xf6, 0x57, - 0x93, 0xf6, 0x6f, 0x28, 0xff, 0x1e, 0xa7, 0x07, 0x05, 0xa3, 0xe1, 0x07, 0x1d, 0xa1, 0xb4, 0xe8, - 0x82, 0x9d, 0x53, 0x6f, 0xc4, 0xd7, 0xed, 0x4a, 0x96, 0xf2, 0x54, 0xce, 0x9f, 0xad, 0x85, 0xd2, - 0x0a, 0x3a, 0xe4, 0x08, 0xea, 0x93, 0x39, 0x9d, 0xbc, 0x13, 0xba, 0x2a, 0xea, 0xfe, 0x93, 0xd4, - 0x3d, 0x13, 0xb3, 0xa8, 0xaa, 0x4d, 0x64, 0x93, 0x1c, 0x42, 0x75, 0xe2, 0x2c, 0x97, 0x8c, 0xb7, - 0x6b, 0xa8, 0xd8, 0x4b, 0x29, 0x70, 0x6e, 0x50, 0x30, 0x94, 0x95, 0x38, 0xae, 0xf7, 0x2b, 0xea, - 0x5d, 0xb4, 0xeb, 0x59, 0xc7, 0xf5, 0x83, 0x98, 0x12, 0xc7, 0x85, 0x36, 0x62, 0x2b, 0xcc, 0x66, - 0x7c, 0x34, 0x99, 0x9b, 0xcc, 0x6e, 0x37, 0xb2, 0xb6, 0x32, 0xb4, 0x19, 0x7f, 0x26, 0xa6, 0xc5, - 0x56, 0x58, 0xd0, 0x21, 0x4f, 0xa1, 0x39, 0xa6, 0x33, 0x66, 0x8f, 0xc6, 0x0b, 0x67, 0xf2, 0xae, - 0x0d, 0x28, 0x6d, 0x27, 0xa5, 0x7d, 0x61, 0xd0, 0x17, 0xf3, 0x83, 0x82, 0x01, 0xe3, 0xb0, 0x47, - 0x1e, 0x41, 0x83, 0xda, 0x96, 0x92, 0x36, 0x51, 0x7a, 0x25, 0x15, 0x01, 0xb6, 0x15, 0x08, 0xeb, - 0x54, 0xb5, 0xfb, 0x35, 0xa8, 0x9c, 0x9b, 0x8b, 0x15, 0xd5, 0x6f, 0x43, 0x33, 0x16, 0x29, 0xa4, - 0x0d, 0xb5, 0x25, 0xf5, 0x7d, 0x73, 0x46, 0x31, 0x9c, 0x1a, 0x46, 0xd0, 0xd5, 0xb7, 0x60, 0x23, - 0x1e, 0x27, 0x31, 0xa1, 0x88, 0x05, 0x21, 0x3c, 0xa7, 0x9e, 0x2f, 0x02, 0x40, 0x09, 0x55, 0x57, - 0x7f, 0x02, 0xad, 0x74, 0x10, 0x90, 0x16, 0x68, 0xef, 0xe8, 0x85, 0xb2, 0x14, 0x4d, 0xb2, 0xa7, - 0x1c, 0xc2, 0xd0, 0x6c, 0x18, 0xca, 0x3b, 0x3d, 0xd4, 0x86, 0x61, 0x40, 0xb6, 0xa0, 0xc4, 0xd7, - 0x28, 0xdd, 0x30, 0x4a, 0x7c, 0xad, 0xef, 0xc3, 0x56, 0xf2, 0x93, 0x5f, 0xb2, 0xb0, 0x42, 0xd7, - 0xf1, 0x9b, 0x11, 0x02, 0x65, 0xcb, 0xe4, 0xa6, 0xb2, 0xc0, 0xb6, 0x18, 0x73, 0x4d, 0x3e, 0x57, - 0x3f, 0x8f, 0x6d, 0x72, 0x05, 0xaa, 0x73, 0xca, 0x66, 0x73, 0x8e, 0x77, 0x40, 0x33, 0x54, 0x4f, - 0xf8, 0xea, 0x7a, 0xce, 0x39, 0xc5, 0x50, 0xaf, 0x1b, 0xb2, 0xa3, 0x6f, 0xc3, 0x66, 0x22, 0x90, - 0xf4, 0xd3, 0xd0, 0xf9, 0xf0, 0xc3, 0x93, 0x07, 0x00, 0xe7, 0xe6, 0x82, 0x59, 0x26, 0x77, 0x3c, - 0xbf, 0x5d, 0xdc, 0xd7, 0xba, 0xcd, 0xa3, 0x96, 0xfa, 0x5e, 0x6f, 0x83, 0x09, 0x23, 0x66, 0xa3, - 0xff, 0x59, 0x84, 0x9d, 0x4b, 0x41, 0x20, 0xdc, 0x9d, 0x9b, 0xfe, 0x3c, 0xd8, 0x82, 0x68, 0x93, - 0x5b, 0xc2, 0x5d, 0xd3, 0xa2, 0x9e, 0xba, 0xde, 0x9b, 0x6a, 0xdd, 0x01, 0x0e, 0x1a, 0x6a, 0x92, - 0xdc, 0x85, 0x1d, 0x73, 0xec, 0x53, 0x9b, 0x8f, 0x62, 0x9e, 0x68, 0xfb, 0x5a, 0xb7, 0x62, 0xb4, - 0xe4, 0x44, 0xe8, 0x88, 0x4f, 0xfa, 0xb0, 0x37, 0xbe, 0xf8, 0xd1, 0xb4, 0x39, 0xb3, 0x69, 0xdc, - 0xbe, 0x8c, 0x9e, 0x6f, 0xab, 0x5f, 0x78, 0x7e, 0xce, 0x2c, 0x6a, 0x4f, 0xa8, 0xb1, 0x1b, 0x1a, - 0x47, 0x6b, 0xe8, 0x07, 0xb0, 0x9d, 0x0a, 0xc5, 0xd8, 0xc9, 0x16, 0xe3, 0x27, 0xab, 0x7f, 0xac, - 0x40, 0xdd, 0xa0, 0xbe, 0xeb, 0xd8, 0x3e, 0x25, 0x8f, 0xa1, 0x41, 0xd7, 0x13, 0x2a, 0xa9, 0x52, - 0x4c, 0xdd, 0x0a, 0x69, 0xf3, 0x3c, 0x98, 0x17, 0x37, 0x2a, 0x34, 0x26, 0x07, 0x8a, 0x88, 0x69, - 0xcc, 0x29, 0x51, 0x1c, 0x89, 0xf7, 0x02, 0x24, 0x6a, 0x29, 0x24, 0x48, 0xdb, 0x14, 0x13, 0x0f, - 0x14, 0x13, 0xcb, 0x99, 0x0b, 0x27, 0xa0, 0x78, 0x9c, 0x80, 0x62, 0x25, 0xd3, 0xfd, 0x1c, 0x2a, - 0x1e, 0x27, 0xa8, 0x58, 0xcd, 0x94, 0xe6, 0x60, 0xf1, 0x61, 0x0c, 0x8b, 0xb5, 0x14, 0x0d, 0xa4, - 0x30, 0x83, 0x8b, 0xbd, 0x90, 0x8b, 0xf5, 0x14, 0x49, 0x95, 0x24, 0x0d, 0xc6, 0x7b, 0x01, 0x18, - 0x1b, 0x99, 0x87, 0x96, 0x22, 0xe3, 0x71, 0x82, 0x8c, 0x90, 0xb9, 0x9d, 0x1c, 0x34, 0x7e, 0x93, - 0x44, 0xa3, 0xe4, 0xdb, 0xb5, 0x94, 0x36, 0x97, 0x8d, 0xff, 0x8f, 0xb3, 0x71, 0x23, 0x45, 0x64, - 0x15, 0x0b, 0x9f, 0x85, 0xe3, 0x81, 0xb8, 0x7a, 0xa9, 0x48, 0x13, 0xb7, 0x9f, 0x7a, 0x9e, 0xe3, - 0x29, 0x7a, 0xc9, 0x8e, 0xde, 0x15, 0x8c, 0x89, 0xe2, 0xeb, 0x33, 0x20, 0x45, 0x4e, 0xc4, 0xa2, - 0x4b, 0xff, 0xb9, 0x18, 0x69, 0x91, 0xa5, 0x71, 0x3e, 0x35, 0x14, 0x9f, 0x62, 0x7c, 0x2d, 0x25, - 0xf8, 0x4a, 0xee, 0xc0, 0xce, 0xc2, 0xf4, 0xb9, 0xdc, 0xe6, 0x28, 0x01, 0xac, 0x6d, 0x31, 0x21, - 0xf7, 0x27, 0xc9, 0x75, 0x1f, 0x76, 0x63, 0xb6, 0xa6, 0xeb, 0x8e, 0x90, 0x22, 0x65, 0xa4, 0x48, - 0x2b, 0xb4, 0x3e, 0x71, 0xdd, 0x81, 0xe9, 0xcf, 0xf5, 0x5b, 0xd1, 0xfe, 0x13, 0xec, 0x5e, 0x38, - 0xb3, 0x80, 0xdd, 0x0b, 0x67, 0xa6, 0xff, 0x5a, 0x8c, 0xec, 0x22, 0x4e, 0x13, 0x28, 0x4f, 0x1c, - 0x4b, 0x6e, 0x7f, 0xd3, 0xc0, 0x36, 0x39, 0x55, 0x3b, 0x13, 0x5b, 0xd8, 0xe8, 0x3f, 0xf8, 0xfb, - 0xd3, 0x8d, 0xc2, 0x3f, 0x9f, 0x6e, 0x74, 0x63, 0xb5, 0x0f, 0xa7, 0xb6, 0x45, 0xbd, 0x25, 0xb3, - 0x79, 0x6f, 0xe6, 0xdc, 0xff, 0xc0, 0x3c, 0xda, 0x13, 0x8a, 0xc3, 0xfe, 0x05, 0xa7, 0xbe, 0x3a, - 0x0b, 0xe5, 0x81, 0x16, 0x7a, 0x40, 0x6e, 0x42, 0x99, 0x9b, 0xb3, 0x00, 0x4b, 0x01, 0xf8, 0x5e, - 0xbe, 0x7d, 0x6d, 0x32, 0xcf, 0xc0, 0x29, 0xfd, 0x97, 0xa2, 0xc0, 0x50, 0xe2, 0x0e, 0x7c, 0x55, - 0x17, 0x5b, 0xa0, 0xcd, 0x4c, 0x1f, 0x8f, 0x5a, 0x33, 0x44, 0x53, 0x8c, 0x4c, 0x29, 0x45, 0x34, - 0x68, 0x86, 0x68, 0xea, 0x7f, 0x94, 0xa2, 0xd8, 0x08, 0x53, 0xd5, 0x25, 0x0f, 0xf7, 0xa0, 0xc2, - 0x6c, 0x8b, 0xae, 0xd1, 0x45, 0xcd, 0x90, 0x1d, 0xd2, 0x97, 0x29, 0x55, 0xfb, 0x42, 0xb7, 0x31, - 0x09, 0xbf, 0x08, 0x92, 0x70, 0xf9, 0x0b, 0x57, 0x91, 0x72, 0xb1, 0x8e, 0xeb, 0x39, 0xce, 0x14, - 0xf7, 0xf6, 0x45, 0xeb, 0xa0, 0x3c, 0x96, 0x26, 0xaa, 0x89, 0x04, 0xac, 0x4e, 0xb7, 0x16, 0x85, - 0xe0, 0x4f, 0xa2, 0x08, 0x88, 0xd3, 0xea, 0x6b, 0x7e, 0x5b, 0x7d, 0x37, 0x8a, 0xff, 0x10, 0x64, - 0xfa, 0x1e, 0x90, 0xcb, 0x84, 0x92, 0xd5, 0x50, 0x92, 0x3d, 0xe4, 0xbf, 0x50, 0xb1, 0xd8, 0x74, - 0x9a, 0x5f, 0x0f, 0xc8, 0x69, 0xfd, 0xb7, 0x12, 0x54, 0x65, 0x32, 0x27, 0xd7, 0x04, 0xe7, 0x4d, - 0x66, 0x8f, 0x98, 0x15, 0xf0, 0x05, 0xfb, 0x43, 0x2b, 0x76, 0x68, 0xa5, 0xc4, 0xa1, 0x11, 0x28, - 0x73, 0xb6, 0xa4, 0x0a, 0x0d, 0xd8, 0x26, 0x57, 0xa1, 0x66, 0xaf, 0x96, 0x23, 0xbe, 0x0e, 0x02, - 0xb3, 0x6a, 0xaf, 0x96, 0x67, 0x6b, 0x9f, 0x1c, 0xc1, 0x66, 0x0c, 0x14, 0xcc, 0x52, 0x09, 0x6c, - 0x4b, 0xb9, 0x86, 0x7e, 0x0f, 0x4f, 0x8d, 0x66, 0x88, 0x8c, 0xa1, 0x45, 0xba, 0x80, 0x04, 0x19, - 0xc9, 0x24, 0x21, 0xc9, 0x52, 0x45, 0xb2, 0x6c, 0x89, 0x71, 0x95, 0x45, 0x44, 0xa5, 0x72, 0x1d, - 0x1a, 0xe2, 0x24, 0xa5, 0x49, 0x0d, 0x4d, 0xea, 0x62, 0x00, 0x27, 0x6f, 0xc3, 0x76, 0x54, 0x68, - 0x48, 0x93, 0xba, 0x5c, 0x25, 0x1a, 0x46, 0xc3, 0x6b, 0x50, 0x0f, 0x09, 0xd6, 0x40, 0x8b, 0x9a, - 0xa9, 0xc0, 0x35, 0x84, 0x9a, 0x72, 0x31, 0xb3, 0x52, 0xba, 0x03, 0x15, 0xd7, 0xf4, 0xb8, 0xaf, - 0x0a, 0x84, 0x20, 0x7f, 0xbd, 0x36, 0x3d, 0x51, 0xa3, 0xaa, 0x7a, 0x49, 0x9a, 0xe8, 0xc7, 0xb0, - 0x99, 0x18, 0x17, 0xd7, 0x8f, 0x3b, 0xdc, 0x5c, 0xa8, 0xd2, 0x45, 0x76, 0xc2, 0x9f, 0x29, 0x45, - 0x3f, 0xa3, 0x3f, 0x81, 0x46, 0xf8, 0x0d, 0xc5, 0x51, 0xbb, 0xab, 0xf1, 0x28, 0x28, 0x7b, 0x37, - 0x8c, 0xaa, 0xbb, 0x1a, 0xbf, 0x94, 0x95, 0xaf, 0xeb, 0x7c, 0x50, 0x55, 0x9b, 0x66, 0xc8, 0x8e, - 0xfe, 0x14, 0xea, 0x41, 0x55, 0x95, 0x2f, 0xcd, 0xf9, 0xd4, 0xfa, 0xef, 0x45, 0xa8, 0x4a, 0xf8, - 0x65, 0x54, 0xda, 0xff, 0xc3, 0x12, 0x74, 0x45, 0x47, 0x62, 0xd3, 0x28, 0xdc, 0x0a, 0x5f, 0x77, - 0x52, 0x74, 0x78, 0x76, 0xe1, 0x52, 0xa3, 0x81, 0x56, 0xa2, 0x49, 0x6e, 0xc2, 0x86, 0x94, 0xf8, - 0xdc, 0x63, 0x76, 0x10, 0xfa, 0x4d, 0x1c, 0x7b, 0x83, 0x43, 0xe2, 0x93, 0x4a, 0x13, 0x66, 0x73, - 0x15, 0x4b, 0x75, 0x1c, 0x18, 0xda, 0x5c, 0xbf, 0x0e, 0x65, 0x5c, 0x07, 0xa0, 0xfa, 0xe6, 0xcc, - 0x18, 0xbe, 0xfa, 0xae, 0x55, 0x20, 0x35, 0xd0, 0x86, 0xaf, 0xce, 0x5a, 0xc5, 0xa3, 0x8f, 0x15, - 0xd8, 0x3e, 0xe9, 0x3f, 0x1b, 0x9e, 0xb8, 0xee, 0x82, 0x4d, 0x4c, 0xcc, 0x31, 0x3d, 0x28, 0x63, - 0x16, 0xcd, 0x78, 0xcc, 0x76, 0xb2, 0xca, 0x39, 0x72, 0x04, 0x15, 0x4c, 0xa6, 0x24, 0xeb, 0x4d, - 0xdb, 0xc9, 0xac, 0xea, 0xc4, 0x8f, 0xc8, 0x74, 0x7b, 0xf9, 0x69, 0xdb, 0xc9, 0x2a, 0xed, 0xc8, - 0xb7, 0xd0, 0x88, 0xd2, 0x60, 0xde, 0x03, 0xb7, 0x93, 0x5b, 0xe4, 0x09, 0x7d, 0x94, 0x1e, 0xf3, - 0x9e, 0xb9, 0x9d, 0xdc, 0x4a, 0x8f, 0x3c, 0x86, 0x5a, 0x90, 0xb9, 0xb2, 0x1f, 0xbb, 0x9d, 0x9c, - 0x62, 0x4f, 0x1c, 0x8f, 0xcc, 0x27, 0x59, 0x6f, 0xd8, 0x4e, 0x66, 0xfd, 0x46, 0x1e, 0x41, 0x55, - 0xa1, 0x34, 0xf3, 0x9d, 0xdc, 0xc9, 0xae, 0x12, 0xc5, 0x26, 0xa3, 0xe7, 0x4e, 0xde, 0x03, 0xb8, - 0x93, 0x5b, 0xff, 0x91, 0x13, 0x80, 0xd8, 0x3b, 0x27, 0xf7, 0x19, 0xdc, 0xc9, 0xaf, 0x02, 0x89, - 0xb8, 0x3b, 0xe1, 0x4b, 0x23, 0xfb, 0x31, 0xdc, 0xc9, 0x2b, 0x04, 0xc7, 0x55, 0xfc, 0x07, 0xcb, - 0xc3, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x39, 0xd6, 0x39, 0x74, 0xab, 0x11, 0x00, 0x00, + // 1565 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0x4d, 0x6f, 0xdb, 0x46, + 0x13, 0xc7, 0x2d, 0x51, 0x12, 0xa5, 0x91, 0x5f, 0xe4, 0xb5, 0x9f, 0x44, 0x51, 0x0e, 0x71, 0x88, + 0x27, 0x4f, 0xec, 0x3c, 0x89, 0x95, 0x3a, 0x48, 0xe1, 0x24, 0x45, 0x01, 0x2b, 0x4e, 0x2a, 0x21, + 0x40, 0x9a, 0x32, 0x46, 0xae, 0x02, 0x25, 0xae, 0xa4, 0x45, 0x24, 0x92, 0x21, 0x57, 0x8e, 0x5c, + 0xf4, 0x23, 0xe4, 0xde, 0x73, 0x7b, 0xec, 0xb9, 0x40, 0xbf, 0x41, 0xd1, 0x43, 0x3f, 0x41, 0x0f, + 0xf9, 0x2c, 0xc5, 0xce, 0x2e, 0x5f, 0x4d, 0xe6, 0x90, 0x43, 0x2e, 0xc6, 0x2e, 0x67, 0xfe, 0xab, + 0xd9, 0xe5, 0xf0, 0x37, 0xb3, 0x86, 0x6d, 0x7e, 0xe1, 0xd1, 0xa0, 0x8b, 0x7f, 0x0f, 0x3d, 0xdf, + 0xe5, 0x2e, 0xa9, 0xe2, 0xa4, 0x73, 0x6f, 0xca, 0xf8, 0x6c, 0x39, 0x3a, 0x1c, 0xbb, 0x8b, 0xee, + 0xd4, 0x9d, 0xba, 0x5d, 0xb4, 0x8e, 0x96, 0x13, 0x9c, 0xe1, 0x04, 0x47, 0x52, 0x65, 0xfc, 0x59, + 0x01, 0xdd, 0xa4, 0xef, 0x96, 0x34, 0xe0, 0x64, 0x1f, 0x2a, 0x74, 0x3c, 0x73, 0xdb, 0xa5, 0xbd, + 0xd2, 0x7e, 0xf3, 0x88, 0x1c, 0xca, 0xd5, 0x95, 0xf5, 0xd9, 0x78, 0xe6, 0xf6, 0xd7, 0x4c, 0xf4, + 0x20, 0xff, 0x87, 0xea, 0x64, 0xbe, 0x0c, 0x66, 0xed, 0x32, 0xba, 0xee, 0xa4, 0x5d, 0x9f, 0x0b, + 0x53, 0x7f, 0xcd, 0x94, 0x3e, 0x62, 0x59, 0xe6, 0x4c, 0xdc, 0xb6, 0x96, 0xb7, 0xec, 0xc0, 0x99, + 0xe0, 0xb2, 0xc2, 0x83, 0x1c, 0x03, 0x04, 0x94, 0x0f, 0x5d, 0x8f, 0x33, 0xd7, 0x69, 0x57, 0xd0, + 0xff, 0x6a, 0xda, 0xff, 0x35, 0xe5, 0xdf, 0xa3, 0xb9, 0xbf, 0x66, 0x36, 0x82, 0x70, 0x22, 0x94, + 0x36, 0x9d, 0xb3, 0x73, 0xea, 0x0f, 0xf9, 0xaa, 0x5d, 0xcd, 0x53, 0x9e, 0x4a, 0xfb, 0xd9, 0x4a, + 0x28, 0xed, 0x70, 0x42, 0x8e, 0xa0, 0x3e, 0x9e, 0xd1, 0xf1, 0x5b, 0xa1, 0xab, 0xa1, 0xee, 0x3f, + 0x69, 0xdd, 0x53, 0x61, 0x45, 0x95, 0x3e, 0x96, 0x43, 0x72, 0x08, 0xb5, 0xb1, 0xbb, 0x58, 0x30, + 0xde, 0xd6, 0x51, 0xb1, 0x9b, 0x51, 0xa0, 0xad, 0xbf, 0x66, 0x2a, 0x2f, 0x71, 0x5c, 0xef, 0x96, + 0xd4, 0xbf, 0x68, 0xd7, 0xf3, 0x8e, 0xeb, 0x07, 0x61, 0x12, 0xc7, 0x85, 0x3e, 0x62, 0x2b, 0xcc, + 0x61, 0x7c, 0x38, 0x9e, 0x59, 0xcc, 0x69, 0x37, 0xf2, 0xb6, 0x32, 0x70, 0x18, 0x7f, 0x2a, 0xcc, + 0x62, 0x2b, 0x2c, 0x9c, 0x90, 0x27, 0xd0, 0x1c, 0xd1, 0x29, 0x73, 0x86, 0xa3, 0xb9, 0x3b, 0x7e, + 0xdb, 0x06, 0x94, 0xb6, 0xd3, 0xd2, 0x9e, 0x70, 0xe8, 0x09, 0x7b, 0x7f, 0xcd, 0x84, 0x51, 0x34, + 0x23, 0x0f, 0xa1, 0x41, 0x1d, 0x5b, 0x49, 0x9b, 0x28, 0xbd, 0x92, 0xc9, 0x00, 0xc7, 0x0e, 0x85, + 0x75, 0xaa, 0xc6, 0x3d, 0x1d, 0xaa, 0xe7, 0xd6, 0x7c, 0x49, 0x8d, 0xdb, 0xd0, 0x4c, 0x64, 0x0a, + 0x69, 0x83, 0xbe, 0xa0, 0x41, 0x60, 0x4d, 0x29, 0xa6, 0x53, 0xc3, 0x0c, 0xa7, 0xc6, 0x26, 0xac, + 0x27, 0xf3, 0x24, 0x21, 0x14, 0xb9, 0x20, 0x84, 0xe7, 0xd4, 0x0f, 0x44, 0x02, 0x28, 0xa1, 0x9a, + 0x1a, 0x8f, 0xa1, 0x95, 0x4d, 0x02, 0xd2, 0x02, 0xed, 0x2d, 0xbd, 0x50, 0x9e, 0x62, 0x48, 0x76, + 0x55, 0x40, 0x98, 0x9a, 0x0d, 0x53, 0x45, 0x67, 0x44, 0xda, 0x28, 0x0d, 0xc8, 0x26, 0x94, 0xf9, + 0x0a, 0xa5, 0xeb, 0x66, 0x99, 0xaf, 0x8c, 0x3d, 0xd8, 0x4c, 0xbf, 0xf2, 0x4b, 0x1e, 0x76, 0x14, + 0x3a, 0xbe, 0x33, 0x42, 0xa0, 0x62, 0x5b, 0xdc, 0x52, 0x1e, 0x38, 0x16, 0xcf, 0x3c, 0x8b, 0xcf, + 0xd4, 0xcf, 0xe3, 0x98, 0x5c, 0x81, 0xda, 0x8c, 0xb2, 0xe9, 0x8c, 0xe3, 0x37, 0xa0, 0x99, 0x6a, + 0x26, 0x62, 0xf5, 0x7c, 0xf7, 0x9c, 0x62, 0xaa, 0xd7, 0x4d, 0x39, 0x31, 0xb6, 0x60, 0x23, 0x95, + 0x48, 0xc6, 0x69, 0x14, 0x7c, 0xf4, 0xe2, 0xc9, 0x7d, 0x80, 0x73, 0x6b, 0xce, 0x6c, 0x8b, 0xbb, + 0x7e, 0xd0, 0x2e, 0xed, 0x69, 0xfb, 0xcd, 0xa3, 0x96, 0x7a, 0x5f, 0x6f, 0x42, 0x83, 0x99, 0xf0, + 0x31, 0xfe, 0x2e, 0xc1, 0xf6, 0xa5, 0x24, 0x10, 0xe1, 0xce, 0xac, 0x60, 0x16, 0x6e, 0x41, 0x8c, + 0xc9, 0x2d, 0x11, 0xae, 0x65, 0x53, 0x5f, 0x7d, 0xde, 0x1b, 0x6a, 0xdd, 0x3e, 0x3e, 0x34, 0x95, + 0x91, 0x1c, 0xc3, 0xb6, 0x35, 0x0a, 0xa8, 0xc3, 0x87, 0x89, 0x48, 0xb4, 0x3d, 0x6d, 0xbf, 0xda, + 0x6b, 0xfe, 0xf5, 0xf1, 0xc6, 0xda, 0x3f, 0x1f, 0x6f, 0x68, 0xcc, 0xe1, 0x66, 0x4b, 0x7a, 0x45, + 0x51, 0x05, 0xa4, 0x07, 0xbb, 0xa3, 0x8b, 0x1f, 0x2d, 0x87, 0x33, 0x87, 0x26, 0xc5, 0x15, 0xdc, + 0xc6, 0x96, 0xfa, 0xb9, 0x67, 0xe7, 0xcc, 0xa6, 0xce, 0x98, 0x9a, 0x3b, 0x91, 0x73, 0xbc, 0x86, + 0x71, 0x00, 0x5b, 0x99, 0xbc, 0x4c, 0x1c, 0x73, 0x29, 0x79, 0xcc, 0xc6, 0x87, 0x2a, 0xd4, 0x4d, + 0x1a, 0x78, 0xae, 0x13, 0x50, 0x72, 0x0c, 0x0d, 0xba, 0x1a, 0x53, 0x89, 0x98, 0x52, 0xe6, 0x13, + 0x91, 0x3e, 0xcf, 0x42, 0xbb, 0xf8, 0xbc, 0x22, 0x67, 0x72, 0xa0, 0xf0, 0x98, 0x65, 0x9e, 0x12, + 0x25, 0xf9, 0x78, 0x37, 0xe4, 0xa3, 0x96, 0xe1, 0x83, 0xf4, 0xcd, 0x00, 0xf2, 0x40, 0x01, 0xb2, + 0x92, 0xbb, 0x70, 0x8a, 0x90, 0x8f, 0x52, 0x84, 0xac, 0xe6, 0x86, 0x5f, 0x80, 0xc8, 0x47, 0x29, + 0x44, 0xd6, 0x72, 0xa5, 0x05, 0x8c, 0x7c, 0x90, 0x60, 0xa4, 0x9e, 0x41, 0x83, 0x14, 0xe6, 0x40, + 0xb2, 0x1b, 0x41, 0xb2, 0x9e, 0xc1, 0xaa, 0x92, 0x64, 0x29, 0x79, 0x37, 0xa4, 0x64, 0x23, 0xf7, + 0xd0, 0x32, 0x98, 0x7c, 0x94, 0xc2, 0x24, 0xe4, 0x6e, 0xa7, 0x80, 0x93, 0xdf, 0xa4, 0x39, 0x29, + 0x61, 0x77, 0x2d, 0xa3, 0x2d, 0x04, 0xe5, 0xd7, 0x49, 0x50, 0xae, 0x67, 0xf0, 0xac, 0x72, 0xe1, + 0x93, 0xa4, 0x3c, 0x10, 0xdf, 0x61, 0x26, 0xd3, 0x04, 0x0a, 0xa8, 0xef, 0xbb, 0xbe, 0x42, 0x99, + 0x9c, 0x18, 0xfb, 0x02, 0x38, 0x71, 0x7e, 0x7d, 0x82, 0xaa, 0x08, 0x8d, 0x44, 0x76, 0x19, 0x3f, + 0x97, 0x62, 0x2d, 0x82, 0x35, 0x09, 0xab, 0x86, 0x82, 0x55, 0x02, 0xb6, 0xe5, 0x14, 0x6c, 0xc9, + 0x1d, 0xd8, 0x9e, 0x5b, 0x01, 0x97, 0xdb, 0x1c, 0xa6, 0xe8, 0xb5, 0x25, 0x0c, 0x72, 0x7f, 0x12, + 0x63, 0xf7, 0x60, 0x27, 0xe1, 0x6b, 0x79, 0xde, 0x10, 0x91, 0x52, 0x41, 0xa4, 0xb4, 0x22, 0xef, + 0x13, 0xcf, 0xeb, 0x5b, 0xc1, 0xcc, 0xb8, 0x15, 0xef, 0x3f, 0x05, 0xf2, 0xb9, 0x3b, 0x0d, 0x41, + 0x3e, 0x77, 0xa7, 0xc6, 0xaf, 0xa5, 0xd8, 0x2f, 0x86, 0x36, 0x81, 0xca, 0xd8, 0xb5, 0xe5, 0xf6, + 0x37, 0x4c, 0x1c, 0x93, 0x53, 0xb5, 0x33, 0xb1, 0x85, 0xf5, 0xde, 0x7d, 0xc5, 0x9e, 0xfd, 0x44, + 0x23, 0xc4, 0xa9, 0x63, 0x53, 0x7f, 0xc1, 0x1c, 0xde, 0x9d, 0xba, 0xf7, 0xde, 0x33, 0x9f, 0x76, + 0x85, 0xe2, 0xb0, 0x77, 0xc1, 0x69, 0xa0, 0xce, 0x42, 0x45, 0xa0, 0x45, 0x11, 0x90, 0x9b, 0x50, + 0xe1, 0xd6, 0x34, 0xc4, 0x52, 0x48, 0xc1, 0x17, 0x6f, 0x5e, 0x59, 0xcc, 0x37, 0xd1, 0x64, 0xfc, + 0x52, 0x12, 0x18, 0x4a, 0x7d, 0x03, 0x5f, 0x34, 0xc4, 0x16, 0x68, 0x53, 0x2b, 0xc0, 0xa3, 0xd6, + 0x4c, 0x31, 0x14, 0x4f, 0x26, 0x94, 0x22, 0x1a, 0x34, 0x53, 0x0c, 0x8d, 0x3f, 0xca, 0x71, 0x6e, + 0x44, 0x75, 0xeb, 0x52, 0x84, 0xbb, 0x50, 0x65, 0x8e, 0x4d, 0x57, 0x18, 0xa2, 0x66, 0xca, 0x09, + 0xe9, 0xc9, 0xfa, 0xaa, 0x7d, 0x66, 0xd8, 0x58, 0x91, 0x9f, 0x87, 0x15, 0xb9, 0xf2, 0x99, 0xab, + 0x48, 0xb9, 0x58, 0xc7, 0xf3, 0x5d, 0x77, 0x82, 0x7b, 0xfb, 0xac, 0x75, 0x50, 0x9e, 0x28, 0x13, + 0xb5, 0x54, 0x35, 0x56, 0xa7, 0xab, 0xc7, 0x29, 0xf8, 0x93, 0xe8, 0x08, 0x92, 0xb4, 0xfa, 0x92, + 0xef, 0xd6, 0xd8, 0x89, 0xf3, 0x3f, 0x02, 0x99, 0xb1, 0x0b, 0xe4, 0x32, 0xa1, 0x64, 0x6b, 0x94, + 0x66, 0x0f, 0xf9, 0x1f, 0x54, 0x6d, 0x36, 0x99, 0x14, 0x37, 0x07, 0xd2, 0x6c, 0xfc, 0x5e, 0x86, + 0x9a, 0xac, 0xec, 0xe4, 0x9a, 0xe0, 0xbc, 0xc5, 0x9c, 0x21, 0xb3, 0x43, 0xbe, 0xe0, 0x7c, 0x60, + 0x27, 0x0e, 0xad, 0x9c, 0x3a, 0x34, 0x02, 0x15, 0xce, 0x16, 0x54, 0xa1, 0x01, 0xc7, 0xe4, 0xbf, + 0xa0, 0x3b, 0xcb, 0xc5, 0x90, 0xaf, 0x64, 0x62, 0x66, 0xda, 0x81, 0x9a, 0xb3, 0x5c, 0x9c, 0xad, + 0x02, 0x72, 0x04, 0x1b, 0x09, 0x6a, 0x30, 0x5b, 0x55, 0xb3, 0x4d, 0x15, 0x27, 0x6e, 0x62, 0x70, + 0x6a, 0x36, 0x23, 0x7e, 0x0c, 0x6c, 0xb2, 0x0f, 0x88, 0x93, 0xa1, 0xac, 0x18, 0x12, 0x33, 0x35, + 0xc4, 0xcc, 0xa6, 0x78, 0xae, 0x4a, 0x8a, 0xe8, 0x61, 0xae, 0x43, 0x43, 0x1c, 0xab, 0x74, 0xd1, + 0xd1, 0xa5, 0x2e, 0x1e, 0xa0, 0xf1, 0x36, 0x6c, 0xc5, 0x5d, 0x87, 0x74, 0xa9, 0xcb, 0x55, 0xe2, + 0xc7, 0xe8, 0x78, 0x0d, 0xea, 0x11, 0xce, 0x1a, 0xe8, 0xa1, 0x5b, 0x8a, 0x62, 0x03, 0xd0, 0x55, + 0x88, 0xb9, 0x3d, 0xd4, 0x1d, 0xa8, 0x7a, 0x96, 0xcf, 0x03, 0xd5, 0x2d, 0x84, 0xc5, 0xec, 0x95, + 0xe5, 0x8b, 0xee, 0x55, 0x75, 0x52, 0xd2, 0xc5, 0x78, 0x0e, 0x1b, 0xa9, 0xe7, 0xe4, 0x26, 0x54, + 0xb9, 0xcb, 0xad, 0x39, 0xae, 0x98, 0x39, 0x3e, 0x69, 0x89, 0x7e, 0xb3, 0x1c, 0xff, 0xa6, 0xf1, + 0x18, 0x1a, 0xd1, 0xdb, 0x25, 0x57, 0x41, 0xf7, 0x96, 0xa3, 0x61, 0xd8, 0x1d, 0xaf, 0x9b, 0x35, + 0x6f, 0x39, 0x7a, 0x21, 0x1b, 0x64, 0xcf, 0x7d, 0xaf, 0x9a, 0x3b, 0xcd, 0x94, 0x13, 0xe3, 0x09, + 0xd4, 0xc3, 0x7e, 0xab, 0x58, 0x5a, 0x90, 0x04, 0xc6, 0x6f, 0x25, 0xa8, 0x49, 0x2c, 0xe6, 0x34, + 0xe4, 0x5f, 0x61, 0xa7, 0xba, 0xa4, 0x43, 0x71, 0x02, 0x28, 0xdc, 0x8c, 0x2e, 0x81, 0x52, 0x74, + 0x78, 0x76, 0xe1, 0x51, 0xb3, 0x81, 0x5e, 0x62, 0x48, 0x6e, 0xc2, 0xba, 0x94, 0x04, 0xdc, 0x67, + 0x4e, 0xf8, 0x51, 0x34, 0xf1, 0xd9, 0x6b, 0x7c, 0x24, 0xde, 0xaf, 0x74, 0x61, 0x0e, 0x57, 0xf8, + 0xab, 0xe3, 0x83, 0x81, 0xc3, 0x8d, 0xeb, 0x50, 0xc1, 0x75, 0x00, 0x6a, 0xaf, 0xcf, 0xcc, 0xc1, + 0xcb, 0xef, 0x5a, 0x6b, 0x44, 0x07, 0x6d, 0xf0, 0xf2, 0xac, 0x55, 0x3a, 0xfa, 0x50, 0x85, 0xad, + 0x93, 0xde, 0xd3, 0xc1, 0x89, 0xe7, 0xcd, 0xd9, 0xd8, 0xc2, 0xea, 0xd3, 0x85, 0x0a, 0xd6, 0xd7, + 0x9c, 0x3b, 0x6f, 0x27, 0xaf, 0xd1, 0x23, 0x47, 0x50, 0xc5, 0x32, 0x4b, 0xf2, 0xae, 0xbe, 0x9d, + 0xdc, 0x7e, 0x4f, 0xfc, 0x88, 0x2c, 0xc4, 0x97, 0x6f, 0xc0, 0x9d, 0xbc, 0xa6, 0x8f, 0x7c, 0x0b, + 0x8d, 0xb8, 0x40, 0x16, 0xdd, 0x83, 0x3b, 0x85, 0xed, 0x9f, 0xd0, 0xc7, 0x85, 0xb3, 0xe8, 0x36, + 0xdc, 0x29, 0xec, 0x01, 0xc9, 0x31, 0xe8, 0x61, 0x4d, 0xcb, 0xbf, 0x13, 0x77, 0x0a, 0xda, 0x40, + 0x71, 0x3c, 0xb2, 0xd2, 0xe4, 0x5d, 0x75, 0x3b, 0xb9, 0x9d, 0x1d, 0x79, 0x08, 0x35, 0x05, 0xd9, + 0xdc, 0xeb, 0x74, 0x27, 0xbf, 0x7f, 0x14, 0x9b, 0x8c, 0x6f, 0x45, 0x45, 0xf7, 0xe4, 0x4e, 0x61, + 0x67, 0x48, 0x4e, 0x00, 0x12, 0xd7, 0xa1, 0xc2, 0xdb, 0x72, 0xa7, 0xb8, 0x3f, 0x24, 0xe2, 0xdb, + 0x89, 0xee, 0x20, 0xf9, 0x77, 0xe6, 0x4e, 0x51, 0x8b, 0x38, 0xaa, 0xe1, 0xff, 0x61, 0x1e, 0xfc, + 0x1b, 0x00, 0x00, 0xff, 0xff, 0x93, 0x8a, 0xe6, 0x33, 0xd2, 0x11, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 6538ba2d..6cf02966 100644 --- a/types/types.proto +++ b/types/types.proto @@ -66,7 +66,7 @@ message RequestInitChain{ message RequestBeginBlock{ bytes hash = 1; Header header = 2; - repeated int32 absent_validators = 3; + repeated int32 absent_validators = 3 [(gogoproto.customtype) = "int", (gogoproto.nullable) = false]; repeated Evidence byzantine_validators = 4; } @@ -166,7 +166,7 @@ message Header { string chain_id = 1; int64 height = 2; int64 time = 3; - int64 num_txs = 4; + int32 num_txs = 4 [(gogoproto.customtype) = "int", (gogoproto.nullable) = false]; BlockID last_block_id = 5; bytes last_commit_hash = 6; bytes data_hash = 7; @@ -180,7 +180,7 @@ message BlockID { } message PartSetHeader { - int64 total = 1; + int32 total = 1 [(gogoproto.customtype) = "int", (gogoproto.nullable) = false]; bytes hash = 2; } From 9afd3da3b24f31541cb4bb83297677a9b48108c7 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 2 Dec 2017 01:56:21 -0500 Subject: [PATCH 385/545] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5395989f..38a7c7d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ BREAKING CHANGES: - [types] use `customtype` feature of `gogo/protobuf` to replace `[]byte` with `data.Bytes` in all generated types :) - this eliminates the need for additional types like ResultQuery - [types] `pubKey` -> `pub_key` - - [types] `uint64` -> `int64` + - [types] `uint64` -> `int32` for `Header.num_txs` and `PartSetHeader.total`, but generated code uses `int` + - [types] `uint64` -> `int64` for everything else - [abci-cli] codes are printed as their number instead of a message, except for `code == 0`, which is still printed as `OK` FEATURES: From 2b804bb5a13a7d1a66e5d53e5108879f2dae9847 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 2 Dec 2017 11:47:02 -0500 Subject: [PATCH 386/545] remove custom type int https://github.com/gogo/protobuf/issues/359 --- CHANGELOG.md | 2 +- Makefile | 1 + types/messages_test.go | 6 +- types/types.pb.go | 225 ++++++++++++++++++++++------------------- types/types.proto | 6 +- 5 files changed, 132 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38a7c7d8..6d66384d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ BREAKING CHANGES: - [types] use `customtype` feature of `gogo/protobuf` to replace `[]byte` with `data.Bytes` in all generated types :) - this eliminates the need for additional types like ResultQuery - [types] `pubKey` -> `pub_key` - - [types] `uint64` -> `int32` for `Header.num_txs` and `PartSetHeader.total`, but generated code uses `int` + - [types] `uint64` -> `int32` for `Header.num_txs` and `PartSetHeader.total` - [types] `uint64` -> `int64` for everything else - [abci-cli] codes are printed as their number instead of a message, except for `code == 0`, which is still printed as `OK` diff --git a/Makefile b/Makefile index d2384ae4..d5fe913b 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ install_protoc: rm -rf protobuf-3.4.1 protoc: + ## Note to self: ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 diff --git a/types/messages_test.go b/types/messages_test.go index 7f078979..607215be 100644 --- a/types/messages_test.go +++ b/types/messages_test.go @@ -10,7 +10,9 @@ import ( func TestWriteReadMessage(t *testing.T) { cases := []proto.Message{ - &RequestEcho{"hello"}, + &Header{ + NumTxs: 4, + }, // TODO: add the rest } @@ -19,7 +21,7 @@ func TestWriteReadMessage(t *testing.T) { err := WriteMessage(c, buf) assert.Nil(t, err) - msg := new(RequestEcho) + msg := new(Header) err = ReadMessage(buf, msg) assert.Nil(t, err) diff --git a/types/types.pb.go b/types/types.pb.go index ec42f252..9233a05c 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -647,7 +647,7 @@ func (m *RequestInitChain) GetValidators() []*Validator { type RequestBeginBlock struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` - AbsentValidators []int `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators,customtype=int" json:"absent_validators"` + AbsentValidators []int32 `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators" json:"absent_validators,omitempty"` ByzantineValidators []*Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators,omitempty"` } @@ -670,6 +670,13 @@ func (m *RequestBeginBlock) GetHeader() *Header { return nil } +func (m *RequestBeginBlock) GetAbsentValidators() []int32 { + if m != nil { + return m.AbsentValidators + } + return nil +} + func (m *RequestBeginBlock) GetByzantineValidators() []*Evidence { if m != nil { return m.ByzantineValidators @@ -1398,7 +1405,7 @@ type Header struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` Time int64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` - NumTxs int `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3,customtype=int" json:"num_txs"` + NumTxs int32 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` @@ -1432,6 +1439,13 @@ func (m *Header) GetTime() int64 { return 0 } +func (m *Header) GetNumTxs() int32 { + if m != nil { + return m.NumTxs + } + return 0 +} + func (m *Header) GetLastBlockId() *BlockID { if m != nil { return m.LastBlockId @@ -1492,7 +1506,7 @@ func (m *BlockID) GetParts() *PartSetHeader { } type PartSetHeader struct { - Total int `protobuf:"varint,1,opt,name=total,proto3,customtype=int" json:"total"` + Total int32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` } @@ -1501,6 +1515,13 @@ func (m *PartSetHeader) String() string { return proto.CompactTextStr func (*PartSetHeader) ProtoMessage() {} func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } +func (m *PartSetHeader) GetTotal() int32 { + if m != nil { + return m.Total + } + return 0 +} + func (m *PartSetHeader) GetHash() []byte { if m != nil { return m.Hash @@ -2036,103 +2057,103 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1565 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0x4d, 0x6f, 0xdb, 0x46, - 0x13, 0xc7, 0x2d, 0x51, 0x12, 0xa5, 0x91, 0x5f, 0xe4, 0xb5, 0x9f, 0x44, 0x51, 0x0e, 0x71, 0x88, - 0x27, 0x4f, 0xec, 0x3c, 0x89, 0x95, 0x3a, 0x48, 0xe1, 0x24, 0x45, 0x01, 0x2b, 0x4e, 0x2a, 0x21, - 0x40, 0x9a, 0x32, 0x46, 0xae, 0x02, 0x25, 0xae, 0xa4, 0x45, 0x24, 0x92, 0x21, 0x57, 0x8e, 0x5c, - 0xf4, 0x23, 0xe4, 0xde, 0x73, 0x7b, 0xec, 0xb9, 0x40, 0xbf, 0x41, 0xd1, 0x43, 0x3f, 0x41, 0x0f, - 0xf9, 0x2c, 0xc5, 0xce, 0x2e, 0x5f, 0x4d, 0xe6, 0x90, 0x43, 0x2e, 0xc6, 0x2e, 0x67, 0xfe, 0xab, - 0xd9, 0xe5, 0xf0, 0x37, 0xb3, 0x86, 0x6d, 0x7e, 0xe1, 0xd1, 0xa0, 0x8b, 0x7f, 0x0f, 0x3d, 0xdf, - 0xe5, 0x2e, 0xa9, 0xe2, 0xa4, 0x73, 0x6f, 0xca, 0xf8, 0x6c, 0x39, 0x3a, 0x1c, 0xbb, 0x8b, 0xee, - 0xd4, 0x9d, 0xba, 0x5d, 0xb4, 0x8e, 0x96, 0x13, 0x9c, 0xe1, 0x04, 0x47, 0x52, 0x65, 0xfc, 0x59, - 0x01, 0xdd, 0xa4, 0xef, 0x96, 0x34, 0xe0, 0x64, 0x1f, 0x2a, 0x74, 0x3c, 0x73, 0xdb, 0xa5, 0xbd, - 0xd2, 0x7e, 0xf3, 0x88, 0x1c, 0xca, 0xd5, 0x95, 0xf5, 0xd9, 0x78, 0xe6, 0xf6, 0xd7, 0x4c, 0xf4, - 0x20, 0xff, 0x87, 0xea, 0x64, 0xbe, 0x0c, 0x66, 0xed, 0x32, 0xba, 0xee, 0xa4, 0x5d, 0x9f, 0x0b, - 0x53, 0x7f, 0xcd, 0x94, 0x3e, 0x62, 0x59, 0xe6, 0x4c, 0xdc, 0xb6, 0x96, 0xb7, 0xec, 0xc0, 0x99, - 0xe0, 0xb2, 0xc2, 0x83, 0x1c, 0x03, 0x04, 0x94, 0x0f, 0x5d, 0x8f, 0x33, 0xd7, 0x69, 0x57, 0xd0, - 0xff, 0x6a, 0xda, 0xff, 0x35, 0xe5, 0xdf, 0xa3, 0xb9, 0xbf, 0x66, 0x36, 0x82, 0x70, 0x22, 0x94, - 0x36, 0x9d, 0xb3, 0x73, 0xea, 0x0f, 0xf9, 0xaa, 0x5d, 0xcd, 0x53, 0x9e, 0x4a, 0xfb, 0xd9, 0x4a, - 0x28, 0xed, 0x70, 0x42, 0x8e, 0xa0, 0x3e, 0x9e, 0xd1, 0xf1, 0x5b, 0xa1, 0xab, 0xa1, 0xee, 0x3f, - 0x69, 0xdd, 0x53, 0x61, 0x45, 0x95, 0x3e, 0x96, 0x43, 0x72, 0x08, 0xb5, 0xb1, 0xbb, 0x58, 0x30, - 0xde, 0xd6, 0x51, 0xb1, 0x9b, 0x51, 0xa0, 0xad, 0xbf, 0x66, 0x2a, 0x2f, 0x71, 0x5c, 0xef, 0x96, - 0xd4, 0xbf, 0x68, 0xd7, 0xf3, 0x8e, 0xeb, 0x07, 0x61, 0x12, 0xc7, 0x85, 0x3e, 0x62, 0x2b, 0xcc, - 0x61, 0x7c, 0x38, 0x9e, 0x59, 0xcc, 0x69, 0x37, 0xf2, 0xb6, 0x32, 0x70, 0x18, 0x7f, 0x2a, 0xcc, - 0x62, 0x2b, 0x2c, 0x9c, 0x90, 0x27, 0xd0, 0x1c, 0xd1, 0x29, 0x73, 0x86, 0xa3, 0xb9, 0x3b, 0x7e, - 0xdb, 0x06, 0x94, 0xb6, 0xd3, 0xd2, 0x9e, 0x70, 0xe8, 0x09, 0x7b, 0x7f, 0xcd, 0x84, 0x51, 0x34, - 0x23, 0x0f, 0xa1, 0x41, 0x1d, 0x5b, 0x49, 0x9b, 0x28, 0xbd, 0x92, 0xc9, 0x00, 0xc7, 0x0e, 0x85, - 0x75, 0xaa, 0xc6, 0x3d, 0x1d, 0xaa, 0xe7, 0xd6, 0x7c, 0x49, 0x8d, 0xdb, 0xd0, 0x4c, 0x64, 0x0a, - 0x69, 0x83, 0xbe, 0xa0, 0x41, 0x60, 0x4d, 0x29, 0xa6, 0x53, 0xc3, 0x0c, 0xa7, 0xc6, 0x26, 0xac, - 0x27, 0xf3, 0x24, 0x21, 0x14, 0xb9, 0x20, 0x84, 0xe7, 0xd4, 0x0f, 0x44, 0x02, 0x28, 0xa1, 0x9a, - 0x1a, 0x8f, 0xa1, 0x95, 0x4d, 0x02, 0xd2, 0x02, 0xed, 0x2d, 0xbd, 0x50, 0x9e, 0x62, 0x48, 0x76, - 0x55, 0x40, 0x98, 0x9a, 0x0d, 0x53, 0x45, 0x67, 0x44, 0xda, 0x28, 0x0d, 0xc8, 0x26, 0x94, 0xf9, - 0x0a, 0xa5, 0xeb, 0x66, 0x99, 0xaf, 0x8c, 0x3d, 0xd8, 0x4c, 0xbf, 0xf2, 0x4b, 0x1e, 0x76, 0x14, - 0x3a, 0xbe, 0x33, 0x42, 0xa0, 0x62, 0x5b, 0xdc, 0x52, 0x1e, 0x38, 0x16, 0xcf, 0x3c, 0x8b, 0xcf, - 0xd4, 0xcf, 0xe3, 0x98, 0x5c, 0x81, 0xda, 0x8c, 0xb2, 0xe9, 0x8c, 0xe3, 0x37, 0xa0, 0x99, 0x6a, - 0x26, 0x62, 0xf5, 0x7c, 0xf7, 0x9c, 0x62, 0xaa, 0xd7, 0x4d, 0x39, 0x31, 0xb6, 0x60, 0x23, 0x95, - 0x48, 0xc6, 0x69, 0x14, 0x7c, 0xf4, 0xe2, 0xc9, 0x7d, 0x80, 0x73, 0x6b, 0xce, 0x6c, 0x8b, 0xbb, - 0x7e, 0xd0, 0x2e, 0xed, 0x69, 0xfb, 0xcd, 0xa3, 0x96, 0x7a, 0x5f, 0x6f, 0x42, 0x83, 0x99, 0xf0, - 0x31, 0xfe, 0x2e, 0xc1, 0xf6, 0xa5, 0x24, 0x10, 0xe1, 0xce, 0xac, 0x60, 0x16, 0x6e, 0x41, 0x8c, - 0xc9, 0x2d, 0x11, 0xae, 0x65, 0x53, 0x5f, 0x7d, 0xde, 0x1b, 0x6a, 0xdd, 0x3e, 0x3e, 0x34, 0x95, - 0x91, 0x1c, 0xc3, 0xb6, 0x35, 0x0a, 0xa8, 0xc3, 0x87, 0x89, 0x48, 0xb4, 0x3d, 0x6d, 0xbf, 0xda, - 0x6b, 0xfe, 0xf5, 0xf1, 0xc6, 0xda, 0x3f, 0x1f, 0x6f, 0x68, 0xcc, 0xe1, 0x66, 0x4b, 0x7a, 0x45, - 0x51, 0x05, 0xa4, 0x07, 0xbb, 0xa3, 0x8b, 0x1f, 0x2d, 0x87, 0x33, 0x87, 0x26, 0xc5, 0x15, 0xdc, - 0xc6, 0x96, 0xfa, 0xb9, 0x67, 0xe7, 0xcc, 0xa6, 0xce, 0x98, 0x9a, 0x3b, 0x91, 0x73, 0xbc, 0x86, - 0x71, 0x00, 0x5b, 0x99, 0xbc, 0x4c, 0x1c, 0x73, 0x29, 0x79, 0xcc, 0xc6, 0x87, 0x2a, 0xd4, 0x4d, - 0x1a, 0x78, 0xae, 0x13, 0x50, 0x72, 0x0c, 0x0d, 0xba, 0x1a, 0x53, 0x89, 0x98, 0x52, 0xe6, 0x13, - 0x91, 0x3e, 0xcf, 0x42, 0xbb, 0xf8, 0xbc, 0x22, 0x67, 0x72, 0xa0, 0xf0, 0x98, 0x65, 0x9e, 0x12, - 0x25, 0xf9, 0x78, 0x37, 0xe4, 0xa3, 0x96, 0xe1, 0x83, 0xf4, 0xcd, 0x00, 0xf2, 0x40, 0x01, 0xb2, - 0x92, 0xbb, 0x70, 0x8a, 0x90, 0x8f, 0x52, 0x84, 0xac, 0xe6, 0x86, 0x5f, 0x80, 0xc8, 0x47, 0x29, - 0x44, 0xd6, 0x72, 0xa5, 0x05, 0x8c, 0x7c, 0x90, 0x60, 0xa4, 0x9e, 0x41, 0x83, 0x14, 0xe6, 0x40, - 0xb2, 0x1b, 0x41, 0xb2, 0x9e, 0xc1, 0xaa, 0x92, 0x64, 0x29, 0x79, 0x37, 0xa4, 0x64, 0x23, 0xf7, - 0xd0, 0x32, 0x98, 0x7c, 0x94, 0xc2, 0x24, 0xe4, 0x6e, 0xa7, 0x80, 0x93, 0xdf, 0xa4, 0x39, 0x29, - 0x61, 0x77, 0x2d, 0xa3, 0x2d, 0x04, 0xe5, 0xd7, 0x49, 0x50, 0xae, 0x67, 0xf0, 0xac, 0x72, 0xe1, - 0x93, 0xa4, 0x3c, 0x10, 0xdf, 0x61, 0x26, 0xd3, 0x04, 0x0a, 0xa8, 0xef, 0xbb, 0xbe, 0x42, 0x99, - 0x9c, 0x18, 0xfb, 0x02, 0x38, 0x71, 0x7e, 0x7d, 0x82, 0xaa, 0x08, 0x8d, 0x44, 0x76, 0x19, 0x3f, - 0x97, 0x62, 0x2d, 0x82, 0x35, 0x09, 0xab, 0x86, 0x82, 0x55, 0x02, 0xb6, 0xe5, 0x14, 0x6c, 0xc9, - 0x1d, 0xd8, 0x9e, 0x5b, 0x01, 0x97, 0xdb, 0x1c, 0xa6, 0xe8, 0xb5, 0x25, 0x0c, 0x72, 0x7f, 0x12, - 0x63, 0xf7, 0x60, 0x27, 0xe1, 0x6b, 0x79, 0xde, 0x10, 0x91, 0x52, 0x41, 0xa4, 0xb4, 0x22, 0xef, - 0x13, 0xcf, 0xeb, 0x5b, 0xc1, 0xcc, 0xb8, 0x15, 0xef, 0x3f, 0x05, 0xf2, 0xb9, 0x3b, 0x0d, 0x41, - 0x3e, 0x77, 0xa7, 0xc6, 0xaf, 0xa5, 0xd8, 0x2f, 0x86, 0x36, 0x81, 0xca, 0xd8, 0xb5, 0xe5, 0xf6, - 0x37, 0x4c, 0x1c, 0x93, 0x53, 0xb5, 0x33, 0xb1, 0x85, 0xf5, 0xde, 0x7d, 0xc5, 0x9e, 0xfd, 0x44, - 0x23, 0xc4, 0xa9, 0x63, 0x53, 0x7f, 0xc1, 0x1c, 0xde, 0x9d, 0xba, 0xf7, 0xde, 0x33, 0x9f, 0x76, - 0x85, 0xe2, 0xb0, 0x77, 0xc1, 0x69, 0xa0, 0xce, 0x42, 0x45, 0xa0, 0x45, 0x11, 0x90, 0x9b, 0x50, - 0xe1, 0xd6, 0x34, 0xc4, 0x52, 0x48, 0xc1, 0x17, 0x6f, 0x5e, 0x59, 0xcc, 0x37, 0xd1, 0x64, 0xfc, - 0x52, 0x12, 0x18, 0x4a, 0x7d, 0x03, 0x5f, 0x34, 0xc4, 0x16, 0x68, 0x53, 0x2b, 0xc0, 0xa3, 0xd6, - 0x4c, 0x31, 0x14, 0x4f, 0x26, 0x94, 0x22, 0x1a, 0x34, 0x53, 0x0c, 0x8d, 0x3f, 0xca, 0x71, 0x6e, - 0x44, 0x75, 0xeb, 0x52, 0x84, 0xbb, 0x50, 0x65, 0x8e, 0x4d, 0x57, 0x18, 0xa2, 0x66, 0xca, 0x09, - 0xe9, 0xc9, 0xfa, 0xaa, 0x7d, 0x66, 0xd8, 0x58, 0x91, 0x9f, 0x87, 0x15, 0xb9, 0xf2, 0x99, 0xab, - 0x48, 0xb9, 0x58, 0xc7, 0xf3, 0x5d, 0x77, 0x82, 0x7b, 0xfb, 0xac, 0x75, 0x50, 0x9e, 0x28, 0x13, - 0xb5, 0x54, 0x35, 0x56, 0xa7, 0xab, 0xc7, 0x29, 0xf8, 0x93, 0xe8, 0x08, 0x92, 0xb4, 0xfa, 0x92, - 0xef, 0xd6, 0xd8, 0x89, 0xf3, 0x3f, 0x02, 0x99, 0xb1, 0x0b, 0xe4, 0x32, 0xa1, 0x64, 0x6b, 0x94, - 0x66, 0x0f, 0xf9, 0x1f, 0x54, 0x6d, 0x36, 0x99, 0x14, 0x37, 0x07, 0xd2, 0x6c, 0xfc, 0x5e, 0x86, - 0x9a, 0xac, 0xec, 0xe4, 0x9a, 0xe0, 0xbc, 0xc5, 0x9c, 0x21, 0xb3, 0x43, 0xbe, 0xe0, 0x7c, 0x60, - 0x27, 0x0e, 0xad, 0x9c, 0x3a, 0x34, 0x02, 0x15, 0xce, 0x16, 0x54, 0xa1, 0x01, 0xc7, 0xe4, 0xbf, - 0xa0, 0x3b, 0xcb, 0xc5, 0x90, 0xaf, 0x64, 0x62, 0x66, 0xda, 0x81, 0x9a, 0xb3, 0x5c, 0x9c, 0xad, - 0x02, 0x72, 0x04, 0x1b, 0x09, 0x6a, 0x30, 0x5b, 0x55, 0xb3, 0x4d, 0x15, 0x27, 0x6e, 0x62, 0x70, - 0x6a, 0x36, 0x23, 0x7e, 0x0c, 0x6c, 0xb2, 0x0f, 0x88, 0x93, 0xa1, 0xac, 0x18, 0x12, 0x33, 0x35, - 0xc4, 0xcc, 0xa6, 0x78, 0xae, 0x4a, 0x8a, 0xe8, 0x61, 0xae, 0x43, 0x43, 0x1c, 0xab, 0x74, 0xd1, - 0xd1, 0xa5, 0x2e, 0x1e, 0xa0, 0xf1, 0x36, 0x6c, 0xc5, 0x5d, 0x87, 0x74, 0xa9, 0xcb, 0x55, 0xe2, - 0xc7, 0xe8, 0x78, 0x0d, 0xea, 0x11, 0xce, 0x1a, 0xe8, 0xa1, 0x5b, 0x8a, 0x62, 0x03, 0xd0, 0x55, - 0x88, 0xb9, 0x3d, 0xd4, 0x1d, 0xa8, 0x7a, 0x96, 0xcf, 0x03, 0xd5, 0x2d, 0x84, 0xc5, 0xec, 0x95, - 0xe5, 0x8b, 0xee, 0x55, 0x75, 0x52, 0xd2, 0xc5, 0x78, 0x0e, 0x1b, 0xa9, 0xe7, 0xe4, 0x26, 0x54, - 0xb9, 0xcb, 0xad, 0x39, 0xae, 0x98, 0x39, 0x3e, 0x69, 0x89, 0x7e, 0xb3, 0x1c, 0xff, 0xa6, 0xf1, - 0x18, 0x1a, 0xd1, 0xdb, 0x25, 0x57, 0x41, 0xf7, 0x96, 0xa3, 0x61, 0xd8, 0x1d, 0xaf, 0x9b, 0x35, - 0x6f, 0x39, 0x7a, 0x21, 0x1b, 0x64, 0xcf, 0x7d, 0xaf, 0x9a, 0x3b, 0xcd, 0x94, 0x13, 0xe3, 0x09, - 0xd4, 0xc3, 0x7e, 0xab, 0x58, 0x5a, 0x90, 0x04, 0xc6, 0x6f, 0x25, 0xa8, 0x49, 0x2c, 0xe6, 0x34, - 0xe4, 0x5f, 0x61, 0xa7, 0xba, 0xa4, 0x43, 0x71, 0x02, 0x28, 0xdc, 0x8c, 0x2e, 0x81, 0x52, 0x74, - 0x78, 0x76, 0xe1, 0x51, 0xb3, 0x81, 0x5e, 0x62, 0x48, 0x6e, 0xc2, 0xba, 0x94, 0x04, 0xdc, 0x67, - 0x4e, 0xf8, 0x51, 0x34, 0xf1, 0xd9, 0x6b, 0x7c, 0x24, 0xde, 0xaf, 0x74, 0x61, 0x0e, 0x57, 0xf8, - 0xab, 0xe3, 0x83, 0x81, 0xc3, 0x8d, 0xeb, 0x50, 0xc1, 0x75, 0x00, 0x6a, 0xaf, 0xcf, 0xcc, 0xc1, - 0xcb, 0xef, 0x5a, 0x6b, 0x44, 0x07, 0x6d, 0xf0, 0xf2, 0xac, 0x55, 0x3a, 0xfa, 0x50, 0x85, 0xad, - 0x93, 0xde, 0xd3, 0xc1, 0x89, 0xe7, 0xcd, 0xd9, 0xd8, 0xc2, 0xea, 0xd3, 0x85, 0x0a, 0xd6, 0xd7, - 0x9c, 0x3b, 0x6f, 0x27, 0xaf, 0xd1, 0x23, 0x47, 0x50, 0xc5, 0x32, 0x4b, 0xf2, 0xae, 0xbe, 0x9d, - 0xdc, 0x7e, 0x4f, 0xfc, 0x88, 0x2c, 0xc4, 0x97, 0x6f, 0xc0, 0x9d, 0xbc, 0xa6, 0x8f, 0x7c, 0x0b, - 0x8d, 0xb8, 0x40, 0x16, 0xdd, 0x83, 0x3b, 0x85, 0xed, 0x9f, 0xd0, 0xc7, 0x85, 0xb3, 0xe8, 0x36, - 0xdc, 0x29, 0xec, 0x01, 0xc9, 0x31, 0xe8, 0x61, 0x4d, 0xcb, 0xbf, 0x13, 0x77, 0x0a, 0xda, 0x40, - 0x71, 0x3c, 0xb2, 0xd2, 0xe4, 0x5d, 0x75, 0x3b, 0xb9, 0x9d, 0x1d, 0x79, 0x08, 0x35, 0x05, 0xd9, - 0xdc, 0xeb, 0x74, 0x27, 0xbf, 0x7f, 0x14, 0x9b, 0x8c, 0x6f, 0x45, 0x45, 0xf7, 0xe4, 0x4e, 0x61, - 0x67, 0x48, 0x4e, 0x00, 0x12, 0xd7, 0xa1, 0xc2, 0xdb, 0x72, 0xa7, 0xb8, 0x3f, 0x24, 0xe2, 0xdb, - 0x89, 0xee, 0x20, 0xf9, 0x77, 0xe6, 0x4e, 0x51, 0x8b, 0x38, 0xaa, 0xe1, 0xff, 0x61, 0x1e, 0xfc, - 0x1b, 0x00, 0x00, 0xff, 0xff, 0x93, 0x8a, 0xe6, 0x33, 0xd2, 0x11, 0x00, 0x00, + // 1554 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0xcb, 0x6e, 0xdb, 0x46, + 0x17, 0xc7, 0x2d, 0x51, 0xd4, 0xe5, 0xf8, 0x26, 0x8f, 0xfd, 0x25, 0x8a, 0xb2, 0x88, 0x43, 0x20, + 0x5f, 0xe4, 0x5c, 0xac, 0x7c, 0x0e, 0xf2, 0x21, 0x4e, 0x8a, 0x02, 0x56, 0x9c, 0x54, 0x42, 0x80, + 0x34, 0x9d, 0x18, 0xd9, 0x0a, 0x94, 0x38, 0x92, 0x88, 0x48, 0x24, 0x43, 0x8e, 0x1c, 0xb9, 0xe8, + 0x23, 0x64, 0xdf, 0x75, 0xbb, 0x29, 0xd0, 0x17, 0xe8, 0xb2, 0xbb, 0xa2, 0xcf, 0xd0, 0x45, 0x9e, + 0xa5, 0x98, 0x33, 0xc3, 0xab, 0xc9, 0x2c, 0xb2, 0xc8, 0xc6, 0x98, 0xcb, 0xf9, 0x8f, 0xce, 0x0c, + 0xcf, 0xfc, 0xce, 0x19, 0xc3, 0x0e, 0xbf, 0xf0, 0x58, 0xd0, 0xc5, 0xbf, 0x87, 0x9e, 0xef, 0x72, + 0x97, 0xe8, 0xd8, 0x69, 0xdf, 0x9f, 0xda, 0x7c, 0xb6, 0x1c, 0x1d, 0x8e, 0xdd, 0x45, 0x77, 0xea, + 0x4e, 0xdd, 0x2e, 0xce, 0x8e, 0x96, 0x13, 0xec, 0x61, 0x07, 0x5b, 0x52, 0x65, 0xfc, 0x55, 0x81, + 0x1a, 0x65, 0xef, 0x97, 0x2c, 0xe0, 0xa4, 0x03, 0x15, 0x36, 0x9e, 0xb9, 0xad, 0xd2, 0x7e, 0xa9, + 0xb3, 0x7e, 0x44, 0x0e, 0xe5, 0xea, 0x6a, 0xf6, 0xf9, 0x78, 0xe6, 0xf6, 0xd7, 0x28, 0x5a, 0x90, + 0xbb, 0xa0, 0x4f, 0xe6, 0xcb, 0x60, 0xd6, 0x2a, 0xa3, 0xe9, 0x6e, 0xda, 0xf4, 0x85, 0x98, 0xea, + 0xaf, 0x51, 0x69, 0x23, 0x96, 0xb5, 0x9d, 0x89, 0xdb, 0xd2, 0xf2, 0x96, 0x1d, 0x38, 0x13, 0x5c, + 0x56, 0x58, 0x90, 0xc7, 0x00, 0x01, 0xe3, 0x43, 0xd7, 0xe3, 0xb6, 0xeb, 0xb4, 0x2a, 0x68, 0x7f, + 0x35, 0x6d, 0xff, 0x86, 0xf1, 0xef, 0x71, 0xba, 0xbf, 0x46, 0x1b, 0x41, 0xd8, 0x11, 0x4a, 0x8b, + 0xcd, 0xed, 0x73, 0xe6, 0x0f, 0xf9, 0xaa, 0xa5, 0xe7, 0x29, 0x4f, 0xe5, 0xfc, 0xd9, 0x4a, 0x28, + 0xad, 0xb0, 0x43, 0x8e, 0xa0, 0x3e, 0x9e, 0xb1, 0xf1, 0x3b, 0xa1, 0xab, 0xa2, 0xee, 0x3f, 0x69, + 0xdd, 0x33, 0x31, 0x8b, 0xaa, 0xda, 0x58, 0x36, 0xc9, 0x21, 0x54, 0xc7, 0xee, 0x62, 0x61, 0xf3, + 0x56, 0x0d, 0x15, 0x7b, 0x19, 0x05, 0xce, 0xf5, 0xd7, 0xa8, 0xb2, 0x12, 0xc7, 0xf5, 0x7e, 0xc9, + 0xfc, 0x8b, 0x56, 0x3d, 0xef, 0xb8, 0x7e, 0x10, 0x53, 0xe2, 0xb8, 0xd0, 0x46, 0x6c, 0xc5, 0x76, + 0x6c, 0x3e, 0x1c, 0xcf, 0x4c, 0xdb, 0x69, 0x35, 0xf2, 0xb6, 0x32, 0x70, 0x6c, 0xfe, 0x4c, 0x4c, + 0x8b, 0xad, 0xd8, 0x61, 0x87, 0x3c, 0x85, 0xf5, 0x11, 0x9b, 0xda, 0xce, 0x70, 0x34, 0x77, 0xc7, + 0xef, 0x5a, 0x80, 0xd2, 0x56, 0x5a, 0xda, 0x13, 0x06, 0x3d, 0x31, 0xdf, 0x5f, 0xa3, 0x30, 0x8a, + 0x7a, 0xe4, 0x11, 0x34, 0x98, 0x63, 0x29, 0xe9, 0x3a, 0x4a, 0xaf, 0x64, 0x22, 0xc0, 0xb1, 0x42, + 0x61, 0x9d, 0xa9, 0x76, 0xaf, 0x06, 0xfa, 0xb9, 0x39, 0x5f, 0x32, 0xe3, 0x36, 0xac, 0x27, 0x22, + 0x85, 0xb4, 0xa0, 0xb6, 0x60, 0x41, 0x60, 0x4e, 0x19, 0x86, 0x53, 0x83, 0x86, 0x5d, 0x63, 0x0b, + 0x36, 0x92, 0x71, 0x92, 0x10, 0x8a, 0x58, 0x10, 0xc2, 0x73, 0xe6, 0x07, 0x22, 0x00, 0x94, 0x50, + 0x75, 0x8d, 0x27, 0xd0, 0xcc, 0x06, 0x01, 0x69, 0x82, 0xf6, 0x8e, 0x5d, 0x28, 0x4b, 0xd1, 0x24, + 0x7b, 0xca, 0x21, 0x0c, 0xcd, 0x06, 0x55, 0xde, 0x19, 0x91, 0x36, 0x0a, 0x03, 0xb2, 0x05, 0x65, + 0xbe, 0x42, 0xe9, 0x06, 0x2d, 0xf3, 0x95, 0xb1, 0x0f, 0x5b, 0xe9, 0x4f, 0x7e, 0xc9, 0xc2, 0x8a, + 0x5c, 0xc7, 0x6f, 0x46, 0x08, 0x54, 0x2c, 0x93, 0x9b, 0xca, 0x02, 0xdb, 0x62, 0xcc, 0x33, 0xf9, + 0x4c, 0xfd, 0x3c, 0xb6, 0xc9, 0x15, 0xa8, 0xce, 0x98, 0x3d, 0x9d, 0x71, 0xbc, 0x03, 0x1a, 0x55, + 0x3d, 0xe1, 0xab, 0xe7, 0xbb, 0xe7, 0x0c, 0x43, 0xbd, 0x4e, 0x65, 0xc7, 0xd8, 0x86, 0xcd, 0x54, + 0x20, 0x19, 0xa7, 0x91, 0xf3, 0xd1, 0x87, 0x27, 0x0f, 0x00, 0xce, 0xcd, 0xb9, 0x6d, 0x99, 0xdc, + 0xf5, 0x83, 0x56, 0x69, 0x5f, 0xeb, 0xac, 0x1f, 0x35, 0xd5, 0xf7, 0x7a, 0x1b, 0x4e, 0xd0, 0x84, + 0x8d, 0xf1, 0x67, 0x09, 0x76, 0x2e, 0x05, 0x81, 0x70, 0x77, 0x66, 0x06, 0xb3, 0x70, 0x0b, 0xa2, + 0x4d, 0x6e, 0x09, 0x77, 0x4d, 0x8b, 0xf9, 0xea, 0x7a, 0x6f, 0xaa, 0x75, 0xfb, 0x38, 0x48, 0xd5, + 0x24, 0xb9, 0x0b, 0x3b, 0xe6, 0x28, 0x60, 0x0e, 0x1f, 0x26, 0x3c, 0xd1, 0xf6, 0xb5, 0x8e, 0x4e, + 0x9b, 0x72, 0x22, 0x72, 0x24, 0x20, 0x3d, 0xd8, 0x1b, 0x5d, 0xfc, 0x68, 0x3a, 0xdc, 0x76, 0x58, + 0xd2, 0xbe, 0x82, 0x9e, 0x6f, 0xab, 0x5f, 0x78, 0x7e, 0x6e, 0x5b, 0xcc, 0x19, 0x33, 0xba, 0x1b, + 0x19, 0xc7, 0x6b, 0x18, 0x07, 0xb0, 0x9d, 0x09, 0xc5, 0xc4, 0xc9, 0x96, 0x92, 0x27, 0x6b, 0x7c, + 0xd4, 0xa1, 0x4e, 0x59, 0xe0, 0xb9, 0x4e, 0xc0, 0xc8, 0x63, 0x68, 0xb0, 0xd5, 0x98, 0x49, 0xaa, + 0x94, 0x32, 0xb7, 0x42, 0xda, 0x3c, 0x0f, 0xe7, 0xc5, 0x8d, 0x8a, 0x8c, 0xc9, 0x81, 0x22, 0x62, + 0x16, 0x73, 0x4a, 0x94, 0x44, 0xe2, 0xbd, 0x10, 0x89, 0x5a, 0x06, 0x09, 0xd2, 0x36, 0xc3, 0xc4, + 0x03, 0xc5, 0xc4, 0x4a, 0xee, 0xc2, 0x29, 0x28, 0x1e, 0xa7, 0xa0, 0xa8, 0xe7, 0xba, 0x5f, 0x40, + 0xc5, 0xe3, 0x14, 0x15, 0xab, 0xb9, 0xd2, 0x02, 0x2c, 0x3e, 0x4c, 0x60, 0xb1, 0x96, 0xa1, 0x81, + 0x14, 0xe6, 0x70, 0xb1, 0x1b, 0x71, 0xb1, 0x9e, 0x21, 0xa9, 0x92, 0x64, 0xc1, 0x78, 0x2f, 0x04, + 0x63, 0x23, 0xf7, 0xd0, 0x32, 0x64, 0x3c, 0x4e, 0x91, 0x11, 0x72, 0xb7, 0x53, 0x80, 0xc6, 0x6f, + 0xd2, 0x68, 0x94, 0x7c, 0xbb, 0x96, 0xd1, 0x16, 0xb2, 0xf1, 0xff, 0x49, 0x36, 0x6e, 0x64, 0x88, + 0xac, 0x62, 0xe1, 0xb3, 0x70, 0x3c, 0x10, 0x57, 0x2f, 0x13, 0x69, 0xe2, 0xf6, 0x33, 0xdf, 0x77, + 0x7d, 0x45, 0x2f, 0xd9, 0x31, 0x3a, 0x82, 0x31, 0x71, 0x7c, 0x7d, 0x06, 0xa4, 0xc8, 0x89, 0x44, + 0x74, 0x19, 0x3f, 0x97, 0x62, 0x2d, 0xb2, 0x34, 0xc9, 0xa7, 0x86, 0xe2, 0x53, 0x82, 0xaf, 0xe5, + 0x14, 0x5f, 0xc9, 0x1d, 0xd8, 0x99, 0x9b, 0x01, 0x97, 0xdb, 0x1c, 0xa6, 0x80, 0xb5, 0x2d, 0x26, + 0xe4, 0xfe, 0x24, 0xb9, 0xee, 0xc3, 0x6e, 0xc2, 0xd6, 0xf4, 0xbc, 0x21, 0x52, 0xa4, 0x82, 0x14, + 0x69, 0x46, 0xd6, 0x27, 0x9e, 0xd7, 0x37, 0x83, 0x99, 0x71, 0x2b, 0xde, 0x7f, 0x8a, 0xdd, 0x73, + 0x77, 0x1a, 0xb2, 0x7b, 0xee, 0x4e, 0x8d, 0x5f, 0x4b, 0xb1, 0x5d, 0xcc, 0x69, 0x02, 0x95, 0xb1, + 0x6b, 0xc9, 0xed, 0x6f, 0x52, 0x6c, 0x93, 0x53, 0xb5, 0x33, 0xb1, 0x85, 0x8d, 0xde, 0x83, 0xbf, + 0x3f, 0xdd, 0x58, 0xfb, 0xe7, 0xd3, 0x8d, 0x4e, 0xa2, 0xf6, 0xe1, 0xcc, 0xb1, 0x98, 0xbf, 0xb0, + 0x1d, 0xde, 0x9d, 0xba, 0xf7, 0x3f, 0xd8, 0x3e, 0xeb, 0x0a, 0xc5, 0x61, 0xef, 0x82, 0xb3, 0x40, + 0x9d, 0x85, 0xf2, 0x40, 0x8b, 0x3c, 0x20, 0x37, 0xa1, 0xc2, 0xcd, 0x69, 0x88, 0xa5, 0x10, 0x7c, + 0x2f, 0xdf, 0xbe, 0x36, 0x6d, 0x9f, 0xe2, 0x94, 0xf1, 0x4b, 0x49, 0x60, 0x28, 0x75, 0x07, 0xbe, + 0xaa, 0x8b, 0x4d, 0xd0, 0xa6, 0x66, 0x80, 0x47, 0xad, 0x51, 0xd1, 0x14, 0x23, 0x13, 0xc6, 0x10, + 0x0d, 0x1a, 0x15, 0x4d, 0xe3, 0x8f, 0x72, 0x1c, 0x1b, 0x51, 0xaa, 0xba, 0xe4, 0xe1, 0x1e, 0xe8, + 0xb6, 0x63, 0xb1, 0x15, 0xba, 0xa8, 0x51, 0xd9, 0x21, 0x3d, 0x99, 0x52, 0xb5, 0x2f, 0x74, 0x1b, + 0x93, 0xf0, 0x8b, 0x30, 0x09, 0x57, 0xbe, 0x70, 0x15, 0x29, 0x17, 0xeb, 0x78, 0xbe, 0xeb, 0x4e, + 0x70, 0x6f, 0x5f, 0xb4, 0x0e, 0xca, 0x13, 0x69, 0xa2, 0x9a, 0x4a, 0xc0, 0xea, 0x74, 0x6b, 0x71, + 0x08, 0xfe, 0x24, 0x8a, 0x80, 0x24, 0xad, 0xbe, 0xe6, 0xb7, 0x35, 0x76, 0xe3, 0xf8, 0x8f, 0x40, + 0x66, 0xec, 0x01, 0xb9, 0x4c, 0x28, 0x59, 0x0d, 0xa5, 0xd9, 0x43, 0xfe, 0x0b, 0xba, 0x65, 0x4f, + 0x26, 0xc5, 0xf5, 0x80, 0x9c, 0x36, 0x7e, 0x2b, 0x43, 0x55, 0x26, 0x73, 0x72, 0x4d, 0x70, 0xde, + 0xb4, 0x9d, 0xa1, 0x6d, 0x85, 0x7c, 0xc1, 0xfe, 0xc0, 0x4a, 0x1c, 0x5a, 0x39, 0x75, 0x68, 0x04, + 0x2a, 0xdc, 0x5e, 0x30, 0x85, 0x06, 0x6c, 0x93, 0xab, 0x50, 0x73, 0x96, 0x8b, 0x21, 0x5f, 0xc9, + 0xc0, 0xd4, 0x69, 0xd5, 0x59, 0x2e, 0xce, 0x56, 0x01, 0x39, 0x82, 0xcd, 0x04, 0x28, 0x6c, 0x4b, + 0x25, 0xb0, 0x2d, 0xe5, 0x1a, 0xfa, 0x3d, 0x38, 0xa5, 0xeb, 0x11, 0x32, 0x06, 0x16, 0xe9, 0x00, + 0x12, 0x64, 0x28, 0x93, 0x84, 0x24, 0x4b, 0x15, 0xc9, 0xb2, 0x25, 0xc6, 0x55, 0x16, 0x11, 0x95, + 0xca, 0x75, 0x68, 0x88, 0x93, 0x94, 0x26, 0x35, 0x34, 0xa9, 0x8b, 0x01, 0x9c, 0xbc, 0x0d, 0xdb, + 0x71, 0xa1, 0x21, 0x4d, 0xea, 0x72, 0x95, 0x78, 0x18, 0x0d, 0xaf, 0x41, 0x3d, 0x22, 0x58, 0x03, + 0x2d, 0x6a, 0xa6, 0x02, 0xd7, 0x00, 0x6a, 0xca, 0xc5, 0xdc, 0x4a, 0xe9, 0x0e, 0xe8, 0x9e, 0xe9, + 0xf3, 0x40, 0x15, 0x08, 0x61, 0xfe, 0x7a, 0x6d, 0xfa, 0xa2, 0x46, 0x55, 0xf5, 0x92, 0x34, 0x31, + 0x8e, 0x61, 0x33, 0x35, 0x2e, 0xae, 0x1f, 0x77, 0xb9, 0x39, 0xc7, 0x15, 0x75, 0x2a, 0x3b, 0xd1, + 0xcf, 0x94, 0xe3, 0x9f, 0x31, 0x9e, 0x40, 0x23, 0xfa, 0x86, 0xe2, 0xa8, 0xbd, 0xe5, 0x68, 0x18, + 0x96, 0xbd, 0x1b, 0xb4, 0xea, 0x2d, 0x47, 0x2f, 0x65, 0xe5, 0xeb, 0xb9, 0x1f, 0x54, 0xd5, 0xa6, + 0x51, 0xd9, 0x31, 0x9e, 0x42, 0x3d, 0xac, 0xaa, 0x8a, 0xa5, 0x05, 0x9f, 0xda, 0xf8, 0xbd, 0x04, + 0x55, 0x09, 0xbf, 0x9c, 0x4a, 0xfb, 0x7f, 0x58, 0x82, 0x2e, 0xd9, 0x50, 0x6c, 0x1a, 0x85, 0x5b, + 0xd1, 0xeb, 0x4e, 0x8a, 0x0e, 0xcf, 0x2e, 0x3c, 0x46, 0x1b, 0x68, 0x25, 0x9a, 0xe4, 0x26, 0x6c, + 0x48, 0x49, 0xc0, 0x7d, 0xdb, 0x09, 0x43, 0x7f, 0x1d, 0xc7, 0xde, 0xe0, 0x90, 0xf8, 0xa4, 0xd2, + 0xc4, 0x76, 0xb8, 0x82, 0x5c, 0x1d, 0x07, 0x06, 0x0e, 0x37, 0xae, 0x43, 0x05, 0xd7, 0x01, 0xa8, + 0xbe, 0x39, 0xa3, 0x83, 0x57, 0xdf, 0x35, 0xd7, 0x48, 0x0d, 0xb4, 0xc1, 0xab, 0xb3, 0x66, 0xe9, + 0xe8, 0xa3, 0x0e, 0xdb, 0x27, 0xbd, 0x67, 0x83, 0x13, 0xcf, 0x9b, 0xdb, 0x63, 0x13, 0x73, 0x4c, + 0x17, 0x2a, 0x98, 0x45, 0x73, 0x1e, 0xb3, 0xed, 0xbc, 0x72, 0x8e, 0x1c, 0x81, 0x8e, 0xc9, 0x94, + 0xe4, 0xbd, 0x69, 0xdb, 0xb9, 0x55, 0x9d, 0xf8, 0x11, 0x99, 0x6e, 0x2f, 0x3f, 0x6d, 0xdb, 0x79, + 0xa5, 0x1d, 0xf9, 0x16, 0x1a, 0x71, 0x1a, 0x2c, 0x7a, 0xe0, 0xb6, 0x0b, 0x8b, 0x3c, 0xa1, 0x8f, + 0xd3, 0x63, 0xd1, 0x33, 0xb7, 0x5d, 0x58, 0xe9, 0x91, 0xc7, 0x50, 0x0b, 0x33, 0x57, 0xfe, 0x63, + 0xb7, 0x5d, 0x50, 0xec, 0x89, 0xe3, 0x91, 0xf9, 0x24, 0xef, 0x0d, 0xdb, 0xce, 0xad, 0xdf, 0xc8, + 0x23, 0xa8, 0x2a, 0x94, 0xe6, 0xbe, 0x93, 0xdb, 0xf9, 0x55, 0xa2, 0xd8, 0x64, 0xfc, 0xdc, 0x29, + 0x7a, 0x00, 0xb7, 0x0b, 0xeb, 0x3f, 0x72, 0x02, 0x90, 0x78, 0xe7, 0x14, 0x3e, 0x83, 0xdb, 0xc5, + 0x55, 0x20, 0x11, 0x77, 0x27, 0x7a, 0x69, 0xe4, 0x3f, 0x86, 0xdb, 0x45, 0x85, 0xe0, 0xa8, 0x8a, + 0xff, 0x60, 0x79, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x15, 0x2f, 0x59, 0xab, 0x11, + 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 6cf02966..2424474d 100644 --- a/types/types.proto +++ b/types/types.proto @@ -66,7 +66,7 @@ message RequestInitChain{ message RequestBeginBlock{ bytes hash = 1; Header header = 2; - repeated int32 absent_validators = 3 [(gogoproto.customtype) = "int", (gogoproto.nullable) = false]; + repeated int32 absent_validators = 3; repeated Evidence byzantine_validators = 4; } @@ -166,7 +166,7 @@ message Header { string chain_id = 1; int64 height = 2; int64 time = 3; - int32 num_txs = 4 [(gogoproto.customtype) = "int", (gogoproto.nullable) = false]; + int32 num_txs = 4; BlockID last_block_id = 5; bytes last_commit_hash = 6; bytes data_hash = 7; @@ -180,7 +180,7 @@ message BlockID { } message PartSetHeader { - int32 total = 1 [(gogoproto.customtype) = "int", (gogoproto.nullable) = false]; + int32 total = 1; bytes hash = 2; } From e99e6ea0c7d913a8484b642d222044a47565d65a Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Thu, 4 May 2017 11:29:25 +0200 Subject: [PATCH 387/545] Extend abci-cli to allow integration tests This commit adds the basic test command 'abci-cli test' that will allow developers of server for their own language to continuously test their implementation. --- README.md | 44 +++++++++++++++++ client/grpc_client.go | 5 +- cmd/abci-cli/abci-cli.go | 51 +++++++++++++++++++ tests/server/client.go | 103 +++++++++++++++++++++++++++++++++++++++ tests/test_cli/test.sh | 0 tests/tests.go | 1 + 6 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 tests/server/client.go mode change 100644 => 100755 tests/test_cli/test.sh create mode 100644 tests/tests.go diff --git a/README.md b/README.md index 1b7f8900..3c7453a2 100644 --- a/README.md +++ b/README.md @@ -192,3 +192,47 @@ Here, we describe the requests and responses as function arguments and return va #### Flush * __Usage__:
* Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. + +# Implementation + +We provide three implementations of the ABCI in Go: + +1. ABCI-socket +2. GRPC +3. Golang in-process + +## Socket + +ABCI is best implemented as a streaming protocol. +The socket implementation provides for asynchronous, ordered message passing over unix or tcp. +Messages are serialized using Protobuf3 and length-prefixed. +Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. + +For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. + +## GRPC + +GRPC is an rpc framework native to Protocol Buffers with support in many languages. +Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than +the ordered, asynchronous socket protocol. + +Note the length-prefixing used in the socket implementation does not apply for GRPC. + +## In Process + +The simplest implementation just uses function calls within Go. +This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. + + +# Tools and Apps + +The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. +See the [guide](https://tendermint.readthedocs.io/en/master/abci-cli.html) for more details. + +Multiple example apps are included: +- the `counter` application, which illustrates nonce checking in txs +- the `dummy` application, which illustrates a simple key-value merkle tree +- the `dummy --persistent` application, which augments the dummy with persistence and validator set changes + +When you are developing an implementation of the ABCI server in your favourite language, we provide the `abci-cli test` +command that allows you to run our tests against your own ABCI server. Please make sure that your server supports at least the TSP protocol, and optionally gRPC. diff --git a/client/grpc_client.go b/client/grpc_client.go index 9328fa32..f277e1d7 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -48,7 +48,6 @@ func (cli *grpcClient) OnStart() error { return err } RETRY_LOOP: - for { conn, err := grpc.Dial(cli.addr, grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) if err != nil { @@ -83,8 +82,8 @@ func (cli *grpcClient) OnStop() { cli.mtx.Lock() defer cli.mtx.Unlock() // TODO: how to close conn? its not a net.Conn and grpc doesn't expose a Close() - /*if cli.conn != nil { - cli.conn.Close() + /*if cli.client.conn != nil { + cli.client.conn.Close() }*/ } diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index e7fae52e..9e8e86b9 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -19,6 +19,7 @@ import ( "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" + servertest "github.com/tendermint/abci/tests/server" "github.com/tendermint/abci/types" "github.com/tendermint/abci/version" ) @@ -141,6 +142,7 @@ func addCommands() { RootCmd.AddCommand(checkTxCmd) RootCmd.AddCommand(commitCmd) RootCmd.AddCommand(versionCmd) + RootCmd.AddCommand(testCmd) addQueryFlags() RootCmd.AddCommand(queryCmd) @@ -271,6 +273,16 @@ var dummyCmd = &cobra.Command{ }, } +var testCmd = &cobra.Command{ + Use: "test", + Short: "Run integration tests", + Long: "", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + return cmdTest(cmd, args) + }, +} + // Generates new Args array based off of previous call args to maintain flag persistence func persistentArgs(line []byte) []string { @@ -287,6 +299,45 @@ func persistentArgs(line []byte) []string { //-------------------------------------------------------------------------------- +func cmdTest(cmd *cobra.Command, args []string) error { + fmt.Println("Running tests") + + var err error + + err = servertest.InitChain(client) + fmt.Println("") + err = servertest.SetOption(client, "serial", "on") + fmt.Println("") + err = servertest.Commit(client, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + fmt.Println("") + err = servertest.Commit(client, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x00}, types.CodeType_OK, nil) + fmt.Println("") + err = servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x01}, types.CodeType_OK, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) + fmt.Println("") + err = servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) + fmt.Println("") + err = servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) + + if err != nil { + return errors.New("Some checks didn't pass, please use the cli to see the exact failures.") + } + return nil +} + func cmdBatch(cmd *cobra.Command, args []string) error { bufReader := bufio.NewReader(os.Stdin) for { diff --git a/tests/server/client.go b/tests/server/client.go new file mode 100644 index 00000000..502e4e8e --- /dev/null +++ b/tests/server/client.go @@ -0,0 +1,103 @@ +package testsuite + +import ( + "bytes" + "errors" + "fmt" + + abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" + cmn "github.com/tendermint/tmlibs/common" +) + +func InitChain(client abcicli.Client) error { + total := 10 + vals := make([]*types.Validator, total) + for i := 0; i < total; i++ { + pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() + power := cmn.RandInt() + vals[i] = &types.Validator{pubkey, uint64(power)} + } + err := client.InitChainSync(vals) + if err != nil { + fmt.Println("Failed test: InitChain - %v", err) + return err + } + fmt.Println("Passed test: InitChain") + return nil +} + +func SetOption(client abcicli.Client, key, value string) error { + res := client.SetOptionSync(key, value) + _, _, log := res.Code, res.Data, res.Log + if res.IsErr() { + fmt.Println("Failed test: SetOption") + fmt.Printf("setting %v=%v: \nlog: %v", key, value, log) + fmt.Println("Failed test: SetOption") + return errors.New(res.Error()) + } + fmt.Println("Passed test: SetOption") + return nil +} + +func Commit(client abcicli.Client, hashExp []byte) error { + res := client.CommitSync() + _, data, log := res.Code, res.Data, res.Log + if res.IsErr() { + fmt.Println("Failed test: Commit") + fmt.Printf("committing %v\nlog: %v", log) + return errors.New(res.Error()) + } + if !bytes.Equal(res.Data, hashExp) { + fmt.Println("Failed test: Commit") + fmt.Printf("Commit hash was unexpected. Got %X expected %X", + data, hashExp) + return errors.New("CommitTx failed") + } + fmt.Println("Passed test: Commit") + return nil +} + +func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) error { + res := client.DeliverTxSync(txBytes) + code, data, log := res.Code, res.Data, res.Log + if code != codeExp { + fmt.Println("Failed test: DeliverTx") + fmt.Printf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", + code, codeExp, log) + return errors.New("DeliverTx error") + } + if !bytes.Equal(data, dataExp) { + fmt.Println("Failed test: DeliverTx") + fmt.Printf("DeliverTx response data was unexpected. Got %X expected %X", + data, dataExp) + return errors.New("DeliverTx error") + } + fmt.Println("Passed test: DeliverTx") + return nil +} + +func CheckTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) error { + res := client.CheckTxSync(txBytes) + code, data, log := res.Code, res.Data, res.Log + if res.IsErr() { + fmt.Println("Failed test: CheckTx") + fmt.Printf("checking tx %X: %v\nlog: %v", txBytes, log) + return errors.New(res.Error()) + } + if code != codeExp { + fmt.Println("Failed test: CheckTx") + fmt.Printf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", + code, codeExp, log) + return errors.New("CheckTx") + } + if !bytes.Equal(data, dataExp) { + fmt.Println("Failed test: CheckTx") + fmt.Printf("CheckTx response data was unexpected. Got %X expected %X", + data, dataExp) + return errors.New("CheckTx") + } + fmt.Println("Passed test: CheckTx") + return nil +} diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh old mode 100644 new mode 100755 diff --git a/tests/tests.go b/tests/tests.go new file mode 100644 index 00000000..ca8701d2 --- /dev/null +++ b/tests/tests.go @@ -0,0 +1 @@ +package tests From 8357326db011b1b30bc13392423e953a815d95cf Mon Sep 17 00:00:00 2001 From: Krzysztof Jurewicz Date: Fri, 20 Oct 2017 18:44:37 +0200 Subject: [PATCH 388/545] Fix test command --- cmd/abci-cli/abci-cli.go | 43 ++++++++++++++++++++++++---------------- tests/server/client.go | 39 ++++++++++++++++-------------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 9e8e86b9..3ee454aa 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -16,6 +16,7 @@ import ( "github.com/tendermint/tmlibs/log" abcicli "github.com/tendermint/abci/client" + "github.com/tendermint/abci/example/code" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" @@ -274,10 +275,10 @@ var dummyCmd = &cobra.Command{ } var testCmd = &cobra.Command{ - Use: "test", + Use: "test", Short: "Run integration tests", - Long: "", - Args: cobra.ExactArgs(0), + Long: "", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { return cmdTest(cmd, args) }, @@ -299,6 +300,14 @@ func persistentArgs(line []byte) []string { //-------------------------------------------------------------------------------- +func or(err1 error, err2 error) error { + if err1 == nil { + return err2 + } else { + return err1 + } +} + func cmdTest(cmd *cobra.Command, args []string) error { fmt.Println("Running tests") @@ -306,34 +315,34 @@ func cmdTest(cmd *cobra.Command, args []string) error { err = servertest.InitChain(client) fmt.Println("") - err = servertest.SetOption(client, "serial", "on") + err = or(err, servertest.SetOption(client, "serial", "on")) fmt.Println("") - err = servertest.Commit(client, nil) + err = or(err, servertest.Commit(client, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte("abc"), types.CodeType_BadNonce, nil) + err = or(err, servertest.DeliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil)) fmt.Println("") - err = servertest.Commit(client, nil) + err = or(err, servertest.Commit(client, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x00}, types.CodeType_OK, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeOK, nil)) fmt.Println("") - err = servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) + err = or(err, servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1})) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x00}, types.CodeType_BadNonce, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x01}, types.CodeType_OK, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x01}, code.CodeTypeOK, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x00, 0x02}, types.CodeType_OK, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x02}, code.CodeTypeOK, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x00, 0x03}, types.CodeType_OK, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x03}, code.CodeTypeOK, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, types.CodeType_OK, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, code.CodeTypeOK, nil)) fmt.Println("") - err = servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, types.CodeType_BadNonce, nil) + err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil)) fmt.Println("") - err = servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) + err = or(err, servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5})) if err != nil { - return errors.New("Some checks didn't pass, please use the cli to see the exact failures.") + return errors.New("Some checks didn't pass, please inspect stdout to see the exact failures.") } return nil } diff --git a/tests/server/client.go b/tests/server/client.go index 502e4e8e..f1757fe1 100644 --- a/tests/server/client.go +++ b/tests/server/client.go @@ -17,9 +17,9 @@ func InitChain(client abcicli.Client) error { for i := 0; i < total; i++ { pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() power := cmn.RandInt() - vals[i] = &types.Validator{pubkey, uint64(power)} + vals[i] = &types.Validator{pubkey, int64(power)} } - err := client.InitChainSync(vals) + _, err := client.InitChainSync(types.RequestInitChain{Validators: vals}) if err != nil { fmt.Println("Failed test: InitChain - %v", err) return err @@ -29,38 +29,38 @@ func InitChain(client abcicli.Client) error { } func SetOption(client abcicli.Client, key, value string) error { - res := client.SetOptionSync(key, value) - _, _, log := res.Code, res.Data, res.Log - if res.IsErr() { + res, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: value}) + log := res.GetLog() + if err != nil { fmt.Println("Failed test: SetOption") fmt.Printf("setting %v=%v: \nlog: %v", key, value, log) fmt.Println("Failed test: SetOption") - return errors.New(res.Error()) + return err } fmt.Println("Passed test: SetOption") return nil } func Commit(client abcicli.Client, hashExp []byte) error { - res := client.CommitSync() - _, data, log := res.Code, res.Data, res.Log - if res.IsErr() { + res, err := client.CommitSync() + _, data := res.Code, res.Data + if err != nil { fmt.Println("Failed test: Commit") - fmt.Printf("committing %v\nlog: %v", log) - return errors.New(res.Error()) + fmt.Printf("committing %v\nlog: %v", res.GetLog()) + return err } - if !bytes.Equal(res.Data, hashExp) { + if !bytes.Equal(data, hashExp) { fmt.Println("Failed test: Commit") fmt.Printf("Commit hash was unexpected. Got %X expected %X", - data, hashExp) + data.Bytes(), hashExp) return errors.New("CommitTx failed") } fmt.Println("Passed test: Commit") return nil } -func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) error { - res := client.DeliverTxSync(txBytes) +func DeliverTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) error { + res, _ := client.DeliverTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log if code != codeExp { fmt.Println("Failed test: DeliverTx") @@ -78,14 +78,9 @@ func DeliverTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, da return nil } -func CheckTx(client abcicli.Client, txBytes []byte, codeExp types.CodeType, dataExp []byte) error { - res := client.CheckTxSync(txBytes) +func CheckTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) error { + res, _ := client.CheckTxSync(txBytes) code, data, log := res.Code, res.Data, res.Log - if res.IsErr() { - fmt.Println("Failed test: CheckTx") - fmt.Printf("checking tx %X: %v\nlog: %v", txBytes, log) - return errors.New(res.Error()) - } if code != codeExp { fmt.Println("Failed test: CheckTx") fmt.Printf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", From f6e22e42960e32c91a050529b712ed64e13947fa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 5 Dec 2017 17:22:06 -0500 Subject: [PATCH 389/545] update readme for notes about grpc --- README.md | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1b7f8900..5ab2bfbb 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,12 @@ [![CircleCI](https://circleci.com/gh/tendermint/abci.svg?style=svg)](https://circleci.com/gh/tendermint/abci) -Blockchains are a system for multi-master state machine replication. +Blockchains are systems for multi-master state machine replication. **ABCI** is an interface that defines the boundary between the replication engine (the blockchain), and the state machine (the application). By using a socket protocol, we enable a consensus engine running in one process to manage an application state running in another. -## Install - -``` -go get github.com/tendermint/abci -cd $GOPATH/src/github.com/tendermint/abci -make get_vendor_deps -make install -``` - For background information on ABCI, motivations, and tendermint, please visit [the documentation](http://tendermint.readthedocs.io/en/master/). The two guides to focus on are the `Application Development Guide` and `Using ABCI-CLI`. @@ -28,9 +19,17 @@ The community has provided a number of addtional implementations, see the `Tende We provide three implementations of the ABCI in Go: +- Golang in-process - ABCI-socket - GRPC -- Golang in-process + +Note the GRPC version is maintained primarily to simplify onboarding and prototyping and is not receiving the same +attention to security and performance as the others. + +### In Process + +The simplest implementation just uses function calls within Go. +This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. ### Socket @@ -45,15 +44,10 @@ For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), th GRPC is an rpc framework native to Protocol Buffers with support in many languages. Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than -the ordered, asynchronous socket protocol. +the ordered, asynchronous socket protocol. The implementation has also not received as much testing or review. Note the length-prefixing used in the socket implementation does not apply for GRPC. -### In Process - -The simplest implementation just uses function calls within Go. -This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. - ## Example Apps The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. @@ -64,6 +58,15 @@ Multiple example apps are included: - the `abci-cli dummy` application, which illustrates a simple key-value merkle tree - the `abci-cli dummy --persistent` application, which augments the dummy with persistence and validator set changes +### Install + +``` +go get github.com/tendermint/abci +cd $GOPATH/src/github.com/tendermint/abci +make get_vendor_deps +make install +``` + ## Specification The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers. From fff8e963f89fe00a5b529e3a06b5babb94b69996 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 5 Dec 2017 17:45:26 -0500 Subject: [PATCH 390/545] update readme --- README.md | 53 +++++++---------------------------------------------- 1 file changed, 7 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index adf9e9ef..83c4e33b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ attention to security and performance as the others. The simplest implementation just uses function calls within Go. This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. -### Socket +### Socket (TSP) ABCI is best implemented as a streaming protocol. The socket implementation provides for asynchronous, ordered message passing over unix or tcp. @@ -48,11 +48,15 @@ the ordered, asynchronous socket protocol. The implementation has also not recei Note the length-prefixing used in the socket implementation does not apply for GRPC. -## Example Apps +## Tools -The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. +The `abci-cli` tool wraps an ABCI client and can be used for probing/testing an ABCI server. +For instance, `abci-cli test` will run a test sequence against a listening server running the Counter application (see below). +It can also be used to run some example applications. See [the documentation](http://tendermint.readthedocs.io/en/master/) for more details. +### Example Apps + Multiple example apps are included: - the `abci-cli counter` application, which illustrates nonce checking in txs - the `abci-cli dummy` application, which illustrates a simple key-value merkle tree @@ -196,46 +200,3 @@ Here, we describe the requests and responses as function arguments and return va * __Usage__:
* Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. -# Implementation - -We provide three implementations of the ABCI in Go: - -1. ABCI-socket -2. GRPC -3. Golang in-process - -## Socket - -ABCI is best implemented as a streaming protocol. -The socket implementation provides for asynchronous, ordered message passing over unix or tcp. -Messages are serialized using Protobuf3 and length-prefixed. -Protobuf3 doesn't have an official length-prefix standard, so we use our own. The first byte represents the length of the big-endian encoded length. - -For example, if the Protobuf3 encoded ABCI message is `0xDEADBEEF` (4 bytes), the length-prefixed message is `0x0104DEADBEEF`. If the Protobuf3 encoded ABCI message is 65535 bytes long, the length-prefixed message would be like `0x02FFFF...`. - -## GRPC - -GRPC is an rpc framework native to Protocol Buffers with support in many languages. -Implementing the ABCI using GRPC can allow for faster prototyping, but is expected to be much slower than -the ordered, asynchronous socket protocol. - -Note the length-prefixing used in the socket implementation does not apply for GRPC. - -## In Process - -The simplest implementation just uses function calls within Go. -This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary. - - -# Tools and Apps - -The `abci-cli` tool wraps any ABCI client and can be used for probing/testing an ABCI application. -See the [guide](https://tendermint.readthedocs.io/en/master/abci-cli.html) for more details. - -Multiple example apps are included: -- the `counter` application, which illustrates nonce checking in txs -- the `dummy` application, which illustrates a simple key-value merkle tree -- the `dummy --persistent` application, which augments the dummy with persistence and validator set changes - -When you are developing an implementation of the ABCI server in your favourite language, we provide the `abci-cli test` -command that allows you to run our tests against your own ABCI server. Please make sure that your server supports at least the TSP protocol, and optionally gRPC. From 1b2c383205e6bffc5b1cbffc35b663096c6920cd Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 5 Dec 2017 18:41:48 -0500 Subject: [PATCH 391/545] ResponseSetOption includes a response Code. Closes #64" --- CHANGELOG.md | 1 + README.md | 1 + cmd/abci-cli/abci-cli.go | 3 +- example/code/code.go | 2 + example/counter/counter.go | 10 +- types/application.go | 2 +- types/types.pb.go | 202 +++++++++++++++++++------------------ types/types.proto | 3 +- 8 files changed, 123 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d66384d..029067a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ BREAKING CHANGES: - [types] `pubKey` -> `pub_key` - [types] `uint64` -> `int32` for `Header.num_txs` and `PartSetHeader.total` - [types] `uint64` -> `int64` for everything else + - [types] ResponseSetOption includes error code - [abci-cli] codes are printed as their number instead of a message, except for `code == 0`, which is still printed as `OK` FEATURES: diff --git a/README.md b/README.md index 83c4e33b..46abcc4f 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,7 @@ Here, we describe the requests and responses as function arguments and return va * `Key (string)`: Key to set * `Value (string)`: Value to set for key * __Returns__: + * `Code (uint32)`: Response code * `Log (string)`: Debug or error message * __Usage__:
Set application options. E.g. Key="mode", Value="mempool" for a mempool connection, or Key="mode", Value="consensus" for a consensus connection. diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 3ee454aa..18437ff7 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -429,7 +429,8 @@ func cmdSetOption(cmd *cobra.Command, args []string) error { return err } printResponse(cmd, args, response{ - Log: res.Log, + Code: res.Code, + Log: res.Log, }) return nil } diff --git a/example/code/code.go b/example/code/code.go index 94e9d015..b7e37d36 100644 --- a/example/code/code.go +++ b/example/code/code.go @@ -6,4 +6,6 @@ const ( CodeTypeEncodingError uint32 = 1 CodeTypeBadNonce uint32 = 2 CodeTypeUnauthorized uint32 = 3 + + CodeTypeBadOption uint32 = 101 ) diff --git a/example/counter/counter.go b/example/counter/counter.go index 0978799e..abd7bb18 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -29,8 +29,16 @@ func (app *CounterApplication) SetOption(req types.RequestSetOption) types.Respo key, value := req.Key, req.Value if key == "serial" && value == "on" { app.serial = true + } else { + return types.ResponseSetOption{ + Code: code.CodeTypeBadOption, + Log: cmn.Fmt("Unknown key (%s) or value (%s)", key, value), + } + } + + return types.ResponseSetOption{ + Code: code.CodeTypeOK, } - return types.ResponseSetOption{} } func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { diff --git a/types/application.go b/types/application.go index 6c0b8bd0..c8ea19c3 100644 --- a/types/application.go +++ b/types/application.go @@ -42,7 +42,7 @@ func (BaseApplication) Info(req RequestInfo) ResponseInfo { } func (BaseApplication) SetOption(req RequestSetOption) ResponseSetOption { - return ResponseSetOption{} + return ResponseSetOption{Code: CodeTypeOK} } func (BaseApplication) DeliverTx(tx []byte) ResponseDeliverTx { diff --git a/types/types.pb.go b/types/types.pb.go index 9233a05c..69777d6d 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1212,7 +1212,8 @@ func (m *ResponseInfo) GetLastBlockAppHash() []byte { } type ResponseSetOption struct { - Log string `protobuf:"bytes,1,opt,name=log,proto3" json:"log,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Log string `protobuf:"bytes,2,opt,name=log,proto3" json:"log,omitempty"` } func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } @@ -1220,6 +1221,13 @@ func (m *ResponseSetOption) String() string { return proto.CompactTex func (*ResponseSetOption) ProtoMessage() {} func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} } +func (m *ResponseSetOption) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + func (m *ResponseSetOption) GetLog() string { if m != nil { return m.Log @@ -2059,101 +2067,101 @@ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ // 1554 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0xcb, 0x6e, 0xdb, 0x46, - 0x17, 0xc7, 0x2d, 0x51, 0xd4, 0xe5, 0xf8, 0x26, 0x8f, 0xfd, 0x25, 0x8a, 0xb2, 0x88, 0x43, 0x20, - 0x5f, 0xe4, 0x5c, 0xac, 0x7c, 0x0e, 0xf2, 0x21, 0x4e, 0x8a, 0x02, 0x56, 0x9c, 0x54, 0x42, 0x80, - 0x34, 0x9d, 0x18, 0xd9, 0x0a, 0x94, 0x38, 0x92, 0x88, 0x48, 0x24, 0x43, 0x8e, 0x1c, 0xb9, 0xe8, - 0x23, 0x64, 0xdf, 0x75, 0xbb, 0x29, 0xd0, 0x17, 0xe8, 0xb2, 0xbb, 0xa2, 0xcf, 0xd0, 0x45, 0x9e, - 0xa5, 0x98, 0x33, 0xc3, 0xab, 0xc9, 0x2c, 0xb2, 0xc8, 0xc6, 0x98, 0xcb, 0xf9, 0x8f, 0xce, 0x0c, - 0xcf, 0xfc, 0xce, 0x19, 0xc3, 0x0e, 0xbf, 0xf0, 0x58, 0xd0, 0xc5, 0xbf, 0x87, 0x9e, 0xef, 0x72, - 0x97, 0xe8, 0xd8, 0x69, 0xdf, 0x9f, 0xda, 0x7c, 0xb6, 0x1c, 0x1d, 0x8e, 0xdd, 0x45, 0x77, 0xea, - 0x4e, 0xdd, 0x2e, 0xce, 0x8e, 0x96, 0x13, 0xec, 0x61, 0x07, 0x5b, 0x52, 0x65, 0xfc, 0x55, 0x81, - 0x1a, 0x65, 0xef, 0x97, 0x2c, 0xe0, 0xa4, 0x03, 0x15, 0x36, 0x9e, 0xb9, 0xad, 0xd2, 0x7e, 0xa9, - 0xb3, 0x7e, 0x44, 0x0e, 0xe5, 0xea, 0x6a, 0xf6, 0xf9, 0x78, 0xe6, 0xf6, 0xd7, 0x28, 0x5a, 0x90, - 0xbb, 0xa0, 0x4f, 0xe6, 0xcb, 0x60, 0xd6, 0x2a, 0xa3, 0xe9, 0x6e, 0xda, 0xf4, 0x85, 0x98, 0xea, - 0xaf, 0x51, 0x69, 0x23, 0x96, 0xb5, 0x9d, 0x89, 0xdb, 0xd2, 0xf2, 0x96, 0x1d, 0x38, 0x13, 0x5c, - 0x56, 0x58, 0x90, 0xc7, 0x00, 0x01, 0xe3, 0x43, 0xd7, 0xe3, 0xb6, 0xeb, 0xb4, 0x2a, 0x68, 0x7f, - 0x35, 0x6d, 0xff, 0x86, 0xf1, 0xef, 0x71, 0xba, 0xbf, 0x46, 0x1b, 0x41, 0xd8, 0x11, 0x4a, 0x8b, - 0xcd, 0xed, 0x73, 0xe6, 0x0f, 0xf9, 0xaa, 0xa5, 0xe7, 0x29, 0x4f, 0xe5, 0xfc, 0xd9, 0x4a, 0x28, - 0xad, 0xb0, 0x43, 0x8e, 0xa0, 0x3e, 0x9e, 0xb1, 0xf1, 0x3b, 0xa1, 0xab, 0xa2, 0xee, 0x3f, 0x69, - 0xdd, 0x33, 0x31, 0x8b, 0xaa, 0xda, 0x58, 0x36, 0xc9, 0x21, 0x54, 0xc7, 0xee, 0x62, 0x61, 0xf3, - 0x56, 0x0d, 0x15, 0x7b, 0x19, 0x05, 0xce, 0xf5, 0xd7, 0xa8, 0xb2, 0x12, 0xc7, 0xf5, 0x7e, 0xc9, - 0xfc, 0x8b, 0x56, 0x3d, 0xef, 0xb8, 0x7e, 0x10, 0x53, 0xe2, 0xb8, 0xd0, 0x46, 0x6c, 0xc5, 0x76, - 0x6c, 0x3e, 0x1c, 0xcf, 0x4c, 0xdb, 0x69, 0x35, 0xf2, 0xb6, 0x32, 0x70, 0x6c, 0xfe, 0x4c, 0x4c, - 0x8b, 0xad, 0xd8, 0x61, 0x87, 0x3c, 0x85, 0xf5, 0x11, 0x9b, 0xda, 0xce, 0x70, 0x34, 0x77, 0xc7, - 0xef, 0x5a, 0x80, 0xd2, 0x56, 0x5a, 0xda, 0x13, 0x06, 0x3d, 0x31, 0xdf, 0x5f, 0xa3, 0x30, 0x8a, - 0x7a, 0xe4, 0x11, 0x34, 0x98, 0x63, 0x29, 0xe9, 0x3a, 0x4a, 0xaf, 0x64, 0x22, 0xc0, 0xb1, 0x42, - 0x61, 0x9d, 0xa9, 0x76, 0xaf, 0x06, 0xfa, 0xb9, 0x39, 0x5f, 0x32, 0xe3, 0x36, 0xac, 0x27, 0x22, - 0x85, 0xb4, 0xa0, 0xb6, 0x60, 0x41, 0x60, 0x4e, 0x19, 0x86, 0x53, 0x83, 0x86, 0x5d, 0x63, 0x0b, - 0x36, 0x92, 0x71, 0x92, 0x10, 0x8a, 0x58, 0x10, 0xc2, 0x73, 0xe6, 0x07, 0x22, 0x00, 0x94, 0x50, - 0x75, 0x8d, 0x27, 0xd0, 0xcc, 0x06, 0x01, 0x69, 0x82, 0xf6, 0x8e, 0x5d, 0x28, 0x4b, 0xd1, 0x24, - 0x7b, 0xca, 0x21, 0x0c, 0xcd, 0x06, 0x55, 0xde, 0x19, 0x91, 0x36, 0x0a, 0x03, 0xb2, 0x05, 0x65, - 0xbe, 0x42, 0xe9, 0x06, 0x2d, 0xf3, 0x95, 0xb1, 0x0f, 0x5b, 0xe9, 0x4f, 0x7e, 0xc9, 0xc2, 0x8a, - 0x5c, 0xc7, 0x6f, 0x46, 0x08, 0x54, 0x2c, 0x93, 0x9b, 0xca, 0x02, 0xdb, 0x62, 0xcc, 0x33, 0xf9, - 0x4c, 0xfd, 0x3c, 0xb6, 0xc9, 0x15, 0xa8, 0xce, 0x98, 0x3d, 0x9d, 0x71, 0xbc, 0x03, 0x1a, 0x55, - 0x3d, 0xe1, 0xab, 0xe7, 0xbb, 0xe7, 0x0c, 0x43, 0xbd, 0x4e, 0x65, 0xc7, 0xd8, 0x86, 0xcd, 0x54, - 0x20, 0x19, 0xa7, 0x91, 0xf3, 0xd1, 0x87, 0x27, 0x0f, 0x00, 0xce, 0xcd, 0xb9, 0x6d, 0x99, 0xdc, - 0xf5, 0x83, 0x56, 0x69, 0x5f, 0xeb, 0xac, 0x1f, 0x35, 0xd5, 0xf7, 0x7a, 0x1b, 0x4e, 0xd0, 0x84, - 0x8d, 0xf1, 0x67, 0x09, 0x76, 0x2e, 0x05, 0x81, 0x70, 0x77, 0x66, 0x06, 0xb3, 0x70, 0x0b, 0xa2, - 0x4d, 0x6e, 0x09, 0x77, 0x4d, 0x8b, 0xf9, 0xea, 0x7a, 0x6f, 0xaa, 0x75, 0xfb, 0x38, 0x48, 0xd5, - 0x24, 0xb9, 0x0b, 0x3b, 0xe6, 0x28, 0x60, 0x0e, 0x1f, 0x26, 0x3c, 0xd1, 0xf6, 0xb5, 0x8e, 0x4e, - 0x9b, 0x72, 0x22, 0x72, 0x24, 0x20, 0x3d, 0xd8, 0x1b, 0x5d, 0xfc, 0x68, 0x3a, 0xdc, 0x76, 0x58, - 0xd2, 0xbe, 0x82, 0x9e, 0x6f, 0xab, 0x5f, 0x78, 0x7e, 0x6e, 0x5b, 0xcc, 0x19, 0x33, 0xba, 0x1b, - 0x19, 0xc7, 0x6b, 0x18, 0x07, 0xb0, 0x9d, 0x09, 0xc5, 0xc4, 0xc9, 0x96, 0x92, 0x27, 0x6b, 0x7c, - 0xd4, 0xa1, 0x4e, 0x59, 0xe0, 0xb9, 0x4e, 0xc0, 0xc8, 0x63, 0x68, 0xb0, 0xd5, 0x98, 0x49, 0xaa, - 0x94, 0x32, 0xb7, 0x42, 0xda, 0x3c, 0x0f, 0xe7, 0xc5, 0x8d, 0x8a, 0x8c, 0xc9, 0x81, 0x22, 0x62, - 0x16, 0x73, 0x4a, 0x94, 0x44, 0xe2, 0xbd, 0x10, 0x89, 0x5a, 0x06, 0x09, 0xd2, 0x36, 0xc3, 0xc4, - 0x03, 0xc5, 0xc4, 0x4a, 0xee, 0xc2, 0x29, 0x28, 0x1e, 0xa7, 0xa0, 0xa8, 0xe7, 0xba, 0x5f, 0x40, - 0xc5, 0xe3, 0x14, 0x15, 0xab, 0xb9, 0xd2, 0x02, 0x2c, 0x3e, 0x4c, 0x60, 0xb1, 0x96, 0xa1, 0x81, - 0x14, 0xe6, 0x70, 0xb1, 0x1b, 0x71, 0xb1, 0x9e, 0x21, 0xa9, 0x92, 0x64, 0xc1, 0x78, 0x2f, 0x04, - 0x63, 0x23, 0xf7, 0xd0, 0x32, 0x64, 0x3c, 0x4e, 0x91, 0x11, 0x72, 0xb7, 0x53, 0x80, 0xc6, 0x6f, - 0xd2, 0x68, 0x94, 0x7c, 0xbb, 0x96, 0xd1, 0x16, 0xb2, 0xf1, 0xff, 0x49, 0x36, 0x6e, 0x64, 0x88, - 0xac, 0x62, 0xe1, 0xb3, 0x70, 0x3c, 0x10, 0x57, 0x2f, 0x13, 0x69, 0xe2, 0xf6, 0x33, 0xdf, 0x77, - 0x7d, 0x45, 0x2f, 0xd9, 0x31, 0x3a, 0x82, 0x31, 0x71, 0x7c, 0x7d, 0x06, 0xa4, 0xc8, 0x89, 0x44, - 0x74, 0x19, 0x3f, 0x97, 0x62, 0x2d, 0xb2, 0x34, 0xc9, 0xa7, 0x86, 0xe2, 0x53, 0x82, 0xaf, 0xe5, - 0x14, 0x5f, 0xc9, 0x1d, 0xd8, 0x99, 0x9b, 0x01, 0x97, 0xdb, 0x1c, 0xa6, 0x80, 0xb5, 0x2d, 0x26, - 0xe4, 0xfe, 0x24, 0xb9, 0xee, 0xc3, 0x6e, 0xc2, 0xd6, 0xf4, 0xbc, 0x21, 0x52, 0xa4, 0x82, 0x14, - 0x69, 0x46, 0xd6, 0x27, 0x9e, 0xd7, 0x37, 0x83, 0x99, 0x71, 0x2b, 0xde, 0x7f, 0x8a, 0xdd, 0x73, - 0x77, 0x1a, 0xb2, 0x7b, 0xee, 0x4e, 0x8d, 0x5f, 0x4b, 0xb1, 0x5d, 0xcc, 0x69, 0x02, 0x95, 0xb1, - 0x6b, 0xc9, 0xed, 0x6f, 0x52, 0x6c, 0x93, 0x53, 0xb5, 0x33, 0xb1, 0x85, 0x8d, 0xde, 0x83, 0xbf, - 0x3f, 0xdd, 0x58, 0xfb, 0xe7, 0xd3, 0x8d, 0x4e, 0xa2, 0xf6, 0xe1, 0xcc, 0xb1, 0x98, 0xbf, 0xb0, - 0x1d, 0xde, 0x9d, 0xba, 0xf7, 0x3f, 0xd8, 0x3e, 0xeb, 0x0a, 0xc5, 0x61, 0xef, 0x82, 0xb3, 0x40, - 0x9d, 0x85, 0xf2, 0x40, 0x8b, 0x3c, 0x20, 0x37, 0xa1, 0xc2, 0xcd, 0x69, 0x88, 0xa5, 0x10, 0x7c, - 0x2f, 0xdf, 0xbe, 0x36, 0x6d, 0x9f, 0xe2, 0x94, 0xf1, 0x4b, 0x49, 0x60, 0x28, 0x75, 0x07, 0xbe, - 0xaa, 0x8b, 0x4d, 0xd0, 0xa6, 0x66, 0x80, 0x47, 0xad, 0x51, 0xd1, 0x14, 0x23, 0x13, 0xc6, 0x10, - 0x0d, 0x1a, 0x15, 0x4d, 0xe3, 0x8f, 0x72, 0x1c, 0x1b, 0x51, 0xaa, 0xba, 0xe4, 0xe1, 0x1e, 0xe8, - 0xb6, 0x63, 0xb1, 0x15, 0xba, 0xa8, 0x51, 0xd9, 0x21, 0x3d, 0x99, 0x52, 0xb5, 0x2f, 0x74, 0x1b, - 0x93, 0xf0, 0x8b, 0x30, 0x09, 0x57, 0xbe, 0x70, 0x15, 0x29, 0x17, 0xeb, 0x78, 0xbe, 0xeb, 0x4e, - 0x70, 0x6f, 0x5f, 0xb4, 0x0e, 0xca, 0x13, 0x69, 0xa2, 0x9a, 0x4a, 0xc0, 0xea, 0x74, 0x6b, 0x71, - 0x08, 0xfe, 0x24, 0x8a, 0x80, 0x24, 0xad, 0xbe, 0xe6, 0xb7, 0x35, 0x76, 0xe3, 0xf8, 0x8f, 0x40, - 0x66, 0xec, 0x01, 0xb9, 0x4c, 0x28, 0x59, 0x0d, 0xa5, 0xd9, 0x43, 0xfe, 0x0b, 0xba, 0x65, 0x4f, - 0x26, 0xc5, 0xf5, 0x80, 0x9c, 0x36, 0x7e, 0x2b, 0x43, 0x55, 0x26, 0x73, 0x72, 0x4d, 0x70, 0xde, - 0xb4, 0x9d, 0xa1, 0x6d, 0x85, 0x7c, 0xc1, 0xfe, 0xc0, 0x4a, 0x1c, 0x5a, 0x39, 0x75, 0x68, 0x04, - 0x2a, 0xdc, 0x5e, 0x30, 0x85, 0x06, 0x6c, 0x93, 0xab, 0x50, 0x73, 0x96, 0x8b, 0x21, 0x5f, 0xc9, - 0xc0, 0xd4, 0x69, 0xd5, 0x59, 0x2e, 0xce, 0x56, 0x01, 0x39, 0x82, 0xcd, 0x04, 0x28, 0x6c, 0x4b, - 0x25, 0xb0, 0x2d, 0xe5, 0x1a, 0xfa, 0x3d, 0x38, 0xa5, 0xeb, 0x11, 0x32, 0x06, 0x16, 0xe9, 0x00, - 0x12, 0x64, 0x28, 0x93, 0x84, 0x24, 0x4b, 0x15, 0xc9, 0xb2, 0x25, 0xc6, 0x55, 0x16, 0x11, 0x95, - 0xca, 0x75, 0x68, 0x88, 0x93, 0x94, 0x26, 0x35, 0x34, 0xa9, 0x8b, 0x01, 0x9c, 0xbc, 0x0d, 0xdb, - 0x71, 0xa1, 0x21, 0x4d, 0xea, 0x72, 0x95, 0x78, 0x18, 0x0d, 0xaf, 0x41, 0x3d, 0x22, 0x58, 0x03, - 0x2d, 0x6a, 0xa6, 0x02, 0xd7, 0x00, 0x6a, 0xca, 0xc5, 0xdc, 0x4a, 0xe9, 0x0e, 0xe8, 0x9e, 0xe9, - 0xf3, 0x40, 0x15, 0x08, 0x61, 0xfe, 0x7a, 0x6d, 0xfa, 0xa2, 0x46, 0x55, 0xf5, 0x92, 0x34, 0x31, - 0x8e, 0x61, 0x33, 0x35, 0x2e, 0xae, 0x1f, 0x77, 0xb9, 0x39, 0xc7, 0x15, 0x75, 0x2a, 0x3b, 0xd1, - 0xcf, 0x94, 0xe3, 0x9f, 0x31, 0x9e, 0x40, 0x23, 0xfa, 0x86, 0xe2, 0xa8, 0xbd, 0xe5, 0x68, 0x18, - 0x96, 0xbd, 0x1b, 0xb4, 0xea, 0x2d, 0x47, 0x2f, 0x65, 0xe5, 0xeb, 0xb9, 0x1f, 0x54, 0xd5, 0xa6, - 0x51, 0xd9, 0x31, 0x9e, 0x42, 0x3d, 0xac, 0xaa, 0x8a, 0xa5, 0x05, 0x9f, 0xda, 0xf8, 0xbd, 0x04, - 0x55, 0x09, 0xbf, 0x9c, 0x4a, 0xfb, 0x7f, 0x58, 0x82, 0x2e, 0xd9, 0x50, 0x6c, 0x1a, 0x85, 0x5b, - 0xd1, 0xeb, 0x4e, 0x8a, 0x0e, 0xcf, 0x2e, 0x3c, 0x46, 0x1b, 0x68, 0x25, 0x9a, 0xe4, 0x26, 0x6c, - 0x48, 0x49, 0xc0, 0x7d, 0xdb, 0x09, 0x43, 0x7f, 0x1d, 0xc7, 0xde, 0xe0, 0x90, 0xf8, 0xa4, 0xd2, - 0xc4, 0x76, 0xb8, 0x82, 0x5c, 0x1d, 0x07, 0x06, 0x0e, 0x37, 0xae, 0x43, 0x05, 0xd7, 0x01, 0xa8, - 0xbe, 0x39, 0xa3, 0x83, 0x57, 0xdf, 0x35, 0xd7, 0x48, 0x0d, 0xb4, 0xc1, 0xab, 0xb3, 0x66, 0xe9, - 0xe8, 0xa3, 0x0e, 0xdb, 0x27, 0xbd, 0x67, 0x83, 0x13, 0xcf, 0x9b, 0xdb, 0x63, 0x13, 0x73, 0x4c, - 0x17, 0x2a, 0x98, 0x45, 0x73, 0x1e, 0xb3, 0xed, 0xbc, 0x72, 0x8e, 0x1c, 0x81, 0x8e, 0xc9, 0x94, - 0xe4, 0xbd, 0x69, 0xdb, 0xb9, 0x55, 0x9d, 0xf8, 0x11, 0x99, 0x6e, 0x2f, 0x3f, 0x6d, 0xdb, 0x79, - 0xa5, 0x1d, 0xf9, 0x16, 0x1a, 0x71, 0x1a, 0x2c, 0x7a, 0xe0, 0xb6, 0x0b, 0x8b, 0x3c, 0xa1, 0x8f, - 0xd3, 0x63, 0xd1, 0x33, 0xb7, 0x5d, 0x58, 0xe9, 0x91, 0xc7, 0x50, 0x0b, 0x33, 0x57, 0xfe, 0x63, - 0xb7, 0x5d, 0x50, 0xec, 0x89, 0xe3, 0x91, 0xf9, 0x24, 0xef, 0x0d, 0xdb, 0xce, 0xad, 0xdf, 0xc8, - 0x23, 0xa8, 0x2a, 0x94, 0xe6, 0xbe, 0x93, 0xdb, 0xf9, 0x55, 0xa2, 0xd8, 0x64, 0xfc, 0xdc, 0x29, - 0x7a, 0x00, 0xb7, 0x0b, 0xeb, 0x3f, 0x72, 0x02, 0x90, 0x78, 0xe7, 0x14, 0x3e, 0x83, 0xdb, 0xc5, - 0x55, 0x20, 0x11, 0x77, 0x27, 0x7a, 0x69, 0xe4, 0x3f, 0x86, 0xdb, 0x45, 0x85, 0xe0, 0xa8, 0x8a, - 0xff, 0x60, 0x79, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x15, 0x2f, 0x59, 0xab, 0x11, + 0x17, 0xc7, 0x2d, 0x51, 0xd4, 0xe5, 0xf8, 0x26, 0x8f, 0xfd, 0x25, 0x8a, 0xb2, 0x88, 0x43, 0xe0, + 0x6b, 0xe4, 0x5c, 0xac, 0xd4, 0x41, 0x8a, 0x38, 0x29, 0x0a, 0x58, 0x71, 0x52, 0x09, 0x01, 0xd2, + 0x74, 0x62, 0x64, 0x2b, 0x50, 0xe2, 0x48, 0x22, 0x22, 0x91, 0x0c, 0x39, 0x72, 0xe4, 0xa2, 0x8f, + 0x90, 0x7d, 0xd7, 0xed, 0xa6, 0x40, 0x5f, 0xa0, 0xcb, 0xee, 0x8a, 0x3e, 0x43, 0x17, 0x79, 0x96, + 0x62, 0xce, 0x0c, 0xaf, 0x26, 0xb3, 0xc8, 0x22, 0x1b, 0x63, 0x2e, 0xe7, 0x3f, 0x3a, 0x33, 0x3c, + 0xf3, 0x3b, 0x67, 0x0c, 0x3b, 0xfc, 0xc2, 0x63, 0x41, 0x17, 0xff, 0x1e, 0x7a, 0xbe, 0xcb, 0x5d, + 0xa2, 0x63, 0xa7, 0x7d, 0x6f, 0x6a, 0xf3, 0xd9, 0x72, 0x74, 0x38, 0x76, 0x17, 0xdd, 0xa9, 0x3b, + 0x75, 0xbb, 0x38, 0x3b, 0x5a, 0x4e, 0xb0, 0x87, 0x1d, 0x6c, 0x49, 0x95, 0xf1, 0x77, 0x05, 0x6a, + 0x94, 0xbd, 0x5b, 0xb2, 0x80, 0x93, 0x0e, 0x54, 0xd8, 0x78, 0xe6, 0xb6, 0x4a, 0xfb, 0xa5, 0xce, + 0xfa, 0x11, 0x39, 0x94, 0xab, 0xab, 0xd9, 0x67, 0xe3, 0x99, 0xdb, 0x5f, 0xa3, 0x68, 0x41, 0xee, + 0x80, 0x3e, 0x99, 0x2f, 0x83, 0x59, 0xab, 0x8c, 0xa6, 0xbb, 0x69, 0xd3, 0xe7, 0x62, 0xaa, 0xbf, + 0x46, 0xa5, 0x8d, 0x58, 0xd6, 0x76, 0x26, 0x6e, 0x4b, 0xcb, 0x5b, 0x76, 0xe0, 0x4c, 0x70, 0x59, + 0x61, 0x41, 0x1e, 0x01, 0x04, 0x8c, 0x0f, 0x5d, 0x8f, 0xdb, 0xae, 0xd3, 0xaa, 0xa0, 0xfd, 0xd5, + 0xb4, 0xfd, 0x6b, 0xc6, 0x7f, 0xc0, 0xe9, 0xfe, 0x1a, 0x6d, 0x04, 0x61, 0x47, 0x28, 0x2d, 0x36, + 0xb7, 0xcf, 0x99, 0x3f, 0xe4, 0xab, 0x96, 0x9e, 0xa7, 0x3c, 0x95, 0xf3, 0x67, 0x2b, 0xa1, 0xb4, + 0xc2, 0x0e, 0x39, 0x82, 0xfa, 0x78, 0xc6, 0xc6, 0x6f, 0x85, 0xae, 0x8a, 0xba, 0xff, 0xa5, 0x75, + 0x4f, 0xc5, 0x2c, 0xaa, 0x6a, 0x63, 0xd9, 0x24, 0x87, 0x50, 0x1d, 0xbb, 0x8b, 0x85, 0xcd, 0x5b, + 0x35, 0x54, 0xec, 0x65, 0x14, 0x38, 0xd7, 0x5f, 0xa3, 0xca, 0x4a, 0x1c, 0xd7, 0xbb, 0x25, 0xf3, + 0x2f, 0x5a, 0xf5, 0xbc, 0xe3, 0xfa, 0x51, 0x4c, 0x89, 0xe3, 0x42, 0x1b, 0xb1, 0x15, 0xdb, 0xb1, + 0xf9, 0x70, 0x3c, 0x33, 0x6d, 0xa7, 0xd5, 0xc8, 0xdb, 0xca, 0xc0, 0xb1, 0xf9, 0x53, 0x31, 0x2d, + 0xb6, 0x62, 0x87, 0x1d, 0xf2, 0x04, 0xd6, 0x47, 0x6c, 0x6a, 0x3b, 0xc3, 0xd1, 0xdc, 0x1d, 0xbf, + 0x6d, 0x01, 0x4a, 0x5b, 0x69, 0x69, 0x4f, 0x18, 0xf4, 0xc4, 0x7c, 0x7f, 0x8d, 0xc2, 0x28, 0xea, + 0x91, 0x87, 0xd0, 0x60, 0x8e, 0xa5, 0xa4, 0xeb, 0x28, 0xbd, 0x92, 0x89, 0x00, 0xc7, 0x0a, 0x85, + 0x75, 0xa6, 0xda, 0xbd, 0x1a, 0xe8, 0xe7, 0xe6, 0x7c, 0xc9, 0x8c, 0x5b, 0xb0, 0x9e, 0x88, 0x14, + 0xd2, 0x82, 0xda, 0x82, 0x05, 0x81, 0x39, 0x65, 0x18, 0x4e, 0x0d, 0x1a, 0x76, 0x8d, 0x2d, 0xd8, + 0x48, 0xc6, 0x49, 0x42, 0x28, 0x62, 0x41, 0x08, 0xcf, 0x99, 0x1f, 0x88, 0x00, 0x50, 0x42, 0xd5, + 0x35, 0x1e, 0x43, 0x33, 0x1b, 0x04, 0xa4, 0x09, 0xda, 0x5b, 0x76, 0xa1, 0x2c, 0x45, 0x93, 0xec, + 0x29, 0x87, 0x30, 0x34, 0x1b, 0x54, 0x79, 0x67, 0x44, 0xda, 0x28, 0x0c, 0xc8, 0x16, 0x94, 0xf9, + 0x0a, 0xa5, 0x1b, 0xb4, 0xcc, 0x57, 0xc6, 0x3e, 0x6c, 0xa5, 0x3f, 0xf9, 0x25, 0x0b, 0x2b, 0x72, + 0x1d, 0xbf, 0x19, 0x21, 0x50, 0xb1, 0x4c, 0x6e, 0x2a, 0x0b, 0x6c, 0x8b, 0x31, 0xcf, 0xe4, 0x33, + 0xf5, 0xf3, 0xd8, 0x26, 0x57, 0xa0, 0x3a, 0x63, 0xf6, 0x74, 0xc6, 0xf1, 0x0e, 0x68, 0x54, 0xf5, + 0x84, 0xaf, 0x9e, 0xef, 0x9e, 0x33, 0x0c, 0xf5, 0x3a, 0x95, 0x1d, 0x63, 0x1b, 0x36, 0x53, 0x81, + 0x64, 0x9c, 0x46, 0xce, 0x47, 0x1f, 0x9e, 0xdc, 0x07, 0x38, 0x37, 0xe7, 0xb6, 0x65, 0x72, 0xd7, + 0x0f, 0x5a, 0xa5, 0x7d, 0xad, 0xb3, 0x7e, 0xd4, 0x54, 0xdf, 0xeb, 0x4d, 0x38, 0x41, 0x13, 0x36, + 0xc6, 0x5f, 0x25, 0xd8, 0xb9, 0x14, 0x04, 0xc2, 0xdd, 0x99, 0x19, 0xcc, 0xc2, 0x2d, 0x88, 0x36, + 0xf9, 0xbf, 0x70, 0xd7, 0xb4, 0x98, 0xaf, 0xae, 0xf7, 0xa6, 0x5a, 0xb7, 0x8f, 0x83, 0x54, 0x4d, + 0x92, 0x3b, 0xb0, 0x63, 0x8e, 0x02, 0xe6, 0xf0, 0x61, 0xc2, 0x13, 0x6d, 0x5f, 0xeb, 0xe8, 0xb4, + 0x29, 0x27, 0x22, 0x47, 0x02, 0xd2, 0x83, 0xbd, 0xd1, 0xc5, 0x4f, 0xa6, 0xc3, 0x6d, 0x87, 0x25, + 0xed, 0x2b, 0xe8, 0xf9, 0xb6, 0xfa, 0x85, 0x67, 0xe7, 0xb6, 0xc5, 0x9c, 0x31, 0xa3, 0xbb, 0x91, + 0x71, 0xbc, 0x86, 0x71, 0x00, 0xdb, 0x99, 0x50, 0x4c, 0x9c, 0x6c, 0x29, 0x79, 0xb2, 0xc6, 0x07, + 0x1d, 0xea, 0x94, 0x05, 0x9e, 0xeb, 0x04, 0x8c, 0x3c, 0x82, 0x06, 0x5b, 0x8d, 0x99, 0xa4, 0x4a, + 0x29, 0x73, 0x2b, 0xa4, 0xcd, 0xb3, 0x70, 0x5e, 0xdc, 0xa8, 0xc8, 0x98, 0x1c, 0x28, 0x22, 0x66, + 0x31, 0xa7, 0x44, 0x49, 0x24, 0xde, 0x0d, 0x91, 0xa8, 0x65, 0x90, 0x20, 0x6d, 0x33, 0x4c, 0x3c, + 0x50, 0x4c, 0xac, 0xe4, 0x2e, 0x9c, 0x82, 0xe2, 0x71, 0x0a, 0x8a, 0x7a, 0xae, 0xfb, 0x05, 0x54, + 0x3c, 0x4e, 0x51, 0xb1, 0x9a, 0x2b, 0x2d, 0xc0, 0xe2, 0x83, 0x04, 0x16, 0x6b, 0x19, 0x1a, 0x48, + 0x61, 0x0e, 0x17, 0xbb, 0x11, 0x17, 0xeb, 0x19, 0x92, 0x2a, 0x49, 0x16, 0x8c, 0x77, 0x43, 0x30, + 0x36, 0x72, 0x0f, 0x2d, 0x43, 0xc6, 0xe3, 0x14, 0x19, 0x21, 0x77, 0x3b, 0x05, 0x68, 0xfc, 0x36, + 0x8d, 0x46, 0xc9, 0xb7, 0x6b, 0x19, 0x6d, 0x21, 0x1b, 0xbf, 0x49, 0xb2, 0x71, 0x23, 0x43, 0x64, + 0x15, 0x0b, 0x9f, 0x84, 0xe3, 0x81, 0xb8, 0x7a, 0x99, 0x48, 0x13, 0xb7, 0x9f, 0xf9, 0xbe, 0xeb, + 0x2b, 0x7a, 0xc9, 0x8e, 0xd1, 0x11, 0x8c, 0x89, 0xe3, 0xeb, 0x13, 0x20, 0x45, 0x4e, 0x24, 0xa2, + 0xcb, 0xf8, 0xa5, 0x14, 0x6b, 0x91, 0xa5, 0x49, 0x3e, 0x35, 0x14, 0x9f, 0x12, 0x7c, 0x2d, 0xa7, + 0xf8, 0x4a, 0x6e, 0xc3, 0xce, 0xdc, 0x0c, 0xb8, 0xdc, 0xe6, 0x30, 0x05, 0xac, 0x6d, 0x31, 0x21, + 0xf7, 0x27, 0xc9, 0x75, 0x0f, 0x76, 0x13, 0xb6, 0xa6, 0xe7, 0x0d, 0x91, 0x22, 0x15, 0xa4, 0x48, + 0x33, 0xb2, 0x3e, 0xf1, 0xbc, 0xbe, 0x19, 0xcc, 0x8c, 0xe3, 0x78, 0xff, 0x31, 0xbb, 0x09, 0x54, + 0xc6, 0xae, 0x25, 0xb7, 0xb5, 0x49, 0xb1, 0x2d, 0x78, 0x3e, 0x77, 0xa7, 0xca, 0x33, 0xd1, 0x34, + 0x7e, 0x2b, 0xc5, 0xda, 0x98, 0xdd, 0x79, 0xda, 0x53, 0xb5, 0x5b, 0x21, 0xde, 0xe8, 0xdd, 0xff, + 0xe7, 0xe3, 0x8d, 0xb5, 0x7f, 0x3f, 0xde, 0xe8, 0x24, 0xea, 0x21, 0xce, 0x1c, 0x8b, 0xf9, 0x0b, + 0xdb, 0xe1, 0xdd, 0xa9, 0x7b, 0xef, 0xbd, 0xed, 0xb3, 0xae, 0x50, 0x1c, 0xf6, 0x2e, 0x38, 0x0b, + 0xd4, 0xf9, 0x28, 0x0f, 0xb4, 0xc8, 0x03, 0x72, 0x13, 0x2a, 0xdc, 0x9c, 0x86, 0xa8, 0x0a, 0x61, + 0xf8, 0xe2, 0xcd, 0x2b, 0xd3, 0xf6, 0x29, 0x4e, 0x19, 0xbf, 0x96, 0x04, 0x9a, 0x52, 0xf7, 0xe2, + 0x8b, 0xba, 0xd8, 0x04, 0x6d, 0x6a, 0x06, 0x78, 0xfc, 0x1a, 0x15, 0x4d, 0x31, 0x32, 0x61, 0x0c, + 0x71, 0xa1, 0x51, 0xd1, 0x34, 0xfe, 0x2c, 0xc7, 0xf1, 0x12, 0xa5, 0xaf, 0x4b, 0x1e, 0xee, 0x81, + 0x6e, 0x3b, 0x16, 0x5b, 0xa1, 0x8b, 0x1a, 0x95, 0x1d, 0xd2, 0x93, 0x69, 0x56, 0xfb, 0x4c, 0xb7, + 0x31, 0x31, 0x3f, 0x0f, 0x13, 0x73, 0xe5, 0x33, 0x57, 0x91, 0x72, 0xb1, 0x8e, 0xe7, 0xbb, 0xee, + 0x04, 0xf7, 0xf6, 0x59, 0xeb, 0xa0, 0x3c, 0x91, 0x3a, 0xaa, 0xa9, 0xa4, 0xac, 0x4e, 0xb7, 0x16, + 0x87, 0xe0, 0xcf, 0xa2, 0x30, 0x48, 0x12, 0xec, 0x4b, 0x7e, 0x5b, 0x63, 0x37, 0x8e, 0xff, 0x08, + 0x6e, 0xc6, 0x1e, 0x90, 0xcb, 0xd4, 0x92, 0x15, 0x52, 0x9a, 0x47, 0xe4, 0x2b, 0xd0, 0x2d, 0x7b, + 0x32, 0x29, 0xae, 0x11, 0xe4, 0xb4, 0xf1, 0x7b, 0x19, 0xaa, 0x32, 0xc1, 0x93, 0x6b, 0x82, 0xfd, + 0xa6, 0xed, 0x0c, 0x6d, 0x2b, 0x64, 0x0e, 0xf6, 0x07, 0x56, 0xe2, 0xd0, 0xca, 0xa9, 0x43, 0x23, + 0x50, 0xe1, 0xf6, 0x82, 0x29, 0x5c, 0x60, 0x9b, 0x5c, 0x85, 0x9a, 0xb3, 0x5c, 0x0c, 0xf9, 0x4a, + 0x06, 0xa6, 0x4e, 0xab, 0xce, 0x72, 0x71, 0xb6, 0x0a, 0xc8, 0x11, 0x6c, 0x26, 0xe0, 0x61, 0x5b, + 0x2a, 0xa9, 0x6d, 0x29, 0xd7, 0xd0, 0xef, 0xc1, 0x29, 0x5d, 0x8f, 0x30, 0x32, 0xb0, 0x48, 0x07, + 0x90, 0x2a, 0x43, 0x99, 0x38, 0x24, 0x6d, 0xaa, 0x48, 0x9b, 0x2d, 0x31, 0xae, 0x32, 0x8b, 0xa8, + 0x5e, 0xae, 0x43, 0x43, 0x9c, 0xa4, 0x34, 0xa9, 0xa1, 0x49, 0x5d, 0x0c, 0xe0, 0xe4, 0x2d, 0xd8, + 0x8e, 0x8b, 0x0f, 0x69, 0x52, 0x97, 0xab, 0xc4, 0xc3, 0x68, 0x78, 0x0d, 0xea, 0x11, 0xd5, 0x1a, + 0x68, 0x51, 0x33, 0x15, 0xcc, 0x06, 0x50, 0x53, 0x2e, 0xe6, 0x56, 0x4f, 0xb7, 0x41, 0xf7, 0x4c, + 0x9f, 0x07, 0xaa, 0x68, 0x08, 0x73, 0xda, 0x2b, 0xd3, 0x17, 0x75, 0xab, 0xaa, 0xa1, 0xa4, 0x89, + 0x71, 0x0c, 0x9b, 0xa9, 0x71, 0x71, 0xfd, 0xb8, 0xcb, 0xcd, 0x39, 0xae, 0xa8, 0x53, 0xd9, 0x89, + 0x7e, 0xa6, 0x1c, 0xff, 0x8c, 0xf1, 0x18, 0x1a, 0xd1, 0x37, 0x14, 0x47, 0xed, 0x2d, 0x47, 0xc3, + 0xb0, 0x14, 0xde, 0xa0, 0x55, 0x6f, 0x39, 0x7a, 0x21, 0xab, 0x61, 0xcf, 0x7d, 0xaf, 0x2a, 0x39, + 0x8d, 0xca, 0x8e, 0xf1, 0x04, 0xea, 0x61, 0xa5, 0x55, 0x2c, 0x2d, 0xf8, 0xd4, 0xc6, 0x1f, 0x25, + 0xa8, 0x4a, 0xf8, 0xe5, 0x54, 0xdf, 0x5f, 0x63, 0x59, 0xba, 0x64, 0x43, 0xb1, 0x69, 0x14, 0x6e, + 0x45, 0x2f, 0x3e, 0x29, 0x3a, 0x3c, 0xbb, 0xf0, 0x18, 0x6d, 0xa0, 0x95, 0x68, 0x92, 0x9b, 0xb0, + 0x21, 0x25, 0x01, 0xf7, 0x6d, 0x27, 0x0c, 0xfd, 0x75, 0x1c, 0x7b, 0x8d, 0x43, 0xe2, 0x93, 0x4a, + 0x13, 0xdb, 0xe1, 0x0a, 0x72, 0x75, 0x1c, 0x18, 0x38, 0xdc, 0xb8, 0x0e, 0x15, 0x5c, 0x07, 0xa0, + 0xfa, 0xfa, 0x8c, 0x0e, 0x5e, 0x7e, 0xdf, 0x5c, 0x23, 0x35, 0xd0, 0x06, 0x2f, 0xcf, 0x9a, 0xa5, + 0xa3, 0x0f, 0x3a, 0x6c, 0x9f, 0xf4, 0x9e, 0x0e, 0x4e, 0x3c, 0x6f, 0x6e, 0x8f, 0x4d, 0xcc, 0x3b, + 0x5d, 0xa8, 0x60, 0x66, 0xcd, 0x79, 0xe0, 0xb6, 0xf3, 0x4a, 0x3c, 0x72, 0x04, 0x3a, 0x26, 0x58, + 0x92, 0xf7, 0xce, 0x6d, 0xe7, 0x56, 0x7a, 0xe2, 0x47, 0x64, 0x0a, 0xbe, 0xfc, 0xdc, 0x6d, 0xe7, + 0x95, 0x7b, 0xe4, 0x3b, 0x68, 0xc4, 0xa9, 0xb1, 0xe8, 0xd1, 0xdb, 0x2e, 0x2c, 0xfc, 0x84, 0x3e, + 0x4e, 0x8f, 0x45, 0x4f, 0xdf, 0x76, 0x61, 0xf5, 0x47, 0x1e, 0x41, 0x2d, 0xcc, 0x5c, 0xf9, 0x0f, + 0xe0, 0x76, 0x41, 0x01, 0x28, 0x8e, 0x47, 0xe6, 0x93, 0xbc, 0x77, 0x6d, 0x3b, 0xb7, 0xa6, 0x23, + 0x0f, 0xa1, 0xaa, 0x50, 0x9a, 0xfb, 0x76, 0x6e, 0xe7, 0x57, 0x8e, 0x62, 0x93, 0xf1, 0x13, 0xa8, + 0xe8, 0x51, 0xdc, 0x2e, 0xac, 0x09, 0xc9, 0x09, 0x40, 0xe2, 0xed, 0x53, 0xf8, 0x34, 0x6e, 0x17, + 0x57, 0x86, 0x44, 0xdc, 0x9d, 0xe8, 0xf5, 0x91, 0xff, 0x40, 0x6e, 0x17, 0x15, 0x87, 0xa3, 0x2a, + 0xfe, 0xd3, 0xe5, 0xc1, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x6a, 0x92, 0xbf, 0x11, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 2424474d..516cca15 100644 --- a/types/types.proto +++ b/types/types.proto @@ -114,7 +114,8 @@ message ResponseInfo { } message ResponseSetOption{ - string log = 1; + uint32 code = 1; + string log = 2; } message ResponseDeliverTx{ From e1ee4d6bf5067c366acb484393da17e395fa4332 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Dec 2017 01:56:39 -0500 Subject: [PATCH 392/545] types: add MarshalJSON funcs for Response types with a Code --- types/messages_test.go | 8 ++++++++ types/result.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/types/messages_test.go b/types/messages_test.go index 607215be..32f09623 100644 --- a/types/messages_test.go +++ b/types/messages_test.go @@ -2,12 +2,20 @@ package types import ( "bytes" + "encoding/json" + "strings" "testing" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" ) +func TestMarshalJSON(t *testing.T) { + b, err := json.Marshal(&ResponseDeliverTx{}) + assert.Nil(t, err) + assert.True(t, strings.Contains(string(b), "code")) +} + func TestWriteReadMessage(t *testing.T) { cases := []proto.Message{ &Header{ diff --git a/types/result.go b/types/result.go index cb2fb7a3..1963520d 100644 --- a/types/result.go +++ b/types/result.go @@ -2,6 +2,8 @@ package types import ( "fmt" + + "github.com/gogo/protobuf/jsonpb" ) const ( @@ -71,3 +73,36 @@ func (r ResponseQuery) Error() string { func fmtError(code uint32, log string) string { return fmt.Sprintf("Error code (%d): %s", code, log) } + +//--------------------------------------------------------------------------- +// override JSON marshalling so we dont emit defaults (ie. disable omitempty) + +func (r *ResponseSetOption) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{EmitDefaults: true} + s, err := m.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseCheckTx) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{EmitDefaults: true} + s, err := m.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseDeliverTx) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{EmitDefaults: true} + s, err := m.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseQuery) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{EmitDefaults: true} + s, err := m.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseCommit) MarshalJSON() ([]byte, error) { + m := jsonpb.Marshaler{EmitDefaults: true} + s, err := m.MarshalToString(r) + return []byte(s), err +} From f860c33515cd06a1dd65af9062bc5cdc6b35e63c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Dec 2017 02:33:35 -0500 Subject: [PATCH 393/545] changelog and version --- CHANGELOG.md | 2 +- version/version.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 029067a0..47bf9293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.8.0 (TBD) +## 0.8.0 (December 6, 2017) BREAKING CHANGES: - [client] all XxxSync methods now return (ResponseXxx, error) diff --git a/version/version.go b/version/version.go index e02653d8..c0699526 100644 --- a/version/version.go +++ b/version/version.go @@ -3,7 +3,7 @@ package version // NOTE: we should probably be versioning the ABCI and the abci-cli separately const Maj = "0" -const Min = "7" -const Fix = "1" +const Min = "8" +const Fix = "0" -const Version = "0.7.1" +const Version = "0.8.0" From 293cf5e63426fcd9c50f5b20018ee03bfb9dae1d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Dec 2017 02:41:14 -0500 Subject: [PATCH 394/545] minor fix [ci skip] --- CHANGELOG.md | 1 + tests/client_server_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47bf9293..64c0cbce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ FEATURES: - [types] RequestBeginBlock: added `absent_validators` and `byzantine_validators` fields - [dummy] DeliverTx returns an owner tag and a key tag - [abci-cli] added `log_level` flag to control the logger + - [abci-cli] introduce `abci-cli test` command for simple testing of ABCI server implementations via Counter application ## 0.7.1 (November 14, 2017) diff --git a/tests/client_server_test.go b/tests/client_server_test.go index 646c8b60..3d74478b 100644 --- a/tests/client_server_test.go +++ b/tests/client_server_test.go @@ -1,4 +1,4 @@ -package main +package tests import ( "testing" From 47216538fd160531769af3fc9a98113a05e6c5ef Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Dec 2017 03:15:38 -0500 Subject: [PATCH 395/545] types: add UnmarshalJSON funcs for Response types --- cmd/abci-cli/abci-cli.go | 4 +--- types/messages_test.go | 14 +++++++++++ types/result.go | 51 ++++++++++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 18437ff7..47ffd6bc 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -311,9 +311,7 @@ func or(err1 error, err2 error) error { func cmdTest(cmd *cobra.Command, args []string) error { fmt.Println("Running tests") - var err error - - err = servertest.InitChain(client) + err := servertest.InitChain(client) fmt.Println("") err = or(err, servertest.SetOption(client, "serial", "on")) fmt.Println("") diff --git a/types/messages_test.go b/types/messages_test.go index 32f09623..15e84b62 100644 --- a/types/messages_test.go +++ b/types/messages_test.go @@ -14,6 +14,20 @@ func TestMarshalJSON(t *testing.T) { b, err := json.Marshal(&ResponseDeliverTx{}) assert.Nil(t, err) assert.True(t, strings.Contains(string(b), "code")) + + r1 := ResponseCheckTx{ + Code: 1, + Data: []byte("hello"), + Gas: 43, + Fee: 12, + } + b, err = json.Marshal(&r1) + assert.Nil(t, err) + + var r2 ResponseCheckTx + err = json.Unmarshal(b, &r2) + assert.Nil(t, err) + assert.Equal(t, r1, r2) } func TestWriteReadMessage(t *testing.T) { diff --git a/types/result.go b/types/result.go index 1963520d..782dbac6 100644 --- a/types/result.go +++ b/types/result.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "fmt" "github.com/gogo/protobuf/jsonpb" @@ -76,33 +77,63 @@ func fmtError(code uint32, log string) string { //--------------------------------------------------------------------------- // override JSON marshalling so we dont emit defaults (ie. disable omitempty) +// note we need Unmarshal functions too because protobuf had the bright idea +// to marshal int64->string. cool. cool, cool, cool: https://developers.google.com/protocol-buffers/docs/proto3#json + +var ( + jsonpbMarshaller = jsonpb.Marshaler{ + EnumsAsInts: true, + EmitDefaults: true, + } + jsonpbUnmarshaller = jsonpb.Unmarshaler{} +) func (r *ResponseSetOption) MarshalJSON() ([]byte, error) { - m := jsonpb.Marshaler{EmitDefaults: true} - s, err := m.MarshalToString(r) + s, err := jsonpbMarshaller.MarshalToString(r) return []byte(s), err } +func (r *ResponseSetOption) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + func (r *ResponseCheckTx) MarshalJSON() ([]byte, error) { - m := jsonpb.Marshaler{EmitDefaults: true} - s, err := m.MarshalToString(r) + s, err := jsonpbMarshaller.MarshalToString(r) return []byte(s), err } +func (r *ResponseCheckTx) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + func (r *ResponseDeliverTx) MarshalJSON() ([]byte, error) { - m := jsonpb.Marshaler{EmitDefaults: true} - s, err := m.MarshalToString(r) + s, err := jsonpbMarshaller.MarshalToString(r) return []byte(s), err } +func (r *ResponseDeliverTx) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + func (r *ResponseQuery) MarshalJSON() ([]byte, error) { - m := jsonpb.Marshaler{EmitDefaults: true} - s, err := m.MarshalToString(r) + s, err := jsonpbMarshaller.MarshalToString(r) return []byte(s), err } +func (r *ResponseQuery) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + func (r *ResponseCommit) MarshalJSON() ([]byte, error) { - m := jsonpb.Marshaler{EmitDefaults: true} - s, err := m.MarshalToString(r) + s, err := jsonpbMarshaller.MarshalToString(r) return []byte(s), err } + +func (r *ResponseCommit) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} From d6e821ea4fb1d08ae1ff34202d30d4b0cf728f38 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Sun, 10 Dec 2017 22:11:24 +0000 Subject: [PATCH 396/545] linter: enable in CI & make deterministic --- Makefile | 10 +++++----- circle.yml | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index d5fe913b..7176ab10 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ GOTOOLS = \ github.com/mitchellh/gox \ github.com/Masterminds/glide \ - github.com/alecthomas/gometalinter \ + gopkg.in/alecthomas/gometalinter.v2 \ github.com/ckaznocha/protoc-gen-lint \ github.com/gogo/protobuf/protoc-gen-gogo \ github.com/gogo/protobuf/gogoproto @@ -62,7 +62,7 @@ get_deps: ensure_tools: go get -u -v $(GOTOOLS) - @gometalinter --install + @gometalinter.v2 --install get_vendor_deps: ensure_tools @rm -rf vendor/ @@ -71,11 +71,11 @@ get_vendor_deps: ensure_tools metalinter: protoc $(INCLUDE) --lint_out=. types/*.proto - gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... + gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... metalinter_test: - protoc $(INCLUDE) --lint_out=. types/*.proto - gometalinter --vendor --deadline=600s --disable-all \ + #protoc $(INCLUDE) --lint_out=. types/*.proto + gometalinter.v2 --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ --enable=goconst \ diff --git a/circle.yml b/circle.yml index 7d4545e5..95d1dea5 100644 --- a/circle.yml +++ b/circle.yml @@ -2,7 +2,6 @@ machine: environment: GOPATH: /home/ubuntu/.go_workspace REPO: $GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME - GO15VENDOREXPERIMENT: 1 hosts: circlehost: 127.0.0.1 localhost: 127.0.0.1 @@ -16,7 +15,7 @@ checkout: test: override: - - cd $REPO && make get_vendor_deps && make test_integrations + - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations post: - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" From 7167d4e4c76333e1a2d7cd420ea18104ade7bbc6 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Tue, 12 Dec 2017 01:15:36 -0700 Subject: [PATCH 397/545] types: compile type assertions to avoid sneaky runtime surprises Ensure that the types in result.go implement both json.Marshaler and json.Unmarshaler and thus avoid any accidental deletions of their respective methods which would then cause surprises at runtime. --- types/result.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/types/result.go b/types/result.go index 782dbac6..34df4a04 100644 --- a/types/result.go +++ b/types/result.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "encoding/json" "fmt" "github.com/gogo/protobuf/jsonpb" @@ -137,3 +138,18 @@ func (r *ResponseCommit) UnmarshalJSON(b []byte) error { reader := bytes.NewBuffer(b) return jsonpbUnmarshaller.Unmarshal(reader, r) } + +// Some compile time assertions to ensure we don't +// have accidental runtime surprises later on. + +// jsonEncodingRoundTripper ensures that asserted +// interfaces implement both MarshalJSON and UnmarshalJSON +type jsonRoundTripper interface { + json.Marshaler + json.Unmarshaler +} + +var _ jsonRoundTripper = (*ResponseCommit)(nil) +var _ jsonRoundTripper = (*ResponseQuery)(nil) +var _ jsonRoundTripper = (*ResponseDeliverTx)(nil) +var _ jsonRoundTripper = (*ResponseSetOption)(nil) From 310beae63c4fee549faea4a6d4c0d9e027e5a707 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 12 Dec 2017 10:14:50 -0500 Subject: [PATCH 398/545] types: check ResponseCheckTx too --- types/result.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/result.go b/types/result.go index 34df4a04..d094b78d 100644 --- a/types/result.go +++ b/types/result.go @@ -152,4 +152,5 @@ type jsonRoundTripper interface { var _ jsonRoundTripper = (*ResponseCommit)(nil) var _ jsonRoundTripper = (*ResponseQuery)(nil) var _ jsonRoundTripper = (*ResponseDeliverTx)(nil) +var _ jsonRoundTripper = (*ResponseCheckTx)(nil) var _ jsonRoundTripper = (*ResponseSetOption)(nil) From 66338896329fcf7fc1d847063a7c9acd09f5b13c Mon Sep 17 00:00:00 2001 From: Krzysztof Jurewicz Date: Tue, 12 Dec 2017 21:06:56 +0100 Subject: [PATCH 399/545] Short-circuit assertions in test command --- cmd/abci-cli/abci-cli.go | 64 ++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 47ffd6bc..32bf2af8 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -300,49 +300,37 @@ func persistentArgs(line []byte) []string { //-------------------------------------------------------------------------------- -func or(err1 error, err2 error) error { - if err1 == nil { - return err2 +func compose(fs []func() error) error { + if len(fs) == 0 { + return nil } else { - return err1 + err := fs[0]() + if err == nil { + return compose(fs[1:]) + } else { + return err + } } } func cmdTest(cmd *cobra.Command, args []string) error { - fmt.Println("Running tests") - - err := servertest.InitChain(client) - fmt.Println("") - err = or(err, servertest.SetOption(client, "serial", "on")) - fmt.Println("") - err = or(err, servertest.Commit(client, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil)) - fmt.Println("") - err = or(err, servertest.Commit(client, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeOK, nil)) - fmt.Println("") - err = or(err, servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1})) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x01}, code.CodeTypeOK, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x02}, code.CodeTypeOK, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x03}, code.CodeTypeOK, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, code.CodeTypeOK, nil)) - fmt.Println("") - err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil)) - fmt.Println("") - err = or(err, servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5})) - - if err != nil { - return errors.New("Some checks didn't pass, please inspect stdout to see the exact failures.") - } - return nil + return compose( + []func() error{ + func() error { return servertest.InitChain(client) }, + func() error { return servertest.SetOption(client, "serial", "on") }, + func() error { return servertest.Commit(client, nil) }, + func() error { return servertest.DeliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil) }, + func() error { return servertest.Commit(client, nil) }, + func() error { return servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeOK, nil) }, + func() error { return servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) }, + func() error { return servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil) }, + func() error { return servertest.DeliverTx(client, []byte{0x01}, code.CodeTypeOK, nil) }, + func() error { return servertest.DeliverTx(client, []byte{0x00, 0x02}, code.CodeTypeOK, nil) }, + func() error { return servertest.DeliverTx(client, []byte{0x00, 0x03}, code.CodeTypeOK, nil) }, + func() error { return servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, code.CodeTypeOK, nil) }, + func() error { return servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil) }, + func() error { return servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5})}, + }) } func cmdBatch(cmd *cobra.Command, args []string) error { From ecc13d5a8e0b05a98d5c4fc01f4f5ffa9b1514d1 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Sat, 9 Dec 2017 19:48:29 -0700 Subject: [PATCH 400/545] cmd/abci-cli: use a single connection per session Use the single client connection at startup time for sending over commands instead of shelling out for every command. This code fixes the regression from https://github.com/tendermint/abci/pull/117 which instead used "os/exec".Command with: "abci-cli [args...]" The purpose of this code is to restore us back to the state after cobra replace urlfave/cli. There is still a bit of work to implement Batch itself, but that should be simpler as a focused command. Fixes #133 --- cmd/abci-cli/abci-cli.go | 104 ++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 13 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 47ffd6bc..0aa60f4d 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "os" - "os/exec" "strings" "github.com/spf13/cobra" @@ -348,6 +347,13 @@ func cmdTest(cmd *cobra.Command, args []string) error { func cmdBatch(cmd *cobra.Command, args []string) error { bufReader := bufio.NewReader(os.Stdin) for { + // TODO: (@ebuchman, @zramsay, @odeke-em) Implement the actual batch logic + printResponse(cmd, args, response{ + Code: codeBad, + Log: "Unimplemented", + }) + return nil + line, more, err := bufReader.ReadLine() if more { return errors.New("Input line is too long") @@ -358,19 +364,11 @@ func cmdBatch(cmd *cobra.Command, args []string) error { } else if err != nil { return err } - - pArgs := persistentArgs(line) - out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() // nolint: gas - if err != nil { - return err - } - fmt.Println(string(out)) } return nil } func cmdConsole(cmd *cobra.Command, args []string) error { - for { fmt.Printf("> ") bufReader := bufio.NewReader(os.Stdin) @@ -382,18 +380,67 @@ func cmdConsole(cmd *cobra.Command, args []string) error { } pArgs := persistentArgs(line) - out, err := exec.Command(pArgs[0], pArgs[1:]...).Output() // nolint: gas - if err != nil { + if err := muxOnCommands(cmd, pArgs); err != nil { return err } - fmt.Println(string(out)) } return nil } +var ( + errBadPersistentArgs = errors.New("expecting persistent args of the form: abci-cli [command] <...>") + + errUnimplemented = errors.New("unimplemented") +) + +func muxOnCommands(cmd *cobra.Command, pArgs []string) error { + if len(pArgs) < 2 { + return errBadPersistentArgs + } + + subCommand, actualArgs := pArgs[1], pArgs[2:] + switch strings.ToLower(subCommand) { + case "batch": + return cmdBatch(cmd, actualArgs) + case "check_tx": + return cmdCheckTx(cmd, actualArgs) + case "commit": + return cmdCommit(cmd, actualArgs) + case "deliver_tx": + return cmdDeliverTx(cmd, actualArgs) + case "echo": + return cmdEcho(cmd, actualArgs) + case "info": + return cmdInfo(cmd, actualArgs) + case "query": + return cmdQuery(cmd, actualArgs) + case "set_option": + return cmdSetOption(cmd, actualArgs) + default: + return cmdUnimplemented(cmd, pArgs) + } +} + +func cmdUnimplemented(cmd *cobra.Command, args []string) error { + // TODO: Print out all the sub-commands available + msg := "unimplemented command" + if err := cmd.Help(); err != nil { + msg = err.Error() + } + printResponse(cmd, args, response{ + Code: codeBad, + Log: msg, + }) + return nil +} + // Have the application echo a message func cmdEcho(cmd *cobra.Command, args []string) error { - res, err := client.EchoSync(args[0]) + msg := "" + if len(args) > 0 { + msg = args[0] + } + res, err := client.EchoSync(msg) if err != nil { return err } @@ -419,8 +466,18 @@ func cmdInfo(cmd *cobra.Command, args []string) error { return nil } +const codeBad uint32 = 10 + // Set an option on the application func cmdSetOption(cmd *cobra.Command, args []string) error { + if len(args) < 2 { + printResponse(cmd, args, response{ + Code: codeBad, + Log: "want at least arguments of the form: ", + }) + return nil + } + key, val := args[0], args[1] res, err := client.SetOptionSync(types.RequestSetOption{key, val}) if err != nil { @@ -435,6 +492,13 @@ func cmdSetOption(cmd *cobra.Command, args []string) error { // Append a new tx to application func cmdDeliverTx(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + printResponse(cmd, args, response{ + Code: codeBad, + Log: "want the tx", + }) + return nil + } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err @@ -453,6 +517,13 @@ func cmdDeliverTx(cmd *cobra.Command, args []string) error { // Validate a tx func cmdCheckTx(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + printResponse(cmd, args, response{ + Code: codeBad, + Log: "want the tx", + }) + return nil + } txBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err @@ -485,6 +556,13 @@ func cmdCommit(cmd *cobra.Command, args []string) error { // Query application state func cmdQuery(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + printResponse(cmd, args, response{ + Code: codeBad, + Log: "want the query", + }) + return nil + } queryBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err From cabc516726a7a46bc7714303e50e86b1e2c9915d Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Sun, 10 Dec 2017 21:39:30 +0000 Subject: [PATCH 401/545] batch: progress --- cmd/abci-cli/abci-cli.go | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 0aa60f4d..b36948a3 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -347,12 +347,6 @@ func cmdTest(cmd *cobra.Command, args []string) error { func cmdBatch(cmd *cobra.Command, args []string) error { bufReader := bufio.NewReader(os.Stdin) for { - // TODO: (@ebuchman, @zramsay, @odeke-em) Implement the actual batch logic - printResponse(cmd, args, response{ - Code: codeBad, - Log: "Unimplemented", - }) - return nil line, more, err := bufReader.ReadLine() if more { @@ -364,6 +358,15 @@ func cmdBatch(cmd *cobra.Command, args []string) error { } else if err != nil { return err } + + if len(line) > 0 { // prevents introduction of extra space leading to argument parse errors + args = strings.Split(string(line), " ") + } + + if err := muxOnCommands(cmd, args); err != nil { + return err + } + fmt.Println("") } return nil } @@ -394,14 +397,22 @@ var ( ) func muxOnCommands(cmd *cobra.Command, pArgs []string) error { - if len(pArgs) < 2 { + + if len(pArgs) < 1 && cmd.Use != "batch" { return errBadPersistentArgs } - subCommand, actualArgs := pArgs[1], pArgs[2:] + subCommand, actualArgs := pArgs[0], pArgs[1:] + + //if cmd.Use == "batch" { + // cmd.Use = subCommand + //} + + switch strings.ToLower(subCommand) { case "batch": - return cmdBatch(cmd, actualArgs) + fmt.Println("WTF") + return nil case "check_tx": return cmdCheckTx(cmd, actualArgs) case "commit": From 5ea42475ced24148e1d636de39450172f87dbb04 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Tue, 12 Dec 2017 00:55:07 -0700 Subject: [PATCH 402/545] cmd/abci-cli: implement batch Can now run batch which can be tested by: ```shell echo -e "echo foo\necho blue" | abci-cli batch ``` giving ```shell I[12-12|07:55:55.513] Starting socketClient module=abci-client impl=socketClient -> code: OK -> data: foo -> data.hex: 0x666F6F -> code: OK -> data: blue -> data.hex: 0x626C7565 ``` --- cmd/abci-cli/abci-cli.go | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index b36948a3..cce7addd 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -359,14 +359,11 @@ func cmdBatch(cmd *cobra.Command, args []string) error { return err } - if len(line) > 0 { // prevents introduction of extra space leading to argument parse errors - args = strings.Split(string(line), " ") - } - - if err := muxOnCommands(cmd, args); err != nil { + cmdArgs := persistentArgs(line) + if err := muxOnCommands(cmd, cmdArgs); err != nil { return err } - fmt.Println("") + fmt.Println() } return nil } @@ -397,22 +394,14 @@ var ( ) func muxOnCommands(cmd *cobra.Command, pArgs []string) error { - - if len(pArgs) < 1 && cmd.Use != "batch" { + if len(pArgs) < 2 { return errBadPersistentArgs } - - subCommand, actualArgs := pArgs[0], pArgs[1:] - - //if cmd.Use == "batch" { - // cmd.Use = subCommand - //} - + subCommand, actualArgs := pArgs[1], pArgs[2:] switch strings.ToLower(subCommand) { case "batch": - fmt.Println("WTF") - return nil + return muxOnCommands(cmd, actualArgs) case "check_tx": return cmdCheckTx(cmd, actualArgs) case "commit": @@ -438,6 +427,9 @@ func cmdUnimplemented(cmd *cobra.Command, args []string) error { if err := cmd.Help(); err != nil { msg = err.Error() } + if len(args) > 0 { + msg += fmt.Sprintf(" args: [%s]", strings.Join(args, " ")) + } printResponse(cmd, args, response{ Code: codeBad, Log: msg, From bbc3b807c6151474d10609e4bfca5ee66c84e04d Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Tue, 12 Dec 2017 17:23:13 -0700 Subject: [PATCH 403/545] all: fix vet issues with build tags, formatting * Build tags need to come before the package name and have at least a blank line, between them and the package, please see https://golang.org/pkg/go/build/#hdr-Build_Constraints * fmt.Println doesn't take formatting verbs * Fix a missing formatting argument to fmt.Printf --- tests/server/client.go | 4 ++-- types/protoreplace/protoreplace.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/server/client.go b/tests/server/client.go index f1757fe1..8d6751a1 100644 --- a/tests/server/client.go +++ b/tests/server/client.go @@ -21,7 +21,7 @@ func InitChain(client abcicli.Client) error { } _, err := client.InitChainSync(types.RequestInitChain{Validators: vals}) if err != nil { - fmt.Println("Failed test: InitChain - %v", err) + fmt.Printf("Failed test: InitChain - %v\n", err) return err } fmt.Println("Passed test: InitChain") @@ -46,7 +46,7 @@ func Commit(client abcicli.Client, hashExp []byte) error { _, data := res.Code, res.Data if err != nil { fmt.Println("Failed test: Commit") - fmt.Printf("committing %v\nlog: %v", res.GetLog()) + fmt.Printf("committing %v\nlog: %v", data, res.GetLog()) return err } if !bytes.Equal(data, hashExp) { diff --git a/types/protoreplace/protoreplace.go b/types/protoreplace/protoreplace.go index c859098f..3ea0c73d 100644 --- a/types/protoreplace/protoreplace.go +++ b/types/protoreplace/protoreplace.go @@ -1,7 +1,7 @@ -package main - // +build ignore +package main + import ( "bytes" "fmt" From c532e8cabcfede2dcb640a7ae7404c53fbcd4f36 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 12 Dec 2017 22:44:55 -0600 Subject: [PATCH 404/545] add \n to Printf lines --- tests/server/client.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/server/client.go b/tests/server/client.go index 8d6751a1..9cc8131d 100644 --- a/tests/server/client.go +++ b/tests/server/client.go @@ -33,7 +33,7 @@ func SetOption(client abcicli.Client, key, value string) error { log := res.GetLog() if err != nil { fmt.Println("Failed test: SetOption") - fmt.Printf("setting %v=%v: \nlog: %v", key, value, log) + fmt.Printf("setting %v=%v: \nlog: %v\n", key, value, log) fmt.Println("Failed test: SetOption") return err } @@ -46,12 +46,12 @@ func Commit(client abcicli.Client, hashExp []byte) error { _, data := res.Code, res.Data if err != nil { fmt.Println("Failed test: Commit") - fmt.Printf("committing %v\nlog: %v", data, res.GetLog()) + fmt.Printf("committing %v\nlog: %v\n", data, res.GetLog()) return err } if !bytes.Equal(data, hashExp) { fmt.Println("Failed test: Commit") - fmt.Printf("Commit hash was unexpected. Got %X expected %X", + fmt.Printf("Commit hash was unexpected. Got %X expected %X\n", data.Bytes(), hashExp) return errors.New("CommitTx failed") } @@ -64,13 +64,13 @@ func DeliverTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp [] code, data, log := res.Code, res.Data, res.Log if code != codeExp { fmt.Println("Failed test: DeliverTx") - fmt.Printf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", + fmt.Printf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v\n", code, codeExp, log) return errors.New("DeliverTx error") } if !bytes.Equal(data, dataExp) { fmt.Println("Failed test: DeliverTx") - fmt.Printf("DeliverTx response data was unexpected. Got %X expected %X", + fmt.Printf("DeliverTx response data was unexpected. Got %X expected %X\n", data, dataExp) return errors.New("DeliverTx error") } @@ -83,13 +83,13 @@ func CheckTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []by code, data, log := res.Code, res.Data, res.Log if code != codeExp { fmt.Println("Failed test: CheckTx") - fmt.Printf("CheckTx response code was unexpected. Got %v expected %v. Log: %v", + fmt.Printf("CheckTx response code was unexpected. Got %v expected %v. Log: %v\n", code, codeExp, log) return errors.New("CheckTx") } if !bytes.Equal(data, dataExp) { fmt.Println("Failed test: CheckTx") - fmt.Printf("CheckTx response data was unexpected. Got %X expected %X", + fmt.Printf("CheckTx response data was unexpected. Got %X expected %X\n", data, dataExp) return errors.New("CheckTx") } From 25f6f6518c0fee985ed391bdd1023d3ea419d231 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Dec 2017 17:50:24 +0100 Subject: [PATCH 405/545] Update the ResponseEndBlock values * Rename diffs -> changes * Add consensus_param_changes For context, see: https://github.com/tendermint/tendermint/issues/924 https://github.com/tendermint/tendermint/issues/952 --- types/types.pb.go | 356 ++++++++++++++++++++++++++++++++-------------- types/types.proto | 30 +++- 2 files changed, 276 insertions(+), 110 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index 69777d6d..5a0e9b7a 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -33,6 +33,10 @@ It has these top-level messages: ResponseInitChain ResponseBeginBlock ResponseEndBlock + ConsensusParams + BlockSizeParams + TxSizeParams + BlockGossipParams Header BlockID PartSetHeader @@ -82,7 +86,7 @@ var KVPair_Type_value = map[string]int32{ func (x KVPair_Type) String() string { return proto.EnumName(KVPair_Type_name, int32(x)) } -func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30, 0} } +func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34, 0} } type Request struct { // Types that are valid to be assigned to Value: @@ -1394,7 +1398,8 @@ func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } type ResponseEndBlock struct { - Diffs []*Validator `protobuf:"bytes,1,rep,name=diffs" json:"diffs,omitempty"` + Changes []*Validator `protobuf:"bytes,1,rep,name=changes" json:"changes,omitempty"` + ConsensusParamChanges *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_changes,json=consensusParamChanges" json:"consensus_param_changes,omitempty"` } func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } @@ -1402,13 +1407,130 @@ func (m *ResponseEndBlock) String() string { return proto.CompactText func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} } -func (m *ResponseEndBlock) GetDiffs() []*Validator { +func (m *ResponseEndBlock) GetChanges() []*Validator { if m != nil { - return m.Diffs + return m.Changes } return nil } +func (m *ResponseEndBlock) GetConsensusParamChanges() *ConsensusParams { + if m != nil { + return m.ConsensusParamChanges + } + return nil +} + +type ConsensusParams struct { + BlockSizeParams *BlockSizeParams `protobuf:"bytes,1,opt,name=block_size_params,json=blockSizeParams" json:"block_size_params,omitempty"` + TxSizeParams *TxSizeParams `protobuf:"bytes,2,opt,name=tx_size_params,json=txSizeParams" json:"tx_size_params,omitempty"` + BlockGossipParams *BlockGossipParams `protobuf:"bytes,3,opt,name=block_gossip_params,json=blockGossipParams" json:"block_gossip_params,omitempty"` +} + +func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } +func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } +func (*ConsensusParams) ProtoMessage() {} +func (*ConsensusParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} } + +func (m *ConsensusParams) GetBlockSizeParams() *BlockSizeParams { + if m != nil { + return m.BlockSizeParams + } + return nil +} + +func (m *ConsensusParams) GetTxSizeParams() *TxSizeParams { + if m != nil { + return m.TxSizeParams + } + return nil +} + +func (m *ConsensusParams) GetBlockGossipParams() *BlockGossipParams { + if m != nil { + return m.BlockGossipParams + } + return nil +} + +// BlockSizeParams contain limits on the block size. +type BlockSizeParams struct { + // NOTE: must not be 0 nor greater than 100MB + MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` + MaxTxs int32 `protobuf:"varint,2,opt,name=max_txs,json=maxTxs,proto3" json:"max_txs,omitempty"` + MaxGas int64 `protobuf:"varint,3,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` +} + +func (m *BlockSizeParams) Reset() { *m = BlockSizeParams{} } +func (m *BlockSizeParams) String() string { return proto.CompactTextString(m) } +func (*BlockSizeParams) ProtoMessage() {} +func (*BlockSizeParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} } + +func (m *BlockSizeParams) GetMaxBytes() int32 { + if m != nil { + return m.MaxBytes + } + return 0 +} + +func (m *BlockSizeParams) GetMaxTxs() int32 { + if m != nil { + return m.MaxTxs + } + return 0 +} + +func (m *BlockSizeParams) GetMaxGas() int64 { + if m != nil { + return m.MaxGas + } + return 0 +} + +// TxSizeParams contain limits on the tx size. +type TxSizeParams struct { + MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` + MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` +} + +func (m *TxSizeParams) Reset() { *m = TxSizeParams{} } +func (m *TxSizeParams) String() string { return proto.CompactTextString(m) } +func (*TxSizeParams) ProtoMessage() {} +func (*TxSizeParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } + +func (m *TxSizeParams) GetMaxBytes() int32 { + if m != nil { + return m.MaxBytes + } + return 0 +} + +func (m *TxSizeParams) GetMaxGas() int64 { + if m != nil { + return m.MaxGas + } + return 0 +} + +// BlockGossipParams determine consensus critical +// elements of how blocks are gossiped +type BlockGossipParams struct { + // Note: must not be 0 + BlockPartSizeBytes int32 `protobuf:"varint,1,opt,name=block_part_size_bytes,json=blockPartSizeBytes,proto3" json:"block_part_size_bytes,omitempty"` +} + +func (m *BlockGossipParams) Reset() { *m = BlockGossipParams{} } +func (m *BlockGossipParams) String() string { return proto.CompactTextString(m) } +func (*BlockGossipParams) ProtoMessage() {} +func (*BlockGossipParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} } + +func (m *BlockGossipParams) GetBlockPartSizeBytes() int32 { + if m != nil { + return m.BlockPartSizeBytes + } + return 0 +} + type Header struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` @@ -1424,7 +1546,7 @@ type Header struct { func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} } +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} } func (m *Header) GetChainId() string { if m != nil { @@ -1497,7 +1619,7 @@ type BlockID struct { func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} -func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} } +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} } func (m *BlockID) GetHash() []byte { if m != nil { @@ -1521,7 +1643,7 @@ type PartSetHeader struct { func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} -func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} } func (m *PartSetHeader) GetTotal() int32 { if m != nil { @@ -1545,7 +1667,7 @@ type Validator struct { func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} -func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} } +func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} } func (m *Validator) GetPubKey() []byte { if m != nil { @@ -1569,7 +1691,7 @@ type Evidence struct { func (m *Evidence) Reset() { *m = Evidence{} } func (m *Evidence) String() string { return proto.CompactTextString(m) } func (*Evidence) ProtoMessage() {} -func (*Evidence) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} } +func (*Evidence) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} } func (m *Evidence) GetPubKey() []byte { if m != nil { @@ -1595,7 +1717,7 @@ type KVPair struct { func (m *KVPair) Reset() { *m = KVPair{} } func (m *KVPair) String() string { return proto.CompactTextString(m) } func (*KVPair) ProtoMessage() {} -func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} } +func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} } func (m *KVPair) GetKey() string { if m != nil { @@ -1651,6 +1773,10 @@ func init() { proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") + proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") + proto.RegisterType((*BlockSizeParams)(nil), "types.BlockSizeParams") + proto.RegisterType((*TxSizeParams)(nil), "types.TxSizeParams") + proto.RegisterType((*BlockGossipParams)(nil), "types.BlockGossipParams") proto.RegisterType((*Header)(nil), "types.Header") proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") @@ -2065,103 +2191,115 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1554 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0xcb, 0x6e, 0xdb, 0x46, - 0x17, 0xc7, 0x2d, 0x51, 0xd4, 0xe5, 0xf8, 0x26, 0x8f, 0xfd, 0x25, 0x8a, 0xb2, 0x88, 0x43, 0xe0, - 0x6b, 0xe4, 0x5c, 0xac, 0xd4, 0x41, 0x8a, 0x38, 0x29, 0x0a, 0x58, 0x71, 0x52, 0x09, 0x01, 0xd2, - 0x74, 0x62, 0x64, 0x2b, 0x50, 0xe2, 0x48, 0x22, 0x22, 0x91, 0x0c, 0x39, 0x72, 0xe4, 0xa2, 0x8f, - 0x90, 0x7d, 0xd7, 0xed, 0xa6, 0x40, 0x5f, 0xa0, 0xcb, 0xee, 0x8a, 0x3e, 0x43, 0x17, 0x79, 0x96, - 0x62, 0xce, 0x0c, 0xaf, 0x26, 0xb3, 0xc8, 0x22, 0x1b, 0x63, 0x2e, 0xe7, 0x3f, 0x3a, 0x33, 0x3c, - 0xf3, 0x3b, 0x67, 0x0c, 0x3b, 0xfc, 0xc2, 0x63, 0x41, 0x17, 0xff, 0x1e, 0x7a, 0xbe, 0xcb, 0x5d, - 0xa2, 0x63, 0xa7, 0x7d, 0x6f, 0x6a, 0xf3, 0xd9, 0x72, 0x74, 0x38, 0x76, 0x17, 0xdd, 0xa9, 0x3b, - 0x75, 0xbb, 0x38, 0x3b, 0x5a, 0x4e, 0xb0, 0x87, 0x1d, 0x6c, 0x49, 0x95, 0xf1, 0x77, 0x05, 0x6a, - 0x94, 0xbd, 0x5b, 0xb2, 0x80, 0x93, 0x0e, 0x54, 0xd8, 0x78, 0xe6, 0xb6, 0x4a, 0xfb, 0xa5, 0xce, - 0xfa, 0x11, 0x39, 0x94, 0xab, 0xab, 0xd9, 0x67, 0xe3, 0x99, 0xdb, 0x5f, 0xa3, 0x68, 0x41, 0xee, - 0x80, 0x3e, 0x99, 0x2f, 0x83, 0x59, 0xab, 0x8c, 0xa6, 0xbb, 0x69, 0xd3, 0xe7, 0x62, 0xaa, 0xbf, - 0x46, 0xa5, 0x8d, 0x58, 0xd6, 0x76, 0x26, 0x6e, 0x4b, 0xcb, 0x5b, 0x76, 0xe0, 0x4c, 0x70, 0x59, - 0x61, 0x41, 0x1e, 0x01, 0x04, 0x8c, 0x0f, 0x5d, 0x8f, 0xdb, 0xae, 0xd3, 0xaa, 0xa0, 0xfd, 0xd5, - 0xb4, 0xfd, 0x6b, 0xc6, 0x7f, 0xc0, 0xe9, 0xfe, 0x1a, 0x6d, 0x04, 0x61, 0x47, 0x28, 0x2d, 0x36, - 0xb7, 0xcf, 0x99, 0x3f, 0xe4, 0xab, 0x96, 0x9e, 0xa7, 0x3c, 0x95, 0xf3, 0x67, 0x2b, 0xa1, 0xb4, - 0xc2, 0x0e, 0x39, 0x82, 0xfa, 0x78, 0xc6, 0xc6, 0x6f, 0x85, 0xae, 0x8a, 0xba, 0xff, 0xa5, 0x75, - 0x4f, 0xc5, 0x2c, 0xaa, 0x6a, 0x63, 0xd9, 0x24, 0x87, 0x50, 0x1d, 0xbb, 0x8b, 0x85, 0xcd, 0x5b, - 0x35, 0x54, 0xec, 0x65, 0x14, 0x38, 0xd7, 0x5f, 0xa3, 0xca, 0x4a, 0x1c, 0xd7, 0xbb, 0x25, 0xf3, - 0x2f, 0x5a, 0xf5, 0xbc, 0xe3, 0xfa, 0x51, 0x4c, 0x89, 0xe3, 0x42, 0x1b, 0xb1, 0x15, 0xdb, 0xb1, - 0xf9, 0x70, 0x3c, 0x33, 0x6d, 0xa7, 0xd5, 0xc8, 0xdb, 0xca, 0xc0, 0xb1, 0xf9, 0x53, 0x31, 0x2d, - 0xb6, 0x62, 0x87, 0x1d, 0xf2, 0x04, 0xd6, 0x47, 0x6c, 0x6a, 0x3b, 0xc3, 0xd1, 0xdc, 0x1d, 0xbf, - 0x6d, 0x01, 0x4a, 0x5b, 0x69, 0x69, 0x4f, 0x18, 0xf4, 0xc4, 0x7c, 0x7f, 0x8d, 0xc2, 0x28, 0xea, - 0x91, 0x87, 0xd0, 0x60, 0x8e, 0xa5, 0xa4, 0xeb, 0x28, 0xbd, 0x92, 0x89, 0x00, 0xc7, 0x0a, 0x85, - 0x75, 0xa6, 0xda, 0xbd, 0x1a, 0xe8, 0xe7, 0xe6, 0x7c, 0xc9, 0x8c, 0x5b, 0xb0, 0x9e, 0x88, 0x14, - 0xd2, 0x82, 0xda, 0x82, 0x05, 0x81, 0x39, 0x65, 0x18, 0x4e, 0x0d, 0x1a, 0x76, 0x8d, 0x2d, 0xd8, - 0x48, 0xc6, 0x49, 0x42, 0x28, 0x62, 0x41, 0x08, 0xcf, 0x99, 0x1f, 0x88, 0x00, 0x50, 0x42, 0xd5, - 0x35, 0x1e, 0x43, 0x33, 0x1b, 0x04, 0xa4, 0x09, 0xda, 0x5b, 0x76, 0xa1, 0x2c, 0x45, 0x93, 0xec, - 0x29, 0x87, 0x30, 0x34, 0x1b, 0x54, 0x79, 0x67, 0x44, 0xda, 0x28, 0x0c, 0xc8, 0x16, 0x94, 0xf9, - 0x0a, 0xa5, 0x1b, 0xb4, 0xcc, 0x57, 0xc6, 0x3e, 0x6c, 0xa5, 0x3f, 0xf9, 0x25, 0x0b, 0x2b, 0x72, - 0x1d, 0xbf, 0x19, 0x21, 0x50, 0xb1, 0x4c, 0x6e, 0x2a, 0x0b, 0x6c, 0x8b, 0x31, 0xcf, 0xe4, 0x33, - 0xf5, 0xf3, 0xd8, 0x26, 0x57, 0xa0, 0x3a, 0x63, 0xf6, 0x74, 0xc6, 0xf1, 0x0e, 0x68, 0x54, 0xf5, - 0x84, 0xaf, 0x9e, 0xef, 0x9e, 0x33, 0x0c, 0xf5, 0x3a, 0x95, 0x1d, 0x63, 0x1b, 0x36, 0x53, 0x81, - 0x64, 0x9c, 0x46, 0xce, 0x47, 0x1f, 0x9e, 0xdc, 0x07, 0x38, 0x37, 0xe7, 0xb6, 0x65, 0x72, 0xd7, - 0x0f, 0x5a, 0xa5, 0x7d, 0xad, 0xb3, 0x7e, 0xd4, 0x54, 0xdf, 0xeb, 0x4d, 0x38, 0x41, 0x13, 0x36, - 0xc6, 0x5f, 0x25, 0xd8, 0xb9, 0x14, 0x04, 0xc2, 0xdd, 0x99, 0x19, 0xcc, 0xc2, 0x2d, 0x88, 0x36, - 0xf9, 0xbf, 0x70, 0xd7, 0xb4, 0x98, 0xaf, 0xae, 0xf7, 0xa6, 0x5a, 0xb7, 0x8f, 0x83, 0x54, 0x4d, - 0x92, 0x3b, 0xb0, 0x63, 0x8e, 0x02, 0xe6, 0xf0, 0x61, 0xc2, 0x13, 0x6d, 0x5f, 0xeb, 0xe8, 0xb4, - 0x29, 0x27, 0x22, 0x47, 0x02, 0xd2, 0x83, 0xbd, 0xd1, 0xc5, 0x4f, 0xa6, 0xc3, 0x6d, 0x87, 0x25, - 0xed, 0x2b, 0xe8, 0xf9, 0xb6, 0xfa, 0x85, 0x67, 0xe7, 0xb6, 0xc5, 0x9c, 0x31, 0xa3, 0xbb, 0x91, - 0x71, 0xbc, 0x86, 0x71, 0x00, 0xdb, 0x99, 0x50, 0x4c, 0x9c, 0x6c, 0x29, 0x79, 0xb2, 0xc6, 0x07, - 0x1d, 0xea, 0x94, 0x05, 0x9e, 0xeb, 0x04, 0x8c, 0x3c, 0x82, 0x06, 0x5b, 0x8d, 0x99, 0xa4, 0x4a, - 0x29, 0x73, 0x2b, 0xa4, 0xcd, 0xb3, 0x70, 0x5e, 0xdc, 0xa8, 0xc8, 0x98, 0x1c, 0x28, 0x22, 0x66, - 0x31, 0xa7, 0x44, 0x49, 0x24, 0xde, 0x0d, 0x91, 0xa8, 0x65, 0x90, 0x20, 0x6d, 0x33, 0x4c, 0x3c, - 0x50, 0x4c, 0xac, 0xe4, 0x2e, 0x9c, 0x82, 0xe2, 0x71, 0x0a, 0x8a, 0x7a, 0xae, 0xfb, 0x05, 0x54, - 0x3c, 0x4e, 0x51, 0xb1, 0x9a, 0x2b, 0x2d, 0xc0, 0xe2, 0x83, 0x04, 0x16, 0x6b, 0x19, 0x1a, 0x48, - 0x61, 0x0e, 0x17, 0xbb, 0x11, 0x17, 0xeb, 0x19, 0x92, 0x2a, 0x49, 0x16, 0x8c, 0x77, 0x43, 0x30, - 0x36, 0x72, 0x0f, 0x2d, 0x43, 0xc6, 0xe3, 0x14, 0x19, 0x21, 0x77, 0x3b, 0x05, 0x68, 0xfc, 0x36, - 0x8d, 0x46, 0xc9, 0xb7, 0x6b, 0x19, 0x6d, 0x21, 0x1b, 0xbf, 0x49, 0xb2, 0x71, 0x23, 0x43, 0x64, - 0x15, 0x0b, 0x9f, 0x84, 0xe3, 0x81, 0xb8, 0x7a, 0x99, 0x48, 0x13, 0xb7, 0x9f, 0xf9, 0xbe, 0xeb, - 0x2b, 0x7a, 0xc9, 0x8e, 0xd1, 0x11, 0x8c, 0x89, 0xe3, 0xeb, 0x13, 0x20, 0x45, 0x4e, 0x24, 0xa2, - 0xcb, 0xf8, 0xa5, 0x14, 0x6b, 0x91, 0xa5, 0x49, 0x3e, 0x35, 0x14, 0x9f, 0x12, 0x7c, 0x2d, 0xa7, - 0xf8, 0x4a, 0x6e, 0xc3, 0xce, 0xdc, 0x0c, 0xb8, 0xdc, 0xe6, 0x30, 0x05, 0xac, 0x6d, 0x31, 0x21, - 0xf7, 0x27, 0xc9, 0x75, 0x0f, 0x76, 0x13, 0xb6, 0xa6, 0xe7, 0x0d, 0x91, 0x22, 0x15, 0xa4, 0x48, - 0x33, 0xb2, 0x3e, 0xf1, 0xbc, 0xbe, 0x19, 0xcc, 0x8c, 0xe3, 0x78, 0xff, 0x31, 0xbb, 0x09, 0x54, - 0xc6, 0xae, 0x25, 0xb7, 0xb5, 0x49, 0xb1, 0x2d, 0x78, 0x3e, 0x77, 0xa7, 0xca, 0x33, 0xd1, 0x34, - 0x7e, 0x2b, 0xc5, 0xda, 0x98, 0xdd, 0x79, 0xda, 0x53, 0xb5, 0x5b, 0x21, 0xde, 0xe8, 0xdd, 0xff, - 0xe7, 0xe3, 0x8d, 0xb5, 0x7f, 0x3f, 0xde, 0xe8, 0x24, 0xea, 0x21, 0xce, 0x1c, 0x8b, 0xf9, 0x0b, - 0xdb, 0xe1, 0xdd, 0xa9, 0x7b, 0xef, 0xbd, 0xed, 0xb3, 0xae, 0x50, 0x1c, 0xf6, 0x2e, 0x38, 0x0b, - 0xd4, 0xf9, 0x28, 0x0f, 0xb4, 0xc8, 0x03, 0x72, 0x13, 0x2a, 0xdc, 0x9c, 0x86, 0xa8, 0x0a, 0x61, - 0xf8, 0xe2, 0xcd, 0x2b, 0xd3, 0xf6, 0x29, 0x4e, 0x19, 0xbf, 0x96, 0x04, 0x9a, 0x52, 0xf7, 0xe2, - 0x8b, 0xba, 0xd8, 0x04, 0x6d, 0x6a, 0x06, 0x78, 0xfc, 0x1a, 0x15, 0x4d, 0x31, 0x32, 0x61, 0x0c, - 0x71, 0xa1, 0x51, 0xd1, 0x34, 0xfe, 0x2c, 0xc7, 0xf1, 0x12, 0xa5, 0xaf, 0x4b, 0x1e, 0xee, 0x81, - 0x6e, 0x3b, 0x16, 0x5b, 0xa1, 0x8b, 0x1a, 0x95, 0x1d, 0xd2, 0x93, 0x69, 0x56, 0xfb, 0x4c, 0xb7, - 0x31, 0x31, 0x3f, 0x0f, 0x13, 0x73, 0xe5, 0x33, 0x57, 0x91, 0x72, 0xb1, 0x8e, 0xe7, 0xbb, 0xee, - 0x04, 0xf7, 0xf6, 0x59, 0xeb, 0xa0, 0x3c, 0x91, 0x3a, 0xaa, 0xa9, 0xa4, 0xac, 0x4e, 0xb7, 0x16, - 0x87, 0xe0, 0xcf, 0xa2, 0x30, 0x48, 0x12, 0xec, 0x4b, 0x7e, 0x5b, 0x63, 0x37, 0x8e, 0xff, 0x08, - 0x6e, 0xc6, 0x1e, 0x90, 0xcb, 0xd4, 0x92, 0x15, 0x52, 0x9a, 0x47, 0xe4, 0x2b, 0xd0, 0x2d, 0x7b, - 0x32, 0x29, 0xae, 0x11, 0xe4, 0xb4, 0xf1, 0x7b, 0x19, 0xaa, 0x32, 0xc1, 0x93, 0x6b, 0x82, 0xfd, - 0xa6, 0xed, 0x0c, 0x6d, 0x2b, 0x64, 0x0e, 0xf6, 0x07, 0x56, 0xe2, 0xd0, 0xca, 0xa9, 0x43, 0x23, - 0x50, 0xe1, 0xf6, 0x82, 0x29, 0x5c, 0x60, 0x9b, 0x5c, 0x85, 0x9a, 0xb3, 0x5c, 0x0c, 0xf9, 0x4a, - 0x06, 0xa6, 0x4e, 0xab, 0xce, 0x72, 0x71, 0xb6, 0x0a, 0xc8, 0x11, 0x6c, 0x26, 0xe0, 0x61, 0x5b, - 0x2a, 0xa9, 0x6d, 0x29, 0xd7, 0xd0, 0xef, 0xc1, 0x29, 0x5d, 0x8f, 0x30, 0x32, 0xb0, 0x48, 0x07, - 0x90, 0x2a, 0x43, 0x99, 0x38, 0x24, 0x6d, 0xaa, 0x48, 0x9b, 0x2d, 0x31, 0xae, 0x32, 0x8b, 0xa8, - 0x5e, 0xae, 0x43, 0x43, 0x9c, 0xa4, 0x34, 0xa9, 0xa1, 0x49, 0x5d, 0x0c, 0xe0, 0xe4, 0x2d, 0xd8, - 0x8e, 0x8b, 0x0f, 0x69, 0x52, 0x97, 0xab, 0xc4, 0xc3, 0x68, 0x78, 0x0d, 0xea, 0x11, 0xd5, 0x1a, - 0x68, 0x51, 0x33, 0x15, 0xcc, 0x06, 0x50, 0x53, 0x2e, 0xe6, 0x56, 0x4f, 0xb7, 0x41, 0xf7, 0x4c, - 0x9f, 0x07, 0xaa, 0x68, 0x08, 0x73, 0xda, 0x2b, 0xd3, 0x17, 0x75, 0xab, 0xaa, 0xa1, 0xa4, 0x89, - 0x71, 0x0c, 0x9b, 0xa9, 0x71, 0x71, 0xfd, 0xb8, 0xcb, 0xcd, 0x39, 0xae, 0xa8, 0x53, 0xd9, 0x89, - 0x7e, 0xa6, 0x1c, 0xff, 0x8c, 0xf1, 0x18, 0x1a, 0xd1, 0x37, 0x14, 0x47, 0xed, 0x2d, 0x47, 0xc3, - 0xb0, 0x14, 0xde, 0xa0, 0x55, 0x6f, 0x39, 0x7a, 0x21, 0xab, 0x61, 0xcf, 0x7d, 0xaf, 0x2a, 0x39, - 0x8d, 0xca, 0x8e, 0xf1, 0x04, 0xea, 0x61, 0xa5, 0x55, 0x2c, 0x2d, 0xf8, 0xd4, 0xc6, 0x1f, 0x25, - 0xa8, 0x4a, 0xf8, 0xe5, 0x54, 0xdf, 0x5f, 0x63, 0x59, 0xba, 0x64, 0x43, 0xb1, 0x69, 0x14, 0x6e, - 0x45, 0x2f, 0x3e, 0x29, 0x3a, 0x3c, 0xbb, 0xf0, 0x18, 0x6d, 0xa0, 0x95, 0x68, 0x92, 0x9b, 0xb0, - 0x21, 0x25, 0x01, 0xf7, 0x6d, 0x27, 0x0c, 0xfd, 0x75, 0x1c, 0x7b, 0x8d, 0x43, 0xe2, 0x93, 0x4a, - 0x13, 0xdb, 0xe1, 0x0a, 0x72, 0x75, 0x1c, 0x18, 0x38, 0xdc, 0xb8, 0x0e, 0x15, 0x5c, 0x07, 0xa0, - 0xfa, 0xfa, 0x8c, 0x0e, 0x5e, 0x7e, 0xdf, 0x5c, 0x23, 0x35, 0xd0, 0x06, 0x2f, 0xcf, 0x9a, 0xa5, - 0xa3, 0x0f, 0x3a, 0x6c, 0x9f, 0xf4, 0x9e, 0x0e, 0x4e, 0x3c, 0x6f, 0x6e, 0x8f, 0x4d, 0xcc, 0x3b, - 0x5d, 0xa8, 0x60, 0x66, 0xcd, 0x79, 0xe0, 0xb6, 0xf3, 0x4a, 0x3c, 0x72, 0x04, 0x3a, 0x26, 0x58, - 0x92, 0xf7, 0xce, 0x6d, 0xe7, 0x56, 0x7a, 0xe2, 0x47, 0x64, 0x0a, 0xbe, 0xfc, 0xdc, 0x6d, 0xe7, - 0x95, 0x7b, 0xe4, 0x3b, 0x68, 0xc4, 0xa9, 0xb1, 0xe8, 0xd1, 0xdb, 0x2e, 0x2c, 0xfc, 0x84, 0x3e, - 0x4e, 0x8f, 0x45, 0x4f, 0xdf, 0x76, 0x61, 0xf5, 0x47, 0x1e, 0x41, 0x2d, 0xcc, 0x5c, 0xf9, 0x0f, - 0xe0, 0x76, 0x41, 0x01, 0x28, 0x8e, 0x47, 0xe6, 0x93, 0xbc, 0x77, 0x6d, 0x3b, 0xb7, 0xa6, 0x23, - 0x0f, 0xa1, 0xaa, 0x50, 0x9a, 0xfb, 0x76, 0x6e, 0xe7, 0x57, 0x8e, 0x62, 0x93, 0xf1, 0x13, 0xa8, - 0xe8, 0x51, 0xdc, 0x2e, 0xac, 0x09, 0xc9, 0x09, 0x40, 0xe2, 0xed, 0x53, 0xf8, 0x34, 0x6e, 0x17, - 0x57, 0x86, 0x44, 0xdc, 0x9d, 0xe8, 0xf5, 0x91, 0xff, 0x40, 0x6e, 0x17, 0x15, 0x87, 0xa3, 0x2a, - 0xfe, 0xd3, 0xe5, 0xc1, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x6a, 0x92, 0xbf, 0x11, - 0x00, 0x00, + // 1756 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6e, 0x1c, 0xc7, + 0x11, 0xe6, 0xee, 0xec, 0x6f, 0xf1, 0x67, 0x97, 0x4d, 0xca, 0x5a, 0xad, 0x0e, 0x96, 0x07, 0x08, + 0x4c, 0xc9, 0x16, 0x69, 0xd3, 0x70, 0x20, 0xda, 0x41, 0x00, 0x2d, 0x29, 0x69, 0x17, 0x06, 0x14, + 0x65, 0x48, 0xf8, 0xba, 0xe9, 0x9d, 0x69, 0xee, 0x0e, 0xb4, 0x3b, 0x33, 0x9e, 0xe9, 0xa5, 0x97, + 0x42, 0x1e, 0xc1, 0xc8, 0x35, 0xe7, 0xe4, 0x12, 0x20, 0x2f, 0x90, 0x63, 0x6e, 0x41, 0x9e, 0xc1, + 0x07, 0x3f, 0x4b, 0x50, 0xd5, 0x3d, 0xbf, 0x9c, 0x31, 0x02, 0x1d, 0x74, 0x19, 0x74, 0x77, 0xd5, + 0x57, 0x53, 0xdd, 0x5d, 0xfd, 0x55, 0x75, 0xc3, 0xbe, 0xbc, 0x0d, 0x44, 0x74, 0x42, 0xdf, 0xe3, + 0x20, 0xf4, 0xa5, 0xcf, 0x9a, 0xd4, 0x19, 0x3e, 0x9d, 0xbb, 0x72, 0xb1, 0x9e, 0x1d, 0xdb, 0xfe, + 0xea, 0x64, 0xee, 0xcf, 0xfd, 0x13, 0x92, 0xce, 0xd6, 0xd7, 0xd4, 0xa3, 0x0e, 0xb5, 0x14, 0xca, + 0xfc, 0x4f, 0x03, 0xda, 0x96, 0xf8, 0x61, 0x2d, 0x22, 0xc9, 0x8e, 0xa0, 0x21, 0xec, 0x85, 0x3f, + 0xa8, 0x3d, 0xaa, 0x1d, 0x6d, 0x9f, 0xb2, 0x63, 0x65, 0x5d, 0x4b, 0x5f, 0xd8, 0x0b, 0x7f, 0xbc, + 0x65, 0x91, 0x06, 0xfb, 0x0c, 0x9a, 0xd7, 0xcb, 0x75, 0xb4, 0x18, 0xd4, 0x49, 0xf5, 0x20, 0xaf, + 0xfa, 0x12, 0x45, 0xe3, 0x2d, 0x4b, 0xe9, 0xa0, 0x59, 0xd7, 0xbb, 0xf6, 0x07, 0x46, 0x99, 0xd9, + 0x89, 0x77, 0x4d, 0x66, 0x51, 0x83, 0x3d, 0x03, 0x88, 0x84, 0x9c, 0xfa, 0x81, 0x74, 0x7d, 0x6f, + 0xd0, 0x20, 0xfd, 0xfb, 0x79, 0xfd, 0x4b, 0x21, 0xff, 0x40, 0xe2, 0xf1, 0x96, 0xd5, 0x8d, 0xe2, + 0x0e, 0x22, 0x1d, 0xb1, 0x74, 0x6f, 0x44, 0x38, 0x95, 0x9b, 0x41, 0xb3, 0x0c, 0x79, 0xa1, 0xe4, + 0x57, 0x1b, 0x44, 0x3a, 0x71, 0x87, 0x9d, 0x42, 0xc7, 0x5e, 0x08, 0xfb, 0x2d, 0xe2, 0x5a, 0x84, + 0xbb, 0x97, 0xc7, 0x9d, 0xa3, 0x94, 0x50, 0x6d, 0x5b, 0x35, 0xd9, 0x31, 0xb4, 0x6c, 0x7f, 0xb5, + 0x72, 0xe5, 0xa0, 0x4d, 0x88, 0xc3, 0x02, 0x82, 0x64, 0xe3, 0x2d, 0x4b, 0x6b, 0xe1, 0x72, 0xfd, + 0xb0, 0x16, 0xe1, 0xed, 0xa0, 0x53, 0xb6, 0x5c, 0x7f, 0x44, 0x11, 0x2e, 0x17, 0xe9, 0xe0, 0x54, + 0x5c, 0xcf, 0x95, 0x53, 0x7b, 0xc1, 0x5d, 0x6f, 0xd0, 0x2d, 0x9b, 0xca, 0xc4, 0x73, 0xe5, 0x39, + 0x8a, 0x71, 0x2a, 0x6e, 0xdc, 0x61, 0xdf, 0xc2, 0xf6, 0x4c, 0xcc, 0x5d, 0x6f, 0x3a, 0x5b, 0xfa, + 0xf6, 0xdb, 0x01, 0x10, 0x74, 0x90, 0x87, 0x8e, 0x50, 0x61, 0x84, 0xf2, 0xf1, 0x96, 0x05, 0xb3, + 0xa4, 0xc7, 0xbe, 0x86, 0xae, 0xf0, 0x1c, 0x0d, 0xdd, 0x26, 0xe8, 0x47, 0x85, 0x08, 0xf0, 0x9c, + 0x18, 0xd8, 0x11, 0xba, 0x3d, 0x6a, 0x43, 0xf3, 0x86, 0x2f, 0xd7, 0xc2, 0xfc, 0x14, 0xb6, 0x33, + 0x91, 0xc2, 0x06, 0xd0, 0x5e, 0x89, 0x28, 0xe2, 0x73, 0x41, 0xe1, 0xd4, 0xb5, 0xe2, 0xae, 0xb9, + 0x07, 0x3b, 0xd9, 0x38, 0xc9, 0x00, 0x31, 0x16, 0x10, 0x78, 0x23, 0xc2, 0x08, 0x03, 0x40, 0x03, + 0x75, 0xd7, 0xfc, 0x06, 0xfa, 0xc5, 0x20, 0x60, 0x7d, 0x30, 0xde, 0x8a, 0x5b, 0xad, 0x89, 0x4d, + 0x76, 0xa8, 0x1d, 0xa2, 0xd0, 0xec, 0x5a, 0xda, 0x3b, 0x33, 0xc1, 0x26, 0x61, 0xc0, 0xf6, 0xa0, + 0x2e, 0x37, 0x04, 0xdd, 0xb1, 0xea, 0x72, 0x63, 0x3e, 0x82, 0xbd, 0xfc, 0x96, 0xdf, 0xd1, 0x70, + 0x12, 0xd7, 0x69, 0xcf, 0x18, 0x83, 0x86, 0xc3, 0x25, 0xd7, 0x1a, 0xd4, 0xc6, 0xb1, 0x80, 0xcb, + 0x85, 0xfe, 0x3d, 0xb5, 0xd9, 0x47, 0xd0, 0x5a, 0x08, 0x77, 0xbe, 0x90, 0x74, 0x06, 0x0c, 0x4b, + 0xf7, 0xd0, 0xd7, 0x20, 0xf4, 0x6f, 0x04, 0x85, 0x7a, 0xc7, 0x52, 0x1d, 0xb3, 0x07, 0xbb, 0xb9, + 0x40, 0x32, 0x2f, 0x12, 0xe7, 0x93, 0x8d, 0x67, 0x5f, 0x00, 0xdc, 0xf0, 0xa5, 0xeb, 0x70, 0xe9, + 0x87, 0xd1, 0xa0, 0xf6, 0xc8, 0x38, 0xda, 0x3e, 0xed, 0xeb, 0xfd, 0xfa, 0x3e, 0x16, 0x58, 0x19, + 0x1d, 0xf3, 0xdf, 0x35, 0xd8, 0xbf, 0x13, 0x04, 0xe8, 0xee, 0x82, 0x47, 0x8b, 0x78, 0x0a, 0xd8, + 0x66, 0xbf, 0x41, 0x77, 0xb9, 0x23, 0x42, 0x7d, 0xbc, 0x77, 0xb5, 0xdd, 0x31, 0x0d, 0x5a, 0x5a, + 0xc8, 0x3e, 0x83, 0x7d, 0x3e, 0x8b, 0x84, 0x27, 0xa7, 0x19, 0x4f, 0x8c, 0x47, 0xc6, 0x51, 0xd3, + 0xea, 0x2b, 0x41, 0xe2, 0x48, 0xc4, 0x46, 0x70, 0x38, 0xbb, 0x7d, 0xc7, 0x3d, 0xe9, 0x7a, 0x22, + 0xab, 0xdf, 0x20, 0xcf, 0x7b, 0xfa, 0x0f, 0x2f, 0x6e, 0x5c, 0x47, 0x78, 0xb6, 0xb0, 0x0e, 0x12, + 0xe5, 0xd4, 0x86, 0xf9, 0x18, 0x7a, 0x85, 0x50, 0xcc, 0xac, 0x6c, 0x2d, 0xbb, 0xb2, 0xe6, 0x4f, + 0x4d, 0xe8, 0x58, 0x22, 0x0a, 0x7c, 0x2f, 0x12, 0xec, 0x19, 0x74, 0xc5, 0xc6, 0x16, 0x8a, 0x55, + 0x6a, 0x85, 0x53, 0xa1, 0x74, 0x5e, 0xc4, 0x72, 0x3c, 0x51, 0x89, 0x32, 0x7b, 0xac, 0x19, 0xb1, + 0x48, 0x73, 0x1a, 0x94, 0xa5, 0xc4, 0xcf, 0x63, 0x4a, 0x34, 0x0a, 0x94, 0xa0, 0x74, 0x0b, 0x9c, + 0xf8, 0x58, 0x73, 0x62, 0xa3, 0xd4, 0x70, 0x8e, 0x14, 0xcf, 0x72, 0xa4, 0xd8, 0x2c, 0x75, 0xbf, + 0x82, 0x15, 0xcf, 0x72, 0xac, 0xd8, 0x2a, 0x85, 0x56, 0xd0, 0xe2, 0x57, 0x19, 0x5a, 0x6c, 0x17, + 0xd8, 0x40, 0x01, 0x4b, 0x78, 0xf1, 0x24, 0xe1, 0xc5, 0x4e, 0x81, 0x49, 0x35, 0xa4, 0x48, 0x8c, + 0x9f, 0xc7, 0xc4, 0xd8, 0x2d, 0x5d, 0xb4, 0x02, 0x33, 0x9e, 0xe5, 0x98, 0x11, 0x4a, 0xa7, 0x53, + 0x41, 0x8d, 0xbf, 0xcb, 0x53, 0xa3, 0xe2, 0xb7, 0x07, 0x05, 0x6c, 0x25, 0x37, 0xfe, 0x36, 0xcb, + 0x8d, 0x3b, 0x05, 0x46, 0xd6, 0xb1, 0xf0, 0xab, 0xe4, 0xf8, 0x18, 0x8f, 0x5e, 0x21, 0xd2, 0xf0, + 0xf4, 0x8b, 0x30, 0xf4, 0x43, 0xcd, 0x5e, 0xaa, 0x63, 0x1e, 0x21, 0xc7, 0xa4, 0xf1, 0xf5, 0x2b, + 0x44, 0x4a, 0x3c, 0x91, 0x89, 0x2e, 0xf3, 0xaf, 0xb5, 0x14, 0x4b, 0x5c, 0x9a, 0xe5, 0xa7, 0xae, + 0xe6, 0xa7, 0x0c, 0xbf, 0xd6, 0x73, 0xfc, 0xca, 0x9e, 0xc0, 0xfe, 0x92, 0x47, 0x52, 0x4d, 0x73, + 0x9a, 0x23, 0xac, 0x1e, 0x0a, 0xd4, 0xfc, 0x14, 0x73, 0x3d, 0x85, 0x83, 0x8c, 0x2e, 0x0f, 0x82, + 0x29, 0xb1, 0x48, 0x83, 0x58, 0xa4, 0x9f, 0x68, 0x3f, 0x0f, 0x82, 0x31, 0x8f, 0x16, 0xe6, 0x59, + 0x3a, 0xff, 0x94, 0xbb, 0x19, 0x34, 0x6c, 0xdf, 0x51, 0xd3, 0xda, 0xb5, 0xa8, 0x8d, 0x7c, 0xbe, + 0xf4, 0xe7, 0xda, 0x33, 0x6c, 0x9a, 0x7f, 0xaf, 0xa5, 0xd8, 0x94, 0xbb, 0xcb, 0xb0, 0x17, 0x7a, + 0xb6, 0x08, 0xde, 0x19, 0x7d, 0xf1, 0xdf, 0x5f, 0x3e, 0xde, 0xfa, 0xf9, 0x97, 0x8f, 0x8f, 0x32, + 0xf5, 0x90, 0x14, 0x9e, 0x23, 0xc2, 0x95, 0xeb, 0xc9, 0x93, 0xb9, 0xff, 0xf4, 0x47, 0x37, 0x14, + 0x27, 0x88, 0x38, 0x1e, 0xdd, 0x4a, 0x11, 0xe9, 0xf5, 0xd1, 0x1e, 0x18, 0x89, 0x07, 0xec, 0x13, + 0x68, 0x48, 0x3e, 0x8f, 0xa9, 0x2a, 0x26, 0xc3, 0xef, 0xbe, 0x7f, 0xc3, 0xdd, 0xd0, 0x22, 0x91, + 0xf9, 0xb7, 0x1a, 0x52, 0x53, 0xee, 0x5c, 0x7c, 0x50, 0x17, 0xfb, 0x60, 0xcc, 0x79, 0x44, 0xcb, + 0x6f, 0x58, 0xd8, 0xc4, 0x91, 0x6b, 0x21, 0x88, 0x2e, 0x0c, 0x0b, 0x9b, 0xe6, 0xbf, 0xea, 0x69, + 0xbc, 0x24, 0xe9, 0xeb, 0x8e, 0x87, 0x87, 0xd0, 0x74, 0x3d, 0x47, 0x6c, 0xc8, 0x45, 0xc3, 0x52, + 0x1d, 0x36, 0x52, 0x69, 0xd6, 0x78, 0x4f, 0xb7, 0x29, 0x31, 0xbf, 0x8c, 0x13, 0x73, 0xe3, 0x3d, + 0xad, 0x28, 0x38, 0xda, 0x09, 0x42, 0xdf, 0xbf, 0xa6, 0xb9, 0xbd, 0x97, 0x1d, 0x82, 0x67, 0x52, + 0x47, 0x2b, 0x97, 0x94, 0xf5, 0xea, 0xb6, 0xd3, 0x10, 0xfc, 0x33, 0x16, 0x06, 0x59, 0x06, 0xfb, + 0x90, 0x7b, 0x6b, 0x1e, 0xa4, 0xf1, 0x9f, 0x90, 0x9b, 0x79, 0x08, 0xec, 0x2e, 0x6b, 0x99, 0x7f, + 0xa9, 0x61, 0xa5, 0x90, 0x27, 0x24, 0xf6, 0x04, 0xda, 0xf6, 0x82, 0x7b, 0x73, 0x51, 0x5d, 0x26, + 0xc4, 0x0a, 0xec, 0x35, 0xdc, 0xb7, 0x11, 0xec, 0x45, 0xeb, 0x68, 0x1a, 0xf0, 0x90, 0xaf, 0xa6, + 0x31, 0xb6, 0x9e, 0x4b, 0x02, 0xe7, 0xb1, 0xd6, 0x1b, 0x54, 0x8a, 0xac, 0x7b, 0x76, 0x6e, 0xe0, + 0x5c, 0x81, 0xcc, 0x9f, 0x6b, 0xd0, 0x2b, 0xa8, 0xb2, 0x11, 0xec, 0x2b, 0xd6, 0x88, 0xdc, 0x77, + 0x42, 0xfd, 0x24, 0xd2, 0x59, 0x39, 0xb6, 0x4e, 0x8e, 0x5f, 0xba, 0xef, 0x84, 0xb6, 0xde, 0x9b, + 0xe5, 0x07, 0xd8, 0x19, 0xec, 0xc9, 0x4d, 0xce, 0x40, 0x3e, 0x43, 0x5f, 0x6d, 0x32, 0xe8, 0x1d, + 0x99, 0xe9, 0xb1, 0x31, 0x1c, 0xa8, 0xdf, 0xcf, 0xfd, 0x28, 0x72, 0x83, 0x18, 0x6f, 0xe4, 0xb2, + 0x09, 0x39, 0xf0, 0x8a, 0x14, 0xb4, 0x11, 0xe5, 0x73, 0x76, 0xc8, 0xfc, 0x13, 0xf4, 0x0a, 0x8e, + 0xb2, 0x87, 0xd0, 0x5d, 0xf1, 0xcd, 0x74, 0x86, 0x1b, 0x4a, 0x73, 0x6a, 0x5a, 0x9d, 0x15, 0xdf, + 0xd0, 0x06, 0xb3, 0xfb, 0xd0, 0x46, 0xa1, 0xdc, 0x28, 0x6f, 0x9b, 0x56, 0x6b, 0xc5, 0x37, 0x57, + 0x9b, 0x44, 0x80, 0x27, 0x58, 0xd7, 0x87, 0x2b, 0xbe, 0x79, 0xc5, 0x23, 0xf3, 0x02, 0x76, 0xb2, + 0x33, 0xf9, 0xbf, 0xcc, 0xa3, 0x95, 0x7a, 0xce, 0xca, 0x4b, 0xd8, 0xbf, 0x33, 0x1f, 0xf6, 0x25, + 0xdc, 0x53, 0xcb, 0x10, 0xf0, 0x50, 0xaa, 0x95, 0xcc, 0x9a, 0x65, 0x24, 0x7c, 0xc3, 0x43, 0x89, + 0xbf, 0xa7, 0x1f, 0x98, 0xff, 0xa8, 0x43, 0x4b, 0x95, 0x80, 0xec, 0x01, 0x56, 0x07, 0xdc, 0xf5, + 0xa6, 0xae, 0x13, 0x67, 0x25, 0xea, 0x4f, 0x9c, 0xcc, 0xb1, 0xaa, 0xe7, 0x8e, 0x15, 0x83, 0x86, + 0x74, 0x57, 0x42, 0xcf, 0x90, 0xda, 0xe8, 0xb2, 0xb7, 0x5e, 0xd1, 0x8a, 0x34, 0xd4, 0x8a, 0x78, + 0xeb, 0x15, 0xae, 0xc8, 0x29, 0xec, 0x66, 0xd2, 0x8b, 0xeb, 0xe8, 0xb2, 0x67, 0x2f, 0xbb, 0x3d, + 0x93, 0x0b, 0x6b, 0x3b, 0x49, 0x34, 0x13, 0x87, 0x1d, 0x01, 0xe5, 0x9d, 0xa9, 0x2a, 0x2d, 0x54, + 0x3e, 0x6a, 0x51, 0x3e, 0xda, 0xc3, 0x71, 0x5d, 0x7b, 0x60, 0x7d, 0xfb, 0x10, 0xba, 0x78, 0xd6, + 0x94, 0x4a, 0x9b, 0x54, 0x3a, 0x38, 0x40, 0xc2, 0x4f, 0xa1, 0x97, 0x96, 0xa7, 0x4a, 0xa5, 0xa3, + 0xac, 0xa4, 0xc3, 0xa4, 0xf8, 0x00, 0x3a, 0x49, 0xde, 0xeb, 0x92, 0x46, 0x9b, 0xeb, 0x74, 0x37, + 0x81, 0xb6, 0x76, 0xb1, 0xb4, 0xbe, 0x7e, 0x02, 0x4d, 0x5c, 0xf5, 0x38, 0x68, 0xe3, 0xaa, 0x87, + 0x56, 0x5b, 0x48, 0x5d, 0x65, 0x2b, 0x15, 0xf3, 0x0c, 0x76, 0x73, 0xe3, 0x48, 0xd0, 0xd2, 0x97, + 0x7c, 0xa9, 0x37, 0x4a, 0x75, 0x92, 0xdf, 0xd4, 0xd3, 0xdf, 0x98, 0xdf, 0x40, 0x37, 0x39, 0xe2, + 0xb8, 0xd4, 0xc1, 0x7a, 0x36, 0x8d, 0x2f, 0x4b, 0x3b, 0x56, 0x2b, 0x58, 0xcf, 0xbe, 0x53, 0xf7, + 0xa5, 0xc0, 0xff, 0x51, 0xd7, 0xfa, 0x86, 0xa5, 0x3a, 0xe6, 0xb7, 0xd0, 0x89, 0x6b, 0xf1, 0x6a, + 0x68, 0xc5, 0x56, 0x9b, 0xff, 0xac, 0x41, 0x4b, 0xa5, 0xc7, 0x92, 0xfb, 0xd9, 0x97, 0x74, 0x71, + 0x59, 0x8b, 0x29, 0x4e, 0x9a, 0x80, 0x7b, 0xc9, 0x9b, 0x80, 0x02, 0x1d, 0x5f, 0xdd, 0x06, 0xc2, + 0xea, 0x92, 0x16, 0x36, 0xd9, 0x27, 0xb0, 0xa3, 0x20, 0x91, 0x0c, 0x5d, 0x2f, 0x26, 0xc7, 0x6d, + 0x1a, 0xbb, 0xa4, 0x21, 0xdc, 0x52, 0xa5, 0xe2, 0x7a, 0x52, 0xa7, 0xc1, 0x0e, 0x0d, 0x4c, 0x3c, + 0x69, 0x3e, 0x84, 0x06, 0xd9, 0x01, 0x68, 0x5d, 0x5e, 0x59, 0x93, 0xd7, 0xaf, 0xfa, 0x5b, 0xac, + 0x0d, 0xc6, 0xe4, 0xf5, 0x55, 0xbf, 0x76, 0xfa, 0x53, 0x13, 0x7a, 0xcf, 0x47, 0xe7, 0x93, 0xe7, + 0x41, 0xb0, 0x74, 0x6d, 0x4e, 0x95, 0xc9, 0x09, 0x34, 0xa8, 0xf6, 0x2a, 0x79, 0x02, 0x19, 0x96, + 0x5d, 0x02, 0xd8, 0x29, 0x34, 0xa9, 0x04, 0x63, 0x65, 0x2f, 0x21, 0xc3, 0xd2, 0xbb, 0x00, 0xfe, + 0x44, 0x15, 0x69, 0x77, 0x1f, 0x44, 0x86, 0x65, 0x17, 0x02, 0xf6, 0x7b, 0xe8, 0xa6, 0xc5, 0x53, + 0xd5, 0xb3, 0xc8, 0xb0, 0xf2, 0x6a, 0x80, 0xf8, 0xb4, 0x80, 0xaa, 0x7a, 0x1c, 0x19, 0x56, 0xde, + 0x0f, 0xd8, 0x33, 0x68, 0xc7, 0xb5, 0x4d, 0xf9, 0x13, 0xc9, 0xb0, 0xe2, 0x8a, 0x80, 0xcb, 0xa3, + 0x2a, 0x8e, 0xb2, 0x97, 0x8f, 0x61, 0x69, 0xd5, 0xcf, 0xbe, 0x86, 0x96, 0x4e, 0xb6, 0xa5, 0xaf, + 0x2b, 0xc3, 0xf2, 0xbb, 0x05, 0x4e, 0x32, 0xbd, 0x24, 0x57, 0x3d, 0x9b, 0x0c, 0x2b, 0x6f, 0x0d, + 0xec, 0x39, 0x40, 0xe6, 0x76, 0x5c, 0xf9, 0x78, 0x32, 0xac, 0xbe, 0x3b, 0x30, 0x3c, 0x3b, 0xc9, + 0xfd, 0xb4, 0xfc, 0x09, 0x65, 0x58, 0x75, 0x7d, 0x98, 0xb5, 0xe8, 0x59, 0xee, 0xab, 0xff, 0x05, + 0x00, 0x00, 0xff, 0xff, 0x2b, 0x22, 0xd6, 0xe4, 0xe1, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 516cca15..59424e75 100644 --- a/types/types.proto +++ b/types/types.proto @@ -157,7 +157,35 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator diffs = 1; + repeated Validator changes = 1; + ConsensusParams consensus_param_changes = 2; +} + +message ConsensusParams{ + BlockSizeParams block_size_params = 1; + TxSizeParams tx_size_params = 2; + BlockGossipParams block_gossip_params = 3; +} + +// BlockSizeParams contain limits on the block size. +message BlockSizeParams{ + // NOTE: must not be 0 nor greater than 100MB + int32 max_bytes = 1; + int32 max_txs = 2; + int64 max_gas = 3; +} + +// TxSizeParams contain limits on the tx size. +message TxSizeParams { + int32 max_bytes = 1; + int64 max_gas = 2; +} + +// BlockGossipParams determine consensus critical +// elements of how blocks are gossiped +message BlockGossipParams { + // Note: must not be 0 + int32 block_part_size_bytes = 1; } //---------------------------------------- From 895e14d6bd9cdad98eab4a051decbaad46f7eebd Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Dec 2017 17:57:43 +0100 Subject: [PATCH 406/545] Update Diffs to Changes, fix README --- README.md | 3 ++- example/dummy/dummy_test.go | 2 +- example/dummy/persistent_dummy.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46abcc4f..025479e4 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,8 @@ Here, we describe the requests and responses as function arguments and return va * __Arguments__: * `Height (int64)`: The block height that ended * __Returns__: - * `Diffs ([]Validator)`: Changed validators with new voting powers (0 to remove) + * `Changes ([]Validator)`: Changed validators with new voting powers (0 to remove) + * `ConsensusParamChanges (ConsensusParams)`: Communicate changes to consensus-critical time/size parameters to tendermint core * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index bfe9ef7a..2d075b0b 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -188,7 +188,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() - valsEqual(t, diff, resEndBlock.Diffs) + valsEqual(t, diff, resEndBlock.Changes) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 6f389c50..f00b7473 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -125,7 +125,7 @@ func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) t // Update the validator set func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - return types.ResponseEndBlock{Diffs: app.changes} + return types.ResponseEndBlock{Changes: app.changes} } //--------------------------------------------- From 9c5e1a824d0c649ba90c91d8429fad771df5b71d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 14 Dec 2017 09:27:20 +0100 Subject: [PATCH 407/545] Updated naming of EndBlock parameters * Changes -> Updates for validators * ConsensusParams.XXXParams -> ConsensusParams.XXX * As per feedback from Jae on PR --- README.md | 4 +- example/dummy/dummy_test.go | 4 +- example/dummy/persistent_dummy.go | 10 +- types/types.pb.go | 313 +++++++++++++++--------------- types/types.proto | 24 +-- 5 files changed, 179 insertions(+), 176 deletions(-) diff --git a/README.md b/README.md index 025479e4..9686a6a0 100644 --- a/README.md +++ b/README.md @@ -185,8 +185,8 @@ Here, we describe the requests and responses as function arguments and return va * __Arguments__: * `Height (int64)`: The block height that ended * __Returns__: - * `Changes ([]Validator)`: Changed validators with new voting powers (0 to remove) - * `ConsensusParamChanges (ConsensusParams)`: Communicate changes to consensus-critical time/size parameters to tendermint core + * `Updates ([]Validator)`: Updated validators with new voting powers (0 to remove) + * `ConsensusParamChanges (ConsensusParams)`: Changes to consensus-critical time/size parameters to tendermint core * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 2d075b0b..4be4f688 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -107,7 +107,7 @@ func TestPersistentDummyInfo(t *testing.T) { } // add a validator, remove a validator, update a validator -func TestValSetChanges(t *testing.T) { +func TestValSetUpdates(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO if err != nil { t.Fatal(err) @@ -188,7 +188,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() - valsEqual(t, diff, resEndBlock.Changes) + valsEqual(t, diff, resEndBlock.Updates) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index f00b7473..a822deeb 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -28,7 +28,7 @@ type PersistentDummyApplication struct { app *DummyApplication // validator set - changes []*types.Validator + updates []*types.Validator logger log.Logger } @@ -71,7 +71,7 @@ func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.ResponseDelive // format is "val:pubkey/power" if isValidatorTx(tx) { // update validators in the merkle tree - // and in app.changes + // and in app.updates return app.execValidatorTx(tx) } @@ -119,13 +119,13 @@ func (app *PersistentDummyApplication) InitChain(req types.RequestInitChain) typ // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { // reset valset changes - app.changes = make([]*types.Validator, 0) + app.updates = make([]*types.Validator, 0) return types.ResponseBeginBlock{} } // Update the validator set func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - return types.ResponseEndBlock{Changes: app.changes} + return types.ResponseEndBlock{Updates: app.updates} } //--------------------------------------------- @@ -216,7 +216,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types } // we only update the changes array if we successfully updated the tree - app.changes = append(app.changes, v) + app.updates = append(app.updates, v) return types.ResponseDeliverTx{Code: code.CodeTypeOK} } diff --git a/types/types.pb.go b/types/types.pb.go index 5a0e9b7a..b3ebc1de 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -34,9 +34,9 @@ It has these top-level messages: ResponseBeginBlock ResponseEndBlock ConsensusParams - BlockSizeParams - TxSizeParams - BlockGossipParams + BlockSize + TxSize + BlockGossip Header BlockID PartSetHeader @@ -1398,8 +1398,8 @@ func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } type ResponseEndBlock struct { - Changes []*Validator `protobuf:"bytes,1,rep,name=changes" json:"changes,omitempty"` - ConsensusParamChanges *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_changes,json=consensusParamChanges" json:"consensus_param_changes,omitempty"` + Updates []*Validator `protobuf:"bytes,1,rep,name=updates" json:"updates,omitempty"` + ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"` } func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } @@ -1407,24 +1407,26 @@ func (m *ResponseEndBlock) String() string { return proto.CompactText func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} } -func (m *ResponseEndBlock) GetChanges() []*Validator { +func (m *ResponseEndBlock) GetUpdates() []*Validator { if m != nil { - return m.Changes + return m.Updates } return nil } -func (m *ResponseEndBlock) GetConsensusParamChanges() *ConsensusParams { +func (m *ResponseEndBlock) GetConsensusParamUpdates() *ConsensusParams { if m != nil { - return m.ConsensusParamChanges + return m.ConsensusParamUpdates } return nil } +// ConsensusParams contains all consensus-relevant parameters +// that can be adjusted by the abci app type ConsensusParams struct { - BlockSizeParams *BlockSizeParams `protobuf:"bytes,1,opt,name=block_size_params,json=blockSizeParams" json:"block_size_params,omitempty"` - TxSizeParams *TxSizeParams `protobuf:"bytes,2,opt,name=tx_size_params,json=txSizeParams" json:"tx_size_params,omitempty"` - BlockGossipParams *BlockGossipParams `protobuf:"bytes,3,opt,name=block_gossip_params,json=blockGossipParams" json:"block_gossip_params,omitempty"` + BlockSize *BlockSize `protobuf:"bytes,1,opt,name=block_size,json=blockSize" json:"block_size,omitempty"` + TxSize *TxSize `protobuf:"bytes,2,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"` + BlockGossip *BlockGossip `protobuf:"bytes,3,opt,name=block_gossip,json=blockGossip" json:"block_gossip,omitempty"` } func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } @@ -1432,99 +1434,99 @@ func (m *ConsensusParams) String() string { return proto.CompactTextS func (*ConsensusParams) ProtoMessage() {} func (*ConsensusParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} } -func (m *ConsensusParams) GetBlockSizeParams() *BlockSizeParams { +func (m *ConsensusParams) GetBlockSize() *BlockSize { if m != nil { - return m.BlockSizeParams + return m.BlockSize } return nil } -func (m *ConsensusParams) GetTxSizeParams() *TxSizeParams { +func (m *ConsensusParams) GetTxSize() *TxSize { if m != nil { - return m.TxSizeParams + return m.TxSize } return nil } -func (m *ConsensusParams) GetBlockGossipParams() *BlockGossipParams { +func (m *ConsensusParams) GetBlockGossip() *BlockGossip { if m != nil { - return m.BlockGossipParams + return m.BlockGossip } return nil } -// BlockSizeParams contain limits on the block size. -type BlockSizeParams struct { +// BlockSize contain limits on the block size. +type BlockSize struct { // NOTE: must not be 0 nor greater than 100MB MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` MaxTxs int32 `protobuf:"varint,2,opt,name=max_txs,json=maxTxs,proto3" json:"max_txs,omitempty"` MaxGas int64 `protobuf:"varint,3,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` } -func (m *BlockSizeParams) Reset() { *m = BlockSizeParams{} } -func (m *BlockSizeParams) String() string { return proto.CompactTextString(m) } -func (*BlockSizeParams) ProtoMessage() {} -func (*BlockSizeParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} } +func (m *BlockSize) Reset() { *m = BlockSize{} } +func (m *BlockSize) String() string { return proto.CompactTextString(m) } +func (*BlockSize) ProtoMessage() {} +func (*BlockSize) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} } -func (m *BlockSizeParams) GetMaxBytes() int32 { +func (m *BlockSize) GetMaxBytes() int32 { if m != nil { return m.MaxBytes } return 0 } -func (m *BlockSizeParams) GetMaxTxs() int32 { +func (m *BlockSize) GetMaxTxs() int32 { if m != nil { return m.MaxTxs } return 0 } -func (m *BlockSizeParams) GetMaxGas() int64 { +func (m *BlockSize) GetMaxGas() int64 { if m != nil { return m.MaxGas } return 0 } -// TxSizeParams contain limits on the tx size. -type TxSizeParams struct { +// TxSize contain limits on the tx size. +type TxSize struct { MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` } -func (m *TxSizeParams) Reset() { *m = TxSizeParams{} } -func (m *TxSizeParams) String() string { return proto.CompactTextString(m) } -func (*TxSizeParams) ProtoMessage() {} -func (*TxSizeParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } +func (m *TxSize) Reset() { *m = TxSize{} } +func (m *TxSize) String() string { return proto.CompactTextString(m) } +func (*TxSize) ProtoMessage() {} +func (*TxSize) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} } -func (m *TxSizeParams) GetMaxBytes() int32 { +func (m *TxSize) GetMaxBytes() int32 { if m != nil { return m.MaxBytes } return 0 } -func (m *TxSizeParams) GetMaxGas() int64 { +func (m *TxSize) GetMaxGas() int64 { if m != nil { return m.MaxGas } return 0 } -// BlockGossipParams determine consensus critical +// BlockGossip determine consensus critical // elements of how blocks are gossiped -type BlockGossipParams struct { +type BlockGossip struct { // Note: must not be 0 BlockPartSizeBytes int32 `protobuf:"varint,1,opt,name=block_part_size_bytes,json=blockPartSizeBytes,proto3" json:"block_part_size_bytes,omitempty"` } -func (m *BlockGossipParams) Reset() { *m = BlockGossipParams{} } -func (m *BlockGossipParams) String() string { return proto.CompactTextString(m) } -func (*BlockGossipParams) ProtoMessage() {} -func (*BlockGossipParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} } +func (m *BlockGossip) Reset() { *m = BlockGossip{} } +func (m *BlockGossip) String() string { return proto.CompactTextString(m) } +func (*BlockGossip) ProtoMessage() {} +func (*BlockGossip) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} } -func (m *BlockGossipParams) GetBlockPartSizeBytes() int32 { +func (m *BlockGossip) GetBlockPartSizeBytes() int32 { if m != nil { return m.BlockPartSizeBytes } @@ -1774,9 +1776,9 @@ func init() { proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") - proto.RegisterType((*BlockSizeParams)(nil), "types.BlockSizeParams") - proto.RegisterType((*TxSizeParams)(nil), "types.TxSizeParams") - proto.RegisterType((*BlockGossipParams)(nil), "types.BlockGossipParams") + proto.RegisterType((*BlockSize)(nil), "types.BlockSize") + proto.RegisterType((*TxSize)(nil), "types.TxSize") + proto.RegisterType((*BlockGossip)(nil), "types.BlockGossip") proto.RegisterType((*Header)(nil), "types.Header") proto.RegisterType((*BlockID)(nil), "types.BlockID") proto.RegisterType((*PartSetHeader)(nil), "types.PartSetHeader") @@ -2191,115 +2193,114 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1756 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6e, 0x1c, 0xc7, - 0x11, 0xe6, 0xee, 0xec, 0x6f, 0xf1, 0x67, 0x97, 0x4d, 0xca, 0x5a, 0xad, 0x0e, 0x96, 0x07, 0x08, - 0x4c, 0xc9, 0x16, 0x69, 0xd3, 0x70, 0x20, 0xda, 0x41, 0x00, 0x2d, 0x29, 0x69, 0x17, 0x06, 0x14, - 0x65, 0x48, 0xf8, 0xba, 0xe9, 0x9d, 0x69, 0xee, 0x0e, 0xb4, 0x3b, 0x33, 0x9e, 0xe9, 0xa5, 0x97, - 0x42, 0x1e, 0xc1, 0xc8, 0x35, 0xe7, 0xe4, 0x12, 0x20, 0x2f, 0x90, 0x63, 0x6e, 0x41, 0x9e, 0xc1, - 0x07, 0x3f, 0x4b, 0x50, 0xd5, 0x3d, 0xbf, 0x9c, 0x31, 0x02, 0x1d, 0x74, 0x19, 0x74, 0x77, 0xd5, - 0x57, 0x53, 0xdd, 0x5d, 0xfd, 0x55, 0x75, 0xc3, 0xbe, 0xbc, 0x0d, 0x44, 0x74, 0x42, 0xdf, 0xe3, - 0x20, 0xf4, 0xa5, 0xcf, 0x9a, 0xd4, 0x19, 0x3e, 0x9d, 0xbb, 0x72, 0xb1, 0x9e, 0x1d, 0xdb, 0xfe, - 0xea, 0x64, 0xee, 0xcf, 0xfd, 0x13, 0x92, 0xce, 0xd6, 0xd7, 0xd4, 0xa3, 0x0e, 0xb5, 0x14, 0xca, - 0xfc, 0x4f, 0x03, 0xda, 0x96, 0xf8, 0x61, 0x2d, 0x22, 0xc9, 0x8e, 0xa0, 0x21, 0xec, 0x85, 0x3f, - 0xa8, 0x3d, 0xaa, 0x1d, 0x6d, 0x9f, 0xb2, 0x63, 0x65, 0x5d, 0x4b, 0x5f, 0xd8, 0x0b, 0x7f, 0xbc, - 0x65, 0x91, 0x06, 0xfb, 0x0c, 0x9a, 0xd7, 0xcb, 0x75, 0xb4, 0x18, 0xd4, 0x49, 0xf5, 0x20, 0xaf, - 0xfa, 0x12, 0x45, 0xe3, 0x2d, 0x4b, 0xe9, 0xa0, 0x59, 0xd7, 0xbb, 0xf6, 0x07, 0x46, 0x99, 0xd9, - 0x89, 0x77, 0x4d, 0x66, 0x51, 0x83, 0x3d, 0x03, 0x88, 0x84, 0x9c, 0xfa, 0x81, 0x74, 0x7d, 0x6f, - 0xd0, 0x20, 0xfd, 0xfb, 0x79, 0xfd, 0x4b, 0x21, 0xff, 0x40, 0xe2, 0xf1, 0x96, 0xd5, 0x8d, 0xe2, - 0x0e, 0x22, 0x1d, 0xb1, 0x74, 0x6f, 0x44, 0x38, 0x95, 0x9b, 0x41, 0xb3, 0x0c, 0x79, 0xa1, 0xe4, - 0x57, 0x1b, 0x44, 0x3a, 0x71, 0x87, 0x9d, 0x42, 0xc7, 0x5e, 0x08, 0xfb, 0x2d, 0xe2, 0x5a, 0x84, - 0xbb, 0x97, 0xc7, 0x9d, 0xa3, 0x94, 0x50, 0x6d, 0x5b, 0x35, 0xd9, 0x31, 0xb4, 0x6c, 0x7f, 0xb5, - 0x72, 0xe5, 0xa0, 0x4d, 0x88, 0xc3, 0x02, 0x82, 0x64, 0xe3, 0x2d, 0x4b, 0x6b, 0xe1, 0x72, 0xfd, - 0xb0, 0x16, 0xe1, 0xed, 0xa0, 0x53, 0xb6, 0x5c, 0x7f, 0x44, 0x11, 0x2e, 0x17, 0xe9, 0xe0, 0x54, - 0x5c, 0xcf, 0x95, 0x53, 0x7b, 0xc1, 0x5d, 0x6f, 0xd0, 0x2d, 0x9b, 0xca, 0xc4, 0x73, 0xe5, 0x39, - 0x8a, 0x71, 0x2a, 0x6e, 0xdc, 0x61, 0xdf, 0xc2, 0xf6, 0x4c, 0xcc, 0x5d, 0x6f, 0x3a, 0x5b, 0xfa, - 0xf6, 0xdb, 0x01, 0x10, 0x74, 0x90, 0x87, 0x8e, 0x50, 0x61, 0x84, 0xf2, 0xf1, 0x96, 0x05, 0xb3, - 0xa4, 0xc7, 0xbe, 0x86, 0xae, 0xf0, 0x1c, 0x0d, 0xdd, 0x26, 0xe8, 0x47, 0x85, 0x08, 0xf0, 0x9c, - 0x18, 0xd8, 0x11, 0xba, 0x3d, 0x6a, 0x43, 0xf3, 0x86, 0x2f, 0xd7, 0xc2, 0xfc, 0x14, 0xb6, 0x33, - 0x91, 0xc2, 0x06, 0xd0, 0x5e, 0x89, 0x28, 0xe2, 0x73, 0x41, 0xe1, 0xd4, 0xb5, 0xe2, 0xae, 0xb9, - 0x07, 0x3b, 0xd9, 0x38, 0xc9, 0x00, 0x31, 0x16, 0x10, 0x78, 0x23, 0xc2, 0x08, 0x03, 0x40, 0x03, - 0x75, 0xd7, 0xfc, 0x06, 0xfa, 0xc5, 0x20, 0x60, 0x7d, 0x30, 0xde, 0x8a, 0x5b, 0xad, 0x89, 0x4d, - 0x76, 0xa8, 0x1d, 0xa2, 0xd0, 0xec, 0x5a, 0xda, 0x3b, 0x33, 0xc1, 0x26, 0x61, 0xc0, 0xf6, 0xa0, - 0x2e, 0x37, 0x04, 0xdd, 0xb1, 0xea, 0x72, 0x63, 0x3e, 0x82, 0xbd, 0xfc, 0x96, 0xdf, 0xd1, 0x70, - 0x12, 0xd7, 0x69, 0xcf, 0x18, 0x83, 0x86, 0xc3, 0x25, 0xd7, 0x1a, 0xd4, 0xc6, 0xb1, 0x80, 0xcb, - 0x85, 0xfe, 0x3d, 0xb5, 0xd9, 0x47, 0xd0, 0x5a, 0x08, 0x77, 0xbe, 0x90, 0x74, 0x06, 0x0c, 0x4b, - 0xf7, 0xd0, 0xd7, 0x20, 0xf4, 0x6f, 0x04, 0x85, 0x7a, 0xc7, 0x52, 0x1d, 0xb3, 0x07, 0xbb, 0xb9, - 0x40, 0x32, 0x2f, 0x12, 0xe7, 0x93, 0x8d, 0x67, 0x5f, 0x00, 0xdc, 0xf0, 0xa5, 0xeb, 0x70, 0xe9, - 0x87, 0xd1, 0xa0, 0xf6, 0xc8, 0x38, 0xda, 0x3e, 0xed, 0xeb, 0xfd, 0xfa, 0x3e, 0x16, 0x58, 0x19, - 0x1d, 0xf3, 0xdf, 0x35, 0xd8, 0xbf, 0x13, 0x04, 0xe8, 0xee, 0x82, 0x47, 0x8b, 0x78, 0x0a, 0xd8, - 0x66, 0xbf, 0x41, 0x77, 0xb9, 0x23, 0x42, 0x7d, 0xbc, 0x77, 0xb5, 0xdd, 0x31, 0x0d, 0x5a, 0x5a, - 0xc8, 0x3e, 0x83, 0x7d, 0x3e, 0x8b, 0x84, 0x27, 0xa7, 0x19, 0x4f, 0x8c, 0x47, 0xc6, 0x51, 0xd3, - 0xea, 0x2b, 0x41, 0xe2, 0x48, 0xc4, 0x46, 0x70, 0x38, 0xbb, 0x7d, 0xc7, 0x3d, 0xe9, 0x7a, 0x22, - 0xab, 0xdf, 0x20, 0xcf, 0x7b, 0xfa, 0x0f, 0x2f, 0x6e, 0x5c, 0x47, 0x78, 0xb6, 0xb0, 0x0e, 0x12, - 0xe5, 0xd4, 0x86, 0xf9, 0x18, 0x7a, 0x85, 0x50, 0xcc, 0xac, 0x6c, 0x2d, 0xbb, 0xb2, 0xe6, 0x4f, - 0x4d, 0xe8, 0x58, 0x22, 0x0a, 0x7c, 0x2f, 0x12, 0xec, 0x19, 0x74, 0xc5, 0xc6, 0x16, 0x8a, 0x55, - 0x6a, 0x85, 0x53, 0xa1, 0x74, 0x5e, 0xc4, 0x72, 0x3c, 0x51, 0x89, 0x32, 0x7b, 0xac, 0x19, 0xb1, - 0x48, 0x73, 0x1a, 0x94, 0xa5, 0xc4, 0xcf, 0x63, 0x4a, 0x34, 0x0a, 0x94, 0xa0, 0x74, 0x0b, 0x9c, - 0xf8, 0x58, 0x73, 0x62, 0xa3, 0xd4, 0x70, 0x8e, 0x14, 0xcf, 0x72, 0xa4, 0xd8, 0x2c, 0x75, 0xbf, - 0x82, 0x15, 0xcf, 0x72, 0xac, 0xd8, 0x2a, 0x85, 0x56, 0xd0, 0xe2, 0x57, 0x19, 0x5a, 0x6c, 0x17, - 0xd8, 0x40, 0x01, 0x4b, 0x78, 0xf1, 0x24, 0xe1, 0xc5, 0x4e, 0x81, 0x49, 0x35, 0xa4, 0x48, 0x8c, - 0x9f, 0xc7, 0xc4, 0xd8, 0x2d, 0x5d, 0xb4, 0x02, 0x33, 0x9e, 0xe5, 0x98, 0x11, 0x4a, 0xa7, 0x53, - 0x41, 0x8d, 0xbf, 0xcb, 0x53, 0xa3, 0xe2, 0xb7, 0x07, 0x05, 0x6c, 0x25, 0x37, 0xfe, 0x36, 0xcb, - 0x8d, 0x3b, 0x05, 0x46, 0xd6, 0xb1, 0xf0, 0xab, 0xe4, 0xf8, 0x18, 0x8f, 0x5e, 0x21, 0xd2, 0xf0, - 0xf4, 0x8b, 0x30, 0xf4, 0x43, 0xcd, 0x5e, 0xaa, 0x63, 0x1e, 0x21, 0xc7, 0xa4, 0xf1, 0xf5, 0x2b, - 0x44, 0x4a, 0x3c, 0x91, 0x89, 0x2e, 0xf3, 0xaf, 0xb5, 0x14, 0x4b, 0x5c, 0x9a, 0xe5, 0xa7, 0xae, - 0xe6, 0xa7, 0x0c, 0xbf, 0xd6, 0x73, 0xfc, 0xca, 0x9e, 0xc0, 0xfe, 0x92, 0x47, 0x52, 0x4d, 0x73, - 0x9a, 0x23, 0xac, 0x1e, 0x0a, 0xd4, 0xfc, 0x14, 0x73, 0x3d, 0x85, 0x83, 0x8c, 0x2e, 0x0f, 0x82, - 0x29, 0xb1, 0x48, 0x83, 0x58, 0xa4, 0x9f, 0x68, 0x3f, 0x0f, 0x82, 0x31, 0x8f, 0x16, 0xe6, 0x59, - 0x3a, 0xff, 0x94, 0xbb, 0x19, 0x34, 0x6c, 0xdf, 0x51, 0xd3, 0xda, 0xb5, 0xa8, 0x8d, 0x7c, 0xbe, - 0xf4, 0xe7, 0xda, 0x33, 0x6c, 0x9a, 0x7f, 0xaf, 0xa5, 0xd8, 0x94, 0xbb, 0xcb, 0xb0, 0x17, 0x7a, - 0xb6, 0x08, 0xde, 0x19, 0x7d, 0xf1, 0xdf, 0x5f, 0x3e, 0xde, 0xfa, 0xf9, 0x97, 0x8f, 0x8f, 0x32, - 0xf5, 0x90, 0x14, 0x9e, 0x23, 0xc2, 0x95, 0xeb, 0xc9, 0x93, 0xb9, 0xff, 0xf4, 0x47, 0x37, 0x14, - 0x27, 0x88, 0x38, 0x1e, 0xdd, 0x4a, 0x11, 0xe9, 0xf5, 0xd1, 0x1e, 0x18, 0x89, 0x07, 0xec, 0x13, - 0x68, 0x48, 0x3e, 0x8f, 0xa9, 0x2a, 0x26, 0xc3, 0xef, 0xbe, 0x7f, 0xc3, 0xdd, 0xd0, 0x22, 0x91, - 0xf9, 0xb7, 0x1a, 0x52, 0x53, 0xee, 0x5c, 0x7c, 0x50, 0x17, 0xfb, 0x60, 0xcc, 0x79, 0x44, 0xcb, - 0x6f, 0x58, 0xd8, 0xc4, 0x91, 0x6b, 0x21, 0x88, 0x2e, 0x0c, 0x0b, 0x9b, 0xe6, 0xbf, 0xea, 0x69, - 0xbc, 0x24, 0xe9, 0xeb, 0x8e, 0x87, 0x87, 0xd0, 0x74, 0x3d, 0x47, 0x6c, 0xc8, 0x45, 0xc3, 0x52, - 0x1d, 0x36, 0x52, 0x69, 0xd6, 0x78, 0x4f, 0xb7, 0x29, 0x31, 0xbf, 0x8c, 0x13, 0x73, 0xe3, 0x3d, - 0xad, 0x28, 0x38, 0xda, 0x09, 0x42, 0xdf, 0xbf, 0xa6, 0xb9, 0xbd, 0x97, 0x1d, 0x82, 0x67, 0x52, - 0x47, 0x2b, 0x97, 0x94, 0xf5, 0xea, 0xb6, 0xd3, 0x10, 0xfc, 0x33, 0x16, 0x06, 0x59, 0x06, 0xfb, - 0x90, 0x7b, 0x6b, 0x1e, 0xa4, 0xf1, 0x9f, 0x90, 0x9b, 0x79, 0x08, 0xec, 0x2e, 0x6b, 0x99, 0x7f, - 0xa9, 0x61, 0xa5, 0x90, 0x27, 0x24, 0xf6, 0x04, 0xda, 0xf6, 0x82, 0x7b, 0x73, 0x51, 0x5d, 0x26, - 0xc4, 0x0a, 0xec, 0x35, 0xdc, 0xb7, 0x11, 0xec, 0x45, 0xeb, 0x68, 0x1a, 0xf0, 0x90, 0xaf, 0xa6, - 0x31, 0xb6, 0x9e, 0x4b, 0x02, 0xe7, 0xb1, 0xd6, 0x1b, 0x54, 0x8a, 0xac, 0x7b, 0x76, 0x6e, 0xe0, - 0x5c, 0x81, 0xcc, 0x9f, 0x6b, 0xd0, 0x2b, 0xa8, 0xb2, 0x11, 0xec, 0x2b, 0xd6, 0x88, 0xdc, 0x77, - 0x42, 0xfd, 0x24, 0xd2, 0x59, 0x39, 0xb6, 0x4e, 0x8e, 0x5f, 0xba, 0xef, 0x84, 0xb6, 0xde, 0x9b, - 0xe5, 0x07, 0xd8, 0x19, 0xec, 0xc9, 0x4d, 0xce, 0x40, 0x3e, 0x43, 0x5f, 0x6d, 0x32, 0xe8, 0x1d, - 0x99, 0xe9, 0xb1, 0x31, 0x1c, 0xa8, 0xdf, 0xcf, 0xfd, 0x28, 0x72, 0x83, 0x18, 0x6f, 0xe4, 0xb2, - 0x09, 0x39, 0xf0, 0x8a, 0x14, 0xb4, 0x11, 0xe5, 0x73, 0x76, 0xc8, 0xfc, 0x13, 0xf4, 0x0a, 0x8e, - 0xb2, 0x87, 0xd0, 0x5d, 0xf1, 0xcd, 0x74, 0x86, 0x1b, 0x4a, 0x73, 0x6a, 0x5a, 0x9d, 0x15, 0xdf, - 0xd0, 0x06, 0xb3, 0xfb, 0xd0, 0x46, 0xa1, 0xdc, 0x28, 0x6f, 0x9b, 0x56, 0x6b, 0xc5, 0x37, 0x57, - 0x9b, 0x44, 0x80, 0x27, 0x58, 0xd7, 0x87, 0x2b, 0xbe, 0x79, 0xc5, 0x23, 0xf3, 0x02, 0x76, 0xb2, - 0x33, 0xf9, 0xbf, 0xcc, 0xa3, 0x95, 0x7a, 0xce, 0xca, 0x4b, 0xd8, 0xbf, 0x33, 0x1f, 0xf6, 0x25, - 0xdc, 0x53, 0xcb, 0x10, 0xf0, 0x50, 0xaa, 0x95, 0xcc, 0x9a, 0x65, 0x24, 0x7c, 0xc3, 0x43, 0x89, - 0xbf, 0xa7, 0x1f, 0x98, 0xff, 0xa8, 0x43, 0x4b, 0x95, 0x80, 0xec, 0x01, 0x56, 0x07, 0xdc, 0xf5, - 0xa6, 0xae, 0x13, 0x67, 0x25, 0xea, 0x4f, 0x9c, 0xcc, 0xb1, 0xaa, 0xe7, 0x8e, 0x15, 0x83, 0x86, - 0x74, 0x57, 0x42, 0xcf, 0x90, 0xda, 0xe8, 0xb2, 0xb7, 0x5e, 0xd1, 0x8a, 0x34, 0xd4, 0x8a, 0x78, - 0xeb, 0x15, 0xae, 0xc8, 0x29, 0xec, 0x66, 0xd2, 0x8b, 0xeb, 0xe8, 0xb2, 0x67, 0x2f, 0xbb, 0x3d, - 0x93, 0x0b, 0x6b, 0x3b, 0x49, 0x34, 0x13, 0x87, 0x1d, 0x01, 0xe5, 0x9d, 0xa9, 0x2a, 0x2d, 0x54, - 0x3e, 0x6a, 0x51, 0x3e, 0xda, 0xc3, 0x71, 0x5d, 0x7b, 0x60, 0x7d, 0xfb, 0x10, 0xba, 0x78, 0xd6, - 0x94, 0x4a, 0x9b, 0x54, 0x3a, 0x38, 0x40, 0xc2, 0x4f, 0xa1, 0x97, 0x96, 0xa7, 0x4a, 0xa5, 0xa3, - 0xac, 0xa4, 0xc3, 0xa4, 0xf8, 0x00, 0x3a, 0x49, 0xde, 0xeb, 0x92, 0x46, 0x9b, 0xeb, 0x74, 0x37, - 0x81, 0xb6, 0x76, 0xb1, 0xb4, 0xbe, 0x7e, 0x02, 0x4d, 0x5c, 0xf5, 0x38, 0x68, 0xe3, 0xaa, 0x87, - 0x56, 0x5b, 0x48, 0x5d, 0x65, 0x2b, 0x15, 0xf3, 0x0c, 0x76, 0x73, 0xe3, 0x48, 0xd0, 0xd2, 0x97, - 0x7c, 0xa9, 0x37, 0x4a, 0x75, 0x92, 0xdf, 0xd4, 0xd3, 0xdf, 0x98, 0xdf, 0x40, 0x37, 0x39, 0xe2, - 0xb8, 0xd4, 0xc1, 0x7a, 0x36, 0x8d, 0x2f, 0x4b, 0x3b, 0x56, 0x2b, 0x58, 0xcf, 0xbe, 0x53, 0xf7, - 0xa5, 0xc0, 0xff, 0x51, 0xd7, 0xfa, 0x86, 0xa5, 0x3a, 0xe6, 0xb7, 0xd0, 0x89, 0x6b, 0xf1, 0x6a, - 0x68, 0xc5, 0x56, 0x9b, 0xff, 0xac, 0x41, 0x4b, 0xa5, 0xc7, 0x92, 0xfb, 0xd9, 0x97, 0x74, 0x71, - 0x59, 0x8b, 0x29, 0x4e, 0x9a, 0x80, 0x7b, 0xc9, 0x9b, 0x80, 0x02, 0x1d, 0x5f, 0xdd, 0x06, 0xc2, - 0xea, 0x92, 0x16, 0x36, 0xd9, 0x27, 0xb0, 0xa3, 0x20, 0x91, 0x0c, 0x5d, 0x2f, 0x26, 0xc7, 0x6d, - 0x1a, 0xbb, 0xa4, 0x21, 0xdc, 0x52, 0xa5, 0xe2, 0x7a, 0x52, 0xa7, 0xc1, 0x0e, 0x0d, 0x4c, 0x3c, - 0x69, 0x3e, 0x84, 0x06, 0xd9, 0x01, 0x68, 0x5d, 0x5e, 0x59, 0x93, 0xd7, 0xaf, 0xfa, 0x5b, 0xac, - 0x0d, 0xc6, 0xe4, 0xf5, 0x55, 0xbf, 0x76, 0xfa, 0x53, 0x13, 0x7a, 0xcf, 0x47, 0xe7, 0x93, 0xe7, - 0x41, 0xb0, 0x74, 0x6d, 0x4e, 0x95, 0xc9, 0x09, 0x34, 0xa8, 0xf6, 0x2a, 0x79, 0x02, 0x19, 0x96, - 0x5d, 0x02, 0xd8, 0x29, 0x34, 0xa9, 0x04, 0x63, 0x65, 0x2f, 0x21, 0xc3, 0xd2, 0xbb, 0x00, 0xfe, - 0x44, 0x15, 0x69, 0x77, 0x1f, 0x44, 0x86, 0x65, 0x17, 0x02, 0xf6, 0x7b, 0xe8, 0xa6, 0xc5, 0x53, - 0xd5, 0xb3, 0xc8, 0xb0, 0xf2, 0x6a, 0x80, 0xf8, 0xb4, 0x80, 0xaa, 0x7a, 0x1c, 0x19, 0x56, 0xde, - 0x0f, 0xd8, 0x33, 0x68, 0xc7, 0xb5, 0x4d, 0xf9, 0x13, 0xc9, 0xb0, 0xe2, 0x8a, 0x80, 0xcb, 0xa3, - 0x2a, 0x8e, 0xb2, 0x97, 0x8f, 0x61, 0x69, 0xd5, 0xcf, 0xbe, 0x86, 0x96, 0x4e, 0xb6, 0xa5, 0xaf, - 0x2b, 0xc3, 0xf2, 0xbb, 0x05, 0x4e, 0x32, 0xbd, 0x24, 0x57, 0x3d, 0x9b, 0x0c, 0x2b, 0x6f, 0x0d, - 0xec, 0x39, 0x40, 0xe6, 0x76, 0x5c, 0xf9, 0x78, 0x32, 0xac, 0xbe, 0x3b, 0x30, 0x3c, 0x3b, 0xc9, - 0xfd, 0xb4, 0xfc, 0x09, 0x65, 0x58, 0x75, 0x7d, 0x98, 0xb5, 0xe8, 0x59, 0xee, 0xab, 0xff, 0x05, - 0x00, 0x00, 0xff, 0xff, 0x2b, 0x22, 0xd6, 0xe4, 0xe1, 0x13, 0x00, 0x00, + // 1744 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x8e, 0x1b, 0xc7, + 0x11, 0x5e, 0xfe, 0x73, 0x8a, 0xfb, 0x43, 0xb5, 0x56, 0x16, 0x45, 0x1d, 0xbc, 0x1e, 0x20, 0x31, + 0x57, 0xb6, 0x96, 0xf6, 0x1a, 0x0a, 0xb4, 0x76, 0x60, 0x64, 0xb9, 0x2b, 0x6b, 0x09, 0x03, 0x8a, + 0x32, 0xbb, 0xf1, 0x21, 0x17, 0xa2, 0xc9, 0xe9, 0x25, 0x07, 0x22, 0x67, 0xc6, 0x33, 0xcd, 0x35, + 0x57, 0xc8, 0x23, 0x18, 0xb9, 0xe6, 0x9c, 0x5c, 0x02, 0xe4, 0x05, 0x72, 0xcc, 0x2d, 0xc8, 0x33, + 0xe4, 0xe0, 0x67, 0x09, 0xaa, 0xba, 0xe7, 0x77, 0x67, 0x0c, 0x43, 0x07, 0x5d, 0xc8, 0xee, 0xae, + 0xfa, 0x7a, 0xaa, 0xab, 0xab, 0xbf, 0xaa, 0x6e, 0xb8, 0x27, 0x6f, 0x7d, 0x11, 0x0e, 0xe9, 0xf7, + 0xc8, 0x0f, 0x3c, 0xe9, 0xb1, 0x06, 0x75, 0xfa, 0x4f, 0xe7, 0x8e, 0x5c, 0xac, 0xa7, 0x47, 0x33, + 0x6f, 0x35, 0x9c, 0x7b, 0x73, 0x6f, 0x48, 0xd2, 0xe9, 0xfa, 0x9a, 0x7a, 0xd4, 0xa1, 0x96, 0x42, + 0x99, 0xff, 0xa9, 0x43, 0xcb, 0x12, 0xdf, 0xaf, 0x45, 0x28, 0xd9, 0x00, 0xea, 0x62, 0xb6, 0xf0, + 0x7a, 0x95, 0x83, 0xca, 0xa0, 0x73, 0xcc, 0x8e, 0xd4, 0xec, 0x5a, 0xfa, 0x62, 0xb6, 0xf0, 0x2e, + 0xb6, 0x2c, 0xd2, 0x60, 0x9f, 0x40, 0xe3, 0x7a, 0xb9, 0x0e, 0x17, 0xbd, 0x2a, 0xa9, 0xde, 0xcf, + 0xaa, 0x7e, 0x83, 0xa2, 0x8b, 0x2d, 0x4b, 0xe9, 0xe0, 0xb4, 0x8e, 0x7b, 0xed, 0xf5, 0x6a, 0x45, + 0xd3, 0x8e, 0xdd, 0x6b, 0x9a, 0x16, 0x35, 0xd8, 0x73, 0x80, 0x50, 0xc8, 0x89, 0xe7, 0x4b, 0xc7, + 0x73, 0x7b, 0x75, 0xd2, 0x7f, 0x98, 0xd5, 0xbf, 0x14, 0xf2, 0xf7, 0x24, 0xbe, 0xd8, 0xb2, 0x8c, + 0x30, 0xea, 0x20, 0xd2, 0x16, 0x4b, 0xe7, 0x46, 0x04, 0x13, 0xb9, 0xe9, 0x35, 0x8a, 0x90, 0xe7, + 0x4a, 0x7e, 0xb5, 0x41, 0xa4, 0x1d, 0x75, 0xd8, 0x31, 0xb4, 0x67, 0x0b, 0x31, 0x7b, 0x83, 0xb8, + 0x26, 0xe1, 0x1e, 0x64, 0x71, 0x67, 0x28, 0x25, 0x54, 0x6b, 0xa6, 0x9a, 0xec, 0x08, 0x9a, 0x33, + 0x6f, 0xb5, 0x72, 0x64, 0xaf, 0x45, 0x88, 0xfd, 0x1c, 0x82, 0x64, 0x17, 0x5b, 0x96, 0xd6, 0x42, + 0x77, 0x7d, 0xbf, 0x16, 0xc1, 0x6d, 0xaf, 0x5d, 0xe4, 0xae, 0x3f, 0xa0, 0x08, 0xdd, 0x45, 0x3a, + 0xb8, 0x14, 0xc7, 0x75, 0xe4, 0x64, 0xb6, 0xe0, 0x8e, 0xdb, 0x33, 0x8a, 0x96, 0x32, 0x76, 0x1d, + 0x79, 0x86, 0x62, 0x5c, 0x8a, 0x13, 0x75, 0xd8, 0x57, 0xd0, 0x99, 0x8a, 0xb9, 0xe3, 0x4e, 0xa6, + 0x4b, 0x6f, 0xf6, 0xa6, 0x07, 0x04, 0xed, 0x65, 0xa1, 0x23, 0x54, 0x18, 0xa1, 0xfc, 0x62, 0xcb, + 0x82, 0x69, 0xdc, 0x63, 0xcf, 0xc0, 0x10, 0xae, 0xad, 0xa1, 0x1d, 0x82, 0x7e, 0x90, 0x8b, 0x00, + 0xd7, 0x8e, 0x80, 0x6d, 0xa1, 0xdb, 0xa3, 0x16, 0x34, 0x6e, 0xf8, 0x72, 0x2d, 0xcc, 0x8f, 0xa1, + 0x93, 0x8a, 0x14, 0xd6, 0x83, 0xd6, 0x4a, 0x84, 0x21, 0x9f, 0x0b, 0x0a, 0x27, 0xc3, 0x8a, 0xba, + 0xe6, 0x2e, 0x6c, 0xa7, 0xe3, 0x24, 0x05, 0xc4, 0x58, 0x40, 0xe0, 0x8d, 0x08, 0x42, 0x0c, 0x00, + 0x0d, 0xd4, 0x5d, 0xf3, 0x4b, 0xe8, 0xe6, 0x83, 0x80, 0x75, 0xa1, 0xf6, 0x46, 0xdc, 0x6a, 0x4d, + 0x6c, 0xb2, 0x7d, 0x6d, 0x10, 0x85, 0xa6, 0x61, 0x69, 0xeb, 0xcc, 0x18, 0x1b, 0x87, 0x01, 0xdb, + 0x85, 0xaa, 0xdc, 0x10, 0x74, 0xdb, 0xaa, 0xca, 0x8d, 0x79, 0x00, 0xbb, 0xd9, 0x2d, 0xbf, 0xa3, + 0x61, 0xc7, 0xa6, 0xd3, 0x9e, 0x31, 0x06, 0x75, 0x9b, 0x4b, 0xae, 0x35, 0xa8, 0x8d, 0x63, 0x3e, + 0x97, 0x0b, 0xfd, 0x79, 0x6a, 0xb3, 0x0f, 0xa0, 0xb9, 0x10, 0xce, 0x7c, 0x21, 0xe9, 0x0c, 0xd4, + 0x2c, 0xdd, 0x43, 0x5b, 0xfd, 0xc0, 0xbb, 0x11, 0x14, 0xea, 0x6d, 0x4b, 0x75, 0xcc, 0x3d, 0xd8, + 0xc9, 0x04, 0x92, 0x79, 0x1e, 0x1b, 0x1f, 0x6f, 0x3c, 0xfb, 0x0c, 0xe0, 0x86, 0x2f, 0x1d, 0x9b, + 0x4b, 0x2f, 0x08, 0x7b, 0x95, 0x83, 0xda, 0xa0, 0x73, 0xdc, 0xd5, 0xfb, 0xf5, 0x5d, 0x24, 0xb0, + 0x52, 0x3a, 0xe6, 0xbf, 0x2b, 0x70, 0xef, 0x4e, 0x10, 0xa0, 0xb9, 0x0b, 0x1e, 0x2e, 0xa2, 0x25, + 0x60, 0x9b, 0xfd, 0x0a, 0xcd, 0xe5, 0xb6, 0x08, 0xf4, 0xf1, 0xde, 0xd1, 0xf3, 0x5e, 0xd0, 0xa0, + 0xa5, 0x85, 0xec, 0x13, 0xb8, 0xc7, 0xa7, 0xa1, 0x70, 0xe5, 0x24, 0x65, 0x49, 0xed, 0xa0, 0x36, + 0x68, 0x58, 0x5d, 0x25, 0x88, 0x0d, 0x09, 0xd9, 0x08, 0xf6, 0xa7, 0xb7, 0x6f, 0xb9, 0x2b, 0x1d, + 0x57, 0xa4, 0xf5, 0xeb, 0x64, 0xf9, 0x9e, 0xfe, 0xc2, 0x8b, 0x1b, 0xc7, 0x16, 0xee, 0x4c, 0x58, + 0xf7, 0x63, 0xe5, 0x64, 0x0e, 0xf3, 0x10, 0xf6, 0x72, 0xa1, 0x98, 0xf2, 0x6c, 0x25, 0xed, 0x59, + 0xf3, 0xc7, 0x06, 0xb4, 0x2d, 0x11, 0xfa, 0x9e, 0x1b, 0x0a, 0xf6, 0x1c, 0x0c, 0xb1, 0x99, 0x09, + 0xc5, 0x2a, 0x95, 0xdc, 0xa9, 0x50, 0x3a, 0x2f, 0x22, 0x39, 0x9e, 0xa8, 0x58, 0x99, 0x1d, 0x6a, + 0x46, 0xcc, 0xd3, 0x9c, 0x06, 0xa5, 0x29, 0xf1, 0xd3, 0x88, 0x12, 0x6b, 0x39, 0x4a, 0x50, 0xba, + 0x39, 0x4e, 0x3c, 0xd4, 0x9c, 0x58, 0x2f, 0x9c, 0x38, 0x43, 0x8a, 0x27, 0x19, 0x52, 0x6c, 0x14, + 0x9a, 0x5f, 0xc2, 0x8a, 0x27, 0x19, 0x56, 0x6c, 0x16, 0x42, 0x4b, 0x68, 0xf1, 0x8b, 0x14, 0x2d, + 0xb6, 0x72, 0x6c, 0xa0, 0x80, 0x05, 0xbc, 0x38, 0x8c, 0x79, 0xb1, 0x9d, 0x63, 0x52, 0x0d, 0xc9, + 0x13, 0xe3, 0xa7, 0x11, 0x31, 0x1a, 0x85, 0x4e, 0xcb, 0x31, 0xe3, 0x49, 0x86, 0x19, 0xa1, 0x70, + 0x39, 0x25, 0xd4, 0xf8, 0xdb, 0x2c, 0x35, 0x2a, 0x7e, 0x7b, 0x94, 0xc3, 0x96, 0x72, 0xe3, 0x6f, + 0xd2, 0xdc, 0xb8, 0x9d, 0x63, 0x64, 0x1d, 0x0b, 0x3f, 0x4b, 0x8e, 0x87, 0x78, 0xf4, 0x72, 0x91, + 0x86, 0xa7, 0x5f, 0x04, 0x81, 0x17, 0x68, 0xf6, 0x52, 0x1d, 0x73, 0x80, 0x1c, 0x93, 0xc4, 0xd7, + 0xcf, 0x10, 0x29, 0xf1, 0x44, 0x2a, 0xba, 0xcc, 0xbf, 0x56, 0x12, 0x2c, 0x71, 0x69, 0x9a, 0x9f, + 0x0c, 0xcd, 0x4f, 0x29, 0x7e, 0xad, 0x66, 0xf8, 0x95, 0x3d, 0x81, 0x7b, 0x4b, 0x1e, 0x4a, 0xb5, + 0xcc, 0x49, 0x86, 0xb0, 0xf6, 0x50, 0xa0, 0xd6, 0xa7, 0x98, 0xeb, 0x29, 0xdc, 0x4f, 0xe9, 0x72, + 0xdf, 0x9f, 0x10, 0x8b, 0xd4, 0x89, 0x45, 0xba, 0xb1, 0xf6, 0xa9, 0xef, 0x5f, 0xf0, 0x70, 0x61, + 0x9e, 0x24, 0xeb, 0x4f, 0xb8, 0x9b, 0x41, 0x7d, 0xe6, 0xd9, 0x6a, 0x59, 0x3b, 0x16, 0xb5, 0x91, + 0xcf, 0x97, 0xde, 0x5c, 0x5b, 0x86, 0x4d, 0xf3, 0xef, 0x95, 0x04, 0x9b, 0x70, 0x77, 0x11, 0xf6, + 0x5c, 0xaf, 0x16, 0xc1, 0xdb, 0xa3, 0xcf, 0xfe, 0xfb, 0xd3, 0x87, 0x5b, 0xff, 0xfb, 0xe9, 0xc3, + 0x41, 0xaa, 0x1e, 0x92, 0xc2, 0xb5, 0x45, 0xb0, 0x72, 0x5c, 0x39, 0x9c, 0x7b, 0x4f, 0x7f, 0x70, + 0x02, 0x31, 0x44, 0xc4, 0xd1, 0xe8, 0x56, 0x8a, 0x50, 0xfb, 0x47, 0x5b, 0x50, 0x8b, 0x2d, 0x60, + 0x1f, 0x41, 0x5d, 0xf2, 0x79, 0x44, 0x55, 0x11, 0x19, 0x7e, 0xfb, 0xdd, 0x6b, 0xee, 0x04, 0x16, + 0x89, 0xcc, 0xbf, 0x55, 0x90, 0x9a, 0x32, 0xe7, 0xe2, 0xbd, 0x9a, 0xd8, 0x85, 0xda, 0x9c, 0x87, + 0xe4, 0xfe, 0x9a, 0x85, 0x4d, 0x1c, 0xb9, 0x16, 0x82, 0xe8, 0xa2, 0x66, 0x61, 0xd3, 0xfc, 0x57, + 0x35, 0x89, 0x97, 0x38, 0x7d, 0xdd, 0xb1, 0x70, 0x1f, 0x1a, 0x8e, 0x6b, 0x8b, 0x0d, 0x99, 0x58, + 0xb3, 0x54, 0x87, 0x8d, 0x54, 0x9a, 0xad, 0xbd, 0xa3, 0xd9, 0x94, 0x98, 0xbf, 0x89, 0x12, 0x73, + 0xfd, 0x1d, 0x67, 0x51, 0x70, 0x9c, 0xc7, 0x0f, 0x3c, 0xef, 0x9a, 0xd6, 0xf6, 0x4e, 0xf3, 0x10, + 0x3c, 0x95, 0x3a, 0x9a, 0x99, 0xa4, 0xac, 0xbd, 0xdb, 0x4a, 0x42, 0xf0, 0xcf, 0x58, 0x18, 0xa4, + 0x19, 0xec, 0x7d, 0xee, 0xad, 0x79, 0x3f, 0x89, 0xff, 0x98, 0xdc, 0xcc, 0x7d, 0x60, 0x77, 0x59, + 0xcb, 0xfc, 0x4b, 0x05, 0x2b, 0x85, 0x2c, 0x21, 0xb1, 0x27, 0xd0, 0x5a, 0xfb, 0x36, 0x97, 0xa2, + 0xbc, 0x4c, 0x88, 0x14, 0xd8, 0x2b, 0x78, 0x38, 0x43, 0xb0, 0x1b, 0xae, 0xc3, 0x89, 0xcf, 0x03, + 0xbe, 0x9a, 0x44, 0xd8, 0x6a, 0x26, 0x09, 0x9c, 0x45, 0x5a, 0xaf, 0x51, 0x29, 0xb4, 0x1e, 0xcc, + 0x32, 0x03, 0x7f, 0x54, 0x20, 0x3a, 0x17, 0x39, 0x55, 0x36, 0x04, 0x50, 0xac, 0x11, 0x3a, 0x6f, + 0x85, 0x4e, 0xc7, 0x91, 0x49, 0x64, 0xf1, 0xa5, 0xf3, 0x56, 0x58, 0xc6, 0x34, 0x6a, 0xb2, 0x5f, + 0x43, 0x4b, 0x6e, 0x94, 0x76, 0xb6, 0x1e, 0xb9, 0xda, 0x90, 0x6a, 0x53, 0xd2, 0x3f, 0x7b, 0x06, + 0xdb, 0x6a, 0xe2, 0xb9, 0x17, 0x86, 0x8e, 0x9f, 0xbb, 0x6f, 0xd0, 0xd4, 0x2f, 0x49, 0x62, 0x75, + 0xa6, 0x49, 0xc7, 0xfc, 0x13, 0x18, 0xf1, 0x67, 0xd9, 0x63, 0x30, 0x56, 0x7c, 0x33, 0x99, 0xde, + 0x2a, 0x77, 0x55, 0x06, 0x0d, 0xab, 0xbd, 0xe2, 0x1b, 0xda, 0x21, 0xf6, 0x10, 0x5a, 0x28, 0x94, + 0x1b, 0xe5, 0x8d, 0x86, 0xd5, 0x5c, 0xf1, 0xcd, 0xd5, 0x26, 0x16, 0xe0, 0x11, 0xd4, 0x05, 0xde, + 0x8a, 0x6f, 0x5e, 0xf2, 0xd0, 0xfc, 0x1a, 0x9a, 0xca, 0xc8, 0x5f, 0x34, 0x31, 0xe2, 0xab, 0x19, + 0xfc, 0xef, 0xa0, 0x93, 0xb2, 0x9b, 0x7d, 0x0e, 0x0f, 0xd4, 0x0a, 0x7d, 0x1e, 0x48, 0xf2, 0x48, + 0x66, 0x42, 0x46, 0xc2, 0xd7, 0x3c, 0x90, 0xf8, 0x49, 0x9a, 0xda, 0xfc, 0x47, 0x15, 0x9a, 0xaa, + 0x6e, 0x63, 0x8f, 0x30, 0xa5, 0x73, 0xc7, 0x9d, 0x38, 0x76, 0x94, 0x4a, 0xa8, 0x3f, 0xb6, 0x53, + 0x67, 0xa1, 0x9a, 0x39, 0x0b, 0x0c, 0xea, 0xd2, 0x59, 0x09, 0xbd, 0x2a, 0x6a, 0xa3, 0xb1, 0xee, + 0x7a, 0x45, 0x5e, 0xa8, 0x2b, 0x2f, 0xb8, 0xeb, 0x15, 0x7a, 0xe1, 0x18, 0x76, 0x52, 0x39, 0xc1, + 0xb1, 0x75, 0xad, 0xb2, 0x9b, 0xde, 0x80, 0xf1, 0xb9, 0xd5, 0x89, 0xb3, 0xc3, 0xd8, 0x66, 0x03, + 0xa0, 0x64, 0x31, 0x51, 0xf5, 0x80, 0x4a, 0x22, 0x4d, 0x4a, 0x22, 0xbb, 0x38, 0xae, 0x0b, 0x06, + 0x2c, 0x4a, 0x1f, 0x83, 0x81, 0x07, 0x44, 0xa9, 0xb4, 0x48, 0xa5, 0x8d, 0x03, 0x24, 0xfc, 0x18, + 0xf6, 0x92, 0x9a, 0x52, 0xa9, 0xb4, 0xd5, 0x2c, 0xc9, 0x30, 0x29, 0x3e, 0x82, 0x76, 0x9c, 0xac, + 0x0c, 0xd2, 0x68, 0x71, 0x9d, 0xa3, 0xc6, 0xd0, 0xd2, 0x26, 0x16, 0x16, 0xc5, 0x4f, 0xa0, 0x81, + 0x5e, 0x8f, 0x0e, 0x42, 0x54, 0xaa, 0x90, 0xb7, 0x85, 0xd4, 0xa5, 0xb1, 0x52, 0x31, 0x4f, 0x60, + 0x27, 0x33, 0x8e, 0xac, 0x2a, 0x3d, 0xc9, 0x97, 0x7a, 0xa3, 0x54, 0x27, 0xfe, 0x4c, 0x35, 0xf9, + 0x8c, 0xf9, 0x25, 0x18, 0xf1, 0xb9, 0x44, 0x57, 0xfb, 0xeb, 0xe9, 0x24, 0xba, 0xe1, 0x6c, 0x5b, + 0x4d, 0x7f, 0x3d, 0xfd, 0x56, 0x5d, 0x72, 0x7c, 0xef, 0x07, 0x5d, 0xa0, 0xd7, 0x2c, 0xd5, 0x31, + 0xbf, 0x82, 0x76, 0x54, 0x40, 0x97, 0x43, 0x4b, 0xb6, 0xda, 0xfc, 0x67, 0x05, 0x9a, 0x2a, 0xa7, + 0x15, 0x5c, 0xaa, 0x3e, 0xa7, 0xdb, 0xc6, 0x5a, 0x4c, 0x70, 0xd1, 0x04, 0xdc, 0x8d, 0x0f, 0x96, + 0x02, 0x1d, 0x5d, 0xdd, 0xfa, 0xc2, 0x32, 0x48, 0x0b, 0x9b, 0xec, 0x23, 0xd8, 0x56, 0x90, 0x50, + 0x06, 0x8e, 0x1b, 0x31, 0x5a, 0x87, 0xc6, 0x2e, 0x69, 0x08, 0xb7, 0x54, 0xa9, 0x38, 0xae, 0xd4, + 0xb9, 0xab, 0x4d, 0x03, 0x63, 0x57, 0x9a, 0x8f, 0xa1, 0x4e, 0xf3, 0x00, 0x34, 0x2f, 0xaf, 0xac, + 0xf1, 0xab, 0x97, 0xdd, 0x2d, 0xd6, 0x82, 0xda, 0xf8, 0xd5, 0x55, 0xb7, 0x72, 0xfc, 0x63, 0x03, + 0xf6, 0x4e, 0x47, 0x67, 0xe3, 0x53, 0xdf, 0x5f, 0x3a, 0x33, 0x4e, 0xe5, 0xc4, 0x10, 0xea, 0x54, + 0x30, 0x15, 0xbc, 0x5b, 0xf4, 0x8b, 0x2a, 0x77, 0x76, 0x0c, 0x0d, 0xaa, 0x9b, 0x58, 0xd1, 0xf3, + 0x45, 0xbf, 0xb0, 0x80, 0xc7, 0x8f, 0xa8, 0xca, 0xea, 0xee, 0x2b, 0x46, 0xbf, 0xa8, 0x8a, 0x67, + 0x5f, 0x83, 0x91, 0x54, 0x3c, 0x65, 0x6f, 0x19, 0xfd, 0xd2, 0x7a, 0x1e, 0xf1, 0x49, 0xd5, 0x53, + 0xf6, 0xa2, 0xd1, 0x2f, 0x2d, 0xea, 0xd9, 0x73, 0x68, 0x45, 0x05, 0x49, 0xf1, 0xbb, 0x46, 0xbf, + 0xa4, 0xae, 0x47, 0xf7, 0xa8, 0x32, 0xa1, 0xe8, 0xb9, 0xa2, 0x5f, 0x58, 0xaa, 0xb3, 0x67, 0xd0, + 0xd4, 0x19, 0xb2, 0xf0, 0x49, 0xa4, 0x5f, 0x7c, 0x21, 0xc0, 0x45, 0x26, 0x37, 0xdb, 0xb2, 0xb7, + 0x8e, 0x7e, 0x69, 0xa9, 0xcf, 0x4e, 0x01, 0x52, 0x57, 0xda, 0xd2, 0x17, 0x8f, 0x7e, 0x79, 0xc1, + 0xcf, 0xf0, 0xec, 0xc4, 0x97, 0xca, 0xe2, 0x77, 0x8f, 0x7e, 0x59, 0xcd, 0x3f, 0x6d, 0xd2, 0x5b, + 0xda, 0x17, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x36, 0x4b, 0x6a, 0x6b, 0x96, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 59424e75..760bb534 100644 --- a/types/types.proto +++ b/types/types.proto @@ -157,33 +157,35 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator changes = 1; - ConsensusParams consensus_param_changes = 2; + repeated Validator updates = 1; + ConsensusParams consensus_param_updates = 2; } +// ConsensusParams contains all consensus-relevant parameters +// that can be adjusted by the abci app message ConsensusParams{ - BlockSizeParams block_size_params = 1; - TxSizeParams tx_size_params = 2; - BlockGossipParams block_gossip_params = 3; + BlockSize block_size = 1; + TxSize tx_size = 2; + BlockGossip block_gossip = 3; } -// BlockSizeParams contain limits on the block size. -message BlockSizeParams{ +// BlockSize contain limits on the block size. +message BlockSize{ // NOTE: must not be 0 nor greater than 100MB int32 max_bytes = 1; int32 max_txs = 2; int64 max_gas = 3; } -// TxSizeParams contain limits on the tx size. -message TxSizeParams { +// TxSize contain limits on the tx size. +message TxSize{ int32 max_bytes = 1; int64 max_gas = 2; } -// BlockGossipParams determine consensus critical +// BlockGossip determine consensus critical // elements of how blocks are gossiped -message BlockGossipParams { +message BlockGossip{ // Note: must not be 0 int32 block_part_size_bytes = 1; } From eb6d412a82c55e26ed7ed56dba1e47ed724ea690 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 14 Dec 2017 09:35:33 +0100 Subject: [PATCH 408/545] Add tests to protobuf objects for pr coverage --- types/types_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 types/types_test.go diff --git a/types/types_test.go b/types/types_test.go new file mode 100644 index 00000000..baa8155c --- /dev/null +++ b/types/types_test.go @@ -0,0 +1,31 @@ +package types + +import ( + "testing" + + asrt "github.com/stretchr/testify/assert" +) + +func TestConsensusParams(t *testing.T) { + assert := asrt.New(t) + + params := &ConsensusParams{ + BlockSize: &BlockSize{MaxGas: 12345}, + BlockGossip: &BlockGossip{BlockPartSizeBytes: 54321}, + } + var noParams *ConsensusParams // nil + + // no error with nil fields + assert.Nil(noParams.GetBlockSize()) + assert.EqualValues(noParams.GetBlockSize().GetMaxGas(), 0) + + // get values with real fields + assert.NotNil(params.GetBlockSize()) + assert.EqualValues(params.GetBlockSize().GetMaxTxs(), 0) + assert.EqualValues(params.GetBlockSize().GetMaxGas(), 12345) + assert.NotNil(params.GetBlockGossip()) + assert.EqualValues(params.GetBlockGossip().GetBlockPartSizeBytes(), 54321) + assert.Nil(params.GetTxSize()) + assert.EqualValues(params.GetTxSize().GetMaxBytes(), 0) + +} From e3d244091d09ebcbc0fc4ed25956ba996603a757 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Sat, 16 Dec 2017 15:49:35 -0700 Subject: [PATCH 409/545] cleanup requested from review by @melekes --- cmd/abci-cli/abci-cli.go | 8 +------- tests/server/client.go | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index cce7addd..7f0f3548 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -387,15 +387,9 @@ func cmdConsole(cmd *cobra.Command, args []string) error { return nil } -var ( - errBadPersistentArgs = errors.New("expecting persistent args of the form: abci-cli [command] <...>") - - errUnimplemented = errors.New("unimplemented") -) - func muxOnCommands(cmd *cobra.Command, pArgs []string) error { if len(pArgs) < 2 { - return errBadPersistentArgs + return errors.New("expecting persistent args of the form: abci-cli [command] <...>") } subCommand, actualArgs := pArgs[1], pArgs[2:] diff --git a/tests/server/client.go b/tests/server/client.go index f1757fe1..4db93e1f 100644 --- a/tests/server/client.go +++ b/tests/server/client.go @@ -21,7 +21,7 @@ func InitChain(client abcicli.Client) error { } _, err := client.InitChainSync(types.RequestInitChain{Validators: vals}) if err != nil { - fmt.Println("Failed test: InitChain - %v", err) + fmt.Printf("Failed test: InitChain - %v\n", err) return err } fmt.Println("Passed test: InitChain") @@ -46,7 +46,7 @@ func Commit(client abcicli.Client, hashExp []byte) error { _, data := res.Code, res.Data if err != nil { fmt.Println("Failed test: Commit") - fmt.Printf("committing %v\nlog: %v", res.GetLog()) + fmt.Printf("committing %v\nlog: %v\n", res.GetLog(), err) return err } if !bytes.Equal(data, hashExp) { From 66296fe11aaa518381c6cd7160bc6318e28c4e02 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 19 Dec 2017 12:13:45 -0600 Subject: [PATCH 410/545] updates -> validator_set_updates ConsensusParamChanges -> ConsensusParamUpdates --- README.md | 4 +- example/dummy/dummy_test.go | 2 +- example/dummy/persistent_dummy.go | 10 +- types/types.pb.go | 227 +++++++++++++++--------------- types/types.proto | 2 +- 5 files changed, 123 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 9686a6a0..d1679221 100644 --- a/README.md +++ b/README.md @@ -185,8 +185,8 @@ Here, we describe the requests and responses as function arguments and return va * __Arguments__: * `Height (int64)`: The block height that ended * __Returns__: - * `Updates ([]Validator)`: Updated validators with new voting powers (0 to remove) - * `ConsensusParamChanges (ConsensusParams)`: Changes to consensus-critical time/size parameters to tendermint core + * `ValidatorSetUpdates ([]Validator)`: Changes to validator set (set voting power to 0 to remove) + * `ConsensusParamUpdates (ConsensusParams)`: Changes to consensus-critical time/size parameters * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 4be4f688..e3cdfc62 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -188,7 +188,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() - valsEqual(t, diff, resEndBlock.Updates) + valsEqual(t, diff, resEndBlock.ValidatorSetUpdates) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index a822deeb..47f8630c 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -28,7 +28,7 @@ type PersistentDummyApplication struct { app *DummyApplication // validator set - updates []*types.Validator + valSetUpdates []*types.Validator logger log.Logger } @@ -71,7 +71,7 @@ func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.ResponseDelive // format is "val:pubkey/power" if isValidatorTx(tx) { // update validators in the merkle tree - // and in app.updates + // and in app.valSetUpdates return app.execValidatorTx(tx) } @@ -119,13 +119,13 @@ func (app *PersistentDummyApplication) InitChain(req types.RequestInitChain) typ // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { // reset valset changes - app.updates = make([]*types.Validator, 0) + app.valSetUpdates = make([]*types.Validator, 0) return types.ResponseBeginBlock{} } // Update the validator set func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - return types.ResponseEndBlock{Updates: app.updates} + return types.ResponseEndBlock{ValidatorSetUpdates: app.valSetUpdates} } //--------------------------------------------- @@ -216,7 +216,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types } // we only update the changes array if we successfully updated the tree - app.updates = append(app.updates, v) + app.valSetUpdates = append(app.valSetUpdates, v) return types.ResponseDeliverTx{Code: code.CodeTypeOK} } diff --git a/types/types.pb.go b/types/types.pb.go index b3ebc1de..202ab71c 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1398,7 +1398,7 @@ func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } type ResponseEndBlock struct { - Updates []*Validator `protobuf:"bytes,1,rep,name=updates" json:"updates,omitempty"` + ValidatorSetUpdates []*Validator `protobuf:"bytes,1,rep,name=validator_set_updates,json=validatorSetUpdates" json:"validator_set_updates,omitempty"` ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"` } @@ -1407,9 +1407,9 @@ func (m *ResponseEndBlock) String() string { return proto.CompactText func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} } -func (m *ResponseEndBlock) GetUpdates() []*Validator { +func (m *ResponseEndBlock) GetValidatorSetUpdates() []*Validator { if m != nil { - return m.Updates + return m.ValidatorSetUpdates } return nil } @@ -2193,114 +2193,115 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1744 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x8e, 0x1b, 0xc7, - 0x11, 0x5e, 0xfe, 0x73, 0x8a, 0xfb, 0x43, 0xb5, 0x56, 0x16, 0x45, 0x1d, 0xbc, 0x1e, 0x20, 0x31, - 0x57, 0xb6, 0x96, 0xf6, 0x1a, 0x0a, 0xb4, 0x76, 0x60, 0x64, 0xb9, 0x2b, 0x6b, 0x09, 0x03, 0x8a, - 0x32, 0xbb, 0xf1, 0x21, 0x17, 0xa2, 0xc9, 0xe9, 0x25, 0x07, 0x22, 0x67, 0xc6, 0x33, 0xcd, 0x35, - 0x57, 0xc8, 0x23, 0x18, 0xb9, 0xe6, 0x9c, 0x5c, 0x02, 0xe4, 0x05, 0x72, 0xcc, 0x2d, 0xc8, 0x33, - 0xe4, 0xe0, 0x67, 0x09, 0xaa, 0xba, 0xe7, 0x77, 0x67, 0x0c, 0x43, 0x07, 0x5d, 0xc8, 0xee, 0xae, - 0xfa, 0x7a, 0xaa, 0xab, 0xab, 0xbf, 0xaa, 0x6e, 0xb8, 0x27, 0x6f, 0x7d, 0x11, 0x0e, 0xe9, 0xf7, - 0xc8, 0x0f, 0x3c, 0xe9, 0xb1, 0x06, 0x75, 0xfa, 0x4f, 0xe7, 0x8e, 0x5c, 0xac, 0xa7, 0x47, 0x33, - 0x6f, 0x35, 0x9c, 0x7b, 0x73, 0x6f, 0x48, 0xd2, 0xe9, 0xfa, 0x9a, 0x7a, 0xd4, 0xa1, 0x96, 0x42, - 0x99, 0xff, 0xa9, 0x43, 0xcb, 0x12, 0xdf, 0xaf, 0x45, 0x28, 0xd9, 0x00, 0xea, 0x62, 0xb6, 0xf0, - 0x7a, 0x95, 0x83, 0xca, 0xa0, 0x73, 0xcc, 0x8e, 0xd4, 0xec, 0x5a, 0xfa, 0x62, 0xb6, 0xf0, 0x2e, - 0xb6, 0x2c, 0xd2, 0x60, 0x9f, 0x40, 0xe3, 0x7a, 0xb9, 0x0e, 0x17, 0xbd, 0x2a, 0xa9, 0xde, 0xcf, - 0xaa, 0x7e, 0x83, 0xa2, 0x8b, 0x2d, 0x4b, 0xe9, 0xe0, 0xb4, 0x8e, 0x7b, 0xed, 0xf5, 0x6a, 0x45, - 0xd3, 0x8e, 0xdd, 0x6b, 0x9a, 0x16, 0x35, 0xd8, 0x73, 0x80, 0x50, 0xc8, 0x89, 0xe7, 0x4b, 0xc7, - 0x73, 0x7b, 0x75, 0xd2, 0x7f, 0x98, 0xd5, 0xbf, 0x14, 0xf2, 0xf7, 0x24, 0xbe, 0xd8, 0xb2, 0x8c, - 0x30, 0xea, 0x20, 0xd2, 0x16, 0x4b, 0xe7, 0x46, 0x04, 0x13, 0xb9, 0xe9, 0x35, 0x8a, 0x90, 0xe7, - 0x4a, 0x7e, 0xb5, 0x41, 0xa4, 0x1d, 0x75, 0xd8, 0x31, 0xb4, 0x67, 0x0b, 0x31, 0x7b, 0x83, 0xb8, - 0x26, 0xe1, 0x1e, 0x64, 0x71, 0x67, 0x28, 0x25, 0x54, 0x6b, 0xa6, 0x9a, 0xec, 0x08, 0x9a, 0x33, - 0x6f, 0xb5, 0x72, 0x64, 0xaf, 0x45, 0x88, 0xfd, 0x1c, 0x82, 0x64, 0x17, 0x5b, 0x96, 0xd6, 0x42, - 0x77, 0x7d, 0xbf, 0x16, 0xc1, 0x6d, 0xaf, 0x5d, 0xe4, 0xae, 0x3f, 0xa0, 0x08, 0xdd, 0x45, 0x3a, - 0xb8, 0x14, 0xc7, 0x75, 0xe4, 0x64, 0xb6, 0xe0, 0x8e, 0xdb, 0x33, 0x8a, 0x96, 0x32, 0x76, 0x1d, - 0x79, 0x86, 0x62, 0x5c, 0x8a, 0x13, 0x75, 0xd8, 0x57, 0xd0, 0x99, 0x8a, 0xb9, 0xe3, 0x4e, 0xa6, - 0x4b, 0x6f, 0xf6, 0xa6, 0x07, 0x04, 0xed, 0x65, 0xa1, 0x23, 0x54, 0x18, 0xa1, 0xfc, 0x62, 0xcb, - 0x82, 0x69, 0xdc, 0x63, 0xcf, 0xc0, 0x10, 0xae, 0xad, 0xa1, 0x1d, 0x82, 0x7e, 0x90, 0x8b, 0x00, - 0xd7, 0x8e, 0x80, 0x6d, 0xa1, 0xdb, 0xa3, 0x16, 0x34, 0x6e, 0xf8, 0x72, 0x2d, 0xcc, 0x8f, 0xa1, - 0x93, 0x8a, 0x14, 0xd6, 0x83, 0xd6, 0x4a, 0x84, 0x21, 0x9f, 0x0b, 0x0a, 0x27, 0xc3, 0x8a, 0xba, - 0xe6, 0x2e, 0x6c, 0xa7, 0xe3, 0x24, 0x05, 0xc4, 0x58, 0x40, 0xe0, 0x8d, 0x08, 0x42, 0x0c, 0x00, - 0x0d, 0xd4, 0x5d, 0xf3, 0x4b, 0xe8, 0xe6, 0x83, 0x80, 0x75, 0xa1, 0xf6, 0x46, 0xdc, 0x6a, 0x4d, - 0x6c, 0xb2, 0x7d, 0x6d, 0x10, 0x85, 0xa6, 0x61, 0x69, 0xeb, 0xcc, 0x18, 0x1b, 0x87, 0x01, 0xdb, - 0x85, 0xaa, 0xdc, 0x10, 0x74, 0xdb, 0xaa, 0xca, 0x8d, 0x79, 0x00, 0xbb, 0xd9, 0x2d, 0xbf, 0xa3, - 0x61, 0xc7, 0xa6, 0xd3, 0x9e, 0x31, 0x06, 0x75, 0x9b, 0x4b, 0xae, 0x35, 0xa8, 0x8d, 0x63, 0x3e, - 0x97, 0x0b, 0xfd, 0x79, 0x6a, 0xb3, 0x0f, 0xa0, 0xb9, 0x10, 0xce, 0x7c, 0x21, 0xe9, 0x0c, 0xd4, - 0x2c, 0xdd, 0x43, 0x5b, 0xfd, 0xc0, 0xbb, 0x11, 0x14, 0xea, 0x6d, 0x4b, 0x75, 0xcc, 0x3d, 0xd8, - 0xc9, 0x04, 0x92, 0x79, 0x1e, 0x1b, 0x1f, 0x6f, 0x3c, 0xfb, 0x0c, 0xe0, 0x86, 0x2f, 0x1d, 0x9b, - 0x4b, 0x2f, 0x08, 0x7b, 0x95, 0x83, 0xda, 0xa0, 0x73, 0xdc, 0xd5, 0xfb, 0xf5, 0x5d, 0x24, 0xb0, - 0x52, 0x3a, 0xe6, 0xbf, 0x2b, 0x70, 0xef, 0x4e, 0x10, 0xa0, 0xb9, 0x0b, 0x1e, 0x2e, 0xa2, 0x25, - 0x60, 0x9b, 0xfd, 0x0a, 0xcd, 0xe5, 0xb6, 0x08, 0xf4, 0xf1, 0xde, 0xd1, 0xf3, 0x5e, 0xd0, 0xa0, - 0xa5, 0x85, 0xec, 0x13, 0xb8, 0xc7, 0xa7, 0xa1, 0x70, 0xe5, 0x24, 0x65, 0x49, 0xed, 0xa0, 0x36, - 0x68, 0x58, 0x5d, 0x25, 0x88, 0x0d, 0x09, 0xd9, 0x08, 0xf6, 0xa7, 0xb7, 0x6f, 0xb9, 0x2b, 0x1d, - 0x57, 0xa4, 0xf5, 0xeb, 0x64, 0xf9, 0x9e, 0xfe, 0xc2, 0x8b, 0x1b, 0xc7, 0x16, 0xee, 0x4c, 0x58, - 0xf7, 0x63, 0xe5, 0x64, 0x0e, 0xf3, 0x10, 0xf6, 0x72, 0xa1, 0x98, 0xf2, 0x6c, 0x25, 0xed, 0x59, - 0xf3, 0xc7, 0x06, 0xb4, 0x2d, 0x11, 0xfa, 0x9e, 0x1b, 0x0a, 0xf6, 0x1c, 0x0c, 0xb1, 0x99, 0x09, - 0xc5, 0x2a, 0x95, 0xdc, 0xa9, 0x50, 0x3a, 0x2f, 0x22, 0x39, 0x9e, 0xa8, 0x58, 0x99, 0x1d, 0x6a, - 0x46, 0xcc, 0xd3, 0x9c, 0x06, 0xa5, 0x29, 0xf1, 0xd3, 0x88, 0x12, 0x6b, 0x39, 0x4a, 0x50, 0xba, - 0x39, 0x4e, 0x3c, 0xd4, 0x9c, 0x58, 0x2f, 0x9c, 0x38, 0x43, 0x8a, 0x27, 0x19, 0x52, 0x6c, 0x14, - 0x9a, 0x5f, 0xc2, 0x8a, 0x27, 0x19, 0x56, 0x6c, 0x16, 0x42, 0x4b, 0x68, 0xf1, 0x8b, 0x14, 0x2d, - 0xb6, 0x72, 0x6c, 0xa0, 0x80, 0x05, 0xbc, 0x38, 0x8c, 0x79, 0xb1, 0x9d, 0x63, 0x52, 0x0d, 0xc9, - 0x13, 0xe3, 0xa7, 0x11, 0x31, 0x1a, 0x85, 0x4e, 0xcb, 0x31, 0xe3, 0x49, 0x86, 0x19, 0xa1, 0x70, - 0x39, 0x25, 0xd4, 0xf8, 0xdb, 0x2c, 0x35, 0x2a, 0x7e, 0x7b, 0x94, 0xc3, 0x96, 0x72, 0xe3, 0x6f, - 0xd2, 0xdc, 0xb8, 0x9d, 0x63, 0x64, 0x1d, 0x0b, 0x3f, 0x4b, 0x8e, 0x87, 0x78, 0xf4, 0x72, 0x91, - 0x86, 0xa7, 0x5f, 0x04, 0x81, 0x17, 0x68, 0xf6, 0x52, 0x1d, 0x73, 0x80, 0x1c, 0x93, 0xc4, 0xd7, - 0xcf, 0x10, 0x29, 0xf1, 0x44, 0x2a, 0xba, 0xcc, 0xbf, 0x56, 0x12, 0x2c, 0x71, 0x69, 0x9a, 0x9f, - 0x0c, 0xcd, 0x4f, 0x29, 0x7e, 0xad, 0x66, 0xf8, 0x95, 0x3d, 0x81, 0x7b, 0x4b, 0x1e, 0x4a, 0xb5, - 0xcc, 0x49, 0x86, 0xb0, 0xf6, 0x50, 0xa0, 0xd6, 0xa7, 0x98, 0xeb, 0x29, 0xdc, 0x4f, 0xe9, 0x72, - 0xdf, 0x9f, 0x10, 0x8b, 0xd4, 0x89, 0x45, 0xba, 0xb1, 0xf6, 0xa9, 0xef, 0x5f, 0xf0, 0x70, 0x61, - 0x9e, 0x24, 0xeb, 0x4f, 0xb8, 0x9b, 0x41, 0x7d, 0xe6, 0xd9, 0x6a, 0x59, 0x3b, 0x16, 0xb5, 0x91, - 0xcf, 0x97, 0xde, 0x5c, 0x5b, 0x86, 0x4d, 0xf3, 0xef, 0x95, 0x04, 0x9b, 0x70, 0x77, 0x11, 0xf6, - 0x5c, 0xaf, 0x16, 0xc1, 0xdb, 0xa3, 0xcf, 0xfe, 0xfb, 0xd3, 0x87, 0x5b, 0xff, 0xfb, 0xe9, 0xc3, - 0x41, 0xaa, 0x1e, 0x92, 0xc2, 0xb5, 0x45, 0xb0, 0x72, 0x5c, 0x39, 0x9c, 0x7b, 0x4f, 0x7f, 0x70, - 0x02, 0x31, 0x44, 0xc4, 0xd1, 0xe8, 0x56, 0x8a, 0x50, 0xfb, 0x47, 0x5b, 0x50, 0x8b, 0x2d, 0x60, - 0x1f, 0x41, 0x5d, 0xf2, 0x79, 0x44, 0x55, 0x11, 0x19, 0x7e, 0xfb, 0xdd, 0x6b, 0xee, 0x04, 0x16, - 0x89, 0xcc, 0xbf, 0x55, 0x90, 0x9a, 0x32, 0xe7, 0xe2, 0xbd, 0x9a, 0xd8, 0x85, 0xda, 0x9c, 0x87, - 0xe4, 0xfe, 0x9a, 0x85, 0x4d, 0x1c, 0xb9, 0x16, 0x82, 0xe8, 0xa2, 0x66, 0x61, 0xd3, 0xfc, 0x57, - 0x35, 0x89, 0x97, 0x38, 0x7d, 0xdd, 0xb1, 0x70, 0x1f, 0x1a, 0x8e, 0x6b, 0x8b, 0x0d, 0x99, 0x58, - 0xb3, 0x54, 0x87, 0x8d, 0x54, 0x9a, 0xad, 0xbd, 0xa3, 0xd9, 0x94, 0x98, 0xbf, 0x89, 0x12, 0x73, - 0xfd, 0x1d, 0x67, 0x51, 0x70, 0x9c, 0xc7, 0x0f, 0x3c, 0xef, 0x9a, 0xd6, 0xf6, 0x4e, 0xf3, 0x10, - 0x3c, 0x95, 0x3a, 0x9a, 0x99, 0xa4, 0xac, 0xbd, 0xdb, 0x4a, 0x42, 0xf0, 0xcf, 0x58, 0x18, 0xa4, - 0x19, 0xec, 0x7d, 0xee, 0xad, 0x79, 0x3f, 0x89, 0xff, 0x98, 0xdc, 0xcc, 0x7d, 0x60, 0x77, 0x59, - 0xcb, 0xfc, 0x4b, 0x05, 0x2b, 0x85, 0x2c, 0x21, 0xb1, 0x27, 0xd0, 0x5a, 0xfb, 0x36, 0x97, 0xa2, - 0xbc, 0x4c, 0x88, 0x14, 0xd8, 0x2b, 0x78, 0x38, 0x43, 0xb0, 0x1b, 0xae, 0xc3, 0x89, 0xcf, 0x03, - 0xbe, 0x9a, 0x44, 0xd8, 0x6a, 0x26, 0x09, 0x9c, 0x45, 0x5a, 0xaf, 0x51, 0x29, 0xb4, 0x1e, 0xcc, - 0x32, 0x03, 0x7f, 0x54, 0x20, 0x3a, 0x17, 0x39, 0x55, 0x36, 0x04, 0x50, 0xac, 0x11, 0x3a, 0x6f, - 0x85, 0x4e, 0xc7, 0x91, 0x49, 0x64, 0xf1, 0xa5, 0xf3, 0x56, 0x58, 0xc6, 0x34, 0x6a, 0xb2, 0x5f, - 0x43, 0x4b, 0x6e, 0x94, 0x76, 0xb6, 0x1e, 0xb9, 0xda, 0x90, 0x6a, 0x53, 0xd2, 0x3f, 0x7b, 0x06, - 0xdb, 0x6a, 0xe2, 0xb9, 0x17, 0x86, 0x8e, 0x9f, 0xbb, 0x6f, 0xd0, 0xd4, 0x2f, 0x49, 0x62, 0x75, - 0xa6, 0x49, 0xc7, 0xfc, 0x13, 0x18, 0xf1, 0x67, 0xd9, 0x63, 0x30, 0x56, 0x7c, 0x33, 0x99, 0xde, - 0x2a, 0x77, 0x55, 0x06, 0x0d, 0xab, 0xbd, 0xe2, 0x1b, 0xda, 0x21, 0xf6, 0x10, 0x5a, 0x28, 0x94, - 0x1b, 0xe5, 0x8d, 0x86, 0xd5, 0x5c, 0xf1, 0xcd, 0xd5, 0x26, 0x16, 0xe0, 0x11, 0xd4, 0x05, 0xde, - 0x8a, 0x6f, 0x5e, 0xf2, 0xd0, 0xfc, 0x1a, 0x9a, 0xca, 0xc8, 0x5f, 0x34, 0x31, 0xe2, 0xab, 0x19, - 0xfc, 0xef, 0xa0, 0x93, 0xb2, 0x9b, 0x7d, 0x0e, 0x0f, 0xd4, 0x0a, 0x7d, 0x1e, 0x48, 0xf2, 0x48, - 0x66, 0x42, 0x46, 0xc2, 0xd7, 0x3c, 0x90, 0xf8, 0x49, 0x9a, 0xda, 0xfc, 0x47, 0x15, 0x9a, 0xaa, - 0x6e, 0x63, 0x8f, 0x30, 0xa5, 0x73, 0xc7, 0x9d, 0x38, 0x76, 0x94, 0x4a, 0xa8, 0x3f, 0xb6, 0x53, - 0x67, 0xa1, 0x9a, 0x39, 0x0b, 0x0c, 0xea, 0xd2, 0x59, 0x09, 0xbd, 0x2a, 0x6a, 0xa3, 0xb1, 0xee, - 0x7a, 0x45, 0x5e, 0xa8, 0x2b, 0x2f, 0xb8, 0xeb, 0x15, 0x7a, 0xe1, 0x18, 0x76, 0x52, 0x39, 0xc1, - 0xb1, 0x75, 0xad, 0xb2, 0x9b, 0xde, 0x80, 0xf1, 0xb9, 0xd5, 0x89, 0xb3, 0xc3, 0xd8, 0x66, 0x03, - 0xa0, 0x64, 0x31, 0x51, 0xf5, 0x80, 0x4a, 0x22, 0x4d, 0x4a, 0x22, 0xbb, 0x38, 0xae, 0x0b, 0x06, - 0x2c, 0x4a, 0x1f, 0x83, 0x81, 0x07, 0x44, 0xa9, 0xb4, 0x48, 0xa5, 0x8d, 0x03, 0x24, 0xfc, 0x18, - 0xf6, 0x92, 0x9a, 0x52, 0xa9, 0xb4, 0xd5, 0x2c, 0xc9, 0x30, 0x29, 0x3e, 0x82, 0x76, 0x9c, 0xac, - 0x0c, 0xd2, 0x68, 0x71, 0x9d, 0xa3, 0xc6, 0xd0, 0xd2, 0x26, 0x16, 0x16, 0xc5, 0x4f, 0xa0, 0x81, - 0x5e, 0x8f, 0x0e, 0x42, 0x54, 0xaa, 0x90, 0xb7, 0x85, 0xd4, 0xa5, 0xb1, 0x52, 0x31, 0x4f, 0x60, - 0x27, 0x33, 0x8e, 0xac, 0x2a, 0x3d, 0xc9, 0x97, 0x7a, 0xa3, 0x54, 0x27, 0xfe, 0x4c, 0x35, 0xf9, - 0x8c, 0xf9, 0x25, 0x18, 0xf1, 0xb9, 0x44, 0x57, 0xfb, 0xeb, 0xe9, 0x24, 0xba, 0xe1, 0x6c, 0x5b, - 0x4d, 0x7f, 0x3d, 0xfd, 0x56, 0x5d, 0x72, 0x7c, 0xef, 0x07, 0x5d, 0xa0, 0xd7, 0x2c, 0xd5, 0x31, - 0xbf, 0x82, 0x76, 0x54, 0x40, 0x97, 0x43, 0x4b, 0xb6, 0xda, 0xfc, 0x67, 0x05, 0x9a, 0x2a, 0xa7, - 0x15, 0x5c, 0xaa, 0x3e, 0xa7, 0xdb, 0xc6, 0x5a, 0x4c, 0x70, 0xd1, 0x04, 0xdc, 0x8d, 0x0f, 0x96, - 0x02, 0x1d, 0x5d, 0xdd, 0xfa, 0xc2, 0x32, 0x48, 0x0b, 0x9b, 0xec, 0x23, 0xd8, 0x56, 0x90, 0x50, - 0x06, 0x8e, 0x1b, 0x31, 0x5a, 0x87, 0xc6, 0x2e, 0x69, 0x08, 0xb7, 0x54, 0xa9, 0x38, 0xae, 0xd4, - 0xb9, 0xab, 0x4d, 0x03, 0x63, 0x57, 0x9a, 0x8f, 0xa1, 0x4e, 0xf3, 0x00, 0x34, 0x2f, 0xaf, 0xac, - 0xf1, 0xab, 0x97, 0xdd, 0x2d, 0xd6, 0x82, 0xda, 0xf8, 0xd5, 0x55, 0xb7, 0x72, 0xfc, 0x63, 0x03, - 0xf6, 0x4e, 0x47, 0x67, 0xe3, 0x53, 0xdf, 0x5f, 0x3a, 0x33, 0x4e, 0xe5, 0xc4, 0x10, 0xea, 0x54, - 0x30, 0x15, 0xbc, 0x5b, 0xf4, 0x8b, 0x2a, 0x77, 0x76, 0x0c, 0x0d, 0xaa, 0x9b, 0x58, 0xd1, 0xf3, - 0x45, 0xbf, 0xb0, 0x80, 0xc7, 0x8f, 0xa8, 0xca, 0xea, 0xee, 0x2b, 0x46, 0xbf, 0xa8, 0x8a, 0x67, - 0x5f, 0x83, 0x91, 0x54, 0x3c, 0x65, 0x6f, 0x19, 0xfd, 0xd2, 0x7a, 0x1e, 0xf1, 0x49, 0xd5, 0x53, - 0xf6, 0xa2, 0xd1, 0x2f, 0x2d, 0xea, 0xd9, 0x73, 0x68, 0x45, 0x05, 0x49, 0xf1, 0xbb, 0x46, 0xbf, - 0xa4, 0xae, 0x47, 0xf7, 0xa8, 0x32, 0xa1, 0xe8, 0xb9, 0xa2, 0x5f, 0x58, 0xaa, 0xb3, 0x67, 0xd0, - 0xd4, 0x19, 0xb2, 0xf0, 0x49, 0xa4, 0x5f, 0x7c, 0x21, 0xc0, 0x45, 0x26, 0x37, 0xdb, 0xb2, 0xb7, - 0x8e, 0x7e, 0x69, 0xa9, 0xcf, 0x4e, 0x01, 0x52, 0x57, 0xda, 0xd2, 0x17, 0x8f, 0x7e, 0x79, 0xc1, - 0xcf, 0xf0, 0xec, 0xc4, 0x97, 0xca, 0xe2, 0x77, 0x8f, 0x7e, 0x59, 0xcd, 0x3f, 0x6d, 0xd2, 0x5b, - 0xda, 0x17, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x36, 0x4b, 0x6a, 0x6b, 0x96, 0x13, 0x00, 0x00, + // 1754 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6e, 0x23, 0xc7, + 0x11, 0x16, 0xff, 0x39, 0x45, 0xfd, 0x70, 0x5b, 0x5a, 0x2f, 0x97, 0x7b, 0xb0, 0x3c, 0x40, 0x62, + 0xca, 0xf6, 0x8a, 0xb6, 0x8c, 0x0d, 0x56, 0x76, 0x60, 0x44, 0x94, 0xd6, 0x2b, 0xc2, 0xc0, 0x66, + 0x33, 0x52, 0x7c, 0xc8, 0x85, 0x68, 0x72, 0x5a, 0xe4, 0x60, 0xc9, 0x99, 0xf1, 0x4c, 0x53, 0xa6, + 0x16, 0x79, 0x04, 0xdf, 0x73, 0x4e, 0x2e, 0x09, 0xf2, 0x02, 0x39, 0xe6, 0x16, 0xe4, 0x19, 0x72, + 0xf0, 0xb3, 0x04, 0x55, 0xdd, 0xf3, 0xab, 0x19, 0xc3, 0xd8, 0x83, 0x2f, 0x52, 0x77, 0x57, 0x7d, + 0xc5, 0xea, 0x9a, 0xea, 0xaf, 0xaa, 0x1b, 0x1e, 0xc8, 0x3b, 0x5f, 0x84, 0x43, 0xfa, 0x7b, 0xec, + 0x07, 0x9e, 0xf4, 0x58, 0x83, 0x26, 0xfd, 0xa7, 0x73, 0x47, 0x2e, 0xd6, 0xd3, 0xe3, 0x99, 0xb7, + 0x1a, 0xce, 0xbd, 0xb9, 0x37, 0x24, 0xe9, 0x74, 0x7d, 0x43, 0x33, 0x9a, 0xd0, 0x48, 0xa1, 0xcc, + 0xff, 0xd4, 0xa1, 0x65, 0x89, 0xef, 0xd6, 0x22, 0x94, 0x6c, 0x00, 0x75, 0x31, 0x5b, 0x78, 0xbd, + 0xca, 0x61, 0x65, 0xd0, 0x39, 0x61, 0xc7, 0xca, 0xba, 0x96, 0xbe, 0x98, 0x2d, 0xbc, 0xcb, 0x2d, + 0x8b, 0x34, 0xd8, 0xc7, 0xd0, 0xb8, 0x59, 0xae, 0xc3, 0x45, 0xaf, 0x4a, 0xaa, 0xfb, 0x59, 0xd5, + 0xaf, 0x51, 0x74, 0xb9, 0x65, 0x29, 0x1d, 0x34, 0xeb, 0xb8, 0x37, 0x5e, 0xaf, 0x56, 0x64, 0x76, + 0xec, 0xde, 0x90, 0x59, 0xd4, 0x60, 0xcf, 0x01, 0x42, 0x21, 0x27, 0x9e, 0x2f, 0x1d, 0xcf, 0xed, + 0xd5, 0x49, 0xff, 0x51, 0x56, 0xff, 0x4a, 0xc8, 0xdf, 0x93, 0xf8, 0x72, 0xcb, 0x32, 0xc2, 0x68, + 0x82, 0x48, 0x5b, 0x2c, 0x9d, 0x5b, 0x11, 0x4c, 0xe4, 0xa6, 0xd7, 0x28, 0x42, 0x5e, 0x28, 0xf9, + 0xf5, 0x06, 0x91, 0x76, 0x34, 0x61, 0x27, 0xd0, 0x9e, 0x2d, 0xc4, 0xec, 0x0d, 0xe2, 0x9a, 0x84, + 0x7b, 0x98, 0xc5, 0x9d, 0xa3, 0x94, 0x50, 0xad, 0x99, 0x1a, 0xb2, 0x63, 0x68, 0xce, 0xbc, 0xd5, + 0xca, 0x91, 0xbd, 0x16, 0x21, 0x0e, 0x72, 0x08, 0x92, 0x5d, 0x6e, 0x59, 0x5a, 0x0b, 0xc3, 0xf5, + 0xdd, 0x5a, 0x04, 0x77, 0xbd, 0x76, 0x51, 0xb8, 0xfe, 0x80, 0x22, 0x0c, 0x17, 0xe9, 0xe0, 0x56, + 0x1c, 0xd7, 0x91, 0x93, 0xd9, 0x82, 0x3b, 0x6e, 0xcf, 0x28, 0xda, 0xca, 0xd8, 0x75, 0xe4, 0x39, + 0x8a, 0x71, 0x2b, 0x4e, 0x34, 0x61, 0x5f, 0x42, 0x67, 0x2a, 0xe6, 0x8e, 0x3b, 0x99, 0x2e, 0xbd, + 0xd9, 0x9b, 0x1e, 0x10, 0xb4, 0x97, 0x85, 0x8e, 0x50, 0x61, 0x84, 0xf2, 0xcb, 0x2d, 0x0b, 0xa6, + 0xf1, 0x8c, 0x3d, 0x03, 0x43, 0xb8, 0xb6, 0x86, 0x76, 0x08, 0xfa, 0x5e, 0x2e, 0x03, 0x5c, 0x3b, + 0x02, 0xb6, 0x85, 0x1e, 0x8f, 0x5a, 0xd0, 0xb8, 0xe5, 0xcb, 0xb5, 0x30, 0x3f, 0x84, 0x4e, 0x2a, + 0x53, 0x58, 0x0f, 0x5a, 0x2b, 0x11, 0x86, 0x7c, 0x2e, 0x28, 0x9d, 0x0c, 0x2b, 0x9a, 0x9a, 0xbb, + 0xb0, 0x9d, 0xce, 0x93, 0x14, 0x10, 0x73, 0x01, 0x81, 0xb7, 0x22, 0x08, 0x31, 0x01, 0x34, 0x50, + 0x4f, 0xcd, 0x2f, 0xa0, 0x9b, 0x4f, 0x02, 0xd6, 0x85, 0xda, 0x1b, 0x71, 0xa7, 0x35, 0x71, 0xc8, + 0x0e, 0xb4, 0x43, 0x94, 0x9a, 0x86, 0xa5, 0xbd, 0x33, 0x63, 0x6c, 0x9c, 0x06, 0x6c, 0x17, 0xaa, + 0x72, 0x43, 0xd0, 0x6d, 0xab, 0x2a, 0x37, 0xe6, 0x21, 0xec, 0x66, 0x3f, 0xf9, 0x3d, 0x0d, 0x3b, + 0x76, 0x9d, 0xbe, 0x19, 0x63, 0x50, 0xb7, 0xb9, 0xe4, 0x5a, 0x83, 0xc6, 0xb8, 0xe6, 0x73, 0xb9, + 0xd0, 0x3f, 0x4f, 0x63, 0xf6, 0x1e, 0x34, 0x17, 0xc2, 0x99, 0x2f, 0x24, 0x9d, 0x81, 0x9a, 0xa5, + 0x67, 0xe8, 0xab, 0x1f, 0x78, 0xb7, 0x82, 0x52, 0xbd, 0x6d, 0xa9, 0x89, 0xb9, 0x07, 0x3b, 0x99, + 0x44, 0x32, 0x2f, 0x62, 0xe7, 0xe3, 0x0f, 0xcf, 0x3e, 0x05, 0xb8, 0xe5, 0x4b, 0xc7, 0xe6, 0xd2, + 0x0b, 0xc2, 0x5e, 0xe5, 0xb0, 0x36, 0xe8, 0x9c, 0x74, 0xf5, 0xf7, 0xfa, 0x36, 0x12, 0x58, 0x29, + 0x1d, 0xf3, 0xdf, 0x15, 0x78, 0x70, 0x2f, 0x09, 0xd0, 0xdd, 0x05, 0x0f, 0x17, 0xd1, 0x16, 0x70, + 0xcc, 0x7e, 0x85, 0xee, 0x72, 0x5b, 0x04, 0xfa, 0x78, 0xef, 0x68, 0xbb, 0x97, 0xb4, 0x68, 0x69, + 0x21, 0xfb, 0x18, 0x1e, 0xf0, 0x69, 0x28, 0x5c, 0x39, 0x49, 0x79, 0x52, 0x3b, 0xac, 0x0d, 0x1a, + 0x56, 0x57, 0x09, 0x62, 0x47, 0x42, 0x36, 0x82, 0x83, 0xe9, 0xdd, 0x5b, 0xee, 0x4a, 0xc7, 0x15, + 0x69, 0xfd, 0x3a, 0x79, 0xbe, 0xa7, 0x7f, 0xe1, 0xc5, 0xad, 0x63, 0x0b, 0x77, 0x26, 0xac, 0xfd, + 0x58, 0x39, 0xb1, 0x61, 0x1e, 0xc1, 0x5e, 0x2e, 0x15, 0x53, 0x91, 0xad, 0xa4, 0x23, 0x6b, 0xfe, + 0xd0, 0x80, 0xb6, 0x25, 0x42, 0xdf, 0x73, 0x43, 0xc1, 0x9e, 0x83, 0x21, 0x36, 0x33, 0xa1, 0x58, + 0xa5, 0x92, 0x3b, 0x15, 0x4a, 0xe7, 0x45, 0x24, 0xc7, 0x13, 0x15, 0x2b, 0xb3, 0x23, 0xcd, 0x88, + 0x79, 0x9a, 0xd3, 0xa0, 0x34, 0x25, 0x7e, 0x12, 0x51, 0x62, 0x2d, 0x47, 0x09, 0x4a, 0x37, 0xc7, + 0x89, 0x47, 0x9a, 0x13, 0xeb, 0x85, 0x86, 0x33, 0xa4, 0x78, 0x9a, 0x21, 0xc5, 0x46, 0xa1, 0xfb, + 0x25, 0xac, 0x78, 0x9a, 0x61, 0xc5, 0x66, 0x21, 0xb4, 0x84, 0x16, 0x3f, 0x4f, 0xd1, 0x62, 0x2b, + 0xc7, 0x06, 0x0a, 0x58, 0xc0, 0x8b, 0xc3, 0x98, 0x17, 0xdb, 0x39, 0x26, 0xd5, 0x90, 0x3c, 0x31, + 0x7e, 0x12, 0x11, 0xa3, 0x51, 0x18, 0xb4, 0x1c, 0x33, 0x9e, 0x66, 0x98, 0x11, 0x0a, 0xb7, 0x53, + 0x42, 0x8d, 0xbf, 0xcd, 0x52, 0xa3, 0xe2, 0xb7, 0xc7, 0x39, 0x6c, 0x29, 0x37, 0xfe, 0x26, 0xcd, + 0x8d, 0xdb, 0x39, 0x46, 0xd6, 0xb9, 0xf0, 0x93, 0xe4, 0x78, 0x84, 0x47, 0x2f, 0x97, 0x69, 0x78, + 0xfa, 0x45, 0x10, 0x78, 0x81, 0x66, 0x2f, 0x35, 0x31, 0x07, 0xc8, 0x31, 0x49, 0x7e, 0xfd, 0x04, + 0x91, 0x12, 0x4f, 0xa4, 0xb2, 0xcb, 0xfc, 0x4b, 0x25, 0xc1, 0x12, 0x97, 0xa6, 0xf9, 0xc9, 0xd0, + 0xfc, 0x94, 0xe2, 0xd7, 0x6a, 0x86, 0x5f, 0xd9, 0x47, 0xf0, 0x60, 0xc9, 0x43, 0xa9, 0xb6, 0x39, + 0xc9, 0x10, 0xd6, 0x1e, 0x0a, 0xd4, 0xfe, 0x14, 0x73, 0x3d, 0x85, 0xfd, 0x94, 0x2e, 0xf7, 0xfd, + 0x09, 0xb1, 0x48, 0x9d, 0x58, 0xa4, 0x1b, 0x6b, 0x9f, 0xf9, 0xfe, 0x25, 0x0f, 0x17, 0xe6, 0x69, + 0xb2, 0xff, 0x84, 0xbb, 0x19, 0xd4, 0x67, 0x9e, 0xad, 0xb6, 0xb5, 0x63, 0xd1, 0x18, 0xf9, 0x7c, + 0xe9, 0xcd, 0xb5, 0x67, 0x38, 0x34, 0xff, 0x56, 0x49, 0xb0, 0x09, 0x77, 0x17, 0x61, 0x2f, 0xf4, + 0x6e, 0x11, 0xbc, 0x3d, 0xfa, 0xf4, 0xbf, 0x3f, 0xbe, 0xbf, 0xf5, 0xbf, 0x1f, 0xdf, 0x1f, 0xa4, + 0xfa, 0x21, 0x29, 0x5c, 0x5b, 0x04, 0x2b, 0xc7, 0x95, 0xc3, 0xb9, 0xf7, 0xf4, 0x7b, 0x27, 0x10, + 0x43, 0x44, 0x1c, 0x8f, 0xee, 0xa4, 0x08, 0x75, 0x7c, 0xb4, 0x07, 0xb5, 0xd8, 0x03, 0xf6, 0x01, + 0xd4, 0x25, 0x9f, 0x47, 0x54, 0x15, 0x91, 0xe1, 0x37, 0xdf, 0xbe, 0xe6, 0x4e, 0x60, 0x91, 0xc8, + 0xfc, 0x6b, 0x05, 0xa9, 0x29, 0x73, 0x2e, 0x7e, 0x51, 0x17, 0xbb, 0x50, 0x9b, 0xf3, 0x90, 0xc2, + 0x5f, 0xb3, 0x70, 0x88, 0x2b, 0x37, 0x42, 0x10, 0x5d, 0xd4, 0x2c, 0x1c, 0x9a, 0xff, 0xaa, 0x26, + 0xf9, 0x12, 0x97, 0xaf, 0x7b, 0x1e, 0x1e, 0x40, 0xc3, 0x71, 0x6d, 0xb1, 0x21, 0x17, 0x6b, 0x96, + 0x9a, 0xb0, 0x91, 0x2a, 0xb3, 0xb5, 0x77, 0x74, 0x9b, 0x0a, 0xf3, 0xd7, 0x51, 0x61, 0xae, 0xbf, + 0xa3, 0x15, 0x05, 0x47, 0x3b, 0x7e, 0xe0, 0x79, 0x37, 0xb4, 0xb7, 0x77, 0xb2, 0x43, 0xf0, 0x54, + 0xe9, 0x68, 0x66, 0x8a, 0xb2, 0x8e, 0x6e, 0x2b, 0x49, 0xc1, 0x3f, 0x63, 0x63, 0x90, 0x66, 0xb0, + 0x5f, 0xf2, 0xdb, 0x9a, 0xfb, 0x49, 0xfe, 0xc7, 0xe4, 0x66, 0x1e, 0x00, 0xbb, 0xcf, 0x5a, 0xe6, + 0x3f, 0x2a, 0xd8, 0x29, 0x64, 0x09, 0x89, 0x5d, 0xc0, 0xc3, 0xb8, 0xde, 0x4e, 0xb0, 0x92, 0xac, + 0x7d, 0x9b, 0x4b, 0x51, 0xde, 0x34, 0xec, 0xc7, 0xea, 0x57, 0x42, 0xfe, 0x51, 0x29, 0xb3, 0x57, + 0xf0, 0x68, 0x86, 0x66, 0xdd, 0x70, 0x1d, 0x4e, 0x7c, 0x1e, 0xf0, 0x55, 0x6c, 0xa7, 0x9a, 0x29, + 0x0f, 0xe7, 0x91, 0xd6, 0x6b, 0x54, 0x0a, 0xad, 0x87, 0xb3, 0xcc, 0x82, 0xb6, 0x47, 0x27, 0x26, + 0xa7, 0xca, 0x86, 0x00, 0x8a, 0x4f, 0x42, 0xe7, 0xad, 0xd0, 0x85, 0x3a, 0x72, 0x8f, 0xf6, 0x72, + 0xe5, 0xbc, 0x15, 0x96, 0x31, 0x8d, 0x86, 0xec, 0xd7, 0xd0, 0x92, 0x1b, 0xa5, 0x9d, 0xed, 0x54, + 0xae, 0x37, 0xa4, 0xda, 0x94, 0xf4, 0x9f, 0x3d, 0x83, 0x6d, 0x65, 0x78, 0xee, 0x85, 0xa1, 0xe3, + 0xe7, 0x6e, 0x22, 0x64, 0xfa, 0x25, 0x49, 0xac, 0xce, 0x34, 0x99, 0x98, 0x7f, 0x02, 0x23, 0xfe, + 0x59, 0xf6, 0x04, 0x8c, 0x15, 0xdf, 0x4c, 0xa6, 0x77, 0x2a, 0x74, 0x95, 0x41, 0xc3, 0x6a, 0xaf, + 0xf8, 0x86, 0xbe, 0x1d, 0x7b, 0x04, 0x2d, 0x14, 0xca, 0x8d, 0x8a, 0x46, 0xc3, 0x6a, 0xae, 0xf8, + 0xe6, 0x7a, 0x13, 0x0b, 0xf0, 0x70, 0xea, 0xd6, 0x6f, 0xc5, 0x37, 0x2f, 0x79, 0x68, 0x7e, 0x05, + 0x4d, 0xe5, 0xe4, 0xcf, 0x32, 0x8c, 0xf8, 0x6a, 0x06, 0xff, 0x3b, 0xe8, 0xa4, 0xfc, 0x66, 0x9f, + 0xc1, 0x43, 0xb5, 0x43, 0x9f, 0x07, 0x92, 0x22, 0x92, 0x31, 0xc8, 0x48, 0xf8, 0x9a, 0x07, 0x12, + 0x7f, 0x92, 0x4c, 0x9b, 0x7f, 0xaf, 0x42, 0x53, 0x75, 0x74, 0xec, 0x31, 0x16, 0x7b, 0xee, 0xb8, + 0x13, 0xc7, 0x8e, 0x8a, 0x0c, 0xcd, 0xc7, 0x76, 0xea, 0x94, 0x54, 0x33, 0xa7, 0x84, 0x41, 0x5d, + 0x3a, 0x2b, 0xa1, 0x77, 0x45, 0x63, 0x74, 0xd6, 0x5d, 0xaf, 0x28, 0x0a, 0x75, 0x15, 0x05, 0x77, + 0xbd, 0xc2, 0x28, 0x9c, 0xc0, 0x4e, 0xaa, 0x5a, 0x38, 0xb6, 0xee, 0x62, 0x76, 0xd3, 0x1f, 0x60, + 0x7c, 0x61, 0x75, 0xe2, 0xba, 0x31, 0xb6, 0xd9, 0x00, 0xa8, 0x8c, 0x4c, 0x54, 0xa7, 0xa0, 0xca, + 0x4b, 0x93, 0xca, 0xcb, 0x2e, 0xae, 0xeb, 0x56, 0x02, 0xdb, 0xd5, 0x27, 0x60, 0xe0, 0xd1, 0x51, + 0x2a, 0x2d, 0x52, 0x69, 0xe3, 0x02, 0x09, 0x3f, 0x84, 0xbd, 0xa4, 0xdb, 0x54, 0x2a, 0x6d, 0x65, + 0x25, 0x59, 0x26, 0xc5, 0xc7, 0xd0, 0x8e, 0xcb, 0x98, 0x41, 0x1a, 0x2d, 0xae, 0xab, 0xd7, 0x18, + 0x5a, 0xda, 0xc5, 0xc2, 0x76, 0xf9, 0x23, 0x68, 0x60, 0xd4, 0xa3, 0x83, 0x10, 0x35, 0x31, 0x14, + 0x6d, 0x21, 0x75, 0xd3, 0xac, 0x54, 0xcc, 0x53, 0xd8, 0xc9, 0xac, 0x23, 0xdf, 0x4a, 0x4f, 0xf2, + 0xa5, 0xfe, 0x50, 0x6a, 0x12, 0xff, 0x4c, 0x35, 0xf9, 0x19, 0xf3, 0x0b, 0x30, 0xe2, 0x33, 0x8a, + 0xa1, 0xf6, 0xd7, 0xd3, 0x49, 0x74, 0xf7, 0xd9, 0xb6, 0x9a, 0xfe, 0x7a, 0xfa, 0x8d, 0xba, 0xfe, + 0xf8, 0xde, 0xf7, 0xba, 0x75, 0xaf, 0x59, 0x6a, 0x62, 0x7e, 0x09, 0xed, 0xa8, 0xb5, 0x2e, 0x87, + 0x96, 0x7c, 0x6a, 0xf3, 0x9f, 0x15, 0x68, 0xaa, 0x6a, 0x57, 0x70, 0xdd, 0xfa, 0x8c, 0xee, 0x21, + 0x6b, 0x31, 0xc1, 0x4d, 0x13, 0x70, 0x37, 0x3e, 0x58, 0x0a, 0x74, 0x7c, 0x7d, 0xe7, 0x0b, 0xcb, + 0x20, 0x2d, 0x1c, 0xb2, 0x0f, 0x60, 0x5b, 0x41, 0x42, 0x19, 0x38, 0x6e, 0xc4, 0x75, 0x1d, 0x5a, + 0xbb, 0xa2, 0x25, 0xfc, 0xa4, 0x4a, 0xc5, 0x71, 0xa5, 0xae, 0x6a, 0x6d, 0x5a, 0x18, 0xbb, 0xd2, + 0x7c, 0x02, 0x75, 0xb2, 0x03, 0xd0, 0xbc, 0xba, 0xb6, 0xc6, 0xaf, 0x5e, 0x76, 0xb7, 0x58, 0x0b, + 0x6a, 0xe3, 0x57, 0xd7, 0xdd, 0xca, 0xc9, 0x0f, 0x0d, 0xd8, 0x3b, 0x1b, 0x9d, 0x8f, 0xcf, 0x7c, + 0x7f, 0xe9, 0xcc, 0x38, 0x35, 0x1a, 0x43, 0xa8, 0x53, 0x2b, 0x55, 0xf0, 0xa2, 0xd1, 0x2f, 0xea, + 0xe9, 0xd9, 0x09, 0x34, 0xa8, 0xa3, 0x62, 0x45, 0x0f, 0x1b, 0xfd, 0xc2, 0xd6, 0x1e, 0x7f, 0x44, + 0xf5, 0x5c, 0xf7, 0xdf, 0x37, 0xfa, 0x45, 0xfd, 0x3d, 0xfb, 0x0a, 0x8c, 0xa4, 0x17, 0x2a, 0x7b, + 0xe5, 0xe8, 0x97, 0x76, 0xfa, 0x88, 0x4f, 0xfa, 0xa1, 0xb2, 0xb7, 0x8e, 0x7e, 0x69, 0xbb, 0xcf, + 0x9e, 0x43, 0x2b, 0x6a, 0x55, 0x8a, 0x5f, 0x3c, 0xfa, 0x25, 0x1d, 0x3f, 0x86, 0x47, 0x35, 0x10, + 0x45, 0x0f, 0x19, 0xfd, 0xc2, 0x26, 0x9e, 0x3d, 0x83, 0xa6, 0xae, 0x9d, 0x85, 0x8f, 0x25, 0xfd, + 0xe2, 0xab, 0x02, 0x6e, 0x32, 0xb9, 0xf3, 0x96, 0xbd, 0x82, 0xf4, 0x4b, 0x2f, 0x01, 0xec, 0x0c, + 0x20, 0x75, 0xd9, 0x2d, 0x7d, 0x0b, 0xe9, 0x97, 0x5f, 0x05, 0x18, 0x9e, 0x9d, 0xf8, 0xba, 0x59, + 0xfc, 0x22, 0xd2, 0x2f, 0xbb, 0x0d, 0x4c, 0x9b, 0xf4, 0xca, 0xf6, 0xf9, 0xff, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x3a, 0x99, 0xe6, 0x77, 0xb0, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 760bb534..99d2ef64 100644 --- a/types/types.proto +++ b/types/types.proto @@ -157,7 +157,7 @@ message ResponseBeginBlock{ } message ResponseEndBlock{ - repeated Validator updates = 1; + repeated Validator validator_set_updates = 1; ConsensusParams consensus_param_updates = 2; } From 811dc071aae355775131d3e6f9325a076995aca2 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Tue, 19 Dec 2017 11:29:59 -0700 Subject: [PATCH 411/545] protoc: "//nolint: gas" directive after pb generation (#164) * protoc: "//nolint: gas" directive after pb generation Fixes #138 Since we can't add package directives through the protoc compiler, yet we need to "//nolint: gas" the Go generated protobuf file, added a script whose purpose is to go find the "package (\w+)$" declaration after go fmt was run by protoc. The competing solutions were more complex and can be examined by visiting https://github.com/tendermint/abci/issues/138#issuecomment-352226217 * simplify script * rewrite script to work on Mac --- Makefile | 3 +++ types/types.pb.go | 1 + 2 files changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 7176ab10..9324570f 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,9 @@ protoc: ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 protoc $(INCLUDE) --gogo_out=plugins=grpc:. --lint_out=. types/*.proto + @echo "--> adding nolint declarations to protobuf generated files" + @awk '/package types/ { print "//nolint: gas"; print; next }1' types/types.pb.go > types/types.pb.go.new + @mv types/types.pb.go.new types/types.pb.go install: @ go install ./cmd/... diff --git a/types/types.pb.go b/types/types.pb.go index 69777d6d..e7549665 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -40,6 +40,7 @@ It has these top-level messages: Evidence KVPair */ +//nolint: gas package types import proto "github.com/gogo/protobuf/proto" From 9a5b943e778567df49ec0f3d5a8f46fe0a928e6c Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 19 Dec 2017 13:17:29 -0600 Subject: [PATCH 412/545] update changelog [ci skip] --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64c0cbce..627e23c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.9.0 (TBD) + +BREAKING CHANGES: + - [types] ResponseEndBlock: renamed Diffs field to ValidatorSetUpdates + +FEATURES: + - [types] ResponseEndBlock: added ConsensusParamUpdates + ## 0.8.0 (December 6, 2017) BREAKING CHANGES: From c14d3982ac6eaf941e246ffca39421a15686e485 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 20 Dec 2017 00:02:41 -0800 Subject: [PATCH 413/545] ValidatorSetUpdates -> ValidatorUpdates --- CHANGELOG.md | 2 +- Makefile | 18 +- README.md | 2 +- example/dummy/dummy_test.go | 4 +- example/dummy/persistent_dummy.go | 10 +- types/types.pb.go | 1120 ++++++++++++++--------------- types/types.proto | 176 ++--- 7 files changed, 663 insertions(+), 669 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 627e23c3..c2b183f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## 0.9.0 (TBD) BREAKING CHANGES: - - [types] ResponseEndBlock: renamed Diffs field to ValidatorSetUpdates + - [types] ResponseEndBlock: renamed Diffs field to ValidatorUpdates FEATURES: - [types] ResponseEndBlock: added ConsensusParamUpdates diff --git a/Makefile b/Makefile index d5fe913b..8487febf 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,12 @@ GOTOOLS = \ github.com/mitchellh/gox \ github.com/Masterminds/glide \ github.com/alecthomas/gometalinter \ - github.com/ckaznocha/protoc-gen-lint \ github.com/gogo/protobuf/protoc-gen-gogo \ github.com/gogo/protobuf/gogoproto INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf -all: install test +all: protoc install test metalinter PACKAGES=$(shell go list ./... | grep -v '/vendor/') @@ -27,7 +26,7 @@ protoc: ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## ldconfig (may require sudo) ## https://stackoverflow.com/a/25518702 - protoc $(INCLUDE) --gogo_out=plugins=grpc:. --lint_out=. types/*.proto + protoc $(INCLUDE) --gogo_out=plugins=grpc:. types/*.proto install: @ go install ./cmd/... @@ -41,15 +40,13 @@ dist: test: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; - @ echo "==> Running linter" - @ make metalinter_test @ echo "==> Running go test" @ go test $(PACKAGES) test_race: @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; @ echo "==> Running go test --race" - @go test -v -race $(PACKAGES) + @ go test -v -race $(PACKAGES) test_integrations: @ bash test.sh @@ -62,19 +59,18 @@ get_deps: ensure_tools: go get -u -v $(GOTOOLS) - @gometalinter --install + @ gometalinter --install get_vendor_deps: ensure_tools @rm -rf vendor/ @echo "--> Running glide install" @ glide install -metalinter: - protoc $(INCLUDE) --lint_out=. types/*.proto +metalinter_all: gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... -metalinter_test: - protoc $(INCLUDE) --lint_out=. types/*.proto +metalinter: + @ echo "==> Running linter" gometalinter --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ diff --git a/README.md b/README.md index d1679221..546342fc 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ Here, we describe the requests and responses as function arguments and return va * __Arguments__: * `Height (int64)`: The block height that ended * __Returns__: - * `ValidatorSetUpdates ([]Validator)`: Changes to validator set (set voting power to 0 to remove) + * `ValidatorUpdates ([]Validator)`: Changes to validator set (set voting power to 0 to remove) * `ConsensusParamUpdates (ConsensusParams)`: Changes to consensus-critical time/size parameters * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index e3cdfc62..96666547 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -107,7 +107,7 @@ func TestPersistentDummyInfo(t *testing.T) { } // add a validator, remove a validator, update a validator -func TestValSetUpdates(t *testing.T) { +func TestValUpdates(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO if err != nil { t.Fatal(err) @@ -188,7 +188,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height}) dummy.Commit() - valsEqual(t, diff, resEndBlock.ValidatorSetUpdates) + valsEqual(t, diff, resEndBlock.ValidatorUpdates) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 47f8630c..4165b9f7 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -28,7 +28,7 @@ type PersistentDummyApplication struct { app *DummyApplication // validator set - valSetUpdates []*types.Validator + ValUpdates []*types.Validator logger log.Logger } @@ -71,7 +71,7 @@ func (app *PersistentDummyApplication) DeliverTx(tx []byte) types.ResponseDelive // format is "val:pubkey/power" if isValidatorTx(tx) { // update validators in the merkle tree - // and in app.valSetUpdates + // and in app.ValUpdates return app.execValidatorTx(tx) } @@ -119,13 +119,13 @@ func (app *PersistentDummyApplication) InitChain(req types.RequestInitChain) typ // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { // reset valset changes - app.valSetUpdates = make([]*types.Validator, 0) + app.ValUpdates = make([]*types.Validator, 0) return types.ResponseBeginBlock{} } // Update the validator set func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - return types.ResponseEndBlock{ValidatorSetUpdates: app.valSetUpdates} + return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates} } //--------------------------------------------- @@ -216,7 +216,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types } // we only update the changes array if we successfully updated the tree - app.valSetUpdates = append(app.valSetUpdates, v) + app.ValUpdates = append(app.ValUpdates, v) return types.ResponseDeliverTx{Code: code.CodeTypeOK} } diff --git a/types/types.pb.go b/types/types.pb.go index 202ab71c..14026a8b 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -13,26 +13,26 @@ It has these top-level messages: RequestFlush RequestInfo RequestSetOption - RequestDeliverTx - RequestCheckTx - RequestQuery - RequestCommit RequestInitChain + RequestQuery RequestBeginBlock + RequestCheckTx + RequestDeliverTx RequestEndBlock + RequestCommit Response ResponseException ResponseEcho ResponseFlush ResponseInfo ResponseSetOption - ResponseDeliverTx - ResponseCheckTx - ResponseQuery - ResponseCommit ResponseInitChain + ResponseQuery ResponseBeginBlock + ResponseCheckTx + ResponseDeliverTx ResponseEndBlock + ResponseCommit ConsensusParams BlockSize TxSize @@ -94,13 +94,13 @@ type Request struct { // *Request_Flush // *Request_Info // *Request_SetOption - // *Request_DeliverTx - // *Request_CheckTx - // *Request_Commit - // *Request_Query // *Request_InitChain + // *Request_Query // *Request_BeginBlock + // *Request_CheckTx + // *Request_DeliverTx // *Request_EndBlock + // *Request_Commit Value isRequest_Value `protobuf_oneof:"value"` } @@ -114,50 +114,50 @@ type isRequest_Value interface { } type Request_Echo struct { - Echo *RequestEcho `protobuf:"bytes,1,opt,name=echo,oneof"` + Echo *RequestEcho `protobuf:"bytes,2,opt,name=echo,oneof"` } type Request_Flush struct { - Flush *RequestFlush `protobuf:"bytes,2,opt,name=flush,oneof"` + Flush *RequestFlush `protobuf:"bytes,3,opt,name=flush,oneof"` } type Request_Info struct { - Info *RequestInfo `protobuf:"bytes,3,opt,name=info,oneof"` + Info *RequestInfo `protobuf:"bytes,4,opt,name=info,oneof"` } type Request_SetOption struct { - SetOption *RequestSetOption `protobuf:"bytes,4,opt,name=set_option,json=setOption,oneof"` -} -type Request_DeliverTx struct { - DeliverTx *RequestDeliverTx `protobuf:"bytes,5,opt,name=deliver_tx,json=deliverTx,oneof"` -} -type Request_CheckTx struct { - CheckTx *RequestCheckTx `protobuf:"bytes,6,opt,name=check_tx,json=checkTx,oneof"` -} -type Request_Commit struct { - Commit *RequestCommit `protobuf:"bytes,7,opt,name=commit,oneof"` -} -type Request_Query struct { - Query *RequestQuery `protobuf:"bytes,8,opt,name=query,oneof"` + SetOption *RequestSetOption `protobuf:"bytes,5,opt,name=set_option,json=setOption,oneof"` } type Request_InitChain struct { - InitChain *RequestInitChain `protobuf:"bytes,9,opt,name=init_chain,json=initChain,oneof"` + InitChain *RequestInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,oneof"` +} +type Request_Query struct { + Query *RequestQuery `protobuf:"bytes,7,opt,name=query,oneof"` } type Request_BeginBlock struct { - BeginBlock *RequestBeginBlock `protobuf:"bytes,10,opt,name=begin_block,json=beginBlock,oneof"` + BeginBlock *RequestBeginBlock `protobuf:"bytes,8,opt,name=begin_block,json=beginBlock,oneof"` +} +type Request_CheckTx struct { + CheckTx *RequestCheckTx `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,oneof"` +} +type Request_DeliverTx struct { + DeliverTx *RequestDeliverTx `protobuf:"bytes,19,opt,name=deliver_tx,json=deliverTx,oneof"` } type Request_EndBlock struct { EndBlock *RequestEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,oneof"` } +type Request_Commit struct { + Commit *RequestCommit `protobuf:"bytes,12,opt,name=commit,oneof"` +} func (*Request_Echo) isRequest_Value() {} func (*Request_Flush) isRequest_Value() {} func (*Request_Info) isRequest_Value() {} func (*Request_SetOption) isRequest_Value() {} -func (*Request_DeliverTx) isRequest_Value() {} -func (*Request_CheckTx) isRequest_Value() {} -func (*Request_Commit) isRequest_Value() {} -func (*Request_Query) isRequest_Value() {} func (*Request_InitChain) isRequest_Value() {} +func (*Request_Query) isRequest_Value() {} func (*Request_BeginBlock) isRequest_Value() {} +func (*Request_CheckTx) isRequest_Value() {} +func (*Request_DeliverTx) isRequest_Value() {} func (*Request_EndBlock) isRequest_Value() {} +func (*Request_Commit) isRequest_Value() {} func (m *Request) GetValue() isRequest_Value { if m != nil { @@ -194,23 +194,9 @@ func (m *Request) GetSetOption() *RequestSetOption { return nil } -func (m *Request) GetDeliverTx() *RequestDeliverTx { - if x, ok := m.GetValue().(*Request_DeliverTx); ok { - return x.DeliverTx - } - return nil -} - -func (m *Request) GetCheckTx() *RequestCheckTx { - if x, ok := m.GetValue().(*Request_CheckTx); ok { - return x.CheckTx - } - return nil -} - -func (m *Request) GetCommit() *RequestCommit { - if x, ok := m.GetValue().(*Request_Commit); ok { - return x.Commit +func (m *Request) GetInitChain() *RequestInitChain { + if x, ok := m.GetValue().(*Request_InitChain); ok { + return x.InitChain } return nil } @@ -222,16 +208,23 @@ func (m *Request) GetQuery() *RequestQuery { return nil } -func (m *Request) GetInitChain() *RequestInitChain { - if x, ok := m.GetValue().(*Request_InitChain); ok { - return x.InitChain +func (m *Request) GetBeginBlock() *RequestBeginBlock { + if x, ok := m.GetValue().(*Request_BeginBlock); ok { + return x.BeginBlock } return nil } -func (m *Request) GetBeginBlock() *RequestBeginBlock { - if x, ok := m.GetValue().(*Request_BeginBlock); ok { - return x.BeginBlock +func (m *Request) GetCheckTx() *RequestCheckTx { + if x, ok := m.GetValue().(*Request_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Request) GetDeliverTx() *RequestDeliverTx { + if x, ok := m.GetValue().(*Request_DeliverTx); ok { + return x.DeliverTx } return nil } @@ -243,6 +236,13 @@ func (m *Request) GetEndBlock() *RequestEndBlock { return nil } +func (m *Request) GetCommit() *RequestCommit { + if x, ok := m.GetValue().(*Request_Commit); ok { + return x.Commit + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Request_OneofMarshaler, _Request_OneofUnmarshaler, _Request_OneofSizer, []interface{}{ @@ -250,13 +250,13 @@ func (*Request) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error (*Request_Flush)(nil), (*Request_Info)(nil), (*Request_SetOption)(nil), - (*Request_DeliverTx)(nil), - (*Request_CheckTx)(nil), - (*Request_Commit)(nil), - (*Request_Query)(nil), (*Request_InitChain)(nil), + (*Request_Query)(nil), (*Request_BeginBlock)(nil), + (*Request_CheckTx)(nil), + (*Request_DeliverTx)(nil), (*Request_EndBlock)(nil), + (*Request_Commit)(nil), } } @@ -265,60 +265,60 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { // value switch x := m.Value.(type) { case *Request_Echo: - _ = b.EncodeVarint(1<<3 | proto.WireBytes) + _ = b.EncodeVarint(2<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Echo); err != nil { return err } case *Request_Flush: - _ = b.EncodeVarint(2<<3 | proto.WireBytes) + _ = b.EncodeVarint(3<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Flush); err != nil { return err } case *Request_Info: - _ = b.EncodeVarint(3<<3 | proto.WireBytes) + _ = b.EncodeVarint(4<<3 | proto.WireBytes) if err := b.EncodeMessage(x.Info); err != nil { return err } case *Request_SetOption: - _ = b.EncodeVarint(4<<3 | proto.WireBytes) + _ = b.EncodeVarint(5<<3 | proto.WireBytes) if err := b.EncodeMessage(x.SetOption); err != nil { return err } - case *Request_DeliverTx: - _ = b.EncodeVarint(5<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.DeliverTx); err != nil { - return err - } - case *Request_CheckTx: - _ = b.EncodeVarint(6<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.CheckTx); err != nil { - return err - } - case *Request_Commit: - _ = b.EncodeVarint(7<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Commit); err != nil { - return err - } - case *Request_Query: - _ = b.EncodeVarint(8<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Query); err != nil { - return err - } case *Request_InitChain: - _ = b.EncodeVarint(9<<3 | proto.WireBytes) + _ = b.EncodeVarint(6<<3 | proto.WireBytes) if err := b.EncodeMessage(x.InitChain); err != nil { return err } + case *Request_Query: + _ = b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Query); err != nil { + return err + } case *Request_BeginBlock: - _ = b.EncodeVarint(10<<3 | proto.WireBytes) + _ = b.EncodeVarint(8<<3 | proto.WireBytes) if err := b.EncodeMessage(x.BeginBlock); err != nil { return err } + case *Request_CheckTx: + _ = b.EncodeVarint(9<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CheckTx); err != nil { + return err + } + case *Request_DeliverTx: + _ = b.EncodeVarint(19<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.DeliverTx); err != nil { + return err + } case *Request_EndBlock: _ = b.EncodeVarint(11<<3 | proto.WireBytes) if err := b.EncodeMessage(x.EndBlock); err != nil { return err } + case *Request_Commit: + _ = b.EncodeVarint(12<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Commit); err != nil { + return err + } case nil: default: return fmt.Errorf("Request.Value has unexpected type %T", x) @@ -329,7 +329,7 @@ func _Request_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { m := msg.(*Request) switch tag { - case 1: // value.echo + case 2: // value.echo if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -337,7 +337,7 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_Echo{msg} return true, err - case 2: // value.flush + case 3: // value.flush if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -345,7 +345,7 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_Flush{msg} return true, err - case 3: // value.info + case 4: // value.info if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -353,7 +353,7 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_Info{msg} return true, err - case 4: // value.set_option + case 5: // value.set_option if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -361,39 +361,7 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_SetOption{msg} return true, err - case 5: // value.deliver_tx - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(RequestDeliverTx) - err := b.DecodeMessage(msg) - m.Value = &Request_DeliverTx{msg} - return true, err - case 6: // value.check_tx - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(RequestCheckTx) - err := b.DecodeMessage(msg) - m.Value = &Request_CheckTx{msg} - return true, err - case 7: // value.commit - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(RequestCommit) - err := b.DecodeMessage(msg) - m.Value = &Request_Commit{msg} - return true, err - case 8: // value.query - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(RequestQuery) - err := b.DecodeMessage(msg) - m.Value = &Request_Query{msg} - return true, err - case 9: // value.init_chain + case 6: // value.init_chain if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -401,7 +369,15 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_InitChain{msg} return true, err - case 10: // value.begin_block + case 7: // value.query + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestQuery) + err := b.DecodeMessage(msg) + m.Value = &Request_Query{msg} + return true, err + case 8: // value.begin_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -409,6 +385,22 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_BeginBlock{msg} return true, err + case 9: // value.check_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestCheckTx) + err := b.DecodeMessage(msg) + m.Value = &Request_CheckTx{msg} + return true, err + case 19: // value.deliver_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestDeliverTx) + err := b.DecodeMessage(msg) + m.Value = &Request_DeliverTx{msg} + return true, err case 11: // value.end_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType @@ -417,6 +409,14 @@ func _Request_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer err := b.DecodeMessage(msg) m.Value = &Request_EndBlock{msg} return true, err + case 12: // value.commit + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RequestCommit) + err := b.DecodeMessage(msg) + m.Value = &Request_Commit{msg} + return true, err default: return false, nil } @@ -428,52 +428,47 @@ func _Request_OneofSizer(msg proto.Message) (n int) { switch x := m.Value.(type) { case *Request_Echo: s := proto.Size(x.Echo) - n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(2<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Request_Flush: s := proto.Size(x.Flush) - n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(3<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Request_Info: s := proto.Size(x.Info) - n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(4<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Request_SetOption: s := proto.Size(x.SetOption) - n += proto.SizeVarint(4<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *Request_DeliverTx: - s := proto.Size(x.DeliverTx) n += proto.SizeVarint(5<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Request_CheckTx: - s := proto.Size(x.CheckTx) - n += proto.SizeVarint(6<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *Request_Commit: - s := proto.Size(x.Commit) - n += proto.SizeVarint(7<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *Request_Query: - s := proto.Size(x.Query) - n += proto.SizeVarint(8<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s case *Request_InitChain: s := proto.Size(x.InitChain) - n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_Query: + s := proto.Size(x.Query) + n += proto.SizeVarint(7<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Request_BeginBlock: s := proto.Size(x.BeginBlock) - n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(8<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_CheckTx: + s := proto.Size(x.CheckTx) + n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Request_DeliverTx: + s := proto.Size(x.DeliverTx) + n += proto.SizeVarint(19<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Request_EndBlock: @@ -481,6 +476,11 @@ func _Request_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(11<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s + case *Request_Commit: + s := proto.Size(x.Commit) + n += proto.SizeVarint(12<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -552,34 +552,18 @@ func (m *RequestSetOption) GetValue() string { return "" } -type RequestDeliverTx struct { - Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` +type RequestInitChain struct { + Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` } -func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } -func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } -func (*RequestDeliverTx) ProtoMessage() {} -func (*RequestDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} } +func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } +func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } +func (*RequestInitChain) ProtoMessage() {} +func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} } -func (m *RequestDeliverTx) GetTx() []byte { +func (m *RequestInitChain) GetValidators() []*Validator { if m != nil { - return m.Tx - } - return nil -} - -type RequestCheckTx struct { - Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` -} - -func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } -func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } -func (*RequestCheckTx) ProtoMessage() {} -func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} } - -func (m *RequestCheckTx) GetTx() []byte { - if m != nil { - return m.Tx + return m.Validators } return nil } @@ -594,7 +578,7 @@ type RequestQuery struct { func (m *RequestQuery) Reset() { *m = RequestQuery{} } func (m *RequestQuery) String() string { return proto.CompactTextString(m) } func (*RequestQuery) ProtoMessage() {} -func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{7} } +func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} } func (m *RequestQuery) GetData() []byte { if m != nil { @@ -624,30 +608,6 @@ func (m *RequestQuery) GetProve() bool { return false } -type RequestCommit struct { -} - -func (m *RequestCommit) Reset() { *m = RequestCommit{} } -func (m *RequestCommit) String() string { return proto.CompactTextString(m) } -func (*RequestCommit) ProtoMessage() {} -func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{8} } - -type RequestInitChain struct { - Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` -} - -func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } -func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } -func (*RequestInitChain) ProtoMessage() {} -func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9} } - -func (m *RequestInitChain) GetValidators() []*Validator { - if m != nil { - return m.Validators - } - return nil -} - type RequestBeginBlock struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` @@ -658,7 +618,7 @@ type RequestBeginBlock struct { func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } func (*RequestBeginBlock) ProtoMessage() {} -func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10} } +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{7} } func (m *RequestBeginBlock) GetHash() []byte { if m != nil { @@ -688,6 +648,38 @@ func (m *RequestBeginBlock) GetByzantineValidators() []*Evidence { return nil } +type RequestCheckTx struct { + Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` +} + +func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } +func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } +func (*RequestCheckTx) ProtoMessage() {} +func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{8} } + +func (m *RequestCheckTx) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + +type RequestDeliverTx struct { + Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` +} + +func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } +func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } +func (*RequestDeliverTx) ProtoMessage() {} +func (*RequestDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9} } + +func (m *RequestDeliverTx) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + type RequestEndBlock struct { Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` } @@ -695,7 +687,7 @@ type RequestEndBlock struct { func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } func (*RequestEndBlock) ProtoMessage() {} -func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} } +func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10} } func (m *RequestEndBlock) GetHeight() int64 { if m != nil { @@ -704,6 +696,14 @@ func (m *RequestEndBlock) GetHeight() int64 { return 0 } +type RequestCommit struct { +} + +func (m *RequestCommit) Reset() { *m = RequestCommit{} } +func (m *RequestCommit) String() string { return proto.CompactTextString(m) } +func (*RequestCommit) ProtoMessage() {} +func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} } + type Response struct { // Types that are valid to be assigned to Value: // *Response_Exception @@ -711,13 +711,13 @@ type Response struct { // *Response_Flush // *Response_Info // *Response_SetOption - // *Response_DeliverTx - // *Response_CheckTx - // *Response_Commit - // *Response_Query // *Response_InitChain + // *Response_Query // *Response_BeginBlock + // *Response_CheckTx + // *Response_DeliverTx // *Response_EndBlock + // *Response_Commit Value isResponse_Value `protobuf_oneof:"value"` } @@ -745,26 +745,26 @@ type Response_Info struct { type Response_SetOption struct { SetOption *ResponseSetOption `protobuf:"bytes,5,opt,name=set_option,json=setOption,oneof"` } -type Response_DeliverTx struct { - DeliverTx *ResponseDeliverTx `protobuf:"bytes,6,opt,name=deliver_tx,json=deliverTx,oneof"` -} -type Response_CheckTx struct { - CheckTx *ResponseCheckTx `protobuf:"bytes,7,opt,name=check_tx,json=checkTx,oneof"` -} -type Response_Commit struct { - Commit *ResponseCommit `protobuf:"bytes,8,opt,name=commit,oneof"` +type Response_InitChain struct { + InitChain *ResponseInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,oneof"` } type Response_Query struct { - Query *ResponseQuery `protobuf:"bytes,9,opt,name=query,oneof"` -} -type Response_InitChain struct { - InitChain *ResponseInitChain `protobuf:"bytes,10,opt,name=init_chain,json=initChain,oneof"` + Query *ResponseQuery `protobuf:"bytes,7,opt,name=query,oneof"` } type Response_BeginBlock struct { - BeginBlock *ResponseBeginBlock `protobuf:"bytes,11,opt,name=begin_block,json=beginBlock,oneof"` + BeginBlock *ResponseBeginBlock `protobuf:"bytes,8,opt,name=begin_block,json=beginBlock,oneof"` +} +type Response_CheckTx struct { + CheckTx *ResponseCheckTx `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,oneof"` +} +type Response_DeliverTx struct { + DeliverTx *ResponseDeliverTx `protobuf:"bytes,10,opt,name=deliver_tx,json=deliverTx,oneof"` } type Response_EndBlock struct { - EndBlock *ResponseEndBlock `protobuf:"bytes,12,opt,name=end_block,json=endBlock,oneof"` + EndBlock *ResponseEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,oneof"` +} +type Response_Commit struct { + Commit *ResponseCommit `protobuf:"bytes,12,opt,name=commit,oneof"` } func (*Response_Exception) isResponse_Value() {} @@ -772,13 +772,13 @@ func (*Response_Echo) isResponse_Value() {} func (*Response_Flush) isResponse_Value() {} func (*Response_Info) isResponse_Value() {} func (*Response_SetOption) isResponse_Value() {} -func (*Response_DeliverTx) isResponse_Value() {} -func (*Response_CheckTx) isResponse_Value() {} -func (*Response_Commit) isResponse_Value() {} -func (*Response_Query) isResponse_Value() {} func (*Response_InitChain) isResponse_Value() {} +func (*Response_Query) isResponse_Value() {} func (*Response_BeginBlock) isResponse_Value() {} +func (*Response_CheckTx) isResponse_Value() {} +func (*Response_DeliverTx) isResponse_Value() {} func (*Response_EndBlock) isResponse_Value() {} +func (*Response_Commit) isResponse_Value() {} func (m *Response) GetValue() isResponse_Value { if m != nil { @@ -822,23 +822,9 @@ func (m *Response) GetSetOption() *ResponseSetOption { return nil } -func (m *Response) GetDeliverTx() *ResponseDeliverTx { - if x, ok := m.GetValue().(*Response_DeliverTx); ok { - return x.DeliverTx - } - return nil -} - -func (m *Response) GetCheckTx() *ResponseCheckTx { - if x, ok := m.GetValue().(*Response_CheckTx); ok { - return x.CheckTx - } - return nil -} - -func (m *Response) GetCommit() *ResponseCommit { - if x, ok := m.GetValue().(*Response_Commit); ok { - return x.Commit +func (m *Response) GetInitChain() *ResponseInitChain { + if x, ok := m.GetValue().(*Response_InitChain); ok { + return x.InitChain } return nil } @@ -850,13 +836,6 @@ func (m *Response) GetQuery() *ResponseQuery { return nil } -func (m *Response) GetInitChain() *ResponseInitChain { - if x, ok := m.GetValue().(*Response_InitChain); ok { - return x.InitChain - } - return nil -} - func (m *Response) GetBeginBlock() *ResponseBeginBlock { if x, ok := m.GetValue().(*Response_BeginBlock); ok { return x.BeginBlock @@ -864,6 +843,20 @@ func (m *Response) GetBeginBlock() *ResponseBeginBlock { return nil } +func (m *Response) GetCheckTx() *ResponseCheckTx { + if x, ok := m.GetValue().(*Response_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Response) GetDeliverTx() *ResponseDeliverTx { + if x, ok := m.GetValue().(*Response_DeliverTx); ok { + return x.DeliverTx + } + return nil +} + func (m *Response) GetEndBlock() *ResponseEndBlock { if x, ok := m.GetValue().(*Response_EndBlock); ok { return x.EndBlock @@ -871,6 +864,13 @@ func (m *Response) GetEndBlock() *ResponseEndBlock { return nil } +func (m *Response) GetCommit() *ResponseCommit { + if x, ok := m.GetValue().(*Response_Commit); ok { + return x.Commit + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Response_OneofMarshaler, _Response_OneofUnmarshaler, _Response_OneofSizer, []interface{}{ @@ -879,13 +879,13 @@ func (*Response) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) erro (*Response_Flush)(nil), (*Response_Info)(nil), (*Response_SetOption)(nil), - (*Response_DeliverTx)(nil), - (*Response_CheckTx)(nil), - (*Response_Commit)(nil), - (*Response_Query)(nil), (*Response_InitChain)(nil), + (*Response_Query)(nil), (*Response_BeginBlock)(nil), + (*Response_CheckTx)(nil), + (*Response_DeliverTx)(nil), (*Response_EndBlock)(nil), + (*Response_Commit)(nil), } } @@ -918,41 +918,41 @@ func _Response_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.SetOption); err != nil { return err } - case *Response_DeliverTx: - _ = b.EncodeVarint(6<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.DeliverTx); err != nil { - return err - } - case *Response_CheckTx: - _ = b.EncodeVarint(7<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.CheckTx); err != nil { - return err - } - case *Response_Commit: - _ = b.EncodeVarint(8<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Commit); err != nil { - return err - } - case *Response_Query: - _ = b.EncodeVarint(9<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Query); err != nil { - return err - } case *Response_InitChain: - _ = b.EncodeVarint(10<<3 | proto.WireBytes) + _ = b.EncodeVarint(6<<3 | proto.WireBytes) if err := b.EncodeMessage(x.InitChain); err != nil { return err } + case *Response_Query: + _ = b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Query); err != nil { + return err + } case *Response_BeginBlock: - _ = b.EncodeVarint(11<<3 | proto.WireBytes) + _ = b.EncodeVarint(8<<3 | proto.WireBytes) if err := b.EncodeMessage(x.BeginBlock); err != nil { return err } + case *Response_CheckTx: + _ = b.EncodeVarint(9<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CheckTx); err != nil { + return err + } + case *Response_DeliverTx: + _ = b.EncodeVarint(10<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.DeliverTx); err != nil { + return err + } case *Response_EndBlock: - _ = b.EncodeVarint(12<<3 | proto.WireBytes) + _ = b.EncodeVarint(11<<3 | proto.WireBytes) if err := b.EncodeMessage(x.EndBlock); err != nil { return err } + case *Response_Commit: + _ = b.EncodeVarint(12<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Commit); err != nil { + return err + } case nil: default: return fmt.Errorf("Response.Value has unexpected type %T", x) @@ -1003,39 +1003,7 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_SetOption{msg} return true, err - case 6: // value.deliver_tx - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(ResponseDeliverTx) - err := b.DecodeMessage(msg) - m.Value = &Response_DeliverTx{msg} - return true, err - case 7: // value.check_tx - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(ResponseCheckTx) - err := b.DecodeMessage(msg) - m.Value = &Response_CheckTx{msg} - return true, err - case 8: // value.commit - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(ResponseCommit) - err := b.DecodeMessage(msg) - m.Value = &Response_Commit{msg} - return true, err - case 9: // value.query - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(ResponseQuery) - err := b.DecodeMessage(msg) - m.Value = &Response_Query{msg} - return true, err - case 10: // value.init_chain + case 6: // value.init_chain if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -1043,7 +1011,15 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_InitChain{msg} return true, err - case 11: // value.begin_block + case 7: // value.query + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseQuery) + err := b.DecodeMessage(msg) + m.Value = &Response_Query{msg} + return true, err + case 8: // value.begin_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -1051,7 +1027,23 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_BeginBlock{msg} return true, err - case 12: // value.end_block + case 9: // value.check_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseCheckTx) + err := b.DecodeMessage(msg) + m.Value = &Response_CheckTx{msg} + return true, err + case 10: // value.deliver_tx + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseDeliverTx) + err := b.DecodeMessage(msg) + m.Value = &Response_DeliverTx{msg} + return true, err + case 11: // value.end_block if wire != proto.WireBytes { return true, proto.ErrInternalBadWireType } @@ -1059,6 +1051,14 @@ func _Response_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffe err := b.DecodeMessage(msg) m.Value = &Response_EndBlock{msg} return true, err + case 12: // value.commit + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ResponseCommit) + err := b.DecodeMessage(msg) + m.Value = &Response_Commit{msg} + return true, err default: return false, nil } @@ -1093,38 +1093,38 @@ func _Response_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(5<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Response_DeliverTx: - s := proto.Size(x.DeliverTx) + case *Response_InitChain: + s := proto.Size(x.InitChain) n += proto.SizeVarint(6<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s - case *Response_CheckTx: - s := proto.Size(x.CheckTx) - n += proto.SizeVarint(7<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *Response_Commit: - s := proto.Size(x.Commit) - n += proto.SizeVarint(8<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s case *Response_Query: s := proto.Size(x.Query) - n += proto.SizeVarint(9<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *Response_InitChain: - s := proto.Size(x.InitChain) - n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(7<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Response_BeginBlock: s := proto.Size(x.BeginBlock) - n += proto.SizeVarint(11<<3 | proto.WireBytes) + n += proto.SizeVarint(8<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_CheckTx: + s := proto.Size(x.CheckTx) + n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_DeliverTx: + s := proto.Size(x.DeliverTx) + n += proto.SizeVarint(10<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s case *Response_EndBlock: s := proto.Size(x.EndBlock) + n += proto.SizeVarint(11<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Response_Commit: + s := proto.Size(x.Commit) n += proto.SizeVarint(12<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s @@ -1239,79 +1239,13 @@ func (m *ResponseSetOption) GetLog() string { return "" } -type ResponseDeliverTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` +type ResponseInitChain struct { } -func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } -func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } -func (*ResponseDeliverTx) ProtoMessage() {} -func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} } - -func (m *ResponseDeliverTx) GetCode() uint32 { - if m != nil { - return m.Code - } - return 0 -} - -func (m *ResponseDeliverTx) GetLog() string { - if m != nil { - return m.Log - } - return "" -} - -func (m *ResponseDeliverTx) GetTags() []*KVPair { - if m != nil { - return m.Tags - } - return nil -} - -type ResponseCheckTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Gas int64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` - Fee int64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` -} - -func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } -func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } -func (*ResponseCheckTx) ProtoMessage() {} -func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} } - -func (m *ResponseCheckTx) GetCode() uint32 { - if m != nil { - return m.Code - } - return 0 -} - -func (m *ResponseCheckTx) GetLog() string { - if m != nil { - return m.Log - } - return "" -} - -func (m *ResponseCheckTx) GetGas() int64 { - if m != nil { - return m.Gas - } - return 0 -} - -func (m *ResponseCheckTx) GetFee() int64 { - if m != nil { - return m.Fee - } - return 0 -} +func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } +func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } +func (*ResponseInitChain) ProtoMessage() {} +func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} } type ResponseQuery struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` @@ -1326,7 +1260,7 @@ type ResponseQuery struct { func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } func (*ResponseQuery) ProtoMessage() {} -func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} } +func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} } func (m *ResponseQuery) GetCode() uint32 { if m != nil { @@ -1356,6 +1290,112 @@ func (m *ResponseQuery) GetLog() string { return "" } +type ResponseBeginBlock struct { +} + +func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } +func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseBeginBlock) ProtoMessage() {} +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} } + +type ResponseCheckTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Gas int64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` + Fee int64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` +} + +func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } +func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } +func (*ResponseCheckTx) ProtoMessage() {} +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} } + +func (m *ResponseCheckTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseCheckTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseCheckTx) GetGas() int64 { + if m != nil { + return m.Gas + } + return 0 +} + +func (m *ResponseCheckTx) GetFee() int64 { + if m != nil { + return m.Fee + } + return 0 +} + +type ResponseDeliverTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` +} + +func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } +func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } +func (*ResponseDeliverTx) ProtoMessage() {} +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} } + +func (m *ResponseDeliverTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseDeliverTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseDeliverTx) GetTags() []*KVPair { + if m != nil { + return m.Tags + } + return nil +} + +type ResponseEndBlock struct { + ValidatorUpdates []*Validator `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates,omitempty"` + ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"` +} + +func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } +func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseEndBlock) ProtoMessage() {} +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } + +func (m *ResponseEndBlock) GetValidatorUpdates() []*Validator { + if m != nil { + return m.ValidatorUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetConsensusParamUpdates() *ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates + } + return nil +} + type ResponseCommit struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` @@ -1365,7 +1405,7 @@ type ResponseCommit struct { func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } func (*ResponseCommit) ProtoMessage() {} -func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} } +func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} } func (m *ResponseCommit) GetCode() uint32 { if m != nil { @@ -1381,46 +1421,6 @@ func (m *ResponseCommit) GetLog() string { return "" } -type ResponseInitChain struct { -} - -func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } -func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } -func (*ResponseInitChain) ProtoMessage() {} -func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} } - -type ResponseBeginBlock struct { -} - -func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } -func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } -func (*ResponseBeginBlock) ProtoMessage() {} -func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } - -type ResponseEndBlock struct { - ValidatorSetUpdates []*Validator `protobuf:"bytes,1,rep,name=validator_set_updates,json=validatorSetUpdates" json:"validator_set_updates,omitempty"` - ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"` -} - -func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } -func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } -func (*ResponseEndBlock) ProtoMessage() {} -func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} } - -func (m *ResponseEndBlock) GetValidatorSetUpdates() []*Validator { - if m != nil { - return m.ValidatorSetUpdates - } - return nil -} - -func (m *ResponseEndBlock) GetConsensusParamUpdates() *ConsensusParams { - if m != nil { - return m.ConsensusParamUpdates - } - return nil -} - // ConsensusParams contains all consensus-relevant parameters // that can be adjusted by the abci app type ConsensusParams struct { @@ -1457,7 +1457,6 @@ func (m *ConsensusParams) GetBlockGossip() *BlockGossip { // BlockSize contain limits on the block size. type BlockSize struct { - // NOTE: must not be 0 nor greater than 100MB MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` MaxTxs int32 `protobuf:"varint,2,opt,name=max_txs,json=maxTxs,proto3" json:"max_txs,omitempty"` MaxGas int64 `protobuf:"varint,3,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` @@ -1755,26 +1754,26 @@ func init() { proto.RegisterType((*RequestFlush)(nil), "types.RequestFlush") proto.RegisterType((*RequestInfo)(nil), "types.RequestInfo") proto.RegisterType((*RequestSetOption)(nil), "types.RequestSetOption") - proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") - proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") - proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") - proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") proto.RegisterType((*RequestInitChain)(nil), "types.RequestInitChain") + proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") proto.RegisterType((*RequestBeginBlock)(nil), "types.RequestBeginBlock") + proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") + proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") proto.RegisterType((*RequestEndBlock)(nil), "types.RequestEndBlock") + proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") proto.RegisterType((*Response)(nil), "types.Response") proto.RegisterType((*ResponseException)(nil), "types.ResponseException") proto.RegisterType((*ResponseEcho)(nil), "types.ResponseEcho") proto.RegisterType((*ResponseFlush)(nil), "types.ResponseFlush") proto.RegisterType((*ResponseInfo)(nil), "types.ResponseInfo") proto.RegisterType((*ResponseSetOption)(nil), "types.ResponseSetOption") - proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") - proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") - proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") - proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") + proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") + proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") + proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") + proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") proto.RegisterType((*BlockSize)(nil), "types.BlockSize") proto.RegisterType((*TxSize)(nil), "types.TxSize") @@ -2193,115 +2192,114 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1754 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6e, 0x23, 0xc7, - 0x11, 0x16, 0xff, 0x39, 0x45, 0xfd, 0x70, 0x5b, 0x5a, 0x2f, 0x97, 0x7b, 0xb0, 0x3c, 0x40, 0x62, - 0xca, 0xf6, 0x8a, 0xb6, 0x8c, 0x0d, 0x56, 0x76, 0x60, 0x44, 0x94, 0xd6, 0x2b, 0xc2, 0xc0, 0x66, - 0x33, 0x52, 0x7c, 0xc8, 0x85, 0x68, 0x72, 0x5a, 0xe4, 0x60, 0xc9, 0x99, 0xf1, 0x4c, 0x53, 0xa6, - 0x16, 0x79, 0x04, 0xdf, 0x73, 0x4e, 0x2e, 0x09, 0xf2, 0x02, 0x39, 0xe6, 0x16, 0xe4, 0x19, 0x72, - 0xf0, 0xb3, 0x04, 0x55, 0xdd, 0xf3, 0xab, 0x19, 0xc3, 0xd8, 0x83, 0x2f, 0x52, 0x77, 0x57, 0x7d, - 0xc5, 0xea, 0x9a, 0xea, 0xaf, 0xaa, 0x1b, 0x1e, 0xc8, 0x3b, 0x5f, 0x84, 0x43, 0xfa, 0x7b, 0xec, - 0x07, 0x9e, 0xf4, 0x58, 0x83, 0x26, 0xfd, 0xa7, 0x73, 0x47, 0x2e, 0xd6, 0xd3, 0xe3, 0x99, 0xb7, - 0x1a, 0xce, 0xbd, 0xb9, 0x37, 0x24, 0xe9, 0x74, 0x7d, 0x43, 0x33, 0x9a, 0xd0, 0x48, 0xa1, 0xcc, - 0xff, 0xd4, 0xa1, 0x65, 0x89, 0xef, 0xd6, 0x22, 0x94, 0x6c, 0x00, 0x75, 0x31, 0x5b, 0x78, 0xbd, - 0xca, 0x61, 0x65, 0xd0, 0x39, 0x61, 0xc7, 0xca, 0xba, 0x96, 0xbe, 0x98, 0x2d, 0xbc, 0xcb, 0x2d, - 0x8b, 0x34, 0xd8, 0xc7, 0xd0, 0xb8, 0x59, 0xae, 0xc3, 0x45, 0xaf, 0x4a, 0xaa, 0xfb, 0x59, 0xd5, - 0xaf, 0x51, 0x74, 0xb9, 0x65, 0x29, 0x1d, 0x34, 0xeb, 0xb8, 0x37, 0x5e, 0xaf, 0x56, 0x64, 0x76, - 0xec, 0xde, 0x90, 0x59, 0xd4, 0x60, 0xcf, 0x01, 0x42, 0x21, 0x27, 0x9e, 0x2f, 0x1d, 0xcf, 0xed, - 0xd5, 0x49, 0xff, 0x51, 0x56, 0xff, 0x4a, 0xc8, 0xdf, 0x93, 0xf8, 0x72, 0xcb, 0x32, 0xc2, 0x68, - 0x82, 0x48, 0x5b, 0x2c, 0x9d, 0x5b, 0x11, 0x4c, 0xe4, 0xa6, 0xd7, 0x28, 0x42, 0x5e, 0x28, 0xf9, - 0xf5, 0x06, 0x91, 0x76, 0x34, 0x61, 0x27, 0xd0, 0x9e, 0x2d, 0xc4, 0xec, 0x0d, 0xe2, 0x9a, 0x84, - 0x7b, 0x98, 0xc5, 0x9d, 0xa3, 0x94, 0x50, 0xad, 0x99, 0x1a, 0xb2, 0x63, 0x68, 0xce, 0xbc, 0xd5, - 0xca, 0x91, 0xbd, 0x16, 0x21, 0x0e, 0x72, 0x08, 0x92, 0x5d, 0x6e, 0x59, 0x5a, 0x0b, 0xc3, 0xf5, - 0xdd, 0x5a, 0x04, 0x77, 0xbd, 0x76, 0x51, 0xb8, 0xfe, 0x80, 0x22, 0x0c, 0x17, 0xe9, 0xe0, 0x56, - 0x1c, 0xd7, 0x91, 0x93, 0xd9, 0x82, 0x3b, 0x6e, 0xcf, 0x28, 0xda, 0xca, 0xd8, 0x75, 0xe4, 0x39, - 0x8a, 0x71, 0x2b, 0x4e, 0x34, 0x61, 0x5f, 0x42, 0x67, 0x2a, 0xe6, 0x8e, 0x3b, 0x99, 0x2e, 0xbd, - 0xd9, 0x9b, 0x1e, 0x10, 0xb4, 0x97, 0x85, 0x8e, 0x50, 0x61, 0x84, 0xf2, 0xcb, 0x2d, 0x0b, 0xa6, - 0xf1, 0x8c, 0x3d, 0x03, 0x43, 0xb8, 0xb6, 0x86, 0x76, 0x08, 0xfa, 0x5e, 0x2e, 0x03, 0x5c, 0x3b, - 0x02, 0xb6, 0x85, 0x1e, 0x8f, 0x5a, 0xd0, 0xb8, 0xe5, 0xcb, 0xb5, 0x30, 0x3f, 0x84, 0x4e, 0x2a, - 0x53, 0x58, 0x0f, 0x5a, 0x2b, 0x11, 0x86, 0x7c, 0x2e, 0x28, 0x9d, 0x0c, 0x2b, 0x9a, 0x9a, 0xbb, - 0xb0, 0x9d, 0xce, 0x93, 0x14, 0x10, 0x73, 0x01, 0x81, 0xb7, 0x22, 0x08, 0x31, 0x01, 0x34, 0x50, - 0x4f, 0xcd, 0x2f, 0xa0, 0x9b, 0x4f, 0x02, 0xd6, 0x85, 0xda, 0x1b, 0x71, 0xa7, 0x35, 0x71, 0xc8, - 0x0e, 0xb4, 0x43, 0x94, 0x9a, 0x86, 0xa5, 0xbd, 0x33, 0x63, 0x6c, 0x9c, 0x06, 0x6c, 0x17, 0xaa, - 0x72, 0x43, 0xd0, 0x6d, 0xab, 0x2a, 0x37, 0xe6, 0x21, 0xec, 0x66, 0x3f, 0xf9, 0x3d, 0x0d, 0x3b, - 0x76, 0x9d, 0xbe, 0x19, 0x63, 0x50, 0xb7, 0xb9, 0xe4, 0x5a, 0x83, 0xc6, 0xb8, 0xe6, 0x73, 0xb9, - 0xd0, 0x3f, 0x4f, 0x63, 0xf6, 0x1e, 0x34, 0x17, 0xc2, 0x99, 0x2f, 0x24, 0x9d, 0x81, 0x9a, 0xa5, - 0x67, 0xe8, 0xab, 0x1f, 0x78, 0xb7, 0x82, 0x52, 0xbd, 0x6d, 0xa9, 0x89, 0xb9, 0x07, 0x3b, 0x99, - 0x44, 0x32, 0x2f, 0x62, 0xe7, 0xe3, 0x0f, 0xcf, 0x3e, 0x05, 0xb8, 0xe5, 0x4b, 0xc7, 0xe6, 0xd2, - 0x0b, 0xc2, 0x5e, 0xe5, 0xb0, 0x36, 0xe8, 0x9c, 0x74, 0xf5, 0xf7, 0xfa, 0x36, 0x12, 0x58, 0x29, - 0x1d, 0xf3, 0xdf, 0x15, 0x78, 0x70, 0x2f, 0x09, 0xd0, 0xdd, 0x05, 0x0f, 0x17, 0xd1, 0x16, 0x70, - 0xcc, 0x7e, 0x85, 0xee, 0x72, 0x5b, 0x04, 0xfa, 0x78, 0xef, 0x68, 0xbb, 0x97, 0xb4, 0x68, 0x69, - 0x21, 0xfb, 0x18, 0x1e, 0xf0, 0x69, 0x28, 0x5c, 0x39, 0x49, 0x79, 0x52, 0x3b, 0xac, 0x0d, 0x1a, - 0x56, 0x57, 0x09, 0x62, 0x47, 0x42, 0x36, 0x82, 0x83, 0xe9, 0xdd, 0x5b, 0xee, 0x4a, 0xc7, 0x15, - 0x69, 0xfd, 0x3a, 0x79, 0xbe, 0xa7, 0x7f, 0xe1, 0xc5, 0xad, 0x63, 0x0b, 0x77, 0x26, 0xac, 0xfd, - 0x58, 0x39, 0xb1, 0x61, 0x1e, 0xc1, 0x5e, 0x2e, 0x15, 0x53, 0x91, 0xad, 0xa4, 0x23, 0x6b, 0xfe, - 0xd0, 0x80, 0xb6, 0x25, 0x42, 0xdf, 0x73, 0x43, 0xc1, 0x9e, 0x83, 0x21, 0x36, 0x33, 0xa1, 0x58, - 0xa5, 0x92, 0x3b, 0x15, 0x4a, 0xe7, 0x45, 0x24, 0xc7, 0x13, 0x15, 0x2b, 0xb3, 0x23, 0xcd, 0x88, - 0x79, 0x9a, 0xd3, 0xa0, 0x34, 0x25, 0x7e, 0x12, 0x51, 0x62, 0x2d, 0x47, 0x09, 0x4a, 0x37, 0xc7, - 0x89, 0x47, 0x9a, 0x13, 0xeb, 0x85, 0x86, 0x33, 0xa4, 0x78, 0x9a, 0x21, 0xc5, 0x46, 0xa1, 0xfb, - 0x25, 0xac, 0x78, 0x9a, 0x61, 0xc5, 0x66, 0x21, 0xb4, 0x84, 0x16, 0x3f, 0x4f, 0xd1, 0x62, 0x2b, - 0xc7, 0x06, 0x0a, 0x58, 0xc0, 0x8b, 0xc3, 0x98, 0x17, 0xdb, 0x39, 0x26, 0xd5, 0x90, 0x3c, 0x31, - 0x7e, 0x12, 0x11, 0xa3, 0x51, 0x18, 0xb4, 0x1c, 0x33, 0x9e, 0x66, 0x98, 0x11, 0x0a, 0xb7, 0x53, - 0x42, 0x8d, 0xbf, 0xcd, 0x52, 0xa3, 0xe2, 0xb7, 0xc7, 0x39, 0x6c, 0x29, 0x37, 0xfe, 0x26, 0xcd, - 0x8d, 0xdb, 0x39, 0x46, 0xd6, 0xb9, 0xf0, 0x93, 0xe4, 0x78, 0x84, 0x47, 0x2f, 0x97, 0x69, 0x78, - 0xfa, 0x45, 0x10, 0x78, 0x81, 0x66, 0x2f, 0x35, 0x31, 0x07, 0xc8, 0x31, 0x49, 0x7e, 0xfd, 0x04, - 0x91, 0x12, 0x4f, 0xa4, 0xb2, 0xcb, 0xfc, 0x4b, 0x25, 0xc1, 0x12, 0x97, 0xa6, 0xf9, 0xc9, 0xd0, - 0xfc, 0x94, 0xe2, 0xd7, 0x6a, 0x86, 0x5f, 0xd9, 0x47, 0xf0, 0x60, 0xc9, 0x43, 0xa9, 0xb6, 0x39, - 0xc9, 0x10, 0xd6, 0x1e, 0x0a, 0xd4, 0xfe, 0x14, 0x73, 0x3d, 0x85, 0xfd, 0x94, 0x2e, 0xf7, 0xfd, - 0x09, 0xb1, 0x48, 0x9d, 0x58, 0xa4, 0x1b, 0x6b, 0x9f, 0xf9, 0xfe, 0x25, 0x0f, 0x17, 0xe6, 0x69, - 0xb2, 0xff, 0x84, 0xbb, 0x19, 0xd4, 0x67, 0x9e, 0xad, 0xb6, 0xb5, 0x63, 0xd1, 0x18, 0xf9, 0x7c, - 0xe9, 0xcd, 0xb5, 0x67, 0x38, 0x34, 0xff, 0x56, 0x49, 0xb0, 0x09, 0x77, 0x17, 0x61, 0x2f, 0xf4, - 0x6e, 0x11, 0xbc, 0x3d, 0xfa, 0xf4, 0xbf, 0x3f, 0xbe, 0xbf, 0xf5, 0xbf, 0x1f, 0xdf, 0x1f, 0xa4, - 0xfa, 0x21, 0x29, 0x5c, 0x5b, 0x04, 0x2b, 0xc7, 0x95, 0xc3, 0xb9, 0xf7, 0xf4, 0x7b, 0x27, 0x10, - 0x43, 0x44, 0x1c, 0x8f, 0xee, 0xa4, 0x08, 0x75, 0x7c, 0xb4, 0x07, 0xb5, 0xd8, 0x03, 0xf6, 0x01, - 0xd4, 0x25, 0x9f, 0x47, 0x54, 0x15, 0x91, 0xe1, 0x37, 0xdf, 0xbe, 0xe6, 0x4e, 0x60, 0x91, 0xc8, - 0xfc, 0x6b, 0x05, 0xa9, 0x29, 0x73, 0x2e, 0x7e, 0x51, 0x17, 0xbb, 0x50, 0x9b, 0xf3, 0x90, 0xc2, - 0x5f, 0xb3, 0x70, 0x88, 0x2b, 0x37, 0x42, 0x10, 0x5d, 0xd4, 0x2c, 0x1c, 0x9a, 0xff, 0xaa, 0x26, - 0xf9, 0x12, 0x97, 0xaf, 0x7b, 0x1e, 0x1e, 0x40, 0xc3, 0x71, 0x6d, 0xb1, 0x21, 0x17, 0x6b, 0x96, - 0x9a, 0xb0, 0x91, 0x2a, 0xb3, 0xb5, 0x77, 0x74, 0x9b, 0x0a, 0xf3, 0xd7, 0x51, 0x61, 0xae, 0xbf, - 0xa3, 0x15, 0x05, 0x47, 0x3b, 0x7e, 0xe0, 0x79, 0x37, 0xb4, 0xb7, 0x77, 0xb2, 0x43, 0xf0, 0x54, - 0xe9, 0x68, 0x66, 0x8a, 0xb2, 0x8e, 0x6e, 0x2b, 0x49, 0xc1, 0x3f, 0x63, 0x63, 0x90, 0x66, 0xb0, - 0x5f, 0xf2, 0xdb, 0x9a, 0xfb, 0x49, 0xfe, 0xc7, 0xe4, 0x66, 0x1e, 0x00, 0xbb, 0xcf, 0x5a, 0xe6, - 0x3f, 0x2a, 0xd8, 0x29, 0x64, 0x09, 0x89, 0x5d, 0xc0, 0xc3, 0xb8, 0xde, 0x4e, 0xb0, 0x92, 0xac, - 0x7d, 0x9b, 0x4b, 0x51, 0xde, 0x34, 0xec, 0xc7, 0xea, 0x57, 0x42, 0xfe, 0x51, 0x29, 0xb3, 0x57, - 0xf0, 0x68, 0x86, 0x66, 0xdd, 0x70, 0x1d, 0x4e, 0x7c, 0x1e, 0xf0, 0x55, 0x6c, 0xa7, 0x9a, 0x29, - 0x0f, 0xe7, 0x91, 0xd6, 0x6b, 0x54, 0x0a, 0xad, 0x87, 0xb3, 0xcc, 0x82, 0xb6, 0x47, 0x27, 0x26, - 0xa7, 0xca, 0x86, 0x00, 0x8a, 0x4f, 0x42, 0xe7, 0xad, 0xd0, 0x85, 0x3a, 0x72, 0x8f, 0xf6, 0x72, - 0xe5, 0xbc, 0x15, 0x96, 0x31, 0x8d, 0x86, 0xec, 0xd7, 0xd0, 0x92, 0x1b, 0xa5, 0x9d, 0xed, 0x54, - 0xae, 0x37, 0xa4, 0xda, 0x94, 0xf4, 0x9f, 0x3d, 0x83, 0x6d, 0x65, 0x78, 0xee, 0x85, 0xa1, 0xe3, - 0xe7, 0x6e, 0x22, 0x64, 0xfa, 0x25, 0x49, 0xac, 0xce, 0x34, 0x99, 0x98, 0x7f, 0x02, 0x23, 0xfe, - 0x59, 0xf6, 0x04, 0x8c, 0x15, 0xdf, 0x4c, 0xa6, 0x77, 0x2a, 0x74, 0x95, 0x41, 0xc3, 0x6a, 0xaf, - 0xf8, 0x86, 0xbe, 0x1d, 0x7b, 0x04, 0x2d, 0x14, 0xca, 0x8d, 0x8a, 0x46, 0xc3, 0x6a, 0xae, 0xf8, - 0xe6, 0x7a, 0x13, 0x0b, 0xf0, 0x70, 0xea, 0xd6, 0x6f, 0xc5, 0x37, 0x2f, 0x79, 0x68, 0x7e, 0x05, - 0x4d, 0xe5, 0xe4, 0xcf, 0x32, 0x8c, 0xf8, 0x6a, 0x06, 0xff, 0x3b, 0xe8, 0xa4, 0xfc, 0x66, 0x9f, - 0xc1, 0x43, 0xb5, 0x43, 0x9f, 0x07, 0x92, 0x22, 0x92, 0x31, 0xc8, 0x48, 0xf8, 0x9a, 0x07, 0x12, - 0x7f, 0x92, 0x4c, 0x9b, 0x7f, 0xaf, 0x42, 0x53, 0x75, 0x74, 0xec, 0x31, 0x16, 0x7b, 0xee, 0xb8, - 0x13, 0xc7, 0x8e, 0x8a, 0x0c, 0xcd, 0xc7, 0x76, 0xea, 0x94, 0x54, 0x33, 0xa7, 0x84, 0x41, 0x5d, - 0x3a, 0x2b, 0xa1, 0x77, 0x45, 0x63, 0x74, 0xd6, 0x5d, 0xaf, 0x28, 0x0a, 0x75, 0x15, 0x05, 0x77, - 0xbd, 0xc2, 0x28, 0x9c, 0xc0, 0x4e, 0xaa, 0x5a, 0x38, 0xb6, 0xee, 0x62, 0x76, 0xd3, 0x1f, 0x60, - 0x7c, 0x61, 0x75, 0xe2, 0xba, 0x31, 0xb6, 0xd9, 0x00, 0xa8, 0x8c, 0x4c, 0x54, 0xa7, 0xa0, 0xca, - 0x4b, 0x93, 0xca, 0xcb, 0x2e, 0xae, 0xeb, 0x56, 0x02, 0xdb, 0xd5, 0x27, 0x60, 0xe0, 0xd1, 0x51, - 0x2a, 0x2d, 0x52, 0x69, 0xe3, 0x02, 0x09, 0x3f, 0x84, 0xbd, 0xa4, 0xdb, 0x54, 0x2a, 0x6d, 0x65, - 0x25, 0x59, 0x26, 0xc5, 0xc7, 0xd0, 0x8e, 0xcb, 0x98, 0x41, 0x1a, 0x2d, 0xae, 0xab, 0xd7, 0x18, - 0x5a, 0xda, 0xc5, 0xc2, 0x76, 0xf9, 0x23, 0x68, 0x60, 0xd4, 0xa3, 0x83, 0x10, 0x35, 0x31, 0x14, - 0x6d, 0x21, 0x75, 0xd3, 0xac, 0x54, 0xcc, 0x53, 0xd8, 0xc9, 0xac, 0x23, 0xdf, 0x4a, 0x4f, 0xf2, - 0xa5, 0xfe, 0x50, 0x6a, 0x12, 0xff, 0x4c, 0x35, 0xf9, 0x19, 0xf3, 0x0b, 0x30, 0xe2, 0x33, 0x8a, - 0xa1, 0xf6, 0xd7, 0xd3, 0x49, 0x74, 0xf7, 0xd9, 0xb6, 0x9a, 0xfe, 0x7a, 0xfa, 0x8d, 0xba, 0xfe, - 0xf8, 0xde, 0xf7, 0xba, 0x75, 0xaf, 0x59, 0x6a, 0x62, 0x7e, 0x09, 0xed, 0xa8, 0xb5, 0x2e, 0x87, - 0x96, 0x7c, 0x6a, 0xf3, 0x9f, 0x15, 0x68, 0xaa, 0x6a, 0x57, 0x70, 0xdd, 0xfa, 0x8c, 0xee, 0x21, - 0x6b, 0x31, 0xc1, 0x4d, 0x13, 0x70, 0x37, 0x3e, 0x58, 0x0a, 0x74, 0x7c, 0x7d, 0xe7, 0x0b, 0xcb, - 0x20, 0x2d, 0x1c, 0xb2, 0x0f, 0x60, 0x5b, 0x41, 0x42, 0x19, 0x38, 0x6e, 0xc4, 0x75, 0x1d, 0x5a, - 0xbb, 0xa2, 0x25, 0xfc, 0xa4, 0x4a, 0xc5, 0x71, 0xa5, 0xae, 0x6a, 0x6d, 0x5a, 0x18, 0xbb, 0xd2, - 0x7c, 0x02, 0x75, 0xb2, 0x03, 0xd0, 0xbc, 0xba, 0xb6, 0xc6, 0xaf, 0x5e, 0x76, 0xb7, 0x58, 0x0b, - 0x6a, 0xe3, 0x57, 0xd7, 0xdd, 0xca, 0xc9, 0x0f, 0x0d, 0xd8, 0x3b, 0x1b, 0x9d, 0x8f, 0xcf, 0x7c, - 0x7f, 0xe9, 0xcc, 0x38, 0x35, 0x1a, 0x43, 0xa8, 0x53, 0x2b, 0x55, 0xf0, 0xa2, 0xd1, 0x2f, 0xea, - 0xe9, 0xd9, 0x09, 0x34, 0xa8, 0xa3, 0x62, 0x45, 0x0f, 0x1b, 0xfd, 0xc2, 0xd6, 0x1e, 0x7f, 0x44, - 0xf5, 0x5c, 0xf7, 0xdf, 0x37, 0xfa, 0x45, 0xfd, 0x3d, 0xfb, 0x0a, 0x8c, 0xa4, 0x17, 0x2a, 0x7b, - 0xe5, 0xe8, 0x97, 0x76, 0xfa, 0x88, 0x4f, 0xfa, 0xa1, 0xb2, 0xb7, 0x8e, 0x7e, 0x69, 0xbb, 0xcf, - 0x9e, 0x43, 0x2b, 0x6a, 0x55, 0x8a, 0x5f, 0x3c, 0xfa, 0x25, 0x1d, 0x3f, 0x86, 0x47, 0x35, 0x10, - 0x45, 0x0f, 0x19, 0xfd, 0xc2, 0x26, 0x9e, 0x3d, 0x83, 0xa6, 0xae, 0x9d, 0x85, 0x8f, 0x25, 0xfd, - 0xe2, 0xab, 0x02, 0x6e, 0x32, 0xb9, 0xf3, 0x96, 0xbd, 0x82, 0xf4, 0x4b, 0x2f, 0x01, 0xec, 0x0c, - 0x20, 0x75, 0xd9, 0x2d, 0x7d, 0x0b, 0xe9, 0x97, 0x5f, 0x05, 0x18, 0x9e, 0x9d, 0xf8, 0xba, 0x59, - 0xfc, 0x22, 0xd2, 0x2f, 0xbb, 0x0d, 0x4c, 0x9b, 0xf4, 0xca, 0xf6, 0xf9, 0xff, 0x03, 0x00, 0x00, - 0xff, 0xff, 0x3a, 0x99, 0xe6, 0x77, 0xb0, 0x13, 0x00, 0x00, + // 1741 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x72, 0x1b, 0xc7, + 0x11, 0x26, 0xfe, 0xb1, 0x0d, 0xfe, 0x80, 0x43, 0x4a, 0x82, 0xa0, 0x83, 0xe9, 0xad, 0x4a, 0x0c, + 0xd9, 0x16, 0x69, 0xd3, 0xa5, 0x94, 0x68, 0x27, 0xae, 0x88, 0x92, 0x2c, 0xa2, 0x5c, 0xa5, 0x28, + 0x23, 0xc6, 0x87, 0x5c, 0x50, 0x03, 0xec, 0x10, 0xd8, 0x12, 0xb0, 0xbb, 0xde, 0x1d, 0xd0, 0xa0, + 0x2a, 0x8f, 0xe0, 0x7b, 0xce, 0xc9, 0x25, 0x55, 0x79, 0x81, 0x1c, 0x73, 0x4b, 0xe5, 0x19, 0x72, + 0xf0, 0xb3, 0xa4, 0xba, 0x67, 0xf6, 0x97, 0xbb, 0xa9, 0x94, 0x0e, 0xbe, 0x00, 0x33, 0xd3, 0x3f, + 0xd3, 0xdd, 0xdb, 0xf3, 0x75, 0xcf, 0xc0, 0xbe, 0xba, 0x09, 0x64, 0x74, 0x42, 0xbf, 0xc7, 0x41, + 0xe8, 0x2b, 0x9f, 0xb5, 0x68, 0x32, 0x7c, 0x34, 0x77, 0xd5, 0x62, 0x3d, 0x3d, 0x9e, 0xf9, 0xab, + 0x93, 0xb9, 0x3f, 0xf7, 0x4f, 0x88, 0x3a, 0x5d, 0x5f, 0xd1, 0x8c, 0x26, 0x34, 0xd2, 0x52, 0xf6, + 0xbf, 0x9a, 0xd0, 0xe1, 0xf2, 0xfb, 0xb5, 0x8c, 0x14, 0x1b, 0x41, 0x53, 0xce, 0x16, 0xfe, 0xa0, + 0x7e, 0x54, 0x1b, 0xf5, 0x4e, 0xd9, 0xb1, 0xd6, 0x6e, 0xa8, 0x2f, 0x66, 0x0b, 0xff, 0x62, 0x8b, + 0x13, 0x07, 0xfb, 0x04, 0x5a, 0x57, 0xcb, 0x75, 0xb4, 0x18, 0x34, 0x88, 0xf5, 0x20, 0xcf, 0xfa, + 0x0d, 0x92, 0x2e, 0xb6, 0xb8, 0xe6, 0x41, 0xb5, 0xae, 0x77, 0xe5, 0x0f, 0x9a, 0x65, 0x6a, 0xc7, + 0xde, 0x15, 0xa9, 0x45, 0x0e, 0xf6, 0x04, 0x20, 0x92, 0x6a, 0xe2, 0x07, 0xca, 0xf5, 0xbd, 0x41, + 0x8b, 0xf8, 0xef, 0xe5, 0xf9, 0xdf, 0x48, 0xf5, 0x3b, 0x22, 0x5f, 0x6c, 0x71, 0x2b, 0x8a, 0x27, + 0x28, 0xe9, 0x7a, 0xae, 0x9a, 0xcc, 0x16, 0xc2, 0xf5, 0x06, 0xed, 0x32, 0xc9, 0xb1, 0xe7, 0xaa, + 0x67, 0x48, 0x46, 0x49, 0x37, 0x9e, 0xa0, 0x2b, 0xdf, 0xaf, 0x65, 0x78, 0x33, 0xe8, 0x94, 0xb9, + 0xf2, 0x7b, 0x24, 0xa1, 0x2b, 0xc4, 0xc3, 0xbe, 0x82, 0xde, 0x54, 0xce, 0x5d, 0x6f, 0x32, 0x5d, + 0xfa, 0xb3, 0xb7, 0x83, 0x2e, 0x89, 0x0c, 0xf2, 0x22, 0xe7, 0xc8, 0x70, 0x8e, 0xf4, 0x8b, 0x2d, + 0x0e, 0xd3, 0x64, 0xc6, 0x4e, 0xa1, 0x3b, 0x5b, 0xc8, 0xd9, 0xdb, 0x89, 0xda, 0x0c, 0x2c, 0x92, + 0xbc, 0x93, 0x97, 0x7c, 0x86, 0xd4, 0xcb, 0xcd, 0xc5, 0x16, 0xef, 0xcc, 0xf4, 0x10, 0xfd, 0x72, + 0xe4, 0xd2, 0xbd, 0x96, 0x21, 0x4a, 0x1d, 0x94, 0xf9, 0xf5, 0x5c, 0xd3, 0x49, 0xce, 0x72, 0xe2, + 0x09, 0x7b, 0x0c, 0x96, 0xf4, 0x1c, 0x63, 0x68, 0x8f, 0x04, 0xef, 0x16, 0xbe, 0xa8, 0xe7, 0xc4, + 0x66, 0x76, 0xa5, 0x19, 0xb3, 0x63, 0x68, 0xcf, 0xfc, 0xd5, 0xca, 0x55, 0x83, 0x6d, 0x92, 0x39, + 0x2c, 0x98, 0x48, 0xb4, 0x8b, 0x2d, 0x6e, 0xb8, 0xce, 0x3b, 0xd0, 0xba, 0x16, 0xcb, 0xb5, 0xb4, + 0x3f, 0x82, 0x5e, 0x26, 0x53, 0xd8, 0x00, 0x3a, 0x2b, 0x19, 0x45, 0x62, 0x2e, 0x07, 0xb5, 0xa3, + 0xda, 0xc8, 0xe2, 0xf1, 0xd4, 0xde, 0x85, 0xed, 0x6c, 0x9e, 0x64, 0x04, 0x31, 0x17, 0x50, 0xf0, + 0x5a, 0x86, 0x11, 0x26, 0x80, 0x11, 0x34, 0x53, 0xfb, 0x4b, 0xe8, 0x17, 0x93, 0x80, 0xf5, 0xa1, + 0xf1, 0x56, 0xde, 0x18, 0x4e, 0x1c, 0xb2, 0x43, 0x63, 0x10, 0x65, 0xb1, 0xc5, 0x8d, 0x75, 0xcf, + 0x13, 0xd9, 0x24, 0x0d, 0xd8, 0x67, 0x00, 0xd7, 0x62, 0xe9, 0x3a, 0x42, 0xf9, 0x61, 0x34, 0xa8, + 0x1d, 0x35, 0x46, 0xbd, 0xd3, 0xbe, 0x71, 0xf7, 0xbb, 0x98, 0xc0, 0x33, 0x3c, 0xb6, 0x93, 0x98, + 0x4e, 0x79, 0xc1, 0x18, 0x34, 0x1d, 0xa1, 0x04, 0x6d, 0xbf, 0xcd, 0x69, 0x8c, 0x6b, 0x81, 0x50, + 0x0b, 0xb3, 0x3d, 0x8d, 0xd9, 0x5d, 0x68, 0x2f, 0xa4, 0x3b, 0x5f, 0x28, 0x3a, 0x2f, 0x0d, 0x6e, + 0x66, 0x68, 0x6b, 0x10, 0xfa, 0xd7, 0x92, 0x8e, 0x46, 0x97, 0xeb, 0x89, 0xfd, 0xcf, 0x1a, 0xec, + 0xdf, 0xca, 0x25, 0xd4, 0xbb, 0x10, 0xd1, 0x22, 0xde, 0x0b, 0xc7, 0xec, 0x17, 0xa8, 0x57, 0x38, + 0x32, 0x34, 0x47, 0x76, 0xc7, 0x58, 0x7f, 0x41, 0x8b, 0xdc, 0x10, 0xd9, 0x27, 0xb0, 0x2f, 0xa6, + 0x91, 0xf4, 0xd4, 0x24, 0xe3, 0x6f, 0xe3, 0xa8, 0x31, 0x6a, 0xf1, 0xbe, 0x26, 0x24, 0xee, 0x46, + 0xec, 0x1c, 0x0e, 0xa7, 0x37, 0xef, 0x84, 0xa7, 0x5c, 0x4f, 0x66, 0xf9, 0x9b, 0x14, 0x9f, 0x3d, + 0xb3, 0xc3, 0x8b, 0x6b, 0xd7, 0x91, 0xde, 0x4c, 0xf2, 0x83, 0x84, 0x39, 0xd5, 0x61, 0x1f, 0xc1, + 0x6e, 0x3e, 0xa5, 0xd9, 0x2e, 0xd4, 0xd5, 0xc6, 0xd8, 0x5e, 0x57, 0x1b, 0xdb, 0x4e, 0xbe, 0x47, + 0x92, 0xbe, 0xb7, 0x78, 0x1e, 0xc2, 0x5e, 0x21, 0x53, 0x33, 0x81, 0xac, 0x65, 0x03, 0x69, 0xef, + 0xc1, 0x4e, 0x2e, 0x41, 0xed, 0x1f, 0x5b, 0xd0, 0xe5, 0x32, 0x0a, 0x7c, 0x2f, 0x92, 0xec, 0x09, + 0x58, 0x72, 0x33, 0x93, 0x1a, 0x55, 0x6a, 0x85, 0x33, 0xab, 0x79, 0x5e, 0xc4, 0x74, 0x3c, 0x44, + 0x09, 0x33, 0x7b, 0x98, 0x43, 0xc4, 0x83, 0xa2, 0x50, 0x16, 0x12, 0x3f, 0xcd, 0x43, 0xe2, 0x61, + 0x81, 0xb7, 0x80, 0x89, 0x0f, 0x73, 0x98, 0x58, 0x54, 0x9c, 0x03, 0xc5, 0xb3, 0x12, 0x50, 0x2c, + 0x9a, 0x5f, 0x81, 0x8a, 0x67, 0x25, 0xa8, 0x38, 0xb8, 0xb5, 0x57, 0x29, 0x2c, 0x7e, 0x9a, 0x87, + 0xc5, 0xa2, 0x3b, 0x05, 0x5c, 0xfc, 0x75, 0x19, 0x2e, 0xde, 0x2f, 0xc8, 0x54, 0x02, 0xe3, 0x17, + 0xb7, 0x80, 0xf1, 0x6e, 0x41, 0xb4, 0x04, 0x19, 0xcf, 0x72, 0xc8, 0x08, 0xa5, 0xbe, 0x55, 0x40, + 0xe3, 0xaf, 0x6e, 0x43, 0xe3, 0xbd, 0xe2, 0xa7, 0x2d, 0xc3, 0xc6, 0x93, 0x02, 0x36, 0xde, 0x29, + 0x5a, 0x59, 0x09, 0x8e, 0x0f, 0xf1, 0x44, 0x17, 0x32, 0x0d, 0x4f, 0xbf, 0x0c, 0x43, 0x3f, 0x34, + 0xe8, 0xa5, 0x27, 0xf6, 0x08, 0x31, 0x26, 0xcd, 0xaf, 0xff, 0x01, 0xa4, 0x94, 0xf4, 0x99, 0xec, + 0xb2, 0xff, 0x5c, 0x4b, 0x65, 0x09, 0x4b, 0xb3, 0xf8, 0x64, 0x19, 0x7c, 0xca, 0xe0, 0x6b, 0x3d, + 0x87, 0xaf, 0xec, 0x63, 0xd8, 0x5f, 0x8a, 0x48, 0xe9, 0xb8, 0x4c, 0x72, 0x80, 0xb5, 0x87, 0x04, + 0x1d, 0x10, 0x8d, 0x5c, 0x8f, 0xe0, 0x20, 0xc3, 0x2b, 0x82, 0x60, 0x42, 0xe0, 0xd4, 0xa4, 0xc3, + 0xdb, 0x4f, 0xb8, 0x9f, 0x06, 0xc1, 0x85, 0x88, 0x16, 0xf6, 0x59, 0xea, 0x7f, 0x8a, 0xdd, 0x0c, + 0x9a, 0x33, 0xdf, 0xd1, 0x6e, 0xed, 0x70, 0x1a, 0x23, 0x9e, 0x2f, 0xfd, 0xb9, 0xb1, 0x0c, 0x87, + 0xf6, 0x41, 0x2a, 0x9a, 0xa4, 0xaa, 0xfd, 0x8f, 0x7a, 0xea, 0x7b, 0x02, 0xc5, 0xb7, 0x94, 0x1d, + 0x42, 0xcb, 0xf5, 0x1c, 0xb9, 0x21, 0x75, 0x0d, 0xae, 0x27, 0xec, 0x5c, 0x97, 0x0c, 0x74, 0x6c, + 0xfb, 0xfc, 0xb3, 0x7f, 0xff, 0xf4, 0xc1, 0xd6, 0x7f, 0x7e, 0xfa, 0x60, 0x94, 0xe9, 0x9a, 0x94, + 0xf4, 0x1c, 0x19, 0xae, 0x5c, 0x4f, 0x9d, 0xcc, 0xfd, 0x47, 0x3f, 0xb8, 0xa1, 0x3c, 0xc1, 0xc8, + 0x1d, 0x9f, 0xdf, 0x28, 0x19, 0xe9, 0x22, 0xf3, 0x4d, 0x5c, 0x64, 0x9a, 0xef, 0xa9, 0x45, 0x8b, + 0xa3, 0x9e, 0x20, 0xf4, 0xfd, 0x2b, 0x3a, 0xd6, 0xef, 0xa5, 0x87, 0xc4, 0x33, 0xb8, 0xd8, 0xce, + 0x15, 0x18, 0x13, 0xce, 0x4e, 0x1a, 0xce, 0x43, 0x60, 0xb7, 0xcf, 0xa3, 0xfd, 0x97, 0x1a, 0x62, + 0x6d, 0xee, 0xac, 0x95, 0x46, 0xf4, 0xb9, 0x49, 0xa8, 0xfa, 0x7b, 0x9a, 0xab, 0x53, 0xd0, 0x58, + 0xd5, 0x48, 0xac, 0xc2, 0x95, 0xb9, 0x88, 0x28, 0x9a, 0x0d, 0x8e, 0x43, 0x5c, 0xb9, 0x92, 0x92, + 0xe2, 0xd2, 0xe0, 0x38, 0xb4, 0xff, 0x5a, 0x4b, 0x33, 0x21, 0x2d, 0x1a, 0x3f, 0xa7, 0x95, 0x1f, + 0x42, 0x53, 0x89, 0x79, 0x5c, 0x0a, 0xe3, 0x62, 0xfb, 0xed, 0x77, 0xaf, 0x85, 0x1b, 0x72, 0x22, + 0x61, 0x20, 0xfb, 0x45, 0x0c, 0x61, 0xbf, 0x81, 0xfd, 0xa4, 0x90, 0x4e, 0xd6, 0x81, 0x23, 0x94, + 0xac, 0xee, 0x37, 0xfa, 0x09, 0xeb, 0x1f, 0x34, 0x27, 0x7b, 0x05, 0xf7, 0x66, 0xa8, 0xcf, 0x8b, + 0xd6, 0xd1, 0x24, 0x10, 0xa1, 0x58, 0x25, 0x4a, 0xea, 0x39, 0xb4, 0x7c, 0x16, 0x73, 0xbd, 0x46, + 0xa6, 0x88, 0xdf, 0x99, 0xe5, 0x16, 0x8c, 0x3e, 0xfb, 0x4f, 0x58, 0x9d, 0xb3, 0x88, 0xf5, 0x73, + 0x06, 0x91, 0x52, 0xad, 0x60, 0x28, 0x3b, 0x01, 0xd0, 0x40, 0x12, 0xb9, 0xef, 0xa4, 0xa9, 0xd0, + 0x71, 0x64, 0x28, 0x84, 0x6f, 0xdc, 0x77, 0x92, 0x5b, 0xd3, 0x78, 0xc8, 0x7e, 0x09, 0x1d, 0xb5, + 0xd1, 0xdc, 0xf9, 0xce, 0xe7, 0x72, 0x43, 0xac, 0x6d, 0x45, 0xff, 0xec, 0x31, 0x6c, 0x6b, 0xc5, + 0x73, 0x3f, 0x8a, 0xdc, 0xc0, 0xd4, 0x66, 0x96, 0x55, 0xfd, 0x92, 0x28, 0xbc, 0x37, 0x4d, 0x27, + 0xf6, 0x1f, 0xc1, 0x4a, 0xb6, 0x65, 0x0f, 0xc0, 0x5a, 0x89, 0xcd, 0x64, 0x7a, 0xa3, 0xbf, 0x5a, + 0x6d, 0xd4, 0xe2, 0xdd, 0x95, 0xd8, 0x90, 0x97, 0xec, 0x1e, 0x74, 0x90, 0xa8, 0x36, 0xfa, 0x5b, + 0xb4, 0x78, 0x7b, 0x25, 0x36, 0x97, 0x9b, 0x84, 0x80, 0x59, 0x6d, 0x7a, 0xbe, 0x95, 0xd8, 0xbc, + 0x14, 0x91, 0xfd, 0x35, 0xb4, 0xb5, 0x91, 0xff, 0x97, 0x62, 0x94, 0xaf, 0xe7, 0xe4, 0x7f, 0x0b, + 0xbd, 0x8c, 0xdd, 0xec, 0x73, 0xb8, 0xa3, 0x3d, 0x0c, 0x44, 0xa8, 0x28, 0x22, 0x39, 0x85, 0x8c, + 0x88, 0xaf, 0x45, 0xa8, 0x70, 0x4b, 0x52, 0x6d, 0xff, 0xad, 0x0e, 0x6d, 0xdd, 0x21, 0xb2, 0xfb, + 0x58, 0x79, 0x85, 0xeb, 0x4d, 0x5c, 0x27, 0xae, 0x2e, 0x34, 0x1f, 0x3b, 0x19, 0x48, 0xa9, 0xe7, + 0x20, 0x85, 0x41, 0x53, 0xb9, 0x2b, 0x69, 0xbc, 0xa2, 0x31, 0x1a, 0xeb, 0xad, 0x57, 0x14, 0x85, + 0xa6, 0x8e, 0x82, 0xb7, 0x5e, 0x61, 0x14, 0x4e, 0x61, 0x27, 0x53, 0x26, 0x5c, 0xc7, 0xb4, 0x2f, + 0xbb, 0xd9, 0x0f, 0x30, 0x7e, 0xce, 0x7b, 0x49, 0xc1, 0x18, 0x3b, 0x6c, 0x04, 0x54, 0x3f, 0x26, + 0xba, 0x86, 0xea, 0xba, 0xd2, 0xa6, 0xba, 0xb2, 0x8b, 0xeb, 0xa6, 0xc8, 0x62, 0xfb, 0xfb, 0x00, + 0x2c, 0x4c, 0x32, 0xcd, 0xd2, 0x21, 0x96, 0x2e, 0x2e, 0x10, 0xf1, 0x23, 0xd8, 0x4b, 0xbb, 0x57, + 0xcd, 0xd2, 0xd5, 0x5a, 0xd2, 0x65, 0x62, 0xbc, 0x0f, 0xdd, 0xa4, 0x7e, 0x59, 0xc4, 0xd1, 0x11, + 0xa6, 0x6c, 0x8d, 0xa1, 0x63, 0x4c, 0x2c, 0x6d, 0xbf, 0x3f, 0x86, 0x16, 0x46, 0x3d, 0x3e, 0x86, + 0x71, 0x8f, 0x44, 0xd1, 0x96, 0xca, 0x34, 0xe1, 0x9a, 0xc5, 0x3e, 0x83, 0x9d, 0xdc, 0x3a, 0x16, + 0x27, 0xe5, 0x2b, 0xb1, 0x34, 0x1f, 0x4a, 0x4f, 0x92, 0x6d, 0xea, 0xe9, 0x36, 0xf6, 0x97, 0x60, + 0x25, 0xf0, 0x80, 0xa1, 0x0e, 0xd6, 0xd3, 0x49, 0x7c, 0xe9, 0xd9, 0xe6, 0xed, 0x60, 0x3d, 0xfd, + 0x56, 0xdf, 0x7b, 0x02, 0xff, 0x07, 0x73, 0x15, 0x68, 0x70, 0x3d, 0xb1, 0xbf, 0x82, 0x6e, 0xdc, + 0xaa, 0x57, 0x8b, 0x56, 0x7c, 0x6a, 0xfb, 0xef, 0x35, 0x68, 0x6b, 0x74, 0x2b, 0xb9, 0x67, 0x7d, + 0x4e, 0xb7, 0xa7, 0xb5, 0x9c, 0xa0, 0xd3, 0x24, 0xb8, 0x9b, 0x1c, 0x2c, 0x2d, 0x74, 0x7c, 0x79, + 0x13, 0x48, 0x6e, 0x11, 0x17, 0x0e, 0xd9, 0x87, 0xb0, 0xad, 0x45, 0x22, 0x15, 0xba, 0x5e, 0x8c, + 0x0a, 0x3d, 0x5a, 0x7b, 0x43, 0x4b, 0xf8, 0x49, 0x35, 0x8b, 0xeb, 0x29, 0x53, 0x0e, 0xba, 0xb4, + 0x30, 0xf6, 0x94, 0xfd, 0x00, 0x9a, 0xa4, 0x07, 0xa0, 0xfd, 0xe6, 0x92, 0x8f, 0x5f, 0xbd, 0xec, + 0x6f, 0xb1, 0x0e, 0x34, 0xc6, 0xaf, 0x2e, 0xfb, 0xb5, 0xd3, 0x1f, 0x5b, 0xb0, 0xf7, 0xf4, 0xfc, + 0xd9, 0xf8, 0x69, 0x10, 0x2c, 0xdd, 0x99, 0xa0, 0x0e, 0xe3, 0x04, 0x9a, 0xd4, 0x43, 0x95, 0x3c, + 0x65, 0x0c, 0xcb, 0x9a, 0x79, 0x76, 0x0a, 0x2d, 0x6a, 0xa5, 0x58, 0xd9, 0x8b, 0xc6, 0xb0, 0xb4, + 0xa7, 0xc7, 0x4d, 0x74, 0xb3, 0x75, 0xfb, 0x61, 0x63, 0x58, 0xd6, 0xd8, 0xb3, 0xaf, 0xc1, 0x4a, + 0x9b, 0xa0, 0xaa, 0xe7, 0x8d, 0x61, 0x65, 0x8b, 0x8f, 0xf2, 0x69, 0xfd, 0xab, 0x7a, 0x0c, 0x18, + 0x56, 0xf6, 0xc2, 0xec, 0x09, 0x74, 0xe2, 0x1a, 0x5f, 0xfe, 0x00, 0x31, 0xac, 0x68, 0xbf, 0x31, + 0x3c, 0xba, 0xdb, 0x2a, 0x7b, 0x25, 0x19, 0x96, 0xde, 0x11, 0xd8, 0x63, 0x68, 0x9b, 0x2a, 0x53, + 0xfa, 0x94, 0x30, 0x2c, 0x6f, 0xa2, 0xd1, 0xc9, 0xf4, 0xa6, 0x5e, 0xf5, 0x92, 0x33, 0xac, 0xbc, + 0xcc, 0xb0, 0xa7, 0x00, 0x99, 0xcb, 0x73, 0xe5, 0x13, 0xcd, 0xb0, 0xfa, 0x92, 0xc2, 0xf0, 0xec, + 0x24, 0x17, 0xcf, 0xf2, 0xa7, 0x93, 0x61, 0xd5, 0xbd, 0x61, 0xda, 0xa6, 0xe7, 0xb5, 0x2f, 0xfe, + 0x1b, 0x00, 0x00, 0xff, 0xff, 0x4e, 0x51, 0x0d, 0xe3, 0xa9, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index 99d2ef64..74249c09 100644 --- a/types/types.proto +++ b/types/types.proto @@ -10,18 +10,18 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto"; // Request types message Request { - oneof value{ - RequestEcho echo = 1; - RequestFlush flush = 2; - RequestInfo info = 3; - RequestSetOption set_option = 4; - RequestDeliverTx deliver_tx = 5; - RequestCheckTx check_tx = 6; - RequestCommit commit = 7; - RequestQuery query = 8; - RequestInitChain init_chain = 9; - RequestBeginBlock begin_block = 10; + oneof value { + RequestEcho echo = 2; + RequestFlush flush = 3; + RequestInfo info = 4; + RequestSetOption set_option = 5; + RequestInitChain init_chain = 6; + RequestQuery query = 7; + RequestBeginBlock begin_block = 8; + RequestCheckTx check_tx = 9; + RequestDeliverTx deliver_tx = 19; RequestEndBlock end_block = 11; + RequestCommit commit = 12; } } @@ -36,17 +36,13 @@ message RequestInfo { string version = 1; } -message RequestSetOption{ +message RequestSetOption { string key = 1; string value = 2; } -message RequestDeliverTx{ - bytes tx = 1; -} - -message RequestCheckTx{ - bytes tx = 1; +message RequestInitChain { + repeated Validator validators = 1; } message RequestQuery{ @@ -56,46 +52,49 @@ message RequestQuery{ bool prove = 4; } -message RequestCommit{ -} - -message RequestInitChain{ - repeated Validator validators = 1; -} - -message RequestBeginBlock{ +message RequestBeginBlock { bytes hash = 1; Header header = 2; repeated int32 absent_validators = 3; repeated Evidence byzantine_validators = 4; } +message RequestCheckTx { + bytes tx = 1; +} + +message RequestDeliverTx { + bytes tx = 1; +} + message RequestEndBlock{ int64 height = 1; } +message RequestCommit { +} + //---------------------------------------- // Response types - message Response { - oneof value{ + oneof value { ResponseException exception = 1; ResponseEcho echo = 2; ResponseFlush flush = 3; ResponseInfo info = 4; ResponseSetOption set_option = 5; - ResponseDeliverTx deliver_tx = 6; - ResponseCheckTx check_tx = 7; - ResponseCommit commit = 8; - ResponseQuery query = 9; - ResponseInitChain init_chain = 10; - ResponseBeginBlock begin_block = 11; - ResponseEndBlock end_block = 12; + ResponseInitChain init_chain = 6; + ResponseQuery query = 7; + ResponseBeginBlock begin_block = 8; + ResponseCheckTx check_tx = 9; + ResponseDeliverTx deliver_tx = 10; + ResponseEndBlock end_block = 11; + ResponseCommit commit = 12; } } -message ResponseException{ +message ResponseException { string error = 1; } @@ -103,7 +102,7 @@ message ResponseEcho { string message = 1; } -message ResponseFlush{ +message ResponseFlush { } message ResponseInfo { @@ -113,81 +112,82 @@ message ResponseInfo { bytes last_block_app_hash = 4; } -message ResponseSetOption{ +message ResponseSetOption { uint32 code = 1; string log = 2; } -message ResponseDeliverTx{ - uint32 code = 1; - bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - string log = 3; +message ResponseInitChain { +} + +message ResponseQuery { + uint32 code = 1; + int64 index = 2; + bytes key = 3 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + bytes value = 4 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + bytes proof = 5 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + int64 height = 6; + string log = 7; +} + +message ResponseBeginBlock { +} + +message ResponseCheckTx { + uint32 code = 1; + bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + string log = 3; + int64 gas = 4; + int64 fee = 5; +} + +message ResponseDeliverTx { + uint32 code = 1; + bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + string log = 3; repeated KVPair tags = 4; } -message ResponseCheckTx{ - uint32 code = 1; - bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - string log = 3; - int64 gas = 4; - int64 fee = 5; -} - -message ResponseQuery{ - uint32 code = 1; - int64 index = 2; - bytes key = 3 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - bytes value = 4 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - bytes proof = 5 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - int64 height = 6; - string log = 7; -} - -message ResponseCommit{ - uint32 code = 1; - bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; - string log = 3; -} - - -message ResponseInitChain{ -} - -message ResponseBeginBlock{ -} - -message ResponseEndBlock{ - repeated Validator validator_set_updates = 1; +message ResponseEndBlock { + repeated Validator validator_updates = 1; ConsensusParams consensus_param_updates = 2; } +message ResponseCommit { + uint32 code = 1; + bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; + string log = 3; +} + +//---------------------------------------- +// Misc. + // ConsensusParams contains all consensus-relevant parameters // that can be adjusted by the abci app -message ConsensusParams{ - BlockSize block_size = 1; - TxSize tx_size = 2; - BlockGossip block_gossip = 3; +message ConsensusParams { + BlockSize block_size = 1; + TxSize tx_size = 2; + BlockGossip block_gossip = 3; } // BlockSize contain limits on the block size. -message BlockSize{ - // NOTE: must not be 0 nor greater than 100MB - int32 max_bytes = 1; - int32 max_txs = 2; - int64 max_gas = 3; +message BlockSize { + int32 max_bytes = 1; + int32 max_txs = 2; + int64 max_gas = 3; } // TxSize contain limits on the tx size. message TxSize{ - int32 max_bytes = 1; - int64 max_gas = 2; + int32 max_bytes = 1; + int64 max_gas = 2; } // BlockGossip determine consensus critical // elements of how blocks are gossiped message BlockGossip{ - // Note: must not be 0 - int32 block_part_size_bytes = 1; + // Note: must not be 0 + int32 block_part_size_bytes = 1; } //---------------------------------------- From 3798f9fa8e65f2c2410f7deef7089f50dfa5b4ef Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 20 Dec 2017 00:07:58 -0800 Subject: [PATCH 414/545] Reorder README --- README.md | 115 +++++++++++++++++++++++----------------------- types/types.proto | 1 - 2 files changed, 57 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 546342fc..dbfd8634 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ See [the documentation](http://tendermint.readthedocs.io/en/master/) for more de Multiple example apps are included: - the `abci-cli counter` application, which illustrates nonce checking in txs -- the `abci-cli dummy` application, which illustrates a simple key-value merkle tree +- the `abci-cli dummy` application, which illustrates a simple key-value Merkle tree - the `abci-cli dummy --persistent` application, which augments the dummy with persistence and validator set changes ### Install @@ -91,59 +91,17 @@ ABCI requests/responses are defined as simple Protobuf messages in [this schema TendermintCore sends the requests, and the ABCI application sends the responses. Here, we describe the requests and responses as function arguments and return values, and make some notes about usage: -#### DeliverTx +#### Echo * __Arguments__: - * `Data ([]byte)`: The request transaction bytes + * `Message (string)`: A string to echo back * __Returns__: - * `Code (uint32)`: Response code - * `Data ([]byte)`: Result bytes, if any - * `Log (string)`: Debug or error message - * `Tags ([]*KVPair)`: Optional tags for indexing + * `Message (string)`: The input string * __Usage__:
- Append and run a transaction. If the transaction is valid, returns CodeType.OK + * Echo a string to test an abci client/server implementation -#### CheckTx - * __Arguments__: - * `Data ([]byte)`: The request transaction bytes - * __Returns__: - * `Code (uint32)`: Response code - * `Data ([]byte)`: Result bytes, if any - * `Log (string)`: Debug or error message - * `Gas (int64)`: Amount of gas consumed by transaction - * `Fee (int64)`: Fee paid by transaction +#### Flush * __Usage__:
- Validate a mempool transaction, prior to broadcasting or proposing. This message should not mutate the main state, but application - developers may want to keep a separate CheckTx state that gets reset upon Commit. - - CheckTx can happen interspersed with DeliverTx, but they happen on different ABCI connections - CheckTx from the mempool connection, and DeliverTx from the consensus connection. During Commit, the mempool is locked, so you can reset the mempool state to the latest state after running all those DeliverTxs, and then the mempool will re-run whatever txs it has against that latest mempool state. - - Transactions are first run through CheckTx before broadcast to peers in the mempool layer. - You can make CheckTx semi-stateful and clear the state upon `Commit` or `BeginBlock`, - to allow for dependent sequences of transactions in the same block. - -#### Commit - * __Returns__: - * `Data ([]byte)`: The Merkle root hash - * `Log (string)`: Debug or error message - * __Usage__:
- Return a Merkle root hash of the application state. - -#### Query - * __Arguments__: - * `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 (int64)`: 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 - * `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 (int64)`: 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) + * Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. #### Info * __Returns__: @@ -172,6 +130,22 @@ Here, we describe the requests and responses as function arguments and return va * __Usage__:
Called once upon genesis +#### Query + * __Arguments__: + * `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 (int64)`: 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 + * `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 (int64)`: 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 + #### BeginBlock * __Arguments__: * `Hash ([]byte)`: The block's hash. This can be derived from the block header. @@ -181,6 +155,36 @@ Here, we describe the requests and responses as function arguments and return va * __Usage__:
Signals the beginning of a new block. Called prior to any DeliverTxs. The header is expected to at least contain the Height. The `AbsentValidators` and `ByzantineValidators` can be used to determine rewards and punishments for the validators. +#### CheckTx + * __Arguments__: + * `Data ([]byte)`: The request transaction bytes + * __Returns__: + * `Code (uint32)`: Response code + * `Data ([]byte)`: Result bytes, if any + * `Log (string)`: Debug or error message + * `Gas (int64)`: Amount of gas consumed by transaction + * `Fee (int64)`: Fee paid by transaction + * __Usage__:
+ Validate a mempool transaction, prior to broadcasting or proposing. This message should not mutate the main state, but application + developers may want to keep a separate CheckTx state that gets reset upon Commit. + + CheckTx can happen interspersed with DeliverTx, but they happen on different ABCI connections - CheckTx from the mempool connection, and DeliverTx from the consensus connection. During Commit, the mempool is locked, so you can reset the mempool state to the latest state after running all those DeliverTxs, and then the mempool will re-run whatever txs it has against that latest mempool state. + + Transactions are first run through CheckTx before broadcast to peers in the mempool layer. + You can make CheckTx semi-stateful and clear the state upon `Commit` or `BeginBlock`, + to allow for dependent sequences of transactions in the same block. + +#### DeliverTx + * __Arguments__: + * `Data ([]byte)`: The request transaction bytes + * __Returns__: + * `Code (uint32)`: Response code + * `Data ([]byte)`: Result bytes, if any + * `Log (string)`: Debug or error message + * `Tags ([]*KVPair)`: Optional tags for indexing + * __Usage__:
+ Append and run a transaction. If the transaction is valid, returns CodeType.OK + #### EndBlock * __Arguments__: * `Height (int64)`: The block height that ended @@ -190,15 +194,10 @@ Here, we describe the requests and responses as function arguments and return va * __Usage__:
Signals the end of a block. Called prior to each Commit after all transactions. Validator set is updated with the result. -#### Echo - * __Arguments__: - * `Message (string)`: A string to echo back +#### Commit * __Returns__: - * `Message (string)`: The input string + * `Data ([]byte)`: The Merkle root hash + * `Log (string)`: Debug or error message * __Usage__:
- * Echo a string to test an abci client/server implementation - -#### Flush - * __Usage__:
- * Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back. + Return a Merkle root hash of the application state. diff --git a/types/types.proto b/types/types.proto index 74249c09..da46b2dc 100644 --- a/types/types.proto +++ b/types/types.proto @@ -3,7 +3,6 @@ package types; import "github.com/gogo/protobuf/gogoproto/gogo.proto"; - // This file is copied from http://github.com/tendermint/abci //---------------------------------------- From c268c4e767fd04657d17dbe50e788ada67d15c1d Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Wed, 20 Dec 2017 10:33:24 +0100 Subject: [PATCH 415/545] Update Circle and Makefile to run tests/linting on CI --- Makefile | 20 ++++++++++---------- circle.yml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index cadf8544..9e7a9c90 100644 --- a/Makefile +++ b/Makefile @@ -74,23 +74,23 @@ metalinter_all: protoc $(INCLUDE) --lint_out=. types/*.proto gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... -metalinter: - @ echo "==> Running linter" +metalinter_test: + @ echo "==> Running linter" gometalinter.v2 --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ --enable=goconst \ --enable=goimports \ --enable=gosimple \ - --enable=ineffassign \ + --enable=ineffassign \ --enable=megacheck \ - --enable=misspell \ - --enable=staticcheck \ + --enable=misspell \ + --enable=staticcheck \ --enable=safesql \ - --enable=structcheck \ - --enable=unconvert \ + --enable=structcheck \ + --enable=unconvert \ --enable=unused \ - --enable=varcheck \ + --enable=varcheck \ --enable=vetshadow \ ./... @@ -100,8 +100,8 @@ metalinter: #--enable=gocyclo \ #--enable=golint \ <== comments on anything exported #--enable=gotype \ - #--enable=interfacer \ - #--enable=unparam \ + #--enable=interfacer \ + #--enable=unparam \ #--enable=vet \ build-docker: diff --git a/circle.yml b/circle.yml index 95d1dea5..32ce4a7a 100644 --- a/circle.yml +++ b/circle.yml @@ -15,7 +15,7 @@ checkout: test: override: - - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations + - cd $REPO && make get_vendor_deps && make metalinter && make test_integrations post: - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" From 57c49cc825d39960ac6f4aa2ffa909b0003a3584 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Wed, 20 Dec 2017 10:40:35 +0100 Subject: [PATCH 416/545] Include unsaved circle.yml file --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 32ce4a7a..95d1dea5 100644 --- a/circle.yml +++ b/circle.yml @@ -15,7 +15,7 @@ checkout: test: override: - - cd $REPO && make get_vendor_deps && make metalinter && make test_integrations + - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations post: - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" From e46a99a32f20e805601d315b948d1c5ab28bf34a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 20 Dec 2017 11:02:22 -0800 Subject: [PATCH 417/545] Fix Makefile --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9e7a9c90..dc996d12 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ GOTOOLS = \ github.com/mitchellh/gox \ github.com/Masterminds/glide \ gopkg.in/alecthomas/gometalinter.v2 \ - github.com/ckaznocha/protoc-gen-lint \ github.com/gogo/protobuf/protoc-gen-gogo \ github.com/gogo/protobuf/gogoproto @@ -74,7 +73,7 @@ metalinter_all: protoc $(INCLUDE) --lint_out=. types/*.proto gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... -metalinter_test: +metalinter: @ echo "==> Running linter" gometalinter.v2 --vendor --deadline=600s --disable-all \ --enable=maligned \ From 0d69ace9617a0a580b60cdf6df4acfce8eab17be Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 20 Dec 2017 13:40:26 -0600 Subject: [PATCH 418/545] fix circleci config --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 95d1dea5..32ce4a7a 100644 --- a/circle.yml +++ b/circle.yml @@ -15,7 +15,7 @@ checkout: test: override: - - cd $REPO && make get_vendor_deps && make metalinter_test && make test_integrations + - cd $REPO && make get_vendor_deps && make metalinter && make test_integrations post: - cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt - cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}" From fa15e4f5541f35af02d1d4123896666c32dbc5c8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 20 Dec 2017 15:16:11 -0500 Subject: [PATCH 419/545] update changelog [ci skip] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b183f1..0dc591d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ BREAKING CHANGES: - [types] ResponseEndBlock: renamed Diffs field to ValidatorUpdates + - [types] changed protobuf field indices for Request and Response oneof types FEATURES: - [types] ResponseEndBlock: added ConsensusParamUpdates From 2927caa0eba91f9056c2f86ef530da29e21847a2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 20 Dec 2017 15:41:28 -0500 Subject: [PATCH 420/545] fix flag parsing in console mode --- cmd/abci-cli/abci-cli.go | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index 7f0f3548..7655a775 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -168,7 +168,7 @@ var consoleCmd = &cobra.Command{ Short: "Start an interactive abci console for multiple commands", Long: "", Args: cobra.ExactArgs(0), - ValidArgs: []string{"batch", "echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"}, + ValidArgs: []string{"echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"}, RunE: func(cmd *cobra.Command, args []string) error { return cmdConsole(cmd, args) }, @@ -391,11 +391,43 @@ func muxOnCommands(cmd *cobra.Command, pArgs []string) error { if len(pArgs) < 2 { return errors.New("expecting persistent args of the form: abci-cli [command] <...>") } - subCommand, actualArgs := pArgs[1], pArgs[2:] + + // TODO: this parsing is fragile + args := []string{} + for i := 0; i < len(pArgs); i++ { + arg := pArgs[i] + + // check for flags + if strings.HasPrefix(arg, "-") { + // if it has an equal, we can just skip + if strings.Contains(arg, "=") { + continue + } + // if its a boolean, we can just skip + _, err := cmd.Flags().GetBool(strings.TrimLeft(arg, "-")) + if err == nil { + continue + } + + // otherwise, we need to skip the next one too + i += 1 + continue + } + + // append the actual arg + args = append(args, arg) + } + var subCommand string + var actualArgs []string + if len(args) > 1 { + subCommand = args[1] + } + if len(args) > 2 { + actualArgs = args[2:] + } + cmd.Use = subCommand // for later print statements ... switch strings.ToLower(subCommand) { - case "batch": - return muxOnCommands(cmd, actualArgs) case "check_tx": return cmdCheckTx(cmd, actualArgs) case "commit": From e4b9f1abe794a2117a59738a1294e09b46d0fa00 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 20 Dec 2017 17:32:32 -0800 Subject: [PATCH 421/545] Id -> ID using gogo --- types/types.pb.go | 232 +++++++++++++++++++++++----------------------- types/types.proto | 8 +- 2 files changed, 122 insertions(+), 118 deletions(-) diff --git a/types/types.pb.go b/types/types.pb.go index 71272628..7ab18fe4 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -1534,11 +1534,11 @@ func (m *BlockGossip) GetBlockPartSizeBytes() int32 { } type Header struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ChainID string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` Time int64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` NumTxs int32 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` - LastBlockId *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` + LastBlockID *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` ValidatorsHash []byte `protobuf:"bytes,8,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` @@ -1550,9 +1550,9 @@ func (m *Header) String() string { return proto.CompactTextString(m) func (*Header) ProtoMessage() {} func (*Header) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} } -func (m *Header) GetChainId() string { +func (m *Header) GetChainID() string { if m != nil { - return m.ChainId + return m.ChainID } return "" } @@ -1578,9 +1578,9 @@ func (m *Header) GetNumTxs() int32 { return 0 } -func (m *Header) GetLastBlockId() *BlockID { +func (m *Header) GetLastBlockID() *BlockID { if m != nil { - return m.LastBlockId + return m.LastBlockID } return nil } @@ -2193,114 +2193,116 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1741 bytes of a gzipped FileDescriptorProto + // 1766 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x72, 0x1b, 0xc7, - 0x11, 0x26, 0xfe, 0xb1, 0x0d, 0xfe, 0x80, 0x43, 0x4a, 0x82, 0xa0, 0x83, 0xe9, 0xad, 0x4a, 0x0c, - 0xd9, 0x16, 0x69, 0xd3, 0xa5, 0x94, 0x68, 0x27, 0xae, 0x88, 0x92, 0x2c, 0xa2, 0x5c, 0xa5, 0x28, - 0x23, 0xc6, 0x87, 0x5c, 0x50, 0x03, 0xec, 0x10, 0xd8, 0x12, 0xb0, 0xbb, 0xde, 0x1d, 0xd0, 0xa0, - 0x2a, 0x8f, 0xe0, 0x7b, 0xce, 0xc9, 0x25, 0x55, 0x79, 0x81, 0x1c, 0x73, 0x4b, 0xe5, 0x19, 0x72, - 0xf0, 0xb3, 0xa4, 0xba, 0x67, 0xf6, 0x97, 0xbb, 0xa9, 0x94, 0x0e, 0xbe, 0x00, 0x33, 0xd3, 0x3f, - 0xd3, 0xdd, 0xdb, 0xf3, 0x75, 0xcf, 0xc0, 0xbe, 0xba, 0x09, 0x64, 0x74, 0x42, 0xbf, 0xc7, 0x41, - 0xe8, 0x2b, 0x9f, 0xb5, 0x68, 0x32, 0x7c, 0x34, 0x77, 0xd5, 0x62, 0x3d, 0x3d, 0x9e, 0xf9, 0xab, - 0x93, 0xb9, 0x3f, 0xf7, 0x4f, 0x88, 0x3a, 0x5d, 0x5f, 0xd1, 0x8c, 0x26, 0x34, 0xd2, 0x52, 0xf6, - 0xbf, 0x9a, 0xd0, 0xe1, 0xf2, 0xfb, 0xb5, 0x8c, 0x14, 0x1b, 0x41, 0x53, 0xce, 0x16, 0xfe, 0xa0, - 0x7e, 0x54, 0x1b, 0xf5, 0x4e, 0xd9, 0xb1, 0xd6, 0x6e, 0xa8, 0x2f, 0x66, 0x0b, 0xff, 0x62, 0x8b, - 0x13, 0x07, 0xfb, 0x04, 0x5a, 0x57, 0xcb, 0x75, 0xb4, 0x18, 0x34, 0x88, 0xf5, 0x20, 0xcf, 0xfa, - 0x0d, 0x92, 0x2e, 0xb6, 0xb8, 0xe6, 0x41, 0xb5, 0xae, 0x77, 0xe5, 0x0f, 0x9a, 0x65, 0x6a, 0xc7, - 0xde, 0x15, 0xa9, 0x45, 0x0e, 0xf6, 0x04, 0x20, 0x92, 0x6a, 0xe2, 0x07, 0xca, 0xf5, 0xbd, 0x41, - 0x8b, 0xf8, 0xef, 0xe5, 0xf9, 0xdf, 0x48, 0xf5, 0x3b, 0x22, 0x5f, 0x6c, 0x71, 0x2b, 0x8a, 0x27, - 0x28, 0xe9, 0x7a, 0xae, 0x9a, 0xcc, 0x16, 0xc2, 0xf5, 0x06, 0xed, 0x32, 0xc9, 0xb1, 0xe7, 0xaa, - 0x67, 0x48, 0x46, 0x49, 0x37, 0x9e, 0xa0, 0x2b, 0xdf, 0xaf, 0x65, 0x78, 0x33, 0xe8, 0x94, 0xb9, - 0xf2, 0x7b, 0x24, 0xa1, 0x2b, 0xc4, 0xc3, 0xbe, 0x82, 0xde, 0x54, 0xce, 0x5d, 0x6f, 0x32, 0x5d, - 0xfa, 0xb3, 0xb7, 0x83, 0x2e, 0x89, 0x0c, 0xf2, 0x22, 0xe7, 0xc8, 0x70, 0x8e, 0xf4, 0x8b, 0x2d, - 0x0e, 0xd3, 0x64, 0xc6, 0x4e, 0xa1, 0x3b, 0x5b, 0xc8, 0xd9, 0xdb, 0x89, 0xda, 0x0c, 0x2c, 0x92, - 0xbc, 0x93, 0x97, 0x7c, 0x86, 0xd4, 0xcb, 0xcd, 0xc5, 0x16, 0xef, 0xcc, 0xf4, 0x10, 0xfd, 0x72, - 0xe4, 0xd2, 0xbd, 0x96, 0x21, 0x4a, 0x1d, 0x94, 0xf9, 0xf5, 0x5c, 0xd3, 0x49, 0xce, 0x72, 0xe2, - 0x09, 0x7b, 0x0c, 0x96, 0xf4, 0x1c, 0x63, 0x68, 0x8f, 0x04, 0xef, 0x16, 0xbe, 0xa8, 0xe7, 0xc4, - 0x66, 0x76, 0xa5, 0x19, 0xb3, 0x63, 0x68, 0xcf, 0xfc, 0xd5, 0xca, 0x55, 0x83, 0x6d, 0x92, 0x39, - 0x2c, 0x98, 0x48, 0xb4, 0x8b, 0x2d, 0x6e, 0xb8, 0xce, 0x3b, 0xd0, 0xba, 0x16, 0xcb, 0xb5, 0xb4, - 0x3f, 0x82, 0x5e, 0x26, 0x53, 0xd8, 0x00, 0x3a, 0x2b, 0x19, 0x45, 0x62, 0x2e, 0x07, 0xb5, 0xa3, - 0xda, 0xc8, 0xe2, 0xf1, 0xd4, 0xde, 0x85, 0xed, 0x6c, 0x9e, 0x64, 0x04, 0x31, 0x17, 0x50, 0xf0, - 0x5a, 0x86, 0x11, 0x26, 0x80, 0x11, 0x34, 0x53, 0xfb, 0x4b, 0xe8, 0x17, 0x93, 0x80, 0xf5, 0xa1, - 0xf1, 0x56, 0xde, 0x18, 0x4e, 0x1c, 0xb2, 0x43, 0x63, 0x10, 0x65, 0xb1, 0xc5, 0x8d, 0x75, 0xcf, - 0x13, 0xd9, 0x24, 0x0d, 0xd8, 0x67, 0x00, 0xd7, 0x62, 0xe9, 0x3a, 0x42, 0xf9, 0x61, 0x34, 0xa8, - 0x1d, 0x35, 0x46, 0xbd, 0xd3, 0xbe, 0x71, 0xf7, 0xbb, 0x98, 0xc0, 0x33, 0x3c, 0xb6, 0x93, 0x98, - 0x4e, 0x79, 0xc1, 0x18, 0x34, 0x1d, 0xa1, 0x04, 0x6d, 0xbf, 0xcd, 0x69, 0x8c, 0x6b, 0x81, 0x50, - 0x0b, 0xb3, 0x3d, 0x8d, 0xd9, 0x5d, 0x68, 0x2f, 0xa4, 0x3b, 0x5f, 0x28, 0x3a, 0x2f, 0x0d, 0x6e, - 0x66, 0x68, 0x6b, 0x10, 0xfa, 0xd7, 0x92, 0x8e, 0x46, 0x97, 0xeb, 0x89, 0xfd, 0xcf, 0x1a, 0xec, - 0xdf, 0xca, 0x25, 0xd4, 0xbb, 0x10, 0xd1, 0x22, 0xde, 0x0b, 0xc7, 0xec, 0x17, 0xa8, 0x57, 0x38, - 0x32, 0x34, 0x47, 0x76, 0xc7, 0x58, 0x7f, 0x41, 0x8b, 0xdc, 0x10, 0xd9, 0x27, 0xb0, 0x2f, 0xa6, - 0x91, 0xf4, 0xd4, 0x24, 0xe3, 0x6f, 0xe3, 0xa8, 0x31, 0x6a, 0xf1, 0xbe, 0x26, 0x24, 0xee, 0x46, - 0xec, 0x1c, 0x0e, 0xa7, 0x37, 0xef, 0x84, 0xa7, 0x5c, 0x4f, 0x66, 0xf9, 0x9b, 0x14, 0x9f, 0x3d, - 0xb3, 0xc3, 0x8b, 0x6b, 0xd7, 0x91, 0xde, 0x4c, 0xf2, 0x83, 0x84, 0x39, 0xd5, 0x61, 0x1f, 0xc1, - 0x6e, 0x3e, 0xa5, 0xd9, 0x2e, 0xd4, 0xd5, 0xc6, 0xd8, 0x5e, 0x57, 0x1b, 0xdb, 0x4e, 0xbe, 0x47, - 0x92, 0xbe, 0xb7, 0x78, 0x1e, 0xc2, 0x5e, 0x21, 0x53, 0x33, 0x81, 0xac, 0x65, 0x03, 0x69, 0xef, - 0xc1, 0x4e, 0x2e, 0x41, 0xed, 0x1f, 0x5b, 0xd0, 0xe5, 0x32, 0x0a, 0x7c, 0x2f, 0x92, 0xec, 0x09, - 0x58, 0x72, 0x33, 0x93, 0x1a, 0x55, 0x6a, 0x85, 0x33, 0xab, 0x79, 0x5e, 0xc4, 0x74, 0x3c, 0x44, - 0x09, 0x33, 0x7b, 0x98, 0x43, 0xc4, 0x83, 0xa2, 0x50, 0x16, 0x12, 0x3f, 0xcd, 0x43, 0xe2, 0x61, - 0x81, 0xb7, 0x80, 0x89, 0x0f, 0x73, 0x98, 0x58, 0x54, 0x9c, 0x03, 0xc5, 0xb3, 0x12, 0x50, 0x2c, - 0x9a, 0x5f, 0x81, 0x8a, 0x67, 0x25, 0xa8, 0x38, 0xb8, 0xb5, 0x57, 0x29, 0x2c, 0x7e, 0x9a, 0x87, - 0xc5, 0xa2, 0x3b, 0x05, 0x5c, 0xfc, 0x75, 0x19, 0x2e, 0xde, 0x2f, 0xc8, 0x54, 0x02, 0xe3, 0x17, - 0xb7, 0x80, 0xf1, 0x6e, 0x41, 0xb4, 0x04, 0x19, 0xcf, 0x72, 0xc8, 0x08, 0xa5, 0xbe, 0x55, 0x40, - 0xe3, 0xaf, 0x6e, 0x43, 0xe3, 0xbd, 0xe2, 0xa7, 0x2d, 0xc3, 0xc6, 0x93, 0x02, 0x36, 0xde, 0x29, - 0x5a, 0x59, 0x09, 0x8e, 0x0f, 0xf1, 0x44, 0x17, 0x32, 0x0d, 0x4f, 0xbf, 0x0c, 0x43, 0x3f, 0x34, - 0xe8, 0xa5, 0x27, 0xf6, 0x08, 0x31, 0x26, 0xcd, 0xaf, 0xff, 0x01, 0xa4, 0x94, 0xf4, 0x99, 0xec, - 0xb2, 0xff, 0x5c, 0x4b, 0x65, 0x09, 0x4b, 0xb3, 0xf8, 0x64, 0x19, 0x7c, 0xca, 0xe0, 0x6b, 0x3d, - 0x87, 0xaf, 0xec, 0x63, 0xd8, 0x5f, 0x8a, 0x48, 0xe9, 0xb8, 0x4c, 0x72, 0x80, 0xb5, 0x87, 0x04, - 0x1d, 0x10, 0x8d, 0x5c, 0x8f, 0xe0, 0x20, 0xc3, 0x2b, 0x82, 0x60, 0x42, 0xe0, 0xd4, 0xa4, 0xc3, - 0xdb, 0x4f, 0xb8, 0x9f, 0x06, 0xc1, 0x85, 0x88, 0x16, 0xf6, 0x59, 0xea, 0x7f, 0x8a, 0xdd, 0x0c, - 0x9a, 0x33, 0xdf, 0xd1, 0x6e, 0xed, 0x70, 0x1a, 0x23, 0x9e, 0x2f, 0xfd, 0xb9, 0xb1, 0x0c, 0x87, - 0xf6, 0x41, 0x2a, 0x9a, 0xa4, 0xaa, 0xfd, 0x8f, 0x7a, 0xea, 0x7b, 0x02, 0xc5, 0xb7, 0x94, 0x1d, - 0x42, 0xcb, 0xf5, 0x1c, 0xb9, 0x21, 0x75, 0x0d, 0xae, 0x27, 0xec, 0x5c, 0x97, 0x0c, 0x74, 0x6c, - 0xfb, 0xfc, 0xb3, 0x7f, 0xff, 0xf4, 0xc1, 0xd6, 0x7f, 0x7e, 0xfa, 0x60, 0x94, 0xe9, 0x9a, 0x94, - 0xf4, 0x1c, 0x19, 0xae, 0x5c, 0x4f, 0x9d, 0xcc, 0xfd, 0x47, 0x3f, 0xb8, 0xa1, 0x3c, 0xc1, 0xc8, - 0x1d, 0x9f, 0xdf, 0x28, 0x19, 0xe9, 0x22, 0xf3, 0x4d, 0x5c, 0x64, 0x9a, 0xef, 0xa9, 0x45, 0x8b, - 0xa3, 0x9e, 0x20, 0xf4, 0xfd, 0x2b, 0x3a, 0xd6, 0xef, 0xa5, 0x87, 0xc4, 0x33, 0xb8, 0xd8, 0xce, - 0x15, 0x18, 0x13, 0xce, 0x4e, 0x1a, 0xce, 0x43, 0x60, 0xb7, 0xcf, 0xa3, 0xfd, 0x97, 0x1a, 0x62, - 0x6d, 0xee, 0xac, 0x95, 0x46, 0xf4, 0xb9, 0x49, 0xa8, 0xfa, 0x7b, 0x9a, 0xab, 0x53, 0xd0, 0x58, - 0xd5, 0x48, 0xac, 0xc2, 0x95, 0xb9, 0x88, 0x28, 0x9a, 0x0d, 0x8e, 0x43, 0x5c, 0xb9, 0x92, 0x92, - 0xe2, 0xd2, 0xe0, 0x38, 0xb4, 0xff, 0x5a, 0x4b, 0x33, 0x21, 0x2d, 0x1a, 0x3f, 0xa7, 0x95, 0x1f, - 0x42, 0x53, 0x89, 0x79, 0x5c, 0x0a, 0xe3, 0x62, 0xfb, 0xed, 0x77, 0xaf, 0x85, 0x1b, 0x72, 0x22, - 0x61, 0x20, 0xfb, 0x45, 0x0c, 0x61, 0xbf, 0x81, 0xfd, 0xa4, 0x90, 0x4e, 0xd6, 0x81, 0x23, 0x94, - 0xac, 0xee, 0x37, 0xfa, 0x09, 0xeb, 0x1f, 0x34, 0x27, 0x7b, 0x05, 0xf7, 0x66, 0xa8, 0xcf, 0x8b, - 0xd6, 0xd1, 0x24, 0x10, 0xa1, 0x58, 0x25, 0x4a, 0xea, 0x39, 0xb4, 0x7c, 0x16, 0x73, 0xbd, 0x46, - 0xa6, 0x88, 0xdf, 0x99, 0xe5, 0x16, 0x8c, 0x3e, 0xfb, 0x4f, 0x58, 0x9d, 0xb3, 0x88, 0xf5, 0x73, - 0x06, 0x91, 0x52, 0xad, 0x60, 0x28, 0x3b, 0x01, 0xd0, 0x40, 0x12, 0xb9, 0xef, 0xa4, 0xa9, 0xd0, - 0x71, 0x64, 0x28, 0x84, 0x6f, 0xdc, 0x77, 0x92, 0x5b, 0xd3, 0x78, 0xc8, 0x7e, 0x09, 0x1d, 0xb5, - 0xd1, 0xdc, 0xf9, 0xce, 0xe7, 0x72, 0x43, 0xac, 0x6d, 0x45, 0xff, 0xec, 0x31, 0x6c, 0x6b, 0xc5, - 0x73, 0x3f, 0x8a, 0xdc, 0xc0, 0xd4, 0x66, 0x96, 0x55, 0xfd, 0x92, 0x28, 0xbc, 0x37, 0x4d, 0x27, - 0xf6, 0x1f, 0xc1, 0x4a, 0xb6, 0x65, 0x0f, 0xc0, 0x5a, 0x89, 0xcd, 0x64, 0x7a, 0xa3, 0xbf, 0x5a, - 0x6d, 0xd4, 0xe2, 0xdd, 0x95, 0xd8, 0x90, 0x97, 0xec, 0x1e, 0x74, 0x90, 0xa8, 0x36, 0xfa, 0x5b, - 0xb4, 0x78, 0x7b, 0x25, 0x36, 0x97, 0x9b, 0x84, 0x80, 0x59, 0x6d, 0x7a, 0xbe, 0x95, 0xd8, 0xbc, - 0x14, 0x91, 0xfd, 0x35, 0xb4, 0xb5, 0x91, 0xff, 0x97, 0x62, 0x94, 0xaf, 0xe7, 0xe4, 0x7f, 0x0b, - 0xbd, 0x8c, 0xdd, 0xec, 0x73, 0xb8, 0xa3, 0x3d, 0x0c, 0x44, 0xa8, 0x28, 0x22, 0x39, 0x85, 0x8c, - 0x88, 0xaf, 0x45, 0xa8, 0x70, 0x4b, 0x52, 0x6d, 0xff, 0xad, 0x0e, 0x6d, 0xdd, 0x21, 0xb2, 0xfb, - 0x58, 0x79, 0x85, 0xeb, 0x4d, 0x5c, 0x27, 0xae, 0x2e, 0x34, 0x1f, 0x3b, 0x19, 0x48, 0xa9, 0xe7, - 0x20, 0x85, 0x41, 0x53, 0xb9, 0x2b, 0x69, 0xbc, 0xa2, 0x31, 0x1a, 0xeb, 0xad, 0x57, 0x14, 0x85, - 0xa6, 0x8e, 0x82, 0xb7, 0x5e, 0x61, 0x14, 0x4e, 0x61, 0x27, 0x53, 0x26, 0x5c, 0xc7, 0xb4, 0x2f, - 0xbb, 0xd9, 0x0f, 0x30, 0x7e, 0xce, 0x7b, 0x49, 0xc1, 0x18, 0x3b, 0x6c, 0x04, 0x54, 0x3f, 0x26, - 0xba, 0x86, 0xea, 0xba, 0xd2, 0xa6, 0xba, 0xb2, 0x8b, 0xeb, 0xa6, 0xc8, 0x62, 0xfb, 0xfb, 0x00, - 0x2c, 0x4c, 0x32, 0xcd, 0xd2, 0x21, 0x96, 0x2e, 0x2e, 0x10, 0xf1, 0x23, 0xd8, 0x4b, 0xbb, 0x57, - 0xcd, 0xd2, 0xd5, 0x5a, 0xd2, 0x65, 0x62, 0xbc, 0x0f, 0xdd, 0xa4, 0x7e, 0x59, 0xc4, 0xd1, 0x11, - 0xa6, 0x6c, 0x8d, 0xa1, 0x63, 0x4c, 0x2c, 0x6d, 0xbf, 0x3f, 0x86, 0x16, 0x46, 0x3d, 0x3e, 0x86, - 0x71, 0x8f, 0x44, 0xd1, 0x96, 0xca, 0x34, 0xe1, 0x9a, 0xc5, 0x3e, 0x83, 0x9d, 0xdc, 0x3a, 0x16, - 0x27, 0xe5, 0x2b, 0xb1, 0x34, 0x1f, 0x4a, 0x4f, 0x92, 0x6d, 0xea, 0xe9, 0x36, 0xf6, 0x97, 0x60, - 0x25, 0xf0, 0x80, 0xa1, 0x0e, 0xd6, 0xd3, 0x49, 0x7c, 0xe9, 0xd9, 0xe6, 0xed, 0x60, 0x3d, 0xfd, - 0x56, 0xdf, 0x7b, 0x02, 0xff, 0x07, 0x73, 0x15, 0x68, 0x70, 0x3d, 0xb1, 0xbf, 0x82, 0x6e, 0xdc, - 0xaa, 0x57, 0x8b, 0x56, 0x7c, 0x6a, 0xfb, 0xef, 0x35, 0x68, 0x6b, 0x74, 0x2b, 0xb9, 0x67, 0x7d, - 0x4e, 0xb7, 0xa7, 0xb5, 0x9c, 0xa0, 0xd3, 0x24, 0xb8, 0x9b, 0x1c, 0x2c, 0x2d, 0x74, 0x7c, 0x79, - 0x13, 0x48, 0x6e, 0x11, 0x17, 0x0e, 0xd9, 0x87, 0xb0, 0xad, 0x45, 0x22, 0x15, 0xba, 0x5e, 0x8c, - 0x0a, 0x3d, 0x5a, 0x7b, 0x43, 0x4b, 0xf8, 0x49, 0x35, 0x8b, 0xeb, 0x29, 0x53, 0x0e, 0xba, 0xb4, - 0x30, 0xf6, 0x94, 0xfd, 0x00, 0x9a, 0xa4, 0x07, 0xa0, 0xfd, 0xe6, 0x92, 0x8f, 0x5f, 0xbd, 0xec, - 0x6f, 0xb1, 0x0e, 0x34, 0xc6, 0xaf, 0x2e, 0xfb, 0xb5, 0xd3, 0x1f, 0x5b, 0xb0, 0xf7, 0xf4, 0xfc, - 0xd9, 0xf8, 0x69, 0x10, 0x2c, 0xdd, 0x99, 0xa0, 0x0e, 0xe3, 0x04, 0x9a, 0xd4, 0x43, 0x95, 0x3c, - 0x65, 0x0c, 0xcb, 0x9a, 0x79, 0x76, 0x0a, 0x2d, 0x6a, 0xa5, 0x58, 0xd9, 0x8b, 0xc6, 0xb0, 0xb4, - 0xa7, 0xc7, 0x4d, 0x74, 0xb3, 0x75, 0xfb, 0x61, 0x63, 0x58, 0xd6, 0xd8, 0xb3, 0xaf, 0xc1, 0x4a, - 0x9b, 0xa0, 0xaa, 0xe7, 0x8d, 0x61, 0x65, 0x8b, 0x8f, 0xf2, 0x69, 0xfd, 0xab, 0x7a, 0x0c, 0x18, - 0x56, 0xf6, 0xc2, 0xec, 0x09, 0x74, 0xe2, 0x1a, 0x5f, 0xfe, 0x00, 0x31, 0xac, 0x68, 0xbf, 0x31, - 0x3c, 0xba, 0xdb, 0x2a, 0x7b, 0x25, 0x19, 0x96, 0xde, 0x11, 0xd8, 0x63, 0x68, 0x9b, 0x2a, 0x53, - 0xfa, 0x94, 0x30, 0x2c, 0x6f, 0xa2, 0xd1, 0xc9, 0xf4, 0xa6, 0x5e, 0xf5, 0x92, 0x33, 0xac, 0xbc, - 0xcc, 0xb0, 0xa7, 0x00, 0x99, 0xcb, 0x73, 0xe5, 0x13, 0xcd, 0xb0, 0xfa, 0x92, 0xc2, 0xf0, 0xec, - 0x24, 0x17, 0xcf, 0xf2, 0xa7, 0x93, 0x61, 0xd5, 0xbd, 0x61, 0xda, 0xa6, 0xe7, 0xb5, 0x2f, 0xfe, - 0x1b, 0x00, 0x00, 0xff, 0xff, 0x4e, 0x51, 0x0d, 0xe3, 0xa9, 0x13, 0x00, 0x00, + 0x11, 0x26, 0xfe, 0xb1, 0x0d, 0xfe, 0x80, 0x43, 0x4a, 0x82, 0xa1, 0x83, 0xe8, 0xad, 0x8a, 0x0d, + 0xd9, 0x16, 0x69, 0xd3, 0xa5, 0x94, 0x68, 0x27, 0xae, 0x08, 0xa4, 0x2c, 0xa2, 0x9c, 0x52, 0x94, + 0x15, 0xe3, 0x43, 0x2e, 0xa8, 0x01, 0x76, 0x08, 0x6c, 0x09, 0xd8, 0x5d, 0xef, 0x0e, 0x68, 0x50, + 0x95, 0x47, 0xf0, 0x3d, 0xe7, 0xe4, 0x98, 0x17, 0xc8, 0x31, 0xa7, 0xa4, 0xf2, 0x0c, 0x39, 0xe8, + 0xe0, 0x27, 0x49, 0x75, 0xcf, 0xec, 0x2f, 0x76, 0x53, 0x29, 0x1d, 0x74, 0x01, 0x66, 0xa6, 0x7f, + 0xb6, 0xbb, 0xa7, 0xe7, 0xeb, 0x9e, 0x81, 0x7d, 0x79, 0xeb, 0x8b, 0xf0, 0x84, 0x7e, 0x8f, 0xfd, + 0xc0, 0x93, 0x1e, 0x6b, 0xd0, 0xa4, 0xff, 0x68, 0xe6, 0xc8, 0xf9, 0x6a, 0x72, 0x3c, 0xf5, 0x96, + 0x27, 0x33, 0x6f, 0xe6, 0x9d, 0x10, 0x75, 0xb2, 0xba, 0xa6, 0x19, 0x4d, 0x68, 0xa4, 0xa4, 0xcc, + 0x7f, 0xd5, 0xa1, 0x65, 0x89, 0x1f, 0x56, 0x22, 0x94, 0x6c, 0x00, 0x75, 0x31, 0x9d, 0x7b, 0xbd, + 0xea, 0x51, 0x65, 0xd0, 0x39, 0x65, 0xc7, 0x4a, 0xbb, 0xa6, 0x3e, 0x9b, 0xce, 0xbd, 0xcb, 0x2d, + 0x8b, 0x38, 0xd8, 0xa7, 0xd0, 0xb8, 0x5e, 0xac, 0xc2, 0x79, 0xaf, 0x46, 0xac, 0x07, 0x59, 0xd6, + 0x6f, 0x91, 0x74, 0xb9, 0x65, 0x29, 0x1e, 0x54, 0xeb, 0xb8, 0xd7, 0x5e, 0xaf, 0x5e, 0xa4, 0x76, + 0xe4, 0x5e, 0x93, 0x5a, 0xe4, 0x60, 0x4f, 0x00, 0x42, 0x21, 0xc7, 0x9e, 0x2f, 0x1d, 0xcf, 0xed, + 0x35, 0x88, 0xff, 0x5e, 0x96, 0xff, 0x95, 0x90, 0xbf, 0x23, 0xf2, 0xe5, 0x96, 0x65, 0x84, 0xd1, + 0x04, 0x25, 0x1d, 0xd7, 0x91, 0xe3, 0xe9, 0x9c, 0x3b, 0x6e, 0xaf, 0x59, 0x24, 0x39, 0x72, 0x1d, + 0x79, 0x8e, 0x64, 0x94, 0x74, 0xa2, 0x09, 0xba, 0xf2, 0xc3, 0x4a, 0x04, 0xb7, 0xbd, 0x56, 0x91, + 0x2b, 0xbf, 0x47, 0x12, 0xba, 0x42, 0x3c, 0xec, 0x6b, 0xe8, 0x4c, 0xc4, 0xcc, 0x71, 0xc7, 0x93, + 0x85, 0x37, 0x7d, 0xdd, 0x6b, 0x93, 0x48, 0x2f, 0x2b, 0x32, 0x44, 0x86, 0x21, 0xd2, 0x2f, 0xb7, + 0x2c, 0x98, 0xc4, 0x33, 0x76, 0x0a, 0xed, 0xe9, 0x5c, 0x4c, 0x5f, 0x8f, 0xe5, 0xba, 0x67, 0x90, + 0xe4, 0x9d, 0xac, 0xe4, 0x39, 0x52, 0xaf, 0xd6, 0x97, 0x5b, 0x56, 0x6b, 0xaa, 0x86, 0xe8, 0x97, + 0x2d, 0x16, 0xce, 0x8d, 0x08, 0x50, 0xea, 0xa0, 0xc8, 0xaf, 0x0b, 0x45, 0x27, 0x39, 0xc3, 0x8e, + 0x26, 0xec, 0x31, 0x18, 0xc2, 0xb5, 0xb5, 0xa1, 0x1d, 0x12, 0xbc, 0x9b, 0xdb, 0x51, 0xd7, 0x8e, + 0xcc, 0x6c, 0x0b, 0x3d, 0x66, 0xc7, 0xd0, 0x9c, 0x7a, 0xcb, 0xa5, 0x23, 0x7b, 0xdb, 0x24, 0x73, + 0x98, 0x33, 0x91, 0x68, 0x97, 0x5b, 0x96, 0xe6, 0x1a, 0xb6, 0xa0, 0x71, 0xc3, 0x17, 0x2b, 0x61, + 0x7e, 0x0c, 0x9d, 0x54, 0xa6, 0xb0, 0x1e, 0xb4, 0x96, 0x22, 0x0c, 0xf9, 0x4c, 0xf4, 0x2a, 0x47, + 0x95, 0x81, 0x61, 0x45, 0x53, 0x73, 0x17, 0xb6, 0xd3, 0x79, 0x92, 0x12, 0xc4, 0x5c, 0x40, 0xc1, + 0x1b, 0x11, 0x84, 0x98, 0x00, 0x5a, 0x50, 0x4f, 0xcd, 0xaf, 0xa0, 0x9b, 0x4f, 0x02, 0xd6, 0x85, + 0xda, 0x6b, 0x71, 0xab, 0x39, 0x71, 0xc8, 0x0e, 0xb5, 0x41, 0x94, 0xc5, 0x86, 0xa5, 0xad, 0xbb, + 0x88, 0x65, 0xe3, 0x34, 0x60, 0x9f, 0x03, 0xdc, 0xf0, 0x85, 0x63, 0x73, 0xe9, 0x05, 0x61, 0xaf, + 0x72, 0x54, 0x1b, 0x74, 0x4e, 0xbb, 0xda, 0xdd, 0xef, 0x23, 0x82, 0x95, 0xe2, 0x31, 0xed, 0xd8, + 0x74, 0xca, 0x0b, 0xc6, 0xa0, 0x6e, 0x73, 0xc9, 0xe9, 0xf3, 0xdb, 0x16, 0x8d, 0x71, 0xcd, 0xe7, + 0x72, 0xae, 0x3f, 0x4f, 0x63, 0x76, 0x17, 0x9a, 0x73, 0xe1, 0xcc, 0xe6, 0x92, 0xce, 0x4b, 0xcd, + 0xd2, 0x33, 0xb4, 0xd5, 0x0f, 0xbc, 0x1b, 0x41, 0x47, 0xa3, 0x6d, 0xa9, 0x89, 0xf9, 0x8f, 0x0a, + 0xec, 0x6f, 0xe4, 0x12, 0xea, 0x9d, 0xf3, 0x70, 0x1e, 0x7d, 0x0b, 0xc7, 0xec, 0x17, 0xa8, 0x97, + 0xdb, 0x22, 0xd0, 0x47, 0x76, 0x47, 0x5b, 0x7f, 0x49, 0x8b, 0x96, 0x26, 0xb2, 0x4f, 0x61, 0x9f, + 0x4f, 0x42, 0xe1, 0xca, 0x71, 0xca, 0xdf, 0xda, 0x51, 0x6d, 0xd0, 0xb0, 0xba, 0x8a, 0x10, 0xbb, + 0x1b, 0xb2, 0x21, 0x1c, 0x4e, 0x6e, 0xdf, 0x70, 0x57, 0x3a, 0xae, 0x48, 0xf3, 0xd7, 0x29, 0x3e, + 0x7b, 0xfa, 0x0b, 0xcf, 0x6e, 0x1c, 0x5b, 0xb8, 0x53, 0x61, 0x1d, 0xc4, 0xcc, 0x89, 0x0e, 0xf3, + 0x08, 0x76, 0xb3, 0x29, 0xcd, 0x76, 0xa1, 0x2a, 0xd7, 0xda, 0xf6, 0xaa, 0x5c, 0x9b, 0x66, 0xbc, + 0x1f, 0x71, 0xfa, 0x6e, 0xf0, 0x3c, 0x84, 0xbd, 0x5c, 0xa6, 0xa6, 0x02, 0x59, 0x49, 0x07, 0xd2, + 0xdc, 0x83, 0x9d, 0x4c, 0x82, 0x9a, 0x3f, 0x35, 0xa0, 0x6d, 0x89, 0xd0, 0xf7, 0xdc, 0x50, 0xb0, + 0x27, 0x60, 0x88, 0xf5, 0x54, 0x28, 0x54, 0xa9, 0xe4, 0xce, 0xac, 0xe2, 0x79, 0x16, 0xd1, 0xf1, + 0x10, 0xc5, 0xcc, 0xec, 0x61, 0x06, 0x11, 0x0f, 0xf2, 0x42, 0x69, 0x48, 0xfc, 0x2c, 0x0b, 0x89, + 0x87, 0x39, 0xde, 0x1c, 0x26, 0x3e, 0xcc, 0x60, 0x62, 0x5e, 0x71, 0x06, 0x14, 0xcf, 0x0a, 0x40, + 0x31, 0x6f, 0x7e, 0x09, 0x2a, 0x9e, 0x15, 0xa0, 0x62, 0x6f, 0xe3, 0x5b, 0x85, 0xb0, 0xf8, 0x59, + 0x16, 0x16, 0xf3, 0xee, 0xe4, 0x70, 0xf1, 0x57, 0x45, 0xb8, 0xf8, 0x41, 0x4e, 0xa6, 0x14, 0x18, + 0xbf, 0xdc, 0x00, 0xc6, 0xbb, 0x39, 0xd1, 0x02, 0x64, 0x3c, 0xcb, 0x20, 0x23, 0x14, 0xfa, 0x56, + 0x02, 0x8d, 0xbf, 0xdc, 0x84, 0xc6, 0x7b, 0xf9, 0xad, 0x2d, 0xc2, 0xc6, 0x93, 0x1c, 0x36, 0xde, + 0xc9, 0x5b, 0x59, 0x0a, 0x8e, 0x0f, 0xf1, 0x44, 0xe7, 0x32, 0x0d, 0x4f, 0xbf, 0x08, 0x02, 0x2f, + 0xd0, 0xe8, 0xa5, 0x26, 0xe6, 0x00, 0x31, 0x26, 0xc9, 0xaf, 0xff, 0x01, 0xa4, 0x94, 0xf4, 0xa9, + 0xec, 0x32, 0xff, 0x5c, 0x49, 0x64, 0x09, 0x4b, 0xd3, 0xf8, 0x64, 0x68, 0x7c, 0x4a, 0xe1, 0x6b, + 0x35, 0x83, 0xaf, 0xec, 0x13, 0xd8, 0x5f, 0xf0, 0x50, 0xaa, 0xb8, 0x8c, 0x33, 0x80, 0xb5, 0x87, + 0x04, 0x15, 0x10, 0x85, 0x5c, 0x8f, 0xe0, 0x20, 0xc5, 0xcb, 0x7d, 0x7f, 0x4c, 0xe0, 0x54, 0xa7, + 0xc3, 0xdb, 0x8d, 0xb9, 0x9f, 0xfa, 0xfe, 0x25, 0x0f, 0xe7, 0xe6, 0x59, 0xe2, 0x7f, 0x82, 0xdd, + 0x0c, 0xea, 0x53, 0xcf, 0x56, 0x6e, 0xed, 0x58, 0x34, 0x46, 0x3c, 0x5f, 0x78, 0x33, 0x6d, 0x19, + 0x0e, 0xcd, 0x83, 0x44, 0x34, 0x4e, 0x55, 0xf3, 0xef, 0xd5, 0xc4, 0xf7, 0x18, 0x8a, 0x37, 0x94, + 0x1d, 0x42, 0xc3, 0x71, 0x6d, 0xb1, 0x26, 0x75, 0x35, 0x4b, 0x4d, 0xd8, 0x50, 0x95, 0x0c, 0x74, + 0x6c, 0x7b, 0xf8, 0xf9, 0xbf, 0xdf, 0x3e, 0xd8, 0xfa, 0xcf, 0xdb, 0x07, 0x83, 0x54, 0xd7, 0x24, + 0x85, 0x6b, 0x8b, 0x60, 0xe9, 0xb8, 0xf2, 0x64, 0xe6, 0x3d, 0xfa, 0xd1, 0x09, 0xc4, 0x09, 0x46, + 0xee, 0x78, 0x78, 0x2b, 0x45, 0xa8, 0x8a, 0xcc, 0xb7, 0x51, 0x91, 0xa9, 0xbf, 0xa3, 0x16, 0x25, + 0x8e, 0x7a, 0xfc, 0xc0, 0xf3, 0xae, 0xe9, 0x58, 0xbf, 0x93, 0x1e, 0x12, 0x4f, 0xe1, 0x62, 0x33, + 0x53, 0x60, 0x74, 0x38, 0x5b, 0x49, 0x38, 0x0f, 0x81, 0x6d, 0x9e, 0x47, 0xf3, 0x2f, 0x15, 0xc4, + 0xda, 0xcc, 0x59, 0x2b, 0x8c, 0xe8, 0x85, 0x4e, 0xa8, 0xea, 0x3b, 0x9a, 0xab, 0x52, 0x50, 0x5b, + 0x55, 0x8b, 0xad, 0xc2, 0x95, 0x19, 0x0f, 0x29, 0x9a, 0x35, 0x0b, 0x87, 0xb8, 0x72, 0x2d, 0x04, + 0xc5, 0xa5, 0x66, 0xe1, 0xd0, 0xfc, 0x6b, 0x25, 0xc9, 0x84, 0xa4, 0x68, 0xbc, 0x4f, 0x2b, 0x3f, + 0x84, 0xba, 0xe4, 0xb3, 0xa8, 0x14, 0x46, 0xc5, 0xf6, 0xbb, 0xef, 0x5f, 0x72, 0x27, 0xb0, 0x88, + 0x84, 0x81, 0xec, 0xe6, 0x31, 0x84, 0xfd, 0x1a, 0xf6, 0xe3, 0x42, 0x3a, 0x5e, 0xf9, 0x36, 0x97, + 0xa2, 0xbc, 0xdf, 0xe8, 0xc6, 0xac, 0x7f, 0x50, 0x9c, 0xec, 0x05, 0xdc, 0x9b, 0xa2, 0x3e, 0x37, + 0x5c, 0x85, 0x63, 0x9f, 0x07, 0x7c, 0x19, 0x2b, 0xa9, 0x66, 0xd0, 0xf2, 0x3c, 0xe2, 0x7a, 0x89, + 0x4c, 0xa1, 0x75, 0x67, 0x9a, 0x59, 0xd0, 0xfa, 0xcc, 0x3f, 0x61, 0x75, 0x4e, 0x23, 0xd6, 0xfb, + 0x0c, 0x22, 0xa5, 0x5a, 0xce, 0x50, 0x76, 0x02, 0xa0, 0x80, 0x24, 0x74, 0xde, 0x08, 0x5d, 0xa1, + 0xa3, 0xc8, 0x50, 0x08, 0x5f, 0x39, 0x6f, 0x84, 0x65, 0x4c, 0xa2, 0x21, 0xfb, 0x08, 0x5a, 0x72, + 0xad, 0xb8, 0xb3, 0x9d, 0xcf, 0xd5, 0x9a, 0x58, 0x9b, 0x92, 0xfe, 0xd9, 0x63, 0xd8, 0x56, 0x8a, + 0x67, 0x5e, 0x18, 0x3a, 0xbe, 0xae, 0xcd, 0x2c, 0xad, 0xfa, 0x39, 0x51, 0xac, 0xce, 0x24, 0x99, + 0x98, 0x7f, 0x04, 0x23, 0xfe, 0x2c, 0xbb, 0x0f, 0xc6, 0x92, 0xaf, 0xc7, 0x93, 0x5b, 0xb5, 0x6b, + 0x95, 0x41, 0xc3, 0x6a, 0x2f, 0xf9, 0x9a, 0xbc, 0x64, 0xf7, 0xa0, 0x85, 0x44, 0xb9, 0x56, 0x7b, + 0xd1, 0xb0, 0x9a, 0x4b, 0xbe, 0xbe, 0x5a, 0xc7, 0x04, 0xcc, 0x6a, 0xdd, 0xf3, 0x2d, 0xf9, 0xfa, + 0x39, 0x0f, 0xcd, 0x6f, 0xa0, 0xa9, 0x8c, 0xfc, 0xbf, 0x14, 0xa3, 0x7c, 0x35, 0x23, 0xff, 0x1b, + 0xe8, 0xa4, 0xec, 0x66, 0x5f, 0xc0, 0x1d, 0xe5, 0xa1, 0xcf, 0x03, 0x49, 0x11, 0xc9, 0x28, 0x64, + 0x44, 0x7c, 0xc9, 0x03, 0x89, 0x9f, 0x24, 0xd5, 0xe6, 0x3f, 0xab, 0xd0, 0x54, 0x1d, 0x22, 0xfb, + 0x08, 0x2b, 0x2f, 0x77, 0xdc, 0xb1, 0x63, 0xab, 0x22, 0x31, 0xec, 0xfc, 0xfc, 0xf6, 0x41, 0x8b, + 0x40, 0x76, 0x74, 0x81, 0xc5, 0x16, 0x07, 0x76, 0x0a, 0x5f, 0xaa, 0x19, 0x7c, 0x61, 0x50, 0x97, + 0xce, 0x52, 0x68, 0x17, 0x69, 0x8c, 0x96, 0xbb, 0xab, 0x25, 0x85, 0xa4, 0xae, 0x42, 0xe2, 0xae, + 0x96, 0x18, 0x92, 0x73, 0xd8, 0x49, 0xd5, 0x0c, 0xc7, 0xd6, 0xbd, 0xcc, 0x6e, 0x7a, 0x37, 0x46, + 0x17, 0xc3, 0xbd, 0x9f, 0xdf, 0x3e, 0xe8, 0xfc, 0x36, 0xaa, 0x20, 0xa3, 0x0b, 0xab, 0x13, 0x97, + 0x93, 0x91, 0xcd, 0x06, 0x40, 0xd5, 0x65, 0xac, 0x2a, 0xac, 0xaa, 0x3a, 0x4d, 0xaa, 0x3a, 0xbb, + 0xb8, 0xae, 0x4b, 0x30, 0x36, 0xc7, 0xf7, 0xc1, 0xc0, 0x14, 0x54, 0x2c, 0x2d, 0x62, 0x69, 0xe3, + 0x02, 0x11, 0x3f, 0x86, 0xbd, 0xa4, 0xb7, 0x55, 0x2c, 0x6d, 0xa5, 0x25, 0x59, 0x26, 0xc6, 0x0f, + 0xa0, 0x1d, 0x57, 0x37, 0x83, 0x38, 0x5a, 0x5c, 0x17, 0xb5, 0x11, 0xb4, 0xb4, 0x89, 0x85, 0xcd, + 0xf9, 0x27, 0xd0, 0xc0, 0x3d, 0x89, 0x0e, 0x69, 0xd4, 0x41, 0xd1, 0x5e, 0x08, 0xa9, 0x5b, 0x74, + 0xc5, 0x62, 0x9e, 0xc1, 0x4e, 0x66, 0x1d, 0x4b, 0x97, 0xf4, 0x24, 0x5f, 0xe8, 0x6d, 0x54, 0x93, + 0xf8, 0x33, 0xd5, 0xe4, 0x33, 0xe6, 0x57, 0x60, 0xc4, 0xe0, 0x81, 0xb1, 0xf7, 0x57, 0x93, 0x71, + 0x74, 0x25, 0xda, 0xb6, 0x9a, 0xfe, 0x6a, 0xf2, 0x9d, 0xba, 0x15, 0xf9, 0xde, 0x8f, 0xfa, 0xa2, + 0x50, 0xb3, 0xd4, 0xc4, 0xfc, 0x1a, 0xda, 0x51, 0x23, 0x5f, 0x2e, 0x5a, 0xb2, 0xf7, 0xe6, 0xdf, + 0x2a, 0xd0, 0x54, 0xd8, 0x57, 0x70, 0x0b, 0xfb, 0x82, 0xee, 0x56, 0x2b, 0x31, 0x46, 0xa7, 0x49, + 0x70, 0x37, 0x3e, 0x76, 0x4a, 0xe8, 0xf8, 0xea, 0xd6, 0x17, 0x96, 0x41, 0x5c, 0x38, 0x64, 0x1f, + 0xc2, 0xb6, 0x12, 0x09, 0x65, 0xe0, 0xb8, 0x11, 0x66, 0x74, 0x68, 0xed, 0x15, 0x2d, 0xe1, 0x96, + 0x2a, 0x16, 0xc7, 0x95, 0xba, 0x58, 0xb4, 0x69, 0x61, 0xe4, 0x4a, 0xf3, 0x3e, 0xd4, 0x49, 0x0f, + 0x40, 0xf3, 0xd5, 0x95, 0x35, 0x7a, 0xf1, 0xbc, 0xbb, 0xc5, 0x5a, 0x50, 0x1b, 0xbd, 0xb8, 0xea, + 0x56, 0x4e, 0x7f, 0x6a, 0xc0, 0xde, 0xd3, 0xe1, 0xf9, 0xe8, 0xa9, 0xef, 0x2f, 0x9c, 0x29, 0xa7, + 0xfe, 0xe3, 0x04, 0xea, 0xd4, 0x61, 0x15, 0x3c, 0x74, 0xf4, 0x8b, 0x5a, 0x7d, 0x76, 0x0a, 0x0d, + 0x6a, 0xb4, 0x58, 0xd1, 0x7b, 0x47, 0xbf, 0xb0, 0xe3, 0xc7, 0x8f, 0xa8, 0x56, 0x6c, 0xf3, 0xd9, + 0xa3, 0x5f, 0xd4, 0xf6, 0xb3, 0x6f, 0xc0, 0x48, 0x5a, 0xa4, 0xb2, 0xc7, 0x8f, 0x7e, 0xe9, 0x05, + 0x00, 0xe5, 0x93, 0xea, 0x58, 0xf6, 0x54, 0xd0, 0x2f, 0xed, 0x94, 0xd9, 0x13, 0x68, 0x45, 0x1d, + 0x40, 0xf1, 0xf3, 0x44, 0xbf, 0xa4, 0x39, 0xc7, 0xf0, 0xa8, 0x5e, 0xac, 0xe8, 0x0d, 0xa5, 0x5f, + 0x78, 0x83, 0x60, 0x8f, 0xa1, 0xa9, 0x6b, 0x50, 0xe1, 0x43, 0x43, 0xbf, 0xb8, 0xc5, 0x46, 0x27, + 0x93, 0x7b, 0x7c, 0xd9, 0x3b, 0x4f, 0xbf, 0xf4, 0xaa, 0xc3, 0x9e, 0x02, 0xa4, 0xae, 0xd6, 0xa5, + 0x0f, 0x38, 0xfd, 0xf2, 0x2b, 0x0c, 0xc3, 0xb3, 0x13, 0x5f, 0x4b, 0x8b, 0x1f, 0x56, 0xfa, 0x65, + 0xb7, 0x8a, 0x49, 0x93, 0x1e, 0xdf, 0xbe, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xb9, + 0xeb, 0x12, 0xc7, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index da46b2dc..c80261e0 100644 --- a/types/types.proto +++ b/types/types.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package types; +// For more information on gogo.proto, see: +// https://github.com/gogo/protobuf/blob/master/extensions.md import "github.com/gogo/protobuf/gogoproto/gogo.proto"; // This file is copied from http://github.com/tendermint/abci @@ -184,7 +186,7 @@ message TxSize{ // BlockGossip determine consensus critical // elements of how blocks are gossiped -message BlockGossip{ +message BlockGossip { // Note: must not be 0 int32 block_part_size_bytes = 1; } @@ -193,11 +195,11 @@ message BlockGossip{ // Blockchain Types message Header { - string chain_id = 1; + string chain_id = 1 [(gogoproto.customname) = "ChainID"]; int64 height = 2; int64 time = 3; int32 num_txs = 4; - BlockID last_block_id = 5; + BlockID last_block_id = 5 [(gogoproto.customname) = "LastBlockID"]; bytes last_commit_hash = 6; bytes data_hash = 7; bytes validators_hash = 8; From aaaacba1cd08596eba63f28a159a9bee97a664ea Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 22 Dec 2017 19:41:19 -0800 Subject: [PATCH 422/545] Use gogoproto's nullable=false (#166) * Use gogoproto's nullable=false where appropriate. --- example/dummy/dummy.go | 2 +- example/dummy/dummy_test.go | 18 +- example/dummy/helpers.go | 8 +- example/dummy/persistent_dummy.go | 14 +- tests/server/client.go | 4 +- types/types.pb.go | 279 +++++++++++++++--------------- types/types.proto | 20 +-- types/util.go | 2 +- 8 files changed, 174 insertions(+), 173 deletions(-) diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index fdb4851c..7592a7d4 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -39,7 +39,7 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { } app.state.Set(key, value) - tags := []*types.KVPair{ + tags := []types.KVPair{ {Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}, {Key: "app.key", ValueType: types.KVPair_STRING, ValueString: string(key)}, } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 96666547..530c01c2 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -92,7 +92,7 @@ func TestPersistentDummyInfo(t *testing.T) { // make and apply block height = int64(1) hash := []byte("foo") - header := &types.Header{ + header := types.Header{ Height: int64(height), } dummy.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil}) @@ -124,11 +124,11 @@ func TestValUpdates(t *testing.T) { vals1, vals2 := vals[:nInit], dummy.Validators() valsEqual(t, vals1, vals2) - var v1, v2, v3 *types.Validator + var v1, v2, v3 types.Validator // add some validators v1, v2 = vals[nInit], vals[nInit+1] - diff := []*types.Validator{v1, v2} + diff := []types.Validator{v1, v2} tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power) tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power) @@ -142,7 +142,7 @@ func TestValUpdates(t *testing.T) { v1.Power = 0 v2.Power = 0 v3.Power = 0 - diff = []*types.Validator{v1, v2, v3} + diff = []types.Validator{v1, v2, v3} tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power) tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power) @@ -160,22 +160,22 @@ func TestValUpdates(t *testing.T) { } else { v1.Power = 5 } - diff = []*types.Validator{v1} + diff = []types.Validator{v1} tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) makeApplyBlock(t, dummy, 3, diff, tx1) - vals1 = append([]*types.Validator{v1}, vals1[1:]...) + vals1 = append([]types.Validator{v1}, vals1[1:]...) vals2 = dummy.Validators() valsEqual(t, vals1, vals2) } -func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) { +func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []types.Validator, txs ...[]byte) { // make and apply block height := int64(heightInt) hash := []byte("foo") - header := &types.Header{ + header := types.Header{ Height: height, } @@ -193,7 +193,7 @@ func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff [ } // order doesn't matter -func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { +func valsEqual(t *testing.T, vals1, vals2 []types.Validator) { if len(vals1) != len(vals2) { t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1)) } diff --git a/example/dummy/helpers.go b/example/dummy/helpers.go index d6b4338c..80f94ade 100644 --- a/example/dummy/helpers.go +++ b/example/dummy/helpers.go @@ -8,18 +8,18 @@ import ( // RandVal creates one random validator, with a key derived // from the input value -func RandVal(i int) *types.Validator { +func RandVal(i int) types.Validator { pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() power := cmn.RandUint16() + 1 - return &types.Validator{pubkey, int64(power)} + return types.Validator{pubkey, int64(power)} } // RandVals returns a list of cnt validators for initializing // the application. Note that the keys are deterministically // derived from the index in the array, while the power is // random (Change this if not desired) -func RandVals(cnt int) []*types.Validator { - res := make([]*types.Validator, cnt) +func RandVals(cnt int) []types.Validator { + res := make([]types.Validator, cnt) for i := 0; i < cnt; i++ { res[i] = RandVal(i) } diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 4165b9f7..4d272246 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -28,7 +28,7 @@ type PersistentDummyApplication struct { app *DummyApplication // validator set - ValUpdates []*types.Validator + ValUpdates []types.Validator logger log.Logger } @@ -119,7 +119,7 @@ func (app *PersistentDummyApplication) InitChain(req types.RequestInitChain) typ // Track the block hash and header information func (app *PersistentDummyApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { // reset valset changes - app.ValUpdates = make([]*types.Validator, 0) + app.ValUpdates = make([]types.Validator, 0) return types.ResponseBeginBlock{} } @@ -131,7 +131,7 @@ func (app *PersistentDummyApplication) EndBlock(req types.RequestEndBlock) types //--------------------------------------------- // update validators -func (app *PersistentDummyApplication) Validators() (validators []*types.Validator) { +func (app *PersistentDummyApplication) Validators() (validators []types.Validator) { app.app.state.Iterate(func(key, value []byte) bool { if isValidatorTx(key) { validator := new(types.Validator) @@ -139,7 +139,7 @@ func (app *PersistentDummyApplication) Validators() (validators []*types.Validat if err != nil { panic(err) } - validators = append(validators, validator) + validators = append(validators, *validator) } return false }) @@ -190,11 +190,11 @@ func (app *PersistentDummyApplication) execValidatorTx(tx []byte) types.Response } // update - return app.updateValidator(&types.Validator{pubkey, power}) + return app.updateValidator(types.Validator{pubkey, power}) } // add, update, or remove a validator -func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types.ResponseDeliverTx { +func (app *PersistentDummyApplication) updateValidator(v types.Validator) types.ResponseDeliverTx { key := []byte("val:" + string(v.PubKey)) if v.Power == 0 { // remove validator @@ -207,7 +207,7 @@ func (app *PersistentDummyApplication) updateValidator(v *types.Validator) types } else { // add or update validator value := bytes.NewBuffer(make([]byte, 0)) - if err := types.WriteMessage(v, value); err != nil { + if err := types.WriteMessage(&v, value); err != nil { return types.ResponseDeliverTx{ Code: code.CodeTypeEncodingError, Log: fmt.Sprintf("Error encoding validator: %v", err)} diff --git a/tests/server/client.go b/tests/server/client.go index aaea9f34..9d85a2fa 100644 --- a/tests/server/client.go +++ b/tests/server/client.go @@ -13,11 +13,11 @@ import ( func InitChain(client abcicli.Client) error { total := 10 - vals := make([]*types.Validator, total) + vals := make([]types.Validator, total) for i := 0; i < total; i++ { pubkey := crypto.GenPrivKeyEd25519FromSecret([]byte(cmn.Fmt("test%d", i))).PubKey().Bytes() power := cmn.RandInt() - vals[i] = &types.Validator{pubkey, int64(power)} + vals[i] = types.Validator{pubkey, int64(power)} } _, err := client.InitChainSync(types.RequestInitChain{Validators: vals}) if err != nil { diff --git a/types/types.pb.go b/types/types.pb.go index 7ab18fe4..06553825 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -554,7 +554,7 @@ func (m *RequestSetOption) GetValue() string { } type RequestInitChain struct { - Validators []*Validator `protobuf:"bytes,1,rep,name=validators" json:"validators,omitempty"` + Validators []Validator `protobuf:"bytes,1,rep,name=validators" json:"validators"` } func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } @@ -562,7 +562,7 @@ func (m *RequestInitChain) String() string { return proto.CompactText func (*RequestInitChain) ProtoMessage() {} func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} } -func (m *RequestInitChain) GetValidators() []*Validator { +func (m *RequestInitChain) GetValidators() []Validator { if m != nil { return m.Validators } @@ -610,10 +610,10 @@ func (m *RequestQuery) GetProve() bool { } type RequestBeginBlock struct { - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Header *Header `protobuf:"bytes,2,opt,name=header" json:"header,omitempty"` - AbsentValidators []int32 `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators" json:"absent_validators,omitempty"` - ByzantineValidators []*Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators,omitempty"` + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header Header `protobuf:"bytes,2,opt,name=header" json:"header"` + AbsentValidators []int32 `protobuf:"varint,3,rep,packed,name=absent_validators,json=absentValidators" json:"absent_validators,omitempty"` + ByzantineValidators []Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators"` } func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } @@ -628,11 +628,11 @@ func (m *RequestBeginBlock) GetHash() []byte { return nil } -func (m *RequestBeginBlock) GetHeader() *Header { +func (m *RequestBeginBlock) GetHeader() Header { if m != nil { return m.Header } - return nil + return Header{} } func (m *RequestBeginBlock) GetAbsentValidators() []int32 { @@ -642,7 +642,7 @@ func (m *RequestBeginBlock) GetAbsentValidators() []int32 { return nil } -func (m *RequestBeginBlock) GetByzantineValidators() []*Evidence { +func (m *RequestBeginBlock) GetByzantineValidators() []Evidence { if m != nil { return m.ByzantineValidators } @@ -1344,7 +1344,7 @@ type ResponseDeliverTx struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Tags []*KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags,omitempty"` + Tags []KVPair `protobuf:"bytes,4,rep,name=tags" json:"tags"` } func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } @@ -1366,7 +1366,7 @@ func (m *ResponseDeliverTx) GetLog() string { return "" } -func (m *ResponseDeliverTx) GetTags() []*KVPair { +func (m *ResponseDeliverTx) GetTags() []KVPair { if m != nil { return m.Tags } @@ -1374,7 +1374,7 @@ func (m *ResponseDeliverTx) GetTags() []*KVPair { } type ResponseEndBlock struct { - ValidatorUpdates []*Validator `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates,omitempty"` + ValidatorUpdates []Validator `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates"` ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"` } @@ -1383,7 +1383,7 @@ func (m *ResponseEndBlock) String() string { return proto.CompactText func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} } -func (m *ResponseEndBlock) GetValidatorUpdates() []*Validator { +func (m *ResponseEndBlock) GetValidatorUpdates() []Validator { if m != nil { return m.ValidatorUpdates } @@ -1534,15 +1534,15 @@ func (m *BlockGossip) GetBlockPartSizeBytes() int32 { } type Header struct { - ChainID string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - Time int64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` - NumTxs int32 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` - LastBlockID *BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id,omitempty"` - LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` - DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` - ValidatorsHash []byte `protobuf:"bytes,8,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` - AppHash []byte `protobuf:"bytes,9,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + ChainID string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Time int64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` + NumTxs int32 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` + LastBlockID BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId" json:"last_block_id"` + LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` + DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` + ValidatorsHash []byte `protobuf:"bytes,8,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` + AppHash []byte `protobuf:"bytes,9,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } func (m *Header) Reset() { *m = Header{} } @@ -1578,11 +1578,11 @@ func (m *Header) GetNumTxs() int32 { return 0 } -func (m *Header) GetLastBlockID() *BlockID { +func (m *Header) GetLastBlockID() BlockID { if m != nil { return m.LastBlockID } - return nil + return BlockID{} } func (m *Header) GetLastCommitHash() []byte { @@ -1614,8 +1614,8 @@ func (m *Header) GetAppHash() []byte { } type BlockID struct { - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Parts *PartSetHeader `protobuf:"bytes,2,opt,name=parts" json:"parts,omitempty"` + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Parts PartSetHeader `protobuf:"bytes,2,opt,name=parts" json:"parts"` } func (m *BlockID) Reset() { *m = BlockID{} } @@ -1630,11 +1630,11 @@ func (m *BlockID) GetHash() []byte { return nil } -func (m *BlockID) GetParts() *PartSetHeader { +func (m *BlockID) GetParts() PartSetHeader { if m != nil { return m.Parts } - return nil + return PartSetHeader{} } type PartSetHeader struct { @@ -2193,116 +2193,117 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1766 bytes of a gzipped FileDescriptorProto + // 1778 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x72, 0x1b, 0xc7, - 0x11, 0x26, 0xfe, 0xb1, 0x0d, 0xfe, 0x80, 0x43, 0x4a, 0x82, 0xa1, 0x83, 0xe8, 0xad, 0x8a, 0x0d, - 0xd9, 0x16, 0x69, 0xd3, 0xa5, 0x94, 0x68, 0x27, 0xae, 0x08, 0xa4, 0x2c, 0xa2, 0x9c, 0x52, 0x94, - 0x15, 0xe3, 0x43, 0x2e, 0xa8, 0x01, 0x76, 0x08, 0x6c, 0x09, 0xd8, 0x5d, 0xef, 0x0e, 0x68, 0x50, - 0x95, 0x47, 0xf0, 0x3d, 0xe7, 0xe4, 0x98, 0x17, 0xc8, 0x31, 0xa7, 0xa4, 0xf2, 0x0c, 0x39, 0xe8, - 0xe0, 0x27, 0x49, 0x75, 0xcf, 0xec, 0x2f, 0x76, 0x53, 0x29, 0x1d, 0x74, 0x01, 0x66, 0xa6, 0x7f, - 0xb6, 0xbb, 0xa7, 0xe7, 0xeb, 0x9e, 0x81, 0x7d, 0x79, 0xeb, 0x8b, 0xf0, 0x84, 0x7e, 0x8f, 0xfd, - 0xc0, 0x93, 0x1e, 0x6b, 0xd0, 0xa4, 0xff, 0x68, 0xe6, 0xc8, 0xf9, 0x6a, 0x72, 0x3c, 0xf5, 0x96, - 0x27, 0x33, 0x6f, 0xe6, 0x9d, 0x10, 0x75, 0xb2, 0xba, 0xa6, 0x19, 0x4d, 0x68, 0xa4, 0xa4, 0xcc, - 0x7f, 0xd5, 0xa1, 0x65, 0x89, 0x1f, 0x56, 0x22, 0x94, 0x6c, 0x00, 0x75, 0x31, 0x9d, 0x7b, 0xbd, - 0xea, 0x51, 0x65, 0xd0, 0x39, 0x65, 0xc7, 0x4a, 0xbb, 0xa6, 0x3e, 0x9b, 0xce, 0xbd, 0xcb, 0x2d, - 0x8b, 0x38, 0xd8, 0xa7, 0xd0, 0xb8, 0x5e, 0xac, 0xc2, 0x79, 0xaf, 0x46, 0xac, 0x07, 0x59, 0xd6, - 0x6f, 0x91, 0x74, 0xb9, 0x65, 0x29, 0x1e, 0x54, 0xeb, 0xb8, 0xd7, 0x5e, 0xaf, 0x5e, 0xa4, 0x76, - 0xe4, 0x5e, 0x93, 0x5a, 0xe4, 0x60, 0x4f, 0x00, 0x42, 0x21, 0xc7, 0x9e, 0x2f, 0x1d, 0xcf, 0xed, - 0x35, 0x88, 0xff, 0x5e, 0x96, 0xff, 0x95, 0x90, 0xbf, 0x23, 0xf2, 0xe5, 0x96, 0x65, 0x84, 0xd1, - 0x04, 0x25, 0x1d, 0xd7, 0x91, 0xe3, 0xe9, 0x9c, 0x3b, 0x6e, 0xaf, 0x59, 0x24, 0x39, 0x72, 0x1d, - 0x79, 0x8e, 0x64, 0x94, 0x74, 0xa2, 0x09, 0xba, 0xf2, 0xc3, 0x4a, 0x04, 0xb7, 0xbd, 0x56, 0x91, - 0x2b, 0xbf, 0x47, 0x12, 0xba, 0x42, 0x3c, 0xec, 0x6b, 0xe8, 0x4c, 0xc4, 0xcc, 0x71, 0xc7, 0x93, - 0x85, 0x37, 0x7d, 0xdd, 0x6b, 0x93, 0x48, 0x2f, 0x2b, 0x32, 0x44, 0x86, 0x21, 0xd2, 0x2f, 0xb7, - 0x2c, 0x98, 0xc4, 0x33, 0x76, 0x0a, 0xed, 0xe9, 0x5c, 0x4c, 0x5f, 0x8f, 0xe5, 0xba, 0x67, 0x90, - 0xe4, 0x9d, 0xac, 0xe4, 0x39, 0x52, 0xaf, 0xd6, 0x97, 0x5b, 0x56, 0x6b, 0xaa, 0x86, 0xe8, 0x97, - 0x2d, 0x16, 0xce, 0x8d, 0x08, 0x50, 0xea, 0xa0, 0xc8, 0xaf, 0x0b, 0x45, 0x27, 0x39, 0xc3, 0x8e, - 0x26, 0xec, 0x31, 0x18, 0xc2, 0xb5, 0xb5, 0xa1, 0x1d, 0x12, 0xbc, 0x9b, 0xdb, 0x51, 0xd7, 0x8e, - 0xcc, 0x6c, 0x0b, 0x3d, 0x66, 0xc7, 0xd0, 0x9c, 0x7a, 0xcb, 0xa5, 0x23, 0x7b, 0xdb, 0x24, 0x73, - 0x98, 0x33, 0x91, 0x68, 0x97, 0x5b, 0x96, 0xe6, 0x1a, 0xb6, 0xa0, 0x71, 0xc3, 0x17, 0x2b, 0x61, - 0x7e, 0x0c, 0x9d, 0x54, 0xa6, 0xb0, 0x1e, 0xb4, 0x96, 0x22, 0x0c, 0xf9, 0x4c, 0xf4, 0x2a, 0x47, - 0x95, 0x81, 0x61, 0x45, 0x53, 0x73, 0x17, 0xb6, 0xd3, 0x79, 0x92, 0x12, 0xc4, 0x5c, 0x40, 0xc1, - 0x1b, 0x11, 0x84, 0x98, 0x00, 0x5a, 0x50, 0x4f, 0xcd, 0xaf, 0xa0, 0x9b, 0x4f, 0x02, 0xd6, 0x85, - 0xda, 0x6b, 0x71, 0xab, 0x39, 0x71, 0xc8, 0x0e, 0xb5, 0x41, 0x94, 0xc5, 0x86, 0xa5, 0xad, 0xbb, - 0x88, 0x65, 0xe3, 0x34, 0x60, 0x9f, 0x03, 0xdc, 0xf0, 0x85, 0x63, 0x73, 0xe9, 0x05, 0x61, 0xaf, - 0x72, 0x54, 0x1b, 0x74, 0x4e, 0xbb, 0xda, 0xdd, 0xef, 0x23, 0x82, 0x95, 0xe2, 0x31, 0xed, 0xd8, - 0x74, 0xca, 0x0b, 0xc6, 0xa0, 0x6e, 0x73, 0xc9, 0xe9, 0xf3, 0xdb, 0x16, 0x8d, 0x71, 0xcd, 0xe7, - 0x72, 0xae, 0x3f, 0x4f, 0x63, 0x76, 0x17, 0x9a, 0x73, 0xe1, 0xcc, 0xe6, 0x92, 0xce, 0x4b, 0xcd, - 0xd2, 0x33, 0xb4, 0xd5, 0x0f, 0xbc, 0x1b, 0x41, 0x47, 0xa3, 0x6d, 0xa9, 0x89, 0xf9, 0x8f, 0x0a, - 0xec, 0x6f, 0xe4, 0x12, 0xea, 0x9d, 0xf3, 0x70, 0x1e, 0x7d, 0x0b, 0xc7, 0xec, 0x17, 0xa8, 0x97, - 0xdb, 0x22, 0xd0, 0x47, 0x76, 0x47, 0x5b, 0x7f, 0x49, 0x8b, 0x96, 0x26, 0xb2, 0x4f, 0x61, 0x9f, - 0x4f, 0x42, 0xe1, 0xca, 0x71, 0xca, 0xdf, 0xda, 0x51, 0x6d, 0xd0, 0xb0, 0xba, 0x8a, 0x10, 0xbb, - 0x1b, 0xb2, 0x21, 0x1c, 0x4e, 0x6e, 0xdf, 0x70, 0x57, 0x3a, 0xae, 0x48, 0xf3, 0xd7, 0x29, 0x3e, - 0x7b, 0xfa, 0x0b, 0xcf, 0x6e, 0x1c, 0x5b, 0xb8, 0x53, 0x61, 0x1d, 0xc4, 0xcc, 0x89, 0x0e, 0xf3, - 0x08, 0x76, 0xb3, 0x29, 0xcd, 0x76, 0xa1, 0x2a, 0xd7, 0xda, 0xf6, 0xaa, 0x5c, 0x9b, 0x66, 0xbc, - 0x1f, 0x71, 0xfa, 0x6e, 0xf0, 0x3c, 0x84, 0xbd, 0x5c, 0xa6, 0xa6, 0x02, 0x59, 0x49, 0x07, 0xd2, - 0xdc, 0x83, 0x9d, 0x4c, 0x82, 0x9a, 0x3f, 0x35, 0xa0, 0x6d, 0x89, 0xd0, 0xf7, 0xdc, 0x50, 0xb0, - 0x27, 0x60, 0x88, 0xf5, 0x54, 0x28, 0x54, 0xa9, 0xe4, 0xce, 0xac, 0xe2, 0x79, 0x16, 0xd1, 0xf1, - 0x10, 0xc5, 0xcc, 0xec, 0x61, 0x06, 0x11, 0x0f, 0xf2, 0x42, 0x69, 0x48, 0xfc, 0x2c, 0x0b, 0x89, - 0x87, 0x39, 0xde, 0x1c, 0x26, 0x3e, 0xcc, 0x60, 0x62, 0x5e, 0x71, 0x06, 0x14, 0xcf, 0x0a, 0x40, - 0x31, 0x6f, 0x7e, 0x09, 0x2a, 0x9e, 0x15, 0xa0, 0x62, 0x6f, 0xe3, 0x5b, 0x85, 0xb0, 0xf8, 0x59, - 0x16, 0x16, 0xf3, 0xee, 0xe4, 0x70, 0xf1, 0x57, 0x45, 0xb8, 0xf8, 0x41, 0x4e, 0xa6, 0x14, 0x18, - 0xbf, 0xdc, 0x00, 0xc6, 0xbb, 0x39, 0xd1, 0x02, 0x64, 0x3c, 0xcb, 0x20, 0x23, 0x14, 0xfa, 0x56, - 0x02, 0x8d, 0xbf, 0xdc, 0x84, 0xc6, 0x7b, 0xf9, 0xad, 0x2d, 0xc2, 0xc6, 0x93, 0x1c, 0x36, 0xde, - 0xc9, 0x5b, 0x59, 0x0a, 0x8e, 0x0f, 0xf1, 0x44, 0xe7, 0x32, 0x0d, 0x4f, 0xbf, 0x08, 0x02, 0x2f, - 0xd0, 0xe8, 0xa5, 0x26, 0xe6, 0x00, 0x31, 0x26, 0xc9, 0xaf, 0xff, 0x01, 0xa4, 0x94, 0xf4, 0xa9, - 0xec, 0x32, 0xff, 0x5c, 0x49, 0x64, 0x09, 0x4b, 0xd3, 0xf8, 0x64, 0x68, 0x7c, 0x4a, 0xe1, 0x6b, - 0x35, 0x83, 0xaf, 0xec, 0x13, 0xd8, 0x5f, 0xf0, 0x50, 0xaa, 0xb8, 0x8c, 0x33, 0x80, 0xb5, 0x87, - 0x04, 0x15, 0x10, 0x85, 0x5c, 0x8f, 0xe0, 0x20, 0xc5, 0xcb, 0x7d, 0x7f, 0x4c, 0xe0, 0x54, 0xa7, - 0xc3, 0xdb, 0x8d, 0xb9, 0x9f, 0xfa, 0xfe, 0x25, 0x0f, 0xe7, 0xe6, 0x59, 0xe2, 0x7f, 0x82, 0xdd, - 0x0c, 0xea, 0x53, 0xcf, 0x56, 0x6e, 0xed, 0x58, 0x34, 0x46, 0x3c, 0x5f, 0x78, 0x33, 0x6d, 0x19, - 0x0e, 0xcd, 0x83, 0x44, 0x34, 0x4e, 0x55, 0xf3, 0xef, 0xd5, 0xc4, 0xf7, 0x18, 0x8a, 0x37, 0x94, - 0x1d, 0x42, 0xc3, 0x71, 0x6d, 0xb1, 0x26, 0x75, 0x35, 0x4b, 0x4d, 0xd8, 0x50, 0x95, 0x0c, 0x74, - 0x6c, 0x7b, 0xf8, 0xf9, 0xbf, 0xdf, 0x3e, 0xd8, 0xfa, 0xcf, 0xdb, 0x07, 0x83, 0x54, 0xd7, 0x24, - 0x85, 0x6b, 0x8b, 0x60, 0xe9, 0xb8, 0xf2, 0x64, 0xe6, 0x3d, 0xfa, 0xd1, 0x09, 0xc4, 0x09, 0x46, - 0xee, 0x78, 0x78, 0x2b, 0x45, 0xa8, 0x8a, 0xcc, 0xb7, 0x51, 0x91, 0xa9, 0xbf, 0xa3, 0x16, 0x25, - 0x8e, 0x7a, 0xfc, 0xc0, 0xf3, 0xae, 0xe9, 0x58, 0xbf, 0x93, 0x1e, 0x12, 0x4f, 0xe1, 0x62, 0x33, - 0x53, 0x60, 0x74, 0x38, 0x5b, 0x49, 0x38, 0x0f, 0x81, 0x6d, 0x9e, 0x47, 0xf3, 0x2f, 0x15, 0xc4, - 0xda, 0xcc, 0x59, 0x2b, 0x8c, 0xe8, 0x85, 0x4e, 0xa8, 0xea, 0x3b, 0x9a, 0xab, 0x52, 0x50, 0x5b, - 0x55, 0x8b, 0xad, 0xc2, 0x95, 0x19, 0x0f, 0x29, 0x9a, 0x35, 0x0b, 0x87, 0xb8, 0x72, 0x2d, 0x04, - 0xc5, 0xa5, 0x66, 0xe1, 0xd0, 0xfc, 0x6b, 0x25, 0xc9, 0x84, 0xa4, 0x68, 0xbc, 0x4f, 0x2b, 0x3f, - 0x84, 0xba, 0xe4, 0xb3, 0xa8, 0x14, 0x46, 0xc5, 0xf6, 0xbb, 0xef, 0x5f, 0x72, 0x27, 0xb0, 0x88, - 0x84, 0x81, 0xec, 0xe6, 0x31, 0x84, 0xfd, 0x1a, 0xf6, 0xe3, 0x42, 0x3a, 0x5e, 0xf9, 0x36, 0x97, - 0xa2, 0xbc, 0xdf, 0xe8, 0xc6, 0xac, 0x7f, 0x50, 0x9c, 0xec, 0x05, 0xdc, 0x9b, 0xa2, 0x3e, 0x37, - 0x5c, 0x85, 0x63, 0x9f, 0x07, 0x7c, 0x19, 0x2b, 0xa9, 0x66, 0xd0, 0xf2, 0x3c, 0xe2, 0x7a, 0x89, - 0x4c, 0xa1, 0x75, 0x67, 0x9a, 0x59, 0xd0, 0xfa, 0xcc, 0x3f, 0x61, 0x75, 0x4e, 0x23, 0xd6, 0xfb, - 0x0c, 0x22, 0xa5, 0x5a, 0xce, 0x50, 0x76, 0x02, 0xa0, 0x80, 0x24, 0x74, 0xde, 0x08, 0x5d, 0xa1, - 0xa3, 0xc8, 0x50, 0x08, 0x5f, 0x39, 0x6f, 0x84, 0x65, 0x4c, 0xa2, 0x21, 0xfb, 0x08, 0x5a, 0x72, - 0xad, 0xb8, 0xb3, 0x9d, 0xcf, 0xd5, 0x9a, 0x58, 0x9b, 0x92, 0xfe, 0xd9, 0x63, 0xd8, 0x56, 0x8a, - 0x67, 0x5e, 0x18, 0x3a, 0xbe, 0xae, 0xcd, 0x2c, 0xad, 0xfa, 0x39, 0x51, 0xac, 0xce, 0x24, 0x99, - 0x98, 0x7f, 0x04, 0x23, 0xfe, 0x2c, 0xbb, 0x0f, 0xc6, 0x92, 0xaf, 0xc7, 0x93, 0x5b, 0xb5, 0x6b, - 0x95, 0x41, 0xc3, 0x6a, 0x2f, 0xf9, 0x9a, 0xbc, 0x64, 0xf7, 0xa0, 0x85, 0x44, 0xb9, 0x56, 0x7b, - 0xd1, 0xb0, 0x9a, 0x4b, 0xbe, 0xbe, 0x5a, 0xc7, 0x04, 0xcc, 0x6a, 0xdd, 0xf3, 0x2d, 0xf9, 0xfa, - 0x39, 0x0f, 0xcd, 0x6f, 0xa0, 0xa9, 0x8c, 0xfc, 0xbf, 0x14, 0xa3, 0x7c, 0x35, 0x23, 0xff, 0x1b, - 0xe8, 0xa4, 0xec, 0x66, 0x5f, 0xc0, 0x1d, 0xe5, 0xa1, 0xcf, 0x03, 0x49, 0x11, 0xc9, 0x28, 0x64, - 0x44, 0x7c, 0xc9, 0x03, 0x89, 0x9f, 0x24, 0xd5, 0xe6, 0x3f, 0xab, 0xd0, 0x54, 0x1d, 0x22, 0xfb, - 0x08, 0x2b, 0x2f, 0x77, 0xdc, 0xb1, 0x63, 0xab, 0x22, 0x31, 0xec, 0xfc, 0xfc, 0xf6, 0x41, 0x8b, - 0x40, 0x76, 0x74, 0x81, 0xc5, 0x16, 0x07, 0x76, 0x0a, 0x5f, 0xaa, 0x19, 0x7c, 0x61, 0x50, 0x97, - 0xce, 0x52, 0x68, 0x17, 0x69, 0x8c, 0x96, 0xbb, 0xab, 0x25, 0x85, 0xa4, 0xae, 0x42, 0xe2, 0xae, - 0x96, 0x18, 0x92, 0x73, 0xd8, 0x49, 0xd5, 0x0c, 0xc7, 0xd6, 0xbd, 0xcc, 0x6e, 0x7a, 0x37, 0x46, - 0x17, 0xc3, 0xbd, 0x9f, 0xdf, 0x3e, 0xe8, 0xfc, 0x36, 0xaa, 0x20, 0xa3, 0x0b, 0xab, 0x13, 0x97, - 0x93, 0x91, 0xcd, 0x06, 0x40, 0xd5, 0x65, 0xac, 0x2a, 0xac, 0xaa, 0x3a, 0x4d, 0xaa, 0x3a, 0xbb, - 0xb8, 0xae, 0x4b, 0x30, 0x36, 0xc7, 0xf7, 0xc1, 0xc0, 0x14, 0x54, 0x2c, 0x2d, 0x62, 0x69, 0xe3, - 0x02, 0x11, 0x3f, 0x86, 0xbd, 0xa4, 0xb7, 0x55, 0x2c, 0x6d, 0xa5, 0x25, 0x59, 0x26, 0xc6, 0x0f, - 0xa0, 0x1d, 0x57, 0x37, 0x83, 0x38, 0x5a, 0x5c, 0x17, 0xb5, 0x11, 0xb4, 0xb4, 0x89, 0x85, 0xcd, - 0xf9, 0x27, 0xd0, 0xc0, 0x3d, 0x89, 0x0e, 0x69, 0xd4, 0x41, 0xd1, 0x5e, 0x08, 0xa9, 0x5b, 0x74, - 0xc5, 0x62, 0x9e, 0xc1, 0x4e, 0x66, 0x1d, 0x4b, 0x97, 0xf4, 0x24, 0x5f, 0xe8, 0x6d, 0x54, 0x93, - 0xf8, 0x33, 0xd5, 0xe4, 0x33, 0xe6, 0x57, 0x60, 0xc4, 0xe0, 0x81, 0xb1, 0xf7, 0x57, 0x93, 0x71, - 0x74, 0x25, 0xda, 0xb6, 0x9a, 0xfe, 0x6a, 0xf2, 0x9d, 0xba, 0x15, 0xf9, 0xde, 0x8f, 0xfa, 0xa2, - 0x50, 0xb3, 0xd4, 0xc4, 0xfc, 0x1a, 0xda, 0x51, 0x23, 0x5f, 0x2e, 0x5a, 0xb2, 0xf7, 0xe6, 0xdf, - 0x2a, 0xd0, 0x54, 0xd8, 0x57, 0x70, 0x0b, 0xfb, 0x82, 0xee, 0x56, 0x2b, 0x31, 0x46, 0xa7, 0x49, - 0x70, 0x37, 0x3e, 0x76, 0x4a, 0xe8, 0xf8, 0xea, 0xd6, 0x17, 0x96, 0x41, 0x5c, 0x38, 0x64, 0x1f, - 0xc2, 0xb6, 0x12, 0x09, 0x65, 0xe0, 0xb8, 0x11, 0x66, 0x74, 0x68, 0xed, 0x15, 0x2d, 0xe1, 0x96, - 0x2a, 0x16, 0xc7, 0x95, 0xba, 0x58, 0xb4, 0x69, 0x61, 0xe4, 0x4a, 0xf3, 0x3e, 0xd4, 0x49, 0x0f, - 0x40, 0xf3, 0xd5, 0x95, 0x35, 0x7a, 0xf1, 0xbc, 0xbb, 0xc5, 0x5a, 0x50, 0x1b, 0xbd, 0xb8, 0xea, - 0x56, 0x4e, 0x7f, 0x6a, 0xc0, 0xde, 0xd3, 0xe1, 0xf9, 0xe8, 0xa9, 0xef, 0x2f, 0x9c, 0x29, 0xa7, - 0xfe, 0xe3, 0x04, 0xea, 0xd4, 0x61, 0x15, 0x3c, 0x74, 0xf4, 0x8b, 0x5a, 0x7d, 0x76, 0x0a, 0x0d, - 0x6a, 0xb4, 0x58, 0xd1, 0x7b, 0x47, 0xbf, 0xb0, 0xe3, 0xc7, 0x8f, 0xa8, 0x56, 0x6c, 0xf3, 0xd9, - 0xa3, 0x5f, 0xd4, 0xf6, 0xb3, 0x6f, 0xc0, 0x48, 0x5a, 0xa4, 0xb2, 0xc7, 0x8f, 0x7e, 0xe9, 0x05, - 0x00, 0xe5, 0x93, 0xea, 0x58, 0xf6, 0x54, 0xd0, 0x2f, 0xed, 0x94, 0xd9, 0x13, 0x68, 0x45, 0x1d, - 0x40, 0xf1, 0xf3, 0x44, 0xbf, 0xa4, 0x39, 0xc7, 0xf0, 0xa8, 0x5e, 0xac, 0xe8, 0x0d, 0xa5, 0x5f, - 0x78, 0x83, 0x60, 0x8f, 0xa1, 0xa9, 0x6b, 0x50, 0xe1, 0x43, 0x43, 0xbf, 0xb8, 0xc5, 0x46, 0x27, - 0x93, 0x7b, 0x7c, 0xd9, 0x3b, 0x4f, 0xbf, 0xf4, 0xaa, 0xc3, 0x9e, 0x02, 0xa4, 0xae, 0xd6, 0xa5, - 0x0f, 0x38, 0xfd, 0xf2, 0x2b, 0x0c, 0xc3, 0xb3, 0x13, 0x5f, 0x4b, 0x8b, 0x1f, 0x56, 0xfa, 0x65, - 0xb7, 0x8a, 0x49, 0x93, 0x1e, 0xdf, 0xbe, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xb9, - 0xeb, 0x12, 0xc7, 0x13, 0x00, 0x00, + 0x11, 0x26, 0xfe, 0xb1, 0x0d, 0xfe, 0x0e, 0x29, 0x09, 0x86, 0x0e, 0x62, 0xf6, 0x60, 0x41, 0x91, + 0x45, 0xda, 0x74, 0xc9, 0x25, 0xda, 0x29, 0x57, 0x04, 0x52, 0x16, 0x10, 0xa7, 0x64, 0x65, 0xc5, + 0xf8, 0x90, 0x0b, 0x6a, 0x80, 0x1d, 0x02, 0x5b, 0x02, 0x76, 0xd7, 0xbb, 0x03, 0x1a, 0x54, 0xe5, + 0x11, 0x7c, 0xcf, 0x39, 0xa7, 0xa4, 0xf2, 0x02, 0x79, 0x83, 0x54, 0x52, 0x79, 0x83, 0x1c, 0x78, + 0xf0, 0x93, 0xa4, 0xba, 0x67, 0xf6, 0x97, 0xbb, 0x89, 0x4b, 0x07, 0x5f, 0x80, 0x99, 0xe9, 0x9f, + 0xed, 0xee, 0xe9, 0xf9, 0xba, 0x67, 0x60, 0x4f, 0x5e, 0xfb, 0x22, 0x3c, 0xa6, 0xdf, 0x23, 0x3f, + 0xf0, 0xa4, 0xc7, 0x1a, 0x34, 0xe9, 0x3d, 0x99, 0x39, 0x72, 0xbe, 0x9a, 0x1c, 0x4d, 0xbd, 0xe5, + 0xf1, 0xcc, 0x9b, 0x79, 0xc7, 0x44, 0x9d, 0xac, 0x2e, 0x69, 0x46, 0x13, 0x1a, 0x29, 0x29, 0xf3, + 0x1f, 0x75, 0x68, 0x59, 0xe2, 0xbb, 0x95, 0x08, 0x25, 0xeb, 0x43, 0x5d, 0x4c, 0xe7, 0x5e, 0xb7, + 0x7a, 0x58, 0xe9, 0x77, 0x4e, 0xd8, 0x91, 0xd2, 0xae, 0xa9, 0x2f, 0xa6, 0x73, 0x6f, 0xb8, 0x61, + 0x11, 0x07, 0x7b, 0x0c, 0x8d, 0xcb, 0xc5, 0x2a, 0x9c, 0x77, 0x6b, 0xc4, 0xba, 0x9f, 0x65, 0xfd, + 0x0a, 0x49, 0xc3, 0x0d, 0x4b, 0xf1, 0xa0, 0x5a, 0xc7, 0xbd, 0xf4, 0xba, 0xf5, 0x22, 0xb5, 0x23, + 0xf7, 0x92, 0xd4, 0x22, 0x07, 0x7b, 0x06, 0x10, 0x0a, 0x39, 0xf6, 0x7c, 0xe9, 0x78, 0x6e, 0xb7, + 0x41, 0xfc, 0xf7, 0xb2, 0xfc, 0x6f, 0x84, 0xfc, 0x86, 0xc8, 0xc3, 0x0d, 0xcb, 0x08, 0xa3, 0x09, + 0x4a, 0x3a, 0xae, 0x23, 0xc7, 0xd3, 0x39, 0x77, 0xdc, 0x6e, 0xb3, 0x48, 0x72, 0xe4, 0x3a, 0xf2, + 0x0c, 0xc9, 0x28, 0xe9, 0x44, 0x13, 0x74, 0xe5, 0xbb, 0x95, 0x08, 0xae, 0xbb, 0xad, 0x22, 0x57, + 0x7e, 0x87, 0x24, 0x74, 0x85, 0x78, 0xd8, 0x17, 0xd0, 0x99, 0x88, 0x99, 0xe3, 0x8e, 0x27, 0x0b, + 0x6f, 0xfa, 0xb6, 0xdb, 0x26, 0x91, 0x6e, 0x56, 0x64, 0x80, 0x0c, 0x03, 0xa4, 0x0f, 0x37, 0x2c, + 0x98, 0xc4, 0x33, 0x76, 0x02, 0xed, 0xe9, 0x5c, 0x4c, 0xdf, 0x8e, 0xe5, 0xba, 0x6b, 0x90, 0xe4, + 0x9d, 0xac, 0xe4, 0x19, 0x52, 0x2f, 0xd6, 0xc3, 0x0d, 0xab, 0x35, 0x55, 0x43, 0xf4, 0xcb, 0x16, + 0x0b, 0xe7, 0x4a, 0x04, 0x28, 0xb5, 0x5f, 0xe4, 0xd7, 0xb9, 0xa2, 0x93, 0x9c, 0x61, 0x47, 0x13, + 0xf6, 0x14, 0x0c, 0xe1, 0xda, 0xda, 0xd0, 0x0e, 0x09, 0xde, 0xcd, 0xed, 0xa8, 0x6b, 0x47, 0x66, + 0xb6, 0x85, 0x1e, 0xb3, 0x23, 0x68, 0x4e, 0xbd, 0xe5, 0xd2, 0x91, 0xdd, 0x4d, 0x92, 0x39, 0xc8, + 0x99, 0x48, 0xb4, 0xe1, 0x86, 0xa5, 0xb9, 0x06, 0x2d, 0x68, 0x5c, 0xf1, 0xc5, 0x4a, 0x98, 0x0f, + 0xa1, 0x93, 0xca, 0x14, 0xd6, 0x85, 0xd6, 0x52, 0x84, 0x21, 0x9f, 0x89, 0x6e, 0xe5, 0xb0, 0xd2, + 0x37, 0xac, 0x68, 0x6a, 0x6e, 0xc3, 0x66, 0x3a, 0x4f, 0x52, 0x82, 0x98, 0x0b, 0x28, 0x78, 0x25, + 0x82, 0x10, 0x13, 0x40, 0x0b, 0xea, 0xa9, 0xf9, 0x39, 0xec, 0xe6, 0x93, 0x80, 0xed, 0x42, 0xed, + 0xad, 0xb8, 0xd6, 0x9c, 0x38, 0x64, 0x07, 0xda, 0x20, 0xca, 0x62, 0xc3, 0xd2, 0xd6, 0xfd, 0x26, + 0x96, 0x8d, 0xd3, 0x80, 0x7d, 0x06, 0x70, 0xc5, 0x17, 0x8e, 0xcd, 0xa5, 0x17, 0x84, 0xdd, 0xca, + 0x61, 0xad, 0xdf, 0x39, 0xd9, 0xd5, 0xee, 0x7e, 0x1b, 0x11, 0x06, 0xf5, 0x7f, 0xde, 0x3c, 0xd8, + 0xb0, 0x52, 0x9c, 0xa6, 0x1d, 0x3b, 0x40, 0xd9, 0xc1, 0x18, 0xd4, 0x6d, 0x2e, 0x39, 0x19, 0xb1, + 0x69, 0xd1, 0x18, 0xd7, 0x7c, 0x2e, 0xe7, 0xda, 0x08, 0x1a, 0xb3, 0xbb, 0xd0, 0x9c, 0x0b, 0x67, + 0x36, 0x97, 0x74, 0x6a, 0x6a, 0x96, 0x9e, 0xa1, 0xc5, 0x7e, 0xe0, 0x5d, 0x09, 0x3a, 0x20, 0x6d, + 0x4b, 0x4d, 0xcc, 0x7f, 0x57, 0x60, 0xef, 0x56, 0x46, 0xa1, 0xde, 0x39, 0x0f, 0xe7, 0xd1, 0xb7, + 0x70, 0xcc, 0x1e, 0xa3, 0x5e, 0x6e, 0x8b, 0x40, 0x1f, 0xdc, 0x2d, 0xed, 0xc3, 0x90, 0x16, 0xb5, + 0x03, 0x9a, 0x85, 0x3d, 0x86, 0x3d, 0x3e, 0x09, 0x85, 0x2b, 0xc7, 0x29, 0xdf, 0x6b, 0x87, 0xb5, + 0x7e, 0xc3, 0xda, 0x55, 0x84, 0xd8, 0xf5, 0x90, 0x0d, 0xe1, 0x60, 0x72, 0xfd, 0x8e, 0xbb, 0xd2, + 0x71, 0x45, 0x9a, 0xbf, 0x4e, 0xb1, 0xda, 0xd1, 0xdf, 0x79, 0x71, 0xe5, 0xd8, 0xc2, 0x9d, 0x0a, + 0xfd, 0xa5, 0xfd, 0x58, 0x24, 0xd1, 0x64, 0x1e, 0xc2, 0x76, 0x36, 0xc9, 0xd9, 0x36, 0x54, 0xe5, + 0x5a, 0xfb, 0x51, 0x95, 0x6b, 0xd3, 0x8c, 0x77, 0x28, 0x4e, 0xe8, 0x5b, 0x3c, 0x8f, 0x60, 0x27, + 0x97, 0xbb, 0xa9, 0xa0, 0x56, 0xd2, 0x41, 0x35, 0x77, 0x60, 0x2b, 0x93, 0xb2, 0xe6, 0x0f, 0x0d, + 0x68, 0x5b, 0x22, 0xf4, 0x3d, 0x37, 0x14, 0xec, 0x19, 0x18, 0x62, 0x3d, 0x15, 0x0a, 0x67, 0x2a, + 0xb9, 0x53, 0xac, 0x78, 0x5e, 0x44, 0x74, 0x3c, 0x56, 0x31, 0x33, 0x7b, 0x94, 0xc1, 0xc8, 0xfd, + 0xbc, 0x50, 0x1a, 0x24, 0x3f, 0xca, 0x82, 0xe4, 0x41, 0x8e, 0x37, 0x87, 0x92, 0x8f, 0x32, 0x28, + 0x99, 0x57, 0x9c, 0x81, 0xc9, 0xd3, 0x02, 0x98, 0xcc, 0x9b, 0x5f, 0x82, 0x93, 0xa7, 0x05, 0x38, + 0xd9, 0xbd, 0xf5, 0xad, 0x42, 0xa0, 0xfc, 0x28, 0x0b, 0x94, 0x79, 0x77, 0x72, 0x48, 0xf9, 0xab, + 0x22, 0xa4, 0xfc, 0x20, 0x27, 0x53, 0x0a, 0x95, 0x9f, 0xde, 0x82, 0xca, 0xbb, 0x39, 0xd1, 0x02, + 0xac, 0x3c, 0xcd, 0x60, 0x25, 0x14, 0xfa, 0x56, 0x02, 0x96, 0x9f, 0xdd, 0x06, 0xcb, 0x7b, 0xf9, + 0xad, 0x2d, 0x42, 0xcb, 0xe3, 0x1c, 0x5a, 0xde, 0xc9, 0x5b, 0x59, 0x0a, 0x97, 0x8f, 0xf0, 0x74, + 0xe7, 0x32, 0x0d, 0x91, 0x40, 0x04, 0x81, 0x17, 0x68, 0x3c, 0x53, 0x13, 0xb3, 0x8f, 0x78, 0x93, + 0xe4, 0xd7, 0xff, 0x80, 0x56, 0x4a, 0xfa, 0x54, 0x76, 0x99, 0x7f, 0xaa, 0x24, 0xb2, 0x84, 0xae, + 0x69, 0xac, 0x32, 0x34, 0x56, 0xa5, 0x10, 0xb7, 0x9a, 0x41, 0x5c, 0xf6, 0x4b, 0xd8, 0x5b, 0xf0, + 0x50, 0xaa, 0xb8, 0x8c, 0x33, 0xe0, 0xb5, 0x83, 0x04, 0x15, 0x10, 0x85, 0x62, 0x4f, 0x60, 0x3f, + 0xc5, 0xcb, 0x7d, 0x7f, 0x4c, 0x40, 0x55, 0xa7, 0xc3, 0xbb, 0x1b, 0x73, 0x3f, 0xf7, 0xfd, 0x21, + 0x0f, 0xe7, 0xe6, 0x69, 0xe2, 0x7f, 0x82, 0xe6, 0x0c, 0xea, 0x53, 0xcf, 0x56, 0x6e, 0x6d, 0x59, + 0x34, 0x46, 0x84, 0x5f, 0x78, 0x33, 0x6d, 0x19, 0x0e, 0xcd, 0xfd, 0x44, 0x34, 0x4e, 0x55, 0xf3, + 0xef, 0xd5, 0xc4, 0xf7, 0x18, 0x96, 0x6f, 0x29, 0x3b, 0x80, 0x86, 0xe3, 0xda, 0x62, 0x4d, 0xea, + 0x6a, 0x96, 0x9a, 0xb0, 0x81, 0x2a, 0x22, 0xe8, 0xd8, 0xe6, 0xe0, 0x63, 0x04, 0xb1, 0xff, 0xdc, + 0x3c, 0xe8, 0xa7, 0xfa, 0x28, 0x29, 0x5c, 0x5b, 0x04, 0x4b, 0xc7, 0x95, 0xc7, 0x33, 0xef, 0xc9, + 0xf7, 0x4e, 0x20, 0x8e, 0x31, 0x72, 0x47, 0x83, 0x6b, 0x29, 0x42, 0x55, 0x76, 0xbe, 0x8a, 0xca, + 0x4e, 0xfd, 0x3d, 0xb5, 0x28, 0x71, 0xd4, 0xe3, 0x07, 0x9e, 0x77, 0x49, 0xc7, 0xfa, 0xbd, 0xf4, + 0x90, 0x78, 0x0a, 0x17, 0x9b, 0x99, 0x62, 0xa3, 0xc3, 0xd9, 0x4a, 0xc2, 0x79, 0x00, 0xec, 0xf6, + 0x79, 0x34, 0xff, 0x5c, 0x41, 0xac, 0xcd, 0x9c, 0xb5, 0xc2, 0x88, 0x9e, 0xeb, 0x84, 0xaa, 0xbe, + 0xa7, 0xb9, 0x2a, 0x05, 0xb5, 0x55, 0xb5, 0xd8, 0x2a, 0x5c, 0x99, 0xf1, 0x90, 0xa2, 0x59, 0xb3, + 0x70, 0x88, 0x2b, 0x97, 0x42, 0x50, 0x5c, 0x6a, 0x16, 0x0e, 0xcd, 0xbf, 0x56, 0x92, 0x4c, 0x48, + 0x8a, 0xc6, 0xcf, 0x69, 0xe5, 0x43, 0xa8, 0x4b, 0x3e, 0x8b, 0x0a, 0x62, 0x54, 0x78, 0xbf, 0xfe, + 0xf6, 0x35, 0x77, 0xa2, 0xc2, 0x4b, 0x0c, 0xe6, 0x5f, 0x2a, 0x58, 0xde, 0xb2, 0x48, 0xc2, 0xce, + 0x60, 0x2f, 0x2e, 0xaa, 0xe3, 0x95, 0x6f, 0x73, 0x29, 0xfe, 0x5f, 0x1f, 0xb2, 0x1b, 0x0b, 0xfc, + 0x5e, 0xf1, 0xb3, 0x57, 0x70, 0x6f, 0x8a, 0x5a, 0xdd, 0x70, 0x15, 0x8e, 0x7d, 0x1e, 0xf0, 0x65, + 0xac, 0xaa, 0x9a, 0x41, 0xce, 0xb3, 0x88, 0xeb, 0x35, 0x32, 0x85, 0xd6, 0x9d, 0x69, 0x66, 0x41, + 0xeb, 0x33, 0xff, 0x88, 0x95, 0x3a, 0x8d, 0x5e, 0x3f, 0x67, 0x40, 0x29, 0xed, 0x72, 0x86, 0xb2, + 0x63, 0x00, 0x05, 0x2a, 0xa1, 0xf3, 0x4e, 0xe8, 0x6a, 0x1d, 0xc5, 0x87, 0x02, 0xf9, 0xc6, 0x79, + 0x27, 0x2c, 0x63, 0x12, 0x0d, 0xd9, 0x87, 0xd0, 0x92, 0x6b, 0xc5, 0x9d, 0xed, 0x88, 0x2e, 0xd6, + 0xc4, 0xda, 0x94, 0xf4, 0xcf, 0x9e, 0xc2, 0xa6, 0x52, 0x3c, 0xf3, 0xc2, 0xd0, 0xf1, 0x75, 0x9d, + 0x66, 0x69, 0xd5, 0x2f, 0x89, 0x62, 0x75, 0x26, 0xc9, 0xc4, 0xfc, 0x03, 0x18, 0xf1, 0x67, 0xd9, + 0x7d, 0x30, 0x96, 0x7c, 0x3d, 0x9e, 0x5c, 0xab, 0xbd, 0xab, 0xf4, 0x1b, 0x56, 0x7b, 0xc9, 0xd7, + 0xe4, 0x25, 0xbb, 0x07, 0x2d, 0x24, 0xca, 0xb5, 0xda, 0x8b, 0x86, 0xd5, 0x5c, 0xf2, 0xf5, 0xc5, + 0x3a, 0x26, 0x60, 0x86, 0xeb, 0x5e, 0x70, 0xc9, 0xd7, 0x2f, 0x79, 0x68, 0x7e, 0x09, 0x4d, 0x65, + 0xe4, 0x4f, 0x52, 0x8c, 0xf2, 0xd5, 0x8c, 0xfc, 0xaf, 0xa1, 0x93, 0xb2, 0x9b, 0x7d, 0x02, 0x77, + 0x94, 0x87, 0x3e, 0x0f, 0x24, 0x45, 0x24, 0xa3, 0x90, 0x11, 0xf1, 0x35, 0x0f, 0x24, 0x7e, 0x92, + 0x54, 0x9b, 0xff, 0xaa, 0x42, 0x53, 0x75, 0x8e, 0xec, 0x43, 0xac, 0xc2, 0xdc, 0x71, 0xc7, 0x8e, + 0xad, 0x0a, 0xc6, 0xa0, 0xf3, 0xe3, 0xcd, 0x83, 0x16, 0x01, 0xee, 0xe8, 0x1c, 0x0b, 0x2f, 0x0e, + 0xec, 0x14, 0xd6, 0x54, 0x33, 0x58, 0xc3, 0xa0, 0x2e, 0x9d, 0xa5, 0xd0, 0x2e, 0xd2, 0x18, 0x2d, + 0x77, 0x57, 0x4b, 0x0a, 0x49, 0x5d, 0x85, 0xc4, 0x5d, 0x2d, 0x31, 0x24, 0x2f, 0x61, 0x2b, 0x55, + 0x3f, 0x1c, 0x5b, 0xf7, 0x35, 0xdb, 0xe9, 0xdd, 0x18, 0x9d, 0x0f, 0xf6, 0x31, 0xd5, 0x7e, 0xbc, + 0x79, 0xd0, 0xf9, 0x6d, 0x54, 0x51, 0x46, 0xe7, 0x56, 0x27, 0x2e, 0x2f, 0x23, 0x9b, 0xf5, 0x81, + 0xaa, 0xcd, 0x58, 0x55, 0x5c, 0x55, 0x85, 0x9a, 0x54, 0x85, 0xb6, 0x71, 0x5d, 0x97, 0x64, 0x6c, + 0x9c, 0xef, 0x83, 0x81, 0x69, 0xa8, 0x58, 0x5a, 0xc4, 0xd2, 0xc6, 0x05, 0x22, 0x3e, 0x84, 0x9d, + 0xa4, 0xe3, 0x55, 0x2c, 0x6d, 0xa5, 0x25, 0x59, 0x26, 0xc6, 0x0f, 0xa0, 0x1d, 0x57, 0x3b, 0x83, + 0x38, 0x5a, 0x5c, 0x17, 0xb9, 0x6f, 0xa0, 0xa5, 0x4d, 0x2c, 0x6c, 0xdc, 0x3f, 0x86, 0x06, 0xee, + 0x4b, 0x74, 0x50, 0xa3, 0x8e, 0x8a, 0xf6, 0x43, 0xc8, 0x4c, 0xfb, 0xae, 0x18, 0xcd, 0x53, 0xd8, + 0xca, 0x50, 0xb1, 0xa0, 0x49, 0x4f, 0xf2, 0x85, 0xde, 0x50, 0x35, 0x89, 0x3f, 0x56, 0x4d, 0x3e, + 0x66, 0x7e, 0x0e, 0x46, 0x0c, 0x26, 0xb8, 0x0b, 0xfe, 0x6a, 0x32, 0x8e, 0xae, 0x4e, 0x9b, 0x56, + 0xd3, 0x5f, 0x4d, 0xbe, 0x56, 0xb7, 0x27, 0xdf, 0xfb, 0x5e, 0x5f, 0x25, 0x6a, 0x96, 0x9a, 0x98, + 0x5f, 0x40, 0x3b, 0x6a, 0xf2, 0xcb, 0x45, 0x4b, 0xb2, 0xc0, 0xfc, 0x5b, 0x05, 0x9a, 0x0a, 0x11, + 0x0b, 0x6e, 0x6b, 0x9f, 0xd0, 0x1d, 0x6c, 0x25, 0xc6, 0xe8, 0x3a, 0x09, 0x6e, 0xc7, 0x07, 0x50, + 0x09, 0x1d, 0x5d, 0x5c, 0xfb, 0xc2, 0x32, 0x88, 0x0b, 0x87, 0xec, 0x17, 0xb0, 0xa9, 0x44, 0x42, + 0x19, 0x38, 0x6e, 0x84, 0x1e, 0x1d, 0x5a, 0x7b, 0x43, 0x4b, 0xb8, 0xb1, 0x8a, 0xc5, 0x71, 0xa5, + 0x2e, 0x21, 0x6d, 0x5a, 0x18, 0xb9, 0xd2, 0xbc, 0x0f, 0x75, 0xd2, 0x03, 0xd0, 0x7c, 0x73, 0x61, + 0x8d, 0x5e, 0xbd, 0xdc, 0xdd, 0x60, 0x2d, 0xa8, 0x8d, 0x5e, 0x5d, 0xec, 0x56, 0x4e, 0x7e, 0x68, + 0xc0, 0xce, 0xf3, 0xc1, 0xd9, 0xe8, 0xb9, 0xef, 0x2f, 0x9c, 0x29, 0xa7, 0xae, 0xe4, 0x18, 0xea, + 0xd4, 0x77, 0x15, 0x3c, 0x88, 0xf4, 0x8a, 0x2e, 0x00, 0xec, 0x04, 0x1a, 0xd4, 0x7e, 0xb1, 0xa2, + 0x77, 0x91, 0x5e, 0xe1, 0x3d, 0x00, 0x3f, 0xa2, 0x1a, 0xb4, 0xdb, 0xcf, 0x23, 0xbd, 0xa2, 0xcb, + 0x00, 0xfb, 0x12, 0x8c, 0xa4, 0x71, 0x2a, 0x7b, 0x24, 0xe9, 0x95, 0x5e, 0x0b, 0x50, 0x3e, 0xa9, + 0x99, 0x65, 0x4f, 0x0a, 0xbd, 0xd2, 0xfe, 0x99, 0x3d, 0x83, 0x56, 0xd4, 0x17, 0x14, 0x3f, 0x63, + 0xf4, 0x4a, 0x5a, 0x76, 0x0c, 0x8f, 0xea, 0xd0, 0x8a, 0xde, 0x5a, 0x7a, 0x85, 0xf7, 0x0a, 0xf6, + 0x14, 0x9a, 0xba, 0x1a, 0x15, 0x3e, 0x48, 0xf4, 0x8a, 0x1b, 0x6f, 0x74, 0x32, 0xb9, 0xef, 0x97, + 0xbd, 0x07, 0xf5, 0x4a, 0x2f, 0x40, 0xec, 0x39, 0x40, 0xea, 0xf2, 0x5d, 0xfa, 0xd0, 0xd3, 0x2b, + 0xbf, 0xd8, 0x30, 0x3c, 0x3b, 0xf1, 0x65, 0xb5, 0xf8, 0x01, 0xa6, 0x57, 0x76, 0xd7, 0x98, 0x34, + 0xe9, 0x91, 0xee, 0xd3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x2c, 0x50, 0x08, 0xef, 0x13, + 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index c80261e0..f968b948 100644 --- a/types/types.proto +++ b/types/types.proto @@ -43,10 +43,10 @@ message RequestSetOption { } message RequestInitChain { - repeated Validator validators = 1; + repeated Validator validators = 1 [(gogoproto.nullable) = false]; } -message RequestQuery{ +message RequestQuery { bytes data = 1; string path = 2; int64 height = 3; @@ -55,9 +55,9 @@ message RequestQuery{ message RequestBeginBlock { bytes hash = 1; - Header header = 2; + Header header = 2 [(gogoproto.nullable) = false]; repeated int32 absent_validators = 3; - repeated Evidence byzantine_validators = 4; + repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; } message RequestCheckTx { @@ -68,7 +68,7 @@ message RequestDeliverTx { bytes tx = 1; } -message RequestEndBlock{ +message RequestEndBlock { int64 height = 1; } @@ -146,11 +146,11 @@ message ResponseDeliverTx { uint32 code = 1; bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; string log = 3; - repeated KVPair tags = 4; + repeated KVPair tags = 4 [(gogoproto.nullable) = false]; } message ResponseEndBlock { - repeated Validator validator_updates = 1; + repeated Validator validator_updates = 1 [(gogoproto.nullable) = false]; ConsensusParams consensus_param_updates = 2; } @@ -179,7 +179,7 @@ message BlockSize { } // TxSize contain limits on the tx size. -message TxSize{ +message TxSize { int32 max_bytes = 1; int64 max_gas = 2; } @@ -199,7 +199,7 @@ message Header { int64 height = 2; int64 time = 3; int32 num_txs = 4; - BlockID last_block_id = 5 [(gogoproto.customname) = "LastBlockID"]; + BlockID last_block_id = 5 [(gogoproto.customname) = "LastBlockID", (gogoproto.nullable) = false]; bytes last_commit_hash = 6; bytes data_hash = 7; bytes validators_hash = 8; @@ -208,7 +208,7 @@ message Header { message BlockID { bytes hash = 1; - PartSetHeader parts = 2; + PartSetHeader parts = 2 [(gogoproto.nullable) = false]; } message PartSetHeader { diff --git a/types/util.go b/types/util.go index 17c53f65..57c997d0 100644 --- a/types/util.go +++ b/types/util.go @@ -11,7 +11,7 @@ import ( //------------------------------------------------------------------------------ // Validators is a list of validators that implements the Sort interface -type Validators []*Validator +type Validators []Validator func (v Validators) Len() int { return len(v) From f390385baf0d5213f7cc4d208ef1347802cdd3c0 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 24 Dec 2017 18:39:16 -0800 Subject: [PATCH 423/545] Fee is a KNPair (#167) KVPair is {[]byte,[]byte} --- example/dummy/dummy.go | 4 +- types/messages_test.go | 2 +- types/types.pb.go | 288 +++++++++++++++++++---------------------- types/types.proto | 17 ++- types/util.go | 20 --- types/util_test.go | 15 --- 6 files changed, 147 insertions(+), 199 deletions(-) delete mode 100644 types/util_test.go diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index 7592a7d4..c8fb0f37 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -40,8 +40,8 @@ func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { app.state.Set(key, value) tags := []types.KVPair{ - {Key: "app.creator", ValueType: types.KVPair_STRING, ValueString: "jae"}, - {Key: "app.key", ValueType: types.KVPair_STRING, ValueString: string(key)}, + {[]byte("app.creator"), []byte("jae")}, + {[]byte("app.key"), key}, } return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags} } diff --git a/types/messages_test.go b/types/messages_test.go index 15e84b62..f077449c 100644 --- a/types/messages_test.go +++ b/types/messages_test.go @@ -19,7 +19,7 @@ func TestMarshalJSON(t *testing.T) { Code: 1, Data: []byte("hello"), Gas: 43, - Fee: 12, + Fee: KI64Pair{[]byte("pho"), 12}, } b, err = json.Marshal(&r1) assert.Nil(t, err) diff --git a/types/types.pb.go b/types/types.pb.go index 06553825..b11463fe 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -43,6 +43,7 @@ It has these top-level messages: Validator Evidence KVPair + KI64Pair */ //nolint: gas package types @@ -68,27 +69,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package -type KVPair_Type int32 - -const ( - KVPair_STRING KVPair_Type = 0 - KVPair_INT KVPair_Type = 1 -) - -var KVPair_Type_name = map[int32]string{ - 0: "STRING", - 1: "INT", -} -var KVPair_Type_value = map[string]int32{ - "STRING": 0, - "INT": 1, -} - -func (x KVPair_Type) String() string { - return proto.EnumName(KVPair_Type_name, int32(x)) -} -func (KVPair_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34, 0} } - type Request struct { // Types that are valid to be assigned to Value: // *Request_Echo @@ -1304,7 +1284,7 @@ type ResponseCheckTx struct { Data github_com_tendermint_go_wire_data.Bytes `protobuf:"bytes,2,opt,name=data,proto3,customtype=github.com/tendermint/go-wire/data.Bytes" json:"data"` Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` Gas int64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` - Fee int64 `protobuf:"varint,5,opt,name=fee,proto3" json:"fee,omitempty"` + Fee KI64Pair `protobuf:"bytes,5,opt,name=fee" json:"fee"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } @@ -1333,11 +1313,11 @@ func (m *ResponseCheckTx) GetGas() int64 { return 0 } -func (m *ResponseCheckTx) GetFee() int64 { +func (m *ResponseCheckTx) GetFee() KI64Pair { if m != nil { return m.Fee } - return 0 + return KI64Pair{} } type ResponseDeliverTx struct { @@ -1710,10 +1690,8 @@ func (m *Evidence) GetHeight() int64 { } type KVPair struct { - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - ValueType KVPair_Type `protobuf:"varint,2,opt,name=value_type,json=valueType,proto3,enum=types.KVPair_Type" json:"value_type,omitempty"` - ValueString string `protobuf:"bytes,3,opt,name=value_string,json=valueString,proto3" json:"value_string,omitempty"` - ValueInt int64 `protobuf:"varint,4,opt,name=value_int,json=valueInt,proto3" json:"value_int,omitempty"` + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` } func (m *KVPair) Reset() { *m = KVPair{} } @@ -1721,30 +1699,40 @@ func (m *KVPair) String() string { return proto.CompactTextString(m) func (*KVPair) ProtoMessage() {} func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} } -func (m *KVPair) GetKey() string { +func (m *KVPair) GetKey() []byte { if m != nil { return m.Key } - return "" + return nil } -func (m *KVPair) GetValueType() KVPair_Type { +func (m *KVPair) GetValue() []byte { if m != nil { - return m.ValueType + return m.Value } - return KVPair_STRING + return nil } -func (m *KVPair) GetValueString() string { +type KI64Pair struct { + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *KI64Pair) Reset() { *m = KI64Pair{} } +func (m *KI64Pair) String() string { return proto.CompactTextString(m) } +func (*KI64Pair) ProtoMessage() {} +func (*KI64Pair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} } + +func (m *KI64Pair) GetKey() []byte { if m != nil { - return m.ValueString + return m.Key } - return "" + return nil } -func (m *KVPair) GetValueInt() int64 { +func (m *KI64Pair) GetValue() int64 { if m != nil { - return m.ValueInt + return m.Value } return 0 } @@ -1785,7 +1773,7 @@ func init() { proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterType((*Evidence)(nil), "types.Evidence") proto.RegisterType((*KVPair)(nil), "types.KVPair") - proto.RegisterEnum("types.KVPair_Type", KVPair_Type_name, KVPair_Type_value) + proto.RegisterType((*KI64Pair)(nil), "types.KI64Pair") } // Reference imports to suppress errors if they are not otherwise used. @@ -2193,117 +2181,113 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1778 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x72, 0x1b, 0xc7, - 0x11, 0x26, 0xfe, 0xb1, 0x0d, 0xfe, 0x0e, 0x29, 0x09, 0x86, 0x0e, 0x62, 0xf6, 0x60, 0x41, 0x91, - 0x45, 0xda, 0x74, 0xc9, 0x25, 0xda, 0x29, 0x57, 0x04, 0x52, 0x16, 0x10, 0xa7, 0x64, 0x65, 0xc5, - 0xf8, 0x90, 0x0b, 0x6a, 0x80, 0x1d, 0x02, 0x5b, 0x02, 0x76, 0xd7, 0xbb, 0x03, 0x1a, 0x54, 0xe5, - 0x11, 0x7c, 0xcf, 0x39, 0xa7, 0xa4, 0xf2, 0x02, 0x79, 0x83, 0x54, 0x52, 0x79, 0x83, 0x1c, 0x78, - 0xf0, 0x93, 0xa4, 0xba, 0x67, 0xf6, 0x97, 0xbb, 0x89, 0x4b, 0x07, 0x5f, 0x80, 0x99, 0xe9, 0x9f, - 0xed, 0xee, 0xe9, 0xf9, 0xba, 0x67, 0x60, 0x4f, 0x5e, 0xfb, 0x22, 0x3c, 0xa6, 0xdf, 0x23, 0x3f, - 0xf0, 0xa4, 0xc7, 0x1a, 0x34, 0xe9, 0x3d, 0x99, 0x39, 0x72, 0xbe, 0x9a, 0x1c, 0x4d, 0xbd, 0xe5, - 0xf1, 0xcc, 0x9b, 0x79, 0xc7, 0x44, 0x9d, 0xac, 0x2e, 0x69, 0x46, 0x13, 0x1a, 0x29, 0x29, 0xf3, - 0x1f, 0x75, 0x68, 0x59, 0xe2, 0xbb, 0x95, 0x08, 0x25, 0xeb, 0x43, 0x5d, 0x4c, 0xe7, 0x5e, 0xb7, - 0x7a, 0x58, 0xe9, 0x77, 0x4e, 0xd8, 0x91, 0xd2, 0xae, 0xa9, 0x2f, 0xa6, 0x73, 0x6f, 0xb8, 0x61, - 0x11, 0x07, 0x7b, 0x0c, 0x8d, 0xcb, 0xc5, 0x2a, 0x9c, 0x77, 0x6b, 0xc4, 0xba, 0x9f, 0x65, 0xfd, - 0x0a, 0x49, 0xc3, 0x0d, 0x4b, 0xf1, 0xa0, 0x5a, 0xc7, 0xbd, 0xf4, 0xba, 0xf5, 0x22, 0xb5, 0x23, - 0xf7, 0x92, 0xd4, 0x22, 0x07, 0x7b, 0x06, 0x10, 0x0a, 0x39, 0xf6, 0x7c, 0xe9, 0x78, 0x6e, 0xb7, - 0x41, 0xfc, 0xf7, 0xb2, 0xfc, 0x6f, 0x84, 0xfc, 0x86, 0xc8, 0xc3, 0x0d, 0xcb, 0x08, 0xa3, 0x09, - 0x4a, 0x3a, 0xae, 0x23, 0xc7, 0xd3, 0x39, 0x77, 0xdc, 0x6e, 0xb3, 0x48, 0x72, 0xe4, 0x3a, 0xf2, - 0x0c, 0xc9, 0x28, 0xe9, 0x44, 0x13, 0x74, 0xe5, 0xbb, 0x95, 0x08, 0xae, 0xbb, 0xad, 0x22, 0x57, - 0x7e, 0x87, 0x24, 0x74, 0x85, 0x78, 0xd8, 0x17, 0xd0, 0x99, 0x88, 0x99, 0xe3, 0x8e, 0x27, 0x0b, - 0x6f, 0xfa, 0xb6, 0xdb, 0x26, 0x91, 0x6e, 0x56, 0x64, 0x80, 0x0c, 0x03, 0xa4, 0x0f, 0x37, 0x2c, - 0x98, 0xc4, 0x33, 0x76, 0x02, 0xed, 0xe9, 0x5c, 0x4c, 0xdf, 0x8e, 0xe5, 0xba, 0x6b, 0x90, 0xe4, - 0x9d, 0xac, 0xe4, 0x19, 0x52, 0x2f, 0xd6, 0xc3, 0x0d, 0xab, 0x35, 0x55, 0x43, 0xf4, 0xcb, 0x16, - 0x0b, 0xe7, 0x4a, 0x04, 0x28, 0xb5, 0x5f, 0xe4, 0xd7, 0xb9, 0xa2, 0x93, 0x9c, 0x61, 0x47, 0x13, - 0xf6, 0x14, 0x0c, 0xe1, 0xda, 0xda, 0xd0, 0x0e, 0x09, 0xde, 0xcd, 0xed, 0xa8, 0x6b, 0x47, 0x66, - 0xb6, 0x85, 0x1e, 0xb3, 0x23, 0x68, 0x4e, 0xbd, 0xe5, 0xd2, 0x91, 0xdd, 0x4d, 0x92, 0x39, 0xc8, - 0x99, 0x48, 0xb4, 0xe1, 0x86, 0xa5, 0xb9, 0x06, 0x2d, 0x68, 0x5c, 0xf1, 0xc5, 0x4a, 0x98, 0x0f, - 0xa1, 0x93, 0xca, 0x14, 0xd6, 0x85, 0xd6, 0x52, 0x84, 0x21, 0x9f, 0x89, 0x6e, 0xe5, 0xb0, 0xd2, - 0x37, 0xac, 0x68, 0x6a, 0x6e, 0xc3, 0x66, 0x3a, 0x4f, 0x52, 0x82, 0x98, 0x0b, 0x28, 0x78, 0x25, - 0x82, 0x10, 0x13, 0x40, 0x0b, 0xea, 0xa9, 0xf9, 0x39, 0xec, 0xe6, 0x93, 0x80, 0xed, 0x42, 0xed, - 0xad, 0xb8, 0xd6, 0x9c, 0x38, 0x64, 0x07, 0xda, 0x20, 0xca, 0x62, 0xc3, 0xd2, 0xd6, 0xfd, 0x26, - 0x96, 0x8d, 0xd3, 0x80, 0x7d, 0x06, 0x70, 0xc5, 0x17, 0x8e, 0xcd, 0xa5, 0x17, 0x84, 0xdd, 0xca, - 0x61, 0xad, 0xdf, 0x39, 0xd9, 0xd5, 0xee, 0x7e, 0x1b, 0x11, 0x06, 0xf5, 0x7f, 0xde, 0x3c, 0xd8, - 0xb0, 0x52, 0x9c, 0xa6, 0x1d, 0x3b, 0x40, 0xd9, 0xc1, 0x18, 0xd4, 0x6d, 0x2e, 0x39, 0x19, 0xb1, - 0x69, 0xd1, 0x18, 0xd7, 0x7c, 0x2e, 0xe7, 0xda, 0x08, 0x1a, 0xb3, 0xbb, 0xd0, 0x9c, 0x0b, 0x67, - 0x36, 0x97, 0x74, 0x6a, 0x6a, 0x96, 0x9e, 0xa1, 0xc5, 0x7e, 0xe0, 0x5d, 0x09, 0x3a, 0x20, 0x6d, - 0x4b, 0x4d, 0xcc, 0x7f, 0x57, 0x60, 0xef, 0x56, 0x46, 0xa1, 0xde, 0x39, 0x0f, 0xe7, 0xd1, 0xb7, - 0x70, 0xcc, 0x1e, 0xa3, 0x5e, 0x6e, 0x8b, 0x40, 0x1f, 0xdc, 0x2d, 0xed, 0xc3, 0x90, 0x16, 0xb5, - 0x03, 0x9a, 0x85, 0x3d, 0x86, 0x3d, 0x3e, 0x09, 0x85, 0x2b, 0xc7, 0x29, 0xdf, 0x6b, 0x87, 0xb5, - 0x7e, 0xc3, 0xda, 0x55, 0x84, 0xd8, 0xf5, 0x90, 0x0d, 0xe1, 0x60, 0x72, 0xfd, 0x8e, 0xbb, 0xd2, - 0x71, 0x45, 0x9a, 0xbf, 0x4e, 0xb1, 0xda, 0xd1, 0xdf, 0x79, 0x71, 0xe5, 0xd8, 0xc2, 0x9d, 0x0a, - 0xfd, 0xa5, 0xfd, 0x58, 0x24, 0xd1, 0x64, 0x1e, 0xc2, 0x76, 0x36, 0xc9, 0xd9, 0x36, 0x54, 0xe5, - 0x5a, 0xfb, 0x51, 0x95, 0x6b, 0xd3, 0x8c, 0x77, 0x28, 0x4e, 0xe8, 0x5b, 0x3c, 0x8f, 0x60, 0x27, - 0x97, 0xbb, 0xa9, 0xa0, 0x56, 0xd2, 0x41, 0x35, 0x77, 0x60, 0x2b, 0x93, 0xb2, 0xe6, 0x0f, 0x0d, - 0x68, 0x5b, 0x22, 0xf4, 0x3d, 0x37, 0x14, 0xec, 0x19, 0x18, 0x62, 0x3d, 0x15, 0x0a, 0x67, 0x2a, - 0xb9, 0x53, 0xac, 0x78, 0x5e, 0x44, 0x74, 0x3c, 0x56, 0x31, 0x33, 0x7b, 0x94, 0xc1, 0xc8, 0xfd, - 0xbc, 0x50, 0x1a, 0x24, 0x3f, 0xca, 0x82, 0xe4, 0x41, 0x8e, 0x37, 0x87, 0x92, 0x8f, 0x32, 0x28, - 0x99, 0x57, 0x9c, 0x81, 0xc9, 0xd3, 0x02, 0x98, 0xcc, 0x9b, 0x5f, 0x82, 0x93, 0xa7, 0x05, 0x38, - 0xd9, 0xbd, 0xf5, 0xad, 0x42, 0xa0, 0xfc, 0x28, 0x0b, 0x94, 0x79, 0x77, 0x72, 0x48, 0xf9, 0xab, - 0x22, 0xa4, 0xfc, 0x20, 0x27, 0x53, 0x0a, 0x95, 0x9f, 0xde, 0x82, 0xca, 0xbb, 0x39, 0xd1, 0x02, - 0xac, 0x3c, 0xcd, 0x60, 0x25, 0x14, 0xfa, 0x56, 0x02, 0x96, 0x9f, 0xdd, 0x06, 0xcb, 0x7b, 0xf9, - 0xad, 0x2d, 0x42, 0xcb, 0xe3, 0x1c, 0x5a, 0xde, 0xc9, 0x5b, 0x59, 0x0a, 0x97, 0x8f, 0xf0, 0x74, - 0xe7, 0x32, 0x0d, 0x91, 0x40, 0x04, 0x81, 0x17, 0x68, 0x3c, 0x53, 0x13, 0xb3, 0x8f, 0x78, 0x93, - 0xe4, 0xd7, 0xff, 0x80, 0x56, 0x4a, 0xfa, 0x54, 0x76, 0x99, 0x7f, 0xaa, 0x24, 0xb2, 0x84, 0xae, - 0x69, 0xac, 0x32, 0x34, 0x56, 0xa5, 0x10, 0xb7, 0x9a, 0x41, 0x5c, 0xf6, 0x4b, 0xd8, 0x5b, 0xf0, - 0x50, 0xaa, 0xb8, 0x8c, 0x33, 0xe0, 0xb5, 0x83, 0x04, 0x15, 0x10, 0x85, 0x62, 0x4f, 0x60, 0x3f, - 0xc5, 0xcb, 0x7d, 0x7f, 0x4c, 0x40, 0x55, 0xa7, 0xc3, 0xbb, 0x1b, 0x73, 0x3f, 0xf7, 0xfd, 0x21, - 0x0f, 0xe7, 0xe6, 0x69, 0xe2, 0x7f, 0x82, 0xe6, 0x0c, 0xea, 0x53, 0xcf, 0x56, 0x6e, 0x6d, 0x59, - 0x34, 0x46, 0x84, 0x5f, 0x78, 0x33, 0x6d, 0x19, 0x0e, 0xcd, 0xfd, 0x44, 0x34, 0x4e, 0x55, 0xf3, - 0xef, 0xd5, 0xc4, 0xf7, 0x18, 0x96, 0x6f, 0x29, 0x3b, 0x80, 0x86, 0xe3, 0xda, 0x62, 0x4d, 0xea, - 0x6a, 0x96, 0x9a, 0xb0, 0x81, 0x2a, 0x22, 0xe8, 0xd8, 0xe6, 0xe0, 0x63, 0x04, 0xb1, 0xff, 0xdc, - 0x3c, 0xe8, 0xa7, 0xfa, 0x28, 0x29, 0x5c, 0x5b, 0x04, 0x4b, 0xc7, 0x95, 0xc7, 0x33, 0xef, 0xc9, - 0xf7, 0x4e, 0x20, 0x8e, 0x31, 0x72, 0x47, 0x83, 0x6b, 0x29, 0x42, 0x55, 0x76, 0xbe, 0x8a, 0xca, - 0x4e, 0xfd, 0x3d, 0xb5, 0x28, 0x71, 0xd4, 0xe3, 0x07, 0x9e, 0x77, 0x49, 0xc7, 0xfa, 0xbd, 0xf4, - 0x90, 0x78, 0x0a, 0x17, 0x9b, 0x99, 0x62, 0xa3, 0xc3, 0xd9, 0x4a, 0xc2, 0x79, 0x00, 0xec, 0xf6, - 0x79, 0x34, 0xff, 0x5c, 0x41, 0xac, 0xcd, 0x9c, 0xb5, 0xc2, 0x88, 0x9e, 0xeb, 0x84, 0xaa, 0xbe, - 0xa7, 0xb9, 0x2a, 0x05, 0xb5, 0x55, 0xb5, 0xd8, 0x2a, 0x5c, 0x99, 0xf1, 0x90, 0xa2, 0x59, 0xb3, - 0x70, 0x88, 0x2b, 0x97, 0x42, 0x50, 0x5c, 0x6a, 0x16, 0x0e, 0xcd, 0xbf, 0x56, 0x92, 0x4c, 0x48, - 0x8a, 0xc6, 0xcf, 0x69, 0xe5, 0x43, 0xa8, 0x4b, 0x3e, 0x8b, 0x0a, 0x62, 0x54, 0x78, 0xbf, 0xfe, - 0xf6, 0x35, 0x77, 0xa2, 0xc2, 0x4b, 0x0c, 0xe6, 0x5f, 0x2a, 0x58, 0xde, 0xb2, 0x48, 0xc2, 0xce, - 0x60, 0x2f, 0x2e, 0xaa, 0xe3, 0x95, 0x6f, 0x73, 0x29, 0xfe, 0x5f, 0x1f, 0xb2, 0x1b, 0x0b, 0xfc, - 0x5e, 0xf1, 0xb3, 0x57, 0x70, 0x6f, 0x8a, 0x5a, 0xdd, 0x70, 0x15, 0x8e, 0x7d, 0x1e, 0xf0, 0x65, - 0xac, 0xaa, 0x9a, 0x41, 0xce, 0xb3, 0x88, 0xeb, 0x35, 0x32, 0x85, 0xd6, 0x9d, 0x69, 0x66, 0x41, - 0xeb, 0x33, 0xff, 0x88, 0x95, 0x3a, 0x8d, 0x5e, 0x3f, 0x67, 0x40, 0x29, 0xed, 0x72, 0x86, 0xb2, - 0x63, 0x00, 0x05, 0x2a, 0xa1, 0xf3, 0x4e, 0xe8, 0x6a, 0x1d, 0xc5, 0x87, 0x02, 0xf9, 0xc6, 0x79, - 0x27, 0x2c, 0x63, 0x12, 0x0d, 0xd9, 0x87, 0xd0, 0x92, 0x6b, 0xc5, 0x9d, 0xed, 0x88, 0x2e, 0xd6, - 0xc4, 0xda, 0x94, 0xf4, 0xcf, 0x9e, 0xc2, 0xa6, 0x52, 0x3c, 0xf3, 0xc2, 0xd0, 0xf1, 0x75, 0x9d, - 0x66, 0x69, 0xd5, 0x2f, 0x89, 0x62, 0x75, 0x26, 0xc9, 0xc4, 0xfc, 0x03, 0x18, 0xf1, 0x67, 0xd9, - 0x7d, 0x30, 0x96, 0x7c, 0x3d, 0x9e, 0x5c, 0xab, 0xbd, 0xab, 0xf4, 0x1b, 0x56, 0x7b, 0xc9, 0xd7, - 0xe4, 0x25, 0xbb, 0x07, 0x2d, 0x24, 0xca, 0xb5, 0xda, 0x8b, 0x86, 0xd5, 0x5c, 0xf2, 0xf5, 0xc5, - 0x3a, 0x26, 0x60, 0x86, 0xeb, 0x5e, 0x70, 0xc9, 0xd7, 0x2f, 0x79, 0x68, 0x7e, 0x09, 0x4d, 0x65, - 0xe4, 0x4f, 0x52, 0x8c, 0xf2, 0xd5, 0x8c, 0xfc, 0xaf, 0xa1, 0x93, 0xb2, 0x9b, 0x7d, 0x02, 0x77, - 0x94, 0x87, 0x3e, 0x0f, 0x24, 0x45, 0x24, 0xa3, 0x90, 0x11, 0xf1, 0x35, 0x0f, 0x24, 0x7e, 0x92, - 0x54, 0x9b, 0xff, 0xaa, 0x42, 0x53, 0x75, 0x8e, 0xec, 0x43, 0xac, 0xc2, 0xdc, 0x71, 0xc7, 0x8e, - 0xad, 0x0a, 0xc6, 0xa0, 0xf3, 0xe3, 0xcd, 0x83, 0x16, 0x01, 0xee, 0xe8, 0x1c, 0x0b, 0x2f, 0x0e, - 0xec, 0x14, 0xd6, 0x54, 0x33, 0x58, 0xc3, 0xa0, 0x2e, 0x9d, 0xa5, 0xd0, 0x2e, 0xd2, 0x18, 0x2d, - 0x77, 0x57, 0x4b, 0x0a, 0x49, 0x5d, 0x85, 0xc4, 0x5d, 0x2d, 0x31, 0x24, 0x2f, 0x61, 0x2b, 0x55, - 0x3f, 0x1c, 0x5b, 0xf7, 0x35, 0xdb, 0xe9, 0xdd, 0x18, 0x9d, 0x0f, 0xf6, 0x31, 0xd5, 0x7e, 0xbc, - 0x79, 0xd0, 0xf9, 0x6d, 0x54, 0x51, 0x46, 0xe7, 0x56, 0x27, 0x2e, 0x2f, 0x23, 0x9b, 0xf5, 0x81, - 0xaa, 0xcd, 0x58, 0x55, 0x5c, 0x55, 0x85, 0x9a, 0x54, 0x85, 0xb6, 0x71, 0x5d, 0x97, 0x64, 0x6c, - 0x9c, 0xef, 0x83, 0x81, 0x69, 0xa8, 0x58, 0x5a, 0xc4, 0xd2, 0xc6, 0x05, 0x22, 0x3e, 0x84, 0x9d, - 0xa4, 0xe3, 0x55, 0x2c, 0x6d, 0xa5, 0x25, 0x59, 0x26, 0xc6, 0x0f, 0xa0, 0x1d, 0x57, 0x3b, 0x83, - 0x38, 0x5a, 0x5c, 0x17, 0xb9, 0x6f, 0xa0, 0xa5, 0x4d, 0x2c, 0x6c, 0xdc, 0x3f, 0x86, 0x06, 0xee, - 0x4b, 0x74, 0x50, 0xa3, 0x8e, 0x8a, 0xf6, 0x43, 0xc8, 0x4c, 0xfb, 0xae, 0x18, 0xcd, 0x53, 0xd8, - 0xca, 0x50, 0xb1, 0xa0, 0x49, 0x4f, 0xf2, 0x85, 0xde, 0x50, 0x35, 0x89, 0x3f, 0x56, 0x4d, 0x3e, - 0x66, 0x7e, 0x0e, 0x46, 0x0c, 0x26, 0xb8, 0x0b, 0xfe, 0x6a, 0x32, 0x8e, 0xae, 0x4e, 0x9b, 0x56, - 0xd3, 0x5f, 0x4d, 0xbe, 0x56, 0xb7, 0x27, 0xdf, 0xfb, 0x5e, 0x5f, 0x25, 0x6a, 0x96, 0x9a, 0x98, - 0x5f, 0x40, 0x3b, 0x6a, 0xf2, 0xcb, 0x45, 0x4b, 0xb2, 0xc0, 0xfc, 0x5b, 0x05, 0x9a, 0x0a, 0x11, - 0x0b, 0x6e, 0x6b, 0x9f, 0xd0, 0x1d, 0x6c, 0x25, 0xc6, 0xe8, 0x3a, 0x09, 0x6e, 0xc7, 0x07, 0x50, - 0x09, 0x1d, 0x5d, 0x5c, 0xfb, 0xc2, 0x32, 0x88, 0x0b, 0x87, 0xec, 0x17, 0xb0, 0xa9, 0x44, 0x42, - 0x19, 0x38, 0x6e, 0x84, 0x1e, 0x1d, 0x5a, 0x7b, 0x43, 0x4b, 0xb8, 0xb1, 0x8a, 0xc5, 0x71, 0xa5, - 0x2e, 0x21, 0x6d, 0x5a, 0x18, 0xb9, 0xd2, 0xbc, 0x0f, 0x75, 0xd2, 0x03, 0xd0, 0x7c, 0x73, 0x61, - 0x8d, 0x5e, 0xbd, 0xdc, 0xdd, 0x60, 0x2d, 0xa8, 0x8d, 0x5e, 0x5d, 0xec, 0x56, 0x4e, 0x7e, 0x68, - 0xc0, 0xce, 0xf3, 0xc1, 0xd9, 0xe8, 0xb9, 0xef, 0x2f, 0x9c, 0x29, 0xa7, 0xae, 0xe4, 0x18, 0xea, - 0xd4, 0x77, 0x15, 0x3c, 0x88, 0xf4, 0x8a, 0x2e, 0x00, 0xec, 0x04, 0x1a, 0xd4, 0x7e, 0xb1, 0xa2, - 0x77, 0x91, 0x5e, 0xe1, 0x3d, 0x00, 0x3f, 0xa2, 0x1a, 0xb4, 0xdb, 0xcf, 0x23, 0xbd, 0xa2, 0xcb, - 0x00, 0xfb, 0x12, 0x8c, 0xa4, 0x71, 0x2a, 0x7b, 0x24, 0xe9, 0x95, 0x5e, 0x0b, 0x50, 0x3e, 0xa9, - 0x99, 0x65, 0x4f, 0x0a, 0xbd, 0xd2, 0xfe, 0x99, 0x3d, 0x83, 0x56, 0xd4, 0x17, 0x14, 0x3f, 0x63, - 0xf4, 0x4a, 0x5a, 0x76, 0x0c, 0x8f, 0xea, 0xd0, 0x8a, 0xde, 0x5a, 0x7a, 0x85, 0xf7, 0x0a, 0xf6, - 0x14, 0x9a, 0xba, 0x1a, 0x15, 0x3e, 0x48, 0xf4, 0x8a, 0x1b, 0x6f, 0x74, 0x32, 0xb9, 0xef, 0x97, - 0xbd, 0x07, 0xf5, 0x4a, 0x2f, 0x40, 0xec, 0x39, 0x40, 0xea, 0xf2, 0x5d, 0xfa, 0xd0, 0xd3, 0x2b, - 0xbf, 0xd8, 0x30, 0x3c, 0x3b, 0xf1, 0x65, 0xb5, 0xf8, 0x01, 0xa6, 0x57, 0x76, 0xd7, 0x98, 0x34, - 0xe9, 0x91, 0xee, 0xd3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x2c, 0x50, 0x08, 0xef, 0x13, - 0x00, 0x00, + // 1726 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x72, 0x13, 0xcf, + 0x11, 0xb7, 0xbe, 0xa5, 0x96, 0xfc, 0x35, 0xb6, 0xb1, 0x10, 0x07, 0xbb, 0xf6, 0x80, 0xe5, 0x00, + 0x16, 0x31, 0x81, 0xc2, 0x90, 0xa2, 0x62, 0xd9, 0x80, 0x14, 0x52, 0x81, 0x2c, 0x84, 0x43, 0x2e, + 0xaa, 0x91, 0x76, 0x2c, 0x6d, 0x21, 0xed, 0x2e, 0xbb, 0x23, 0x23, 0x53, 0x79, 0x04, 0xee, 0x39, + 0xe7, 0x94, 0xbc, 0x41, 0xf2, 0x04, 0xa9, 0xa4, 0xf2, 0x06, 0x39, 0xf8, 0xc0, 0x93, 0xa4, 0x7a, + 0x66, 0xf6, 0x53, 0xbb, 0x7f, 0xfe, 0xc5, 0x81, 0x8b, 0x34, 0xb3, 0xfd, 0x31, 0xdd, 0x3d, 0x3d, + 0xbf, 0xee, 0x19, 0xd8, 0xe4, 0x57, 0x0e, 0xf3, 0x3a, 0xe2, 0xf7, 0xc8, 0x71, 0x6d, 0x6e, 0x93, + 0x92, 0x98, 0xb4, 0xee, 0x8d, 0x4d, 0x3e, 0x99, 0x0f, 0x8f, 0x46, 0xf6, 0xac, 0x33, 0xb6, 0xc7, + 0x76, 0x47, 0x50, 0x87, 0xf3, 0x0b, 0x31, 0x13, 0x13, 0x31, 0x92, 0x52, 0xda, 0xbf, 0x8a, 0x50, + 0xd1, 0xd9, 0xc7, 0x39, 0xf3, 0x38, 0x69, 0x43, 0x91, 0x8d, 0x26, 0x76, 0x33, 0xbf, 0x9f, 0x6b, + 0xd7, 0x8f, 0xc9, 0x91, 0xd4, 0xae, 0xa8, 0xcf, 0x47, 0x13, 0xbb, 0xb7, 0xa2, 0x0b, 0x0e, 0x72, + 0x07, 0x4a, 0x17, 0xd3, 0xb9, 0x37, 0x69, 0x16, 0x04, 0xeb, 0x56, 0x9c, 0xf5, 0x05, 0x92, 0x7a, + 0x2b, 0xba, 0xe4, 0x41, 0xb5, 0xa6, 0x75, 0x61, 0x37, 0x8b, 0x69, 0x6a, 0xfb, 0xd6, 0x85, 0x50, + 0x8b, 0x1c, 0xe4, 0x31, 0x80, 0xc7, 0xf8, 0xc0, 0x76, 0xb8, 0x69, 0x5b, 0xcd, 0x92, 0xe0, 0xdf, + 0x8d, 0xf3, 0xbf, 0x65, 0xfc, 0xb5, 0x20, 0xf7, 0x56, 0xf4, 0x9a, 0xe7, 0x4f, 0x50, 0xd2, 0xb4, + 0x4c, 0x3e, 0x18, 0x4d, 0xa8, 0x69, 0x35, 0xcb, 0x69, 0x92, 0x7d, 0xcb, 0xe4, 0x67, 0x48, 0x46, + 0x49, 0xd3, 0x9f, 0xa0, 0x2b, 0x1f, 0xe7, 0xcc, 0xbd, 0x6a, 0x56, 0xd2, 0x5c, 0xf9, 0x03, 0x92, + 0xd0, 0x15, 0xc1, 0x43, 0x9e, 0x42, 0x7d, 0xc8, 0xc6, 0xa6, 0x35, 0x18, 0x4e, 0xed, 0xd1, 0x87, + 0x66, 0x55, 0x88, 0x34, 0xe3, 0x22, 0x5d, 0x64, 0xe8, 0x22, 0xbd, 0xb7, 0xa2, 0xc3, 0x30, 0x98, + 0x91, 0x63, 0xa8, 0x8e, 0x26, 0x6c, 0xf4, 0x61, 0xc0, 0x17, 0xcd, 0x9a, 0x90, 0xdc, 0x89, 0x4b, + 0x9e, 0x21, 0xf5, 0xdd, 0xa2, 0xb7, 0xa2, 0x57, 0x46, 0x72, 0x88, 0x7e, 0x19, 0x6c, 0x6a, 0x5e, + 0x32, 0x17, 0xa5, 0xb6, 0xd2, 0xfc, 0x3a, 0x97, 0x74, 0x21, 0x57, 0x33, 0xfc, 0x09, 0x79, 0x08, + 0x35, 0x66, 0x19, 0xca, 0xd0, 0xba, 0x10, 0xbc, 0x91, 0xd8, 0x51, 0xcb, 0xf0, 0xcd, 0xac, 0x32, + 0x35, 0x26, 0x47, 0x50, 0x1e, 0xd9, 0xb3, 0x99, 0xc9, 0x9b, 0x0d, 0x21, 0xb3, 0x9d, 0x30, 0x51, + 0xd0, 0x7a, 0x2b, 0xba, 0xe2, 0xea, 0x56, 0xa0, 0x74, 0x49, 0xa7, 0x73, 0xa6, 0x1d, 0x40, 0x3d, + 0x92, 0x29, 0xa4, 0x09, 0x95, 0x19, 0xf3, 0x3c, 0x3a, 0x66, 0xcd, 0xdc, 0x7e, 0xae, 0x5d, 0xd3, + 0xfd, 0xa9, 0xb6, 0x06, 0x8d, 0x68, 0x9e, 0x44, 0x04, 0x31, 0x17, 0x50, 0xf0, 0x92, 0xb9, 0x1e, + 0x26, 0x80, 0x12, 0x54, 0x53, 0xed, 0x09, 0x6c, 0x24, 0x93, 0x80, 0x6c, 0x40, 0xe1, 0x03, 0xbb, + 0x52, 0x9c, 0x38, 0x24, 0xdb, 0xca, 0x20, 0x91, 0xc5, 0x35, 0x5d, 0x59, 0xf7, 0xdb, 0x40, 0x36, + 0x48, 0x03, 0xf2, 0x08, 0xe0, 0x92, 0x4e, 0x4d, 0x83, 0x72, 0xdb, 0xf5, 0x9a, 0xb9, 0xfd, 0x42, + 0xbb, 0x7e, 0xbc, 0xa1, 0xdc, 0x7d, 0xef, 0x13, 0xba, 0xc5, 0x7f, 0x5f, 0xef, 0xad, 0xe8, 0x11, + 0x4e, 0xcd, 0x08, 0x1c, 0x10, 0xd9, 0x41, 0x08, 0x14, 0x0d, 0xca, 0xa9, 0x30, 0xa2, 0xa1, 0x8b, + 0x31, 0x7e, 0x73, 0x28, 0x9f, 0x28, 0x23, 0xc4, 0x98, 0xdc, 0x80, 0xf2, 0x84, 0x99, 0xe3, 0x09, + 0x17, 0xa7, 0xa6, 0xa0, 0xab, 0x19, 0x5a, 0xec, 0xb8, 0xf6, 0x25, 0x13, 0x07, 0xa4, 0xaa, 0xcb, + 0x89, 0xf6, 0xdf, 0x1c, 0x6c, 0x2e, 0x65, 0x14, 0xea, 0x9d, 0x50, 0x6f, 0xe2, 0xaf, 0x85, 0x63, + 0x72, 0x07, 0xf5, 0x52, 0x83, 0xb9, 0xea, 0xe0, 0xae, 0x2a, 0x1f, 0x7a, 0xe2, 0xa3, 0x72, 0x40, + 0xb1, 0x90, 0x3b, 0xb0, 0x49, 0x87, 0x1e, 0xb3, 0xf8, 0x20, 0xe2, 0x7b, 0x61, 0xbf, 0xd0, 0x2e, + 0xe9, 0x1b, 0x92, 0x10, 0xb8, 0xee, 0x91, 0x1e, 0x6c, 0x0f, 0xaf, 0x3e, 0x53, 0x8b, 0x9b, 0x16, + 0x8b, 0xf2, 0x17, 0x45, 0xac, 0xd6, 0xd5, 0x3a, 0xcf, 0x2f, 0x4d, 0x83, 0x59, 0x23, 0xa6, 0x56, + 0xda, 0x0a, 0x44, 0x42, 0x4d, 0xda, 0x3e, 0xac, 0xc5, 0x93, 0x9c, 0xac, 0x41, 0x9e, 0x2f, 0x94, + 0x1f, 0x79, 0xbe, 0xd0, 0xb4, 0x60, 0x87, 0x82, 0x84, 0x5e, 0xe2, 0x39, 0x84, 0xf5, 0x44, 0xee, + 0x46, 0x82, 0x9a, 0x8b, 0x06, 0x55, 0x5b, 0x87, 0xd5, 0x58, 0xca, 0x6a, 0x5f, 0x4a, 0x50, 0xd5, + 0x99, 0xe7, 0xd8, 0x96, 0xc7, 0xc8, 0x63, 0xa8, 0xb1, 0xc5, 0x88, 0x49, 0x9c, 0xc9, 0x25, 0x4e, + 0xb1, 0xe4, 0x79, 0xee, 0xd3, 0xf1, 0x58, 0x05, 0xcc, 0xe4, 0x30, 0x86, 0x91, 0x5b, 0x49, 0xa1, + 0x28, 0x48, 0xde, 0x8d, 0x83, 0xe4, 0x76, 0x82, 0x37, 0x81, 0x92, 0x87, 0x31, 0x94, 0x4c, 0x2a, + 0x8e, 0xc1, 0xe4, 0x49, 0x0a, 0x4c, 0x26, 0xcd, 0xcf, 0xc0, 0xc9, 0x93, 0x14, 0x9c, 0x6c, 0x2e, + 0xad, 0x95, 0x0a, 0x94, 0x77, 0xe3, 0x40, 0x99, 0x74, 0x27, 0x81, 0x94, 0xbf, 0x4e, 0x43, 0xca, + 0x9b, 0x09, 0x99, 0x4c, 0xa8, 0x7c, 0xb0, 0x04, 0x95, 0x37, 0x12, 0xa2, 0x29, 0x58, 0x79, 0x12, + 0xc3, 0x4a, 0x48, 0xf5, 0x2d, 0x03, 0x2c, 0x1f, 0x2d, 0x83, 0xe5, 0x6e, 0x72, 0x6b, 0xd3, 0xd0, + 0xb2, 0x93, 0x40, 0xcb, 0x9d, 0xa4, 0x95, 0x99, 0x70, 0x79, 0x88, 0xa7, 0x3b, 0x91, 0x69, 0x88, + 0x04, 0xcc, 0x75, 0x6d, 0x57, 0xe1, 0x99, 0x9c, 0x68, 0x6d, 0xc4, 0x9b, 0x30, 0xbf, 0x7e, 0x02, + 0x5a, 0x45, 0xd2, 0x47, 0xb2, 0x4b, 0xfb, 0x4b, 0x2e, 0x94, 0x15, 0xe8, 0x1a, 0xc5, 0xaa, 0x9a, + 0xc2, 0xaa, 0x08, 0xe2, 0xe6, 0x63, 0x88, 0x4b, 0x7e, 0x01, 0x9b, 0x53, 0xea, 0x71, 0x19, 0x97, + 0x41, 0x0c, 0xbc, 0xd6, 0x91, 0x20, 0x03, 0x22, 0x51, 0xec, 0x1e, 0x6c, 0x45, 0x78, 0xa9, 0xe3, + 0x0c, 0x04, 0x50, 0x15, 0xc5, 0xe1, 0xdd, 0x08, 0xb8, 0x4f, 0x1d, 0xa7, 0x47, 0xbd, 0x89, 0x76, + 0x12, 0xfa, 0x1f, 0xa2, 0x39, 0x81, 0xe2, 0xc8, 0x36, 0xa4, 0x5b, 0xab, 0xba, 0x18, 0x23, 0xc2, + 0x4f, 0xed, 0xb1, 0xb2, 0x0c, 0x87, 0xda, 0x56, 0x28, 0x1a, 0xa4, 0xaa, 0xf6, 0x8f, 0x7c, 0xe8, + 0x7b, 0x00, 0xcb, 0x4b, 0xca, 0xb6, 0xa1, 0x64, 0x5a, 0x06, 0x5b, 0x08, 0x75, 0x05, 0x5d, 0x4e, + 0x48, 0x57, 0x16, 0x11, 0x74, 0xac, 0xd1, 0xbd, 0x8f, 0x20, 0xf6, 0xbf, 0xeb, 0xbd, 0x76, 0xa4, + 0x8f, 0xe2, 0xcc, 0x32, 0x98, 0x3b, 0x33, 0x2d, 0xde, 0x19, 0xdb, 0xf7, 0x3e, 0x99, 0x2e, 0xeb, + 0x60, 0xe4, 0x8e, 0xba, 0x57, 0x9c, 0x79, 0xb2, 0xec, 0xbc, 0xf0, 0xcb, 0x4e, 0xf1, 0x3b, 0xb5, + 0x48, 0x71, 0xd4, 0xe3, 0xb8, 0xb6, 0x7d, 0x21, 0x8e, 0xf5, 0x77, 0xe9, 0x11, 0xe2, 0x11, 0x5c, + 0x2c, 0xc7, 0x8a, 0x8d, 0x0a, 0x67, 0x25, 0x0c, 0xe7, 0x36, 0x90, 0xe5, 0xf3, 0xa8, 0xfd, 0x33, + 0x87, 0x58, 0x1b, 0x3b, 0x6b, 0xa9, 0x11, 0x3d, 0x57, 0x09, 0x95, 0xff, 0x4e, 0x73, 0x65, 0x0a, + 0x2a, 0xab, 0x0a, 0x81, 0x55, 0xf8, 0x65, 0x4c, 0x3d, 0x11, 0xcd, 0x82, 0x8e, 0x43, 0x72, 0x00, + 0x85, 0x0b, 0xc6, 0x14, 0xdc, 0xf9, 0xb5, 0xe7, 0x55, 0xff, 0xd1, 0xaf, 0xde, 0x50, 0xd3, 0xaf, + 0x72, 0xc8, 0xa1, 0xfd, 0x3d, 0x17, 0x26, 0x48, 0x58, 0x4b, 0x7e, 0xa4, 0xf1, 0x07, 0x50, 0xe4, + 0x74, 0xec, 0xd7, 0x49, 0xbf, 0x1e, 0xbf, 0x7a, 0x1f, 0xb1, 0x54, 0x30, 0x68, 0x7f, 0xcb, 0x61, + 0xd5, 0x8b, 0x03, 0x0c, 0x39, 0x83, 0xcd, 0xa0, 0xd6, 0x0e, 0xe6, 0x8e, 0x41, 0x39, 0xfb, 0x56, + 0x7b, 0xb2, 0x11, 0x08, 0xfc, 0x51, 0xf2, 0x93, 0xdf, 0xc3, 0xee, 0x08, 0xb5, 0x5a, 0xde, 0xdc, + 0x1b, 0x38, 0xd4, 0xa5, 0xb3, 0x40, 0x55, 0x3e, 0x06, 0xa8, 0x67, 0x3e, 0xd7, 0x1b, 0x64, 0xf2, + 0xf4, 0x9d, 0x51, 0xec, 0x83, 0xd2, 0xa7, 0xfd, 0x19, 0x0b, 0x78, 0x14, 0xd4, 0x7e, 0x64, 0x40, + 0xb5, 0xbf, 0xe6, 0x60, 0x3d, 0x61, 0x28, 0xe9, 0x00, 0x48, 0xac, 0xf1, 0xcc, 0xcf, 0x4c, 0x15, + 0x71, 0x3f, 0x3e, 0x22, 0x90, 0x6f, 0xcd, 0xcf, 0x4c, 0xaf, 0x0d, 0xfd, 0x21, 0xb9, 0x0d, 0x15, + 0xbe, 0x90, 0xdc, 0xf1, 0x46, 0xe9, 0xdd, 0x42, 0xb0, 0x96, 0xb9, 0xf8, 0x27, 0x0f, 0xa1, 0x21, + 0x15, 0x8f, 0x6d, 0xcf, 0x33, 0x1d, 0x55, 0xbe, 0x49, 0x54, 0xf5, 0x4b, 0x41, 0xd1, 0xeb, 0xc3, + 0x70, 0xa2, 0xfd, 0x09, 0x6a, 0xc1, 0xb2, 0xe4, 0x16, 0xd4, 0x66, 0x74, 0x31, 0x18, 0x5e, 0xc9, + 0xbd, 0xcb, 0xb5, 0x4b, 0x7a, 0x75, 0x46, 0x17, 0xc2, 0x4b, 0xb2, 0x0b, 0x15, 0x24, 0xf2, 0x85, + 0xdc, 0x8b, 0x92, 0x5e, 0x9e, 0xd1, 0xc5, 0xbb, 0x45, 0x40, 0xc0, 0xc4, 0x57, 0x2d, 0xe2, 0x8c, + 0x2e, 0x5e, 0x52, 0x4f, 0x7b, 0x06, 0x65, 0x69, 0xe4, 0xcf, 0x52, 0x8c, 0xf2, 0xf9, 0x98, 0xfc, + 0x6f, 0xa0, 0x1e, 0xb1, 0x9b, 0xfc, 0x12, 0x76, 0xa4, 0x87, 0x0e, 0x75, 0xb9, 0x88, 0x48, 0x4c, + 0x21, 0x11, 0xc4, 0x37, 0xd4, 0xe5, 0xb8, 0xa4, 0x50, 0xad, 0xfd, 0x27, 0x0f, 0x65, 0xd9, 0x50, + 0x92, 0xdb, 0x58, 0x9c, 0xa9, 0x69, 0x0d, 0x4c, 0x43, 0xd6, 0x91, 0x6e, 0xfd, 0xeb, 0xf5, 0x5e, + 0x45, 0xe0, 0x70, 0xff, 0x1c, 0xeb, 0x31, 0x0e, 0x8c, 0x08, 0x04, 0xe5, 0x63, 0x10, 0x44, 0xa0, + 0xc8, 0xcd, 0x19, 0x53, 0x2e, 0x8a, 0x31, 0x5a, 0x6e, 0xcd, 0x67, 0x22, 0x24, 0x45, 0x19, 0x12, + 0x6b, 0x3e, 0xc3, 0x90, 0xbc, 0x84, 0xd5, 0x48, 0x59, 0x31, 0x0d, 0x75, 0xfe, 0xd7, 0xa2, 0xbb, + 0xd1, 0x3f, 0xef, 0x6e, 0x61, 0xaa, 0x7d, 0xbd, 0xde, 0xab, 0xff, 0xce, 0x2f, 0x34, 0xfd, 0x73, + 0xbd, 0x1e, 0x54, 0x9d, 0xbe, 0x41, 0xda, 0x20, 0x8a, 0xd0, 0x40, 0x16, 0x62, 0x59, 0x9c, 0xca, + 0xa2, 0x38, 0xad, 0xe1, 0x77, 0x55, 0xa9, 0xb1, 0x9f, 0xbe, 0x05, 0x35, 0x4c, 0x43, 0xc9, 0x52, + 0x11, 0x2c, 0x55, 0xfc, 0x20, 0x88, 0x07, 0xb0, 0x1e, 0x36, 0xc2, 0x92, 0xa5, 0x2a, 0xb5, 0x84, + 0x9f, 0x05, 0xe3, 0x4d, 0xa8, 0x06, 0x45, 0xb0, 0x26, 0x38, 0x2a, 0x54, 0xd5, 0xbe, 0xd7, 0x50, + 0x51, 0x26, 0xa6, 0xf6, 0xf3, 0xf7, 0xa1, 0x84, 0xfb, 0xe2, 0x1f, 0x54, 0xbf, 0xd1, 0x12, 0xfb, + 0xc1, 0x78, 0xac, 0xab, 0x97, 0x8c, 0xda, 0x09, 0xac, 0xc6, 0xa8, 0x58, 0xe7, 0xb8, 0xcd, 0xe9, + 0x54, 0x6d, 0xa8, 0x9c, 0x04, 0x8b, 0xe5, 0xc3, 0xc5, 0xb4, 0x27, 0x50, 0x0b, 0xc0, 0x04, 0x77, + 0xc1, 0x99, 0x0f, 0x07, 0xfe, 0x8d, 0xaa, 0xa1, 0x97, 0x9d, 0xf9, 0xf0, 0x95, 0xbc, 0x54, 0x39, + 0xf6, 0x27, 0x75, 0xc3, 0x28, 0xe8, 0x72, 0xa2, 0x3d, 0x85, 0xaa, 0xdf, 0xfb, 0x67, 0x8b, 0x66, + 0x64, 0x81, 0x76, 0x1f, 0xca, 0x12, 0x10, 0xa3, 0x77, 0xb8, 0x46, 0xca, 0x1d, 0xae, 0xe1, 0xdf, + 0xe1, 0x8e, 0xa1, 0xea, 0xc3, 0xfd, 0xb7, 0x64, 0x0a, 0x4a, 0xe6, 0xf8, 0x4b, 0x09, 0xd6, 0x4f, + 0xbb, 0x67, 0xfd, 0x53, 0xc7, 0x99, 0x9a, 0x23, 0x2a, 0xba, 0x8c, 0x0e, 0x14, 0x45, 0x1f, 0x95, + 0xf2, 0xc0, 0xd1, 0x4a, 0x6b, 0xe8, 0xc9, 0x31, 0x94, 0x44, 0x3b, 0x45, 0xd2, 0xde, 0x39, 0x5a, + 0xa9, 0x7d, 0x3d, 0x2e, 0x22, 0x1b, 0xae, 0xe5, 0xe7, 0x8e, 0x56, 0x5a, 0x73, 0x4f, 0x9e, 0x41, + 0x2d, 0x6c, 0x84, 0xb2, 0x1e, 0x3d, 0x5a, 0x99, 0x6d, 0x3e, 0xca, 0x87, 0xc5, 0x2e, 0xeb, 0x89, + 0xa0, 0x95, 0xd9, 0x0f, 0x93, 0xc7, 0x50, 0xf1, 0xeb, 0x7c, 0xfa, 0xb3, 0x44, 0x2b, 0xa3, 0x05, + 0xc7, 0xf0, 0xc8, 0x8e, 0x2b, 0xed, 0xed, 0xa4, 0x95, 0x7a, 0x4f, 0x20, 0x0f, 0xa1, 0xac, 0xca, + 0x48, 0xea, 0x03, 0x43, 0x2b, 0xbd, 0x91, 0x46, 0x27, 0xc3, 0xfb, 0x7b, 0xd6, 0xfb, 0x4e, 0x2b, + 0xf3, 0x42, 0x43, 0x4e, 0x01, 0x22, 0x97, 0xe9, 0xcc, 0x87, 0x9b, 0x56, 0xf6, 0x45, 0x85, 0x60, + 0xd2, 0x07, 0x97, 0xcf, 0xf4, 0x07, 0x95, 0x56, 0xd6, 0xdd, 0x61, 0x58, 0x16, 0x8f, 0x6e, 0x0f, + 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x54, 0x68, 0xd8, 0x0b, 0xbf, 0x13, 0x00, 0x00, } diff --git a/types/types.proto b/types/types.proto index f968b948..95575e4e 100644 --- a/types/types.proto +++ b/types/types.proto @@ -139,7 +139,7 @@ message ResponseCheckTx { bytes data = 2 [(gogoproto.customtype) = "github.com/tendermint/go-wire/data.Bytes", (gogoproto.nullable) = false]; string log = 3; int64 gas = 4; - int64 fee = 5; + KI64Pair fee = 5 [(gogoproto.nullable) = false]; } message ResponseDeliverTx { @@ -230,14 +230,13 @@ message Evidence { // Abstract types message KVPair { - string key = 1; - enum Type { - STRING = 0; - INT = 1; - } - Type value_type = 2; - string value_string = 3; - int64 value_int = 4; + bytes key = 1; + bytes value = 2; +} + +message KI64Pair { + bytes key = 1; + int64 value = 2; } //---------------------------------------- diff --git a/types/util.go b/types/util.go index 57c997d0..b8db686a 100644 --- a/types/util.go +++ b/types/util.go @@ -44,23 +44,3 @@ type validatorPretty struct { PubKey data.Bytes `json:"pub_key"` Power int64 `json:"power"` } - -//------------------------------------------------------------------------------ - -// KVPairInt is a helper method to build KV pair with an integer value. -func KVPairInt(key string, val int64) *KVPair { - return &KVPair{ - Key: key, - ValueInt: val, - ValueType: KVPair_INT, - } -} - -// KVPairString is a helper method to build KV pair with a string value. -func KVPairString(key, val string) *KVPair { - return &KVPair{ - Key: key, - ValueString: val, - ValueType: KVPair_STRING, - } -} diff --git a/types/util_test.go b/types/util_test.go deleted file mode 100644 index d006d56b..00000000 --- a/types/util_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestKVPairInt(t *testing.T) { - assert.Equal(t, KVPairInt("a", 1), &KVPair{Key: "a", ValueType: KVPair_INT, ValueInt: 1}) -} - -func TestKVPairString(t *testing.T) { - assert.Equal(t, KVPairString("a", "b"), &KVPair{Key: "a", ValueType: KVPair_STRING, ValueString: "b"}) -} From ff654213241611bfaafbc74040aefa83c9f2ef20 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 25 Dec 2017 00:14:13 -0800 Subject: [PATCH 424/545] Proposal: New Makefile standard template (#168) * Cleaned up makefile. * Improve 'make all' order * Add devdoc * Update circle.yml --- .gitignore | 1 + Makefile | 162 +++++++++++++++++++++++++++++++++++------------------ README.md | 1 - abci-cli | Bin 0 -> 17846814 bytes circle.yml | 2 +- 5 files changed, 108 insertions(+), 58 deletions(-) create mode 100755 abci-cli diff --git a/.gitignore b/.gitignore index ea27eda1..439908fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ vendor .glide types/types.pb.go +*.sw[op] diff --git a/Makefile b/Makefile index dc996d12..522c568c 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,56 @@ GOTOOLS = \ - github.com/mitchellh/gox \ - github.com/Masterminds/glide \ - gopkg.in/alecthomas/gometalinter.v2 \ - github.com/gogo/protobuf/protoc-gen-gogo \ - github.com/gogo/protobuf/gogoproto - + github.com/mitchellh/gox \ + github.com/Masterminds/glide \ + gopkg.in/alecthomas/gometalinter.v2 \ + github.com/gogo/protobuf/protoc-gen-gogo \ + github.com/gogo/protobuf/gogoproto +GOTOOLS_CHECK = gox glide gometalinter.v2 protoc protoc-gen-gogo +PACKAGES=$(shell go list ./... | grep -v '/vendor/') INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf -all: protoc install test metalinter +all: check protoc build test install metalinter -PACKAGES=$(shell go list ./... | grep -v '/vendor/') +check: check_tools get_vendor_deps -install_protoc: - # https://github.com/google/protobuf/releases + +######################################## +### Build + +protoc: + ## If you get the following error, + ## "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" + ## See https://stackoverflow.com/a/25518702 + protoc $(INCLUDE) --gogo_out=plugins=grpc:. types/*.proto + @echo "--> adding nolint declarations to protobuf generated files" + @awk '/package types/ { print "//nolint: gas"; print; next }1' types/types.pb.go > types/types.pb.go.new + @mv types/types.pb.go.new types/types.pb.go + +build: + @go build -i ./cmd/... + +dist: + @bash scripts/dist.sh + @bash scripts/publish.sh + +install: + @go install ./cmd/... + + +######################################## +### Tools & dependencies + +check_tools: + @# https://stackoverflow.com/a/25668869 + @echo "Found tools: $(foreach tool,$(GOTOOLS_CHECK),\ + $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" + +get_tools: + @echo "--> Installing tools" + go get -u -v $(GOTOOLS) + @gometalinter.v2 --install + +get_protoc: + @# https://github.com/google/protobuf/releases curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ cd protobuf-3.4.1 && \ DIST_LANG=cpp ./configure && \ @@ -21,60 +59,41 @@ install_protoc: cd .. && \ rm -rf protobuf-3.4.1 -protoc: - ## Note to self: - ## On "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" - ## ldconfig (may require sudo) - ## https://stackoverflow.com/a/25518702 - protoc $(INCLUDE) --gogo_out=plugins=grpc:. types/*.proto - @ echo "--> adding nolint declarations to protobuf generated files" - @ awk '/package types/ { print "//nolint: gas"; print; next }1' types/types.pb.go > types/types.pb.go.new - @ mv types/types.pb.go.new types/types.pb.go +update_tools: + @echo "--> Updating tools" + @go get -u $(GOTOOLS) -install: - @ go install ./cmd/... +get_vendor_deps: + @rm -rf vendor/ + @echo "--> Running glide install" + @glide install -build: - @ go build -i ./cmd/... -dist: - @ bash scripts/dist.sh - @ bash scripts/publish.sh +######################################## +### Testing test: - @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; - @ echo "==> Running go test" - @ go test $(PACKAGES) + @find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @echo "==> Running go test" + @go test $(PACKAGES) test_race: - @ find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; - @ echo "==> Running go test --race" - @ go test -v -race $(PACKAGES) + @find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; + @echo "==> Running go test --race" + @go test -v -race $(PACKAGES) test_integrations: - @ bash test.sh + @bash test.sh + + +######################################## +### Formatting, linting, and vetting fmt: - @ go fmt ./... - -get_deps: - @ go get -d $(PACKAGES) - -ensure_tools: - go get -u -v $(GOTOOLS) - @ gometalinter.v2 --install - -get_vendor_deps: ensure_tools - @ rm -rf vendor/ - @ echo "--> Running glide install" - @ glide install - -metalinter_all: - protoc $(INCLUDE) --lint_out=. types/*.proto - gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... + @go fmt ./... metalinter: - @ echo "==> Running linter" + @echo "==> Running linter" gometalinter.v2 --vendor --deadline=600s --disable-all \ --enable=maligned \ --enable=deadcode \ @@ -92,7 +111,6 @@ metalinter: --enable=varcheck \ --enable=vetshadow \ ./... - #--enable=gas \ #--enable=dupl \ #--enable=errcheck \ @@ -103,10 +121,42 @@ metalinter: #--enable=unparam \ #--enable=vet \ -build-docker: +metalinter_all: + protoc $(INCLUDE) --lint_out=. types/*.proto + gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... + + +######################################## +### Docker + +DEVDOC_SAVE = docker commit `docker ps -a -n 1 -q` devdoc:local + +docker_build: docker build -t "tendermint/abci-dev" -f Dockerfile.develop . -run-docker: - docker run -it --rm -v "$PWD:/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash +docker_run: + docker run -it -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash -.PHONY: all build test fmt get_deps ensure_tools protoc install_protoc build-docker run-docker +docker_run_rm: + docker run -it --rm -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash + +devdoc_init: + docker run -it -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" tendermint/devdoc echo + # TODO make this safer + $(call DEVDOC_SAVE) + +devdoc: + docker run -it -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" devdoc:local bash + +devdoc_save: + # TODO make this safer + $(call DEVDOC_SAVE) + +devdoc_clean: + docker rmi $$(docker images -f "dangling=true" -q) + + +# To avoid unintended conflicts with file names, always add to .PHONY +# unless there is a reason not to. +# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html +.PHONY: check protoc build dist install check_tools get_tools get_protoc update_tools get_vendor_deps test test_race test_integrations fmt metalinter metalinter_all docker_build docker_run docker_run_rm devdoc_init devdoc devdoc_save devdoc_clean diff --git a/README.md b/README.md index dbfd8634..902e3a08 100644 --- a/README.md +++ b/README.md @@ -200,4 +200,3 @@ Here, we describe the requests and responses as function arguments and return va * `Log (string)`: Debug or error message * __Usage__:
Return a Merkle root hash of the application state. - diff --git a/abci-cli b/abci-cli new file mode 100755 index 0000000000000000000000000000000000000000..445f635d8281769eb4fec1edfebe941a4ed8c7b1 GIT binary patch literal 17846814 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⪚{;n$}T*kaedlmhJP*V)@j5s!})IAZ}?*b3ydBZQy9e0O+(l z9?&U$j*7HdUfH!CIn2PFW)G=?_Z69m_~81i(nMGrDpDD7UO2pgY>Fsd8VjgoYe$zG9nolreYu!}fC1fLN4t(@SWKKm+9ThlK zsfxdx7b?6`u`7)(X}3HxTPW6ehx>dqBWr1@fAt_HUTHLp*i=uWmBQ6&ST zMh(8GYC&A0Mhg93n`0q(tHH+nqrqo+H>ehVyDpmQnt}46L7oERC*z7@X$yL+JIn@s7$%9yu z9~O-_DrYJ(DaA@bGH*SsFzYDhe0b^^AVq7}x2r!5^{qR`Px+6SUJyh4lEYkm?_aL~ zB-jOifa47RwijI$bPtb~f^oKK>K5?F4{YK{#sSJ=96eG|0hWmu%zFL$FMV+Bb~s{oGYW}uT-uT zpF}6LQdhye**8$Lo@-b09=YyXy-!*VfK#H!te!cB2Vp3`t6*W#KP=M(nwhZlljz76 zdKB=t3m1qMF6EHFHNF>rlS|-NbQP^#**@RDVUBSOS|nn@8sa;;X_ybf4Mu()p3z-B z0nhZne-M8b6aHCw(jO|xw@NZ9OkW0Nz7%I3Ttg(u5|rfpSUcB%9?=ct6k4M9^sQJ= zHF`pJ1IG>O*Jy=wfBiT&aG7*Z7T>s7S^s-q1Nz;@pACx6|J?bbdg*gb^q(^Slauyn z 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 z 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
9k%J(Aip#lMCwtsrg;! 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
W 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¨ z2tz-*&-TSQ31aM2oCE;@6MX3Ffd`!_-MPByc%Q};5y5IA14*@#Fba$G`vEBA^U=+) z;#guBN}0Eczs0J8at(p3P98^az?l}39bJ;(LG=p(OIp^Aw!gS@9$`JitvE*vQ%7&H zA+t|`yBQb(?2I=rn8W>mi8Wf?@dhb9H0|-G3cRV52oR@|^J70VPGtr6M)2pCmCnLX z$)Dmf_adB0KB(7wpvO1(IyCqT9uV3 zAWNzJKFGdiEHvyIvpS;1U?6zGuTDW4VYM$pW()I7CyO8&mL?{E$G2e4XIM=+jxvQH z>VtgCT;%`bx73s^+?ahvyl?MB=tuu}1m8fK*c&qyb>(NoOM45VRgQZ)q5!LaCWB&4 zfrroZBH(BkEkQ#o@iWRuW@_m;F-p(HtdSEmAnYEoG77l$=w0GcmB{_|JDvhofNvF<6cEQDCSx2Xf-}?7(0Tpj&ggWj zfGHY0BrjPeYtc#eLCE678K@KEiBiQ5Voa6Wm_+lcoNua#MKBCbe$A|t5SzK=pGg(- z_5>7lM`|_rdPGfcVry6C{PF7;2O?C`tQ-f8Kne$Hp~nnZUV-lot@A}h%KenYqG*BD z$grFIyPNy#mzdlEh8$((NCpKGhy)A$q#O9~Pb|hbh{bwJb)DIrT+F5*0QOAG3vigx zJK-7UVMK;cYeeN{s2H9LD&^)FQOpZ!cymV&-dHfu0b&FRMFRWEqHltL9wV}qb@OPy z+~|$O6@;pWFF8~u5dy93a>SwgFr@-to`@x~_k+sqCuik(fyjfW>p(;e+Dpfhc|<1S z#F1k{lRO{I5PSE@Oo*R-{DTNF{f}J;G0^}Ihm(;I&+}-FOoXUB+%FN#+Nrk7x)P!~BOxLn z1WxDLKIt}WWA3w>76XBYn|(IEJ-1Z+ks9^U4?^*YKXgIyJ_8meFw#)GSTy17%n>`tfj(~Lu&l4?$k3Mj0$y?#(LNPy1Ar%|~ z0CU9?4_VRyqVe=-`2;4N8o#9T3Lfh3rxoLC_tAZk`YJ6r9+yrIE@K79#u8^^rRoLP z+`K;A_-E9{2YoI)D=~U~@T|nK>&q5?*z0txbM40$YYUFX^*R0crW~%ufS{J=caAfk z-BBwq(hKJzSgvqUcpfY+SEU|1wq$u-Id6~V?eV-lnek`TaZiKIs^vNkoJRrU1(akG z!jHuClNgr3_oK!**sBaHT2-$fe~4Ch4{Kc(D`=p){fhn$1r5nFGQz7d5TpN8W9{+6@5B5m@wk z4BiSl`W8OwKflu&pa=8^kZ)LvbA+BdcU(>cfptNZG!s?E2YR-CpO;Ai_3D*CY7ht} zlGh0zoZ!#-`KW)sL|hLt@*H^^q)r7MPUEXMK4KAYTSVM&LJc8$u>;rmYj6&Io0#sS zF@*xAwNU#q@Wbh_AiY^y2eB6TBhCwWyQ71n_~tdW1F*pt?hGezKJqb7qhc+1?*@tG z;F);uf1z%*_Y6<~FgAjjpOHA_2aR0pHS!lii3%N@$pg<)ZF%q2Ehmt|1Op`YBH&Z^ z>_G<#h6(!@q?iD`BNImV)Rwd}6Q(Z^CJY}7CNw~@I??}8bPoDwmM0ORLm*FE)5Yi) zT8vm+_W@+$^+z)Z%7nvHFd9K=>*2HZaPWOi_^w`* zowtJN05xUgTH<`WOw{QVr+I6*nV(k0I!~t$mW(cg1TGWO)Zic!>F3o#g{a8!Lj2{WTD*cq8j1`J$8SJeKzc~#^= zzY1DcKcZ<}!7#4U$ip6orD$ED<>4HBR@4`mdP+I*1=2d^W*-u3URt|1zjY|+!2y65@@s}qXrrQVdw}Slr7>%$WC!N3O$7nN8{cS*%60orL6w9=q@%Za+ z*Eol6jk(TNr+G(hud<`QFbSirn`7Z;`V55)84h!K4w$Q7uUiPxeBPQt6{km1q%o@a z)_?6M2moDPD)#O17ZLO39d!p`%_?QRj0eYwtXKLh6Gh{QjbGv%4TR3^ucvVAL`zW6 z&=OQl_6PseC6|Mif3dWr!A+y*4P!t{Km_kdU4gBDIn!&+)m<2KaTPbu13ZY#FC>?E zQ6v}8#T>|Q9%kqRGq$vXuAv70z-0^GMZ`eYP;Xv_ugErcwf8p+?Y{pj5Sy6(>#+F9 zwxumF#8>URKaPs|MBT!+pOCh@;&(OLhp`z4vI9TJCeYCM!LkN>sFzJA*k-Dc)VKl3 zVvA%Rkc<$?N4^jwALWm>5fTirS=LZnssKnsI(<*uMgIpQ?6%AJ1xec*4Lp%NZa+ct zH*EW{?~7lSdM~wYZW+g>x`SDq{QJ%4FN{K8Y_Q0CIV z{|O)XD$?Pg4s`H=ORf`WgKGW1^w}LztnCu}qn^2yr;mWo)R-I`$5A_k(iy>POFv== z&KBsu#ejXZBi(?(kg%YFqE`qG;|rl^29B|ZSV9pG$Vr8j6J1Abx&#`>F{hEpba^NR zE&y&EV1hgXFb=G+Ru8!_Ax{t;<;a1h>V(@g^cbJB3+NYLV6mEpKH4AG9i+F9Fd;+x z2xQvQ+lOQ|PGS3An*-VAvz_h3FEYq4miG$j0DF-p-EspeFhj!!N-n}9J7@@^Ne07H zm1P&Bv%3X>bohs%KM4LfGKv4_KENkXIyfFwPzc}C{FuM>2*^{oSY5@|f1i>5J8l0) zw*MWBCA+n8Q-=2Ybl?8&(JL>FUY`kbcS^5&F8aTuR|#AHKcv@N7k1ZvcuJ1;=a7)p z_=O`wOg%MiAYtSqMA`~$?OAsi?C_SCdAd*NBmO|HQd(+4!_SsLu-(Ale?;$WL`R0} zhpyVvp$=N6)ha5odh$v1ryuu>`1C|z zVtXs0yp}&1pv-JT3_~OTnhaFKZ+@+z#mBBqCz0UMI}^DTzM6r z==@%ivdz3AYZlUyiSAYtwi=oNSPqGuU%x%?&I7HmLUG7#JWLi;MH^1&fr^&}N+w>7Wc3Q45hV`8S*gv1#fe zui+^Ri9#2j0>u#p7#d9k5{o#uK9Vl-W=*O1P=^;_>d=Zr;2K?CiE>T}tY;A69)Zs5q@=wzd|DNqGqEO|Ck(+ym2ii^oBeeOJReV`-e*VUKh zI$2stjH`B@kxyJ$=)?yWZ~-%yVIuto;V`R@@pd&;tVSPkD@UU1HT*JNKt(WB<&%Qy z!e4-Psq>0b_6(ule7zp#IUH2n-FifhE~=ARxlFgL|15hQ$NDQ6^?HHw(F4{FL^uM{4Lk*;Pb$Z z+b3XaIu~ZxE+L2NSIk_aQQ%MQrU|*()DcfATORD^66~&rJk-StBpp9waVlP*y;;l& z-e-{Kg1{*5uGeq5xqF?0HQYF~vZ<2AZeZ4%1Rkzt)gW6gS9Ygx7BV^&_cg5E0cpOP{m< zBytO+ieN0#i-tGKo20O>nFwVIiXfk(G_%;uOrv#^AULe{eppStsPTW{0Pq zi?=0Cl5+|hw`SJ`lIOu%ka|%t=EFBqW1OfqD;@u`V;q1?jb~4Q9~m;hTX!_S`bumF z7^RUC-lA4KO7GBVb)B1g`3?L68FCYS_SdN;mx4B|`h45K|O9r60^NQ@-4T;s$>F5@5%p`Di71wID^yY3o3~)u;%2)g894 z6bW=g)1?y@5A+w`-ks{Us7;S#K(2A?)wL_(rS6b}^r!Mj-Q;(iA#(%c>hyunrY1AjhT~@@vD>qRz+!A?TiZnfR8< z4h}<(=L|U}N$)H^!dINUjs%4&XtTfxnz=?tw9SQN0-8m4by8XJ25Ln8W=UD(@z@a& z6svBDXc1xBCw9lgO2@p>E42rI8DlAauXYnW1 z)Wg1}`k{?G-zP4iU*jjKkEgb+>D`H-gJ`~0Al%OuT3Ajtw06a)MO~fYsS{_UcE6z| zeISTtFx)c*R=9aA5?CZUS(&_!D=F}nwv-0}J&@ZosOlM6!)rfcBaR|;u_8{nWAT&7 zujCEt=Ya+hYif&#f*UG`(bQ6u4*ZRn+9qTyJ6hD7hq~f4;GN_GS+UVslyA#W8HT4e zUpyUMT;E>kOQ>grKG>CtegS=u zuO{+m@FyjpSwBga^$ik*g^gsp-y9uaT)VY~zgVp;QCgc2n5t9AtAe*@x zt~Z|Owww$$854Q%M2|f$HhB`5eY`Bi0kkIE5@*zea=%$_6&Vq;eBbk#%<^;hXF$l9 zW&JXh<;eqlUdo!~Cl@e`X7L@q;^Z|n%grm2`2YxX9RoZ3{++*W{%2#(%1W-l zwQ4v6q3to)Bj6i=rQ%zR4{o@r>)59#HU3hUwxh*FZslW?E~fLm(A5N}Mc4zK18~r9 zXx|zRcwm-KHzYf248qeGn?pk4&wa}yg7hc z92~`f*+yU40=k6I5W&Z}>+GI#`7GtBBHPcy=DwiGdO#G4}63=&W`H1{-XUteg^ zp{!zo)a3Vj;)t+uQz6t>`(3&fw5ACMDiInTj2;*?a=DSk;2_8Y!tZ#RGkr zJ-g8p^655YYk51t>I{0(F!~Rn%nsbF;GAr;63m zPeuMslvLFI4?)2V{dct${yV+0hg;O>`_g~}E-2r&FuE37o{K&Vc zy%4TZ`zv7xt9VfPAF9m=W~5nc2fET8LHjujO@wZGO0@qM(Ec7Rp7sMG4%#k4q0xSP znp-lFGGeQJiX%4UE|WLWU5F!;Qd)uE@2l;M)Bbl-5Dm|sVXZ*IE4vQ|^CW-Fw>9;! zYOHZ9KB~NlD%-fVSGegzQQpvob*<VhVeTI-e zJ)29wtx}bLG-#PyRK|w4@p5HgZ*FsqDS5KWxndEc*HmI zX9TZBoYnxt9nm1z2c4B93hJ8^w0S6`F=!n8I}XWZT~dr%*T!E& zvO?Zg-0;t)8>rZAyr*gWUCL-w@L&ZPjgzd=_^Fm;h`cH_#@HCju3aH}Bj=ug^sUmD zJ=VZ%tAl6vn+Ta>;5iTgRs(J8rJINa7iKaMel%N@x>HMi4NL@1TyO(ZM;jAye83kV zRHXuhbN}d>i092=IG`wGu0vwUs!| zSJ_$#Yb{|Y{{DWK=I=9xLYnsmE=H*-Q#2G>(2b#J6JTj5knmbAH?@qO7nqF6L@u?{ zsRC{fLO^V$oYW@=X?p^XY&I~%o`}IvYz8-weZ7~NH^?!WIS$g6DoVO)V}Ozx*7Ya5 zXlc#~H@%oLC4ow9O0Wo7#~*`ee6-nvHTlMnBV|oGH3w_5QPjYKJ6(4Ol29bjp|K|Y zd1ucF0M+1GOjSJ8Rbfy*5iBL3RC}uJmkC12Q~i`x~XF|BZfEC%X2l z_WU_a)EFD2r0kQ-NA{*^YE1hc6Ci5!L3FS0+W(xg%|B`h6a+%P&s$w|{uZ$k_FS&i z_~nihtv#7IS=*DLwx%^EG9HE{X@93nt4XmWXw{BbPM}iQ^bl00fpFn0(xYB=CU3_z zhA?@oGI=3yynqCs)txH(1oJYDuVBmP)Lzn7eU9u-Jn9X6-?F0&pK&b1XB^88UBfk< z_2oU5>y5NW;cUtnhd9{Er=C61#xSUZ*hLQX;9_Lx42eiZZRKzCx?7R5GuENU8kUQp zu#c>wlq|$RPN1L+-)b+2%fOf{i7=@zErJoH&R zP&j2s*8G}S8+$q$cJZ1Z4K$g;0A5X)WLCypy{r|)4PC>Z&ZwXdK?&Bkf(+1jGB)Gj zhzsF#0`QHrA&;%6Uv5!(h&<`1s}RrN5LP#L-i0RNamjaj0t|+SQ6H>M0Bt5hQy%dW z9*?AkJTUOII#;34pYW*A@l0s)BS?5mwnH5}r8QY#BBrR9@E9o#vaHoBdl<)a$sP#O z5D^fhz47fdxdd}H@`fTvejebNJjg;Z7`1UEtj%a4ys>xgpp|^~6Pc?T)W+*lmb-)I z^7?*WLmxd|>(on&`o~m1=~~olY4cc^>6aTPwqH8=O_F`YEY2&6Ej%TVl zo~dRZ^T8DU@%m|fDcAnzv+Z+G5bgmK{NVL83UZ(_)o3; zvKLiO9QNYHH@md@wdjiM{MAcMJ;vCuL$qJA6&Rn0GNz4BQv0~M!vOI|E0M*Diz2nM zP-}fLLx?C9gaq)Se2zG-mhL4@@!nZFOh_Mb0C14wryDfjsTiSCONbGECZlcB2isA*I*MRX^({!Hl3-;M5gatGbfRI->p+~mi!MctWpPg(B%-7#r()#E>f?yTi7 zAmv}((t^!;y-F*UX7Z*M5sW$7)wt#ty==vE{;|i+`ckg_&z0}_Mtf~7Jf&ym+Ad<> zE-GT3PntgMU1as?yPLE=&GuEcDrJK*Xw{gmx?1de!$0tE1$bgx=~GBSod$$rY4V$R zp0<#h;DEf#&Ii-)C8iPLS)yHNaL1pVH&6@|XVf8dM(m6~Gc6g)8 zo9uvxy}J3UM-T#|k6vu9yU}vdqIMuaVr)K*uT5Ukf*)$-%yW!Zp7ga(D`AaoV1C6c z(aH+M&X3EUQ^5m-#-J2DbYAYeIp9^N3mxm{*hJb=zrJH75x_V zNrtCvXQQ;Tt2Sq6cw2pRJXDzbAFSuoziIlsQS0-UJ0H)t`GBC5^N+x_$(6o-+FnD4 zXS19-ym@689X^*`d3Dls_~*x39WK5>>u^6`<&+LnV#G5JU6a;4NKNR-qc;B1|2{=a zWxKQcGTy4|frp$#gg{GD4nC04EfW2CO!Qaj6@O4>7=1g2w<$Lqae4rhBHXl>sK%*~ z``i;}ltbEDme7iiuew!V8)t-!6 zwMg2RVFAGxb$jc$_e$s^cNmh?mb@)$fov-2G_(bVnkpdrg@!6AHP=+J@VC|d2@p5m z0f^l}2LqbqJM=7=-@Tcgxr6rPGg+dO*72}R9WPr5EV7b)M8no3zhFx+5F!BybFeH9 zp@}fIfW^ZpL5zEG5MdEFxK-mIk%@<%Cnx!+VPE+49>KTFr0|?+$&5mqaZwDl2AgDN zqM|sFd)7Tv`^q9N9ehOCAxA1#6v?`&nG2_J7q|%~fJ{c=1?@;(5!k=3C;XHQbe6+c zJJGK81W%eM;7?(GIGsKD2+aV)hJjUM+YATU?SVGXvt?HQ}$8D2mHuG`g~|2aPc{_val_r7R%>2%La<7 z$3^%&!O=_*wn;|IP!Cb4nFT}Uz#(yU1AGqwK#n9YaFK^1tY_`u z>q)x?^zWau%l#&1yz>K}r)jA-fPLjI@y?vHyI`UhGe@;|o{d7|on_9>(cU@Gc9%}b zSEME6QA#)bY)Jd;+*uhzPi$qkl~il5~|U-#DY5YD~&B@=MckuKbkO z$cb_jtwq`wXt4_&Aw9BefLGQ)K`yzsmzIJ$vSXO#vQ;3Wv@_DN)70@fpx}@&7+*AmIN9xb7 z`gR6YrpbJ@NO%esPYsYy0HAQ&DL~bv0&uEQIMq466#F?=^9%3M_JLoOgtA)D0BkiH z!8dEDu4DzC!P667a^Z7;BAY@GlmW9^=Hc*o9v(Z*-_#A1W=J9#lBuW9)6Gb%5Fxgi ztQjeodS_z#J21?GzDFsj_G4F2hv+0hiU<%ASOJf$_$cK(4764~a-iN|QcNVG-Sv(p zc4Db~#1ZcSenD7sdZ;>VU}K>{4HSaJ@(390O(~X5P-@FzV8tXKD}*5_f95t7$jNXg z4b2HpIT+%LA-tSP5uZ~~LpHhkSKYVgwhnX^1XiU^qOVY^f=tO_V6j>7&;P2KOF{1! zdf;0DpUZ76$A?2Md!;q2G!eKQKMu~}bAOAq`23by7S5w!lslvnC9y={eEgK*Y|W++ z_nI&;0EdHW`!F4zLy64DH)2P;fFV!Tr2usR!@WInG!D)!Y^n$ng+ZHoo{6>wrnZBS zX*uW|zQKCd;;Xbiq1~neNu*=_o4f~PQ41~U>Yd)p^1ml@Q;2mb5KbH~0yu~pqni0c zH3k5&Ne)vJseK3&OcYr4#3^R{!J{L)h2>~iggA{?o)w5V2s6_xe zF#UA420^RFImh9tKb5=bW>SwV0~V^{blnl0iA~8%SUbI-m_T#d+Wm>idK3v7fNn2= z4lo($&=7&BW*Y{&=F1r@%ztj?8$VWi9lwwBm#i%T9*mLYe4E5~yWr!guI|7Co%oy1 zRqL`|{q0Hkya(_s?XecCt#BKjK8yXirHAyu9LCSaEOFw2qZhYk#Y4y9-$dYs1k5V3 zqN7*~;j;)`Jg`3sNdnM0@FS^MZYs+3BPwcc1io3sR*FpF3WA10VRbz4j1=}Wg?b#; zq~{vrf%{R&E}+zbHde%VB_4QLUfFm%p{m15P@T*`l_yR0N?bo7*M{TZooYFW^f%fy zc?p#bsgA%+tcUVcGh|jT?2T!ki{b-)#UfoybC*;Yaf_TX?lV zBs7-D-X9ZG`|C6PIAY9+xqAOVjP#A<`OZI!P>~?%1WG&t;8BE7GZ@d zFPjHQL>&^f{en)SKRyw`5f4le2;du!J-5H@3{6cFC=HT@(ysVeJ4~VmN-G57zB4EW zO$AcV@V$Wzkg+U~)^L-f{G8Ud)vd&LBmWkj(MFvItsQCmev_~p1p881E zaH?cf48{V@=lI~Bkfr+n5U6Z9$(BILWMa&nUO?c5Z7NWs;exrdA41`$;Y^>B!}}F_ zV9rK9k%bZsoe)T53RqMSU=-ae)SF&V$$K|<>vt)lXpIq~h(LmjD)`WD5Ty^>+9^?L z8UEDv#96s-PGMj-IEUxuilxSct4LRTAn8#p@KC|$8nXhw=C}(q{78l5sIRZvB|XNY z6AaOgBElXmxD?eLg(H}(qG@6zf6utr$d;~5b$%)doARp6{Ne=-A)nua=N|Df(3dwL zQIwM8Nn%0<4coviDFc0iOtpa`VQ-Gw@9*4@C_#uBuwd{6=|V5k#&cpWw24cB6G6Ah zW2I=YSU=5ILKN5uM4mVzvCcP=aXr2G@S8he5T~oG>EN;eln{Ya!X zG#*VPa%-hMMlL*&@M{npnjXb0H4nrKH@!{C#yP)Ii}}ZrH@F>rGr6^um67{O=Cb$y ziTj;c<+!CMrCje*FVgisgMSl&9gX7T4k0g%+igWb20s?(V$ zV?al86n@kr`y-xy>8rHtkUxLmmKLnh`E!}&oxJI3@-9Bd*jn?8?AUTV=N~gvYxJdD zZ?M;HU_T-QQmP@3Nj9Ok+{1u*OH2am53<>W10c1u#M^e$3c{pF z-Ot(Kt~$s5ziOSPqvB#hhFBmQ6{;Q1`DzN*dKmeuPE>?4)Uc z2XsU}v_D2jsqT>2K9#L@z_h4oyOg!*1fST8DA8$4gKlo#x7NPremx&}dahM0k~-=^ zW8N9D7Sid#jJFCvm2iHN&*u&nXnE5LB-M2U6uNx9*>lGjhSl)B`BgL;CR`9FV^M-o z8I&-J%|B9JJqYSg4-WLuI)e`gob-#vA{6N=HVcT%M(-kZha#wU3R8239ahjsQ#N>0 z$r}nsi&{0dD{lt0B@c!TZBfr;C{&yJLu${1fiyYI(N3c85io5Xj*Q2DPVe2gsh;C; zcoO~tAtCqp$7`a^KVG-W6|UVt?YveH9uhk1VUf_$a-Sxl0}iwjdgDb}LKi?7)y?v4 z0lQdRi_|oBK;o&D=5%{RD)cUl70%4Jeut!L7&d*B0(JSB((T|_gZ`^MSNs`fg3t}Z5Q!rUFnGrGG`gp!Od@9 z!}l`CjuDaw#Rc+U1P8)^VZQpsCmO;k%7#`p(HtX6kQykDU4L}%Xg~TevkU2ScZ+ft zr@h*u%G2)E9s5GMo=8cT-yVv5Nrcvzw*D>=s84WzU+zu(p;5pwAUK70l{OWS0(iN# zlZHEqV!BhD1s|1wzqm|)V!3Sn2bj)@mLIUL{LojqUah9Q`PDiHpNGqFIu@oiGVw*G zg^qx@?ih)jjrl|~dVsvAvf5R8Syp_56aS+91HMt3I&oQS0b_rFg5&Ht%W-~?hEDjw zb9hBV0Y;Q20iV7AK*{T=U|#OXYs1ZdfN+3=soas;b7##t384Uz_qt(@_*C9Lp!!|l zA#}QvJ|{TA*@@mX-S7`h?@({3vh{gXAPI*}v{p#6iA{?LM~Ge?;Vh;ThDoahdeFC@ z@CwAU+G`GAhkX?p1W~n>Os#brvR9NJvm9KY#{XT5ELtOrkuue5-F|zEj`QW{7&o;2 zN}Zuz7R~DotB?rYjB;d6<&(1#4!NO*39N$w&9Z2OCMgm6g|1Y{0mFTGf|5d(;J1js ziO>nUMlnL@%ki{WO2I7Xi4#qP`s-p&f*``ydj}AK2z?A0z~C4FcXRI@k5vS+7AM{x zajR5jUbf;rjbUZ`Qimlrb)-)83f%O9gKa@_l!Q5W$qhX+p4hR$j(?a2lNbl;c-{@Y zHP#ky^omzeq20hkCz}t4_I^Dxt&hK1(|R~X!42IZO<}Uh(t2-{TUyIf4>#0bpz+f> zd6QHUS})Wz?nLWlx&~++Zf?{y4823y54BSFzkU!u@rr07cb3$}p+D>DP6I2j?kZD8 z6vm1^f`5Q}|6ejsZkOX*o979gSX0vPukTuhJdsZK$8ACKDob~dS+{#-$JjDAwD&J9 z(Xa7}KO@nhPXK867+W0kiXTU@x;6w=t@N$B_#yf_`!Hbr|CYX9IN0dxqP3Z2=(8Ks z^!1FK7Bn(rVA*JMP9Md*MI-q=GEztOBU7{=PL|^yUH8SbzIkQAxhx14DwY`pAem{M^^4i_g*YI1GA)WN~n+>KQ zgTB7)mHG7bl4~tbUi6B6`g-?ew)lRpSoHO!K0DV}$xx)n%Wl9aHf)@+%E!h+oLz*G zX9G(Ce=TNe|60zPOsthWTiqp2 ze3|1i-bhuu*Hnuokc-f+x4dLwZ6BOMA4MqCKFx-JjP+)tGyd`VX?+Q!!hpX~HrWmO z)rrJnpc%yIt`PXB&kThyZXp&3ay%^Bn=#b9`96q7B6JIX&~~eB8$km5q@8AeslHTY z5JY~obNqrK=F@uoT#$|GlQ*rAx98}cQJ9Qcj{ER=ZQ*?o-147F{!`6=>N$qmfMTo) zgF#kD{*LrZJ@OArLeGXcETKMbJWCHt9z@Wjp8NM!ndNd4ec{tFIE^p%9x&LNHWAY+BvGIo6|6rzo2v2F^%t$P8ZXR}N$Sg-bdMa~E zgFR6hvm9kuBX-9Y48i8ZA7>#q)V!MGvG|#J@k=6!K*M;d+L?tM+|QDNTfu}TSxqPr z-6?zs&TquqL@7#!E8e)d&;82`aS(0kR0%Oo(=Vdi zUcm?k!+8_HorsTRK|_gY-~%d{57uw0~DEXGn52ogYLY=x!} zV&1RYE!hxunV{jO{skrrj!}W97PGN}pK3vkaU9odYDtw(Gv%?wsaQ`2v}0~y&gbPw zIU^VCB6icc=lJ;=PRO!^e?coMSmj$Rk^ztY`f4JrMFAlqlNDb~Nu5b^2qR?VI7dWz z0V)kcvQtw~4o1w>L5A1IX+yDC`OU?R7<28MrKT>zf7eWnnfL|6Y> zk7Qa?i&}cF&I3>-kfWidV3B|sM5^Ve>Q+G@>7kF9`rlOGv$T63@^m6FL|$_IJfViwq!5VLKcH5 zSd8!8Pw-pjW(T!GCEvtti+cSRT`^YSY#5Rk(zbMTim!f3p-Vrn8-g1Jy+m*wxd7J1 zqE8?4u^YPgu~yA{8xv*__EPi;-MCh&!sN_-NYWq|%e~*;1b*Jfra@{((B9NtkN4_c zvpN;H+`Iysn>AWFYD$xl3#PEZ5pW?I#F?v@L6yahuz)RU;W>I(UkD4%)4=6zfbzt# zoL}N}6CUNXuSEVMy=E5*w5YnY8tVC;AnY@=(4FWh-}_Df9tT>huw>NhF|-8=jeK<1 zWc&}0)WZ3CQWdaY`=F3}OsPti`&3XrkZnS}ON; zP0)zR31U*cHkT%-qD9>_O4AXmM3)o`9q~HN9jL66Quh?F5x}jrQb-amgY8byKLZ4qlmn3H-o=1Psz>2bpsYzz{aEs=eWO~wG*Yx0(H2B^% zIuNYKBlh0FU(ARLo|BgleY4ofHchLyRl+I_D<%!d8#grLAsfQIUh2#kbLeQ4h-ETVinxFFYsKfpz$FV%*s+_3_?(ROAb7@;ldf zS?`sV<`sN|s;OWB>Wm#K`+iH%GcR+(&4&sQO%fv!5;8Cbze>+g4k4Jb4WR-baEcTU zYJXIIMOAir$wxTCtg)@o=~xttzY&YCPVPzi!L;se>_I2PSK9MHHV3Y!b4R zm9*6&_hXn1Y@_VGvOK<+xwi^pjr1N|baI9G)cZx^8Q)e57Bls-DM&xXn}5^Yhad#dg=+AAU`1VGnSNk>?d|MoF_3zYQ{1FDR-gu*0CL^aQ2 z>RED>lERV=nj|M|niwS*gaL;dgRo(tHjZc|We{=!bRzVhE7J_Z9{cb(dJzR=0cHOi zD)h?5H=Ps_Z5plQ2Pz##IBY9WFG_^G3=iv zfn(VDS|t4Z()f$*NePU=pNJvQytWJk>L&zxcWfGg&fDQx%xX=b7g51aAh9#MZ!zbL z-F*V-rb&UND>4x1#qHK&{@z!t3G~YLuR4-daK@ed{XmW|8aGu^M=Llug&JTkBjE(U z10{3(6KsJviipHHkLP2qI|{F~|2Qh#VSeU#*VQ0KjfEkkAPVNaK>q z#j18I1nMd1St|6AtCW1Xr3D*w@Y7R|_h+*O1V63(MerlP2!8O%AqmzgS6OPW=ei4i z%w~Ux1q8+n4jKP!=KF|$4zlsj0#DeC6G+8BS7>dXC9i~zxyNX;jYeqkKD)eog{If! z9}Rz-TY{sWU#C$#-`{Mwj+22Zv z5_X11!w0lc=C%Kl6>?}GkG@EnmzIlE32g|h22{Y#lCd{f5-w;#EQ0B_ZZ>1#xkoz0 zXqskbJlch3opxtoQi|`gZNA4pUX$MZ>q2uo5WYZGP%vo%aK-+ZfCu0f0$j`|T3Rq^ zx0>H;19n2yDiX9h`6>0~e*-5sF#P}{wI{rgL29)Rs;o-$LF>Qrd{DjiK_{Yu-v_l2 zf8&F8Lu3o9c3)(5)0D|m7Zc!4B7361#^S?$#o7lA{R$@I-L%oXe|{78Vw$!WZ)kh5 zRj`<&*Y?0(Y{os4OViCNpP6Pw{L2_;tG)RA*u!l|Z|dW{R`!AyX3OtfBf8!z+psua zGQ8n=(+eI$9oYG8a0AcjkbYZ#Wc(zg*U3{tG7Yt2iN_=|FK_-hJY|AZcub;3JiwcRDN zPOM~cct*24HWmnWrILmzO1I|db-~&DVL!pe^uMwFf=H#(gF@j z$K%&tq*eXbeCmd740!Q)jaKy-Di~Eihs3V8dR`0~@Q-$hvl#Z;vDa=WdXd(1orTbY zBAQ7m7F-kc&D)BEcB#b|OW>xxfBU^o9L~TEeUNP<@soYU$#a3`&;+A83n)DWQO)M0;s|j7RXJQolyZvYu0&Iolbrm}+5sXn$S0pX{>K-ITqFYs zMu_|_2?1Tx6quMB}r}e+wbxCe;;i==kxiT&pGe& zzMuEGv4817`n;_h-**LX=KNhc^JY^kD9Q;>%{?G?|0RQop)>2o5wA^RC(+;ro?jpYyaDwwAi|Q+l1H1VgS@6I*s@RckK*Tn`pVZQne&=YIJ9oL^`L z6r7`QYmpU#3Q;0F?I)5eXV_!Qs_4I(UWuleDDV|IFX$Hw3ixtb_4(b{M-d+>twxFP zG5KqyBNW|^X00%PZzD%9qsYRi?oCUcjVeh`B{VTzzLNEK->P>4c#q)ps>b(->&a27 ztaT*HlZDI4>P7J!WffQQ2G&=JMaII+`n~LE$$&DnS_X64H2d({J+Ki${+peW%E(a^ zSlp~r);{=+C!S!zh%d`kCJ}w;*RD;o>30arX`uD;2hq#aA+Cp!$C+Z-h{?h>XB;0y zr(TE7MnB(McTq1H#9EhCP{MdCw zj2>7OPmfB`1NzAhBuC%)P0bD)f0Hh3Sa$X0RAhid-vZ4)Dhg-qF6${J+qPj?Y`(Sw zQ(X68mDAKYWf+eOWAj;j#H&@=wNhP8rUVSZu!LV(Zg!ol|1M%md&x zwyY*Ep1>}MA4_=)KF zKhPRJ+uHs>99*_U?y48t;Q|!!9Kfi7@MroM+`}LJWY`ct8^n*a-4pRdM6#Hb5rrTn zNvpPXW%S{@sx;rlU56wXw}TiA3eQ1ZOxO~;@=?l?#h$G`PD7*+?bQ!e&4dqPSK55D zF|X7HC$N*=ro-aPUmIG}_I_{ep3m0iVK0qqjbrAZh=S3FY(AFu0xRt)l{zxcuL!TO zZmI7`BjR1w4DlN`=0*ZXgKn1U4T@IGs-M!`mQpj9IEM3E>4eGs%~}Qdk8C;?`=nJl zcm)a!6bLpLSzyuX(y;DFI@DRHru_(|@6;HYJcjUb8dK|Gh44C#*iH>6mD|D3p}!x` zALj-))(F(Z5@(n2*Udfw`uYfT(i^hUau4(qKdjXi;FVryX$T#jj)NyKX@tiLZ7ac1 zh;_`**9W|!TUVeDg2D&?c0P~9=WoE(8dN_Oe!{<+V1K^SpB=(QP1sEwNOuUR|e zTFuPN^89{{lSkl6R~yLOO_kz}MmG8|22%f69D(C$+I?XS5Dkc8#4Mm zZ}9c>y#NGCh3%Nk!a4Mbjha7^crmUX)k+uO)=u(m8wz3_U-N~A`jUkm-(piK(9b6P zlwb>CK#kwUCewVD#w1?W-k6EU^;T`@xmFEu$iOVY>JjJThlVe0lU_#>YyZt)>q0__ z*^xD{4IY!D;z1LO<^DYP+av}Hi>(4{!unaq@pKj^Q;bB2AgB}&g$&Xf-9h0kg^q}* zkL7W8*^G}_?zrgbjm%*lI%9Ze^{{Gjpi1kxGW^aLB&^}{c8LdYV!PG@Rl_D#%;`An z$1<(HmLfh;bMj>g*&NEKI{26i2gS z^qMOyN5uJ2w^lM?Ouziqp*SXITrPt-aX7<8pQmK{j>8KWD{9#TlnpNs6^zx4yQr;; zGE>^A-}MotZ!R$RFk94=iK4fm=$_xuTRin2QtqIW-b}aNIc_ucZ=o@DiNha=R#9(J zt)RD9M{^=QkNJ1IaiWtl4VUJ6`yOY$g|gHK(!+#Uu4UbXG)L zWZFBV{bVzBI(fp^_jScSZ0cEtPpVmQ2&v_TVKto~*_zdAq@RJZFx-EDr?O7#$)%st z1F86h;fG)DUtV~?U$HSiWmF<#W6p|4>sOEtzhBvMsqwAvKi+LsyUGQwegb5TOPZn= zJ|p|G)Y77NZ(iEI`0ju+E<3A2sq2h!IpvkexLh^H8JCx&nm6Q;(@u(yx-aIVD@vT8yY%jsez0X54hjM)H&vD*9}r&I z*o=t-Yz3A)5k=m_|Jfz+3D4`uwP+!WuYyWh&9OFhsZ5P&D5e*Amqm(uFXmUI*Hmi! zn|`d*eZD7^oK{XPrIF@l+Kn`~R_&s;Pm{m+WJ*6XYN8rqmsN#mw8&>P}8oQ23{h#1$yQQ_^oB0@3itV)Kv1 zekeTB3BF>>cIjkKxQ%qn4(4%e*-3ewtgE$7+2`GZ!JYMkc|ez}*gY81SwDmaLu2!Y zx(7o$>lvEcm>-+}0kTUO`JMIoJlG~S|F7=BHl6j`@L=26{HNW6Z9D6?_GZZ@qb%S_D@03_7;M99z+c6Pk#B$TUD{6uTQI3kHb>w z*9z&;a_PuQA`TT_vxviT6U9Vw-Ul!~EgSCt{A+hG8?mt&jo4KvVf>!^}E8 zI?+cOW*(}$lYEq6=I3>HvLXyr*dS^(id!p{YSNe~p4OvvE5fEyQy=HJ%bD(SvR#Pn z*wpuMx0k?@#+Ul_w+%l(b@-v^^Jpaa;ZJ^n9d=B6Q!;FIejw-G)@DJ!DZ z@yyKAW6KCkcaGv<%e5MdRKZRc>A zd!ee^m`@kpxQDgsI(J#%E*&hnt_LojSG4HLwpqJ@nby7rrfb z3SeLa)kZgTFPLoR&g$h}9$VC%+mi4XyE#4k=?&WORcp{jyA*HIrB8$IV9tY~tWWv7 zt8rt}jiZTu+IO{UUuBm31ASFQKhW&y2cDr{Sm@hVs`kmbZQh4Q&Kwn6me;m!{ls;y ziS;6u7w0E-%`}mzhb_AbJypU-Z@7yH*rfpfWmi2MJ*bzHCtMI zYq}@4_WL;9noFLeHRB_C_i4`wTh-@GavGzTrpFV*oKusdX|6rLi`V0?u*;+wx};qv z>74TL0>*nxY}(f6X*JDVU~g=9dv{B-{XN|NvR7)ZRJpb$q~ZGOpYU8%rphd#%$}85 zdHZX_@B+N3blydup7$HX&ZE4k(?Qp#XP=H^l+OMIW!Jplb{%uV(g|&n66QS%;urMM z@G2E0iqtcKZo(sT*~V?R5$!LrsdVon+|OB0psF-)h5im&(O;izaQs&;eL_!4e<%>W zO&GFWzOjMPafMR6sN#0}*cIj{QYXe0LdxsV^m5bZ;kkfn4Z#{5t8Xe8SK3}W0FjCB zpakPMig&ebEV^hP1}cZ?Lt7VIXUgd5^mgT@&@VM*_r;f{60G0 zoq`p}@MoAaCq&J5P`iG4lvXxNXR-or1L(@@tS!SKs~g-oy=;7JS^bdCQ_9Ani(znv z;>O3WmFq(^N+c+v2y^_D2!~#k@KV88DT#yH)(0OQn<7IszDO4h#kH!41cIXO zk1Tvq_!cWgggmjtu$d>z)3sr^c&8hNn;F-mXb5iRA-ao(-)8QoI~#hV!W{He^+!)Q zt=NdnSd@0~4|iMxbIR7rBSH+#fco zisHZNLW%Vv5@lN#A}TvPcx1%>j@co11Hc-&8!eHBBYf#8(5AD)oIO?Bv-QJHv1OxL zH)D{smxfajZ)dBBKK$?ZkEzP_&&B^NO4!+qk@TdZ5gqTDdS`@|p2M)%74Fu??CHXa zLx%}u8d(&colz38_6O}diA-Df2j;?aR#m)h-7s-&Lp*P_u2i`kwO|9M@-D5$*}g^q z*aSRo_sCN~V%uf_aJRVjX%TS%XizLUX{V!aWxykUq+JS&xtO(49HCU>IOX9P3^YoU z;n&96KNjrZlCt{)8TUW}hXc~QT%=Ac!s3PwbK5w-CXl?ULoY9lKSkjw^CLMm5jE+g zPlCc~7JF$>l3L@8LDfunVeZ~X$CiyOsG0EIjLM@>^syuNe6eQ2V>7;ZR3}e+my=}< z=U&@zW;ER(3MfS0c=+ash?)MSGD7IJ1vHSE0*$9iC77djv;qLNPHvG%0*DQ%(_p&r zpRRO$((_t)>>pspt?VBYwA&WcZpz>9^Fi;tw<<)?#1gl4V&JbtGi=U{CX`*Ie1thF zEo0h?Smb8o7;o)DJXrvh3bc~+IKEl5hy0k6m1jJ>k3De(VnJ7}poK(AUKU5qy+|9H zDnWa)|4IObLF2`QA!Qpuy z?=FG5&_tiarxTJejUr_FF#%}Rs(ne+27GPtZ8xbKw5r4E=~!4EHoKB}t+O(aOd56$%&|og#9>aEO%JP61g!FE|Da zX~w3X;VThFy0Bg*(cw9dI1w|3D3{@J)4vv^r+<};o8~<#?pqN)K3we0Q5E+jra&Z3 zU!y$X$d#v(OT(e<1BLPiZyjhgtS+?-8DR&a%PyVD_*Tt?O_vuRu@ba`OV($pagC{; zkfk;l{bj3tx4yO4!sDgk{I-6z*ZL8rt)NWm#6ak|dTQeF9{7y8%^H|Z-AT-|Cb5Aj zv|1{o2&lV*6H_O17d}|%n%1N91|OVfsPvhy~i^WG^q2(~Wf zN?xRpymi@maX)>zT{(G=Bdo-*O<6jxWeXm*NHRXzp{F*{!t_MopMIpxq!>G*vZX4B znFJ45fztt05{)xw*Ugv-Y@}h9kZ7F zXvkY=Tb!n4l4o^-4bF}}4S)V9K*`2N`vS zi~#|dfhrR|O9cmq`{1 zR0hO~v(Rc885rW%LMvEPr7{ChG;87uquFeiXfJD3f*<8H?c-+nsYQ}4S?R2n0Ff^X zMHD`Jt%I$y=O9mh-0 zWBZCP03IIW{FX9tQBL?FEexK8$SM|Ec#W&Js%LdvXbcKJZ?))MbNbzaaB(-(-P>uZ zKKlCzrw^)f`-Aij)C=Hbg7z1@QiyfDBx0g*V;xT`1xD%MsblzSyB)A&NHC&pf?^Vr z+PTm@J6{)((7Y};-k_~(e7{TwBM}RkEvbn*E2jQv9r#7v3CW}&VVWa?IK9k`hsE38 zqnG(Ay-W?-<=IilCKu_hW+{C=3q_TOUyJJOSs0GWH-E@8vv5VIQ@muF!N zo9_M6$U7>nk>BS+BRh3*jhrL>)J*5|b&&L_jjWFk&<;AHv;*x6J<^@gf~XlL5e>ow z?UYoKDpks)q&$?evN~zxxS?t!k%8GzBZFM)exR55vJYN;xiDIGk)xv`bEy=L|1B)m zC6(Ov7E-Vu%*cO0F$z?`N-fhwm~zQqk=8A&oI9EY1}sRJF;;!B1FI`naSkj?9JESd z<($_5RqF>RrR~uI#XGA2+~0*C4fd_cdgv@(AO3#O@i&b*51zpW*LzHfp`v-z0&KPm zWc>V1XH^(lAs(&0@)d(_-q{U<`FYOZ53YE$0plcGt0&sAMRFpki7lI!*J;tc69*IB zW2EB3A)0DGHnwa+Rp%U{ZRnXeXf(}Orvxl>>Otb1!ehCZ&lCKR@@fOf<9aNJv^c6L z+>Zq(qUpg9V7e0HNqkL-FO&GX5@Si65T`@P_$rOqo08OsSbMR-=);%>wK{_8ez$V< zfD?{1zz>W7C*Es-A0)sl$!LIADFNWOk2k=t=i&fgsOJD)*$40$?>N8@0y+p@O&qbh z3@@&_>_8GkKd|B?juzmR0{nUn1Z+#NyhD8~I*+ZC98ZXFz6p+Ly`44eyc1@T@A__r z08&Tub5QA+%rLzu=!{6|A$aqJj~` zR2%m|K1YvpAdeZ4Vy%{w4%PrspL%Re~Xhw(IRj5T5P+-GO( zNIYsV0}liiyY*!GMel@{_r8Y`5g(L;Nt)*6vHz1aygBkXvl;NqC5xr$u?ajbkyJ!? z^fYfv9^?qCLMo(fL$7n0bLB>g44uw^f`y3UD)`>n1w-+=m z4w^pjxVc%tMA-@!qpvDdT2jSdlQZ@ZQ#8`xYYts;veLaWnBDuQBDyxzZHB@%QZ&s;u6magY zL5laQnXqQYF=*Ri+ty52J7Y4bk=rQrJcubRM4ykWe7a>9?VT}U^_=HcIz5XOjtriE zLN(Eo@Z8PP3H@J)Z($?+*wnWmZMf4i(58J<)2hJ|2-=yWoS?bI6s$e5flZ$+gWsUK zEOf!;ugj>QX9ldcjvd?@_^oHj;>@gQ7JAPn=Ew44lyo zy|Ioz2}UpkX`S|q3r3jMJGn*SkJ1K#8apk!TruDWtG@S~z;mN5^=b>>+GI5;h0ifo z?P{dWrJ3%OA3KP0H|aaN9K{Phtfyg`K7|05!ou8XSrL_0gjfB{^)ca7Q_a5p=>T1y zwu|EN1e%cqjWR=LN=7REsW&3P256K8(CD?_@E3<0S|kyPdcQQ<(9jS1r#|=;=>PE3 z&jNjT{x9Lu&Mb?Y;Xj+-c56R>5{!)lVVcbhxQ(I$c$IFIhZWo{Wa<$N57AO82Z+k5-p7%n$mji!P5bdNOnHY#0KKg<~N|9>8#G^8F-ptj~ zHMHJBOE99mI&#I7j1Ra`q*)Ed@C5f(^}io%0lcW0H*CyYj|SzgKKo!O(-2S(F5ZPa>fG@a8%ttmXa30)+f5D&p#Z5k53+R2O9R%lO5fHuT31}+R2uOd&Eo*3JqlxFVaFA*C ztzvq=$%O4XW4cs^3#nivY{AWBq!X~i&VkmvdVi9Q#QPo%$L&^)+p; z4zA66f=65I>-PP~F!rM($3COM6ZEvJFxqoN98+0?<&Om++F8n2gFOY|i01`W6cS2{ z(51>WsaMN3uDL+zNYNlg!89Jk+N$lbt0uN=+zwT(TlSB&pJqdi+Pw&K!KQax$jBq@ zFSC3D<{BZM+&Oe?JU9xMdPA(Ol$S?#R*&Tl`P@NY2S*K#ODr#9jAng&`4$wxN4@bq z--`$1Mw!-Fi@pI-Bf-=rFg4HA5Bp@b&r&L=-63x(rhopKx?82SVU~M$mwTd~0tVfw z$JnM-3L%*CNmi_ceS2$%^XDQEyJ>Lqm*_^QEe$qAU6Xi*S6u`KK}8G@!r++9_HXs@5b2Uh8dTz^n4r`*gT_Yawmn5&|_s3U{V{rLwQHvcuinrP$R387vkMDE^|%^hsEt(s71vgA0dB)~jr! z`x+Mfnyfo>d1UtR1REoBEYS}{Z(AX`fE3XVB87gkIKunEjElwkjh!R+AXDMYv&c|L ze}(a*^)pWBoW2LM={F3YiK{$qIFASG@dO?-HDE(*W_fJcWY$X_GXw)RW7p2=J%(sY zQJ}AK@|XB{>_@4ma7V+5>x~u1yUYIWvaenKYmE8-8yksksj0aB;aA=@2J$8%^;>zy z|1D^>v)9v+)v0wm<5i|klq<|=lT#pWm8dj?Bt4#Ri>hn;X$)z-RV(p@dQ;ci^b>E> z%C6(0$>SLduFeZHqC3YUX zgMEg9)Fl9g^_md+_*|y4?^e{hdH?3~TQ?tq%GR8($LG8$2cdzFtyA6@CDMIygv8Dz zABtCnEhL=EYUg!2htR<-yN*9)CLP6R{-^cd1VPTHAsb29SA3uj6<-xe<_7#K9DOHE zE&-2GlQZq5Klgy^&zX6h_tt7bpIB1XttFX`xYD!p2nO)wE(!) zm%_)EWPvHRTgFqAietEz00Ub66SBixAR zPgHwQc*At{Wa(f<7}cQXa`N~Asc-0w!@I^k-5w5nY6de@f}ftRcS%cch|)pf+1t61 z&_Sk@+x^B~o}}|06{YDVtM?jJBL}U!S@1j1dlK;kBo7MTIbNXZ^=(Ai$W?R?goom>li6C>8mHfrZWX(g>WT|R-df`ovzcyMUlSqM@}HHG|Zn0!3}L& zU?fy4L_U#JG}BLM_UmxzuQS=fF+ z-=*c@Ps4NMAz{b7^^u2r$n#&4hp%t*pUA_~3mwh`dRiV{u8ZX1+N{?m58>TEMBCn& zo~t9BOZRU7*A*X;Qo%-)&?gu;zGm@_zX(hH=7-cvv$p?G@9bD=MOTpqsZ9l*kd2~n z$X_BcgR$UF6RMM--*F7QKhr#2_Oe|0E7B1i>0J95AbVeRKxRTv;fNbt-?LK65OFe> zTpWyJPd`$VLk4;l+(_RIu%l1HybKSPG^hbXWO{3g3pUalLbGeB&(ev-<{c9g2(No}ry3b3`I9qnpS zrVWIGV3o&i(bf%W$^~C=1yD&Xg+r*Jc3^r?{Nopo!_Ys{@&#$QE|r2dlWx*aX=x_? zL><>l%+N5%Kk6QB3xddm3np-g3`1U7{X|MsNg2(bE`b%cE&F<;-9eVvGKaKlU3&1u zak2K_$v7$Fu9mT7q|4MYjO*Zu2gTa8=2LiTsjJLXOMX zhdNDHB1D+M?&53x)c&nQo0=(23^cZT*uU9IlyNI1r{<~KHt`n3>0nZxtNZZtbp!IV zKIiBsDV1}TAz2{iyMB2)-L%bOFtv_qT&u-XkpYmZ(T!swY;w5kC>0<%1wCfoOQln) z9Am?Q;7>dSLrRThaRmNg4rYiWnUTnFL@@r7KO7G<}9Q2|3Dhb~#TpuicD zeFSz;Sd@}T8oX*`JUJqsJPC$A4)E$rlA}*0J9DFpv@Pp1%8<~Yo-)PBRK;y+vbfS^ zDpwpfuuSzx&US3WQ6Ep%$of|#3wN?i^*V3w1nsvj%Ij5CvT(z;X1Ktq7H!gV;4#H} zq%_1iDJ#ft>%DQ1?F{DpFv}%FeW-UL8<~d{NnZH*^uxu%hU@!`h#ra{t-zT&!R)%; zD`fqicXk@n@3T(Xd*cluN)%WNW`+pgX z?|sa3|JkPx%>7sAJMQ1tasQ5g|8(v@o$L|!KPNB;;{HQiCgc8VEYkqoUu>C-`%mn{ z{hNlSxgRBx=6;WC!!ufRblX4S|1Rq(s2`HyfA2Il_B@fr|LKR{%i{m&VVb|SYTCUw z{{NOkT896N?7cL1;Tz_Z8UIJwQjhlK|Iz*VfBe72|2YKqJNdu}xvYUK94cA3crmi@ zAuhC3ct#$uE^A!>{7Chn=e^}5YKc>tfxlv#Bw=2gkF?HrmNswAk`Aj~A}@TcHp+T! zzQ*5_=*?PxQ>vSF{-#_vp}(mJzvqPr&F19-0wO&cdvtv-4W1!Ks11#A;ZUF(?{j8@ zPF;gSKMPeH7NIKB3-UAakqOsxz0dVrsYELs^pW#_eB_! zk3OAinSbO)q{sL*A?b;}5fF>v`(pw4`Wbo>f_|RG9GLH&ly^ z&Fuqa(d>KEy+Pskt^c5UF3HMi8)(R_X{AJORkq(HlB$f4RS=dP*jKRD^ND`?e1l6` zdcgiM2FGzo`+yvRsJ){;>hS9kwHv&s4dnknAbFYhR;%iz8!}tn5QyNg>4hv%o@|#% z8%sqd$WhM=*Q8!v_ePCSG!|f=N%Tkj}rZ18`vKc9Bf;=X1cpMI|f}cy1h1*!B`f`=)#Gno_a1If^(i>Y;MxA`6=Ex)< z1r~af2&{7NB?5=&aicj*LE-5i-3UNFmLpM@rZ8d6Ql_(6Y1Ya+AJDR|#fR^o;W(

Vr%(Azm#td0FZ{cSF1?3n8+Y-@$k!bgmfjKs~P^ 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ⅇeNSugI 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

TOGp4f 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 z z{;>ZQR=ZouCF7*KX6w$OiINd%%8*17k8pmZ2|=RK%E*Ng#9l7N!1&@5XxlrEm82Hk zA^1dygc|3?tI!G96rdGyvaGY2#qn~O%S#<}Q!mI{2GSClQ~NgumqH`fT=kVa1aIx( zC6SfNNJ2!uG9Gu5#7sksU(EJdWY5eK<(K(68nsKh{t%iVepB*zPBuiPpsCO)5bVo$ z_+21BaA)I_>L}5lDO8hJeZ4lFqh&-*(;y*!LD!(Hc^cue*B5L)iydpj!zxrGtUVCB_t;0fKZSLB<63GQ6h%Q0@ zUTfF)H0~mXykhdN?nOZu*yCv9E#8h5BkW-!>O~BbuOXlCj}p^}XUh#|7n&kt!8;>r z1qz83-Gq7Rg;`bjKUcE*EQre+=idAhySYvdGz?BD^4O^&Mk$M8i2QU)?J-el#r^sg52Q+D87Ga+Uuu-8w z?NOnvy|$D?aH~9FWRm%ltX*NPxxE810schTVg{dJ;!L8&KmMNM{D$~TJC0w>=3Qhz z-ihK5Ls4B|>LxCW3O!*C|vmYt;3Fp^{n8j-I$eo%k{|eoD4mv~4mW%%%;;seGs%ihvOmj4;;|v*w z8jg%i3KPW)#q_`)ona_Ubg#LdgD^BxQE4(W)p6Ry%{%1XC9X%3$7NC~d6h^Wm%R5e zT?&^<%>VoS{np;+>@yGC|NZ>`^P#=ZUa#MK{nlE)wN|Kst10+W1IC!j^JZN8c7y0r}h+IBVQ14RE~+jl@!Z~oDEd%IXz6!vieGn zg(@l00r@R!UEOWC6G@ylr~isNaP|TKbjMo&cg+M$yXTCP;BT&gn3`o82|q;kNCIb* z*|P~zXGeu@g^D4ACjdm~DDvgNcpC=e-(fJ0EzoA+D}9YB5unI*o}PjzxhncJ|J+Mt z8R}LMKb_W0s=?2y_^$Zr{6o^Q^fH%XYzHpB(Db#tn#&YnfB*(504yQeuveTvC4&nL zgJsDmjOevA=htI#cQVuezi9KG^D+L%O#

@ zu>%iYVyOJ++}Clf{h_&KfDD|D~u2Yn^< zH>pL_*u%TFYV7S3lN$4w$cEZuqSuJa#HT1eAMW8YQPK%)^M}rI^Hml@6rT8>VGoV6 zf<~j*i_=--AK&N68{X}}%IN-SLSmcwkU7hF=TfCVh%AP|b@XOQIh3h+C=vE5dd6Z2 z0|@pwo2%P4E_UERa~GKQl0iabyDdVkHXs;vDl4Jtu#s>=dqrPx0JOK7SX3 zOBjZJ@Zb3Vy<>x9xD?}Gy6LQT9>2sJ^j+jgNuP-uZ$uAp?*o}NTBVN+y;ZX?G5jZIgb!k)%r zPkRB)T}g81UoJKII{%8EUQJtCY7W$Hss*#y7)U}$wbH2%(+a8M0nHo>BU;ZR7FRSu zPFkA3aIW5+lI47`21IS^{1phteD%+20YCgR^}-kEKm`8TYT;wxh=HavxZ9kQBIK*| zcJcupUAKf06%OmT_OCmuv{YhT3mR1+QC_Oumx=nK((S&_gqlnHsxxXMb-R*}9{dG)m>p&4qjmhe=SMFu6oHoz& z!lZidchg~9A7i`ImJuydv~1tj6wTRLiKpGNq3B*RymtK%s+F^@vrzQKRiG#%jM|l# z`D`=g{0Ws8pHs#OGq(nW?L=Vm6l|b|CuAK}diPlx;3v1Vy>r0^eRX z|BRuF)IFBdA2lI1BCGMOP@`_xAAwwmVzZ(nz+~OfyivIU%#b5~F=X1pq?WMPdC#BNM-stdHsm}ni3ui@ zkp7kN#ZdAH;-8=DgVR+q^CJMR4uEPH3n#bCUV@tZuv0t@t|dwp(6qy1RfC7ZZ{hDK zimTQiKMb|HKdk6Fm$~ud@!iSjMi&o_-nvj5H35Kh^+h-#`C;d^IyP2AS43JgL<5`9 zpNg_TKjIr@UPhN}prv@C_&uBKuyqnHK84k+cnP1<;urBf zx+*@xOs=eCMwh=Jk5K@%?J~peKF&SM`2^z8BZAdG7pW>t~_R*O?XmZ zM5w52N3sf_v4IJ+FTLc0*q2v6H})k%zReLW4mCbPs|Hq9iG2~%vRn@a`pN3E+^YW) z2Lo*q<28vn?cv4gun*gxF!q5i7aBtq6w!C4kS!c(ffHfM9k`BB0l6(e+5->>OrNiK zd1%HLV%p|-izm=`d|k<}43vD4FN`HFk!UJ4S({+8mRLG13KjRJzHq*nfJ6u}y5R=Xyv4;zjJ(kz-RGeH###*gz^EjQ@iRcRU<+h@3VWD=Xc z1>|AV)y5*xu)%tjM!RK~+L3Hnui!rpqV>W8KhH}ljSkN?)(fNrUo4?yCARj!{y?}R z*y|jDkk+wcd)Gr4x>#OXye%|ireNvLA)q1odJ(@CuM5qPlM(y;6tT|-MYkVqE%_3i zzz?A4myz`4gbvMmN^K9^{c$pRKz;;#1PBs%h528ng~q}T6vd4}ebL-_2vDq~48=i3mix0kt2!}ZRkd|m)p@g3V1ORBiY8fA%z8WZ{zUE9Vl9+H;{#|*O$UAK>-do1{ z`oooUG3WpxegqPo0XvWsmOc2@M=48#(B1gg3Z(I0ucXQO0Z{u_+4Epy?;5*A1p zH-jgDK`SaTq(%ec*IyPU?B&2|!dd+xo}`LkRQ&UV;|)yG^T~`T)g;fAB zGVxR~4z8$?EP#9>{ic%mJ9M^g%rNTN4>hQI5?^%c*#KWA9&_bIoUYR*c)hz=EEj%( zUEl`H@e^PIBhe-+y4i|ui_fR8=ThD|Meevxhy>_vpsI-PkDS2eo`+mt(?|w*;Ppws zD(tKt-;Sv=7POkoM9tbv{7z$}<^d6dzmRiX{3%+f8`9NS2l|+XNo}<0_czC&O~1dX zf+GH=QC;*7CGk_>7dm%72eS~TpXdH1?1Rjg*HBOw!s+W6A7R1L4nF!6S2;|Vg`7$F}q+F&k_F2RjBna_eV zmqOB9#+YXcf1V%@TJr~U@(^X`&0}@W7aGd}WN8>qkBlNgYI;5p1Q40}iMNS-gI>Ga zQ8}>>YJ+6lzX?e#pnO}*3UsMOY-0Oy+5}K&$gd+b&|Hf@q&vY6fBd2Tc5LVj~;XZx(lMpPj%+wdn+$$E?(u-m`d9N%Dc#Z6Z9KvHr0vfsi4K>eIBTKQ= z`>_EH!d>-@jQADw9h~7_+QsKV8oQ_t7p5)CxHu9D$%y3dard z4o%&4XB_ms?G{+{;&rtD!xKz_= ztpq2kd^VX-LejfibJap2jfBfK7iwo?UxBe*sFf){nk%NWo9}S;TmUk{}ECVjW3!B!r!BcfdsuC<8rVI1GTTX2L{5Tm&kY zEOq8Sg=LXzJaVS$qghX=Bn%a1KHaD`;?ru?RgmQj5FVDOX-9#^sl7ydU?Ejltp}vA z3PN4Yu5_Xm?U|2G62Qa9VHpM4IC!opad&ykq$*h9OzEr`f#?z1B8)RU^MZkn~*eh0d?Hzr$^-sHvN{fVrp$7K0i< zET~V~2E-1GL??^I2u)%g^;jTwRy~QvZgDy4YcDjtiPfa6kMKNoov{U@aOfCpJAf}l zG>UqV*=Q13ddjj@p|pl(i`HXqRi+7a3283VRx z(0O|eyLt*BX7VkvU=vxe$?1+Ld|l}XluXrVSVD&^gzn-K{Lr~G7$(jlW?GrHjEygK z?tC1Oj&^mMJW0SS_NprlknhYwtpD!5M_cQ^TWM{V2e#&N{rB7hzQX$N0{= zVLbjz_d}w4lrs!@M`VZhL&_u^-60^5>s)iaZxaY_S8{%Q6l6)9=R@}voQZ!6sdWiu zo+JtSb4@>UaI18m{>l9w5CqS@C$ANU6AOPbigrC{gnxtLN#|q3SbCPe41jiUzX#9X z_+9N4lB1{?F1x=m_yAsG8y-Pp9i6}Nhvem@Z`zla2WGY-FMlEk|G)Bb`gN`4W%+_O z<>kfVR`TGJmxEi&lV4tb$NsBHo7F>+{)_vsz;D-*oY;^=M&YE1b=eK@wz>c68k)gY z`>#+GIwf-ly#KQH?AY;H*qVShM4}nB(>q$ZZ2{4rv6Jz{aZ|oVf89>{2lUhvSmbAp-)tTDoHV z@Vesr-q)_!`RWHX@K6Zj$ClGpR8SYxk43-o?{5Y|?O_YqE79oVn=>MLft?}Z_;`9& z@&da=U_9^@WT>li-9tdHgLtOU^nWTpDhOpc9fopWd`V?8ew-z#xv&HLmc3{2o8iX~ zoCSw5!saZHI388%0%80;k=sh@07b+bV!NYiptkv6t!eQ2@omtc_Jm{_NQ})rUkVLk ze*+D6@LU$Z{HNYm(|Kp{RDAcB~Xd_8p;eQotD?28{tG2T<%rw(On#mzru+wXxBcGxAjmFMo` z(e$8Cf#vQv8^gKh9Q-_R46+m*fPc;&f#^Irif0dT4g!11wFgFCMKsxUgR}5j;0no$ z9T;$tdP_PA*biTwTd&jb(ZX2ppzi9QJ%}D3{>;0*#o219CUZ^AIHX)E%uZW%8*cFm zY#6N->aGcKzbbCf3JYSvf9|3c4$=w_(+W>NKdHhXD#VyPo2vBlgyhQhCv-ng_bQuh zDtiYT2LRpX{RFzhp`x0?fIlvcGC&Ia*oKaY>bVyq0+& zJCJuma)rHE;rMGjB91T>7HEa9 zdtpHEzEW$x>7b;V=}5L&^M&^&*L)zdIT?wXZ#FfTXw5}h^VJiRYDS1i+cmE~EVENu#;9;p%tF_yFj(KCxbeaHE%J}3j<}F zns3VxBAlQ#r+=PA1V$%|j2TczJdq4)AuBw;!2@-WsqkQ}FrXD~9F|m}r(Y;4HM?eD zb|e{8QHQbwsGkOv2+!$QckMnx)w?Q^YVPKODmB}IBex`jIs{*xZbl1WORqN-mTQGq zYJ~?$Xsn`3Dc3ON5KUR+Df?*3mc5c`@GMgv;f#qLT<%Mm z$CP4CxzCp}ohdJKn#2xX?MoTUl+!h($(M36Q@-CKWfu8TikLE0Q+oPR_F_t|rfkbg zhB}iek7Mr-ASm>e`TAm{9E%hu`!2YiXW)#aq%pnEUmO1y_-Y08y~Fgq!~L5$ASj|# zV<5Gq^OQqm`2?A?ViTxZ}^ zGl)f0CeA42*xw$4;8|1iEuq^ z_?Q@g1sXeHo2PeQSKu$-a_j&@A;uUzcbaq8&F(rnzGJi%e1j8!v7C41k+)JF5|+Uj z0ALD3fM`q{E0$i013Ry~gI=UP5_sgym8rvB&%k>B8hG@>*T4*Au8HN1g?&IkMB|y_ za1L7I+A$cNcVs~418ApIfbtZe-U`s}zXi}(I*$raGiTuJ)&PCbSphmo{LDdXG(>iI z{!pC#S${Zs9ox#A8Oc9}RGJ7P!SXib*YO2^5bow<%%X@r3Yjos%W{f}bkZ1OaLOPA zZXy>g>ZCy6^W-rb$!^(_fmt~aK<^>F7&jrOISc0NkpyNa?6ObzhKjSD<{RCW7ksN! zQ9=T^Cm|PHFp1^uMC4-wL-H8B<CNxQbn@0MUdMcRDu*Lsvbeyg)!&-IV4En=R=5caHBlTVm649*DN0xbA;t6 z&@GH^C^6wcPMcU=<8doZ9f^PKok1C}tr zU?}t#TaYL=SHFUuWHIO2@nP7YokR7-QXqd?=n$=Jyn+VYan5=yNRT zGn2%@AKz!|E6N1xh9>B9tkUQ80jcz1*~BLMz`tbjCxt$mr)~NidH-+F=gJ#?2YqS_ zg+AluF?a$VhCWlzG_*N`Nh!2Bv6D-iT2PvFiGVI5R}`bGpP`3>HK+N+aoRE(cpMLn zHE5ax=lb*DL%oIt{fUcvW4Z`#pmsWm=uXUQJAF@9@ZGt!2xgpQ0xFub`e3+pIjb_L z?X~;E$NM`zfZ6lqVXTW77KlI%A}JZsfxX)^neKtHBfy|;TFuK6AOC$WI{h3tWdQHJ zr#k>|)=BMxcanhDHvwLug4d@#@WzWnm(#@u-bH}K2Oic0ol^qoy?Txd zA6QEslC_KQG2RGI5AfZ#$R(eIgGsa<%$dSh);@f@2z(pUJnn8jknj!uS{^Cf9Ru!u zDPCgEDyDnj_4B|3ccE5{Npp55cuV010=%D}a={bw33v!lRPY`>v0d_wL^H9RG6j$1 zJ4E2h>1)7)+!?2%lGoJZxQ2bj@66fJ2j8r-lgQ`7Hvu2xH^Aitd}nk7-%jnrx3(YQ zd!*$mDhJ_v0w3TTJuDA#mr~&Sj;DXxIoB|QN573{dGI;ebKt}s*@6EXn*J>${fe!=qMFEI3kglpx3ctg{g5CG@YpoPey! zE)<+%3!x9?YWg%QhnCm>MbQa2uM~P?Jyx1wTCJBhOVSiFrkvrX#80I)BcqTAjF@kksAb@$!OAYY*_F|)uDhL|xfw)F~8L25@1Nbg@zw&D2W&&6Rkd4EVfCi@i!G zugW&HcEc$Q;H9Zl1~jO&Gb*KGptQRRtZ|3nyim~45)?EMl~6M`js_=PLxF|&9cbzSn#LqlSlza9(kMjAjJ$hxiB~7Lk|+<6fbONxzoeWJ9#}7L+mRD zxfEOx%dd;Hh`<3YVqmq|lQY{X`{WH^<|+_jBjN6lD=}CcS#_W?+v(-Y>iqR>5zbli znC)cxQb{bxn^mMirzId9W3L4nyg~37DUG*kz5!TwLER9`-}3wo$w2mhD?S0r;Cy;5 z)Z$<0qrI_u8~V|kJZ`;yiU0xI3X|&2&tWAGMM?!J3~Bx1#QhMIh$|Ui5iX^3DGz5P zAaH2XyP6-RP3Q#1{=DAP4y^uEqnVu3MjAsJ3(ne#4&s&Ci~$W}v8h2n#N<-C8c zBhz3;P#GY|(A$+nO+}bcWCSemv8V-GJsEu1#flEgj$bL}XMmP-9vs8=u-!0z7Qbs# zt`)gP6482dJrPhQ*n!U`F_0d*WN3H)I1H|Ts!FAC+fjq`|Wbb$sf+U_&3sx)y@k2v;n3G&i#6wgHPDV(^d+QGif=z3tOMjN`8p%ABz84r3(RKOd#OC_^)#`4IQU3 zVqsuju+*`mXuJJ*o{NA#x{$H-8~G2^3C1jomK-KtVo`=8m=t=#dqfcQ#dF?^SGN^( zLQBNHQ+fh00r%Zq`@@LTy$!S63|!S5_S?7VS%B=EbG@Bc^m{fzUr$m)*ycgl2w zAG1R2@gJlg;v*WCYc3yzPAA?}!F~LecykoL#=8d#33)a$te1Z2Q z3$mgSTHIE=`ET0~=ixuOrUCLwvjGf@D?yU;RMj-+rsb|}NwFVgY`J~=aYdWs|; zq<#r!GT#F_UGduA3%l<8TuEf9C|10oz4DnNk&bXXjLgbvR@fRbIh?3-paKT!5jF- z;RN15NUnF_4fK-fejQ>Yd_DKgx%FzmRbwQ>uaE7+lkUQUHvY@-boo!<$#mfXv;WKR zTrsUp`k>P@=YhxyNjv8Y#?09UwuRezD5((TSsO)^=j3mY=jj+s;It`qQ8$qLo5=l5 z&dvxf)~y%=Z!Dn-a=b&I!FKm8I(K}eYA3t7ub?hW3@z$1Gm?L}jIqFZOKDR$%rSRRE3P=;B(?|kYr`xpG&}Y&-%Pl&S#*mO zHN*FowUqw?CRP!%Fe|OZ;M94Bre)WB=iA{)rlo>;D#d>6-mLZm_F*i)LIr4J6$sqg zoISHV8*_I#-+qmJu~N_<_iw&c+m~hpHelr?Y6JA_i3W4RK+2&NGH9g{IN$^Yq5}2< zK$-TKlI^9`N22*STtfUkcY@j(Qt7REhZ=6D;RU*&BF)hpr6O)$g$~SaAq=0S>XoGKsiw)lnAJ#VC&Ww9} z6T2>aV^?olRRDnZKHyQT|8HcGoI~cn7_c9Ka)443t9^+2)Qm%F$eu?ge zvc_eLp+$T;Xyu$f1?J%kcMrMGeukzW2-QmUMZV%(k!&W0Li8U9wuMdKHQ8ZYN( zxorHBP~#Z=kx{qpyint@`U97aUm9wVTWe8I?f(87$}e?qD8IzLq5RxXgPijy_6OQj z!j9a6B#9GQE-!ZAkR$eoR-u=)DTT!FGK`F|`w84!PoqRtoI zFeERJiSWZ<#2>(0s6kE|tlts{HOguFG$lgpb3%>02~4?kZm4mC{s5QG3N^0MAK+3g zf=l&BX5F^)YbK!$R8_;O7wufP4F!2fyw-AgsFCMw;|FTNj}!EV@Vaq`{y;64;}r8l z@yn?fvHAT3dJ=$GvEQAaph`fEyc|a(&M!x~FWj&zrcN&KkTIP5R((4-WFO&aRo`X*Nqw2lmF?BH&wo;1nsY#V z^{tusoA?g*(+_$)_a?KS_uj#-O}2wi?+p?}vt$r46FnygTaZN9DmL^$TjMv@UqJqZ z>A`>*G6@Qy!;7&gw?D7!W)B8V!JL$^ev9>+Ntmpp`cub?zx5j^m7dRDKtMKJEKHR0 z@!#7IjP7wPKmg2uLuO1B=1SHBc@8vQ%+(tjH#;!RyyrScf33KLnN&iAfIOW%J16r% z(iJ|+h(Ru0k*AP(O2kJQ_o>&{fjl~fK}*3`&m;8Wvrt1o760NM$VlH};W1imA$A9@ z9}ksjy&t$CzmiHS_doSwc=xo8jG^L`E6uZIn4&E!*CXsu9 z5voV0!C=Tv>JB zWt5E{I3D5lL)k6C^R=HhR|!o9`d^sSx80t}bscBvfnj#w94Q7a+UCF?q1vOSm@9m< z%!L6B=F}*WQe}OKVZB?k+p(dak#19Gx28O-G=h3y8W|)4hv#@#ih!VVlQwj4}3$zS#rY$4SaPs6F!=yd+?#P~oNgJD!m;~W9OhOl( zQ}GXF(tLqf=g(7_bPLl^cagxAI5=QEzVnYv+8}TGP8X1W{7w&$e`xB*{$vuIU)$VT zN-xnV$@aSsdWjN8*Bhi*;6*8>OcF?hNnKhMW2-DCJ|{?KSy5#Y^j7rKt+{O`t^b?L zBsc0%7=^|r0`~KsRx*hL0<>nMF?ekt3&+!m+d4V7VCOA(ftVs#V4MkRgu-xqVh6t~ zWD1nWc4rT$r-MR18lcW9E1D4t)OM(UfTa#dy<|ks(yR&$g}@v_GHAtWK*g=xiRQt6Xb+uiZUmIKs&Ij z6jM=MEJ@_tjB$HC@$tD~DPlZSreVVBx zdvd81OSLD@v?}($v?nv~cbU|dJ=yKaKVnbDJWEVrPxdvDo1Q(nryo;N?a4-*1fN6$ z&z|JJ->yCBB1!*sdvb_4j4Adc&;6+OU!a0#A z%pRQ!nfv650-Y0DvmZWhS57MzDFbN8*-x=&ar-?Lm^t}%Ohdo7floLquJNCT-~3~_ z`T8pFk0rfR{rQK!kB>?JTRbv+O5HBHY6XW`%Z^f-e{L+wCb!C`}+$R(1p-!gP8w zuA`yPMKFupkMVKrG)G?qA>B9%aSXZO347%5Jk zVWgciH*CfkpBb^ z4Ts4>L)lB69;mMQ868ae{0-JO8TEmQV^It0!#{z@7iPTry$KpbrKU$H5PW;QlXtu zL8DRo?VnbPQ_C9zqXS$^?Gfpb;#a0lIWaou{Zjih%-t^(6s_X##{Gp|4Eu!$ zXN;xcbGql2#zu9=RS>Idd*dyi3oJOVe{6nbnLQyR65SMuepxC3-I3_m@oUI!>LN%A zc?cYMiW{}oJzb*Kx-F3DX*=i8o@!`$W;MuxiFuv|E+h7^bL>7miIvNMF-$^4AY7QE zz&e8+7?h78gf#{NMWiimNe)|rg#%}mxXa{0( z{|bHy?Jf;9K5TxHc9=2cLIzVi;U{KBOU=(r{2Uu<9SsdTv)RjcNSqyq3n^M?BpXs*)6sEH1>y0u;^mR(R}`BjR3D!yq#fju z_N|dFX&1L(m87fl_(MwC!Rz-VX$N5eCxx_FVRf4KZiBSgs%Qs3=|$2~Sv>lxo+Oc$ zAuk?YMo3Dd+qtk)L5L^HeJ35~;CUJy=lBVzcASHU40oL4$=}Rz{cq;rd9EF|QidE5 zwfJmwr+m&d&pPv*h-U<&w+OT>i?YB~t_V5^1TgDe9sH5&d@g*5ZsMI}_VYKTb)^J!p0O762Lbabas=XytKTwLgrl`TFcO)&l zEH)}Fw+zd?4MzgNV`8JThfMo<;h2^Up~im`VmohTcz>K^`fBZ^wI`LvhQa{sSQcGc z8vRK`v^4s%E20sY0l!Ml5eVI5<{@KKP?c+O;?H5=&V5e0&}awJPI4vs%k7lth`nF% z&wW8Nu0^6dpgdQ9=zfNg4DaR4p!;(r5v!baXAl)6v)Dz4j+YXVMd* zL6Qo(bW-O4d2|je?7CLyo@i^}2au$&g>_P`p>vF+H6*1}uq{yMp}qG{i#J0K*jZNN z8~^w|(S2_pKJ=a}L64rfL7;{2CY@if7i+TJJnTGMFIA1W#J5xh@4HfJY{;+D8g~SI zR+P>=CPXBOj^e0a+=w9Hif-H;r%ZmDMg(ZB-3w@43ACKi52#(qtJ{q=ftFBwc9FWc z55l6nOc6$4Ut&GDMM#dMl=)*>XxE69iE#_+kYJaX8urU6_9jJ$X64s`4qWhMqsAC% zUmAhksg5s0q_Fek{Q@QSxlX?VN3Vnyb*gXLfB>WuozYhEA)TlVwSe$5i2>L&8&Cd$ zOY#X)#2h4v$PDMLm=5ObRz~K~alyy%F8JsSdR${>3n?@3=w_KI(}w&CR)R{KSQhP- z$Zr`7HRvR(jf>#%v30EPyNIMUXIj4IaSy175IeX2>}TC9|Fz|IAUDtDxC;$^sk2%Y zn=fd>E#wpSUwUK;$}BS@%wm086Czy3h?>M((9UvB9fYB&Y{AECTONXsdQ;PiJm zuA}afU*aZ$k@ODu6>bGu2af07$!uI}LAF9Pl;&J{itcGEA|xe3Viw6Jhzd$(zH{Tl zZ?(VyMae3f88J7w!`9w`u(IDv=)_0;Tdd-Dr{qRrog&3BQL-bUercA~vI5^HJIt9Y z#g6p)7UZkv=`iqJU6+xTO@bVdwJg>%qbzn#Mpl`9L3&y7%c1%RGQ(ZWfc37)z~(&k zA?#Yh+U;X9I}$wyw(=VUa={W(Fx?0VPWeMh9a0AS;Xav+o@I5YVLBn=E+2`gLy-iY zirzw1`T8a~$vTk=D$LqO>t{I1p<)#KH10iDo6aIxv!&{F(xy_Cj5p3duc48M4T(X{ zMFbpf6=PQ3US5qWpMO2ts{awUm%m}9f5*;ay-;sFkcEF^^?{quunzDB79D6ZHHzpl zxlW;g%@?Bin%<-V2R1~XgPPe+%Ol*VVun4_maRrfT-e(7@MpHOrj6Xrg1g1+w5s~P zHZr#c;HoxrL6=05V>vr*0DEG2AwJl55z|~J_bAUTvppQX+i7tpGsDR9kvE0FTP*>o~Q?W&b?YSlo>5Z=xV^wUvI8EnkS7c}o znuMjsS!O9Hwe4N8$9#^7RvMlTu`#pQo`M`|VVJauZPQk;euwU)Y^evEZ5uF^1b-)OGab( z9>GPG-sD2+{6c8D+#Ba#v$g{>UpM=huG=eVP6e|M!AI*%P-|^+3jCtruJ>?y0rM@l zFT?x;R2ux2^W$w&4CY^3>b&ifTWb3b>MBD9FdS;KD69Fomd@5Fos=2Jq`tEsQ4`vtZ< z%RuwsR(WtLkDdO}%n84v%8HFcjYnFD6l`o1wsXt`w_8{)y@4~n*wdg;LnSkTe~fZU z4^5Y|lkpQ3@ia~xA8Y4KA4xCL9oDjUaF%XS$qTFG`A&WnX~cZdmOyQZ8-MdP1jmcN zd0T&I{0(`E6pg=`uRkRI2GQ530pU{VgU+oDhZYSxyW~$dTvmt*PYUHxK?p#2wQ#99!%%zKT$lNN|L7J;~2Xzs= z_!w|fUPihv&?)^g1TRjHxuRIm9SeYnwJ4VtB{5jVY4Ql?is>8Kfo^*p4q6+3qBo1! zD67nCZF3@L`)!V_h|8jXVCP+3H%LCxT>SYvzw2bQ+?g)363(T!6IQ3_R7mJJScO!1 zl=(eC+YcUxoNsCUqjkLhsykT8@<3mtr91t~v6bk!U9gMjiF-kffAqk?lLe39ZRD%? z=g~Lu&#fDgy6YAkQ2F=ka2Vw(oSW<%GyDr|6L6mQZ4;PxN=Ng1oPYcs=iPQaB*|hT zFh6O(fb(sCHx0aiKLoD=lb+ZE*c&akdEV_kAF^SuhZxMgtDO z&>VBl8wJWy9R2oX{4l^?&|&-!jed3)VCkHEqboZA2sOL*&*_57n;$ero6Q1s!5#?8 z7OP#bDFSMGe3rW@B6lgk|4B-u*gJ`OONpr;jR-VzA9P9bd9@|*9t!8o@DT$96&&X7BW^U1lD4ei}(_M9$I2Vxh?s; zhM9fm@A}SDPB|}{G6jEYF$<|+y2D}d2O7-y%sB3=O}4OeIDjCa1?s%RFI+EaZdCqQ z7^iyPhH`B=&>Bs>cK=%8SAdd&pCB6VH!LYL3i;%9{1o6;M0&d{9M4__XQ| zl59yqvMqrT#3=XM(-cr3Ba=cYr&T5TgWUjVoBhEulH+&F2kh5LVk?tY%89U;F%Z$1 zF)?11YP|Y=;TH|DYUa8T6$;p?+iqyBFneuFRv4b3jf_36PgWS3K4(Ns6lTB)V8z}( zR%t_c?iAL#;}5qJA|G>X9z zRFu7}Q-81cX>@WG8h-q>haylU2NgJbmw_l8?7P~QqCcVOZPKG^yrIXpCY&*gpd`^_ z_r)F2W6k|Sk13Or=t1FUC2b5tJEF(0U0Ts&gwr-X#@*8fJ-*q~M~_hCx9HKJ@?lXv zN+=)FUqimNzm{G)%b6f-6q`t%z-fW0kjoYgcajGG7yY8=z9I*W3G%{BjR7@54M>*= z630Xsd`)C8Ujj>MEp^Tr0Z`BUO?ke(BX}e9D(I2fITzYg9CuJGJ_B3=jWI30_q}B6 zUB5M>_CPp<&}W`!ga4@Qa@vunyr?M&SYlRA%qnpCn))MogRUEx*1XcW<9MK9C86Q7 z-=XQBEBt^nNgrq4+8e-vlmL+v0cp4g*qU%gH78xrk2469ZgffQ@q#QA1nc3BcucGUr-v2|+S%&zv$fo;`;Zy@%93;TqM=#61t;Z-Dn`f2+}w`&E!sr z>K9rByD7JLLv@@rfRb52qkO5;avYd)M3Qu-(&HrHl1qAEQi1=V60zEVI6W4~ev)SJ zq$~u|c4rb=8j{88b%Tf%rEN959slZ2fiOGM)NizAp z1bo-zNY6);BQKnDeko}mAB>67Im8X*y*iu5%0zl&Hk3Xakb?%yRSz^a4y=^by-AoV z#y+Zp2}SJ6O}>v&VeR26DibGJGh_|Qy^9LERB{Esrm5}KgJS#0(1|0 zJb|tZ^-Lsnl?I1}Bw2#PCXv(C8XVSOpoA=xLR?@zVelu?hRPdYm-%nb;gKTXmDsHU zd5P*i>OhaxoJtOM;{y}mtA(1zv5py`n6|75pS_qeG*6FVYj-jmD8zZA6Rm)%#wXtQ zV)?!;{yNtIy!0iKuFRH8cp*W5x`gC{tNFPJ9uz`WxIzf&&nC?&J||}|E5zq-8&Zi` zAyIap{5?U;-GHl+oqO&O+1dMRG98QoNwUP+gBjU8}Nl zix5?hd+k_ubfa5Bb`H3XctCbGn`l8n8O~y`Iz1sfQoqQ~vmYzEP!u}hAbhzM-7yyY z?oop-&KBq_s=}F5=|UNWzgChdJE6u`32bZm;hYR=J)_XVQa0p=bE0^I{M4W!kf%-g zLDV5OHoG#&Gyk}!zZ|99t+N0UrV=~FYYyy>*h^Ka86(5LDQD0{$|3)_O0iyF0eXk> zc!7A4Ad3Y0sJu~5Px8KhA#%7aeuYmS`Qp6hpRU zCpCap`~V1)vquSf`8kL=V1Fwv9p#oUxqM0N-D}k!oAbop1kcbP&toa{$D;b^kNMR8 zcs|~|{y5+C$LG<+VaR%c5!!nY2SX(nb5c#AWwB%nn*ECr+Vek1H7V6%Qto;vVN&Fz z(kM+zpz;J%IR1)Lvd$w0)r!h-2eCp~Yr02rc)JTQL>d3dDCh zQ6sc}H<3GnGA-yq+uIV_iSMThZMg{TV}DBs?FQ1y^u86^`(7`}YC-Q~GKgF0_P`1$ zs6*q2I0e|vs^4otd&&_5CYoLjSu95-Cqqp&Slvx20rk)|_Bj>c8#e`Dh-qBR7yQvQ zioBS^*hFI$PMW|I#4n?1x<+GeCI{k>GOTSE5Y`3bT=FC7=Rj|H~fC{ng&M=tjmDcheY{^5Qa9$Ma4(^LUKU7xB> zC8AE{4<^(}jiUC@M!xz>a>6K9`elo~Gx*Dpw8T-bGO+K+yVE@Zfq~1#C?3WKjN)TL z$6010Mu#HPLpJF6jUq*&llR^A?pAvuLn3@84jj6_cp;5q=8-UpAqJ)0_{7z19*7F1jC_L0_Fs?_?gn<8aObENz2tBMYq9FsLJxFE&C|ata{#@~J72GOH)W+b^7J&59O>k;e?N6^XE`mTDl z)^)4_sx%W%SC!`RTavXd7i)c=sFGT13)cFG2I37DBRv^!s#4vLt}3}BKoV}%+o|Z5 z2)Y?b=oYXIW36FS=5^R*ob;Fpa?R$8M|&0xzj;3__gRWBkk5za@3B zmjDRe8dbGId^xIcn$PN&c;AV6lm@TqXvq*ukCVhGHT!=b`sypt?ciT(3Amtp<_ zIx-f$yDk3&`cEgC7m9Lxm{`Y9B(TxypqwOM;T zuSb9QFhDgPcqu%hnur*y-pXI9f4a1?lmk_CH2c{otb~y!;VS$hY=K?{~Y=3PQ0Y;(5X~2oCfrJ_0P!EVv-B1)oV zqv zgYVpdNy`w0DD47KYMzlOw#zk~c%SX8s&5U56F3CCECE*&{FC^#J4i7996Y4A5bJz~ zT_7&nTK9qqG84cneDv|^{KH*dJ#qzkRa;CQD8xyNMGddiWY2aE6PVmtc@PYHKR8p9 zjL*;?fX~~rogIC7oe}*3`LUjTO@ZI6_d~K+IqVk*)&~5$bqxQ5hq>_oYofs4TWTR= z0V5<6x_s~Ew_9dA7hg@{x`@nn{^a}Z+*t@qp#NMqOf7p+akSL*mh7f+qrw1AD8QW zzXh(@&Sc+5=N|_H!2*vP$^Np)(^kc=iu|Y~KPoBkCHN|?iuR&*;HIlgzXoBdR=u#{ zABaonj2?j%ZdI~S!<{S%>XcCKtTrmcqDZFrP-v&zZKpzBK%H_{UV$Fq;L0R-Czq8% zt0lE9cjwC^=Q{*>ZS2_s&$)Vb>*Q0HrC znP)Ej>rJ8QG7s#FKS03ayc;D-&woGkzT-7a?`kBbJ2$RI_+80&pSL)Z3J|c@dlGJd z?*ACxwl70)-tJY1%X^~d7cI`8^6}3t4}96;jQbiTzRBFy;>6eg+T#512{IqO>Z2Ct zwoIHL{_?y}Tb$M3qu9gPdh9I9!#~rm!?)K?#WCV5Zja->X`U(`9Dub_J8;sOsnm1L z7&$_63VXwRar&fv0RowoBPdV6T09w7dA@ZEdV5U%iikvmN8+P%33lIFvCRBfa3NFC z@h)Li(ZClEV4!FR=4_|8k4_4$WN`)5iO4bY5PM^X0PMX)^^GM(4i}`sP zy03g903BAB;Z%H%_oLw0fuX(vgP8IIyW6w+L3mzI>2CeTK#3oJ0PD-EIWQ zIZy5);Fo$XS5D{)ukd9NLZAH^-|>By8SUM7`O^-xL-ZxV*5vyxGg{wwc{|(wkM6t7 z_+Q+2d4EuCMi_l&>-#P?$fgU5a73Iz2)K}Q^+-O=7(W9v z>HkW66!lH!KRB>Xgy3EwjYrf~Fh#l`ud|^51bxnDzWwz49rqlKfwSUr2v~mJo9@sgM?Yx{ZkG)2bCe9BzJuiUevs1 z3t%<^9i;DVevQ+OnoF18xU=UCNj9WItLU?v?{Mbt54thDzP0?#Q+S~#G8~tG0$V~l z8dH{m0x)F5xlRRjaGqP{k_M^(VQ>xZUyIzhB4mTxFS5ZUK|62$?yS!&`>GF7n^KGC z380|@HdIMPGDCQ$H{eIyWgGCntnil;ev392{{)JX;I9w^Pxvbp{-2k&2|sgGNe;YJ z1Att9naD3;=c^%#8^~ll9Uv$>4)b2ytrc#!rnF!p954eolhC5t5>5+>r~pY5`_YL= z?xjdd&!GRL*ozg4FL>e32RP3L-)XTHKRIVzZ>Q@)xEzW@@Soz=l5KlhxMpz4)}yUH ztE?ETmEChkE4t3Q;H|V(w;gHqSq%)b(pM9a?7{pr8Gcw~r}RMDVdpO695RRsp5X;F z6b%JSg)kh>Ipd&*#064Dn~GY%H!c!FaH~nDiR563jGh~trgUT7EdjREd=D-^gjnvp zA29Bjf^iDI&$hxB{H+Kkmbc_Vk4%GW5IGhqJe#wD-dHY zy%9baAC?Eszs7iKCJM<8q_K3=H5~76hD){{F4=pJ@H0UJjLuSiz8#-G^?hD|&(eWF z4%SPGTh9$l*&VcY7WV?x|Em22hzqLplMOfIayBIucPI4!p#P6n{nnCk*yy!(%0=VO zLc|(8Cmc(##j5{msqeH8w^8=A&@fO30p$2FFdo z2_u=^t(KRL2`yS#TK~z^(zTx`MlQ2!G2S~ehK`2neJ~axLmy8 z$(%5dnO2#wF&J>NPLEUpmSI88L)SxT%6WoPEU@u0sqmkCpesj((mP03U@8=YmLmVX zxpdQp|0bRdPhp2svnFJ}jcL$O{R;lOXh7GJx?k%;SI?3qjCX0>>bLC}nl*yI?UT~2 z;%$0ycS&f`y3nGUuIUkbNJeRNv$f>Q&Xzsukh;>Jmec{C+WjI?&cSjn5}1{^DC!^> z#w!d?7A)nZ#`PPZr>rXjb#>CZcCzd_hos@Q7*k!%-0GKxu|x}YG83EtiteCA_r)i#)V^-1ZeFQ0 zOw5~7JD^l&EphaC_f<$iysVEG^zpPl9@EF)cmmT;r056^Sg6=63-Ur<(AQ?tAf~^`)&zc;3 zmT;^l;0^zrLoSRlz=YL_0FEb1EBmtdW^$$BXFba%RrCi z>xFTWgxFC0mZR z`eW5Y=HgrDc24O5VXTIg@xxQw9z22n5S}F)_FmJxWXsuaRZ;JypFnsKroa}nqrpts ztgmQX5fGrB{5YuHAPlj8nsPGK?!&){n7z&imci$tP5$wHzP`%)W9~af2aB1Gfk6|W zF$3SUWdwU^BsL633ysK%#JWd{-<*0Udi_}v$a4%v`)6ClzfL#}$AnEd*@{leE$y?Z z)ULp}7e8b9@_U?n@zL>i&)pcnJdZV-h=d59Y@I=t+VY$>TXuFlQ@VJ2;I#L8BliIH z&&Z5y=c>1`A_Myv=Fbu}lAu@xDF*L{J!>+3VmPs67;qSo9l_CbGYAfW?X$VG<&{#5 zR7&eNw?ueM$FDf~jPd z*9KYqsNxU77(XicqlsilA$V!DN$w(ay8cAphYv~5?7tvKf2@vnB%)$> z`q$bM`Sd?D{c)n?n?EQ0EfNR|7FlTy;{*7~&;~3FbBI}B#cJRxW1n(wQn_4+i}|qCCz+ZMq~Rh7zKH9ST%(LX^cHs%H{DWbO$dtW=FA$%dPJola~7gaIWu zp5{#avJ8GQA*%ITu&+Sx-gdW2==mqK4-FZtY#u9%jRPfWAd0a`pv&ZZi{}V|4AnT9 zEFCsvR5}!}XL=+$5^6Ofdw4APUfoq`$I!5Soz7!XdT`j!BiE=SrAt2P#8ZTt@Ltws zm7ECZY^hVY=Ha8xLDCz-shu;9K@DVQxg5fCxcn-#`anfxU)jf2pS4!Ys|m~WJ~LO- z)5Ae7s1+v`m58=io?v$aj4&k;+?`y8F~E#XYz>%ABoI~diKE-n^i2^+m(rSY;Ov1N zEgsoG%nGt#rIe0jfFA-%Bm?0AA5Z1jxAt;=n`lM5fr=DX6E3E^XGE)qAYkYTW^Ss5 zE{evcQz$ zIO{;RX;Z#XNUc4P6EJk& zy_6eq3{XJ)06BQ?79oG-a)NVPIrDlDvCs7_&L6wa(Ug=th0F>iGO znV7eQDkl)nY->q#C;E)JL^13zu#+G`W!QZ|(=wW`!DboGOGekk_k^75YxCFU`6-&h zjZuS5!HHsB?32WK$CkFhRrAEFnu>xa2R5 z>yGIUxZz92?TAY=qbntN*?H*{>DXP8Y4`Mxe=FTY%M0QY(1vqCHl*_$v+(DW&++41 z_jQ$k8JZ|Fq3#A3uw2!=oP+_D#aWR~P+Sl*+gzn&<3vBRpceK7C;{;&?Gqi=x)4C( zZYux!M`*fSHSX_!?SS*<0V;;5w9-I83nA9>qQC1>kF*vRR~H9kHvW}B*a6!nr<%OZZg^L=ruL%8$1#h@gjOj3b0>a3sIJ+&1=LMXdtVu?U|HNvN z4YZRs0hkaXjA##jhxB-+jpdohPY@`{4^f462qPxSxcCK*o`!4001R|Tkvb?#*lMR= zH;{2ff{ZEj`?xjzuzvNLtFJCc1@^=>JK4@t54WYY4Of$wfD*FKqminCMiE>poRIYW zgtJQftS_^z7I&aky3c!&^f$3A49Ve|ZJ&=QwAu6(!6DsQ!jT;a0iH0{hHIBm+}_$g zwjY(NO?BZ;6@jDrDaBEtjEtz_F1Jd^Ex3brk-OL?Cb1 zKO_P|Tr>;g;v8aVT}WIy5`jKDLIg662qgG#H{@s2iIV%uF3kbsrfsa|ARxLRzlu-W zJmFhbK}`5ZkE_~!hjPu9K?ClBe#?rk#exPDMby|;>&6d4jXR0CeO@lBh{TSA=cr@h zNbJO{GM+)|?8-*5ccqfC)Q}!Xjc{j{?2a}Jnxp4;GM-oWCvv{1Gx;Ol30#Cw!{Oag zllTB;FtTDf`luGG@uSeSn|4MT4&M}z?W@8Odl(LHR$s1k+Ljhz5~{C4riRW|?5cuD z?1ZpY{Bvm5G5FNK<(U4jV5S4p;n<3fBn)A8!#qf+ekgvI#ky_d>HBoX%VO78fIeja zv*D!xTCCsFsb=4@*yxf-@p_08-Jr(r(H1h2sFLwBp<;tj$ckp_VbMH9cpeiNm{1nm zGZKAkh?*P7XoESC(vXSgSaNEpVG6NmxK!%H6s(38)1LVa*tiaGN^Egbn0A$1`fJ7v|SdDlm8F3Pbc=E4s?U zVn-DBFSnM4hVLkHI2}IvK0G{xuVUOaUqHkD6oJSH-Lz$t#igM|;1FKu63E&!+EEbZ z8pt7G*AfOK2rRhlGNXAudc5!M?F-1@r53;D^>__>g7k`#tS%@M3;y|X>FWApnQyzC z77CgLuQ+1@3c~9ZxFD=;z{QG@b%hjSr#446y=eW-&&qE7j*7#FD#h zB9Pt`E*#fi-tbnB^TPPJuvr%L(UBs8h@?r zX?4MG)8)3n6@5cku`PZCtb@e^(KW643zn*5RV~PZ`kyy?y}21b{M^?qcj{8VNAB7K zC)`8QV++j-t5Qji7FM&~7;mQT!qFWubI-g)e^Nj6oQEEb9jrNq(SDS9 zjA!KF1ZT>2od7IRBM8tcDWK7zS+T&hY8fyehP`bNhkHkpt7^(9bt*-(@qJ~t}i8nEg z)D>AesY3Ar_A`a=@DQ-^oSpz6yoI`F*8oi$CV)TS+-&0DbCdH5V(ukM9pWx_5BV39 zP85GuMI9YN5-{QiXUU;ouYa+jA8fbc$Kd zCwD0`(XoqLGAqAIfP+R#u|W747NcUgQ@SMIL#>KUG{x%p1mGe8^-U%0*8p^2{bH@h zxwKW$nWpG$ZE?4-b(mk$qM|8c*HIGXz!ZvUTed>IwEq~+v zv7~pg$L4#J`<pzYGj?8g0Wt-sLu3U8yEUa;N9{O=K9UY3je`nR&B?ffM$Z@x z(lFaO^KPYln8e;f0z&lQzs@pyUvOCs8;YGiF+q12-g(R^^BKTQwHy%*JZzm8e$hb= zM`BpxeSb*H8V2JPAYLEmt%w)sQk^ywRxVpOoVUCI94>yprUc=ydjt91dVxdH)vW~o z5Q!5urp24lRi`O_xpWdPg0Z|SSZQqFg?tFKkhWas$WLFD2*GeeQ|+FF4v@KUC~z{t zNbbmtsy8_X(Vqxt`A0RVbKgNaerEw8A$~Irb|Ukhq{WP0EN4SRnC59eD@pVgZ&E%% zC&&`khXgnY$ERrh4wjeTf*rD43}6^6zjS=7(5#+dx$uPTgvn}4fR~wpIdU{P{VSPB z$N6?&tB=Ay4`UmcRp*1-U70}zkQG-SDa}AegZ!aF$7O+yqBk69g6?5KMf&Jj#vOm9W`D@j^1UffO9+Ze zT#8=3FVk9zK1O^6Y(wb6v9a`gz`ns8rEb(bb`n4t4cPiq!5!5F*Is9FAQs#FbT$s#$D8&bl(od{Iu=r&o#p5oS(SiZinK zszg-!#hXN@XlUF#=mMSNUd0^!S|@v`&cWx*c%F0cyJBF#4pK+SA{>*!q4yVY4j#(S z`E^h>m5hcwptw@P9mpyL;*4x&A(ej)nA?*Qrv$cNO&-YP2=2z5ZQu_(XXz^`An(uY@X`E7leabQ9p0`cbmRPGlVxvv3L ze=zs5b}aXA^z2yfKmCrxHE708wkY={A__jaPva+^n915ag;ysZmLc0YY&?lzT*8%7 zf#+Oo=#y|R*gwGYgW{A!aqw7Z6z7f5j5-$MLe~Fq_bu>sO2T8Ckg7-2E3`&X1Zf+TrjoR|b9*Ri6h*v?qBDwmPTF)dZ9Q7gV#bs)oGUfz zF;$Pz@Bd$G?{m++dA7`a-|x%s*PeUNJ!kK=*WMk~Vf zfY1yMkVMkVLRKH`zQAgbgzlSiP@a@eEn~U(F2&&cdh@*j#X`TPFvQ)+d+tI#{4Wvb zHe;&1F6c}@?nN?IlR?63u_Kr7i;_MQA$#FtYqyD|j~p*%i)9)Mwdh2V6K#>8C`TwU zX8e`(d(w{@t_K-tbnn7p@gb?=lV+IoGVh2Z)ub~QBF2qC*2bh|iwqDzBgTQTd5M|9P{?QKADZJ}bTh$}EZv zdk>q_4G-P9IKBW!-AkUOz_99wPZ}wrVS=(*-pf^L^x2qaLN^){Ca9OQ5zcJmYK-e5 z6Br$VSya?`F{&W^H?s-QoJL;pqj*3+=z#h#hHbqZxcA;hd+;is;H&B{YbDr4%LmU- zba%8Cw*2{<4C!n>dImFd3-~&U3G?cv|L~}N%@9Rp^lHs(Fk8XY+FVCoo0(gpukHR? zAlS)cW1wF`8TE@XPBxma!45xoA9vT`ynL3JM?&Ti9Y9E135`IarFNlZ6|Z%T*G>i1 z_ur(*?6o|n?E}82W>d1x@v|w9%T8a+rtCkm%h{AGJk(&G$o4_x!K{!qyk$L*a9o*7b-`$A~#}A`(SO99eqfs8N#BhW= zYq2T8Cj+dU0-*|d`%;v-3GIy_24bG z*NGmJA4?xX+TAfZn1Qi_6CH)0B_@6^{#3A6ZQ+Er^Ai=(QIg8)n>74%OS9t|E*nTDlAoz2q zV}@2=i$q`X_*mQv=6*U2@q*~< z9S0}t>+`rB(AQr2v)lj4#{&Aw+^XoSBw4)&+tpX->@j7r^iNAgUrUU>!pn3;U-N~O z_VqRVMW^~Y;%f23@H7j%m- zdYP|*)zP25#cn6kguE{}kWB-JcVov377ve6i5H@0WyJcAJr(-)!NiN5XkR8=aiE3F zB&%*@)hMzI{lT=_tz!KL>w_qC2qqtn$W{03VW>Ao*-0eiS4$hu0orts%(ie`@)SM>H{iDt&TB|o?be_vEhE@`U^-uqzG?J`Z*yi%|l=!qO|N` z;vJ1Zb1KmswB&TYP!ebf!?ZMXuA*n8K`%~9%Zl}xe6nqhO0G;=;foN>u@M$KV3gcn z7TM;Mu{q^zvOeRzA4hYBTD47S&+jxIfVd}6arhs|s|v&e72f@6C2hOedV565%+kUExLFr*8H4>gBj1jPbR`SRJyZl zGybGIs~<&>We{X}Q^f7F*8!Sj(;lfN+0d!tB;Xux;(Y-~gSOGqpiqz&Vm*JbG3l7L;$Ik=<-p#4KSpoK+fLD&(M;k)IfnPjqJA7lWIE^ z335=1y%Rmi;hIkDgX1!o*HJA+OaMnA60p^#F6$fR2O2q&3R)3%MSB<1CP+2znt^3N z0L`^R4G68sX1)XpxG7Y}6^CSjydJwY+e!P85ooDQpEw^sa(4I>&i%$AnUR>zt1f5a z16-NH3F4<@7ZtuAa@i~4WbawH7RPRv9u5qwIJS3$V;ygiB-Cqk1EqhRj#nB$SM`E<@fMrj?4EN~E@w0%8 zREdCbS3TLLalhDsaZmgNBB+LOr{L=WwC7gy(W^zizA+0lRZ%^>%qF#D+%iC7EV<0L zz%>}VXAF<_TI6s6 z-dE(TkPgtbbb_Rr7nAES6ha68_?dRiKWe_2x$gFP;a;_A!jIJjL{3z-0tWpM=B&5jtvfR4``1DYQ&YWl ztN!%n+V=r}{{O+gi=w?Y{z~@U@9qxl`-$69RRgBjj(s09ao~1m`MPTCTU)M0p5kBwPt*J^_u4;22yD7VFlDfvE;A zA)gDYMo3hK-V>ZP!#sNIUOkK5lC+}2AEusCJJjdFWs zAOo<^s3?0`oq~51c~4N4;pNRoxbqs;rhR!kae&Ln5Csv@(G>VH1@k4hrV2X+2ZVS9 z^HV?#`g?mRnD|g}igt&c3Ye>Hn^Wc+_fTgxPpAhBjR6xG{uMpVD770@P`y(nZ z2xtO=ZOE%a1~mlqZI|%2#cK1}lp7Gu%x6K{jc?4OZ_J@g5FW$r9&RKk4NgFGn4{6+ zPuyXcO*AF9ymlKjbUR2evK=JYd%I%nyHH%%H1+f%_ew}`%61tLSy54R#0qT0QMn?k z$nCKr)_<4dz`PG8?o$-)y&}o)LZl6#oPYGe73gVIq08I@Vr0+%oJUlQ1Du}*K#aK% zBW_ccHa_D7lpk+N6=T9?(E>9Rtzx|4SP|pCDn^b;NMHIr8hM!${YJW9XdT@1enyt% z3HQAE;eh%2MYlXn_bg5o=GlBq#D|%x(J;bi@S!6&Ra!kl}cJ5lKn|*&+0s1wV5`8XAIz(82BNFUIRKan zDUyG-5pPCf)AI2x5{u^XlHf94X9O1!xlDmvwwbzd6XZ`_$z#hLy zU<1qJb6MWKkG}&`kU?won8|XG!_dcnVpZcix_KODb3dJ-q-#mg3D6-`ps);Dd@ zGR2}Wvl1Bufd+eG4m)3}_;XEjpJW4_*wY#aJ_19l*>&o-i&71C z$$erBJLLCo`>wPG(Xo$<_9fPr<^Aa~`z8q6D9ka0b(8vqFicYvPEqHD4}5b@y?s-f z0#2a`Nl#3wwKL67cD58}g?Xd4?nHpuZQ8WNRFYVA18cJ_v8#@1HueqGev*z~YBug1 zs#}jFEk-)u*f;=ufgjlAPU<~b!x{GY4b$VzHA}8;=GK?x;#td^ysa&7K;0s~Av}Ue z8s&@Vhy+YYjk*UXi?JSIbtw}L`uJQe17$Vyb?~W_DkeX|^t6J7Y9r{E5Q{6Y*+j_Q z4V|IjVvHX6j%}!V9p-FW=0wq1K_7({5Q*JdfD2Lzt5894>|WMW%sf1YSMf%_+}{?w z7pi6F7SD$DS$QaSue?(CNoe|!`s{9abmFDOvENI{L@Wn63enZ#*bb5Cis3q;Ek~Jx z4BcK-ZD|_V)T-U_9D)RRSB~fmb=VU@z>A3w7>@)^7kB$zJC{7}zY z+!hUngiHRwSO^l{_i~l6QD#)4nln=h!jsGP2#k8~$|79*44o=6h1sl;A9DD?tNVwl zfPpBKsN~OVlYH-;T{)=Wy)Ktj-ZACF;tBs)>9ULPP!`rDc$gmNHcy?g$-6}BIbSYh zyVxaIz|UfqiY}N2!sZBWeg3euMzmrMZ$nHutZJToF#rR5vx?de#U-{*0HQEd0w!m9 zcLmF82$r=VSeBz5KxkmC&H}et7}I-$*4OiS^y;#}7|x^0;1w%oF5v_h>Ll@+pV!D| zSTF6OED;3J{i79f3NLe0FslLrSJ)f)AsP%NqQv;e&r~}3oT_-Jfr{?L>P2N@)p_y_ zi`@VR7GS`z0HhA=Zs7sM zgK7{gP|6Kx23?XsT7GR59$@1`$c7xX`!?CikEZ z;3|~@whfsH+rdX~_8Y9x(8xAGMMN0lmceSgM&JC?lnyz3iYySQHSv!Yvz{`w#Z+lA zw>)4Q2)?Ksj0O-tjc7H~P22FK2;#~@69k#Ypg1(f+u+&aTJsByPBOpSf6`}zLPHfo z1o}#>PH13PieF|)-9WEYmYuWu9UNA$fw0>Nyf1qlVenR%;~k8DW&YC6Y;E%S$57ug zz=<#)d`GWTW}~3Pi0)?PSeT_SG&V<=604?bP}1-wq(qY;=@gePiw5uWyuJTID>uWS z`IJWm->PEI!%WSH)dx!^FDNzd*-gqYSe(&vup%jN{p>1LiZyh7N3qQZcLIox0kbSb)SB?k@Z3MUkk%wG zAqw)xltqB?e0>#7f9R8#6K`_FMu-FstIsAmiTResi1)Uez z+bkkVVTKx4Bvws2wKGZMI>Vq5>Lp5{{2Ufd;?V*k?(Z=ly_No%ZK@137!#|A9r4&9 zVqzFuWh&XIb(k7m&I&5xXCl+>h-uU2e!h*Zwz`cIvax)%6RCPXtbkcg#Dryb=L7wD z;Mt@xz%ppq1ZWm=GcYk3|DhWgLB63)K%^`*hePuCn(fUMUirOZ+5>+mBP^Ni#iOXO zukp8x`?FZPkfn{B zW9WucftlEaPzMTQnG=UF-Pn6E0dE)lG%7k|F}E;Wiwe2q@J<22+2%Cf-e$A7L60kz zLSKH6FStvr;!BUcDCqhr(NQ|t-?aKrrO$D*T7}7VOZp;Xi#3hV= zBw#a=TONs>C<#oc3Ael8QGtsNhSDQt@(o^aq6az4jy5PcO?+eQHWfuwp+Vvva#x%r zjE+;g*Wy*I63n47%#mWClHQjuT3-RHp2yn|SOEp5;3WCPxrQkUn&m)7faU;_^v1*? z?8P@od4iiDnz(5*IWtXO#OThnrOkL$=kfaQQEN{9gPN(5U~AWkTOLwfp*atd=WOQ3 zGShO>Kqoi|u#dkZsA=Gp`iX$AUMOWA2JH;f`)7IkKWa5rl-2EX*o;=-dF%NKo?xFu z2t1Y11aB5UVf_FzY6lEo@KevN7oJN7tuv;~Hj!UDOpDF(NPTRM%Dh^IO+AELTO|!+ zqyctPS+nW|vnwIwo-e473rKuEg{!aHq*bbLs5)f!5?R7w&0UQx-V9ts;(f!V9VFh1 zs#7zzRpblm=U#h=aHS!dvHe@V=uw^{qo_>0n+nZz8LgIG+p72hsGEFWB#kARz*}!O zv(f~01d4C@lXuWxfaCpBPjnrRU}k{qU=6%8`?Ky(lbyCswPSv6HOmLy$rbd>;`gYH zuXcOH+6>qUB#_>%h=EZR@kP!EHg*f3?Jlbz%);Yv>w+m z(QG0sewoH8YU-V1mb^%{Wwx@G1&*cLJ4&9gSsBYZVVm#_^QCC);kZX*chjf6$}|=y z8X{3uHHf6R=_{%=3+6!J6{<5kpRM)`dld)8E(L>?qju4`uO{^a99tk9PHu*`W(hQ_ z)%+L~Z{qdUs!t8Viq`SEmT5Xbvo=Z%b2K?c2!XJ&{p4trYEIJLf&*b#k;4|0(RI-b z=(=_=u1h&@U03BpDp+VJkpNtR>q@98yvehokJ`l0)3dCjIz?_{oxjipM};1>^-@q* z^-^HFdMU`AUTP%vU)%8js43{tSU%vT>J_nUe@?U&ZGxX*YS(!P`+HVOzu!A3zFZ%{Q61x1Y} zmWP6paAM?L@`P0r%QWE_0zwAzMnV6j3c6EV6|{;uw`x!@gjBfc``GjDphQ)wqgR}v zl|vV#dv9W9?~cBzqqZg13#PQhO&|Co>%yuvR)Okf;d+2p_slicB+Sp?ZHAZDPK^Vl zM(^W4L+dmBi6p-uUKK?yVKcM67X;KhjE^rs#cjvOq3K+-jhH;2F?nMCuYc|1@a4eWu3SYuOgW+iOHf<_f?Tgh2dPJAltg zqh^|9Hj&}>b)B^<<7Ry#kIjS|me9a}d^WMTl)5d|*r85%X+@-k8r~saJBMUpzGv-h z#Lp3oAN8%mSPB!t!*YjfCKwDQ#-ajn6tS!myRktUg;>a}^5+Ot?JNU5TBXrJ#AjNi z#d$L!mFv|6l-&Mjqe>@sI;up@Rz?UiF!5PRu|{H3(jcUSA)i*E;hz>yp8c++GoF20 zuDSs8vqPVzD}oKbT}CtL$q4qqw20{ZqnRzzk79a?p`w8XBVdnwz%QZEywz;qLJ34B z{h4#DL0#C>#UrIolw6fG3WH8K7d(qV!+Y4Z&*HIieN3`( zR14g4Sh%Q4ws*ik_1S!uD|QDZotaw=`dD@jYpHOW)@yK4cS}YM==2!1fgQk z0t!$sJr@!Ws27o+H|{>a)hP-S9l=@ZK6j04lUsO~E~!Mj=UV<;ZFCd$*>FG|Od zOnbZxNW)#~8sirTpe9S&+vho;(KN=w3H*`#>|?aVn$-Ec737_+Klshv>VHLEzzOl& zL`N$f2#sS*U_`!5HW@CqEepw>%#hEMV2IDls1J~$?NRtc%y<9E6Us4qig!hfe7=OAvOO6lfGO8QulQ&EuY894D3e78zITSk(>v3B*k2MO zfXTmjr!Rsi4}nIgM@fC8}l-)RAc88kNe>X>ZrQ8MSzazanpN8}tUwSF|zR>iwoyl+R9h)h?%2x90f;~R? zsYgct=6pr@E2W+_f7VZviL@b%wOf;kJJ1l?5$QtbCCcIIl57$PxVLXwe*58o{F{eP z4%JA^fzFv*gLmrQz|kgXc37H?4~~3rGaJ`agpwH}^10~~*9NAA48>E9Yh5S{V80H~ z2EOuxciCbc_s=JYiyJ5W5#%g{nHhj}%dgEqR5z0c4Rpj}^EfIfK|xYeseEuV`xsIM zZ%aYyb|V9%?#ZV?s{Gp4^p%$zyGSbPE|V(pq1@Dc+n36wGGaZ3FVp7*Pru&V)GfcZ zRrkoQ*6pT0QD8RRm^4`}2`bA7epxu9FRF=U-qoLd?uq+jpN)#wxH)D9J{4}7gikix z*^2vAdN*^pJWk_yzgo*KXle3({v$N=f?yvnML*X-($G&dZUSN<=w~VIs+^YO4aR%? z2G7X&jv4DHAIGx#KexHq@4plPCnLz?Nq6XIg4`2l})q-N`J$gMzb;X_zHV1LOkC_pk& zlpTk^KNnCQO&iItj5hIJik?SbQsv2G%kud^g%peuVYfDT^(lz{5I<2A-5MHRP%N;bW?S(J1_sn=}*q@S|hUj?cY1EF?oXp`;B@|yGo-(e2R ze@{)c6lW#Bk)%(Pj)gAeQI`U_TV-)xAYT=PNbX z;lexi38V<_Cp}5!ho%p0Utcx8jm!@CQv|A=#X++%a7Dm09W#Z} zaEiqNgV;}!aTU`63RBuyFv1fm*;uI(AnN7ZrL-8uLJlLRQ|*GiK|Nr7V@x8&SRcak zZ1SvvsK+|QHT7|OY|n=wzN(6{Am74es=p`I)QmO zbnK|?NbZP>%i;&`{__HZC^^bEbXUOHQTWF_6z<)*^&Ses<$P|gts~;C_xxCQ6-hxs z{+=J~U_xO9Fpo)O4ij~0>F@a(k_xnX# zvPl{Yh>;|C1Z3Kdb1u;e>G`wgj#lWfJyzQ;7$i$~{>TfMKugQ;R(_7-uu&FD5W}|j z#~rQ#GYrJvbO6s7GexBmuISTQtT5YKdzuYfS$Y5v4?X4p)F^c@bBa&d-aoieC!Wy= z2_MR!Mq87&qNfsF6*&rn2#kY|!Tx3vZ^%wddb zQW0FU|0}HlJothR)&RadE?_;-&jLiTz{EaWV)%k??dghjn) z(t)D@m>yG6uvYIr3CW~jnNy`@wglDy+Ub3^Q|~p*g9Kv95=hbCVak7~?wXIIAKJL0&VTETx&*Eh*46X^flRa7&&Lo8?U( zj{OVeBx_Z7|8Z~FL*Vg42_7f-i~hiR&9{H4<8!lEG4k!wOL5H=y)9*nVYo@H2InY- zYGvbca0)zMxWDlH0bUY3?>i=i=XFOJo)47KI%x(RTxRBZhUc>{O67TZmwBEc8+Tiv z`2q9y$@3g?5}IQonlSZOfTe=imQN3XJQwntlc;kT0MK?nDe^!{vy96p=72|>(T8o| znuT3+bF1Z6Vs78@ZolniS|3)5g=X+6o$ZI(%jDMMxK*6CIzoo&a9<_V@|$<{phN)4 zOfw|~3Iw{#un!z2y)af{fH0Xw=jw;Gk&#<9VX} zPw+ypQNQJkR_zB%G*>%gSZl-qx@CsWHQN7&@>K0Fp!O4L4C=IxI6W^2BF%UTwzWpKFQT3jKHc;KZ?sJBeFT~A{q0_`u{i-R z0sbZM<;kw&i!#*CHxQnlyRYzc3@;!9JcR{&-=2`d(}NFh8&RGwGdw+-la`WDyz7Ya z^!Y)a&ZAv{r$(Nj$4Lg0Y}z$6MaBTo?N>yxNV-6g!#G_d1ENC^VEoy_$Gg2TBMt#$ zB(_I!;S!4|=%jF>3=jpk6j9z&M5&}7g226d-s~7rF6*_~h;qq}X!({QO3kHUzkxO& z%7{-5qC8(_5d}Siz%ooUImg@nbRr5OPtJG}*AFHcb^}oYfkuLNf+*mZK@>aCxKIZg zQ*c1+)+qPr>#cGhdYCA8w+1Np{=w`|D|~oI@u7nF0RP4R5C`W{V>9pJg}4A|WOz+~ zZ#xb?JzwMCDvK$=&TKYK6g?w(R7LJG6#jQ4Mg1%H$BIM-F?r&>aEu1j5-JD^pe1r1 z6|JX$nu(o=R)pMl#q@`)qR*@St9-%HFqHr|_lW6d(r9o5Rp$6qqbcdK8=f{kXf$JR zx^e)BAVswJM!_G@1%L%I9o0*p0T!0XBwjS1!4|lIgQediHsL$+Z2jV&LZH>lHGrEK9Y3t^R z=bEo^1LCI!;c5E4dxwK^L$D?-F?d#||?Q;tsv)bn3zoY(0K% zsxDM@Sr;ar8`OpKsAzJ@T)p*1f z)Oa(r0iA$B7~#wu$H)l!%O>-WpV>zKF^p^Ab=p#@p9$kE5!AHpE>zqlgW~7IIK1U+ z6?zW{pHArg4fYur&&I;Hk{7ZjCC9t@WJ2$FA9^k4Ez2b{m9%G(6@qXcYbglaW${}i zu2bq6m67sRRL9c)x`$ZFtGwVT6|bG&(MB6VEd!D}>#fz+3=yl1+zzWfH4)b(>{a5q zxzwVR{i4!0?k;tI&kJBkWbZZY*BY0zjDkwM6ddiAumrm6oq1e}8O|MS%y4Vb-!9<^Yy*o0 z1yz23n{MUTbdbnz<{ZfHxCH7Zc|6yOg$Gbqd5jL*zr zu=y#<1rDXtK*U2JT7xQeCrAe76Y)>nb{DMZYz>`C)DkddZJSSUxA7E9J(&Bd{M zXqkjg_JoTHzX{DyEVYn>HAQllSQ<&gwgbZg@ZxR1ykji=Fzpv$>FRA%V-1$F8|+U> z5iDI2ntACj!qPu88bX-~EWPFfgQee|Y_SxeOJ0KQl@?2nD`EN#Q==Hh<|+I`P>_+8 zft8TRK<6^E6Rj8;i7C4cmf~a&FqcCZZDMJ_x~A4x>pE|cSl5BKz`7nzpku3e_CA)J zygn7F(*oRu+p!~tXhdl(2w+Ry^s7$XM-0tdolova3PO}nh71{?x#`dE85qXPVPUXl z#G-r{#ik4>I`IE)d;qSvgQ>SXerdTedD`15TXoDe3& zNI_RTLt|q>DC9I0hJvm_L4Ti$6QIVTkkc~id-P@V%29-{uR=cft-z$w7spU-=yRmo zX8i~iD96h>J~e9_rd1cv3n6~s+Jnb_zJ|$K1Wnle^yDMx-)tM z!6<^G9jj4!IJt5gOKRme7k65Demj+;TNYm^Zr@fu{hZ{=y$5ch{P0YY{3anazYcAg z0JVVZz*9-vp=U6F9K<()*gPsi7LpU$P2L$O2uE=EfASDcmEW}3S?q1&EL#F5;K17@ zm0Pv6P>Hfq256J&4^4lS^(5;*YK4#;5K{s{XFKlYIO6`bsRuajNKgZZjt8KhJ$C9y z)aX;aF`9NV4C3HKNk&_w2d%|?O>aP?Q*JN$Nkomo7ZEkLf5hU=Z)9_5Cu%v}uPlkv zZ+nN|2u}9}6O=_HQg+cdd`M~kD_v=S54Qg|XnzmC{hc@e&5{n9zt5;no8RX<%c1_|P_+3FZ7x3)@Ibf48;^2U zf8-2qR-?Ms43t4R4CI9=REG+h0|muU{PQo=H(w@Z|_gMYW;O1zfHs=X5qSZlj)?JS(Z%ESCLvqU=`f2~FQm@g4Ry0agha!88G|DkB-#M{MqWCc9GbK2LpBfpAzC-9TC& zAg}^WEWj!3p&2();{msD8I=$m4ragFN&DWR7llkK_%@1wwR)o)HF&}6bVeNCLEVn_ z0&~BIdNxknkGD{i?B7?9qWQ-T+bsPE5F^bsOUwL>JDw&!k3&S*vfTU4n;KB0-&brs z116P{iYy5zNPmvE;W*k0rguwJp)3GV4&6f)0X`hhgU)+Ly3qb-6VY_4eqc-~6>sy% zOYbRvY!k&|B&wN2!twaH`^ikm>Q5=@m*bZQi?S!8l7v&RPTAM;$E!Z*9Gnp8=x6&p)bsppF!EcB~H%XW2QaJ;b- zF_G?r%Drg@r8I~#+GaT`tza=wet)DC^M$r*!RdYJizd_cK&y`m5?M-DP)6$7aNPK* zN`6WdM{039gSWk>%=GO1_#yN^v7>XGXvzi=;1ocHz8;Z3+`JGh%R?$juwVdYu*w)aUbOJjHka`NI=2^Z6k&y>FV3A`vxwsXyvk|yt>dN7GwfT*8H_#c#Q z)-S)uo_Ra#m)-QwkF(mISo#kdXXZArfoMpU_u0N}>3nSobv{MZpt79Jh5XrO5jr$7 ztdfV&EBrkShcVHH^^nJBMPhx63!6hT?m*?tH} zXBFifl1#5+9T5b>bmSdh3(y@z=0c{DMla)}<9U1*H=!(MOe8ixx0*No<;e7T@)nio zjgtX*i@iHuQNZiJ<8cH$ZZ6Bz4STqx7uiBi)jMxEvxO1%aLv%Ka77p*ya=!XzLx!9 zC*DhhZlwS%ikTrY6q(`O`;cl=KG`cu481Z-YrySF*gr=uUSbOX30UG_SB+pM`!wL= zrm5E+h|!py+lfwX$BSiy9UX4P0lOnkI~?L%JE*l?R0qPcoTyd*b8hg}-%2K60Weuu zfHwiK!e*dB;9LAS)%#O=3XP}o(g}^;g>^81bUP}Q(0}RwZbKEVS?3TR(D9c4(l?H< z8gDYtP;s8ZdOfI(gajlYNEQvi` zH@p^%`m2u=sdyp$YEphxkzW<$7xdKR?ClgIGi@n(#tXN`^k;J!-y|v-TeONaGFE|| zA8G8oz8N=ZE=cH{h^5`zlK0`_!d0OeFUsQ_n}A)F$}LI4q~XB4Auu-K6O7G!3KYnhIPs-s6NR68l z>q{t)Ci&;lbn*(xEq8m>%?292J6fTEP7cseNoYWvpwKY#2ttENTjV9!3kD=ONNYws ztH3}YDUW{!$-#V&*+xub2rn>O(n}K|t<(gi(>wV($T|maq}anem2U;*YsY8pAd4AY zGs|j4zSu0aC-xAi<)RUc$Eqj+$|kPn(*83Luedz)x03WPqF^a)3@sfEFz*>Dd^t4Z zY22jbO38r|xy5~tB55lf04N_vL3A`fKN$#Fp@b?>7zzctdYuS#l(D|R@K8da3`jsL zh&A%0N8n$QY{4fp3~J;Fm7zSplz0eHQ_FqclP{|<`|LNI!Zb&zu)R7e#0KYh*Bq`m zpJxW-EiV&1B7fl0!5c6ozCndJDP4p(nHLC8-Ig6mvc!3_sv*R~lMR-Q2VD6hp@<=Z z+v5R9bPmg=Mm8y1VwP+&!1V9id0z!x+3NMs)6NC8%MmwzO1udcWV)p(`t^SWKb&z} zf*&_wEep8;@tB~>sGGr$b3gyDV_3HTdz&ksaVi&%$4XAKkl)>V3OahxpOw z+P3lICB+YzW|#Z}Hf@Amk3dJKR=2mAr4S;6rFQphX|@qDJNZO?#TMmXcdhG1=5;v4Q8 z6_D+n-uNX(wjT_$VIvLM_YG`$j(6aplr1_c#zCmZ0{o94;=(0Zo^e_V00q3FYtS74 z)AQ0qw7c-qzH2ya3Pd}=qDqqePMU&PDTlH}T9^Nk6d!CjDbyXZ9glJ7g?aDGD-Xxs zLMl&oqhN%wS<)pCP$kdsI=IK6Fs+$zR6q}v4NsaQxKuz~O5E}qt_EcnAp$hm!b=i; zq3PH0jjqrL60z_tBlL9X1+^cfP-@5=x7dj?mfHeKH(Uiu&mpBL^ex#u`v51ot7)kA zTye0obE}0T+P8;pK;m79pJH1Ae>czX*ht3x^S=&%)lR@f?)HZN*_gJ1-~Yj-eH-a}CFHv&Z6rm$FK(WE1Ne8kNcflFAA5Ew_;){VwZ=cJ3*sM)@E5}0J(ECLC+nA{5g#@m|B@&*bYkN4mcrk6 z6G7>@0@Nw?@yp^r#j!*$Xftte^ZJiBVI@dMR&wsz|2hCpJtklzcYERIZ2UK*0|4wf z=obNC_wU6@zTMcNmGr5EgxlypHf|pNiGM=`7#1h@%OQ}-ffNX2a-cN?KJ`Gy!ma!8 zzb@Q+u?ER@Esz`-x5x$1QuKl;qI*v zm}I}3AO8XL0wLfp1i*&NKv&1{UzhRE#HfA*h|u%bBlNq9_VDjj+DB*S>0*|Xq-}yd z_fYNme3g@DG+i!OSQelfv7kK-Gm$tyoYnw8U#)o;jQRwV=-e8CnWu6|zDN@N9x)e_ zL>Cu~*xj3sWh*`w*5eVIdNF zW^-xrb1}r@WZk#zctH;c+FW__2(l5ag^(j{rLe>?~4I69Jc`FmZIcIcxmllF{ZNz!(nG}8XF9I@TbkjjpE z?MoYi7KT~_NtO2YUyHOieWkeAKq=dCg`ie?{V#^Jvwdl&^gkzEi`XlV{o~+#m_#zJ zAUPR_1Ex6_4j8F9IcR#e=sip_!`q9@gFPYV#z6z^AwwzbOqs-Jqkqf0b^^$|AlO4r z!tc;@j3P2V>mpEkc92r-)FO!n!k?iR8;s?XvSK38{^gy6w!b$ za<>T|`~gacnD1tJ``xM51|2oC{Y{>+T+`Y=ye-ytL1MH|GTUodMdEZ55T!#8NWD>K zT)U17I^{j|J3cFe$Fj3ht=U4`ZZw#>g*QtI4lRC%6+V`_mg|r|Gxj)Wzf|;P!V2RU z7~l1-%hfnEkLm4#gg|7{L1M>AWvnoisXOR;X?(F@aMBqbI#R+Z0%)hVp^qI^6Weh6 z{B|IR?94h8;efYSPZDh!osIpva-3*lPjy&#wQ!KO1$s;96j1m{^p-LzWA?7*aC=~3 zP33W++O4~jomCl_5}FyygKRg3>i)qobeso|_E%v0A$;TET2#$q*@OsM#oQ>)JHZ&N zD>`O1)L-AI&gBKsHC>ydtE9^VW>;2>Z6;;t%dT(aQZ#B3bWPV_%MwQ>LyOZ=mpHzJ z)gI(Yd%AZ0o1$yyCB$!BxgCQr-rP|oLrEBWp@!AHM+iu)d11pDVR~}4n@x76XEz)Y z(6i}Y$z!T#1D5SeJ>x2BNQT;_Lo8%Nj<@Sx8WLkDT}HbZbwDdbppc~%<3i)REqjp{ zWfHYC-biJGIw+|x=vyQ+6^1O{qM;Lke{C9MB3nK1**OI)EgU3{(daJcDX>$115sb_GpBAZ*ko)+VnM z7!O`X4<0sS{C+qGF`A9{k#UB&F~9L_HbjQ_?It-TZ)ka_SXOy*jJVAe=>Tz47D0 z@*4tyi^-uU`CBs|=muh0JM)21bOo9#bHJ+P1C&X6D^^76@B&g2bY&8ITb3Iuah$~; zcXw)5bXUnh#byZud*^y*z0MZ;1#+E(aD&cAAEIl*Vr9OX<(+T}3nat?guqyX8YCuRT*GBP-D(>vPfCyw2C-{F zY;zC30mfS(#O$~~zNX@UHPffT$VK^}{0rC~Ku9&O{%j$;O5d(wN&bEC2cTghR*^Py zqdV}df^9^x7=?IW#uBi$^sG(PRje(205h)Ga$pOPpTJ@wNf}O7Z~<7R0*g$Jpr3Oy z&%d`7uvDCu3@kEH@MxgQ*W=`j8Nty{|{K&{xc$`Bahp_@%brNU4?nU%QZ%_~FOchXon$zIKVG!eB|H4w7{h-${2kTu0{m zVU~-oB-Yp1O#}%^t)ICSRlMDvMjLysfNGd86BjQWKtomf<7c59@2dMXsu}v#?u=?U zXKB3Y3y>owdLFS0qZ;@WSyN1+l|CaA=ubI;3yPK`4HzdwXh=cW51z+osj=<<4>7iW zyjX~W(XqossH*4H>}}&6dKMJ!CNVYznS}WOI@J9}&^^QmYR|;H4;!UoYDwscW(iuF z0^=vHKi~AA4*Uxm+JQGo(pPAkrbZS*qu}#ZIVB0YP`yPPGf4e;15nOWpq#tQpa5b5 zhyt%t0$ALRd1l-fE0Xqi&L*W^LnrBRuE7ctvcySvq@+n@#m%addYrP+N!UN%fnrf3 zu4=|s>y3mH=&{TbL@27VEL?NV;i0E-?ua=pA$BXp!*GqZP4l2-zzZFu+n_^tRf$WT zO^q#oq>9qI`In@wtz3~3WK?vQ{Z&O-ha5TKy?c)dypQh}2)xiMZt-NKeXytTXpp}A6(8>jDK?>F0J*Pt}=cl-U1Rl!# z#A?3SwfqJZ7=p$8_~jF2Em|1wqEO7ukFNFUDf}}o>|ld=pkkZpc&=j$I8VLOh9E8DWgw~Maupz4?ybPAxaUj>SqvP z3}ds3x&3o9cp$*cE+s4hw;ty$U79Q!EFCcK3M^$dJWBwvBgY3Tr zMe|d_Kvsq=)*iC>$>F_hFT7G=b_;a)zacW7%_DyOWQx zGLMB*xgk;*qvfChSa4ZpEOLe-fVCw4zH0Bge-rI(=A|?3{YNR3;$JD+8|?oi@Nvua zqaSqP3^pL49!AY|giZCsB)4Sg(+dhMJapBZw_0X#oZw`$4R9#QyD7nYBjj$qo052M zrnScWzGMB^yJ@raBWL**>&MW2lJsN4T%#Ws?`-v>jm$#h4yl<1V46gM!a8L%P0%tC z$d{xa&wL>IF^`wd^rPvNPV__YO$@Eoc|`^O94roO1Y)}wH_MCwD(W_Hj+38e&S57) zVFym^y8xyB=w*=fF{yYb^j^;= zw}jqA(zzqL&oYqQ9^GwGJN9Hyd$Lm7w*8&e_4owb1Dle&ye3EiA|s&w1c*F%1ECr_ z2YncFvjm~7!fX=&W~h#Czf)?r-+|FJC?1bzEPW{ux+OFt7bOTdGo*$E;#N=GDo$Gx ziEggR@;5~oVSY^IQ)5gytce|NmW%mpxHVo4(5xo=@uD{}%k?xQg&Nz$% zBtX6iF@F>--7X^%>$P2^aLE;C7rQ-fEFRYlD#%%x zj4q3Ln&b-qFs|UHVmX+8EBz&~!Y2Zp$+MMBxtUcU8n8WCZ_isrT5WV_-yMzCvs2Z! z{XN9|de`Ek4(w0+1_!V#cWB+~gCP_oPA2rFwn#95#7XOQmos00QDEJrtchC&hJvNb z8DOE^OnMZ)cg;EMa|!A<;8*bUQ1bN9Na5m8%^iRa@HNU^VW|2=u^Sn}gUt^3OS8qZ zTNw_+NNgW8SizLL{mz9M?k{sFD>YACIa?(s` z$i8}`3qaQEc$o5`7y@XOPZs}A&(uLa4vN_Uo;?SJNZ=VbpF>bPKZs(X8b%nfxXnYd z3<@dSCX$(IrrZ_?mjH6u+i~@Cs^56otRctM220RrANcZaY7h86jDTD3LB@UpGlBn! z`2X}@G5+`n0tm(*nPS7%nQck@!Gm5?;t#H(Y#o1$#u^dwxjk6f^BIMehiUhC&cce5 z*i1S#{*n3gO5Apv4}f#$L%@@KF&-3 zwSo^lB_loZy4dUyymS_Pl#YZJ)@WBWp?_kpa`Oi zp>^Uf4L<7oNboUwCRG?S3Yxd>Ao$oV?Uw`}{ZW+_cwB;y4`NztpA)6lc7l%wy0O;H z3_h}?XzC*S`SHid*pOxam*S5%W{6;;N%6;-I|S@k;*Z_x)qaQGv{eW3$3K61?N>^EnE2zB zm&I&f|e%!H`HHlAW(GRFT^(ylNmBkhBVebe zGtcqlR7Hma_WOZ$%2N?!2o+<$W{wCK0bKJf(E$@xTg?$c>qwVrBGZ*NDV3PR#K9Fg z4{zsxD~ zSvq(#0olqLZVQHvQyJROEpf|>7NEJkO+q7)&q>7dKR{c%IG&PXPpR{*%6&7!oWOqx z8C^4@R&xSnD&UVO!Av$8&&ej33iuIj6{oFLGZI~=8Et)G$7b}-y=q1^LQ>F-7O(AL zb&O+~JuvB5#u8Af7|#Ubw_6!cIbRDK<9RFnl;jd^s!8w4|vO%0No-mU^P>|NfgE>f^M!6jObdM%n2*la1s$%rVmN3mTE;&@p{E~VPPMWzm~A)`oh2N-lHvLw19XEO z&8P!aF{1wjtt&RACkFO<^mGb;4%KkK@S@nT^-k1`lGkkt)xNq-w{DmSTg^2bzvYgw z={@Li{6%CK2b-DO4L=qm??wczz%&5ShH~Hi+@HG!^cKf1$SRHvmXZGvNH20syDEaS ze>g5EclX8J;=^8q*`XYudUh@d=Llbx|ur8Bl}yjzXvWx8MRLx&k<6rX#hVTPs7 zeHN=^FVrqPISFEPXA55`yln5#d_GQH@aOVzqy)I#01{=U+R3OSRC}CMB{TG!PBt_2 zb9oP^3E)*aD*wTr)>A=a1H{B_&`4 zHGp+#+h)od8%{l3&->GsQi-q`WBMo0!0{9=#);Z!g+4pG?PuYV$pvVB`ZIhf)_)!^ zFdZNcAm2N!&q~=LIH$I8;*KPtfmMN<3vg|@8}DtB_cGVZd$zjTHmids)@|Uzq*YGz zb<(z$g<;j9whJ3`FNv>Wliefse4UF2FpyRL-Ab8(3KB(@v-N-sf2ovNn^cuSq9Mbi zwMjA+mhp$1nR|JwB?JcyOkP4@ik7uWgYT5y2@1rdBs0g;?Z0wN9tWrZU=5_)%{**6 z78M*sv=!Juect45j6SrimL{w#=*|{FN0v3>oo?|}OdUp7#Gm5T?O%l=1@JV8v6>9r z_YRPfRQ=<7;c>5Jl0xwj=YB;f=4{`}){{k^YVq?Wob%wLMO&%{Kz3}7h&?0UvKa_f z5YS=KYRd62l9vDhDjQM}lo)f0%Udi{;M!6hyL$ZW^$bNc#$kRkz9BtgS2SiKVL z@t;Xr=_n?+2<7tq96xjdCD2BhD=kCIb8{Qz8Hp+BP`D~$`|h;SZusAcUCGssdz@%i zJN`{<6q8DHAz7&IFStPfTZ>YP`R)S=8x7S~;Y)&N{x*?S zW)#IGjfA{N?0f`OgNh434$WX=BGLJ}N)of3s^sn+tT-*sF?tC^$(}6lHLMyTXUf}w zyt{4}l^jmuR-puco@%Y~1NI6dkxAO(s~C%k4d2ornzsFDXxddg)PPp+7eY;I`VWPo zn%44&S6iuSHuT4TQOy_@PN1AYC8um*OrJASkB?K$#xq>z)VqM1fmb4}grLfN?z!pH zOY*=YtQn$;fqBZc_}gM87C>HT6F`1DcsT?{1Zggc{*XYB7Yu?djzr&$AB2J;ZlAxe z*blU0Y0N&~sKx;yY7KbI)FlME4hf5yWQF756a!R{M=SZO8xaUd=Loj`@x`qWqy@`{ z$?`B2w!m7wBM9>491+(s20`XgVy)N$J)L|)UN^KW0>}{6cQgMvP1iY6spNPI--Ntf ze_~q(Xoc4CQoC@Im z^*0D#j{DArFRAeub_-@a1}&R_s0Z;FLLX6IjmN-E@C7K65|klU(KtNx#5bJ(H3ghg zkN5YG%bqE4hyhA3?62Le|yb*a*NX-L(P(4YTJyO1*gFd?$(qeK$v|1x<`X zwL8Y@<5OA}=oM9nBzN2&k~{*2p@FFRKPetvtMTX~M9^vL8o*bc7e0qq#G`UW3|f!x z{9`;iOFx3Wb`gXxc!@_711YgVBSjKe1swRo<9YRkM%4_b{wXp8^Jgf zb=WDw%EqFa=I$mjt7}IhKaeDVijE3O zfJK$irU|GmR4Y?zi4AW5_eYsPPtrUL^nj|Nx_$7RzmEx{yaUjbMfismnP%&KpCTu) zwl0M%Z#SWxeHb$XbpcrmniBkj0+kx`_%Jl{Re~gnrWn{jih!`zC|7f|A_77Y*R-V# zxXpm@&BtK$HXzhzZ5);IESUxE2KUk*0 zU&tFB6BP^vUn3q#ix3KGi;#?15`UD9b&u%#7ZVDe`GuNknatTktuSA^%Val;;#ia_ zu{>?VM{x-oDj5f+_bVrg(`u2OAdGbL2JDfF;?=mVC_eCJLGc{3nzRZ!@p2J#0&x>? zE%UG`i2sgAj{i0&M6-;Rm4N8DV6q?oJu6>V#P8x2@gGWyzsAq8^o8@u@yrK!0ZST% z3hT3y1?5#t5W_Cq7lu8=j4CJWS^CR+p>-Yfm!b7JlwC;*KIh{E9q8<*SP%LdG7y-D zT05KM30%tBlL%wR(RfCdM)z={@Ums*nLLH1&=ZSUb_Q10;n?w2nu>v?NuPVgHQ2O) z=_7Cvnm%lIAi(Y!oacKHzP$^>uN*@#b&3;sNJz-=e#oKTQ+jRp$)UP_B~$KTb?`~H zJD&2@JK!Q=;f4WVA$Rde^>4B+uGM;gFj5IB856|9czdVSZso*!W8Dxq@u0sL9@dco zT&cvdUNmV-jjlvc5W*wiWe>bb_M&A4P86VaFGYuMSq7juF%4x%W6VN^qe%8hs9pln zQ{+FYwfy~z96ppoy`&O|KwAW2;K#KwAc=c{{3Op{imcn``d1K^fK0d{iO!k&BWQBw zffE}G6TyxpSh5Nc;{ZXFB@br72s8LZO(S9}`m{elb20F91)r3cyvnlztrd>#$~wyU zeEBRd9lf4_6!DtFy3G45@(R-uaq?Ngcb88LzB|i%HtBmJLuvUj%eyt{iNTG7mk)j; z-UEF0UfmlUpA&GR34Xg+oJzDhe0Wx9`ekMdAhI7Ww2@c1P`LuT*YG=edo-VmWjHn8 zr-iN`NY}@^yNC}Y!(Uu800p4;1meg-d|^Lf(qCT_YZP`uc|;f{;DGW2j2&0IDxp&w zotkB98K13Ze74@(?F9BQE(SgQ_xKDj7R7vJ%+(f>*p;+z(%Q1Txz!4|;wHniXE5HZ zoCGPjGgrDqvUns)0>=SBHcQ&~#}w-$&~>h52ot0it9et3WEmH;{ztTk1tWKqB6y(|_{MYb1#dty0p5tLjsg0t)_u35jFs%Ow5*4} zWLvP;6I$5Pomwi#>x?B2*aRAY}*JqsvDsLskyYj#-h%Vq}-U=y8bqTq{J@S~Rar1IU`T!&^N{^gjhLD{r* z1)|RLbMtwHe~~Msm4om6qvZ1JXGq53b9Ss`mOLGs!v{=sPZ;En1hyuVuy^LF%LcPzR3NylT>GIq7-?d$u?|M_i##qfix78pVPU zNqW0)tE7a9q@EPd;0eaDAXwL0`63By%`7Pb0hLOe*c1jOFG#&O%AIxJJ$b6{WXWbUSNKe zMn+3>=yaRe#;E#k1uFV(w607Y_nX^T=CWO65%GgTxb0xo>Sz&X7#t#<*;2ux3dH_s z?ZVuRtO2KJf?4Z@KebXRd)!Q&vQn{M=J3jBzj%ELg$)NyeaiE`?4dNE4AT_^E#ST$ zfKAm1(>cR88ZnvntYyt8M%q&@?IA!470|G3ej#-Pz8ng%f}irdyLZ!5;2Y$9hKIKQ zPnbbLuo;&Pd5{m@- zbrcUZD+A(=AiyhpJv8HJ5xw?v3FzJUojA7~Gw!VUdfY zvQahlrY)_Rxq@9*AWSJ<M^7vR3tq{L*V-v;DkzYBgMg0mSYsNb)maP%d z$;=Z8BIgkNDo_cW7cB6`96ib*ics;zZ3qki7@$CAKo|&s>I@Rc1j-~o z%jh-WHu7oQR1vCL0dcT|>3c$h-y@LEP#}(wlyTG~%R6E#MZ_FZ(trm@Nj6a#Q>ER3|_gV@jZfJR&Tkeg;e^4y}~H9A=_` zdHg12a6ZXtG~^V}M#a5=F<_Yi=(YUW0JJK)0q80ppf}sk;9H^<`W68Fecik$i=wJvvK_ptCut~OOS_R`Pe3FBypyNFg3#^^R^vLrRMVqM ztWh^0o3@5vBjxcUWuAt7t!hX7GszUrRj34H3Pw*`N;_=w!aKouN14Q*G2npxj>t9n z{3b?L?d0=Okw_v|KS!EmHv5B-Zdy&_gu{tYZy+c!+9}7V0;5H|4-J7TgV*9^#Jl|d zvw+dgl0r=YqD(VJ3-dE&YX7|Z{?;;3Ff7oN>0NZ9Elw)*?|*Z&J}+VcH9|;IiD?N! z5>csamt#mM@I9STYa!6a9UyQDEcS!Nf%>6*e3$m5rog_reF1iZ7sv^aFHOd?-gY}F zop^!DK7ua@TP4rOKHHUT)R4@ZQ*llNUq!iUN>n`++vt*nuj*$`--OJn8w}$?PvSh& znvH!!wf`m<)@j?~P}zY(htMCWCAK zX}O0+S2+-24tZ0de1yJ)g)L%hqCFED?F;g(usfLY>wVN;mV7edROVS}> zmTvF3aA$lv`4ijhF7oNEeYHqvWRkfIJ3$M|GWV_BF6~rQZ~P-b0vcsRRqBf>pKPwO zdSBt|Jw!-D`O{1GeR$86XK`z2bRcPa9cCU`$2QJ|ogHs0g6J7-#G>sQG2MSqVILhiy&0 zDviX_9C%+G4;{KemQ&U>UOV0?{CjA|BPf)?k{~BSi88s%sqE&!9g-w z-y%WM9wWUcOCk-MJ=yZmSF%B>37>!=-Pk%*DRBV&w_we*rE5_qxbz!>2dxq^g1X?z>T z@v(I81{qs?kC)D9i`A>^o>dQ04PV6J8`*#=F9*XutT#uo#_jXvgRQovjy$S9#XN(s zRMl*3g*0Cp1|BHZ!pNN%_Dg!7u}AuzLavD&=8z27Ga7FW^etRcd5}~0#>7mkyE>f? zKP%Hs6y1vHru%^kny)86`ajEyM#pfm-i7N{Bu{tLs!*D$_JBNDGAk7p+H)9hVUh~-diuKQ8g_v|+`@QsM`d8cU zi>YONaDf=pX-IVs-FtsdTlg?k=ZXr-w1uirU6njx(ns9zi|c_G;U+hdK9{T%QE*2b zJ!5_99+tn9av5a+n@~iE_h(NwmVSdvMrKy?(wSoUzt3*lDBS)7AD|ZX%k?T=webiz zvq(5&yt8gg4{SG6KXD>F1eiw-2ZsE`n5ndG=0K;_#I1ui=@?p=?J8hjT&j?XTZddB z)_n+v{N41@GdSw0z)AI6Wk^vAv74z4{o_Ck`w$Z zU%sx4N91b5=vbczXOf})AL4~!k(j-=DxT2HY~qp-P>0R5O>f~xsR& zkeX$r8wt?Ne_aMXE}uAvZ^GcAmzl9KWM;=!qY;3-!Zb(T+pIym+bu6RfF2VW^w~Nl zeERP9yWSj5ma)PoO#1tSjM|hQl!p_yC#kfGJ0@ zQrw1rpc{XOYLrjU9;T7xanZwtPOLBz3nM*%c^AvBI0;JtzK_Iaup^9#b`!UCY8KOX zw=8v{7=^W&<&0uH9$hkAyNAGQX4>2#;E2>KXE{;i=;uJ|SbYwO z!L*P*=Qp(SLrd>hX_{vg#cq=768dCL&Xq>tsDj1uN#Zz3ZS<>nDZY5GbcZM=!(3bS zw>iEvHANOMq&(0|>)Hvc`lz;f$|!sSk7R;_w4AL~>A+FAd<;(rQ!Dr>%R89Gpph_Y zafvdhZsE|f$vc4LF>TjIK5sfq5lmKdF%+aLs*t1&Z#XJD|z&=?hnCXk`Zy$JQtJp4HE}|}XFILT@WAv%gdB3+fH4tx zHyIfz0XX!(1niPy5B|b?s0Jj!Y0Z-->{Q}|W%Ix)_{3+$Z^7@45(jA~0D>0Cx7-=H zn(xC1V9iS}rKb{>niK%|x{{9!Y$k&pjzL{NT>HkoLo@zL!vahwpj`$YFzJTT6@-@& zdwi0dl0+h?kYx-l=YSb;amFsh&$58~nx!vCCL!MjD?T_)bxDjWh5~XVXe&@sAjd{AQE0=lh&A z0COw>-Q6SHY42@NS&Z%fWN5i)U}Mpy=Ay+Lk1DEJzo}@?#v->z0V9X&@1bO)AJWED z8ws)AenPy@YjB1Mw89mWFCij2Q3xCw3a%6Ij==e^7P_G%co>h67VheYcc3M_VUv%P z9ICXg)(#;W-JG_RD%<3FzZF#cNG?wF8;d z*Sk-i#9+d%jdn0Wf^13QAWO;sEyug~ISwX>)yf>L;wxU4Apb!6bn&ZgI##Xmz<8^HYaqX4C>u%y`SmmMkm zVDg0G!Z#C_NWca=$r8|+o5#ypAMh;QW9jJ^a-{R>4EPN| z_ZX-_vlIO~emWf*y$3s1UYW#m7PG85YnGBlY&NtZ7if%(`Gy|ZD&{-#-!`6svLgmY!kW`(nCG4v3V@a5~0cyC^91br;OxP5MUaR6FQI}^{w zpcPFqJw5Lkr8l~2Qh%5laM3Q_bJlNIZ8UAaUeJ3$`oqyqasVmE&h>)&VOgpi;yasM(^qnJ{SZ+;rAYVjrDp zJu{&ZXWIbiH_;G5JVc1j30hWykO33?Drrtvq925*Vn2sw%*12t>y{BKOK@xQqzIDX zmUJR_;nTWtYMi%9WEGkSdT%Lyg zdoLjBYgz8q4X0sXFRP!PPwIk8j5&pZ!N`zz!qXHC7B3ixFcA=1DI8!k0ZmRkPr``w z(rQMlnMJ(74T@eHpOK))yYNSdW1@{PjL-5XXF{=cawZu~9@jNiBJY8)SJql*vvEz< z`Qw@*&sp>mHS55(2>@-#vx4#zhis>XnCSr~Jk#}~lJ&V7a`KmdBF!=icmtq6!R?I? zC*?Z+8YnNAG2sbrsck2S zZlAB84Vb8O->Ic$A=Gad8cm?U^AbFja9DXr9Rb(CF;18Ox4f)?BOGTdKz(-*9|L9IuhopaU#s)I}j##Ho_SvY=F9Ni8xzc4v6zk zZ~hT#*!}ljM8hU7ipxlL`;-1eaWbO-aTZu{LUsYx3BTZ|DN-;A0jEmyk?$bQldb(G z+25oyVS72WJ@iueADV|M%((d(!1lEF0w*MAIpem)D&`W(ILe5|^iRMEI*7DpY6qxe zNi|Dzn!G`%y2TAxe=GaHVe|Bb9;TYIW!9JWe~gG0YV4oS(YF1YQ$9K~e>gMW{Lv)u zwY-is=B{)8>*oLb(ty6)?M*q{nEy9VC7D0;J7E6DE}*`M<-;3TeW94bmWAz`|CRrS z!klCjCRtz5Y3^8G%(m+OrWRS)EPb<7=BIC=GQUr#Oj7-!>6@)D2KIj$!eF=)8lQwP z_wiOMgt=>R?Zwp_HzF2H-17JRbmUum=t}vmH0AkonQuF4$BbuADpxVI~M88M3>+`6*7RU%2Ngf z7WapsqSRkv*XnF6401P%o^bkK?0A4vU)@F?HyMwV(?^%Kb4WY`$#Zf8$|E6Aa;!1< zOi`YZMCo#WrL~O|c{fY|&hplbM~EE^E%13BsNf&bxxGW;OBz*mST_!d-{DZBI`w~4 z)se|NL>Wx+i7?VYip%@pQJvm~m=n_rNCiT;L}K0ygiCYSrz7k*a!9U0F>~RD{Mu<oS%*3MiFUK7&1O`7)nkYzN$kbh=oMkaH14~ zAp}B|?Bpy`4P?jO?QtYo52uG^swNiFq<>N2n$V0-SvVRFebc#;au;)^k^eDMIuQ|x z7`=b(sVWDxHn|O>a?me!UtSt3DmQ@^qsa>yRb0a=?18J2rC>CW7&%0zz;yRPXSP?~ zq5^>Yq=RgS*UWUN7}is;z-ddHaq)*CwLbQN7QLu?NfyY8VsFwAqncklZdFrqdF*JT z=|(lf5BoDOk^Cir|A)GFkF$E(|HqqZ*Pv~W%Vb<)IwmH%G^Wy(c;6`}yNH zk4NqGe!th{b$`9qT>-aiRV<-}z%pbaR8?9gWb;&fGnZ&TaVM$Z4D)t+%x>crV5o|p z+(6KSQPOxxKIKwZWk5vDBnE&+%*I|C_+q9LCECLbbsdnVD@Q@D`@=;<$3|j5%Y@rC zJX7Meh&fZ@eZFh@jQHaQ?S**aWZ!HQ$LM(^_9QGJZ?xzX!z5b+%_3qc6||IF*_BAx z<;ZW;^9p<683bf<;O}&x zidUZ-W>LHfv_~i^LoS#;*5`lGAPbgHB6Gt`@X@l+5_l4KY$?SUonveco+PmZrjP3s z2r}1C65RHnCNIujD;H1Kcg^vN#VACespO*>T>Co`176=ZQJfrUDD*(D~FZa)gsQs&65 z#NH``SFb-y*v;V8)BQh6jNmjF#QK#*!mV;F@--ccS=gTbR?DQ z{=NT#zu7Hyxk{?PiA)(m#rTc$?O?+>xBYuB&c5z8vez*e%O6fN7mr=9oXb~Nm2whI z9^XOaX(S+UWt+J;d+KNs$5@@;dvW$Y|IorPO7yl(T?_o3PSaOtm;-(QVaqSh-ZufN z-xhdz$G^r3YRP)pKlENUh%p^9xO;-R2*)dZnaD%b0F}(Q|*I@uv06 zVJvo&vtYE@@7Nv}!)WHv9Hwa05#+Pi{bM{ZhzT1w$F8ilvV)ja8U@TdiMkzWm@8h#%#Co{re#3-!Db3PqS~mZ3%_MZ&_C-- z6{JF1rkNxF1S&rme56_(gGM5;L!~J>@8VzCW)5ygzSD!v>QFS&@QaWfTZLH>kGvqy z?Aj4rLXM%%sCTMNQ`HhRu2Lo(!m#EOXnui$l*ZSUtOZ~dO0MQ$iL*ub)H&}I!B_Q(8yqe{VK54#Utl1DhnoJE+V+^{xo-SZLDK= z0qSbR5vbU7X$vFsl*)3l8**so1kkVvEvSQO2bY~6`mKY@C~X}dTqZ^(IfXx8RIxOE zBh3Wq3X`S>m%*f!qvxDo8h?C=e48bfP43Yp)5VloyC!dWa9L^A=TT@|@<=d0H+S9 zukEd3b?}h;C|2B22eD$nk6yHh6?O{vx6VivtC-qhupZ{$aI1_?WHy0?L!d1~^#4W| zJ-7_gg;gP?2y{ud;NUVf81pk4jP!%c$U_FAE9KWcxNNU$%)w=s{6!@W2qc%lH8TJ2 zJGiWG?=*{XAhubP&?Olx#v!G`uA_~`u#zl79FPU%c(HSEa9JyX^1}TN)=-ne)9&E1 za~^k$$!{NAHU@RugUjwdPweuI{P_*L?C-M@0Z_=ESeA@`WIj{Q=1iOasw3=M5Y}iu z6V^aPQ4HnG?i~mhWLDM+!TON06)H-pK@7;J+l3;JFGJq|rHYM@Tom!-`Z@Sfl;r3i zMji(99F+k_^0^WR>1>Q<{YPAHf5>BG?z0-iU|rQ00?M90cv~L`Jqu<9o}xja4K1NPpvIy_j;+<4NONn1izkz5 ztNi7Jigy;G1Utcpr7WWOE+v|O5=UctJn>+vF8-_r6np&@;8~j{2&?MZ*>4d-*$Vw%K7q8n4}W9^#gg*k4J|PDpFht)Xv^;RjJK%iozC#Z zgdRdMvr4pSM*z-619J>J3JGPtba3QEF)w$YKd14f`!&iJP@b7nMm0ci5jWU3)?A_- z0u!S2ILORMf}6-6B19aSsA2*vR7zk4Eht$*8%H(A0zmRq2E1(Ci$TO4O5`UeEp8zX7nLvh8=y7 zfgwZ&P9SpbZS)uza+PR=B3nsrl#t#awI!#~UG%hU*_dVf%HR1zpwH8rsNzZdllmR|KhW<1 zQ@=u|HlS2G0890z(I*uk4la+|g*0 z32Xd4%~>Y-^dTj*Zs^yUwQn#~aK2{Vw#ih=0Y#`i)m>*{9DcDcnIlj5kqf637A#W zd97#{O3X451cQ9pg9AWo89}t+g%d&GeC!_Gq`zq*h|>5&Bs)8lt@xFQVXeI2fHf${ z5JcX-$F~|sB*z8($GWM(sigas*3JA`t&W^sbCejIE7{FtRZcfkPy-J@T6zpJhp7st z^8A`(R8GsH=8E$uosKZ7`80;2h%V?6`N#AMO#*u(cas-W95YO&U3{NfB|@9PBJ@pu z-<{3CN9!$i;3Gr4vDQm9OiAVlU%(POa+E@QnG8n2SzuPt&P_a`@pVv{nPB>SapA^8C}bT{MYl_1xh%rRn9~<2R?5 zD3>u7+HR=IECyZma*{k^Rfc^lq+AJ!V5N9rr1=1u_OS*lSp5oFM#Lt6jG}Z+tpD{g zaJV-l$BCEVe=a`+yamO_0U(e6DTgr0iiQhGaGhzD;H8N5ne)GA#60jZ@kI7@A~o03QT%=~T)&gRHuK zanT}wTjF)42?Ytx>+aghOwY-9QT(sDZ#o@jIkL1TcQ0T^6=kx7=xeh8{MPRK3gG^X zX$mej$1Oh$#%gKJWdt13ii7wHnseA+siHZ2=|LaZAD7bH$ zEP=^n&#`(}yUhpO57%E#R)`mbno8iE3MfI(C&VcvZb#3V_zoE;p$uSHfd8SvC>jDQ zb@L+RN_rt&DhVLQqwVANz5;F2ItT#qn_5{7=%zbqvw6Hlbx!}bMwudJrSdyyH+kaDiIL`WcmHF-TTF z06`8!wFDzT17Ev(=Xh1uc=5pZukAYUhii7lF}c`xw+J65{qtoI1Ked@Tsp%?jGWj< z|42fVBF{InaNr>O0j_)7?{9(95wcGUpnpp%(}c9Y2bxD zoFY-TF$$t^V5EWf^~fkxPx<;s2z;}68_u%{OW~e{Cyb+f#!+6coBNPyW`RWzIhkv6 zu)3=>-VF;Us=JQhmPFf?#poyv;#ez23YfQOJLUxhU_V9+{CmGjploIum!E0J8HQM8t-MWhTbjD zANy!>u51rRTa5yTT^~cTL%6FF9>WVSbnsll&Ngi9AZEkN_5sx#|Az|{t9-%%is?*Q z{G@!43Ousb=&y(?B6FdsxNYcK)O=T&*6feDu{~8@Daq!p$ar|_!9tY&Fbx-eLqG~W zuQ}(`^iJYanR_xir0Xi8ue{8<60;@Cfz3FGz`J(*IKQd8X>~Kx*CO)uNK< z|A_uVpXJwu7`#}CMnt7C-`MbWb=PS8BxnH^N0Q%FDiPGtPeey^zwJ#O<@^UeSH#Qn z;XQ_80m)n$c*iL6uVXa;M+Q3|!L^5wzBaT3Ef|U*UJQ-btM^noGe%Db-yr3yp+25D zoQGW-|I(e5rFoILrL>mF4g(j%S(>{DJfS0{90qm2V!K{wfBRf>o;>d^&yX&A!nhae z@+J%>s>$~I=kSp6NCRi6X^92qRw0OinWoCXJe%*mUYAS>VE%9{Ltz866cd=AH|{rp znc$j}l-|1cAQS<(bDINM6&GY?yW=N9?oWrXqqh_E7Xbj4nY|r}B@~2<^1*}nWhK%0 zuwt^IkU$iPa?zKQJ@mhyUhU54^k7+-n_~QS^8fj!gRv^E^mJ6=L5iW^o)|ALbX5Z} zrsjtHbBQq(*Gn${!hXVC43~J|>23##s_jM5f#m`?YIs`wF?l>@-H74j#gtBThgh)$ zV&ur#x3VS_T(ty>@^(V6KT#cP@q1^epvB)N!&{(VAh2Tb)oWu^BBPW@Dr<|sVyARS z`o9gu>dZKN^(ikMW ztPwNvS+Y-(;t1T}Aj4Hdcquq|ep-`Cq}gs6#6eLRtTc0nnfLhu^^25 zUP`dc2zfas8^yAr!ivDnOU7U~5m?3QX(`_puq9do4BR!$5Zs<_W)Dcw8GJNRga!vt z=GLrdptC6Kd`T@2CxPNTrA?%fohN1B*`n z^CtMJNGwHJF&m?4Hr`nPv%zCn9p{W>(tb$)a0Mw*zZ$$4M|I?Xs5#1-$&?c9NkwAZ z{wRLg%RTHu?MOk6M13te_gTT~!yZSa1qG3IDE4fdjkZs@< z6nLy@F`F5pE&k%|^%9IC^dpKFwfJ*Vo&z9T{JT;<@aBtX)3U@F>=`a=0|~b2sQ=@^ ze9%aU{airJo4mT5dHTX@ppO>!=L}y~m+Rs>Ue7~@oB~|9v z^^$c}z!U^FtK4a0!i2)C1XMHHCS?LMI_*1aMzvH7o$&b@azpmoWxl}4Y^-J^_L>M( za1>7@_ME&p5yKI~U`_1st}%Q7u8t58I1xcF_o_TKfEDCyWiXKlli+vy3FHJvg@;gO ziCWZxRWf(B|Lu2na0$3ezZUvh%Koz%1}Ta*nZR20?3-Jh0x(r#SR@i;e+2?qOb7%! z(5;oQ(m09v>ivzD1!}=a3+#$9U%W;_;uE}r_y^O204JXn7y4P|XvZi8lz5ei@G=E3 zX}d1Hi2QPFSCqsIFtGa{1%Q%ZV~J-tj(q;3z11_6u)-8!XyDNdj1ek@K}IGgFQ$m% zYHUOYm(%-$Lt-$oT;N{+vlk%nyP#ZB=ac&G4K46h*qb#TSL-*+h>!gZ9deuy#5 zkPws{MLRR)0qX3ZcBWpa1^p$p=t_9wt_-HyQtTSru_ZdgE?2W!%iNUe8qapBgL#K6 z@J=!gY4Z08wi_P|5@F5mGSXWFtcs22P<$!`0y3?VBQCH+r{_!NcZdVYgB1v57!2^o zbyhpM5eYA|{b7fh>%lPmauh2?eZzp7^g6gqnBBXh8g2i<5Nh&b(r?kr`WgUk*?WL6 z@E}WIGq4Zpn$@l%Rac&6$N_k;kjBa``j^|7t9`yE=Mm7<0RsLp-Ka^>*sfDCy9~T= z;cK+mAiZZlQ5VOQQ}jqe@{c$kslDU)5NMV&*o0G1K;$xUu%L0&^m}S`HBbr9zwy3A z>yfGbD5`xwz~MWaq6;?Rh>&$S&gHXc7Eb&aR1od^Az1|8QG{Z+lqgUgaBE?7fsd8b zddNe3LjJ%tk=RQ_4eU;;4#36YT$~7VzkK5T2z_5J^^V=-90$X7l(i$WmXuP4`(j-y z!&i2NqV->NCj@!^KMS;CBfs$7pfe}1yxq2CgJNiautZc0ZGd8PFF1?e%WeOgO|Roz z22%_pVW~pmzbT*ny`O{Lo+KfDQeVYCKSYnv!TPTffNulVB)cF&<$SN&ZGPir;4(C; zDm#kp?;dXkj7;61b@#>5NE01yy%o*cC?>Qo_JXl934-PL?_q(yatqa$P-^lyAR=vW z%bJJ>Cm-}yQtZ3VVM9|FLm-CrT{6OpfiJ3ub9)7H(3eKxh*>ic`N5%z-KO zhwrJ(K?^dDN<+^JDbA#D;Z;d=K?0J(%Mr4c0f-ie!oXM2IcSo3gz`i;dUa$3G<0h? zz$4z@E*FXpd_OYv1qu(h!p&i#FM54gDvS`*C!c-ac zcHD!6h~mDt$kYaw0&OY?co|+@aVbtJI+R;$#Gr^X@t?wO5|Rw+B7>EYA)KUH>TjYkLCVtzf!EQrzc#?DLFPQyu#u+0tH77 z8|qh#=aigu6{T_}wsQKXi64^kQp znBxLEp@CJ8C4C!H?es;Wnfle0Y@>p0;J;Ai{z-#dr7QwZ5C_l@#ZOfa46qEdKs`uV zWG)0R_IC9#2q^1+-c*efY7Bo(&qqTBnv*CrmjVfiHC2?bNX;9By#fJjrHtj{{8+~) z7Q-igSCirs1DLLWX{JF2&yv=^`b3;~c{ChhG};t6LMVD2hy;Mqu?cUwlFrS58THuP z0a7{saXG{>2}_XjLbLiMX@f9GTs;k-l>6?qq$k1_l_V^IC%TX#fF45`fPfo&I>=X*m@s%Ny+->iS1p_L5V$3lfV1Z5TU;CZUK{%{Phq{vo(p=U**L*lUH*& zDdY7#{(9yY&aec}0tnKK$!wbOyiGHZlC&2(E+7K>1bA)e(5&mCMNGz??63rkHX+Y7 z-H;o~E2Uia!e)eXs#DnOR(C6;E{(&Hm=|K>X3?h^jbI40g2Ow)SUOO&S8Sln@t^;i z!e?So?G}$?Ze(IefDo*N?toU3H3R{aF*smq4&}W{P$JJTxQ7UUMuAkKwKq9+JO@1Utt8(It{dw?Jp~$7*uQUk&1@lFg}+c=)GY zGD>&?K)w7Ij#FaZqys7P!dGspL5^l~>r_mxiD~h7=&FNwB8rn2Q!;fp(F^Y>RZ{S` zolK0ibzB+Xrc>HpBd?kk|!{SJo0L2(oQ0z@{-KZ47K`N#B1Ng)kJ`h15jX*-6#i?!}D z!cyOsFD3^38D3)}a_a->=oWV+rOW`!X}gKLypT0Y&B+0l>uikxw2h5I)|c>ii)lNm za|YVt{L2md8B&^&8f}>7bRO=QTy;Z-5(52|@dL~q(#Ev->$5Vn5D*rFAKj_;U<*{6 z`a;B8_d{+kB-WvUv?&uDQ0zEYyuP~zK887Sd} zE;!hz=>FB@I^jamR@ie7wm zii&!n>-!`!JNIL*K6NvDS>Diiuh}n*{ zxyc0fnuJh$nG-+&3AS zx({t>hRFXv(WU_i%U{!h5tcy@qZD`6WYfe z&W!)3iJ`}sH9cc-?L%RMv#N)Nn<6_5-G*_UCWB$>;?LCAo&f}y>@jXT_@V){ut z1TQhscP&nabhMzAL#4S;GDSmdl$gzk2T!=ABVo;iZ~ zH^wGj?z3Guf>{a~fP|MvVF3JNKi42i3@~1S*^oQQ08>OQUwoJ%3?@^PR7Gs_|u{C8?Oqe+XRc$@c~k}9Qzp*Lo+3kTr<=& z(r_s?S#kjlCIB-ml;7~7GxiDTq(@;6#$5zH$G_zo%>mD9g5AkB#D+uTA;D&W}1g&$WVaq`wOPUYuN<$YunFLVwC5+7@Vx zbBPZCS+YHDnXrx+nq1t{}z!TOV7q17#)I9j(3=`1~1&}+;&4A$rkQAMl~&; zQik~k8D5LTI%iqhYL;brOK=r%qBi-h!1)%9K(!C6_{mWG0-HQ4Cew6g$@T>syXj z0B6$Ugy$RoZr3+P8svT|R3^SIUJ|A3wh>V<%8o3d_a6o1I!C^SR(B1p?i&9bEdJFs zKz2<tm85&Mv^G{s0O}8hy7uqq=uKQ1%)YLo+4y>BP@`biM(nU5M(Ata&;#sjV zoklN|yOa_DR&Wu=0K(!W#~rbX7nYQjF_F)N|IDMhd8Cl41B0hnP+KyIjIQoH3r0hx ziSEV?SsFybs)t*^t4iZ(dsRh;uoY4uejP`aNpxZ{rY+ngCq%;5?w@S@oA0_hT)2DSK}!>fD;VajPSJ%FYIa-puIQ7;b{v$ z!ZP89zd8Jkhu3CnfHQ-J(XK(WtK?yZ0jst}8twI_nvHyN23Ejyi4c!6(wFeZ8Ybmk zpYcI~m=57-8N1Nb1h17zTg;9E7Uv7c7{88u&DJ0#r6FWkNhBnMoneLs*$YMNfhbJY zbcjWhplB%8bnJJx)>35y3BtV{{^`#g6YyY_9Or@%!~}!nX`6fIL#cQ1|)PewKU#Y?iRQYO_$=`GJ?Q?6?xmh zw<%W)(0Lz+Eii-`b=jCzryDDDx^buOVj3}pW9yTP2DZo)Hj($X7)a$0zX;~9&EMg3 zGX;7589D_?4cr0D)t}ysrgF4S023?Y23eH7=cK(WPZwtmy6M*FGa(U`PIw9tT zK;-OAFi;YOsPsscGnEfkyt#r4-DzZyQ9L!VD<(Ti{9!G2iwmj;w~XdO4#h}&p~6!! zYS09{Jo|}wjUS*kRiMg~??SOVzm<_UFZ9G2q$Y}4X%#2|qZqVv)5guslZE1LkIufoF_ zcnR+wn4Q%2&;Nhh{*Ck0 z?hA2T0N%S50K^DDO8b#1r_t2audW~s;DY!cEL@#%b$wRkMi~yEQTf8Yit!d&B40xB zg>%Fc5@nL`Laz_Ey1^XemVbKxRK-9kY8$2qLYGW;BH#U46dnz+tMDACmKY~^^C`qhF;qh z?foWwawX5^;`pH6D2H|!yjgJoPxAa1X)sV9bb&gG2DuiiW?yaE>(M!xoiJDor|b^( z^S@tVry!DSOD=5?+Zr&!U#yv7bhnt$q3TfLTmonW0|NCgSHJQWFfInF@+TD+!AI? zC#G$j#62Qd7F1315)4f&{F`mjM22vjG7FRBW%B?o_eG-;Q$g5QpmF|D@K;KTJTL-e z5BBgvC$2~t!U)XT1}wK;b)$dM->rJGUj7kF*3Gt7^0!@`{vKMy3tc{+i)6ZLXoLA$ zfC3YaUrFTIL_QP#h8b$c4HE(M7B~3VyM)p2ej_yNNztqneKPCWUtqlboAZO&l$_Xw z%p2GAnUYTK{i*}B47kJs+1?)u?aPc_ZrwlG_ZCibau5q@5svv=zoa%2vMVwezOsku zbytj3M<`#))4SYt8z2*qX6f$OF1JL0>~mR(@}EsPl7}C12t|pi1B^D@KMJ6AGz1gw z&l_XA%6M1H0)W&k@hW5%SZcfHix*N~h5FzII3MM&eqPIpn-OiwXJAyNk*CZTnGSZb z_$5}1+UX)taiRbE4O+g$n%JlU2E_rG4B-wNNDfHS0Y@IupZFuIT*E(eTbO!m^=?PD^qk22(ij+onCmr)E~Gsk3u zrl-VYpps|{EJq8WfJ2WW4#Ne=s00kf4BK$%EolR$QF6hUkc8)UdkE+#bRQ!F3jVHf zkbo9&;nvK4!*#X|3b5d+i^n!G@3DyXpaAx>^nFzNsd=*W9gZu_@be=L<@ zrwHr4Um2`M63y$8GX%_hCBMEhn=|rPz3Xp9z^0m*LgAAc4m8K3TV%wIID(4#i&Ef= zOqoiiw5Qp;6Rg*=G$YAGIgjYBa$AqYp?Xgg&<|+5|2SShrlb z44_1TOPQPYFv#r>ZUSdV+m4yRCkZbE#+(;$rLOl_LD-wj25ry$#?6>C6ky75nT%?d zalgpi?dpF1gPEW8a%+z5gR(mo_#cmOY;cJk*tGnGk@uw)62DpJY$%L;ST7$avR-(v zFg40rI{%@EzZ7H(iL5RGk<&_rAZDb<>vdTb$;=MB9j26yqwot=`RC*)X!$%%piszs z0Q4z`;R!62bcP56($XJd8diwT6QeDp4wjY2bfg%huH-{D3*(`Ra#A9ek}^_CU1aFu zT0o@dp%VV_eVe2-y~L)y(7wlzl2B4Fa7eYX{hRgy=tJ(*s?t)jKA4nsLv0x|5RmN; zO)JCpScYw(%z}SAW~i6Ev-Mg_1TPFo;cA%h@0;dYA|OD*@s9wJc&wa+Yfm(j6@n;H z)#kFo>0dm^NYc&6JCamv-L)$~_HqdJ*}!uZAoSgEAjNq%?Fo3QjjQy}f5-|D4SA^m zX~xCDrdo1xjlrajzj)T#jJb8#9(CDXMn=*Q^N;E2nv`^_lb&hQUg)B~B)vr~r6k+G z-Rw$CGFXf|=*jxPte!_F87z99?Vp=ghV79DYzt+M-qq>*_m+3b;WX|3r!siK&Hp8X zDf`7ZVc_@alD~YZ1e!z@-oak%9SCk2&AEwvDu`2|r;=fsZ~^BsJ~rbxs3 z9nciM6w8-lgpqk5p1dlQSJ;y*RpS_U^SqwV;C?3(lzEZPwrSk&FqqsMR8Zq!g{#v>0&Qgvl{G7{aWOi^;U~k6BcEGe87;@2zY_nS% ziLDmez&Y-Hj`pCzVUiYIROCb*go7P`eQ@X!x36&vBV=jbVvT{V1P0I_i9POAM2X%- zoLCXjE9b8l+FqoPj-}a{YewI@r4_3%#VWPfN5X6^MqX*~_|Rm|yP* zFO(M$Gz)4hufmIrA_4hK`1d!f@Cu_rT?#I@sTz4s43wcUt|W%A7Rkq$EC`6i>HGx_0vD=jHP0dwc%G@%u6WcT7wrx8MVq#|j*Jeus^bp1;M5vsNTJY` zf72s|Qgsa9q^w#px^%wr50FYEYBb_(!sv1hqfhvkgwcqoVrotiNkha+@D&6y=6CX9 zT4gMpVN7T9(W~7gp`cd03R{xRBs^?M4h;Cm8VBLCOGs zj5&5FX>V99?G39$&U;Nxl2ZJr_}YEbim_D|V~Z&E#Ri8JvLh1ZwQ9=>WK>o#;U}8j z+mx6rV@4|ywIZgMVOibU$c^7|IIZb)&`LMO4*YP!2}2`uyY?*ghGz{M_`!t1cq;9g zHEhA>*(0`Eg14Rdc3*kh8E}FF5&BL#G?e&}$iBVUxK4O>hNY)asj+ih%9eV zzoRB28o`@)rAKV0`XoA{B1*nkK@oXq(#1}?#7ReO+6$HTPm)QiBEIjLgUXV!$ZAO@ zRtdmwJv>>gm94=FX8ZS;Vo5TwRcZ=bM6o@Ob?}X_9IU8TZLKIWIb=d1pz~SuIg#mB8W7!;-~j zvo%5efwW?5mBrX1id}q$gF5`RpsrPCMt#f_7xlKpGu*7RZXsNGC)~EFempDEFp8>W3WG|scH6`X*B1fvFRy*V` z4t?@S378>mIKO7dk@hj#W2vI#deX_)I$h}s{f`~()2Aet*y{vQ(_K{bA`rOyd!xs%ix&n zD1$>mw)*wmA~$A%8l0#zi^_PS{-YwZ7fS6=~cK0!zj9y6DfLib5r2!IsN zQ4G-Ev59;p{L!YuC@TDw$jj8c_awtJ;M>aP@yGN`lLq2^lL7HP22fET06#_A3jix3 z;;aOScgcjf=E;osoNE>FssQoCAAznvf1V7AJS{&de(I!?Hs7gLKV@9~GQlWmc9-xO zs@%q3*oc;le(HdGtc?hbEwq-?Ew4H8VfBds0UAXVwB%S&ysaDMEQ{na^#EQg*C^F-N$kHs@ zl-egb=DATM69YC{?H)578tqJc;H$Lh%)V-utKqBeC2g>Rt&0q_ z7#dZg=15FM%b^KWsS0iJk7`xxr0bk?qfL9^?t3LE#7f2B`Zx7xPa#%I3b9HTRaVPq ziz=&z5?*z;gQ|7QT8Bjy8P)nQ;U6#wsLoxZsPagjXcKIBF!nbIqWk)h1j>x5#W}7I zJ5fuR<1(y>A;rW8tDv~=T#8}LBat!_E$QO$kcyrBSa2Grk=#TU-ekM*D#5_3ZTlSu&l9` z{svK7S(S|Xv8wtFSrP9J*q(^@4d@(cSSC>IQn#@v($I!9=dL*_YgQa{=K&YcL}DSS zb2v~pTYkW*d3eV^vW-VTnbo4E1ODNt7&ocVnrI!FRczcu^>am}DwYGM$)mJRnPRJyMGh>jU~5(mu}F3u z6sNJY;BY_?pPigOIb28I%Cl3jg2Jfl8G@PM=J&ZiVHDRVV42Wx83(3R8*SKfiAESe z_GbIf;rK$zG}~A;n;fp$B{CNr?O(I)vw$1J?fpMW>_b)Ow;uBC*hp-9zVUjkN>I2F zQ#@G|2sfvoAkvU4Ec*WNJzb?DOMkuajP;CuAe$7erf6O~{46ryN|ziQ%3MJ~uR}3> zfpZPNoW-H%+-LaHRF)sl^(1e3Ar=wtfjos)S`ip}x%uzcAUD>SBqnjxD!_2XK!vP! z)iUWO1Z@!g=Yx+oina8@Kd&Q%{C1E1mcTW9o2n15$r0pFj>NvSsqs~7Oc5M3yrTi3kejcsW|}&WIitv`$)0w8fo|*DU0=2l4eWeBMmF`fdwNC zujzvnZs6+B#2xsL(BfJK{y$g#rxscgm8C@CQR0@LIP@Ax+zXs!qkkex$4Qm3_ z21gn`3{WeLG%OBK8yRVMOdq-mo+oiIleHAvTAG4d&Z(KGxQ?s2SaF?DGa3n$1k!n? zByNZYJEZjafI-qk`kY9^m-+yt$3+_6(+40uA=0o^AEc&+`FKby<(L)#S@pR5|FHaj zzx@Aa{;zk~Fo8>EC1)aP6Gt)Oh}Qf$u4rM9v6Fv2mVcy+R@XGqk_AVB@fX8ygs!EX z{Qmfm+la_-pNx&9%kN8a;*9k$ZX?_`0524Z#C`?TgieD7USETi6=b>N!aDG5@DErg z=PVFJnvpO6U~A7Fy*Fw>NaO|U3RZVcv9++-5)Z;ju^h^bdd2Y&yU9D7$9f1-AlU^R zUj09Nh=2>xDtKSG;U2IZTonL&k%J?+q_wdOwb=^#nbXxccwgYC-taOb<0364s zhNU>(a)QjvpihO9u5{8>HVxae9_eWPLO5VTf%{GOqyxtCm`Agee93U0RTCCgOD?vt z89cLUK2JB#tRCcT^d0ir*$J(~k{9Mo$;*VlYP^ycICAYwMh6@-^BZRBq@4o>4kc*$ z?Oim8pfHrEN4$ll z=6xyPNzT?{^_2-|;1=Ktx)vaBC;zImbT^SuG@pztB>7gdB1ok#zh3qQ65uf$2T>gVmce5wZ_XN$mv|0WhbtZ|I_p4^z~FHYKP5rloG_LEF8`>> zDvX9V0JnwUsxY=i0%7EmA|n~#Uoj+sf8=F}la4y+GMmmIj7#&4Fy?OxHup%xYlaZf z6ssj7ZEOb5teVdP9-dh}L}Hh(GYBKWqj;#dP8G(ps{UtPhcs5A=~!M;8Y@*APy9~` zIw@Ric%vN`fBd)0#jhn6GhF~QvwBebu5TPh=L3!?!hV9+5u3pj?N<$wv?lJmRnHW zd?#J#q>F4i14p;*WjK1?#uU`SNmfl&WwoyAvT8mHocPY_LC%L)W#FjRky&-`ANT)? zqcGot0KpKEPGu;%W;CWZ{+xnUiUu!Q+K!np0lgk6Mq{6gVB`$26iTovM{vK7r>`ICc|X5XV}`$f#DW@0^QdO z{WF<~63Wv2>gAh$h~%JOqcJBW3I5C8!PB7+s70;(qiLvf(v42K#ila|(o5pZ5s>V* zA%)~h>U7mOBN1A`-7fJvT&%fu<0koDU$}i@RDJn)xdt=S{8BuV)wod z3%8R`I^guXhkHONUnusw1~3u1*7TT%av0Z3T=6e}h5_1|9{t;7U?_1O-pIizqxtE- zZDQxhv<0|#G_lkFQb|u#f;$P{Nnq$Y?{o}Zk3H}hn#98Vk6^mhz06-zI*+`pK#`T))iZ!sS-4`>J}vSX5xB<2~C%< zwW!-PMwdgK1u%AKz0loULEwLJ8mRULB9xQ?e_HVzL0LDk zw4>)xrDqxUutcLC{}XzmEgU$qBvQW{Gk9G~7$25LM~)(4=o!cRRd1Fy6%>@pJlItxAEZF@!D!O=pDXX#4>6bv z(x@darfh6z`f2ie6J;*#41!AXwhZ*1aEa1-H2F}y2yIVV z1njyl;=b^zVaQMlT9%Z?yS@fezJ^bwuj!2sLOjwK-~$it($H0t#$%>1HV4hffA)Djl&((cjC5LYBbragcKGCZDJUatwMyj`>Omp5recVOvr& z!~*rWq}iW25*y6^qGltt{wmaudd8tv)L+EPzVhpz*KnA zl%YqI0G62hxN`g}V;SI9>qoD z8j0Y%1pk@IieAT>_h12YXzUOJVZ~1v{^e81AWL-XaEahN&c75W=NGi%7ry6EaqQ)E z>;#b~HZV;P_-tG{KBZ#b@cjqqzc3H_tQNKR`CGm?ptOrJ`=N zU)AcD{1Ni?R}3Rt<-{++1c$jq0PbqXtQd||8JYzMjIDFN=OFIcE{3D;du)fXXTZmu zq>;y$A!NW3L10VU*iPU7s`_3|8;)R;|Diz)SVlKRCvVuqg#h)-NgyB##-n2F4DhP5 zxLv@L4d(I7(C$@uvF_UKquzw9XcIOQywdeUm>O)8$5E)ScINqSRBg&Cc$LGz1Eil+ zfb-wF>u9)0Ce+o49Ox>{9+?x*oj4CHc)KPy+62_V1cKM}fp8v|Y&3B&10?d_ku5D! z9z|EZiwnFa2+JT4J+Li@sMRknU*vCnvu;2Tgs>Y5*N7j*Dxx@?9Z-?nID)gM*#Zr% zj`C%We^RT{bw#D%h^-T${6BJ80N#v?{y;DoDipGbJSO~Qx4gP39(v>%M5rR|U{Hmb z>j#4{*RQxOPh0}pDQ1+K4YC6Sc~^bv_bP>m6gwu!@E@~i1ai^qa4;ZpKTLt)AL@e` z(9&?9b~!La%cT9lHzynwjSpBG9r)gaLy%Y#jbDzh;7D}fTN6;Q$3~n)Gyw;>bzLIc z;&BVY4Eoo?XdLy{FV0@%FKiJyW@ryJaaNE1ec-|gdq(5C;WV#m*8TE?TvYjew5jWI z;P-v9vKpx@T|U2s1Og@K{W$0uhkPu*!F;W0yqNDnCW75YsjO8sKNebs%xfzmzq zyEO<2k4vdR2q!BzGDDDF{`RBN_@9uovNK`u=2LF_+@9f|mZAI{D5dIbHQ5ih%WbB4 z{#6(18E`mMu{uKG6_!U66PQ1ER2+8VyG$?~oesl0N2cR&0jD4{mA}Muagb#Lw`3^4 zYe(h#rk5X?q5NA|?vSzl@0-)w-yuW!dX)DMI}Rr9-&lenUNGseV2N9GG2+2yF(O#O z^B-35*E7F}Vb;id1_8-K8er3N*G?f2bc)bL2D+X6$L@Jwm{3GrtfV|b!Nf6eew|xk zSr_-%Hh<3@-Eo}IF&?&NzL}@JqBwr=hfhqxiQmT+HT)E5xQCgV&Mu0^&xU&QSe*D3 zsC$ma1N9rbMZ8hlvc`?rmwPQ%=wXFRx50Jm$3z+i;ys>@&BEiAk%r#pu`?dA&S)$1 z*aeU0!7_z4b5}fK%}IZ*^?T*G64)i`a1MZkVWMY*Ec!cNq&5<-rT>66h0ND9L{8{x z_y_O&dZkUuf(kGIB*4HWSC5M}Es8E!*_E^bB6AArr20YKDBZP)`npNfS2heM+0~2$ z?2*BB8?YegdQ^y~6M)GEz&hSM0+S7w)$IN9kTP6KeKg_(r>#lTq6nIVkyu5CW)?}M z2bxMRjWq1(R9Y2j*v6@}x~AL9Lr%>7ImL4H{ zx0>N5dsR(|&3;bJ!8ZH3HTy6Ls&BYh>jT9%oTv4LkQ~eUMrI}UfyYLDp@`QLtKyF7 zzw{U^XC22kSA4CpUW+kF%jx?@0%CvE*iV3Cs zPbwy?`#cpB)_bXn3F|zcm0XyW;37g)f~9*i;R=;hk=VVkMK51R?aGpm*EQh6 zHVv;G8V}b#Dx}-!h)q`&o2pVX-g^v>36Rcv)5I!`$KRS1O56g2ih;m_O5CM2!aE%Y z>}@;>gK#;+>ep^6?Y#n*T$RR0)pDS-sx&?ZwLM^#Ou%~f#idpVKc&ZpMb1x8ru8f} zk&IZ+GGjdvt;kXx6aS!N(*j&H`a-yY$bm-J%N;LOFf3#+#42b6#NrnD6N=rafE`@5 zQp0QG;VWiwiD?b4tTHTEzaf`zgNMypx1G$~e(n7uK!rVM&j zYI?#6Zo~11O))aIRm7Wt@UVXyZ@TD$6u7lb#CrgyQ{Qz)3h$8beqg8XxUUQEx>rwP zZp`RzVmGu2r)vOrb~SEarM^+!5-fQq|G0CKF~eS#6fa-*Fuq~QT{`~KvF*@E+|aJU z0nfV)Ncg(w+-GLVrSirU0h(wRx(TXU`3ya>|X)71?l!lehs z!r05tLcb+XyRlXhu5Sf6@$f~DaD@NP>3D!lV5H+ZCNq%bHm*es`iHuo#fZalziUi- zFW>`(QI;};7wg`1VdMH{|M{~GX?_Dwp+{nC2#m|z#%tUP1=+)H&xkC%GpUXZ;>zw}Lfu zk-h6`w?aX7#BFKFo|4Yl;aDYp%S>WAimSw_=O9O#oWGQ^lI@Fabnes#Hn{TopzBg_ zB=3OZf8KCG5{CZk%-@6Kb_{8)lrV6{rP>=C4w7Ll)mVw9Z$+i>3o@=P(Nag+C_16C z(g|7w1qvk|hM-EK)h2GYi5qO9!6qgl5dg&g6abogqYIF9vbz2k01XuxG8$p3ezqm8 z>W4@Feq1jW)}>bc$D7is{^Ng9_03oz1L}22WZA@eEQpgg&)dY4Tq4&l!qg!AZkTK^ zjzRbZk%p=IBtbZW2Hu{BkH^BXuSZyLnt5apjLN@B@a?do|%USoZ!>&EPk=!;DEh2cYP1v#(NFdEEOo%@KMeA`0V$Q&wLZ_wXc3I z)6YBL^U^~3%r}V_xwMRjeR{o~l-HvXgw~q@y4r=8u7O2o`@sH`*nxrYX?kBr)!!A;W-S=OA zxBUb@i*xXwMWgZ1gt-$@Iz0A%>^*5Ru?1?|VI$X}aD0uO$v({M*~KadZuqtk1O*V7 zhG4=Ub2JyCr1o+sFA46Mkie2#t=@e9w=&mw+HYxcwEAtJnud}GG; zjP0yr?N-S8$jUX0uX^F_qyR@oKMT_-@3> z@@BN8B54fF7>DIolL+Hvh#(4N2Vyu#+-Xt_bL99ZD~8!1qCXrfB?2<{V17pokpX1B zpfwYj2MXkd%tJMcL*^gyMM{;-ee|K+b#Li*XE z&tFwae}g{Pd;@-|9!?AttyuQpv=hTKq&d=OXZN$E&)DGe&$0zYOQ(n-#^JU|40ZlZ z)%udZxbzgY9u9i4CfS--6#X4CevkCK(qWKszjpfYlPmbJFFVa}0l|1fCw~Ffas+_% z%Yk1e&PTiy(9b^F?Pn&V+Hwida}PC+oZWgD{!kh=T= z>PkHGf~Rlq6vHxGkkAY1Iq-BXOTSXb*Zjl2UdcCIieszzOuS^iLe0n5{ELV0mVC3L z(yXptV7{dXNqv0HKaTBGF-!c}Ry=ZarWTKsbEB0ptf*d%O5));cjzwZIjqtPhjtTVONzzA)8$*uc)WjM7kN(# zVg0whKM3z{?IrJ(P+bcmb0JB{gBe-)7g7s>B@1B_I(dlMIp=CVFMO&Lr?H(Sdr%ZY zTvCZ_B#T70Uic_!o!J_kY>Dv_csr|4yznu*5+3F}!_8TQobm9I>5A(##dVnEZB$%m z$+wzQfYb7w9bBjBd-O-bA1G~zYa(KrZcPIDoP1`}D`iuO;*$7E0@f6Cs-ywtoa^LV zbu+OhGzRO31FUa!vL(vcG>7yXW|6S%xcWNE$HSlAo`UJ2%00z&p?niezsqwleMH|A z(^r%-f@vQEzk}(_fXF||CJ%$@Mh5(;jJrV^Af~T7Inyw`Js`+~PBy_b9^O6`m;04F zipx*8$p9?5wx^5Br~00_9OU3~x`EKaWyb)QecYzmXK9Da!kw&Wb#ij1;nF3*f(>L3I&Mi&dO!s+NBbors&$w0bnIA zV8@u8j=HVvX)*2TaxB^`MtuQMtB?>dSRwGRrTndx8G$@w^ zm;22yy2G{e16-=zrmr+P9b9${a2f98OvB}r0GBJ3!V;(-RZ=Z; z5Iwy77xACZ+>+`)w?EVMpLs0%8_~nl2hoKZN?*@7kJ~CYBUA6*l41!)D7}>r^W>XY zg0FUTEJ3Tjr%ZjKd=ozGDq&@cOuZP8ZMAGRF@Sx~vA|SI5R(RI2^Kmz)A;act`)tz zoNUGtWT)b?K=K;6gUibZN@qvSSjLo0Q*z%Z;)_JO!8W0WKA8)90C-4le7rv$!1Ma!R6i@Hf3-* zS>F?vCsalSm$zi#I|Y}U19G?i;NbG0$?4#NHKYcY%blEQxJ(XEKEcUm`G@%Xub3i< zhn~CvSYhIH0-n%6+{ntIC6x@WnkEaULN}N^eKgNQ5dtt-JaA~d`SuwmUQzxkp~_@p zNq$Jg-ZZ%okMYoP$Qt!-D#8O>yq+ZjXEB+tQNa(t9Ei%h7Wg0hlgl!9U>VFgp)WB_ zf%5JwHWlp83YxCxV>Esp+rZIV)5Qf{FSTJ{Sg*I2X)7%MvXjtPk9k+brB2F3i?I?@ zh8VCsXNDe?frXLi2b<9Xj+`*61{X)Y&jDIl)QACQUZ>!f4cE$qWbsA?hr0nVW|1## zf}Sk|OX|Rbz$le?;XjYn3U&4!7$KXiU6iGJSYVDf=(J!O9k4cHRidA>5Axvr{*8uE zv(3%I+41mK&7@X9s1g)m$L(K4v*|iM287~L&@?Kc=ZaM<#1zmW!%eLM4?1*jYln^p z#WjqOdZg!Eiu}@tMt+nuEywTFrk)h6@R+))6)rADk*r5al$8}t15=_+6Z*`0X zWOZnj=q_C;A!cK%pe7d}C-)xUL_S=-)hzuG8C~EKI`Rp0&-R}>o2Zpy@dn=IBybNV z2Ku)Gh}iKpET#?+t{3o-JE}uc-0;bCv{HhVRPQ;=9I`5vWFRyabghdSb%QVs1^B6 zk_KUbW@-d z*kBwC20ABFp#!rLOy(a)M}197dW}t^GqZx~P#=LXxP|1lOxR^5vD?u0a~OqRIz2pjEgm{Zpbjv8fHk$} zCr${p{M=0dGMcz97GT`Z;pZ*JtUCM*2N)mi0(hax>6q&0Ll)zmot$YH{}QnM2ZU)B zVv8}l1Zrna5eNh9ZXopSvFoo`(25=_jT`KCPGZ+n=&SsETDsvW(z-4H<~$dexXI~Y z_f=Pm-QiBoH0-_(h_IuR&0?2lvAd$4^bfFGk_o$!l1Fs0$i?n(eNSn{CLsC_(Z%x3~ zm)4-uO$Jt&hNcq^jBQt-w-gv$gd-%dMgC{_IUZISnVVDhGuH5L0yvSmWm$DUV+H>Y z`p~)VXRPA+N*}t^{frgywD*y@C0z$$>As9Ugl?Ox44#HBVAMLHujvy_lyAb=3%Upc z)yR&~_hjr;RaRl_f21Ft!r01y50A-}(}uC{nw$<}yGaAYJ?7+0W9(^3{yW)(vGLHW zbt$;)>EiO3d=p%5>FnTgo4zM5PpR+zr)L+VFSRq~Ovbc?~Y_$Tz_y$HnD&eNSBS9b67E5Vlg{n*_qF0GIA= z(>>C0d3@7x2A5AhPhy>h%bEb?xlXpg{zMv@FcTc8f6`ruiOKB@z@y$BVq)IL;(D4G z^gGp_+$5%k7K3{X{qu29eLG8$ZdzgeW{oHKrqwc7{$86o4Y|1Zdq=Tp% z@$@_Z!av5=ZIU8j$(0JqD!VB=^zaRgn{)5Hig7asTF?@(JbIcNH`^mhSvPZN+zdvb z6}yse`mRpg{Dtl92C_l^9`l*Xr8+h>xK?@+i)lbCLLGQLG+oucXW1w)wd+~7WCJwm zSY6`i0VBEY&A?j|G91s2rcE~5N!6#0ICra-y#iaHB)mHepn{yi(E8k5KqY3_8 zA)k#l;^D6Po)|SLk;DZ5AYIB7KrWKc#H`G%eu>G+>WqP_3uv&HlM`l3w7p}d)n1vx zvWFD? z1gyBrtv&zC%*m-?glKpBu#w|qRWu!lGn4Cm^8A}WBGrt8KJ-&ONN>Aiwokqy zh3ylSM=GA@nQw;eyC<=Yhlj~GVf)ML9k%z!`&737O+O3UAN(X>`%HOFwqNt1L;HH> zNM-x^LC%w%oM~*oHelv{PPR;JzjcGv)h=#MWqZ}-0ozZJe1`4i`krk6Rf*IQ+dmDM z`M?JbW*ON2V}RL2C#UFYHZ};-n1)u?03P%{_Qw+($>4Q>9rPhNjXRCZ9bAdcVzDW- zDWTbtUtDf4souEa>H3~7_a(tAaJe}jtIV{D5ka)!h3=OebdsO1APU-^x?I&C$u^(B z(8Kx9x!G=xhxSQAu}(4>D7M%4pknBrBov7nF{mm1iMjxUvz)pU$D5oE6t@LX3~+L) z@~FudV7vchfeky^5--w(%DnrHX2gV~O?7Cat5cNZOli=_MTz-llq5^QHV&;ozKN3D z@o%&PgRne^|L5R-G_maTqUomB&Wach|*cik*XvEgPaFAIn$J6OdxUDPPR-+ zQY++Q)1SWQG_6W<{DeSBrb|9UjDz$&m83*k(mq87ht@j)HkZpqXX>iLmWtOMQRvyGLL_8W1yWQ zvG1uKHlPY3L<}5MCC6psC!;2u_0koGRv_$~uXiz@))uXQWerz*uHkCWHU7s3auMz& z5Qv!MV6`@mEE2^wr;Z1<-JCv-k$+kpT7Li-(<8^@p#d=&tnG7I>R|22Wp2>97vc9z zgFsn>PMM-((8+|q=XTDDl=bgZ$~vSQJP)KJIcRddj~e3PqRS}TI%t9(X{ijFT(?Gu zCq4_x2+>s@P`qx$q*lgmO^`e3;IjSY>AC-phD$D}Qp0P8OIp`bfsGkEUcQNu&HF*# z>u||I`kv;kNEA}X!5)?{EycWTC!c9LuYD(JVH4MyoQ~ak=6g24oToTB)x0@Yu#>>Y zZ2LRev`-zn>(UflURRh|Iv%=Kz6mZvr76=#yFlL)m(f28jugGbC#GM~N{%*(Wj#VZ zv+1Yac5r#h_z%wW!6mN`wUg}?BUz{1a! ze1;e&>U&!Fv!taCE&NddAb)nN&tTzC2>_Yk2VPZ-!}O zl%bU1c-WI~!nCcwb(mIz_o+aIZ~PSNRV^7lQWHJ zivkK<=48vnv=0O#Hhr9%Q<*mB;(%#)DCA0v8Ty_~8?4L}RnFj+{}2G;zv*C>foa77 zATK&ORh55Nm*ulJNj1}Di7m&2+}bBr9mmt#>4_B=0XM|KW(qrt&4botO<7;lJ`Rre=(@QN(l%q6Ge>-FhSvuEu!x?q&j^W%XR3UQM695lBo?0e(KsG zE)_uELMOCh7pBnkL88>2rWKM$Xqvmqp=ng#lcxKLC=4Wcxxnn48j5o5M9vXdKd5WKC24@tk& zbdSC^c*B)O^fJMi+%&y81dFb+DV2d2nx;2~AYRK8X>B(5QG_Nidrn>37w4{GOYs@3D;a4M?7f==XayX}ib=92-qJKVGhsu3w$c9zh;^ z1hU+z5Jy&&U}A41b_#WmzOn#;Gk`9OF8HF$R?GXpUBBVl%lE=;V0NVbC@`q$wffJm ztzTN#*qpPH88ewJhV$D|IXILlVSu z$DchRlFxhLnFg{jQG!7O|DQ+l><+(5e=gLY12=$EXF_3gqn`OcgbldLXB|CHPGRB?oIrWC3kWT5s)t?E}NFIYm9(QQrUlU9q7-KNRz}sDuo`ADV+TVj79$+ zb6)};MU{n{Kw1Ms+fj)Ig|X47!8K7BgMxGZ(pcU}oO;UcL{iy6$%NbM8(U zAx->GU{pjdNH;U*UkOJBdFAbt24oKCK-LOy8rqXcF|3Pm^jWC3MnJ)}3@8ngUss7^ zg-Rku?7li(tQ>v!s*Yq7&IjU&@!+5V{{SjrFRPp|WjDM`@5ZB&V~RwmK$FPeo30&i zS!Defus&=zE@h!awOrE38Jy_b6j8{ETuP~$6X<2WPZISSR?OHTA$}|+`Hrn1+B%QW zCef=*(F;(I1SdhSQUYA=8R7s7ybyIlwGP0HbIQSU_`I7>cqPy82*yDS;zfJ3gSmZ=u%MROMX_ zTJjQ+N1Pu#+u2B52+@?v54}(0LFCZ_L_xmy8!UEY`>$X^R52kze+yogT~W2)H4`+Q zuqhojk^5a!__XvBnvo&jwOd9=lqJ8XsHMPG=C;KSnY(QoNitIeEoYx7PBXBt?(d~E zsEjGN+Kbqz6?pivJQM*V%id6#AimBdz3d*1*Xh1h_PF4PEx<)gx#nuX* za@k2BlV&aXn_&-q@m&E9Mn+Cr;!$!~pskP^44C?7n1Ml;smS@agUDMP0qwMrubI4FeHc+uUNnepCbGAZu zfkw7ZcGFst8r;xRU%l%?)&<;FYz5|=bg~kXGhX)yiTHQqR`s0=Sgp`5cZdIn9r&NsSr2M;1AdyJ=%GCcNH+3fzH5$SUi!A3?P}5LQB$O3@3Kp1_{Rw zZGZWlVI6Q|USgHrC2;p#55NjzU5$AzSTs# zA|*hCf+UtVnDvHQ*sl=5A+9+8IZJ66pf6_g?r8#{KQEeme)jlKjchjoXB94kv&>$j zFQJ@`&EP%;TUgK^&df0y6@V2r>HIp7G}`n!R~=NgL4dX6tJF~f=?up5`Q4V-ZYAE zHURPo-|0xu`1!gH`vqN0z|0bbVs;dt!KW2C&eNL0fUQ+FD>hRXo282V z@`3}T#!x(1-)2D4pt99EKFz>4*TWcF!H-IP{Ze%rfEY>9m^6|JsuSjmZSPi>JJjJv zXf8y|k(GEz`lHYm_MD`U)$4~|Ufq)lUO#|G&QQ%+nz6qRy65Lqc5~T|4jv749dh6({<8SVdd886#gCL)6I%W3E8bc~tEVMutqMA| z#@Fd}&mvhZn1?4vc`HgMc-MDU<{^hphTr4SwdnVBc4G>R$G4oB42=~EV+DuSz3Abu*LhHFRi51%lZ zfx)PMDE^62vVxu2q?P$D(i@jbW{MD7v5WjUzh8$eHNq6^bH)$hjeV3q*AgVe`{~%g z!FK$GK5V7SYX#qsIyAN;B#VRXbv|q(DotbC9pIiR=qPNhUWy`NoGbMNw?c)srzPN6Zzd_EGouMf@4Oj_r2qB^oYJP!+*;`^Nw*sEgAOTwY`^G&@IE5 z42N#+#L!K84SLOA(&}4*Z{I&w0q!UnB_o5{CL+QY`<9c*3)p-!IPg3Ogk#OD;SrjO z+gVfWELgd-;B1{mk{$Ct&D+XIY$of1Q_GcXbF!=XyZ7Rdbqqh4y?LQf1HKiT1JjGm zP?0*s8XpGa)eS&Lv4ate+Q_X(obcH3@;Q)fD-_}7Sl@-%7}rCAiFP&)esm6%P@s}Dr1P^WM~Hjz$O6R0ZcogE0{W!Ss_c@&`r{?w^0yr%bp?)D(f0x%w^kXfPl$?|B8Z=uHZ9TES_ZPCz1tGamIOZXm47@E;!$aff(j z=-*lL1WM_wBZh6%j}N8gMmNJMMa$Dg)=1zq5uqu1a>78)O5|k9GKB1;ihvR05!t*N z3if9hx}*rHKcETFA+=dlDuJCe>q?k(3YQBO>=Z&lw-a0h)eQoc+d1rZu#Tu9R~wi` zPUN1Zvax$2+0Vro-^W7$9IRD{z{R=@*ENfHZu=b>;cbH>)9BiT z702B1z0HsEI$FxY3;_r95jx$+c!Bmn^?nnB2%wYXWWSnA_8hrJFRfHXh|LNKb$E;# z36d{JXaXg=8fgb52vaIqrev4MGbYWsq~?rX=Sp0frQxs&QsaGfjI%*t2Jec1>$GfD z&vac6dUWovCi}%rt7WXZrmm`8<155M+CjBaORNA4FUYC^ema6R<#=?S^so8^R-o`7 z+JmrOdr~iLMHy3eIftTEl}j*HeSiwYB*Cn~sCv4(YmS$8IEL$biHMaaRb^<~hR(t; zznneBZ}Dr~xQ1<>f<%YS@%0>uV>E#_l_=BKhP+vhlq`@OWD)h0Ufiaa6SWXBTIcxZ z0u5>t&%8piXbU?}Vp&y-5)U@?tgc1Lk1}MejnL5Rw5b@WxQJ{Qi&p}mqZE%rHEtv9lPI3(W9g_2e1!bB4yNQSo~Hwhm#axnD)9i zsd1C?xq>@HmGn(e=A9#yRRr6stA!fD)T?FuZ_8DDjG)Po5Qk9@IH);fY>fL$ba zcBi&HQsi!OMka7%WT==E1H4%Sk>_jrRD*cgidOI5w}QZ3xM-Me=RgVm{*6 zi5Aw!&k(~Cc=SrLF*uzMIO=kh6|*kR%NTiqk*&sy43qHbHef&UIVk#?8eMNTAM_~A z;Dk-8=tuyJDGvM>czc;PKW6Z$3(zttLI#S$;RnPmacfAH{imx}${Dvg7)h>OOhW{l zr}E0AiykvW!7>CM4vZsa+-z5lvsfw4?BZY@{tzm(OVU$;FyFO3h zChP&Yq3>_KL8uq9RI25LNUes#Hq9_VhUuOTd$jdttoTeGaP%lVfFe{B&{bTtyh_V zhiI6?|79|sZcjPULmx03(OZ`R3_?rO8NuB}5X7{_5S5A)ppjD0y8la#dIU10UM;~T zWJZSFGf}U)_tl6oY<;s(WEmGpI=g!y%bJw#^{7f@6#Xb-=`$hD>r{B4RV3a1Ynpmu?g%rn3?7M$*_kR6p?2)vkZs=Zr;alp}80H%F3EI0e~4eLo(k- z>av#?BY0L|z}o|Xh+ZZ(dJa3#TFJ%G)@PQ=#=T%^F~S2J+B0$*cS3=qQti(Y_uxDPunsa~&WL+sRH zGYZN@@|jSUKLeB2Ufim{->}HRZ3t2nZqI7m-f{6h#YvL|1!mx>f>z;wLIJ4Yzn%H4 z`#kWMOM4prOH{Jv4&m?afuHMVG$b8e_-8&1`1>bPvRwG@L5d&#&My47IB9x81cP@G zI!2fmNTMsLOo&%P!tIeCLDmmV7~CXzpTG`W^YvEP<1>t#Ru_nbiP9I9u(^C9y?hu@N_HvyMap|8WceGH-xHsLlpK*rc|__H`A3R^-;wekUEGSDG$kc~90pr; zi<8+WN4(VupZ;=Yt62V3p`oz6k@;LcQI|(9^k6wuC3|$?XhkEz^1Ot^AK=n^`jf!2 zcOs>$)JH5QBE^qomP>&@IcZv#*Y<4{{`0)>zr=h#_&2@ff&X5W?1BFyC58h31JEL^ z%Wt{#{tUNL$8SrdOqcoy|01OL;a~3J_Nt{z7 z{^dyVbN(_{DqeKb_DMgtp57{!=XtSwkNJF9E?D4^@0V4w2g{EXmjz3Ye!k_>``?fG z^>d`uM=otdiXY46E(Ml4X<9%3&^r8|DgYIi4rm7di1{A)f9fshdEmcPVK4A|^z&?& z-hBwaM?X7BeT4r=2gXLnik7&z?dPN^{XF))7W5PSmF;RVTR%F{37b^^_{HpMm{bG( z6?q~UmVS&rW?}}@JT4US4!X6?HQS#j#-X8hnJL>{xoO#YO>S^A2nVG9)pG!fiRk%lJglb8q%!)v&T zQZ;nN-Bw9ix&6cp{82!1BfsYuDOiCU6uT5RBPxsXiJ{snRhCcQ@Nl%7%AzlB1KV6QL$x-ieq)b=!E=S5_sCOJGQ~8EB;$7-W@rXyLg^G*u_Y;1!avrHn zIX~T-$nxeGfE;RqkfRE}Jjy<{a+>Zy*L=HLXT(V-MuHcmt6!Rv-Ff4$f!aYnW_fwFt906)0p z*2fKRd;+nbrR?850l+(9Qv>Udy{MMW!Tv3m_MGE1X;l&n0fECbz21vVGP_MX?KaTA zSFJqyj^+bv5y6T|(i+3L_LV&vgr>P1m{Hp=U|iRs5zWJKYJ#i;)eQrV)AeKur?2pX z){zw*$Gv0NkQ;yy41V0KV$*}v9!UQSXOp+ir&Jc5uC7ucqh1ctHZ^1 z7oe1eFn$HU0{;zC6$Zupv~bpWl2^EQ<`1Mr=FRfxb~_&sWf9A;(86e{BTIAb-KQv; zMEJ9ue9h;m$xOBa0xRMS@4(TBze97>VuKMhSI$yot*=~Za0zuwtu&a23X08wjACF< zn^kNU$wkySXZ6$2y^jhKs${V_EaM!|8~0cPz;U>{j{?V~23f_B!2&fQ8uo}Bh&zK7 zq^^U_t~!oW_;vhk4Tb2A18mmiGS5Zejo4BOdwKk9p{m0QXU=L`i>%NflA_WNa5$YxXE1 z?o2P{4Jb+c;~YY|^A0y5Dx)RJh^@-ong@$eNweng3rmPuuJ_WA^)?C?o2ldx{jI|z z+$4T37%(ln8XvKoVtD!h@V|DD@rZ3GRS2npqI8;#fAAwT6TUQtrA1KT;>|R1 z)9NO3rI6ZdNkQ2gp|M{~mn|4oi($S?Fh7~(Kc7dN@Si#KpJDpXFcHXA7Bo~7MKTvb z8!6-y zpT8-54B`_ZKBOOo7u!`=RE>xKt{4*y%SB?k@-6^Zupg(JTycHh@I-b^r}ON_-v6LuoN`#8VtFY191dy_6gN%(wC zu%estiBB%^$t6CZA6J@y0q_GtR^E;x)BibyH_WzRJADw%|EsfX3OO*;k~wH115{t0 zkFQXYiwclORy9KBGVKf(TXFzCms|k5)M>v~eKj7958bXQmnkY;Qeu~AG)Uvw>o)s8W*h9d#4~#0R zLv(Zxby-9vsm$OXddM_fZ*(ZHf0p(reW?mvv9Tw(q9ePQPHb4CB2`n1 z3nw#S;kmh|LRR!KHj6OA%doT7sOq5=6jHKIScXeSf8&xp_JzQuEU}2IGP%0fHBZ*L zaCIv~QJc#Q>%U3^VbeDwJ$*YU@x;tyQJm3nFuRvCwJW_i)R|>B^mD};Is@ntgw))` zicHK-Bnz?wmfhtC2V5P^66_38yqX*YXMuxkE!C6N{FPx3o8c4_EUnBdO37#{8g&*J zXV`CzP!MTKKxU`1N@hZ}rOI66txT$9L8vomW>>xNn@~k|8Ptw#k3vp2&kAgm3t!j> zsHptP+pnp9p3{)-rOcDo*wu4DVnbQ>g>rBPBNI{q)CUi>p^5M;v`a+V=<=t?OW>) z{-k&;3?hE$Dx}BvW2o#j1MWcnv`j<($nqJp_X)>5v=T2y5TtPwG80Gs?TO_3n%_S3 zw^i7S1z+*|Gqtby=eSmVMaQFDU(s(yvafh7ZLfVrJ1I*Hq2bmSFU6$p?Xxyh|=TO0*YB1wi zLMlJFb$aOgN@v6LplbA2baIO9JrvJCmfOeHsmK*NTO+#_x#M?=iWgA3YKb;@x^78a z{v6#>C0eR|!L<&$9M>pEG6`ypu7I|sHBiM^*gs8Cwd4|xYDx`kO%6fHq1l7Y0VaB! z3$T>P$5Rb+EVgi{J2Q)VZx2NmVRQH(v!`s2K)2iY=!a4&3p-faHAelVYIG^ld&dV*^`Cjjg&XgDC&8_^9%P)Njda^k(_Y;ISVV+=);Uz$iEjWQBHS)5 zCHgApt)${D(EEL{4PJ(QM46IT-iuJ7FSeO|vCa0~8xz7*E+N5`>@q&7*J6#a)N-s> z5@d7cp`WfvL_0M@WjFU;3Bwl%!u85~90xW^I;`G;t;)j%cPV+$?1UylM;N-%Es3)@ z)y)C6ET{NMoB-XOD)f>PI4qGr{3V}X>B?FJM5Vkz=F?Gy(7_p}Vzn#`m28k2wTdRF z+2^YSHB&S-w@Z5oYBuG2smVs{73&o>!xX4osaji|hX{g|`H-nM&WzWKF@bW8J`PUl zo|IC$=d5vM02jhqWlD@fnpv?taVc^^9A;@?~|lUZ7FAi@xRjuwFP#Y>5hVn z=xvASX)9MHJK~iZIU1za0>t0vCL1g8>2QiAhEAWl#S=o-Q3S2vTcBqrU^r)5u(J|$!-xs9#|}1oRU;=(y-2U!S~V2stYH!PifNowG9E z+>wBx@m}JIv`3jnYh~Za%#eM-$O=wGLi{Ysk#?U1znXX=?g?fU{ot4H#y?ku))KKvBL}sizM2k`hU#L zeNcB*DAC=UDTLHZ-g`HMtVX$+6EPKbOwN-wvH6o5jU}UORUU&^#<-*_R}&QLfR7VS z2!2(-SB$s`m5ifru7q?zrgH4x{aMLWE-^}x8aZ+c-JL8=$r@C|_>$r=0$`kSAz+;S ztgVoQouI{_xOYZJ)G?cmdzj0yBS1&3?_;l)>zzC%G*nw9gG+v&a;SXMol-5KPyXud z`XfV%-TzAuoz*bUn__?cwOuaXoa3hM%O_eO3s^W!yAFqYkWx}ryp_ng{vozd*Z}(B zJhe{5)8j30^RCA;I_P$^H_E+EK6LNb8HLiApJUJ}!D^qR8lb5S2T>{M%Q%vQkPi1F zf6)x(uZ2y1lxyXii*iKpXbokN09r|+EKJ7_L0JJwl(+v*p`1@{W4H#~PW7~#K>4R{ z6o9Ui4Am<6O?XrLQ6Wp>17+h(`?chfRaZK~l&F4cvrMq&)3QZ>tU&;JTJ{FYuys~y z{82H2ZFs*n-AG&I_txR9m8+#Zvfy!e=W^KPzl8**Kyi{mrPf{%9x<`oEY|^sYHwtF zFc;)+{I36rw^bS*wtw2F_zzYnv*1DVR$)k61Z#`nPB>P(hnD0vzVqZZR&~kYtdm zx)UA2K(>1)1sFH)l`ig?p$u_Ur(|!?m@b`lk2^uo!j+3{TLk(oID27>oq4yb;Z=u8 zw@9e0SI!_n921{R+??TED{!5jO7i%Zy6I|sH%#@_K@O;u=m*dnN$(U5XW8ejSHwk5 zaSM#M9^WehI`(4W7pjJq?8Qj2Ol^?5Ewc$zs3K1g3z#UGc7wYOlU<@A@~qMuyloLh zB^dD~+-JV$S|0J$a&k+xRLX93C@04;7`?#1|0&LphJwujJqc-Yu^fYw$)G=MiZD=( z9mZE-3%H&4t&DObO-6K|r@;@^oT~GwL0Rf9hW;4zDB*z5v6q*)mP7LunyFW@A&4zw z4WMMHJOO3Gas2)bmJIBF3?>V~Wbi3gE#%4k_tE^Mwb9W~tXOdma>(HbKf8nc<2!rD z@}4}x2ZWTq(0Vz60pn@>P%w$(tkHmq1x#!v4cqZB8gL>qM1m_Y8alDf&M3%~Aena< zT1Kyqp64MMs70!AW&F$4VU3}JNMoqD zC_M?ya)6d&UnldXiA9LgmL^p^oBG!(YES_Y9a?gGHk8ll70ZckWI}xQcdWq6ktx~$ z(AF@t5ZR*KQlaFB1dNH%|FC@#VslolEdy}P$I%{%M$Ta)u7{r1;=qZ0(Bqge`5b)) z--O9khVOiXft1;n*MF!^$B0jekC2!0%YiK3V$4qw$Njx3AG|#dFx5~BgtrpDiTf|* zTb8{}kG6n|)F*T_%cMSvi9KI87~wA!+^*Ax(hVVS>@Zka#@fmgtAS_;$^Z(qrBI(+ z;9KO=EWd7`qkU^~13XC@2*!^QPtrnDEi`XGIUNL_4gvBKJV9>@^C67k+$Gw5k!Yh{EK z6_;a}G#IKKD_?ado!#UNJAT`TOm^ zGSBCOQuTnOf^jlUQ1dZC<{ct6#p(?QT~8#HKm>&jX8o^}4@N!~TVO%h4qS;_fG@H* z=$cUNG4jp@Lbrr!JE|Y;s(0KJs{Il18icof^^U4g?FaG$w{2I1YG23uys^OejXUt) z<0`lunbFjphOIKT#S7p&a3Vh(~NIBTUuQ&79~TIpo4Oa{t} zWwsvyFE36?OKG#oyexZxzM3Rg>n8fD6Qzhkk4@NFLW0BxnyQP0I47-D*1{!DmAElE zW|XzSjpcxy{NqHGi2H;k)B>y^fEKYRIq9^?PXz1N=1>HeQPV6i-@-_wABkV=>pA(b!-A!VHwM9H2z)-g^X zA(q6cMRdY;yf5bq{z$w!d8%(1zwNdO4ENx*#L9>HVlRJ2ot%?T zhGAT;4MExq_}9MZgWqEV68d7F3j=AG5^OMrk@3<4Kt4*a;v^!;RwS`40#*%F06@uE zH#Oa`c-u{k^9j zj_v=9doc4(KOU;xPI0n=W#=IkHQ3)>3_CmT)oE*wv43|Gj%VW{#BFf{D^lur^fT&r z9%l4d$*-XEfyT8Tq^x}845LRwtN=3*3-p-q9Ob1Flc}j#@y>M)Se)~`h_4mMU9F}{ zM5gT7i~KUDLquh>IP&i>Li%406No|BfP$nDBmBs*V?4|haw#S}zb&@xjXHmKtB;OQ z;RaBQe^l*t>J_c4?^Hm3gE~(e!UaOG6HwapZ29KoX<3znPbyW`?x!tPURKApClvSh&Y&2I`@A>?kks=LKe4$a9H+q#Q)9Uxz028L z#p~@l+Gn4dIE1MtT?9mYnVw>(+l^4P!{{TaE8^~)cn+db>IB&FFMp-pwdNdYk?qHI zCsxA(@@*#A_#-K4hWJN0<9Cvj-$2U1KU?&Rfhi3f1#zee*+XV$LXL(3ddEQQO@T}XghXoqwO}R z0%p-^@{f#bJ*IVH(m5?g0``sfpv$-(D~8=JW1_z(=RN&}5o>hQ816Tz;2Nh2N?0}9 zg;{0y_(=PWmCD|`k!7fM0E%&7oI(s)oyz>!pn@H!>UveRN2O!vuEQZR)w?=`YG@U! zcXh;ib-Y-kHbkm-Uml7IfiWH{4Vrgm80L8FdOJI7GJFuHO`ATZoy2Eq76PCPL|zP> zW18IdxSHmGr)a=+c@X^}K};|BL+8B$+kD2LYtUK>;JApQU50WZkOw(4C+R$f%SYXru5zhsD;fEWZB3#i9q(`MlE9fUeqCXdW3_<#s{c5%vCwIVYb z;$>1GvV}TF@CxUa6C8`bPNPQP!52%=yN~$-;%+zYr1`o(`j)vLIkZN41 z1;S@LRUIu=WgfzZhnO6J!-@~t!|4*>c!}km^=DY|B`k7;(w==cboU&D(5~+CC856- zIxXafjQ5<0wJjL$se^KH3;H}hG2SCjDD-mtc18|PWVgcW84y*_3;3@yIexCQHV^BA zrB>}TpziDRZ}A=Yy+Qw$5D~wXgVS>xy;p}UxqHoWoDKrux#ep62LfDf{en<{#q5J{ z?)qaH@}X~tld|y zoX%yN($6k(>u3S;DQD9&fmk+BT*^x zQ`ILG&T`(Z;9~~u3Ou1D8;}6J{kLq7Wq@Ql69YOBumVM&JH8wH$E1BR9GG|~z=Au> zL>5xe8k{y?>|g)l354@ygsh()AuB~N(mquCm2@ptm7%%kcEH_}`!NMmbO4a9A#6Xs zggnrZtXgMsw-lpeh;B~}-6aP|B1ehwJbH*JxCxA4Kz3CC0zUrjPmU}k!~p8AFmXGD zln|hjWnZr+c34lI{bo< z?fCIHer$)28AgXMaCT>VqxYIonV1_(ZI4Syvy2W~Z|#JKe)K(1~{9KwPQ=S=X6i@rifAWY_Ju$@RJrrKJ%kxYEh0F#W_rB$J{EdK)3~8 zIdrPeSH3LHB4JS|<74fA)GHa+vV;gnWX(Jbw@nza!_?tQ9=Twt6uakjN;sTSGHZzS zT^uRJ5*-{!@d%&`)l4CbCe{|hCQQaV|M65!#!~b4C{xV*(E?yzwxaxS5=o_T{X=?F4U}F@;Kf*af-q=*2{%LGEh#_#XoJ$j6 zhwR29{ESQrwXDG1>sm(V;3eJ(Sk?8It|PdX*;##$51kFN`UBgws6(yUWEg#6XH1#2 z)9qCYlT4bLt0|3dmes^Z|kc8|1)EstM7Q2>pU%P&U23|N<= zDgN=jLA|2s%qvc#7Ng&5@q8afKlYE^l6@D;k{K)q9IUktZVn&BcV&L}j8~QqmCR5) zDNI!Y#yMasKydn<(J4OMFaRmz-(+q)$PueHu(i*cfOzXMtVeAn-je>3EOl>ozBmju zb%I{BhRcfe(d&S%6u$(>GI;^F&|%V{o>)Z4|3?l998Fj3?c3yy`;|JgIEuB1zv&fz zl6WSY2G+CqL}w>)fHxozTY{=eNWpRe4lfn*Vg(L~I0l(HkS*Ols;i%sjAM|1PGeyC zhb>~jxi;ib;^{C;MIWQJrb-x=A0I+Lv1mN#Z^2Lb=+Ec^o*y_bmhb4SBAz<|LWX}x zlQ=&MozGFnGJ?!7(O?L11Mjd2!njPyjG1hf{W=ZqUE4;%QT z>4d5&m82TL)ku)S5Y9gJL3flaQbPR=8?afP5e$$;yL9kAgB9ZZ^kE!|V!eS^w_>cD zoHVQ&6;_Zp_Gc?sI1wC@^*jimP!J&y^+Tk?CPc9rcHWgqLo|`YoDJfHUaEiW_eyF2 ztkw}go<&GSm#xf^|7up|VHgc}bwXJB1>9xw8fO@+z$JY-h^|N_bx5ZTq!JAjQk6Ot zaOd_Y76XYTFBNpSeBgx&df>v!++XT+M(libO@aGr4or_DFM zVw_-I9koOvC~X`Lf`EJ2c&5J)vTYKxfkBynIYpaN=w!O+q)`0*UTVB4hs1>;5h36L z2(${KPE*Do{kbx*pZ&S$vJD*B(Yx1fo~iqER=27M1%sphbM#~zhA=q0z>?~egDvZo zWT19EXNgwC{JdttI*vb``IJAZq!~f+Sl0=ZKh+9?|8u@< zsgcHq4Xf|{d89!fJq|)?k`90@mA8-n11TYs)G`#!Rq+g1P1q}_e}otQO_4qiX&x4& zFsLqCk@?W2Rj8ScYMRbMU$x~>zk!47qtSGGIL^%@n`Qt%EChhTahOW=Q(Fc$Fb%oO z+3GsU$O9F)SzsrI%FHexOCb)&-+d;@-VnvmiWBM)PV^(U|96FUUN8#+>)!SA`3vb24R6x5EcATK~NWfhuGO4g8Y=WT(-vk zGj}dk0%GejkwQUPur=bHbv(UY>cqiXLRW45CoG{;z@YO+}vagVb~LJp_+Sy2RM%l zA)k$R{_%aYdWCqX@7xl@Z!pxatYHWT$Y{g5$~Pwubs1l?0J{W7)Xx8z&dZS&4%^ErBjBIQMi3ixZkt~U#UHhK&p5Fe|D2lhk<%&Lt${a9e7 zMHYN26scXi#r2{fzS7co8M{-U5o_ch-^qG;$JkIES*O{L>E;0Y7kil<Gc_kEuaEP2TGPvr=jtI zJ6E(ANe9na%Dw>go@#?I0X*5m9KfyPeSHDCivc79prs{nMuLA}J@95T_#{zX&qlgV ze99NzfeQdwPb5g>kQiHlZZQ=A3OZpznS)AG>`V1(wp`*WX7UOL3W^iQN;=x5vmiGn zje-yaGh~NR^h5%{xp@Q+{TDr11EFOK|0uvr<)0@<>t%J5Vf&viCpD>hi=<9Gt}Q_; z?YCOHoiYm2G#@70(}PKpr`HH+^ZUNQ5uAbRj0U9}tG^;KL9Z2eUWozi=f2{&cDI@G z==D4wz1QD)DJ@#W=>5yB#kf%&vk(!Pg;37XHFlnPhkOz_V)Urz6Oo*1Vf^Fj?B9{_ zrqLxOi|zHVs{y-JjgOP4`s-1*0J)Q3a6QQR`#Xis{Y4WXpqPwMit(Zzw$e|CpzxFN z?zzmz`y;jN)sZ-WD&5}CJ$nk;Q9-c~=_+@l2cV+&UUHsxA`2$APCTPK~m*hCGNPf3DMk$ZLJhaf`_z;$eQ?3$&i|#Y7vbz25V_pQ> zHQT;l->C?4)?`-;tODqtmPOJDcqD^A@ywDZ2mlc>>QRnnFDWZkQR$2`<%(sl>@515CWm zO?=2%mGn>XSoLvq?j!(v0imRQ%SagPOY!D2*jE|8_+}%kjcx*BBZ<8H7nmm$fDZM; z0vigdPyi-Z_F90rR`8=aBs;(n!DUJ*e+qHRlt6A|go(oR`jt1p&La_&DTP8tGT^^% z9p;+s9?Q{rZ!+q4_cNkfn~d)78L3;8N$#;qhwZSVcH}CDgJ>^@Etj(?_y@ur#euVS zw^zh>S%D|tfDc$!PvhVCk^QIZL5oy6FCYG+OMrVWanB*{_%AT^&rSrUwG!acX^MU> zBz^Hy+by(hXxU)l=#t#U_P?)tuc`5o1j&8vg(gWCy`}NvS!4vyPLZpD-Dt`RHlC+D z9A;CDB4sU-MtL zst8$x8WP})Q#k{mzR_|=u}L&NW=JlOf{L1q8$9F$gwEaYj4kj(xCbFIfvLxxl2#RaV z>(A&9R*KN38~;e@aN}ewW5e00t3y-r`Sl;w1-~|(PO;$%ljre*NOHmsu9d!J9625l zQNoKMFIMo$XBfGN@g~8oK*q&A@gYq)i{p{YfXGBBZ7qq+2bIag6UruQiSTt$n8H7X zi&NEWil>7Dph{FSlt5mrV0#T+3EM9PblbLi#!te?Md&28CFpwYHFW51N|OMhTwbi; zT~8~@l(Fq{wEbvHZA)rPZO&JeqQ_Gdv`J2qzq2Vy(M>>Y zB#DmyFl-(=5c1Cd^7$WBlbv%8uzn8^4f8_)YVkre0*_fwUYQ|0j973 z2g>Bwrw#Z(r~<=Ig|>qG9j$j>+>qmmXoR!*6fra&!F{nb2KI0{5{WhdU(><&%A?4I zF{*mK1jQjGgb*>rl2VM{Qc}>IpX4CFYYW`G_QzL(R2zj8-FEKH68`MY&>; zC@w9qj{(4qPZKU*{h>)_GyNe#A>c2eyV20H6t05O;?Q8!r#_KK)R*a6RB&ksHY zefgaNQ@8VvBFE6JoqvpvV?Ii;I#@)yLRP7qvKV+OgB85#SR(6;O4%vrDp=5(>NHmN z!{ExGe-x#d-HP!)R*0U%2NehsKSs`UA~+7WVS;GQNf@m-itCV?r?u3iqiRSFyJa%4 zAU#^3UI8#rp))S;jGgI4J#K|&;ID5Gkl-|VWIo0RidKkZwOQQ0qYRQ&>QTZZe*K%^ z`^TTGz~o=^&G znT4y^HM%?lq0oLW?ES0tCr??*~FgQRgXH zcE1^5AOyDpc_my_N|~q&0wYpj4>(D?03}$2Ow5}-;&Kq^y99yuhCb!LX!@M2mtv+9 zCJ%kS(^hyN=##zje?gy@Hu>oDp^sh+xn~&)6n`z7{rd6|gFyg;((Un&sgpt>sbT~WC(uUN zhyJL(yKNN504$+Tuw9T zP3MdNANF|vn5;)CR`%D=k9nIlKgR1tl*#gX8mF27?mqCNa#?~OGKk#{%X8A-M^f^w{$;Rho4^gKaq6ra|!7FV5|1wL`84#c_a)W^S&WxF8#BU#hLMR5Q z=G=7*Mt>*vNbr+HK?Y8cX^<)y+@&@csmqzO)KewO5OBohfuY7Rzy!6~y?$N61D~5i zU^iY2g3fgbny|O%&FK3>H?tGi*8QQHz$F^dF= zke8q_I}RuY*QjHhFkPS_fldW$!MOQDLheU|>WDhZ*ac^lfek9y*#g=Zn;0Uve>t-O zwlT%#MHxe^uI-DFx#XPQYeIK1iF;QnxaFiwKD~rb=cF!I7g>tXaFNMEY$+kDOA_N4 zSc!@cWkw7eRs;7gM(3-JW0^8IjZIdhskmcp79+xLelz%%Wlvc_m1|``gZW~1H2}dR z_hdZK%}~`W^UO2t265QF6jGYJtQsabqBgV5PEp@(Cer2_*I z5GycjfFu0*Ka232fn}dk_=5BJK&+@*(i53UHQ8$}gkJn8Vsq}tb2QWivSPc=uuGjIVCB%daw*u0A-MJ&h=tJ8kerjlaw;9~Ok!p*tq+*@B$2aGx#6ptt{H3v&69 zjGkNz5`I`)kOvQTEQpxCN?H)v&<7^i-v?K!~uiMglBbIQV83m4TZ`~xqy>J+W`?$nlRrCJ#DrFDK8Gn>9{s6xN#yVgZ?RiaVT~3&Z zVn4pO@!^s~}f~EZOyC_H5wEP&FSyw9Gqk4Dx>1 zjSAMJWmCW?y&3j9a-g3lt_juNOHs9gPaWztGdT#J69~jrWr(ZF7yE|Q+WIOiQ32EM z`#Bs>YZQ*ZTLO+}CCr)Mo^4Q@J8QURZ^EV-1R?gK3K%T?Gy}ud3itc-A$%j3Yo{tM zgR{P#Pq(l5-Em2-06<9e+6Pd=nG2x|$XEK1Iln0x$YF(H_>fVbQ3en}tyB>d_$Rgs zKwuDzGC($v_jibpbOrCRO87>}Jt_ltz!>J?My#uc_YF8jk&F;sn2<@I!F)v^aqcEn1`~Rq*5Y~$X1QZ9%e28PHlL%xERH=b zp_v%S?eanGcc*!&kgvS(P@B!-*j0|%JR5sUh*=q_tHJ^mcvYyt>yUql*}RjinJjG9 zv6n`Tn#=MfBrbSLVZ~dP9jsGSKsQ{8_!yD_il>P`CCaD=@mU>exG!qMDTIMIndVOzL+g3UVD@h7Tx5x&$CqXPfGKS9e&{ReYV57JCp42%im}_ zoGyY5nGq|7n|@le!>^NoR?lIE*=I96+vW`H;cRbK=AuNOY#3ne=Fj$?AJ5p&wZdHw z@+#p=OI;<@1B2jZk`;dBjsM;X7wwA`jwL+oOT8TqPWz{D@Y2EHpwWiC?YBpJyRkup zX$>DShnsK94L|>ZT^+GK$*z97QQOtWX!T@uTq}0mTpYhV>I1WYwx+J+b}&M}}3TUj;S;{@^Iu@f$_aejNx!d%|Zb zrJI{%FJ-}3(tIFq{g#atlR42}10@&^d6roHmMp`(9TGT>J*xYp2M5P3bgfCh^Z%U~JPPz>LF zvI>gdyCM0ESUn9W#z*4l%vYGv>^7SZ=#1cyWna<*^ue-F+?-U|l>=sFFv&8RQ7$it zCKEG?5u#x<{+R%j5uS3!peo(|c>qZKqQ{nzz&`qp9t>ZU%f14lcK&CAw&oy^X&A7h znH1syHao4ivO^#+<2y73x`^RnxhR)5O+b5%PY4$i|M}VrP3lhq`{vV0*>Z=(6|5K_ zaGDfv8TJo7)PfbwFOb7<$WbCMLV09Gl#Vp12bt*agk~9hv0uMHEkF>KfzN^gyDAu7 zt7gtvXK+}BYGefm|8w=$^`B;2w1@5}Rv#5vL+U-x@QKA5)l%87P`(?MKn1QsH=(s|)VFDZr zevXeQ{!>5Cilq}-e0p;6!=?D!e^!=9km9H6;;E{5R|V1R_dN6nv-ql2N%UBW zhRndPFDis)awByt_@-)o_B>DV-?R9Xr&-?y2{1-3zC0RRSs@e<&N=t0cD|7d8V%NLRIBys>*qR zWW=A{n<~3Ym5tCxDn?xPR|h+*Dg(P2e`vc5PAKQ#ypT63_UcJ$WhxeKKg&uG8{93G z1Z2G23WN_nw#`bWBr3T=S8}|nWZ3H>6uUCou4G`MlCHXvcLF4O;9qm4lC?$26soz? zCAu;bM=haXe*V0o#waNsJOm$UWm1xrvTAvfR$aB2#UIzj4^zc2!bcRJ*RE|8YHD3# zUd&2B%=tX|DHa%}P>8JPhqDq;FHMhZ#-A0%282YPYr_`C+1q&Z1`(O-@&pta?>wGOmlq zW@peW41YUGHG0>PxltB}o%srRATKB2BUIxrmw1XF!s3S~7yo`Cix=wRlU4E0@e##$ zFUO>j*G$+>VoE2Ka-c8eaHc%L1xi-%!B@PPrZVLeNeT3Q%S*TK_D9MZE~2plfAyuj z%aq$CCD_AP+pA3Ju2PQmr98}(Mcgf81z-Ef3&D7%{83T@$NSp3nki{2<*PTnunlI) zgWUXV1-|p8Tb0cRjr%X9}jt2eGIc3nS0~9rJ856xJs7*K(%B#MgZiM=9Mo(PWXQr;{_EyD#h-hKs|_{Ug`l= zNSp*OXOZ`bzGujgCuodrGpCP69c6Z&%4rd3lu(!Mup9;_i>2| z@L4+QU^DHNSlWHDuCI8IiQlG?*&_Ft`{ilOnii0`t~oL_Hw!X1^aL{b4l>F8_0XjE z6+RfC7>OYQj1gg+Krakqe-vXKbRQRmlvkBLYOZ0Oi(w3mY(T2g?fDr=X<;{w(#;En zQtU&jR3;f+Vg+c>so?wHB~^e%owWD-Y0-KNZ8(l-wwnexBBWm!iipMPx19={dFBcQ zGKqh484URP|HM}@Np`8>T8IiT?Dll*Pz=>vg6w%KxMyt;3!1#d6oZjw1)gKDiSf%& zO~B3aD=;;&Ep&JoMQgt#WlbX&J05f7cp3Bd9HaNo>fA?Fr#ky_5Lzz<{1tfK4ui9+ zatM$AdFFT@&=-f6P*3pSxd5DUV18H| zJ(rwiA8;@SJAKW>S0h3|k(CS-gqevVgzSvY&5Q7C7W=6@u$AZUi=A=)OXBZ~N}eGm zBOw!zXAst7&p|`So>K#{CLOmmf5*(5nR&Cl2J7c}kAmI#88sdX{^`L#88a)RoJAmK z1`YnXlbc(cbql--is1%Y(Klv!tqr>DDfZVlh=RV83#?Al!kR3vqlZ9NF(NY(oB((b zJP$761THeX2dOOrJ8A8mYnt#XYmZnox+H6{eHmJ7obJ$$Papk8Uy1f|ytcs8Uaq%2 zkcI8#_}hb4P{Ls9(6U@q%@JhB`Dpe0 z0I9&$EXsB8Wr66DjK%gCw(zWK;lHmR=19@gtv{>P`mrly6YSqet}*3*UihK?3HU)c z!Vc;5@(ZLZCh24uikKx<5?vBrY(ISxaJoNs`QwhJv?R}E`=GBpxlT-()1GK6q)?`&L{S-X z3DpwL^aR3icLD}KzGv-&zKR#%@nx!gSDRKIj}~S+E&R9jLtB&TzitopU%0pW3bx36 z5;WFhUGYt{291(_pqkd!t;YeUX~fBo&*jPdY94Df27KXAv>q+!kVoPv8M9alP_ zMi6cMh=1QJi2Z*3kDZ$N^~R^{cY8pUTJ7(Q?%yiC2sCh4NBrQX$rO7wl(R*eT#Ggu zpVKs94#>O~dmQ2ooHAg9%|Yo7LRpJ}!#17Y&%ZkW587qF1GIxsc>GiIzM@PhxxK^e z>gI;$h?atd&u;P>9*LjlUM+^_i5yUi%dip*{@=k@Grl=| zd6dY07tEI9xDw2Vwj}GG$XbHsV#KdwJ9y+Am80Uux%NMg0cCiux}RTd(<7ntA6(<$ z46_5N@)!pD5A7YICE0@;(C!}SF|Ij1Kn5WPKo{k}l{=&lNCQnNbWMR+0jwhEy}qSB ziDR%-Pk`%3)AlD>+&&33Y?a+`G>CG&Pn`YsGBoLbHQw=@^pO2s>Ce`Cg_|}6;X(Uy zuW-wFNAD{|`Hm#CZH;%#Q~k>^v=J4w5fzS&Km@-ayPA!-VPK8=jZx;BGo*Vdp&tm( zxK^)Lz-UKQPC&9cW6|D-)$j(g5~gxBGFNf}ybt!okHeZtt8lfmUr4QpFM`xYxgK?} zl~zP!nTy4h^~i%Ivc+cSdaQr1=fe2a8O2uD)y39TOuH)EC^S!;bnn=d0kuC=U4%Pu zR-*tLLuNDc1|(q3Sv|J(9*hoOJz%H@u*5SeHz{!;4iMswV@Zn-B$zguwuRp)MXDU?iAZh*%2ag+oN0 zaO;zE@R2xk>5MamMtF)Oy|6dTHxL4SHv6h~)KR;+7-cLYft?L~fzNJhj_83cAv*cm zW{BQ+xgdJckwElFQ9K`hqnpJ;>^_pHVsaojxS#m9<>F=$5ilb1nV}9HZbCv?**`= z?uZ5Cj^^96j{*Gg0uszmuf4S2980wif*B!$0dh0@y>*v|aA?&X%ldnGPxd=B>F!qO z2l_)Tb+|7+L|{0eKoNjv5<)VCNe(S#_{$+^LrVmO98d%(v|@&`?0ev>JyzY`eFW%q zvDc#e>9sHM+(sy+q8E_y(&S+@@*l@@tT7#H3Q3^&_yzBILMaKVeCe0Z-($Ma6%3HY z2C~K=e#4tdC4BYWwCDQbH#LXHPrp3ao-EoPJsyNJFLhA%V&{PhDf^T1Z$LM<6M6mb zL9I93fKlLCmXdnZfNPdT(qb>X`x8zb+5Oo+9$FUZH2VBgGL}U$Hh=X2Hn>De6=sn# zKHXzT{P4i)`{1zx3-0IXdDwi@{%gg)^nGuP^I)aLal&jwFQRBt+b;h>!+{<#$bC^{M$3PW?#PBo%Ukx=v+{+wKx-`QwdioD}K#5gbVzGuYn zi0+PrYIXxw9$|IYk9@)LLA?4GKF;Xzez7&Msi=N?zoO{orlRi4i>yxIJ)F1rduk!f zre7yHfcgns8o3-+b_TtgyJVo5$G-BowH}L%rjZy=Y5ak` zB*Qyn2YYl!4X;Sbj!yYq4&6taCHn4-Gl@#xKfcf~6#TR>jjS`MS(qbvT2e6`L?(Ln=0peH6 zBov6Pjt|FAk`lQ}gqZOq%useXWTz2R%C0te`{!0oHYZBdmaDrF`C-eIA?$uJTh-ILDt+L|w z=4w<@jmz)ApY8df=zOlmh}JDPwynd5Na(J=@`L4^w+bg`H9Hm5CERY#c!M_)qkcns z+!heskv{4KBL?<=g;~wT#u}SkHo9yzx-X4Pp3|9a;{O~SRK7n0g`2ayXmt`M0H+$)1+5-E)IZme& zO#lXv0C1$+y>FCe?pGB@>n3Z_y%h(z@158V#4?F^Ar#dj7ZD@1p!&@?&~nk5;9X4ZhbZwBQ3P!#=l#vNxD_5M5*tw*+Vtg6(a-d}{GbJUM^ z^5Z%6qrLoi1V7F;dmeXotn%rcqNXK9(YMoB%ea5A#@I&#VoL|a-Y-PNnuQKjMq#W| zHj_hEE+xb2_QyF@DTB<;Ut{VxqcCr4Vcu>an3cL2!k!U|_CoFE`O|Vz8^D^**q%9O zF0=RCXvBVAvjMss?(#wRMUeLm@MI|1Su{V~Wo!4P9k!fhr5%JKsc)zv1>05+=ulsf zw_^bI$VPXg_67{{6x1*6Xjab2DNKED!qRWer%KTK>|AUG2hXoc8ESU@syMcO&9`i5 zK$jH--G6qPLZ&r8O8YCi|6I^vMSrVPkAnKTj-Y^GVq&PkS*4%Eqye$|g4p)h`vYQ) zh2{xz(}Kj#;Q_Io17h0>SsvJ;8vstb^qSHDQ?Gx8L)Lkq9$Z95VfSC48X4O@DD1wo z!y3G1rG5hXmV~040z%*RuL|~GD~vzJM`D}0Wx}F|Z<{zAN)M{`y6iP(O8XW^_paFp zt3d*8fxT!()y*9iX{x^Px}s`f3}o4{ZFOPydXT{-?KNmfNLx(Ou9#4tz51LHP$Ras z84MX>cKWs;wyGGV*8n!~acg1sFEn)vp?IAO*2EQk3%ai;?C{=MR;QExFA_K$n(}uc zaAkH^&@VTHeW$=++gcL2pu-mfAeSI+Vd@q|-Du)o zbIL3sZ((*Pn1QZ^_>X2H60(N5lDw;6+s6aCZ!7Gui`|cd86x98cb^_F`2jrdC07jwi z`$f@Rr1E_YKR6Xiim;SjkbWEF`pe>|YWHj(GNFO@LwR0MuT5qRB8BFq4u0ydQd)}~^}Z|6O) zh51xSyqJn)VFum>L|h5;_GDomtL)Im0kLHTc|J*I2$?Vy_1Z|Rf=L2-zfF*r>Y_-T zB)}l?2i>=HSSQCYroJB=)5*-INz1^G!qjE4F&PlBo`q&wHh*Eb?aqZpeG}s1 zZB0h>yNHpx(}*svGonlJuRap*u^r5P@qA(KGwSiUdOWBeQ`IA;9uw7Lta?<+g8}_R z5M_2a%Q2!^vG^*(b6)!Bp$I<^^`C%X?}TjZ92z`Yb`EtgKp_d2 zJP6}URRwu<7-d3_k}$JB4Nm7{$gY$V37keO!!%-$aKt@q$3aPAg}9xi^x!QVfsX$rAVEza1HYjr>5QXa!#9i^FfheiuDx))619Br zAhOu5>jdxz`@m0ze}?o1{paU$fH-#qjU(VszD_|!LB|?0UqWl6!IB; zD_->0m9^H^-EjpDlR5P-SpREgX7dp{(99frD@XhMc`}& z_FMITnEMj=Dyr-M1b7;d_@amnC^cx*P?v@Z8Wc5bI?;zlr8VLfMQK#j2nj}INqh<9 z`7(-1l`7WMx=_WRxFIUGfgl9jSgPVu#ie><(4wfISn~gV&%N_z=H-RF0QFx!A2Rc1 z?sD$g@44sRF%u{-P#U=?Lv>xo*&6u)tdK8SmBfRD&{+WSEGvS^z0eaSKuVm8vb9-0C!w2O-h2`W z);XH1t=+-LBXpc4PX5Mg{so^-z-TaqD<(7$49&mbTH#-3+b&pGU1_)$NNIy8C>9Q$ z=LYNV8<6oCOnaOJMkEb*1lmzHTIF~S^y5`W`H_&}g-e>Y%!=zy!EpdbDO zej21d9HPSJ!^UY`&9iD{%?E>p-{3zyfG`SKg_uIttk|FhOC^LVSM6J&hi{B^FM!j` z4^VoXx3>O<$zOncPXHzWBmM-692h@bY1T;CL*8;Z?1B_Y03^ea(2W4n?A`~EAyP)x zB0}^s;Pt5!1xPd&T$qBD<5F@+J~$Ge#<{c`0KPCDU_bpv1E0BsHHWa~(3Q)p)hq%u z8zI18j1a`*Oz@JM$I5*0&QIMT zyk`HFU%uv?W$-(FxmUj0!(o!5^|1gZqGhE*yq0W8>%L?>q|Pg3|49M3?dCHEXH=7X z@%&&-H1NLhvVj-mw}LD6hbasnbo288B50ZqLK?>p3E`b{ zoq_kD|02A9ndpP}!PeK3f%j&OUq3&nQUmX`%M$WK94?dOhqVGA_#v7SY=TDgvcdP; z0qrHkZX7;mCZd1SpB(x(I`EMJzyX$z1=9R10Hdi{KyH#?fx_#2C_RfnUJ%Cuaq!k8 z!e^!f??EwmX}@Cf6$e<7_`F%5V>{UW7i^-D@uKuE{{gfY#X%eA&jn{B#Ba%c4*i$@ zSMj^)S|5JD{%I%iyJ)U~_wP#_cy|MS4=yEi?c#R?q3saAN9p++jLrlwD0~FWduS6e zd9u6nU1SMY`v5L?%LZ#0l15^I`A{KkQ(n-Pt#S74o4{MOnBrpM1V2VX>1JY^p=V~8 zG{N7&8N5t*$WlwV4Os?I(=c6ft1Y-0g*@bb#=XQCzEom2I2eNj2fV?%WFA>eH5#1x=wQcxodw<&s;+=(f8?mVX5*Zc4BI3?A2 zj8%>leO%@XxMMq*$gXzYQo}V*qjM&2`P%aqOHe7z#qL|Y_PoWsCZ&0}=WR-==PhO? zDb3k@D^#ZFH}~dGeB6>d{#DBl;H!nPX;_?o32S~TB0m+9p9&4i>600+HjNwtj0-(X zz#~%~0<4Ko7Fp7uy1_9!d1$b_YxtvJZ7BPs${*5#GpA#e*t%Ks1YjB(EZd)R%Szny zADuW8_OJuB)6GZ8&itFhJs_&ZkCGjNveESGFXK@X<)guAdp^XiLI8=!Bun_L{1Gfc z1x_ggpRX;uS7K(TqP&S8A+KdvT1&MRapGW)!G~(Tj?^Zn+35=(WP@BczukCOR?DB! z;?r};()(qr7hduJmCxDCN#Nuy?*tc0K1XooERLrgenx^WIMKt;X3hY9HrNF}(}e*9 z;Ac7ene&M6t|E>o#iESa>&cZr1j~DibZb0%aENe0C83C6Rn0z8rt@~-h-n77-z@fw zLy*gTV$t-z;{>_Iz(uiq=G=?i_NmtUj*%MWSSLit?jM)Np?rml@;tbKEzcQz|MW7` z9Ek7!#yhlHZdIeUfJ=+PrE&Z@gLy!He+^i{&QauSw~%*%G7H~E=84x!euR(4AW-AGMQN6S)8Um zWO;DrJp3vMH*Ak3xP>>QhEkVsPxYLaI0P{dKc=Bjt zaf9U1wL@tAb? z7dzb_)~5SDGWs*z?q4~w{n5Xjzr)eblByj2G`D;8z-EZ(h0Fo+{)>~>CurIH-!leN zh`h>QIkUC{c7fPWv}>H5%c^TD9AeF98+EW$;ep zcI>~%AqTj!aJRS}fXx?RBnW`bxE&(xxoXt76)3$pMJAllX0ijd+T@99PIAMdy7Te+8! znCBAl<2_RGsCT&jwSdwe1yh{Vbez-L)yLTPxLk;(5%h$K$911 z1`ZQ5_rpJ?25WvI_ha>;D7f&L{L1Y|1*_NdiTED6-D`8b?UF~-uL|B0{uc9}Mawor zPBD*S2`<`4)(4r?>?U7`3pQ7X!0+gg05AZl)Ar@Js<5d&6I!`@u)3R6q8}CBx<~mi z@^5i)VOr%6lgkGM7h0*6KU`9N1a7)i{xGrpVBB=A{Nal7KDg;t`NK8k8Nr45fuUvP zX-J9v0bL*_Mj4E?RVZzhJ8fO#v^B|T>k_A}@uscIrL7-zTh8j2^XV7E2x|T>eFxG4 zw;A-pG?$P))bZ;y9iStGA*!=QFtAcWHUqR9&;!s#UJWCIz{_OAZuT-6vn$nmL9-{N z8ZHHe4K0w5Q=8>$<48{=w>yY#zJn68;us3M=?aL6bw%1Y_hgZ>uOL)U#A{2heA(66 z{BEnxcV-e7@|`nziOkQI^-@a*SS)<6ehXb-;b!A7L0kMEQ&fP}H8i>&6e$*uyK@$=Hu zh2n-m4qIMTRV_gGTtB)!_QVD=#Q1#*OcD59*dF}ObZZOz&Z~R?x;lFiNegPMrSNzq1lNmK{|3ZlI@95qJ=`r9>cS7$o+!v$;A09p@9-Ps6C-T%t6( zJCMNR>FktZ=gRO5>{rPiYDE@n6d+H!0bqq7mPE;D?24(LfVv^OcgBcvoK&yZ>O+vR zTD%`cHMS9s23t8fWcNG$pNF9kwtHgFW}*Hh3e5P)A&75=y69LBn=)SXDVpG{ekf|6 zh_R=mwu~K$xX>8K3-CsmJpaU4ZAWL|%d@M-a3)y9gq3TE20~>;3Ng^S?DcX#TU0d2 zapvC)Il$`Rd2s}0n?g|h>cgR?1I~Yk*1{g@^>%DBfMC%lur0AmMa_4D@5Ioei0+YW z^0(*MfRk*aVQHR3E=288Djw0e_))U8B;K@?rv`kX=9s$cqD;SRU0$cMd&_MbN zH*uz5_`AQf?)Xo1SjqNTaudz8B1>D>5qG%+Cx^pTQbGHHAnAb*Ia=F!#d*Z|a12Qt z1v?WlKKhT)+I3t+m!B-u##cDgG=2aCkrGkQia8sF3NJ1!AiEHy4JY`edR7y>)Y%I~kZte&CjvBaj6pjp=rBCU+ z;fAAxUsV00F_eyEAX@AdG(c0KqXB|7vUeWJql7A8d45JJ%uT;Xq(EsVgEDWRfBMYO zE=8Hqes%g)7GK%s6;wk}7J03S51{Z?^J=H(KI_P3`qdZF28#l5ihSq#Z`^ILZ(kH$KfaPz49LG8GB10w9=sRV;5}L+2=) ze=F>$i(yDCHY7o@UJgTR)R67=O;GF=YBf9X_FpNX)#BiCo|OSG4-*^&=KtAc6Z*f} zVfcQ!kA)-PNg2!E{s4LVmU+7W_yorKV%&LrBmex*uFfuH_a_X?2+lYN6HeG`u6oly zP2&~zT3-Xdzn&ZcU*XnyF^({M%fM-wQVD#q;0%{9?iKSlTQrMUhv*;cg}VD?YYjsO zwNJ2Syp)5UW+TyB;Q(+g6%ySq{k0L0((zE!w@IoWT%#@yEc6JGiH1+&IkQgl5nEK! z95vUZ;yt7F4^9cRCD9Wf#$vzt5-cbV=AzuN=MWG&OdlErWmc`7TgN%h7b?V@{TZX(FyzK$94e+K( z`Hb(ln9c#~at&uVCwd>G{<;eOU)@|q|yVEGo9jtsgH1UgQ;cCu&rm&2GWB&mqt#4_=96FPpGqw>Edlrjx;99PH$Uq^4RH^b4T z5A@G|PUdV2%~He=-^t*r-1R~w)0Nj(O(8ef>BsD8VyiDa;L+(@4Q-`RBrTf$zD15J z6em&~q2V^k!_+(U_QI^n~>F*Cf=o@6)Bv^$@cYq9lUNm?~JZM9P zs%4}OyaC7Uybc~@%Ldvxw@H%aJn<~y0Rx1VxjHD|CEF15p15mPhSOF{{}2wqvR>}N zWaLLBKd{|b7){R3yhI&`{K zpTm1nNO*7gD3|x79eA5qUOhaH_wGkAJ;siB?>jg%F7N3kiNJq~ljHIp8Op%|o!6J- z{p@U_wOLjfV(k2Y_tgW!mbcUke%#}0!&~FFM2pZT`-kmA0W4wqyQ_LS)K*hlV-p!j* z)r+4N!0SqRLLGrXgn26#b(Z-7Hiy=gp&F0{2@c4D9{k8re}0E!kJCn|tB0$#kfsAU z;psF7$AVj63OMy*N-df1;1X2WV5pEqYRxlL0B+%jwxI&mlI~PCV&QYJQse^S7)vKI zE^Y&92gm8y2%vp~x!D@Wob92e#xbW;_@QykJvR8Eam;Ka{LnbQAiGpOf%!`EIMxF( zIF=zgIF`W+j!#^_4qs~!=8s2o{BL6_qqX&dIv`30?#@9dEY<1wsF)C#FCi#W2s%Df zP>he8%kyV6YhZq%*~PK=j@dBfvG}05#*{})kmWY+dyXaS64@ zVDS`na7mgBAwP%TmUi5EFcP2gGt(nb1r{Hkd@dX1R;HMkeTCe2VFA3|B>u%Src|uR zE1n_?Oc5#SwldEtf+=t@itrz&!zG^kQqO&b=f2Xp2SYXBo+pTu0`w3C3co{;i4ysZ zNg{uPW=-;Zw)Dkuu^;M?)x5f39c92`6@tZ(Y^@YsoIT4_k*aQ$ACb6Dd`JL>6osUQ z02vhqzh#Y?=7U0d25fOgAhf0G@|YvO5b!Ju0uHJ;-Zkwx*^Wb?_7hde@x@f3Kt!I8 ziK)Qm!ZhB%#Aa3t1w|DiXe&R=y6Xn{!Hhw#m=cSd1a^c~RT{quf+xZn;f8#2RtjN} zsheS>1T0kd68+tt&Apun_RzREoAxg_pN?IW}`UYKk z40DE{K5*$a9Vt@HcX@o5_3|?P&=rRQmGsT(^n{!ySUrI=@;TuEHyQU#iqk#&bg1LH z1Z(b~9Ey7uc<5K+bdC6!Q#~}tC6nIr+HtzjpV!-WovvJV0?!NlAy}@KJrXbv}g;V_BF6FFSu zNj;p0J0Qlu48hk_guTT*rC7V&_@SvN)>z<#XQJNz00iu17*up_)GB06&E&300n1gA zK!Sc?rdEE;suzrUm$=e`)nWDuR$eW=YxlqrT`)X+Km!&q<{H&Z^~IYMIyy|~O-GH5 zAs_)`Kyen)cCqZJAGA_(5P=ZJ!1t(I*9(Ys`lK$%x<$y*fd-u)%ti*WSxFwUEojr= z6hyXK13t8>T2o-3g125pHdxWfA8fIKEuxCxD>4-NQd>)EM{tqI3H%dv&sGhRj3>)r zPYhV4v>@9=A;Ng0L2Z)9dYR1{vN>qy39Mu&4q7W1w!G=_HiPxMSVX_ji~5LKPv|9r z3p~y<_;)q%0(lZMfuAD9UOP$%aht+m3!kI(jB%98sDT$7noh|s@oV52k~3x8Q=F5= zC8C~!iaK4NtB7*oox>M$*l@7!Zi5TKiG2|wZBTlqqDG&_90?MSx4I@#NplUYwMHux zT*9Jp9QABnQ;G-zdO;)zz50F=F$=Go1?(bp%Y<<;ap27S=0`kSsM~?#^S9p0S2IQaA9>e-ARO!%XWwaN2dxB zHVL1D8;~E{+A3R5vshc}Q>~u0KE=5BVwS0pAsbXP)#+;h$qH^wumdNbWzsYEnB_5X zo5+GI^3#q4b4AmSI98_SXJ9^_|2KvP(r~x@7jZN507@k{Ge7^2v6;D@{?$utkqkEy zj|nb2Z@CXx+NUhg95VBl_EkP?J%&htK_KX!I&(@LCdV9i^p1Iy5Q>tZ!Hx5w+9G-7 z)QCj{r8NkGn-2kFaR<7 zJUr#_t510X4HX=cqZKto;$9`86<^=FyR>5I7aW;aD>4BprV-1=$E>7i!zuW78)mG; zYAeEk>ziK_{g%GuY|%nb@j@;1&N0bqpVX8x|-0yBTt;%LsW(BgOjb|6eTfsE!L zi_2CffgaDKbMTHug~Kw^Wp#F;`K>`f?vB<`Im*>hQblyp+2a!Hs9V1C@YAm7sE;;6 zGd#YTG>_Bt;jKM_Gn)x?cx(6ai5!B)kJdLDJx1TOqpiMOhIs6A^qRmxT2$yQ!Q_i{ z5cT+>MI|;v`S)5tbbvtA`5y0B-r6c|S|>W3#tt9-1}F$`-78o_I#EqO4;Z1QcWU4- zzCwg{a^T-nNgqr&b^_G}O*_$JHG5pZ1rx?YYSyA}kAbS#891JNskK#3e*n#sF;JU> zV;hW-dUzGbPiXAGJ*OEXb%{x3gm`N^;TowKzm6HHd!KWRRR4YAj8rj7C1<1--r+G) z1=1po)cttOvBZp2x8Te#saV2Wy98%4>lb&aW%%mK)-Et#wyZyOo^xwg?gRlR5oP~2 zer#u@a|V1UE?6Wfome}$y8&w(nQHXQ==BEnih~PxPBZlAT;F09Rn1EDo4S*uEos;Z zUDS&`-u9J@bdTW7t2EgI!Rp?d zd%@GAxFlwwbCejaVD(YB4owYKa}gVII~8g*tW0>Thsl@}wYr*YZKv-soiAaa?GOr! zgT8L8c0Vu+k*N@-+$ftA0I*jCG{o(08Rc}*V+v5`zP zkT|xLLlrM!1#~8{h*>OZ_p?Wu1;sHYL((+{bRVR3E@qbxa2FJHc!JZG;9hYS;S3Z@ z<Wm7qbZHNH1I+lYqr+E`IZQnLO7>YW}y0J-U-LU(m}Fx>R!?Tql|sClUs0 zmUBE1ZgGpyt@ujbsfKo0>Fn-zhmHv7X-|G3sRS$5KOB!3c1%K{UvtHYcbAjVrVzul= zB(I$LPk-_X5?L;@Jozgr439|u%GU>jl2scur1P^Yh;rnw$Q1yh6cyiJoxBz3j$sl?mSkpLN1vYfQ zu{po=?3?prY0?sKU|MB#&cMvFJ3|Wc9?Z@wK$LQnIQi`?&zo}CmcVksg;TPx&#xT{ zk|4KGD2)U;1|v7%M~L%Q#%Y!O0MBy4iwd0|pUP5CJgp^3_ei>$;D=0l@k4_^j=>KZ zBi>+62o4jV#KS|>S~~WwZ7q@~vB>Hz%84Pk0Xe7?Hy~HUAB2+DtC&9sC4ZEtA7rnI zVeYDB7q<`lH5vEQddjiG+*CeIMpn^8y&$^3b>ziX(as>Bz^ca1aD520ARp{^juIs7Gt7jUa> zaA(}iAKfJJ@`<=PU}u29tTV?@zar1E#Rku{p^k7>3W}DniY=dKs!EZtvE@QrPjZ8l zc2}Y#xgjT(H_(fm0glkxyHYcfqwAg3N0*WGx@on^Ky9CqrllB08g-)w%c}_swTQq3 zM*4l$4jF0AM3<3t&qUbAh4G9e?Fu99FAcU~q_@+Bk?uUw!$>$X7-;N}ksyw79$!5x z+Wqc5-Z0XoH+Y8VFp?A!MhYL~GE$x%IAo+>Y8)e7fMUrp(o@(v;xdwMl6bjCwv@DG zq?_fr*W+u$NEe%`L}atWNJ+9phS4puZoUKEa@BTCO!b=z55Ah>Sz^pDU6#1Wywn^o zx}~PnWeMFghyKPH@hlk!acVgY6m!AV#=I# zE3>q<16C;h$*{uVlRd1^V5qHlrI{%>aEGjL<25cTam6uMwWYq=&*tm676s~Ktjf{u!6KBtkC*X z94nlpA!l;4W`%$HHhSGZ4Xm(A9%)w4O%Wf}c$J71CdhMqMyP#OC@@u}h-L+k;|xxn zC6uDSiyzv>qwt7p2LqMGemivOo(6zi93=TQoczZG{pzBI# zV82|aP`pmZDa=ye&LfMrbqclii{%LF=}ep%J#{~{kEV55V>N+_Tww@oNnrn&$j*}M zVzZ>+%&HtKYszCey@DT8$`qt7mh7E&69muJX@N)(%;(fd5(IDN<^V|$JSiY|NDzE6 zX6SDa7y|z~j%!|Kw#Ed($;JWDFzW=tO=SM4lOU)>6im7*69kVz6`dfMCkXZ?2)_2d zp(fJowz6rY+38X-AO2BKkwvD66m?VBW;#VWn-qxhwP=$6xaQZy<`GdS22MGbX~1tL z2o}k2td;UNc~_oer#H(3@>02C3lpy{SUn9`tiqy95S(SI%rRA@s$1oq_cT6OC4;>} z;W9yxR5l5Mmt|LYvI9T8S9`$IDpv87I4VCdiPe1N#KP+ z7Q1)zNyzdWvZ|b4;?9U-BYPBex@F6RT{`oiM6`sXKLoSRq%wyvJNhG6?bi#Yv_I2O zI2=9s4@{qPsDP89E+5Gc1+$7)5|#DBnvU!{9=13Nvf63~ZeB;b)-79gzt&?q7I1`i z`l$QaGJ3Mzt!waqM(L7(nn(k$Npa@)b?fao5x)Gsm%E6~8~4JltWE$LW}5ONHT!C$0$q9dJM;>G;re5WVlV5 zV^YZV5(Ck?NIQR87n!6GZZ5?+7Dn!xW_VDWOHeTz0wsJBQ!4b4Xil9;4>1`b3&c9G zl5I9^ERrWNOR)GY$Mm~XXa*Chkk*y?pU zZz>au&6?jG1_qnBAua*XVPFB!Vc;xv%KZT2PVQi_13w-?7ZiGA$(0^GvYzCMB~g8r zA?_!WsJ6}FatPx$Ro}#UpA9IL+}w2kve?`d=dDPKbV6Gvd7MxuiRyE+(MHRe4!_S6 z265ahk+Vt>A0uZa@*@`ankVcXANLYvy1;P0t`Q5UN^6)x`6To^l-2UmU}{Ni%FC&e z37Dk3%n57Of{73j7}G&!zd5!*yUI{|9mz}Gx?PZ$ZJ%rTkRit8h1T+~Ddg5_9xF** zr}Y$VvsX_+JoMTaN{KoX6ya%>y5uQ6>^u(JQ4?O5MV&b&9x+gI-V!?{b1Qp8TR$ur zgXv#hY9@mKT0APA8_Z{qsv<%d}jm`B!v?@}l}A69hasyC=0+;e0j zbDt2Lv*(&3$c0tEJIQBw9pj^JU9ATU@f3qBUR=DA(TFy2aL2Sk$rukNM=7i_6Ehk# zqY?htl zj)wg13l0zM?3i;NKzB9lPI9LvWAq-QRGti(U!Lk3rLhh8TFy=yrq}KUC_ge|&JJ91 zs4+}Am$hq{M)!yrrc3W|43lb!Gfao0RC0!CDt4KepsAgnAuZA{jhD?Qpd^G}vU`y@ zbua~A5~l`JC4`YUbt8WxacWSKq&u^6S4sEUpMkGcCef}VPMLK^Y^}6xI3gjE?cZtN z;n6>$%X87?PRCM8*g|gt&7>F+6U+6X(+#HN>o_|hQq^?4{%jK3IzrTQ(@bwW zt+X!Z5Pzf75s__mspb%5TkVWO$#KBhX@&AI{k^~7q?lxI{XAru)&;hAC#CrMx#(_C zlHHx=bhop;b-xF_E!R1GdnRX<9)5OLhxqNo==3ZT=je!^j&r)(S?)ddF7);ZllLGi zwXj7FX=cg21T?V9W`1O-<=1e0PB1~QLuYXUnngy$Tn4nAZ8rEa6P(#JH0zi~Y1i7f z4y`?JIw)vCzXxN$9ZggB!BUY|#0Afl#^J59shX8#6Sa)HV*jSsFe7G6BcL+5Cex01YMEbOoxIu0Rsg zm2_V!-K%ElY9u#k#r$?>knR+pFsr?1>G1((Sxy%h)i4Br%?GgfGMYtT&jGN$d?Uf< z`)%=wmMrUvl_{(4Ie}l(=zC&I*Qfq$rLF-N7h2=i;?7$1-k^nV-~7P=BdjgWJV$HE z4=3a60Q>TTlr`^7Jqy0X5C73;5#=yBAh#cTu>-|poIn(Divgsm$IW4&zyyPVM3eA& zxyAGL9CTY(tj!-Dgb;G2-QZ5JC}a{W3ho4p6&j1<;Mue+R-wBv_C593{pYXA_#YQT z;r%8YJIE72aFZ`k@)0OXsl%PHR;GFy?ek|Ac5X}s7X&^&NMfX)$VE=`M5<%IRO1OX zl;@f>$J738VVl%Y{KZzgqj&*Pi!f^8z7mcaXG-Doa_;)zxp2r@mhsy&JHWhyqYtbB z>p+Gw!ZcpPbgl~%LXVM@n0E%4oB#~(fe3iz5+A!m9LYo0p)~|2E1j}d_VPA%bp=WTXBGE?=}CvKE--5 zWy|f??@j(leTSqkLdQTvT&J5_-ry;7n_8OGO|wDJW3d3LPl3WHdmf5yU&x!g1n20< z*BipV?+4p~CUpb`gow+T=fxab5}B-to+VQy-?_2m2HXfJFf+srn2eKFJH6q3__?^x zAa)SBmZe3`S#g)o7dh%aF7XJvpkh9i@_sy}v>;6yLp9_BjM7I*LcA?7EO@F2yquqb z&qiNA$QsaO*`@eq&-Rn8@b~y;&+As|H$+FNH2~+;$yyZlMgT_AM1SE$rMRV0R)hpuIqh0cv0xZV2?C5K~J45iRlAkV0S zf2~0Q%_YtuMx06y>;ihA1Kf!6O5?bpgQ#3^SID~@HJsKOMKBbu1|dyMSc@k~5jc7W zCy&sq1u*l4z0(}HGMt-Cxj_q-6>(NMve;q{-IQDgrz=r}o=2@*4e5a3Vj#GrQT;dz zxO>@QGZ%k=bdgS8oynP6)y5{NKR>&HSKC~pPSPRAix|3;A?%y|>jeM?l3}(7!ddV)0TgF=!$Fw+;IySE8A&LEUb(kD zL#17=z0)i=InA-51;DoP-h_jr;=NG}0gFZuT(>o(3&16Bw9D&gN0<_vE~ZXAjlldL zw6X=SOE7-$U*th77N7ffC${K@l>igg&4~~&1_T1jI_5_)ak^E0P;UVi#t=n+sI?1d zuuNHS52$X+M!Vw!7E=MgIqF|Fw3p@b_iAaY+PJQm2b$mFfn(vYfxoMkk<`f9Oy8pq zZD8*$nOrA?qWI;HH-hxCfgB%-veH@}bB)@~7s7zt3-wcb0Rsuje?f9TS}EqsDAcdPG| z#s@$98QB!}g#$ABuZ#|mY#I%`wIz-#UXuqguIT%c%N6wklIR6L*4qvZLIQCA9Yk(P;R_7hD*)`kNcEyJs>E2yvze<$J2lYw1KR51fgYsjB?c*IQM6 z4ILU(f!u zRsHoQ@E5FO4ltME^|A8!08+iRt8=VRY##8?VIJcM4QV7p9fin7Ou0fl0*m*%Atf4E z{v8|;YbDdOc?@rjY|!rO$qvmO^R5kSQ<>H!xfy)zkOVFnraI%FI;n&+6~?imU$DUK~PK zQ@yvYJ{J!$gx_D|ss1Zgzc;@6jZ%Htw;BVBQ3e>eT37$*K2P<5tbRd!_0y$#jZ`nc z5>GO3>$Mg{oAQ62W^7I8=%8`cv{6&lKzZ5TSOtXe; zFFQsE)s`CJ1~3mOV&fE6dJn1@0CF>SM$4P}IA)#(gmbioBAIH{?@1~cCBqpcz{3Mq zwmhJ6Ie^ps4Ccr0#U1niz455i^e1G3d#E??|H}^U<9Ph>>epIZqQ*A2mA@O%e=g+@ z?lJ#>x53hyx4|MVZ*MO%eE~~? zg9ClmSzEr47)=BRh2iVK1K#DA(Cndo3$Vv27O}wx(hz%y7GzZY$e_)X zz6JKk%+#u-DaT&EjAP4$Ccxm~wl&tQotnJue|iV-oCo|s!O%qje!%q}na}m&2dGOZJL&1UsJv}FioBp{gfm6N$V!RJQ1JQ1Ad4jXJ>#P-Fx7-yzqlH6T(m4 z2N@ZD#a)r`zMAufW@-!?%7~PPd~sm~qchXMQPY6gQczm-EwbeCUhGp2I9)<`xx8t< z@47Y4Oi_=)#}C07RV?kBPx;1B=p930dptU?)S-dE3p|37I1|dkcPYUAGA`zLV<6CO zoDA!4m^rgGb^TO~=F&KMBz||DKj#0|femnY`J*fP^zjG#8wXtElAexz_Rtd^r(=WA zQhT_lJIm=$NhjN!H#N>lML{EY2lkA=PNN zY^Y;c6-+YlM%Eki=|uS~i)#6hoIB)6Y=&=J@z%sXpJ9ePN4b2EvoX`y1Mkfqof;ROe1<;tMGM6R{ z+DMQF7+W9(@ntbyfiV-bIr~~*YzOOu$>Gb5-gxj8i{8ZHYw`rl$C8ZS$Q)0?Paa&U z(J^%b(f~n5+%VCXNxhkdnea{NH5efl8@(FUwHNevl7a_30xoB|7Phb)9;-46v4Oe#r4@i?-{KhL9p3tAVaF_#+C?QbWgl{fG-z|4|>5-7WV$LvD2!+VQ zQbcbMF?6EKdCs&nCS!hlPEKaNjRp&ePau`yHZMNeJ!Hw~2IvhqRO+3V;=?zhJ}Nxn zn;8>;+3QGYA3VVsGsyEv#ADEJ5n%#g5?S%mxX;B7PEo+{oG%;$I4Rj+h>BR|HqU1> z@|KS<1+r{Ez6vm2=;uZ+J;;x{O#k$e4y^I?NAG_6v%gD$o808$Glu^yE8>;MFHd&* z6WpLv2uO&yjD=^uxDq|rIt=5Z&*ZXX_=QXnqYe1Q)4$6vYJ>?~<^m8XOIdn=I?$An z6qH!7uLuw|Ptufd;YlbD=o+Fx`+y@{dLX4hqBB{p7`XM5_LpgS0bgF+NCF=%lkm*g z^Zel%={?FNW30?!IG}(CP{QzxhyN3fhX~7LZlJ_wvKX70h;DUkhBR`=BldoG$j^DP zkh1Uyh7S68!99czS2y{pR;S6TAhxM?Vek7~b8WpJMhhPCqRh zpGZILvOfHBh(pV`{>HTFFR{FgqXIzPEEC4@$;a;0U+0u)NR!ZCb1qM$zjllL=oi!H zarnwcpSxf`s6)kng4Xl;D^s7158t%0ACF%4bJ!2)#S)U43bK?0&rx5GG8ExYueXs2 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%0AcM>sZzru%Cat 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 z

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

;T&Gzd!dtFa3!8YCY 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

vscMtR~dvRSMg<#=i+*U8%OK9#8$p+0Kp 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�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

4Y94D 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

    E(sttqPXZw2phSf6;#${-Gb^a^*$zGwMHx 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

    s!>(Tt0*eT^hh43F;Jy^GeRAg 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%0D>dKd`^` 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

    A{$JKk_5|pfe#qeWmeCQ@)G1>3;p` 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%0Dx^ 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

    AAM`6U z_(+!zynhVt8oRXpIr#4n|G?AGhxZKRgL{pd!ytdiH->wSL$%$7JD$}L`2@!nDvkFC zBfj#QDiSR;2$!NfeVC)7_ZJ$7{5+&xL*y62y~Z<#;CT<_V>aFg5P2r%BmKbad*NIM z;duxT*m)(|j~JvHf-C@g9i=yn_tlU~wIe3L!p? z{>6wN^?L+v8ZkVt<4@vV0OmZ z(uVuNkpEL%4JMt1=YK_e7VTG46r2@bA{hQIUyV4OX0h{P25@3O?A?pcV9E$5Edx#q&Tr^oO*& zvl8h6S|Wd|Cv^LOv;*M~(ueYxKzJH272$c@^3+V zgY9@fYdzktaeD(B?_;hG@DIFRLgg)dY!W>81Vt~IDaP2 zYOgd_#mU|2iSPmIObS173fzJBkzaLvBG*Y{DZOr8ga>@Mo&1MSK>WbK>&TuwqrK7y z=TrKkz1u5|hC4X?5W)w#k0QH00PhQQ)BPb_afGEIm&jer8y`)cno0iM52N_(Pj$nE zyyTO=$lJcCjnW9B|EzZBC^fQ;fyg^PxQ)_y7VTAHMXrjR*T!JSwUnaZ06Yu4Gm_JP zDZ&Guynx)3SF}O>&_;a;cWX#3<(9ND82ugEPqZ&`6~C2kx4TjL#r>jf6uxt0TcvU5 zePkE+T=ZX4`|pp|hyKq%em=adLHT;*|FwJLbI<1R@V*XEa~Fk_7}`c@j7I-dKkpva z)OwPwi!#_l||$e6m?)|Z%T=(95_$gdL_ zM*iiyQREv<;m7n{A^D!2NGCpx{0m==A9(4*^l+*(zws9eN4~Eo`Dk*P?!e=kILjD$ z=2xlvS91D&-x1#ZEQOP(LjHs7|H+$~KZ^Jw=GU*F@WV$FA7*~}Zxp_KmuEEdc@L%Y zQRZW8x@wA~*T|yXZ^g zHs>5lzkDCo;?M^1cZj@`s9z>>TgKm~OKhd@E7|OSG=G=Mn(7)x2h|M-&mc(7rjV+ciCOcMxPHkBvt-xSpFS{R#n!h+RCm^ z>2sE5mcNaDslFutcWFlHNmQeJVjS_a>R#gIdruldnkD>5Ip3kphxqVCemHd428!YEv zD13**Ss~x);qU*JGJnwX{Js{2e?aoTv9_{~Ao;6hndNUCoLT;E?*7T&t@l48|HOXE z-y54*{?>mo%Rl_<{>fh*l`enLgXr(O$KQG_HUA&N_5V?&`2P5b)hoU~?mU}W{__2I z$^RbLds07hc2M)DQhpFVzz)BKIA481?`1K6+{Nkjc>(hUpHTj^P9^;YnQz&N{5xx1 z!$>_-Je~dDH_!0J?Ek#qDc*2b@-O+n@pD*wA!{`0D#h5WgG#rMb6bD8BY-yawGza-y-=Jt-GQ;qq%c-BXh z&qe-cIh1~XyLp3;ml>?t{Jk#g_jG-o{}P9D809z7*ZW_vewz|6`f56y_(Uh-3pt_F zwh`~OC*EehYb_4HCh?-*&iuVR?=|8>?0>L)SB!blyO`qdmy6t0TK-li3O~Z~U;GIA zd-v}B{;abiv;1BD{;bHqY#N2*o4-sA6U z3omkL79qLGcMRqI{^IsgcuuZb^?17fK^%UVzY8h;&t(4L7so8{Tc2n*ReV|6^P|KUH1D`8&L7WoG%u(a+VF$bUD>Q|cLVRq7JubRE{e49*>$u&NdZRCgQ!L-@ zIv0%5b=$sI37{+}7<`bXBkY9%nApQZBw=CAkCc_|mSa{ia^FIwz>3+Hp;3z*-@{Yl|P@5PT$c@bXpp1eGrw>g{v zT+fJq(fhVP()~-mZumtyU(DfnY?iV4^PbrqQtO{5x&Fz01^ItzO8$Ro-{gNce~(zb zO7#gxqx|0~7Wvm~m@a3L|MV+~_qWS3&JsCT9KmV)y;|W#{%14q{W{SlJD{_u-`BMD8B4_!&c6c_;;}&u_KkztO;&qunn(KdSJ@r@1m|r!L^8=S_k9oHb zr>7O^aSikK#l*`vF~PjUrs#F-R~=`i%D*<}|7*U+bm7{73j9U#cV5XX|G*FF@^8xD zHI{ahqf>dDPT@uVhd)Z`6yD+oPFlw6poYEWrFrYM! zdxqSt<_I6y^FF07(XgJa9Nhp-lQYd?Nl(%kSCO z%N?0vwg;P3RT}DQ3Lm?hl*a2(^5?=$;})na4(kWV$TU4H%C z^6lO8GwDZvKVDz%=~Qp&@5HC-=a46mUp~Wnc!zw00@(Ex4Z;r8J|EAv&LI-Nu@Hsl zb;?&7@55cs*N0BbHyCp-`fCU;aa_K^Hmo0*^??@oNBhaUHaSE}_<7wcoK@(r~7 zy>s@upRp9WDc)% zIGXLD)<{24)-`?oVIA)ua*jpXfwNZ7^Z)I4H+v{&bJ|zoWvT7UXFR{U6wRA;Wo;FG zl-ifX>P6;>gZMcyqf@IOH!77!ucNkHO6`J-ci6jngXiIe&tr!jyj~!Dkoms1q=!?) z{JpoP^I_(rLpYs7sQ%~duDbI)r-aYNOl{sn;YhniwFH(lm!)2n&!aL60dhpRkAjC$;^tuJ(-Ag7eYusZ(Etd3+gu zCv*K4=J6$#W6gCwkE{IS%dJOpy};u?DThH`uaj}1)Pu1i@^6iM$b@TA@aim{FAtXx zFYR8n3&_9JBPE=kFE$hJ@_Jx|`J;GTB77M%wM|9SDixzCOp|SDOtgM8Ltxx z?=in^R=WQ+%=_1w3=0^!mzufyQ$xo>@P7U#z}F zKTF3`y)5T$IU2RQ9m!L8DZgj-qVT2t7QJn2?V3kLegz!Rb0cY9L3o?_#0(mbhO1Nj z((W|wMZ8sm_z3$iZBOY*)Fi%?`MW&YP~ozFm-!f{-)dcEm=(8Bb$ zFQ%7QQ`H40^7y&|<=1e>#q5&|*|(scqy0X)?0O#WEAV{tHdhUU2h=~w79kaA8B#IW zUG%RbxQ_x`Z8+D#e!^BEWdpiB48Mr>4)?*MLuxJT`gtoK?tpF&y$#qegZl&^=KTet(Ve=~;rI8gm*ejzsMX*>G= za($M>9nvG$jk-Ndu?sKdNy=yUc{``2mY*$GdB$toS=fKJ8)IGWzu6yTEE^#O#Y?cBl#yWJDo4!&^Deyy!8>Kr;z!G@bjpAA$yst zKG!o=ZJNIIH!F-6* zWB*O{LyY+d&)ZqNo-BGW5924v{=~ezd!0F{`YF8HGhR=<2uvp+Ji`+Wh@ub zgX~Wd`Blv89Y^w(c4l-x&PP1&wnp^xIPu|DRPV)^U%~5P*3VS$CYa~sssgr)dCmDd zzfILoLoPpRB|NsNUZEd{^XtJJkeL4R({D1R%U(nBka)X1#&TLsywq=noX^~<#7nta z$9l6vBtMG-DreqfKFItM=B>u$-)6p)^(o_+5cAvbqVxzqkoi5=6K_2<*D#|0ABGU` z-9znFnEe+^x#j&KCCo4RoZr_b|4Q`0<=GoZ>C6+JpUY+YZnj@}(Dq|e^%Lj*K?DWZ zItO!&GLO44bNP|=;UW(A6fW=TlQNEhjAwb@oVDCFgy?5G*Bi1vEc&U-{UYg)Nx2%w z;keJG>#YgL>)bfkgkM0>s%Ac3IgrWj?%|%2he@Vnq2y%;$H`dpvdi;G-)&$LFo+ebhAKMIY;B9iP{2^EjZj9KN%R`V|)Qzw5=|ai1~=DfAP7{66SB<@q@fqgn5V8&Fu)) zf1{bdk;73e2Z#9x%SZT9=8M^sbeweMj6Zexaq_9XT+02omM>LNiPI0RSlP{WR|sN~iIRAK_))MD*pdJgqj1jaSiE9?y44{UiEXJc#wndThcG zTy=Rm-<0_!JRc+B9L9WkFZR#tn-=q*olU&QKc|ao+18+6P!MG0tA{Q~&FKw7{{<`t6B=AHz>BXs1Q#D4= zB0qip#{I6AN;Df}aKtIFFUNYvv9JTL-wpdZ%r9&oXz=%`NC(ct#>)p9%+l(ZkMj$? z2N`T0j`N%!;QY?%gA8tb4A1wjrJ`L28QivnU$D*~WR5{<+Iq4Fnhe6;jzMbkM9v`W zZ8+8d^cCNM_yBhRxx2sO9%wa!?3Nm&G^%30AaO=5ei~_AMD7WsSHm61{#(O8P~|GJ zM>-5r8f$oey#z3g=bz%u2jP6}AT{=8N>AcDga<6ae3F@uKMC&xyf}cKjCR8N0@*In zo0xw+v$8bP{Lg7$Q3zHi)*t%Wsrvh%1pU8Pah|Mtk->;^n%_v?P^2_Q-;MYCvnIwI zryJNOBD^jbpBz+VP;d`q1bgDBB7=`mq3Zb&YgCcJ2A<&bS`{gcXN#0M4-i6l8Zn+< zOVq>jz@vV&v&r$e^qv0Po>Q}bs!wz(3yVVTo2Zp{w`n9bhrBVG|jA!tEft!mAco|&9T0nll zZ}(tb3+I>I+DHqK?aE~bF&Cct(7H_eJ9q%SpIcsLp3wVTQ}yR|qWQU4r_+>1IqW)p z&Pk^k*nQDIX^ite@ANXLi}Ivi!~7}SHF8mrxTn`rv4(gaXo>P5^-sCxu5Kzk9sMMC-nFe zSLk!tft75JmiJN`ZSEuahrj8iG&)Aep1{3Ewe4h&?dYX6mc5Vn&&T-tXv7aBrf_~f z67d6{UPJza%X=w}66jMUP>Fro%izJ^C_Uj%5Fe2361|Bz=##Ua&!oR6H&X~!z%@5I zs!aL|9@#)?6yHhu^d7ILG^S#>WaeL=tfvCN6Lk>GH#JqvYG4p7gkq*BI^1j2{T}hv%TckV^$eV?sE_;QDD`YT0~_T% z+y>|GVpuN+9!GxC{zK2zGYI!b`G9)}>C^ZH^@k2WiLffX7NO zUk(3q9ggy%%d6+KF-UUz5?k5^@^7OiaQhN_19sp?ZAT_btZ!q`Temj|&$%7vuK+o( z1k9m4bC?)5aTlKfN7`>w2;h?oA6$NPSqBnc{y1N!kL>bFUM(PDmt?62Z}=TXdm zjn_dIY)5s*3sdVYMsHpE+CiO@D28 zzE<8x;y;|nF*f(RMIQ(Ayn^_*_< ze~afAt!ib4DP(?(%y)9UHuF<`d=c}v`S=j?Gkkn8^Ksue=ex7g$1TtJ#v%Mzg(310 z^Rs@3*Ma^TCVC`|A6Z`+ayjA3h%#RE7Fbi^S@xK zf#|2`{xZzox*rWQ{uY_tFizF+#jm7v*zl+A=fa;h{g=grKRFI?(xtg)i^47XDF?V6>tMQHqmG6f(Eng^PryyJ z?58%dUA5|`EZ}%F97IXrLXv_QecRmgmu!#Uo;)E}{#kDbfy7SE4`m_PYB;{ENS+mphP{1jpT$=}oY zYnX35jCe`UXy$_@%%6;cj>|E>N{v30!})QBVM>|z8!i)3Hmmlowxli$<#zXKa4rN3v8 z{ded7k*r&Z{$AwvH8GU*TEzaVaX-*)O79h7zBcn-2Wr2Ing5&D0VJP=nQy@BcWNpG zhAYB+=nhUN^A7X=^}8tZ?dGw6?q`t}*)heC@Wre;`5iMq9p?6L-j$y5op%N*^82e- z=uhq3H~sA#O6l-^r1@HjdgEopJ3kOF`Ww87)BO$c0e;}@%aBL30fcf3LUsW+5WWL5PoX+#9eGq-u|A^CLQM+%m|LWYom3So|6mWTUT2MG4 z_W!^i6pr|pd{DsWm4y$p|M~3S<8+oV?>9tmVt&2y{kEy)PxQB`H^%R)F+cq!$;w;4Lo^H^&TYZr@V=q~mdiz9;yvbr%(uLnc!$TYotW<|{R8F;nQs;)|I%J| zVZQbFbiOO|n|$*R-I(Xst1#?}JGvPa+_ur^@7Q$xxnH9Hxp43KMf=x%(_d#!NBAO= zmqd5J=!4%=^yEB3?<3>!`uxB|=0#pI-E}mF@A>8d`uli`!@0!Ai(Z4wOZY+d|1-B+ zlAcb?_xLhBohLBglfx1JQV)lG{yVe(VxRvm%zw!9N)k>t=KV&P37gH=9}4%@^=G6x z>F+5XKkT^__2T1u^{0N@H~q=~3^=kt!tuy@vG7v<*a>tP??hk5y51)JjyF~3FTm6(_IlAS9Ik(-!zE^M(W)BJVGa%$JCWqd z6n9c?Vt2se;rvFU9D{CWVH~>+^Rx8{MaR=PEdY0o>KJfXa1X;>qhh@Q_i^CutI&q- z!r%>a;2QHMp#OU)&I2}te?ZnF^qQ2$5AdIO5n;nkqx#iI&&%+OXEoOF^Ksm3lrM&V zgy+Jq#=OTVeL=WsJjHew_ZqUE5JuWHawlROI2h{*xYuY0yZ0m3KX9+ne?7v(>Ua|O z8uQMD`_EWEL0lS#VJNNV>*cC*Da9{#Jq}F0Iyv-wDyQ#7Z(`o?!lhd?=`VH)_e=QP z?rxv{igd+-ajJJ~O@n|QH$$HR2Wy_d7jx?*y!I z1NuCo{=a2=9R70{sDtje&cBgq2p^D3^d{znJs&4C=`YepPXr;%4peXIeaNZh@3JKl zBAK7-_fNSJ+fyvKJ+TNsC!lN%#6|(&?(5RsABDSfBFa+N0S4dd1h#>HzJ3|QH(l^N z&}uo^?al*~#uBRjRp{ga2A{D#(Px0t*u{1`1pmMvAJX&TGX^LP#p~svo_HQu#Nj94 zrZMmdT7TkHsNgy2_SQSn?ae<{%KLI}d5glogZwPlG5Ej7RQp84pK9MQ1LZTZ*S|a` zdK0sx>x9vn^p|{%p0Eya&5aH!Re!Sn?sdibDIn{!cJ~HKL)K@LaMO_T6~?`WE-(KB&A8d!z;&udp(MIH$l$oj3-4eOR&9t>S&7*pqNXuMuf?j8EcB5{-5c{uyw-18-HMHHh*JxuSe$2Cn zaIc};OZ$Gz6Q4K8pu;KXPvH6R`GX9)494>hVSRn%AcKMvU`P9E!(C%(53(omyv9pt z5_J5DA@C2pr01m(zkLz>1AR`V_#<%BxDa-05Yl%6o(IZG5x@42dyVz5>-g0Nx$a* zQqK55hVL_V;-6I~r^ngZ1G8*yq6xM9Z+=54-(n zM}yHd;r~;l_o0pkleGQ9S{ReU9k>$fGG1-ePqSeMHg-XH2cdq$y~Z1lQTr3d^BU8% zygEUDWgQK6L0*Y3AkW1e4W?^->_q%)5FT(zDb_#VKz|bV8aM0p9k>Ud>S*wpURQb( z@xiX)_DA~%_vEwi4>Vdt&%4Xv2CRhs6aRreH*_>O>@>uupNC!J2=o`iSa*tj($SzX z{@)?2|370B(gz&G>w>Wj$106A!>E5^eSWOc_?!1r*$*TAK(y8f-Dg1=yY5+Lno=qK!#0$MIX{zCg1`2qiL0?2-+$nkZRMyB>uzhAUw zeFNQ|>i3J*f*r`zp6d8xhtxOF?WvB>KDfR?HvMj-Y@yb$dFlD1o2Ry~Zp1T>CQnEH z-GxSq*B7l?WrjyJk!I@kMSYE?>Re?zzbgCNW&J_&$>6*P%=6(BTw_}17kTMi;;r4Z zt`uZ`;uplbZPVwk$39HFtY;Om|Mk4C;%%b#JH&hkUat^7m(#zS=Vh!Fj~bsI^92hj zeAQ~M;X^DxnNRR|zA4OnoX<;0dP_n7C` z_=n+gdd1B9t54ee`Le4#^US&}C{K$~miYXhIw-S#?aNTGafyEY|CeAK@#FIU5XkzE z=yx>p)@KyH#SawmI*ObFDrDZif#f6dw3&bWqI6#LJM?na3(p6Oeq|j=&f{VF!(4Kn z%<4|-E)nKGdz8WveU&nQAMeYN`PwM+WA5ejY^QLf`!t!?$L!yTciDgQ1o^MfFY|}H z#5>ElAIp3;qul3E;A|YG=VyaFzbEtSyB zqPv3k4+)>k4#)Gp8sSCnJwK&zH7blx(oQomJ6=L?uum!}9;pF8tvfPBDisyv6(yUdNa6)sp#(nx)5E!2C1Ji<~7t zbiS1Q3orR0EdRg4`w(mn=Q}#sujZ>YEwBz-3+LV&AU&_; ztLxA&^WZ;Rvp@yxeAR3r;x9t{IR(l(C0|XPK;d}@7bs_0zUpx|=5>%BCjk4Ze057t zgpYYJ?@;*Pl3y{e=rt`+(Vz3xE9jDVuc4oG2*O{Uuf9Y-KJf|cb&ezjeQetn|?75*$=y>uPY!&jsX?>~qeP;jA_^Hrl= z;;NMOM!xC^HS6&7&SPaUopK2lkd*de;&(2EbEm8=E*pk*;GBhPzSW0-#Z02 zKu;~V?=c>=>ll~~IIw%LYe@gpgv#+{eWIPe;@0P@BtU+kE~;n z??&T&fOnsv_YFd@8ZVFG^xlH>0zW-VcIWOoN~7Z@*fBq8^@F?sxkRsG{<*7T#_x+g zsjHRo_`XudMfB*kHPZAeRQ-=O`Krs2DkysMV_PaJg_cK{@sO`kJ3nzJ-7(} zX91Y`W>Aq)n7;xP|NmRy7Ni$=uQ$?$^vl(WiilX%cB&>Zwi;+4-;WGU$NyPqJV#!W zi;*5+`bT7sBW{hA80zWEyDMbS?l!W=m%$xaF@@gWc^2{kx~?L3=MLC`+BcAU@HV^; z(CA+3NGHc3K0q$ftC-);F0YlT{O;;c&xdmsn@9Eet<>@>|1)FeD+dD_9y?&osbtWI!f=89Mel_$a$~8i|ApR4Ao0ros5_rg#>r!cBZpAK zW*tHER0YhhDIz|64b4;O=3QU@c`)0s_+A?OPjsj7L(D%d>s9Aa`iq(O&zpsr_s^R} zn16FTkE3~>#9`j%|LKu&Qz`Qw@wph8?}{=%h4-lm?=rvjPHx~^%{5Gnd6{Rko*~|2 zUgp{Cr{)-D4f6>$JvP7XnWw*B(8OW=Zn~0OCeO$I`3?u;!&kG7PwxnlPk^5jQ!POs z8kgv|;(t#*r12ViSNXjD=eElH&_sRLAXDOTr`|tEHg(LGz zQRe;mZ3gqNp2PBFeZ`oMG4JsI6|G=?6VIc{_}XJ$@&0k)UuS*_uWJe~^1q4qKMId( z++4YQ4pR6y^M71L=@fng^WXWx*~q-(Gi$#SPy0T?Le}qb>+%1SE6|VUeOd02nf2?U z9nhEP_dh&OsGe~RFF#?C!^sp*E<60d`^xP1DIW%y5Ai&nbrALM@|b^`&uz*6cZ>P> zrBuG;JVF8UtJbi5S}ZV3kolt~6EEi=3Yp)?>6d&GVt&r|>G`3U`34-m>{~-KY_85< zrTgdMgIaS3*8@Bs5@!GF*Ry}-OPGIi7WtR|(~2;^jCnPAmSILSFLD+0)4rmkFX@D~8U5XW)yE(LyXubhH`p~s!|q`HJA!)+>2F6>AEnW_ z8vJ8@)zxl*d{5THy@sqeC2_AY3I*Fj|HV40kHM~U@cefeKf=@EH1sDfT_^@8bRB zDnt0G&kOH2B=XQrJB zuYtWTVsYCU$p4pwr@;;Q1@lsB1LQxaox#gjLmmyV*YKWp2Geus|80|Zw^JGoMq(Zc z<5%~-b_NgP|8I4C?qt}3ra#j7)_oXujX30w@mu^Zga_1FPx)Eou|mr?yYNaY}z;A>;#Wd^_A2N{|OTxfRumtW26m` z@}Jy*_y8&Y-l|$kL&|^hWw--U{@pk6JW&5hWRH~cum7)E=TEr`us>Co|JWA1AF#6@ z*`05ZeqeM%D!&%oG&*5@S(krn0qlVN3)OGQGQ&xn=W?(sPdh{IgFd0k8VOTS=?kC%0i=C`GX zV{tgg`S_O1PvZWRgkQk?EwWzC>5&q+$+tckWdAqvI-Z1s=F(i-zD<{#^gDiAoz8b* z{|)$@iG*V_pUn_?i@EB8BM#0~{uiEy0*}kRwv5cjbJbzE6Zv;Rcgfz0`LcPP4YpTD zeTMVcG1xV%)l^@H7Ian`Z#Ad-EIhxn(zxy$)K{x(pziBz;PxT^7VH}LZbf8px8PUf z>E-l%^wG}vW<+PT76-(2{TPLtMn2jTZ4bjuqa5of=6T#(z^x?|Ujk{<*v!v+aMP&y zEx9|0TjN#ux1YoR3&Tz0PP~r}&tBNsKw-auiebmn@ zxM}>Z<9{6Qk9&<4Bj|nYJ|`=UfbP#={w;vCYRLFM;UfLOy}ihPY%b&t9Q!@`2R~r1 zdHXH~rMcK|^$OAlyM|old?RM-vM-L+<2N~fxqF0Xd@Q^K=^fcnd81|-yVI8Pfs}hO zy`facmBG8dHu8P~IbTRDmN;fn{*``kE<5U4rS&^(Yu&_{l~80e97{Yc>lxY zN9M6|*`fJM>HY)Ed%ke;n7>Wtb$DNc#r)+wKV*MC&oBkdf6V^fdNlu6$b7}TU6|gh zh{pZEZH|G98xGt6dF!NR^>)|%qr&hxJ4*ssP`x~Vv!u%Dlk$;)LbeR80 z>X#EKA4QpWS3{2={ViM>z)>I2`8`AE)%`GmsAAlXG(V45WwWWgMx`Kqip>+==K@ z52iDaPP6oLkV)8OT&d4MMvg@In0JzMkS^l;e?12&au;*fGfgti|Lwx}i}dC0c8!_r zT1DwGljIw{zNXOsjl9;>AfUSe9_C|U*Z2Zehr)gq5BD0S?4H2AhMa#?uQyd1qQ@Za zHRSwb821`-{xOPs4ZZ%V|9>)$dks1NsNO($fauA_y@vFk9o%b3|JlX8h8h1Oy>Z-Y zh+dPp*ATs0Z#GpLqSp}aHAJrt?lsy$&-#384EGwM*97i0M6ZF>O_f1s$m>J&_rGpp z&~Fspuif7HzsJIG#}(KNcR*nuls+FR*T`S!F8oastc5mFHA2Xj*!LA{jrf70jTldC z!uiAwh!4niNr+-@d~a9A?~m#Jfxay67wCRKYW}!(3B?c^it~uT;X5#Yh5TU;!}&!( z&yVQwP4LJ52A`i!{#Eq>N~3lWm8(RuztUL$6uG;2RwIG;*H?7Z0E4D6au3x+e86jL zCswIZ+sJ>c-T8m35`_Ywc40}N!oF9y3t#}D9+{Gbq*#(LQG6~B6b!Ptw*F2BcY zp!Z9ZAZ@_-Ybn0K!8i{JOlNzj2GR#KyN=u=BL*mq3ozfK=Ziu=^*4yXuH_TOyK8&| z{p$3Dkrs{9S4hlc%6ZHr;?}r|-MugRD~+4kp11<(112=${Dpg^xyvb>;N_49knNIu zA?DeSY`!Ja{J{%zIfOQRgZ)*h`C}030|)cn)};dtnk+$J?8pK zupbFncturZ;XGt;*g%6B7?0b>)JD1o8eCY8=ka}?B%aq8g7EdeN$0|W2H)uVNY58s zGSDE<1OAa8!*JKQeK694_9QtH&jVGzgM9%0|NJWW*U;mAZND1#zzj^Jg*RaRVL1L@ z9XJa~Pi(}`5TqZF@Bai5wuaO<>H@d}djFR_m-5?O5;KNU%7sN>vZ@9 z+TpyAet&PkKm!Z&+4}vxlVJy5N|L-2d5{Mn`@e`)YGs7-Tlg@%FYo}C-u3^@Mk9D1 zVD3%u33K8mvR#rd#N2%87h^KzkHo2zp2QtxCMdnWkeWYA?tuK` zXg{uLYp@D-%R_xSt*ybTGx69`=Nq zZfkJoc;pZ4Lk+)(=K=RF)TdwL{NAXx2G#^BkKv_o2M*ne^kRL;S>Dzlg!6Iw`QS_V z?_QwFHlz>hUCFE48sruueVFeFBRq|t;I7ZpB_3>R;N45^L8MRPi?`s8K8%a^(a`OS zK2Pr4g7|<#QJ-qNx)tdM!jq_ea9)EuPiW$2W67JOpX76TUorMZLtlv>@!tn4uAaJ-L3)u8?e6z zxEs%#^@EK_AJ9&xzcIeI{Vn!k1LxgC@^M~<9VkP7NWCsa|3N<=cpCBmcHPMB$x@^b zDA)DJ+P(U2za8PF=sz)-!jB);T4@~nd}`=uqG#j%Az!)leokGV$TjLyxg+y-ZBOx^ z?z-0ojig=6&bscroT^o4`uE@G%t3zr3g@Gm&oKTiyUdsAb z(-r$mgr~PxsyELc2`}TGIXvGWd^HZp>PzD#;bq+;!uvB+Et<~~N#*t-|2EHOpxH84 z-W!S|`*(S!bi7V>Aed===86r;S`&5*y~-$i?--2+EK z-*A`q$T!Coao?g_ZZVLuWRc&YWpAIM*+_MaY0x4(W7^q*3{eBC?UzTIbE_n&n4 zziMHAIwk*og!R`{JB#5ThRuozvianIjq%j^i-{vW^GtD7w4ayl{r_sa2jvemd*%{T z{(s!#@cy^|zxvNVN#BVpW|?$^I6Zs#{F9tND`DRM|J4rjoq1kJ&hwQr@Bja5DjiD6 z|5wYr!%X(yZSHh)XSJd9xXg!`m-I;a@&Dg-oc%jIUnl-IGXLJ66n=ukPcrZSf9zbA zzyJTSE#^I*H<$VJ0_Him3d7|)F%Qe1pZ5QfgGPA9$AurGeZ&4Vncoce%$z@DepB*C zw(nQ^=e=_|9Top)UuC{w0?ePq`<)VhE;39W^HH8R_7>B8n8o}IA78-yFZ>-u(QAABq`XjlX<8_bG z%$M^#zof@u{twwF#{26^nU6k}9!`|`1&xSzmd-WI4CehtITK?3{Yu%4)cT`3*B^7| zp?xf?SFu0UIjzh*DfNb!vOiVwhyQ}H5dBSMUcxVB|Ep_K`Xzjq`7zRN z?xuRBjCt?6^mt>;FZb~)n2&Br_wO-3pTAcu@vdS1cAx(^^ZtFk8=3bTd0ejq*o-Wx zu_!fvOym6VPBrudKC7n^t*JeCi|7p{Ux=yyS3_TtKV%(D)ewnL3cB&Uz1x4WA##aU z8+lzz4LM?oYhv zbu+KaiF^_q&PeXJNxQk5`B6Sz+9P(ZFhnn6&K~Z>ZywKtcES$Kf0y1T`h9byA(!L}F;D(B|EWy*!|qAX zhsTxCqgY2v%^xzp4fpAxG|c$+yPC?uy@rf$ZQN@d4gKi(!dMaf0y5sUruV>i)O#oy z@5U~KJ0RoT@DPL#=<#kC3c0iAJ zRZGl=&4wGG$GaBX6ZiKp(BoaF81q;2dKl>OZnzpoYr}dN$avQtf%pI!?NEJ&kohqW@1h~|W6@iWQ5rHoX5-y8WPVJ_rOc0sefy87pI(=F7w`rsNAT2QB+%cc%Oixs2=6pJ-eW>{cZ$f6UkOQw#8Z zr*tqVNBP!Q{K*am?zLpMPV1mFemtH0yWKh{jX#UXUG>BBK%CDLGpiCl`*~r=6YCS! zaR?6>{sH-nweNuaXdTq(Wn_;B5f%`gCLxizohM47cvj=;XO*&Qp#FHFgTX1heiB*K zL20bPdW*h-k906-HHPfbDR>_E3-g=$vK~izfR6c8oPgxurP@IJuV4Jm%B4dMf4)Ta2NBaj~8Nw$ZFb-?-! z{P!pS$xetLh;=2q{9bZD&9_8m;C%sA_0Trgjk@;wOGo{G?7a(^9aGviyhPABkc}K# zbSURe#+W@0NfU>X1TB)-2->-FXgYG*k`B!{6oPh~?c5Be;uyv|_7Jpl83`>;dyGRw zuoHtum^}s)#?1TOPp$juRMm96@Bd%l`(5+@*H_nd?^^3#Pd#hZs;6q5*LHs4%$Pl8 zx-)0qtmbJm8+VyGueq^hWW*hM#;nFU&M*x*Wu((MYtrNyjZ>Y;vuDp3>CA1K*F1Ih z8MEkZYMeB+an8|mrZqP=DtGei+0AKAFFT@f<|Jp{v{}u&?FwCurybEeX-;!Q4BvgE z(>!g;^tqOTNEdU!tf@|ye`aG!U}j@194ZeQ-KB31Qa5eZDP8y3JZI9B#!>T5&Na`$ zea*}_pV@uT$@6B+sK>SI4xKn@+Klc)B~IjER|d+><|V$l&6B1~pEzl9S5TB1+)TvI zXcUP#NbOu_=A`^_)_sCpE%{)*M>L++b#F5#&6$4m>^ajL=Zu>)xpBr^=eXUvq$kfi zd0aQo7j!amn-$JEYBBb#-wi!4oU*vv{o&@lhyMHX*Eh~jZ2v=m`Mp~~h1O4XesAs? z%-;p>ya?|TzQ@_?_KL9h1qj1mxfb(ZfiLL~5H9$`{s>2XwD6~q5k?(p{pRD5Mi3qX z`mFp2-8EFyJNqsoP_Xc5tGW3Z*kGKWr z-wpX&ArH6Uaa`|1pAT8Vi5*s75pIFbzYRA<+JGBTEs_4sQop?;9C(!V=iwIw49~(X zXurgU=inB6J;VAlnZ1pm#BdjG!A1Aj@B(B7*U(>qTQFdz4fp3Dy?{f15n%$IAM7G8 z1UkPVb2a7*1D7Ab{DQj-6!P#(eytoC0lsbzwHrO}Ht*^`bXWfD@u9ukF}8hEzIUU9 z{p9dGLd*yE_8b?XUFKs;{Ckayuu&7jA47c=;evfnvEd%V1wa1;`XOI{ThK$sgE1c> zgj>)6`DnlBk>iXDG#+NJ58)OJp?n2y!MO+*`TXAFBHSqQKgD?BK8PPU_XR}P4tv~h zT!cfAKJz%n58)Slx2+xTGA_b_%yu0ALRcAi`X1|d5GJ_wUF&z@7CeIYN9@UiTd?~J z*6+hD2rt6@B0mDS1y?XX%5V!D*t=Yx*&lHOtEn#wx8Sr(?fsYF7Ho<6?2^AZxCNtN z@6q+6a6NFmygv@cFX0x9mHFxN{=hBhf4J2bz%95^^}}5P)^#}OGLs|2^MOq>`^WoF z!sajv_txP4zwU>!(6;x>$1IHa&7)szVb8O74AO;TnLQc(KO}d!?cbo7S<3z+onNZo zvGX|}S=YZ-^MV)IuVPa3NbAU#Z@nXutfl-uDL%&+Hi{slxO9& zpQMxgVZ2}W&|B?&@Oh3(@m1t|&ais4KTeXX*4X zl6YVx>UNuN-nIVNIlg=Qk#>_DYCmtVpH2IJY^X7-8f`kA?UVhmeSc;7@U^=lQHK}! z%PIe>1reim61-#WS@%uMQvTu}lJa%r!(~a{B|q>it4H&*p8TS}Gd;s>zg&)d>viN0 zMn@Bl2J+rnmiNAp0ugQe=ojIs^-xXZxBWf!u%8~qSag&)@7}w{-fy1#Vf?>T-8a-H zuj}S@9&&+v!yQ(?v$;*beLIkzCoPY~jge$P`8Q}k{*B3gWCs7sDMLojuWdG<61N|n z-#QWN8~o$&mASy`^-i?*gRfq6=-FW2(qJ&IrMu>_dV5-V(q^+cO#g73{wfA^&2xI> zFcUm}n9+Go9{jl{4l_E>$$u2{gq~hI}`{u#_OLOCJxd@}HtpFGUyJf|YAH}LB` zr_#gNgX*!vjLvhaz@J5YnNj$xH z>9amJJ#R4Ux82TP+V>D^A>~$U2Qp5$HI%8{Y5gbYkG;A8t^Z^PV1Fw>>pub9g0A|{ zz?|^_t^btZ7HIva^vMJx(E5+pIl&0D{^JhH89`V52VoUJ>p%Xd6O2IXKbg-ape~7U z)_;n)R-pACzZ&~<0b2j5z%9`FPi_nB4F+iarwF$|>pz*nkOj2l07%e88jmtAE1$RX~qgI@Au1yXfsH^8Lwje-!=x$o>k>rki6fu>D?_ zxzB>m7tyoqyHE|CdFs{q_0A5~?lj)PT0gnpmQ!lK>3wlDUFrQx94gXv-5Kn;V79~F z2fHI+zl~5=gd2Wc*DZTGl;PKP+_Hy*w|#OShX8&ZhmbuS%JAztZrR77u)`r;>$r39 z=XOl)<6w45?&DB|ziS=$wuczE_K>c1+p=dv2)~X?$es<^p~-z4%JAzvY}vCR7-wAu>(3`~oLtw{Xu2C| zKUz;#`_cVZ%8%QAMzx>!b=+;7tuKj<%F)DnY`HFo{7&?X{lagv<)f|(&62;4`|fDH z9j{e%WGC7BkMb`05!@HY&DwfMJ$e6Ft6%vB^37aFs_T)O$lv{BQh#3cbG^IH-)bQr zaQ=mpwe?}2{E1wzt>cxg6v&S~-QJh(Thm6q z=7l65kniMKufOiD>A#HI&keL6AMc<#I7tRF;-OMY){?;K|J)RSMu@#~=4@;UNO zmCa{wpCDq?98m632FM5k*{L?U)w2V z@*2OMZ~r=Xciet9qy1E5e(oK8y4qjCw1trdwHrNa`%CRdzdyQf6Qec%<@e{Qb$owL zSjYEg-yl-$FoOTx-=Fg2?!Q0EH!xoP{+Ne?h*5j{fBXIMM*h!ye@^5+dD;)4_L=_v z*r$xS`l;_vk@s7bI_HkNe*5nF52gJT9c*_=JIeu)v8;)=n;f)t;_W7BJH^{g(st7I zA<}LV#M@2Mc8a%~r0o=MH%Z$m-foh%Q@q_IZKrsxz%9`AA^vBm zp91$SMZKbo{=LATuk4lO0`voerNb5DE4h{ZBK-6hHr)LNX$3~Z zFZ%LGt3dXHmBalG;lRz0*z{KrCOCDf4bPV$5A6Fk>bZxa9q}IIfy)Y*uLFMwx8N=8 ze-(wlk8t3%v!M_B;f8oN0`tAqr@y4^8yO* z+VqtmD_GZ&wy)~C?Ur_DU+#rAKZBcWx#VK}eH)37imzHf8NAgtpAIA1FB=Yd9W=WF(QuRPEQ9;83N&mheIA7sA$ zl+SxV_<=RQwDSJ<1F~EmyS+MfX$U#Q%%%814_}f4u z2pL~6e2@{m%JAayfktrd15DrUgNz3(+lc)ob%RV9aL_K2!~JTY1?LmwKSTV$^RQnT zkMJKrdVwpyj>L`s0sKH`FZeOvpnx!e?hkLqB0m8gkGEGDGviQo+4J4sVLaqJJdeSU z2X4mq$Hjb?5_AcM;W0(Wb8rBwATNjWBJv9;|H}FcuOfcnFAUGUg}emLeG=hV&zpM` zen5{7I<$Uu_SH*A$Lm*jvwkJ}FF9Lmj{jn`<-M7^FuHO8uh+AT+saX8v)7#2X4?<` z%eMYWar4P#LF824US-VH?^r%u*%pPX{oe5t`vFzHItsQvL>&QR1AgSLaKX`c%xisE-@}IqzgZ*DWN! zKL1xo>uE*udMeSO=d&Mt|HQa`y+Qku^>x8dVPD+8)#ExlwJSYq{ax)#$KQe)n=Xxa z4d)k!$6G$bfby?-AK%#ga>!r$#0`;4+hJMq?uS-h`Q6D^7FfRgg?;hVUP>Y5C!;{X zp?1+@uH`kKa@2F)`pJ0pIlsbj!eA?#{ygRDc1-H=mDfMyWjnr&eAQc4zqb4JEj;-~ z%R2*XeI%fK>#}5e^f`ZeiH%qFu=;22=lF^8|3N+F_nFRptcD`_GtXhXKiGKN$v@go z{urBYA^DnjlY9qxJyp@6=U&&3KBT+y@%xqdzFvg?*H~ivBc*=7Ew0V*`ro;>JkFNU z-wQZnG0uTXTKFRRf`R5E@%itC@9|UUZw0iz9xg#RaO!==1TSD8jTdqej-QS1_iOmx zK8N}-aLZD}eR$OWIl~y2r z;JPnt!o9a359BbPS<+j04eEAWw&!*&ur~G@T{G(F-`jme{%70yd%^7>XdqOfjb5ip2Q~t|R{=3m$ zkoQNAV#+`6?PU0|DgP?S$Ma)#%3r-NG{>H=lk(T5{F;vRxtfHYCtUF8H}Udy?5SZS zA@jEb{I9o`uOa7gYqLPlQoh#UiU#V{@g0BULNfML$9Wyv53KfId#HWU-M4M|s^8c6 z{P0R@es~u1tK;*-z0~}0H#I*zNX-v-Q}e@1GDkc%Kit85?D+ifLTY|^HZ?!oPt6a{ zr{;(IsrljM)ckOR^u_0gms9h@!_@rn{C{J9_RuqNB_HrYG(1dF_|yK9_2L;Z$2+2sw{R z?XPtUYnR>`R*$|fUHy8`VgA7Lv3@=H{TE{WdW$h%VQH*i5B}myv3@=Hofl*Mdbr;0 zSlh2>#1H-2k5~RZ3IO=K`tg>apYY{aKOX$vE3tk&__MFBo&ONx`VgGalL(!AAbbV%4Te78sTuG;jQ>;F0_g=V8in{4RhbOr z1${?D|Ndx?_ueGJ66lxqqJy*wnuc3{5%()-hd-!7`+Nk_4{SOH^>@r~clLxl;9-9) znO_xbj`RRBUKahINFSsZn0guf@1eh-YLf`ko_EVg-&RN;(1~z^{K&v9sOg9FBENzy zp$}LAd4Cn|ZwTT7S}w=^J%Q_Ma6NGNF-X2#4_U$Eh(GuM?eFc7K48rVgrk4A+-s8v zXXULw3%}rZU)uf+xBn(4g0wGjI74wgP(uH;|16Av$H=p+BN&GC0S)`v>vM1m^zi9G zbkXtqjW0VR{{7o`dKmFCKhe#t-M`tr)V^VO%+aA|nYXwFn84Cq^IP4ctvqSdG5*HL zsry2x{r`6NB=7Koa!S6A{QZNH@;UOqCtp6uzOPN>sd<#S0m*rkCHUj>D1FSE zjL)O2z#pF{>0zE@eBNU@HSaONJjeLF$IKS!m*Kh(ne&(j;`1I$@W3-V7Y!8=y|6ZPt_q!VF#rGN;;Z51! zY9(H>v121V{t<-H|Cb*&HbQX;-j~<$eK~M!gm1-vE&AVfg&zp+gulF@@#@D$IN=n; zFW2vg>wzr#7t6T5c)-{Q<|61Hh5hvgj*T!B-_ziGyx*h8Mkqku!T!CueUUz3*2nlh zAbn+|Pf&&Lql`a>{l`XFc9%_$KN$Le8PG4`2Kofwx-yY7(u!X!VOU*dj%X`ds0`Fjoo%_@2Jj^0_omZ*zm)gneyh`Oe$QRzT>CyR_ zTEFVcaTi?=Ql|V~olHN+fhy#0y^wm?o-urWHFsNH*L_rxf1Udxss0T4Te+@EfJkGx6EH*O-I{=dgO`GWqxBJH+?{NlkkS{L~<$*2EM(kHL~1L+!@&u!!n;ir}ITilwa4WgD+qk&)ZMEWZNFG{|73c z6-JjX8->0d9QyxYg=?*SR!1!6d-HsY?!&ZoK*pY0IgaVK+wWo(LvQ0gar)dc3@GI<7Io=iL_%1&s9mj zmVAZtl-0hn%JctSl&>SdX1vv-@w(*e^}Td$ySZNFInUZ9pCdp0BCALF2J)w;c#pjP zFLJoA)!#(^H&eF?^n~WcJp_R?}ztUI}IqmjOAEBduS)G z>t8kfA$dmMby7Rg^Vd&5b$xgB&x;SYmpD259W0?LwgV`&C!OzCS>D$Oddm3lGaH%U z-M$g-NBu|YAB9zYBP^8q%o6O6RE8hW{{sl|M+X8U5A^d5jq_gL2r^&LI{^DjSNcZy z;TY844n+N~cH;=891Du|(NG3HKF+4s`x5fNFti`#2sgkUm4JisW;wjx8%H>g22tK| zV-gUrXTsBm96Y*OB&u2YEqwFzV~Fjtg!2cn~{Q(EzwFq%PA>tP3|A*udCdf+r2IUl<0sT*se+6*^e`>Y<$_c%V;4bKw@FKzlok*Xg zzXZ2n&d~_R`(vP65Y6Al__B+%3bZ|wfm`tLK~Q%m+BM*p!S*n2>A=BeL4sesC^dE(J4^-EJ9YG_E~^ip!QjTtU&G4`4IX5wNDSa1!|uj z!USrc0o($$&kEcEwa*;l5~zK;f5QC$YM&*zP z$a_HTvjACv+Gieaf!b#YvI4bF^FH(eYM(B23)DVcgbCC>eYgc`pCz~jYM)ueB~bfx zKEV9|YM({KEl~T+Axxn5=^<``+NX~&f!b$?FoD`<1#W@brw82vwa)<83e-MBxCLsT z0j?FOeU=d>Q2R8v7lGPm7P;TEWU`p_--KV_c<#4XT6?NZNgy|~+l z-Pz}mDfoUCF#mD?AOC)4_C)ywsC^dB>um&TpXCwwj~hVkGaT332-H6P^Lt|-FK{g1 z1HZQssC^olxCN+v`iDXuQ2TTcw?OT)oI`wo+NXDTZzE9qEFXbzK<(2#x3>|feddnr zZ3Jqc-gsOOblK-o2nWIH2}f!NfX&+Gh^;B2fGE z;1+24?(Tv3fpwMdehZ!tpyhiRvH~sN3vdgxe9t0ofgWm?dVb*H6T1C>w{aiX^4)9x z@$YBQ7xi60?X#5WYXoYaKEecQpP5ZizXsGkGn>K>sC`y&tw8NF2U$UveZuVnYM&u= z3)DVCgbCC>O+Qp*0kzK@+yb@FBH|LLeFg{BB8h`z%6Mp!Vq@tpc^r zEZhRMPXk$j+Nau$+Nb*0WuF?Z_NjigPxY&PW)QbP54B4@|9rMPp}X(rjQ_Ou=`8y3 z_EF|-)TaQoPiHyGM?mefg0_c1?bBa|@&i!&^dKux`*h(JsC|Zz6{vldC*yqt)IPI_ zTcGxtJsIyKp!S(>?rj8WpI#Hb2Y}kAL0kg0&kEuasC@=-3)DWHcW{4z+Gh@N3)DVy z2otD%77->;`z*sPQ2We5w?OSPk81^Lp9OIPYM%vMD^U9^B21w6S%O=j_US;kK<%@H zXCYAg4B!^1edeKC@PEoaeZ(!$L+w(}<5v%;>CQfbXK0_X_WMpyqWw$Ses^DnJppQ; z`4a9AQ2TTcCQ$nvw?OSPhqwf4pYCh8A3*K1gt!H2pLv7{)INR0El~Rm5GGLjEF(;y_L+e$f!e1J zw?OSP#I*vo&obNswa*Z`1Ztn?Ji?~OYwgp4TcGxtgKmM^r@^%Xwa?N^xIaMcGeDRi zZJ)Dyss-6|`gtjzuJ3CRX%pz7cB|)xYqq|oJNv!qV%z@|&RSdkcW1x;MksFp zwclbNlsACduZJ*!+Ha)_b5wcj$r1Zuwy?p2`nn}b`R z_8Y=2Q2RAVi$Lwyfm@*VYalC7`*jf}(C@1Uw?OT;09k?BuZy$_)P6H?3)Ftga0~uj z?6;uq4?N-lAr%ZXTJNsRBy0u?#_K(}I_cgwEfZA_i4ZaPzW}x0(&xx8 zK<(E@m_Y3}^C|2TQ2WiSh96M-t>9XL+HVfB0<~WsZh_iw2;Bm;-wvqE40JYyd+yb@VGTZ{S zUkBF;)P7yK1!}(zWCd!!9>N4_zdqaowcjFS1!}(@(kf8<&B85E`!$di{JYq125A%M zp?0h1S$e?#P4tUzp!8P zCEg7{?Kk@s-e&+=7>#e2zrgneQ2WjQ8Q&j3?Kcluf!c2lZh_iw5wZfc-!j|+wOZQ2X@|CQ$ng z5GGLjEx|2N`*opPp!VzIT7lYc0JlKx*T=O2wcik70=3^V+yb@V40H?BenUJ9f!c2Y zZh_jb2i<~y7yHd4Z2~=XKCYhK!S0{q^II3s3?tE=PhdXElbdzTZ!JHuFygnMB0cN; z>n8iTHWjY-a(4VRCGBYm_iu5;FmPx;+~3dVe6}0yd^Vler}Jdpoo!V*x@zHsG zTu-L+=b&Mw@~`rLc6EMZf&53@$5HvK$(wtU>1iW>8t38qzqIKI$h(}+tMS^WW6aOE&#tq= zGDXUd(fxn8e{Bc(^#1^q$oCv!=gFq`CDnbYb$)l5@{e=Ax$+hABah~NrRI-cp2~;y z*0UEJ%YA?SFYNv5ymG2DRdne2xZSqzw*HXY#TsP!+qs!i=V~s%9w-n|fJ%X{AuZ8s}l{sT0==zrY#aIslRPABcYm|?`^?&r?+n}@pzB+*d0Y?Z`j+4V+#Aq|>t#Mz@oMA+ zpzB*oa0_&OOXg6-2k82i>|xLc==zr8Ok5A>`j*UjkOy>qi@64Q1L*peEZhQJ-%^-{ zya9B5i+d*00_ggd(nO>O(Df}jTr1G^Ek4|WX`jOoF#ocGv<9Etn{mM^#Rxs#ASKo9-? z>3QX?wHvRG`Q61G?L7U1P7ST-p3wgs_NVV_=kNN@+V`EWki2=P zS&gZ3;RLKVS~S9Bo*!Yp#{68rg!PpVk1$2}9n5$1Wj{#x^Dm4rhkXS3_b|Wjkr5_@ ze}Zen%kT#sBTNDE?$emB`RE8!f!{-YCV)SL-+yt0slj|bnZK87M|?{$c^CE^>4)Ek z|5y7%9{c@e9vfjw@ONAcc@)wm_`R1#nD3!auFpS?>t7yW`X2@F=Np$dTaQN%;)}Mnv^X3S173MpKa{r4V5C1gCOZo!%OYlE}aPeoBAilRom@^Pw z{tEwZ3x5&*PRuus@8^>_9rCeb#_wXDm{Y&odY-sP%Wt}?KQCiRu7|69ZTRQSTV z8e-2kXu?U??v)H*!|#i-dG7bA{%lJAP+dqtf%cUDZz=z`52+@5z92Q;b!SU5{DG8z z7UqA)kH4hG(`Ky3`cS-IdQ3dqe*e_J@dS0*bEhusAf5i-m;DY+%C~X8x3a6-)Md}N zOilX3-bw%SDgWLBlHn^;@%30+WsU?7e*oWu7uVk3MgxrrhOV`j=9GL=`&wT$ooX&) zce&vJ)V~LLqbgCz7=GU)`(K3h;au19WA^VoR$~(Ozy1&tw|}?ikRP@G!gn<$ZvVMG zhhWazTKg|OT4Un&pL@2(#O*(S(9P{-egk?LR+qi1{)5&p%aT;`Z--Ut{9-?;!u<_MfX7vew{Ju1@;(e9^#s zqWxLR_UAQcqyBr#+V-cnbYXPmmb_li+Wu_g=cbPBAN^l5js73pA4}U^`u^Q_@%532 z+dsKK+W`L0T0mak+f&)D^G{q5UFR@@0^5xmZ^DqGufu!BR`M(z=U7gc$>)Y&V6Z=&y#<(?S{yu|D)GJ zelza-p#MYRlV6zHN41rFIkoTVrR0zQj`_^}b_(Q&54R`N}ve zulz#t4TmK8B6|KH?4?unQ( z`E{N2{`7oe(|+ej|4U(*P0u6K!|2j|r=mRV$aJmW^j@)ds&=nu**8-Twg1Dnv-#{x zgD`gNs_WLtS264=UH|#2wYLoU#rN`gRsAYrs>#2|eiN6xL%ziI>>k%E)+*2S-723Y zzf($29r;(DwDIbCMVEZrE#&`pQ^eGhzlHl!h2(SOH(@`K&wcM2$WLwHeUU$&{26@j zT=J;iM#pldM|qEYhWVraLo}IuYpUO83VHp1qHukipITk{q1C2G^)yocAzgRRd_I}{ z81C1s@~4nD^LbyCZz6yEXVlMnM4o(kaZ$IxyU<=SX9M#SxH7z6_9J$%f3SA}_5}pu`xZLbTd?c@ zNZ|H>uKy#!zJxx|^?xLASAeenBY`^uOz1@1i>plb7uaVI$ov)i_52K#$X2{?z+XCh zm{9ze!4LfNM(ij0Om9=U2>O8Pz2VRGGWq$~ClNRS`ogEM-xJaz(EXBSA4I`N(w;^A zIc&y0hCqB@MA;iLcNE%N2+v3u5Z@=!!@h@I|91kn4|M(C3ETlt9*6IV)L(I}patvq zqWw?KfFIERL&=|x^aA%SMg4Ce?*DAuKcN4IQl1B0K-3?O_EWU)BGRY*CqBXi8=<`@ z|2r8VE`f6>{>KeUT(|{S+|LK8&lB~{AN!xm_fzey|F8UCO7bo-b&Q0bH@$ZBJ>9i` zjr8x}aM-US?zsKO`)j1nCf;8oeKzs_8tJo%_t!|D%>)9dLV*M#uL`)j1n=1KI|gnhBz6mCJh|3><7;{7+$hZFC=kv^Pw|BdwF#QSfg z4=3J#BYimW{u}ATiTB?a^x4GwZ=??=-hU%~IPv})>BEWl-$)-$y#Ge}aN_+p(uWi8 zzmYy1eIKO%MiB46kv^P3_z-LVjr8Hf`){NVC*FS}eK_&{8|lL-x8i-0{DoUk#(qEI zFTpJ^^1i`u(4QlS_xDJjPrScJ`h4R3J<{hB@9&X5pZ8H9#`}9VI9)7q?Q!_;*1E-Y zQp&HPYWI5n>7Gk>?9Tq@VK~TdTOVr!7e<%1qkY|-{hKS%kpZavn_t2YsQm|iFRZuf z)n)(wdA*E4?LU7$zR`f%f4&udpv(R*>}5hg?ccc=x&gI+7Y#{)+JA5^;sezFy`MlA zp!Of!fN((VKX+*_BT)MfEylFf-d`?kNg7E{@p8ZJ)rjQU5o1hY)xk3_CHrEA~ft%4^a!Z=fhI{NgAqlujgA& zn7Xh#`_IYxL>$4xw@2p^_A}TSE{*n(z9=v6LVe(xY=p7<%l8ELwm2K%S05uhhkJQG z8)1>i_rdr6afAc+PlSI3`sd%vMtB?Y<#*Aa`~maeL&OK%x-I144?lu#z`F?X^+td8lUWPM zhr{6y;Rkx3g8CKwW(D*Ccix4(z<5CT6s`xZfqXCq^@(S2f57fYpTYhV#kaE&w#W4n zURs`w@G@P(O0ezg@lq=>_gXeM`o7oNKcY8ipf&L*K*D z2P}FK`GxSzBIG}CItJ8(e#qZ@APP;_Vri`=kdA_C3t- z0`yu0LQq}}NOO-d9;(qad$#_{*-r)Y?<&C>pvb@Rfl`L;UT(9;n zWlf884HvCcyKFmp9&?$?_(P`-zt~2I-HNHxB&q^20%X#mf(a^v27N9MT&v zKYZj*y!uo2hs-d62;W8`wlyW~&&#>$)5t$aOsXS|g+D=nWRzZd^l$GLYw z#OQnfr*@|EM4L{J@>i$!t!^QI@gghl|H{g@l6SAOyy`EIzv)}1lk;5K$iJxhbBfgy zkbmYfrl0cd-AKqsBj~*xg2>V;ZIy>L0Onx@+SNp9hC|~+W$qhpZn5&!w98G|&#V8_<&gi3|8wkJW1mZwd}f@@&)}Ln zqZs!l-|{}w^AoGTf&A+8nGdg_LVzPrKJv&9{d&K_&cU1U`EBmZFcMv{80BeZGvjV$ z^D|u4{rll=vSB2z???K7kfT8STrhz4^67$zs$xLbzU6g6#8i{Ng7cz+Y1V#g$*1?p z%#yDhL;W|}{HP=U!ExldAG=Hb#0_me>HhFJ^6TsVdX)Fb>;7)eUDl5BYzsqBYT{yOqGj*pnt_P*N4=h>ee9Bj+ofcy&I-k0+B zsbOB=v&sA^Qog^=hg)hjw3FBULLKrUd7TfZ_SixG1dbEw_)(d>_UpRe+w`v_zmn-u z`Bmg~zshpGy{}H?b^agU`wID9-1pG=sU64pntbV2d%voG4f(9@Gf6$)k=Ij!^8%`P z-r;xcb@BJZnHO47)UU!~&#v)@@<%qOwcOCNjz8%8v9A3j^}R{guQWf@E>P`>j!QT$ z;qPbfJ41fwg?!HJr>`bIr!&ddkiS>wol=iO{z1Ms&J)(&Yss&fWA&uRD;)iw#L#{( z>L~x(Kdrp?jOEqt7A>%R$aJFW9UTX($L|;UcJlrCoHZZNbcl{&DSk2eB^=N3F1GQa z>J%NF+?P`KjqE@_uN>i6<`4JtERlcpBBqn$a?8kH@uKB}Ev#La$*<3GmEb@d?;7%b z_?^)GA=hkbHvQwsM;GJAThF@myyeuM55?b)J7~?L9pYTJ8Ot=lR@@N!o9o`?iMU)lMgTXyv=| zgAq^SxR*1?>dBE`wbIH5)t2|j&u2Mg4z}YxP0DY>=fMB5%#*)d`KRpjZy|rxbIJ7h z=XCz^8BbaJ)%@>EJG*}c?VazR)~^P!e&8@4w0@=Klg=B^ z`c*T(PdXpGmio1P@>xDx@a$)?Pkq>g-vKU6PY#%!vGR=FMuJHnVY;S+koPM>|;CZPut6v!_gV zCeNNdW27_dz!~%AHjSP%rK$07q-w520Cvoz=1Fn?s3VSudymLZnw9W3Pnt44P8{Ai zcS=G;?{JKy)J7fM&=HL@Cv~Mzq%$YVjvv=K15rE2ouDzDLalQ7+~zaH z7NUn^&7~#bZ$9FT#>V`_#yKiQ~vhD`fPmNUPy<(o_S^m?y)^6C0Rj{GQ=hrv^}-qk=p{l6m~`SkyeQPeVX{61J28IdfIwU zk@D$vfm+{7uOkd8KY;baU>~cwgZx*VC#v>|UoJ8x5KKcE2r2X)JUs}mCntwSJ z1}3T3mRvgm@7GO*ZS4K({Pmt8#=>IKtzT$t6Q4-( zRScLhD9LBYFFHBN>wEWfiq~{B9FUZ+rJgl6B>61)ZyS?*9r;7gPVz4Ko;N1>dh!d` zB>5cq8~NqhdVZn*fBB+Kr`E5veWvF# zKmB~?c=e<=Y_FvcX{d#!_?~DDv6gL}b{*Y%f z&2ZX@euo`iFmdaoo-FwS+t)gu+a-T4-&5u5$!BS|nr}JsKQLb9427gPq@ja) znzTK7iA~Qk@|Uej-dCA?korHLmE^0KZ>qnO{7lYo4vGsRW)1lzDc-DS19sZM#_KR2 zs>rvWZu#(U><=d2%=~nipW09I67#{Q9*6R6cTqp(YsoWNrd{LXdC)UAd>ViMo}3j% zqRj^LQ+~U)d^7*BPhcA=(zBLt`u_F2+s3cYP2)X+<+*dLeV)|}a9Ex@e9rowZCJK? zwB1`z`ATa3w!TlL6yHGkhnU~0$0J`&yHmc2yu*#8n#TX}sCCTwrz%g0$>?Yg+c^7?(M zqy4(HH;?l5Gz<0n_!Rl`xnj#BhfuR#C(y1u>SoqJAUe$dn0~ZD$;ZLUQ7hR z;j;YOY7x_0XY-HZ=3>@koK5X_u$lp9aC}|Mty=Q4b-n`oZL{Rd*INB5Uq}8xj-xB@ zlAn2xZ4W44PyXEgNj^t@YD!N7`Rh{h9{D@ouzIw<(nLNptSxc{KePFeCx2f`Pb>N7 zQhEyH>r#5GR%32H)8>OWJcuNVl<&#)YQazJcRVD2-CMR^rR8o1c|XO=G$J`Zxzyg5 z%44}gbj*D|$z$4EbX@VRO^?dIO#Y2ClJUMm{*1${ytBsILy7!_yCt7Xnfzs``bQ`E zdst7^ct0io)(tjZwYLiSlQ{oF?Lpsz?^r)mJ^DR3^GKV{@Nf1xX81l;t+2f6(Q^=e#P=m z>rEQ()tB%-Sx>KGKzckNL%x&cox^e8YL!2pdidTtnYg75zLVhC0MO42}UdNT)7wq@Hm3)7e*D7Bi zujB5))3!d_M!uTmj^AX*X!x~{{!<=$IJEo=Ve_dpYLrG&%yGl z%j557^Q;*=`1nHd>GAO*`Sdt=JNfiDct}1y4&Fh2U;h8J&X-dAHYX*Y%QDK3;dfTc znNIRe2U~e(w6%M+{+b>KcWKwlZ)5)R zJ6lga-M>9f-vhRDbsW5be0m(*Bd_xlTz*INeM*my=P7^A2Fdg^lON9cK8EA(E##T4 z|8lA#qvx|WnS5e*>qD};^@t>cgYA1O;}j#nWO)6!`Ka^a|J=Q^heoL1!}>$`1$XX` z`Q!M%!yMcK4;dAHw4rg%85&{uW$0hRdW+lz2nU>-dPM6XimgM9;J{aHM3onY8o{bL z)*t%N4>Zlh`2LI7Z|N5Z7aVNE-G_!ET|>=|r&Av85V!;LaGZk?-+71+=zQ5;Z>5a6 zg%budUko*Z{@hQ?{ADQin;dGMz0Br^`*-LEZsA0^%4Wli;JRrxyqFn={~H=+c7{1e z>pL#Py#ZIeX=4ihFw_XH_{RFZr;sw#k)vG)_qhaY$y@yqki-Hh}BuOeKI%vsO}%y`TC-G^~MzzL69f4b4aFW~ zL(Sl;VQ=q2|J~3JRQ9v>Re2C@pk%8DCLA*?LIC}8xUf$_$E!Ad;ia%2pk+U6KPAK^ z7A4Z}(Ux@tLYxA!8`EEb^9&5c*&pJOp zPkrffP~+{9`flrYV6=ZjB%!IjpY}T->bvMtM!(U{PMxJ{iNwEk#Ey=3LNMC z1NrUwzwesQ%g8TF{cn9I`M>CVmhrY8{3-c&F0|=1~%T{v6E zH;cA^*s-s-DQ#izHy~dk-}iFMJJ$wLjJ|zcOtrSV$hVTeiS-{H$1IRlc>~mDUngPeRSi4d_ zOa9r%lKG?WQQJ*P-lKeQbCOs4zmNOin8R&9o!b9VxU+z318x4alV8knJ^ux3Zz1{RO;%p{cG}yrHp}Zcdy)3@F2{+K*LmpslXsc^ zGUd;Cn0kI{@2iu1-SsyA9r9{#pS3gp$*aA+#eOW0>r=9{pJ$kF0p;t-*K&U%wR4aB zu0w2kl%GU?mv+l*em0Tc=`5R0l~=pE>+e=x?WBeBi%(D5Re}6psK3nhPz%YoaDOG` zL-L=TY4t0=jQlM2pDAA3H9I0*T)*l1<@6zI>DNaB*Fc8=KNMH64gaf<4AEj>$(g*a| zAMqXB%XsxQ5nPGyQS9fM!~FoVUep_a^ejMnfN^sD*j^?)9M=Q7e}Q=r=>v5C0>6m+ z1v>XY{77#FaSN^!{V!p^;`87K_I(k4toJNDQWIeu{m!BqBY2SMEgpdT0WMu=)9+7* zexT>k)}K4K#t5FKytg;*2Y6tn&CmQk$X{SF!sU5+dmtQmi~jIt+z)Uv>{9Y4e>LO< zYMc&&V@d10oFZW;a zk)Ob&kPpjPkN#U+56J#GlD^8%kw3uSq2I&v2s_alC>r_#@m9-sq$iQm5k`3qcr0K&09 zLm|NP0X*JMVNdvhuORRK4Eu}RS`%RfCL;hvw!G3{fcEtWl@K;Vp{s6i^qIVzC2I%4AvB{z5#+B1X$IIvI zW`$Asoac}q+x9nMtu5b!!M6O_Aqq7{&tWwT1xG8tTZ;zU?^eiqF2&8WoQLg>fT7~3 zVnCVo9bGS`-;dYxR*$*Te*bDIKXnVsJ6qoqFMgb$P`-)0VLz(gZwvYUoL`{r2A}-6du@7x1vdSyfR)~Fti zBdENgeLr%6mDhd$wf>%eKgnyq+T;|k_4)(all29M`U|&NJ>K92QA%pb=NhfN=0iRC z$Bwr0!BT5iIr2sF+7IfH*Lk4YKi@?DCCWQoU#|UU%nnmONL}{)@F{l>!ux$wX-dts-}UwOKGfbdwkke<<*OLbpX~(YGvwP(OX{g6|N9j0 zkk5}x%GZ+rlI>pApCvz+?P}%g$p4UfUtRKlPwA;ApXGN#_2kI^n(ch$8_4%y|E%&J z`G2t8t9%pr7OpE(K2N@ycCCC1`Kvg;KzX11Le57}zLoq%|48Orf&AmgB>6V-&77a2 zdIIuyrk=|}@(1!et@1_kQ#cNzd^`EWF0=7=%_AhghVgdsRW@KDpS#cUMAzdqv%RXk z&M!Qj-)SAM*ZGA5=i7L--mLQrPn?nDb$;Qur&_+ubuK!;aLrQ7>wP(V-!2G~d@cDZ zmM1EoCEq{A*O9+!Wm1nzp4rs3USHq)^!&!%XN8fd%x^5;-p{z3+49@l*1q36QjwnB z9=7}rSbqQC`HeP%{-@_RuH-x#?O)RO^-Q)CmDl(3Nw(|Ne)au3{9S7=%G;-GjLwsE zdfEDozLz>r(wuGkEA+k8d6GWoNm?s1COuEGgZ7i2Cs`(+o+sH!{&|j<>HNku1a`Wv+T_U!Wts7K3tomZ*yTHZ68x=vMe>3P-(d+*&{`+Oq) ze@c#U3@xH@1G6{$nTRz;$G3_bj>i5+qm7PlWi}d(|5F}q$F~-2U;=~*WPHn8wV}x) zOwhCsJASB7$Ga+hM;n2TcjY!8Z3H^rw+G?_ zbbO5FYNjmd5k24X{>X1Y$IHAoM&tiqa1Z-h$-+iRKcM4f9_&G&<7EzPQJ~{xS=f$1 z$IJ3NBYxoWC!r7NDej8&0Ww}Des44A19ZGB^K;}spyOrcSGafJ9l0KdHxlx|x(@v= z=y}lPw@vEq`*8MR^a0$sKK{GiwnH;tu9x^eMEfJ+|9o;s4v28h$9P^D?5B4U{6PC~ z=}+m6zNP^YW*i88=nttB21Jnmmy!3UkRK4?2ZW1Xk86%qmp$K-@}K^N)fYZF0RJg8 zz~uR1^%o*OV9{~*y3C6MjNruAti1m?!h!7`u>Ra*NH37t3-b8Cs$lAX2oKkrXuLd} z4E@08@XL{FggmeU`s4^shCFZ-2A-n*2|vgE0J&?d{>&oi1{%+>^4{eGj9`W~)Gcks zPNIXS+B1{>>5G#7iQ|&~rquN(q{4TjK4;hfBk<&7A3NrxuAiN{em>J%+I@f#EdOKd zVmJ>@rFUWK{(8QVl)pF?-)0OiZ#TdQ3aRkJxsF`5?Dn;F`3-oUK-FZM-%bhl2UKu> zVo$+5JRe|#Z>)UfK7;|Q`91b7L0$m2ys};-P>x$OG#-e47nM>r=mMe()DPus@{! zf6hd%kIH;tGpIP}`bbq_7h8|0rD8oFyNwOk_Kn87hV?q-s~GU&c2+*%{xMn~x!}E| z9^RfA$o8(!_Fn__Y?R`UC*L;C>QQ-*{8_Ab>HNPY^2L;Vo_u|ZZzjJB+l7u3L`)0$ zo=+tEiG1=iIXM4?6(<7PA zcJeFOFRA&);>LVRdF4aO@6G3>`Orar+EdB=FOmP}woE7YA6iB}JukCN{)Ss^IzvA9 zPVx@pHT`WrT7~>6CtCg91wq7UJ7Ue1mJc~ELhJwIT9f?Fd@o*k(ei31S@O#!BzbKw z%)c+mYkT2>9g@7Z7skv<^4eawV@Zs6#g*>yb z>r_RTp3gY=$*S(^4>CR=hs$vR83&MBNhV@ZZtjjS%%2J$9v|V8j}Wj8#w(ti5aAOS z-@~^t-t)|a2=f0E!828+a^v_2yThQI4erAksJxiW&Eq31 zdlB)yfbqp&AwHnzW*Nd17~-lKUMTy2YtZaSK05qpNAhf_f?xQ z#eNfvVAq9KpVNPW5p2T$uX8f+0}Tw%{c*ezI0%pGQ_moMz?>s&{na2$@Dbvd!(TE! z!sQ5;Bl9})2Pht9uXkr5{eUm^Aso&fh!4>Hh%;9}9=QJst1mZWf)UK+iFS7ELDHDv~ z!WNs7>}1#@a25T*B*X_i4gGQiS@?mISzpSXjQjxRoo4eVvpw_!-%>t%B=iBRdeXjd ze?G7+=O1SAM`nUgkxV%%k0L$5&*obD$v2HRg6jXU{>oW+AAn9??;i$zz@i)N^=1L` z1GxH8>#rd11$VaD{B;qx;Mha0y_OLsxN4crkKC5HA7Ix$)}AtbaX&ya>L+qkzD4{% zJ;LRA`3MvIaVKkEg^ebleS|nr|BxehH}nB-&$H<_c=rTbeQ(44U*mdUmv^n-y9du7 z(4%0Z?ds=T^v)%n@$t!tv%*O9V|@Pog=@zz+!3~ZvNILwS;sH3cph^2{Emm0EU*NB zdvx0Gtgc_w?^q_qS5yAjqpZCD;7t+ZkUxyPAzw>g_fd48vhrE-A9f_;ts`F^Z~1cT zT@mAwZ((_(>1-iCBgOmVKV!dJ`S_b7rj>kkN=zmR;V)`z%Wvq-+-AIt}q z)9vK%Uq^kSiS?Hp!=QV0S z>8Io;eq{A1{~7sv*`Kfc=j2Z>C*@a@U%WKQqxl*gyFPDum-FhrB!A)jWIgQ9*2%{J>vYJz5V~Lw?VfEU)XL4BwwwdB#h7t0Mn0$LF;^mmz;-!OH9WCv6{8uAm-1 z_blcAp5nDWItq*;DI@81TPafrWoo@Lu=Q}o$ zzwsi=YyHnBZ>BK+`CMAbyUbU84{u#~=Z^CIad)!v7o8eL60=s~f`j`TcLM9FBklJ` zOE^8d`>tn3;tGB52DAO6{rik=?f*&-vwAWN*pBli!oS+@Mm71GJM4X_9*6ws7m|FI zy!Pj~l|jY>v_B_=+x%sa`T8+@8_^!scKB&L;@ua`+I~rooV^aRV{?@i{RjT?m z&3MbSrQ}b%CMn+se@Js)V9vK)^Tz{Ls zP!w>~;OJkqOs}-(ds6a`=z{1^`Tcz%btzj%M(<0<)O)<;xFm22x8 z>c1ov-z%x>-$>o>;gVkT-{?_J*{7GfpBGZkGl%?&r}r|c55?Y>YmlC}f5Qio_O&df z@A%a78bip~FEg8iNZhZ%z=OIQ2sjXtOkK9Bm`^?f32 z-WTbY`uGifBIta{?2UcU|JBEAgK)PB|1WbB-w>#y9| z#|Y-T)*m8FkcrxFi2ql(9+38;w$2!df550&S8Wq`!YQ2>F9ai-iS!BDlCdMEfm&d!GpH z)aTyO#|TbGdS$+*gL@HNcL_4{S+rN~LVSRa@iG4%^mpG4eSkCE-f#XM=mT1gvVM0V z^Z^HLjQEzIzZ`BsEAu0`7wH2ooQd|Qi}{xK;d-D$uE%`V{BPg~vS@6}{pRjRegV@_ zp^^JDzr}+EKF0OZo~pnt_>&Ys@Mr%6*8<<8ee9u896o^b1Fp>H#C+DEi1>k>m!j>1 z`I7nHAwJ*@=#Tz?@IlA|7at9MOYwXj!t()UZi46c7ySPZ+=9E{Hy7C}EC^EbsG zJPiGS-vIv`c>a&T4aj`W@Q--@kK%rSjSoP$^tV2N_<`H*LpbEK?MOdxFXUY*4<5t) z0$W4ghkOZcK`pNj9!GpY->^-=uU%Y+ScXk+E8jW8M zL?Y(dg3vj@e#d@B#d`Ip@rob9v75{GR8GwhnHnn1d!h+0VQ_ zrJp-t;&1)BPM`SwWlj7?j6Smd8~VLvn#k`Bzi;GB;}^N4VpA#4_;n7M^kozOD+Y&6 znfRKCw~W5I{+qh|rio9!Q#sVF+il&%C*P?|;xC%`FaEl&f9mfaR52SSK4tdnCvvHN zYh2)s9=G)eI_1MAeTUIcH-GUBD&|oW|4@rwcG<+g{^PnG61@zwoccXJ^C}%MdfyjJ z{8!(s(P3TNAzYg=RlzvXAbdN&lD0zRi!n zNwxfjiGTHz_4_7&cPHUnrhER6)27LnoF6{t4PDLOe$wza*?(^R`}L`fRWpx{YW~(^ zN=(kl_j7@|)Gy(08}HTpC#k^yXa4s7|Cjvj(1v>CLG$2*za`&woiOqLH~u#C${)?& z)?cCHmrOYmZ_(|)Y0{TXe8TrqCO+YB3E$f^LNLngkJ?_DzS3E$iN(+w4~Y2p*UxAkH@ZWI32%J&{K>09|;qOP>^y}vN& zTlwCWiErh5kDK^bzL)T^R=$_;u~xp9@Ud3D_k=0GmGAw~#3y`j%Y2VGW#&)o_bd`V z*2?!1KDN}t_YywV%J*(C<+t*^guk`&Jb(FA13^*l^+h7@<06z&3`scITI$nl}~0(e8MM} z%y*L?Hu0uAQ#YBwZgYO*8P{fo|5+WnzDLe(syj+Q?Y;q9i{XE>n*aTT$(NiHz4e5N zKWg?9ENxtwdFsx;nSDX)2B*Bnq`%eRXIsM?DkiDd)%x$&ciK`{>%SY1x23Mue^Y=MM^xvUp?$m!%NsM-@Q}+9lCy}{(Jcbbew+Vd!zq$KMnneYtb)7_wBxMr~bSB z^qu-|>RCJW-;HPQ)PHyX!cP5n$=a#^*0{b}|6S+$YW=r+&rbdK;w{waD*e~m+oJ#8 zu~Yxu-LX^u-F^E`{kO*btM%W@ojdj4t*)K=?{@c2{dc=(r~Z5Kz)t-)b>~j~H+$Dk z{kN9hssCQ)`fB~x8s4e@?jGE!|5}H3>c7_Eo%-+6&`$k#oAR#Ke=lct>c2}zcIv;i zv7P$wHutaAe^bYH>c3mlJN4h)vpe%SZH@74P6wv7(|U;HcsV&y+Q^;q+FE2sJ60aI>rUN36>_c0?MzVAlOPZRwssm9M1bbPW8JZZj; zkL`@#YciY|-&xL(iGRV*?~Koy_~#dQ#xI%p&%JhM`85;&O~c2Bo~PxX7n%4wKD0Ca zMHByHj@B2F_e!{bm-!w+692GC|MWRsPNGLVYT}z;GUXe6=dy`^%14Zx-}X8c^O%Xx zntk$1U()egCjRD}E@#Q4f84~srexwx`fU?GV)`XX|AdLZ@a&!G6Zz+2QjRGL{h!QtT$A|QO?;*0 z`=WQ4__pNl&Kmu3zls0$L%JUmeLRs{Wv${B^Wual z|KY#Tq$@?}<{QG}FKR202>n8r`DP4|bzEAg{ ziLV_s?fHPN=Z1-Ylc|5o#6M)>Pn_DB{*s9wKDjggVH2NSHtlB0*);LD8GUyB&-J){ z)Wqk_bCbU>d)dUlEU~|v@v~*(Q=TqAnO~2a_{(`6ziGz#6DIzB$#adpK4tjb^9&A< zjQ`yx{&hzFO#1OA6K|%+|8cs;#3bjxn|%G(f0X@0?6aG%{0V&Jb-Rllc9y)mP5uLa z1D^ZkYf?*(Vh@EL6#46K_`bmJ-l*tmd#Tt=zyDTV@Q=V_fB$KUwug|9o=Pn)->B$n zd#cz}e?13&{4e0eAA6djTd_9`eeoKwY4Stme)3P@5BG%|6{nhp`KT$|chWlHt zpWb2*+uvdjeo0IEdyui1J1$(H;dZOOmhQr}ujd+cs0|6)t}Uv5c%x#fAUXu1Ejmiw=N z-p=~&XS`hf`yT19?(c8$epk2u;g<9pPciqm6^uRr>Bl~w)@3M%Op{+Z~9k)?oZP`&nEo?hZUuc!mqi`-hWup?Iq-2HW67h z@hzDSkY2){VA@Y z_2l`VCoS}g-9$|3;KY$zVt_w z4}Iade&5=kk{-I|PCb4%FASxGelo*-?4MhNg{)tIN;+4)>v1xzBjoDw7|2POS59{2A>7?N6?Ihp>|mr5=2_ zzQ6Tl(nD`euD`)GbhEF^-<=!6ADKRXuD-rRSm+_vC;4sl(Erf!zt`8h`$!L+|5JTk zOAn=lE}8aS{}SU3dSB8WU!gsqPbAlW%{8?9kl}y-LH|Jynf|@}_~De$Bj$SZYov#c zoBDSD3;hd~%=Oj}c^~ML$@71l`3`+CxxSujXs>zR*1wV-`c>0EsV5B~w+yA;kX+x$ zHS|PT*Khr);Fi5LZACveZBj8v>o&`lYZ-~WdTjT})izzukm|68^hHSSaDY7YPd`{CA76P{Mz$FHInCPNWk4 zn*;v%G6tp7&hyedpwvC;1-r)xXu2>pwB` zDM_=O%tsUPK+E+jTJpc-qdUw0Sg^DHuV~5tO!Ix{-V?R z_YYgHXIh?LY`K1M%kzG_rGGx(a((MNclOugE&adU@;={f$^Xul{(g4Lc>Y{V|Nm9X zb$?6xzLxRu{g(94Y$QEn#zRa0EVlG-lKLTISh~iXZ+fu#A6MhAmuj0T=|8?1eeu2j zxxZw?L!suER>%K5C;Lm*jq3ah#?L7EJ0B)_>fek%ezKn<;s4bWuT)7Azla{OP5k4NJJWBO_}0HK z@+}j8tHI%tavnGFp4m5(;Dz5a@qcLi!jky^$HX5n`(cy#@0<9?|6124i8o?ks`hpr zpX?(^mZSgvd>x;RpC6cV{=xKbGJc*g@m)9XeBYE|YuTm$rcxy3B>qHCeB7k}pdJs` znDm!TIm!Ot-6sB^dEaE8(@iEm*{_rQJt51)f570K*2mtcp1;?`7tMT0#(B4i|H#*L zeXKX?@qEz4KV-gVwsD_{H|*?SR8pUtOnmsbDc|s!XPJ20?3Yj8*D~>0(=VI7|;#ZJ2n~=vN)CG2!I=*-!q{ z=^rIui+yeLm-+t5yyoj-M_VNCZj=9C-U9!Z{iiRyNm2JC18o!kYf|u4V z-lXWW-_rND$8Smrz1&Ns*5AYTUS4pMqVLmOg7<9w=1qzeK8(G6E9M$%oaK4n;CsaN zn-qQMTFU?UHL3O7O^QCo_4+7yz@pX;p$ zsXufV&y(xTckz7aI0pW=hMDRgoQpTjGq3sCdm&yAo*$UjW<(1^nA*f{<2%6O=@UA z?+?9z{@c0+|MNR|KJ;p?1)sXKkMz(2{UP@+lU69?TJCq>&hw$fzOeKP-Vd6je0jg! zucB?CM?S;*ZsMOlL3-$W(%#f(_uIHH^vBef{SVzE+=rfRt~ZD2FX);v+EeQP+tdf@ zWtwfUf28~Uq=&A3p)PNUvVD=n(k@zpuTV`31f89)15J_k=d5X%Et` zzl8RMQZu^!H-CkD(7?O&eCvJ(&x7Kp>iTS*rLCdo29(G6O40U0l@nZpzg@nY_JZE> zcG~01jK4#a2YrV2Tj%=X5YLBxa)tK(9Q}Wo_J{r#@4xxyvg^DlX z`TV_<>>&LO-ThszNq?EJ&{uh$q#xp0LNBBI6#cd2(mv3&HO&t$p5pn?W8jBsypA$n zp@+Z=hh)4G7Wxm$m;SpnPWwY2`m7$m7c=CCcF*emuFi2o%;0KRZ;StOi?+K^&!E(x8B>I5=!uw><9Z(LJ9t2J+m(*l;AJBpV5~R z68wAP=fR6_?^7iBi(F^-^(jj57whNA4<-1^MXN6*l;AI$PwPtwCHTw5XK^1&@Rt-} zp#*=~d^_o(1b^9l8`qHFFY^4Q_i+zO@Ry}`at$T;OX}T}2c7x0#=qC!LS87rUoJkx z^PvQP*?b4(LxR7k_kBO7*^Z9YJL=u-wyzW9sO4|=P?o3p<}+d$7x1n`&eeo%t1r;cz9 zCHVTKiN2Ijg0EYr=^rS;*RvVQgA#mQITDgS!PhSxB|ntl>+4gr2lNx~)b-tdDQTgP zoBC~r)F1jSQ@@Lk4Wxt;Jbw2K;|WUe_@U`OeA)U^xBRUx@8ZjNUns%nx1US-P=e2I zE>J#{;PV@^v@ew4^R@ZDlu&}tXYb+tplcHR_1F4Rm!Yqk_T62lKG2lG19msLhVC-; z8T!kClu&~2XHQWcl;Hat_wsxw!S^p$DIZGk{UyRe3BJEw;eDX@7<dLQO1xoA*mw$)$ zhZ1|j>Ink&HF%!ePj2(a1AB)jf>wW zKlIV0{%>UbK`UmyY|c<$=%c1S7r)1RhZ1|p?jKSfl-NU-{)7BbVh`E6mbQZudr0=j zS&yJ*(th6=NLf%~AKCp~%7YU7$o8jsA1JYpY~0?T5=!hN7ypdr` z)YlN?pu}FX{Rrhjoj<4N&(r62J=Xu?dPU!S3TqAfbGNw`O7z8zOV_7_#J_xqk1SnkUa#mNueh|d zE0tZlUeOcsyvO)^CKs<)bcXt@-?uBZ{Tq}A{Tk0t{WkLduTx)WX_EDNY*%Xih+37ME~R?N}F5@Rk$zm*3c)&4{h>%3;(6fR}qH(V2J!*za~|C@OnjG zCI8lEkVpO-^@CpVeBSRv=o5s6o_&`3e1q?Ey`Fc4e!%_IGW8`a6eHg({VwTWOM0jm zd0~Bu`o50(Lcjes(xY!&dW`mfzV&J3d1=otav$2vvHsIu+t=Qp=nr__Chc|Ux*HVz z9{Gnpcunf!Q|KS)seeR$dEX(@3;i+qQ~Z6GOFv6`==0>aoL#Bf^*1Q`EcrLcpZ%E| z6g`XlL*u(rDbfmkjr`Vspg%WgPiW{nl#hSa*2}I})U!f*{)$QVm9!7^8uG96y|T-% z;eDa$w{uPYi*3{oI?44G*V)}X4{D0O{^PXYu^SYXrM#b@e?#gIl}NwwKgoZJ{LmNV z{YY<}W&A;p4x8uyJmo>pBmV~Vsol)`K`-Vy^<%WpKJr7a;ChMc?k=7O9bBM2xz6^J zAKH@l=Xu#-uAwygr0D-cZ{yve@(XAW-fwg521Va0bN_!K|Nrt0ivG!5FTLUh^vN4i ze@OXTq~CfSWkW9`|Im||wQr$)p$EC%;M#g8?*qM+>(rCEem~dHb?DzqTn~Mi_JFz{ z=bGm&eS-3#1b^6m2jdM&@Pf;Ph5EpUHvWqDogpuD#|Y(rjqSKMF`rShPpd#kj%CI!peIJoVpC z-JlOhdyxO)?UV=Aq&>*rO~2p zt}VhsKhOIO(Z3sa@;qpp@|MWIbddId_R_vXAE7@7C=Ys6>O=l*!a}!@e_i;2Mctr3 zMfb-jn*^^@=`4eMO(Y z%-SMU9?;iIgoVWaQ}pqnpP>Jty*};r1^DStF+QQ68RPkaw>^paLQCK$qHk}?S^(vq zOndRX^^d@Rp>FULi}hgh_qY#z3p_)<*KmpPB=iyR3c*9x-$Z&S!8f+y6+-)8r1ker z-c?Axk1(`Ff89@iLH=i{-&c6v3#cE|{4Vup{9k$@_m(q`ilJ zmG^@#gV$`h^xp&YA9TMdZ|FhpLoYPt)n3hg=&UJk^Of)~C~L|~y^8Xo$6rEwvR-YS zXM91{yQv@R)#e4#L(lqY`j_=?=#7*Q{W0&e$@S9PXiKOM{A82$&w4v~p{19S|6|nu zt&|V>ls7cZ`w-+CA2K^MrsLHp&nO&*NgoPdkKiVSy#g8)opueF$Tjb9^ zOxr+vz?+61;e9_sdC>DIZ;AX{goQTAzr_2dHh4eiBKOzn&!JC|9(tubkM+9tY2FX| z#&@|-e{Oz~ywGJCU#!=uKO{diC+#Qg|9Z-YI(YsT?SJtNlnwnZ<8$j<%%8tx{y;s_ zAD^NAe|5d0ZNbClX&>$hJt5bO&&v-nU!e2yK3vz{j(h_R8AI+RD$^5*mAl&uMRO&$XXu zFSeg+kJ=mU&0Fn#*1o;_+HUWrmU_!^6|V@n~Umc{CV}#&hG|WOlMR=^yi^a#NM5 z>QpclPt~W#rVG>Vv^VWfH)o17m6>2Bn(dlBmL1JbXA9Y4*3B+wy=;(;<_q&H^VRtv zcQWVZf_uG_drnqP)=oyJPVY(YIkacb;w_7}E$&_1w|M(v$71JV*JAhLU5keohZjc{ z#}+e-^NS0M_bi@T+_Sj2czW@^MQ1U;SXeABE-(6v;bOEHFV+_ui>r&x#q*077Vlqt zpv}6j?R5Hd+nF=Yuv0AtZpJ;ge5B--YNfc`>+SOBOd z_^uxXU4b8jK~$@TUEy40Mf1^~*o}j@QD3On>QVE=g$obtd!X%s2R`}XKY2NQV$mbk zxMfXSbjs~}tz;&=w=m{bGP6fAxrrlg z{z&MJXL92?d)$r3OZIqdPdNUB6HU(KCYL)VtM;THA9ehr^~%w@f6QH*njN3Y*;7t1 z<@!?QVR)U$JF;ll^3-N4dXGaIKo}CS% zEa5nu%Z$&t_IxHc@5J*3d)}?hyYYNIKVPrT*Zo|%o(uYNaV1xGbIo`mH+tOhj(g5M zZt;X?@42mO&%U-j*R?J7_Ad4gEcV{H*n4oX_pZg>{9^C&;sIyzKz{K+Vex>wcxQg` z&f;S8Lff_1olf6r=(v%yY&#{_sl-mT=J-XYX6L<9p%fIIwPMjO zx}~BU6}_{7uhxpt{!mnwEC z=D$mda#ZmOw&&TN&ws{T?A7|b+JG0^XC3;(uDJa7DSMaL1@wN?6K=jVNr|QNfPfI4ZA2VIhjjQRK&kT3m@@@`r2nVy#}S)I+ZxRvMnOTC-O} zyXo0$uKz$=+b2I9eg2W??|=W}YRp@=@3So1ww}X4?>J;xY0h^K4qAhQhpeHYA!~YM zpLN}?Hfz^)ZI%;RmJ?gna&6G^e9Q8S&plnXKSU-T5-9v z=9fC7Myaz|t#rlJT6eR(3AY^WZr(Y1fVr8rYJ+K}V>;c{eRq3wD0%f^`Aui-;li5D zlnjTLLwmR!REPbdJsbz#FpWIIy%FL^yf_*Og39P@_TJIixv^2FQeo2Cqud)UJJr#$ zXO9L&cQmN2jn-@S*l=!m%!$flPVA0R29w$zBkfq=yJJCYkA*=kGc#^8&FxH~9Arq7 z;eMv#Rx^IRnu#47DrKm{5$+w~-jN`z9tmCdNElSdXU9j!i619^oH8de!(;G;@`MA6 zAZ{Xv;)$RhPL54wCTEV!PLg)ASaB!0M{@@74SO=0JvK@CN4a;Dc(}+KY{Wgr^)arG zd46$fcJ$a3*Hdm3O%XTcMfItmurd{u?P=bB+KE=C^Fec(G}GLl_MBikD0(wa)tw;@ zHsj0?Kf^oEcC|NWiJRqmw&wb?JUcr%GoGED&t;k9S?*=su$tw5miEjBVVn)!4K~gzx44y{;49OZX(=lWrKClra5ssy#ZrXTP;)vFp_7#d>%5VzWEH z*n~SaVUJDtV-wccge5i)xNS1Ac2x(jYwPIP#X@x2@(0gUqY|9aa|#)FV-Z@jVUVFi z`EW)X)(Dksr^fx7YdewO<3zE|biUn*iV! zZh>)KaB3E07o4aE>V*zKeNaC%0J#Mhjzl?yvf~%%tAbYy3m(@VWdxO|5cqz9xlo|J zi%#r7Zjomf>9?Z0JP6~qi{vkQPNnF%oEt)Jk$Sky2bZ)i_uWziGl!d3abQW6 zavaw@r@?Act$8$p$8$X9owvMfd*t&<#8+z-SXsc(Ita1g#F1BPu--HVyeRL}gjJ7s zI!oTOGO8@5Rq|GuS5>cQ`^;M(=|dz6pLy+* z*3U;ZpR_cv?eh$uHPwgL`(6Y!Y@apLXVLWG{XXL#QLV~4X#1>qKC7EwuT)@jc0d^c zWd!66%3PB^fHwqT(T3>8Vl@aGc0ha799Bz*3FpM+8u@DEt1ImHETibKrPI$ zsJeCyo^g)*=jvX3t{%i;S38r%XOOPhA!CsB)(*MPitB{DXIQD)VL-ZIH41Cor(L3a zxDqknqJj%GN)dS(`7xt#B_c1&vmJR==)4XIT1W3I#;)&*omXqtwr#k zi1&@^wH~M!Isn{KrMEoIOaJqe2InMjzg~+hjllGKh;Tt z7|;g|)Jaok5Ya?-9bQ$By-L0A73)MaoJzXkgli4bH{e|j(l!{+tDIN8&|UT7@+wW* z?C-v-NnF$K=vX5yqJ+K1^%`ZI=lVS1^Q&iVgot*ef>TqcIb=^;tp80U>CQGQEmFk9 zncN@;M-HVygp2)_b&p)q^p;id<3Xz|mu0zIKEtI~Y$AR;9FS}*i?$rJVkgfbKnkf# z;yQ^%t{7=Ac8YXii3)YQ#B|CbEr-GO=+>Kix@`_Ua_E)A0S*Twbf8ZTNFz7*N!)-W zxog0_6)F6}t-?NU+jHyPhxQ_??b|PJvtL-0h!~ab&V!xZJ^hIBcODc`BHeY@Kw2hw zT1MgBVFVo?jY{3dk4INh40RULA25 z)+4aSl@VcPBa(PTl8n^LUU39o9F0!U@*;8Aqrw+QD^3)RR#<&GMDD1}MdXcTdsMQG z$ud4RGoQA`WFZ`r6==)}x#8yPCFBpUIwpz7BynbLZgwss)y+uB83x;0#xJI=j3mjN zt2>oU82SN+Ak3&7GSWpFv5z3yOdavuO7Td=DMd#rffFC8)T8nd$$KQI`^6(6RXZZt z#-&!{@{Do0JC69WGA=hJa=C2Rgv5!M5=}_lq)0)NA|gym)g~p|Bw~DX(vJuFCMEG? zKwC{lV_rBJQMt)z#;Z)Kyi&EJlH{md9+Rd!CJ#SWuDYR!GU;P-_n6$Bk{eU9UQS61 zO*ygWPkGh6h&E1TO43b9I@G2@8LcViK-{#%%}CxExtx*9S*hu42@!Bs;$}l{&6$l@ zm}b>osa3Y4x3`Z&|3J3mz(GR&y**h;oRuUZ+1SsO%jc>~8BNcvyW!d#BHg`n+0nE$ zCpDFWJ15me_Ni3oToi;k7j0lp^3F-K&q)Duuz~gy_{3^Dmh7iE?S*ea%7r16{?EZ6RbL{?GBtuM5$s!bwB$m$8WfSPR(;wbgRmABao|#3u*ec;7wgsPT2U4qr75{o5Rs6oYT>Yoq~}(n8VbHT z)T@K86y=I|z(VWUsQp1m{kfE;6Y-Ek7}#!u=5U*ZioNV0OD;S0O1#XXR9O~oCSqf> zEP|9A+-2cw%YLwIFH7-AA}jW?6e^a_TvZTCLNu(pBM&cwJLIZ-O zRHGCZ3U;Z13|5x5Dm#^B4ib{-f?Qb%%92B*%BWle04YmeS!;Ub5P8xDo(RUCyn~0h z)+>hta^MNn6fWmBJ->zo;Kw}!91iqy80hmv&hn&qPZ+3In{i`LiuWQxJR(XEiPHw3 zSVrC)jhkoXu1KDPD>8gm;t@vpuuG1Y3HPB=Ophrbty}m zNaS`XVr+6 z;Oz+T(f>5l+us_R=pzX zhg`0TXs{}AP3fbi%(o_7i9^MYnxa-VC0$b`5lv=IAdofDuh-R-qoE zuv9w^p_7Q}3KrUN2%`ZnRU2%-x!HjZ(%#)+SXwCnLcEC+mXZ993l=RpDcxh-L4X zQ>!`XDZ$wlPbn(alyiP9ZB4l~IvAB?#Vt(n5J2ffK~mWfWC7!XMP25?j-xA9KWz1(r)s38G6H;k^e0 z(M?>Tw@TMMei7V?4|DdoprQ0=y$+6`=&5x(GyRKMU0lCq$B ze4&go5Y zG^b7rLVN1IRL3u#-XmOS&tkp3yYGZjc@C=MU5oYQ<>g|Vn0|KcQXKt^l4~7Rj-z;j zQi4E`W2!F4hO2JcN+rVDCcFZfs#dm@LIl1nVire)6q*gOgd=>Mqae)ceU(ZiN|0dD zYUDVp3`+E%$Q|g*D>WitWL-xK5`L0bk~#=9*i;_z5f!Pj0%{}2J~;x}C{+n<2+bix zCmNd)&1h^+9Z`V@qa2|+jj7{;Iu_NjF2@CxenF*QQ0W&``r}&HQg@H5yT_HzbzG%6 zuF@3M-J-f%RPji7lv!5KDywIe)w9a#S#_1ZuF}_4`npQrP|s?pyA5@>q4hhJra>CT zQL*}=1mu+zBI+KPypk$J&C4idkC-)VKj-pmVi74QFreUI-bD8c8G!|@2Wq8Hjh2Ga z%T$Cy>1DNW3o8n#Z}bUX-xw$epe?w4q2em-uUM$m^XQX`Z=(P*@8syk1;w{HB7+r_ zY=&43_b!BMSTsc$M2S@LN@F*-$0N5D4@@SIQ*T1r@VQom`BsjCnEUl2WiROC4=jjcr%Sz%pPPwtJ55;aHb& zs7g?+fzIg%meM>UEmta-Hc~1lf+g^~t&W6cg<4(~Zp_q_<5_h?Cn8*l{YWXB4SN|O zt*2KV`{Z~)juFZ$f}W2RLwW~2lrU#Eu~?=6N#5J*`u!w?G%A z4LQQcI0ATJ?Vzu*cZi~?+S5Zu=f!JxU?lfyvW9v}d+^RNTu@8%eowbL9*|DXC>=FY z$A;~xb@QyM=UG+02u-#8SrxycR?-!(QgMrwVX1jVtw*At7PW%PF$~crMHaU)iAfp- z(NqwuMQe3EEc}X7A*hSCNz;&*W1SeB7LFiUz7xZve1#+-Qc-8tPF5(HNKx8% zhpE5M8ZAenILh16Wmtzq6Bboi#V9z#mjPt^;1(PeI^e7J5v^FO#XM0d^H_vX82n%) zD6S#d(<%n72?q|A zaHMJ^AC98OH&ks`)qAZP#6%T;n zqH)V;50vZ_)I=^tt3-XqzD8eY9ab%0=-eVx@w(J15N5A5ZZz;Rg1%C+^XjO>Ri7Rb zJyx`B6l(Y=M`;12a4(~A)2Fpi-bhUvlxcaRP>uG`DdNl`s&r8+)cP1Hy_&F$e>qAT zne`zHHWn~77eX}`LNyma+?WfYnhT?lKQ)frteR^;XS& zlz3V|Y4Nfkc{Nm6X$?{7(Z)HFUX9^MjbQ;c{UXOY$RI0=Sn>QK3bB$rIr2i08&`b+ z0O-L;$($UKIc4abQ%C?RIZ%K)(ra`nZ^V#9A`&DZvLh;0TZ=?ukE3%6Y&a*HY;=yn zs*Z%!TjSSLWZ48904x9)s7Dd+E&^2u|L2G_OCCWgI8uJSrouG|t1%p@F&wP|NLXOc zvC~u_fgOw5BLySb#xB4b$0%+uD!8D5I~4M5T!vF}1U3LD5Ls6N2Ur-;3so+GNcXE)T0W^Jbj!P0ncLl}oT*6fA?tQxBPRW+`VOIW#@D%@0XbW`!Srh22M z;%rUT?@fiiH5I37sy@Z=O8MXta9|WQ=GTP_?a>1deDlR`YcFB7Yz($H_FH=yi2gon zFIW^VRqC`4L#cAOQhLE5tGLE%4_bo3MS~W8XP7@N(J;6IgD7Am0+VT1&t3iEY<1V217a=3 z-Lb2u_h4GDQ)xYQ(|V-aN{1XA(vqb{E9_w{3FC(~#?s7*c^YZl!X9RQ!tO8(94Mzq zrlmnD?BRwCcAr5YBISsS{+b4}z&=v}uE17MaYvA%>Hg8#nVHOJZggR8E;ExGRo!HR zV#u>bwG^#!41q9wER3TfFXx&H!~pfc9D=|tr;1CY&ln?;(Ii$_Uy!X)xFjO$s7#l% zHCnHYGRsES;MqYu=9EA-?J@nJF_;jnbBuVF)-mRLuwrY(19vbb(QC{DhcHwq#|PaQ z71%=r$;j6DMx>0eARJ=7h|aoL#| zo)gzJaUILd&4YW?{UDgob(x&D7MPNgvvj-{PtMQYgW*;~9R}sVG8@Ii71Z=7#vD2+ zEfBer5o5|LPHL`#YbtYe?I+LDP6(ovEGik`QhoYes#iN=XeD$5s-*TnQdJV61+GZ1B*n{upQv; z={3i%I^m3d-i+f14DT8JyczvGY$K~!dob_HaMKuyJ)6x<&d$th{6suv1Hn|Z+Ml7G$%%k|jF$=oC#_G{euIEm+8PWLT7#Su7;;4cedMFTK4 z2#kP_3%bcQ1_Qvts#A0q#NeK8ThL9exLR5xx=~u8ESRUk5Ll&->jmMS;kg-*C>hi| zNI@-lyz3Se7rrrP?WE>zCw1gW{YIw-_q0cQPM=b&`ShZ)Gw<7_%$wG(hG08`Vs^HB zsv2;y9pDRCf}<<1@s~cqm*H+2X#r%3#WPn%uyW!nhA>`)w<_i(PLbd+{+dbx`$ZEYkSj0odqw7hk`Hxv4ySI#^!jjYZw&B+M~i3>KOv8hM=jkWNJ~4gfFk zriM$&2|_F}>mU_(421HWk(D+Q6%IEj6&7>Md={*}`5Ew(5F6q>er_M zeLAR4y*f#+z6ZXjFcov9ll1AUex0vhN8ZUvcYjIq0)@O3l^f}*vxdvQ@TF2g+0;N{ zq&+!_CAbvy;6K)b@F%}gteU43SF-dUCS(zkIjIb>Qs(eN4$)O%#I%LD2Z+yXS=k>V zP8boDr+`Ni1|_|TyL!y9L6R5lCSItB!DT%P#D5KbuDsQ{y2@+HbEK>c7`BI&Kx1oQ z$Dla?IR?+sU=5aUn7`*ML6>R6;v~MR=zz%AFgsj`YYLC|YG;I{Y5WGDMg|%>gy%;9 zHkvP;#mS3qJ*y=Fh0`?b6}>(%kc8E9l99E-MhKh_E5k7h1UQXI)12V*L~8Ls;2cJe z%*ACu98P6W7ETp$gbl-*!uc z!AS-fz|bffutJIQa#d$}sd~uLtTeu=E~t^XS!?iUuo}e*Cen5bUmGj17f5#~)QFRA zNB~r6NCAuJ2Osp7cK{I+j1<&}Xif?NMOm@vW(5I}J*dg5h6Lv09<8vTjDmsSC^$`s z%C8_G!GmalRZb{aL~1xdK|)|ldVp!D2jeW5gjZ0f0L(|Jg??i~TF}>PKRy-1>Pmx5 zsL@jERjIy#gusCm936;L5-t@=vlaIWLDoZ)|?Q65{vJaQ7z zPdQnz2ZhxPfC9Hs<{e=GV%sW87o3Gic?sqTMly zfr5&Pb#(%=5LXNqMNX3}}<=~KTt9h9RL-lb1^!ZO2Tgb4b?6qSBsnU@nYRZg_EoS3O{ zVy4Ooc^42$W@_j(RhjvkKB;*N93}HM%@gmeSJX8Xm#YrZ*0v?xW-;!uwQhAu3q2)2a;QsN}hVMF9`Btg|?sCh+XDu4kI4{#Wg_XFrsxR#z= z0$TA#5gVff)f5I^NposYCUytLvW;iDm_v=a-qQy?aRvl?;|>7D|GCBQ^*G{bde zSv<}e>fk1k*qx*leBc>G3dB+;aq?3z7WflrmN=$p+M1oRho)(2S~?Rx!9z@6Ji!GdWRRpk4;MIz?nq!WSn| zM&u+QASac96B+ajk5+xvJUEIVJ7|0imwVOL_*F_mw4ylI$o?5l!f^42B3iICQE+%Kc_X}kM8($-nhk~~GDBUnnYtc> z8bDK?{J6r`wamv!WWKuZG$;-c*r#*rTI;E636PUY5{g(6i)jVPu|Z#ms|_F+J0v*C zCI>`&>09M~2l%BmA~^wr%4~p>HE1}1Ms=bT+D~5z?kGqAokT0j5Jsbr!W3Y3j*}*Hk$SOlF_gL;t+)hx0B@Nz1@y4D$ybkSS%U{flyD z4`(qjP%My8du>BlJl~eirE7(xL=A06H6g|HXg0;#1Me(k&SQnXZU}wrWLL>tq zARRk25n~LPR%8c)Lbo{cdQxspYwH%HxUe#Ks{J|26?|`dXHWMzATRblbVqXT9w>HJ zig|qwO6m-rtIq64l&uMDNwn2g1+`n@{`QFf#EP-rzI9%~y%+Z5BLv`-8%tATOVWXG?N)dMyHX(?Q5&ICbky|eYN13bA&PQ?f6Cm&y?Xp5S z$M6>~pPBNe+~ru>V~XBz!ZX9>JTiq0DeW@tlpQ>0JkTtqIcpyuP^#H8YTpLu?A+{$ zd)ZqlS=o#*!n9lATvYEr6W}$2ZJy2Dsvl6NrKTRFpa)fI16nGbz?mbpK| zRL;&#&dyEd?xpbTk;xgnegy0lj~@Z{{5V?%k3N%ivOxqR2>dKU3vPROBw%jDiE@rn zi)SqGl%w{q$XWKP0`R!9wU52zIdT7yu_B<|{KP_TZ1$cRHkj8#@!J8Vl5H=XkBFW} zuenZja%^5%H_{g1Qr>}y=kVacTc;}L;~xGyWj2rqUL+q2a7yKza9#jIb>@Y0thThQ zY8&vR^a8&7yg&ipou&YQ3$s$DhKHKnL&n_w|?FQXl`zle05wFYU<^ z*4A3(Ccn=$q^B+-3O5 zeW$FB=bgU&mitb1cieUQ4$k7)bNel4+9SRTaiL9l?f?kLzRwOEz71?-p=d1QXajIm zv1A2OUOI>aisd)*0ves?O|&--OQm2!GXNwG+XWCK*907rMNIZ6FrDMPo8hwy;|3T4 z+ELCAY(W4A6;({IA+cs~R;nOpS=VjsQcA|p3)d1qo}j7NzVbYYs_a0}00O)96^Nq_ zXJRp~h!GELh0Ou7msG(wfI1ps7rj<_)^k?;M$W=-yxd>8-p`++`f1qTz;Y$F}8Ab{U7UPKZ0hzugW4>Y(GPW4Nr$oQj z?N~AG$QKoquaN8|pjXhU(MxGyY*?~?8B9i$<~kpFKr_b(B*tDrV3j8Y*obg*;U8Mr z#oqxr@(l6_jzMr48Z+ns1jT(cI3xMQ`#~-EO7m^tok9J4=C3}Z^@?AFj_0i6ITK$C zSm2GX1ml^Frbum~7i+;>44fhjb5^19*kc;(#aGZ3w=B;E#UFf~-|icBv>WRK}f566p^)V?j}Bsk)X80r~ne`T{S= zW&jzr)LUk&i~~7KI`KM?{@3R^T3ki-KdS&+#e=GxdGQrF%XsC?B}yi0o|rY|tkW^^ zLUb*cJqteCkyiDXzDizaD?ml{v*=ex9reC$+0GbQZ zh|EdOSVh_!5%!ECG7j&c_ylKpC6u7bfo?v&f+#4DkyGrB&Z7s(V#Hc1XTW+?16W(5 zlQU8ZayXqSzkGvPF2|z5n5wxZw)mPgQndZvv@QjW)BlZq{8<-h_YhRTG8?pE-#-)c(4<;j=8KAX~B9IPbB* zmF(3#<~l%u*(ZQVlUN1!`r9PCh_XW<6mSm%Thk3F0#L};Y3P# zz?|-~FF-_5ya6!4s{r2q*xp%VWFtUi(LU^LW{Qg8{*-(oMK*}=os?x$vKdv_=sVe~ z<)MB=^f1*Yz=8@tV2?8_*(qYxXP)4c z3QX5$<|j{PMv-uogguJAW?tHE6tUZ*He>H&F|$3AcG>499p(-K^p4 zQ{fw1>}TKwd{G6aWo=A!f}TkM$gxhKEyxlM<}(?M2z-S@do=5h*0IP4g| zB~YotaeY^51JYM2Aovx57#wQM#xop!x4g0g>h%zAorBz6PPjl%QWt^56 zwH-hL?332F)HVT$5z93&R3k5m*E*4U;y?>cN-YsVBM1))B95jIrA1Mhmkn}gDp<4- zF-2ur4hr?iS!J|{@F0R5!IIHlP>(>NG^8Z1i)wqEC@N|t5=}*6PXsjjM8G5#u3lpp zi*;Ku8Ppdg;fZNm3krFB7BSYMA+fBgB{g4L!7c<^R*5J!60^P z%-<~J1bj<`1x5o7_UtAwfq4lmtJhKf_I#s6DL?oX4fOGH;_U-3GHMT&Y)sJtLCIb; z`H)vP&*PzDKWD966N`NzX`f=J-&ARkr@gAEefaC{SK%HR_?$NGhUb*>O8ZN)v;U=E8#So2<{0MeA; zX%<45AM-&vY`+Cjb9%Z}rS?-jnMfTXVK0+eiHNet8h}08i=#0%P5Rv^KjPnR#BTVT z7X0yM*H0JxPwle!q$Pl`BLQ@pUit8ka!v2b%U5{dYh8RwOb7Uem;{tSDFLa8 z_F5Nj2WbnD%v6Au*M?BV-c>V&b(j+77G+D~yK$Z1u1=?X(5FLv2`Dng{)(d-uYt}J z#g=?L2qlM4XTT+Jl-6&Gq(}#ey-`8HnD=Chw9+&fvra|SIaHi8dLK1YK`T#;mk`_w zt;Vzl>J0m3DOuYJ8KRg8HA15_7}-pu0y4r?fP_Z5;pL51gBl~#O@<9F6S|#|Hu&x$ zTu#IWwQxv4bvZUYwe=6*k{X>&n;{}ii2x-5tp_sg)r4Qu^0VV4x@b(TW zR+#jK=n<;BDMlQd)0Qz65vUnmOK^PUK8jf9Ds~Yz^!gKpt4;ks>h#5dA{vYeCKuR- zywOSzvqjH1e85A3Y#r97m;=2@;6M`SO9K5#U?2(HnFJ0dfxAqguR96!B!Q&lzNF;7 zq~yM&&G zq;LuO){+j8Qwk(*8wu4?}=wTqmL13xQQvo0XMgxneNL~aq4^sg|24axB1R5ex zMGjJXt@Qwi!WrA4K{5JVs<08AXT!o*KyF} z6JUT*Xj3|I!T}muPvWy#cn82a9I^i}DuA{KsCTr*y(s9y^G^rZDso{#8<&jPr9DCg zQa@26#6elCET}x}7(}=ha|_>0bD4N(HZ?KisZU4h{Qxc>dt#!T6P0LCh4Aqf#ivv7 zzPUA#JqCwt{(KAJG;e; zd7!8JK)?FzlQG=0fTgcUB{n*ha$`c}nP6d=1&pw*X`C>IOYWd3J#<0cJv2NrI;lih z#6X6V^372m%F4`fMc+v))LZdU>2?e%0s-y=Mf)VrmFIeBGc3?veCWPo8 zcT5)9RBeEGW02uB#^8ilflyh-*nkf>j_j?sS4(+fm>FiFUR5EC2-qYgP9)e>J2RRX zb}}<#qLpNZr{&X>BI)v>C~cG>q(Bo@`|;W7;S*R7M(4+I*g^e38x!eWn=2-0e>B+W zy0!_~)~Hmp$+66Ib~cycbGBKv?H(z8Qg#Zc@(2y|=}q#2hmK*< z{*JNA1$fVum1#x4kr-L18Ox}I^c#uNq&1!^np2v!Nf}+z*7W3bMsM|=mc^$mN)slS zj6jLpRo^TT>*O@0Fy3kLY0-eQV(FY&n3_6se0XXhBX!F%%P`l7Z?RHxW&+D}6DrrJ zb_*wDoVf|jYryV`9+sZ16wgfZod&NUp{)3Ys8FsRt`HJ!=?r>jS($Ex58+^p7Nfc% z%hwaBKOBgvv3Sn06-+9rYKx8*h$_VVAS6g0maVz@oax^=XVtu((%fiWKBGA?%t+D( zn_<3RWkUTu$^m;Gk47|nSl>Ld37;7Tv6^?|4!zNz(5UvjBxIbQMK3g}n+UZzslHae z?#*T9Rp`jn>~Kzn#^+`ivMR(Uj}P=Fp@F^}O`vuX^XX2{S3H(aRS7IBBU{F(9wiug zuvAGOE%*Yq$Xr|S`K++oV}M2$%B1zUE!jqC{u9?~3wu-xcla zzANh2eOL6a`>rTp_g&Gz?h{`drGnjeMF+djC}F44O;gIANx^ARfA-vWYO!`<>H&;H zXQrjy#&`oAIs)%ye6R;oq;wUM-A55z5;aoh8JaYshDAaYtZ-g!l5*-r54MlHl@1|^ zcqUZi0|4soD(I(ZStY)uf&>7LRjIP9XJ|*WBMXuCp0fMCh zIr&%!EsS?6J)?|3;A+$5%#R8U^hrnzxN1YZg!HBr3F$?r z#22q^#+5p&&o9Z)sfpP{_m*)p#Pd(786sGk$=RY*LyyxM``gQOw=!w4<5+Z8tx5>qq9jA{g<#)1vq!y~c3{w3B54V%4XhGq z2A28`i-CUA7GM7=yX+!^!^!Tog0f2>g?8xe^n}i6BMTujuG9;mfB*|C7cA-hsK(-> zCXNzxRs9f_0J+2rlE}Ow^osP$&=C^=AsItDByq|J(IHzmW2a;QJ|-n%smKQk?9aP= z%vZzz;xVH_TIdy1fO-#EdNkjad4ELa4fvbtK~@r#M8v|qDpV?9$WDaebL!)y2*W_3 z2Kq;Is|yEaIh752$V^IoM@ps9#Zgg9r;OsN`aqCEYc1`-j`Mf z_!0cSsw{X|02qIud?LV#F@W$2vax&=$Rr@Bvmw{2L4ZObVk$yub}lozPrhYp{@;2< z61;G$a@3G5@fU8rBBNZmRdA)KQ@&QpemsqLMrok^VIN63jN0&`WpWAAmmuJP3MRs? z8-_^`M%ATkKI-G92fF)v?ld1ZweW_ox}AL5{XZqyZW~!zzE*%de|KWt4QeC!4U98p zaDJEI9NdVWANk*ez3W;WN4B;5`_uERd#GhMZOLtl^FgR(8*z}Z5zrJ!?j^gcfhrI! zpb!N}T55lHwV(BWUBJGk{f;psA~Or*-3Plev#837jF@xGF~^*t2p=MuPE9LoyL%h! z8!O9uYpL3f`?(DqYga5xKz2?{eBgw(>Z4YpAVR-BFsjYc+Sc;3&9&~%e&>a7=!>XU zQ_u94nm+e?Mv?*R))npX%eDxg`z+IGIm^c^Z}K_Xgg3zD z@o9W-u%Z5Z0iu;PSUI>9X`K@YJmd}6s^Pka*FV47p(3EGchiY|d2KDB$hSSP8Hg-MepiJJG&dNc+{<**Z#h9aMN8mz39F;xDmW06y_1r zw7t_!^>e$f7a!N-4ut7Y!!H4^{0hGem)+@;TL}qN2OO#@Ef!n{xoQ`T$E4)ph%N;1 zz{Mac%`ds}b5DWp-;*%1|Ndq+yicsbiNvGpa4iaDE_%2Qu z;_K7bZ$W-t1K-zlk=l_Px;SwuTm05|X_xS3?3dq`{*V6o0Q_2D=6J!GE@aE=v}vai$uOF`=7;1Er{HtSHhQ2j^ia zfjsRa%`UPlq@80w)JVdGgjcX<_Dsn!u4Y)bbxXk#|RAVJ(J{a{N&Lx!!Jely0 zpca;UK+&fucD;-Tn{`8iK-oMmJ>{;h4#J*=U2Lhhw>WkYB2*0n|ImJ4YqTl|JY8Yn zsp@6z?2KSAut4{Ia%2!9^d6AdfDGTQLR;b!vtU_27bmy)Myg|KmuIxE(d2MMY9{i-=&%&DdCM>NvcXpC1zb*8)|ONo5Y+O zz6O3h<_-yJpxvW*N1B`{;0X>}x}o6AIjaxzWQsEiC=#JAbNj?SMt?jezNGP}TCzB6 zaUruDMoi3jnlwP!a+YMQ5CpU1f|slXExLkXYao`g4%zy*B=*%0gvIh{FBooko%n5u zt!`s4q2I1Pjk~QeQ}AuNhbvbw_-9tol;)g#We+fTib~@8VsPQr68Q52wzi)MSK&!1 zi+Gn_YVdHq#QE{kNKX%4+7`=Mc)7cx9Z+D}vRH0ta<8Me@e)ggZ95>XrI!v#3V0P} zRXZynARFQMYlF$9!Sd=U?EKiRq3n-`H)OBf;u1yV)%C;c^W$@6m`FPKo;1Km4{sFq z!{(3`U|T3aKit+(8j~HIhgKnIGb{Ia$>V@eKwP4J2Y}ty^+#zk+7!|t8IPByEB_l! zlprII(nqV^vwK+eMs6rqV;`-yO#TCo8NF9_B^pRYGo z_g*{#55JLZ02u%FXS)`=MgXXys=5IHR)6aX_l zp1%2xIqf2K&I3s$cj3YH1W)7j_Ro5)h~8LrT)(tsq09q=Rahk=?sIn6B3KIjXOX9% zxt*Guo?Bd4bT`a}`RT_qk7wO};;$*PKxY5_vKH7fA_!pr@&ykz5q--fz3EZ!&?R1n zU3~@_(p}-p5Se;N{>qMBKm73h%Esz$c1IAjXqfkx)eL~%5sXTRJObPX#TKvk6cnjz z1R|?`PqY}X$$W+6NMD1092c@n5ZHqbVJodWTWiqAzmT`kt(lC4iYu=nimhJ=(DK2PC!oVCk^-kwJ*b;zM#C6?5K&bjc?9d2QAv7UkM#wdC~!?m`9&i}*P?hDrEiD7R7^1C(D zE%FwL6GPHdXMe$;K(>48q}kosSX)`^C>V`N_XOqeLAL{RL4eR9*f~mFP&+QxG8sxc z2P`70e3`D8`SDwL4W*D?8#e}+?VzN+KJ9K%gL`TayuR_v+G-+W{W{^~musEQGW*pH zoWgaP`984DS`N^`{$-VLpfhHn=6JLu3J%n&?a43W8``SPbK{rs9Z6XFz42$Cq@gFg z)eeady7*Wu4ux~AUy(54?5Sjf!7*1$I!p!z39rw&ZNi15wijo9t(N&lcGo63v*j0{ ze7@3x>}8K6UZ13(U$33rVzTRXvf}Dl2^;D`jXsqiTe>RH?EV^aJvhkv%SsL%gzmT?n%qAB5<9w^Fz^83E5h~lV0zs3pEC zd-O&OExhh6K&_269TJgtkB6HzmQ7qDulb-rhoXY1j%W9Q;oB41nI9$pF9H%1acvNkeW}rz_R+LC0zXn7pr1Wd=UGUWU`002(t$sqZIDv)fvjr0&TzaM%mMXuQ zU-Je+vRjds*i%KS@ml)~<=3dK%48_GhXZ?uPqPJSm=tej%_FitToJVu@pE|4WF=9UdQ>T+(L*2>t;)&OLA7wXK0y(UERESb$L3-U4VXm^*oZ2v0-(irJ0pL~=h&)|_d5Ua6My^$#a8g6_TiwAWq1U1fNF};rOdZ79GGkP~MvpKy zq^COQ?!nhGsz2k|$;yEP!JpXfD%T^euwO`NEvzF;n^VsMOU{zV6@ z5?Vm(wgdD!>}ov(^|DjSgk^F=s}mF)!(0s~ZiZJA7~6xhiIc(1;?(T?Y)h3H+9mqYe;>7>s z9IhyKB&BO;tbYl*`m-SeK~dChik{E`lG&&ZtPM3#mdQ%MH~1hQuY*Evt+8zz+rvpf zyasAz@#fpW9Y=RV1uxG@Bs+J;w_hY68R#S(1leYIYtzU*y*NDsr)m2~z@^j&nx4K< z2@rG_`u7ty(p4BZZj4(1{VI`(51<|VH$EVrZ$@(?Ou2z5a_+UPD_?4D49PCzQ;jTD z30nAMLF4g^IfaeOfastMh!3)UNC*3uncxM>5)_bh1NOe8OW!)_@^MueR|jl`mKfh> zW}aUvn&|#~`tIP}&1u5@dx4mdA{0Hz*5JAlWpE%Y9K)LqVt7RbzhJitR3wnWNFL8w z!a(_o4tDsslM6#(E6;Zd4~%M(1B>rGqR}^gE&36egU&Ju4qUmzBBDQ-Y<7+#tRv3_ zxx3L!fv^R7tCA_~bW~!RlnQZ>#0omtc>eRo=H^mMU4l9I+y2JhQj5sxIutJ5mCfzW z+Gu|u#ob+9N6l#T7mF%A#F7$v z;0-Q_abQ!&?ZeuzWujK80vYfWE(TfEgmIvYSlv$cBnMDBCq3 zoD3+JTxib(h$P{z-H5dt=yxg`lKS6pkrG{g##7f-P6xC3bdsV;sI`8opd=yGpJ1!v zzp$-IhJgEf>*MSLidz6D>ZjvDg*fCleU50YgOj={qbk~v5r zY2_Q->>nJf^gP-EYa-)x-Tq0cVHMmC+uZpe7_X->FfSr^HWW1p4aSe7x=>R~a?UM& zvJW5>D@5mm%rA0K@SS+a&ij1jr%v#|cwd-)zz7*hb>EPa(nC%7&8cpFpTQizP(a5G zm#&oaRQaILqPPo_R2*Q|u?hNdd>E4oV1x^i#M1|7nCjR=r~OQk(Z*_Ey5wGKpl*x} zf858zBMRy*1m#leM(PE9j|es8#(`i$E`61Cksc3{S^LfuzSQc@Oq0e&Iw^=5Lbg}) zfTeI!CWV_z45|6LU}4ajOrcVq<}Gz?W;FN_!hr1jZLaf`Z{V7=s}czqezxo6*=d=vOQve zALLf74r83vC#&yH&&QR|bgfdLqyzv!M%wu%yB&!wSBt0#IHa~5gs#RzE2&hF8BSr^ z*52Cg*79bcHF0)^tFN`aQtnO>ert32+1h4G#x8Hh(eB#L8a`$c~p6Ey`BO+Afq22XeWTY7Vl_P(6;0})bqCgTK#kCMaZlF+=AB0-l+g{mDBSD&35ok9uzB_L(ZCQi|DQF|S zrN)G$Jau5DbS=IiQ-JXez!`OGO+e*u>|JIc4N-aZZg*{cAGna^lWTw52a|PQvaS2} zsvr&dub#e?O*|8(!8yVL8`Km4=%a!F<0zSxNQf5<2x3`&whLl$W6_XYKEsrY7wsgn zGJZooir>&lWo~h8U-H|+6=&EH@8swcN$n)5)ZXSSjHsF%{@VV_w?905^zS#neg6F) z(YNAY{CIhM-Q6o9SscAA5)#4tYUMCBlIte(C!}*&`l3du%%Bnqe z69tgN#gP-n8M4@0X3P@xGy*M9T)b0LS#q$WYoh;)+r8yXtVk9F3Qgwe*dtuoaBHyU-J8+cGf{WMCz<(#{)>P-SzzrCf&VYQ|WeGE_ajOrZP z#%jPKA~xfFS*op_t>h4e(3H~+-=86mH?IV3`2N-U9PTt9MVEVcl>_v98e*^s@G%On zKhUwDvNTF+Qc-nGmur%ygA1NJpH+&p$LP+9SgbV-3ya6X+39E|AJspJ6tFfcAavEo zk?%dAiU>TdFH`oH0o2n_zoA4mCe8yM6T}QsH+~TA5@xku`A;eY0C7HzJTH|S%%m%VfW%iDMumKkne8JmBI zlss$DL6lE^(zKHGPviw2?Tl zEfV+`n*kk?(52r$@%@8`kN*1okKa96`t_@cH^2QrPWHO3xXlDx>nUK1RnkU!0owXS z*;VmOSAFgeU~EWrj`YA7{X-n`2pxZofU5b)`N^rt>8ZKNS$D^tnp>KjU7DP0Ya4*c z$=S)t)-&vITHvz_^NTYJQ*(>cE~#M?#mIH=8?m{Wt%~}=@0U9(8ynqHX&*pf+<={_ zkPbH)L^Y6+!xI=w!lCe}dmqzO1d2K3L4&a%r7RHVvV)A$CV+xdW&dkxYLj)I zP*2LDYAFc!CDCJRkMUu4C*~=qHDA!Fhnxs)lsCoIy+8y+w;-ZSEguAcw{*niyL7i~ zVV)25S+o`#K4-5WD#XcN;e&Jw;-_lh%eR;?6<56`0#t3W@y}WiOkn7YBFF`uBt8gqrb_(#IJcOZz?TBKLqt-)( z*^f>J%P6TKPCxi2D^%vn``V!@=Bh*edK%TL2J~u21#47sv1eO;i8Mz8jt1Wir z1u3IrAJJ`fbW*fFk;8SmxunddFgHXtxVoM4wAVxmgUups(>8V$Xy zeXkA`;=3tZ>8*`Fu(6cduKwl>w|ow%otUFYX~9RN>~D@W^I<6TemIAEI-vy(TU4>P z(o@QHOlr1BmN9dn2IPNp<`)bGnikY@j#-e*T9i;^aY*{_tui-aQK9h0pTm6M1mu5p z2zru?k-F5A3qGfYNuwyGfUg4K;uocuC9hu{vXVX}=S4g!)io(MCB9qLz!=f`u!6MI zef`}3#3nh&!=M+4KNMDkpQCm?4%>iyO^Ny!%KUR8+ za}&^N1^IFKQ^&kk0fLewvQAp+)ndvg@w5hiv`1p-gp7Sy0c9sl`$y-L(>Z6#QknP{ zykqT9{yH7XIjZqWK%@)^HKCvt1NHf)IxL1bgmY2gGf*(*`K5wo9$5_(>Wvxs@lflB zX^!Npvj6&9a^?;r;t3`!2ubiaLp*6E^PrF2e*Rp>W9)r2u}y)~@F~?WM6kAnlvap+ zf7+5_gyA8Ui9klnDn|=E)E2>)pj;99Wy;N@82QZ}$Pjyn6fx zdYWqI)wT8N80|Og_%wN#sl~a4$5WH3p4tI+3B~>j%tws`G=)tcyZ!!Y^FOWS6Q;Ks zckp19HeF7xWVatI>B`ZXo474Quu14=1XhC<6&j33lu$!~miahi%W`Z~#peOx&{1tD zpMbwk6kX-$D*`VZzpm^mU`a4xEr;<5V^s84kaf^{vP$@?@CFr%+_f}f?ti*=itQf;!9>i4VTy%cx_ z)u#+(1$%Tovr)b-(B=<_-|sS2F@jz047Xh!>-XIDUjk5&#~yWgMr^2R;!0J!t(CU} zCA;|%2|^a&n2v*<;(8-{%W?gd1yVEEaudXD?^#4q4z>}SdKK7mS!KQSH>H-ESq-A( z@>@2z)J9F8WJ?R2hBS0PWL7&{kw6;;8CU>jg{}f&a{Td=QspTI@z7{er1_AW;C7{! z+}_`V(A%P~>=MgP$mP<&u{NHCDNgibi27CtSSj8ZkbyM#*+rNVJD{f>k;?rWJ=Q*t z0*NgeHpf~p^DYgZwXlfJ`8;a-<8;H{5Rq9B9re4J5t zIVOgbf%Y-{318qePz74AOpAb8?dOc90=Ax>hf#8D1&pNy2^Y@rR>WFWm2~)25t8z8 zDq|4^p+QLA&i9{5N!e*W<$KKT*_n981Xw_T)+5NbM8-88(GHBMc=Hom+%5lnM=VPjg1=R{U$};5ZzD8plpEpDs#V!Y}TqKhdz$YhzI+d_(H`RG#XMfaS7r2g$w{bM{2A|?e?dyUzZ8FAvCW9&Vv zG}-(2US#8!3eq)TN%&Yq%77V`jBo`l$j3R4Vp)tLw6{)f* z3D}|*O%+(*qUg7E^0XYE@FfT-%kc#$Zu|JSI#$d&tgZ`~*RKl}bByh~Qh`zka-!EK zI|~rQ1|su3CsL@#2FeIOj6#-2EG3IBv(P$&V|gF_UlB_Tr@Nqk%VSN!R)AtwF7gN5 zTcXwTP0?S5_CfiM4ZT_vFQAsx+#ET6#4%}i1=}sB7$AG| zE$Asd5qLw3qq`#vy8dJ_W+&BXFCV@8fd7=LCi_pdRI2y@wN`2Z-ls$eOw6mA%Op(-27F?AjpNr!;q}QOG>Pt7`=c zo`9{5|NWma_K|(h373;$^;=sy7u&^lYt`znG&t;NklK)@4Q0Efk4@G~*8U`-v~_s_ zspIoIYM&ABFfXdm@3WNuk)YwWr2o$v%0g*ZF-OE8zf>n82>DnM*OPNWT~9rpo_svL z_;_w^azUGF%srl;oSmPYU09f#aa9qqaO{qiH5cmU1QBsQfc4AL0C*xt(a zOKSU(m~C$*-J}&k07D`ihEc2jO05E20&aJ-q7Hrav~-Q1UiPj)wG+>;XwCAZb|N5g zc>7%$hGp9b!A-v^N`kEy%UdgJ-M??|?{+C8e`$Gu>qY`BKheGxtlA3sRW3O(XqEmz z^`HEjI!reMoK93kX4L9;_m)+_uZF&E1~t{4>h6*#m&l;P<(^8&Cy$Fn5|IRu$3vz0 zZI6V**$4->p_&^HA)Cy$roU^^s(8Nj@MUN35rQNU6IfUo1gy*^3w2otD8)RknvZIf zgvxdQjyKY8c=D1^rPtb#@LuZFvrk)t3-7YQ2M4uEpg~OFN}&>|_!;b_=*gi-BPFlc zB%LV1OfxZ0v~tu4H>9{^caiJ2iuVqsy5s~gKKBPxN6isPX5(tU6OU5eU7 zW6m_|I}D^Cdv}jvRn9sPKy7)@hGDC-v9`6>U0>eV+~1{?Xh2^zl7(p!4)>(PLQPZR zcdIGu0URk5FedG@avz3Fr$+)12$EJsStU;t)4Zm|%Fo(dX^*u$8ssd=-4_#;!;oU4 zsuLHkit`iHpGf`y{e(3KndyY~#-tM-4*)!`6NXLFJDg!e4+kfV=82h7jP4ja$g5Jw zRGmx=W2?*r<(36b)WVG`#{&o=G}e^_pK@y?dwsQ z7*Q|G&TE=Lk1YSA~))is|GlkB80Ts3e?H%eh{Ws|6?p1y z9*v&(EuYYwX&o{@^uzne;Fu)0QZXV?vG$>ooL&%|UZcyPo>|!cWU|Sd1N9)j{JC5W zQ8Onbh{N!?ISBRf-hZiP=`hfunFbeK;$CG(6C7{b-L&bw(mVk;YMvmunohXJR1on| zIiZY`E2y;c>Oqy)mH%PTPWe-C@ubp1T;MgGLXQg&U~4i}7HB=0!X)v?j;NM@$^>u_ z+fRT}iI7N=4uRGb(5txR^x~NdrA)QQbF6Xi&My$ARAjuCW;p@>{&9SSkpDPdqvXll zV5s^Z-%{TwGa|&!SD#;IN(VWe{qTclB`U|!pUyya6%oKxrWpR4p3 zBrSnQt^ZA&$mu-V|1?gB4D*SJIPEa477J)5_e(IK2glgbeX1c2!8g?Ox9s*zfLg=* zVJ*F=Ut88e5i6hSuplRo^z9Hu+F=`U&wzbF^uMtl-1ag5*T41uTZ3!D-(+F1^@*4_ z3-8&Pp>e$;KYkpuw3I59Gr3;ryR=`00^~sd;AIKa0xnN}lmsnZ62;8?|i4XqNDC=4|xM6aFQ@YC}W3?+? zpwoKoZ=89hoGuSSa6_(GAg!XA^O*{8teI#s2ha+%N|(sjU15&htoL+Sky@K|SN3=o z>oTIfI?{bU7?&;9hFTbSg#A+^XV?KQp}?Aq0yIHoli&+w?TE!x=tFYsouwWP)rRyW zb)2bRQvELdN}Z{Gmw$JHi~%HrD-1!bS{R@pO(Y5rKH=nirc!DGF4Jvi49gke+S;$+ z%w0{#h|GcaWCC6Gl^PY!7_L^pekbE%a9K$4Vox}>wkUVFV`8LE9Ro~B`&S_bf{XP| zkhA3W!`1FOim79DpJ{;gLWwVv4k!8c7Jf6ysS7Qie}ZxVF{*odfZENW+%s6x0{<#d z*x&kjiw)_ziKOq2^)h&bHJ3P#l`H*)XJNNv8N%Qy&*ZXy#gjLqEckEG+C=Uf6iO&+ zK#F%=C%Qk5tC~c3P#~U*<00zN8Hhn3bW3?28Zqe1iRc)hA*VrR4Lxg*snt}t%EUf_ zpg0w2WiR1c7(jX=tQ1>Ghfq6%gTs8W?*R8gUAQU+qZw$HNT?NNYY$G~7If)4nRt2v z!a+ETM%%t(5016iD=A7ta|~y)4sY!89;9qzD!f^vT4+akkZTMlNbZ209jM%a4V2mg z$8&P@OjY;&3#JxS%h{)=6}YqX(C98}T7@BH9IN-xv+11st!XHvd+iE}7A5Qnl%fz; zbw(0Skmj&Dqml_xd)1lC!6nP9>bOo0CS+OA=^4rH zsGASGx(2`3JVQ)9f@$UTn(tBHk#uIMC4pF=SXo*i#H_k+XHfFsNf2UuV0I8>|F?&L!32&~e!IxI>u$|6W`jO8B zouZzU%`-x!H4vIY$l95dB&(g#2S6oeU@A*V2PJsoe5Ue5`HTR0OB+*aa~3ShweM~F z3JUM!*7P;2+i{9yj-Nk+J;#Q>|2{TM`z$vUE50O>T70^|Ji0Zy2hda%_SMy$E$!dI z*geWp7FNj#%bi)L9wx$DRIVv5)H?q*inw<$hJp#d;c{t zHT!sSYHEIJ>M_!m1=rz=d(6t{L@+PR&P~oOPC_d`212{;Y#HNm#V%k$&{@X+40m4Q zeYyFu_basN?-@WJ0&dhl^latG>BrNfPM{FUT#ElrI=cUOz$rtA)l;Tp)Zph+fhLw( zlmGER;M0(*!ldO?1xig5G6m?Gp&g**p%X)_7}MD+CP4#k|J2!I>XwH7D}V1MG_|qX z=|(Yn7wL&N_}bW7UWEas=nSYui&!=t-q_mM+n|Cil|73sR`tB|T zq3DhYUH{p+s;t(5Gc&<8tgTbDCx^y?uZY2`ATdw&zinqn=_g^UG`5zE{DqfAKuSx=rrLY0q2@2$&{^$vPu)7cNv^Ut&!%vPDwbT)rs4n z*y_Db0aIzOBu=>KkQ2%CzyEWNJ-ISePjcwYo$3$6B7=8B;@N=jS3%*XE~T~lkHkjy zPKV4X0e7Ku+vjKx6phljW(&aEvIRh7DSXBh)G#}lTNER86z||h(EC6XBksFYSQ(HD zE`8!--_a?7@<-SpZLG(CbsojECpmw}Lx$^box>DKE+bro6Hr|fEFB=P$RHq~M90;Y z-F_5V9%N06cUdi7CU-Ga)l`)bN3LBRi6N5rtO4ZiN9J^6C^WAN^bd_Cs;1 zVR9X>TVEaTGGPo_bG4P)aM$?XtW65Yt~Dak&dO65-kXd2Io?yEIk`0+Oh(caF=mZI zKIH(Fj{{ogQ&hRP6#M}a>ZhcI#CPOV;@0>(rTjB^t~JD!;(Eklrj#B^DzfdtOX`&J z?vb2#sCn*OJ@8jbX$l^(_Zek>^V>ICAW~!)W(#jmi2e1xZv2VW)H(Ujtuoj8W_vxq zg7CGh=zHrSqu=I`ES$^I6r^f)GMOx9R_`Ghl#quvPWj+LoXQeqB{gsd7%2q4s7l@? zBvv8tVvsAwxLCQ2rk5SV$L3!RSZ+U<-(~R9Hfh&9wV`NzMQ9vNv>GW6L~PXdHO5P)tmGh! z=GhV+KGG7Sg_n$>vO|~T+1NyjEyJ~IEdO1aou8ju%uiX?6LGTsCHL7Tq+-Ce%vCKZ z`(0JwVJK<0S|gGr%g5yhZWE{_HV$GxP9+#F?gliPka^(n23U_%M#R`tB|aEe;*ot+ z&)PgImMQ{+W4bqyVyX+p0m_18KyS>Ijjm}JIrEIYlYU(8B%eBj{ibq2_mof7>Q~CC z(@XNUeph&eMpDKkvp@`=pCaXtbCZv&@xsdDLHLh4f^?HFcslmpdv?)>{{qWJ`?vjE@(arjjVx_+}r^ZE32j*K@&SO4b$+T zd5*eJ&KW#Q;Lx8?c%qgw6Eh3bbJLF}VV7s;ryj?i!b={0t#uMRBzJ*sPYYNMy{*ym z%BFL}B#G&R-x~YK{~oNWnsHsbpyb$NkSOPj6$2&;jd<9vUZ}xC|vamGLjhi zPwbm*<-B)hXpK!$Unz~O5G?SBVxLbHgr!l(F|?(#gdOxl1UNNH*tk``M<8~agv*ta z!m`Lok09{sn~D2VYlNhi*xb;5OaS0YI~`hT5phL7UAyOuWb4gT>rGHMEy+F@vkF|e+T@tq=Rw?UmGGG*&c~JsgR;=V=Hap z(Y7T|%|*F81^4sYM{8C5k}4JM@1+aJa$1mADvOMekTW zsPz_`zW7Y*gh%cLd_ms=1jBCI8t*&V-C2QDpfGWFFt14W}pRbE{&qxDR4L)jX1++$pb6wWV2 z{#Wxpz*~ZFlEC_b2(-mHqm3Q@k2o#;tv1DNmLK|k zJk~~8VQ8Z1$M}iAi}@0GcZZEp;`Y>t;`DfeQ12~ISh5w(*fAJF6V5TL$(5CJHQE=B zQu6T^t*0m35k$W$xs2^iH1kQza>I`iL>;XCyhK>yj z>77GzP^wk|zgeLBAaj8V=OW?@Qbn4j3ow2)cf&sOM@h<2f%~MZ#*8XtcJbL$Hn_rg zH}&QSG7Ma?{tVTDN7yS0PoZ(={@vKQ38W)s+B}DsfSDLMM*^}xlh2(a*il`7=lbR_ zor6t_E(Ln_Db1#zS>|Oy*f@7_-|&VN>dxQ}{ZM(I1j6lTz^}9)>p8VN3H#DO*^z~L z1g6&Jmdnb3h+*K#lPec;$TO4lf?8XOn_0@)9A*I6o^#Qt%n&^UIv%)ql4%9TU{V^Y z(3btVhll{qlXM~@>nMWP--`5()faHPj)!;B6Re#}MU(=o;=rO#D95&SfrZwEKK};W zfoGHk9=8#cSxr~1JNL8;RNVAO|4qmHYFv_4K+=V}j3?>!{*+J~Ad6}DO%f`zD3ThG z>2`ZM;29d>nxjx#4aUdaHG=SdGuHd9b`nVl*2?U093_XP3c3Z1d4Xr3jTUZf7H%#9WeI zKyAjk5+F2@*poG^vS76gAyfIv{odBZ-MpgoxUP<{UqI;|dbsnUb`ra7v}Mg;5=iO_ zUc5eRO6tB~Do_DxB0~Ieg1~pMqfQ1YUC~6_zdl}+!bZxqJLw)ZnK6r8gHZ2N!!c{nzYi@b+f?>a=rk zodpR|HR=YV(jU1AQhM6w$EEXGSn!ja*aow>fq(xy^vy>621szRTk_$+$!8aq&35e3E`N7u=*@X9Cb1bRl>*e>G6hWb;P=f z@l5)J;)m>+jZ)Ri+NJC+@}+446>&FLD%T`fz4S!w4|BuowZuyL7fG1_-vFu?E={8! zsGQ>jyX_jmyckV7x(r)i@mzwJJ*EsFg{vJ{X~_uF*u${+_7AqltUFp)U6Q~H%Z7$Lvz2?JCm-p`OezDI@LSHv0z7=?}UJ?sLdvi>Ghw~ zu=cP#g~&YDFlwx0IiVW(e5K5r2ia(Gw1m$mZL8D#94;Td3%r$;|#5;{pydhv%sYh?5muj_s?9uiFY%`8E9(ylOlh8~Iy&}B? ztt#)K1tNB^0&7F9Y5IdHv=X-&JBhO|4LvqMVInyB<`-N^%0^($JE>OWvqbXZR*iSx`M|jo}@Myb8Kuc3Uf?^3igVtae~dc${*w!a*&1z=El* zE5LbXM2DGaS%(p*b5ee4DnnUEi;z-uA7P%WD?c0LWUaf&NsV>CwS}V0iG(nboV>aY z{0~a4np>n^7fgw~5k2ojAgaeE%)(RG3=ufP1Lo1td&q2Xx?NY!!#-Xg;Tq8l>%^2bKt(VDvN z$LazbEa(v9E8@$9{eLD3;pjqO)@KfK~Rk zKcRF)YEvdX>rkCw*>RZPjlQ4M#01cALb$oGk8J|&T5Z_!;j^Qa-fDmC_)go3C?uOD zyFbsi)C)6{3kx%kfoduh%hY619R@k6oX?7STGcTHPcQ52J`e#0+uUAVd$#|)E2?q2 z`+S=%&e>CHtrLI8Uo;v{*v|S7WfB#OC>)4{a!N~=I-bT^7Iol&b!%Wpk=~2`8A_-_ zNkdd%lcqwHTbXrWaYSlXHCIinM?De{OQa;uxL;(LzEvP#y94yDmJN&PQ1m8J-Gtp! zyVTB0ac(E#^Iik1*0H7sFI zS>x;mX^54#82856GLktDU%H?LZMpHhv-k7*Cbdpjh`c$T2+qzP8FYNl;eaTBi-XII z$XG`VON6vz!~Lr3b4w)dL2D0J#DY*O8?lr&8c|{Mi}zsw0D14Q@x)-MVu_J=M@<7) zp`PJCgvplLfBALdVf!zS*uh`d*ppMiebbyp8JlvAaaLYmAB|*+oRWG^r^FJW#*@U$j}6P& zs3uQ%C`OKfRiX-dVuQ&w_TB*~{eMPs;?O7?rrr|lxz%KXvzAKY(B<2piCf0?)LYpb zW3;o1wuvFLZnk+gD`lH!vl6y>Ht-x}ii~v)urkM`h>f#NaN4nhr~%QHR7!hrJ#5mY zF|BUYCdtsqp$_Bml(88bz7-%d6{=Cs_RI)1cf#^X(U(4Zr|#8f?-UmKtTArA6hvn$ zyLTy_=@p?~@4~rTKLQeVhcG~pn;=8&B$Xm0txYR-Sz91i95xGIU4IYx0Wte!sv$AJ z4{BC8MvZGwrqNS4H}KHeD+!y$rC?)Z2y{H7rzaT zuYha3qyt4@*T~uQ>#DPI_TvnbAXS|Zh2()PYyCLZBh>^s$0}BrxFbfx4<(bLNyU(U zc;c}XIMjOdiv$J1`60=_394h*WC8*zGl-I=nFVi;L z&9k_@BxCR%U3oev=|eBu1nk=ig?t~xH|LWD?&m4siBis{DIAuzoNeq6kiCe*gTH8rt-S+DP}iudYA(#qZW4%Q*gt2(mX67t1Z*(K%$9 zGKS6(M*IjKrp7V$A#+IXJ$+ffxQojN@#}9clABco&Tz61REC8)#6#U;NwV;yU3jm1nf0sf3K@FaBA5({lEQSc3{NH>00OU_9!g$5-FI+lq?Km6W(Dw4*A7hxSj)0pYYuTQ*MI$hDC|)Ujle(!}#&E z6}fjGXtbs+Dl&tvr3~tUE6{3WcGKzNaa7g^?(t~`g1ap&JnE3ZXkwlj!RlEWAgOZ# zF1a?@@`p;|qGW0MyL>t^l$p=Ur+GMTumPq~WBGhKzb#?DNEN3^RESz^C{i?wp&D|m z#8xtV)*2<*KU4?Rs6BWNnWTtA#D5iTv*HO+qV|>X)bxx+MM!XRp^~2pL5Y*lMD*>~ zA(T4+wK_yS!;F?JI%U2jU{Fpcc9uD%JW4)oJIuTB@32zui%L}S{>N*`Eu%It*My#s zz^lb5VaN07wC_plMF}9j;4YFP7|)PY1HE3nv<$qP>x$f#&J0oAYMMJkp`B1m0J$tQmwcb?X+ToYt)m zjvs25fk)7}ZKI!1c-PSxoATahRyK8|OuEReSh$o&*leOxF4iuU(|2H-C>C|2gJ_{D z^#gj7Z~`pPcXb_>fK3X)vLY4VUbllT6+5D{y@X7XjXk}&J|0KEs-6hvSl#Ano=Nq% za_DbA44Xs06jmRdS^nCZRDpkuvH3BjffavXJkR%1-LdOO5(;HxLtja$slt;0Y#9UE zRz0H#_YS&Dh%vk9{2_7r4(g241$LtK#E{65nZW3qJZ`jA%W;4{w+1nljw=cM zN- VlU&2kpiQB(C$?3dzhe;ot8~zi!KEp^Scv&lDIM$Y%$)E%@1bZlApS+peDCX zxq40G`Xc$D{lWqBMU@jixt61-%g_Vx#_B{=#@PH5E%iSw2{?v&c5MsUCVl`6uL$t|->DW~^aL!$Xg`LIugAlG? zoerWxXH8U>|4|rf40mF@Yxjn1mgoti@e(H_$&Ik1m^&F!s5{Sy=e%Y}nEl>wxVW$v zLs{ulb7NcNM3#Zy_?5c{ zA397m&39@(3>CynoTcPT5{icMRWYBfXD&f9TF`nJ`*=S$yVUARyVuROsY~hr>yNpu z`L2lpr9RgnB-}U)tfYn-EnAxBE0$Kc8N|ml$Hmk4!1fTxRGpU@=fOeIV%VMryLy*v z;xXkeRN&JVLh9hTQ^J+}Dk+A3oAQ)!H-HHlKAC;44!&scYCRHsh#`mQr<4hEO0l(jr zcEZQxpD`P%zqtdD?UFU9iRo-|nwcLK=oJ8?b1tlpqTjG_q29m93&tI4WWm^Jv8NI#ewa;n$KM?QKKINfg7|L9At63Scjf?AYK1j~-M5I>o z%Z!zm@TPBZp@CcL23M{?BL3J@OT(#3k+*Eg#aI-Gn)pB1Sm_hX`2el5(Ao~{=l-X% z@UsUY3CArVIPugj#skmHQI$lv63_tm@Is&>Ux`PTSlz4MrEj`aXtEjl3a zD$b|Tj(_!x$qo+f;o*L`GkAl9*Np>Zqep?@Tg*>rt68X_>Q$|b_(5>#Ii!LX)?DCi_W`;;7 z4AvREK*C6P7Ud&wdY8!cr7?`An7r%gU8oyzAm{cSG9XvY3+P61Dsdq(B3bQNXy00H z+Ez`I$ig=lcuQ%(nI~x(DKC0k>`FGH!Bi>VAW;&{dmvoMygo z$7@!3-Wd%BS4X8%8YkzB!l@zPwb~2r3R?VciNqSS#OW$%AG)kuRhM zmQ`=6e1S3f_=&Q>O}P997WT8Os@w6H9@=aOW3QZW}m$6sTY|a>2#&Rbn79F8PAv zAFM*D=gt@IJSbm?&F(Tw8z4{+9SnFVO37*%Oqs{G&SQRX#7JQ*XiK0u?|YzZNY3<) zjdY*dW-N%eKHyXCz~GTA^HM9C%0_9Jyjt25rY@lf6P}?v2my{n^v}WVfN9sey6!?S zg)k~sncx7BuwYvodFb%8UtlFtNUMyr@Dk0d_>WS$T^0Ryf$Cko&)c!xxuW8EUx^-8 z1R}8mqT_L|5%Rxsu}*l~ca+Ur>M%L@^@5YXEg9kuaQcbN?6tm~n3|oNqY!>>ngsCt zJVii@lk@YlO8yE$PfSitOis5lgibr{E=(`XQA9L9#nx&wv(s~rCue5zF1t!@IC~W4 zE;VKwwhWdFKFHyZw!v`L?_nXoYD~zz_;d3B0n>BJY>}>ZH@BbD!s*qTS~zt#d9mpX z(yP!NxrZq!V0nRlFGEn5%!gn9FIhP#_mQ&f`z3m-o zy9R6>cXMHDt*2D#W1#rlVz%T>{_$q~FTed@{P`Ck>96g0`RIo~jlfDN0qzH!iU%{| zbm@1#CGQ54Ot_2=PKXty;@9BS0D{JxJbYJ~h|vn&0gVEc!V{;2))=E3Ty^2E4o|W4 z&ZDGQ=NTtjyPN@bYU!s0Y)kGa#T!HnfO^GzYMF`XM@d*Z6`fqT8~k9x{X|?(pt;-^ zHP^cdezD&gWrE6;ozVu{gcCgKPXJ)nV#Ae+gi#auDC4(@N+d(^^|4Gpjxv5kdT9)* zD_XDkZH4(nJ(zQzt9P^Let?qOa!s5eU)UPzTLGvLtCZl-M60Cc# z;A2x8=+VF7N@{b*Lcw+quKs;>a;X0w{QK?jO#eTy;a+OhP%2apjy<8#8tC+wSE#cX z|J{@(R{wtn{^8i|BWZ92AXB#|osz;-PeJ9NnPm$2mnXWcl`w;N`D^;#L~)$Rz?hd2 zxdpqFS6iL|iNl0(K2`LW}&%8Fxh~p^3n%c&j|H zojxsxNb=Caqx_8{H)H)^TJ&*&HgtvElrMK^TCxu4+%yaD=L&o1WWTuAcSb$ z*1VEYbQEPpjiloyJ;Cx6niyAxZrIjj=+}y_<9*L=~V@>kbc>h`Lm%M-5&`hR!}!pP90?}|KZ0szx|{8`QN|) z-&T#&&B$5P_^DbmS>q{4bINX(1Q`4%=4pFo`h63yx)>)T*7_ykdyx0Nmn>P6@=wif zKeylf_T9gq{^jALfBxV9{E@r;$DhCb^{a^={`&pr-&1>mks`MVb!>=yV!R?iC8Qa@PFf0tY>09 z@(4k9#9LIJ8KMe8l8{n@iDODq!D#ag-3AywOLQ{lh zmp9yhEYxWGxTg$A%!yhO-(&jK7m5F`{_$(?^UUvW##_Jrz^m!ZV{UZ-(S2K%7! zwBM_YE!u=onkq%8)*a|D=)BSJ$I&_|m?SGEGdZ&HN(K&(i?l~j+$h_1z%atq1j;B! zj>%;!b%>sU2dl*VQNj(GJ0vf(zT3U>X;?F_XGF842g9qVPdJq z%p|DU%VpzH3KTatsfj|MJ_sD66hI^I4;L?n(FRHvU-kbLts7CH zB%4*KVDG`!?`TVkue&=p^jGN;@k?Xc2xz8kiNaoL@>xK-fr@-ic%_bnD&(Die2fx* zRb3)|>mHBtSe|%>fURHFwl;nl?MKD1p6m@$g}<^LXdqH-6#|K5`j|n=Yw4QdDjur_ zachj){ixItDYqk7NcDORXvy0kLQ`8UL5x}|OPw>camhWGF3y#V%b4|l|0e`~4F;C` z_JRsnKdf!vU2(7?XJy!@T-_yoe9@VTo*lguK)1nI*jMroh+of(80o4i$Uj(?GVdC3 zab9%~7+m5MUlZz)>TAed$^H|!q+N9LNbf=h)d0AvAQdU%Bs@XJu*nIV8!m^2iv^1% zDH{REx9~B{mdGDa?O5lP9n*-njZ6{?kFXC87eWB12_r&Dt_uG8y$bbC%~Yt@j8S!I zda}Bt(YeZ(=1A#Rmnik^_i8dqt-!jJGGX+TIbw;_9J6R0LPb9St*Fc(X)y`I=5A!E zilLO?)sgCI3GQ~p(R{A-30hKwC;f>b-8&#fE-oZn!2i3YKsK_eBxm>qMC#VEU$|xf zHnljl_;~U0?BvYc?A+qq{OrOUT8G$T_VMK7*~haBlT!-|(`-FE4X~Y>n~dFNR|=dY z=&YQAdtL|j%#nPh8&It2YXy8JYCNrZMWqUhS*dJSl`GpRl|$*VF50}~p-$uKd5)DI zpDy~$pRr&py@Z1t0Kdd}Tz1zJvlcNgpD0yH6P%vs=N0iHrTcaiJ#AAerE?TAc3;vU z5uo{EA0jtJWoLj*s_Vd8CpVW|V@H6M7j)afg1`}ZWrkjBPbrT2UZAo#xbA-MKORVN z!2cdE@Q=lRKYsM6E;?xHF0b4@IYG)19vFFn>HzTE()6ju_)-{$NknUtMCTvrK z$u?7<(&#?a@0Fq=;Q;+zI6)J}!tm}5f+;4thzFPgc3o4g>=mXWdkDKn>TZ>T8-6#> z;;RL!%9%oSRM!@(g{fY&EH_`PnXp|R3yHvJxMX0As>47AyRIZK6G#s?O@oquZ*a|Z zyp$adx+p#QVBV$FD7mI-FsGVzA<}DslVR=xQm5n$;}k4O z0>N(1%9j?cp4LhQkaJ}xnFiKMT!Ug7t*f#JIeTEJQe%yHP7b{kb;+;c)KW(%Y>e{8 z5k02HP>8k!j^tI+b5-Uwt3>Qm5?eL?y}~nacY)-09gQ$~s0>J;#EW(=MX2z4Vw=m; z5=V{N^rStwI+^%5AybH7IqJ7rLUd4#9Z~Ht^r_DJq*#CST3!4VI##)QcXw^6`6CoO zi-lIDN((NvyhP2rrg}KsRTO5iR%3@%Sz_6Wq=Dt{6pKVpB}O`vl86cPnH5WE{9Vv_ zULU_C-2PoD;hdSy*Z%$o*R(FQ0PEO4|6PL8&eDtmYNhb`vsAdJnNqD)1{4)Uo}pv! zHP7;ACLn}P_WTeZ?Kz&c5Gj4YMxPhs**3(r{MQ17((-9l_A7SzP*n}AH>RlUbmz7~^Ozy2+;$2%X^u8EY6L{j?NTFF;t zkIVB@aB4Ubu@YhmC&V9OvL01<%RmRmeuxqIMA8sJnj{>(3m{fzy@*5f8Q4K&9z230 z+A~WwNC*}H;<-cwjce{fWmd<(LE_Ck?nwluPaGSzRTcIn78~JiWXlDwih>;bz}^)7 zUN(#J8LBFB!E8t_GGooqrRRDREhB~J9B)Q^kwp#}Z19m&|OuL1Morq@?w0y6KH(e7Z&@9q4lkC@FSh*(OpDqfE$?p{Ko{6Vtaze{;hZ(&q zYRYX<2|muimS@#9r42-5uz^Qby_C;X$4-F(AT&x+m5Ee;$5V-lNM(tZG-`@AF&vQC z|L_09k9tT1`q#fA#5}%!G%?*M0`nTt;|t>Et_E1wa4I0oFX+DDLu<5u>TGXePT&RdY|bb` z^ilTx`C35w1ph_RFh%PTK>crpq3hSm++pIVLrD6Uz^5R4E`S)Km*^RkpeF^n;dgKP z!5<8rIUL!QfX?0&`mlSpw$5$tG zz0^-twLyMxIX&Rc^56WZyZz=17yanI(QTy&4%^hD1qc~^ek=8Z!v|~cSxc^Q=h4?6 zojx~1d*o}BhXrBes8*;4hsz!Jlv0>!vCTx1(;>;!(hGt z;UyByZ5Z;a*J;0ZtqS>uYV@dI>Y@^oRHHk*IYf9d?4GiF`014;L!&iYEHR0q?++dj zE&Dlx3J7gRA`8VJO2piI@nQhxhHA%nVRjD=PX&L2Af!q@(OK+@ML%)i#gGH&GAihD#b^Baej8h`fSY2GGE-Hr5>|=RCv^XH;Y4V6v z1fc}})Z>LoLJ1YH;ENbl%(VLaG4AqmgX0AG4^%9h?-duHqB=zYg9(uKmoHu&&Hll~ z*dvEQhiD~bkI;)Q%!pUK!7Xii1U1Jvg5@NFbuT?{V8u9zV&Oc)wL&iGnNK(p5rC7A zfHGyyE1ZtvgcIsS_yUlM(0r7H{pZtG_xTD;>B%uRJh4^g#I$Yub<5D>(R~=+qv*W= z3hAC@CMMtIv`;@)2tQv`po0a!k9d#ta>nu0oVCvm+qYBg&A~zMSrngXfwIsNSg!+e z-EFiv3Dhl$uC`44)XCe&MdCwjzR6YLB)qb!U;$JiWYTA)-BHgzQJf{>nIYxAYZ4D; zCAB|dy>3)b8_%#pN-k22GOv8G0n5G6@ZtGl5*TB!9q2?uZta1r{MJ41V$j+^wFLD?DiK>Ln-A46c1%HoT^p{lNT>LQVTGpQ+K_tM>!D`|<5;B#KC$k2o z6@ylZIZ|p7cKAScPs3Z7;u7aPU)vM&sXb(3pRPOn;)+;@7h9oRfOi86l766V8Wi~oRIh*=k{ZjpM4KpHL+|N$B`1gA+ zX6*b*$fCUs{t)iOS)(b<8+a|X)@VQ_K#+%7BUI4yc8GqP&^mM9f{IEAwaBo^#jC?x z!NC%nMf;n8JL>&bE)p4Xd}8aBwrQ&-&EkPPYHYAwaJZc~6hmpoTWey_(jL*| z_pU!Rn(`*dpQ6Yy6fb4+hmonL4KiJiwB>Q-(NlNv>f%(5P84xWc~5n5y7reKA5042 zG12z5h{&mWg5bKR(GN4r_8|xe_@NpsDQ=^A!t+$rL~UD=uY4(fh>ptB(+e{TGxG~` zv$Hca>|%3Yc5Oh39h(3UT~27GK?QywBAAU13<`cZ||9_uyye0M{8azawjZhlkw;;ljF8aPY;*=ihAP&pi` zbY@4MTO2P7@u1b=h`s(+^lRm01kHE1*Ifg^Gt;kX?%=iG*@azU^;}Um1l7R@1!vlt z;%~VM1$f`pX|BH7i#@?|qv-l4J4SxNZM$Yx+uf!zPub|_j6SRxXgii-cWg9^S0@jLkG{htxs4a}K%((eXqq@W7yA0+ zwXsb!Q_>U<2Z)K6xx_BZ!XnmZAH}!H}_osOD;P60(cK(uLxDD&cVCWC`@v82pTBK#Zpp^d5I31Ngqp%d7q;% zbBF=(V4Z=V$_~Jxloq$AbT|RPu}Y)fE&J)xoTJW=Kgd@TLhC*k(DR-o!P6rYD?!XyE)(oKXX_8jUYe>RxY<>MZgGajw~+ z`_xZP!s`_U%ymAHC%d`3Z_onI6eM+~sRAOhL9ftN#J&jxQVIu1j|51%S|_^;zf

DGPeZ=?DrBd@FLK=0(|3cOw_fv1KvX z873jCng5jfvdYZzt_FWDk^?+0=Uwe_KwlwHqxJjLhQr-0G9(q>g}c8<%J&8O*%QCN z@NaOPVRFZ+OPrUFJ#plB9YoLS3zRdP)%UUoo(NF8eLH(FtpJOD&mYw1dp6dQGArag zA^e(F8sJwqdq=H{C+2--%K~f_c~chbqw^a6-0w(^PWIE8@XWk)l*?PIf@xyy|4?~I zN2{)qj$55{+_ImO4ivHG#|M*s-tDDh_6u?ywIO2}Mp&0j6*ffKQcKbTqD9VGQc*nYcOnq8kY-FDm_Rpeas>LOBhW9y zPbbiMWRD26qdpmkKu239M1LjyVqs586q5rZ`Nk zWLb?p{)-NNxY`fX%;w0bs$~9)8wJrx@_Y{FSSdE@XwPi>7UZA%9#loWt+CRhcxzum zDy*bh3QtunOrP(0z|k-QOE1@ZUubsfL?f4vMTKkA&p($##_s5OnvCusE7NmR(jCSd zqHL-8M!ZLWbWmz1tSXxbr#{etA8M}7oBLgN%&56Kr{*fZkb|1+_NN=}{ZQiGrj|Sh zqv>W+et1-XrrVQLuD|Th$C~W??M%GB;Fy+d&R&_xctY5}?uFy^B-&BS*MdBX?OK7drDi&Y$Y7PGJK@;?Y-?CJZ zns>#$IDu9W6F=IY(}Q5rL;DKBHcR!svQ}!r9bWls?+$-yT3U*n50lY!$9?PsNqbAe z!r%T|T9AaGety8-WRC>NX4wuTNLxP2Xu6CbsaIf{?iG8TD@B5swrubbh)JVro7|S9@=q{8$5yk8+5b5GPxahg_stvR{qNk)`IWS89N8n)*XVD{g)*avP>(#dMis2c#LZK@-v+nbb*d53DVFtEy79B`7?9Z*i45=6zsw5Rpv~eb0MOf_2q$gXnPMS3qB$+RG(v zgYEF9D`BIRX{Yq8c(fn2#(OS@cfjI#;DC-6BvBU#-l3O`*3~dql@<{Uy?iJ05nwh* zuZ*@bf;L*DQ%x@lFS^fBw?qXDm|xEK_Blm_pUelkMvxh~%sKGI=0BYip#{` z0EvM|;F|bf1$H!e>bOh(s_2O432`Kl=yf-|CWM9e9;C+D0F{pn$Kymy>hwAK(uH)> zlO`fdKKw+ z;!G1<9&3v!BYeYlRn>XDjGJ`)(dx-RehWiV$--*86i?NK#)BCRfEosZ(MK=zmeTnoi^BB@vfy5q5MJ5Ci`?I@b!=R( zY8$dyCUTsfJ3f-OHIcM=-hL?k<~jl`r`X2RD38}_^a0GD%&+|Y1%ncKh~27g6R5-^ zHpM1f_n6HsyQ>`x-;NCA>dTJasG*jqxm)>SUm7o{1fLA@Jb@*!)r7HUdzM{ zV7h4k3z#bW9@8s>C{Gnp5++&KIVfceQ@jm&67^@iMa3GOwp&1ozDc zGE)lk`+&7C>IOz3M}M?mAIB~poPf4oRMyHj?Sqr2BQZ?ZIQ??hEEva+Etw?ErpBRH zdxd>WJd1^FU?^8%pZkt65G{@*3Pifd1Uh>vZ@td8p&A5F^EMQX24QdxDnm$YOxYfS zUSpF>T5zFvu574A#ENRr%NgmH3)v%xW(_iB&CWEbC#1BQxcCUIAx=s%7(FiVB5~=_ zecO|(v~PM_?TK|fN{Irr$&8TajJAy<=kBJb04?xYc_rYjL8(TmW!R>RFWDzO@p9X1 zF%I8huNG;Yw#_5wZfl?R=$Nz1KdkD0XDAb`hc^4CKaaB|&=?ji_>)k^yb|yIV|;n< zVevMOLfrF}c;55a^2-?U#jN3vI;9tGW<`gGNHiR?TsUn^oni*;J=XCXn_D}CwuyDF z`HiW4Eywe0*aWPR|}5Br{dsaC$`^_Xm<3*+D{@e zHNhnPeI9?ScF@!be~5Kd+N0$xOf#`{J{4k1?j{r4NxfvPo$yMmW4grla5 z$5R*i?QkA;+u;zyx6Pe^wL)be#@)ioJU6GTCb$?ecBgo@Z+j$X(^ydc`A1gDpQiO;fr>;BI4lmJPQ4XubggPQY z2KyjB!g+-5hh6+aM}-(8r%MoX-f9k&gN?&3jbSo6xgfke>%DmuOppRlH_lbVe)ydf zJGq^Wz-EI0Hv-bWE&a8F5_N9)V(t+GpdeQP+?XK2#er5*GV{%$UUcU4XoAtQg*Kd?Om2bj;4EMOw{ z7*EmT}3tJ zw-t8Lp2B8ba-fU8@zZg#zjPD$s_&km8ujLH_KJPpT<*fAJK{m=cirl;j5YrFk2MR!`DgBi0wiIcQv0Bei4Qq6z zfsOd-P3+QOD$b+d*?3_a3S^cPQdedOa7zp!wWBgru#wD zs4vpbfAr_~?C9)Sm!V;a^A`huMS>lAoO~~}Jd!2w<{UC(_~_&cW{HIl4s#RIGMrv2 z)K$raK+NzpTCgOx^sD20FiUJ1+Yg@;>yTNAEt`_px{-NlbB&99G)y7+1MPtyu)>*> zs&&vL7H(TF(f*s6ggudCcPWB8AK zc@3vGiTsTsKa}^ZMt6MO(md`pN9Av#WO}`WBSTKYY6`$}jw~E}!Mg zwk<3i7+(SEw3B3nD#**A$*K(xDfLmiEYLLgY|IQ=t1`5wQFoAtX+g|CjT1gu0uZ zC)Njb;n-Qo&mVHEQTBWavqwJ`SN7}QD&`PtPlzs2%<8wZ4q>OI?AW2mvr68p zQ7&RuhZ=*c2i&fZ)VxhSr#}6BtmAJgMW5IPM(pVsj4%16K6yFTaj(^IN?E+QdETbl z{l3)OV!;abr^;`>M|oB&+6j|4Yl16Y5z58KIxN-zN{NRg4mINAt?+ZJ`rmzR(Rk1 zh15ZMlw>0AG(fANFqpxCrc&4a@KZrsZl(TKyhbz-pTcHda&XH%JPNH(L=lNST(9F$vPobRegVbmrE zPwri#Mb|~_d^1wt5tcfJmT4|6OVN6MD&mx?XjF{6eNs)rHtV9bv2VvqGbvn3%E$%B zC?^QX$`n5IphXGVnrYwu;BRZ~3#!Zfc*f^ZevH>Tz3#)===(0(uGYHX^4MoMxSG|1 ziI3TClwRgk){;_vTpDLFIXkD99hDwW01LpSm8N8=k5=w#IWL_J=MvXWSQ`t@L-E%p z&%ld6i!)G@V`@P&Yi9OyN08St8nK$9rzXErn|Ob6@AHN`IPhqRe%wq)u}O)#H^B_} zL{oos)YQ-TEMxH_pCE!tN5ZPpLsdg}VQbx8h*cE+@a5YE9f>YKTyHp#m8YUiy>5Zp zxmSW-t*vQWQB)h8kymSos7b8lh)b=eTxVwiQ7rbzPG!^dm(`P*V+`3n*jUO|15e-x z;-2r*OZjEHrX(YJyf*!39t>S)WND6A4aN$;@+D1~H#fy1%>F>C?7~4sYJ14875qn4 zu8p<7Y|2(*>ks4NxHK?yi-8b1NEr;(tGYTnkIQ3dFc=yv47L8nVQ74Wp}_?-Jc8G7 zk4dLZ2!yhLI@cFU{T>(`QsgYc69wTftE9$7Mvo5zSUv%c6%h2?4pMGu%OIsw06U~u zs4tC_G5ZaO6bVY5)nFy3+*o9^BVYg9knxX^r!F_2&K94|duyFOOe}E~Ay2Z=PM%bS-_nU)eFY}Sg3k} z`@FZ7{^a9ZGoJ_*Q{|YcFD{nXx3vkJEcREW*84n%rayit{qfD#zn_}iyEgIS8+N~$EQwMeL0hM=Fr~bfuj^{q-WwrgL9@0+zC%o(80KtHc(i$BDjjgZDy8@Q7WO)9 zUc_F$`U1tOid21x04WWh9Fxsk`m(Y%(7tsUR}fFuR_FXXc=|50>9xD?)Z{3joZS1Y zB)8mI13<`tm)gxNpK)*|o`9^t8fmV8xW=?Jzbf@LwOH%*ZJt^(|GHl7x>1F_C|sx{ z$mm@oxX~wGFleoYPJ`lEvwei*v@d75t_>m?tjQ=_VaE$DF7iDw504>Mfh>bfmn8a; zEc^yJh>K`TRSuMl!aHttVJU2+pWH36RFqbT$I?OJ$Tjly7Wj?g+x<@BUU=p`x{hq= z6@}J9KraZtGtt4@(6cz6kj^#8^k#bW#*R9YVG4;n}KeQEvaw{MXdBG&*64`#xZ8){6KQ=&dQeuV)y zVSVh%De8NUSy>w##cA$2KCyCq|4b!}d^!)LRr?&R=^>#~8f^JV}QL*pB)Hk~L| zBN82)n6;jmIEBZgPNDbXL~6pR;jEl8JA`e@tk=$bnPO+1Bc`GSQBcVDLFJBEWz(pP z=Q&$*WMnONNA8<+P#QDO}WJ8U=-|g1%XOljw4@Q6D z(w}LWqO=Kp~wCbBEfe9J6nLZPJ~|AKo5z}2DOGzyO6;wT8S*NW{G zYXV9{VGg^!!uwU?ar469dB^+FFoFxN)grLseTDEPoEgE4Co)j{{+etkIB}7D`M)~L zp!fxstwRw>;HN{O+P5NsC;Y4*lY7)u3(W;qxhxbg@% z0pqwSLRmC)6a_}T&z}MA^t144Hhr8OBgpY@V)MT*+z+s3+K?=OGIn?{t6(Fmec5pi z+zG2^O~xr?Kd8rNRmR7#sd~0We9_@Lk7G^LEUZafMjA_P&wqHDQo{`j1>lxIpGk z{--q+V=ONP7NHnRWF@7Qr z#Z!^nd-yO@2LC~IS*z<0-^ipW;!A@>i^LK)jWTf8*a_Y0QvyP|FZl{{ zZ`}zjuCst*9}){n3kWy|kL6QD+Xj}e|3WF8BYE|)Wg}WQF<@{l&lvX0Yu&_v!QY76 z%L$TuZ$p1i*n^wR@7LmqW`*#z6|VV(!K7zOrU4!cTTZlTjv7CTTrJi^aWH#4F<3}) z{fEPuJJj?Cb$L!IP*3>~E8W4vtZVQtM>C-f5)_=$df<1B8S=mIlhO;7IZ#?3*uzztpONg3+&D9oC{5RBgPzTMRNpvPHu6%X4Z;`pci_xcM3_Br z;)!w2bcWX~aea|eX$LT)K^hGaYNSVStg+f$dTmyET~<2GO0SR75K7<5!_{|c+d5sn zpm90tkakf+GA(LkG~j3?E6 z2q~kepVIOn^i%o)m$YJgev`{BmbelO^q z6%PU51%?A=$u+n~gG|6;xrr*!EWk}P26%2Z7Kx~hDIEb9Yu^BR(A4~mUPP*VwcbRk{9boMa~L};S94?%Iy8aH@;Api zcD1yc{*742aCbv~>_8qjS$3dhq!1_l|FIpZwkh?#-vF*cU_>$-zW$Cr6HmYxjbZ{5 z;U;l?HYdmpGwuGE&Qw<2fRH5lgMMv}dVbyBo(+ zzi>B0Bwii2ag(~qm(cUD%IR6AzfrwCcUsx)+C4Sa!5+1_%ntLq!E|4f8%&q%!n{}O zn`P6e3C=&rSJLuD-<0#Crl?K&z}jSBwQrYh(;$Nu?a;zHbM%G(DAw_YyKyzW=x(g0 zjwiWEt>QatO;($Fmg-6B63LVj7e)z9agQ48M%E*pl||lj%{Pw7i^DW1Je4^qY4S2F zKjZSHY{Gx$!O)cLtTRBdV{h)qHQQ{x*!%w>NL@XtHDD<`@dRAhY90>|5A7DY`i$on z&%TFA=Xl!Y-NUI8c^)9z1UjLvcic*(H8Ae7kj#m`fRh?v@<~%JV$fm2mX?z=T->(h z4BKp~iqE1@ure20W^x^%wa{%FPi=ltk2P$s(T8-_Wbv<;Y6iUQ8`bu_Lav^*`tvYV zy>j8PgL-}$&i*nRF!U1OaX8TDk*oz9?MJQV=my6}&ktHor(YD6etl3kLU~ZS{A?8*tkARBnrkk6yX*WwV7zsq{F)w<<;JKW;UcC3+j;U+`iBQ{zskZNZ zTE!TSu?P4ljDI&Dt`sA?lNtN+rOmllgGvXxJ>3@=**YB+7lymv!5Lb3heqOgkBZ`i zr3+{MLOcXHVCoXVE1xf%cJq6^1mOLw5|w^#ccrp5VCRP3Y56p#(JW#DizleZ=&>lP z5MsC`&eUz7ZiolfLubbmo@>;`@EH`M-j%8eRtlW~PGd-oFVP_4BYwf&Kt;d3u?Ow&XTqC|KC5{l9MDiMIK=*xo3L-?m|!Scg!p zPwQgK3R*Xw7wdS12Rbp{rn+gXC~lY?H6zyXdv`OWbtASx?8BR(tsB1?>(H!**s`kp ziQkEJ+)7#nR)DmY8L?%BJ3e&Vp!Ua_t#98T45KR=$s(BB9xYixmUkYsEPoN6QA|}8 z0v(b@Lxac>wCeMnsM&xh^(~J%DDa`YA!y(Gw3x1dqqMd+pi<|0@)&s2^$h=|oB2pv zEzLoLm}Hu)DL}4b zg>KgQo61n@5)6})Z4_iQc|*>o9~3fa;l_a@Q_D>kB}k6oViUJ^KMPWfOa*J~HMMnG zgfR+fiekKVdQAF@8wavf0XNxCBAVDV^%=mol2t1sb=qOkA^*I?Qx ztxaobx{o6V#b2%W^8^msDIIb09m-X1A#1YmWOR%IVhdDeQ26i{72T#5w;2l)1r8yD zpD1vQ8t(+eO%&L`NBXHrgQ6w{g&*JTCI_g+!ie>&`nDAOXNoiXwVQx+@b%ng!Wk6q zXYlCtfmyFz2Nh8<6h#;TIPpa4kCMB#4co^$F2vtSV^0ib`^hEqw^=FIrSRk5>rx!* z0*_Ql=w=I(%--L~A%Z`F9d*)m=P6}hi7mTmu+9yf6kB!)2MEq7o5(p3gE`2!>@aDm zMu!GuN(qh*+?6V7lf}ch=v?Gja4dz@26#o9n4_t6%%YQ-eDgAQ5Z_@G)hw<26%s8< zOd>H;iHRg;5gaR`=y+f;56LuyUZ^LKul>(TfRIpEL#9GIMNJ%+ErO|E z*~@=RbsabN(zK)L(A zC3r-+Sy``*a^dxH3~4t<51bXx@n6-&q5s+_{}nmaAC${sG#8GA{i8%YO4M1xM5JxQ zs912Tsodofj*56N9pz-o!1sZ?nVjXj+ZAZZQL!t}(l@9T@A>j8$?_4;AqFPlX z>P$uJr?iUKPkxiHLTyfItI6=N1s2cepq^FT!mdpM3=>De3m+n>x$z9JyTSQWts1ME z_m*qHlCoA6k3VHsY~Nzt6WxggCu8nn9k!et0Tn1waBQsJSbUav>+bHx1(I~`5pP^@ z>|yy|tGan4)OB8^$U!tp?Tt-P{DSdBIN;4E`*46BH;E0VS?L^x zOYz3e^--cBN;Fym;O``X5r(6O>8pet!WNHXKiOSZ!T0;hx|9V?1yjq8{*dJ!Vnl4W znEENt)MW3+)F)iTmqGrT{UWCJ0}95{eBfEyOiW2Qs&9kTmNQj6EEkswG+=cC#BNq; z{`1FruKw+ISzJ9^Ts;h+lZAi3+i9*R)r6pM=gmSiW7R{;ctE)x*JfC`F$$}Z*sKU~gy-Qb~B5{$2hPZ{N9hx&NY|@vQg5-P?02m6@?9YSQhRTFyDP`yfW)8Z; z8Sn>mi|gI3D-K+%uJaxhC;B;Y=z(zYj%p=bu1%-V5kcXRn;eh@;T(I11yAj+9wywR zY9uKtTR)|{Ej2(L9=WNXC{Qpc;l$^0_82ko3C+AY{HNN8y7(><|Z|mKPn+RDog~`Q={h&wvhwQScmO`>!142?!`Vz+wyG^7TP`83snnS zk3<4>#Fh1fQa_c6l(=^2JWTg}tYeX-1?O3@jw{`bgYy!18&(<%$luxD2kq}K z(?H%8r7~t~5R_UmE^YrpxZU7$_WI_Q6L1QYUPI6^J-AG^U zm<#*{a2IWpB})y;Q|IP7->}39lk}Y)H~P8GR;$^GS>*6`Vw&({E%T;Ava6riFf9Su z>=_g`{>Yh-Ze@dmSL=#?Z^DGk_9i4MR92)j<{)k8xy9tc!K63eiQc4R?hX{Mp~B0) zFVqVU>aE_adN@Dhe0LmR*p#1zfqFHh%OKK(??pc|JNea2^Zc9v(@nl@rY(HiqI5S! z=%@CpVftk^PBuTgaX<6^Sbfi}Vv<&6m(Y{$w6yu>nQ?QRgUEuwd%EfJ*-FD0v!~Qt zw3c@ch)|_xOo3?wo^Fom4D`?g_Gz?O)vY$l02>~57(DuIq&UN)8U73?PAcNi$wjgG zKP5ngNnHyT6hdF4D<;*hfH+8OEQZ}nFOr2T|Cnaj6-wqZ>}=1lE_kc>!g-!&e>)^i zF~36u4VCi(#r}GiV_Ty#DBfUg!@XfUE>&-w`x`QO&b3+k8i9?RoC0#`C(0>y9;NL_ z5j_tIf6?VQx6}$`5Jgw?xV3ZMqiTMde_hey($(gRIe_VZ8FeH0^#0DQ_cozRFuTtq zM*h_z$H=8Jrr1b}OZb6#gxtrtG?(NT2I=UsMn5?wIXDYtpT|;@pF7o8>W~x^zZj1*V#3}zy$Yit z1g6)B0CPSbdVwtxeytZl;j}6(V5SdWpO=NQb%Hu5T(tdQUV@cm;l)2O9<+c2zDS6Ot1w&yht9g9FV>=u$PJTX1GDSgslzEW4HUJ|oQr$$jij3L@Fc{Z-!+#xr8TX1Z(y$J~nP!sEYGf_&+$NPC%SLGB|M z2GoX;4=zjsGsN;ZVwk1G(Bg`-$b4j(%<$`^SQpR6)!U=j;SW4!vZz!1T(ig*H2Q)`HE_=p%;>Y{3{_o(#ySox z%FdWzD(V<|aI9?GCD1$#MgH+7${pfN{X&7*G8lp42&tMkQe;IhNKY>-ReO?4MZ?N!8T zOP+)l(a^QEoFzr9Ka9l_Ycwf}Zt)9aU+U?^O&mPgbvjLB8&`yatjgcv_UhnGM zA-qN-w*cdfy)gsoRfkU!9*XS%ral_`jO_=R&3@qp0Zc{^6SYhK-suCV93DK>*b$`i-mD!Mc@R^ovw0b?VA7Xy@Y(ZG=7T_M`Tgsu(ut5 zzz8fEfseK)lOIu3qDWXwaMXH<=jdx4h1KO@~~;G z+$GLOGy7lWDq3T%!4G(E4t$Nqke17`ZM&p1lSyUYsrQt-)UGxaJU!FnZKkwa$wA?k zN!mASSXpi0Hkzr0OW7~g$0T8Bu{MpX5}#JYC%ic0%om} zZW}Z;m_7oBsimwYQ9Xj`fVN=yqVk&FZpl++ZQ`+b;>B8azW5s|v^D|Fh1KwC^Ta6H z)(u&iJ&%NIXSujV$_&B7n&vLd|rK!`n(a&zN>w%+q;k-E?N2(MI) z#MwQy$>)+6Xi<3(mY`L~W>quEj#i)ld&6Y@eiMDDYNwB#i--JcY$+Y8I`jwTYF~m+ zc|hhkp~d>zdMLZ{-uF-@h_e^EHx^OqBCQ|azJ8tSi5MYixe<~+v|lqJ45mMp)Kq(a zu#U-jYFSWtk8Mb;cjeJLH=m8tx>O0?fJ)a-Y1N>g`iK2iW~2jt;D`PgNJ`sWZp<(^ zmNYXTVYph#FN5NW@Z}v;ezoi2REe`Hv1giVye4&>j4N<-85HD;*tlQo!z(MG_>M;L zjC>otuTTR9*e^{eq22~#JEc&_)(GD)THqU28jdM+KmvPiFB?EwRX%{Z#zvD8yy66L z1XDTJG5q@h0C)zzO|Jg&@o8hLt;eSwM>qxK_(oO+CDLV;d)zz5@VGbbph2a|_JGd@ z{FzA%IHm2*Jd&+aH*0*hs&KY%a9j;GOII&>Z}4+(=dh26!%j4k9*uZL!>4%hRv0$O zt`D2Q)`G7{U|aRv2SUTu`-2_ryo|v1p`ST6ZEw{}x7BGp2XKsRj($cpaN(&26MCu{ z2U;b+SA;tY;%T|`G=BRp!TZsU|6O>` z{?h*~yxSE2ci~;O-~TPV(Ro{lM6O8xhy1Y30PqIY(SAdJlmk2Pena@3-?9UP;Ai!i zh9ehYL9N3kUZfZs5Sapq`FT=8lNeeSeq5t5CzEw=kkObnv(3EQSo`&sQ&tsyPsgih z?{LU;S$Ta!?_t4#0*Qhv)w#UVcAe)AaZ<+sIKtbfIT&z#ZDN%9w2Hl?-dmpCOB9VU=G5y8EXc8>!LxgJ08U>GVY zWQa@KA8Q$m!%j^AL*)HLs}nHaMR7QdHWLluB+jGJ5L? z#B~C~OaS}$TRl>Pg>mXJO2>mpgF%LH&$(GarwRf=J=dt&-dqQTBdi4Z(8b$W33A%s zn$zc_)YB;D@b}*_7mUv$fV`h=4)iEVZpxe zLfe4$`+bLh&~~0WD*6LPnqtcaX)27iNe&OWEt?(@Rv>@2Lt7MnaC<}&ML#+Oi9^2V zk)fS^<*d1<%0dI$x@MxvW{waWfGTyu2#ghtwM238XhLf=mo>AdyaBdj0)*or(IN+k zXs)WKhyy|txvBB9P^83D#QA;E)YfPh&}eUf%(e;rfQpoe;WL9=*d*hWmxS9iIHbT5 zo>gI53tBWQgdGI}qWYsD@+cJ87b)RKWpKoM(hg_EqyDz}M~^vvXc9j(iXR#cfyNKb zZ1@rZC45Gt@Sr>9>+9`?zdqAxbC|nUqDH4%R9tFQkB*#*M&MOn8(ZiyV==>YVI>+t zMvLj(Es=ypcyoX_hVpf;tE_%~m z>T~q|w$kWv;n*~qA-KOUA3lGMW6x|F11$KA$n-CJV9(v0Mew7$vI%ZyhG!tD1;0=S zH2Phv!J$^aK%$cHZKPMg_7#-aG6bcn{Ui9t?Xw>#;YbfehS@VUIK=%>*YJrw!J$ry zb_mSiFK91oko4Pl>)T8z!i7}eRUxVpT?2nbP~y7RcUiK zb6w;^%#L#^^$crTApR^;<4d$?r*zLj;piHNd6a;6MM1i6ixV}!?Gh*|m!jwrx1dVl zraADsMu&D42*LPAE?`_PG0ypyR#VvfLRNg$WX!A-05mvLB@^#LXpYm34qod~ep7tH z=2&nL;MXR%sZAcsj9@2`Q?Zppr*cja$8JoyeJcC+KN9PBAJEtv{-nE(!z;s!KI3oc zh>aiP06(T^lhexaE72qM1irqi0>}<~J;#$ge$JqTfd!3z#k95`u zoHQ^$Z^r4#(TDS$f`8VoVB%ApeZ4Qd{*+cfm}IxDDq?>S7Ba2Z5^lbP@3#1D8#Qo- zG=y{C5scpN1}Uz%o?nNLp5Ow(hAe=qXvK zvJx^2B-T*0@K9&Zqo}W6*TM4!|GdCzYG-lZD^99crZU5q>};9|dQ0YB#!FW`UW1p*paHSLQR#lonuxk)(=D|i{*JuJQlWr{t#yydo^i6%!YXbd*1iDM#2D1?8ixKFx zUZ9(_<(9JtUhjoV-pmqckl+eMpg(BH73en07?}$PcS;5!TcF?BKN9Hsel>tVU&GN9 z8K27U5t1}h>$#d6fb?@~5X23%Lq7@SAjoQIgz8Q`^T&hh-8y^Y@`YLH^-&r{tg=+L z%8_7Zmk~a<3+%1=gx+t6E?M@kI$964$np0BR-Rw)gYjFcdpLKsJ$L-Q#?qd@*ZLbs z>DvyoJN_O#C_J16*D~e*n!ndL{$AeLkH5e2Y!-hnHhBC1;ivPrp(4%S6_hUn2Ch0O zBQj*-Htg4%>yE`3MB?&zqQvvK#v>=ZFyrjx_<(ofXSJm^82ZPKkBrCvs4*)6T@y61542X_ZeZk8 zGR&URD{Qf~_|h4z)o(;R9u(IK9yA8{aHaO#7Z#kBVRZ$07F&LAcY@+ke3Cj-u1|u# zova(mW$1npr$4R;3Z|=%US{BUgPNMnxTK|{^%Dac!=x9Ax$o^A`PN%5_r1!|Po9o3 zFLgOxpIb&4D}jlpV80LNd!tAQotk$%APc>eA7H^#q?%On0R z8Wdh}*ns@ol-AGUC5szQbNrk4CkDukNapHEKVP;ci+@{{Khn<)Y5nXSFe?oo7)SU% zrwG#y*gbsc9k6V@JPkVHc(q(SH95I-s@QMB6EnV9lX%ItBTv+p;GGQ{Qk~qVD6if)6)=DhZTjPr#bVj2 za>ba4ff7q223n&QL*%t~UF61TVTO=<{lrXZ#(;qq>sfR}1@H8|e#)mZ^vltXl&!MT z8n#avte1d+9?NE+4F6bvd7?;{6TgzmA|gfnr1=u1@wdb}rpJwM(h)w`snsfnX~O1H z9k-N2$V#<=c|0pb^%C7GEdWW+kOHp@t!Yt=V5_mI^G1SU&3+%ae|n2Vvn^-6 z5RlJSU#h)9?>Ha#If)ILNbz|p; zzRB=V6x9^)3eB_M|No=zJK&?L(zg>}B%J{9p9p4CsI}ecQ{s>$+?=;0ejYwuci&&Mb4NR`d!Hs>kRu(bgXW;*@sFB=sOBFfP33T& z*b@jo+31L*ez4vBO@H0q{-$Y4Yt?SvBQ$LQ;KKnAYr($URyA93+UszEImV%L&N*BC z@t~+*6Sx`Bn!EJ`t2>UXxByE^%D06L0sXC$x0HMf06O5%t0%@5-z(bKy^A75>Ff`>_d7#7} zaxnxV07Evg`?|q)DGs#Wdcwfk4NU{PY#5yVw%R8QmOFP9>-jRGv;%7u)?#$=aj145 zAxdS}>Zxt^L74v_%f1mO=wd_Oz}m*v>d-U30Xg1^!}isU)pnp)N4@T2zxQ3Qj5>Hx zBxi55H5NSSCVE++da)UH@a#SG=1R>ES^IGS@_1LLE1jmc;5DEW{t*=vZ2s~4Z1t6z zY1wsZO~@Q3L4`N+6DFpHpYARr#(0dn+dz7&`-cL(iF{}ISDsgZRKgVRD5OTxkvT{z3e+r3L*}?eM*4xw zaw0RI$OK09G-sJXrYQ4bA~Pb$>_8yer?ld^6{P}Ax{6$#MULZ^htL!rfXRCs$kxGj zr=tl-u_BN-o-P6>?)RcpWWw%osRfZKRE9B8$i$=vh-Zd#JR=2~JeRx`h@oMnR(ISp zI}l>98Dg-$X;7E7t8?s70ZC8wF-t!5v4kLEd3*uNalY9dN-TnCMpA#lzZs2F ztk**8kD!Z>|D2J}6CQ24P7U;|d?3p?;RW;a5d5T?&z>6Sh_6(SIf$R;&Ua!cIq|p| zKBmq$G*Y?MrrP%kvG4aW4fkS0O7ED<9?KC+co2oL2NK}vf@&mi4fw?$LT##R{>XPq zaLo&eQb@xBjY9VY3E-dxPch4``+_gTIv;&6W@&kjcMWiYMWfdr$4xG{mG`4%9t|Q} zce%q1_n(hZ8l;Eh57wW{O=xHj9V$+I4+9#9qVCfCSm*agQqco~<$!aOwYplBu+S$8E)ipz#Bt;7ST(c`?aUT8staBQRb>9qdumis1ZLNh(37 zu;~$xp{y+g^@BMhp@-1tVyXnC!;F^GD#NvAR+Q>UUIlHPzkZ~;Udo-15DpUDiMkJK zRlJyE#7gr}`X4`8yg>$482mifpD0HqMd1}=`|&v>8cXeI^2A@JHi&}9;2Ox;`GJ{S z=3R6fKVW@;M@IUeUHhZE#yrGIK}c{pzPI*nh2MCFZpV*giEs}ia@4jR7;_61GaFz| zTySRmkLoG7LLCD=NkZ|DdQ~JCdbNSSU1H$?g3Bp9kL?QKISAi?a-aN!CX4Z|&5ZB< zsrdesK-vj>7rtl444{+%0caDqNUwdi)Dey7fa1CtHKcX~Xs;{QXiwSYSm#OSl`!+Vpc{;PS& zvMS;i`cOU5pSYhS3aa& zFgQVB&{ekSc$CfNwQHd;M!-%&r$JyMbc zQ#kRE<0qv-7na|X72ih~tdN8RDy{MVR2?f$zzL^*B$BRlA3max#D`~@hb*=veuax9 zD$m~j#DkMavPun-_BMIqpJ*h7wKjV^nnY4ql%})r0Uwewum`y5fO4F*ZGf8(lei%q z0D;Cz95~@Zp>iJ_bYaC{Ok$A;YXAzMB{4NbCy8|Cya~U|@3AEDo)>@HEe}kIld^G~i{QCus(xLa#51{2E$Iwnc1XiWmCwtC0%Z2PE`i|8b`MlRTpZRxMOlsCLpUEWIpp()q3G{KCOBUUq|P~V|0swWV}a> zx*{8rVJ9U+q5A&{{tyqN+=SV1F?s3u`)8rX-*F2wGU4w{f1(F}!v`4rJz(pBaB&UFpML@TBeF??vQo9)B|>wFUUA zP#H7oKS@f*-w$OwfxqeR7^r#mpZhQcf0vqsO!zz5pXkBg*ZmFtx|lrw2LA4tn1;V+ zX6_vRR{Yii{K-1?X8g%es{MVf5b&wNt!1)5P6L!xk5}psmIzLCaDT-w=>meZ6mO@7Hlg9 z;;mFh4#dxcH8pyg*7mzUvj#z%jHY3M#M(}{h+JV{6^gyw<16b?H}a7p1#hWN7AM|T zc9swKb|2p9x3gQ8=-k9vN&GCIXZfi=F)wLn$DUwt_L9jHe@AC?l) z8n3hGge1bmP~|u!cli+}E05@Bxdp(sZlG-)y#?6%2W@MLJ^cglbR$~7BRt*NUE}HZ z*E8ek;LCk@I^+25;A!*l?cr&)q_zN0&!~)<@N}0XrQ_+S3tEJyRf{s=VDA2=Bm^D3Wlz zt>_BhaQD_XRTsmFWlAw|WP79g&=WYh+&okuy3kche8ci5dIBe1L~m2wbv1b;aN?Z2 z5eyDPJ*DW2`_=dleBmZo#4|9Yq-v$@kk}g-Ehi>G#m6eJw+icBTk#z*6M7s9(~6ab zkpxB~W-x(piIu|k;3}po)Q_8dm?XTVSa8ZYe>G-8O&V#3a*gui?V z084~hl^;R*=o5n?IC!k3<=c4^i`W$&j9|LLwgWZjg|k6dDt0cygbF59Q@QKy$ENjo z?2>0jFE4pO(JZHrulXvR5nYTWdGQ{E32C!4bU~a+>M-qQ9iDa{C$-5*;#?s~bV%fb zQDjua+00Ds{-kGGyVrkDvinPV4mJ#Psw+jPWquJ8s0^4U$>Kye0J{Td?9$_Lo0v7_ zJ`dT?r(-R|u_yw9825Oc#q)+%hUy=ePQJxU)cOP21G%&Ai+8!R4FU_^fd0Uf^W$w; zN`q+`pp8*&fGLbU6zYm*i%l#}kkMT@iKo+aEgAD4^1Dt-cC5)f)nz$it&calDzow*(Q z^nWLfK1=`dZ_{VP+bqpTpBj|*N7AQceL8&rwmJ6@nsk^Uruo>RpEW;8Ku%j`Z|8Rk zeYyAq_$y1*pD`Yt#h^Vv6M@>1$s+>O$ci2Kp-MGFT|t?{f;cfFDhjRa)k7sGFP?P5 zj?!B|9u;o}72;gD4qYyV8ZbRdY3~cov=;%(36@vaqtV!=Bavz7DQ>M7Ms##fTP znQ(ntZ|p!tVQL@PJE(1F5@+alN*$m#(AGFd&JMgIK2S4iVA8+PwIe)TlP=0Ma|*w_ z{PgvI^rhfcguKEW2med9|L3LN_A@9;Bw8dgSSS_<9d=&(#&0^ruaT7=EUtDzWWMw9 zj~kj2Qw{ymzI<~ zXgmPyT%6>V#=(65w1v%9Hu2_qHALo|{Uw=mTLtnzg66~A&7x?5jy+$M!*z-zG2$Lm* z3w!2#)|L%s&e{dx`A!HGB%U%*md|AQnETb|3$+3FnmbsD8m^jMAmkH&ub0;_2r)mO6d(@p{d zaGe$xP-Cfy|EwPU9NqUn=e`JO2;>fTh^ysGTz`l~S)1F2Y#W7z>bl_n$~HK@YZ6Bb zOr{T$dj&;-ix$DQe39}oyQwQ8;GBf&aLjOJRT018jNz)P!}zTY^L633 zK+TqsRr?aiC0Z4H{0iEg6@QDtkkoqm%&Xi7H)ScE@iFfA=>QEqoHj^BW6p*m^?Fej(-bnH?u_gCDxk61s$6O!Kf3X2-(4U#AIBbYx)B58bA ze;Gx=YrTz^GVb@5QGooWwK*w;d0KlB;OM2v7h)8AG?@dMumFtA8Ygr!Wwvd;%Z+|{5#u#5-EuZc*7W2X}qi*To>l_e7XFfJ0v89p3a@OQtwPpu9I3v&$=K1_c z-ndrP3+)>)L|X^EBFZDj>CXn?r*sb04e?bs-RbZ9?M(U>#C-}NND>#{lJtc>*5@rf zL?Z9xc}vbgxZurgjm3_Fz@!IA4Wi4~Pn-lUVvTXw2SI~lf`R@dcEk>J*`!(EJmFzM zxwVLt&&YxjVZr7Smjzu|FVruS~aV)tmy6@#_~}_=^$G#?ay~kX|ISAW-4$fk*rp+!12=bVL4!O zC%GjY3&a}OS?K#3e!8nv&El_V&$7XIKe5u8{Wa~kpQA~Bio86*Lj3VJw=?)sjbu<3 z?u7ZG`sqz7lq5SabToU;#V0^YIlqbj0v;%l1KH^d0FY(;hS-c=`Iql}=XxCP~G zF!*Q*T7g>(x)fMTfgv0@gHtg3d@ydW&I^E3jfiN0?AF%9pqjB*m#;tp+o|2K6c!Tx~5nQFP7AXmVBp zOIa#GaR2Mn%8)VOOJ3)jpnRDE84@69V!7v0+eWPDXIA%>>{KC_>EblPOgw&>}piLf}(D@>hfDHRun!qXTm>$V|UUr&EKIl$Bt8 z_qXMi`MKLb`Hi6bQY#y)h6N8Yi02-U!l{bV0EL(vl3N&xdVPLQ@`NN|eVY1wOi#3v1_A;xzL>=L+>5*juH-eIzx?%Ryom6S1zAA0okmt+(bS z7kcg{l`K3doSk@Gz9wF@JOy0Knqoy2{7?l{0-Vug0ab6XE7FS+c|XpJf}JS`3uoB@ z9ift=B@o@5YVcxc>AdneIL^!5l^ILn_odDAn~WC*+Fi;x8tw{i1^ zbMgbs0mWtquev{Ve-pdrTz0n^$>V3SDg*Q?R0Ro#?9O}i;zfWkD0zBmA?QA!D`buW<^cyKEe8;(*+TUg(9( z0%-@}Qi0LEz*lN;T&tGj6b6+30InOyLd(%U@PJtkKRFCVvC9$<%kxB>rI)dZDkSZk z$tGUpHN_%u!!6%=MSoHAKjqY~Wz?@ILc~k~teT|)+y+S0Z=RuRzVkb1pc-ZeC(hJ@ zhBl(V;0)z#>kK7l;0g@_2rh&uVK>6mTo!f|(n$SEwndbgMEB*0+-f;PxF0~tQAPze zM78fA8=|=Fqz1I+#_>VAMd~o$t*w(p3r+i+{6LRHz#}{i(0&$=LR0>S35ctApNkzj zO|ruV8>_4?G9s<8vhhhD7t8>+wv8G!5T}^T{Z@_vE*%&h)FbCKd-pvC#Pa%{!o9sK zs=5!1cIq+Ews76_u23)Pu-z7p^}t_^}8#W}H}^G|*N`+(XMBU)HwMLQvmFb^@CF*v|U zON%S8sjK3h3TeL@*t5UWA5;Am6bJwc6SJL<_m^ItB$-inqQSZABVc!^%=q~5I{Grm z79cVLodZ_ULnvb_O00@MLeSZPLHlzcP2&ztsBSabMGs)Z3V$Fsl(qOL6dHiAoRU)v z7Y_m44yZjbMUS#rvS{~QMy*z&>*J1w(B?*JwiRAqfdBh|6n3Y3v1hAx;WEhcMv`$N z#=uQkH5iF;}n zz5y}>#yqH>Z?xq3q>T3c4%X{GGZ6&F=wVZ<@l|9_G50*m{^;VBRcG+|^(TtNpw&D$ zKg*FL#PCusv**)y3)iiv?10U{twJ;ABDz~Lbx_wK?g2!~WOL5@06iI?dy>+A)(ZOL zoe_{6$dJYAFpS4OuJ>6qTGk7n@}<~(iKs7)-1!MQx4XVC<{+&(?;06_T>SclHTV10 zmfh<%94uOBE&tZ)zTT?c+J4kcQwMcI0OTa-z2$s&)B-TI{iq9>ZR(&ly^{2?)>^-Q zWZ6TYn6|*HhS}&c4};M5y-1}TQYn}JX~OYS+jO+-GnxiO8wY{j=&xJHxLNd?YVa}x-5io7 z&#+*#YjLDA9N|l5X!|S>MEgKa`1d?KE9^XX3u#Kv0v!YfF<2dBmt=E%CEMQ7HQ1d2 z>^)j|3|c5x!aJQhkkEK^5FQPTek_xZECZu+7(IE>^eTiB*`p&N@gUMZR` zUKjXbn%en=+u77k(CgeQN@J-MI-07*rH!T@VO`o^N9T<9{ zP$|(4V|GI^9cvecBU5{Iq_5XBA34T;mTXgMd!%n@iyHlm?-_a_zh-MVRQ~`_AaQt1 zT6_ao~{SQ*PS6g--$9QmfCZG2=wgttf^aXgtc&ffPvlu}vScEb-L}tnQ2X zPGMTuW4$UMTR!utBQUA3v1(6ZCAv_yNw1F=g9a3>3JztDw68G0zDM_RV`nV)kWR|LvB)fUYoAe z@$VwV4{(*{v^gKsG%(lUeVd*Z0Y3$7FZel#AmVg8Id)b?j)k2ge>EJ#OBlG3ZC?q4 z$Z)c2sr(ZBw)Zf}`57K&YQ^37h=t9%+FRlf_= z3&6;#t4QiFtIcIhd*Qfa7}FkLpZZ4snoS+Xw60wgw)!j`)fcC@v^n}@+rs0`9mcfj zU)vb&U%aVmABlS}9Qzh@U?B{%woCk#<^FO8@5#pb9~x1S&!qms^njxdZ=J~?!o;Q14t+#?v!B&dGsW@!XYlw$?)Y)TRWQM2)bfBZg2eU_!%KPH76DAz`Xcb5Ps*hB@nU<=L?B{U#Q|= z71a0Oy8IVdBkOoIVr7BF!s9&wPjE+oibklFENF&aUlLtvb^nNd6<4)9Lo~s+IskJi z@U7N|YG>jJ)_&$T)oebTjv``s>l3e8_U;{-JY^JLKpd<)a8%hfg40*9DgyWzICm4y zJ6VTge-;n6+Y4RFxDtEvad_brh_|Kfxq_Tco6Z!l{WuvlMM3UVg91+!j|cz_A8vW;*hH=)#ZO}JA6iiAE= z_F|%`qz7)jqMw16;ZQ9f*Ddryr<|ItHKQ&Hy|CJ{ugk98dU)mG=(I1}Se&?GP?a1D zl*2{9d|RL8V>%|2r@2D~mFxtANs~k!EaFxQ3kNC6rxbsue9gI7 zeJoZVL*#>4CHnZs@6**+;MUA;Ihz&&QO`^UQ@ow#xaLt!nO^b;uf|}f)dREuNct{T*aX3aPPuYG>K{=(X(rZJ__ZTju8^P=kzE$LBtSU=_) zePG=RYf&S=R<@S-1&9UhkHIp!t0KvDE252wFC_c*yGeFX@Px#Bbt@7t&B0gPH?BS& zrD88ZSq!n10vVizn4-}wK1sw&)4wuEvHCv9T3S;&p194N7BX976|M z8w8Q&Sl=k$3#!sgZ&4w@(W{rMCXw0c^;O#BB(`2-d&z-kEmueMn~sDb=R?Q z^y(JQ7g9f9FtR)Zj}%m@y;lSSBYhb|*K9i~RNtT3n&vXolqx3MMU$T5J%znsy!xFQ zp{*JVdGC%3E*U$wZ-lNhv*4SpY^W3lgzz7j1c$(>JYB_}!+Py~7S@B}{2z=Kl+uEV zpqtD_;nX9jw$0g90kk0TC4x6?%)#Uq20Buv9enl)HplSdj(t?|05ylioDk&T1V2>4 ziRTc6s*zVTlE4?}7kWbaOFq9iySLNrl(w+|^unk;Q3?7a6FYd_lez`5ykkyK#yiKd z%?U-YH^vdm?fuy@dvi{o3_RiHz)R#26g&UcU{@tN~f-_V zU{))xR)qPn;jEbpal02IB9F(IlsDMh(c_^TBc8F99hi1FCP~=>JMfQ2uA3sVe=SjS zIF@N!i9Bc3rTm6INX!oyb`m!dP#pB4(FF=x$RfN)H;Hg4B0VHHo-O1ZylxAV?Snt7 z*H1mI*0YL8K_AqBFVqL}35#G{FRXiLM3PvE+5CdPRM(6;g?|(*x?f@lPG$MrAzKeoxI@W@_sp7!xpNa zCJIPrPOhxr=nu2*b(cu;URG=`(j1_dL)0&z>BAAAud&pLxCbzj6|%cAE9b>1JSG~B z40uRq%#@V}t>W*h37Yu|Ym+2X040Qr=y79Mifv* zkQuSyN8Lqm%fOZg?zv3HfwoE~WcgUbCk=-|ex3H&IF^i8c~H-FYNq31}%ub0cFy-ga!iG_>d3Or>E= z(SYJ)riJC=FA~p^vgh(g{C&o0K+os#=?s4rn(Zijb2Xd#lGJZ9-swv|1_2Nlifry@p8mx&+vH(GT;8WBAla#s;PeSe^rY8a96)=Mcepm!imWDnE zH596wF3RX6D!fh~QVy4e>MP|LW${AXJwlaW2TmwZ#=u#4E)785=Xt3OGvfq0lLmc| z7D%KH4Wbn^5@=68+fztcMtjbpB7&M~Clz)6pc^Z~x}MjhB3Lw0%&)T3cCh+$N+j@n zKuxMda`|{HcpiAkWAvGZMwpr%*l49 zU#~PNC?Sz)afYbhp#1BWOO<(p+LOfM#~}_F!yWbD!&Ix68$XryT4O zV2!LV7Xm~S0lFj6OMo&_Nqzzp9o!NE;7xY2bgI!&h5%QaolZ_)ljbFWwza6T0nO!~ zPaZvl29rBpr>G>L5xiLOkEm>LYdg;E0&4p#GiGBSjN+JN2hRFblW42Hg)qm}+6p5F zb#+O!TNf82#fn6`Akj-ASerDA?A5g;B*L2{QPGrC65Sa#80lcr6p89r$GZv&^QNza z!sSW>LQuSu9a7Bs?M3LBN0WLcsbA~?*r+3yIqeq!!6&X&dg4i?O5i_Ti=*g0@Ubi|7yl&>cT^ zadB}Ln^J9X(SSF=sOIg89sIJ3!VAqa8QRECxEo57FCaHu&4O}?nx;B7RkhMRE&12> z1~_Xx$?9Ba48N3WDH`cfE#+(~=t5mb)gs4d$MV*PlxiuarZuXi)5n@j^KZ;RCZ%1R zu#ZgR%Utm(Rb*O(3|f4IOyxU4rdPr(ClksgnO2EomO>`yVne2vJjseoP{Zi7(mvG5 zk))2NsX+?8i`20K8OFbKruFLTRE{9QiN<;yz|T?y9)PBxG7=vpDyylovlW9B5dOvD z*Ao6vTiI#Jd%DTNP~DgGE9#r5@Z@bOJifU{sBRIH?7(HKG~?Rckb!ZGlE#8Z9iSM; zMP{&aM=*}0Y-5>X+#blF8FvmlP?5$sJOs7$3EcPrYH26d4rU$Da@L__vaa(a55jR! z3)GDryhCg@lebMwCaaTw>YL)f(gnrmGX06u44a@r0+6uG>aDeo2QXT|T zaVQZ%I!4JMUB}sGNM~(XCqueLEEO*ouuNytGE)>vQL80*W23BQikdjbHLEFVx3M#k7PBExsnLJyK}3I5k!B=KwCmAq-DPK<40)`+|m0K>5x)(2OqkYNRyn+t5~4Vr`Y_#fstSy@0(l zz0khIAKZ~vmApkI5UT$ZBqDye_=1`G=!Pj-T@{-Hg< zAbAsr8pmxt(93i)3|J9Zat_d!eZz%Qq8dMr`C@tJv{kMN#KO2HKKz(rW|H{R$-3s6 z?tK@_*#vfw&rFDOUU`!G$915I4JZ!?BqPqJL6e4IcC#yc;{R5a{2svaD?2da2^Ad8 z#Y(=w8-Mfsc*6VRspJn#0aTsfmWRa$C@&BHx2|lJ_&W+2mdt7gF7*Del0UFuvua}E zrDRZHxMlVaKws+l|K&@M`BkPP~A4oSxl;&BjXcRK{2Evu{awUksNOGS+g zi!j>Wz?Wj<0Wya9F%zzoV_$t96NHSWPIM}~B18zGtww5XCGSEpa9UPrA1)xokJ&5~ zY6fp}k{#brgkE7Nz%F2;3Y|q~t2h>1D;X}M?Q+pKI>WLTM!I8mi<`?Ze7rZRJmDM) zMk!ywbKNs(NNgA$Ak=W%y`GGgn^87`)qTpA0lV@Bb=ubgR7OVu5Hyv#RL8vWNC!Jm zutus-1CXmpEeF>E1Ms>Wz+IJ7!p3^bk@r3Ivn^s?ly)<#OJSS%Cb$A6=F|*T8fz6Q zV#p z%)w3rTPk!gQZA%0`gH(ae{{&Urucz+V9egp+OFYeYOf&eDqR`uv~*8>&hiq4D$t!E zfnNkCTeTvJ@d{la0)>Kx;G| zd&6^$QiTg}H`jUauGAr3m~2OgyRj-nFiIU|@uOsXkayBM93KF=-;eM(AK2z*&hgu8 zZwZK84F~+eb>||l(4kxn41U?m9T*gnJQXr9u!F(9mCLW_qHnoOV}c5o;T?Dx&Y`1K z{nd##gw1xar&PzZJ>0ZfMzpubI%ls(p{RqdqSh)fssALNdKEpC+O?>fs{?HQ2g+2t z+M(aB1dRYp@jO)DnXiEFHRPJGR8}y0_^AXh$xkJmdhwT1b+1#^QKv2?J7alIWznE{ zY9>&W%@WVcjjTX=EfQF;0T%=_(ND1yR=!HZ*vOARJL#koZ?BJk16$9^PB>;GX^qO?4@W64eSTwAGXE=%BmU}!2k zID1z!%0AOgi>i(ygEM|`ibz$;Vi8rDkrcNwFMXV^xNR3tL~je`AUJd|V=^fYAYZb{ zqdE(vLC9a6S#|1{lJdh5NIp6Xt%%7?lr?B zj}g*XY)J0JEr|=4e;BIYKyhSRYo^(G_kNDuL7b8OPUKXNve5dHQ2io##MxMQ z5ZC31({Zpk9XgwcvrIV;gMiWNh+@O)GU6<(qz=r*yW+7J>80!Pne*5C+-N=H~;bn!}Rf8_sV6B^wo6uc( zZ7Qrki5pnI=%xYIdXSFbkfhd_Y=s% zDRc>U z3CA6+s$j~45BA|Y(7cD_qw~Y^!4qDh=b+q+a$|WzSnP@_Oz`i4+DAP_;;oP8i09G^ zEG3nm8mXuR3y60UAENYjRi~r$x_la_yn6ZQJXt<`rEh2_rDGA}9*G7Efo4_U1^xmj zOS$o}^v&$R)9Vxk^dNz;4%oL`=PvLg-ckHFV+GT=3;Rer8@K4b=+iax_#HELNwyAZfev`1mc=E6a604wT$fa==V}YWwoLRRk zaVTI+6qzJ+EC*!ux_6=V>Xq;xdnvL}u3khl2V!W zu$wlE+7B>-J!ikW>+a^_yrC>c2rEJ_$g&35SWgouSX* zMopie%QDlaQ(Kolz5BXOqoz;OE}7}GZ`B84F8?L!HGaK#*2pa~|>K&WPhH4~g zm|_8!EBV3cfqSwNQ&JH6cDdoer_w1qc(D{n4m|CqJuuywl<+kYEiY#u(EM^=iu3qP z@QO?I>C~m*dFS{Q>fK^~^}5UO>)0<^#4pZpk)4`fKifOOuQA{INMYyg^P1+@YZqqb z*Eg+Qer5GZ<=0{)X5!bH)*1M<-xaC+db-$*shYGm6-j_!E8@OJdiXWRm*Q-`t9gFi zwo~$TaZwt-dN(6qb$1wk-Tb-Y*YDexFATh4UcfJ0F0MqZ|FoT8*#gH$4Lk3$S2WAo zU67e&N4IiWHn?{x%kq$ziDgH$%D}R6@#iq@kuW0mn?58z#~I|Nfn^8y8|h(Lz?b5j zawk}ZpjMhaZB+b%0UZJ73Gs^(T2G}0@ueC>6vbF5UjYAdj+Lg}gx8QtAPij#Om zFfeqP)-#QzMrDfRcvR*;ZZ|A_@l(GDmLV>ZL1hNn7+aP&QDv^b*~3q9mBgq=Xw+Sm zSwY@cPj`O)R`Ih0&JuUS=iUC2=I61)Jp8nh&eEk>EK0+}|}O#?sA@HY}INAnRKn(h?&Q%HMqBwh=iI^{FK-Gh_@ zg~PUf6~`qUF(6w$hOD0BLsIo?gW^A`;czk;zv6)SVy4MK<`{c$+=eh4`=iD$^Oq_{ zhgp?3q@=?a1+qlub+RnR!7w7=vtNaK4Wyt1!UdKFh02;iHDnHBJu_Iy!7)Och3?4^ zC=mdaVCPw=3g2?Uz;P?tP40U~H^W4tbL-7&KcRpD#D~i%4OZwRMewbJwdXqz9i$8ueaf-%T5NiaY3*a5PLgBzFWptF&y}0uLhbuB(i&Z4nmgzP9`fCc^F_>#euI(d;%2SG1!Uw(bP3XvevC1l(6EOs*GGA8JfoJ5@Y^kV%_$+3imzaq^34pMNWvmji92l}2 zN9bq{RHi)4aeh2p={jJ8Az)v7^eR;JG^IVLpavBr9t_o~;}$lx3Dwu)39Dv`Zr?Sg zec0`%+II%N;LPY=p}I3U7_a4v=i!@rAyhwDzDuV<^%3=h9Sha>R6p?YF~AOf#P`I1 zEFtl#{QrXdKif1R@jvF971e81z`yUbib!fg=T$8KpqPY#$_Wy85#p6f+(jW*A_vai zw?gRlz+)f$Q}yS|3jZMQ2!IVTSjxi7>jd<5cSvkdf;Q>~_8xpdmVo>fS~tlmKT6^H zZX_uXNd^{bwKRyjRWD(V$YP5xMJ;!p-x;#g=i`vMZoT#ELs2xe>{Vxa>>13t*+y{N z<_1}OsIOaJm|T2Vo_3GYpOM$xqx3a7%?njiuUqf0G8It79+XVx0_qanr~-}6Ti!ZJ zCfuXsxo$lIV;R9Ym6C+`wZ3j0T2yX%o4IZ#=pe_7n0ZI7luc|6(uOT=3(DO21H4LO zdX#p}O1#&tcXS_O&ZifY0JMt}Fb_%Q@|5e=o%0n1(G4cHCi2KMJNOrOZR7%zM_;!N zLm=8E*7@j8RBA;B@dM#L$S7Cw47k?aPmLuP;IdLz?sew8&$&rQm7F>!+X|GKNz=Cidxx-uo;2dZz5Zn#J88bI4QavDJ1-3xM`eF;tOuJ8@| zj=;J+;5)*$muP&qNyYawg3TN&iiz=|1C)aR0%$nnIZZ8>h+e~tcHW;}A!uP-pD*!% zwwR!$4U7dp-KapjzvK_z@EMI|4tombAP_$cYJO-T_T=QpI{yQC4QOR`dnV9MQ<(&` zw>AgbDI$0j)?e>K4#`{R2RY?g94V+mKSVyv7^7|W#*xDRvoJ(iLlzvDgH!tv$i1g+)qg%R&}7s6Mt8Os8m1!G?mF0 zNRe(M9ViX3S$iY_7FGaz=@1{lGISDf+D15i9tE6U_QEMuU;YPpy7a^y<7wL*ji<~1 zlo?O<&pteL|71IOx&(Q5h^M|P)AsSSuVl)Ir{6ZPl5{-HNVEt~{m#vRrvmq(2TyyO zhneuS@f=-@O7!5V?P`Ok6(-M4;c1Y}u@IWHxuUSH?AlU1-8yAQc#=EH)6Y-R`e~0; z{q$;5Ke49}R!R!S%Hk8`yP66*D@9X1{DMZ-Zi7;hMQ1h^?D>-qSr@*&9b~md-W?+A z%k`3J`^b7tGG#>8gOZevtYhN}S!L`kOuwrI{F>^kvoauSsr%4_te4EgOvsw$PxK(` zxVH?ls!bjjSxP}cEtNN~seaXsVy7sfy}>tl9XMV(*%{KUL!? zn2M)Yl6c}&M(I?-DZX~ca60=r4X0NJW`@((|MJ0Uk0slI(;Vd8A)IbknYIt7k&-DR zoX(V_bT}oxZ4sPi49x(i3GPD=oUSqtGr?)FKhXoHwTld#x|=*Z1*eBN=irA^;{h#z z(=UY6x03*;O!x8rA^NF2ZD5eDpV~a50d@7MnE`eC4?aM>ws1Rux&nE32&fZPrtJf& zvt-H$s8*7c4yb#+ZV{kP(jKGFlRDCU=mAs*^Dq;jemg_sQYCr-b?=)7P^(OyodVQQ z%$}qG>e|jN0F>ybJ8J%W`svDpvQoyG>2P}fX$_}NCufG!fP@cDBNuE3PWi~YLpW{t zUNUVTPD>?IMmRkyN$GGp{mT}?>F2>32i`lwKX)H`;PjSxm#}b!87Az zc-0Z?HAbEogUK*YZ3o<^i-J^`J_Uw|EUOl0FH3{f3$%>4YTqfGnCm<{4ow<~q4jp- zEB!N%KN(W2+dtJB&!;tp3U{vPteOK{OSlkqGoS$fj!^}^JBC^9;L;}va|~9CPW1Fv z#-D1<3SmQ;0*`7EX`iWD%#itTE} zhJa=RG00}bkFk|Y=xK7e%?e8NpqBRe~I(dR7!ds}@NPH_S!kmv{Sz|d>-TRIzI0ITrjNFxMwcV6!IvA9bMf`8 zq$+$p0)qPSWdUCiprtStyjf)|hA>|Z#Cd}o*GiJ$OO7r`!I#T3JNU~d3TWk|Kt;2I zh`(9}Q`ot$m;E_W_hFqMXcZbL0=mF zWc6tJ_*Hb2+_MfXi+Gue9?v%T>()Wx4;onOHz1KQCaSiP0=>Kqk7^4(tY0ehRA_C| zR|UBgFw&3 z%OtKg?PCQr4Ar+6S1ZyRK3s2*x+&~Fg!u;gz$~TF+L{Cfw6lCb`(ArIA{Zs{yrf3k zDuXZrZK25%e`hCRYmu#KxVms}pE65A)r+Dm)Zx^Q28v$SC`#H)sv+1TAlZTqiNJ=) ztSV*^)S2Na-#PeFA$8zOHEYXvto=Mw z!A749f*(LQRw_6Se?-Ia?PEP~l<9UAKiRNG!SP_pAME_Hs|m}}BE5@{*T8XA8XO;& zR0YSG+k<0`%1Ag~Y~WZ7C5bTa<&q?Dl!g)v zC;@mj}w-~6o_o(K+90h>dsQ^vEU!U#R z+kH~)twdL#hn>6H6Nq|dOaKPR%lxqTbJ#kl{kd%qYI}Qmu?J-ZP)IpgMvW+){h807 zTmPzyvXV5EU4py@W$FIhNs`)}Kj%?;9aTo64E~%_dNiy+S<|PiK~QG=YQH~s%lk_E zm60XoNz-Cx6@XR(t#^Ob+XCay5i$q54^#ZPT}=XkR-!L#GydG#h%QPcdi=RJUok*i zZ1Q;gIXHu9jr5q*lQ$;u6;}AVbPpfCkXd=LqUX^qPj>;awS?G&>j1GQd=N|G3jt=m zAGL1)aB1c|YAhXij1nP}?7J`{Cb1jv#LP+G3>4~#>`?tU^+U}`R|r05sOfP`de#;3 z0XkldH4L2`tZ%oAK0Tifhn~Yp>SE>!J7s&ZI&HCqb?BqabDC51s};)oDqVW@KQ+qru^QO@5DV5K53rZZ z4Fx}wBAO0BX413=FI2e-nCltla!ot+yZDpGsw~9!Xo98`k3~ky6v#WObWZd3Wjf3V zLGC##!w&w>3Z+&XSp{Z!7fXXuc93f2s?3mc(($VA6^Un!G@xcmLwA!BA1!LKy~pwg z-Lzv(n%i%_`-66tD&m`Ds3LP}hsiPmCNFi9pGGoH-7e=E@0;Km7eSe1eU8>1e&@*@dp5Ou5zgAZLm35!I6tVLiN4X4~5Mx>W5lv zajtn0=P%==;mRspPNG(h>|<7D1l7unV?uR@GBb98%AyaV`dx*(z1tDVayY>ST;P;q z^X#JA?$apTd~{|McKJx5P|h^5gWoLAfWqHbHMl6uW5q5vyeRxoxJ3Y z?$iWUT{c(1QOHiYLV2k8CGjcokr_R(^ZxdV7Q~|qJusFKP_BYnE<$+92nch`L~s6alVVniR+ z3K_^i`>4v8GSp3}w-z0tbt*yBnrBzZGeJ82}|OrIcEh<;$w%4$@7Q>ePmfN9{7b< ztCRZIoXapvpRd7o)N(15D+n+=HE1UPe2zb!PgjqHXzDfRuyXX6acb4$l>VMdxl7{- zJXXl)Mpl5^uyC72sCHiwP)G*W+-EoS#j3pznH&p@T7$)%vEXp|$h(Fg08E&@$|biT zgPpt0Ay%<=?eBVhqOh=lgg_orRf!k&nZL6_(0Umkp%6&|vABD_1XLe_mj>c_NkJ^{ z0c1rWHH@Wa2WTO@s8R`GDXTB@LWlaAI9{t=s)EEa;gqU|DJ$HR7~t&!F@yNP@vu8va9*UnbG~XJi8s z7U3TSx=|1CfXWCDbOK`_=h#OSZqRd3i6^cDdH|GMiio^rT!2>24p*?l#Xw7hhsZp$ zgmw&IlnRiHLd_0JeiItyJFBZz@nIH^I>cWk@lZ5Mm0LGVsm^DYql?{LFrkAfcxt8a zgiee=uOQ*7c~$~FK|PhJd7UB!Bjqm&qRT9ce;c6s!r#H;h@tOghG-& z7{BQA$IeDXWIN}NiIW&*gOlfJfp^J+k3gzfT^prlo^WFqU2z>@UrBnss*fBKom9zN zcGcA^yl4bQ5Be4yg5DU=)xsxlBfR0Mb8+Pefrp1Y8ZFCtaW935G7=i7I;(3rZ|S)} z=_%7^MFY*C+O4fZb|qZ`9PYE2Rn+rdIiB!?LpO#yF9P}g8- zx>ET($|8)%yi>#&R`DMYW5knb#CQTLlNBOuUV0&V#ZV>w9SxrgQmBiyxa>ZzP89d_ z=1kF^aw7cs^RZ~0=MVIhX9_~0dgUAsfw&-!4<}b2vWa8i?V^GObgMptTScNoSBC1} z6zZG?Ng0|8$JlI#YudD_)InzwhXs&s>oJL)T#=r09heO?xU4_=HV zM}~i-Z;)Gw^S}9491Hfvo#2tE+z}1z6Lj&f*nI7MV0%5&;yk_4iY|*EjJ(eAmq6~K z*yZi2;H3PCf7?mvrwH{^G4&Hfno1Fnt6z^Q_zOH>thK}vKD;AOOG{zum05g+4{$14 z8?cJpxp@{h5y0u4ED1b9p1TYBEUdb~ik%1+ot}>yJ}Ps2G-CHfnMXy(PJ$qxhJT|V z-TPUw8}Wh7_Y`T7Wk_s+6~)j%j>v+9<~mF7R~tDBIVh$yRYI%Vfo|8EjR@Cl!7^lA z;Raix({^*yhDaJFbjxI?h%yxXiC()J{*LcoSGMN=ot@CB^2c?9PR3 zUbFt&=zg%RVYUxik^iC40@J>sd1j1&_T{oFSP!uy%vrl2Jl|=$2>W54axH-llBBJe>#`LR0oq7ltB>)Mx=mma2g3>jy;46#8AuQ%wa0(=)QL3y<#$TXs zmf;!ysBgqFO=V#UAd5pGw&uds2rhoga)0b6TTSTWa5oM6DVv`3H4-gH^I@B( zJKy+HoI}nB>oV<+ZB19Kb}e2T0dzuVlo1j&=n((-omk=@nNndzq3EJGi;2IWuBk}K zwOR0GbOs;S{$6Uh_S}PtYxH{fUIoT7P(sk|V3ve+g=+z+i6Q5S^O~02bDTBj*%==k z;_P-LZd}DB+~4zF72feVcS}dBJFZ||Xn-H#{z2&6#-FUvp$mTsNL$4>YR-}ca-J|WFm?>Um{Ucrz7hx zQPc@+nGfpVcd1-uClFDoq{9*23>|PyGgLZmRorCgu&0|gbGq~OD|VVu$m|>QWj8n22H6M}&ihUndUD{^F7v zkDpM+S0F(ooPH&|Q~QfM-^Fe+K!I+m{l!Q9spb2NPugJGk9HIodu0erAeRHkI07%G z_ZQzb!L(i)jy6NbL;mpvAU9zxb|~NZ_NNvWZU?F#W;ZlewZ2kX#I(REI0wxAZ|*Pt z6;@G(aw+?ZpFaDK-d~)34|?nFFP`!a51r~9e%jq%+%H1UWvBKRZ_%_C3`WQf0BXnk zi&vg$_7~sqxsO>GUbT@CfSq^LU;d;0#U+0>ZvCA=$U{^F`Cy}x*PRm=7lS9$jr5C5<1 zFTP!?h@>WTE~skZ{^DncLg;q5zgRATOxs^y1IFqtDOZcX;8`TLl@20RKcYjlOJX1S zgWfKGfH(RGK~W{E!+31$9+0gKz5pF+i!;-Lb_fl2(>Hqd!n+7FgM(S>sAs4)y%*jt zx@MxDB>d+-9tWYE4uYC}`0Z7iz)-zj_EU2owH3^uw*IMmJl{ojvnIn`h?crB`7xDA zmXh1jYqK#K)?*;;C?*VRB@>p}E~z@#EX!aLCIHJN38sEY)qx}k^e|?u@kNMIWKBJE?VHf=}jZ$iFd82S@d(K`|xgeb$~O`JT$$HpDXcES8M=Ld3 zKJ~n|%Tk18?&1vLFJ}O~CHOYnGUtKI_~u`P5`#^TAHw^|1YsA9xM3Ltuy= zr2wV8u^5B{k0tP{?n&&eP{t2*dsgevh1u((MC9}QH^6~bZuldx5Ms>Uh?2O z$-_Sen45XiF1mKSM*jzTnO_bY?Lq&xmlXQDQE2VpBwDZSp#ME&H|YPTRGwj5{u3&b zpx?j4*@OOi$t37^S7K`PUnNO`euHbGUlUvCT#h-L4YPs&h79=cqy)X(Y@{HR?{pt} zHd0J94_*A9?ZiMbL5qIfC>sgaSE=P>w1n zM^GD_Jc`L7qR;6QO?mTH^i^e0U=fhpT;nlAT>%1_$PzR3oVr*8q*Heyyz1VGKvjdl zF=;X%m+PE-(@;z@U?BOVUUdjbQ3JoEsaXDk5|-1Hu$(Q%SBN13C{~~l?lk&Qk{`=^ z5ZOgoa6E-9aFUBVd1ioxOlWjTIF>g~WfEa|QpjUW1x%qi!=h9&$&QQ)n1W)`vOzM_ zS{y5>A}>cXWx7g1C7PN-NYGG|FS-ay==rB0J%ZOLt%rGwc)qFw1xR&1@v^cZd_L6k zTo3(dDR`PiZ%+~nBR%3pt}ro6`%GDW5b+gz()LaxPv6V_3RQpnuOd=v^q{TEjjr2g z2Ea5dGrmm~taWGv|7c`3sju>#$lxEJyEnD~K?)&t84&_e`w;@>j2{S5o4K9%{T#~6 z#I-dnA0eA+hHL<7)f+8jHuHFe>=2KTDeh?@yIYFUE>na4Awnkbg}8*B)3rS+aP5)E z5%{emDP@Rqhw5G=Xw7{T9J#8+eMN_VLmegJMF-37cU(1XM&GW^gF%nSR6#M|uq_sR z>sciRdU4;E54bjCDqEQ9G2M&o#%9E&3$z*Ba|DE9E(xnsV!_dp35!|bi77GQ4L>U8 z0AJ}`NiLzUggIK}5J3uLZkZy`Tcy)sI+l;iQK|)d_TCfdoYE(Hff@KL!s=0`2xTp( zLBrgT4&El-FV!AnMdEo&gv52RERzz)+%yb=@v;it=R8YDIa;(n`Q|xggG5T+dyTsY z8VvB)>pdP7aar8A(TZ+}<3d{$w3tV+@JJ%Bb-DiSH0yHfSE)ik{l-74$YwhZbXU=k zG@Jr-ABJx#l%EnmhCR{o{MX<*?;xJ9p+1c{y-+_;9_Y3(khiNm7=l@%&JRrDXcV)D zaj`<$6M~mtgARo1WqCGKG>O=NC&DHEFtPwx8Mje_HC*y~#C~i5XKmp4KoLs7SBLi@ zF*G%7#V;%m(ow@tO2_>a7rST=*}TbfyrAdGARV2nv~<+9^GHW^QaYZTt)zo1%7DNH ze|4opggI3@#v!|rj z_8_`E?Cku{l`I3*L^HHlH5P+LVu917C@c?c%Sx|2*|k9$qCa8EsZ+In%T4u{@9~&&rEft}ize7JIfyWYF&vmUqEpUgAsnG85eF0aBln;~Cbo2hE1nFuiCit-o zh@`J1P?{fbJF**1CyPlk3DQW(lqyK{V@1=QA<2FzVvCUqg=eBl)OiQ1oYZ-PnWEe( zQF|{xi2efd(2g_I?SJ@D#vhxcD02az@(w9F4SYUv0r8-n1XCcT+nR^3Uf(!UDW#;9XI)FD-Znd7DAZ7 z;rz!G{AGoz9b7rtHS|ilxyR*x~Z;xZ|k-LucFo=p!9yLRki{ehvy}mLOfP9 zL<;dcD;7LkWuXT=22YFm6suZae^+j`c!M8e>yMCp2$ag+0W1-Ma$LjA_ycNQzn@Gu z%A`)iUz2*`0&)NdH}EXmjlEYoMmxa(P!7v-26)oq*9&x&a{y7LRCM*G_j1#diZI8? z_Ga-61*g^s zm^^m=qIdB@or=EHLJa9Iru0uGiHM50z(iY6YR>l*OtM#zco)z>>yf8j6uep^r828o zq|E#ug_J)_F~P^{G9aZ2c??qalll#%6jD$pk@6>%O^~vj?R7PcRRH#0EW1PLZyc;L zioa2>Gp^#N)|Ap&LCn@iq-G-K1Qs`4X^+RolqR$~asnmw3DzhPKcvXfC zQ3IJ7D+-sfCB$Pcio)<{lI+ElT|x{k!;%XfY01A4Wc4eP9F??e5+XC>Bo%9hS--ek zoArgiD@~t6DBmqzHhL}bkV5OV3awiwWmvl}*t4DJ#)~4;j3a zArF8$R^<_(&eVC(e({QPF~y<0V$%}>;)#FytQ06E9gwY4M@nh_ty61ID*xaczi|%> zRE$nq{}cv``lC6#WEYCGDn1zlK;zho0g|YZTjIh}MpsPl>P=U>SW{t}?alIL61G!o z3~WCa?@L#517W+dM^n55zi?00j~J@Uo+@r;kuUd}FSqfFwl;AKKb-l;z#Na?e~0_4-bOZHKW%^2R}$vJ|5s=YZ9`!HkN;~K|&hBlLok-tb z^;2t;(xUxUJtymaZP}dKFZeyuFMh^?9aX=Y+h289v+ZW6MaN5WoU`24y^+em6U7s78{4PoN-`QVvJywUay%?$JnOuuA95SYb z(=@GX4eK_Jh#9$IwnuH0qVHaf9AcfAm4CEUH0Au`_vz{@G_85fdHZPe_`kTnYVW_v z{;D?ekr(6#Bri-sgbb?vRa0v9{;EIy>cOg*0p#)RuNrZmNMTF%SM^8M)csW_aCwac zYPlu^R4`lf=+ja!Pt$%{`u?ix-4yPxYX6YlUv=+BHW{zR0-LVOyua%1(Xzklk{+OR z^ZTn1U(ow&R?(nOT-!jVMfL6jTYtjcevHr6qIK`WXAG_NY`BmXKN_U~NPu$+OaZYa zWCyIYx~Z_>+``@EjTV?fgPTj|pni2_xfQ!9XF%-K-2M|csok=2Fa{%^2cvNVqniiW zc|GnsJ!@c}Eus3>Y;W{Ka5L%>~KYaRK7j@HreTG2mtwhkY(~&#Da-b**9-L#1P5Uf^(7!7IeGkD}voYfN6Z ziCP!___GIJ5|#Dq_&x3wbb&6$(FIjGjgZ_%3wh)=+OO|vFlzo_=BAV(B}^&{fl&sD z2?AHgy>6+>NT_w$rW#Y7c*}}XnVLG8*v2HrZ=&E&6K5I^#C?bDyg+-3 z)rr>$0lficJv<74#EO0%UunL682^@j#`#A=3U>R#~DBFL*rt8!9afD1mCF*epH?Hb#)WDqcbA$C*c$U(6)a!$rV>HZV9 zC^3?S*4R*1Hx)87IQsS=`{3_qo}M+h&pV;|Kg*-JgS5*Xs(U~rNo_knh}+QWrm)?1 zzkTnaBz=zH27V8Mpir+@p2)zCo}a`sE(xWe$kBk94lk77&*7dGKA$BUA1GWx)`<&9 z?fC=k8z5Y-%2ZHY+mmDcb7a!{(E=r15GXxM0^Cj0ftb7{3Is)Khm6 zc%gb(_yHizA!4xzO>J>{2H(nKO8UI?a zs~l`q0);qli3oZ{YZ$@XZdW%$ zv`kl2dF;yb;solh-aj}xci^H%)Q}aw1=)c^2y47TeMMq?GQK+hI24k4K}vuw8K0B! zfNTs*yI-`_isfL~+r17!wck;TXh9jP%I34!zbbbXzBH*zE*607Giz*`z5?7cdK zK1&S>;9n-!$83?6RaMw~Mh;7`7SpQy1|j7!O!x*k(boWe!>qf&X^nGiSub>;Y@*T| zV{4=)qtBI@p`T!C3XFQ0A+_Lee)w8v-qD*7z3+VZlDxBuAHH`qhP4DI>v4*@gZ9$_ zuM~QJK;ccfKU#(phTe6LG6&>9U=D*_e-0ji5p``O!6iM6X80FHdLT?D9=L-7q^HrY zJem!qDDaQp8|53>pk)lIWf{}ZQL|E9L{PI~M%Nmqg6iOeITS#cp@}N|a7X97LIyt? z^gC#XSsyIR6lC=ehHlPSoEJ;BS!{C&ISa6H?iB*2B-aGS^vNe^Zb~!JyFeU^rcqAd zkvYPdJNeOUhs|mx9rE*ZIPm+6^8Pk{H2c1BaP(Y`=Y7Sd_{C_9b7D8JJcw_~FzWx4 z{I}itb(xy{BlpXl+RNQ9XH>E*TNLR?`jHqEg9Wfs=qosYPpIa==4%;_F#F}G+??L; zD|;basbMxSt6Yg8+zxJ;oAEEM4Tp+6Kj9h;067+n{YCWQabDL1ycM+$3X_-oBehql zuPFUV<$w9M%o)#y>hA^Z4^^uzb1aO1G-3h{V3~!b7UcZ>VDN;26_+Q(9std#D>O4S ziP%Jam?3hhbc{H$O^gEQu)drj(EOaS0E0;Uc^|gZplC z=g)!oW+i@3;z9K9e{f&P&`*^lNe4s=!b*|tT<~xWl?Cpd zy;a$BbN|g49Ss!OOuhdGdCd%;1gB+&FJ-~oG?l4<^D+L_p%8Yn;Oz>@Bn#fKIux-$ zz^edXBDnuXl9H=K3-OqX8NQy((4KeX7eV+X{r;Pu6dK)gI*FcY_n~KX=w;@iD5BK+ zZ~TcIURzPPt9J0*(I$9zpvmJNvt0@fi)fX}7w8GyMo61E`*juZct*AD#-_haNobZ60RA)5d>kSgJ%1p4wI#JgqQ! zb_!2}WH|_->Eh|i*IJ6FTf;lT(|><|$SXY{Gf>J9blMoN(`;*EV4JpdG}=>HsJ&`P*>uQ4#8vUD_$}KMeP(q zm8va2(1fx-5E8}v83KjdbWDTBuLp#O5oBi&>P$S%UNz5O8H$;%l-{bQj^8ADCoP(j6A*N$(d^qDll>tV?F&)+e`|lpZd#OJg|vzkIg-&jd@A}+Tx8PR{*Y<12E(&I zWWQ5rGcX4+Nv{@!Brs?Uk4d@sPfS!|p!bK&lkfpX$~u0Qx&r1sel>64w`A9AAh7}NKM6quBh{UN#TbN~L3O?uk~G@2rk zcYnyFkp}q7O}3Wp4;ebs$iV=rNqSe;{v%Zgl5Rq}6>&Glz^Rh`AvNuR?*G00A^nH^ z@%ux5=&lS6WJ1q;KqgwgKV&2}p>k3cc1rCJ`TayK9m7{CQj2uROr(;IY5#}1FM*D# z%GynU(lC@26zo8Q7H!m^tp)*26tzHx0-^>*jW|U?jfxsgf>EZ#B#^SWf{Ka?8i#IC zQPI|bikbj2I5M;dYAepS3^F+}D0$zv&pEelRVo4c`M>qQtOa%NJ=31|KJz4{9eRJr zlVcqxF^kS5UOO&DcB385?hnb5OwH~O=_1L^?+@8Ik!^^Bh}j=hmaI$6poR&GL02UMVawY(+Tlycphd`T7}V_kkOw4F{IYhVaa;yhA~|ALw$};C zWhLB{`zU8I`$L|1PQjnbs24*+9GjQ@A;(Bn&F&9*y@*xq>;8~SWfuzSPP9KHptq>R z?+?jvzQ^tlNj2XcHoEqQJanzGa}gb4mG0C2kn3j>9~DIBDl=C-FNQSm@04EtMGCMzde8(`YajN9-1#gC9J@c{(9?A|JaMg~ zMbU6rS-Qt>Q;MYbhrA{oB8da&bedSYB4js;)a?F{vn5l!B02j*PLSkSEh-bXa|~IT z4mFJIQ8^hA#P1Jzs1W!-moZfJ)f=pK(fv_5F(%%cvGAOE~|5yhegQ6+*Z# zDZ5uvA-d@9&1UNI0H7qC-0c~_z#kNo_b*rVM>x_8?Dc zvb>+)K&HvQXrA*Cona8EbQW_?-Jr0IxqtB%=VRP`Jr|h-K|Aigo_?{3uKRjUa145y z$>X}O2SDcw(0C}2hbXYF=@9F#s1*8@6h8A$1-y2A4)$PmzBY1ZVg-TgH(cqkye&lS zPrQHesU!C$Uu8QZL-O zx1=ih`Ug{ESid1Tr5cpi=kdHO9|Rklb{4G_Ws4|ViP+@=XS^E8J{}X)~IcP>s2NvAy$gMyyb7U#)Xf zDC6&6{3tfjb^l`V5F?Z?nmqr-{fkFVjfy6s3Jw+xcr;ctE7Qw_)MgydAPqAo_b*=A z3Ie*f`xpPN>|HJo$HB4<{s%jT#k7!=woG#$7Vjma~{mFOMYx(*Qh1T9%h8DpUD$h z4J$g%E$M$@uO@D;U>5X{s*%TR8eayRqxNmy=&O2FyRb2&m4?)k16|EpF$$mGzPCHe>h1?rO5Cb5 z1XJ+ZE9N%Ei>_0W*=WG!i ze3lKvHK>$-7&trc3RY-N=TQ^VjE$U8WfLlj!%MM$dQV}W-%zVkOv~&;uQQ1Wu2g)@ zN$cxqgSJs1dW!v!la3RS%`&a^R~P{v?<7AX$(89fL;xMyxx@s2d}jBWf3X-?oxR6t zw^qD3G4o~@DCYH5%*&T{GYgjwq!=F%YAlx}c^1>U-X?mtFnM~zA8&ZAcsK9;BVV;M52Qn4g@nvy8rV51+zA!@CEtm?#Sb$9@zj5)~dTB zYbXc!gXehjQdXrznsXPNB@uN0qa{v5#hSH%6#%jEp*n)gk6do}=kWG8C+%>P z=8%MCy-xanqP!h`nc?l`6^8XQkt~~>Pm_GWod72gIK*8w< z@j^|{(_BTOit9Ox83D%%d@-)41Hui*^)$AY7v*}ks~6>ZzQqf6TS2D4Fum3utNvwR ztztLa+5%?4Apjh9^VOanC~L&|Cp?YWS34;gZ}4T8s<&2n!+n_NsJGU58|$l*fi+Yp z;WN8+a>xbh+bAvS1nhc}cU;?L^EG{2|KGGKi5?%v7=afRcPAePc^5G?G_x z7M>_|MI~qAi4s>_l8vV}c)F_O1Uz~0bR+Isbr4oyJ94E7Alt};%iCbQ1JuFYJ#W!c z&=5d;QV-%s%)X)vzzZxN+q6yO1;LhVnUOW)+LKzHTTkGI1Wf$Bqn8*$G|g5XHGz;4 z_HNFn%`cIiXw_0XT5?I7<()7ejM_#Pkx3Oh zQhb%m*ce<{@o2_Ov!rPqiCCT#&PcFMOV8(!0`}u~$M^s@n5d#<_@d@CMb2G~F{e*= zj+)bMO$256Vi>ig$Tf0GNvw=S)Ut+XteBe;8^D^M_=7wdnALXv_Io)<3@;kh^%V#uAQx|Or>QAG$PN1?Lc&mct*)>+;Y zXOOEB0StuQLul;Bj)e?$V1(seBRT0aH`HrJH>?yX06|mirOwBDsS5$X3PXj8jt`vaZl;89^SJe*_R1vUky|{L&bDQ9Q!l zvH0ksSK)YvUah9LNUy2=#%3FK>x^KswlmA`eb^!gA$W4s$GHWq_6 z=&Wbb!v|pcl6{pjc3iQeRq>5@_u$f8%X97B#E1F;+0G@(R1|%vgXLLNoF~bCCTC!j z2(<9r_FNDjX)c{D56i+DMJ0vMW>%VFZyv;x8&D?YHg`J|#h7*m^>Zgvv!luOwOfET zXJ@Ha1VjQ2z3(f|9=*k)3GM)dJ-Q7xVNyWbnj>FU0B5LOX53^cc9i?ghQZbh8YQv- zSBFyqJWpLhR*U80;#kKFkY;F5fK^urN-s@NuaI3Ju+7-mk9=8@4-WzJpe#w#D(u@f z1K)ImujLu~yK3D}R*JG`L^r)f@dr0{sQv%{LGXq6xtfq6elFv$rGF9U%-}o50m&uU zd*uunO5&x4X%bT6Wv+g~`4`W+MxbF!^LfiYshL;ZbK z#}F=_fzgK#R`>ZAQ*(Fwsu(Sj{&~Kt1Na!mxeQgGmgv(h<_j3+`dhO-Ro^m;(4dUz zp|XCAy(0cpqypKZ>7P+}w# za7--~G3tBmMLf*`r(#_qVx$DXS2aW=33sbj{aP}B*B6^JET-v83rx>uw)9rmu3sux zq>g-mWC_K}m(~G6NS2W}Ox=!yWMODyvUGj5WQo*3va}Leowxm_g=^spj&PX;Lwb{5nF_>TErx3t`TB$`>dhxwDdB5193rDLr6UY0d1ItL_N@hK_alL zhPg%9HcG&yK+@+o$oCbl?~y_nBAkWxhKS-4lue4v!t>D3wn!O8@!beSaU41;D(H#I zqr``Dv`vEZo}%X)JSS{&9S>O`A9%?-V#4kiFo>c`v>EL}d_bc@+^f5;_&hPkR}d+T zzsULw<(eRBbU~k1DdM9P*YP2YpFt$>M~NVH9F~R0LMkhk<|9O;11qMTxP)c{OIz%p zu*N|Tf|RssxD$=_Iz?ZOxL%eD8h)r<%YYN5N77OZgFpG@Jn<*D(w{)e3!L+ZI4Dmz z`4z0EEP=CS0v4k>%X7>H#{8qY3_JXi(y>h9lSO(2hzOC2c5U=Q04{{Udm+ar34#Du zq?iLpVb9m4(h>hRe`1JZJcI5gMe7QChNv>ZCS{r_N;>#zhxV+*=-pZo5A6jwoc9bc?}f(q&& z%kWKlANCM^W(UyIh=fO^1;ZDC_r(x^?Cr%@QmPBIRNL240+du2C^mX3;-#8aoquHF zD)op$dLc0&+Q>98(FKW~y;4%ge!hJWmQolY_o&tNh(Au&a=!H$$BxNdl7ZdT=kSgY zIq$|kn!`noE?J$gJP%u5@@Phg3dovbU#_FD!iF`F#GNG~i9hfMNF+w61=8AqZy{tn zqOtk@*Xfj=MDtmU9t1Ezt#qkn>9IU7Z8v%eCeD@OG9sc6eK6vb1r^VZ=z7#^34j36Ntsq$)YUW=I z`C@qv(yM}uHonkNPeH@0EJC5@AMHq;{A$5=S7CqhHK_a#@KLB7r_YO6EJ6Q+aW$sk zKF}%zsP)Vp#Doh6f%P@O`t;{C)>U&|So_1?SI!o!dlL8z!Fr(Xv!FrXYnJE%Qgb4m z!W5Z_=`Sy;`uq)Vi@%UkNP+Uo2`HwR{rgwI?r0r+1H%~n#+3j!n1r!_0ftHjS<|E{ z%X8*!B%Bx)J;dS1A@)`fssLwV(f0@>yKhz(2*PwLn!GkknH3lV#$Bi)z?`rxY@uRl z<`VlF0>wk1Fh)=8Prn2#;~WCfT7ZXW zp}Id$@rcsPa?V?MQz@NNt9fcypQV4HZnMZi+5|k;$g@^GrBvE*8-1cnJb8NJcP>+aJKa##Pi* z$gFnEicg$Vw>nR|4x45|=s~Rg$L7Yc$D31w;-oiNSc*jx6Iiq`7)s`EK`_)mHSDp6 zBa<~EMef!D(q(Kj)IVie|FmRB_nNbS2usCQIcK#nsxx%}O1qszn`ph^1p=?zXUf*+ zsRT%g+(h5+HW<+O6#|7Bag1%n{`L!Sod=Re`780=U&z{6eFyOiQI#lVfq9TGNXeHE zmdLnR0MGT=JkgTe=R2f7#jalYVvRbf!2{Pwn_1WsUfl>(Nt%zsqMQGEtGDS0Yo2~rxS1xMHM)sK3w z^);BwNHwp-yTIjz&Vx}@jtL-2C0NU zK9kw}bAQL@GJeA!p%GkQPdrCwMQMqkg$VXrVQA^A%0*+K=lnrYdIq4>IK&0?#5s@N z%VX$Szf_9mp`O13|Hb#2VV@kli!J-`wpjcPC#Iq#O04?3p|`9Xq8+|L)meZ#VM0AO zy6Ob;nPYr2b@oKV=8mFH4gg92h1n{W`j=q8>-NTm`LXqlj>Fwh7Bzc@^^FQUcuGk) z2RaJ@|8PK5z?Ih`AYhUA&4bcq2iy|ZQ1bDMEW_drS{kKY100OkVLe9PV?;_ z<2G3Ns{PO>&9(2FGEMOx%1qk_nr24B7Z4*ryy2%jXSsj@#Yv0-3Yf+Hqr_0w6SN2* z2X*DfyQ31Xb!B%+Vu}A(9f=L(mXn)Rn?u%Z_AiZEX0|J{OQQl*P!4LoZmwv525RFN9H?;jXG1 zcLQ}Jk5VVfTu3>#vPk<+?RK<=z%(-WpPv!^9 z0aD#(rbX#zRi?{zd#CnK^-Ym`Ny|6M^j>J5S{8wjO_oQ5EA{LrElZ_Z7C?#PiyA@G zAzKEW8%b+l-Bp<>5zRc((eJB8|G9c(`h~Pkknh>54}}geg!<+58j!yiMwxaD>b3H$ z&|eDM3rk&gX9bff1`+Ap%~en|%D{w?Vf|NaAe)C`tY{@PHpl94BKkyw!2d%DCJPU>hG*n}SfxX) z@e)qvk%pk3A)TTc7e$mIdk#P-lpR4_9-(Z)X4z(eHVKHzgti;zV6o*B_tF&f0ZR>t zGX8~L1L1>#f-K4;Q!qf1CBK#G)LhUz zh<8$fF-i5z^gOj}lHeG5)HUNL+Cr3hEBVrOfgHQj?Jb^%tlmQQVb(_Z2e){YPfU+t*Y zWxMA=)g{@jK36s` zm9U6Tz$8gGQPf9~j$ix^oOnSy(=-ut;0*AhC<)7iWgM9V%JNQMb3O27G(ut}Fm!T=M}RQq4)+hph|t+EdHObOp&OB4u3tUVQ#CfRqm z3RKFfatDoo5GI3_K=j#t^Za}s2bXC3(ONEL6f(dOyzIrk$}s9fo+L&T*^7(&kT?`f z{&93qq!YrNk8jH=(+ikHX%+D*UrMP{%L+(yRP+|Tak%?@amq4+Oe5Ii6-EaLEwMx? zH5m5pWOL!pKj5dqB5VRyu%Vp&Nri0KGf?2}-j_dWFq&1ZdpTOwA*kwuD~Vm_x9}4= zgG%AlCKHKn;@j}$ef6>474i3M**1GA^>H(Px4ibgL{NRa`HNIow!P+v5`yp zLfx+VCt-6Gxog?(VqaAV-=NgVWxGfFs*2Q0tFqmNC5HrG$6FG|3UG2W2Dlb$02(jhT*7+hF zmUs3O3fL5TtfV0%lRGm=*2t6WM)BccK4>mQ?!t?&@&O=*v^GAAix+%V6@sU+$Yf;6 z4VsB1ml3Xy1=R}*L#|H6OJpk}F#yo8 zNdB*t|K}Sh8~&+QRU`nc!~ixX5n%7>YQcIuDY=5@k!J#iwWb)pLxRYcuj&Q$q5$Jg z+sK{xuO+|?h*4u=b$_HQ*+7E?nUMul_B5<1p%VHLB2PY)A|$E{jQO=N!lT-oewA&= znp5rut~}V?032nKeXP5IgQZeaU&O+7NwHs2(VSiSKK%Y6>MA9dzjxL*jG?D)W_<(X zmjhY+qb%3SlX`Z4XPC!7TBN!Bg_aVm`SMK9S+rHb28Y28gigbK8`=CrOrB=4~ z)pkp@irxy8?dfuB>xw1*>TapQ#>L1m;R}omuIV-e)na7uRlSfNIxZZ zB%gI24@*U&m&zIdHvryq1OQ_1(Ev11|5RoKM|H)Ag@bJ>cD7P8^A$U>HQ-pufx%LY z)_nz=_wY__^A^u=*}Ov9ybiz{`(I8{Hg7GdV0pXVL6M2Ec@ilrR~ntJrp+sEugplS z%~Sl-p^;%=rhVmNW%B|g2MnK_VLu=(?70>Ih|R0Rea)d^V)Gn%uspXPr)*vw;nP!l zGwhk&5JUwl=w$Y=Pf z%Cm&wO0_Ub4rw!E$F7lb^eRYpiMG%W?_Bkp9wwi6SBz93PY??o(Cb;-M~TI1(g2?e z_Ejh@Z@V8taaLWtBSic{M>rDAYexv7P>#?g6jvRaNGK+EZA!wZ8!VSiBoI3-6bdPd z#5H<*NuhL;XpHmHh_>bVBPTk@oTt2L*Q*r85IqS&jYca&CwFM*LC9QGFyYK-1-Yt% z4P#UVh{dFPp;-rcqeYBl!sO1dU+&Tr6?@Ba7~v5f!AMyV$2J3v#KQ@x@A zRw_C_Apv1Ekrj)E6!t3k;e;A)E1#C_X4ttvZwcfIWtP*}-Np__3A0=uFBl zd`cP=fPd6f3B2?(LpA>Kd%*Qfhnna+`zPkRyKJiKd&0IX&##>g%ARA-WX~WL=?mBV z*l2tO#--n;TR{%{goBh@d7iyx%QOFc-7Wr$UcQ+^t1$~OEl-Mq;n1Og_ZCnz!%m+_%_O~UO@QK~b{Nep*>^Y|JhbqFEeT7l)4Sb1lb+H_hGv?i>8roXIj zpm2ujKF2D2j_#2@`D($5<@xq~uEm2M9aX(f#(?PwyF0bBqO~R<)4SUmy||QePl> zNNTu4VS|g*Z6}b_63=ng0QAYCL?}`#Tr{bN`blED^jl+wPzu#e(<4}ws`m`#1eML| z&q}?zvr^kJoeAl*!IVqdWoY!IL$L0$5#vEcmt&kYxv^~5@g-i?GXunpG_Z$nY-|(@ z%kyCp!x5?`7*3dz?1BYKc7O}9ii5A=S$lzpa|JW(6Ao@_C?xorBp@O9>Mbzp@f96> z1^5kgaF!`ZY%j3_y`xPS9&1h2({VCa8k13yxL6muyyf7iwL#_xZPx-|K7sp3P%8#h=lt>s6QpJuvB}ZUr zZ|ON4Y4g6qpE$T9quEy;UB@~Zmu$;!5{jLz8;Ztqsv(7Vl8JZ_c7C*wuX5F_43AG7AFh@A<3Ggf`l1 zqZG`D6r~LrkHsPJ9Wi_G8=yln!#Y zw!F(;GqKU^C&6s!L=6)7$2llk*`{Q?!#2jYWq1KdK5L=-jUBB&#?)Y$Rg^lqDnnMF zq(OL?rOk3hZL*^2>j#o4A=84^GrWUFrl_{ z@r!}{`AniPi5!$KrFg^)IA`A&0XOdMm#8Q5V*a|I(sKLnutG6K39 zQ-eInf&NH*elC5A5R?O?uW@=J1lI~_5uXJn7o!sCN6y9|IP1({YANc?glEV>cf(iN zS;ii)6G~KJ6ndIii6MaXNpD=sLfFfOd}EaHxg{yy_{@L9F+MQ^ZpM!4ctjafF~Ab( zqfY`j7=&daLdl?9Sl*E@8H=>*VP%n4A%TC?Eyfo7H_eHBV7zEUVf z<12WZ8f0b2vID=dAB&)KU?;L`d2PBc`jiY0KF z3n=(UV$OFxFEr1fP#qzKkgdQkbYc~gXtYFt%a>BF5x4+z6=!tr%Lc;TPvQ@xR0l4P z&Wsu@m>JJaoyBMs;ztKAj2<8ig*tGFR`~LXVz*x5Pqf0b<0?FT0CRcIz>f}GoC;0g zVt8cV(bm{4#T`8n2QipWj4|X0H>or&K*YkB46j~_nvt_=Ihn%dCqRP6H zZlo&*5lB;7Gt!fBj*FgR&0^>oV;D>jLM?Asa2 zz_7eyrm0yJ6|bji^3IZ0#cpW-?YAHLry9)wmNH6@XiahrO9^`q`l}j8kOR26)zMIm z^KRR^)_|?UxUBzjrpyvvsHv8{>VW0>sw2D8Minp)h~iomnzAkgGvPGB(DUbs?BXj} zvD!vFGQWT3`X0%V;M%kPGZG8~)Qv?=2B^)-jdUQx!Qm%}yXAdIJK-5%nWRQdy zh9eX*g9fs4#b~lU5Qi2~tig3Hyz-b}xWke7hEB`C zbXz&&YC5{|O-i`tDe-|b7BPYir0(*M_HdPYY~pBW8u%CQfa>I{`kt^J%k$drLxj7q ze_MLeno*+xTtGD1{_Csmxf9PkxC5W^XsFjpo}k7!fTd4Mg4Xz^ z69Q2B-(%^Woge@-v{zrH6bHH~iw|WiQ1=x5s&7j!!MZ|0CE(D@QrYQ5EI=EFK*DdQ ztX07jh_C0#5KWj6UXQo)kiK6z(_gXcXJ6GOJ?9??uHG07VObw%&e-9jeG0naze}Al zv`V%PYzT&a!k#f-)mCDQr4OG>?C7iQ(=kx_YjJy7>hQ^gEy2(y3Q>WZh-N+ZJ7k4% z6Vz1<7vKbjIj~n&=iAqlGFTV!SfNY1%1Ab3gGJ+P@Y{z{y-F^oBr4OFg3S%oe&*9c z0s|n=6cY2CNHAvD>wez?h_r~6FQw!ucj;75omeHiHB{)-Fawmsw6`3u3_W4J5`Fcc z)iNLS2<%2Cg4xapY!q#HUWInWdToWDxyeCW57cU$S9ew>4Shv@O4RgFmf^$OUdf@x-g8xMKr zOTKw1kO$NUZEZS&3PO$EWz1SM_IHn)o{1%+oCq((Zky62cBi>Oo5x%`mRdbT@wW!1 zuUGcEf!3pZlM=#tf*9w+YXA}{FrUA)To8zb@(h8XudS08M4$F||8@l^LCy7Om#In} z#jp2r%F<7d4e*rA%^lPWnl{+T2#yG0@jno7cMflJq{l+9X`3AqKUrPCKHS@GXd+16-7$*2q@$T!G#NR?+$3O=xFiOGnBP1;VE0#KO zFxw(~%1~OASz>tmChQs^k(JmgEre~|h+N&66Be_EzvWBG`z1JvhS+1K8kyGPiGMmj zADiZ1#{7{gYGlQZ)Dk&7biU+Nq7r!tNjQXYW#nn*u{ux8(N?nZIu~JPpolNkQ?uiS zB%lfGIJpY!u+?T)n<#eGteK`tVR!e(3Okmj>mbA$+EjjOiXEqC8(y?`JPFJ?A zM`E#f#f}c+hWcuApjarMUp=e?K6%GM`=El=!@PJqXj}&0`c@A+2yeb|U46As$LdkO zU}zPk5-_0A2!~(nPwg#SZXQ~OAk^}{F}g`u^x7q^uqcnkfrlO>66gb5$WTU_Wp9`? zR9Tv0cEE}WJjT%Mr?63kz{8PhYU3q~FCy7^3Gk(cbwueNdbi;vyTcRU^ zd)(=;{b}TNDtV3nJii}t9@v1s!PnOq0kynSJ#mBq zz183EB{h3)SGejwI?zo0XYY6YvwzWtc^u)Ye@JunZ+>il;qPYPUvhPnKFz{^*M8T3 ziK&0ItNsIL} z_F~Ra%=rp)&OnyPjdU90=73Id^ZDX`>BGU#0QrePivNLS@NY`!PhX{ap5QWEgYFz7 z>e7oB#9e@m0X#4=pMHQ4$U4delbY6YRvW^dP{95G zQCGuv!H_-~%Km(@ngKz@GFp+0BVV0jcILx?_u}T@MZB!fbKgy-HGiJ_3MR{OE7SB^ zK37kggH4#u&WN2B$j35XH7y`uA-E+c%1{x0)iQ>n2w5c)Eo7m)Yr;Ipnq;4`3G1#9 z;A78Wad)T3qLhA~nmsRHIv+WgxN6eziEClQj)rJ8ts0g(dF@BH%O3E#4}nf!s~97y z&sJr6K4_=9SeqdfAd#Oxp?PZEo~3`o10dwX0+eTjN27v_c_8t(qy@vbr{shOqz?4e zPLrjlgK$7v%(CNQ<$-J?~1THIQ~ae4NF`3Mfqh z3Q~~dEhNeKP^unO*lV6CnC5wgc}8`xt1`)C7L2MTslHmZBN#h>nHj^lcjE_ZUKfew zjAeGw+lJYCmNEpS07oppE50YcO<#sAm%$|V1}u&P0E|@oO*_gd$h0PK`BKsyJdQ1$ z%Q7xDcl;q*7}7#gL6urHEKs{3NU#tkx8a}en(T+RQV75+KX?T#y(KepDP+Ok{s5%n zM+{83!$a441?c;@t6}TF3o0sXT_zh1Vwo_+AdoK_9t@ucG2lX~aBm!V3QK?iLJCNR zQfg3%g@B6oZh3q{5pitB0N4l2f}gG=ATIfI`v2W1NzM2FmHwg~npGLkkr86|z(Dkr zCS)`F4*-#Gf$ElB4WKgYRnHkY1n;t3(g&9dfuE3`$Mq@sM$2^R`%^b7&bdCT+JS3{6Y@lk`%V#cY_s0IMrzdz1ll-Pc; zz5IT#5~dQYjM7i+^=1xr$MqMLy#~jIfk~p%*wZiP;&L7_T$EbA=Zi_lXZfani`Vi! zYsW6b#>WrH1N5H;0le%DzN(k_u6y+A3`E{@3dV|Az!`!+`6?`+82X?-l2+Z}aOEA4 zetTMub!PI=>>Wkdg?_8woEoSu?t;!V_%e#6Q**5Tt%hc=FB%luUB4wIP(9%wOyeMx z^`46!&~2@Q*}oO}t1oHSn%}X|8S@^TrblC_$MkCLuRmeG&;CsPe58IpkROd-)njCZ z$7={A$I|vGtmJ=T4CnP!9%O{TrX79OmP)_!Tw+4px z+&0v@tua{Nct)_|x5i+PJ;CJdL0Ssc$EEg{iPsPl2ZU(bl2-%x$mt9@o)FM9A^^id zyhXGRiF@!7j?@9RYV`OPsGPryRvcY85^C!}a#$G=UgRCejM1GOS zA4mOV6wX2BK$~@1S{D-J3!IS8cbqFwhVs6uUBdFq0Xll-I<(}4A$3R%mhW!F&!mGB zfB`O96WZe>3L%~lZbJ?Z5yAU8tiTrd|4!m+M%K&qxPPFVf;*7JiscMa{i zb7W&9#gHh|iWC(`LA0|iE zaNBBVZNqZ=#0?@KudkQ!fr`chd{ym%A!l#dYaisRP3d2@b4!Q+j^m)b9K(BJZG*v_drXf$00hqY`Q%dPFN$yVK# zQTQ69io)A(GmF1*OQXFTwIm{{m~;4$b0Lu_Ts#3~#^?;CjjlD7L1!90t>0eXN)7*I za?m7;l9#W~fz7K@P|~)lkEFzN&MP z;#=Uh0?>5m^47@%VGfG2LLXdRA4w5g02vx3unWtxKQ8J7GtgelKt(+^ouovL0YvuU z9}A1p8b zV?I1D{I9Luc5%vOcrD+fRHj0y%(vWAM3p%SY19syce(4vSCubXqz_5qRXj(FA`OE< zBM~x#I6Ko<5FUy}d=MF7Ph_utMHlxn>AU2G2PD^xIG~ zgat9rAcOsM%D|?W{u+)8H_d<%6MN=_+n<$OpA)_iQgeCgS=pDplp%iS zV5l8f#^_bdvKsdfhG-EH*4STPhEV@=yWdA-vCas}ITHj&NCI!5@l|ycg1wwxgUS$W z9?-vR2lNt8gQ1r@pqG4vUhaTi@)3Hu1A56v=;aRRB_E-eJE)gkc8Xs1-x9Bvxvijd z!(}c?57uc%Oy8pP@;GLxMizTCYH13#V(BfQ2lWyTp23dk&d@|*zfW?!HiCrM;zMQ? z1VaZfUdk7}#Hb}^KvzW`g^5nolp;vvSQvJtoh2oZk55h$&BX17gc{mOQRGY}Gk zD4OAkcTs!joi5r1a`oAfkX+gyT`ImwDe*FBzKJ@cFJ70Nc$tbW7N_(9Yx1KN}s_frS!=?KfcQ`4R)~MSTi9QN%odIluZiI zCS{Qdg~}%V`YUacuj)Lu7Qz8e9Ul^4e40ok|i<>pj(!9FN*Xi%WdpBDeAXRDp!QeWT6ZfA)ot2j5}-^jr&5hB*xu!sJF52tuKOo z|1`K$_H&~tw2FkxP*eQNqdn7#l^--)!q1st{z*Q^Y)%-6AN z)&GtEf>IsInxRz1&q67*)J|QU>v+D%g`08HHx=JSkb$=vf*f;%5Crg76MoL_?!ZGh zm|DJ5^~<&+peWy2y7SXi-&8IbEZ?d6Xjh0dcJGo!v$MokCDN&vRO7rMR)RiLJE|dw zfIChghj7{$tRMHHYn%;34(9xy7KNna{wa$3I+)F<)8BjnP+x*i3jC74!Akyc z62Zm&TryU!*;WFkB}LAm)QItD=fK3^fl>r>@A+UTT{vw6l*!NQ;_L~NngQyk?fWXZ zLjfcuw+{8`b*ZW+68t9YIJDsI!HPqkCb=(>+`{LoWTJ0*pMFXcs2=dRLGjiTuwd;Z1X_yk#ykayGDH2N8p?p&0 zKt6}hgaE-E{uMEln1eV;P|C)rHNCm^9^SIAcy2q_#eW%tR4k2LCfvR3?eP62hk=`2 z`Up2mzzQ{?rSxb3)<~7_oO{%Uha}g(daGPRqq%&wts~tem+Gq4;~6|(d7|h~2~L+% zKEYS@6jFQ(k|LYAG-|mJq#>e(4fj(kscV=@uN1k8SHSS$67z7LTneKChR9&PIJVsj z9K~HmW?@%sFbwaATbztyDMh5KwLEt&aq|=wJ;|=SP4QF|69OgS3w7+|&7x!I4;)JL-0*_D^2Lb%vS1+Ec* zMB@IxA0LIrj!J>a=)~BJb;87;`4hALXl%fEST_|U*o$)^E*tHJa-eh)gjJywjW+>8 zjhei8i&|g4X(PeL&veQI=&V~709u$0)$@8pS_23=yu z`|tfw&F>(Yl*xew5N$z524G3{m1~^gdS9gpN$AN{0ng&DkKi<_m+?O~X#9ge498GM zDoLDXpL;aJkK}rS*M=m66#0tYUbM}D5UIRH^M$WxB zO${Xry~>wv1ZXnPq%oSNci+?BI!IZo9i)m+<>xGv5@89*gXQ^jc{8nMsa8)#s}0po z#A@&Un9~z>n=-KZa2Ntda^v|e4*93ex(5(3&f@De{D9d?&{ecSP zt14%4d$aRo%d-o&|f}2$m;@=BfzY_JY(nwtNcvL3? zNT53maSEW5g`;H;#-NnXs-&9WE+b#n&3Mvr_NDTu;_TOf667Y^khAPe!mOtz(7l<# zbm%rb1&0t}oh3p=7ywO94SQxp#1&i_40UC(xsrWadJTU=1N_+UgA7pqGz<@c#OUf; zo@rgUw8G5Qn2j{-G?p(dLqS*#8UzyR#T;em@*9>b>xc0#d$#j&8gb>3nCL&0bXI+b z5-)yR_3KmOi5x+HXAH6BdGAgYIx5-jBp^y4gt0UGzN!H%$G$0!kEAhF`EhV)PxYdXkL-pQIJ~U)^(~Wc^;ZlOHaQG5doA_wVO}sa z91J`!HSGQHd+{^Z2Sey5h+8-lNX2vV%#5(-AIKTB&hsly4)=pH1Jc}_oUOM+#c{ z47#LCDKM7zuJ<&h&kyVarE{Z{zUsTgl&)dD;FRc2Xn020dn$4YrB_mC&LpMt{<2S$ zrfg0eswkc7rgVYxk(9>aq~BnS$Vk_EdFIFmr0ZSvqNM9h^`b^TUc^ge2C0i0csMEk z$Kj;-f4u8aajH|fM%n74qsKg@pGZKI(!Kp8#tSe4mK?`Io4(@^3a$3wsNZaOFdj$-yNp|s z@Ub$zhKRuVI)1}G_*Nk81@~ei3RnDCnVv`9%Kq#-)wrcvvocSe^XBjvQ8;36)kT4)Q^>>U~Mi=7H4l@=6JgIg& z2NVH8nl^sY$wjEs?8Y0FUzFAs3dJQ@lJO+H!UhM>A}|mvvOn=noxp~BV)yvV3Ynhk zg4QJ0H2E%0mI(opcLhTPOoWSF&YPcb(MSxUqLDW4u!fv-B6YSfDr!O^6 zS)O#xq1=Iw{NrwnB*?ybPH{b_x}MX_Gb&_Ru7Y7Xg2FPqhL`!dDu#K7()oEUF`+e+l)B121X!n z-wo#x);_Rki}bC<6CllN^+`>z31%k-N2aw+Lw_Ue%>@+b7oWhd>xDqbpqDN|DhfD5 zm`g1dDW%9oR>HxFd{{GzQdv*dJJY9+StrIJgBvaUyaDyjqUc zeZ{%MK}?u<#A_+2Uiyov<{^y_b}_cShCOHh2f>a~08Lk(4PRF>0KJ9OXe6pF0BGUX z5X^Jq03j{bsKgQLNH2O_0zf?MYb91w^*21z)NWjA|MsBEs#X(VF&zsjOcl7v{*I^k zgeH^`d5~|`h&|5aT*X%y_t6vn$=IE0_F}=jS%rY)WxYOIbplA^5=sGV%}=)u4fgz;m#pLt?fJ=B)~Lpz^}De;<|nL<`INd#AsL$dsY9dC zheJbkLqn@`LThqD>w}?ftSB$?83G~us9MfzI)>2l%pUFT9vw^)fU>LjD-wVg3JPDa zANU&6U4mxSNM1c05`YX|_iK*Gpxvvla_f+!N_9X2C>T&3^z%Oz(La%*FEyZlZh5yX zV&8h2zO$iH-3@`oZ+;TId?~%PvyE1jB7Z}tE6H8~NE%+XhrJ@WS)MO{As`rOn%gHH zkmZ4tuE-tszW<59(F=_q_&P~IFbeh+49mObH5MWit=&+(W-onNW{%&GABWH&BiW?9 zG1Le~UBVs-YM^PhC8X7>12VAPn|sx^a>x-zHwgUs$LC!097i5|xN3NyY8c})KWi#H z-a7#msFh*w@(m6ZHVrpaxbpRVWQOHkAcaVUKl-_N@!CEEeZdWg-9~U6(-p4`H2e2^ zBG^XIsswPJw&nU)f;GmS5F{ZjtomJ>;SXt)YJi>GbkwoP zdv96q5cRuj4N<+XDWWcvc1)0|adB@Hx4bV(Arf`&sj7v%hBs*3wRMJLWK4LPoqeBU zy(m#IT_ptYtL+-Vr+dW%sAPZj#}0s}y=VX&`|3Uem?DJ;;DIgx9fj_IQBrq+Wo$P+ zx;^MYW&DEV+k6s((V3t9bBm|MGWanTm0?yR7(;hbfUNRRXdX({L*mupzFM%1d@G2m zpjt(voVREn)HluUG{%IwFj5&*%R;;g(1vZ01$3LoNojkG8IN`(j<_mM71MGV+G`FO7 zSSkDNQxIh=zU&~!%m&^K7!z_ z;e0^r9L!MDIlYq;!n$EbA>y_f)V!2Mv6bQ|+3=Bl^9y29uah6+=6d}a$ze>SwY}kc zyWO?0C9lBCNk34=j1qYnv1TxTEc#an`}}Gy8bib6NY%=57{bGi zE`j0{+@pX!9O{Z#KPEde;Fh#v+V7nD3-+|w=RGgbPAI@i_lKfg(%AMcj+>jo_-Ic( z-Ut$ADL(!>}@ECfJYs&9#3!=2%JHHRom??hOg=6^r;?;ZOccS)>-XD3p>jJmD z)!iA>ey_c@@0;?5k~eT>EbIbwEZ2xm(R2lfz3Uj4=ma4;JD)b9Gm@eM>uN7cR(Zfl z4&s9gLClqgJ$qJZ(ZSlUQ`i*eDlE@}SE592S#+K|UxfK|3iFqDX^0Bk5K)+~aUjY` zKV1oP9}Q8wFpo75L6~QVM2RpT`C3$%A#E)P^IriG1r#z2lZ*$gk$4hRM3|+DH2cHK zCc2I z4z$mEmiBp>=a+XLO-i<}`pfP{JGbX=jrLzJ-ri`}dVXrOM@;*r(ayOG2}9=miv6qe z@$}r`NZ3)g8@**u^#>fY1yf*nQZVe5WH)|{1TY4D`{EB6T=}Z5LSHHv@_cjwR`^+- z$Xr(u8A5(9TBN@&lBSBhq>5Dkm7$q##miP6j21aa7kRg%v@%^4sr}K_3I;lHe?zp$ zr|&DkCaEH0Rgv496zLr;GFKPrrHTwyMc(+%)k+FmNs1OJ(M7(2*8uuQsUpYCcNOul z$ouOYiVe_39#BPEt0JfW!=>LHW@c`Hx zs>q?oaR^5fnSeEQc=qDCN;dtJ;yeztF;J}7>6v&Fdc7~dj~gJYZiw~}-eQ=0>EG1= zmWaH)Ob)|=zoEU#;4vNbU$#N6Nj6G_`(U?TPJ6hsAl81IssTJr0L%&<_u)^T%q*gHbkFPD^zSaM$(G zN`>Qrs;<*rbuokjT&-KG>(>`uIEHjxkF^&ZcU=<2k=vh8*Mg%Az4Sl_oU-m5q}tE8 z>pD%>b*ifCY*km-b0ojRskh;Gs6#HKKJp#TQSJ;*aa%XQ|@5f0W{%tZ@~WZF;BZ;yMxt zc{d5W*HZr_ox^fy0C>2L89_I|NUA@FZbQiVKq_^3*^vIpwYA~OI$+V)IQrKhsA=P{Os z49XN&$a|$KO|sbsBy4-GD*ZG|dq?ZG(^cD*sx&uI+IGUyPRO6enY>GwF@6cV_E zYAF3o!qU@JX-i6f|F*)rSd}ioM@91_du+neH>%P%N$IC`>29j@Fs8vi3~*R(oMUq*LHCz}>*tfw77 z*ss0tgy+KE#-$3+Jir4g<*yS+A3W0qsdyGhDy?s{M{R#wo`L%!>=h^cdoV^8)AS1jh@XWv=WD*A; zhE@nCPnZvg-ViQ;VC;xW-zaG5dG%B~*VILC`}GnKa3Q z01s3-^n}17Uj->wnd*q@j>QVq9x~*sPz`&&;#a6|^lZ|Q=j?yaNwQbUggCGbd6vD! z{-dYQ{qa`$sxRZL@<^K|;Vxb0Bo17LyhHF2#g}EciZd*-kBTq;(f2HVjxK(rD!u|A zQQUv4tN5WT{{6c zE|>Cm7QZ&W_`>f9{5`t3T!kL;K8ueWEH!E&{=}Y>ixGCnuOCd4etIfQ`P?mYl0x2R z@PF8w!&=}|xL^njn1hcX!DH=QI3PqxvcLHvjs#B#5MBYI1bt%fLj=I`4FAUvRHSA1 zXFy}OyHPj4Mpc1oid1K;bUUWp$E8S?_xKnhZ2cQjR&(;o^8U<-!y(T) zrrf4dUW-Xt#FQQ?B|j$Rai*-q(au2iyG?GARx{;hN%3xy6a(9hOzEOhw#TH5WJ*2P z>|5R$;_XbCQP5$r1+WAPEtHM-?$+-fGN*n{tB@DEhc4C52TzcDc<#8yJ@h7 zDLa3WGS5qjk*S4DsZlAFF)5EQWr#|-^Fs{*n1^tf%$v;Q$j_*fOtn0|5!Zw0Ou33F zuS8SMcT$Ek<(z0rZzrXf)b^88TSq75FHFJAvuS5bu4(5FKT^6!Q{Hz{zGlh-UdW?h zd)7%=$&?Y%l#rA10#h2cIc2VKQto3)6;mwl%^$eQI-V(8c$qfa;SvqI0H5d};byvb z*llR75KPDxEDNm@Bu`wwJG35f4G9V`9=fjcGR;8rHq6r04-;^h5cH_?cxd^LjKgF&NY?BBCvrjF-49yX=5CJT+}TpylktF3LkVFlkC4LeA@iK z$EUnmeBQjLDL(#0_^jUU#s_`zBzt&R_|xa?ed5nE`zvoadWOrUAf!7}OOC=BEoD0! zOK|>cAh}|ruV1onW?ihb^{Q*wjDJ5s>g>ClVm0h8g+PqdT|0%*hLJkyg_qnZSY37& zu*!Bz-T$EetRB~#{v4J7lQJs-CO_o5G2t!;``M6SGBanN`15D#&zH^ObGGO{%rpB@ z+8)fGmH?jvPjTbJWl8p@Fln#{ONak2!e^4`N-RDb!wK-I{EHhO=^C_G`20L2CDqZK|%|pOO1d+j>&Nu@drh9Vv*c^X96V8(~_x-9@%RjHC34A zBa+9s)hXV7-^;#8#iqRI{9rKb@<;h@f0QqK<>jzAvuFZ732XR^F)Y6;wWJFpbo2~l zTjfAZ>N=BNyhsD<78^e2t|8bDoHac{pY(o_KIy$}H4mh=`c7!eNx(izRAtDPU4A~; zH@8wN9nxq!;P7NYH+!2BYM|Kwj=`R=nA`dKPUKJawn<}ERN}08zI43m*5E`=9D|Lc zdGs;Z!D@XBHV&P49fJ)6=sE@)=a!gbu(6L4i<04^WuLFT&f?@&F!VvgbQr=fM73f$ z*FThib2nsB$1&2GnYn}BH*SrYCoh{FGa9C9x*bpoV{jh0varh(MjR#JrzQO@qKEx&UaMxVG)FeJ!eOrvZiJBUBsMuR9N-ReAO-X=J@e^*Ya$?4=yF)N~dJr(; zEzArRyg%51pSg0rX2_1Fu6YG1U@h%kS8_+Jy zjRj1=7n0?|7wd|n_y&pZInClrS%n^G`2}tan2bzk*iTfb=p_^Ow17gY4jBfL`J$Au zNG`5SfaK2-hMG8xW6JiAWrF0oGl66eA{mF@pDCXsLNWYIET8v^cEuty`cXGB6h&aY zS-VD;E%hs8+7g*&>F;5@mZS2r%jDp0!80)Cku132Q-h* z6eWL92SyT*KWK+b{+jkLaZR8)EgOc`6?}9{0A`1u-DKw|A;?~&1_7o8jjmY2l=`pQz)N>*TYX77Hb)kB#0jUx z=_dul{W@|NK#&K_77op>^HuQ7u%Y!E+wcgvtO4jpC#Rep?vOkfXOktjtsdAhWnlHl zj%|Zhn~np+oe!PI{VQuqPRR*%=s2LdI5}lN^(Dz|!=68$eKZLNg(YKQ=t09m{V-(^ zUFgFFiW4v#a*+>1mN;~~4YrAJ2y-aj>2v}NCkQ0r)39YVJZ6WgB$&W(rO-B3R;KD6 zp^_ENgm&5uyJSCoqA$9wj-XDK6s6~4PJFo4PST4Uk@n5@Tj3NV8 zDlbODUaO!q#Ul62wgeJ(h4w}+r>ah#OS-KpkSFY?+ zH71&4{PwW%f_(4Of&4+S$T!7*j>3Q6?ZGkTsQtBt>ab=gnC!YAh$sl+n;XN#U&@=} zQF4&#b16L7=K>xlJ*+sZm?+llj@t!~>rVq7gB?8L?88z8|GxXv5yC&11x$^gEZXk8 zp&J3>u$k#f5Ro)-sP??xvCF5$=gOhYE{}Rp0yNLaa-+#D2tae5?u05d#iKrao1j_Q z4`?3lpy^0#9KLrbeD|GSKCI_NkI8Mj^UIntysII8QOx`vGy!TZeaI9dCh!zVRm&^L!9Kz^A>nz2sO%b7P$ zkiRb*$frVp;^c=b$6=56xqs)Ye2f%Q{vNT6^7j~)fWI%3ly2yX<0_1x)n_%mC_;hd zMc0A?I|qh6mp}O^PIv6ElYTdA5PbCC;c-@nJwx!F9vh3xcT#m!{|>$#9vedi_EQHc zkBwmnnD7+)0ld=;0suC}W^(YF)$lUzm(@i3VM0@)y>M^>qFvgQXt$OK(ekrEw0B+3 zx~VxTZwixj6xtqaJgEDe>MPHwu{F z^#YhpfM8U-C;aTZol`_?D4{N8?B13y%y|)o=xR?r3nO?>=%$`o1 z1u#S2%~=$B`ze6U1+aNb>`|G(^?bvUICyy;G~mr3yne##Crp{a5CMkAXU{?PBaT5% z`*Ua%GXP#%Q)>ircG5w^ODTF8lu1J;#-#nTeOwv>B9nG!Y+6M9 z_zqGKP;QH~yAivi4R%e&V{cIL7r-3L_(k3$%Qdaw-6F zXCVZ|zg!ay72#!kCT3fFawt`=mAs{@j)V*cgSfy5;1%NEc)0U*#gmy_T!N%LB;j8X zB%&04{kP(iCFwXMHu;A&U=@e`EO>6>4AeSEeV< z&u)s;FFRQyKVm1D=&AWHzW(_98T*&t+jB4ZWATj~x1aeZ9=m__zkl3b^2cuQjdai4 zzx=1+;s!%X`E8k=WVD|giHz){3dY$Vi`?2L`y*Y=%WjCXKM-qeM?{HbDQ9+Uri%Ks zSc4*?N}ZfcaR%kxVsR65*s?HDD&CxWF2)IF4^X=XbO^Pt;v?ZXM{ zCDLOvMjJLm> z#1qHX6~+?JI6*&Z5z$*mk3A3loeemDbHT8K(fL8=z9oy;4Gsfi&!nKXSchn;iA4ml zNwvrAAA5pg&BiDDLa%p|Tc(#R!m7Ql8G7A-_FJNt`0@njDa#@yneoRl`#6|AoP}G{ ziu+NvN>Y0{Ym}6ufGmLsl%uN<+Vo-k^OAO5NL6`E`pB#`yX`!JD2 zO_MCK5*3E=nrdHp6wo^^4!v0W<(pEO*xn}Kf!L|juW6nK2k&W?2jV;E8SOu=HWkD% z%HsQzH3HcEhZ`$9tX0!&uuf$~>f+EBfGO14jLG*?Yt_bWJ4>o0vT&@fk##|%7E2UF){UBDnX(Q5$+zDmSu+LgqP>PW)NJ((_Dr{zqyyo@njjpj zAN$~69{xR!?662~|I&(NpK?_*WIqj1G;c4*-46YXmwk{?3BO!P;@C>tahF4$-ggf}9Rs5Iz_z@t`4eF@Efe{Gik~y2ltJ592NXZNRp%h<(v_mjD=|q5LoO z9st^>?r^aZdhCi{?ZcfkFb5`;Ra7kXFR{Nn9BMO@K0l^C-;~EmvwgNHQU3|hIAWiN zU#v^pSO0kvRx6N}E%?tI$r4M;uzeKZmn(x};olc}wg0VodTsgDq{Y#z_OSmI^g06z zAofD9ZjvRQUcYuvNH5=%XB5BpB4Z!_V(0=hgJGl*@L|T3ydIzCGBYnY@~6u|W=*+! zW78_?1CDjEZ*|h*_;5V&XlcK|V+qH*Ao_`XqOWo=veO#)D*Lja+!ja~E`%)K{(pFT zA2_S#{C|8VUEOG$8;0?xb+d!X`ZH0?P~1{ElRHdgO$p=g4#Lpf42sFjRM+VcLI~r3 zY*wE|vcjac!cu9GEV35o?hPrDqWL|aulM`hd(NFZ&18Ll^Pu}af8Ou+>;LQZe!c%3 z%CXV79u!iqd`eo$cTYycrieWWW7K9e-j{ks2b$<_H2%M)7$ygavLDldCKF_l2p;42 zbga%=k;V2F($83`q3uF(l!_}OB;L$_EVBQ63^Z( zVxr>NDx^&-CB8&Fi;Ej78PBH7rdb1Ns7CS=zh_rtc0Zdm(7(8Qz}Q`ZQ-akHZKS~; z;pWRLS{fj4jBqV)gewQ~JD=za_XPV z`u?{WTvWLAE2aKN|6~2L!`|U{8~FYCNA@p>BrfWq@^P8)w)g&?M)vnZE;bx@B@MN@qPC*Cn3t33^u+Zn3eRu5rxA*VheLwxv z9sTEbs-jPy$9J61aJGKuu_2t|@%Xw={m&W}!q<5tVj0W*O`joHz_BS*Z>&32bM;C;Ik0=%J+!t;J1FP?Jtk;*$*>}AU9m{ zVQfEa>g#RH8{WG_XJFxiydytEv;WOz#gBtC&M^GR$KY6+74BkpcqW%jt>m?RIWdYs zZf!o0H@ucc*$Y2^Dl_fBXDu^g_w-u&B3brV7KZ%{nlQ%d`(xr0aLpW3hL!(*PegEc zWW>AUceFor+sXbKv-M|8u2=kp-{5jX#PkRgJUE(O9KoNUX_XaApWuFl@&hQr<#93# zr7D&nX)Xmo5JqTtA{2oCi*jECkK6>a)s_Lr*#o@bKm;uK-{=qMJ4ugP^x2mFwcvLN zY0>f8b)f|mz+EatpGcy(ln|PDdg&zLMZl!kSk zwO9O-qO2L0J)w+Rp`vx#TDeE1iotS$@)@j*4-=(6K$5atM*vRoC#i_jZ@+ekA242> zrO&+GveIXK-456<4*Q~5!2*iFEGz3(<61AF5d<-VESalaV8gWyD+EM|t2*+hI|Ls< z`|aRs%=^vZtN1P9`%jNfz_;V_4`cWLRQ?GyM?iM%sI z^5K0EmiH~$-rRmaciu6Ti#ZnS9#SDWfaTo24$0fTyi41cMTC&JIUU6DB(PI!2R^{6 zhK%;rzW2X$2T5O&#Eq7~4(u;a*3-EX@Q%3>>r-F;#yf^`uKLWClZ@#781$RP9~zS< zDfvU&9Ll)s+e+L%A>Hir9`vd6Gqv(P2hhv}Z>R#Y3WJO~9m%|`^S+cu$%QfLg!T%Y z7yI}UFwQ+ekmUlAG(SBqfPe7lM&A~i2SCRag!u5$#G~<{3BbZl&Gw%7d>OkUz{h+{ zB9R|R$KWi+mQu0iniZ%qC_MIUrY&jI=r0|s=Di2`(A$39Hc z>WM)}kn1ba?v25ywX<3JY3wq5uM6PFsuEc`$3)~SSc@R3r^c3Ad?|cLp^1$rfRc0V zFOHTKD@UmnE0tKW@?q>C_E5ybB;(6c{Z5#Ql@s_1Ny?k?GADiMoZJocJSq!4J2Bt- z2O*u#4|1si?1^`bF7xDjneEt&w|53H+g;DoHvVcW-|XL&H96L)NL$)sM4RrUD-4S} z7sJI*&L7!rmUyod_#Xc+k3MC=mkAQ*;FH_I_v65J@x96~zhpR6P0c?+rYNfHU*oG+ z;&_BpRcL4d4_JwlP;#LcL#lH=x?>>(TPR4r?vw+bM4fP6NpyxhKc(c^qf@F2A56>w zg=Fd25yM=(A%^~Bj=U5kak^)|RG<_QKssNS`6f}@c%U#FST@w{CBp;V)D_qq=fNgp zylqT&vg4!OkF_snH(T(IWp=ejcjeVz$@vkcw>s(z&bn5#X$kbTV~iA z9Y(1d(;F~zl^B<(8PZsKX&!9AaO57^TbgHr>Chp2IDWx%AsrKY&Z$_QKu3Y@d`t6W z=`C|a_35!(Ie5je>lMRvghN!sF}fIm z1_T!a<-Z^Zsk#a!X(+ufwd2g&4Q^_$ySZU=Fv+SwzKEW%?VoNfRwn?7`A{wulC zLl3_$2*YLB+xr7tnQm)upT{Ms>>Ac6LlUEc#~bjm z74LkyfBuvdRrAsR{Q4J3>U8$~#`W3X_s@qWzTTi-bBBj*=EpPN|9;2b&-O-j)vF$$0|(SqcQ-;BwfAKwNcRnDo$`s}bh0-jU{$IgN8xOP|vF6m*d7;;1wIZmFxfrf?q zrvhhrNk-AmF>Wsz7X6_gVD7d%zMYRwvc)fIfQt}Ct?!j>a9Gcalxa|{zT*ascWO_Q zC}k*CG2krD(FI7E_P2)bZ&mJ(i24xh+Q6m_l=iWP7g~|R?QD=j(EKI-|Fz--765veWWC(91Y)%Bzow<+pE0XX2Gg`JO*JeY?+v!XS`mzve4< zWYqAr_uBT`OT5+=9-n-5W_*x*%Of_7hY-ZML#gGdXBqL(-5cA9haPE<|Jl}KrWeLB zfAK5U6CZ#@7hVsZWrx?#Scj0wZOeIo131l~(jPzW$o?DA$5)SbHAU;3M<4Ha(?eJ$ z>Y$JAXpixPG%zvMK!&RIBZTL9Ba5v0vF!T|A=OYTy?zJ^1EFBjb~OIK1`nuf?QhgH znb&|I=pESEmIytG1q_))eGV%0tTXXDfL-YU+b55|YCQqQGiuF6g&Jo7FC=CDm-R5K z*8|9G>j_fhTa0%&2i@U%9hD=hAgu)^p?Xycx@wk$?J9!=RG1yd+sI+bQ3(7ZHm1Gn zsWu=x(xr!YP zi~MtcC2EW)@=y7uXsiCQrh&@I4?C+37cl?sEC$USbHgAGN0_*RhVV)cGX=P{nEjU) zkSHz$JRQ$}cbq>L_(b)(q)->w8x}%$UBma~8?NqVkmZ4IK$iCB3oh@__c1XMb@GS~=dIFZj1dp!KLiqeg>-8DlCFA*36WToY>FfCO{rt|D z&+0z$C=(}as`;$k)xtcEot&>0b4;0KI;;DHcR0H82!eCU*Pv)z88;0-NP|{zq3 zF?a0dE|Pt_`ZMJ|{EW%HnQxi2PV^5dUq_X%GcCO^MQu=oRMM0-y-^Dw${-~&GMs>^ zu(MjshNbJN59?WRz4KrJj~~Z}w?wM#Uhh17GRpfGIv3+qda?$7PG()BJlce35xQM9 zw4h;0wgm2#O8ow~t|asjO{rw(Rcxq)Z&$MfTSZf12d>$br;#ZI3i3Nw{MNj5qfY$d zi2@Y=upBLL=jP1<5zG;%O56__UM*$tKWYcw-u1K`&YLdGME`qIGhG~re zh9Q}?z^7<=54NFZiLX&`RwcmGBQmmSUV9JWS#KUcC}d1N z0XcUl35jLK=P2UY>X)<23wiiI*RuikinKR#59opPFa1U3n2MCB0zMFiXhR&rWKK10 zNQmM90!x0dmXb8^#yXI_bc@j_UnOXI*J$F3405>=^uvtu1oT+C<)(|G(4%@h;%UEi zY!T4#ncX!~79Z0REQ?25K=>m@K9o~t@81H#?_L(~2jEwjaU37`x{PY5sbq4{nfxN@ zCSrcwF8y%S)C}D+ggadS zeyQKT61ZYB4s-Gz*nkVc8x}-BeIs@-8!ug0+a>uPjbwz>X2FyKunxlt7C{)q(vTdf zd(P)yz|T(djCY{lElR&XMQRiJ-NM%5bCjGxzeV043d?w(OP{!^13$2eg0)N5QPa{q zf)%4m^9zJS*{U^7s#_zvg3`g#6r7S3{ zO^E)4zJ>b&w_v@93$L3dy_W_Nd(Q(nZE?d!u5xJt#LC zpTyUO$Ga|X*s_b!C>b6r@ccMhvL&@6=;VS}9g`>)$!RQHfw%cb{aLMwQeNwp0iDC= z0C_!sq58s_NsC)>32yg;)nce<1x{rzR{m-H0ph?6lH*h_NvnRZG;%Hl6!J14N|D@} z+RUyXNcbuY$nphUfK?Ge;93m-3Z1GmxfgQE-}%5ji@DF1s6Du~Y~kh;%No|Vmi68o z%>{S_tz$*P5oKTH_UP8~ z($z-Op1Hg^rqC?M%84o5vR)qlS9zbe%I(X6+%G`xht~4mi6|IR&xg4QIdPt@sXV@f zht8iGACns#V)c5p{Gpsv?E$$%n?8zNaB92F_!G76Z$__C>rv9P+^&Y?e{3{7kBif+F^hvju4m*8v{qjFxiRG-zSsff z#*NRQ+SF*8YTZe-#NS~K)5tkG*7_fit3`uOjzaEI^>cyzkh~pgBn;D3AVxNcX5xCf zz9wthu*E*;?{}Syz@ZR|iuHA5QAoUU6v`2HR^R991BAMmN(anjMoSBG{La~E*2=%? z6r2P5ZmgdfZy*P>VAE?!lIx@*?8$5`+0H-lGs+D7Xt?a`waCSVC05rZMp7 z1UVt~LPn4?8~JvujTu?naQ^cN{Bi4M&q``F_dU#JzzRxl=Nk;YB6$2M%Q`G5h~iUL%N!%-%G)d`;ZfC!5^H>G4Ux zW<2EigFmnWlFS1zriOE;)< z5F}37jCLEg99Y}Sn0FHPwbveuWgo@Fg_?aJ9y;G0NeC3Q!0j+O)Woz-LJ+>pjN``& zTyic2LdH3Hr%PFuVdg*a^QpMMXQ6Y2{+c^{IydTharcju(KScP6NjZn$`R5M-rFp2 zS?U!hJFm;ZYGAw_0cKF42iZaAk*Ac4tV%wc;`fZsOIdtX;{KmW=)i}UQlnmPN26wF zjdI0{`Jbg=~j(k0`nahWhDlwomt4fM5rPL(v^=Feh>7>^5}wG7^$i z?X?SHB$^?Aeq%(#LY1mcOy-EyR!deHYdU3zr!_^CaVo!SjCPepr9z1LJfMv-vPNbmlkIIQdN@eJ-H-pt7sc+cT^ak8%0c=Z5t1pK@{3x7p z+t)Ij;@2!>%CZ&`Ns2h9Vl1rZOpL}_c}ct|vWK81^4P%xoxj~l@ph$IB)J%Gy1Dt% zWfMnIF-&9L{$1*~)*B69L8^^;AL(5s5x7UAaSSDWYo5{cmT1wl{l5){Qe9oaC|x=O+G5{e-lrAV){a2rMd* ztEj^8aDjfJbGqp#);RRlPq5B&7T-avYpKH%AUeQb`~k=cR5_%tPMm@fRKwN-W5eYV z=^LqzZ;s~f#dFa~WcV_*iR`YsRC7gaE}XTwp9wd5tmYmW@=1)#VS;ll>oDP$4UR=p zF-_9iQ#`P|k>3WE?g9(aQY1D2auG7)OYz0gbQg)sq~SDGc5(i4JJDc>0YE}YP;*c1 zQRqXQZ*Tjq6{L};(z+s70*k)3#}c#!q!p*xx~ZKMMFCbNJ-okHi>-!!J58!qsCK(JCrwwR7TGIEE_3d97Y5^FjFWr@ z!)GtX9|~I$rmZNTtq?w-SJkXD!eWcO-M};22BW=Xi@!eiM?_d38D#zgBu%$Ig*gcA zMIa1byM+Q4oV|3WQ&23XZ4!S_$?h=i$~op$E74uX{s?38e75KNo|>{Nh`Y3X6A`L{ zeVce5Y#XT2*R-y~9x`-6o+>?4Yk@f?Sitci9%|u6M7}2(3w*fdL)!=pa?m_%s0>EO zLbV(CJx{jjV(a|=7A12*3P&j0`%Vr}%3QzWqo*6W@p!-ew2j zAxMK3wJO>95A8v@qk0sH z59EMM>6AC%mSi4b%}GCSK3fj*tb>|*1vY~|{F)T_Uqt$ZNuRJWFYwec59JKV9gpz_ zZ!*Ii>*idzH&a4O0u~<`iLHCjXZ0^CRqv_lk4g32q+9A;U*-tyypU9I#cd6rtOi@1oOdYyeg^yaJHC_aBWO*WfA6M3M_~}x zFG1wiNVIoJZi2SIr-tad&=$T+|3G{`wd`!`MZ41}0F40cBi z%zwjXP|2s`3i5nuCDl_5dj*F+R^DX1fH~6;A_B+*pu}y+K;EtALno~K+xQd5M#sE! zq_f&G9cSZP1x}uL7qCY6tLi!_>vQQ%~*_1-0|u zJBu*!+4b(T1ipYI(UvJ+{-`}Uc0!thBaOxcBOuZuB(%81Xq>I@7)?AmQSR0nO>0n2 zEZ`$zmRzCXaAn8NAGM3uH;~BAXUq zM$Nrhlso^b|9i-cuLo>0+a487>k};~%z= zTp<6>lYi&(Upc!_3RjZ@yi=WG#knXMjlZKfH*5|VO}qF6dzjI*Uf~2727&hK0x(38 zgG*t1hT3NfY`O~S-!j%jb1|GO57g00Jk`qivFjE3V`G;q^vA`Q-%;Qqv?7rW|hL?;@E}SegbYdIE<90jx0P9ws6`mCj&AV8=Kc+hDN21 z&<0CFe7Tyi*RUtlmB~$6;MG`IPrP7(O<3THb}jHN1TWS@i)!OF(Q=jg%uxQg}-2DJ}Z2I zzLUiY&*vj>p;B34z>(IERb5FBS3kh+9OnS6V)0A0NJavCx#YgOVuaDY6?OrY)Gf>g zY{GV}aK3`Rb5_{VHuTq9;U{zpJ7k3`6Xy!fZLP4v_E%crr?m0gaVvb4uK62TVH`R8 zKU?9-loj?#S#me8l!+C7=|9<|ENz9WQdZd4(g|I>Es4Bdm9?eZ#If26S1BvJY$2@h zMhw(pCo}A!J`WikjYSj*dsw0DVH~3vm@6?{Fc~s0N9Up|f;1zkn6TsEXng+a? z;0oZEUZ_}V!nIV9;a1*~L&bAcA}r5GfWLDOil$lVWg1;#;Okxa01!EQ-il%Gr_R9F zfOUZf>;HitOsoJJ$&ZCuAQx)D1z@HT_VdFzl5gW#gcDGdw6yPa9(}bl{CJd=eEa~G zQ@bz*K+5K-29GB;sR31KkAo`+k}yWr6ELlTdteN6te7dSXWO_aGUlml`czJ?;(-jK z@Bjkk&fg;krxAIIk)WWuHG z{w`2!Kkfdvm2s(iYW4d%8KmGAnwl%XLhP9E!8!%ug4#oU@A99-TNaQe6tW_=E^>*B zVto;Ea^G{`0~x~dGLQ^9eRj(gE)}J@L_#2sD};baK~SZqT_yXC#C;XUO|>VPR{z7I zh+VMqtLa8A(I5b96A$*|18ZOp{;2dNCL5f?A4<(m8I7l~iXC_o&=UMclV!r_b`3R5`Usea zF#w`;%}qxW&}KZE+7(001q#fDr6DGFYsz>i*$Okh#*BX#jl=40OB@FI!Su>gSQIUb z5Or;x0;VK`@&K2MqQ4iy)GFPB)H1D)MbT8rlS#jdEPaw-bvQ&q_n{M(b9(;VF3iGNy|zl4t}<-(S}E_=6k)BO zn)6bPenP%1I85@d`WD}8r9AA#=#6P34NEW}0Pe*DAkIvoicjk{86nKl@rB=OfJ zA1Z!z*t=IM>}^F!U_kOgB_ee4;Y)eIbPtjbAF2zLeBk_=o5pB*4Ht=}3={vCp^nN`To zA7c_cD3jpgk}Tw3@#)FygLDWrQM+q5TH_6sP92G}6YXK9kQoleT`tMZ9+2=AXEWg=FNMxN>$_ib3SU&M7tY zV6ysDTkDEct60&fJ`zoGK=rE=zmOx=(Pn%Y8v0|%3j8AsBwAv-n(^JRa3*m)4Y3$K zTB{=kAk|26Z92YG2=ZEmG78B|`|pHbK+tlEe~AYC@s=Sfh*bF^W|-U0@B9VCYkz$w z`BH{)ME)PIp^Ha|D!~E%2|25-AYI(B5H?+65;!grOPm}8V+{Nod>#T_xHwMpBKYnL z0!*MksfD1FE}eKTjKj`D`6WceG1yKJaB}{bQ>JrRrOSNuGF{lf7z&X zM@@`VrU)$%AzpUi3wg{~837z)vK(jS(<-(>n2GR`!I$DzmK}rXsAa&-%Fk7alP9f& zOrQ|R!KLSBq90_$sokuEGtj%6Py-QAj@qbp=yTwDf5@2(gf23z9tUB)4g!zV{*@oq zqTLq3p`HCJaTRK=kasu)vIGCoC@Q&uZ^HN9f3IS!Frh7CsMNT#FHW=r&uk#w-0Y+f zrg~Sm7Vg)msvu(of@E)EY~&N9TP{~*grqP6L`OpOI?^UgZ)-AQq_Bu2!L-y9Xe^+J zNN~7Kg2SD~6h*C5Wi@$8S;J3AP~IgG;EMn%b_EX62o2)Q&Ux7QFtqO*L$OP*bk(@w zL#FPzPdPNSyV(fT#u{Z^b`)_LWs>?RGvj*WiPN%)JY(0f z{dIQ;%v5)S)a1}Kd1~mV!w{NrNE@~DXB^3mlb9nqd%Pz!t4fDv4g0ImY!Q35^M;;~ z3e8GXXm$Z!K+=(+*^NrBR9tq=$r6`c$e%dlvQl|b;<8eiBZB1;x(mro75*Z2trr|Y zX6WP#`_DuKj<6nNODq<*(+}2wQQ2iWmaGC)&kjUX_Nt}Fp0}#`R&TsjJ1DlhrWInhzoK8EpL-8eN=NE@M$?NZ>30#oJ%y{pB>clg z7_tWhL=LS#6GZmKZ)32^g!VuZ^ZkgT$PRC9pC)*rI`KGs<&M@l6nGhpFG4hd3nrx! zAam@*6qZd?NnBOrLRygtrG)Xa3obDu)vPaf!X@UU9s&StCU&&jKB`>b29Ys(sxq>O1dIw7E@Q!GvdKZ^d)=74AoisQZ>?K;xZA&KWr)ay!`tY`FA$| zOvrEtDms1(Exhc@DVAa<(m7|Bo$rwJcX#-!9{56YO9TI)d>6I09dWmiRkBM_NM zd&AQ0(IdF+VS#>TE=kw}b-RkO%;K$I^L+_4>_=}NSS2ecN57OT{iz=pO) z=u2tKXd0|9r9GqRXnm>LY%0WM!qyEZA7}H)hveUT<=;E`Z(^__P(VKHCwI6NP6~&h z;1%GvF#t&mutbgbV--tV0Y=o=DFLPcbnaCVbNOhU7oZQxmZze`qtB=Ob>jVjmi zXveQAfaZh594Je63Rw>2g7r2EJMhXa^fxp$>C__5V@Mqb4SmO`e45yMdhoRn7213U zzx-pFww`~P_8uTw`>RccwlN~yYPEK=L`)~NP9qc z$J?|Wg30OeXG8~IrDMW$d~p2v*t$LtEJ8jGmU%34E6870k^6A13#x{2=NhcMBNP~+dXlQ;0F z-LLZSM&ty|QBL^Bre~_6AW=bhn)v`2Rq}!zGgGKKb^iPm2>b*bi^@Z1(3e{!+vGbd z$Crx`IyYUJf&}EU@}AvO`SgX-h2%Ry6Z|(r%QMGAu1s@CbR#Rg8>>y{MQ{d46rja1 zda?6PyMYO9=I_7>2$FD?L9EN#Fr(KZ^ai{U#!3OqCIMKbgq&~I7ZIoCRE4=aub{?L z_41sdqs?euMhkT|S=#xRmT~iMaBpnZX5_DXereg;E3?+YF{k8-1o0JiBS}*s| zuMz_D>aElfoGb7}>IukLi49jlKnEci6ymRyAK0CQGn(XkCvl9iC}c{$JeC6@m$n?r zTBv4Rp~GWQK$l>O23qi3DU5if(Dc%^!g*W!E744$a7r^p2hecPSzSvsfk$E_N%qs@ zAlW}P$uj7r&lmR7YigsW*Ye9U=yj{D>GeYDNp^a@7gF?MBw}`!ULNX%iMC4}5j2-N zB52Lhtfre7C<+?u2u*MybepeVt8nh3n*_gvZY{i>g>KE`T)IU`w}p>^ZreRy*qHn* zn`*Nr8(SH;Y*-Fs1ATDb02U4XA%-J~n04!m4FGXwTWGprhC*mV>`?&=&VLuGh0Q>e zV@??b!im7UU>Tm+Iz-+CUoG4wRzNl=r!h!-RcwY0S4+Y3CO}CxI*CVt7YEriLhwpI zZt{*`InZt|Uow6ma1GOU7SMN!T?K^TFxMaV{9Z^LB;0UovA^HFn$XRrt5GB!^vz96nLEo620Ey(}j)RGGg^PWq6foMUA{at3 zy>Jn26anu+l@w+)Z1Y+ge&+-w@X~Mr@4+96K|tchZ8$|%)tqzhBOZEY;PWXeW%xtj z1Betp&^rnNZq=~FVB^vs6gQOlAUAOH+`HXi2B~GA0I(E2o-2dkLTw^6M#7s60AS2G0A?#)dR1}lp%qdxUFYW4^ z3}3#M49_wdK2IJ{-n$`!!(@1IGYGw(CbZU~41A}tWB+Hz?V0 z*AgjOP<2rPBbbK*_rqvWtVxj+@C>3V6U}-qy2P0Z-$EQC3>WM9I%G>PTbS?=U_L7i za|XPU9M6Pz_DBuyX*&w93tgBvKupAd>N!ybv^!FQVRBYzXDVX8p>val{?bzq#4|HUog-RXiwDaN!7iW+_s8S#*ORj{K^w{~2 ztY=h1KjP~ zFZuqG-@n*_Wnb&@+HL1~>@6todKg zewXk)M9y~p_&?I)_@-qxj!@GwVTyi)+$tdHs~K_?(P%@RCKT4GGe6f-zt&T~);sqv zW)bq?6Ht`)07&_N|Ts6(Ep_Com_A7&j9^J9W% zwb8(pEoOX)I$9OmW&uVw0Ntb85G!!SPMid6F`BNHm-g&tf(&RK@%YVK)t; zMeG5s-1JkRJJCXS#0Y4GoJ2p_qWAg&nj+=P@QxS;glW#23J+nxPEDAq6k$r#d==mv zL-)p+tJGxGBcQ#zk_nq0|2SMGeWI91CRcd;k>@ld=c;{`{6U<+C^}0(S&Y+a#{CiV zpIs0}VP34tv?X4|PY z*-&z!^UFt^!eT~ry+}`E;b!@rQJ6ylTUv@HEnbV;$iVf`lRy_sYvdRj0;R#G#MKCk zoH^1UK3Q`&gxk6DZb)$%O0M{N#y?S(_K1%G>7B`lZQF=;U+Mz%?VB9bIXhfOXFCSahtV|kds00Bn)RjoAt zv~N7rfE4Rkt168`y87p*lN73YrK%qJ%0r4(+eiv^Vh70}-}7|s32smakHpTG#J-}I z%FgKfd&`a(kT3BXhZeM;1lnmmU)ckZ6D=a3U`1k+cn(RD@Ldua6+-N#!0G<{cS29> zqc)o6=&_2YiNu4fO_5J&4?DX zamUdelP?2-c;R{7qwkoH7|-*xi~ZvV2mv_#IEexkfb<9teP$T9gu&3HE}nzr3zYt$ zORz3Ap4fUjV*2!X+83GbdI|P_Hu^`ku^<(E7uu6RNrLoA%Ycy;=<&;gFfzBVzy%fw z$O1nAJc-xrB!oc=_E!ni*^w8@{rX24o;wZ%T7 zNc)&r=hC6e9xV|ZUY6lU?Nk#{?M*`sntAPJ@WMpXyMA&yQB*RPzYo} zzG^BcTo-^75SR$`@BgV-9fb4ZvWwLz6*yb1(h7|Gi2`*B$P(*e#?Jsit7Uv8HklUC zSviK*(iNrSlqeMgffBweEAdjY3{l!lQF_}3AvvCK)z&93vi~KUy`u0(ND|QyZ*{I&Hjobi0&Ey9@bb&?_I zj66hP2oov;3Q(Ei|X1BxF;teJ6b`s7C^{9#^u5&O>t*u3&Qdl zgz1_t zgagOUS!MXY0y?&5q53GX=mhYZq0aIxU1>C)1|Cqzgv4mRf=U6}OBTg#BZ4-%`rE*( z5ki1$vJxXe)V?U;9a4pVj7LsRixv7KaX&rCPjoj!qKE64cSzNdjv2H4xlJ89I0nta z0W6gp>k-91(zn|##Rl?G08%MYWWnivk1L8Ig@Af3Zu5^=I;w~s^l7l@X)~XJ=gs_` zw3v)U45CHGOIJuK=7yYZPp2Y42BeA+i5p<%yd;N@%0}{3volmC!Hv1Jq{6I)X=UM0 z-mNVm#A^W#|NPMFb7*nwXm;pTJ<^dFv+jCnMU`2He{Hb#$Y>QYZ{bU#a3FMzR6(Im z3U=Vup{@+bBoz7i(eM4HMe_R`3)zAH{?5b6-fY;`slaR&W$<0U1sk1Hra*OvrGjiS z2ntj`U*qMErrX4mzoQnm8_!TgKqDov(yo?TQR<$llZvU&vUeFuPvK%-=4{N-)L3~x ze@C}lQH`Mu4!Y7q-?)hxCFMbc&?pmLDZ_)M;~2U-0MLvlWKz&M{7i((@DORBN_a6- zzYw9in9>dk6;eQc@uV~tVI$a1{(*i?MlGs%1-W>+hl_`@VOyTM$_P^gaYJ;*f-~Vx z9~Yr?bNL)%DID-&l;F;AwWKm)y~5sGa{dLcsp+=3vtPLDq-yNQYl5KPz!qGsP8i(U6}*Ku!vXD?b;R zaT%6i{_k6g(DZuH2U658Ek#p#>sJcWe@_1uf^^fMHiGnz12S2X5~PPO-4Q`L`u0w< z#4G-t5TrLEX{faz?bQbAlpxJ{Xh#HT;`B~K?L2%l1ZjaQNIGE7kf%IKf$w}!N(g|1 zWTQ|cdccsUj)EU@?9^G!815XrBvL2aeJB_Fqijr7Mab4zL<|i)GSh7crbCjy^wm(C zHg;qBiD|-VyYX?acG*4d!7PM>Fl5)jA-81`uATtHZV=!!u+HU^K(+T%BaAe??8d?% z$0)Mjc())bOYztgp;c^}2)oz)i zJR}oe8c4Qcp=St*LyCZoOwc8(kq4{-qk7}txzs=#)vj{SeJ49tZ=B}iDoMv$P46;? ztB{_hLJnLjyl3g4*6%o6e>ylwN{D+yGCBh6+I}?cQY_(B$>_XK1`stS8E2?&WMEsg zUnZVxh&8Yy>_3lcuvi!$Vj%Yg*hZd8*?xErSI6uC6yG0r*8 zaZ^A;pfww9@{i@YZW)818usOikd?RUr&(w+fAN*m^gViC zDXdQgFJ`lK3$JOzl5@Py&_Mf|`3(0%&gkWyEdSSEstJ!=X;j=8Y@jyKRz)$s4+O7N z6EW?&Vjk^09nD1TlXCH~otsWF?Qxi+t0}SiKY?a2jkgBhLV~RJShHjhPF2M>k?;|8 zJ!Qw?YR+)-$!#2+B|pIK)qR`GFqxzCr)q+U(n+Tn9A(1d`#9MAR(pM9zp< z`G*jTcVqh^vj&LIzh? zCH_l3*!goyH9Z;Af)Ju8A-7P#g0oH6B?HKb@ge)-4pW>o|i0+$|3y-?P3EguUu z&*f(-39D1sSryd=%L$3vxezM~wtB}Ecl0kfi*<8)Qm}ywNKO}vmMG!`nBvWmu2;03 zqpm~X@OFAZ-E12IgH>x6d3kPj2JFR*$o%uf>M3am&zW62@DLN z_H>?n<%VN5_ZX;=CI!y&97PjfkWfNvcCcVDbvoOpL7T$@dKb@!1|sRGpV=I%Ufv|3 zK}mBIdm;mL)+OY8p})Kh$lPQizaXhcW%6l^3qF?#x5If?G#OKmU~CI|<{!(;R1uJn zFb#|ARMrF(QWYq*_YcEBVhQF4U#}z-(5vl8>u#^5r1kTEQ(CE7_I*SK(u!G*n-yLw z60JU2JqDe~%gN70PzfK9uMjEK7nSU|3Kt?W)l#qn|LErmr)13t@jiR_B~#2U{em6% z%SeyI3b84Ww2ED2%V5+u`n(kcv4vG2m?T`9XwH-4A&NIkx(}x`;avU$#?rzMBR3P^ZSzyHm9IA}Ns!ZusT{?ZyYe(~GUlY)F<==S~ zpMfO=0E0rDlJbmPuhDpiAkOs+u=%FqjTp~tJSjQ44NsbSw!;&JK2?#pDuLe)OFnKO zOH$Hm<$u3{?yc7spTfPJ4a4m07XvT&DbuX>pr)J9qk=p!$rI35=0`CJLiYshBJ_$) zmx;nkRA1!J1B$NWZJG?xTpVOF@kH|M4_M}(8|#LX$p#eH@+j~sVV7F@%1f-TV~-6u zt1;u!X#9(CDs`mj0Hf({+)+COt~8n&)CJDvxHMLayEv0$Z0uqba2V(bwdHcEh|Qia ziA^@<4ayyWy_wg89w>JifTKJ(Q-bnN18|HezZ{No*8vyT2E?0X0F!YkM|?aY|IU(s z@0Ne3i!o3f%YXSfjwE0>siYEEIlE(R3yB*BX>KxD5~4*CE2;YF%Wi-MW1XONb_hXh zKO7iTd43d)^@C%T$pwys4}wnXH4wF!olz`{$iy4ZQyHc(KVD%TJ5piIvyzE1PbDU{ z#thDTR;8JM3D9rw|9|oSm-zqR`2Q2M-EUz2Vdpd&Q_2yv4_x!iU56M`o`Ee)7U8m~&nggVFVam>b(m#3CyQ(lE{hLPPtT z)*v*Lm*2vM7UFZqFGy2~8i{{Ox`6mr1#{~fxADoe1D_KjkpMp(U_z(DVT=8 zq+kljKJ$SqcKZBx>dYs3@wxPiywS11Yx5|j%HHS!>lSYXPHbx9GJvc!rx4kL2#tCY|Lj#|G`;Kt{_!;M>;9&gh7}A-;#`=zkUQw|Y<7(<&uK$QbS=_9 zFm~;=*T>2!ekW;}xqH59HIU#MOr;J@<0yi736tN#vhSqpg+>#P>Xi@86Ok_|pbMl* z5+BZeQx?lAQN4TM(DU|dHm3Xp@CSa_t=k>fUOe!yTfVwAc6v&YTmbT4bO9(N5%{vv zw1Km19sp_UPP%>t5b%X6&X^Cx`(>Tjy$l49D#fl zjwiw03IA1Jojtoa<)~M&6>-#12koel9NpZ_unidz;3RPSJ!%mS@G_eIj*{%jy8y>( zOPTxfu2QE-(>ui+te zf!F})?9y02G>49^fo5zJ}AJo_rv(t4n*g|yDnV_ca+0p@RkuLGg&Wg z_^S8V6%od+ev)SO5W6j&t|4)P!p-Te|5r zX$j2FNzBs*RXA0d=%pJ@KF;Qo56Qpx%D;EYzqb54#oOa%HkXP%*s3!F%R|VIbo8Oy zms8^KKwmQRoLc$O-LU@;mC-@47N6GH+#T521kZ!roGsqInDlbyV|4+86MmS5*mZd& zjooS*&2)DsX0$f*TW@PYwsu)YYp*;ntqIj{Nwo&xC?QJ|OlinM^dD?nbuw>%(^ zmv2hB!P&0tB#_a`m@lLgGAnUVsuSs8T1IOp<2b4`v4sFH-r^^~v#+NK@Bs~Cng9gX z3)?xqBLt-9;=wgvIsbk}R-*7D*Ro4BzFvRDx*}>1OMT=z+Iy*) zyPV7WtGMpIbj7tdrap%a1BW357yIII0T=s*%|5T2_{_AqaO;U?12(nxUTx+sDHEn42{KnWPGF*4=G1p;(A-OnHF?p=unXIziFS`|wG!g+ojZ4`6|FoJZ%Y(_5*a zH=e-;v7m0*wS#%;CzfPhTgqgcN%B+@|0=W3N_+(#l-Uf*fC#-osIJJ+NiH?YyiRIq z*!($ajgTHuB2v@2fhu-ijou}NP$PwOwMm)PK=JL@c=i$y?@dUhCZ5l~A+xYqOg?_I$aa8HR3+-Y5IoE1;(`AxY_qzxIaLHG!{M^M|UHy z$n%vPs5Z20B_%*9&>T1hX#?HUT4h~2FJ|+mEGgehYf_kWFCrI<)7f7hP=aMC^0s>( z99Gq%^I9ef_{BSv#Jd)dsbS|&V|-avq!F5>f87Y)K^3}nPGLzd9jyRZ4DnLHiune5 zSnsawPndPUS4jp+EYL2PcK^d3r-bPS8H4kHTA>opFLYvW`OXSXp(QlsC=(qtN0oX)&c_ z5%XTn@?5`%YsEdi1kK8L-wyoYF%m$tUkCu;Lm@Qc)V-M%d6FKFMHl!Ugff2@X(c=A z&ic`0vliHfmh~hW$iS@7(uHgx!85UT6n5v*3!z1e;U=g>>G;rY^qe=H!)P!2dDECM zG-^`XY1kHrsKh{@ZUo{| z-h_{MCKVuhLFc^{im>u_D$NU}P%GJ?OH{AYHx0YL7?Db#D@)m-*P^h@rpTU^frmaq zL4i^bT$QRh_G8x;qnQZO51%~DcM#H%79vc*+oW?6njEssCs246p%}n`uQ8^aEC5KS z&ns@YQ%RXV319!@hPEmBQUf6^J|fmdx&?+sLI--tKG;2R1`Pie7=C<}t@jEucRlfi z1){mQ1dc-F8}ecZm?WFE23VcVs87uPaK!vB;bm^1T?rT$Ry@qEqf9=3No@(`}Y8SStCWaDdkO7P;pSni@3217x zW1S(mDZ52(LYPGg)pT>{YL&mPgMSbtaKsId^OkL=Twm%6&9t|)$(2?0NNbspcGQ3r zS&Rmz+zkW(e8O;Ff*Anf^s7{AljcgXFm#%lJBIxV z@me3 zPBUYUu_XGIJt*2JqRAX*mJa${rb-@OLMgt_G`sWRxyY+OsryLVBeq|J_91p-fi2nx zbpqdifc!H=$7zu4J#RKF4lQzKu#wlj_DtrZz9xgR=i{xZqVCr86?}(Dyk}T|)2SeR zvrd0hiVgsnUW@lr*2~#%i(hKRNznm=7H9~xKtWiKYJoBQ43g*)#V3y)!a!B=R+!39 zEfk3&_i~(9t0_^gh5>8)D=MESAAiwD%*W@QxeWPuem}sm&H>ZX`FQqDslwcIOD%>l zs&{Th*(4O_^AMg*+(XP0I#mMA0^DMhm2aQTyH>oJKcy=sbV;sKn_>6l2KHQ-J~}X> zu*lv2QZH4AsBiaGYJbdBY0H|fTCNu}3(AAM>81oezdT$IUV^A&VY(m>rY5bTu@Di^ zN`OkFP^uwR&@CG46p4X_BC!-w)RlaBdeMHw`Hl($TEk3Y0>L?I3olw@A&kX@v6!6$P;A_T*#_+Hs&t?#ppnABya>U-^vD@t4;B)A5LUA{c%tnrkTZi; z-nJ!bx?i@{fH{yWU@Z2DpXvJ)j}gz~Gkr#r%1BEj$d5!#E37BlakI$Eo3CCA^R*{= z7cGE3NCBZ>qEKw*%~0=@U>flX-Uj5HvJt}!bn%Z%m@n+Gu}g`CY&lE zATfX~pDG=ZAPxL@A<)#-Kmg~7J__M54tLj2&>^2pOFg;SeF9MVZK)3WDej7 zV_mHk4yNS_a-b7dcn#8_!#iAnylxcAAomgR5o1C527Fb=d2SS-JU3JPJoebeA_5LG zWc}VkjO;lCA_wAg)KUu$frKOIQhp&i+$#){Q0+uWrb`9vtNZ5?*UJO4N)oStE?$jo z^*TS#3cfQ7I9bgVe4@l4fOFJm>Qf!qMr$(19nuh@P*T4mrRTA-x~Ed-rUusJ2Un&6C_ z8ZG=IH@sJX0&RoAKm&753_txsn_;ttsP4{8b98G(t8En-+ln zd#Xm9X>F>C6++c&w<^S`5sguC?ZD4_up&I`8Eq=o=sxTCYX|CH^{hUOQYN8s3NCt^ zw&CEy3sg8*M7A`u0#qh1$&gPvMKANirGBrcpx;jqyl4SCLyNX2F?RrJ{sp zT(GYe{#s&_8ucJ3u&2h8K+ALC*SX*MgBOT{FkteZRYoU2uu7);H@$}N;u07iXUu&n zaLoU`NqL0P1>!+;D1e3BLIDfTRkPN$T7j|_u1paL)mYp2QL?df65nOHMG5%|SI!cS z%;+dn0{bu9V^lqSpb!JSwQL%HEIXL45i>jkke3(mJfXh}`z{D8~Rs^6BQOU_jsoh`uV!7DggMfR@dO|19osU(*` zO9(3*ou&^|a8<|U=<`o$jvl>II9m9s=BV&cnBH6Vu(-xTS;)j8h~KfuuYaAp$d5TG zHS9p7rWX0l&QoI#xHc`|Fr|8t-*hTZ{ERv)fAFg?DDTF4VUb_8X^n%0UG4ImgW0;o zgEFw3q4)ejvIHSZ_Nd5Wz*%CclNc1!`+DupCGwI6xewcsD8ls}u%OOK@`{U{*XeL6 zHAtGcpZkyOyjyx|U$Py+zWZJ!T397``73Ibpdf0Gu7b_Pe&E62)QZFbY*BQX#&MxU zby}3yQhbXkRrq7M#8ZxV%BEX(&A7+vooHxLzdN-H!nZWvwka|kV4o9by`E$rl>QpkNQq^;f5~nnLqB+s1-i-vko)F!+M5vy zp$V%Kxg!38ob{}(Wl41@K0)=9#t?5S3|VmgaK2K_xl&m#9kyi9(decQp3F?-5cBPeZB6MRhc7-Ie=cHE5ST-0j5We0 z;3(lhZvc&#GRF9v6@~&dj$#tP7;&l4AUJ-Ig^+#q3WGg1(0~DXy5yVy0Fu+vy|)?f z97Iw!WS-}Z5Ljtwy%3311-V@k0}iO6ep0{-OL4 zz00?)t;r-lgcg6|epJB=$&a0h=rwtNx;yW9VMyV0HCVWtf%c?z>xoEwj@ti@)u zu$T`PXaI7YzB&n4qQne%D0?$QSvXva-9a{$wwZV;1ERl%2m2&e65v$Gb4{^Hi%G~u z#=IW8)c#^7}Bnfsg!SVN)ezEOeA9B zYVrphaX=I>YJ-g(6{HA5MV{C6fF;Bexf^nJeTllQNyTGbph-}=F;I52M=DUP20#g)ore$Rg z2EJ&wM`0^AQi*jE>o`NxPlq09)&O{A7~Db;3(k6-2^TnP66Y|}VDTW?O0emp+9SOL z5ki0Vkn6hxsomRrFxkiC@n#Zw{IT3DC6w*J zcRQ!OmQ)obJpKzM3gSJ$7S~$q%sra-DBb`de!OeJEv-K8VD%tQ?3SNew9n( zEy+}rTaT=e$5>dfJ3xuXA1kcK4W1lXM|-jw7yR=%c-(i?ZMjeX$iJvv9f~s8iQ0$P z;+xFT_+f?4TWd4bhD}m!*76rvi5at}*2`_>!j6$II`_c*NSoU1n6=p{^`*|F#-W*d zc|eu31G^M^cLn}|Pas~ZW5f*-GXPsa4@<>@Q+S#h1_&^^MG}s74sjcErYON^&M2${ z`E?WtBt10h29?sOE_IWtmYb$nfd}@Dwcup z0v*hjUyQrtq1J;*i>V$6@3Z?pa#@DWf`K?@h9v+<&YNwt39s-y%mC87T*w!FDZ{NE03=%i(@+ULo>cL8viu;S5}i=;7f;7hO5wJ zxwUV(bpd?o9BHE5j=`61gD>3#U;1UJ922Yd2)NQ1wD6p8-b{+eq2xEin{ECb-HiJ^fXG)(^3jq zpP_a;YD)83NvY-KXgeJcUU~P9p zmXL^AiI7-Fu6ltU-{_O2!1n^Y!#~PE*i$a@l#AW69oUxQr?f|AzV%V246scylkI_l z!+%N3z%q74eRXE&Y6Y|_7(z}{AvJ6PyYrF`P3-Y$HW^U;WS4=!dL;vh(3s)_oBw|! zwKJ+w@*|*Vy-PWir+Ug1HU5$6Gd<;IPkFYdJl8G55|p6qa+Ox2g4c26W?=l(vOYWi zv%5J^8>t6saLhSQKdg<=-d=?liP_j1>*Sq)c%{;_Nj4p?$a;h;*m|4w2;xK}6dA_n zwzgM^uX?u(#-Ab%ga14j(bpWZp#96k1ql8-=^8Hk(>wqsrn4HWo(X z%V5pT_?l>ZRatza3~`p0W6%TWZsTS+20Y4qDeD=9m?}|zUZ=7bDCdiul)F#X%?s=E zE^y+os=<*^K`tty3t^QFO5NF9<9B zfLJY>t}F1%^`W28(<&fv_y!*WsG0mF7lz90<#iyuP$-uW*5hH+9uBYb6THrM@H(G` zqPZZMYCLM2@H|X)x4uaW$&Nr)qv?+r@6(BqX81DXeZ+Jqk72z4;!C1kXtU+# z5#mv9Kh2xb_#6qB%CXM6y!6YPt|+%J%q@>U!Z*tne%^I>d_qBRxILg?h;`5-PdtdD z%>NVXacaCP68p>4&Vcv;e7%$gW~W^^MenBqrH0*5V2C)qWSt9W^5v*K@PWbfQwD(6czQ6>CoVU#u@ad>tJO4-@qUPAbd{RX7R_xr`L#@N8CZ`n(CJB7daP&Nh zP+5Vx$ACl&Ka8&9zxbqP_7Cg37Qg&s*-=HXOY734#jKA2)J^}YK)jjn3+*53hUw$^ zPW6q{T$~wx9=_JhGsCGvP$XIGMg;J3*g0w=rDp=oRV_0Iv_Wm;6J+%XWzVuEK;x(;>`dR#N%=nHQIYR*E#Fb= zexXS_0JW9tGMHM87>QAnxIt2znW7!pIa9Rn(%+dq+-Q=8dJV0)$Wz{qIX^s*PtM{= zKZJv3Lu(hKaVj|lsFY;zyT;HMwYC*91gs@p#}&Jv;c8(k6x*4a@B|N$Ob>!j2khb6 z4COx(H*(P+e8gI5LVvrVjTGqx8rBp_Xf!^BP(|G<%zl^ILvoZpMXh_9<>5mVz$n+i z{=fpGR{6!?RqhhzveFh~%5oIS`z$KAFNZFz?OL|*7Z~gxTFZMo<+&>aZP6#Py#Rtb zZ=)-ypnyl8P7q_FB~wu?i#`=S%w=1*H=|Fe)rq9AP+F@MF8PSwW-WhlJyTyha-E@G zGWF>;L6c^76}9SlgHo%5f&y(J*oQ1Jk%3VL9!jk~`u1Cl;lM*0$@bLBZ}vGzQp5+< zMO_jPi*4OuNqJ{`u|{Ggq}us&Klt-w)aFJch0^|9;;Y|_tgfr%97+Y}P!OhI+I&eQ zEbDOPbfani5)+-DyMaa!cAt?R2#E`X&d&8;d$cx8X)R#9Q)R}j+453@vVzwjT3oSk>}3ceTQ*9wZIg^D28;qAuia69M* z2aCiJf1=}RmB&X3qkD#*D8UR9A~AtS>ch{ASraQf->Ah}JthsTJ6Z?_lQ{RYfT1)# z+KT60k*Jp(V+6NhrHAMR^uRpAHciu(IWE{-QUyTCOCc7V;-ScSU@HfQht6{ed}9h$ zz8)9+W0_LRKh7YkWoyh};n?u^(|r>)bQE+Bj7wOL*r%RVAlb`yGPiTznLys0H$rAwNUOhPLP7i~QJm%fF?>=&=ES z6^=pHC^jc0vx<$GDK^JH;1in#g1ZtMI%G&|h0up3G%YzKy+RmrNK+!L@23waPqV%k zS#PFUUkeUw$*nzJSg=3YStB5$P^VxY3xRA{99fiwIZac9IWDu8eDy;smu507Lics# zlCCTKBoF@GN=YA6XeN$Ei0|yw7ZiRF+;B6u>X#@4u|YnJ5j58ZXVCvnlEeRvOFOW6 zkC7ldld|G}NEG;; zJRA{&jK*f}B+N}C1PiUC{6BBuu+NZyj_p5M=#E*oG-Hnd%Uv6h!;e)vYW zg%4eYayFvh4Mxwdg*YlD_$Rg#5}L3<0k;3O>WicbOhN{{qO|@g$gVj8kWKgXXH4cd zEzoCWhQDxWQY|Ew{-m2zhk9uu41mT-)I$Rb1A8`KE&+~^$Ncj?r@ep~vpK2}OSSF| zCBh&otcF*k#O^A4N`eFaOp8eBgYY;o1ynt0GTR30V6gisNtmwNh6u?T4_N`o;bh15 z@XW&@IBTJ;8T9##h;&FFfGc(ZQXY7unYj{54G0k?w{i1`-j~VEB4^#hDi(z7Q9CJ1 zVl=pLb|gqPmfwoT_xlb5+j9lkPJl0TAbHW%Tl?~}Sr8EC|CV3@@~&8Ws+&QyS5I)< z1x64J<)oam4g>aGL~SzgpUeurJqLhG3?OVW+RY&vkRJF1J8ya`cMPSIE!tR%{s?`- zq)8E)6sKA&1w?c8yaA9wj&#@-ajssev|jH&`0F14a5)tPm**iBD65POj6I%`i+&sfij6w#ylB@E|mmR2X zP@?TD*NYj0>|YeEN=S{XAPEokq!OV7@>1j}a)3j~D|A-e5&;0nZm1!W=T3(~ah-XL z8eFBD&IZ!LaU9|27K3c?Kf!l1;h%l8hTqsx_<;#%O?%>jwFpQk7N+qK81W)RM$aJO zBI0}_<34RXn*DfO(+7AAbny^mGUaFd7~ld!)scUQpk-%p#A^!yG2Jfp8HPH$Z&+Uh z3w*2Fv-*X`UOP)!j86E6KemMr-Gy@gKkD8DJgVya9}mlD6yii78WnWZsKGU~qKTpm z2zY~0gKJQfh+Aw?10)a?B{T_S9IjZGx}sF8MN3<>7H|)X0Ko1_WVaKd)bd$QnjkjjKM)fr zJPa=`AdVD8h+VF9b<`k-CV)tMJv}F$32X8Q$Lzf2^%M~87mBoBcxS2h3nI<=d_{!2 zn!SYiwT@TdjpHF){krGS4&*a)`yIO{h5eqiuVcTDxUXaTy>2Q{qx}Y3x(E?6wBJ4Q z9Q(bY#n^AtOnUo$=OG}$Hrj6qX@r=SXcvkex8J#&J2i%x*zd<*@!9Wh4+fB#+i$?@ zvEPXxU%07LkRdj86d)+)w%PAZFZu+|2sUR27OpqdjFZfaOmWEN z&MEH8!`W~MaJu1K^EY4qx;`vBnl}`~QkIPc&USUK%tt|OqG0tV!Rc>Tt3-^3KL@6dIy{I=^+xDgv;4RSRPqL zBbv+az(3MLpdqKuF+orgi}wIv8S|M4Vr3%5v_idlQIEy{S$dhBnlE=%}m z%~hOMR5KQ5g5lvcld;E|Oh_Do^z;-P_1%@V2V-3TL*zo7p+rNjg#aVt>;nNuH3BAV z2@41+2rZR1TSa9R3z|ZDcg7XEWU{99L2(}d69mn9Zvss=;f8t251=)5#}IdTQji*5 zP$Y{7fdS4!JsVMgb|=y1Inp`9a5yA~5)Ey81{p4R?^3I9 zILGw=a}(=;+9u3$7|U_O*a7mAQ;{|?i;J^*Hw57>LiFPEzmtZ*--js67_{I&;2tCt zyeq|@Fr?67p5dwR4P--D#K#+u)T`^zbn9Fv>hQPEcmfW199l*DXj5Kg`ypwc;f(la zGSlJ}WW(tbk1*y$pXFp#1^X;SpG8a6PV7_S2{wuLSd9qFvuFTJa?1ujc!JZf(fV6S zn6P^Q|3L#)XaK-*-VTBWa$R-jDkwDB z)CfCozwTzm@nvSRB3|Xb#(-AFGh}O;Q?c;4=_X2Wu;~dZVWbzH0yE0d;;C3qT!ow1 z$tlDKYUF{lgf<}9saQ%}D!0$VQsQ9KuSMg9VyA*hRI|vbm{fSMekROkz7~lTl|40V zMNb7hy`W)TxIg%*(56ih=}uNT|B25=&H}t7P&fpfM!Z66M>>)6Kr~mK_q@lt0dO1{ zg|l6IlYYf~teUK=0P8BDeS?L{?W<@Gv$4b28vWSva3w}zQMJ8Jx-YMQLgzsFp8gG$ z&#GvBTspOL9+e-+qg7@FN^$EQyPs$Tc2j}~5PIR=D`LR0Df0L`8)u_JEy&C9VQv5q<67&NSG!8*5WD!ht^uxby zSlEc!cW2CUgc55|b|q0mASzds2%!-XBqLM zce(Z{$^^}!?n9Im@w!dZPoYo?zvkq6r?>c(IvxFXu-;|TC7=hmG!9||dO(1sY^HO8 z3N3KV1t2Gqg64;Dq3$m6jM?$_b>BN-w64U_cheR|OLV6(tbWg0iYbwuR&wq7HrTq2LKR8`nR>L}I_Ba|4 z{*z1tbsW+l{w}=~@=DBaKktEobS>HUVC}F=J=-Jv3jxc%VaNDwJ|4scJY`)%Es|{a!=qf zD2|6CLOy zhh3MWk&~c0S9w}KNw@s;{6wdKmQ9M`9dpJt(@yN^i)``%n-gFbVYf7>|P| z6(0QsfR)r*q3KJ{-I|?%P{0TrGJ>Y5~QPl2rleGq%-sn zUw3i*!`pwQf4Cf6fq&@0J6zuj1lY+{oCN%n{X=k};~y@M`254KzU@LAafJptv#gfaoXo08%4xC1|kkFV_%#EiYcYmfWj+>LOKic>R5|L)Q7 zdgBe$=NB7$`pK$a>JMmOJMjijcaSZd-UIOSoEJwO66yV5D)`%44E+0N3V&*UV4RnO zM;dSNZ3o%H^j(3+;3Rp;I6nvjUA5*=kL~l=e=Cgx*ae+?^MjX7MPVEAgOv84`?~q; z|D?|C|1N3l|J-E$LFOx^16-JR7Ydq-2R${ccMoxBpmmi26Rsqu6?cGQP+rjslmlJS zDb^L8pZ}B?yd#iiN{h}cZ-Nl!7o8xuxob-{xOjqB8k6)X^ZL%f3sczV1wUO0$bpn9 zyCJ=OW__pZd2OG!v%YiWM#n<;dT?9oJ5TKlGW_!T&bJ?SYW^~@&~MN4S-#!`a*Ur> zDdLah_}#Vp^eL9#Vh`#ZWXMrw@%z4hxJT~(o1Zc8U-NQ?{wB4(_GTNBhorIC9mVhObO#=TI+34@2z=W&OxBG@q6m}&hxM>UISieCM3l}R#;1aedon)03t83j zi38vd{2*4p+bM_{yMvy7I8P&-6&`{nz^hl&`09mrpl*S&r~AK{p*@Ae4S@m@Xch8; zOUmn-J1*xu)jp2b{Y23kv4g&ZW zw*n7t?-Qp#YRyWo*IvL$64Tb{!jN9zY}w{7vdFo_kp>sn^W_?L21?v;lGl!-5R#=% zI#2JiCc!M~>t&p+S%zY-o%hf`NE8IKv{L*hS5+=_miXXnx%)JNU|ErcwOQPL2kS4n z2DE~!!JFAV)~JT9k}W}d2ELU=hhqbh-O3_8&ARFyUhkC8rr;L%IvTR9lJ6#-#s**$ zdw+uIQMLPXK{J~zZNM25IFAn!5ADW2Vw`k+CT{CYQj zEwztX@6K_s7Jn+PHCJ7P)gWZU96TcPc4S8z90mzAtE|Y#+-Tn6RkHRKi-{d8x4SIO zK{=mz@Wb^BEpnBNkHlM^Vq&&BUxG5-XX}${U%?k!*uM2R*Jv8Do29xkFg>Lpr2f5t zs~)8cEVYO-rZ!w`=dN%kO}L;uwnfzM*H+|oP-=K?G;rk=z@VkJhZWfqd)mfMg4DXC zP_IgerPoWgu2o-efm|0t@SOx3a@l>FS1z-GXv+A)cIE%9j^%$2TF{fEAoY3sip!-O zn|VLE>aHg##|~HUtQ5{D_COg5a5jWe@4;|Zr6Y>dAhIPe5g#e_{j7;e~k zhP8ZHPVQGCmXjN!WT`WEcD4=$K1D!38%>0?+0I`yMSFcgG z1Np~$g9ridAFinp@SGE|?7Z&sEElgZ?G~Is&V2GK1nF2;qMIs|vY9lsdcC$o#pGO= znm$)xclO!!YrI}S&rmD8f;1;dfC`8MI>dH^w5k~=(I%+!O%TqgM>rv*KKr{`+uw+m zKi%oPf;sFQ_E-KwthCM5_E(!CZGSbQz)_e-ma45+YWo`^CS1T8Y~=ne!grBZJMdbu zS33m%=8+z&Ekp>BT9_}F_w`?stoCD%Yifa_taP9wc{)r9frvxcwbh1LlgncKK$>DP z*&N?5i|$kwJsk_Bx!|3$ThYf?fDxr}Bm|cJyNP4PQUD7v*?lNcRgS%mw9#7Q9gFrl z>a%Uonic4fAKLL%^7nSLv56t@v}L6GQuX#gJr`7lCRtH&qC`8eV&gDPLYNFlI$2+P zn^w16;txtVo50W1TOOcecE%3@TCFd$=sf1|H`6J^vFuY47;_tb{j3`+7@ft7w>U52 zn(l@lymXukka<*K`t;Tv0h79CBc%2mM{48pD(k^dq%<`o?oSM&P&{eH2nlUrJt4)H zT!1_Adaw3oYaIUam6HPW!vU;(+2Zq1Bhf)KU=F*(Ig@bISD~RnKY$S>t7?Z?QFvBP zWW-EG(7stZo9Ukb43f>k@BEMl2*j_Eb3jML zJ>O+*h^D4c$cT#~O;2b01T*L`hrocWVU=}{&RO)-8R^3pS!9_tI#vuxAdEg`$Sh*O z{O2W_>Q?M9n$+&!gKTfOWOLlT$DWFOa*M^Jcw8+u^m}8G%SoYM`$d|5D+#jh+Myq{ z4FQ$VPh&*-z0Mcjs>P1j4pn#Odk+1^;MAy2=;u+5Lh6YYT~5No7s@C}2OI2|ebRB! zU8(3u+aR5(MT;F$U6V}5d)=D{l8(=Q3py^3(=kE*f|`C+l)p-jPvM`yiVfQSsaXp> z^n-iIx%ngN2xh9*x_3a13Tye`Y(NLS8=T9((Y!k@B;oWy%`8fakZJiM*Nx?X$i*#3 zK4mS$*W*H$NH9$ULom%U&Y;0#bNC)eX?f{du3j@a5){l(*wswpA?83;VWAY+S|Jnr zRb&H5_KqQ00=@Q1MX$To8+wf~^Dnd6F6njAhlXCm+&ii1b=hc5uLlH;ZKRinIw7L% zP)7vKp^gZeLmd$`N9u%b^SyLiWWJQEJIwTWp<4@oPC>V#7aY2kQPf7R2i;zci<;=H zkA9Q5KYI~nt&p+?IE9s*+>igb9>KBDke6K5a?nrWC}58y=pd_c11#pd4O}Sj@i*(! z?awau;Z)79O7;nc@SnI8iq~gAvV5!#hya9mcZetjR!tr50RT4{-D8PO8J!eV=41eT z7801b=Yx4IT%LmYrm2H?f@~(pN3ctUw7%iFb?vRM8+e2eMlHfr01HGHO(>TO%rBis zSpsM_pM`*Bt50sy`su(;@ki5~Lpi1gwB8T zW*PALB1#g>jdy@r z11Fx_(&Qf(L^JiI4?ZLp*~kyOBN@4yftX6SSrutbZ~vF_m8ALA_52n1f^LI>k>lkD z!#2!3S8T(0(gZmAO2(CoJFUk;dkfLHs44{o-8hnLdM%4wABxP1sp@T^4aI$^w-%%5`ID`FMhgH;y3Rc!4GG!I#~NqyrHF26df30 zd*Uhw@rnC%zt>WC&q~JA>71zEEm0r15t~3%pN;|5JX|IFqu_MeKB&Q$-`D{)S(_6z z>u=hKz|NaY1!`cT2J#yWm3fiz!b-{@#t1Z?1zJwlk~lk$cjl1#c+BD#QDS^4R~1lQ zvJzUF7{sWL6tFwg!OmN65dB`J`3XIi&`$mdWIOo%9dlsWa3=V9OmxVL4cHf-i!OLN z*noX;Y{L99-;3uW^QBx>dxNzW{tTtmxtsd_OW?VG98Y1U&z{+h1;x0pODwYjczfD9 zi|!^euOQ67w)0n?u#D4X+9!^~?QsR`Y5CTxpD;09AF5||ii^O&(0}ekSa6Zc3-#zG zT`0@9cpq|FA-#}{_)=-U(3;yOZXC`V(G&ad4~mRg(GfVswu`)M~slj6)ie=e-E+~zZtX_$a=UD`4K(;J`lhfMdY+%<4s3V@F3bB2H;Ov&#x&T$%KTbRo zAfV{wf+LzHOr1icxQFXJ5S;ZbsE;^J7S8NyAQVSmFt4ICgk$|E;kYLj8R)eDSiV_7 zSz5s_@Nui~mmglQ)|ce_$OoMm#i?Ea9(8ZMwgI`s5kQ%j@hOSXTx>$!q!bZCsRbpyg#=*uAG({kB^6jo5 z8G|7(R>U2HA?o~)7Yu&oI*|ksy6U)D%vSHoY7pHg#$fI&WUaEy&O042mPLB&I%-_a zNuH3pcs50ea6=wpbVVhpq$pkpREE-&RO~VgipKO%sAnwZW7@iU z>31Bg5e#=7A!+6>EQMivMmz8F2Po=HCZ)K=Wb*TS^q`G?5YLKD7GG-&uBaH8&MI~k z9*p@YVqtgCh69rjE}L^uotk#^Te}266z4_dd2+@OrKN(ZtA|l`BKYxPlq$ft z7vSx=*U)HSY#H~D#-OmWpM)e#(x^O&15RMObQ*P5P!AlfTaMd5*PaHP6MIbe9AHKQ{h3n1?SWp1TfWE2g{gApS2K*z2XUFJRY@&7R=Sod^T2*g6U$9 zBJ*@vAI^Lgdk5>+@-LXcYbDpTvv%MegMw$gP!mi|0LC~JNiblh&TEHNx>+bT5msIPH&^Bbs864E(C1Adca>Iy`EExEJ z=lnA|q-;^}^q>jiL|4MperKk3o9_*9+$Qh>tEEuUQiG`6I}&~g2Bj|$#fJ}UqYrG$ zjplq+dOwDrd$*zHeh_?Mo0tcyVL3;~%OWjA0Kvhx*o8he!j&(2j{XuoIvq&6txMGP z2g$e!M6QySp`HxEmtuYq-Gd>d-0(xAc$dDUrVz+jnaD}Fm`sR#*ZFe>C_vdwPyV2R$0~6yFiVaT1H0j1*Y8i zP#9B__-y$Aq|I#nsQFQ6{KHH-gnWQp(VX^S@a`C@UrhdkZZJXcnD{T<_|fZpA^rH# znE9QKf53YbQV7M3$OWwQUHkzc6~|);j(fCBC1b~dCJoCfv=2d4R4)%RacY^X37c~K z=ppx}j2|sq1F~)B_>nc&&~KKRTj|j6g`t{$+dO`BGhawQezgDJJEb3}r3oM@LcGiY zL3hF}L&y0-C(^O*##D5?#ie5%7B`6k#ZrtPUEto7@uMlLLB|ZokFx)zO^rHZwyOyg zZae2{uFi^J{AhrC2V$6F{OFvMNx1)!@uR{=h$isR<42|MgJhYEAFck#&})C3_fE!$ zypdifEiv>8xOY<1>);`pUjI|$N9$#A3+X1~N4viVy6wpEqoO{(P#gv)%!B};=r{y_ z4IDq3{cgwON3!2i(t6KoE5dNo6acf;aSRi{w-A5JW%!lv9Va>q{5%=8()uu%l=(Q( z%7-!4%3~#RJf^S_Xoy2d$nk%~ETenF?{5G_?q8r`*DmLv@T`)MYmfsQk z3D(n=kr+$We)&4MZq&7&hPLcr(;#F=IHS_WNK5|@d72dss+7r``B)eb*wj5}>oVmV z)|;P}*@L^5l`IaVp8%R_~-AvcubeU!Z zB-u=^(@YnqnY)sjxrG#fFy6(#2AXcc>93iuRTioe6G-g+#lSeB`$^c#mSGzB(j9(Q5*+Jvm)rd${*nZ{gnd zygK#`n79*h(vG*Bm6-ozGTyxbr7;rQSZODTPchzo=$}Uj$!V*h>ooE2{3cNpd^`k# zWClN^6B)t}J>hnZcL!!_rhA;snF$b3_`onanSo_p2aRns}9tGkH9?p1%U$%H;9x`;LLD#SAgS=81H`eSivvdc=u~_Iz`ce z5st{Q*W!@kr6Ng-MWzMMN2`e0I$RAs#T<(GkKM&sS9AJpbVJ%G8eq#-;F z4GYKz>kP8e!th%i6&mI#o|OMTAMakb64+%p-re>`gWn4`XO16`Z5DGQAzpm+9_;(S z9PjQFwh1B%YgJ9(sK0vi}?VX+}a88F_O!<3&NsgjHcGGk8N+ z49i+BIOC#1E-=5oG490$+iW#+tX2^dgy7Y3Dm{u3fp?$uc=5y84~T@jsZ+)8-cI!5 z_3RZNdT~k!KP0P`5GUAl3ZIR*N3&xGM!jjuaqBPk!{(SzqoHV)P4VLk6u>D{Oa1$c z;M8^T!6ry{T%LhUo6bL@WXiO4T8ift)U!d``TMLy8w~Xumaq57DNaph%JRdRtd*OTo6YG~0aqGUpE$YJSZp zM3H$q8U(-Q@;flMEc;14nIYcy2~OX*Uq|#2tGa;g=iG#eX+a}2G0Tpki3v6dJMp|& zy!Etr>(zfT$KGN6A^`&AumfH0c47f=p6zH=!Iu^03oN0N__KJFGWg**5MPv_AlG~e ztJ|w69tKJ0U|2hF(ORC6+JoJ3;FMmo=Q+~ zN!IE}e=2&u?%edyv*t)m&pB)-fu8rf&&LnI1U(|}| zGccm==)St51-No}z-vDRKN%TGf!`gkX!@yvn4U|oBq3%-_yItThzZ0*y@7clbzJb& z0_)1;c~~2u)pDlB0S^nFT6T%&RUcx_{5&GC zsM9(ALJ!6s>WwcF>ZzKx9Mj|U6^XMD_QeAbpFB<)2l$H#Kj_DQ0B4x}hj?Xa#jykV zQ{rI)Fe7-Eov+#G#B$8@aRVbcDC`MhxTtb4ECPl&+pq}8#IE;|)8l_detyI&fT@Bo zl@q3NLQ-i(=uFX~^v)}AjB$q@IQtN<8#Vd))lWEX^x0pzZZs)BzX%gJ23`-`ke?qb z^U*PR2+hJ~nheJqsd&Q+aLpN{r03If(0~6I$Ma1-FMUpq(rz=6#JtX1_}6Vp?fx9d zvo67c`1lo^zEIN##2!b##(!Yg>ZKt{w}@SSp@?0|9DLqwju92%aA*oX8k(kYLmFn| zh6HdBDy(wGlDq^XMGl@DrH}wDorCv(7Wf_EXMZC9m!!l`6UxP}_)x(wT@JqT)=p6b zvS6}t3qn17f%rQyzQJ=2p%FX}mSqioJe@p;`f#wU#38DZgAacOs2)I66Zkhz;|E5K zV@xgo1Qyk4{ZjjzxtJn_kbD+wX%+wi6k4)zYBa6@eQKKzD_Jj4GaMRC6%c+EBFTWXH+VuIIv{v5~aPfr1_qvLovCN=@Tc?=Aa#{a4?PL$n~4_D#@2w>zTb?z=|&PAGsBe^`6C(Y)@v zGs3P%gZ%h%Bo}HcqRpTfzic&s27ClYeomY`i3A^LVsMzFT+S`a*E5VqO!N=Wm_!1E z<2VZ!u;qPu5I}hg2fAQKM$Ej8thORAW0k#}mSsiyXaQ7%(H&(ERK}aF?{a+l-|QIU z`Ip_`;k0EW)WQxCGuiaYT5Q51;)`>;c~xaaf$k8QKiPv9p+#&7`6ZLa8 zX`itEMM_}++prgVxd3Br^r4u!>QOXFCWv8f5dj< zdS#goTOimn@mAt41~urfh&Hnre3|fV(3aN`~a9W$H{SG+HZA(ju$ z<=<%Dus$T*|Hyo}dNRj4!6#Pa%7`p;r)dYpFY;Po&p>WrjH7jUQ^9 zJE`fFx38wx|I~cAwGu>;ZZaRP%ilq_^z-51RZabK_ioUEH1#@YMGGW|11gO(yW+ym z>38($P#F+${zQj}P#^?tGfkC}aoan4Yt=61JGirmjbOI$@~}uG{^lbF!PJ|ad-j3S za_Au-kLKOV?{?pA)37q4H*+dk<@U$&iXe2oE32BqMYv;T(lM5*T z)V^MzikD{{frlD#Y~aZN2;oQ}g2_vaH@6C{2!^vtmTVO%3GruGT?Sn6da$}2Q$oJI zLi%xvUH6$fms1aXQZE{bCe%_HAD}%68nV@}DVkKptuql(e))PifJN6=Pw-GM3^cB~ zN-H!2qHJQxi(Fo)v6p+|Z~(_}1vkq991z1g9$m{{#nf;;Q^WPDHzqMl1xwtyL^R-3 zB_KF>Z(2$gM4%oPud1Cf4`BKwEy*LWgK3U;X{;_zJz4?8K{>01?uw}*Ccp93GvuStvdB= z40Nv}-SJN#kadQJYo?hx>6)O!zyE_4_ucqvH18mOxBDJ*8(yHeD{2A7eG}zAT9NOH zyTT7(cohN0#9nH;uhtJ#i1HsO;Bc!I$x$JI0`H9H*t(Om^jl-u<2{G-{>$pJp3r4m{XSrzoGWDq zwev$BQ4aBeA{}vZ&f3hsu|>PQ9c8u2W39+itKTXtY4x;BWW9KqK3a`1OPzVky~(+KfHXC9BbulR+Tdxd1>G!jKpj|7nYTjabZS6J2X@Y_inJz-T*X>ITSW#KIY}0sREdkgb&+tPojSc=_enZ$(eF zt;3I0(orVLgGYcbYF#5l)vfaO@y_km*^qNb?|Vu+FUK}O;nXQ}p?bH9>Luvg-qenU zb#+v>YARcGJcy&QFo`NfPVK%4CISLpNH{<$rgk7uJ_!V($vW!MBw7u`kK+HJh`27I z1Q%56jako;AB(V@7%RH5cPyH&u%gFe9xGOE!k(3uYzoehV`{LB5()@IEI%y)n@=lQ z5uAb3P_xSVEibdjU>)(=?xl;j3@XI|bEh4!y0puBHV4xnnjv#9PHerDY-cTIG=Ua| z!i}hjV)`_2QcIB2t@Scu5T3h@Rqnx{rS>Rd2}s;E#7qzP@kt`2&CJ}3z&wLOc!TV@ zS7IjJPwR7P^g1dBmJXi&U@_N9oBDdmD|4h&5ieI#Rdt} z)o%`e7&!j_R=@e{EymwId8NmwRMJL?U*bhIm;wVHnD)#tFbP@-k5VaCRb3s{Z^4WF z^7>8xAGCf8-O=JU*KgF*1Pr1auiv~os6)UYx#4&%A#MHU=$O=RnjZp-c3}PH5pw{7 z9-}q&o44Nk5MlBS)rNaG44IgGSG5!fwH{pOpefcXDO{pQ_Uochf(15N$rcQ;d1 zP``;_hAH8La_@lp&EXG%xS7>&+QysuL;K|}Bp_Eb=ja@rq%0OQA|^0fY^yWIM)T_I z^F#}~wWnCvbo*hRQP*kx0s2uW`hklgxqz|M<}9gxvmR=mTz9A^uwts$U!&1US-*MP zy(#sZ@8^JQ+gZO^RPEHiF7wmxn;x2e+g!hSo-d@Y-vlRjN(G^_!+$ zNx1)!`b~wbOL6Nr*WM43Wm3Pf{%PoS#w7{#I_f4vuL16z)bu)M7frAKsrpSw7Qndm zo58a|xAgTJ%y-zn^VD`(;H;to?Vv=?d7A0YQ+w(@%psX!LMr(6N?&5cwKnO-!zOLh zd1`y_;@i#}nq5r$hM;j=K?p_r!lmk1f{^Mw&FwgEnMPLy{^_BCNj^b{LI&KJBAIaB z@?Ik;b~=&?>qzEL$7#_t!3W?)PU3{U;){*1gX1gb9Wgh+$l1k{SlWRb&X2bYteLiq zFfBVV(l*W~G2`t$?}gB$KX3UHI**Lz$4vNAr@=b-kR?`j;Ko@_@Nr*I2OkJDlIF+o zyteyB0YS`<+0OIYZfJJmic601&xt`@uAay^`sK$9Zpn`ev#2L9qJR%9J-=5@yd){4u8{;7k+zIeJ;f&Yck8N%;C8)E6rffgn=J~IWRk5}kG`gnz|!1|I?!{?73aCm%)sa5#~bg_VbuA}ojyAzK= zoygCmv5<8btZ|G*`46~XZbh`NS7==aWoZ$`1?Puwp;kWXv5g-8kj6b+cMEKDvm?OJ z*_KV)>>seT#yZ60%mV-)yeRZ2@i^uWe$wE??O`!_?oA(loCOdbP8DDEV0Axvex^eM zv2uD73qK8Boa>=Mr~cvnp>Zn?ax==m^zdKgAJE1?kn;J{;|&kg4fik&$H@VG?tD7B zNgrOj8DfKRKR2vMu#Ym(kx~BemYJofgE`|L4ry@w!{~15{X;qOhmTGJhVT!C(Jq;L zhe1;u?{IJ-y#r(!&Ve=|ZSwG{4Fc>O*P8_Vf5*3d{y_{T-GhH`_U@PMQ19?>S%xqU zxoHE|s;ff?C8m@o%@4mR89t9Y@Pl~qrJaH($bs(A^0?!ID^Hs(oal%1#+iU~RGgYg z>wUNvD(DGY!}JY0j(-B`R4vu&3^S_|DHx-9QaQtXfd;mdY~kq+vW4fPfWNc@_#aFK zf1v~atnwY=4@|n?;E~1~e9IA3FwA1LVGiMnr^Fj?0v>~t$f` z(5V^PQ_wX8leGiuNAsEhe}?%%#V`Z^)DaoNPxr-O7Lo4`t{;8T2s{RLB0m}D2ic&t zdUUqOHhTO+Gxn(y56;;skmO>-GU27_d_dyM4@Q6N^$!6wnbG({a6y89cxrv8{^7lb zH2z^b@&lp4!}ob;(5Zh|SRA+F#y~ zvFRW`_<+jhkLO@9D#gCwB1Qe^>JPpCf!qe%dro%z!@wWY`-hS64+Dn)L->b&!3AA_ zbcW@l{i+@J(7g}c1Ey8hL3+|=2Y;Ie^ik1r)1$4!8!?Dn|-$S zl2M)7+DzQTvO|3CAwWPY0ce6hh^Bzg;}85Gwp4TqV#e;Ej~~tp>j5X0skj79fcM^H zd9njm*x1vfhh=C_ll(z&0W55D$HNKwkP8!7OYj{JtY=RJ{8oDSA4&y(^B@ENHA6Fm zKeayyF3|NN2ahxf!iEkKgm-TQ9$}xn*h34H-p^(wCtXfkrwdQ>^hl;{{vw)~OB^Ez zAaFfju300t1Ghczwc{wXWU15Ncg_e$sEP^=JsW&NH57T`i6jc=7xHcVldGza^GtJ< z^e>-JLz~PBsufwqW6JShxn8}!Xo;Rs ze7jloV3trs4auf0BPHeFnmM>|53V_kwWw$>D>?!Ab1tbp5S{}^-j_wYTG2Cet&;bH zGZx^DGH0L}Mer*5^=|xHY9F&+Pn+bt@5O83ZArununL5nVOM6}Xr(@=RwjvZR#Tyx z%~?5e{7gL`i%%V0gs=Rt65k?MY$XAaNKf!S9-m~Z^CV8wed73;e4$5~oipnM&LQoI z<7b4&HJlGF6LO~%gw$upx+fWN0yBs&EC;vmGr*H3U_xbVi=^yWXgnO0Iu|=5U;ZU9 zXsN{{?%gntJ9ZKT*(HTqDN&bhq;;+O>UxNJo-;`la(ek5-u1n^0Lzr|hVAOZSsm-c z9JC;m#%>UH-o7P{T$3#j-&}RqF_deEC3x1%->#+%K_Mt{n6_6)u`aiw)glg+$a~$R zWav^#ehk{(ATni9(3Gw<&A`J zdXf!<;g+3eI2=yxLFb}I-2Em?ojJp|VHZ$=@{FePd=PBd8;^JnuBiqg_QEQmzx{hQ z&RObyJQq>QZp#sUYz@xM3TKzu!=YQ7tjGs!2ZX4BDnypc6l==1kYFbANAMaFC?i6k z7<4j_|Fk!#5b*xtnjVn5$TLf~yF8nAmG!!(bW@&H)~l=ivveI3XwL6QP!AGbjG78t zq&Z0fR6rbT`5W5}qN-**FY`vruZ3hr9m!10=OBNpwLQL1%b&Kp^9tq&bIf0emA1j! z9#em%a}Y%%3Y#FzBTLoRm}8GYl#s0R_=|9g^wd`TwM9u*y!lQ27DUxdIEAP(d$;rc zdR&sUKh|GU3$~k)pmc<%!>$##v=y(=;x3jCq$!s3Z2k@?owJfCz<5!Y8s@L?Rq5`_&tZ;r!6B#un~`pj!Ncc0!ceC;Lc%q5j+7GA^ae%8rw^2U@n0K zag3Kh>+Ffz%wG86^=f?yW0BCC9awV-X^u5eAxyosfEnzCQDeM#i}NC`>38^nF#PEc z4nXEnf$8-(>vj z1#L5%|9salXZ~}E3kk@D`Oj?H|;r!>~TeYoGQ_a*y7$^!i)~}DDj&T07 zdj~yNB(Gm@`j~|KUzz_bt6bvqpT~n_naqFA{=K2s8OM6$jr98Og@#@O+&ii1beOxrIHq=9HI@c2^o`%XkgDCJlr;CFaCkS zo8Ba{uLGRxjx_G`%^sTCFjtIl#f6BRMguo~eJ^}Y&NUx!J!CvK+U*E$=8(fiZ871F zrDNntIP~s3)z|&luI|m%M$MS>nNLdScg{7ymHUg+RHAP-fGdOru$P{6#8Ypw8w;?9 zr#Y|q2gE~2(eraV5!Zc)0VM? zrNIT~*EN1vtE}kx`R0Lpnu$u&hrz~2;eZ*Dti=!f@LK6h5J#qE^*!VW(iCe?Z`f7S z6kV7gXDwerki%Et#;XD(AuJB4B*S?Y@Y2sXk*Y&Poo2Lxh$IaR9%rwEKILRpm5Wpa zOOB>v=WuStoZ_APGG;#EimOe2CIaAV3M0_m`h zSmw5EmF39UJe>Il(laG4IEI)2u&fZhE|*zVX-V7ElX0*uLf`99D)>)#boy)TH@W}n z+2Bd<{g6syFRz|BL)R}C7JAh#qxJ-B9kv!J{lLR?N>8F@vuptolVzdAB6z4KMWKs8 z1$j}-pbYT zOYwhsF#&ByNKXw1?Q*ee)lRj=!3Ej%n5|!|P^!338jB8(P9-8;f2?^fT6^Vdq52ujlKK ze7=q+PdLyc`Pz2GeS4||d&6X3g6)VS2nx}q-r)+mAZv-mbReZu&&tYNnZY44gd?a| zAlr$3$YLOHVHCg*uif+@1zu+t8od6pQzBkEkT4UMaU#?KDe%(Iq}J%Yw+F8;D!rm5 zN5W!>Hkd!P2+OqP$kX=sDFC??fNX3R&^_368B9rV!S3~&#|E25$@R!C^_#B=HkIiw zUFFLl{iR#|=5fKMU*U_(=crW)>B3Yg9Ea4n#!#(=B|^+EmGZGMiT25&CIK^T^kThm zCQWd`uF#NR)4ou>;DQlQmkGfp)++D?DpMP5>Y~3uZ7vHoeJ=$$vBI#St&f4+fnd`a zLP(JNl3>%xny8xG$LcR2HyY}vzku9V2b=onFWu`mqw^rXcxVrWFNfFM+%?#^io^lE z=i@Iwyk4X)eYC&-U_<*Kx@p?yYjXga^Hru-d=1)IFJ+zt+UsXh)Bcj0?V$Zp7kQ;t zc1c`}@^Neu=qG}Cc(AEJ2wMu0_YXGhg)fxiD#Bgf`WgtkQ|+%Y)-`Zq?GeERgS!l@ zsV%_Yt^+63_QBt71Fx*@jlbOoiVYhqHtY>Up*i@=52-a*U&iU{k=UvNL$w#WCQ@w< zUw4vHJ1|0uLkU#V&!nc>krTJWhP90*)nu(2{C=#|m@WzdKSYOSnjcqOJm}ngkU?jC zmqZ0*6I4LH4k7sZU3znajy^XwzQ1}ZlYG&H?GS=~f{qix#IEBW(yr>V#tknDV_rjJ zPJe0-81yjVsxb>ptQ{KwsOv95JvRBm}-KHM?@2LLt)TA`I663K0%mAi#jTSM3-I zZv9BLjm7MN>528)l^Yj;*>J;uc5rN9HY*+o4Z_^w^8+HXU<`t28O?dsh7 zzHe9kH{t7jqw)2)!XMhzkUclGs}slJpXR4GwyTD%Kewx^Zw2;t;GdH`f|3WBQv=p< zREtsqvH-(C!B_WYMFSVThG?>-_694GvoC(IqJe^+`6nljf0|k*jdr)`1{EZbhj1}V z%2MAJX;YhzJdw?;tYy31KfE{VrN9R(W@ljxZX6_l=)tS6`v46_Oe&}@FG4uHTD|ay z6prn{{W0D(T__88V>pBf_*@KOeH6ytrLd2_lTP;2mKZ{OHN%R9VN`}(mO#~+54H*k z0HutjI>4!2&`Il`O%H4WGKc>d7cvi7Q@aO(+iW=U?BW%{+gmVeA|Klqwf>lj-}9*8 z4eKn*P?$0lhRTGP6XxhcK}t@jMOt%^Hdjp>Yf7xhmwb3VA6~C|Ve&us15=H6YU&n| zVS-8p>0e2rhCx&dL=Bv?&|`mf02Dafx0+1K{&wK~=XBZ?A~^~+vbc;Yb-)e86 ziIX>`yiUr24z9J^m(WIxwkPrPHqB2MoN?#_GE@W@&=`1v?$6iV>p90=!PsM9cxR%3mi1|pM&u$Lxc8Ulv7O0Qy#%gG9C`gUK?y6}0sZ&Kkihln-tZy0`5byjfO+!%AED1)(PCzzaLjHGjDFk#>9(BU_bibg&Zs zgW2#sjEitm$7+vv$d*Q^VYr(rG+%nTFVjHOIft(xXl3d{R#bsA)k_IdF@6!)!g7Hr zA$z5QZT=4$HZe8%>=<%IX|w|y@AkmPp>@layQyJ2Gy~Ww1S9}iX<&PK&s4DWHn70} zNjS;+7yzsUY^(40z@|5FkfFuYuthK1M!JE^%|sM4e}voVDQpL}+(Qry3rzNjlB$Od z>Z}TA#Et&R56SlVVZP*xKPitzu)r|2XCzQN-!xfV+viiM@V-!5QMsBdWU@Jnp z2E_a7(!Lwo@up!V%qmR&hzeM6OCB2m3Evg-iJ~Lwtaha6BkF|PakDdYww@yp7XDC% zpv*8@u3c(45BQuE4@8WG^6PsIaDgDj<8zZ^r~qCBcrZd@`bPr0Q5CX@rnzj`(xvtQ z{0Icb=UXM;PCPKUpm(qO%>wjD0F46}MiS^k!epZR{qK{(26Zk#o2Wta!GrbBqRHzj z2@?jK_z%FS0)5LtUqFHVNTZncR`O$R^tKZv}eZ2>Q%~qFhE!S(? zdH=eDLd-B42y$qoL=3M`OI1f)=0zem$B-A0o(P7o)J?$WXD+3BZMg zc#w-+_4xg5;=}SATWZhosu2Y3O)DZA1<*H(pp}DK;C;!Oi3bH2^h9w`1Px4SUx`QS z;NLI-A};;^yqj3?S8;+NPypNbTyr*%!nuS_aGtE+cXoi!2Gk`J@S*3XItxCZf*JJ5 zz^A5b>+()9f+UNzn27R!&mM^wd5}?e2}>S73(%MOpihc7zS8hR1l;jRfDF;=UO=~4 z&)Wbtn_t9w5^~pJ;tPO^&xZ)9pU3#D@wVs|o^gGKc5JY2)v#<(w9%v&m||3E2mqri zhzXl=)TsWlftr(m?_0C;{#nMyDehbi2DCP=c$E2RnY$@yEbaTTNo zd^rCBJt`3`OOHB#lSTn{r}o3n$r12Oe9!$G3q>PU-qkuDBkzx)eim+Xqkt#W`X?e) z4x}oUs+A*w)G>z73HapccnH>paXs*XK_NaIP5g>x5J~K9FcZrcOAsK`g<%51s?t!PVpq0;~Z?{E_rW9snG&iGzCVd?)HaYay7uD_=HSofnxooY`a^ z1V^-+o3EeuEbAA+rvB^;KSTQ=akQQh3+0Vs+{OmW*zPyjv;kf4mW5joM1mTz3Zpr_ z^)n$pGv7P|E?OZz18A+{XwLd)q@5y^N+$AWu#|fRuhBnO;pZXzIfS1vJ2hMfXn-38 z9@S3b23#&Y?@Ii{nE#UE|H1|m4?Iyvc6jn8-3lN3$t+*VZ~d#-X5B6CeCFJVT}yLH z!;PDOnKxf_Zw~a_1k$`Y*S#qdizC!kAsTN+-J5!$FxV6u0f{H9&>Rp<_AFPoodKzN zy|ehGg=i<|wA^0(!KX>hiZCUCJ2BUQJoleV@>pSbtuS{bJK7T9c5Qz%8koT6(SJ4y zUfA-No?f2h3|RemEk;18XYd7=T|pso@?SokD@|$q`|A2`VJjjX471ufhe*Fff2MPf zSz4|{4QlS`K=mN4APM@hht>}WoRe>{uQ0f;ZIVAu3(ojZB(xe@R2O0#0H|2z?l^X< zTj_XRsNKw=M#w>=k!WWW0=U)iy!f*Uzd$VzBbBTQ&dB3){g(KH!u5QZLrOL|!|lX_ zjdH9&l&)K1EwnIRw{R<&$ABlo3pRB=!i6meSg=9S0jp)NbI1-IlIkr`37I7ZlcW{x z;jM@?TaK2d9xQzTP{PY-!46!1Hd#&^4R-0|(Tc#}(H`u9e$|MLTKIq~8pRgPPu)uQ zgaX3t!csn{txMoKo7ROu;KzLasD8T2vxRv$))QP*b<%)l6iXS}^#i~+0U)GD`j#Tw z>)dh|ZCPjv!WRe7JR|@zy!ir z^m}5#tcF-Hfl-e<@0qs@qC#$I-CTfF03Ej8mKa}bTYoLLB=tA_xla1KS1fy?KY4l6YS;of-3hl@b}}a0n>mgR$sD+mHoSD*)BPSy5yGcWmLct2fUV`0LH%S}n^HPZ9>E6&q0&Jgr2B#Nt z;!i^To7D(n-LSZ;Q5Bd7i6nzFHlW*%trrA(O~fl;0_elbye4fFTLISE1ldEoq9YiH z=txM(C8GoP0os?vjflVe6H9nJ=OnUz$&Vbzj6_BE+oiP*JALGeHPJRc-j=) z;;;v2+|T#Zdw}V)w2H1(U&QJ~rQA{g@<_LG-`LS;sISuu=WwfAr7 z|5hx*fFS|}f^W~(qq?}tS65egtZ{j3i~4$|CWFy6$_CW2eg*}`XUC86y(t^Q>kewz zfy@DdBUL&6$DBPvz!CId2W~cp-)chVvNzgT{7psZT%+`fgjUB1)asVuP^o7i0XkJp zrB7!5f0*$>G2>@YZzz48uYMDpv73l@stS%cYo4jle`Rx7!O^I{L)Kuw8kRta@i)T! z9)F`15I-C`!k-K^cf(t%$2Xj6F%)mM)IeCA&f!0xHf{xJ@>xk*{JKxj|Fp>?=%`+= zpunRmSI9pv(?Skth-Cwpx(B1KkjD*R&Vx-!=HT4RDHq0WS+QQUeQ({wm(}6JK;*RZ z{|~{e1=y=<(iiCj{{f11hQ6SbaWeP7om>4V&&?;N!i#T?ISo3WDmGjKr=Q+H!(TD-dNEbZhT!XbT0K{u2KM^G5Nd zq3!r!@sfx*VV%0*?cF)9}Y!Nx1);?Q8@DROaCuu1HYVN1Rd)?BOP zz81z`l2_d(t)*5qcL6?+dgP(Q$usLKm$0y z@Ip+vg9J9T^$RwB4gNN?O%2}6CBBe{Fa=BprMM`^k2ITWe`GFAN#qlhL-qB?I++If z7$`vNp|j%9ohpqTn7C7t_dx^loZiHYdcY0~d7*G-XF6FTp?dV%Aod1?s@;W{NC`<( zjIf~{3D?zxuh0&9w^H$i;6l_*z(es?L-;%ztP^#VG90yX3bpd6l#QT`fxvhu`_$}Ot0SUBW=lZ%;eF$OxlhU z>$P=hi4|{^B;i268WZ!Oh$!Exj`d~eX9o^HB_*Bgz=U)+O48lPPklpZ>#(RN;dw)~ zx5sAFmpk{==r6TVYG^yLwvYR>a1|yqOWns;e&c-wu;(f5&$V5YnNPquon5>ec8@K? z?Is#4%FFOnbYS)S_QkO?P%_0p1}}ew%Op1-!=owP0CJ5Rrpoa4DdsJ0aTxTLygB*8 zB=;!8E71x#(Q3q=-`=p7yu7Pe(b!Aymi<@8UZB&YjL8f));T2IS65&LgX`|Q; zG^BEr*WQ@qD3A2L89U8M3mA-=I13BR)lUA$4g(zOvlHP+k=J>nm4tfkq>1pQ5d3if z6uuPh(;1%`@E?cmq1xdR@xcyy?hpGnW`?bDpBH&xc%^3IMR3g?O0G#|fbBM5?v=2t zrFEeyC15qcgaK4MAAt>O)9Zi3a3oml(Tw)2$h?Aj{bYva`8-HE<%rLBr6yxn#O#l zJSv$e;gY@E-ZF+-qsO#POc+Vj!tu3f_QTPM_>!OO0=tgRi&%Wk;5thU4@ zC2$j7i)WYv`h(Yh9HKS!F6qngY1%TfZz(zn)b^|2aye)54&AlOz>915g30Dzg{d{OMrWiG#{np1l`pfoiNYkF;JPUAH z!l@(KUZE8+qQtOSo%5N9(z#)6Has1rc(^bfOy3j(=ieC1BI%hQzTor~)T$KYH2_8} z#ytaLu<3L@2sj}$xOMJYzomHz?%P49Ypblos7x2l(#$~WbYjxLIt9#3(g34$qgQ5V zDoM#(dM6lFBtOoF|5V6y^dL>9YVt#m>fjkyNW&!v{oH=!_u6%tB0c0p6kQ$#ZbjfS>fwITo-HOiR?z}cWMx;*EkB+S@k z{NX);k~$O*x4x;ejsv^*MeLzjE&s;-3FI+2Jw{3-%#oJT512ag6PKw4k^?=Chn*xa zh_T(UjP2@S8cCa);t$k*($IFq)XSNtB|d6fs~a|TnH0kVHDA#F7wei;X|W92fXW!J z*|MH?B^P%KN){(I!OkIm&KOZc+fg<5AR(){1IbwJyw;md%u@?dH<1uGaaG?806{kU z2$DdLwVEE_p}#&60X@cltm%Qqr(OiaYIepIMw&k+2P_MZfI&Yz?UjlB*&KM7F0^}| z@`|@bB+7}9t`s!19a?jEL)++@Kx_&CcRNsDf8@Z>UenC(8)6rD9}wq*@Bs5+|0M!b zFi;DOr*Wl@0U5gCwM2UtocXV&g2?G?TZ2Tz%wHmq$>*21 z&~2jg7f(4SD|P{XQp=8p#JoX?@qaS#7lYq-Y;_0zV$k(owUYV?gg2ePxY-aZ*@OA_mDXP@C*4wxkJXVqFfkCFVh<1}HMCW7*vX`R z#oBw8^Et5uIfUg34NH}QrGkzzEaOCc5#fSNWx*u72rXIQu(@6u?njV1py3FxpUnsj zJx!}Oj|7^1v|DtU?&J5QbAW4pydHp7LJe(WY7cj!qFz!8z{G#(wv*QbGxdk9dYmV_ z^>cnbE{iom=sX)hx#K+a+P}3bNti>Ew;!UBm zcG<|gD_L;i944!l+hiao2Z$KJmph!=L8j0`@h3!M|#VT-{PNYP`6e z<%?O+gSfqS?b%taZ>R?khq&ATTj9zIFXHloV8iU6c{0pS2m5EvVY8e@-;K`^GiXkw zpeKIZ?t7y;fH@WdUMq_(jZ-B0NS_{`>=_PJmzm%iE; z;iVPquYywGgL3Bi6a@4&SD;PYjuNJXWgxYxjno3bt#fdI`L|D?HF~Ft!f0Ms!uwY3fmY3TMq@rO1vgr6CthroTlw(HEldhnfwzd&KnMpK*bl*NB&3aQO&T~({mz8rW86+yw+G6r9#90InD71J7*Z`e~)|9(K* z(`K}pw*DO@J<1{CEJ%YbH(!jG`hVDeBll1pOYLbSlU8fppmh(b}}lVP$k zF$Gf^k>-okbXplZFlM^3jl*3?ASNwr81anO9a_jMY{x=k>V{~qSV_)C)!Qs+D+#Nv ztz;c8U?q#>HCoAF)75+pjcTaHSYCW6j3w?h4wrj*qxjwKyXzwC1_{bF^^%_%Co{mI zXc5y{v(YQJ2&c(sJR~s+kcNsQ5*`}Od1~hDtkdk?tA@ckpIjR0zN!rUuEo=(4U4f? zxsDx5+n3Nj2(R%IZCzR9?Xt+qvdBy9tDHht8QTl8rh^)gR(wC;3PWd zTr?WQu-Ap>8}Dn0t*pW=ET_0hHzX@D{$r$+vZaOD*@I;y8Zu#gw6vI!eO&t&@oDP% zbJA&lx@h%~7!O8P09o1tG}(}Mrg(@f?7S{Vorc$54mO=_dYvP$V}gBjeAtR!Ta1Vw z8*S-bn9A(a5%I4H&JwMZ;C)m$+V{1HZ1DXfVwVf7NcSHZ=L>K`iF&+=-+HTA34j4=5+xsNC42$$q=9G@xLKlWDThG_7R{Kw5=|- zm68jcolo3E8K|2l3t-|m%vSWzSP&f%Z)nQde|0qFx`m=Cd=Vm}IZf^8Dh+7yigoiS z&|T6GANizJE6^PL61$TUoQ7WN-+kbo>M;!>9$$5sKb(U{wd=zAqY$(n9vHUTpFiA! zMmxzLB<|Rj`~fRhLNH}NSF&_r!V-iMforGJM}yl4DzhQNke&`wgy#!8O%Xoa7nC>` zA%V_&G?HoagLd|qbY?0vf|f!`y5%AAToqtqiEc|1i7`5JZV0^T#TB_O`fgbq(?OA?)@BOdqo5bSgq>FHKyI>iNGLsXcU%nf>D zWI3M`6e?Zb0`Rk9Z-KL=kxj9MG%;?}Ej1HbO}p>o6(k9ar%MubuC&M_D_{YU*bp%o zFJUC8SxJ`*4r=bjhNES5Nj{|L`J@0jz5d1JYxFkA7vtj`al2YG0RqZ}U?hx4-#uDemqD&A6iY(EGP*^e*y&SI04twfpXXtvG_O6p5LDi_Iec2tRqXhBq?+A8H zNjBWR-(`We1e;;YW}UQMOEwV z(6&E3;?&j{LqJ`D6!IwTU3Ymi(Ysp2yO?m>3L>x$M|m&hH>HJYy1Okh?OJD%cf=gix)b1c>JJjmwn zL^dgpxnw)g8jSx@weoJq?6H6Jp9$jwd^tqZ{8GImSJ+exjTMSa0RiaBIJDn@`F{@N zxJSr)8OTGe@2legk8gaywVpI!RBRWf^!g+9I|(OJ%=cgxiEe?Z4s%1$lEIUVmi&Lz zy$^hy)BOjYRxfEaZj_Ls1T`^CYDG$|x7Bj1DYsga78B-AMiG@%P?NYxC2pU#rl_fj zjeYBXH(ghBq*`st5XIJF1RKwlqH1Vs^!I*$KIc5oxi_h``_1q7{odCrx#vFT-{*Y( zpL0IvJZ)hRUlyS%84@C&hKgG+F)mZCV?09f7fJp&h+zl2ibTsOij7`5ABnTzb}Ql z%lp1-Cmj zaRQH_%B_B#453cqf(d0H$);qieutQWWFXR$;-Wn=XK|2I@4wj(INSRBUUL;+0Ch4H zA=X1H*iMz|E_i6bL)r-(9N_vsLnvXg{l_7KNY}5C2sYxmvuXatJi5=4A)(`>@u?h z;H*3j?E?avd3I@fB)H07uq$x&2K0!-Uj!3G>t;Pi`0WA3Usc9>a^=^YslpSv+(bg6 z0ht)+>Pj4|E5Iyw;dr+T6e$*#--zDG>u|ZWG7W+Pd;!g0MQ{8}v>{H-l9=2!v!-Mgg zSWLkT$A5MA<0qKz_;YsMw(%P$u#n@=%Nl={{rI8Ea|P)KHN}6{Y$P}Kh~6Of#fyIv zU%ClV?4RO(pLd|Z=*jSSG^YDo+DHtTzR1+E*=*z=aiKkCjxvybGdBZ!IQHeaOO06` zw3_zil3E}GC4n4zLEYGwTtSOtU%(G)UubAxUy9kpcH5UJZ;&gyvoGaAPQAa+X_QmH zrZ4ci0D_f;&nF05GUNRnkcSNWl5p%xJg_g9!oJY7bgSt1F3VQ*RE)(mLnZ!RJ7ifI zAWf|d@GP4IVnQcS%c?P(cFR_*jQ^{hF|0!zart-r->p3;|I*llb4+C8f88G3*4Di} z*!L~a(2HDkiLnQ7z2s<`1gTrAE?i_PStP?AC|iYlkl?Bed$77jq_oQ(hq~a``3eL(148{n8@9L7qdqx_I6BCot!47pR_0&=i$R zRErmR_E{AfuKp#ocE5X-D+<{JOdyo4w0i7Mlrti)uhoVs*ifY$5%wa}oQ9y)3C615 zXhZpI2>utQ27;zf&lXkoz)s+a&+WoR7C-QWLihTtNTyb)(_s3sXtUbbNttr-`X}?I zonGI8*1zU9Ul;%S`|N;h!3z1-zdmtU_xkijY9=poa6c~U!oi>UoCN?) zBuIr?)u(@`vidaIC^0n}*Fk3r1<)B5t0c;5G#HR~b~Q+aaxU&xA{X4GD^Vp(#8IX+ zl~*BU62&MJc;LmDWS2*_L*w3QoGsC~`+)Vi+A}?Pcw;y-zrsG0aix#v6zTAjjT#>K z%r>auPoDa>YWPyR<;U~_NAwhq5V^tq<-F)^51{(VgmR_M(z!;*i^SKR;XZZT_kU-f zA0z>~i3hjq`_V;-!lnrW_q2X`AtwA+pJyDhmNtjlSQlx(Oe`S%ba@kLF~|fsbFeH4 zDvNH3;~w_1fqOQ|hV%NK>aT*F!Yz}rJe0)c!J;8i9`&iNH@&Rg6m>r457+^i;nkyd zN*d}TXvPH^PtXTS6YKHq>=y9^ZT$A^cVzReyiN|x`p!xR{6s2m*8u!zB^NOQGT@;w;HSK`g!MsFgFBc}BJoY@69;@ z!Hr3>1Ng?e;COvIUjor(qk+>Jv&65|Q?1Yf! zMKV~FVO3Ns_8625+W~EyTO`kH89Q|Xgib7M&uGS86@cJQCqML(WFZEv^IZk;lp$XI za?%v9Yulx6)4@0^vMj$;B&1^zRWpqjf{{`}o^+M9GQ~ zd%;zhqr0i-i|zBn!LtuZXZ6Fp5T-fb3X^}}iJ}RTU*T0rG43@tuKM{tLO+C=CJ)9F zo}b-<^RqbcQVYRVKY$Y%U@TwyN1`x>l>g)Y_Wiz)j2KalSF|HC;|Ht|jll7>h^0zZ58o@wH(nPz}>z zHleo>ZK&73VO32VzV|}?o}Ew8M^unyL(Z}y1FtaTN;~!{N#FwKC6)tO92m&;54tmx z{ZNa_0WN6dz2h9l>rcc$6Ck&HuA9+UxlZf|TnCrJGYo~5Bf4@OhgE&7!4(NItzQPh z($7I<^Cd?wr{i>Td%qlJm$!Dl@$Hn00d)WD0zD`XBV$utgb;mDybNUcw~-dqK}ofYT?j0p*{)pldE%wy zpcsg-6!&gK?`++Fsg!7n?JJ==6u!uHnt-j5_?v;Lprv`=iDu$ zqJJxE)3fn^HcTuDSaU8$!w=O|i=@a>12*1z0)%{?hF5vG_X}xehZe=Nu~(eRP!rI? zF(Etp{uy(X?chjo$&K-VlTaccEU^;QTxw%)lDq0GI*4&6ZD(LcX8=@)Nv|8J7k+^GjYo7lY44{(z<2 z=Ka*$*h%L52)xMrn~X<2Yl#9{g3}P-tX#HVm?~I&o~)5zPJqsKjeA$aQdJ={cx%#9 z#J}^cNl>BlHuEf%>Zy!=zdg-0iy%l)1lCNIRXQv>-X zPs3H`{w%lews*Yd{a?V;WY}S>cL8tW!(d8)#vni%Wr5~#6_8AsQwV3k92*WsE#|V* z=)UR3VG#mRzutinl$d;+|D>V{XuuLiDsRrYcJ35yoKGYJe-Lb$dE}elXih_*Fc9uT zS7;rsIR1p?V|WZeWQ>fYjA?!`^1&gpxDG9c`LWXZMfhC5ez}5J z90o|C2Qt`2LC(##4q#=@Sev6eh?jj1nq<8H3nc!V9ND!7k++I`H~UG0UNQSg8y|OY zjkSg13XAK^{Um~7(FYdItNMz(D0rn820Yo#dP-cdpEPlqHqZT(>;8!WciB&3++Mh! zG*GT}vg6MU^Bnoy+WzXp1o2zu>o%T&>@KW@ndN}o*NF(k+=$C)Yw9ZDq!O(lgpmQRnadOFjcejt<1~{CKMGL5LN^ zveC$aEjnLc#<->WbsZcV=If%!FkhE%>+7a+F=y_B7pAhTmv`@A__-_fR(VPuU(_vA zMUV@?No2wjF_3V<9Zj=&U#n^IrYxX?*H^9vKoxTD(=!$Bd^6_kBN}EF!{8CG;Iw0i z)j1|;&AebWMFA_g>S)bcEF&^gXJn!SnZh?KW$y3Stp}^`ZCA?G3>o{=jXa}S!~anLxsCkaa6YH+ z7-O_Su9C-~qK(&!@1_>1%4z_Zrt%_shB7x1qqIYmseSCKn>{R&&G70CwX#bg&J*TVuZqqk)>YEp zDDig%nTq_T7tp=DM6bAoAfdk>J-2bbb&lqwOdEu`tLLt32LiR3e(~`VGNd_wl`+} zImk2wwLmiSQJd)yREEyXUj&&#P=o$Ti~g8Jf1QK=7D=l-iLy8HR08z(d(xo)>fbr? zRG!Ma|BSBkRB7Z1E5|}4NT|wF%*xZ1S}Q}I>R4Lj>2%EvO%i#^ z|9IQwNvo0ZFUH9xae^)SO=Pf$%-A3^kS7I_HA`%!gZ?sI$V2>RkV*9WgFB&1U)r4I z&AajU5?^#LRbS@$3NUZEjW2?c#MTi6*Kb$}Aw?FrU!qVY=8f@Z$SZx?$%Ee1Jdgl+ z`?z`F0nICljMgl)R11%N1N7i$(JP2OS!jY}~bua7BakQZG7qKqB7jzs2CD+H)Ej5*f?IlojDNc@SSs<1if3j_TqnuFC&2r}h1@AK23=P*zKKU@|`T6*5p{G@zUFrD;*6*I4ztpU3 zdM5R87kVDIZS-8eh*H`eJs${ivgtY7=5$BTD}zj-=bR7zyY&3~GKXea^ql*olb1!$ zX>Q)P&~rJCYYII(A0#~wI&E9%soqU@^7)T(Tczi7nw3q@$MkU*dXCvPdj3&WC}f(|6`lzIZgF#6=x8YTn~Xpk#%(#6mC#0r>=q%9mlsM5;jq8 z6BUy1Fma&8fLoU~?>O^g^=et{^b5_XucBRG{)GGS4&ju7(k?m;N2=eT+XYV?y~+!N z=&z%molIc9sIw;~{JTEQo=ns+-_B8>9Zi@nS}R44RE3RYTak?zxPzL9!+7B1Xx3p!mC>QSOU7t<}M9E`Zj z{YYcK-9Dnb1e7`K-1)8D$r$VrBQaAGVduC@ZH~S}&PD@Bt_yg__c@ZmA43QFH_umO zpsXxuEj@)Yl0Y~>xTJ;7WQ9Slw}pBF*x`~E45}_Qz-?*J%8dVjmD9B?tXN#CkLk_G z5)9BSuFO9^pq1PDl9rGq*MG#gVqKTC<^(xLih^aZYiy1#Y2EoQ2yk0KfN(uS{1JIa zXy*DT2n5-{-WyNmag#OPj1$z$7diOm(#nCq8HW)d=j8uUG=erDEaPI#Nh#oJd~T}X z;;~#!jW#YKcQ)^=YnwR#-#i9OTVs)lcjN%)HPcW$AO4>_8BauxG58$=iejBY79>t6 zNks~^2sPGjXa42KUX(ETJ0_NL~PdfABlNIbSa0`U?Ho{s#hNz6E7$=9NDPIb7osQM-YpdC*@s^b^Rix=Gg@dDTMwsQXmCelF&2GZSzZQ!|VaItTsWsghJ zhBhQpF&>CAFR_U%^$v_~WRX;pU=T`c<{kXa7ft9Rlat)E!V9ynScn;O6|_-clRo_I?%$iU+rD`DX@;_$VwDVN-okBdHel@sF-gfiyr zzd!mwvp$d@%Sd=)+zu*X6XiBhVH1^_aAJLct2REwhj`<-`C*!j!w=IPl0rH)u2MPG zE2ueq6hs1g!JDTGNi+}suuUHV+>lSJh?Cm5x6m+afSb(-kJsUftcV&J4sJAz9A~`* zPIz)fF{t#cQz_16gSi9{2yKz?YQ_Ksh3A^WsmQT$2p?EesOya@x9bp6yLosy_MXhL^9SI3z&7*z=Y4G944ywqcwR-0uOc_Xmn8%vi~j!?f~xO#Cj`fS zv5i9TIfCuCTL@a6O8-^}ZZU;Zk)uZaM?!F#?F~Y(PS?usY~895wBDZ~1Xrwu5c~@< zDDIR$)c@iyJxZ3#eCL1{Df}f}A#9Qk`<0rOTybt`tV-xFrt&Tv2_I-x4c-_fn^w8} zjv*_?1keI|mp1}s;C_~(94x8sros(0`&Rna0_(*X_i&bRz4CE|KjmCor+-ruq z;F24Jj;@z>_6dUM=}W#v6@tPr-td3T#cx&g%@VxD^u|9*KK(X2k6vECLe56$V89mY z;ohDH*jF&(Zue+oHERF{C{ghwWTBh>4;PE+{h^gV@7bl5Y5Un$Pz`9eppOPr*~5c( z!*=AgB$cTVhyzyH;oDM@&*WRfG;fZ| zr2p9zcx`$&dyXom%X$!?5s;>?5D6CJ4;v;cyjH)QtOvh6 zYZeJxJ{uYQ(5}+}@&n6u;VpJtwhGa);EHS%vO2qCRaARIj*J6^V5(d@G%aI?1~Q{F z8+f#@42?1iz)R9!iAsq}$XWs~#YxxUfxmVyRqg6|qzm}$pw}RCv!P2uc@zDykZiQI z`}=tl!O)m!0a-S$WZ{*uB7g)|w>~~K1AfSmz>qQe9*A*l&DtnkmSZ@MXSIzy9PtaH zt?xj8dX-|zG66*aWfF9Tn%G;iRT!O%2TwFBuKjUcDwVTR1XJD4Y*{2Oef&JaP{CAg>sVlH=b@?!+WC zhFLJ)*!t_$fcR{q_O}M_!DO+_`=}vlEd&f7N*&S457P@YDe1*dy49wEvO1*W%`k?~ zY#=y<9`M3L=H)bqGZKDHIG*pXdRW!SV&H6HK)h7s7}f?~8al&q780W&xB59j^~qqa zBrb#|;VcxU2||%#Xj4|@1A@vXCRT|Nddj8#wZKq%3ef0}dl?8_lEng9^dH3Rd+z4^5|INkOrNP>=A81k5i;7@PyQ>JS#*DG3Dgx0BR0K@;O>!BWK}h{_;%S+G z%ZotpBV7=j#lK%E|3d1hN3dRwe?}qsHy`$q2sFglcw7)|y14LI`-F-I@kBfMqk&X< zbM&83I^VB`If&w=8^wI-24#wpnSfrb0huC4U&{&@D;}1x0>sr=l6=4UGDT7m-7#o) zx&5mT&OZ&IshpIH?t90ZN93k!ITMq$IyB%7T(RJ`9O97+L)B8N!gd`Y%vfb|5qp7Hv$s z&pS9Sd?;#7{3d6_J>!CdR|;_}Og=NPZ?d`)`Sj{O-0h<+#Q6p6+SW{Q6&{SpqnEvp zA#KWK-TojJ;#o~wz%rrZJ|T0CQAn~WZiCTz#Vw{U^93@wa%P??Ma)T{9_H!Am|Sc2 zr(dnQIL0Ah?l%2s@|3wB)0-sT+f>e~R*on_bMWiVX9;f-7!g;9afjg;W;c((s!?Q( zy~}6Xm0ee`>jtSjTb=n(Qg=cGSF;#&7fGkW~4#9(FbexJD zhk$`N<)8y_=xCR2Hz4Cb^u+9ibix4;ul zf%KIkt}@|s%iQLcIoybJm1xjFe@t=9@Lf!D3lC_a*rsTm>J(AEiV1l|9Jg#F(p6Gp zFu2OO4&Ft_qlhH9Bt##~bz`Hw&t+=9>J9j6#4R{Zl%#)`a-Km3&A+x{o~P zehhW|OnGkP4zO3HALbb%+JFEL7fTt4sTI)lWws2rG5nLAzSGOU+OlP~zi0m}I{K%t zgkD^a@SZGvcq6&7i@%@1syw-dDoU;+mRkgQBO~rtzK`2GMlInyHnD^0Cf|Pwn}E1@ znnhDx^<%-Bd)+G6?4?!YPSLz0WnrnGVKgX3>;DTgNMnMj^KZo+67OKZ#v6XX?>jbb1R&UBCG!7nVOB zZJa@}vra7&&ClaTi1CvUurcJtntm&E_JO7*Lza@b?5uusdd)6Rnu`QjOHOHcc{#n| zKH^U1#(mieFj54JfU|^l&}_byDZGnxy79!^<)S*AfRkQx$v`dGFiiN=ia)yvT`ZeOKx|= z?X2miMAzUV+@I|DTsThkLnb7-oj?tD^gGxt#KB61w3a$;_feJQ_t0$NW6h1u4G<{EHMsh zf`JS`oFE-2&G+{jforTl93F#=&S`Bjliz@{aYbF{B95jdj?1utKiU;#ay-y?SjuqI zgNT^s=hMgHyDOLYW1oSH&3D$wL;3QsJ^<~hQ?$7Vn1G+yF7DVv1KarRnQxfSaxgqU zG^G_znk!!Rd6koC0JqIPgstN6frVYG-H>&>#k)%{h>lOdv4jxarEr zxn%2#RNf_r(E-z_l5vm_@v;Oh5?F$(AMl9h9dM;cs^EAjJ+X*8@3}0^)3QKPyF~!f zYn*h4llGnTdYewwx3dSZ#>~gj7a%c+x>tVnszc{X1ySq*h*~O$Vjs?^H-BPBt)O5{ ze8*_RI5q)*I!GFPw&ob|`9>`wWpcU!Zb#f%8UpueE`Rk3f$L!N7C3sh4sd5Xz)3m2 zQnqn5M}Uq?Y-dQ9I_a2`jyvguO*@#oZAY}lo8c6hCMUTO{8r5@11TK2Ino~?tsoPz zLkH5wJ`T}Hxad*(bgNNxy?igsu2N^KKneSozfDa*(};={!k}DLL+wib2v;~xwzVKH zQZBi1&uGJ&>;g}uOSB;OfTJ>34an*OLfA;eX+(;mN~v_ZWT3p_9#y1jSY`D`I>1z< z`Vh{DFrg61zqt-10}nQS-+&K(c_Z-dq2c;=G%93(up7=l7W2gkcu^Ww9|}0oI)SbXuS$bW8VwC8?>q=IV5mD% zR1K=ZI@iD!Y$+Rq5g9v9m7dQl@BjmX*!(G1srf9X8GwXJ#4xQmW}-Ts8jqWq`vMNU z^Z?^Ip%7O?!AKYl2|W*_l$Sx-YgC3k%0*X>zVm4UjkKx_c0Ns{*3u01k|lCT4Drqn zB`KIbfe%EfpsPCO;WzWbu4&lwu9-&PK>P*x26-&t%`ubBjQiT*I_Ls+ySyS^;n!D? zc#$`Mowa?doP!qq9y5qeWwG=c&I@o0g539x{?TZzgsamrLEjhwFl!Sc!($gH>bQXHQ**Kf!BXU8^5O| z@>2!Xe43h=;E5(-@6_+sqfgG0EBS5?o@iQ(2jIIHiH?^PjgIp^?nIfF5cPjMId)~N z2!(P|1q0C@auPHQ^1hqqax5Jb-1Pw+DVUw**Ap3$3!+>)Akx9dt*9AK6^!OH1nj3G zZy%&{=nt9EylaDOWL25jGrB{6;nG3D?@-z-9kAECq*9Yox{M3+x_yly#<5~%kuL04^^yoy7v{gbj5K37p357tN^o{Vw zq#8L4L(1`ccdcq^-hC545EqkTPoSQ=(G1V_Z05!`|A8*~)4=QgXJ4=53wu(-fq%24 z4jIiQ74f0G<~!*^Ctc*EMet1d1<>vMuPrBCyyyEPgsw(?%|~&+=wCuowRR+urS1Yll{!8&=_V&V+ey!L(k)Ip z2Zq?zmG^m@cJiI)g-*K2rXA`Yv13SGwx`tH^s-V{pCF#VP`Axcm%TZ@$s>r|x73v) zpsoziP*UJ3FO4YE+U{fU(`Abn3>Ygboh!q{` zN<(1-pCOoCK}Q%K`s*MLy(=mRW|mXhW{RdSJLINOK{D z#yQPMQB)}=OsG;K-wU;BSY=;RB^7Diw|lOT1{|)ChQbE^h6sC?E7}D_<%%^-hedyH zil!gq<~ZVW?#SW_?TYH*z+?tja7h!~lI!0ohfa*zc!zt!#wLoVO@GU;HRn>GEKRvv zP|jcar7}`oI~asKqZ?x;2pSA9pAY#Q=><-Dv6F6f(rr$<#WDulancK%^kOI7YST`T zZhMcAk=ULx(l1|7M$#wP7d4F3VmN@kIVe6AvG-QJND<&*J_ltONveY@I9PH82TDeg zvLU5%oo1vcs?@S4RH>71y!MAx!z!dBrNQj1{_9`hQbEsmhWUJ`Ic!~9i_{U|SV-s3kdz#`5GAIn1N`Elod3v(ak z>(qi0i;tm5}gTWe=}0An}hppwt|c3c_g^lSxj~*kEiTgG*8J*<$b)DZUDVUUTNM@ zE}qm-LwHwo;AF|ti|im!V-zw=5U5{ylTe4F^;feEnS7(~e8N+aD)7(&JI7oAueS+0 z_kJ!e{K3-giAAvEaQG1s*{%&FH|`W|c!y~8B2ANtFwQ>!Ppx1Pom6DZ!s<|z9|~rZ zCM8V;$q%2;)g;=o3xJHa#1B?LKR=vI;Q}H(6SSV|*O|=+gH4oGjcaGd;ovcyn;_Rb zL%k5re2qbvF|dw}0~OtcA@o?Ag~3+L?^2OT{f%%4T;pU5{%xlJ%@+IttQT&NG{J>WMOQjccg4=8+1*#eA z1i{Mh=|h5iT8SEI#7IUU6zQ)pyYibKg827BDsz7Xd|~82XWQi8Z-0pdMt8vs1mQ!F z47{JS8|hy3Mkw7X_>2Yh@+R%Vl~XM1^f2L@Xb!sqsk}jZl7PB$I!c5O8jJ+eBY9YS zgy@--Q)wU;!UItfO)X^zPpD;o5WvAgvXFTNm8&c3dl*^AU?__acmO3!CF3B-y@Jr@ zV0meybR=7MJgJ65{HgLntQ$Zta1Q8Q(<46QrRz_Rdne;!L##e6eYY1|EeG6KOgd=~ zjHUzBw~Um8JBk_hvO_mJenf7mU)KV_7(YLk z-`MPsZwykI9Sa=`Rt54x9c+aK?7>qCpmHgla!^_3YfX(DlS?~(B3kUpRXLCpPv`ZBms0>1; z@*dhP6hhsbwCV*34HhDy?wP8fm1CjOP*G9K%m$mOXU841lRc|A8pxBx17@Dm+V8Ih z*@&?J*Lc9hy=E|6X#^nn*ZmbFqdSZr{4l*(lNfgvxK5}3U=~Kt=v2G~ZGt0a_3Wzt z=f4HFwSey&{%RN~@0mPqcz$&H9^7WAUsp@wgT<=&4HlDcbXzCS!D3^>YeNj<375gw z;s_ibEB=e+F;gzNv43>d?euJu8w;Whr)jDX+v1w)A8p{`57ngfW=~E`3d3t#z=D>(5Ap|1j_z!aUAf$*7RGzg#T$2w@j8L0;1KJlDAvy+OovFwb`4AmY zU*s?bS0o=E$MpdM_2qIHpEO^>6bR?_G6&#eDkz8;cUIazi=Uz$<{5qlr z{4|^2U`64D`sHL1BRNus8vCLvDLIf*D>;^9n0d0zl(<3v&UCl4L<%&dq8#9gKCZBd zN}H&%iCRrG42*Md_>dhEPP*Jlb6#W1RNAyNCtUK`NQ@FX+nXcpiE;C%Kdo~@_CQ>0 zWG|p{4u4}Z$KD)fKMukBc48q#R6przqSU3bqZ+PYZ7CA+$kzy@x9Yf@y%k9>*f*1J zzMdj1+-?e|B2#uD`N4@&N>&hM5-7EuNuab6HZUvbO(%hMGBlk8X7T&^wkRfnxpe=$ z$ivN9lR)i_3ks{{;E%%7c~8iO&>9~c2y}tPLS@w?2;2&DSryQXs&5YbkE_1(J*}E= zganpMdc`z^-`Omk+_+D4){VqQa^qgrC*uD;2v?fSkOLQ>JNMhJR^6&C1GcMba^nC2 zV_$&r4}^wgfbnY4cD3b#G5QBub=#=nKhXly@$4oO_LN~iVsKy7MJd*Jj2M*}>_;iT zVL#*>eaGcF$oX}6tqsf%{TlUB%!z1-7*`S$yKXV9PHJEO(J73a|$ zyG|`MeGSI_8*X1hax_0zNN>6erQ&L*8!4LHh>HY|%Lgn_E`_MX57T6Lo2F>lbcvHL zwP`za$NucisEh6o6>rKzR(Pm*j`T}o1g)_|wL%E-$`=h{08^#y59ul=UF)Q&CM>L! z14%n@UBh6DAk5_g`Q_L}b`jV`_TkWIs09VuNXpR*k@C1zQN9c7#E%yK zfPI~B9_CZ=7y2(WD=0+-MbsfwIW+e;Y-Mt`JmmH0tWETl09mU*W)I3^FI?AXyrD0S z#QlG{cjb&?M8a=by15tL_6>hTIx{CC0fa!8db|S-@#WZrg?qJlQ+D$jd3LkUFYgZd zg`M8T^7A4@4!jzjH7~-vGY~y+a|fRDb-8EkGF5PzK!AVDyRGkraxi|#kuT05~YUMZJbgw z3aOKNAbD=hu}t0U*GhT}LI;Vkys7bJ8 z-Ohmk^&BvzjRWI{Y2tz(%tu#D)b}ryc^WD}tmXRorRu;VNI`sJd&P%Vb@>CX*r^-b z@PWP2ZrrmK?0OSMkDhJ#z|AX^H?Z7c_6sq?sU+W2&`)Y*VZf1K07WseiODkNK1Z$f z>9#>3)l~#@AN6HZc@OUxPJb>E_t$WRu0hE1A$o~1dW#b(IB9r6GZL8oFi=4HPT)$F z^Q9rY9|{EjjGcqG6(Xz^G-LJSmM0Z@5wZ@_6*|Qi`gRerOP&jbOo}Eq=0#`ym4%ZV zdqrpcT2tT^y~D={UKf|0!u{Z(1V+b;4S^UIFJxr^aG0|YsVZQp7JjKtBFensc$?k& z>xW_I3yT?5vA8$*xzzE=2$m4G)a)8>-sd?IfU=W5z%E>HUBd6EB!0E4&Ns@uykYnA z%E`W1wy?8RE|(zw1@nD>%7pA?i(29nz|9+2C$t=o;D)~Jb~R4SH=lr<@qls-3(QA> z^qI1DF~>}O;6n-*P7){>$YUDnT#4hZUyE!_Z|BxLKy>wzV3;#d%2gYChL0$e3H9aL zHcOEiB6>7^GCvT>#PCY}BW3olqfbjbz8BvlFIJj9iM@L9FZ5R#f03e%Ja(u7smYDI zMrX~HzT+EMY-$umc8xZk$|8Gp19cq>E7WrgNL&^I+gXqb{rybjh2fzngx`+63$Iuf zf$&#|jxpXt{c<`L%K*)8(FQq!n%uZYwBbhjqsfhXM;jjoaOqn9Y{ni|!1fG%c;%3Bpq1bmBir0zfV8 zbcs%sR>RibUmn6N!vg?u13X))!Ahg z2P}JsQ#QSe=+uy~<%UWXhDuq4UAinpk`x7!iVTv94U(j4IK-KzN-9#aWgbRnWY|)v zW;l^0ZFHfKv>3KD(smxkkEUM~RU2u%CJQy%Acy&iQ7o8zq7fL=YO@$Y zdm|&R{~H6)u90rh7SFhhN*4pMTkq&^2q z>Py*>60bfTHX}t*#W&PnZ>TR-!z%ZfDyhf`Uv;6rT)!?2IMkPh!UigApCIX}I0^<; zcK_5Yl4=tq>5Fp6$f!NMYn1Z?jJ1{Hp&CuU_!+i-DraFu<*{z!Bh3Acrx1%)D&Tup9F@%2TC7=o%xF}uQR=+ENQeR1bY&O?V_` z6gc#CVLVlcw>9JMOdRuhBRYL|X?9=yE{&(A!nzM0xaAcNf!7s9Fc;v6V7aS@@^|&o zH1P1^@#X}{!}TODiK%M-;n@ZvoQRE#sN1aiTzb|Kiyn|A`k z3i@JwR%Su;>JIrn<%TQf@Lw=*m%SjdQ8vJ!7uVYRU3WTa((giZ`Iv=(rDWa&2aJ!3 zC@D-7GvPnB7;dE8wdTeDsgCm5v_;8{`O${)^nwfV&wq0@rPLqwiVCZl2%?(`5?YKa zepIsEDl{t{)Jnq3%O7LMqC2n{%h`wMSl~Ew(g{pe5$0OjpxLb6EMwVYt~*)PH|f!L zL(%TW^1&a~Um~ZZ--2uGe?9{&Hyf#p^}9HYmF)kl%SB)H>q^OaSie(u%6vn6&;jCy znxxiAS2^iQCry(p*OH*$%MsLK5lL>tN>L&VBC6s-P@WA_EoUSHRxY>MbIr|;~DhumE7F0Z#)1^MHe+l zATeJPDQCw2-)Lhy9B098LImIj3vR>Ym$Tp|3eIjsWofnNpRkH>hU(1ZroEz#gQ;`@ zWSgK~)9p@rjg#(h(!NbQz!3pkS*6Tjmb*&H{ni%a&PO_&#A3t(nRq#?+Z9vw31;d-QU7GB?^je7za9I`+?wrYy2Z+ zna&U#(;T*w8V98zAq*1was|M-x(Evnn33tcq|7@Niw~b(e{tNq3X2a{Ad=#PUh(FA zj*WX|$L6L6eErXPIgM}B90w*k7QASgj(gKFi0_PnlC;t)qf6=bYxt>$~ixTAkG1oav%u} zuegX%t*+Tm!z;#PjG{*{FO*?U8yHU?MqP$kV3W|t&H^7fgX%|GWT=JN*Ru#Fj5DN! zm15vf4k-Aqy%0JpR99fT7PQO{)AKbc=><-Dv6F6f(wvj=!@8|by3I+qJLxqx?RY91 z{%SoH%yp4ZWaj%zexsg>KEXJc<2ab?&EeN8{%9o&!p|%qr`EbDQWvysA*5)7qokW6 z1w)tNaHkC^iYl{Bw{zvY%Z)*s7iqVt$h-~erij*bZfBJS95+Q83j2KAG!TcIatc>1 zyhzW>vfLDH0s`S5EJU3ls=4#eA}teMcXXx55O_!oQU!4Uh7T0+*FMw^n0zmk&=Y=U( zb_qbPV>1Ax5ZLF3=^`gB9)NjX;yf>P(z%dbepol(Nf$clA}3vJ(+-QC`kH0YdAj+9 zWy^fO|2@j0>_JoqdL?^R$@jwS9kCY|hAb*YU=iyGm~o~nSq;eLVA%`@N-mYMA;;Y4 zG$Tb(rNdP5O%Rkv3AQ=kuu+B(#OnHw znNfnF3v{_*&?Q+6t-X<_2_Qj{9qduA$q034p#{{63YRl@$?lW>SW`6BZ&hpzWI z+)Yeu?LI{c&I%~W9c*4IKt&`P@sO_P%gG&may`jgsbPxRu=R=fq zH5d6MvhjF-92eN|27y!Kw1v$dJGPK}QHb-1HvWV7f&o&6F7K+cug{5t6=0CK6=7mM zPGl1j>k)07B^5;ihvW4*hiX=_y&R+xb&6Aw-Su$^9v{x8s_+t49P`pl0f{+34}{Wz%nhKJG%lzKz>QzZr1H$huwWHzml)reC?u*$VwigM6Xi z#Jc|i{dRc4r5_hE{9Q5E{*UN4|5QW2mqwC)y*sy&eiF0}2JcG06(4Sueh+F^HvQ)4 z<1X|&Y&+@q=doL(-|vH*Z2HZ$Ia{G$ZICbYyW{8G($5Td3d4P! z`-6Zl6CW?p;s5@8jK82oF_KGjFCYOa`Ly}snTB||6A}4#^;OCt!YSJLpbSEtb*f}c zkL)fs=fz$@$9cpY4u7v4&VgV^ELNGy`|<;_Gb8756%Hz`VN1GWjY$_U$GMhykqzi0 z0lBZ-paHoZQr2$C<18Y7yGJ5|_AvYN^Tue;m7TvKiL|3kR{2AQVAh+Y7ML4 zT$OYkxEPHOhFH-o5**ztmFe$#1#g~faIh>!?)mzChkL5j783^+G~ph_f#n|Ht({)CRZ4vQWl)PBABWvYvB#F0s0< zobF5WLmID$c&r3}1K0|Aj!E)$cRDOYH<-xE=bJRuH^Zq$DHi90M{u2yeidQkm0u z_*(f=`GU1N4$N5W9K+HPvu!wBAOYvrtboqo#luUpi6SQaDMp%#*@Spi7?un%^;~)`p2DYH5c|C z78f>@ay5b?j5`}*+&Zr0oegEE?&D$O7tzMIxmvU`R)n9ZUy1rykVC{Wec7zz`{3sA(!(XYqdtbO1eHYxyFL{-~-e`<>8tyI)$OCC0_WD zGesxOS(bfXWYcJr<=K!xiQlXPW%2G{k`21fGyRI!eAsSEL#*-0tbB&f^H7aVvY85g zOTE0DtKDT|d!|nM16S!}n$uKDgUna`hwq^rS!WvxV)COz>5lJ$DS)%xIYqVED`N>A zPF)AT@yWOxbM-sQNRJbqZ@V1xepB#gQZQD^mQs1Qn5S~%^~yRDf*v;wE^aa_RZh=WMworuQlQLkmviVy+$owr9g4MvN^^QAQulK~y>6bXV<5RpQm zN?**CCG0%0TAfs*Iov#gI0%m=$tX}oz(o8_D@vw6La+`wfmP=RRiFNrs_B_hWgoLP zJ13*4wx0f>6d~-~hq^+Fs3uLn%7C9{)@Ig^O;!`T2CPCP6Al(niI%q-p4uJjvP4T6 zN_5~meUdZ==mS(nx^2+f6BDqu)rQk+xPn4V3UrIboy#uj5eYe5~O&oDcbSIKa=jg)9M@1{T*kA9Yd%*QiJnf%Eao zJ)!eKgo&E7tU!KZuvQ&2;Cy7&z1`OJ^7bC(Iv<>M`~MKx97%t}><-1qpta;l?Fm{X z@e2oDawuKx#ry`_)$u!Yxr=Rg7_bygZrml>I1t?oYGohTkO-w7o;M`8F zZBF`(J(^zUjc;0u2AC@C3eX=}A;712o~p=n;YU`0D#Y^yj-kl7taChD(nCMziXy>d zECPK`A9J=@!pAhyP+^f@)u_X|USKot41)?2Qr0i;z~k%%pEHM1JOQRX3j|fh0q6R| zgPfUGG!?bX9B4Cj57rK=OPC-PjF&g@1lO<$1%GM|=N6{#fq8qku;e;mXELlx22OnQ>8gWJfpq-gSD|z$^GoENai&qN)ZgXqEn5b)4q7EA#{G`VfTK=e%T6Zn z9pc9W_*CsOpZJh|EJT`OLXqY-MH=6DHB59@)$9BwM){q?A|#_!fhW;3LwckEGh1CO zMS^jBbXPbI&EllM%lq^NGm$U-p;|%c4KQ{puX1f@-TM9OqHX#V46#^3PZ;&fnuNd0XpvfvBM9vW9w7gFTc6LzXdenUm#3j%K$5<0}o z+ec;-wx2xHDEpJvi)^Bp34br!O=pWe#~K`p)thzEHKMhF^hUnmBwb0J0n9Y9IzCKO zAMk_TZz|@zf`Ax(E?9bXN5xV;nO_FN>eOALN-W1Ui~8;Jpsvm-qQG8g*EnQoth-IR z({BY}F9ACL&PUyyV;uT)_6Lz}L1X;z`Fu@EdV!N(?4+B3Uw&kePI|7BZgJA{Z8|lv zlA0H)bim@rxh)6Z4ZO|vxDS)>-_WSra{9zh%W!coOQ7UzDH&+3WA3nmW47La#{|r1 z1*J7#${I}!Nopa)XhYfx8T_-kVHRt8@|!qv_6Z zDf^ZNoISZpfhBv0WGQ{!=M#H?4sxQ4RS7)Y?u z&J{d11WOxF-vn2geZmmJUq{#y7<ZJTl&&lLa#VlKZI=7yX}RQAJ4GA6;IbS5BdbcMNEbQjVkceVq)Tnu z0q*Wx7r2}7D+4%@1`8bfaDZELYY3c_gB_DF1&pIf4BSFp0SQIpKBtNl0o%oJc&vHK zsfe}#an_qaLh&Q8N>KE2=tn#&Ckmk;KJ z3Ct-kBHCI6X^O&a(Pyoue3@PXJr=7jGke0b80*DB(@nS$nkVp1^?KEvk}6vYn(Ai6 z$@cDQ_TixIo;iv(9xrS`7T5wbeTWDHaO+KHOmB43IhJ;Kp6jHk#`tl8n~C3}x3rZt z%N@!lhun8%m4&jLP_i#VSwYTYXAYEK-C~Ffst{84Uj{j4-*U8%i=g>_-6YC7=M%_N z#wQUV<%#rc+LmGWt8KXginkhm9Keq`;K!YG!bz7q=?W*^PRm9}(astt-QlEtC%xXL zQ$L4onMSpF{8^9DwhSFu=4q5Phm-Gr?|QW@?14(Y1HBS2zI=BHe178>mievY$7!Ik zEm9Y4aHMR5qoi$-wnAyR-DyLLqRM=Bk17k~dtr7U)A^DWd0^0|5G^3qU$_?JMJh&TnHX)32x>f%I$WvT*&0txDW!ql@)weyA;`JWS(k8} z2tkfEt|N_*0an1m8w3;N57%*_bD@2W!v{ueG8COn(&9tv(%A9?pf1@jTz0MFBe5xe z_?iTx9!GQH9G-g2v6C)w(xpy1X48&@U-M`v;cQPOeB`w%;e0~wD>tH6 zVML9+IT~=&%uvFm2#`=^C0y#F4UUxJ%286nrC=y+e{kB6qNuXbbeqHOP(`YSRcH2VbMJT@G_Obxp26^XyZp^DFXpr zv}NrN9A$7TO}FTLao_#U!()ByIw#%aq-Wc7>Pl$&YTA*bc7K>$HW+gh z_-)9S!=(OOwaR7s1jgEsJKt~_dvi!|3r+#pH~=XEE-SZOCUrqVj+DJ{lw=tx7?SZ+ zrwu8JDsgs$Dhc`Sa{6)~QzaF7YGoHLyOdle4LDpT4TXKak+N`41i16e6ikm`6%ov^ z=z^fA><`H-K$T80WB0U*X2mig6t*}Q0Sz@t6 z?p7z==A_%5^cpAK3anZ7Xmir-PI`@#?yzZxJwAURWDmBd?D6zeWejdlp zveQai($P{&I?G!7S5L%bav^R=<}&N~@!&pO(1Z3<)>l8rZZhVR2|@Bh<^p^34f!aS z=dk22U_qGL4(1vjjf~SQqBdnBb$(MwODUJ!*e5#cqg-?&S2!$Wi+AI zjnuE>>CV_&8*Y49Ah1Bu{DcF8Q-d`!K^@-uDMS!=hM@<@5!}P<6#3^(P|_8Xbgj}N z&vS?ahTY?Xu{8JSB;7IA5n;B@kz|hun}j+VZZ-<`CV)3zO|o@uxN~8E!7lqJU|P1$ z5A_y%kaTu0$m1kU^2q2In54bP$-9RRvKj!Qb=@H^~3K8QF!KHDQ3iA+T3Wv2I>^>He65!BW87U?o@Z5h^Gns^!!}Eubj+qxliz!t# zD5`8URdNUkT|oX0tCX24smRBFQiClr;H)`I1CGI#hQbDRcKQ@r{e=swUgXpvS+-Z( zq3x|cK-D&T!kTknAygU9CV-e+&J{odrT8e+1Pw+Z&v4qyH?)kIFi1rxDUn{U;FQOV zg?eodomGgPoh@X|!DTk+L^gyN`LkgO#_lC}^X%2s^wNa9FnW#VFg$h`a|An#G(x&b zAjIU{%Nss^8-&u#UbG3$UcTCokm+(l=fie(qn$JV4JSWcMU@DK^vRj{Fuh)rfIV{k zF5Ri}RqL{al-0?RteSy(FYjkpxf*s)7Vxl=E)}|0?1fps!YYZmxr%X;anp{4zLHe7d|1WE5altvg-DQde4n!!+kw+PSL{wN=)or( zFQ`t6=mDQUGac}`ctZK|Xr!$D0ZSUEf$)us*oHT*5aAnBSw(tc$T5n<;lP)qA|tg3 zj~U3d2lLq!LPEd=6NL}eFQCEh*6R>H)Gaw(5xWvT9EVzmhB_ZtKD0f9hW>abUtcqA znow3|krKDa0I}W+jj&*%tG*3of8#YIx?tbjyp__0C)`if50Oae!TJ*yM2%5O%@#@~0K-`UTR^cGY~M0>Xj9%UW zr~D_N&D&c+V|NOg(u;aF1oPWObdm@JHpx|Vz)%&&pmoPs{+VT%9lejsQZxu9oF7Si z&O#2VyZ2x7os6*7&> z#sLK5#1M=VUxu}n#e@0&YqA{8Gqw}po53K*Q*ydw8rCJ>e^FH;Gy!K#xP=aq1>c=L zf-#Fb=djftVXJ<_7!2zO@U#vq_>aNBrW^*-k3TemUYbN(qM1Tm#c>t1%j^yzB?=^$ z=PvWt&ZZAzTFAoB%fjzn-#6V%dYRY-3`xb5I6!}9vV|Xo{@;$a`V^Rqu}W1ub@LkO z{|*5Im?$0e1(%^pR09rq>$)GsQ^z6@CbujV$4em-MPuRjP9FwP#-_&Qj!pF*JET3@ z@EjXSK9e8cvLd7Qv}fqgC6EhqG}7GooZ_v9cy~Bvq|+S_?#*4$3WdV$EpeoAjJ{$#M8hkwyUkv}h(mov1-)IMwo7r-o!Evwnde?_=vMdT4=_VAB7 z;ma-l`seU(?}OHF@fW>~f4i>xbc;VD1~1Z!+w zCO7rDZhU;{JG~G{aq0&+MbHB;fF_@Lc`<3UFXW2a{(yN71z~pz_Fv7T2e{3#xiF51 z7T^yYW}2M#a4PTS#~47)s~01`TKUVI6_NKIotM)y93*;}j^}Y`aqXc4PFv?1zjqwi zTQ1n^g1<)MJGriu_$wj)AjA{Fc5hVYF{UmSA97sH4)Nv#l|YEF;c zlJEZ#ydT}w72dm6y6_S-z}r64g_kQ@{&Puz_puYV1>OcWlUxUNI~i^h@LOc)3S5b{ z1c7xvM_FTRjk zM7&Jt8Qpe1HfUAnqxgH!A36%-I4K-Q7Jodh@W(=ZkipNm+$rQ|1f8_vLU9a@65~~2 z4#GWZjC?&uzTU5{))}S$W%?U9T*ib0H=;!8^aKh9ta8VlU3qHPSuRhJeNgcGzjk>F z@tHaP)Oz8mb4Frt-wy`|8yAkxl}jK#90y3Fg0^g%%f~QGuna1M?SuYP&&%Xhgk~#~ z(qJHj;kqAUwWf|90eExwSClvD!0pHlY!n3#u;`XnHZN7Cy+9r2a^f{7e6ppp$vOZT z{YR&FbfKSyhl6GC_HXYug2BFZY_o(M34Y@Bx7CbO9{OT@$XC%u24Dch=YW=JF9K0t z@f{FnJqOUHJqPPN^2PkJRN0G#WkX)7xiHQ}2lAh6QZlNd(EsqKffcJBrP7L#p`!_q zI1C*tCzx+GK|Ms=N{rE5Wj^XdxKK0KDnfgbi zkA8(1A+Uwo%Ki{>|GYYDEAiY_F#U%?!TgW1zr+7*e?-^z;rg&ybO6P!9!$Qpf5SPd z2MV!u<2L^U-v8J+-!$*Ezg2lbc~!yo^S;s37NFZzz*|E}@>UBkb9 z?QcK-{GYa8sqL~y;)}($o!`X%Zb$k5NdIhK``b0%4EU*da~p&|RJTL5%Q{FQ6X}me zWvv)>TRy!gZi{_a{!UkZm-*5XLc2}#yM0j7f8=Uwv*1#4epjSEv^8up32e?T1jA$} zfp_hiF$u)$R>Qn^`eo!Lm&St$qJL1n&C4>D>yCjhdT==92=OQ5%hUB0K;X^?W5#Bd zVP@Ejxf7?KGQLyFjm_i+(+k9n7;c^i(&^(QIL>RMjgLqc-`qK=SRUMg2OFaKu@d|{ zx#Ys=50*w7>+$TG>+xVjDgMP{_?KX6QVjX+(K$<_ced`o6zS)qbCxl^Z2z^GbdHXv zM!-iuInFLIb4Acv>NHIJmR08uVi*RVb1a;KD(<+*snbu)S^Um3jQijD3TCJ;;qQ6; zt;8Q^tWWz-9u0*3#jK`mtAD-y`mbW!^#SC2`{i%@+TVWo|Ci{Ghlg9mU>vsY^~Y3% zxoCk5{-1j7w#hbimA|?sOSTI`(fn;+D}EyP$)&}iXxI-)*`pQd#0IpT=*Z9IOCm+tZ|oS?vKNfS@yFpyEpVsx&scw)mrd z2wdbK6^{SE>u>*m#jhd!qF=XteXxi;cG;C#JQmsye?*@w9s^UDmEdrF@bI94EN1)r zARzdhEM^18Wx;FqpSFSD1l}K=7Vum3WtP{#LwsMe@)~|z3!Cs_xMDa4d`2Eyx|J2f zt~^vKy=3yxV=fPM-skt?_`2DD3di?%53}dE%e0rwu3&NM z^DC4$(SNeHx$XAr*I1RSz`R)u9ooI3PxG5#p=Nr?WF;Mm&<^4X>UStW_?O>zn&O<@*=78cM{)FDQ(C5h5Zw%M>`&>6k zyO(ACvwG&nQ-iU+iCsvn+V6y4y>=QsWKGRT!X;bJ^d&G@ykpBh3Q-e`Y{S-bH8v~D zxGX@2QWcU{XubJOfasE@uU7<>HU9Eadqrq&r z><*K&EidyiKolHJV1d1`9fk+jN^^pnz<)C&iCi7Qc1_q;l4!|VFRRLb&WH#GJC=)AP02X@-nHC+xd>4 zJOq4EpDF+Uw*Q^G^uN!4+W!vS^?wbXE7qLUM zk+D#CkLrzs@a-kuuG`$hRvJ36`U@}ddfnz7r+z&2i0F-L0L;+uMQ^;H-vgtKa|wHL zQ_t&9!v7xC$1q)U=+Gl-`Yc9UIhfZME*pAW%}(;Gb3I;@XOjOIIt-3v=UarW$1?dL zh0#C+4a71UIKtLiKXjN){$uE|(f}&#h_j{1O*>Wh?EIY$)inCOntQ}|_7bmQNYUvy zFS^A`yy6b;h-f1xGU-zM8+!az{k_BrDatEKhaMkoqkyPmwo&G!)ABLV8ZCJ+dv!jhK;5)qt{{R~fr#!`0rV75Zi58}?PPO%K&3B%0besITG${mKS?>uNL`X8Z3z8>y*ftLc*uM?6sKcp9` zc=}Ciu#^F8R7Bvr(xwRmkFhTpjSpE9^?r=-l4x=?{xg=e1wcj@4c)QK>xHxbklt9` zmV=^=eX!MDhW99q#$uEAFX&EO7>f6pydF*d5rHUp`R;@rdyMiXwGXfRs(19p2k>n8 z60*^#hQCJ}{*3ahm`rKevK@Pl^3Fxsf1&IsmSwCg%6=4WXkpu_hveYI=;YU6@#%P? z%??9qRP$T-k$dG}+()`Y8Q{N>Z;}~3oy-5ZM;)bn~sV$-i#C) z>{T;-c-=SXcckPH0v<~mzV!WGqk6v|H2NvvkwzIhCyh2dixjFB)%0aBQL=T1^#6b- zMm7!Bm?jJ(#~+3;a|&=i0=5nztz)D$La1D%8!X#Vb}nE+Xh|MGg4(ELOVlO*b8C*M zCD6G-)l#h0dWC2es#C*ZQCvdHTA9Fy#;Z-fP0TpZ$q+OgSt5rlQ_Kv42n??SW*QDh zN?vs9w^uR}ZIn0hZs0g_Rc}z~{`5N-B_2H;JX$61ARIO5@97niHAze7jq;}4PnxFh z*T-6ek5|d#U*Itl!=C~aIq4*RlEZMu8V-ON^bdX;4jMiJES*2*>Ho%{{eNDhW19kK zzlmHG9pznfKbUD$^H=Ey5o`e{0k6qeWio!j43ru4Mw+jKMKb+3zT<}=L~G2J_|i?o z;z<~@{oCR_*5ewg9ezGFzH+IIB-?-RA`|YjBeSjr2Y1<1|Bb=n4XvFsMtMKO(7ujb zwX=#-`XMkQ9%5L|!`u0A&`0T6`1Y$VRGgfLivMCok=gV~Qt>=gbRHfl75|?8KE5Fk zht}+A85mNvV|30l2vSMkifegzuf_rpSS}N3d>1JcubZ+n^2av6ke-4fu_nek(h=ST zXS26mV6@@RKd5AR@g4|+x=L=*n~!d=!g1B*fh;A+R^?qTI2_A$Um3-H!$zt zbpcU`vBFU7MM0vO@%NOcxPzxAw_$a(;Ujic&UfvK* zK8nJ~o3N9km)r3S1)#-IfMGpS0Lu70qm1kEY&fo#8`b;0(L-Lo^0E_~_US!(%hJ)% zcIa}N7kFzV9(}cZ%4nf~`=08Z!K!hl0PbImmKf{b%5NwtDkOfGCK&w0vlNrx@zV@` zg#J12ep#?ZLb;KTR>_2t`ez()4XXq0Rc$rt{`3HSgwp2GsxMi})-!{`mv?EYy2jXy@dSa>HEKD6^?zchFhJ+Wzb!4R1L zB32q8Sqx=w;Rpjvm`m}t6%)T50GDuAoF&Qf@5jQwF3H?GDixLzTSI*r`Wr_IiZTBo zQN%?RBa@)#soORFFm%&-S1`Bi#$S#=ox!!Jlfg{JJPa;#tvD6&W(3xXX)2@jk~dM# zQ$s_y;uq38?mNRb9g0}fw1G#9-~%_bLo(y^^KfR~D1hoym^gZ95#D}g${+%4$C?3z zKQ0lx(#cschg-1Kv_>zdgA0X;q`nU_-q~TRcD`>@S{*`F+4&4bvNvwej5h29ZvirS z_M1i~yAkB7W?W#1LOjy#lc>|2&~KH#sdpcss7 z>I)^wLyc)195*=C(ck#SR{}bziLAJ*_Fp3Sa4v~@TT4S^J2?* z^QUFxqh(v`r>yxc0Y=;q|LJpxnE-~hkhoAKWp0)9+AUipwGd5EN%Q#)83^AfWN1Zc z)k5a@m0QT)Z7+!ATd;l^;(~XuQs@}Y%RNI*%)l{)X0a4SO+F9jB{03mGJqBWA7R>5 zv@Byj5uN@PflIEdpp4@f5&xlsO6eeh4*FsR>HneaP2l6I%K!faIvAi~0yG$w!XN=s zzAUM>l0XY76qrB?VKwYQ5rW@}fhIIcfz%{z$LWQtMFCL?xD>65ilr(_y4V&_C}k^) z5D@hasaRwyEjIu6=Q-!jlB5Ov{{DHr+Bx^$vpnb7&vUkDh>Xi#6gB{nvcQ#|DXfL0 zIJG6d_`F2-^X;Sb4R=cWHRw|l!_HVJ2(GN+XJ1O4{N)>bMxWt+x6eux%sHL zxj|ApJzuAJ)XomyQy@m?Exh2|5J(I5xpJXITO8A+Z-3SHCe*VB;mJD1989qf>LL9~ zT6ah^S|TW&dZ}C;t)-^IW|7-uV`AI$ zGgn~`ErM@iLBnT^8Ra{&SY13_3=cg#y;h0}G|0YyyO!jb$BB7@h>aj(1Bh6b3`TJ3 za=s{eJNoVOrI)hR!tGiq0YamimL`L9^H91jS-fW0ica+v!OWh1Qp5%gG;WQE-C+r6 z>)W4R4*r&*4fF9AOlIA^9scpKGvdA@~C&rFbm8M)~NFYKKX$T_{>s6h2BEK}9RnrzRmRA=YYD zQ3@!~t39tf$vE?|(T=hFlX!p(Ey3rP7bq5KO7Ybm;}uq4LXx zsG#&M3o65b5$ci^>Czf&$F478bmEV2v;EoXDp!G|OUqrBD*TZN>S+hBi5j{MuvD$O zU%pPF>;^qqPZFQm=r?nP$m!1?vGNk?V_p&94rT%i!dJF^ecw0lyTwY?U79+~x}hBJ zznrTfb0At;clDUb1h{(z8Gi+#hanJYLRo{`UszQ-Iu&9#I%ERz4tDk<)fmLineHj` z-DkE+nPt~G%KTOU2Bqg+A?}4Trny9xJIUa0m10A^h52Qcvox9MzHgHzQ)YZ*n*6vg zhtY^8*0|6ew4wnH`h z{N+M8^5`&+h)Nnh=DrK_Tn1^zNYa23rbZF->907ehVMvCUTqQvXt zJ+~__&Ui1C#TW0@x%rUxFG3NGFVIqpzhVfl0ij2OzROP&McC4er-$b7-~`)&$>Qckxa>wNUuCQ-C1_3^V5T{ z#c?I+Snrpqfl@mu9-d;mD*h2e$m00i3=wz^m>ke5nAuP1fg#73)r@tp%3HAS?_l5G z5O^KQ;y0{J_tj(@+sneso{gyfWNIAEYmPC99eAqHY5rP)VXWh<05u9%d+UZ+&2{=3 zMAQif$XJ_63L2FG@b z4LE{0Ayn)P==G_N1Z+{AF7Kaydr^JRRHZKuQCWSemHRJ{7S*ga0m$LFA%!gyM;dLy ze{)%hz8jm!3v4@7ye|INpJbuWe*JMGgLz*dePn?tXke~yzzNt;;S%=RVCXr|Nva~m zIh+|rGP|RY8d8u%Fxf9nszLaUAr|p=ag|U!ZDHm7H?Qllv8q6Nb=Eq^0Sn07|Ffh~Tyce9^nLY0olc7orKH`%XS<`34LYJZ zODPpXG#f=%m7G4b_PNOQBKXs*SRP?~|q!PJ{P4nF0Nq(GW-I5?d4)1^&qSsaYm z>1@EmAuqteKhFNpI9R@;Di997YObAY3ml-S=W4O;Fzoo=COMIwqlFS!ES1b>F~ieU ztWekri)DUhRmf9CrH3E$US(F5IJR%KOgX)On6;6w_rrgl7SRGb(|)*sZCzQX&8iL9 zp5SyWjvcwdB?0E7ugUC9rQu~$+NzZF;-(_sGa{txy;KtrYN6gS!Ku>;X>#jW$09^bkz$_IZk!j zSDgfq4u$Ws<~%b=wR_(r^Q4So5E~VEzIy(VVPp$O2)-)1I?GoNep_81%vU#^`Jwsh zdaFQub%=*}0d4gEEb_N9-^9X&$LxSBC;ufI)XVwP!Q@Ks&$Y`oZ{45krQ&1?iH;mJ zvq5OR6Na$lmMptK)+V_)b6?hwSaVq*Y_)2teLOzU1;(@FN(Ef)Zy5O2kEP4M5@!cU%tW(=m0yi&8UM2&;~V1H)d=5d46pRlo4pG zww5d+U2Xr=$DsViD>M|sH81zerp(uX{nfr*Z#v;i;$i%AtIgSRKMZXl2ZN!#$l(V= z7m8)9UB*Kz>k`Dn-Sn97xllFmY?e-XMGt*?iQq~|^{4a(mjw7>y!UJa5{3QNI@#;! z=kQ_2u!cj^zuQG0Gp9-IQt_Io;(Sd(x-WX~Z;aJ>WddRd0RJ!Q7@o7TBwYVO9z)DA zAUp~2VX{kX#1P-p$DsU?%RLFtSe2)UI(7p}r${peOi13dSsUhr%<86uC)gBH$=9{G4Atup!>B1SM_uimFXp3|%4 zi;o>*TkfilToLj#nr(>7iCSoYr}C&utxyvYHt(Y{&(i$!5q zerv5+LxIa!pk;Qq*1RdV2FE;Ch~+mmT668ZnM_4?HruPcv+clo2t;1(+hV=>p7p#q z4raZ)IlK;M1gW@LsWLTzZ7~*?b3iH~!d1ztR)?p&<)*@G)aAOYfr@m>hvng|%FMO_ z4<{TqM4eGpRu!Rk`k+o$4Grpd_@7Bm{dAk3li87|X_(2r>$IYgBcZq-qI-*8(#8UQ z^{4bgmqhKyeqxuoY5eBPNg~6yzwL|(YQpA#BeU+!co6%M-6%>i2wf6g*|I>@Q$FWf z>9Z|Z56|3@m=tE;tDvpoZ`(R2e80{R5X8PY(>vhj`Bj7^>g*irU|orpTc=BJxXjF+ zW*yJmB#|`-d{{RiDBUjkp`Gy^tTK5Z-!;FDAUv|sj~_KeyM2Fe z4SY-@JT1p-Aa&iQ*9S5oqnyY<ZXlB`RQPJUhvL2HeiY`ZHc)mW2EN&OX6erMKIi6py)(P7)^ zzNW^;bm^8$&9%VHaJnS905q8tc&$JOC!*&p!PH-V0Nj@0hz*Zf{n|kPV*-?tk!mpp z1C)yJV%9L&=#gC=OgpIqtLhq6W4g2}*Yr-jP3mobw{=65(PQ`$E|Z%!0x2z-<1Ji1 zF0v2apF$)0sf4=BJLVCY?`l&(5!m4$H$t~Yz7C?-365TMn*Vp_4+>0FH)u#VV%65_ zf^;I;I-FBOZVv3mrHGQI+ zZowef^`EUy8NWZ$eQ*5QU0^xW?t>Eot`Xpp!;t*cwRsT0R8p_Sq%;9-nsPX zs=8$Dzgc_mN-~9>fa8!**-Sgd?fa~n@T6l^!Gn2Nsk2V;pU9a7J^b9eVEB7rIFbza zI|$!@pHmGGTN2K?vt4^=oK)~>$p5J6qdqKoZ1Hy=8EM(5_r>6dqI-oJhS?5Si% z?%LHeo@QuQXM2JYAh&8cSpjw39QaTiWCAw&vFutVcgU%4NNx20R23jt0>xEuVB4+1 zwC7luvBUHw{Wo@Qo;ZE?VA@Kai?8YAsr~NEHQ=ywb6vb!J3l%%vyA^zOI+AKJ98eX z@cehc!w#f|?f;Xm|AY9=yr=Ga^o`CXjm22Sk^wJNXD%Wa%ymg8eMfc-(gczpnI22DOR3m0LQ4OjVx zpbe@ty!36lt;MK?Wac~$FZaW(Wb(rWFp@4GVghy ze~r#@3-m%@tn=%U5Cv}!kqqe=yvFVe$z=pOBHn$HRUs!PeI9iH;x6_^0fqFm65ED9 zW=pc?op|@>rD#k=N=H*~S$O9p4^n(_l64~S?juaio7Xe45(JkV8~*vE9M~;D+U(`j zLN7jN*c4SncRH+ZvyGL6L#83Pk;s;V0S{zlt7Yw)>1Sluv5jG^$W?h!pOwjC+(fye zW9+11kRVlFxjtH<2vrh#2PpDjvZf&{u63?cFQXp#w)FZ*XBPE8B`Vg5$<(0(!uL=V--DT2UB2<+NBrWdT{XFcq0ML)~R{8{BRiy4Io|cfXJ3$vkN4-|J=C zD?2KjiX9i-S(UVL;Ch?wWpDcG>6fTlZ#4l-nU4sM&ClGnr^=Z-RHMvIGIMpABh>~U z07<-7y5W=JwFrL5UlguBcEdpbvha-~oiAwNrG2dbM}+U6;QF6eZ{`uEGOUHn(roH} zrNEk_H~P#C6#wiUhOMLK6dD(NO_^$6MOflpd>Fuo>^wf{xIixp_wa?RQzBGdc%}!m zDf0|YEMn(`P=*^dET1)PunOKp1FY@95X~A4(gA$hX6Mfj=~<+ z8ST8{@qQMLNvwO4(~TMiwzbbuR@(ngy%1m;iue&=MI%QK(P*Md13Mj%88f^%h7h-rxmmDQLztT7;k@-= z<@`bs&cRC;``r4QQaLp<*Dp}rsYQ;J0{;s)-)n8owLL1@8p*l4HuN_pnP1sy#l+9D zV|PYgjAO3x?T5;|M6)4gUNT2Tp)5tQE;JuVbt#0E)DwGh80f`kAFT(iD$QRDYWIw{ zB#WQZgv}Cbd%gn^sFG5LY=H10=%kDrSY0Rl08HaNqw)B!{ZBq{(ih>P%kqKyp}9j5 za9`I`1YEZswgH?;j>U|8d*K@^WQR=L&GC?L0G5z)b5*rKgtgS4%tDV%u)Q1zan!>{ zBvb0NUuw8UTiNP zTL&NQD*d)odSdKs>9=@~o#((ex<77L6zpgNK$!5WWwc-<8E_}L)yvYE@Q{glY7Uuk zY7UhuHTToAOwBQfGY|mMGg(A}eAdb=F#kZN!-niIRk;3s)E`Ij3kN=8SQ0+NOXWfB zsalZMdRUYMzlke!%1NrNSj=2JIUPIljN6M&Kyw`mXvIko?V!O8opSPUz+|oz zA;e=E=!6}=R;GMlSu)tvzqlcY9rpdn>>PtbO&z255JZd5&A_x4-8l?<0W@4h=Y1~_ zuGUPgwKvi$PNT`0tc@Y|L9?Mc3t>9#*T+}IpA6LE!N0@`8UX_;3_4bekya~bFtPPW z5re(0o?`|ds#0`?>wF?|i0bSlV;>{VPK!y}ZMD1f-utVZk~IT~TJd@+MW!4Ig4nzR zrTHajaGDDsf8qtlWYv1#=)}&O7|D*`<3!&(vJ+C^Mlq;(VAI{{Yw6^S%49=&`v%Y< zv#HI!8~Aniu$)^lWz2Kj&2qz6+!{5Lc=;Hg`J_e=-qMO%P#|eWDm=8XKXh94B@6l! ze%zN|XL!|32%6xLr6NIByv;ZkDyn4-TMi08S>uK++3&(4w#HAkS>NCzx>MMfjH;1I z>a*5#_kwoaaDT~m_ObMu%{*+cx zOQZZuZ$-t={VU3Egp?nDmnO6K!)Et~T<(;H4ucd+o<5L{F|rFQuZmy6ju8i1iug4>kjObD7fvZNsx zb>!sqfuEfsrS@t&fQ&qneTn^Z8{k^EkA3C6PO=f`Xx*eF7{l1C<<1>inAz08V`Kjx z8-fEbze8HA5`39Efj6lZE7W!(JnDAI?F?@uRkDV2DU9`ptsXQrz($}3v}BGHGy9d! zUB3cz?g*%c?KU7g+ikRY@SZR5-eP8l$9pbPp5VmdhT7ivO}pwrXfU0TMFUFZ$P)1u z`(GL~Low<|MeKer`mY*sq`pY+8TnNRJr&!S7^0Ep9TV{Y@S>I?HO{5TK64(!OgkfT zTunxz3Cy7U4$CWA- zNaoy9#_!*i9T$Ta5KIjx!qja;2&ULL3a2sib9tI9(r!N>zPNb8;q9a1izo3L?@pNu zy20)dO0sPB0snlTT%czvP2dsgCBiL#67XJ2ksjO&cy1xzToklDmT8eogc39Plx9T- zE+B(hSH`Co?kCbjV;D$Y6n=h8gl$3YXDMw@+7_ ze#viUsIQNxXa3yjRWtAzmZ zAzYA<9UwlvmeB{aZUkgtmN};@&AFkl^42&a%klk`vRNGv*-Z{vNvdeJL^?Z$-uM^# zq%(?!!uuy_#=-IRmaDbF18?ZDyToyL``tT;=Ssw0b?Ml~Bu+c}w$;>X*6n+Fq<8y( z3b-*t62b|llpEyXxX8R2y3|GNsJK`45Cnf$L%Y--Hb4OlS6JI!uR0uod<7u^NBD3; z6?L>iiSQvUBBf1}DZ^&nAbUOg6_Oiz3t&ma@C0me)L$R{5`W?(3uOYYksN&et0I3TNlT zAhFHL_~@TFjMw$AGg4E<>n_e)~O@s(2*7;rVxpxwR4-@mX3)A zklWH>nl;6ij&vijgthITAS?dJxvgaFNSE*CvbHL4>-6qLtrpfzpNo+^hpi7APE_Bo zuTqXb)3s#kB4}`WB0c(P_a!0f+Lq$fISGLs{?txSL9BMqA!fXGjkB@z%z{D|D^UCuxo<-5b+$kg z!ts3jcNEo3J%BmmD3uC=d?bJGrV? z_K+cdje$k1O--&cR$~6mx)X*wtb+@NiO+JFUjAIV3S$E`r^yM-S^Ap`!Y6QIs@Lp} zdBszKwoBK`{oolm;qD>)_2KHjMP%Q0{U;1te|*-d#xYwt!_gw;*a%I|9Tna+;Ldh{ z-_%Q{^WxpMW0X!Mt+S|G%erDqll)<_bMNP z;gzGa8wT1>QV*-lLsp^xqVX!%IP`PQ9Em3A2qq%is7Lb#9tq(Nxe%}N)mVb1Rlt;c5T>YYuxMO|_VQd;rj&_9ML6P54jw=;W$N9#@P*&2Bl7*pYYGU*thfCl=YiIB ze=HsQ@-cEh+mFbLI9|4$cRjb!2aLr{mk+U=``k_Zc(s!WP|=d3QMhz1eI7}l^9^1> z|F1chzJuUHnb<$HlACDvI?8UM-7%TwRTq~Rw|^`=*|=e4>_4@-h<3si+&ufEKfS~G zU9-52HfZM#+NQJK9atIr3*TXQUobqL*89I+XuspLemE50`R76t9n0Mli6hwC#%1Ra zKxhAqbmQOfwS|sVz_3kH7@5QbIqnQ%SDSc36cAd12am;xUD@tTtbyCy;Z$NLvR#9K$H(}jqbcz8Y{*eWe*pSPQP=@20n2z$A?gqwTs zc??91@PsXphxn|MoV}nEQ{gD=1#Fdfzi@Lte>T(ac=sAL2M%Dy7Ad1TrCOCr;^q84 zk>B;eOppBfr#|62j1tpXG#qrY*+oFYz300x^w^x6Xq$i*F&v9{;zijahK^*)FJh<} zx`<&9Wy~#NU|M@cQ{Ezm>EF#?#6V3r9pPtrDWz52zYz3|-F+yYpR&1Gz!z^-csyUT z>kvFQ?QD3S^eA|~Ju=M0``d3hd;`K%kOsb6BYfi=KTz2zikVgT5M+6xv> zd`1=e#S=7-NC+`qD>|}^CwPl2g+KdFZt+AEkJ4c5Tf7%7jT!MP=s>i1;*_s#V*+vC z*={&cWsD%e;mzy>qFX!xbBr>Y7YgB$LxvH;yLK7E97peH%u)F#nB!jr|MQI#=|S?S zFb4Vv1Wlzg@CQB0lSkazoW0Ph(l)*qNdiGogPc9F1SyHw*wKSzv06wh3->%o$Wql^ zTIv(T#+MD{{b$Dv)4i8Vhjj0P66@XxkI=p9q5j5qU4LrSpK9-q=JjW&{bObsCSovk zcVS!s$U(|rvv+NLDCGMM2lV^wUoLdvwr*!qH<)d5j|MK$O&@criTDX zi@}Xk3gC&)dfVZXwiPV|CgWU+OP=Ik>(cKuYa}=v@!5FyZDh9%YTa{HFnuyz&^%Ks z&~ozu*KibEA;oEey6`Q1MuMry;cn=l=jybCn{H~w!k>PUaqGyVE2PG`2#SIoWWi$z zYhTM74go4)_NOs*vt2;O>XQR$^^F{wIWqxdgnwNPT3#QdT?fg}hqw-5&QA|TOBgc|#O)@icy;BUx~moKA92^bCEL6#j& zJW**d62gbSH>h$NjlTVC@V8{{+cyS(Ys!AhF~fC(8*a{K3QsSrplfMsPWs1ZzYSud z_x}i9@6WOMApZHXLhr-OS45M@?$Rz)z|k;CyxUIl(FWD-QWdmy;%CA`)8M5J7K(3* zcdv#*PDR{rKE^3fh~PS>2K3xvFOt=~Kq*Y)_u49}R@X$hGW9MCV!#%q^fZ32Mf1?| zh-{WOP4oCIE$L~EWMPy}7F{ywYFR)kzW9`;_~OQ<8X9)WD%nD<&D6^8wapaCQ&t_g zF0I^o$G`JCKJ;}$KmVIppTR<;tg_N!`b^4du4QR(d`fpfs8d!*NSBik6Q^u}^M@A5 z=+X#o#@nBt;fhoZQ)De9r-<&37_P|MujUD@11mGb6=`=rS6WGFUpZcg72-aF4*hPJ zlDoJfAG0DuaWH3?B1>>x!i$%~oL?w#Vg~W&$25C1XuYr2THvyFLS%WXE?ViA#6|1m zq9t<7K;8I|GD<<1Zg>R7wVhH-<((!Qi{3TA*X9@e$_mJY#9yF>+8`YouaPZjoXpJ5 zj52Y)nOzZ%g?G+(#yn}|hJ0t6EDvqb0m=zhhx|I|1%~$rY}M(stlx^)8K`lJkUL^H zzhlF6&~#w&z4KY+>LuZIr$jc-^uh^ZHp6 z8kmp8l&ty{Up#JmwllGJWwx-Wxj>t;U^cMP%|9?7i^^#tKGzV`57ZM2ttS>*zyH$u z;%Bw^0Jf1FO!jC82PO=D+b}}TgbTRksEO?Gq+PQE*B_ruS#-Ne#EyWQ`#EG_rR#l> zCY=`mmj0Ap=#qe$?S5*F?J-lZf2XL0{vT#5fK3*taQ3XPsNe_Zh*sfb7K-Zu-m!sv zxx9_Hc*8dpIae_+p!=B}eYmk}L-B_uWjMAMX?Y9cD6S9V?&m0<%x3c4&@SG=B!z6bTD=i&;pv zc6t8;s=WPYe^C4VKjPtn_TAa*&g#8Y*Ts^l&Hdj@re5lQhYuIF&l&qpe|LD<2$fZb z2kD3BV|1ZweT)2oX88lnLIPq-48g6PX1Li&J2^qsXTZaF+8n#~+(UlL!=ZmhMMlUs zo}`*t^4dLu#AH@SOzPZtY`nXMwMeAc$0zTN)CKXLE!58;%BeZI`PK$m}vB(+ygK5{~Hl*8r3#b37m|8>woYAJi`$sxuzE z`VP*6fuaMQpVfMhPJt^%iWI$+aWIX80pHD@h}iY_Vl6*vJvA7~g+OP5?9Cuso9rf` zx2n-w7uCh*ujJVH%46a^m1?tVIVTS01fik$5qD#S7ALVxiG{*a-btN^&q><@*Y6Ig z4&b7Z3)^=T0dI0^Sogt}sFPo^wGCdyS5rk9JT+NbJ|VrvN&?mmY*tUu+Ozse#1|g} zTOZbTcIuhQfL=GbcGV5XO{!gU!$gzDhV-Q@9UE8y|0h##PD%AmNA<<}n1q(%^A@xi{>XFQ=xFyMS?5#!u_| zQ;Hv#o)BTNnx@$vZAd+oS*`_6-x%mehkkG;B6<#18UKfp=vOn~{!mq~o{CkYXrMo( zMF;)m^h!AKH`u%qPEs&qH&p-6KnbJ&an>{xjK+gCa;rE%Aol6gjCu$2!+5*SDkqVQ z5{;I?8Z=2hn$>Uu{aD2c0R+Srtm&luO&7NPvU3xfKBne|*Ku4>k@<#j0h=6^)~v1`XZ-+!C^KOg+;VpWvJ z`PmkJY}T%!06(c^nNg^R@b>#5kgk^T1j^axU~=U;w|U`xw|>{*W|5huWZ-{cYZE`I zDI{Qt;ZI}uH%p`~(N*$NZ!<-^wXEyP#WP;5VQ9=hi3SGVlW(=fXnU!i>=KH%-Z=we ziSCh=Nr_%klg{h-rBh@0Gfw|IdUod$ALQ2UCVA4WY4G`*fh;|dV1hdP*Y zenBx;C5d48BR=?CyD}bpTlJ++W@xcjG9^o+fL5d&c(AJQUWk^-Rwd+Q!~gI`c!#$~ zb!rz4AU-rTfHA_Se!l&h=x&nwu4N2Yu&MRBs^(o(etl}G;BH~%a6^h+XM@0+t0+wa zhQAl^8o<|T>-Ga~>jlbmojpgp5j=Hgt`N~_A=>}a?aSTw;mV;DdZ|EvQV?oWe@d@$ zN%L*C*>*GnO8Fp-ybH&2*$~!0SOQ_=c<#kxm;j|SpD;Sc{&}(~kk|F|p@8w{;ent& z0h%6!h{#l>#O}s-*6T8Z%2#(d@z$kT?>Nl_Y_GgQrO zfQir@9qi@LrG;F5)G`D*DWs3b7t3=x0u_^5X$y+pa67uS>%aEV={s{_qZR}&$H<1q zyk|CLt3v#}R&MB^p9%AX#0w0F>iaZkW zW*2Y!9Z8-Yz(bZDqO{mSf1+5QrH1LNQ6Q>V3g@nwg2n;DNcqE1n>-(;t#JA;QIfBi z6)Vt>Yn*=EBC(yh-t}>j^VrdkhAx`e74Rv9P2>SPE5kx}|&4XxbRcOfAQ>wRx<8UY^wMqnN zwPD09m?`w65C}$T z2D~c~zO{=A`&o((^&=tNH41dcM1G4NPPj3RjpyIJfg$cRHc;N@w%BoZAEov}xbNFb zYlp|}&NS_gD1*H+8>Mhl7(uF2)GgsV8f0xe-uO9a81;f5QaoD%j z!@k{Xn785CKSM+G;il*GgVyVwif>yzcy7)#msG!TSr9v7gL7kCfCAjS*6ZSIitzQHvZ(0x$d}e{uDxJ#<-JZHojnrl%v`@l43JvnxEpNr={-W% z{TOS2q@36B0$-W9&@tlCP9F7_WC4PBR~tle&xvekbLbq_5GT`Lq~^$Vib7|RGWH6B zntD|Yf1R7SPWe1*&Bu9hq`If>q~@c$(EJbsX_Q@)0mvJq7N!>-_R^&0tTwAG9*gs22+6sWL>m`vP$mU+o1S zjHi$h2h`*7u5n~oIilq7Y!wQi`r0VBKo#XzXe;cfpjRJIR7l+IP8}m@VpZp=>Db60 zSXtjecBajquNQ&sf>l)BRGonzHvm0C)zgQ(wnH&MO_q12I$ZxyOO^3I$$1aP`%p$3jAhzfKI)B3>0QkZ^E_K~N z7puqUj|#zTM1mL#1Oe*75iuf8)UXdu0U3)6e4*N<*HZ(U6K+ED3stYYfJncgC_-v= z|6jx14Sa$>hqoWn5FD@lZ0&3nT%Ng>EcI+|>ze&B3p6(DNvQF?BijC|yz!nZcZg&Fd#-=PP_K zh;X$X*--n)G;L2DQDLEqis1|2fFy0s^vVZ(_;t}mbxGK@16OS})GnX)s;b$upYih% zZEF~QTz_)*coa>f{8*v|tcG=%S=d%J5}A7L=fwD> zW7Ih=b&PkNhR{t~Iidoo^SSa=L9V7YWO=K#OgnJvHMqkMG9e5X{`Q}aPu&EHdfZvq zG5Gbl;|NghfSY}I`z~A_f`N3+a&1j8{)(1pg^}?R0vld-NuI1CW3qSfspD5~zv16P zevL-J5x=gPK3Ue<3e_&V{*y_Q-YmatMKcebi5<<8u8pK0ul7GwnILxvzCon_r_|W^8j|FuL<{b#x#0sG?-_Us-rv^G6a) zwIo;_1W`wqs-qq|wX4<9tYAv`>&*gfwWGf>kzGnho2`dorr&jRxDKLttb<2L^W-{s zk?IIW-*MTH4&HuoUI&em327Qf$w>43A1T?w?vHIya*o2IDN*tU*R$GH@vb+KHR6+# z_uNimAMd^&U&PF=LdNoO4aHpp1laHKZ=CosL-KQ^E6O6VQ)i?HOrTZyY$txT2(qte zV3lrIvO3NFY9IC08wUoaU2dj#&Wy@qQE|X=Aul6QmVP=rzX6q3L_-Ztsa-m4?D2CZ zFn%A}hDaj=u4ZaTdX z`xd>7*g|u9vw4xJ;lFTXlq<6?kVT~7p&5H{4bQYQ zILvgX&do=(l_Uoq;_Y>>=`!xxrPERT*{SL=s|#<9eKvbADlOI|)3nf~S?Z~OH^RUD zH~kchk3Qshj9w(2188@{@@ND`%bOEzaoOy6?4kvO$74hLtC80I#%}VgnbzOW=G$wR z#k+3hHCqUaIav0HcF=^A)qBIs_PJ-Rkh5&s)$XL%Bib%a4m`}VitApRG1^^9JpGj9 zm^Fn+v8!|$((DVd*S+M3&3J(5BMKaT_ec_NS%2W#2yf#IVKmTxN4Vrw!{IONhpOgo zy{f$Nr|qAAO6_zF-rvWVr$JcdC=OKkb>$X(VHSi@t(~f&g$Z`Wax=v(XwhN`2EK0J zoyxOB<=O1frOdA?7Gd}5y=jM=;UbLLC?bJJAv%aX{o)XIzw-TpL(k2DqC~iOgA`0| z_~T<8^gsI`})t5c=h^Max`e=o1-?kc)$aM71PrK0^MR+PF**YRRyY%c&}A5#P> zb@lSzDJGOjc+^zZ+%uCKyS3o;0eU?vZ1^r{`Uhslqp2W1;m^-|RQ|?R&d(!iuv)a| zPqBzKE@|n$ytJHK{V7kMrChoEDXyzVz!dykXdkl6 zVEuU2SQ*gn&4O0 z0lClZT`(OA?t!(*39BNMMR=s)TI{yodv$AwXG(nb@#TCWEr2IJ>sGN|;dvPV&_b_G?X*UT4wuLahQVla^pZahz3T>0iIyV{ z&x=&oIq9SeOq>uW4poS3c_HvizY~SP4|&CLfo=7m|8>a}b1Ri+y822~71FK<2WM-1 ziM4*j&qwHLgpr_8v2d_bl8gz5)<&4p_+VRz1c!e86gc#QE+V|@-n{T=#uSqNBpB5R z8=QkrO9N|EV@Yyi(ZjbL9iQ6)in;#nDt_jLI~JDM20r1rPD6zo+Rh6f#e2^+7RGOd zd?)9WM}hqgCP(wppHx?8u3uODfOb=~ zbZQ{19FdpZ#HvDA!_zRAMB)u|B7}a@u3BNdW*cfJQxht~QOCLRO_+4T5^zs1;ObB5 z)h=miiJbnj@(iMz_0Xr6Lna_6JNE?BWO_z~1SE*0!^o(*lT!LqdY(&KTC%J^hP88c zRBI98bKzTM&kkmT(KGKpo=0Y|1I?Gv(US1WPq`UC7}CrS7&Gn*T)U3{##Fm~;7N6& zS9Q`OB-nLZ4?ycwyMUAq)1T6PmQsm9^R9gBjlPi{9)FR`>yKI+R7d!WZ^2!Q&@%ZJ zTokWR%}OMc$oF0c+4pOvqC4oxRJ2l{|DrNVRH?AtxWAygfCs=H#;#2_%Um#|JK50;8iuFzXE|QY>65{Y^?FC zCsMndkWU|Od(j5Ixea|N`+6z-2qHBefp%5lAFkyl<}`dpEfvW?hT(He&*AQe$CpVV z@d<=fB(Hc#iag0(_Ipk2-~N|(YBXhWQh z3$6C~P1hg#c6;~b)EdCuhxPTvYm!UDeXr;h*khIkGxe+Gw6t%8-t%q8%RAhuot4wHWUH-)cE5(1oFDaou?lxn|uaM^7I7AePXHlDm& zpcRg%gV@4*WteI5UuR_(;23Y0zJ8j*O<($<=XeM}t>$|p`p0tI7xV=BNY3r`;FI-O84C~l4j zqaMw5RB?Ow^{DGl$I;WZkGEg#c*=A``TlyD9{maZz-BZn9lrNfSsl)qHBhZuRW@_| zK|1!>dm{1aB@C_25Y;48oWuYsq5}m0j1s)2g>e51Z8JJA>O>uVfv5Flx{IV_3x)^X z2)cB_*kF77sG~RKrcw*|qAKI-<7iilOGJy>N8(*}+o(by>4pkEjew$cz!7=shSMtb z#BfTVtQKtsK7(4?;LX~nr(K{kNR#PN95Qmjr}T*$_Ng4OldpO70}oh4{j@nNi%c5H zKzsPo&o%IsOM`yDU56{8eFSrt24h#PHNAS7f>*35uhiU=G?1fO%Uv0p9l1^^yv z;XxuLGv4}6(S+h_3eI17_(@f>GIlZFio*vE;QW=7>Jh|cXAm;^a~;u=sv~%u#*M$> zmLoWhTjdS+AJX( zq>$;n^W6}jAN)(lV?6uc!`~#pnkk=WS@Plk+v`K&f9XHNz+YiE;)n~VuuA93gy*a__>cWS_EUFFxz0kBWc0J10pg z*AL~I>HFmGpkweUu3!C(L$t%GaeZQ?;dDoVdzQ!PAb4l0aG^ci7Cv== z0qe%HI5cb;4pD-(lFqOhX-&(W!zPHdYhT=4Vje;-p96%SH3&rnYSr<3sKw=f%2#Om zMmxGqP|egnJe^y0xO^;)zU$It#e;vAYKvHBIQf3q*-z*?723l;&8oDON~<+l0({k& z%Ndj0mh7f#o$}CiqY4H4q-5Y|dmPK1&Uy|YAE@jU`n1dYIVExxT=$^x)S>$7l z9+DDiM`RLB6r$qNk`ug_!2ko!mM?Jj0nR8_IIF?CMj@ohL7PGg2C+5wI5u$3;T~3( z*QL1`DbpdqUle}AyysY#jl4>`?Wg>UHURT0BXHs7sTN#o^SR-}W)R!L@NJy)B!zf- zWyYQ%X!wU8X%=2~#h7X{sNfz@kpH^-Waw$x5!BYA;nW+mPke8@n zii5_zJ!SW!zd`){8`V}ApQK&n9}GevSXUN3DBti$Nssyk zUEC>y%O3S>1{sX*D`;UA&6-dG_OU)qg`iy))yvkYY<$%4^LDFKEF0Cy%cuNHC#I0Z zK=pl*mZ+HF};ghERoYfK{iF9V09o~3P1 z=N|*)k$&J|o8|$kLTw`n2897I-ll=5Y;3FX7sPN|focu-&MOSLf^^1XHqq4=ko+t?~8B)eA z%bjb>a%rlsE^5kHQ0*Kxq>PwX5}Ys+#TI4D7>mN0;d}cIhE3C%DpT#s>~QK?JR%|R zZOK7GAiS{A5E*eZ>|l(WP$InirnikgRYEH=9uapp+p}{4T$erra>`{^wZf2wo6Xj& z>GW=Y8;bcF-Trz7%yIaBVb#QcG`iHE;y=BXa_Kcu8WjVZ`(Y>#G#V`z?Y2m#x~klu z^oy6C;<`!?Rk6u#_{``+40)KtfoG(ARD7Z3^+R5|;+V(BDtK!#4FYS>d{q#8Fk8$+B25(TIHZ_bRWH;cNJuuzka&8R*}JIf zh~AN+N+=Od5Ax}q*%<{K-rb3=`U9(^a=JvRLVcz23FMdxlORW1iT6T0bHuzX6N-!N zaDlrFTZ7$%qtU1K8JUi$_k#9HYRRr zbIm}{eRHgAOG&>8wXZ*=#<)@y-X2Hr^!i&hy!HcnWho2$_b2qoj*lvKeDoYg^RzH- zV&|NHl(7X{&;+I7B`~2es!oNm8>o;Y)Fs!nrmsSUe3|fXaoZIW5B}OtZ*m?h{Ba)m zs9mFz`!s;wvz-&EOpolDF8{)78f2ea!g+mY;z=c$Nz&p5lt6xD3Ofl7w^yrKNSrxB z$yLiCD-zYKpZ;Gc$P5)&<|rN9B;DCetDW2DqV7hdlJLU49Tfo7k8Z)`PU+IWWdy`| zC2l*zaV7q~1Yt%%oG2jfG3P)XUA0o}CReR;KL$*_111v_d=4FmvfCB`3gIFcmPDPa z@lqSrhNG{C3rq4Gf&%`F&w5Z8FQh+pU@nps3X}Al&v!!b-1&ToQ5jM06lj84D$98% zUS%!tU+8>pjyVxtp*E-$MQA~}LF@Rjy^fJ`p-eOR(Q<1;2>7RRP=XLdiKZygY>A+B z%~6rxXi83zzR`OY&;#~0LNy8=D5G8kv0JR1;$0Pkb3uP%)-d^STU6O8W<;yPtOw84#o>-pG4cJzDySgCBMdxRa$4=33B! z%;%(OYG**>N>Aeg`d;%{XbVG3g+0(OHR?4mJ4S(*jfmb3(w6ttAfJu&WNr=<*gRH= zcGW7;Du7`SRoA5>tABefnq^L;<#O$VpC!&&x^8v8hyG;1 zHoByxv+sjEYnxl=@Z8MH9Uq3tX&^3-xon>o7lFuw3ESoKk9kVb5rGFnUA(cE) zSJ{E8H1MwBa3jEk7BpsiEu5Os5yCRsA81CxIZVTi@o zKoZ!*qQVB}hdw2>=ig|e&)fuLOq{FXmA|+W{96g+u^tX4$p5TmAmXJ5T_GV!?X+KW zCAik?MV;Ao(*o;vWX}A?9%SPd^6F1=vcOWLgV^QcB6l>36o@~5v0EXBMh47_9rLdb z&IdqgUk`<`YEb^{;{3rj*rg4>?FErah?zAaF$vL-q$oUbCiW$ZBrMmjpDn~u&kJHG zkk+Yk8i{hRM!E^IyqFxri6{s(L(CiR(pN6boBa(XoUkEvTKCzSx1j6aelaY?O~e_M zgrB?8&G#fk?yBrOU{GH9Q+dzQ2NJ?PRWW2l{b&ks%GA7BBGhiT8<)W>Hs(TE7|YFE zAx>N#ZuzbJNiNIm?dO(T#3LBJ?AJn;hQq2}$O;!Ob2DQQJ|ZvC&CLG@1rRPFl<}vu z;Zf?X zRR%-uIQn$B5gv9D)l|aKh%>hw&~^5N_^cYtKxW-8zl-;bjS8se1am5uAgM&qgS5s;d_rCJ#5=W+p*Kz@SFoW?C|~cNPLZY8JRH zju&G4otYo;D^uPe>%_nwM)|Dxgw;&p^xvFJJ?H)V%$uflS7p}ex2KmcI&)DzSfmQP zo2wq1GSU|*1<%r~)d~;Ul_P~Fn7Mc&=@fHjs#W|_lI?q^M#(2K7m%E}WnQADHQsYn zM5BX@CL-#tF;7&TWy!V9@otHy=ZK!PS_L=PL(r2TKLl;R42W6P-qV|TNUfxgM;On< zRXg7t8Y7;1U!wK7!oH|zmPZe+PYV0+;QFLV4RBl~99M_?!;j`+<}lX(^<-*Q<}2!~ zp(}H`wR;@x+Bv?oYis{yQFZd8W@f2}!RTvt5J8^cw4T%^M-Xiuaf8v%fE-02FNQGFLH3vN zk#J}P1}WKhLV9lfBRS-SFdZDrxVxSF)IioSn%l7CU+hkK7+pncevsHtFn(F)>WDC# zGE409M_^?PO?bx+VE!sA`BEe!+Z$(Z65X}m-eEuur(SaMW9K*^Yac;y!gF>LV<@1J zPJ$Xu{o?7=$kVCDdUFuYLv69lKZu@Wm4?JJC=ITZ|7rdO+Fv*Xeddm`STa0qCh-44 zrE;88n&TWDhwgc1JA2FUJFAyv!5^IHJedWaZ#(VRY3|GkoX-*d`AW=0$c1u|mB`r# zG|vX-Osy3Y&Rp*VY>|^XoGFvOtp31gC;qPfnTp9tAf3WmGR$%6EcUy$%jq$h!b=vr zVa|oBKCd33XrUlAywIV0?ZMnfzZKlrjGd;v_62-}Pg1?wMoGw{HNK;KlOu*i#Cc;8 zs>9uBRdJgNX5rcI)=;^pj`@`uwK)+oZcW=L_5JDfjDp8Y7Y7(0gjhaUMw(Fmh(~1(J0t`n13>%TsYX%*i z&E?TI4hQP$+Yc5gi_g|IuB3K|&+Za{9FW$=g*m-jNR7B=6qjx_7V+QdFxFHQL>Eg1 zRT&&B7dnb`2?b^02~#v;5?W}RWjqh>aTr588F2h*k zn>-a?b1^`@A@Ht=WiFFC+!_=&9P`$|zvE?q!T&Hp{4;AWiyyu$K7VQaJH7iaCH-)G z{xYSP?f-b!8^x*BnKQOk-_Mg#eeuscMCqmRo0rCK>)mlF1^3)m!5w-E(2-d$b=S4A zeEKy0-?ja)t@a=|Bd_2cy_sLBV9@xwZsF5$23tY@-y1y+yEYVOZt#u8dumDbf0HKn zXj?%o8N+55&wFC2`L+ZGD6&nXSz_l=ENs34hWkz-!{zub=&o!O4s85-6Kh>ixf&g5 z{Az;o z=Ka1D>E=J)>vZ!3my_IG)m(jS}CRKfK5SpN`{Yh&O-hn4n6fB*cA)7EmV=KC$Ay-AX z@B~*eu2F+LB}N_M95YraRS=!7r%^Evod&8{%K1l;ITF%E{bVrTex1|V%(_>*AaY)K z$Nj^Qj|xq0Si>L*$vB59y7zvrp9uA*I>BFkw5~t#TIiCr7&~*SY#Evxx!s`8hO_I6 z9WLR1!V^%$KyQ*qE9lnnwO|Zl!=ApmzfXoq4w#ZAJ6@WSr5L$<)pC0jp z^^FgRs%I9L<4ZGD6C_seVH*PLI+WTrpm{%teGq{yrm^5nbmnTc_NFZ~3~@b&CZ@8- z9)K#Ht+0TPZi9pX(g2-&C>D)4XlVxC)#;}?`0CU;dPZx!AhuQO+3H?3K?xI^My065 zbj!AQ%7fn3YyBcjB0Fr;af5m`_aG2HFRc3YhhV#JnOk2#me!NK)zMVqkx<16f76E% z{`)R+oj2{-;_*MXvX>5LkKzYe&VSZv{N@pWqbAAl9N`83tRf0iyVDYc*OKs_EpD2| zdJn!L{qXXCY3>ndumB zr_cOJP#EvkhUC~$mpS9T&X6JFeaoM6#`|%C6ar|Y`wFJGMf?m<-vp{yZ_x^~Bf@T= z9gP0zF(&~xIukA~36FR+JE3O1;S5y9GIsblJ+TJUr`NH0V!^E9qImasSv~BxwUs`j zT9r_}voL)IfLWON{&+;m9NC?=Lu$f{4OsJ`qS+{$$%(X`X^3cdnOExRPi6O^2Gf`n zia0GhE3}NI@wPh{g7*ptcg~C@ow4&4AsByJ;P^G%seLgx}HerfM(~QZq1=nT#b-8o-hk$=8zAVEmhx$cJF)Dqxv;ilVKOE@9p2CYj6n z*U<08ca4AiiDE|cEF_}+6Nfp=(`ZHs4sw9WkT0=MISQdrazs(K%&`)+AjS#yz=Q=b z%^$?R^e5pBNe=(U1}mYqDf5)PVJuUfcu0w6D##z@l|Q??YC*07zt6HHylhjU3dtYk z8C$ARZd@zRpYN(vy}>p{dDYJfF_VQ>$K9F3W$S>cHG-+b5_~ou$3b?;4a(d0c0h)Y zyyrlREOu^2I9elPpnW-&Z>x2-fIw>%riL@rH?Q-cWxi_RC#Pi$2=fyTJk)6!dlNxl zM%M7?3(+z^%&xP!G#Rb`N59f`6OP_#(@MY3v68zJZFDSjISqdkT z+mkEOr3bGTbDx*cMD32slv2b~>u#Is#CRQr=QY#IC`7;nX9M2gEi|P=k>{z&+85)& z*|gb!s)Fnd2!*=UAUoTT{=UtJH>56=3%JPqv<4;{ILjGjBa2=orx4vUqp~LagMcxL z(#Ra^kAm&A)M*bE#xa}qM6&A@hTWS+wH>Xfy(Eq^o@tMLmGwG;Guz>pxU8W*^-vZw zdEQyg@61` z(P_ax-#INf^o0{x#&n%1sD@5Uje6m<;H($Wep|Sfpg#3xGKhkFS$+Knmb;sM=<4MF zoaGI=IzpRi^N=#PA0;JdD})?AxB=e-*-5!R8cWVxAqiqUH~#WPC)1g69LzQqV$r04 zF*_TsAL9gdq28bXp+j`aDvf5nR76;^AogpvmG0EKYqr))wXYXn)8>^Lr1ZmAcQ2ec z)UbbdB}j9lrHlxAal2gz|J-95sFXC z-0Dx(s!zWj#o=X5D7CRtYB_yo@wHzo*N`(Wni;+n$8R)q+tYi^SDgH4)|Y8CLg^#0 zqZSFQrnuRj8cQH2C=v@YSb$cVJ9hoPGAfcn3`5yLDiD~$k(}{r&=BkSwL;lcv`&{c zWxa5_;RX73sw9oSl4(IM!*70uE@_=zzBia3Kctb>PG7&O^8;qCcTBa&g|h?y3)%Wq zvCSLUoVF$l;vY6JU=na7Qa_w;B|S4V}lDG`hx z_xV#e)AH$f&)Gb4{|*BN)6H&3kxYG=N#VYw<|Empu-Tf_RSCbbf?pO+7}mx3vbsFV zv&=arfc-chJJd`gC#&#u4NvUl`}Tl!dwIdjwEJ@)*5eD>eqwwarbethbU z@t#LWo6WOJ_)?G1gERhtP}e@%UZ;Ab>ZBp$mg(84uWlDU;CY?@ZnhKdy;sjOSBPZG zeS1A;MQt3fL{R#5P^A4McEf>OkU8XTpQ7q}RXnTPH(EdrPLl#bx7*ltzJmoNWg!e; z8?J3x9JpPx$8Iu$icRdK1@xy*EzmEms{O1Q%!h(CWH;u|EZZW6z!wDH!^y!Dk3oST zHhMr|4!>~(7;d2rZCT^f*xkIhNKNysX(^6tHx#;h-oS=;|JVd+)lza6IWLmgXoNKyj!!;GdG=l z>fW!%du&2l?vU-RWixXy{@uT-)Qj<+Hw89I&?xtX?(Mlb$a8HFTl?+fX@qI5d;V4E zAx0+q<(Y-v!bc$M%uRdleC1p1UlMsg&jk3azYCy;+fP>)dIgkZB`E*&MIxJq1JYeK z?Lne~45sxGQKCwTF!5-C&}5cLh(PXdEdsPu*WvYMerhiAauvwzXjo@^_wvl&MTpe1 zX1lr>DNVxbkj@NZCzm-ghj+d{JY}El{IBtl^z5KBY&`i7cFD{{`;|FrgR9=Q>#rkS z>2XA$(O5p(jnru&6&rM#A-F*1G*1{wucq6sV>~z|0AiKPX#kKbcN9s@>8UzBZ14q> zdf4b68pGe0h=JtYA==ne+i~dC3~?1F+H;2$ZIo)X2Ko--6ZNT0nQne{*V)bditIJ= z{OaW1&}<%Kkaiu>SeFOa5ykU)a2=7NvC$>||LHDTZ4|A}?^$Dh&*(y~XU*ZXGS{=# zY|lF6hnoULAGn^)AGT*$7r*2?^DU;9u|M^xjhPOT-rU%m4VhW)P09AVpBC@=DL$(i zpj+j{Nq-1oHW>)-_lItv4n$M{gS-)j zw+&bxFJFh|6rAw##ZhuY=8Gi5#ov%|3vZZ$Pq>Lq)j6MVkiYwqxV&(`Vh~%{r~$g| zJybX_wM1@}o68H7AN|tIPLBlF`|eHXwr4+HlHQBM8;-``LW-M`n$V2jxCOS4Fa8uK zP*=x$UbBa3oSnX8I?c ze1d)ug%)W|23dZmH0^0$B*v(Q(q@e6EYa1Qj10%FJ9)#=5*8W`Mdzul&M8hzELLXJ z{`n3Hx(5_kU~zcwWc(^-HcpfI(pn@ctEP_T;>aQK{(VXK&wms)9eE=Meq|V&Wef2v zsAG%Zr=oSOmnk1##UMWz$Q_cUmmS_7FvHj8=k}4t9j!#m%y*4rMY^tD8wIN=1Yb${i?6CZ zUm0O%uIQx>RJw~Wk+yNBgj9d@VE?lj@6y&nJ<@ilU!Ijka^_G3d4lq_yC~)&>Ocb@ zbBPv=D-s~e(72ldNDHr@J zT$|!V)fN%l?iIbMp4+{aw=GV$yO9wDOGv{wSY=;$aDZxQ`0F;c=S2ug8dN}S63MfZ zP)}i=hlR3sjzK9e1)g_|Bo<$~tFidkyuKEFqYRmw#o}v@gT?=cR33|8n#`MT^7i^X z$KUs=f>dOu-7hN?JX5IZK5HV<$5CMFK8Kfp%UxN39=xVZOZ!GBVqFB*r=%N-O6t=i zjCT??BP7B(6u8A7y%h26IN#Kat^d$OlRBl)dW9yM)OAfXp~DyXDX6LFTNFqgUrcW# zqeP<;4e9X>FW$<}#3}Z3*s1zK(wZ7j{>_>WXpzi$zZccnNvY80_W^MM4?1KIIOZq` z2IkqXW4FwEa>Q!ijdxk($&L<-B9JqxHz2;%8)ak?5(gL~*Jq`BRTCdd^dNTBLzy1b zXFVXzIU`c72gjMRF+4byGg}wQhQyCAj`tNI=fPNv+Dr_Mzj$cYmpX|A55u8gyj%qG zxPJSIK>B}+!Pf1Uzs>av0Oz~)6@y%uu(QWTP4#uKVYg?)0{)xl{E=Te{u6n{f1!Ty zN8E4hwMkCtyUuF>mHbI=0A=@?0jR^qq=fS-{EUdjs3QYr_Z*fbQw&FBxx!zzsEcOC zJvGcbh6%))*+n&|Kext6i)u!i7V#@8Qu36eQ6@F&!D%x&*gQCGW~w^7{0MF{QaT;s zNf{BWPAI?E(BMhAz(0IwQc^+E)3sH#HTnnBs7?0Zyo+$RGWCD!ByP6MbN#^{^WB*q zkl4sFbA_nI`sQf$zLQ%yOb%r4Md59%BcuN0dGuL|bTILW%^I~#z?+Efo16hrMn6|L zgo)yI&PoYf#|98FD4l(C{+#_jY9q*xj}7%gUR)xx8j(9PrvD#rUjiRhb+!-aV6?=E zEwNFF9Wa&P8Wc2C&_MwQ4K^rhRH|`9v{WM|5EV6;L>Pywh^U}caYyUIr--zohDAW! zSX@wC;(o_~1s4q1kNltKeb2e~&SXNc{rb;Oxo7S@%X{AaJ*(0;c>u*(h-%r15zskZ zpk+}+7!10Q?I-V~dcAT0_?nwo1L`#x4*}2ks4RXrubZ5>K|F7;cr!U3EG|#dfa1ml zEny-ZFS11bz*0k@1uz#@yR}p000i&O`x3lgFOS?S_<(Vn%G_Yw8S;eUlG3L7iA&ik zNCn5xDa_)RI0qVNy0+_CG@Nu@`wW4wjE zvz?&4Iic$w4Tk^uQm?kBnyxjej(i>t;~p{sFr}bc0M*E#M$(iw=&l_1+7UL=hy4`h zuwpFw1PrQ$RapJP_#jw^F352oIhhg(bC6KLS z@i$|&pZ<;+SMX=;)~?~Y`+3{sPs?cf!u5ms!`w%Wad023q{LJ2|*0UM*#fJ5OP zeVFzMnu2hk{bJcD--HcnL~JQhP|GRQWq7jyEp-6kj|zAmD7m;r7J+DZ{uJpFcfZJT z;Q$}Z7Cu0rASi_cFTc$MHG{f+C6dK5E-*w1ZI$?G*gutS0kQAE?02D_|MO z{raC&?n@l-DcWNMmgWBb-E?MRwM4A!&`4pX?4M_5l6z@SJXbOk0ikD5$b|dVJe7OJ zH@rsas4oCB_}j@nPGAG4I5@wIub{25Utacei*Xje7z`}}u;`Ki=Ph7+mh;34fNHQd z);^$87E+#FZdTfYk*rT>y!(g%W`{q>v*v1RLPBh+bpZRgH+q#MYG#<$BeA$WGYtGC zLn70S(|IcR*#bZwl9nKxEo)?#6gNe^16+mYDPC(3$;4QF zm>35L#$g@7mdb`$?RH%7_CBkt-QKCPQ`1w#p>n}IwT<|#>_1PP7;t(ydcr?){b-wZ z`gZ@3oZAQ7VTv+jbN{?HopV{7U1HHRHF#Abs0MXKxVG1p8a(6~)FfH6;Bw`5EWaYPVv8)Lp_M z*8fsl-6)+9-`H#g0Nr!kUr4R0^5QN**&Dq8mR%TTUf9oJy2{-#CLm z5X5cb$p)L;k_&a^7V*{0zmFh3Qb(sGuR!SaN4o2(*PSRm~qNX&A3yp@V;^nt}G3{s78 z3WWu-o2LbZ!MeWE9zLC88+pPW@d;N6G?0i1Zi&0suat_= z-_|`Yq5cMM3le2@u&yj566UZ9Iu#-LI?K=-F~0ov)$ls`z0gQx3)jco0K>UZ4H-~h zikkRGGL!|<<$?5Qlg2FYrT;tuUIs=Qpf1>!j5N5+!vT_2PGC_ul8} zxq?8*G3!D81^f+MHQ>oVrdQas6B_z0*-=Gbii$^e`|IiK$l|0fi>CHJw4@}s2JZ;A z0X?Dx24&REBmM^6yql~~S(}{AHPmn}DhM!E$KBD8JVcJJHdbARzA)k@{Sik9BW~u0 z_#P4S1MKNX+H@v>wPN{ZBJHU8A^28>Ge`$b6j^4_BxbUev4T?bqntm=%#YFhQEq-f zhrv@YKdSjddIHqf02QvK8uI}FQC+xsBz)u5@&=t{mfFR^TSzcwyh;vT2I~rM$#!#? zO=(4)-J`G6#;jyldfX`hF7B;d|nCiFnHjijf!aSv6Wc-ksE|18 z_d&RJTNYql^cnQ9>R@d3{4IROuD_*4C}IFtOm>bKvazW`q$RQ=*A>YRbc+oZ%a2q` zav~1DW^ZHcZA4(_x+p+VN+_gn?5f;-K8DaZ{m)@DM8?qgh~}I`?vZ!hg9Yhbnuj?f znz0&tx(wKGQ_mKx&Kw%=(mXUisF@4ONn@g*1Y7%g?}@2jC<@$7St@=Ea2G%sKc->J zN-Fpny8)ptc{&0WVnwFInV*4)Vhs=IxWp z`2kIYYrkgL{$C)N)vfNGSgJ^1L7oy)ZHl3q%&4am>?}f)La;#~Sm?$(G7$`6=jS03 ztSbms0)jcGVXuenyH~kf@bJ=rO4~`))qiCcBa69{ej@G5{SIffv%LX&PH=kp3&m z1bhJ#}{E?#O_GJI|d;EU~-zssdd-D zf$TQtUqgkr`||@5m!ePQ`V}C+elr~6ccCa(CnRtRWul@m77vcwxigL5 z>vez5+b5!Bi)cYn2p4`3+z2(A7&p z8X9w^n?Mb?b-x5Y*&g5(%EFgI5jJiSAkE=7t7RwE;)1`;Z$%%7?u33gG#FpXs$@su z6qb=l8z=+B5DO;Uo9?Fr7o^S)fo*Y$dx)L8=Z^$aX_dTE2x!&fOx2F_j5_oekL&`j>g*#QER1oh3{v&B+&lul z7t86}L0bQ*!dk{nzn)V03W27f~H2rbMRnWDT9KR*TZ@;8oYgoNnjPB8x*1 zAM^=S>fuxG!Lrv~aX4GaC$NE2)CM+G?FokY1Tz0gRx&9|kU?gOqJG>B-;bH7D1tC z{%%K5d>~%~M#UQbWFy8N-2FUIW)r>8{|V^-7BJ}P-nqjTs@rVg4V;JM{(ZFV ztW_LQ!xgGHrkF7#kI}TNK}I8QL8F-v075?%HSmu@KO>Ny9Z1iyX(#kZqYcrfm}y(~ zYST;ULeFZY89trR;p=QM)3T8D@2!flRTg85WCvdtWZ#q$*&a%e9mt0iAiuXBYrp2N zi0ryc_%_|B+Ua^#0JvT;Hp`5S&ND92OO$<*RlQNTLhmWY)Y)FZR)N6^!Z=qz(18;@ zp>OEO9RCOL@9Pkt708Q2Tbwi$O5Q-SAuA?Mx^HSF{oDXEUMwusM=-14bP(5 z4MZc!ag6Qoh6s%%b`-=wI3;*-WVI%WSmrKehv29ysqECgSt65oR%>2p)U>_5RG52? zG-~KHn?Eo{Hy72lrqk&q9-UTx|5T)27t%|KO#n$l&>;&jE>erbDdlbCPbh_kjQiTX77bjOE(DsQmb*iAv zMvA;|&e$c)SID;Jc8IBzTv7SgWM9#>4BO%#C-*`t?q4oa-K7zE@-{4#cmKXWg8i;Y zao*aG_hrB4-v~>q^U#XHN`fq?)+lU=w_nLcpyie6>aA5mCrw(i}@0iW$ z%{%a7+-`{_X*>^&@(3KD67j-AxspA*GasOY@k#IMV0_Z11{}17D;c~B_%nFq*2aAF zr5J9eorCxL;|wY=>s?pVthTY<6{KxspE-E(SDEe1zIq17vPS|3KbZz(NKF8%2ReeGaIB3ej3iFnP6;|#sIi7>)j z0D@>=$sl=k4VBqsBf@X)*fgE-4z0s<^nuV6%th78Y87s?M8A{<7{qu@rm<_c?u}b~ zgz@Rjipk<|eV&02V3EJs2{9x!BQ+p`E>*bUecF}5bokqZ+k{GBgyPs^9nfI7{yPCr zc0-Xx82L-z(NK?8gJT$))W=-kCt_|q%=((!9TvAt4Uzg9yw;$ z)!D7oc1fOH0boL~I9wzr^yBuRf82|eI=+F;WD`f-Nr{(n61hDINKd{j6H{J~&3TJZ zr0j9-Yl>RS4hRO5w@3k0l3YtUhZqKERC%O_qD=F9N*@qvr|47FmB7NMGx2%FmEhkMu{a#&5e2d2i!$tMmS@+m zCo!=Q7RIlf^kHJOB*6FOL1r4wA1j!Jfti!v{{zy4;zYywdwy_OM7(Rfih#q^YBJ%z zKV69-Kni?i$&1Yxf=UOws6%6h389(XXFB+yDCAD3!jtz)AB@2j+}HsfQE*luNz?A% zdKj_>T99PdHVK|=vj9Q)pH1J@+b6E&h@B&3z6CU01tgofnG$+Idu*4^Sm5nCMhkx% zdW}2?Ol%Tb&~r)TpYSxbXWu@2$TAmF!F^?$>y0wts3%jc;l?EQNBXc3`*s>p>NG2F zfR7w^N|A?(pepFMDqJ^pg;Xox>ZmAg*|F>YH*0oxYj`HUSeQ0JdT3w0TleFQcn+djp&`>#^8}=!46@WZOLn|+mt&Rkuf<^wmmLtn(Tg;3)7#C zpVsut^P-qHe=(@QtS{X&2Q5t8pj`Tdf{)1y=?1z}2(3VHn+b?4;QzYDU%-E_nZGDv zt~eI((^GhmSuxHfr{T-~)=AT_5(~$C%kd1?a-A0QUBZN%>Rne>q9@=FmRC3|{bZhLL>p5aMms6+y0*6Ni9~E)!oN(=5X8b z6G(Q&52e!%7#I~t{VHaQUj&=52=E2`l>`xYSDfiiy8(Sm-ve?}NVzGNq8O!>=M)o3 z8`^k_OiitxnFq0?Ti$RQY&!Xif3)wbG%0CHKmYi?QBnlf*mDm=s|T%r2Z!H4#xg0r zcS05OgZ94%GeCDJgR|o_Il!YxgpQAmx&T7h3jNA zLk?^%BPtT1zdb^K#3&3**4C>cr@8Y%g5#2Vvt-P_mJj$WFzax--7en+4D*-&=d^gy z%zR3JqlUxmx;=9RCOEEv4dZ^uT;Elh%U7Z#l8x;^85vT;woF1oI)^!n4BV;D3(MbRQ4D} zAa|%d^8dgG7#y%72qO!Xy6-O0o|KbS%E&6C8Dse<5wDe^OQF~SO0L6|HL1A$1t{_E z@W_GhDOYwZPky(BcX-h0F?V=$kZ->LJq)Xy&_mhSMTEY>z;Rs=@TJ&6B5Ls!Gx&kNkc4K%r6=FC*s4-J@R9ZURekWE{^4PQe#-Gs*y8B6@AI(6EhKQJVa#j85ON zTjbvv@-#==c~0JvVddmwvE9V7pgb?*nCL~6geYfF)dU*vd z7zuWmxSeNN;mkQ!Otv|WJmTa&W4Yj3et`F)T9P9I^Nc4`2^aRBq!&kq>z^jWSPZZ( zaULa#Y-6+z#&5P1GIOE$Jx6}qm|G&sUmq460n*c3F~!P^9DWdw98jxA&V>8+jRe~G zAvX9!C+Hm{m*NzE9#y87XISCY$VYuNI_IAr6&Q-hA>kuC?MLBuqQ4Vu2m)#V4*!^* ztVuv^$0E$u(_hNdh(~Hzr)WIrICe{VPt5`ng!(@yI_^+;mCb< zAxk>zSPxil z!Gl$>-~M=k%zwz1msa=X%@CYn4uww{A$X<2A0c=cC?)^Tmak@nV6wc#N*Jf_rFWRq z=q~0vXl=k4^JRfFkHwX_rb?R3wbY*zpz2WOg4F|k)Uvp1-nT=n0?vVyY5DUUC66W zX#GLKAX!C{3q;U*CV3om1IX)yZh49xF2|n1v}GnXp0mit#{7V{`oXcNs#W^qhH8baYer6iy@MKDI&Se=nXOQfS zF|$6fA2mW9RRVIZnR{wSaLyY(=O_cE@lTJPD-LG)GS+3+Tf-AQN-=svauz(h`jV~@=xw%JI_Be_uLWx z?6VX6v)kbrMjlf5CwJ}6@(=i`HUHeS$A4J|ef)Tke-3C*2i;UH{IlxO4E*!WKU(q6 z(K9pi&v~c)Tl}-&wH;V7;h$yyYJ-0Yc2fVmbBWJCFJ{s|vwi(@Ru{uR*QMy6OH}{t zEBy0}sLQtW&+otZf(e|Q@lG~Q?+-sx){=Gg>F9OiMa?tp{3Q3KU&0|#-*LdtAg ztMx;lljNEGA%=Skg-bAL=;R)`2f1WrxPF$r^RJ|WYdld{WjGJRtb1{XobuO$+T)bJ zy}8qz5(T@QTnu)BQWvIy?Mg9QPjA<{{%@UTm|>-a#9B6RL&Hw!%435})UFw8xk{L5 z=z|%U=)(D}m}u_w%uKZI6w5>>(2SWgoXdrC7A2!(hpJ|liclIzV1wT%#HcW~WlmM_LM$GU4Q&-QV0kF4vOBKd2fb z5e)#BV2I%dW6K7C&&+15FhA5`c6;6pw81}+s0`k;nKx>bT=rl+Gue&}8?*U-;!@%( zc%8UT1mdL(4KPIEpErMK*Dh(e)z~+<1G679I{r*zrig3JmBK9D?kBStt}{arChjVl zXIaKFB}1=krYYCJFO)$o6O_6SlnB@Ox0NpuhFPAR!)JX1ZsksP4~)<46gKHiI-#$B znhqFuZt(Wc(>Sn^JyIUI!}x%TL)a*LZr}sDS3jrJsb&W%NFBtic8!Uyb09)C5r^s2 z@dL}}p$pA;1aIK8W7MA@z)wCZFLbokyHy}c_7Z-akuc+I`^&4fm6z)%UDf$OQ{|c9 z!Eraq2&--jRz%q)GnVu0L7H`D;<*ig74MG;u*;hsLIX|T{vv)R1rUoD3h!|w$tH>= zkqCV^RS^EUJaRYi0bEB(ub80To%56;yqpLxGYGdwiL@gQKEip%sX_PxBvS@97wZe& zA~2~8NS(M{u8^odh6tuI=;LEpbxbAs$1hvT(1hbKr0=F{Z|(;DcK9_3{(GP@ycs7CT`bD z8V=!05<&-wxxnSr8(9E1)^8!ID|Xh66OdRx6e~ zm@}j#+O}kb$@t=?1b$Nxy(zElf_b^NzR@N>Nsjn;^yLnvb&w;{+E*UA$MTUTtp`1# zob;bbs~+_VZMY=)iPe;AlN%+eqj2kpOyS*T*^rXv7#J5I`7g}(xt%w`-M9^@^!WE% zR+4(&I_z!==rXJ+>z!p%$zCkBcewsWfxsJ7G9*Z{9IpKs^R<;#3s4ATnrbuQA8s zlY5y*p<~xZsG81V<2ml@7}&9^%XwOSw_&&b4k z8&w~3%u;bZqaN+3PGZ8n?q}7B;(6lGxQ416`Y<)jG;t|0AZIpeS2-d>BB9M3_cu^t zO>3#f<}kC6(Jn+0O8Wk9j@vn;&4{%DO3X6)3=8rhjHpf^9BmU7Hc>4JVI>d4;*H53 zBAHpYJ}kJ($?kR_)iUQWsFrnPIOYCG5L%kjRd<^(e@FC3g~^k*h+a*f0=V`cv@U5} zV4z8cQN)cmfzuv><|3#0{3Y_HDVPI3mPvk(bGIW7lDJ<$p zIGZD-IPs+J8s>(jnXKpg_gm{u)DQWsvV9iu(`bi z*!+D3PTA}ti(P)@(y%;!wRrY~k3z0=z19lcQcjQ@a#FKUc`-fKW5~D+@D}&Re zNRy@cXP^g~NDPHu+);=RY60{z21E@WHGmr~j)TY8HFr)gs;bcN8X{X}Q*4)p$SWC- z6v2@WVaJy3P~}ks7wAS+0=HFyKowg&b|!0M~zbP1HofZ!QstSTMO4gx3Y zjU_CDJa>aK2(sqi&op==i@i!^kO1P7H&ZN}(3dsAK?5wuf{qLw_K5mmF~^&EyS6UX z8`~M)sjvvC4k(->xXuaag@!ctGcWlW))2b;xRAH$NKxMS5wIi268=n=zk$@wt?YjV z>n)FA19z=#;C6P666oO(}(!Sx%f z&Mb*{Ta3JHY2-@m&%PBOux)!K)bej|_U%dluoB9B47jqE*R9Ao0~5f3Up=QthHNS) zfu+E3?wfeu^kzxC09RRpuf z{$M{4xie3=^WW=_SB34*wDkV;KS(GPYNJ03+M|zHdc*%arq6eazi+_+C^}@uKG8Q& zNC|z_$uX%!7H4%`1VS$Yg$6AGg=n)x$xy*P8K@)&G#V8?Y*F~G^iEyUOFC8b1&DMo zh(y6Qe`)mkLi-2y9|PWieMKLPe_ty6w=lqeu^sZ?;;qVmkg1?sRz$WNjgs)Y`h9TK z6)~slsr-e?`oJBUuonFsu@?R8gMLCb)#g>1%JPUHFtdafzyuNyL2F^CHuBt8vDSo8 zN8pYr!$Lo?C$&qXOWbn`1s4UM0~akKf)*9>^zi`|Z2Z}Vo$zO2JHxlg5UBNRakHkm zQ@Klc5-(7UIcIN=)&9I|_$HO|#aPh4Ei?|g#H_J`Uoe;Gg-0`+Py7~sOLr*Yj79KW zJujOmk_5G)!M9x?LsU8Wm9KJ056+k)D-5X2R$rfLS*$tkcg+^yFV#a!o+&OsEB6_o zl-q_&*)TZRZx|k0{0dK&LWjV0 zJ}RowaM5xf70AJchna@cQSn@L22`wNG;i7K7cz}|WFr`Uf8$mAEbsF>{OfU-rNy#N zsQ>Fjz&BtGAUMk+IL9XPm~dk~J?klB#x$W+W1v8mD~Ikv8X=~GDCAy1`M@U|TbgS8 z_MN(dJTjS_fA{*Xp!38HqbW8BA~oszq zs{d4?Dp;0RhRngrF!3bj&$K1Dp)^glu zdn-|eGh?xMEGLnD+)(;c#Ec%Mh;5N4kksX|IJCB~J?9!NmUk_12MkO_a{WCN9w;=S z=)|QYF#Is$i3kxjaMlxAMq?!X1iTP`$Kq4dyj*C3}M z#n`O$@0M0&*dz(Z<`5v9(!_`y{i8S*$veAcn0`Cn@)$C)46-H8-H=qTsgU%+&0+TX zW7Z+^dCn2Ehq2|m7N8uPsJl)B6Ak($FaZj|N_4%D0TT_BnE70prfOq8*O^cdZLRq(>FjB~#LHIm12vjsaf{hh6g;95F%bU}^&nn2MC+QCR!H#+r9v2Sp5g5qTaXzfs3bc}dG?pUBn!Z9X~o?x z?*X6Bw~5a=z*!o9LHU&eSHcBlHc`$5>K={$41#n)@8S##T*8R4$NC5G4bt@K;vt|r zbX_9!?di$_5J9q)FauKHB`95Y&RHrX=s*lAl7foKy;m#6ZH7ALkOO*K&h|P^b+`6x zf)v>Z9ks9PBXbJx%Om##K2R?T+KB}LbgJ8sTCkSUW|soD*I13GV(b9!GMD#2E=)$2 z^d$Sy^`lTFy}gg}n_4j1QmMV>eNc%glmqGEgf=a*9TwLdRgezoB%B|2NtxeCbdcv- zqLXVdQ^T3j3;?62;S_+Ux-AC=d+tWx0WFX5X-N@DlMgvlymmtcBJM$?O(I zWHreRAE|~f0Bg1H`q^J!;tRu*K`G1v1-+TFh^Eg`?uoF9WQpe7C*mGA&joPIZ zG8_(!80X5virq(HDPcSc_yG%0J^$zvG)M|*NQA8}Fv$VpYH!KC=i%BK>qOVTzzWcq zBGmd#Kxi>*q|T2@0+@gyFs?OzK+T3Om=Hi(4`v6_ihZPkt)zws6KNr(^*FLpNs)8Ms`F z!V$-KwH5vy~M3IH$&`?^v21a^c@pXgCkfU52JRx)Lwd&w~QSbsa>L(Zk} z@~Yacdxa;x%lP&&iW3&cG0nI2w@KtE@swV4_0uxVvJp}ibFRklQ45BT?eMS32@ zr00oZtE13orlo&W$m*B_asN>rVcvX>2tiW*6i!miF*V2h%w7_nP) z-32727E>Li@*^}hfeh3dJ(--RwQM2LBvb~%^pO0RGaj5b0bzx69uA3L9*eJv#W6m= zHMyH;d(K4$9eSi2fh_((ye8FK=U!ALns!J0Ssy&Rdm|ZCkj-`PO(4oFp@ddc2n1}>RMddk952wIt0$JS% zekc<}8|lE^aQKOUcTrNtI)KRpQ>y7v$v)~)i$t&xY2OG1?C2JR^a?z%K$&C3jT z9Ev~;H*KDK?U!v5WdT9KUy9iQQTU!jY2ecdCAtMVCc|UkM9q_#D1{%S*@vFevHU`L z^zFq5I8BK%D~%{q3{mPbcg_hlji+GLr3BPwLF#>RD`)02Fp%XYFHup00Mmtw+emk> z9ulqBZq2Ry4V=WJ9Ktf`MaXlqr>vbz!Q+u%q~OuqsfNn*@*$C9=v=*XAr^;+Wt|&! zqGUY`<0`5eTGogg!Py10Dp3L!qgAoeil~EHul^-cAVqxz%s=%JwB7{PDf(M9dL>Sx zKk+$*71hymMa5CLrjsosKj)I9Fn?gG3}d$)oSD`1p54(g}@O8&HdK^f>fmTT*u4dufcgXDZmr^XK3?no@5B^u5$UUhrFvxJPy9yoiFDcB-S1 z>rz}1WR1{5VLe^AejD*)ybkBefAVs^@%vQT zQCS6*KsDWb1FsXB^^ZW^I9p0AM_bIj_-(Bk#+@Sse$_JgDT|{5RiE}ts=j3Bt9BF1 zz&y*md76u2c6`f$hfm)~?+1d0h6~;x41vRM`E<+^YG{SLCr@GYQqpuP@ME3%k>eiu zo+`@-b$Sd;%cckcwA7NQLZ>AP*d(zaw8JQgi(H-DUZsG!EkGj`Hos8Oh9f}tY* zfE%sQ|k?(>B zo?S?y$fZq7sK0z1a&a9H=-ef*EfHoa0ws``XKLwF(1O{0L7)VkfdeXm9Ra}F^)jj_ z*kIu;Xc9LTJmd)CNxKg2EEGh@!Aj=9W(@MhXn>lfKZq`Hb5cQdNx$Xc+HaA$#OZPa zZxte9PmT{-nRBwU>&ibmBUfTI(JVPaWl-Yx=N!hxL|=sKFO^(fR-PQk3M5>lS9O5g zt%SEj9o(COxTPfCU<0p`_?qO|61gmt*eG1r0~uq96X435z&B{TkS@n}{?Vw74x}q= z+R1JlPxq?}=In7NA+w5GaM`)(kq&Jl1&>uyxboz;R?FXl4uHX`p>dPv2DG9sJTuNA z8HS24Z4PP9TVgA(>_ID^JyssMSINV-m1xF*(SghW`eey-mbrOzp47_G{RPa2le+Oh zB(yI1f#A)0J?Bhi_v*}vHmbse(f}^Y9UxyVxm!`%5H~ptRk~Mp*4d*eW=2=1C6jVV zxUeu7sUkU;(FPR80zt6G{0)*eF@LE9!sJPa5NEzXg+jNW(z=8|tjqifGpJb(L)i(t zit1k-cQWtgk@4Cn_<4%K5UwZ|%s^l83Hs;Y$v>tA_e`f@%6%ZD-6@4DSQgQHa;T9B zri6I6&+kv_Vcd1rluz&bNDHhzxJ@zl0OiI!F_mnGr zw9kI`=yd2Pds`iajIpB>P^RELHprL(9^oGmGdqx;6G+dsX(#k_rHxnY zFcGavzjM+BhSf?ld}99AD;Au;?PQ9fSK^kVN-2h6MlE*jOMy76bj2<*591 zk)!1Plp`|>0dSY2sC@&WzWr*95PB&lmmlxIA*7m4~mNtn@((2p)G* zKS7Mv5rjldqdcs;VvWD(_qqH8R2HKH{9`(5(@rRFtVN$0q83&5fSK?x;T_P%;-nUf z0)6ve4B+7~Rtr369*YOIL4_S*!tJn9@NjiE!NX6u0dQo%1BlE400KdtO+=V*A6`LFxUVRYy?S55 zle<_Rg4n*xn1=pJ1!Z2E2~_2tuJ_!T|A5Ee^#`58_5FRW$GSLeJr*E{#^N-JgXrl% zoS1@z0_5)b=8!~@#|Ygd=y&9$*B~yHd&Md0U*};FZy6&c-ALsA77#Sm%ZPtU`{A3q z6So=W(**_wa8fy%0yJ>i+yO8&bQT$Z)^V+9?*^*67@>(WFfCRa3Qw&p)^F2wm&Tkf zcrR1KScnW`R*Yd7_*)o;!FySf%;FNXPGCP6d%OqpZd$3tGG4W@d_`Az*rD{lP{AFm!;P3ta0`l&D9?0Wj&er@l zZU}ghaNS^<*4pj6RPBKhox^pG zsE_TP!}Y@?wQZMhJ+~>x;`BR-Mww)K^e*dnVvyG1%9Gv=*bsUh11@%Lm@_a>H;Fh` zL(HlB@I|p}5G$(1Vk#XiQ<7jWY*gw%&}pr*m@w%an});Pz;_duuE1l7$=`8j^OHSl zSYG%uI0py3f?25^Z+XjhRCS4s>wpb($aAg8Kv7k7Q|`1S@D9QDqVV*Fr0iHugf^YT z1xDGM@$fna!m@LuDLY1E(?Fn1r&0&h7n+GeC{{+w#hfn9arg0>tZ%q(x84or;>h-U z*La7874<-8w%@z!gB#=IdNlN|6Np773g0Rx=VH{-9y7ijm%c7%Z^&X->`Y&V{bG>z z^GX2W79=?g(+M4M30;QNbp|-npUzEXMJ6BbrBhNv4`Yqpud+0jvswWW7DjZ0p~1UB zVwBvJvP+~KJ4T>fgoFOoed zWwLQ(`eMFW+CRyIo(oLW36*>F&d~faTOd5Yq~PdcVdyX$tKGh9xb9#w zZSD3@<<1W$`>hpSl_h6;l=eNfL5tOXj5j@MYU27JmM9Xl28zsT3=jAVcS(82&_SX;((fz5EOoud+q9tV&x*q z4|ul0PM{`!ODYTP4BMO@Cq6j1LimnP5UYbey*sTg_%{3GZyO>w(mL~LraS> zR4FDd`7$HZTHOL8UtnAG%foWVJ?QW=h`f z`(p0mi5VL#Z?fD)AuNM2G z-BC}XJG~KWr22Da{q(E!Q`%TR4bbMYb4Fz@khJmV8qALzckh=-5*h515JAM7=D@m0 zu;&36X-_sNF47A?d(cG^Z;F1>HT(eogsw#_-Urw+m$72#4o>VmGb2(7+pE#dk>{EC9nSikSWbq|Pw-6k#? z6l|TG1_NiUsxu^L7jCEy%|2da<2F3N^NpwpAY*7ro^70a6i;#J-gT@th6~Xfw^ABs z8Lk&=;UC>9y0!eHmol4AyXG6H2TP{%6dh|ZX+w?jgvRBJDUgFmPCcj^R-z#($JZoS zJjsIvIm_umO>0R0Sq4NU5Tur_B4PwgeX!=sK1q{w|^aAt?+$Chun%Onvhi3)EG z!^7t-8_k$?OX=KDyA6)PZMe{L!TGvJ}S92i5zvr~NXUGTsZ%O@uwQrI|a`=S00X6(2wj6K4nsfv1^U6w@6vu%sftr3QQB;@bZd$p~ zXeES6Akrh^qV0$kZV7mQIFvI+omOFWpF$+MPr_=ti+>6ffZdOo{lv**(3DRvOg>6) z+Bj0rGx(y3!~(V?ucTk&8GQL77O*9Grg%I9jyRT_k$WT_y|*Nf=S$DvOLnnZ>#YVh~`S0ezvy)ak6|fgbc#j-sRGfsQYp>Fy>j zSl{sj2>O6(Jm9PB#+M%G$S!~*u1{`k(^pxW(N}p9Z{2Gifvw9$s`dCt_@<*oDpKsX zPhzfFP-SQxS}+~wx`a(-jS~!y3NOdd5Q1n3Isp@055g}ABApzDpq_0MloL~9uK#2^nh@YD&SB% za$rYj*k&!(->73Gq=V@s)%ZsPj9^AgagVpyUoA_t1ZdaWXe7^kC$sVuW=!9ZPWQi1(85egpK zF%~{5c7yNWQgd7pDR7xx4TC*;r7{febvJng%%uC?*J^zS9HqVJDShf&gh%o)WI(5T zRu0C${VRWue~-oP`fb9eecw1xdjAq0=>5}pB>z{w40ugnEtCv>U*VU}wanG>YQSZh z;T(Q>m0$XOF#dFg4x(_-ajwEywDq`H?dFzPcU)0CPjD3LxS9SKIzKL=+N&3C@WALL z5#{5ED6%TY{pl+lOtKyp+X^$DY4TjI`Vx2?14j??TuiJ3ne;VjvPEAyxj%o) zr8`uYTn<4?;-31=j~aM$YD1RRIiYiZ#G%S4>wbB$`aM~MvdG&_iz-n!=U;5)Iqu54 zb?FcKLPr4G&Tvs?E71GruCb6ey!FvX`tC z6QYYp1riaJZZBao(YAsdfj~su&g8g506|k7*}$hi;!sz|`(5+`@uAwfCzKx@eL{P1 zK`-?=ys-u7ZLHs_>q^75PqGYj2#sBMexF^UlPe3(gsItH+tM?9>s9z#+tMRkUy8)b z;IR(TIz(PKvV04wOs#LiT%5r({(Q(&E6Dwe%3q?2qlDi{XRy?-`!-Av)h5 zy7V?adxq!Z&=YJ8Q{b zhlf+qF+9Hk1lWRU#PB3J@c?&lOj<)+^;!~ht_4C{fY6_S(B-j?+vwe}TP2ATBSsdM z$+{T|L|V7xT(>jhi)tIgX!TNU^;A4s8frfcqg_O5<1Yedj6aX$V1yQwwE)qsM_WQP zi$YP_0iwM}SsD#p2)%6>&Tv_BF$CW2_L-=*TzQb(?1LJH+!_UJqCEQE$cG5IN_ZuE zWxX_7h^FajeJCG^W6n zrS&haseC|X)GOFdsduYX5$Y)U&ElT~Pkzk*I6{K={e%y}qgIj5`D>E%TSM`g zl+FKKtN22y5GX|dwZcyFDpN&+Aee(a%JP+mj-ItjibiN(3!x(b156teZv3GiT9SXD z-|{Rb3Q3O?koD&-d);5<%!?!O_-h&slE#O8+632$?>Lf9;YF+Xgq};I|i{u6}SFG(l}OdrrPo+w%pm;pZLY?4{W3Tt<~FwpgU-PT;}$}H%(Ojjgfz& z^k<{&VVN!~kfZR?r_xvgXE5Mw52x=Nr$MwaQ;(UxdN~^+aU|}H%EHAT^|`Dnz7i|W zA(urI`{G!?C1FR8FYX;nTn)9>2R<0|o7>lntwAA4GLUL(J`>c@R=IvD)|Vf0k~JQ2DjkF>!w2>$_Xa7Ii+ zRad42s$v3!gW{IvE#b*AQDBccl;X`ExeLD$EmnmVnjVA@q|_h2X?;fegWz)1MCGZr zHefCVKWqUAff{okXBGG=KI)2Vqwv-!SWv^tL~<$t?fy7atM1hJ0#Ik zJ+3dR#c(sTm&FoiLmwOw!+1~KA$*xQ8zy_bMkWZjAFQKaf+J=QIwN4RD+omtr=4Xb zvWNfc?hfpNELg(p>R3FBJlhZN2^O2kL!h0Qo4K zFBZ&|0YN7fBM0O=R-DM*@U!FqtA*=pH3z<^3K;DPEx3>l<>pp1l&gW$fSkr@DJS>%i4?G|1@5b-dh|4bPE-UecT=;{=1H+YGLi`%h78rOuY_o? z;Cfv&RGvIoYRoVF*l@^rzeW>)IN9G{);@>a_qK8fV;zq}E;CSc@i-(lwtWs6fvOUr z!%)`a5E+^`9P*IQA=|3k=a9})TjNiyYa@pouN<<-d@eT}vbV881OQ9|{3Vx*oLOs> zBRg0S2{vKfE?<(^Kc7u%=n|!-$Nl%82i_+Kdp3zhR>&vCbn-(_l2b_*Dg5t~K(S1L$ckm)vjWDZzuq2Sv7^%eA+>1a#Kr zqAT6ez6`irWbfpeiqax=x%P;I+__+12|3f~eZA7VoIX7?HUEM3t4OnLN8`vczAvI^ z`fd@F8;6~UEm>d2bwOO?Z>kU<$jll>$+-iK&Pc${KW{n}F6w7HB6;N@~Jn*{n?+y;HVQu?5m z4D&#rD8VST@z9^>{)*`$T_A7p#6}iivB&$@Ar6M8ODC7zkuf~@u zIUQ*HLL;Xa)PoPWUqO_V_o|FotQbg^@2&UwIVG3*Q)==0vRhW9~uHpLQkP6Swso8c-xc(qXmv*e#c5%4A ztN!Rzvu$j+emg1*&oAAjX4@6vy0xqw)l>})&(EsadU4gj@cdZEnyq82Fk2t%#Khr9 z>{7G!imC&{^P{`=A6vCQy}=q5RUL~_c+=^>#ya((-A$SvaPN?rdU$d1;h3<{NOVw-?OR~q~@5@kR8ieS75JGe~ zxd)vXCOXidiUw0#)qJuOW?Z-KMhz27{v{Qd+&{b@0c7v7+BDkq&r|Av4%p@!ppq{E`ooMi8x8R>o3$uQKn6Cram z;f-5yOZSI#$41I{x)Um{BKVm0czH-bDT<*1tr=>6wE=1lX3+r|*$wD#=wcni3KKGz z*?>26;u@o6FAr8oZ)oGW?Q7YYE7G;>C2Sr+qVEk29@V~<9d7D@YCI4X_*ypA8`?Ie zeJ$JBuWEghUsXWME|u3*I%(dJ+>hXSL;2z!B3sZK%957>ElWy&FI!XaGEK{_H(ORz z%aUw{Ae243pQSK)E+okPB$RL9?>#MGh#d(Or zaB$#R5u^(fxfko#2o9Vbf?=EpzCsHREyCAgoX06&%Zl(7_Xx%CR)QUmBfa42-eC$} zVbg~(ZxkhNUkWt16IQ-(un*ga9VU`rnP0Nv5;@Nf)-y`e&e?M5qX5*(YF2y@K?y*Op7$XZ>FpkRU~kZbsIBRbFQZ z1U^q04e3!rgro%m+43^L`b288_-3tHztQ+?#=+=#9k{zBg}a0N>(mvL)1JtAOtEb6 z>BJ2Y`V-hfD(71`<_Wj9hz68O7wO_aI%?CfB!w(XKSDi#91h9qkV5`XSCIWNG@N-lwgR7USrYOXX=b2xIBI8jJVxV}j0r~oevFN!6u1Y8xxiN4vI zqllr-S6t5%FU40#ABxnSltrL0%EceM$&X*h9L%KCnK`o|R=d2Be*7l-@tfS*M``i? z0-*DEJBxf}Jj)ZO6!7iIp+{Udhq7>wyxTVJ}Gx#Cbso?n)B7mmrv_0h&sj+|w=}-hta~-4Bin z&}cMi1bsmj)$uE((Fmzk3;K30T=x%Iq9b!uB+!~KeFELcPjM1xp}Z~2Bg#*d0(L1y zx=Nd-<%KvMqA!=peXAli@w2us%?YhL>;{Bz~C++)tA zI`q8xDSC`1Et@;r3^#DtxRb8Y+_LHBJNlLSb-WP?#x$pz*M*Ip~ap3oPnQ}8Ph>bI8Ogto- zQ`&)zW^|x6Hg*?ZlaiNxsEuMF0MZ6a&>ZHt)80`c${R}F%LW_VbuE&I1KssDol+tWrfsbP6G>|1@fc3_Vk68*A|-06VUMPuLaNo6!NB;J3dpqP>C); zwU{cwIvaHh_(Xe(BZVJ0x?Sb~&0$%@(LlkGjK`<~Z%cVkbtkR(2Iw^Ee&SME0ZcE` zbCM8;?pB>_jIrmu>L&ofPnY6TvVyIV%}@jc{ZApw1pwW*nAOQt@E!T520>c@*^OGftG zWyUvo?+=~|Gz)_;zIYmG*JX$Euq_Lfg=PZ^Dvq}rLB)ib9hS{d@f4Ra`25|{Pnp3v`+NchiXbwA4Faz+l(mUGCfrd17^1C2_AyeWS6jeE z?`|3!o$jLd#BwChT)EeX;|47lbkQ%Cms)GnJk2crU*LW6kHRB>RA_L7d{X=-{RuW} zS6DhMS;zo)anTSvDUyWYEfK#w_s~21DD-z;vM= zAaG9Z;Y-PYu)${(2N-Y$Y3gLJDQ%wtum6WKAd7foMVJ3ww8@QXIilu5CbtAN+9$7Ch71*Y~`R|tm-Y186oJcmCBcF61O7bHp ztP-yY$2MU>u`3&sTQEed`6^Mx#ck$$fU2G|{`;VwT63(C$)KKkQC@1TK|S?w;C(<( zkvnddPrB_oMNdr@5nz@}Bny}}c``t7CtrcU>-O(tlqqez;CKvvVLTU>a}1X{@EPtB1{9*Yy+>*+&A|suX^6_jr9pP` z1@R}*&Of>{Q#FZNiOJffWpG>QgGez_<_)9|B?~$k|P4- zje_v6oz%X3kDsSv6eU7WTBr1mkVZcfapHs=aBBO)eK_h#gm#w-%rFT+P|23TXI-MU zuB?5@{^D6y_0oHUB~TTY2Mo~V0S}mO4_XlOR0C_u9qX!hHo?bB?@GfK0Vr;u-ZR~529s(VFg`!u`O)B{UfiVDcA z0HM_!cY%bxJ2u)yepR7BRRNdr+jo?nmS*0v!eZ-_i>r5HKUKx$K~;Q&yaaT?IqrP> zGHp~hB<}}dZsA9e%RTTiXxRJVhXuxC9q&A}u8fr@?)W@3t8nLucHEtl+I9Dvw3GYQ zHPo(MeWOio$ZW^9RbS2pMwhUm(XqsSYzwAjEOuTj3*V~C7$iWf z1Td%zn?Fx{o8w%&uC8yXg5~M9I_Ahq4LF*AG9h_e%~Z|wSKFC*AF9};7D2q&z~@9g zZcKe4D$29W4UM)=z=3-ooB_98O{DfmSE2HZjB$<)adgD}LQu>30mzl8Sj<>gU?m_s zhs$+<-)Qmxh%iotJ%YXGN{2VuR4Z-)sb)NcS?*5dI0-6`VPXe z?%Jirp2fm9nu7g|PZ#B)IB=lW$}b(gFMowj*=2#zHU}LN&^Cqm^4OsEwaw{IskSMk zg(xJHWMEnde-U%XlJ>PtHtI=)zFw_r09}{eplTrkimy4t|oufK_Mv z+$fVf7(?*+ZPU55`lz55L)dhgK+^>fSb=L8xWJsqVy--(aNK&lwh5-Ybp8 zh8*8Mi+%SukHrWi*0MIdm2S}P9ojyNJ&t-3p*ob6YT9D4(UC^4%4Jh#_ZMzBnQQW71DKX_!U&#d;9 zyYd2nQUy&bbL2ieuubOvygzd^zMcE?tbKi+0utbF@cqo~uzpTx@l!f`?_Mg`uh*GV z?qhk0+`HZ&v1LitEVIaJXd#C%hOoByuj+P*C9-e)bVi3n?igluuFB%qkbFHk3++K| zmjYcCkyxU-xFmsHvpO*aWMWGWZIx~f#sGr`HZboD@$)1O5~~iYM13N*JW52xP`wPU zl``Sph=cg)49MAW+Cyl+(Hya@VMf4TPTO2f=Mu`DX9CokD@nKfFC74ma&V+}A2y27 zYmTq9b{0-{tg{e0{5YS?6~<#Q$83=1?prUB(&i0VVlG;mQhn9^UiaY>a1|a6v22E9lSs>cNNGOp zvLk$xReSt~vMfVCgZXK+oB7^ejFc%a`dDMiW-KEP6~*k0!>G9|k(8N|AJTn~v;WNU zc&03OGmDdb?_8q+Un%f3pjjT|WDgwBz7pK{h@y-^tLNA+SgCqYI7bHL?i|#<9(+Km zk^#B#sDJ}}8!CdYzd2d#0Kjpvg8+e}_>P2Rx$G-AOu`DOWy2a;0BVC1vqP6|K zi5!#RerT#6NF!7o#yI-DuM5m#37p`C_Z47z*~G)utWN&b#}HkX9e!?1)t0i~?HURz zD&tHOFfZ;kHHMShUkbxdqb#|{{*M-xX~WekH~>@C%jD0J>y1f@3Xn<^Nwp-Pjib=U z+|dW~g@&LkSlM21?3z}xbUCbf1dY9Q-gH39#)zniI0l<5uyVLB@f_k1Wg)v*dk4`C zC1ZFcHzV(`O(%3@F4x)8>jrGa1%wTYZ};`rRzYbJp8sh!og+w48E`J-{rk_z+NxPp)|>B76`eNzbv($Su2KZ#Ld9~3`l)%;Owi+)=Y(H+%SzD=C!>E? z!7;xc$Fckru6>FxojzE9rq|X$yKinTaRzO6OPrF;o2cVsgRuT(`Q5k^2Nt3y@|OTh zICPqMz_2ywF0yUj1fzlG(OB))j@QGP*Op40Gqw-Kv4gc=30nHhF9BCol*C7DUWI!9 zxr}ku$juEU&PAJ7l*BJ8h@qLPOPQ&hnHrcH&D09eh0b}Gb4fyufS}KXWIN8qV?tg~ ziUTU#%P<#0N)`hm{7)S8TR9$g^>O8a9p-YE&L+}J$hN{D!V#YsKP_fCX|z(v`fpLK zE+Gh3j43t@B9fd}b+_K9Rg)RLfwa2Rs;&MdUtDTFwOjj4Fo%1O)NTou+B`NAx8Qya z@X;&kZ3ow@2>(3J^&u(p9-be1ZPDEw`ga_+2hpRFRJEJC_I~zaS?Ec8?C8F->Dv~! zXvB{#?#X*2b>K7Kx45?r-`L{5p1lS8U)STqw4CiNZvG_v)7%$XZhsxAb6>zeyZ=l4 zm0#~Q5R?N_tX6evW_~A>$^mUli7T+If3F69gO@|cY=WB-dSxke0ZjcWu49R3ABL9@ zvX_68Uge=XQ)Tl%S>;$$<%L>h6JDaqLxwZR4nq0CjGch;IjQn@rphg{7AAX+R@wUr zuDvu>^1e^^`OnmSLC2-jp`)aD;}Y%UU$uBIE&kyLf#SRl*sV@4zMB-k-xMFD#kYMc z9je+KDBhjL`gC{Rohg z``w>L;T!xgCp2m{>$e&g-ZUvUP3i}v5P2vD#Gx_AoTZfGe)+i7y-xO}Kbl4=0*ySI zC5_zSH!|S<42>MRqef~1jVwK2koM$PfkqD1MsoZ{&i-4l5ln8dCo7IIIM39R{Q`~L z_k;E%`wi%F)oyHvitcxS(K@fnO-9q zda_}T-;-5;(w=0G4>WR+HuA$c9=hh=8SIHcSDzgA5$<~M^bt=^OyXdM5K}2xdXhO zG=CUu1Y*QSW*1v@W$4NG#zCiAIodRmeZ4fIJ-Ht|if^}{KJ=*ppLnFNcjbv}uMsnx9=%Z^EokAyfbD4*(*KW_y zlPkSOGN5be!#?5Xn4aYRG0@1~+Q@XjkqMa^>9V6n&I>ehf^FoRg?>+_ia(nBN57GM zGBxt(Q5Ibpda~^yzb7C6)1a$9(1@-n&;9O94_ynVWkA>QUL)dYrW&m~0*zd48p)1G zBg$O~VbSb6q!COfhjzh7I|2!P8`@b2nR4xN1O3|#x76tfXTPi&RJk*iMVDN`FOLL>Apf5mTiO4Q?oItw^_{lorP zE;dR6N4UUF=!-Lm4Sx9mU(mvX-wy7e7md(Ic0wh zx9wPg6B_Pi7_S+k%y5ciKum`F;=BxJAVcykiIC;Xx2Id^`twVvjh&s)lz#S053Tg% zZi6}`SIYF66ur>P(2+$?wi9bk=q&Hc*ZI=r92R{=RwqeO*K2hdG9-uiUzT}ap5T|| zvS>-lO!2-<-_wR@17IR@$T#63#GMvexC&(8m`pF2}$pKn)6pOxy zz9=YByRw9NDYG9)|6m(YCq z0-s94qXvF?OxDnZrlfp%gkMVa%QGoortr&8xZDi%ot*MzEWg~WU(QYWQpPX&_~Kqa z46#fE1AWeAWkpZ zp?iRqBRi~&n`_L=#M@LW=)OJU(L8&rzKqbdE#yl#8FzX5=$aD7?~o`DRwmNocUkhB zwjWX9#bAgzUBv_01c_WrdkhsLcGZ9m2otfj#*SX$@Yz~k`V@1zBIq8u+J^s?tC5+L z@`?Vq^bE78i0W6%y7e;eoLZdmQp0fCKGXCi=Jjl67Z8#v1M5hPR_!wq@0;E%i5DQQ=VWM!$%io=%~z`V`k42K=>;Vcl1qQt zSG!IdJVn57a>WH>QMYZV0aov{Z?0X!!Qmy5smOTpy@oBEk;;$?xS}@)3^Bl8~p#3PD@v&jE1kl8UtSO zBUk_gXu9b(_lcpv;fcPKq``le!ru-KCv{K3p)(v@4;4!DB{;-7sSfVgn=KB3d<=Qv zKuMd)9g?IIw|>c4}$Z)v#S90TYjKIlS)H28Z^6n7T?dYKhz5U!igjwenA9k9*3 z-|BGv{rUp5z&cL8m?AGY$aY#G2J!H$E{yftR(XmLaS-T+(XMC_KI3@~2fZqDaPvkA z&BRvqSQSi~d&>X$pSjK0vrdV*nU<8^{Xi zdN8T4>p@TWR8ON4Z2;XZC+p@wjPjPa2cmtw53qIn5wRaIBqco3dG zE#bu>5(o5Qu?DRgD%!;Hsh~F+G!E5ht;PY36>F3PqM{@u!8{*VLd6PBV67EftT-V~ zZ5V{$7{vi+9IEFvXmO|_RPz0Pd!KvXeM11PYyH>ye_z&ucZW0VdGE8&a1$e5#Mkrs zzgUiA-&$Kxx&ri;83IN_mgl7xSc`|Ftj;IIXiCU^Duf#v=3vHoF{JE^dT{U5#gMtW zg|NY2)E~rKaB0Ls7@I{re2qHk9@QrW;uJ=Jm^G@x(ko95d7GEIHFJ&vANndEQu+~; zqj1np06p%dhDpFS>Qs4&f6rEb15?784e+coO&+U*?NqCl<*_Ls!MXObXClo!I>JVe zT}mL}+l3D6NQgtb=mKJh9=jxZ#9{!fkS;GPO2pGE< zI`R?Z8lfZReD+;GHx)W|A#`LW&juySt5#O#Tq&eo6OMBtc!tLtzOiZ zLI3~39?<16<`7#zZwv?>@&?e@ZDUdM4vaS~STX!~6^Y^7gR_@s+k=(&1nq&%_nmZ| zJ`BXOzr055L6n&FY7csqN5BmMvRnEy=yA^XkjEO*znanm((^E}oMRdCM#nNSNTZBp zO8v16d^%QMF^6v)6>rZ{^n6SZTR-~J^fkZEI?lkg(vSSC{-=j3|=Wd$up3WZHO zo(Bc8(UvRm1QHU=ay9ljL_la^1rqp9z*-wTiza0(GrL&?^5Vn6wiYXpDf;)yFDTLf zkL<@2b5iU|vmbxNi_Nkh-~J@G{dgbGgY0_AmdmsskJ;y&vLBx}3A-LY^#4Qqap`Hj z*^k}ih$9$APRH7e$AtMo`(ac0+csy}k8c{peylp=|JjekzI*>UC6HFFn`J*9+bXyHxD(HV z?3!lFW!jG`?ek69j|Z+1c3oBaBij#~3S#_W<9E8D-0{bEC--JQ-tC}SNVgx){3B>T ztWkOC+ARC=Xr0)P*}wdM_9LmJ@8_)?8lXTbK8$|@jS?`lWe(6`%z|}Z_0jLexvX_iQR?fIcK7M?y*pKQ1 z{-6Cw?E9D7Qv#W0Kc?ZuX4wyum)m}H;dxLXJ8Zd3`!UBp-<17WHBJQb-eEcIhdTl% zJ;`BOeYw=2X>~i3J@L7AmA3swhI9s>C)ykiHMz1?k7#YvQ+Srw$>Gi%m-COS=sVcuD6!FY3uTdTXZj{Gc&ixSq>4g<_6#wF(jAVkpG1%yn^TS6Xa+_0K!<_ z%sNqPW6X*{8@(!Ym)S2&MONv~gf-06tYM~Rjp@LOU)jb8q-Fym84V(XSNz#g;#$qb z;DJBrRMt&1lkJB3*)opHAtT=4yqK)gHEgjKrCMeT>Qs=yivsogIw)wB$vwBcX#;GwBYVYz}`+`~>Tm>v2Pm z92GdMc^I1l!R4(I9KtTG%eD{mvqRDdF1b7j<|w%kh63~O)w($jB7hjp4ehZ~7pdzM z%Yq_gg{MgoqSTDDoXvLof!h4Ir}6T`K?kY?G; z!j5sRn^Opw8(Mm4(7+2$Zm9od!2l7uFNpHvwOCJlr=GeSqijk`&@4#s6x)UOtuZ}b zg4&)_vfRQ~{zYye-gR%YlO>#8-fekcasz^tA-HbnzGT2l?nWe2I>fiEFBdP=7TIa^s_WTrnLbV2?7KC70VaHH`?Jvq02OY zWzSqw&AmmCWEef1bomu#QW-dgxjCndP@q$3F3~2ZYr^JXHuahMvp8dejO=1GU5Dn} z(=hWwpBrD9*8YUq>0pOWyjabSf{h;X%*1h|A~9@Q(ufDLx7=LWnhv`!#Gq>pN(rxO z<-!e(`8XwdR*W8#ZGV#2x41(l)i2+*d%(@=sm%6FlU!E6+r7*Cqdkw(aSbfG4XfS%V%O|eg~GV2oGaNuiokc>*qWIKTGm%aA<&!s5-A`zh)P zVXmoL{G;inQp&YkIO?O68#92_2AWG-PRQdW_IMmZHK)220GQz9`Lx{xAn>v20c;Pwc1IDiBEXkA<1Wkkx6Z#VER=e_bAse+@J3Nuvy6a^SV^FE#_O1y_95 zlU&brrO=Z~C(co-m>z~|R1yGu!D!Wf9B&UpD>Qp)lExa)EY2=_A1!kWw|ksWGUBHt z9V{qNodILi+`3EfQ2S&jR4X7&hdr_{rHSY5kxBcbu6YcL3p{DUN&9pi=nz7!)7g}F z2zzq4Adr%@M)n(!v^L&@3siLe@p^_{f+K|=zMqn`M!ptF+qWZ=Bdku2uqx>C`Mm*- zMCF-{M|$DNttFemk)K`eNgAi|TOMV*%Q~>}3SH*E^o;tCYVxLrbgIP*6hJT`7j9@r zL5AMO&KQQx`Tt1AM51zr2ySTlWdR&iswDczEmCjpzZnROu7ya=;o4#F3ziAaM$b2g z6hMAb!V-GEjh$26C@h13fN9u?A|fUmlhDZm1hzpDIYf47c_OkGYy1IgBsN1twi19+ zBGQ4nK@sWXJ;b65zx?C%O1-3rbi9`mkq*8V5!psI!Bf5gG7PYds$dIP736*4o&b5H z^2{rfo5BtIZ3cz=Ugn7ijL{9>v03!ri}wCRPH!WOATp0z%`@9iOw(R~JDY6){5kvu z=JW8&KVC1;OQQ4myD8H(o3A10Vbkxabn&tS3^d28sJ8#50V;T=i(RmOF4J|zzMDaX z?=FR$#kgpkUK?h~iA#)Cavpo5lc!YejBd=!ELw=7rYZ`bet>?UD&@~5e%p!;F<1Q7 zPDr`#6OF?DV2z;!V~HvrjudGb&#v7;%P*iaSgHYOzagjtC@^r+#We1qU#y|(a=w~; zh!CvAj-EY)5;NI_$AMnSnJ@z4N#y^qH z44MhFS*yxO3PCGls&%fsq>)FP8D8<<`(&~}jA*)7yb9mu4(RiMbJS5Nd{t8*GByjm6wfq8D+Q_g^Kiii>c;9dz1RL7G#3joFT!Z%SOY*cIaP zPKLN-u0NYfJJGv+$&!~C%nJr|VKFbEVJl(PmMz{hO$LKo z@CaGl&`oCsi69KzYgx~?Lw409o+I(S<#pb37+nYT;5_mNKZGB(7dHH= zq!WNU5X!ShYe>Up&$jiTisVz#&9N@3bvopUUi)|V$lg*dWKRi zWxCDn7b^9uk@KusYQ0YKY1VH37 zKXm}QlvqUWwTKAg(3B)Jl^UQ8xNimuBJ8Xg$C{XiB0zb5=6X>O&(4?Jqe>_~2ZMF- zX&9`_FT#i!#6bZblnroVG%4cGZqy{-28nu+=$ltODK+) zjFsB#ajEc!5;5YXpt0tDhGfB}V-Od3YCrWu!NsaS_f>+3Zv!MQhh)i#h4lTPSv6k3 zM0jC>JE;GwR9`FwMRWk#)uH<{a5O5pQo!zu*g-Yns(}Hy`zkUBv_%VH#^U|}B3F3O z_0vrKRnqMc%-#O_0#yhH-vLCA6h5~SDJKa)#PV3Arf_8?6Ai)#JLhEP?g(D~G9_^- z{Y>%mq0Q#!ZaW19a0ei0o;W|q&o&K2+69rsjM*eXF0TISzgb*;(4JnJ$<>|z7UZh! zpiwFHzwx$YMHX+bu?GU>;O#bL0p1SW6mP#8ycxWmc;5fS+pZnJ+g|sFfxjI(zxg&i z8JuQ^Fk`MAP}pCnOP4%{^{6}_XsR zwl<(wNG8~aQR-hYT^BEOX6NYZbi7tdykerHG$v^3&Rk7>a;mnkO-WqkH??-M*OchK zwnr_*AW-Gf&VgXyHwQrQFKs~R7CzGDMFqFnDx4nbv8Q}`(x=rqrkuwn+|ao<5h`n6 z!t%^3lY0bm>F$|g*vVSyBapS{s2En$mNifU1eHdX1PZh#{Npv%n}2}iix-IkV1b~C znGKsGvfyW3!Y^jQ4L!3%K!<2P9M>D9&Rsch=g-ofW?7NJ|&!A~z<>d_so`RW}aG+5y7P0OLZN$wKqc z>KV3q7y|n5RPzD}9+|Ig^XQiB^aPApH?kWvT3}u}SH(8UW{RnNY0`$6SEDWqHU_`+ z#-+p%(PGDm1WIiO1ozv zlmy)Erf=FCGhzTp(UV4s?D%%vS)fG;W7}fJw#5Vq{D4S=#sU@GK@yb?F&}1-hA<IKmGt!;Zpf6` zlT{-xYh(#3NG>b?cfY9t(uJ4t2S-sQ3ioZmQ5`SWkH_kg7QB(kJBTwbYE{f})xayr zdj1hZb$F#B{tI@Ec8kR)dd{(w7v{nnbtD7H5$8B%NTZatDg_ejq7C5=S`V8c@`*1% znXIEGjO-8gGtrzO|I$qE@r>E_@(h}bXo;Lw3(qMKHN1iX$e@v#Z(IREpkdCXZNqH| zfrc1)wqc4LiTLB0IX?k#S>qYl$8ojb1te_@gKGYV)*x<>$NJg~*hJU_Hh~gWOTvB& zn?M;g6D>p#Y->P-D-D#o!gKB)Ayv8tn%3$dNpj*3%w$f zU5Z7~l;DY- zj7KOT5f%ulyQ0jqTLW0^IG>*P?J zi3}zh*~;c<+$u?^cus{=DI;XR|G)PjD@9BGdEcB3rkBb*uck z)vSy5n6twWvDk^f>ok7|8C(w;{HH*5HN>K)-?&R0_h`u9+CJlomfDFn2GNZygC!RD zSqwcd`z=QslnHRGLDMmzLl&ooEn=jQPr6ez%8Gy73bUE_Ypx$AC@?_8K{7?&bd)*w zlYp3uoq{@{E=WTmdjn2TifHqRIulfG#bn+X*Lm^a39GhZchz z(h{*Fjf>35d)hhV?x)Q`{UCYMD0vq+iT-#^XQHc(%Y? z_B$PDTj0r~^eL)i zW1AAQ|GI85BjA~YVd5vP`|-OnZ)^eL?f{Y!>lD5zeI8AdjKx&chIqC<&z9#TIMf1h z4oXo!&0 zhGL2+crx8u8CjBIzg!50RI%M^55yV;v9RGEUh+gTM;stOeY=7P4yNa1L1xGdjh75H zM8a(3mJ7neEQG~u2Vi>H6`O&{P*rn6AF$#|*jirzQ~Z$exBcFHQ2yM|jIS!e7(|)7 z+r^tZm^pz&{;^{idqi3freSvTCy%7`Kx^$s=j7}j!6`rgsu_4im%9C}&@n}l z*m|y(SCDAhp!aXr5`r64il1|fr;Y0Gza*^VX=AhW*G9?`#t{Sdn#AH$nF-x `lk+TCi4qC=5w%{XGR^Xe8!j3h#5Xo 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%0A5NfECY6#yP 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